]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/platforms/powermac/pci.c
Merge branch 'for-rmk' of git://git.marvell.com/orion
[linux-2.6-omap-h63xx.git] / arch / powerpc / platforms / powermac / pci.c
index ec49099830d55b0fe5c256180b3ac8b3c7f4eafb..bcf50d7056e933a6236e3f192390f8035901923e 100644 (file)
@@ -40,8 +40,6 @@
 static int has_uninorth;
 #ifdef CONFIG_PPC64
 static struct pci_controller *u3_agp;
-static struct pci_controller *u4_pcie;
-static struct pci_controller *u3_ht;
 #else
 static int has_second_ohare;
 #endif /* CONFIG_PPC64 */
@@ -314,12 +312,15 @@ static int u3_ht_skip_device(struct pci_controller *hose,
 
        /* We only allow config cycles to devices that are in OF device-tree
         * as we are apparently having some weird things going on with some
-        * revs of K2 on recent G5s
+        * revs of K2 on recent G5s, except for the host bridge itself, which
+        * is missing from the tree but we know we can probe.
         */
        if (bus->self)
                busdn = pci_device_to_OF_node(bus->self);
+       else if (devfn == 0)
+               return 0;
        else
-               busdn = hose->arch_data;
+               busdn = hose->dn;
        for (dn = busdn->child; dn; dn = dn->sibling)
                if (PCI_DN(dn) && PCI_DN(dn)->devfn == devfn)
                        break;
@@ -344,14 +345,15 @@ static int u3_ht_skip_device(struct pci_controller *hose,
                + (((unsigned int)bus) << 16) \
                + 0x01000000UL)
 
-static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose,
-                                            u8 bus, u8 devfn, u8 offset)
+static void __iomem *u3_ht_cfg_access(struct pci_controller *hose, u8 bus,
+                                     u8 devfn, u8 offset, int *swap)
 {
+       *swap = 1;
        if (bus == hose->first_busno) {
-               /* For now, we don't self probe U3 HT bridge */
-               if (PCI_SLOT(devfn) == 0)
-                       return NULL;
-               return hose->cfg_data + U3_HT_CFA0(devfn, offset);
+               if (devfn != 0)
+                       return hose->cfg_data + U3_HT_CFA0(devfn, offset);
+               *swap = 0;
+               return ((void __iomem *)hose->cfg_addr) + (offset << 2);
        } else
                return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
 }
@@ -360,14 +362,15 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
                                    int offset, int len, u32 *val)
 {
        struct pci_controller *hose;
-       volatile void __iomem *addr;
+       void __iomem *addr;
+       int swap;
 
        hose = pci_bus_to_host(bus);
        if (hose == NULL)
                return PCIBIOS_DEVICE_NOT_FOUND;
        if (offset >= 0x100)
                return  PCIBIOS_BAD_REGISTER_NUMBER;
-       addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+       addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
        if (!addr)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -397,10 +400,10 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
                *val = in_8(addr);
                break;
        case 2:
-               *val = in_le16(addr);
+               *val = swap ? in_le16(addr) : in_be16(addr);
                break;
        default:
-               *val = in_le32(addr);
+               *val = swap ? in_le32(addr) : in_be32(addr);
                break;
        }
        return PCIBIOS_SUCCESSFUL;
@@ -410,14 +413,15 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
                                     int offset, int len, u32 val)
 {
        struct pci_controller *hose;
-       volatile void __iomem *addr;
+       void __iomem *addr;
+       int swap;
 
        hose = pci_bus_to_host(bus);
        if (hose == NULL)
                return PCIBIOS_DEVICE_NOT_FOUND;
        if (offset >= 0x100)
                return  PCIBIOS_BAD_REGISTER_NUMBER;
-       addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+       addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
        if (!addr)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -439,10 +443,10 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
                out_8(addr, val);
                break;
        case 2:
-               out_le16(addr, val);
+               swap ? out_le16(addr, val) : out_be16(addr, val);
                break;
        default:
-               out_le32((u32 __iomem *)addr, val);
+               swap ? out_le32(addr, val) : out_be32(addr, val);
                break;
        }
        return PCIBIOS_SUCCESSFUL;
