diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-30 03:36:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-30 03:36:11 -0400 |
commit | 356d164757310cd822d71da2027d50ec39798b7f (patch) | |
tree | 9a4f53bf8a27b66cf654a2fc751e0d23520ca330 /arch/sparc64/kernel/ebus.c | |
parent | 75081322c9d0d56f8880178f9fcc93778bcf0220 (diff) |
sparc: Kill EBUS driver layer.
All that remains is the EBUS DMA programming library for
sparc64.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/ebus.c')
-rw-r--r-- | arch/sparc64/kernel/ebus.c | 295 |
1 files changed, 1 insertions, 294 deletions
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 88408741c320..77dbf6d45faf 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* ebus.c: EBUS DMA library code. |
2 | * ebus.c: PCI to EBus bridge device. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
5 | * Copyright (C) 1999 David S. Miller (davem@redhat.com) | 4 | * Copyright (C) 1999 David S. Miller (davem@redhat.com) |
@@ -9,24 +8,12 @@ | |||
9 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
10 | #include <linux/types.h> | 9 | #include <linux/types.h> |
11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
12 | #include <linux/slab.h> | ||
13 | #include <linux/string.h> | ||
14 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
15 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
16 | #include <linux/pci.h> | ||
17 | #include <linux/of_device.h> | ||
18 | 13 | ||
19 | #include <asm/system.h> | ||
20 | #include <asm/page.h> | ||
21 | #include <asm/ebus.h> | ||
22 | #include <asm/ebus_dma.h> | 14 | #include <asm/ebus_dma.h> |
23 | #include <asm/oplib.h> | ||
24 | #include <asm/prom.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <asm/io.h> | 15 | #include <asm/io.h> |
27 | 16 | ||
28 | /* EBUS dma library. */ | ||
29 | |||
30 | #define EBDMA_CSR 0x00UL /* Control/Status */ | 17 | #define EBDMA_CSR 0x00UL /* Control/Status */ |
31 | #define EBDMA_ADDR 0x04UL /* DMA Address */ | 18 | #define EBDMA_ADDR 0x04UL /* DMA Address */ |
32 | #define EBDMA_COUNT 0x08UL /* DMA Count */ | 19 | #define EBDMA_COUNT 0x08UL /* DMA Count */ |
@@ -268,283 +255,3 @@ void ebus_dma_enable(struct ebus_dma_info *p, int on) | |||
268 | spin_unlock_irqrestore(&p->lock, flags); | 255 | spin_unlock_irqrestore(&p->lock, flags); |
269 | } | 256 | } |
270 | EXPORT_SYMBOL(ebus_dma_enable); | 257 | EXPORT_SYMBOL(ebus_dma_enable); |
271 | |||
272 | struct linux_ebus *ebus_chain = NULL; | ||
273 | |||
274 | static inline void *ebus_alloc(size_t size) | ||
275 | { | ||
276 | void *mem; | ||
277 | |||
278 | mem = kzalloc(size, GFP_ATOMIC); | ||
279 | if (!mem) | ||
280 | panic("ebus_alloc: out of memory"); | ||
281 | return mem; | ||
282 | } | ||
283 | |||
284 | static void __init fill_ebus_child(struct device_node *dp, | ||
285 | struct linux_ebus_child *dev, | ||
286 | int non_standard_regs) | ||
287 | { | ||
288 | struct of_device *op; | ||
289 | const int *regs; | ||
290 | int i, len; | ||
291 | |||
292 | dev->prom_node = dp; | ||
293 | printk(" (%s)", dp->name); | ||
294 | |||
295 | regs = of_get_property(dp, "reg", &len); | ||
296 | if (!regs) | ||
297 | dev->num_addrs = 0; | ||
298 | else | ||
299 | dev->num_addrs = len / sizeof(regs[0]); | ||
300 | |||
301 | if (non_standard_regs) { | ||
302 | /* This is to handle reg properties which are not | ||
303 | * in the parent relative format. One example are | ||
304 | * children of the i2c device on CompactPCI systems. | ||
305 | * | ||
306 | * So, for such devices we just record the property | ||
307 | * raw in the child resources. | ||
308 | */ | ||
309 | for (i = 0; i < dev->num_addrs; i++) | ||
310 | dev->resource[i].start = regs[i]; | ||
311 | } else { | ||
312 | for (i = 0; i < dev->num_addrs; i++) { | ||
313 | int rnum = regs[i]; | ||
314 | if (rnum >= dev->parent->num_addrs) { | ||
315 | prom_printf("UGH: property for %s was %d, need < %d\n", | ||
316 | dp->name, len, dev->parent->num_addrs); | ||
317 | prom_halt(); | ||
318 | } | ||
319 | dev->resource[i].start = dev->parent->resource[i].start; | ||
320 | dev->resource[i].end = dev->parent->resource[i].end; | ||
321 | dev->resource[i].flags = IORESOURCE_MEM; | ||
322 | dev->resource[i].name = dp->name; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | op = of_find_device_by_node(dp); | ||
327 | if (!op) { | ||
328 | dev->num_irqs = 0; | ||
329 | } else { | ||
330 | dev->num_irqs = op->num_irqs; | ||
331 | for (i = 0; i < dev->num_irqs; i++) | ||
332 | dev->irqs[i] = op->irqs[i]; | ||
333 | } | ||
334 | |||
335 | if (!dev->num_irqs) { | ||
336 | /* | ||
337 | * Oh, well, some PROMs don't export interrupts | ||
338 | * property to children of EBus devices... | ||
339 | * | ||
340 | * Be smart about PS/2 keyboard and mouse. | ||
341 | */ | ||
342 | if (!strcmp(dev->parent->prom_node->name, "8042")) { | ||
343 | if (!strcmp(dev->prom_node->name, "kb_ps2")) { | ||
344 | dev->num_irqs = 1; | ||
345 | dev->irqs[0] = dev->parent->irqs[0]; | ||
346 | } else { | ||
347 | dev->num_irqs = 1; | ||
348 | dev->irqs[0] = dev->parent->irqs[1]; | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
354 | static int __init child_regs_nonstandard(struct linux_ebus_device *dev) | ||
355 | { | ||
356 | if (!strcmp(dev->prom_node->name, "i2c") || | ||
357 | !strcmp(dev->prom_node->name, "SUNW,lombus")) | ||
358 | return 1; | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) | ||
363 | { | ||
364 | struct linux_ebus_child *child; | ||
365 | struct dev_archdata *sd; | ||
366 | struct of_device *op; | ||
367 | int i, len; | ||
368 | |||
369 | dev->prom_node = dp; | ||
370 | |||
371 | printk(" [%s", dp->name); | ||
372 | |||
373 | op = of_find_device_by_node(dp); | ||
374 | if (!op) { | ||
375 | dev->num_addrs = 0; | ||
376 | dev->num_irqs = 0; | ||
377 | } else { | ||
378 | const int *regs = of_get_property(dp, "reg", &len); | ||
379 | |||
380 | if (!regs) | ||
381 | len = 0; | ||
382 | dev->num_addrs = len / sizeof(struct linux_prom_registers); | ||
383 | |||
384 | for (i = 0; i < dev->num_addrs; i++) | ||
385 | memcpy(&dev->resource[i], | ||
386 | &op->resource[i], | ||
387 | sizeof(struct resource)); | ||
388 | |||
389 | dev->num_irqs = op->num_irqs; | ||
390 | for (i = 0; i < dev->num_irqs; i++) | ||
391 | dev->irqs[i] = op->irqs[i]; | ||
392 | } | ||
393 | |||
394 | sd = &dev->ofdev.dev.archdata; | ||
395 | sd->prom_node = dp; | ||
396 | sd->op = &dev->ofdev; | ||
397 | sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; | ||
398 | sd->stc = dev->bus->ofdev.dev.parent->archdata.stc; | ||
399 | sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node; | ||
400 | |||
401 | dev->ofdev.node = dp; | ||
402 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | ||
403 | dev->ofdev.dev.bus = &ebus_bus_type; | ||
404 | dev_set_name(&dev->ofdev.dev, "ebus[%08x]", dp->node); | ||
405 | |||
406 | /* Register with core */ | ||
407 | if (of_device_register(&dev->ofdev) != 0) | ||
408 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
409 | dp->path_component_name); | ||
410 | |||
411 | dp = dp->child; | ||
412 | if (dp) { | ||
413 | printk(" ->"); | ||
414 | dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); | ||
415 | |||
416 | child = dev->children; | ||
417 | child->next = NULL; | ||
418 | child->parent = dev; | ||
419 | child->bus = dev->bus; | ||
420 | fill_ebus_child(dp, child, | ||
421 | child_regs_nonstandard(dev)); | ||
422 | |||
423 | while ((dp = dp->sibling) != NULL) { | ||
424 | child->next = ebus_alloc(sizeof(struct linux_ebus_child)); | ||
425 | |||
426 | child = child->next; | ||
427 | child->next = NULL; | ||
428 | child->parent = dev; | ||
429 | child->bus = dev->bus; | ||
430 | fill_ebus_child(dp, child, | ||
431 | child_regs_nonstandard(dev)); | ||
432 | } | ||
433 | } | ||
434 | printk("]"); | ||
435 | } | ||
436 | |||
437 | static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p) | ||
438 | { | ||
439 | struct pci_dev *pdev = start; | ||
440 | |||
441 | while ((pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev))) | ||
442 | if (pdev->device == PCI_DEVICE_ID_SUN_EBUS || | ||
443 | pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS) | ||
444 | break; | ||
445 | |||
446 | *is_rio_p = !!(pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS)); | ||
447 | |||
448 | return pdev; | ||
449 | } | ||
450 | |||
451 | void __init ebus_init(void) | ||
452 | { | ||
453 | struct linux_ebus_device *dev; | ||
454 | struct linux_ebus *ebus; | ||
455 | struct pci_dev *pdev; | ||
456 | struct device_node *dp; | ||
457 | int is_rio; | ||
458 | int num_ebus = 0; | ||
459 | |||
460 | pdev = find_next_ebus(NULL, &is_rio); | ||
461 | if (!pdev) { | ||
462 | printk("ebus: No EBus's found.\n"); | ||
463 | return; | ||
464 | } | ||
465 | |||
466 | dp = pci_device_to_OF_node(pdev); | ||
467 | |||
468 | ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); | ||
469 | ebus->next = NULL; | ||
470 | ebus->is_rio = is_rio; | ||
471 | |||
472 | while (dp) { | ||
473 | struct device_node *child; | ||
474 | |||
475 | /* SUNW,pci-qfe uses four empty ebuses on it. | ||
476 | I think we should not consider them here, | ||
477 | as they have half of the properties this | ||
478 | code expects and once we do PCI hot-plug, | ||
479 | we'd have to tweak with the ebus_chain | ||
480 | in the runtime after initialization. -jj */ | ||
481 | if (!dp->child) { | ||
482 | pdev = find_next_ebus(pdev, &is_rio); | ||
483 | if (!pdev) { | ||
484 | if (ebus == ebus_chain) { | ||
485 | ebus_chain = NULL; | ||
486 | printk("ebus: No EBus's found.\n"); | ||
487 | return; | ||
488 | } | ||
489 | break; | ||
490 | } | ||
491 | ebus->is_rio = is_rio; | ||
492 | dp = pci_device_to_OF_node(pdev); | ||
493 | continue; | ||
494 | } | ||
495 | printk("ebus%d:", num_ebus); | ||
496 | |||
497 | ebus->index = num_ebus; | ||
498 | ebus->prom_node = dp; | ||
499 | ebus->self = pdev; | ||
500 | |||
501 | ebus->ofdev.node = dp; | ||
502 | ebus->ofdev.dev.parent = &pdev->dev; | ||
503 | ebus->ofdev.dev.bus = &ebus_bus_type; | ||
504 | dev_set_name(&ebus->ofdev.dev, "ebus%d", num_ebus); | ||
505 | |||
506 | /* Register with core */ | ||
507 | if (of_device_register(&ebus->ofdev) != 0) | ||
508 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
509 | dp->path_component_name); | ||
510 | |||
511 | |||
512 | child = dp->child; | ||
513 | if (!child) | ||
514 | goto next_ebus; | ||
515 | |||
516 | ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); | ||
517 | |||
518 | dev = ebus->devices; | ||
519 | dev->next = NULL; | ||
520 | dev->children = NULL; | ||
521 | dev->bus = ebus; | ||
522 | fill_ebus_device(child, dev); | ||
523 | |||
524 | while ((child = child->sibling) != NULL) { | ||
525 | dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); | ||
526 | |||
527 | dev = dev->next; | ||
528 | dev->next = NULL; | ||
529 | dev->children = NULL; | ||
530 | dev->bus = ebus; | ||
531 | fill_ebus_device(child, dev); | ||
532 | } | ||
533 | |||
534 | next_ebus: | ||
535 | printk("\n"); | ||
536 | |||
537 | pdev = find_next_ebus(pdev, &is_rio); | ||
538 | if (!pdev) | ||
539 | break; | ||
540 | |||
541 | dp = pci_device_to_OF_node(pdev); | ||
542 | |||
543 | ebus->next = ebus_alloc(sizeof(struct linux_ebus)); | ||
544 | ebus = ebus->next; | ||
545 | ebus->next = NULL; | ||
546 | ebus->is_rio = is_rio; | ||
547 | ++num_ebus; | ||
548 | } | ||
549 | pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ | ||
550 | } | ||