FSL PCIe rescan issue on 2.6.38

Using kernel 2.6.38.7 with FSL P10xx based boards I found that PCIe bus rescan didn't work.
I fixed the issue (also) back-porting some parts from 3.6.

--- linux-2.6.38.orig/include/asm-generic/pci-bridge.h    1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.38/include/asm-generic/pci-bridge.h    2013-01-22 17:36:02.849353325 +0100
@@ -0,0 +1,74 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ASM_GENERIC_PCI_BRIDGE_H
+#define _ASM_GENERIC_PCI_BRIDGE_H
+
+#ifdef __KERNEL__
+
+enum {
+    /* Force re-assigning all resources (ignore firmware
+     * setup completely)
+     */
+    PCI_REASSIGN_ALL_RSRC    = 0x00000001,
+
+    /* Re-assign all bus numbers */
+    PCI_REASSIGN_ALL_BUS    = 0x00000002,
+
+    /* Do not try to assign, just use existing setup */
+    PCI_PROBE_ONLY        = 0x00000004,
+
+    /* Don't bother with ISA alignment unless the bridge has
+     * ISA forwarding enabled
+     */
+    PCI_CAN_SKIP_ISA_ALIGN    = 0x00000008,
+
+    /* Enable domain numbers in /proc */
+    PCI_ENABLE_PROC_DOMAINS    = 0x00000010,
+    /* ... except for domain 0 */
+    PCI_COMPAT_DOMAIN_0    = 0x00000020,
+
+    /* PCIe downstream ports are bridges that normally lead to only a
+     * device 0, but if this is set, we scan all possible devices, not
+     * just device 0.
+     */
+    PCI_SCAN_ALL_PCIE_DEVS    = 0x00000040,
+};
+
+#ifdef CONFIG_PCI
+extern unsigned int ppc_pci_flags;
+
+static inline void pci_set_flags(int flags)
+{
+    ppc_pci_flags = flags;
+}
+
+static inline void pci_add_flags(int flags)
+{
+    ppc_pci_flags |= flags;
+}
+
+static inline void pci_clear_flags(int flags)
+{
+    ppc_pci_flags &= ~flags;
+}
+
+static inline int pci_has_flag(int flag)
+{
+    return ppc_pci_flags & flag;
+}
+#else
+static inline void pci_set_flags(int flags) { }
+static inline void pci_add_flags(int flags) { }
+static inline void pci_clear_flags(int flags) { }
+static inline int pci_has_flag(int flag)
+{
+    return 0;
+}
+#endif    /* CONFIG_PCI */
+
+#endif    /* __KERNEL__ */
+#endif    /* _ASM_GENERIC_PCI_BRIDGE_H */
--- linux-2.6.38.orig/arch/powerpc/kernel/pci-common.c    2011-05-22 00:13:59.000000000 +0200
+++ linux-2.6.38/arch/powerpc/kernel/pci-common.c    2013-01-22 16:37:14.425401030 +0100
@@ -1666,13 +1707,26 @@
 int early_##rw##_config_##size(struct pci_controller *hose, int bus,    \
                    int devfn, int offset, type value)    \
 {                                    \
+   printk(">>> %s: bus=% devfn=%i offset=%08x, value=%08x\n", \
+        __FUNCTION__, bus, devfn, offset, 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 *)
+#define EARLY_PCI_ROP(rw, size, type)                    \
+int early_##rw##_config_##size(struct pci_controller *hose, int bus,    \
+                   int devfn, int offset, type value)    \
+{                                    \
+    int res = pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus),    \
+                        devfn, offset, value);    \
+   printk("<<< %s: bus=% devfn=%i offset=%08x, value=%08x res=%i\n", \
+        __FUNCTION__, bus, devfn, offset, *value, res ); \
+   return res; \
+}
+
+EARLY_PCI_ROP(read, byte, u8 *)
+EARLY_PCI_ROP(read, word, u16 *)
+EARLY_PCI_ROP(read, dword, u32 *)
 EARLY_PCI_OP(write, byte, u8)
 EARLY_PCI_OP(write, word, u16)
 EARLY_PCI_OP(write, dword, u32)
 }
--- linux-2.6.38.orig/arch/powerpc/sysdev/fsl_pci.c    2011-05-22 00:13:59.000000000 +0200
+++ linux-2.6.38/arch/powerpc/sysdev/fsl_pci.c    2013-01-22 16:40:16.897398563 +0100
@@ -27,6 +27,7 @@
 #include <linux/log2.h>
 #include <linux/slab.h>
 