@@ -725,7 +729,7 @@ static void __init setup_bandit(struct pci_controller *hose,
 static int __init setup_uninorth(struct pci_controller *hose,
                                 struct resource *addr)
 {
-       pci_assign_all_buses = 1;
+       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
        has_uninorth = 1;
        hose->ops = &macrisc_pci_ops;
        hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -773,31 +777,72 @@ static void __init setup_u4_pcie(struct pci_controller* hose)
         */
        hose->first_busno = 0x00;
        hose->last_busno = 0xff;
-       u4_pcie = hose;
 }
 
-static void __init setup_u3_ht(struct pci_controller* hose)
+static void __init parse_region_decode(struct pci_controller *hose,
+                                      u32 decode)
 {
-       struct device_node *np = (struct device_node *)hose->arch_data;
-       struct pci_controller *other = NULL;
-       int i, cur;
+       unsigned long base, end, next = -1;
+       int i, cur = -1;
 
+       /* Iterate through all bits. We ignore the last bit as this region is
+        * reserved for the ROM among other niceties
+        */
+       for (i = 0; i < 31; i++) {
+               if ((decode & (0x80000000 >> i)) == 0)
+                       continue;
+               if (i < 16) {
+                       base = 0xf0000000 | (((u32)i) << 24);
+                       end = base + 0x00ffffff;
+               } else {
+                       base = ((u32)i-16) << 28;
+                       end = base + 0x0fffffff;
+               }
+               if (base != next) {
+                       if (++cur >= 3) {
+                               printk(KERN_WARNING "PCI: Too many ranges !\n");
+                               break;
+                       }
+                       hose->mem_resources[cur].flags = IORESOURCE_MEM;
+                       hose->mem_resources[cur].name = hose->dn->full_name;
+                       hose->mem_resources[cur].start = base;
+                       hose->mem_resources[cur].end = end;
+                       DBG("  %d: 0x%08lx-0x%08lx\n", cur, base, end);
+               } else {
+                       DBG("   :           -0x%08lx\n", end);
+                       hose->mem_resources[cur].end = end;
+               }
+               next = end + 1;
+       }
+}
+
+static void __init setup_u3_ht(struct pci_controller* hose)
+{
+       struct device_node *np = hose->dn;
+       struct resource cfg_res, self_res;
+       u32 decode;
 
        hose->ops = &u3_ht_pci_ops;
 
-       /* We hard code the address because of the different size of
-        * the reg address cell, we shall fix that by killing struct
-        * reg_property and using some accessor functions instead
+       /* Get base addresses from OF tree
+        */
+       if (of_address_to_resource(np, 0, &cfg_res) ||
+           of_address_to_resource(np, 1, &self_res)) {
+               printk(KERN_ERR "PCI: Failed to get U3/U4 HT resources !\n");
+               return;
+       }
+
+       /* Map external cfg space access into cfg_data and self registers
+        * into cfg_addr
         */
-       hose->cfg_data = ioremap(0xf2000000, 0x02000000);
+       hose->cfg_data = ioremap(cfg_res.start, 0x02000000);
+       hose->cfg_addr = ioremap(self_res.start,
+                                self_res.end - self_res.start + 1);
 
        /*
-        * /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, we read the register
+        * that controls the decoding logic and use that for memory regions.
+        * The IO region is hard coded since it is fixed in HW as well.
         */
        hose->io_base_phys = 0xf4000000;
        hose->pci_io_size = 0x00400000;
@@ -808,76 +853,33 @@ static void __init setup_u3_ht(struct pci_controller* hose)
        hose->pci_mem_offset = 0;
        hose->first_busno = 0;
        hose->last_busno = 0xef;
-       hose->mem_resources[0].name = np->full_name;
-       hose->mem_resources[0].start = 0x80000000;
-       hose->mem_resources[0].end = 0xefffffff;
-       hose->mem_resources[0].flags = IORESOURCE_MEM;
 
-       u3_ht = hose;
+       /* Note: fix offset when cfg_addr becomes a void * */
+       decode = in_be32(hose->cfg_addr + 0x80);
 
-       if (u3_agp != NULL)
-               other = u3_agp;
-       else if (u4_pcie != NULL)
-               other = u4_pcie;
+       DBG("PCI: Apple HT bridge decode register: 0x%08x\n", decode);
 
-       if (other == NULL) {
-               DBG("U3/4 has no AGP/PCIE, using full resource range\n");
-               return;
-       }
-
-       /* Fixup bus range vs. PCIE */
-       if (u4_pcie)
-               hose->last_busno = u4_pcie->first_busno - 1;
-
-       /* 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
+       /* NOTE: The decode register setup is a bit weird... region
+        * 0xf8000000 for example is marked as enabled in there while it's
+        & actually the memory controller registers.
+        * That means that we are incorrectly attributing it to HT.
+        *
+        * In a similar vein, region 0xf4000000 is actually the HT IO space but
+        * also marked as enabled in here and 0xf9000000 is used by some other
+        * internal bits of the northbridge.
+        *
+        * Unfortunately, we can't just mask out those bit as we would end
+        * up with more regions than we can cope (linux can only cope with
+        * 3 memory regions for a PHB at this stage).
+        *
+        * So for now, we just do a little hack. We happen to -know- that
+        * Apple firmware doesn't assign things below 0xfa000000 for that
+        * bridge anyway so we mask out all bits we don't want.
         */
-       cur = 0;
-       for (i=0; i<3; i++) {
-               struct resource *res = &other->mem_resources[i];
-               if (res->flags != IORESOURCE_MEM)
-                       continue;
-               /* 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
-                */
-               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);
-                       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);
-                       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");
-                       hose->mem_resources[cur].end = res->start - 1;
-                       continue;
-               }
-               cur++;
-               DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
-                   cur-1, res->start - 1, cur, res->end + 1);
-               hose->mem_resources[cur].name = np->full_name;
-               hose->mem_resources[cur].flags = IORESOURCE_MEM;
-               hose->mem_resources[cur].start = res->end + 1;
-               hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
-               hose->mem_resources[cur-1].end = res->start - 1;
-       }
+       decode &= 0x003fffff;
+
+       /* Now parse the resulting bits and build resources */
+       parse_region_decode(hose, decode);
 }
 #endif /* CONFIG_PPC64 */
 
