/*
  * pci_controller(phb) initialized common variables.
  */
-void __devinit pci_setup_pci_controller(struct pci_controller *hose)
+static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
 {
        memset(hose, 0, sizeof(struct pci_controller));
 
        spin_unlock(&hose_spinlock);
 }
 
+static void add_linux_pci_domain(struct device_node *dev,
+                                struct pci_controller *phb)
+{
+       struct property *of_prop;
+       unsigned int size;
+
+       of_prop = (struct property *)
+               get_property(dev, "linux,pci-domain", &size);
+       if (of_prop != NULL)
+               return;
+       WARN_ON(of_prop && size < sizeof(int));
+       if (of_prop && size < sizeof(int))
+               of_prop = NULL;
+       size = sizeof(struct property) + sizeof(int);
+       if (of_prop == NULL) {
+               if (mem_init_done)
+                       of_prop = kmalloc(size, GFP_KERNEL);
+               else
+                       of_prop = alloc_bootmem(size);
+       }
+       memset(of_prop, 0, sizeof(struct property));
+       of_prop->name = "linux,pci-domain";
+       of_prop->length = sizeof(int);
+       of_prop->value = (unsigned char *)&of_prop[1];
+       *((int *)of_prop->value) = phb->global_number;
+       prom_add_property(dev, of_prop);
+}
+
+struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+{
+       struct pci_controller *phb;
+
+       if (mem_init_done)
+               phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+       else
+               phb = alloc_bootmem(sizeof (struct pci_controller));
+       if (phb == NULL)
+               return NULL;
+       pci_setup_pci_controller(phb);
+       phb->arch_data = dev;
+       phb->is_dynamic = mem_init_done;
+       if (dev)
+               add_linux_pci_domain(dev, phb);
+       return phb;
+}
+
+void pcibios_free_controller(struct pci_controller *phb)
+{
+       if (phb->arch_data) {
+               struct device_node *np = phb->arch_data;
+               int *domain = (int *)get_property(np,
+                                                 "linux,pci-domain", NULL);
+               if (domain)
+                       *domain = -1;
+       }
+       if (phb->is_dynamic)
+               kfree(phb);
+}
+
 static void __init pcibios_claim_one_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
         *                      (size depending on dev->n_addr_cells)
         *   cells 4+5 or 5+6:  the size of the range
         */
-       rlen = 0;
-       hose->io_base_phys = 0;
        ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+       if (ranges == NULL)
+               return;
+       hose->io_base_phys = 0;
        while ((rlen -= np * sizeof(unsigned int)) >= 0) {
                res = NULL;
                pci_space = ranges[0];
        
        if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
                return 1;
+       if (start_phys == 0)
+               return 1;
        printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
        if (__ioremap_explicit(start_phys, start_virt, size,
                               _PAGE_NO_CACHE | _PAGE_GUARDED))
 
                               struct pci_controller *phb,
                               unsigned int addr_size_words)
 {
-       pci_setup_pci_controller(phb);
-
        if (is_python(dev))
                python_countermeasures(dev, addr_size_words);
 
        if (phb_set_bus_ranges(dev, phb))
                return 1;
 
-       phb->arch_data = dev;
        phb->ops = &rtas_pci_ops;
        phb->buid = get_phb_buid(dev);
 
        return 0;
 }
 