+#include <asm-generic/pci-bridge.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
@@ -36,38 +37,97 @@
 
 static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
 
-static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
+static int fsl_pcie_check_link(struct pci_controller *hose)
 {
+    u32 val;
+
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
+
+    early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
+    if (val < PCIE_LTSSM_L0)
+        return 1;
+    return 0;
+}
+
+static int fsl_pcie_check_link2(struct pci_dev *dev)
+{
+    u32 val;
+
+    pci_read_config_dword(dev, PCIE_LTSSM, &val);
+  
+   printk("----FLSPCI: %s val=%08x\n", __FUNCTION__, val);
+
+    if (val < PCIE_LTSSM_L0)
+        return 1;
+
+    return 0;
+}
+
+static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev)
+{
+    u8 progif;
+   struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
+
     /* if we aren't a PCIe don't bother */
     if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
         return;
 
+   if (fsl_pcie_check_link2(dev))
+            hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+   else
+            hose->indirect_type &= ~PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+
+    /* if we aren't in host mode don't bother */
+    pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
+    if (progif & 0x1)
+        return;
+
     dev->class = PCI_CLASS_BRIDGE_PCI << 8;
     fsl_pcie_bus_fixup = 1;
     return;
 }
 
-static int __init fsl_pcie_check_link(struct pci_controller *hose)
+#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+
+#define MAX_PHYS_ADDR_BITS    40
+static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS;
+
+static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
 {
-    u32 val;
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
 
-    early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
-    if (val < PCIE_LTSSM_L0)
-        return 1;
+    if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+        return -EIO;
+
+    /*
+     * Fixup PCI devices that are able to DMA to above the physical
+     * address width of the SoC such that we can address any internal
+     * SoC address from across PCI if needed
+     */
+    if ((dev->bus == &pci_bus_type) &&
+        dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) {
+        set_dma_ops(dev, &dma_direct_ops);
+        set_dma_offset(dev, pci64_dma_offset);
+    }
+
+    *dev->dma_mask = dma_mask;
     return 0;
 }
 
-#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
 static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
     unsigned int index, const struct resource *res,
     resource_size_t offset)
 {
     resource_size_t pci_addr = res->start - offset;
     resource_size_t phys_addr = res->start;
-    resource_size_t size = res->end - res->start + 1;
+    resource_size_t size = resource_size(res);
     u32 flags = 0x80044000; /* enable & mem R/W */
     unsigned int i;
 
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
+
     pr_debug("PCI MEM resource start 0x%016llx, size 0x%016llx.\n",
         (u64)res->start, (u64)size);
 
@@ -99,17 +159,28 @@
                   struct resource *rsrc)
 {
     struct ccsr_pci __iomem *pci;
-    int i, j, n, mem_log, win_idx = 2;
+    int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4;
     u64 mem, sz, paddr_hi = 0;
     u64 paddr_lo = ULLONG_MAX;
     u32 pcicsrbar = 0, pcicsrbar_sz;
     u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
             PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
     char *name = hose->dn->full_name;
+    const u64 *reg;
+    int len;
+
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
 
     pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
-            (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
-    pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+         (u64)rsrc->start, (u64)resource_size(rsrc));
+
+    if (of_device_is_compatible(hose->dn, "fsl,qoriq-pcie-v2.2")) {
+        win_idx = 2;
+        start_idx = 0;
+        end_idx = 3;
+    }
+
+    pci = ioremap(rsrc->start, resource_size(rsrc));
     if (!pci) {
         dev_err(hose->parent, "Unable to map ATMU registers\n");
         return;
@@ -118,7 +189,7 @@
     /* Disable all windows (except powar0 since it's ignored) */
     for(i = 1; i < 5; i++)
         out_be32(&pci->pow[i].powar, 0);
-    for(i = 0; i < 3; i++)
+    for (i = start_idx; i < end_idx; i++)
         out_be32(&pci->piw[i].piwar, 0);
 
     /* Setup outbound MEM window */
@@ -146,9 +217,9 @@
         } else {
             pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, "
                  "phy base 0x%016llx.\n",
-                (u64)hose->io_resource.start,
-                (u64)hose->io_resource.end - (u64)hose->io_resource.start + 1,
-                (u64)hose->io_base_phys);
+                 (u64)hose->io_resource.start,
+                 (u64)resource_size(&hose->io_resource),
+                 (u64)hose->io_base_phys);
             out_be32(&pci->pow[j].potar, (hose->io_resource.start >> 12));
             out_be32(&pci->pow[j].potear, 0);
             out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12));
