Merge tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
[cascardo/linux.git] / arch / powerpc / sysdev / fsl_pci.c
index 85729f4..d3a5974 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 #include <asm/machdep.h>
+#include <asm/mpc85xx.h>
 #include <asm/disassemble.h>
 #include <asm/ppc-opcode.h>
 #include <sysdev/fsl_soc.h>
@@ -110,8 +111,7 @@ static struct pci_ops fsl_indirect_pcie_ops =
        .write = indirect_write_config,
 };
 
-#define MAX_PHYS_ADDR_BITS     40
-static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS;
+static u64 pci64_dma_offset;
 
 #ifdef CONFIG_SWIOTLB
 static void setup_swiotlb_ops(struct pci_controller *hose)
@@ -131,12 +131,10 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 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
+        * Fix up PCI devices that are able to DMA to the large inbound
+        * mapping that allows addressing any RAM address from across PCI.
         */
-       if ((dev_is_pci(dev)) &&
-           dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) {
+       if (dev_is_pci(dev) && dma_mask >= pci64_dma_offset * 2 - 1) {
                set_dma_ops(dev, &dma_direct_ops);
                set_dma_offset(dev, pci64_dma_offset);
        }
@@ -386,6 +384,7 @@ static void setup_pci_atmu(struct pci_controller *hose)
                                mem_log++;
 
                        piwar = (piwar & ~PIWAR_SZ_MASK) | (mem_log - 1);
+                       pci64_dma_offset = 1ULL << mem_log;
 
                        if (setup_inbound) {
                                /* Setup inbound memory window */
@@ -527,6 +526,8 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary)
        u8 hdr_type, progif;
        struct device_node *dev;
        struct ccsr_pci __iomem *pci;
+       u16 temp;
+       u32 svr = mfspr(SPRN_SVR);
 
        dev = pdev->dev.of_node;
 
@@ -596,6 +597,27 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary)
                        PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
                if (fsl_pcie_check_link(hose))
                        hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+       } else {
+               /*
+                * Set PBFR(PCI Bus Function Register)[10] = 1 to
+                * disable the combining of crossing cacheline
+                * boundary requests into one burst transaction.
+                * PCI-X operation is not affected.
+                * Fix erratum PCI 5 on MPC8548
+                */
+#define PCI_BUS_FUNCTION 0x44
+#define PCI_BUS_FUNCTION_MDS 0x400     /* Master disable streaming */
+               if (((SVR_SOC_VER(svr) == SVR_8543) ||
+                    (SVR_SOC_VER(svr) == SVR_8545) ||
+                    (SVR_SOC_VER(svr) == SVR_8547) ||
+                    (SVR_SOC_VER(svr) == SVR_8548)) &&
+                   !early_find_capability(hose, 0, 0, PCI_CAP_ID_PCIX)) {
+                       early_read_config_word(hose, 0, 0,
+                                       PCI_BUS_FUNCTION, &temp);
+                       temp |= PCI_BUS_FUNCTION_MDS;
+                       early_write_config_word(hose, 0, 0,
+                                       PCI_BUS_FUNCTION, temp);
+               }
        }
 
        printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "