summaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/pmac_setup.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-09-12 17:17:36 +1000
committerPaul Mackerras <paulus@samba.org>2005-09-12 17:17:36 +1000
commit4267292b0f368c1633ff3316a53b5f7fbada95f8 (patch)
tree4830de68a91351ef29445ec2a7f7ad8d7145b0b9 /arch/ppc64/kernel/pmac_setup.c
parent357d596bd552ad157a906289ab13ea6ba7e66e3d (diff)
downloadblackbird-op-linux-4267292b0f368c1633ff3316a53b5f7fbada95f8.tar.gz
blackbird-op-linux-4267292b0f368c1633ff3316a53b5f7fbada95f8.zip
ppc64: Set up PCI tree from Open Firmware device tree
This adds code which gives us the option on ppc64 of instantiating the PCI tree (the tree of pci_bus and pci_dev structs) from the Open Firmware device tree rather than by probing PCI configuration space. The OF device tree has a node for each PCI device and bridge in the system, with properties that tell us what addresses the firmware has configured for them and other details. There are a couple of reasons why this is needed. First, on systems with a hypervisor, there is a PCI-PCI bridge per slot under the PCI host bridges. These PCI-PCI bridges have special isolation features for virtualization. We can't write to their config space, and we are not supposed to be reading their config space either. The firmware tells us about the address ranges that they pass in the OF device tree. Secondly, on powermacs, the interrupt controller is in a PCI device that may be behind a PCI-PCI bridge. If we happened to take an interrupt just at the point when the device or a bridge on the path to it was disabled for probing, we would crash when we try to access the interrupt controller. I have implemented a platform-specific function which is called for each PCI bridge (host or PCI-PCI) to say whether the code should look in the device tree or use normal PCI probing for the devices under that bridge. On pSeries machines we use the device tree if we're running under a hypervisor, otherwise we use normal probing. On powermacs we use normal probing for the AGP bridge, since the device for the AGP bridge itself isn't shown in the device tree (at least on my G5), and the device tree for everything else. This has been tested on a dual G5 powermac, a partition on a POWER5 machine (running under the hypervisor), and a legacy iSeries partition. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc64/kernel/pmac_setup.c')
-rw-r--r--arch/ppc64/kernel/pmac_setup.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index e7f695dcd8c8..325426c7bed0 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -477,6 +477,18 @@ static int __init pmac_probe(int platform)
return 1;
}
+static int pmac_probe_mode(struct pci_bus *bus)
+{
+ struct device_node *node = bus->sysdata;
+
+ /* We need to use normal PCI probing for the AGP bus,
+ since the device for the AGP bridge isn't in the tree. */
+ if (bus->self == NULL && device_is_compatible(node, "u3-agp"))
+ return PCI_PROBE_NORMAL;
+
+ return PCI_PROBE_DEVTREE;
+}
+
struct machdep_calls __initdata pmac_md = {
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = generic_mach_cpu_die,
@@ -488,6 +500,7 @@ struct machdep_calls __initdata pmac_md = {
.init_IRQ = pmac_init_IRQ,
.get_irq = mpic_get_irq,
.pcibios_fixup = pmac_pcibios_fixup,
+ .pci_probe_mode = pmac_probe_mode,
.restart = pmac_restart,
.power_off = pmac_power_off,
.halt = pmac_halt,
OpenPOWER on IntegriCloud