-static void __devinit add_linux_pci_domain(struct device_node *dev,
-                                          struct pci_controller *phb,
-                                          struct property *of_prop)
-{
-       memset(of_prop, 0, sizeof(struct property));
-       of_prop->name = "linux,pci-domain";
-       of_prop->length = sizeof(phb->global_number);
-       of_prop->value = (unsigned char *)&of_prop[1];
-       memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
-       prom_add_property(dev, of_prop);
-}
-
-static struct pci_controller * __init alloc_phb(struct device_node *dev,
-                                               unsigned int addr_size_words)
-{
-       struct pci_controller *phb;
-       struct property *of_prop;
-
-       phb = alloc_bootmem(sizeof(struct pci_controller));
-       if (phb == NULL)
-               return NULL;
-
-       of_prop = alloc_bootmem(sizeof(struct property) +
-                               sizeof(phb->global_number));
-       if (!of_prop)
-               return NULL;
-
-       if (setup_phb(dev, phb, addr_size_words))
-               return NULL;
-
-       add_linux_pci_domain(dev, phb, of_prop);
-
-       return phb;
-}
-
-static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)
-{
-       struct pci_controller *phb;
-
-       phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
-                                              GFP_KERNEL);
-       if (phb == NULL)
-               return NULL;
-
-       if (setup_phb(dev, phb, addr_size_words))
-               return NULL;
-
-       phb->is_dynamic = 1;
-
-       /* TODO: linux,pci-domain? */
-
-       return phb;
-}
-
 unsigned long __init find_and_init_phbs(void)
 {
        struct device_node *node;
                if (node->type == NULL || strcmp(node->type, "pci") != 0)
                        continue;
 
-               phb = alloc_phb(node, root_size_cells);
+               phb = pcibios_alloc_controller(node);
                if (!phb)
                        continue;
-
+               setup_phb(node, phb, root_size_cells);
                pci_process_bridge_OF_ranges(phb, node, 0);
                pci_setup_phb_io(phb, index == 0);
 #ifdef CONFIG_PPC_PSERIES
        root_size_cells = prom_n_size_cells(root);
 
        primary = list_empty(&hose_list);
-       phb = alloc_phb_dynamic(dn, root_size_cells);
+       phb = pcibios_alloc_controller(dn);
        if (!phb)
                return NULL;
-
+       setup_phb(dn, phb, root_size_cells);
        pci_process_bridge_OF_ranges(phb, dn, primary);
 
        pci_setup_phb_io_dynamic(phb, primary);
        }
 
        list_del(&phb->list_node);
-       if (phb->is_dynamic)
-               kfree(phb);
+       pcibios_free_controller(phb);
 
        return 0;
 }
 
                if (ret == 0) {
                        printk("bus %d appears to exist\n", bus);
 
-                       phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+                       phb = pcibios_alloc_controller(NULL);
                        if (phb == NULL)
                                return -ENOMEM;
-                       pci_setup_pci_controller(phb);
 
                        phb->pci_mem_offset = phb->local_number = bus;
                        phb->first_busno = bus;
 
                dev->full_name);
        }
 
-       hose = alloc_bootmem(sizeof(struct pci_controller));
+       hose = pcibios_alloc_controller(dev);
        if (hose == NULL)
                return -ENOMEM;
-       pci_setup_pci_controller(hose);
-
-       hose->arch_data = dev;
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-       of_prop = alloc_bootmem(sizeof(struct property) +
-                               sizeof(hose->global_number));
-       if (of_prop) {
-               memset(of_prop, 0, sizeof(struct property));
-               of_prop->name = "linux,pci-domain";
-               of_prop->length = sizeof(hose->global_number);
-               of_prop->value = (unsigned char *)&of_prop[1];
-               memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number));
-               prom_add_property(dev, of_prop);
-       }
-
        disp_name = NULL;
        if (device_is_compatible(dev, "u3-agp")) {
                setup_u3_agp(hose);
 
         * the reg address cell, we shall fix that by killing struct
         * reg_property and using some accessor functions instead
         */
-       hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
+       hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000,
+                                                          0x02000000);
 
        /*
-        * /ht node doesn't expose a "ranges" property, so we "remove" regions that
-        * have been allocated to AGP. So far, this version of the code doesn't assign
-        * any of the 0xfxxxxxxx "fine" memory regions to /ht.
-        * We need to fix that sooner or later by either parsing all child "ranges"
-        * properties or figuring out the U3 address space decoding logic and
-        * then read its configuration register (if any).
+        * /ht node doesn't expose a "ranges" property, so we "remove"
+        * regions that have been allocated to AGP. So far, this version of
+        * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions
+        * to /ht. We need to fix that sooner or later by either parsing all
+        * child "ranges" properties or figuring out the U3 address space
+        * decoding logic and then read its configuration register (if any).
         */
        hose->io_base_phys = 0xf4000000;
        hose->pci_io_size = 0x00400000;
                return;
        }
 
