powerpc/pci: Fix MODPOST warning
[safe/jmp/linux-2.6] / arch / powerpc / kernel / pci-common.c
index 6d46bfa..e8dfdbd 100644 (file)
@@ -16,8 +16,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG
-
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <asm/machdep.h>
 #include <asm/ppc-pci.h>
 #include <asm/firmware.h>
+#include <asm/eeh.h>
 
 static DEFINE_SPINLOCK(hose_spinlock);
+LIST_HEAD(hose_list);
 
 /* XXX kill that some day ... */
 static int global_phb_number;          /* Global phb counter */
@@ -50,14 +50,14 @@ resource_size_t isa_mem_base;
 unsigned int ppc_pci_flags = 0;
 
 
-static struct dma_mapping_ops *pci_dma_ops;
+static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
 
-void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
+void set_pci_dma_ops(struct dma_map_ops *dma_ops)
 {
        pci_dma_ops = dma_ops;
 }
 
-struct dma_mapping_ops *get_pci_dma_ops(void)
+struct dma_map_ops *get_pci_dma_ops(void)
 {
        return pci_dma_ops;
 }
@@ -114,19 +114,24 @@ void pcibios_free_controller(struct pci_controller *phb)
                kfree(phb);
 }
 
+static resource_size_t pcibios_io_size(const struct pci_controller *hose)
+{
+#ifdef CONFIG_PPC64
+       return hose->pci_io_size;
+#else
+       return hose->io_resource.end - hose->io_resource.start + 1;
+#endif
+}
+
 int pcibios_vaddr_is_ioport(void __iomem *address)
 {
        int ret = 0;
        struct pci_controller *hose;
-       unsigned long size;
+       resource_size_t size;
 
        spin_lock(&hose_spinlock);
        list_for_each_entry(hose, &hose_list, list_node) {
-#ifdef CONFIG_PPC64
-               size = hose->pci_io_size;
-#else
-               size = hose->io_resource.end - hose->io_resource.start + 1;
-#endif
+               size = pcibios_io_size(hose);
                if (address >= hose->io_base_virt &&
                    address < (hose->io_base_virt + size)) {
                        ret = 1;
@@ -137,6 +142,29 @@ int pcibios_vaddr_is_ioport(void __iomem *address)
        return ret;
 }
 
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+       struct pci_controller *hose;
+       resource_size_t size;
+       unsigned long ret = ~0;
+
+       spin_lock(&hose_spinlock);
+       list_for_each_entry(hose, &hose_list, list_node) {
+               size = pcibios_io_size(hose);
+               if (address >= hose->io_base_phys &&
+                   address < (hose->io_base_phys + size)) {
+                       unsigned long base =
+                               (unsigned long)hose->io_base_virt - _IO_BASE;
+                       ret = base + (address - hose->io_base_phys);
+                       break;
+               }
+       }
+       spin_unlock(&hose_spinlock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pci_address_to_pio);
+
 /*
  * Return the domain number for this bus.
  */
@@ -148,8 +176,6 @@ int pci_domain_nr(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pci_domain_nr);
 
-#ifdef CONFIG_PPC_OF
-
 /* This routine is meant to be used early during boot, when the
  * PCI bus numbers have not yet been assigned, and you need to
  * issue PCI config cycles to an OF device.
@@ -159,8 +185,6 @@ EXPORT_SYMBOL(pci_domain_nr);
  */
 struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
 {
-       if (!have_of)
-               return NULL;
        while(node) {
                struct pci_controller *hose, *tmp;
                list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
@@ -184,17 +208,11 @@ static ssize_t pci_show_devspec(struct device *dev,
        return sprintf(buf, "%s", np->full_name);
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_OF */
 
 /* Add sysfs properties */
 int pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_OF
        return device_create_file(&pdev->dev, &dev_attr_devspec);
-#else
-       return 0;
-#endif /* CONFIG_PPC_OF */
-
 }
 
 char __devinit *pcibios_setup(char *str)
@@ -202,26 +220,6 @@ char __devinit *pcibios_setup(char *str)
        return str;
 }
 
-void __devinit pcibios_setup_new_device(struct pci_dev *dev)
-{
-       struct dev_archdata *sd = &dev->dev.archdata;
-
-       sd->of_node = pci_device_to_OF_node(dev);
-
-       pr_debug("PCI: device %s OF node: %s\n", pci_name(dev),
-                sd->of_node ? sd->of_node->full_name : "<none>");
-
-       sd->dma_ops = pci_dma_ops;
-#ifdef CONFIG_PPC32
-       sd->dma_data = (void *)PCI_DRAM_OFFSET;
-#endif
-       set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
-
-       if (ppc_md.pci_dma_dev_setup)
-               ppc_md.pci_dma_dev_setup(dev);
-}
-EXPORT_SYMBOL(pcibios_setup_new_device);
-
 /*
  * Reads the interrupt pin to determine if interrupt is use by card.
  * If the interrupt is used, then gets the interrupt line from the
@@ -279,7 +277,8 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
        } else {
                pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
                         oirq.size, oirq.specifier[0], oirq.specifier[1],
-                   oirq.controller->full_name);
+                        oirq.controller ? oirq.controller->full_name :
+                        "<default>");
 
                virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
                                             oirq.size);
@@ -391,13 +390,10 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
        }
 
        /* XXX would be nice to have a way to ask for write-through */
-       prot |= _PAGE_NO_CACHE;
        if (write_combine)
-               prot &= ~_PAGE_GUARDED;
+               return pgprot_noncached_wc(prot);
        else
-               prot |= _PAGE_GUARDED;
-
-       return __pgprot(prot);
+               return pgprot_noncached(prot);
 }
 
 /*
@@ -408,19 +404,17 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
 pgprot_t pci_phys_mem_access_prot(struct file *file,
                                  unsigned long pfn,
                                  unsigned long size,
-                                 pgprot_t protection)
+                                 pgprot_t prot)
 {
        struct pci_dev *pdev = NULL;
        struct resource *found = NULL;
-       unsigned long prot = pgprot_val(protection);
        resource_size_t offset = ((resource_size_t)pfn) << PAGE_SHIFT;
        int i;
 
        if (page_is_ram(pfn))
-               return __pgprot(prot);
-
-       prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+               return prot;
 
+       prot = pgprot_noncached(prot);
        for_each_pci_dev(pdev) {
                for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
                        struct resource *rp = &pdev->resource[i];
@@ -441,14 +435,14 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
        }
        if (found) {
                if (found->flags & IORESOURCE_PREFETCH)
-                       prot &= ~_PAGE_GUARDED;
+                       prot = pgprot_noncached_wc(prot);
                pci_dev_put(pdev);
        }
 
        pr_debug("PCI: Non-PCI map for %llx, prot: %lx\n",
-                (unsigned long long)offset, prot);
+                (unsigned long long)offset, pgprot_val(prot));
 
-       return __pgprot(prot);
+       return prot;
 }
 
 
@@ -588,8 +582,21 @@ int pci_mmap_legacy_page_range(struct pci_bus *bus,
                 (unsigned long long)(offset + size - 1));
 
        if (mmap_state == pci_mmap_mem) {
-               if ((offset + size) > hose->isa_mem_size)
-                       return -ENXIO;
+               /* Hack alert !
+                *
+                * Because X is lame and can fail starting if it gets an error trying
+                * to mmap legacy_mem (instead of just moving on without legacy memory
+                * access) we fake it here by giving it anonymous memory, effectively
+                * behaving just like /dev/zero
+                */
+               if ((offset + size) > hose->isa_mem_size) {
+                       printk(KERN_DEBUG
+                              "Process %s (pid:%d) mapped non-existing PCI legacy memory for 0%04x:%02x\n",
+                              current->comm, current->pid, pci_domain_nr(bus), bus->number);
+                       if (vma->vm_flags & VM_SHARED)
+                               return shmem_zero_setup(vma);
+                       return 0;
+               }
                offset += hose->isa_mem_phys;
        } else {
                unsigned long io_offset = (unsigned long)hose->io_base_virt - _IO_BASE;
@@ -604,8 +611,7 @@ int pci_mmap_legacy_page_range(struct pci_bus *bus,
        pr_debug(" -> mapping phys %llx\n", (unsigned long long)offset);
 
        vma->vm_pgoff = offset >> PAGE_SHIFT;
-       vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
-                                    | _PAGE_NO_CACHE | _PAGE_GUARDED);
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
        return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
                               vma->vm_end - vma->vm_start,
                               vma->vm_page_prot);
@@ -1074,27 +1080,50 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
        }
 }
 