@@ -165,12 +236,12 @@
 
     if (paddr_hi == paddr_lo) {
         pr_err("%s: No outbound window space\n", name);
-        return ;
+        goto out;
     }
 
     if (paddr_lo == 0) {
         pr_err("%s: No space for inbound window\n", name);
-        return ;
+        goto out;
     }
 
     /* setup PCSRBAR/PEXCSRBAR */
@@ -191,6 +262,33 @@
 
     /* Setup inbound mem window */
     mem = memblock_end_of_DRAM();
+
+    /*
+     * The msi-address-64 property, if it exists, indicates the physical
+     * address of the MSIIR register.  Normally, this register is located
+     * inside CCSR, so the ATMU that covers all of CCSR is used. But if
+     * this property exists, then we normally need to create a new ATMU
+     * for it.  For now, however, we cheat.  The only entity that creates
+     * this property is the Freescale hypervisor, and the address is
+     * specified in the partition configuration.  Typically, the address
+     * is located in the page immediately after the end of DDR.  If so, we
+     * can avoid allocating a new ATMU by extending the DDR ATMU by one
+     * page.
+     */
+    reg = of_get_property(hose->dn, "msi-address-64", &len);
+    if (reg && (len == sizeof(u64))) {
+        u64 address = be64_to_cpup(reg);
+
+        if ((address >= mem) && (address < (mem + PAGE_SIZE))) {
+            pr_info("%s: extending DDR ATMU to cover MSIIR", name);
+            mem += PAGE_SIZE;
+        } else {
+            /* TODO: Create a new ATMU for MSIIR */
+            pr_warn("%s: msi-address-64 address of %llx is "
+                "unsupported\n", name, address);
+        }
+    }
+
     sz = min(mem, paddr_lo);
     mem_log = __ilog2_u64(sz);
 
@@ -204,7 +302,7 @@
             mem_log++;
         }
 
-        piwar |= (mem_log - 1);
+        piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
 
         /* Setup inbound memory window */
         out_be32(&pci->piw[win_idx].pitar,  0x00000000);
@@ -214,6 +312,37 @@
 
         hose->dma_window_base_cur = 0x00000000;
         hose->dma_window_size = (resource_size_t)sz;
+
+        /*
+         * if we have >4G of memory setup second PCI inbound window to
+         * let devices that are 64-bit address capable to work w/o
+         * SWIOTLB and access the full range of memory
+         */
+        if (sz != mem) {
+            mem_log = __ilog2_u64(mem);
+
+            /* Size window up if we dont fit in exact power-of-2 */
+            if ((1ull << mem_log) != mem)
+                mem_log++;
+
+            piwar = (piwar & ~PIWAR_SZ_MASK) | (mem_log - 1);
+
+            /* Setup inbound memory window */
+            out_be32(&pci->piw[win_idx].pitar,  0x00000000);
+            out_be32(&pci->piw[win_idx].piwbear,
+                    pci64_dma_offset >> 44);
+            out_be32(&pci->piw[win_idx].piwbar,
+                    pci64_dma_offset >> 12);
+            out_be32(&pci->piw[win_idx].piwar,  piwar);
+
+            /*
+             * install our own dma_set_mask handler to fixup dma_ops
+             * and dma_offset
+             */
+            ppc_md.dma_set_mask = fsl_pci_dma_set_mask;
+
+            pr_info("%s: Setup 64-bit PCI DMA window\n", name);
+        }
     } else {
         u64 paddr = 0;
 
@@ -259,6 +388,7 @@
             (u64)hose->dma_window_size);
     }
 
+out:
     iounmap(pci);
 }
 
@@ -267,6 +397,8 @@
     u16 cmd;
     int cap_x;
 
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
+
     early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd);
     cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
         | PCI_COMMAND_IO;