-       /* We "remove" the AGP resources from the resources allocated to HT, that
-        * is we create "holes". However, that code does assumptions that so far
-        * happen to be true (cross fingers...), typically that resources in the
-        * AGP node are properly ordered
+       /* We "remove" the AGP resources from the resources allocated to HT,
+        * that is we create "holes". However, that code does assumptions
+        * that so far happen to be true (cross fingers...), typically that
+        * resources in the AGP node are properly ordered
         */
        cur = 0;
        for (i=0; i<3; i++) {
                /* We don't care about "fine" resources */
                if (res->start >= 0xf0000000)
                        continue;
-               /* Check if it's just a matter of "shrinking" us in one direction */
+               /* Check if it's just a matter of "shrinking" us in one
+                * direction
+                */
                if (hose->mem_resources[cur].start == res->start) {
                        DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
-                           cur, hose->mem_resources[cur].start, res->end + 1);
+                           cur, hose->mem_resources[cur].start,
+                           res->end + 1);
                        hose->mem_resources[cur].start = res->end + 1;
                        continue;
                }
                if (hose->mem_resources[cur].end == res->end) {
                        DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
-                           cur, hose->mem_resources[cur].end, res->start - 1);
+                           cur, hose->mem_resources[cur].end,
+                           res->start - 1);
                        hose->mem_resources[cur].end = res->start - 1;
                        continue;
                }
                /* No, it's not the case, we need a hole */
                if (cur == 2) {
-                       /* not enough resources for a hole, we drop part of the range */
-                       printk(KERN_WARNING "Running out of resources for /ht host !\n");
+                       /* not enough resources for a hole, we drop part
+                        * of the range
+                        */
+                       printk(KERN_WARNING "Running out of resources"
+                              " for /ht host !\n");
                        hose->mem_resources[cur].end = res->start - 1;
                        continue;
                }
                hose->mem_resources[cur-1].end = res->start - 1;
        }
 }
-
-/* XXX this needs to be converged between ppc32 and ppc64... */
-static struct pci_controller * __init pcibios_alloc_controller(void)
-{
-       struct pci_controller *hose;
-
-       hose = alloc_bootmem(sizeof(struct pci_controller));
-       if (hose)
-               pci_setup_pci_controller(hose);
-       return hose;
-}
 #endif
 
 /*
 #endif
        bus_range = (int *) get_property(dev, "bus-range", &len);
        if (bus_range == NULL || len < 2 * sizeof(int)) {
-               printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
-                              dev->full_name);
+               printk(KERN_WARNING "Can't get bus-range for %s, assume"
+                      " bus 0\n", dev->full_name);
        }
 
+       /* XXX Different prototypes, to be merged */
+#ifdef CONFIG_PPC64
+       hose = pcibios_alloc_controller(dev);
+#else
        hose = pcibios_alloc_controller();
+#endif
        if (!hose)
                return -ENOMEM;
        hose->arch_data = dev;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
        disp_name = NULL;
-#ifdef CONFIG_POWER4
+#ifdef CONFIG_PPC64
        if (device_is_compatible(dev, "u3-agp")) {
                setup_u3_agp(hose);
                disp_name = "U3-AGP";
 
 
 extern unsigned long isa_io_base;
 
-extern void pci_setup_pci_controller(struct pci_controller *hose);
 extern void pci_setup_phb_io(struct pci_controller *hose, int primary);
 extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary);
 
 
        int     busno;                  /* for pci devices */
        int     bussubno;               /* for pci devices */
        int     devfn;                  /* for pci devices */
+
+#ifdef CONFIG_PPC_PSERIES
        int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
        int     eeh_config_addr;
        int     eeh_check_count;        /* # times driver ignored error */
        int     eeh_freeze_count;       /* # times this device froze up. */
        int     eeh_is_bridge;          /* device is pci-to-pci bridge */
-
+#endif
        int     pci_ext_config_space;   /* for pci devices */
        struct  pci_controller *phb;    /* for pci devices */
        struct  iommu_table *iommu_table;       /* for phb's or bridges */
        struct  device_node *node;      /* back-pointer to the device_node */
 #ifdef CONFIG_PPC_ISERIES
        struct  list_head Device_List;
-       int             Irq;            /* Assigned IRQ */
-       int             Flags;          /* Possible flags(disable/bist)*/
-       u8              LogicalSlot;    /* Hv Slot Index for Tces */
+       int     Irq;                    /* Assigned IRQ */
+       int     Flags;                  /* Possible flags(disable/bist)*/
+       u8      LogicalSlot;            /* Hv Slot Index for Tces */
 #endif
        u32     config_space[16];       /* saved PCI config space */
 };
        return PCI_DN(busdn)->phb;
 }
 
+extern struct pci_controller *
+pcibios_alloc_controller(struct device_node *dev);
+extern void pcibios_free_controller(struct pci_controller *phb);
+
 /* Return values for ppc_md.pci_probe_mode function */
 #define PCI_PROBE_NONE         -1      /* Don't look at this bus at all */
 #define PCI_PROBE_NORMAL       0       /* Do normal PCI probing */