1 /* $Id: sbus.c,v 1.86 2000/03/16 09:23:57 jj Exp $
2 * sbus.c: SBus support routines.
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
7 #include <linux/kernel.h>
8 #include <linux/malloc.h>
9 #include <linux/config.h>
10 #include <linux/init.h>
11 #include <linux/pci.h>
13 #include <asm/system.h>
16 #include <asm/oplib.h>
20 struct sbus_bus
*sbus_root
= NULL
;
22 static struct linux_prom_irqs irqs
[PROMINTR_MAX
] __initdata
= { { 0 } };
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.
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.
34 /* #define DEBUG_FILL */
36 static void __init
fill_sbus_device(int prom_node
, struct sbus_dev
*sdev
)
38 unsigned long address
, base
;
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
));
49 sdev
->num_registers
= 0;
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",
57 (int) sizeof(struct linux_prom_registers
));
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
);
66 sdev
->num_registers
= len
/ sizeof(struct linux_prom_registers
);
67 sdev
->ranges_applied
= 0;
69 base
= (unsigned long) sdev
->reg_addrs
[0].phys_addr
;
70 if (base
>= SUN_SBUS_BVADDR
||
71 (sparc_cpu_model
!= sun4c
&& sparc_cpu_model
!= sun4
)) {
72 /* OK, we can compute the slot number in a
73 * straightforward manner.
75 if (sparc_cpu_model
== sun4u
||
76 sparc_cpu_model
== sun4d
)
77 sdev
->slot
= sdev
->reg_addrs
[0].which_io
;
79 sdev
->slot
= sbus_dev_slot(base
);
83 /* Fixups are needed to compute the slot number. */
84 sdev
->slot
= sdev
->reg_addrs
[0].which_io
;
85 sdev
->reg_addrs
[0].phys_addr
=
86 sbus_devaddr(sdev
->slot
, base
);
87 for (rnum
= 1; rnum
< sdev
->num_registers
; rnum
++) {
88 base
= (unsigned long)
89 sdev
->reg_addrs
[rnum
].phys_addr
;
90 sdev
->reg_addrs
[rnum
].phys_addr
=
91 sbus_devaddr(sdev
->slot
, base
);
96 len
= prom_getproperty(prom_node
, "ranges",
97 (char *)sdev
->device_ranges
,
98 sizeof(sdev
->device_ranges
));
100 sdev
->num_device_ranges
= 0;
103 if (len
% sizeof(struct linux_prom_ranges
)) {
104 prom_printf("fill_sbus_device: proplen for ranges of %s "
105 " was %d, need multiple of %d\n",
106 sdev
->prom_name
, len
,
107 (int) sizeof(struct linux_prom_ranges
));
110 if (len
> (sizeof(struct linux_prom_ranges
) * PROMREG_MAX
)) {
111 prom_printf("fill_sbus_device: Too many range properties "
112 "for device %s, len=%d\n",
113 sdev
->prom_name
, len
);
116 sdev
->num_device_ranges
=
117 len
/ sizeof(struct linux_prom_ranges
);
120 /* XXX Unfortunately, IRQ issues are very arch specific.
121 * XXX Pull this crud out into an arch specific area
122 * XXX at some point. -DaveM
125 len
= prom_getproperty(prom_node
, "interrupts",
126 (char *) irqs
, sizeof(irqs
));
127 if (len
== -1 || len
== 0) {
131 unsigned int pri
= irqs
[0].pri
;
135 pri
+= sdev
->slot
* 8;
137 sdev
->irqs
[0] = sbus_build_irq(sdev
->bus
, pri
);
140 len
= prom_getproperty(prom_node
, "intr",
141 (char *)irqs
, sizeof(irqs
));
144 sdev
->num_irqs
= len
/ 8;
145 if (sdev
->num_irqs
== 0) {
147 } else if (sparc_cpu_model
== sun4d
) {
148 extern unsigned int sun4d_build_irq(struct sbus_dev
*sdev
, int irq
);
150 for (len
= 0; len
< sdev
->num_irqs
; len
++)
151 sdev
->irqs
[len
] = sun4d_build_irq(sdev
, irqs
[len
].pri
);
153 for (len
= 0; len
< sdev
->num_irqs
; len
++)
154 sdev
->irqs
[len
] = irqs
[len
].pri
;
156 #endif /* !__sparc_v9__ */
159 /* This routine gets called from whoever needs the sbus first, to scan
160 * the SBus device tree. Currently it just prints out the devices
161 * found on the bus and builds trees of SBUS structs and attached
165 extern void iommu_init(int iommu_node
, struct sbus_bus
*sbus
);
166 extern void iounit_init(int sbi_node
, int iounit_node
, struct sbus_bus
*sbus
);
167 void sun4_init(void);
168 #ifdef CONFIG_SUN_OPENPROMIO
169 extern int openprom_init(void);
171 #ifdef CONFIG_SUN_AUXIO
172 extern void auxio_probe(void);
174 #ifdef CONFIG_OBP_FLASH
175 extern int flash_init(void);
177 #ifdef CONFIG_SUN_AURORA
178 extern int aurora_init(void);
180 #ifdef CONFIG_TADPOLE_TS102_UCTRL
181 extern int ts102_uctrl_init(void);
184 static void __init
sbus_do_child_siblings(int start_node
,
185 struct sbus_dev
*child
,
186 struct sbus_dev
*parent
,
187 struct sbus_bus
*sbus
)
189 struct sbus_dev
*this_dev
= child
;
190 int this_node
= start_node
;
192 /* Child already filled in, just need to traverse siblings. */
194 child
->parent
= parent
;
195 while((this_node
= prom_getsibling(this_node
)) != 0) {
196 this_dev
->next
= kmalloc(sizeof(struct sbus_dev
), GFP_ATOMIC
);
197 this_dev
= this_dev
->next
;
199 this_dev
->parent
= parent
;
201 this_dev
->bus
= sbus
;
202 fill_sbus_device(this_node
, this_dev
);
204 if(prom_getchild(this_node
)) {
205 this_dev
->child
= kmalloc(sizeof(struct sbus_dev
),
207 this_dev
->child
->bus
= sbus
;
208 this_dev
->child
->next
= 0;
209 fill_sbus_device(prom_getchild(this_node
), this_dev
->child
);
210 sbus_do_child_siblings(prom_getchild(this_node
),
211 this_dev
->child
, this_dev
, sbus
);
213 this_dev
->child
= NULL
;
219 * XXX This functions appears to be a distorted version of
220 * prom_sbus_ranges_init(), with all sun4d stuff cut away.
221 * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
223 static void __init
sbus_bus_ranges_init(int parent_node
, struct sbus_bus
*sbus
)
227 len
= prom_getproperty(sbus
->prom_node
, "ranges",
228 (char *) sbus
->sbus_ranges
,
229 sizeof(sbus
->sbus_ranges
));
230 if (len
== -1 || len
== 0) {
231 sbus
->num_sbus_ranges
= 0;
234 sbus
->num_sbus_ranges
= len
/ sizeof(struct linux_prom_ranges
);
237 static void __init
__apply_ranges_to_regs(struct linux_prom_ranges
*ranges
,
239 struct linux_prom_registers
*regs
,
245 for (regnum
= 0; regnum
< num_regs
; regnum
++) {
248 for (rngnum
= 0; rngnum
< num_ranges
; rngnum
++) {
249 if (regs
[regnum
].which_io
== ranges
[rngnum
].ot_child_space
)
252 if (rngnum
== num_ranges
) {
253 prom_printf("sbus_apply_ranges: Cannot find matching "
254 "range nregs[%d] nranges[%d].\n",
255 num_regs
, num_ranges
);
258 regs
[regnum
].which_io
= ranges
[rngnum
].ot_parent_space
;
259 regs
[regnum
].phys_addr
+= ranges
[rngnum
].ot_parent_base
;
264 static void __init
__fixup_regs_sdev(struct sbus_dev
*sdev
)
266 if (sdev
->num_registers
!= 0) {
267 struct sbus_dev
*parent
= sdev
->parent
;
270 while (parent
!= NULL
) {
271 __apply_ranges_to_regs(parent
->device_ranges
,
272 parent
->num_device_ranges
,
274 sdev
->num_registers
);
276 parent
= parent
->parent
;
279 __apply_ranges_to_regs(sdev
->bus
->sbus_ranges
,
280 sdev
->bus
->num_sbus_ranges
,
282 sdev
->num_registers
);
284 for (i
= 0; i
< sdev
->num_registers
; i
++) {
285 struct resource
*res
= &sdev
->resource
[i
];
287 res
->start
= sdev
->reg_addrs
[i
].phys_addr
;
288 res
->end
= (res
->start
+
289 (unsigned long)sdev
->reg_addrs
[i
].reg_size
- 1UL);
290 res
->flags
= IORESOURCE_IO
|
291 (sdev
->reg_addrs
[i
].which_io
& 0xff);
296 static void __init
sbus_fixup_all_regs(struct sbus_dev
*first_sdev
)
298 struct sbus_dev
*sdev
;
300 for (sdev
= first_sdev
; sdev
; sdev
= sdev
->next
) {
302 sbus_fixup_all_regs(sdev
->child
);
303 __fixup_regs_sdev(sdev
);
307 extern void register_proc_sparc_ioport(void);
309 void __init
sbus_init(void)
311 int nd
, this_sbus
, sbus_devs
, topnd
, iommund
;
312 unsigned int sbus_clock
;
313 struct sbus_bus
*sbus
;
314 struct sbus_dev
*this_dev
;
315 int num_sbus
= 0; /* How many did we find? */
318 register_proc_sparc_ioport();
322 return sun4_dvma_init();
325 topnd
= prom_getchild(prom_root_node
);
327 /* Finding the first sbus is a special case... */
329 if(sparc_cpu_model
== sun4u
) {
330 nd
= prom_searchsiblings(topnd
, "sbus");
333 if (!pcibios_present()) {
334 prom_printf("Neither SBUS nor PCI found.\n");
338 extern void firetruck_init(void);
344 prom_printf("YEEE, UltraSparc sbus not found\n");
348 } else if(sparc_cpu_model
== sun4d
) {
349 if((iommund
= prom_searchsiblings(topnd
, "io-unit")) == 0 ||
350 (nd
= prom_getchild(iommund
)) == 0 ||
351 (nd
= prom_searchsiblings(nd
, "sbi")) == 0) {
352 panic("sbi not found");
354 } else if((nd
= prom_searchsiblings(topnd
, "sbus")) == 0) {
355 if((iommund
= prom_searchsiblings(topnd
, "iommu")) == 0 ||
356 (nd
= prom_getchild(iommund
)) == 0 ||
357 (nd
= prom_searchsiblings(nd
, "sbus")) == 0) {
359 if (!pcibios_present()) {
360 prom_printf("Neither SBUS nor PCI found.\n");
365 /* No reason to run further - the data access trap will occur. */
366 panic("sbus not found");
371 /* Ok, we've found the first one, allocate first SBus struct
372 * and place in chain.
374 sbus
= sbus_root
= kmalloc(sizeof(struct sbus_bus
), GFP_ATOMIC
);
376 sbus
->prom_node
= nd
;
379 if(iommund
&& sparc_cpu_model
!= sun4u
&& sparc_cpu_model
!= sun4d
)
380 iommu_init(iommund
, sbus
);
382 /* Loop until we find no more SBUS's */
385 /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
386 if(sparc_cpu_model
== sun4u
) {
387 extern void sbus_iommu_init(int prom_node
, struct sbus_bus
*sbus
);
389 sbus_iommu_init(this_sbus
, sbus
);
393 if (sparc_cpu_model
== sun4d
)
394 iounit_init(this_sbus
, iommund
, sbus
);
396 printk("sbus%d: ", num_sbus
);
397 sbus_clock
= prom_getint(this_sbus
, "clock-frequency");
399 sbus_clock
= (25*1000*1000);
400 printk("Clock %d.%d MHz\n", (int) ((sbus_clock
/1000)/1000),
401 (int) (((sbus_clock
/1000)%1000 != 0) ?
402 (((sbus_clock
/1000)%1000) + 1000) : 0));
404 prom_getstring(this_sbus
, "name",
405 sbus
->prom_name
, sizeof(sbus
->prom_name
));
406 sbus
->clock_freq
= sbus_clock
;
408 if (sparc_cpu_model
== sun4d
) {
409 sbus
->devid
= prom_getint(iommund
, "device-id");
410 sbus
->board
= prom_getint(iommund
, "board#");
414 sbus_bus_ranges_init(iommund
, sbus
);
416 sbus_devs
= prom_getchild(this_sbus
);
418 sbus
->devices
= kmalloc(sizeof(struct sbus_dev
), GFP_ATOMIC
);
420 this_dev
= sbus
->devices
;
421 this_dev
->next
= NULL
;
423 this_dev
->bus
= sbus
;
424 this_dev
->parent
= NULL
;
425 fill_sbus_device(sbus_devs
, this_dev
);
427 /* Should we traverse for children? */
428 if(prom_getchild(sbus_devs
)) {
429 /* Allocate device node */
430 this_dev
->child
= kmalloc(sizeof(struct sbus_dev
),
433 this_dev
->child
->bus
= sbus
;
434 this_dev
->child
->next
= 0;
435 fill_sbus_device(prom_getchild(sbus_devs
),
437 sbus_do_child_siblings(prom_getchild(sbus_devs
),
442 this_dev
->child
= NULL
;
445 while((sbus_devs
= prom_getsibling(sbus_devs
)) != 0) {
446 /* Allocate device node */
447 this_dev
->next
= kmalloc(sizeof(struct sbus_dev
),
449 this_dev
= this_dev
->next
;
450 this_dev
->next
= NULL
;
453 this_dev
->bus
= sbus
;
454 this_dev
->parent
= NULL
;
455 fill_sbus_device(sbus_devs
, this_dev
);
457 /* Is there a child node hanging off of us? */
458 if(prom_getchild(sbus_devs
)) {
459 /* Get new device struct */
460 this_dev
->child
= kmalloc(sizeof(struct sbus_dev
),
463 this_dev
->child
->bus
= sbus
;
464 this_dev
->child
->next
= 0;
465 fill_sbus_device(prom_getchild(sbus_devs
),
467 sbus_do_child_siblings(prom_getchild(sbus_devs
),
472 this_dev
->child
= NULL
;
476 /* Walk all devices and apply parent ranges. */
477 sbus_fixup_all_regs(sbus
->devices
);
482 if(sparc_cpu_model
== sun4u
) {
483 this_sbus
= prom_getsibling(this_sbus
);
486 this_sbus
= prom_searchsiblings(this_sbus
, "sbus");
487 } else if(sparc_cpu_model
== sun4d
) {
488 iommund
= prom_getsibling(iommund
);
491 iommund
= prom_searchsiblings(iommund
, "io-unit");
494 this_sbus
= prom_searchsiblings(prom_getchild(iommund
), "sbi");
496 this_sbus
= prom_getsibling(this_sbus
);
499 this_sbus
= prom_searchsiblings(this_sbus
, "sbus");
502 sbus
->next
= kmalloc(sizeof(struct sbus_bus
), GFP_ATOMIC
);
505 sbus
->prom_node
= this_sbus
;
509 } /* while(this_sbus) */
511 if (sparc_cpu_model
== sun4d
) {
512 extern void sun4d_init_sbi_irq(void);
513 sun4d_init_sbi_irq();
517 if (sparc_cpu_model
== sun4u
) {
518 extern void firetruck_init(void);
523 #ifdef CONFIG_SUN_OPENPROMIO
526 #ifdef CONFIG_SUN_BPP
529 #ifdef CONFIG_SUN_AUXIO
530 if (sparc_cpu_model
== sun4u
)
533 #ifdef CONFIG_OBP_FLASH
536 #ifdef CONFIG_SUN_AURORA
539 #ifdef CONFIG_TADPOLE_TS102_UCTRL
543 if (sparc_cpu_model
== sun4u
) {
544 extern void clock_probe(void);