@@ -286,26 +418,38 @@
 void fsl_pcibios_fixup_bus(struct pci_bus *bus)
 {
     struct pci_controller *hose = pci_bus_to_host(bus);
-    int i;
+    int i, is_pcie = 0, no_link;
+
+    /* The root complex bridge comes up with bogus resources,
+     * we copy the PHB ones in.
+     *
+     * With the current generic PCI code, the PHB bus no longer
+     * has bus->resource[0..4] set, so things are a bit more
+     * tricky.
+     */
+
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
+
+    if (fsl_pcie_bus_fixup)
+        is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
+    no_link = !!(hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK);
 
-    if ((bus->parent == hose->bus) &&
-        ((fsl_pcie_bus_fixup &&
-          early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) ||
-         (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)))
-    {
-        for (i = 0; i < 4; ++i) {
+    if (bus->parent == hose->bus && (is_pcie || no_link)) {
+        for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; ++i) {
             struct resource *res = bus->resource[i];
-            struct resource *par = bus->parent->resource[i];
-            if (res) {
-                res->start = 0;
-                res->end   = 0;
-                res->flags = 0;
-            }
-            if (res && par) {
-                res->start = par->start;
-                res->end   = par->end;
-                res->flags = par->flags;
-            }
+            struct resource *par;
+
+            if (!res)
+                continue;
+            if (i == 0)
+                par = &hose->io_resource;
+            else if (i < 4)
+                par = &hose->mem_resources[i-1];
+            else par = NULL;
+
+            res->start = par ? par->start : 0;
+            res->end   = par ? par->end   : 0;
+            res->flags = par ? par->flags : 0;
         }
     }
 }
@@ -316,6 +460,14 @@
     struct pci_controller *hose;
     struct resource rsrc;
     const int *bus_range;
+    u8 progif;
+
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
+
+    if (!of_device_is_available(dev)) {
+        pr_warning("%s: disabled\n", dev->full_name);
+        return -ENODEV;
+    }
 
     pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
@@ -331,7 +483,7 @@
         printk(KERN_WARNING "Can't get bus-range for %s, assume"
             " bus 0\n", dev->full_name);
 
-    ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+    pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
     hose = pcibios_alloc_controller(dev);
     if (!hose)
         return -ENOMEM;
@@ -341,6 +493,18 @@
 
     setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
         PPC_INDIRECT_TYPE_BIG_ENDIAN);
+
+    early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif);
+    if ((progif & 1) == 1) {
+        /* unmap cfg_data & cfg_addr separately if not on same page */
+        if (((unsigned long)hose->cfg_data & PAGE_MASK) !=
+            ((unsigned long)hose->cfg_addr & PAGE_MASK))
+            iounmap(hose->cfg_data);
+        iounmap(hose->cfg_addr);
+        pcibios_free_controller(hose);
+        return -ENODEV;
+    }
+
     setup_pci_cmd(hose);
 
     /* check PCI express link status */
@@ -368,70 +532,11 @@
 
     return 0;
 }
-
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8548, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8543, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8547E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8545, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8569, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8568, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8567E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8567, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8533E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8533, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8536, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1021, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, quirk_fsl_pcie_header);
 #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
 
-#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8308, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378E, quirk_fsl_pcie_header);
-DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header);
 
+#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
 struct mpc83xx_pcie_priv {
     void __iomem *cfg_type0;
     void __iomem *cfg_type1;
@@ -667,7 +772,7 @@
                " bus 0\n", dev->full_name);
     }
 
-    ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
+    pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
     hose = pcibios_alloc_controller(dev);
     if (!hose)
         return -ENOMEM;
@@ -739,3 +844,78 @@
 
     return 0;
 }
