From 53280323350621985b3f2f8ffe649215304bcc5f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 27 Oct 2008 19:48:29 +0000 Subject: powerpc/pci: Use common PHB resource hookup The 32-bit and 64-bit powerpc PCI code used to set up the resource pointers of the root bus of a given PHB in completely different places. This unifies this in large part, by making 32-bit use a routine very similar to what 64-bit does when initially scanning the PCI busses. The actual setup of the PHB resources itself is then moved to a common function in pci-common.c. This should cause no functional change on 64-bit. On 32-bit, the effect is that the PHB resources are going to be setup a bit earlier, instead of being setup from pcibios_fixup_bus(). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/include/asm/pci-bridge.h | 1 + arch/powerpc/kernel/pci-common.c | 58 ++++++++++++++++++++++++++ arch/powerpc/kernel/pci_32.c | 78 +++++++++++++++-------------------- arch/powerpc/kernel/pci_64.c | 19 ++------- 4 files changed, 96 insertions(+), 60 deletions(-) diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 9047af7baa6..2dfa8a3d8c7 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -290,6 +290,7 @@ extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, /* Allocate & free a PCI host bridge structure */ extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev); extern void pcibios_free_controller(struct pci_controller *phb); +extern void pcibios_setup_phb_resources(struct pci_controller *hose); #ifdef CONFIG_PCI extern unsigned long pci_address_to_pio(phys_addr_t address); diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 09ac98e2a50..6d46bfabdbe 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1421,3 +1421,61 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return pci_enable_resources(dev, mask); } + +void __devinit pcibios_setup_phb_resources(struct pci_controller *hose) +{ + struct pci_bus *bus = hose->bus; + struct resource *res; + int i; + + /* Hookup PHB IO resource */ + bus->resource[0] = res = &hose->io_resource; + + if (!res->flags) { + printk(KERN_WARNING "PCI: I/O resource not set for host" + " bridge %s (domain %d)\n", + hose->dn->full_name, hose->global_number); +#ifdef CONFIG_PPC32 + /* Workaround for lack of IO resource only on 32-bit */ + res->start = (unsigned long)hose->io_base_virt - isa_io_base; + res->end = res->start + IO_SPACE_LIMIT; + res->flags = IORESOURCE_IO; +#endif /* CONFIG_PPC32 */ + } + + pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n", + (unsigned long long)res->start, + (unsigned long long)res->end, + (unsigned long)res->flags); + + /* Hookup PHB Memory resources */ + for (i = 0; i < 3; ++i) { + res = &hose->mem_resources[i]; + if (!res->flags) { + if (i > 0) + continue; + printk(KERN_ERR "PCI: Memory resource 0 not set for " + "host bridge %s (domain %d)\n", + hose->dn->full_name, hose->global_number); +#ifdef CONFIG_PPC32 + /* Workaround for lack of MEM resource only on 32-bit */ + res->start = hose->pci_mem_offset; + res->end = (resource_size_t)-1LL; + res->flags = IORESOURCE_MEM; +#endif /* CONFIG_PPC32 */ + } + bus->resource[i+1] = res; + + pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i, + (unsigned long long)res->start, + (unsigned long long)res->end, + (unsigned long)res->flags); + } + + pr_debug("PCI: PHB MEM offset = %016llx\n", + (unsigned long long)hose->pci_mem_offset); + pr_debug("PCI: PHB IO offset = %08lx\n", + (unsigned long)hose->io_base_virt - _IO_BASE); + +} + diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index fdcc898e58d..88304035827 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -373,10 +373,41 @@ void pcibios_make_OF_bus_map(void) } #endif /* CONFIG_PPC_OF */ +static void __devinit pcibios_scan_phb(struct pci_controller *hose) +{ + struct pci_bus *bus; + struct device_node *node = hose->dn; + unsigned long io_offset; + struct resource *res = &hose->io_resource; + + pr_debug("PCI: Scanning PHB %s\n", + node ? node->full_name : ""); + + /* Create an empty bus for the toplevel */ + bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose); + if (bus == NULL) { + printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", + hose->global_number); + return; + } + bus->secondary = hose->first_busno; + hose->bus = bus; + + /* Fixup IO space offset */ + io_offset = (unsigned long)hose->io_base_virt - isa_io_base; + res->start = (res->start + io_offset) & 0xffffffffu; + res->end = (res->end + io_offset) & 0xffffffffu; + + /* Wire up PHB bus resources */ + pcibios_setup_phb_resources(hose); + + /* Scan children */ + hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); +} + static int __init pcibios_init(void) { struct pci_controller *hose, *tmp; - struct pci_bus *bus; int next_busno = 0; printk(KERN_INFO "PCI: Probing PCI hardware\n"); @@ -389,12 +420,8 @@ static int __init pcibios_init(void) if (pci_assign_all_buses) hose->first_busno = next_busno; hose->last_busno = 0xff; - bus = pci_scan_bus_parented(hose->parent, hose->first_busno, - hose->ops, hose); - if (bus) { - pci_bus_add_devices(bus); - hose->last_busno = bus->subordinate; - } + pcibios_scan_phb(hose); + pci_bus_add_devices(hose->bus); if (pci_assign_all_buses || next_busno <= hose->last_busno) next_busno = hose->last_busno + pcibios_assign_bus_offset; } @@ -421,45 +448,8 @@ subsys_initcall(pcibios_init); void __devinit pcibios_do_bus_setup(struct pci_bus *bus) { - struct pci_controller *hose = (struct pci_controller *) bus->sysdata; - unsigned long io_offset; - struct resource *res; - int i; struct pci_dev *dev; - /* Hookup PHB resources */ - io_offset = (unsigned long)hose->io_base_virt - isa_io_base; - if (bus->parent == NULL) { - /* This is a host bridge - fill in its resources */ - hose->bus = bus; - - bus->resource[0] = res = &hose->io_resource; - if (!res->flags) { - if (io_offset) - printk(KERN_ERR "I/O resource not set for host" - " bridge %d\n", hose->global_number); - res->start = 0; - res->end = IO_SPACE_LIMIT; - res->flags = IORESOURCE_IO; - } - res->start = (res->start + io_offset) & 0xffffffffu; - res->end = (res->end + io_offset) & 0xffffffffu; - - for (i = 0; i < 3; ++i) { - res = &hose->mem_resources[i]; - if (!res->flags) { - if (i > 0) - continue; - printk(KERN_ERR "Memory resource not set for " - "host bridge %d\n", hose->global_number); - res->start = hose->pci_mem_offset; - res->end = ~0U; - res->flags = IORESOURCE_MEM; - } - bus->resource[i+1] = res; - } - } - if (ppc_md.pci_dma_bus_setup) ppc_md.pci_dma_bus_setup(bus); diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index ffada88a448..f5fc547284b 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -322,7 +322,7 @@ void __devinit scan_phb(struct pci_controller *hose) { struct pci_bus *bus; struct device_node *node = hose->dn; - int i, mode; + int mode; pr_debug("PCI: Scanning PHB %s\n", node ? node->full_name : ""); @@ -341,20 +341,7 @@ void __devinit scan_phb(struct pci_controller *hose) pcibios_map_io_space(bus); /* Wire up PHB bus resources */ - pr_debug("PCI: PHB IO resource = %016lx-%016lx [%lx]\n", - hose->io_resource.start, hose->io_resource.end, - hose->io_resource.flags); - bus->resource[0] = &hose->io_resource; - for (i = 0; i < 3; ++i) { - pr_debug("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i, - hose->mem_resources[i].start, - hose->mem_resources[i].end, - hose->mem_resources[i].flags); - bus->resource[i+1] = &hose->mem_resources[i]; - } - pr_debug("PCI: PHB MEM offset = %016lx\n", hose->pci_mem_offset); - pr_debug("PCI: PHB IO offset = %08lx\n", - (unsigned long)hose->io_base_virt - _IO_BASE); + pcibios_setup_phb_resources(hose); /* Get probe mode and perform scan */ mode = PCI_PROBE_NORMAL; @@ -376,7 +363,7 @@ static int __init pcibios_init(void) printk(KERN_INFO "PCI: Probing PCI hardware\n"); - /* For now, override phys_mem_access_prot. If we need it, + /* For now, override phys_mem_access_prot. If we need it,g * later, we may move that initialization to each ppc_md */ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; -- cgit v1.2.3