-static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_setup_bus_self(struct pci_bus *bus)
 {
-       struct pci_dev *dev = bus->self;
-
-       pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
-
-       /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
-        * now differently between 32 and 64 bits.
-        */
-       if (dev != NULL)
+       /* Fix up the bus resources for P2P bridges */
+       if (bus->self != NULL)
                pcibios_fixup_bridge(bus);
 
-       /* Additional setup that is different between 32 and 64 bits for now */
-       pcibios_do_bus_setup(bus);
-
-       /* Platform specific bus fixups */
+       /* Platform specific bus fixups. This is currently only used
+        * by fsl_pci and I'm hoping to get rid of it at some point
+        */
        if (ppc_md.pcibios_fixup_bus)
                ppc_md.pcibios_fixup_bus(bus);
 
-       /* Read default IRQs and fixup if necessary */
+       /* Setup bus DMA mappings */
+       if (ppc_md.pci_dma_bus_setup)
+               ppc_md.pci_dma_bus_setup(bus);
+}
+
+void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+
+       pr_debug("PCI: Fixup bus devices %d (%s)\n",
+                bus->number, bus->self ? pci_name(bus->self) : "PHB");
+
        list_for_each_entry(dev, &bus->devices, bus_list) {
+               struct dev_archdata *sd = &dev->dev.archdata;
+
+               /* Setup OF node pointer in archdata */
+               sd->of_node = pci_device_to_OF_node(dev);
+
+               /* Fixup NUMA node as it may not be setup yet by the generic
+                * code and is needed by the DMA init
+                */
+               set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
+
+               /* Hook up default DMA ops */
+               sd->dma_ops = pci_dma_ops;
+               set_dma_offset(&dev->dev, PCI_DRAM_OFFSET);
+
+               /* Additional platform DMA/iommu setup */
+               if (ppc_md.pci_dma_dev_setup)
+                       ppc_md.pci_dma_dev_setup(dev);
+
+               /* Read default IRQs and fixup if necessary */
                pci_read_irq_line(dev);
                if (ppc_md.pci_irq_fixup)
                        ppc_md.pci_irq_fixup(dev);
@@ -1104,22 +1133,19 @@ static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
 void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
        /* When called from the generic PCI probe, read PCI<->PCI bridge
-        * bases before proceeding
+        * bases. This is -not- called when generating the PCI tree from
+        * the OF device-tree.
         */
        if (bus->self != NULL)
                pci_read_bridge_bases(bus);
-       __pcibios_fixup_bus(bus);
-}
-EXPORT_SYMBOL(pcibios_fixup_bus);
 
