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 | |
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')
-rw-r--r-- | arch/sparc64/kernel/pci.c | 96 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_fire.c | 80 |
2 files changed, 58 insertions, 118 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c2ff2de4da5a..2da32e4c985b 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -164,79 +164,6 @@ void pci_config_write32(u32 *addr, u32 val) | |||
164 | spin_unlock_irqrestore(&pci_poke_lock, flags); | 164 | spin_unlock_irqrestore(&pci_poke_lock, flags); |
165 | } | 165 | } |
166 | 166 | ||
167 | /* Probe for all PCI controllers in the system. */ | ||
168 | extern void fire_pci_init(struct device_node *, const char *); | ||
169 | |||
170 | static struct { | ||
171 | char *model_name; | ||
172 | void (*init)(struct device_node *, const char *); | ||
173 | } pci_controller_table[] __initdata = { | ||
174 | { "pciex108e,80f0", fire_pci_init }, | ||
175 | }; | ||
176 | #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) | ||
177 | |||
178 | static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp) | ||
179 | { | ||
180 | int i; | ||
181 | |||
182 | for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) { | ||
183 | if (!strncmp(model_name, | ||
184 | pci_controller_table[i].model_name, | ||
185 | namelen)) { | ||
186 | pci_controller_table[i].init(dp, model_name); | ||
187 | return 1; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) | ||
195 | { | ||
196 | struct device_node *dp; | ||
197 | int count = 0; | ||
198 | |||
199 | for_each_node_by_name(dp, "pci") { | ||
200 | struct property *prop; | ||
201 | int len; | ||
202 | |||
203 | prop = of_find_property(dp, "model", &len); | ||
204 | if (!prop) | ||
205 | prop = of_find_property(dp, "compatible", &len); | ||
206 | |||
207 | if (prop) { | ||
208 | const char *model = prop->value; | ||
209 | int item_len = 0; | ||
210 | |||
211 | /* Our value may be a multi-valued string in the | ||
212 | * case of some compatible properties. For sanity, | ||
213 | * only try the first one. | ||
214 | */ | ||
215 | while (model[item_len] && len) { | ||
216 | len--; | ||
217 | item_len++; | ||
218 | } | ||
219 | |||
220 | if (handler(model, item_len, dp)) | ||
221 | count++; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | return count; | ||
226 | } | ||
227 | |||
228 | /* Find each controller in the system, attach and initialize | ||
229 | * software state structure for each and link into the | ||
230 | * pci_pbm_root. Setup the controller enough such | ||
231 | * that bus scanning can be done. | ||
232 | */ | ||
233 | static void __init pci_controller_probe(void) | ||
234 | { | ||
235 | printk("PCI: Probing for controllers.\n"); | ||
236 | |||
237 | pci_controller_scan(pci_controller_init); | ||
238 | } | ||
239 | |||
240 | static int ofpci_verbose; | 167 | static int ofpci_verbose; |
241 | 168 | ||
242 | static int __init ofpci_debug(char *str) | 169 | static int __init ofpci_debug(char *str) |
@@ -773,29 +700,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) | |||
773 | return bus; | 700 | return bus; |
774 | } | 701 | } |
775 | 702 | ||
776 | static void __init pci_scan_each_controller_bus(void) | ||
777 | { | ||
778 | struct pci_pbm_info *pbm; | ||
779 | |||
780 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | ||
781 | if (pbm->scan_bus) | ||
782 | pbm->scan_bus(pbm); | ||
783 | } | ||
784 | } | ||
785 | |||
786 | static int __init pcibios_init(void) | ||
787 | { | ||
788 | pci_controller_probe(); | ||
789 | if (pci_pbm_root == NULL) | ||
790 | return 0; | ||
791 | |||
792 | pci_scan_each_controller_bus(); | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | subsys_initcall(pcibios_init); | ||
798 | |||
799 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) | 703 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) |
800 | { | 704 | { |
801 | struct pci_pbm_info *pbm = pbus->sysdata; | 705 | struct pci_pbm_info *pbm = pbus->sysdata; |
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); | ||