diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-06 20:58:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-06 20:58:22 -0500 |
commit | e4e88f31bcb5f05f24b9ae518d4ecb44e1a7774d (patch) | |
tree | 9eef6998f5bbd1a2c999011d9e0151f00c6e7297 /arch/powerpc/sysdev/fsl_pci.c | |
parent | 9753dfe19a85e7e45a34a56f4cb2048bb4f50e27 (diff) | |
parent | ef88e3911c0e0301e73fa3b3b2567aabdbe17cc4 (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.c | 84 |
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 | ||
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) |
@@ -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 | ||