arch/powerpc/sysdev/fsl_rmu.c: introduce missing kfree
[deliverable/linux.git] / arch / powerpc / sysdev / fsl_pci.c
index 4ce547e00473ef6a18206048425dd5aee01e3ec5..8f92446ff0ae1f065d0feca9267a8125ed7d5a41 100644 (file)
@@ -65,6 +65,30 @@ 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)
+{
+       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;
+}
+
 static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
        unsigned int index, const struct resource *res,
        resource_size_t offset)
@@ -228,6 +252,37 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 
                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;
 
This page took 0.03637 seconds and 5 git commands to generate.