@@ -994,6 +996,8 @@ void __init pmac_pci_init(void)
        struct device_node *np, *root;
        struct device_node *ht = NULL;
 
+       ppc_pci_flags = PPC_PCI_CAN_SKIP_ISA_ALIGN;
+
        root = of_find_node_by_path("/");
        if (root == NULL) {
                printk(KERN_CRIT "pmac_pci_init: can't find root "
@@ -1032,15 +1036,15 @@ void __init pmac_pci_init(void)
         * future though
         */
        if (u3_agp) {
-               struct device_node *np = u3_agp->arch_data;
+               struct device_node *np = u3_agp->dn;
                PCI_DN(np)->busno = 0xf0;
                for (np = np->child; np; np = np->sibling)
                        PCI_DN(np)->busno = 0xf0;
        }
        /* pmac_check_ht_link(); */
 
-       /* Tell pci.c to not use the common resource allocation mechanism */
-       pci_probe_only = 1;
+       /* We can allocate missing resources if any */
+       pci_probe_only = 0;
 
 #else /* CONFIG_PPC64 */
        init_p2pbridge();
@@ -1051,13 +1055,13 @@ void __init pmac_pci_init(void)
         * some offset between bus number and domains for now when we
         * assign all busses should help for now
         */
-       if (pci_assign_all_buses)
+       if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
                pcibios_assign_bus_offset = 0x10;
 #endif
 }
 
-int
-pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+#ifdef CONFIG_PPC32
+int pmac_pci_enable_device_hook(struct pci_dev *dev)
 {
        struct device_node* node;
        int updatecfg = 0;
@@ -1099,24 +1103,21 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
                updatecfg = 1;
        }
 
+       /*
+        * Fixup various header fields on 32 bits. We don't do that on
+        * 64 bits as some of these have strange values behind the HT
+        * bridge and we must not, for example, enable MWI or set the
+        * cache line size on them.
+        */
        if (updatecfg) {
                u16 cmd;
 
-               /*
-                * Make sure PCI is correctly configured
-                *
-                * We use old pci_bios versions of the function since, by
-                * default, gmac is not powered up, and so will be absent
-                * from the kernel initial PCI lookup.
-                *
-                * Should be replaced by 2.4 new PCI mechanisms and really
-                * register the device.
-                */
                pci_read_config_word(dev, PCI_COMMAND, &cmd);
                cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
                        | PCI_COMMAND_INVALIDATE;
                pci_write_config_word(dev, PCI_COMMAND, cmd);
                pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
+
                pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
                                      L1_CACHE_BYTES >> 2);
        }
