diff options
-rw-r--r-- | arch/powerpc/Kconfig | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/of_platform.c | 103 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas_pci.c | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/setup.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pci_dlpar.c | 2 | ||||
-rw-r--r-- | include/asm-powerpc/machdep.h | 4 | ||||
-rw-r--r-- | include/asm-powerpc/ppc-pci.h | 12 |
8 files changed, 134 insertions, 10 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 65588a6bd2fe..3d26ba7ad76d 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -223,6 +223,11 @@ config PPC_DCR | |||
223 | depends on PPC_DCR_NATIVE || PPC_DCR_MMIO | 223 | depends on PPC_DCR_NATIVE || PPC_DCR_MMIO |
224 | default y | 224 | default y |
225 | 225 | ||
226 | config PPC_OF_PLATFORM_PCI | ||
227 | bool | ||
228 | depends on PPC64 # not supported on 32 bits yet | ||
229 | default n | ||
230 | |||
226 | config BOOKE | 231 | config BOOKE |
227 | bool | 232 | bool |
228 | depends on E200 || E500 | 233 | depends on E200 || E500 |
@@ -469,6 +474,7 @@ config PPC_CELL_NATIVE | |||
469 | bool | 474 | bool |
470 | select PPC_CELL | 475 | select PPC_CELL |
471 | select PPC_DCR_MMIO | 476 | select PPC_DCR_MMIO |
477 | select PPC_OF_PLATFORM_PCI | ||
472 | select MPIC | 478 | select MPIC |
473 | default n | 479 | default n |
474 | 480 | ||
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 7a0e77af7c9f..6029543c1b5e 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. | 2 | * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. |
3 | * <benh@kernel.crashing.org> | 3 | * <benh@kernel.crashing.org> |
4 | * and Arnd Bergmann, IBM Corp. | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
@@ -17,12 +18,15 @@ | |||
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | #include <linux/mod_devicetable.h> | 19 | #include <linux/mod_devicetable.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/pci.h> | ||
20 | 22 | ||
21 | #include <asm/errno.h> | 23 | #include <asm/errno.h> |
22 | #include <asm/dcr.h> | 24 | #include <asm/dcr.h> |
23 | #include <asm/of_device.h> | 25 | #include <asm/of_device.h> |
24 | #include <asm/of_platform.h> | 26 | #include <asm/of_platform.h> |
25 | #include <asm/topology.h> | 27 | #include <asm/topology.h> |
28 | #include <asm/pci-bridge.h> | ||
29 | #include <asm/ppc-pci.h> | ||
26 | 30 | ||
27 | /* | 31 | /* |
28 | * The list of OF IDs below is used for matching bus types in the | 32 | * The list of OF IDs below is used for matching bus types in the |
@@ -377,3 +381,102 @@ struct of_device *of_find_device_by_phandle(phandle ph) | |||
377 | return NULL; | 381 | return NULL; |
378 | } | 382 | } |
379 | EXPORT_SYMBOL(of_find_device_by_phandle); | 383 | EXPORT_SYMBOL(of_find_device_by_phandle); |
384 | |||
385 | |||
386 | #ifdef CONFIG_PPC_OF_PLATFORM_PCI | ||
387 | |||
388 | /* The probing of PCI controllers from of_platform is currently | ||
389 | * 64 bits only, mostly due to gratuitous differences between | ||
390 | * the 32 and 64 bits PCI code on PowerPC and the 32 bits one | ||
391 | * lacking some bits needed here. | ||
392 | */ | ||
393 | |||
394 | static int __devinit of_pci_phb_probe(struct of_device *dev, | ||
395 | const struct of_device_id *match) | ||
396 | { | ||
397 | struct pci_controller *phb; | ||
398 | |||
399 | /* Check if we can do that ... */ | ||
400 | if (ppc_md.pci_setup_phb == NULL) | ||
401 | return -ENODEV; | ||
402 | |||
403 | printk(KERN_INFO "Setting up PCI bus %s\n", dev->node->full_name); | ||
404 | |||
405 | /* Alloc and setup PHB data structure */ | ||
406 | phb = pcibios_alloc_controller(dev->node); | ||
407 | if (!phb) | ||
408 | return -ENODEV; | ||
409 | |||
410 | /* Setup parent in sysfs */ | ||
411 | phb->parent = &dev->dev; | ||
412 | |||
413 | /* Setup the PHB using arch provided callback */ | ||
414 | if (ppc_md.pci_setup_phb(phb)) { | ||
415 | pcibios_free_controller(phb); | ||
416 | return -ENODEV; | ||
417 | } | ||
418 | |||
419 | /* Process "ranges" property */ | ||
420 | pci_process_bridge_OF_ranges(phb, dev->node, 0); | ||
421 | |||
422 | /* Setup IO space. | ||
423 | * This will not work properly for ISA IOs, something needs to be done | ||
424 | * about it if we ever generalize that way of probing PCI brigdes | ||
425 | */ | ||
426 | pci_setup_phb_io_dynamic(phb, 0); | ||
427 | |||
428 | /* Init pci_dn data structures */ | ||
429 | pci_devs_phb_init_dynamic(phb); | ||
430 | |||
431 | /* Register devices with EEH */ | ||
432 | #ifdef CONFIG_EEH | ||
433 | if (dev->node->child) | ||
434 | eeh_add_device_tree_early(dev->node); | ||
435 | #endif /* CONFIG_EEH */ | ||
436 | |||
437 | /* Scan the bus */ | ||
438 | scan_phb(phb); | ||
439 | |||
440 | /* Claim resources. This might need some rework as well depending | ||
441 | * wether we are doing probe-only or not, like assigning unassigned | ||
442 | * resources etc... | ||
443 | */ | ||
444 | pcibios_claim_one_bus(phb->bus); | ||
445 | |||
446 | /* Finish EEH setup */ | ||
447 | #ifdef CONFIG_EEH | ||
448 | eeh_add_device_tree_late(phb->bus); | ||
449 | #endif | ||
450 | |||
451 | /* Add probed PCI devices to the device model */ | ||
452 | pci_bus_add_devices(phb->bus); | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static struct of_device_id of_pci_phb_ids[] = { | ||
458 | { .type = "pci", }, | ||
459 | { .type = "pcix", }, | ||
460 | { .type = "pcie", }, | ||
461 | { .type = "pciex", }, | ||
462 | { .type = "ht", }, | ||
463 | {} | ||
464 | }; | ||
465 | |||
466 | static struct of_platform_driver of_pci_phb_driver = { | ||
467 | .name = "of-pci", | ||
468 | .match_table = of_pci_phb_ids, | ||
469 | .probe = of_pci_phb_probe, | ||
470 | .driver = { | ||
471 | .multithread_probe = 1, | ||
472 | }, | ||
473 | }; | ||
474 | |||
475 | static __init int of_pci_phb_init(void) | ||
476 | { | ||
477 | return of_register_platform_driver(&of_pci_phb_driver); | ||
478 | } | ||
479 | |||
480 | device_initcall(of_pci_phb_init); | ||
481 | |||
482 | #endif /* CONFIG_PPC_OF_PLATFORM_PCI */ | ||
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 74e580d25c1b..d800e19ea564 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -210,6 +210,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | |||
210 | 210 | ||
211 | void pcibios_free_controller(struct pci_controller *phb) | 211 | void pcibios_free_controller(struct pci_controller *phb) |
212 | { | 212 | { |
213 | spin_lock(&hose_spinlock); | ||
214 | list_del(&phb->list_node); | ||
215 | spin_unlock(&hose_spinlock); | ||
216 | |||
213 | if (phb->is_dynamic) | 217 | if (phb->is_dynamic) |
214 | kfree(phb); | 218 | kfree(phb); |
215 | } | 219 | } |
@@ -1242,6 +1246,11 @@ static void __devinit do_bus_setup(struct pci_bus *bus) | |||
1242 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | 1246 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) |
1243 | { | 1247 | { |
1244 | struct pci_dev *dev = bus->self; | 1248 | struct pci_dev *dev = bus->self; |
1249 | struct device_node *np; | ||
1250 | |||
1251 | np = pci_bus_to_OF_node(bus); | ||
1252 | |||
1253 | DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : "<???>"); | ||
1245 | 1254 | ||
1246 | if (dev && pci_probe_only && | 1255 | if (dev && pci_probe_only && |
1247 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | 1256 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 2576e12d7255..03cacc25a0ae 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -257,8 +257,10 @@ static int phb_set_bus_ranges(struct device_node *dev, | |||
257 | return 0; | 257 | return 0; |
258 | } | 258 | } |
259 | 259 | ||
260 | int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb) | 260 | int __devinit rtas_setup_phb(struct pci_controller *phb) |
261 | { | 261 | { |
262 | struct device_node *dev = phb->arch_data; | ||
263 | |||
262 | if (is_python(dev)) | 264 | if (is_python(dev)) |
263 | python_countermeasures(dev); | 265 | python_countermeasures(dev); |
264 | 266 | ||
@@ -290,7 +292,7 @@ unsigned long __init find_and_init_phbs(void) | |||
290 | phb = pcibios_alloc_controller(node); | 292 | phb = pcibios_alloc_controller(node); |
291 | if (!phb) | 293 | if (!phb) |
292 | continue; | 294 | continue; |
293 | setup_phb(node, phb); | 295 | rtas_setup_phb(phb); |
294 | pci_process_bridge_OF_ranges(phb, node, 0); | 296 | pci_process_bridge_OF_ranges(phb, node, 0); |
295 | pci_setup_phb_io(phb, index == 0); | 297 | pci_setup_phb_io(phb, index == 0); |
296 | index++; | 298 | index++; |
@@ -362,7 +364,6 @@ int pcibios_remove_root_bus(struct pci_controller *phb) | |||
362 | } | 364 | } |
363 | } | 365 | } |
364 | 366 | ||
365 | list_del(&phb->list_node); | ||
366 | pcibios_free_controller(phb); | 367 | pcibios_free_controller(phb); |
367 | 368 | ||
368 | return 0; | 369 | return 0; |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index b39753f16d48..7e18420166c4 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -256,6 +256,7 @@ define_machine(cell) { | |||
256 | .check_legacy_ioport = cell_check_legacy_ioport, | 256 | .check_legacy_ioport = cell_check_legacy_ioport, |
257 | .progress = cell_progress, | 257 | .progress = cell_progress, |
258 | .init_IRQ = cell_init_irq, | 258 | .init_IRQ = cell_init_irq, |
259 | .pci_setup_phb = rtas_setup_phb, | ||
259 | #ifdef CONFIG_KEXEC | 260 | #ifdef CONFIG_KEXEC |
260 | .machine_kexec = default_machine_kexec, | 261 | .machine_kexec = default_machine_kexec, |
261 | .machine_kexec_prepare = default_machine_kexec_prepare, | 262 | .machine_kexec_prepare = default_machine_kexec_prepare, |
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index bb0cb5c5b565..ac56b868913a 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -195,7 +195,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
195 | phb = pcibios_alloc_controller(dn); | 195 | phb = pcibios_alloc_controller(dn); |
196 | if (!phb) | 196 | if (!phb) |
197 | return NULL; | 197 | return NULL; |
198 | setup_phb(dn, phb); | 198 | rtas_setup_phb(phb); |
199 | pci_process_bridge_OF_ranges(phb, dn, 0); | 199 | pci_process_bridge_OF_ranges(phb, dn, 0); |
200 | 200 | ||
201 | pci_setup_phb_io_dynamic(phb, primary); | 201 | pci_setup_phb_io_dynamic(phb, primary); |
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index ccc29744656e..23580cf5504c 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h | |||
@@ -26,6 +26,7 @@ struct device_node; | |||
26 | struct iommu_table; | 26 | struct iommu_table; |
27 | struct rtc_time; | 27 | struct rtc_time; |
28 | struct file; | 28 | struct file; |
29 | struct pci_controller; | ||
29 | #ifdef CONFIG_KEXEC | 30 | #ifdef CONFIG_KEXEC |
30 | struct kimage; | 31 | struct kimage; |
31 | #endif | 32 | #endif |
@@ -107,6 +108,9 @@ struct machdep_calls { | |||
107 | int (*pci_probe_mode)(struct pci_bus *); | 108 | int (*pci_probe_mode)(struct pci_bus *); |
108 | void (*pci_irq_fixup)(struct pci_dev *dev); | 109 | void (*pci_irq_fixup)(struct pci_dev *dev); |
109 | 110 | ||
111 | /* To setup PHBs when using automatic OF platform driver for PCI */ | ||
112 | int (*pci_setup_phb)(struct pci_controller *host); | ||
113 | |||
110 | void (*restart)(char *cmd); | 114 | void (*restart)(char *cmd); |
111 | void (*power_off)(void); | 115 | void (*power_off)(void); |
112 | void (*halt)(void); | 116 | void (*halt)(void); |
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index 8894d1d4226b..ab6eddb518c7 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h | |||
@@ -36,14 +36,14 @@ typedef void *(*traverse_func)(struct device_node *me, void *data); | |||
36 | void *traverse_pci_devices(struct device_node *start, traverse_func pre, | 36 | void *traverse_pci_devices(struct device_node *start, traverse_func pre, |
37 | void *data); | 37 | void *data); |
38 | 38 | ||
39 | void pci_devs_phb_init(void); | 39 | extern void pci_devs_phb_init(void); |
40 | void pci_devs_phb_init_dynamic(struct pci_controller *phb); | 40 | extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); |
41 | int setup_phb(struct device_node *dev, struct pci_controller *phb); | 41 | extern void scan_phb(struct pci_controller *hose); |
42 | void __devinit scan_phb(struct pci_controller *hose); | ||
43 | 42 | ||
44 | /* From rtas_pci.h */ | 43 | /* From rtas_pci.h */ |
45 | void init_pci_config_tokens (void); | 44 | extern void init_pci_config_tokens (void); |
46 | unsigned long get_phb_buid (struct device_node *); | 45 | extern unsigned long get_phb_buid (struct device_node *); |
46 | extern int rtas_setup_phb(struct pci_controller *phb); | ||
47 | 47 | ||
48 | /* From pSeries_pci.h */ | 48 | /* From pSeries_pci.h */ |
49 | extern void pSeries_final_fixup(void); | 49 | extern void pSeries_final_fixup(void); |