aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_pci.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-06 20:58:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-06 20:58:22 -0500
commite4e88f31bcb5f05f24b9ae518d4ecb44e1a7774d (patch)
tree9eef6998f5bbd1a2c999011d9e0151f00c6e7297 /arch/powerpc/sysdev/fsl_pci.c
parent9753dfe19a85e7e45a34a56f4cb2048bb4f50e27 (diff)
parentef88e3911c0e0301e73fa3b3b2567aabdbe17cc4 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (185 commits) powerpc: fix compile error with 85xx/p1010rdb.c powerpc: fix compile error with 85xx/p1023_rds.c powerpc/fsl: add MSI support for the Freescale hypervisor arch/powerpc/sysdev/fsl_rmu.c: introduce missing kfree powerpc/fsl: Add support for Integrated Flash Controller powerpc/fsl: update compatiable on fsl 16550 uart nodes powerpc/85xx: fix PCI and localbus properties in p1022ds.dts powerpc/85xx: re-enable ePAPR byte channel driver in corenet32_smp_defconfig powerpc/fsl: Update defconfigs to enable some standard FSL HW features powerpc: Add TBI PHY node to first MDIO bus sbc834x: put full compat string in board match check powerpc/fsl-pci: Allow 64-bit PCIe devices to DMA to any memory address powerpc: Fix unpaired probe_hcall_entry and probe_hcall_exit offb: Fix setting of the pseudo-palette for >8bpp offb: Add palette hack for qemu "standard vga" framebuffer offb: Fix bug in calculating requested vram size powerpc/boot: Change the WARN to INFO for boot wrapper overlap message powerpc/44x: Fix build error on currituck platform powerpc/boot: Change the load address for the wrapper to fit the kernel powerpc/44x: Enable CRASH_DUMP for 440x ... Fix up a trivial conflict in arch/powerpc/include/asm/cputime.h due to the additional sparse-checking code for cputime_t.
Diffstat (limited to 'arch/powerpc/sysdev/fsl_pci.c')
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 4ce547e00473..3b61e8cf3421 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
70static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS;
71
72static 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
68static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, 92static 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)
@@ -113,6 +137,8 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
113 u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL | 137 u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
114 PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; 138 PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
115 char *name = hose->dn->full_name; 139 char *name = hose->dn->full_name;
140 const u64 *reg;
141 int len;
116 142
117 pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n", 143 pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
118 (u64)rsrc->start, (u64)resource_size(rsrc)); 144 (u64)rsrc->start, (u64)resource_size(rsrc));
@@ -205,6 +231,33 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
205 231
206 /* Setup inbound mem window */ 232 /* Setup inbound mem window */
207 mem = memblock_end_of_DRAM(); 233 mem = memblock_end_of_DRAM();
234
235 /*
236 * The msi-address-64 property, if it exists, indicates the physical
237 * address of the MSIIR register. Normally, this register is located
238 * inside CCSR, so the ATMU that covers all of CCSR is used. But if
239 * this property exists, then we normally need to create a new ATMU
240 * for it. For now, however, we cheat. The only entity that creates
241 * this property is the Freescale hypervisor, and the address is
242 * specified in the partition configuration. Typically, the address
243 * is located in the page immediately after the end of DDR. If so, we
244 * can avoid allocating a new ATMU by extending the DDR ATMU by one
245 * page.
246 */
247 reg = of_get_property(hose->dn, "msi-address-64", &len);
248 if (reg && (len == sizeof(u64))) {
249 u64 address = be64_to_cpup(reg);
250
251 if ((address >= mem) && (address < (mem + PAGE_SIZE))) {
252 pr_info("%s: extending DDR ATMU to cover MSIIR", name);
253 mem += PAGE_SIZE;
254 } else {
255 /* TODO: Create a new ATMU for MSIIR */
256 pr_warn("%s: msi-address-64 address of %llx is "
257 "unsupported\n", name, address);
258 }
259 }
260
208 sz = min(mem, paddr_lo); 261 sz = min(mem, paddr_lo);
209 mem_log = __ilog2_u64(sz); 262 mem_log = __ilog2_u64(sz);
210 263
@@ -228,6 +281,37 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
228 281
229 hose->dma_window_base_cur = 0x00000000; 282 hose->dma_window_base_cur = 0x00000000;
230 hose->dma_window_size = (resource_size_t)sz; 283 hose->dma_window_size = (resource_size_t)sz;
284
285 /*
286 * if we have >4G of memory setup second PCI inbound window to
287 * let devices that are 64-bit address capable to work w/o
288 * SWIOTLB and access the full range of memory
289 */
290 if (sz != mem) {
291 mem_log = __ilog2_u64(mem);
292
293 /* Size window up if we dont fit in exact power-of-2 */
294 if ((1ull << mem_log) != mem)
295 mem_log++;
296
297 piwar = (piwar & ~PIWAR_SZ_MASK) | (mem_log - 1);
298
299 /* Setup inbound memory window */
300 out_be32(&pci->piw[win_idx].pitar, 0x00000000);
301 out_be32(&pci->piw[win_idx].piwbear,
302 pci64_dma_offset >> 44);
303 out_be32(&pci->piw[win_idx].piwbar,
304 pci64_dma_offset >> 12);
305 out_be32(&pci->piw[win_idx].piwar, piwar);
306
307 /*
308 * install our own dma_set_mask handler to fixup dma_ops
309 * and dma_offset
310 */
311 ppc_md.dma_set_mask = fsl_pci_dma_set_mask;
312
313 pr_info("%s: Setup 64-bit PCI DMA window\n", name);
314 }
231 } else { 315 } else {
232 u64 paddr = 0; 316 u64 paddr = 0;
233 317