-/* When building a bus from the OF tree rather than probing, we need a
- * slightly different version of the fixup which doesn't read the
- * bridge bases using config space accesses
- */
-void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus)
-{
-       __pcibios_fixup_bus(bus);
+       /* Now fixup the bus bus */
+       pcibios_setup_bus_self(bus);
+
+       /* Now fixup devices on that bus */
+       pcibios_setup_bus_devices(bus);
 }
+EXPORT_SYMBOL(pcibios_fixup_bus);
 
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
@@ -1164,7 +1190,7 @@ EXPORT_SYMBOL(pcibios_align_resource);
  * Reparent resource children of pr that conflict with res
  * under res, and make res replace those children.
  */
-static int __init reparent_resources(struct resource *parent,
+static int reparent_resources(struct resource *parent,
                                     struct resource *res)
 {
        struct resource *p, **pp;
@@ -1236,9 +1262,12 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
        int i;
        struct resource *res, *pr;
 
+       pr_debug("PCI: Allocating bus resources for %04x:%02x...\n",
+                pci_domain_nr(bus), bus->number);
+
        for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
                if ((res = bus->resource[i]) == NULL || !res->flags
-                   || res->start > res->end)
+                   || res->start > res->end || res->parent)
                        continue;
                if (bus->parent == NULL)
                        pr = (res->flags & IORESOURCE_IO) ?
@@ -1329,12 +1358,17 @@ static void __init pcibios_allocate_resources(int pass)
 
        for_each_pci_dev(dev) {
                pci_read_config_word(dev, PCI_COMMAND, &command);
-               for (idx = 0; idx < 6; idx++) {
+               for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
                        r = &dev->resource[idx];
                        if (r->parent)          /* Already allocated */
                                continue;
                        if (!r->flags || (r->flags & IORESOURCE_UNSET))
                                continue;       /* Not assigned at all */
+                       /* We only allocate ROMs on pass 1 just in case they
+                        * have been screwed up by firmware
+                        */
+                       if (idx == PCI_ROM_RESOURCE )
+                               disabled = 1;
                        if (r->flags & IORESOURCE_IO)
                                disabled = !(command & PCI_COMMAND_IO);
                        else
@@ -1345,21 +1379,80 @@ static void __init pcibios_allocate_resources(int pass)
                if (pass)
                        continue;
                r = &dev->resource[PCI_ROM_RESOURCE];
-               if (r->flags & IORESOURCE_ROM_ENABLE) {
+               if (r->flags) {
                        /* Turn the ROM off, leave the resource region,
                         * but keep it unregistered.
                         */
                        u32 reg;
-                       pr_debug("PCI: Switching off ROM of %s\n",
-                                pci_name(dev));
-                       r->flags &= ~IORESOURCE_ROM_ENABLE;
                        pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-                       pci_write_config_dword(dev, dev->rom_base_reg,
-                                              reg & ~PCI_ROM_ADDRESS_ENABLE);
+                       if (reg & PCI_ROM_ADDRESS_ENABLE) {
+                               pr_debug("PCI: Switching off ROM of %s\n",
+                                        pci_name(dev));
+                               r->flags &= ~IORESOURCE_ROM_ENABLE;
+                               pci_write_config_dword(dev, dev->rom_base_reg,
+                                                      reg & ~PCI_ROM_ADDRESS_ENABLE);
+                       }
                }
        }
 }
 
+static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       resource_size_t offset;
+       struct resource *res, *pres;
+       int i;
+
+       pr_debug("Reserving legacy ranges for domain %04x\n", pci_domain_nr(bus));
+
+       /* Check for IO */
+       if (!(hose->io_resource.flags & IORESOURCE_IO))
+               goto no_io;
+       offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+       BUG_ON(res == NULL);
+       res->name = "Legacy IO";
+       res->flags = IORESOURCE_IO;
+       res->start = offset;
+       res->end = (offset + 0xfff) & 0xfffffffful;
+       pr_debug("Candidate legacy IO: %pR\n", res);
+       if (request_resource(&hose->io_resource, res)) {
+               printk(KERN_DEBUG
+                      "PCI %04x:%02x Cannot reserve Legacy IO %pR\n",
+                      pci_domain_nr(bus), bus->number, res);
+               kfree(res);
+       }
+
+ no_io:
+       /* Check for memory */
+       offset = hose->pci_mem_offset;
+       pr_debug("hose mem offset: %016llx\n", (unsigned long long)offset);
+       for (i = 0; i < 3; i++) {
+               pres = &hose->mem_resources[i];
+               if (!(pres->flags & IORESOURCE_MEM))
+                       continue;
+               pr_debug("hose mem res: %pR\n", pres);
+               if ((pres->start - offset) <= 0xa0000 &&
+                   (pres->end - offset) >= 0xbffff)
+                       break;
+       }
+       if (i >= 3)
+               return;
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+       BUG_ON(res == NULL);
+       res->name = "Legacy VGA memory";
+       res->flags = IORESOURCE_MEM;
+       res->start = 0xa0000 + offset;
+       res->end = 0xbffff + offset;
+       pr_debug("Candidate VGA memory: %pR\n", res);
+       if (request_resource(pres, res)) {
+               printk(KERN_DEBUG
+                      "PCI %04x:%02x Cannot reserve VGA memory %pR\n",
+                      pci_domain_nr(bus), bus->number, res);
+               kfree(res);
+       }
+}
+
 void __init pcibios_resource_survey(void)
 {
        struct pci_bus *b;
@@ -1375,8 +1468,20 @@ void __init pcibios_resource_survey(void)
                pcibios_allocate_resources(1);
        }
 
+       /* Before we start assigning unassigned resource, we try to reserve
+        * the low IO area and the VGA memory area if they intersect the
+        * bus available resources to avoid allocating things on top of them
+        */
        if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
-               pr_debug("PCI: Assigning unassigned resouces...\n");
+               list_for_each_entry(b, &pci_root_buses, node)
+                       pcibios_reserve_legacy_regions(b);
+       }
+
+       /* Now, if the platform didn't decide to blindly trust the firmware,
+        * we proceed to assigning things that were left unassigned
+        */
+       if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+               pr_debug("PCI: Assigning unassigned resources...\n");
                pci_assign_unassigned_resources();
        }
 