+
+#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+static const struct of_device_id pci_ids[] = {
+    { .compatible = "fsl,mpc8540-pci", },
+    { .compatible = "fsl,mpc8548-pcie", },
+    { .compatible = "fsl,mpc8610-pci", },
+    { .compatible = "fsl,mpc8641-pcie", },
+    { .compatible = "fsl,p1022-pcie", },
+    { .compatible = "fsl,p1010-pcie", },
+    { .compatible = "fsl,p1023-pcie", },
+    { .compatible = "fsl,p4080-pcie", },
+    { .compatible = "fsl,qoriq-pcie-v2.3", },
+    { .compatible = "fsl,qoriq-pcie-v2.2", },
+    {},
+};
+
+struct device_node *fsl_pci_primary;
+
+void __devinit fsl_pci_init(void)
+{
+    int ret;
+    struct device_node *node;
+    struct pci_controller *hose;
+    dma_addr_t max = 0xffffffff;
+
+   printk("----FSLPCI: %s\n", __FUNCTION__ );
+
+    /* Callers can specify the primary bus using other means. */
+    if (!fsl_pci_primary) {
+        /* If a PCI host bridge contains an ISA node, it's primary. */
+        node = of_find_node_by_type(NULL, "isa");
+        while ((fsl_pci_primary = of_get_parent(node))) {
+            of_node_put(node);
+            node = fsl_pci_primary;
+
+            if (of_match_node(pci_ids, node))
+                break;
+        }
+    }
+
+    node = NULL;
+    for_each_node_by_type(node, "pci") {
+        if (of_match_node(pci_ids, node)) {
+            /*
+             * If there's no PCI host bridge with ISA, arbitrarily
+             * designate one as primary.  This can go away once
+             * various bugs with primary-less systems are fixed.
+             */
+            if (!fsl_pci_primary)
+                fsl_pci_primary = node;
+
+            ret = fsl_add_bridge(node, fsl_pci_primary == node);
+            if (ret == 0) {
+                hose = pci_find_hose_for_OF_device(node);
+                max = min(max, hose->dma_window_base_cur +
+                        hose->dma_window_size);
+            }
+        }
+    }
+
+#ifdef CONFIG_SWIOTLB
+   printk("----FSLPCI: %s CONFIG_SWIOTLB\n", __FUNCTION__ );
+    /*
+     * if we couldn't map all of DRAM via the dma windows
+     * we need SWIOTLB to handle buffers located outside of
+     * dma capable memory region
+     */
+    if (memblock_end_of_DRAM() - 1 > max) {
+        ppc_swiotlb_enable = 1;
+        set_pci_dma_ops(&swiotlb_dma_ops);
+        ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+    }
+#endif
+}
+#endif
--- linux-2.6.38.orig/arch/powerpc/sysdev/fsl_pci.h    2011-05-22 00:13:59.000000000 +0200
+++ linux-2.6.38/arch/powerpc/sysdev/fsl_pci.h    2013-01-17 09:35:15.027189928 +0100
@@ -21,6 +21,7 @@
 #define PIWAR_TGI_LOCAL        0x00f00000    /* target - local memory */
 #define PIWAR_READ_SNOOP    0x00050000
 #define PIWAR_WRITE_SNOOP    0x00005000
+#define PIWAR_SZ_MASK          0x0000003f
 
 /* PCI/PCI Express outbound window reg */
 struct pci_outbound_window_regs {
@@ -49,7 +50,9 @@
     __be32    int_ack;        /* 0x.008 - PCI Interrupt Acknowledge Register */
     __be32    pex_otb_cpl_tor;    /* 0x.00c - PCIE Outbound completion timeout register */
     __be32    pex_conf_tor;        /* 0x.010 - PCIE configuration timeout register */
-    u8    res2[12];
+    __be32    pex_config;        /* 0x.014 - PCIE CONFIG Register */
+    __be32    pex_int_status;        /* 0x.018 - PCIE interrupt status */
+    u8    res2[4];
     __be32    pex_pme_mes_dr;        /* 0x.020 - PCIE PME and message detect register */
     __be32    pex_pme_mes_disr;    /* 0x.024 - PCIE PME and message disable register */
     __be32    pex_pme_mes_ier;    /* 0x.028 - PCIE PME and message interrupt enable register */
@@ -62,14 +65,14 @@
  * in all of the other outbound windows.
  */
     struct pci_outbound_window_regs pow[5];
-
-    u8    res14[256];
-
-/* PCI/PCI Express inbound window 3-1
+    u8    res14[96];
+    struct pci_inbound_window_regs    pmit;    /* 0xd00 - 0xd9c Inbound MSI */
+    u8    res6[96];
+/* PCI/PCI Express inbound window 3-0
  * inbound window 1 supports only a 32-bit base address and does not
  * define an inbound window base extended address register.
  */
-    struct pci_inbound_window_regs piw[3];
+    struct pci_inbound_window_regs piw[4];
 
     __be32    pex_err_dr;        /* 0x.e00 - PCI/PCIE error detect register */
     u8    res21[4];
@@ -90,5 +93,13 @@
 extern int mpc83xx_add_bridge(struct device_node *dev);
 u64 fsl_pci_immrbar_base(struct pci_controller *hose);
 
+extern struct device_node *fsl_pci_primary;
+
+#ifdef CONFIG_FSL_PCI
+void fsl_pci_init(void);
+#else
+static inline void fsl_pci_init(void) {}
+#endif
+
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */


Comments