1 /* $Id: sbus.c,v 1.80 1999/09/02 05:44:33 shadow 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 /* This file has been written to be more dynamic and a bit cleaner,
21 * but it still needs some spring cleaning.
24 struct linux_sbus
*SBus_chain
;
25 static struct linux_prom_irqs irqs
[PROMINTR_MAX
] __initdata
= { { 0 } };
27 static char lbuf
[128];
29 extern void prom_sbus_ranges_init (int, struct linux_sbus
*);
31 /* Perhaps when I figure out more about the iommu we'll put a
32 * device registration routine here that probe_sbus() calls to
33 * setup the iommu for each Sbus.
36 /* We call this for each SBus device, and fill the structure based
37 * upon the prom device tree. We return the start of memory after
38 * the things we have allocated.
41 /* #define DEBUG_FILL */
43 static void __init
fill_sbus_device(int nd
, struct linux_sbus_device
*sbus_dev
)
46 unsigned long dev_base_addr
, base
;
48 sbus_dev
->prom_node
= nd
;
49 prom_getstring(nd
, "name", lbuf
, sizeof(lbuf
));
50 strcpy(sbus_dev
->prom_name
, lbuf
);
52 dev_base_addr
= prom_getint(nd
, "address");
53 if(dev_base_addr
!= -1)
54 sbus_dev
->sbus_addr
= dev_base_addr
;
56 len
= prom_getproperty(nd
, "reg", (void *) sbus_dev
->reg_addrs
,
57 sizeof(sbus_dev
->reg_addrs
));
60 if(len
%sizeof(struct linux_prom_registers
)) {
61 prom_printf("WHOOPS: proplen for %s was %d, need multiple of %d\n",
62 sbus_dev
->prom_name
, len
,
63 (int) sizeof(struct linux_prom_registers
));
64 panic("fill_sbus_device");
66 sbus_dev
->num_registers
= (len
/sizeof(struct linux_prom_registers
));
67 sbus_dev
->ranges_applied
= 0;
69 base
= (unsigned long) sbus_dev
->reg_addrs
[0].phys_addr
;
70 if(base
>=SUN_SBUS_BVADDR
||
71 (sparc_cpu_model
!= sun4c
&&
72 sparc_cpu_model
!= sun4
)) {
73 /* Ahh, we can determine the slot and offset */
74 if(sparc_cpu_model
== sun4u
) {
75 /* A bit tricky on the SYSIO. */
76 sbus_dev
->slot
= sbus_dev
->reg_addrs
[0].which_io
;
77 sbus_dev
->offset
= sbus_dev_offset(base
);
78 } else if (sparc_cpu_model
== sun4d
) {
79 sbus_dev
->slot
= sbus_dev
->reg_addrs
[0].which_io
;
80 sbus_dev
->offset
= base
;
82 sbus_dev
->slot
= sbus_dev_slot(base
);
83 sbus_dev
->offset
= sbus_dev_offset(base
);
85 } else { /* Grrr, gotta do calculations to fix things up */
86 sbus_dev
->slot
= sbus_dev
->reg_addrs
[0].which_io
;
87 sbus_dev
->offset
= base
;
88 sbus_dev
->reg_addrs
[0].phys_addr
=
89 sbus_devaddr(sbus_dev
->slot
, base
);
90 for(grrr
=1; grrr
<sbus_dev
->num_registers
; grrr
++) {
91 base
= (unsigned long) sbus_dev
->reg_addrs
[grrr
].phys_addr
;
92 sbus_dev
->reg_addrs
[grrr
].phys_addr
=
93 sbus_devaddr(sbus_dev
->slot
, base
);
95 /* That surely sucked */
97 sbus_dev
->sbus_addr
= (unsigned long) sbus_dev
->reg_addrs
[0].phys_addr
;
98 if(len
>(sizeof(struct linux_prom_registers
)*PROMREG_MAX
)) {
99 prom_printf("WHOOPS: I got too many register addresses for %s len=%d\n",
100 sbus_dev
->prom_name
, len
);
101 panic("sbus device register overflow");
105 len
= prom_getproperty(nd
, "address", (void *) sbus_dev
->sbus_vaddrs
,
106 sizeof(sbus_dev
->sbus_vaddrs
));
109 prom_printf("Grrr, I didn't get a multiple of 4 proplen "
110 "for device %s got %d\n", sbus_dev
->prom_name
, len
);
113 sbus_dev
->num_vaddrs
= (len
/4);
116 len
= prom_getproperty(nd
, "interrupts", (void *)irqs
, sizeof(irqs
));
117 if((len
== -1) || (len
== 0)) {
118 sbus_dev
->irqs
[0] = 0;
119 sbus_dev
->num_irqs
= 0;
121 sbus_dev
->num_irqs
= 1;
122 if (irqs
[0].pri
< 0x20)
123 sbus_dev
->irqs
[0] = sbus_build_irq(sbus_dev
->my_bus
,
124 irqs
[0].pri
+ (sbus_dev
->slot
* 8));
126 sbus_dev
->irqs
[0] = sbus_build_irq(sbus_dev
->my_bus
,
130 len
= prom_getproperty(nd
, "intr", (void *)irqs
, sizeof(irqs
));
131 if (len
== -1) len
=0;
133 prom_printf("Grrr, I didn't get a multiple of 8 proplen for "
134 "device %s got %d\n", sbus_dev
->prom_name
, len
);
138 prom_printf("Device %s has more than 4 interrupts\n", sbus_dev
->prom_name
);
141 sbus_dev
->num_irqs
=(len
/8);
142 if(sbus_dev
->num_irqs
== 0)
144 else if (sparc_cpu_model
!= sun4d
)
145 for (len
= 0; len
< sbus_dev
->num_irqs
; len
++)
146 sbus_dev
->irqs
[len
] = irqs
[len
].pri
;
148 extern unsigned int sun4d_build_irq(struct linux_sbus_device
*sdev
, int irq
);
150 for (len
= 0; len
< sbus_dev
->num_irqs
; len
++)
151 sbus_dev
->irqs
[len
] = sun4d_build_irq(sbus_dev
, irqs
[len
].pri
);
157 prom_printf("Found %s at SBUS slot %x offset %016lx ",
158 sbus_dev
->prom_name
, sbus_dev
->slot
, sbus_dev
->offset
);
159 if (sbus_dev
->irqs
[0])
160 prom_printf("irq %s\n", __irq_itoa(sbus_dev
->irqs
[0]));
163 prom_printf("Base address %016lx\n", sbus_dev
->sbus_addr
);
165 prom_printf("Found %s at SBUS slot %x offset %08lx irq-level %d\n",
166 sbus_dev
->prom_name
, sbus_dev
->slot
, sbus_dev
->offset
,
168 prom_printf("Base address %08lx\n", sbus_dev
->sbus_addr
);
170 prom_printf("REGISTERS: Probed %d register(s)\n", sbus_dev
->num_registers
);
171 for(len
=0; len
<sbus_dev
->num_registers
; len
++)
173 prom_printf("Regs<%d> at address<%08lx> IO-space<%d> size<%d "
174 "bytes, %d words>\n", (int) len
,
175 (unsigned long) sbus_dev
->reg_addrs
[len
].phys_addr
,
176 sbus_dev
->reg_addrs
[len
].which_io
,
177 sbus_dev
->reg_addrs
[len
].reg_size
,
178 (sbus_dev
->reg_addrs
[len
].reg_size
/4));
180 prom_printf("Regs<%d> at address<%016lx> IO-space<%d> size<%d "
181 "bytes, %d words>\n", (int) len
,
182 (unsigned long) sbus_dev
->reg_addrs
[len
].phys_addr
,
183 sbus_dev
->reg_addrs
[len
].which_io
,
184 sbus_dev
->reg_addrs
[len
].reg_size
,
185 (sbus_dev
->reg_addrs
[len
].reg_size
/4));
190 /* This routine gets called from whoever needs the sbus first, to scan
191 * the SBus device tree. Currently it just prints out the devices
192 * found on the bus and builds trees of SBUS structs and attached
196 extern void iommu_init(int iommu_node
, struct linux_sbus
*sbus
);
197 extern void iounit_init(int sbi_node
, int iounit_node
, struct linux_sbus
*sbus
);
198 void sun4_init(void);
199 #ifdef CONFIG_SUN_OPENPROMIO
200 extern int openprom_init(void);
202 #ifdef CONFIG_SUN_AUXIO
203 extern void auxio_probe(void);
205 #ifdef CONFIG_OBP_FLASH
206 extern int flash_init(void);
208 #ifdef CONFIG_SUN_AURORA
209 extern int aurora_init(void);
211 #ifdef CONFIG_TADPOLE_TS102_UCTRL
212 extern int ts102_uctrl_init(void);
215 static void __init
sbus_do_child_siblings(int start_node
,
216 struct linux_sbus_device
*child
,
217 struct linux_sbus
*sbus
)
219 struct linux_sbus_device
*this_dev
= child
;
220 int this_node
= start_node
;
222 /* Child already filled in, just need to traverse siblings. */
224 while((this_node
= prom_getsibling(this_node
)) != 0) {
225 this_dev
->next
= kmalloc(sizeof(struct linux_sbus_device
), GFP_ATOMIC
);
226 this_dev
= this_dev
->next
;
229 this_dev
->my_bus
= sbus
;
230 fill_sbus_device(this_node
, this_dev
);
232 if(prom_getchild(this_node
)) {
233 this_dev
->child
= kmalloc(sizeof(struct linux_sbus_device
),
235 this_dev
->child
->my_bus
= sbus
;
236 fill_sbus_device(prom_getchild(this_node
), this_dev
->child
);
237 sbus_do_child_siblings(prom_getchild(this_node
),
238 this_dev
->child
, sbus
);
245 void __init
sbus_init(void)
247 register int nd
, this_sbus
, sbus_devs
, topnd
, iommund
;
248 unsigned int sbus_clock
;
249 struct linux_sbus
*sbus
;
250 struct linux_sbus_device
*this_dev
;
251 int num_sbus
= 0; /* How many did we find? */
254 return sun4_dvma_init();
257 topnd
= prom_getchild(prom_root_node
);
259 /* Finding the first sbus is a special case... */
261 if(sparc_cpu_model
== sun4u
) {
262 nd
= prom_searchsiblings(topnd
, "sbus");
265 if (!pcibios_present()) {
266 prom_printf("Neither SBUS nor PCI found.\n");
270 extern void firetruck_init(void);
276 prom_printf("YEEE, UltraSparc sbus not found\n");
280 } else if(sparc_cpu_model
== sun4d
) {
281 if((iommund
= prom_searchsiblings(topnd
, "io-unit")) == 0 ||
282 (nd
= prom_getchild(iommund
)) == 0 ||
283 (nd
= prom_searchsiblings(nd
, "sbi")) == 0) {
284 panic("sbi not found");
286 } else if((nd
= prom_searchsiblings(topnd
, "sbus")) == 0) {
287 if((iommund
= prom_searchsiblings(topnd
, "iommu")) == 0 ||
288 (nd
= prom_getchild(iommund
)) == 0 ||
289 (nd
= prom_searchsiblings(nd
, "sbus")) == 0) {
291 if (!pcibios_present()) {
292 prom_printf("Neither SBUS nor PCI found.\n");
297 /* No reason to run further - the data access trap will occur. */
298 panic("sbus not found");
303 /* Ok, we've found the first one, allocate first SBus struct
304 * and place in chain.
306 sbus
= SBus_chain
= kmalloc(sizeof(struct linux_sbus
), GFP_ATOMIC
);
308 sbus
->prom_node
= nd
;
311 if(iommund
&& sparc_cpu_model
!= sun4u
&& sparc_cpu_model
!= sun4d
)
312 iommu_init(iommund
, sbus
);
314 /* Loop until we find no more SBUS's */
316 /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
317 if(sparc_cpu_model
== sun4u
)
318 iommu_init(this_sbus
, sbus
);
320 else if (sparc_cpu_model
== sun4d
)
321 iounit_init(this_sbus
, iommund
, sbus
);
323 printk("sbus%d: ", num_sbus
);
324 sbus_clock
= prom_getint(this_sbus
, "clock-frequency");
325 if(sbus_clock
==-1) sbus_clock
= (25*1000*1000);
326 printk("Clock %d.%d MHz\n", (int) ((sbus_clock
/1000)/1000),
327 (int) (((sbus_clock
/1000)%1000 != 0) ?
328 (((sbus_clock
/1000)%1000) + 1000) : 0));
330 prom_getstring(this_sbus
, "name", lbuf
, sizeof(lbuf
));
331 lbuf
[sizeof(sbus
->prom_name
) - 1] = 0;
332 strcpy(sbus
->prom_name
, lbuf
);
333 sbus
->clock_freq
= sbus_clock
;
335 if (sparc_cpu_model
== sun4d
) {
336 sbus
->devid
= prom_getint(iommund
, "device-id");
337 sbus
->board
= prom_getint(iommund
, "board#");
341 prom_sbus_ranges_init (iommund
, sbus
);
343 sbus_devs
= prom_getchild(this_sbus
);
345 sbus
->devices
= kmalloc(sizeof(struct linux_sbus_device
), GFP_ATOMIC
);
347 this_dev
= sbus
->devices
;
350 this_dev
->my_bus
= sbus
;
351 fill_sbus_device(sbus_devs
, this_dev
);
353 /* Should we traverse for children? */
354 if(prom_getchild(sbus_devs
)) {
355 /* Allocate device node */
356 this_dev
->child
= kmalloc(sizeof(struct linux_sbus_device
),
359 this_dev
->child
->my_bus
= sbus
;
360 fill_sbus_device(prom_getchild(sbus_devs
), this_dev
->child
);
361 sbus_do_child_siblings(prom_getchild(sbus_devs
),
362 this_dev
->child
, sbus
);
367 while((sbus_devs
= prom_getsibling(sbus_devs
)) != 0) {
368 /* Allocate device node */
369 this_dev
->next
= kmalloc(sizeof(struct linux_sbus_device
),
371 this_dev
=this_dev
->next
;
375 this_dev
->my_bus
= sbus
;
376 fill_sbus_device(sbus_devs
, this_dev
);
378 /* Is there a child node hanging off of us? */
379 if(prom_getchild(sbus_devs
)) {
380 /* Get new device struct */
382 kmalloc(sizeof(struct linux_sbus_device
),
385 this_dev
->child
->my_bus
= sbus
;
386 fill_sbus_device(prom_getchild(sbus_devs
),
388 sbus_do_child_siblings(prom_getchild(sbus_devs
),
389 this_dev
->child
, sbus
);
398 if(sparc_cpu_model
== sun4u
) {
399 this_sbus
= prom_getsibling(this_sbus
);
402 this_sbus
= prom_searchsiblings(this_sbus
, "sbus");
403 } else if(sparc_cpu_model
== sun4d
) {
404 iommund
= prom_getsibling(iommund
);
406 iommund
= prom_searchsiblings(iommund
, "io-unit");
408 this_sbus
= prom_searchsiblings(prom_getchild(iommund
), "sbi");
410 this_sbus
= prom_getsibling(this_sbus
);
411 if(!this_sbus
) break;
412 this_sbus
= prom_searchsiblings(this_sbus
, "sbus");
415 sbus
->next
= kmalloc(sizeof(struct linux_sbus
), GFP_ATOMIC
);
418 sbus
->prom_node
= this_sbus
;
422 } /* while(this_sbus) */
423 if (sparc_cpu_model
== sun4d
) {
424 extern void sun4d_init_sbi_irq(void);
425 sun4d_init_sbi_irq();
429 if (sparc_cpu_model
== sun4u
) {
430 extern void firetruck_init(void);
435 #ifdef CONFIG_SUN_OPENPROMIO
438 #ifdef CONFIG_SUN_BPP
441 #ifdef CONFIG_SUN_AUXIO
442 if (sparc_cpu_model
== sun4u
)
445 #ifdef CONFIG_OBP_FLASH
448 #ifdef CONFIG_SUN_AURORA
451 #ifdef CONFIG_TADPOLE_TS102_UCTRL
455 if (sparc_cpu_model
== sun4u
) {
456 extern void clock_probe(void);