@@ -1386,11 +1491,13 @@ void __init pcibios_resource_survey(void)
 }
 
 #ifdef CONFIG_HOTPLUG
-/* This is used by the pSeries hotplug driver to allocate resource
+
+/* This is used by the PCI hotplug driver to allocate resource
  * of newly plugged busses. We can try to consolidate with the
- * rest of the code later, for now, keep it as-is
+ * rest of the code later, for now, keep it as-is as our main
+ * resource allocation function doesn't deal with sub-trees yet.
  */
-void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
+void pcibios_claim_one_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        struct pci_bus *child_bus;
@@ -1403,6 +1510,14 @@ void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
 
                        if (r->parent || !r->start || !r->flags)
                                continue;
+
+                       pr_debug("PCI: Claiming %s: "
+                                "Resource %d: %016llx..%016llx [%x]\n",
+                                pci_name(dev), i,
+                                (unsigned long long)r->start,
+                                (unsigned long long)r->end,
+                                (unsigned int)r->flags);
+
                        pci_claim_resource(dev, i);
                }
        }
@@ -1410,7 +1525,31 @@ void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
        list_for_each_entry(child_bus, &bus->children, node)
                pcibios_claim_one_bus(child_bus);
 }
-EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+
+
+/* pcibios_finish_adding_to_bus
+ *
+ * This is to be called by the hotplug code after devices have been
+ * added to a bus, this include calling it for a PHB that is just
+ * being added
+ */
+void pcibios_finish_adding_to_bus(struct pci_bus *bus)
+{
+       pr_debug("PCI: Finishing adding to hotplug bus %04x:%02x\n",
+                pci_domain_nr(bus), bus->number);
+
+       /* Allocate bus and devices resources */
+       pcibios_allocate_bus_resources(bus);
+       pcibios_claim_one_bus(bus);
+
+       /* Add new devices to global lists.  Register in proc, sysfs. */
+       pci_bus_add_devices(bus);
+
+       /* Fixup EEH */
+       eeh_add_device_tree_late(bus);
+}
+EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
+
 #endif /* CONFIG_HOTPLUG */
 
 int pcibios_enable_device(struct pci_dev *dev, int mask)
