aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-11 01:25:08 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:38:49 -0500
commit4c9d2800be5dfabf26acdeb401cbabe9edc1dcf2 (patch)
tree8d9a4f96cba4a1cc16a1e661d00f88e3e048491f /arch/powerpc/kernel
parent803d4573e60bc890d7fbc040ad1c18c2dc7f8279 (diff)
[POWERPC] Generic OF platform driver for PCI host bridges.
When enabled in Kconfig, it will pick up any of_platform_device matching it's match list (currently type "pci", "pcix", "pcie", or "ht" and setup a PHB for it. Platform must provide a ppc_md.pci_setup_phb() for it to work (for doing the necessary initialisations specific to a given PHB like setting up the config space ops). It's currently only available on 64 bits as the 32 bits PCI code can't quite cope with it in it's current form. I will fix that later. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/of_platform.c103
-rw-r--r--arch/powerpc/kernel/pci_64.c9
-rw-r--r--arch/powerpc/kernel/rtas_pci.c7
3 files changed, 116 insertions, 3 deletions
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}
379EXPORT_SYMBOL(of_find_device_by_phandle); 383EXPORT_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
394static 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
457static 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
466static 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
475static __init int of_pci_phb_init(void)
476{
477 return of_register_platform_driver(&of_pci_phb_driver);
478}
479
480device_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
211void pcibios_free_controller(struct pci_controller *phb) 211void 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)
1242void __devinit pcibios_fixup_bus(struct pci_bus *bus) 1246void __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
260int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb) 260int __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;