diff options
-rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4ce547e00473..8f92446ff0ae 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -65,6 +65,30 @@ static int __init fsl_pcie_check_link(struct pci_controller *hose) | |||
65 | } | 65 | } |
66 | 66 | ||
67 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) | 67 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) |
68 | |||
69 | #define MAX_PHYS_ADDR_BITS 40 | ||
70 | static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS; | ||
71 | |||
72 | static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask) | ||
73 | { | ||
74 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | ||
75 | return -EIO; | ||
76 | |||
77 | /* | ||
78 | * Fixup PCI devices that are able to DMA to above the physical | ||
79 | * address width of the SoC such that we can address any internal | ||
80 | * SoC address from across PCI if needed | ||
81 | */ | ||
82 | if ((dev->bus == &pci_bus_type) && | ||
83 | dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) { | ||
84 | set_dma_ops(dev, &dma_direct_ops); | ||
85 | set_dma_offset(dev, pci64_dma_offset); | ||
86 | } | ||
87 | |||
88 | *dev->dma_mask = dma_mask; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
68 | static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, | 92 | static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, |
69 | unsigned int index, const struct resource *res, | 93 | unsigned int index, const struct resource *res, |
70 | resource_size_t offset) | 94 | resource_size_t offset) |
@@ -228,6 +252,37 @@ static void __init setup_pci_atmu(struct pci_controller *hose, | |||
228 | 252 | ||
229 | hose->dma_window_base_cur = 0x00000000; | 253 | hose->dma_window_base_cur = 0x00000000; |
230 | hose->dma_window_size = (resource_size_t)sz; | 254 | hose->dma_window_size = (resource_size_t)sz; |
255 | |||
256 | /* | ||
257 | * if we have >4G of memory setup second PCI inbound window to | ||
258 | * let devices that are 64-bit address capable to work w/o | ||
259 | * SWIOTLB and access the full range of memory | ||
260 | */ | ||
261 | if (sz != mem) { | ||
262 | mem_log = __ilog2_u64(mem); | ||
263 | |||
264 | /* Size window up if we dont fit in exact power-of-2 */ | ||
265 | if ((1ull << mem_log) != mem) | ||
266 | mem_log++; | ||
267 | |||
268 | piwar = (piwar & ~PIWAR_SZ_MASK) | (mem_log - 1); | ||
269 | |||
270 | /* Setup inbound memory window */ | ||
271 | out_be32(&pci->piw[win_idx].pitar, 0x00000000); | ||
272 | out_be32(&pci->piw[win_idx].piwbear, | ||
273 | pci64_dma_offset >> 44); | ||
274 | out_be32(&pci->piw[win_idx].piwbar, | ||
275 | pci64_dma_offset >> 12); | ||
276 | out_be32(&pci->piw[win_idx].piwar, piwar); | ||
277 | |||
278 | /* | ||
279 | * install our own dma_set_mask handler to fixup dma_ops | ||
280 | * and dma_offset | ||
281 | */ | ||
282 | ppc_md.dma_set_mask = fsl_pci_dma_set_mask; | ||
283 | |||
284 | pr_info("%s: Setup 64-bit PCI DMA window\n", name); | ||
285 | } | ||
231 | } else { | 286 | } else { |
232 | u64 paddr = 0; | 287 | u64 paddr = 0; |
233 | 288 | ||