]> err.no Git - linux-2.6/blobdiff - arch/powerpc/kernel/pci_64.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/cooloney/blackfi...
[linux-2.6] / arch / powerpc / kernel / pci_64.c
index 7138092826aa4ce99fcabcc21d52217dc3a21d5d..249cca27a9b84ade58c94020534a8aa8a018ee83 100644 (file)
@@ -41,6 +41,7 @@
 
 unsigned long pci_probe_only = 1;
 int pci_assign_all_buses = 0;
+static int pci_initial_scan_done;
 
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
@@ -604,6 +605,8 @@ static int __init pcibios_init(void)
                /* map in PCI I/O space */
                phbs_remap_io();
 
+       pci_initial_scan_done = 1;
+
        printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
        return 0;
@@ -1006,8 +1009,9 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
 
                switch ((pci_space >> 24) & 0x3) {
                case 1:         /* I/O space */
-                       hose->io_base_phys = cpu_phys_addr;
-                       hose->pci_io_size = size;
+                       hose->io_base_phys = cpu_phys_addr - pci_addr;
+                       /* handle from 0 to top of I/O window */
+                       hose->pci_io_size = pci_addr + size;
 
                        res = &hose->io_resource;
                        res->flags = IORESOURCE_IO;
@@ -1041,13 +1045,16 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
        }
 }
 
-void __init pci_setup_phb_io(struct pci_controller *hose, int primary)
+void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary)
 {
        unsigned long size = hose->pci_io_size;
        unsigned long io_virt_offset;
        struct resource *res;
        struct device_node *isa_dn;
 
+       if (size == 0)
+               return;
+
        hose->io_base_virt = reserve_phb_iospace(size);
        DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
                hose->global_number, hose->io_base_phys,
@@ -1068,6 +1075,15 @@ void __init pci_setup_phb_io(struct pci_controller *hose, int primary)
        res = &hose->io_resource;
        res->start += io_virt_offset;
        res->end += io_virt_offset;
+
+       /* If this is called after the initial PCI scan, then we need to
+        * proceed to IO mappings now
+        */
+       if (pci_initial_scan_done)
+               __ioremap_explicit(hose->io_base_phys,
+                                  (unsigned long)hose->io_base_virt,
+                                  hose->pci_io_size,
+                                  _PAGE_NO_CACHE | _PAGE_GUARDED);
 }
 
 void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
@@ -1077,6 +1093,9 @@ void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
        unsigned long io_virt_offset;
        struct resource *res;
 
+       if (size == 0)
+               return;
+
        hose->io_base_virt = __ioremap(hose->io_base_phys, size,
                                        _PAGE_NO_CACHE | _PAGE_GUARDED);
        DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
@@ -1097,35 +1116,27 @@ static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
                                unsigned long *start_virt, unsigned long *size)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
-       struct pci_bus_region region;
        struct resource *res;
 
-       if (bus->self) {
+       if (bus->self)
                res = bus->resource[0];
-               pcibios_resource_to_bus(bus->self, &region, res);
-               *start_phys = hose->io_base_phys + region.start;
-               *start_virt = (unsigned long) hose->io_base_virt + 
-                               region.start;
-               if (region.end > region.start) 
-                       *size = region.end - region.start + 1;
-               else {
-                       printk("%s(): unexpected region 0x%lx->0x%lx\n", 
-                                       __FUNCTION__, region.start, region.end);
-                       return 1;
-               }
-               
-       } else {
+       else
                /* Root Bus */
                res = &hose->io_resource;
-               *start_phys = hose->io_base_phys;
-               *start_virt = (unsigned long) hose->io_base_virt;
-               if (res->end > res->start)
-                       *size = res->end - res->start + 1;
-               else {
-                       printk("%s(): unexpected region 0x%lx->0x%lx\n", 
-                                       __FUNCTION__, res->start, res->end);
-                       return 1;
-               }
+
+       if (res->end == 0 && res->start == 0)
+               return 1;
+
+       *start_virt = pci_io_base + res->start;
+       *start_phys = *start_virt + hose->io_base_phys
+               - (unsigned long) hose->io_base_virt;
+
+       if (res->end > res->start)
+               *size = res->end - res->start + 1;
+       else {
+               printk("%s(): unexpected region 0x%lx->0x%lx\n",
+                      __FUNCTION__, res->start, res->end);
+               return 1;
        }
 
        return 0;