@@ -1479,3 +1618,122 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
 
 }
 
+/*
+ * Null PCI config access functions, for the case when we can't
+ * find a hose.
+ */
+#define NULL_PCI_OP(rw, size, type)                                    \
+static int                                                             \
+null_##rw##_config_##size(struct pci_dev *dev, int offset, type val)   \
+{                                                                      \
+       return PCIBIOS_DEVICE_NOT_FOUND;                                \
+}
+
+static int
+null_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+                int len, u32 *val)
+{
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int
+null_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+                 int len, u32 val)
+{
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static struct pci_ops null_pci_ops =
+{
+       .read = null_read_config,
+       .write = null_write_config,
+};
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_bus *
+fake_pci_bus(struct pci_controller *hose, int busnr)
+{
+       static struct pci_bus bus;
+
+       if (hose == 0) {
+               printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);
+       }
+       bus.number = busnr;
+       bus.sysdata = hose;
+       bus.ops = hose? hose->ops: &null_pci_ops;
+       return &bus;
+}
+
+#define EARLY_PCI_OP(rw, size, type)                                   \
+int early_##rw##_config_##size(struct pci_controller *hose, int bus,   \
+                              int devfn, int offset, type value)       \
+{                                                                      \
+       return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus),    \
+                                           devfn, offset, value);      \
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
+
+extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
+int early_find_capability(struct pci_controller *hose, int bus, int devfn,
+                         int cap)
+{
+       return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap);
+}
+
+/**
+ * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
+ * @hose: Pointer to the PCI host controller instance structure
+ * @sysdata: value to use for sysdata pointer.  ppc32 and ppc64 differ here
+ *
+ * Note: the 'data' pointer is a temporary measure.  As 32 and 64 bit
+ * pci code gets merged, this parameter should become unnecessary because
+ * both will use the same value.
+ */
+void __devinit pcibios_scan_phb(struct pci_controller *hose, void *sysdata)
+{
+       struct pci_bus *bus;
+       struct device_node *node = hose->dn;
+       int mode;
+
+       pr_debug("PCI: Scanning PHB %s\n",
+                node ? node->full_name : "<NO NAME>");
+
+       /* Create an empty bus for the toplevel */
+       bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops,
+                            sysdata);
+       if (bus == NULL) {
+               pr_err("Failed to create bus for PCI domain %04x\n",
+                       hose->global_number);
+               return;
+       }
+       bus->secondary = hose->first_busno;
+       hose->bus = bus;
+
+       /* Get some IO space for the new PHB */
+       pcibios_setup_phb_io_space(hose);
+
+       /* Wire up PHB bus resources */
+       pcibios_setup_phb_resources(hose);
+
+       /* Get probe mode and perform scan */
+       mode = PCI_PROBE_NORMAL;
+       if (node && ppc_md.pci_probe_mode)
+               mode = ppc_md.pci_probe_mode(bus);
+       pr_debug("    probe mode: %d\n", mode);
+       if (mode == PCI_PROBE_DEVTREE) {
+               bus->subordinate = hose->last_busno;
+               of_scan_bus(node, bus);
+       }
+
+       if (mode == PCI_PROBE_NORMAL)
+               hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+}