@@ -1124,6 +1125,18 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
        return 0;
 }
 
+void __devinit pmac_pci_fixup_ohci(struct pci_dev *dev)
+{
+       struct device_node *node = pci_device_to_OF_node(dev);
+
+       /* We don't want to assign resources to USB controllers
+        * absent from the OF tree (iBook second controller)
+        */
+       if (dev->class == PCI_CLASS_SERIAL_USB_OHCI && !node)
+               dev->resource[0].flags = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_APPLE, PCI_ANY_ID, pmac_pci_fixup_ohci);
+
 /* We power down some devices after they have been probed. They'll
  * be powered back on later on
  */
@@ -1131,28 +1144,6 @@ void __init pmac_pcibios_after_init(void)
 {
        struct device_node* nd;
 
-#ifdef CONFIG_BLK_DEV_IDE
-       struct pci_dev *dev = NULL;
-
-       /* OF fails to initialize IDE controllers on macs
-        * (and maybe other machines)
-        *
-        * Ideally, this should be moved to the IDE layer, but we need
-        * to check specifically with Andre Hedrick how to do it cleanly
-        * since the common IDE code seem to care about the fact that the
-        * BIOS may have disabled a controller.
-        *
-        * -- BenH
-        */
-       for_each_pci_dev(dev) {
-               if ((dev->class >> 16) != PCI_BASE_CLASS_STORAGE)
-                       continue;
-               if (pci_enable_device(dev))
-                       printk(KERN_WARNING
-                              "pci: Failed to enable %s\n", pci_name(dev));
-       }
-#endif /* CONFIG_BLK_DEV_IDE */
-
        for_each_node_by_name(nd, "firewire") {
                if (nd->parent && (of_device_is_compatible(nd, "pci106b,18") ||
                                   of_device_is_compatible(nd, "pci106b,30") ||
@@ -1171,7 +1162,6 @@ void __init pmac_pcibios_after_init(void)
        of_node_put(nd);
 }
 
-#ifdef CONFIG_PPC32
 void pmac_pci_fixup_cardbus(struct pci_dev* dev)
 {
        if (!machine_is(powermac))
@@ -1243,16 +1233,23 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev)
  good:
        pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
        if ((progif & 5) != 5) {
-               printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n",
+               printk(KERN_INFO "PCI: %s Forcing PCI IDE into native mode\n",
                       pci_name(dev));
                (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
                if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
                    (progif & 5) != 5)
                        printk(KERN_ERR "Rewrite of PROGIF failed !\n");
+               else {
+                       /* Clear IO BARs, they will be reassigned */
+                       pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0);
+                       pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
+                       pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, 0);
+                       pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, 0);
+               }
        }
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
-#endif
+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
+#endif /* CONFIG_PPC32 */
 
 /*
  * Disable second function on K2-SATA, it's broken