* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / sbus / sbus.c
blobad7825c898afbc9801274e24b5e64676e93b3139
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)
5 */
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>
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>
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)
45 int grrr, len;
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));
58 if(len == -1)
59 goto no_regs;
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;
81 } else {
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");
104 no_regs:
105 len = prom_getproperty(nd, "address", (void *) sbus_dev->sbus_vaddrs,
106 sizeof(sbus_dev->sbus_vaddrs));
107 if(len == -1) len=0;
108 if(len&3) {
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);
111 len=0;
113 sbus_dev->num_vaddrs = (len/4);
115 #ifdef __sparc_v9__
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;
120 } else {
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));
125 else
126 sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus,
127 irqs[0].pri);
129 #else
130 len = prom_getproperty(nd, "intr", (void *)irqs, sizeof(irqs));
131 if (len == -1) len=0;
132 if (len&7) {
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);
135 len=0;
137 if (len > 4 * 8) {
138 prom_printf("Device %s has more than 4 interrupts\n", sbus_dev->prom_name);
139 len = 4 * 8;
141 sbus_dev->num_irqs=(len/8);
142 if(sbus_dev->num_irqs == 0)
143 sbus_dev->irqs[0]=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;
147 else {
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);
153 #endif
155 #ifdef DEBUG_FILL
156 #ifdef __sparc_v9__
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]));
161 else
162 prom_printf("\n");
163 prom_printf("Base address %016lx\n", sbus_dev->sbus_addr);
164 #else
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,
167 sbus_dev->irqs[0]);
168 prom_printf("Base address %08lx\n", sbus_dev->sbus_addr);
169 #endif
170 prom_printf("REGISTERS: Probed %d register(s)\n", sbus_dev->num_registers);
171 for(len=0; len<sbus_dev->num_registers; len++)
172 #ifdef __sparc_v9__
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));
179 #else
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));
186 #endif
187 #endif
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
193 * devices.
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);
201 #endif
202 #ifdef CONFIG_SUN_AUXIO
203 extern void auxio_probe(void);
204 #endif
205 #ifdef CONFIG_OBP_FLASH
206 extern int flash_init(void);
207 #endif
208 #ifdef CONFIG_SUN_AURORA
209 extern int aurora_init(void);
210 #endif
211 #ifdef CONFIG_TADPOLE_TS102_UCTRL
212 extern int ts102_uctrl_init(void);
213 #endif
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. */
223 child->child = 0;
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;
227 this_dev->next = 0;
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),
234 GFP_ATOMIC);
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);
239 } else {
240 this_dev->child = 0;
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? */
253 #ifdef CONFIG_SUN4
254 return sun4_dvma_init();
255 #endif
257 topnd = prom_getchild(prom_root_node);
259 /* Finding the first sbus is a special case... */
260 iommund = 0;
261 if(sparc_cpu_model == sun4u) {
262 nd = prom_searchsiblings(topnd, "sbus");
263 if(nd == 0) {
264 #ifdef CONFIG_PCI
265 if (!pcibios_present()) {
266 prom_printf("Neither SBUS nor PCI found.\n");
267 prom_halt();
268 } else {
269 #ifdef __sparc_v9__
270 extern void firetruck_init(void);
271 firetruck_init();
272 #endif
274 return;
275 #else
276 prom_printf("YEEE, UltraSparc sbus not found\n");
277 prom_halt();
278 #endif
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) {
290 #ifdef CONFIG_PCI
291 if (!pcibios_present()) {
292 prom_printf("Neither SBUS nor PCI found.\n");
293 prom_halt();
295 return;
296 #else
297 /* No reason to run further - the data access trap will occur. */
298 panic("sbus not found");
299 #endif
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);
307 sbus->next = 0;
308 sbus->prom_node = nd;
309 this_sbus=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 */
315 while(this_sbus) {
316 /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
317 if(sparc_cpu_model == sun4u)
318 iommu_init(this_sbus, sbus);
319 #ifndef __sparc_v9__
320 else if (sparc_cpu_model == sun4d)
321 iounit_init(this_sbus, iommund, sbus);
322 #endif
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;
334 #ifndef __sparc_v9__
335 if (sparc_cpu_model == sun4d) {
336 sbus->devid = prom_getint(iommund, "device-id");
337 sbus->board = prom_getint(iommund, "board#");
339 #endif
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;
348 this_dev->next = 0;
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),
357 GFP_ATOMIC);
358 /* Fill it */
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);
363 } else {
364 this_dev->child = 0;
367 while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
368 /* Allocate device node */
369 this_dev->next = kmalloc(sizeof(struct linux_sbus_device),
370 GFP_ATOMIC);
371 this_dev=this_dev->next;
372 this_dev->next=0;
374 /* Fill it */
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 */
381 this_dev->child =
382 kmalloc(sizeof(struct linux_sbus_device),
383 GFP_ATOMIC);
384 /* Fill it */
385 this_dev->child->my_bus = sbus;
386 fill_sbus_device(prom_getchild(sbus_devs),
387 this_dev->child);
388 sbus_do_child_siblings(prom_getchild(sbus_devs),
389 this_dev->child, sbus);
390 } else {
391 this_dev->child = 0;
395 dvma_init(sbus);
397 num_sbus++;
398 if(sparc_cpu_model == sun4u) {
399 this_sbus = prom_getsibling(this_sbus);
400 if(!this_sbus)
401 break;
402 this_sbus = prom_searchsiblings(this_sbus, "sbus");
403 } else if(sparc_cpu_model == sun4d) {
404 iommund = prom_getsibling(iommund);
405 if(!iommund) break;
406 iommund = prom_searchsiblings(iommund, "io-unit");
407 if(!iommund) break;
408 this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi");
409 } else {
410 this_sbus = prom_getsibling(this_sbus);
411 if(!this_sbus) break;
412 this_sbus = prom_searchsiblings(this_sbus, "sbus");
414 if(this_sbus) {
415 sbus->next = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC);
416 sbus = sbus->next;
417 sbus->next = 0;
418 sbus->prom_node = this_sbus;
419 } else {
420 break;
422 } /* while(this_sbus) */
423 if (sparc_cpu_model == sun4d) {
424 extern void sun4d_init_sbi_irq(void);
425 sun4d_init_sbi_irq();
428 #ifdef __sparc_v9__
429 if (sparc_cpu_model == sun4u) {
430 extern void firetruck_init(void);
432 firetruck_init();
434 #endif
435 #ifdef CONFIG_SUN_OPENPROMIO
436 openprom_init();
437 #endif
438 #ifdef CONFIG_SUN_BPP
439 bpp_init();
440 #endif
441 #ifdef CONFIG_SUN_AUXIO
442 if (sparc_cpu_model == sun4u)
443 auxio_probe ();
444 #endif
445 #ifdef CONFIG_OBP_FLASH
446 flash_init();
447 #endif
448 #ifdef CONFIG_SUN_AURORA
449 aurora_init();
450 #endif
451 #ifdef CONFIG_TADPOLE_TS102_UCTRL
452 ts102_uctrl_init();
453 #endif
454 #ifdef __sparc_v9__
455 if (sparc_cpu_model == sun4u) {
456 extern void clock_probe(void);
458 clock_probe();
460 #endif