1/* $Id: ebus.c,v 1.1.1.1 2008/10/15 03:26:19 james26_jang Exp $
2 * ebus.c: PCI to EBus bridge device.
3 *
4 * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
5 * Copyright (C) 1999  David S. Miller (davem@redhat.com)
6 */
7
8#include <linux/config.h>
9#include <linux/kernel.h>
10#include <linux/types.h>
11#include <linux/init.h>
12#include <linux/slab.h>
13#include <linux/string.h>
14
15#include <asm/system.h>
16#include <asm/page.h>
17#include <asm/pbm.h>
18#include <asm/ebus.h>
19#include <asm/oplib.h>
20#include <asm/bpp.h>
21#include <asm/irq.h>
22
23struct linux_ebus *ebus_chain = 0;
24
25#ifdef CONFIG_SUN_AUXIO
26extern void auxio_probe(void);
27#endif
28
29static inline void *ebus_alloc(size_t size)
30{
31	void *mem;
32
33	mem = kmalloc(size, GFP_ATOMIC);
34	if (!mem)
35		panic("ebus_alloc: out of memory");
36	memset((char *)mem, 0, size);
37	return mem;
38}
39
40static void __init ebus_ranges_init(struct linux_ebus *ebus)
41{
42	int success;
43
44	ebus->num_ebus_ranges = 0;
45	success = prom_getproperty(ebus->prom_node, "ranges",
46				   (char *)ebus->ebus_ranges,
47				   sizeof(ebus->ebus_ranges));
48	if (success != -1)
49		ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
50}
51
52static void __init ebus_intmap_init(struct linux_ebus *ebus)
53{
54	int success;
55
56	ebus->num_ebus_intmap = 0;
57	success = prom_getproperty(ebus->prom_node, "interrupt-map",
58				   (char *)ebus->ebus_intmap,
59				   sizeof(ebus->ebus_intmap));
60	if (success == -1)
61		return;
62
63	ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap));
64
65	success = prom_getproperty(ebus->prom_node, "interrupt-map-mask",
66				   (char *)&ebus->ebus_intmask,
67				   sizeof(ebus->ebus_intmask));
68	if (success == -1) {
69		prom_printf("ebus: can't get interrupt-map-mask\n");
70		prom_halt();
71	}
72}
73
74int __init ebus_intmap_match(struct linux_ebus *ebus,
75			     struct linux_prom_registers *reg,
76			     int *interrupt)
77{
78	unsigned int hi, lo, irq;
79	int i;
80
81	if (!ebus->num_ebus_intmap)
82		return 0;
83
84	hi = reg->which_io & ebus->ebus_intmask.phys_hi;
85	lo = reg->phys_addr & ebus->ebus_intmask.phys_lo;
86	irq = *interrupt & ebus->ebus_intmask.interrupt;
87	for (i = 0; i < ebus->num_ebus_intmap; i++) {
88		if ((ebus->ebus_intmap[i].phys_hi == hi) &&
89		    (ebus->ebus_intmap[i].phys_lo == lo) &&
90		    (ebus->ebus_intmap[i].interrupt == irq)) {
91			*interrupt = ebus->ebus_intmap[i].cinterrupt;
92			return 0;
93		}
94	}
95	return -1;
96}
97
98void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
99			    struct linux_ebus_child *dev, int non_standard_regs)
100{
101	int regs[PROMREG_MAX];
102	int irqs[PROMREG_MAX];
103	int i, len;
104
105	dev->prom_node = node;
106	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
107	printk(" (%s)", dev->prom_name);
108
109	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
110	dev->num_addrs = len / sizeof(regs[0]);
111
112	if (non_standard_regs) {
113		/* This is to handle reg properties which are not
114		 * in the parent relative format.  One example are
115		 * children of the i2c device on CompactPCI systems.
116		 *
117		 * So, for such devices we just record the property
118		 * raw in the child resources.
119		 */
120		for (i = 0; i < dev->num_addrs; i++)
121			dev->resource[i].start = regs[i];
122	} else {
123		for (i = 0; i < dev->num_addrs; i++) {
124			int rnum = regs[i];
125			if (rnum >= dev->parent->num_addrs) {
126				prom_printf("UGH: property for %s was %d, need < %d\n",
127					    dev->prom_name, len, dev->parent->num_addrs);
128				panic("fill_ebus_child");
129			}
130			dev->resource[i].start = dev->parent->resource[i].start;
131			dev->resource[i].end = dev->parent->resource[i].end;
132			dev->resource[i].flags = IORESOURCE_MEM;
133			dev->resource[i].name = dev->prom_name;
134		}
135	}
136
137	for (i = 0; i < PROMINTR_MAX; i++)
138		dev->irqs[i] = PCI_IRQ_NONE;
139
140	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
141	if ((len == -1) || (len == 0)) {
142		dev->num_irqs = 0;
143		/*
144		 * Oh, well, some PROMs don't export interrupts
145		 * property to children of EBus devices...
146		 *
147		 * Be smart about PS/2 keyboard and mouse.
148		 */
149		if (!strcmp(dev->parent->prom_name, "8042")) {
150			if (!strcmp(dev->prom_name, "kb_ps2")) {
151				dev->num_irqs = 1;
152				dev->irqs[0] = dev->parent->irqs[0];
153			} else {
154				dev->num_irqs = 1;
155				dev->irqs[0] = dev->parent->irqs[1];
156			}
157		}
158	} else {
159		dev->num_irqs = len / sizeof(irqs[0]);
160		for (i = 0; i < dev->num_irqs; i++) {
161			struct pci_pbm_info *pbm = dev->bus->parent;
162			struct pci_controller_info *p = pbm->parent;
163
164			if (ebus_intmap_match(dev->bus, preg, &irqs[i]) != -1) {
165				dev->irqs[i] = p->irq_build(pbm,
166							    dev->bus->self,
167							    irqs[i]);
168			} else {
169				/* If we get a bogus interrupt property, just
170				 * record the raw value instead of punting.
171				 */
172				dev->irqs[i] = irqs[i];
173			}
174		}
175	}
176}
177
178static int __init child_regs_nonstandard(struct linux_ebus_device *dev)
179{
180	if (!strcmp(dev->prom_name, "i2c"))
181		return 1;
182	return 0;
183}
184
185void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
186{
187	struct linux_prom_registers regs[PROMREG_MAX];
188	struct linux_ebus_child *child;
189	int irqs[PROMINTR_MAX];
190	int i, n, len;
191
192	dev->prom_node = node;
193	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
194	printk(" [%s", dev->prom_name);
195
196	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
197	if (len == -1) {
198		dev->num_addrs = 0;
199		goto probe_interrupts;
200	}
201
202	if (len % sizeof(struct linux_prom_registers)) {
203		prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
204			    dev->prom_name, len,
205			    (int)sizeof(struct linux_prom_registers));
206		prom_halt();
207	}
208	dev->num_addrs = len / sizeof(struct linux_prom_registers);
209
210	for (i = 0; i < dev->num_addrs; i++) {
211		if (regs[i].which_io >= 0x10)
212			n = (regs[i].which_io - 0x10) >> 2;
213		else
214			n = regs[i].which_io;
215
216		dev->resource[i].start  = dev->bus->self->resource[n].start;
217		dev->resource[i].start += (unsigned long)regs[i].phys_addr;
218		dev->resource[i].end    =
219			(dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL);
220		dev->resource[i].flags  = IORESOURCE_MEM;
221		dev->resource[i].name   = dev->prom_name;
222		request_resource(&dev->bus->self->resource[n],
223				 &dev->resource[i]);
224	}
225
226probe_interrupts:
227	for (i = 0; i < PROMINTR_MAX; i++)
228		dev->irqs[i] = PCI_IRQ_NONE;
229
230	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
231	if ((len == -1) || (len == 0)) {
232		dev->num_irqs = 0;
233	} else {
234		dev->num_irqs = len / sizeof(irqs[0]);
235		for (i = 0; i < dev->num_irqs; i++) {
236			struct pci_pbm_info *pbm = dev->bus->parent;
237			struct pci_controller_info *p = pbm->parent;
238
239			if (ebus_intmap_match(dev->bus, &regs[0], &irqs[i]) != -1) {
240				dev->irqs[i] = p->irq_build(pbm,
241							    dev->bus->self,
242							    irqs[i]);
243			} else {
244				/* If we get a bogus interrupt property, just
245				 * record the raw value instead of punting.
246				 */
247				dev->irqs[i] = irqs[i];
248			}
249		}
250	}
251
252	if ((node = prom_getchild(node))) {
253		printk(" ->");
254		dev->children = ebus_alloc(sizeof(struct linux_ebus_child));
255
256		child = dev->children;
257		child->next = 0;
258		child->parent = dev;
259		child->bus = dev->bus;
260		fill_ebus_child(node, &regs[0],
261				child, child_regs_nonstandard(dev));
262
263		while ((node = prom_getsibling(node))) {
264			child->next = ebus_alloc(sizeof(struct linux_ebus_child));
265
266			child = child->next;
267			child->next = 0;
268			child->parent = dev;
269			child->bus = dev->bus;
270			fill_ebus_child(node, &regs[0],
271					child, child_regs_nonstandard(dev));
272		}
273	}
274	printk("]");
275}
276
277static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p)
278{
279	struct pci_dev *pdev = start;
280
281	do {
282		pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev);
283		if (pdev &&
284		    (pdev->device == PCI_DEVICE_ID_SUN_EBUS ||
285		     pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
286			break;
287	} while (pdev != NULL);
288
289	if (pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
290		*is_rio_p = 1;
291	else
292		*is_rio_p = 0;
293
294	return pdev;
295}
296
297void __init ebus_init(void)
298{
299	struct pci_pbm_info *pbm;
300	struct linux_ebus_device *dev;
301	struct linux_ebus *ebus;
302	struct pci_dev *pdev;
303	struct pcidev_cookie *cookie;
304	int nd, ebusnd, is_rio;
305	int num_ebus = 0;
306
307	if (!pci_present())
308		return;
309
310	pdev = find_next_ebus(NULL, &is_rio);
311	if (!pdev) {
312		printk("ebus: No EBus's found.\n");
313		return;
314	}
315
316	cookie = pdev->sysdata;
317	ebusnd = cookie->prom_node;
318
319	ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
320	ebus->next = 0;
321	ebus->is_rio = is_rio;
322
323	while (ebusnd) {
324		/* SUNW,pci-qfe uses four empty ebuses on it.
325		   I think we should not consider them here,
326		   as they have half of the properties this
327		   code expects and once we do PCI hot-plug,
328		   we'd have to tweak with the ebus_chain
329		   in the runtime after initialization. -jj */
330		if (!prom_getchild (ebusnd)) {
331			pdev = find_next_ebus(pdev, &is_rio);
332			if (!pdev) {
333				if (ebus == ebus_chain) {
334					ebus_chain = NULL;
335					printk("ebus: No EBus's found.\n");
336					return;
337				}
338				break;
339			}
340			ebus->is_rio = is_rio;
341			cookie = pdev->sysdata;
342			ebusnd = cookie->prom_node;
343			continue;
344		}
345		printk("ebus%d:", num_ebus);
346
347		prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name));
348		ebus->index = num_ebus;
349		ebus->prom_node = ebusnd;
350		ebus->self = pdev;
351		ebus->parent = pbm = cookie->pbm;
352
353		ebus_ranges_init(ebus);
354		ebus_intmap_init(ebus);
355
356		nd = prom_getchild(ebusnd);
357		if (!nd)
358			goto next_ebus;
359
360		ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device));
361
362		dev = ebus->devices;
363		dev->next = 0;
364		dev->children = 0;
365		dev->bus = ebus;
366		fill_ebus_device(nd, dev);
367
368		while ((nd = prom_getsibling(nd))) {
369			dev->next = ebus_alloc(sizeof(struct linux_ebus_device));
370
371			dev = dev->next;
372			dev->next = 0;
373			dev->children = 0;
374			dev->bus = ebus;
375			fill_ebus_device(nd, dev);
376		}
377
378	next_ebus:
379		printk("\n");
380
381		pdev = find_next_ebus(pdev, &is_rio);
382		if (!pdev)
383			break;
384
385		cookie = pdev->sysdata;
386		ebusnd = cookie->prom_node;
387
388		ebus->next = ebus_alloc(sizeof(struct linux_ebus));
389		ebus = ebus->next;
390		ebus->next = 0;
391		ebus->is_rio = is_rio;
392		++num_ebus;
393	}
394
395#ifdef CONFIG_SUN_AUXIO
396	auxio_probe();
397#endif
398}
399