File: /usr/src/linux/drivers/sbus/sbus.c
1 /* $Id: sbus.c,v 1.95 2001/03/15 02:11:10 davem Exp $
2 * sbus.c: SBus support routines.
3 *
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 */
6
7 #include <linux/kernel.h>
8 #include <linux/slab.h>
9 #include <linux/config.h>
10 #include <linux/init.h>
11 #include <linux/pci.h>
12
13 #include <asm/system.h>
14 #include <asm/sbus.h>
15 #include <asm/dma.h>
16 #include <asm/oplib.h>
17 #include <asm/bpp.h>
18 #include <asm/irq.h>
19
20 struct sbus_bus *sbus_root = NULL;
21
22 static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } };
23
24 /* Perhaps when I figure out more about the iommu we'll put a
25 * device registration routine here that probe_sbus() calls to
26 * setup the iommu for each Sbus.
27 */
28
29 /* We call this for each SBus device, and fill the structure based
30 * upon the prom device tree. We return the start of memory after
31 * the things we have allocated.
32 */
33
34 /* #define DEBUG_FILL */
35
36 static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
37 {
38 unsigned long address, base;
39 int len;
40
41 sdev->prom_node = prom_node;
42 prom_getstring(prom_node, "name",
43 sdev->prom_name, sizeof(sdev->prom_name));
44 address = prom_getint(prom_node, "address");
45 len = prom_getproperty(prom_node, "reg",
46 (char *) sdev->reg_addrs,
47 sizeof(sdev->reg_addrs));
48 if (len == -1) {
49 sdev->num_registers = 0;
50 goto no_regs;
51 }
52
53 if (len % sizeof(struct linux_prom_registers)) {
54 prom_printf("fill_sbus_device: proplen for regs of %s "
55 " was %d, need multiple of %d\n",
56 sdev->prom_name, len,
57 (int) sizeof(struct linux_prom_registers));
58 prom_halt();
59 }
60 if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) {
61 prom_printf("fill_sbus_device: Too many register properties "
62 "for device %s, len=%d\n",
63 sdev->prom_name, len);
64 prom_halt();
65 }
66 sdev->num_registers = len / sizeof(struct linux_prom_registers);
67 sdev->ranges_applied = 0;
68
69 base = (unsigned long) sdev->reg_addrs[0].phys_addr;
70
71 /* Compute the slot number. */
72 if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) {
73 sdev->slot = sbus_dev_slot(base);
74 } else {
75 sdev->slot = sdev->reg_addrs[0].which_io;
76 }
77
78 no_regs:
79 len = prom_getproperty(prom_node, "ranges",
80 (char *)sdev->device_ranges,
81 sizeof(sdev->device_ranges));
82 if (len == -1) {
83 sdev->num_device_ranges = 0;
84 goto no_ranges;
85 }
86 if (len % sizeof(struct linux_prom_ranges)) {
87 prom_printf("fill_sbus_device: proplen for ranges of %s "
88 " was %d, need multiple of %d\n",
89 sdev->prom_name, len,
90 (int) sizeof(struct linux_prom_ranges));
91 prom_halt();
92 }
93 if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) {
94 prom_printf("fill_sbus_device: Too many range properties "
95 "for device %s, len=%d\n",
96 sdev->prom_name, len);
97 prom_halt();
98 }
99 sdev->num_device_ranges =
100 len / sizeof(struct linux_prom_ranges);
101
102 no_ranges:
103 /* XXX Unfortunately, IRQ issues are very arch specific.
104 * XXX Pull this crud out into an arch specific area
105 * XXX at some point. -DaveM
106 */
107 #ifdef __sparc_v9__
108 len = prom_getproperty(prom_node, "interrupts",
109 (char *) irqs, sizeof(irqs));
110 if (len == -1 || len == 0) {
111 sdev->irqs[0] = 0;
112 sdev->num_irqs = 0;
113 } else {
114 unsigned int pri = irqs[0].pri;
115
116 sdev->num_irqs = 1;
117 if (pri < 0x20)
118 pri += sdev->slot * 8;
119
120 sdev->irqs[0] = sbus_build_irq(sdev->bus, pri);
121 }
122 #else
123 len = prom_getproperty(prom_node, "intr",
124 (char *)irqs, sizeof(irqs));
125 if (len == -1)
126 len = 0;
127 sdev->num_irqs = len / 8;
128 if (sdev->num_irqs == 0) {
129 sdev->irqs[0] = 0;
130 } else if (sparc_cpu_model == sun4d) {
131 extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
132
133 for (len = 0; len < sdev->num_irqs; len++)
134 sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
135 } else {
136 for (len = 0; len < sdev->num_irqs; len++)
137 sdev->irqs[len] = irqs[len].pri;
138 }
139 #endif /* !__sparc_v9__ */
140 }
141
142 /* This routine gets called from whoever needs the sbus first, to scan
143 * the SBus device tree. Currently it just prints out the devices
144 * found on the bus and builds trees of SBUS structs and attached
145 * devices.
146 */
147
148 extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
149 extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus);
150 void sun4_init(void);
151 #ifdef CONFIG_SUN_AUXIO
152 extern void auxio_probe(void);
153 #endif
154
155 static void __init sbus_do_child_siblings(int start_node,
156 struct sbus_dev *child,
157 struct sbus_dev *parent,
158 struct sbus_bus *sbus)
159 {
160 struct sbus_dev *this_dev = child;
161 int this_node = start_node;
162
163 /* Child already filled in, just need to traverse siblings. */
164 child->child = NULL;
165 child->parent = parent;
166 while((this_node = prom_getsibling(this_node)) != 0) {
167 this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
168 this_dev = this_dev->next;
169 this_dev->next = 0;
170 this_dev->parent = parent;
171
172 this_dev->bus = sbus;
173 fill_sbus_device(this_node, this_dev);
174
175 if(prom_getchild(this_node)) {
176 this_dev->child = kmalloc(sizeof(struct sbus_dev),
177 GFP_ATOMIC);
178 this_dev->child->bus = sbus;
179 this_dev->child->next = 0;
180 fill_sbus_device(prom_getchild(this_node), this_dev->child);
181 sbus_do_child_siblings(prom_getchild(this_node),
182 this_dev->child, this_dev, sbus);
183 } else {
184 this_dev->child = NULL;
185 }
186 }
187 }
188
189 /*
190 * XXX This functions appears to be a distorted version of
191 * prom_sbus_ranges_init(), with all sun4d stuff cut away.
192 * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
193 */
194 static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus)
195 {
196 int len;
197
198 len = prom_getproperty(sbus->prom_node, "ranges",
199 (char *) sbus->sbus_ranges,
200 sizeof(sbus->sbus_ranges));
201 if (len == -1 || len == 0) {
202 sbus->num_sbus_ranges = 0;
203 return;
204 }
205 sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges);
206 }
207
208 static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
209 int num_ranges,
210 struct linux_prom_registers *regs,
211 int num_regs)
212 {
213 if (num_ranges) {
214 int regnum;
215
216 for (regnum = 0; regnum < num_regs; regnum++) {
217 int rngnum;
218
219 for (rngnum = 0; rngnum < num_ranges; rngnum++) {
220 if (regs[regnum].which_io == ranges[rngnum].ot_child_space)
221 break;
222 }
223 if (rngnum == num_ranges) {
224 /* We used to flag this as an error. Actually
225 * some devices do not report the regs as we expect.
226 * For example, see SUNW,pln device. In that case
227 * the reg property is in a format internal to that
228 * node, ie. it is not in the SBUS register space
229 * per se. -DaveM
230 */
231 return;
232 }
233 regs[regnum].which_io = ranges[rngnum].ot_parent_space;
234 regs[regnum].phys_addr += ranges[rngnum].ot_parent_base;
235 }
236 }
237 }
238
239 static void __init __fixup_regs_sdev(struct sbus_dev *sdev)
240 {
241 if (sdev->num_registers != 0) {
242 struct sbus_dev *parent = sdev->parent;
243 int i;
244
245 while (parent != NULL) {
246 __apply_ranges_to_regs(parent->device_ranges,
247 parent->num_device_ranges,
248 sdev->reg_addrs,
249 sdev->num_registers);
250
251 parent = parent->parent;
252 }
253
254 __apply_ranges_to_regs(sdev->bus->sbus_ranges,
255 sdev->bus->num_sbus_ranges,
256 sdev->reg_addrs,
257 sdev->num_registers);
258
259 for (i = 0; i < sdev->num_registers; i++) {
260 struct resource *res = &sdev->resource[i];
261
262 res->start = sdev->reg_addrs[i].phys_addr;
263 res->end = (res->start +
264 (unsigned long)sdev->reg_addrs[i].reg_size - 1UL);
265 res->flags = IORESOURCE_IO |
266 (sdev->reg_addrs[i].which_io & 0xff);
267 }
268 }
269 }
270
271 static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev)
272 {
273 struct sbus_dev *sdev;
274
275 for (sdev = first_sdev; sdev; sdev = sdev->next) {
276 if (sdev->child)
277 sbus_fixup_all_regs(sdev->child);
278 __fixup_regs_sdev(sdev);
279 }
280 }
281
282 extern void register_proc_sparc_ioport(void);
283 extern void firetruck_init(void);
284 extern void rs_init(void);
285
286 void __init sbus_init(void)
287 {
288 int nd, this_sbus, sbus_devs, topnd, iommund;
289 unsigned int sbus_clock;
290 struct sbus_bus *sbus;
291 struct sbus_dev *this_dev;
292 int num_sbus = 0; /* How many did we find? */
293
294 #ifndef __sparc_v9__
295 register_proc_sparc_ioport();
296 #endif
297
298 #ifdef CONFIG_SUN4
299 return sun4_dvma_init();
300 #endif
301
302 topnd = prom_getchild(prom_root_node);
303
304 /* Finding the first sbus is a special case... */
305 iommund = 0;
306 if(sparc_cpu_model == sun4u) {
307 nd = prom_searchsiblings(topnd, "sbus");
308 if(nd == 0) {
309 #ifdef CONFIG_PCI
310 if (!pcibios_present()) {
311 prom_printf("Neither SBUS nor PCI found.\n");
312 prom_halt();
313 } else {
314 #ifdef __sparc_v9__
315 firetruck_init();
316 #endif
317 }
318 return;
319 #else
320 prom_printf("YEEE, UltraSparc sbus not found\n");
321 prom_halt();
322 #endif
323 }
324 } else if(sparc_cpu_model == sun4d) {
325 if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 ||
326 (nd = prom_getchild(iommund)) == 0 ||
327 (nd = prom_searchsiblings(nd, "sbi")) == 0) {
328 panic("sbi not found");
329 }
330 } else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) {
331 if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 ||
332 (nd = prom_getchild(iommund)) == 0 ||
333 (nd = prom_searchsiblings(nd, "sbus")) == 0) {
334 #ifdef CONFIG_PCI
335 if (!pcibios_present()) {
336 prom_printf("Neither SBUS nor PCI found.\n");
337 prom_halt();
338 }
339 return;
340 #else
341 /* No reason to run further - the data access trap will occur. */
342 panic("sbus not found");
343 #endif
344 }
345 }
346
347 /* Ok, we've found the first one, allocate first SBus struct
348 * and place in chain.
349 */
350 sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
351 sbus->next = NULL;
352 sbus->prom_node = nd;
353 this_sbus = nd;
354
355 if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d)
356 iommu_init(iommund, sbus);
357
358 /* Loop until we find no more SBUS's */
359 while(this_sbus) {
360 #ifdef __sparc_v9__
361 /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
362 if(sparc_cpu_model == sun4u) {
363 extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus);
364
365 sbus_iommu_init(this_sbus, sbus);
366 }
367 #endif
368 #ifndef __sparc_v9__
369 if (sparc_cpu_model == sun4d)
370 iounit_init(this_sbus, iommund, sbus);
371 #endif
372 printk("sbus%d: ", num_sbus);
373 sbus_clock = prom_getint(this_sbus, "clock-frequency");
374 if(sbus_clock == -1)
375 sbus_clock = (25*1000*1000);
376 printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000),
377 (int) (((sbus_clock/1000)%1000 != 0) ?
378 (((sbus_clock/1000)%1000) + 1000) : 0));
379
380 prom_getstring(this_sbus, "name",
381 sbus->prom_name, sizeof(sbus->prom_name));
382 sbus->clock_freq = sbus_clock;
383 #ifndef __sparc_v9__
384 if (sparc_cpu_model == sun4d) {
385 sbus->devid = prom_getint(iommund, "device-id");
386 sbus->board = prom_getint(iommund, "board#");
387 }
388 #endif
389
390 sbus_bus_ranges_init(iommund, sbus);
391
392 sbus_devs = prom_getchild(this_sbus);
393
394 sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
395
396 this_dev = sbus->devices;
397 this_dev->next = NULL;
398
399 this_dev->bus = sbus;
400 this_dev->parent = NULL;
401 fill_sbus_device(sbus_devs, this_dev);
402
403 /* Should we traverse for children? */
404 if(prom_getchild(sbus_devs)) {
405 /* Allocate device node */
406 this_dev->child = kmalloc(sizeof(struct sbus_dev),
407 GFP_ATOMIC);
408 /* Fill it */
409 this_dev->child->bus = sbus;
410 this_dev->child->next = 0;
411 fill_sbus_device(prom_getchild(sbus_devs),
412 this_dev->child);
413 sbus_do_child_siblings(prom_getchild(sbus_devs),
414 this_dev->child,
415 this_dev,
416 sbus);
417 } else {
418 this_dev->child = NULL;
419 }
420
421 while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
422 /* Allocate device node */
423 this_dev->next = kmalloc(sizeof(struct sbus_dev),
424 GFP_ATOMIC);
425 this_dev = this_dev->next;
426 this_dev->next = NULL;
427
428 /* Fill it */
429 this_dev->bus = sbus;
430 this_dev->parent = NULL;
431 fill_sbus_device(sbus_devs, this_dev);
432
433 /* Is there a child node hanging off of us? */
434 if(prom_getchild(sbus_devs)) {
435 /* Get new device struct */
436 this_dev->child = kmalloc(sizeof(struct sbus_dev),
437 GFP_ATOMIC);
438 /* Fill it */
439 this_dev->child->bus = sbus;
440 this_dev->child->next = 0;
441 fill_sbus_device(prom_getchild(sbus_devs),
442 this_dev->child);
443 sbus_do_child_siblings(prom_getchild(sbus_devs),
444 this_dev->child,
445 this_dev,
446 sbus);
447 } else {
448 this_dev->child = NULL;
449 }
450 }
451
452 /* Walk all devices and apply parent ranges. */
453 sbus_fixup_all_regs(sbus->devices);
454
455 dvma_init(sbus);
456
457 num_sbus++;
458 if(sparc_cpu_model == sun4u) {
459 this_sbus = prom_getsibling(this_sbus);
460 if(!this_sbus)
461 break;
462 this_sbus = prom_searchsiblings(this_sbus, "sbus");
463 } else if(sparc_cpu_model == sun4d) {
464 iommund = prom_getsibling(iommund);
465 if(!iommund)
466 break;
467 iommund = prom_searchsiblings(iommund, "io-unit");
468 if(!iommund)
469 break;
470 this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi");
471 } else {
472 this_sbus = prom_getsibling(this_sbus);
473 if(!this_sbus)
474 break;
475 this_sbus = prom_searchsiblings(this_sbus, "sbus");
476 }
477 if(this_sbus) {
478 sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
479 sbus = sbus->next;
480 sbus->next = NULL;
481 sbus->prom_node = this_sbus;
482 } else {
483 break;
484 }
485 } /* while(this_sbus) */
486
487 if (sparc_cpu_model == sun4d) {
488 extern void sun4d_init_sbi_irq(void);
489 sun4d_init_sbi_irq();
490 }
491
492 rs_init();
493
494 #ifdef __sparc_v9__
495 if (sparc_cpu_model == sun4u) {
496 firetruck_init();
497 }
498 #endif
499 #ifdef CONFIG_SUN_AUXIO
500 if (sparc_cpu_model == sun4u)
501 auxio_probe ();
502 #endif
503 #ifdef __sparc_v9__
504 if (sparc_cpu_model == sun4u) {
505 extern void clock_probe(void);
506
507 clock_probe();
508 }
509 #endif
510 }
511