diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-30 06:12:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-30 06:14:14 -0400 |
commit | c8049966b7f903ce61e94efbbddf581cf8860b85 (patch) | |
tree | 991493610dd07896da5b62079bac78c32a110dfa /arch/sparc64/kernel/pci_fire.c | |
parent | edbe805b2b1044659e0727136213bdf42bd1b9d0 (diff) |
sparc64: Convert FIRE PCI controller driver into a real driver.
And now all the by-hand PCI controller probing junk in pci.c can die too.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci_fire.c')
-rw-r--r-- | arch/sparc64/kernel/pci_fire.c | 80 |
1 files changed, 58 insertions, 22 deletions
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index d23bb6f53cda..adc3fe44b081 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c | |||
@@ -8,13 +8,16 @@ | |||
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/msi.h> | 9 | #include <linux/msi.h> |
10 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
11 | #include <linux/of_device.h> | ||
11 | 12 | ||
12 | #include <asm/oplib.h> | ||
13 | #include <asm/prom.h> | 13 | #include <asm/prom.h> |
14 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
15 | 15 | ||
16 | #include "pci_impl.h" | 16 | #include "pci_impl.h" |
17 | 17 | ||
18 | #define DRIVER_NAME "fire" | ||
19 | #define PFX DRIVER_NAME ": " | ||
20 | |||
18 | #define fire_read(__reg) \ | 21 | #define fire_read(__reg) \ |
19 | ({ u64 __ret; \ | 22 | ({ u64 __ret; \ |
20 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | 23 | __asm__ __volatile__("ldxa [%1] %2, %0" \ |
@@ -452,7 +455,6 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, | |||
452 | 455 | ||
453 | pbm->numa_node = -1; | 456 | pbm->numa_node = -1; |
454 | 457 | ||
455 | pbm->scan_bus = pci_fire_scan_bus; | ||
456 | pbm->pci_ops = &sun4u_pci_ops; | 458 | pbm->pci_ops = &sun4u_pci_ops; |
457 | pbm->config_space_reg_bits = 12; | 459 | pbm->config_space_reg_bits = 12; |
458 | 460 | ||
@@ -481,6 +483,8 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, | |||
481 | 483 | ||
482 | pci_fire_msi_init(pbm); | 484 | pci_fire_msi_init(pbm); |
483 | 485 | ||
486 | pci_fire_scan_bus(pbm); | ||
487 | |||
484 | return 0; | 488 | return 0; |
485 | } | 489 | } |
486 | 490 | ||
@@ -491,43 +495,75 @@ static inline int portid_compare(u32 x, u32 y) | |||
491 | return 0; | 495 | return 0; |
492 | } | 496 | } |
493 | 497 | ||
494 | void __init fire_pci_init(struct device_node *dp, const char *model_name) | 498 | static int __devinit fire_probe(struct of_device *op, |
499 | const struct of_device_id *match) | ||
495 | { | 500 | { |
501 | struct device_node *dp = op->node; | ||
496 | struct pci_controller_info *p; | 502 | struct pci_controller_info *p; |
497 | u32 portid = of_getintprop_default(dp, "portid", 0xff); | ||
498 | struct iommu *iommu; | ||
499 | struct pci_pbm_info *pbm; | 503 | struct pci_pbm_info *pbm; |
504 | struct iommu *iommu; | ||
505 | u32 portid; | ||
506 | int err; | ||
500 | 507 | ||
508 | portid = of_getintprop_default(dp, "portid", 0xff); | ||
501 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 509 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { |
502 | if (portid_compare(pbm->portid, portid)) { | 510 | if (portid_compare(pbm->portid, portid)) |
503 | if (pci_fire_pbm_init(pbm->parent, dp, portid)) | 511 | return pci_fire_pbm_init(pbm->parent, dp, portid); |
504 | goto fatal_memory_error; | ||
505 | return; | ||
506 | } | ||
507 | } | 512 | } |
508 | 513 | ||
514 | err = -ENOMEM; | ||
509 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 515 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); |
510 | if (!p) | 516 | if (!p) { |
511 | goto fatal_memory_error; | 517 | printk(KERN_ERR PFX "Cannot allocate controller info.\n"); |
518 | goto out_free; | ||
519 | } | ||
512 | 520 | ||
513 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 521 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); |
514 | if (!iommu) | 522 | if (!iommu) { |
515 | goto fatal_memory_error; | 523 | printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); |
524 | goto out_free; | ||
525 | } | ||
516 | 526 | ||
517 | p->pbm_A.iommu = iommu; | 527 | p->pbm_A.iommu = iommu; |
518 | 528 | ||
519 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 529 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); |
520 | if (!iommu) | 530 | if (!iommu) { |
521 | goto fatal_memory_error; | 531 | printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); |
532 | goto out_free; | ||
533 | } | ||
522 | 534 | ||
523 | p->pbm_B.iommu = iommu; | 535 | p->pbm_B.iommu = iommu; |
524 | 536 | ||
525 | if (pci_fire_pbm_init(p, dp, portid)) | 537 | return pci_fire_pbm_init(p, dp, portid); |
526 | goto fatal_memory_error; | ||
527 | 538 | ||
528 | return; | 539 | out_free: |
540 | if (p) { | ||
541 | if (p->pbm_A.iommu) | ||
542 | kfree(p->pbm_A.iommu); | ||
543 | if (p->pbm_B.iommu) | ||
544 | kfree(p->pbm_B.iommu); | ||
545 | kfree(p); | ||
546 | } | ||
547 | return err; | ||
548 | } | ||
549 | |||
550 | static struct of_device_id fire_match[] = { | ||
551 | { | ||
552 | .name = "pci", | ||
553 | .compatible = "pciex108e,80f0", | ||
554 | }, | ||
555 | {}, | ||
556 | }; | ||
529 | 557 | ||
530 | fatal_memory_error: | 558 | static struct of_platform_driver fire_driver = { |
531 | prom_printf("PCI_FIRE: Fatal memory allocation error.\n"); | 559 | .name = DRIVER_NAME, |
532 | prom_halt(); | 560 | .match_table = fire_match, |
561 | .probe = fire_probe, | ||
562 | }; | ||
563 | |||
564 | static int __init fire_init(void) | ||
565 | { | ||
566 | return of_register_driver(&fire_driver, &of_bus_type); | ||
533 | } | 567 | } |
568 | |||
569 | subsys_initcall(fire_init); | ||