File: /usr/src/linux/arch/sparc64/kernel/ebus.c

1     /* $Id: ebus.c,v 1.63 2001/06/08 02:27:16 davem 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     
23     struct linux_ebus *ebus_chain = 0;
24     
25     #ifdef CONFIG_SUN_AUXIO
26     extern void auxio_probe(void);
27     #endif
28     
29     static inline void *ebus_alloc(size_t size)
30     {
31     	void *mem;
32     
33     	mem = kmalloc(size, GFP_ATOMIC);
34     	if (!mem)
35     		panic(__FUNCTION__ ": out of memory");
36     	memset((char *)mem, 0, size);
37     	return mem;
38     }
39     
40     static 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     
52     static 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("%s: can't get interrupt-map-mask\n", __FUNCTION__);
70     		prom_halt();
71     	}
72     }
73     
74     int __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     
98     void __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(__FUNCTION__);
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     	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
138     	if ((len == -1) || (len == 0)) {
139     		dev->num_irqs = 0;
140     		/*
141     		 * Oh, well, some PROMs don't export interrupts
142     		 * property to children of EBus devices...
143     		 *
144     		 * Be smart about PS/2 keyboard and mouse.
145     		 */
146     		if (!strcmp(dev->parent->prom_name, "8042")) {
147     			if (!strcmp(dev->prom_name, "kb_ps2")) {
148     				dev->num_irqs = 1;
149     				dev->irqs[0] = dev->parent->irqs[0];
150     			} else {
151     				dev->num_irqs = 1;
152     				dev->irqs[0] = dev->parent->irqs[1];
153     			}
154     		}
155     	} else {
156     		dev->num_irqs = len / sizeof(irqs[0]);
157     		for (i = 0; i < dev->num_irqs; i++) {
158     			struct pci_pbm_info *pbm = dev->bus->parent;
159     			struct pci_controller_info *p = pbm->parent;
160     
161     			if (ebus_intmap_match(dev->bus, preg, &irqs[i]) != -1) {
162     				dev->irqs[i] = p->irq_build(pbm,
163     							    dev->bus->self,
164     							    irqs[i]);
165     			} else {
166     				/* If we get a bogus interrupt property, just
167     				 * record the raw value instead of punting.
168     				 */
169     				dev->irqs[i] = irqs[i];
170     			}
171     		}
172     	}
173     }
174     
175     static int __init child_regs_nonstandard(struct linux_ebus_device *dev)
176     {
177     	if (!strcmp(dev->prom_name, "i2c"))
178     		return 1;
179     	return 0;
180     }
181     
182     void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
183     {
184     	struct linux_prom_registers regs[PROMREG_MAX];
185     	struct linux_ebus_child *child;
186     	int irqs[PROMINTR_MAX];
187     	int i, n, len;
188     
189     	dev->prom_node = node;
190     	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
191     	printk(" [%s", dev->prom_name);
192     
193     	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
194     	if (len == -1) {
195     		dev->num_addrs = 0;
196     		goto probe_interrupts;
197     	}
198     
199     	if (len % sizeof(struct linux_prom_registers)) {
200     		prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
201     			    dev->prom_name, len,
202     			    (int)sizeof(struct linux_prom_registers));
203     		prom_halt();
204     	}
205     	dev->num_addrs = len / sizeof(struct linux_prom_registers);
206     
207     	for (i = 0; i < dev->num_addrs; i++) {
208     		if (dev->bus->is_rio == 0)
209     			n = (regs[i].which_io - 0x10) >> 2;
210     		else
211     			n = regs[i].which_io;
212     
213     		dev->resource[i].start  = dev->bus->self->resource[n].start;
214     		dev->resource[i].start += (unsigned long)regs[i].phys_addr;
215     		dev->resource[i].end    =
216     			(dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL);
217     		dev->resource[i].flags  = IORESOURCE_MEM;
218     		dev->resource[i].name   = dev->prom_name;
219     		request_resource(&dev->bus->self->resource[n],
220     				 &dev->resource[i]);
221     	}
222     
223     probe_interrupts:
224     	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
225     	if ((len == -1) || (len == 0)) {
226     		dev->num_irqs = 0;
227     	} else {
228     		dev->num_irqs = len / sizeof(irqs[0]);
229     		for (i = 0; i < dev->num_irqs; i++) {
230     			struct pci_pbm_info *pbm = dev->bus->parent;
231     			struct pci_controller_info *p = pbm->parent;
232     
233     			if (ebus_intmap_match(dev->bus, &regs[0], &irqs[i]) != -1) {
234     				dev->irqs[i] = p->irq_build(pbm,
235     							    dev->bus->self,
236     							    irqs[i]);
237     			} else {
238     				/* If we get a bogus interrupt property, just
239     				 * record the raw value instead of punting.
240     				 */
241     				dev->irqs[i] = irqs[i];
242     			}
243     		}
244     	}
245     
246     	if ((node = prom_getchild(node))) {
247     		printk(" ->");
248     		dev->children = ebus_alloc(sizeof(struct linux_ebus_child));
249     
250     		child = dev->children;
251     		child->next = 0;
252     		child->parent = dev;
253     		child->bus = dev->bus;
254     		fill_ebus_child(node, &regs[0],
255     				child, child_regs_nonstandard(dev));
256     
257     		while ((node = prom_getsibling(node))) {
258     			child->next = ebus_alloc(sizeof(struct linux_ebus_child));
259     
260     			child = child->next;
261     			child->next = 0;
262     			child->parent = dev;
263     			child->bus = dev->bus;
264     			fill_ebus_child(node, &regs[0],
265     					child, child_regs_nonstandard(dev));
266     		}
267     	}
268     	printk("]");
269     }
270     
271     
272     void __init ebus_init(void)
273     {
274     	struct pci_pbm_info *pbm;
275     	struct linux_ebus_device *dev;
276     	struct linux_ebus *ebus;
277     	struct pci_dev *pdev;
278     	struct pcidev_cookie *cookie;
279     	int nd, ebusnd, is_rio;
280     	int num_ebus = 0;
281     
282     	if (!pci_present())
283     		return;
284     
285     	is_rio = 0;
286     	pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
287     	if (!pdev) {
288     		pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_RIO_EBUS, 0);
289     		is_rio = 1;
290     	}
291     	if (!pdev) {
292     		printk("ebus: No EBus's found.\n");
293     		return;
294     	}
295     
296     	cookie = pdev->sysdata;
297     	ebusnd = cookie->prom_node;
298     
299     	ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
300     	ebus->next = 0;
301     	ebus->is_rio = is_rio;
302     
303     	while (ebusnd) {
304     		/* SUNW,pci-qfe uses four empty ebuses on it.
305     		   I think we should not consider them here,
306     		   as they have half of the properties this
307     		   code expects and once we do PCI hot-plug,
308     		   we'd have to tweak with the ebus_chain
309     		   in the runtime after initialization. -jj */
310     		if (!prom_getchild (ebusnd)) {
311     			struct pci_dev *orig_pdev = pdev;
312     
313     			is_rio = 0;
314     			pdev = pci_find_device(PCI_VENDOR_ID_SUN, 
315     					       PCI_DEVICE_ID_SUN_EBUS, orig_pdev);
316     			if (!pdev) {
317     				pdev = pci_find_device(PCI_VENDOR_ID_SUN, 
318     						       PCI_DEVICE_ID_SUN_RIO_EBUS, orig_pdev);
319     				is_rio = 1;
320     			}
321     			if (!pdev) {
322     				if (ebus == ebus_chain) {
323     					ebus_chain = NULL;
324     					printk("ebus: No EBus's found.\n");
325     					return;
326     				}
327     				break;
328     			}
329     			ebus->is_rio = is_rio;
330     			cookie = pdev->sysdata;
331     			ebusnd = cookie->prom_node;
332     			continue;
333     		}
334     		printk("ebus%d:", num_ebus);
335     
336     		prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name));
337     		ebus->index = num_ebus;
338     		ebus->prom_node = ebusnd;
339     		ebus->self = pdev;
340     		ebus->parent = pbm = cookie->pbm;
341     
342     		ebus_ranges_init(ebus);
343     		ebus_intmap_init(ebus);
344     
345     		nd = prom_getchild(ebusnd);
346     		if (!nd)
347     			goto next_ebus;
348     
349     		ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device));
350     
351     		dev = ebus->devices;
352     		dev->next = 0;
353     		dev->children = 0;
354     		dev->bus = ebus;
355     		fill_ebus_device(nd, dev);
356     
357     		while ((nd = prom_getsibling(nd))) {
358     			dev->next = ebus_alloc(sizeof(struct linux_ebus_device));
359     
360     			dev = dev->next;
361     			dev->next = 0;
362     			dev->children = 0;
363     			dev->bus = ebus;
364     			fill_ebus_device(nd, dev);
365     		}
366     
367     	next_ebus:
368     		printk("\n");
369     
370     		{
371     			struct pci_dev *orig_pdev = pdev;
372     
373     			is_rio = 0;
374     			pdev = pci_find_device(PCI_VENDOR_ID_SUN,
375     					       PCI_DEVICE_ID_SUN_EBUS, orig_pdev);
376     			if (!pdev) {
377     				pdev = pci_find_device(PCI_VENDOR_ID_SUN,
378     						       PCI_DEVICE_ID_SUN_RIO_EBUS, orig_pdev);
379     				is_rio = 1;
380     			}
381     			if (!pdev)
382     				break;
383     		}
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