aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2006-04-01 18:07:39 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-04-01 18:07:39 -0500
commit23759dc6430428897a36c4d493f611eca55c9481 (patch)
treec62050927599b36ed223753c35fd737e3c0c6762 /arch/arm
parentd3f4c571b6e596f9d39c596426269006a309d3b8 (diff)
[ARM] 3439/2: xsc3: add I/O coherency support
Patch from Lennert Buytenhek This patch adds support for the I/O coherent cache available on the xsc3. The approach is to provide a simple API to determine whether the chipset supports coherency by calling arch_is_coherent() and then setting the appropriate system memory PTE and PMD bits. In addition, we call this API on dma_alloc_coherent() and dma_map_single() calls. A generic version exists that will compile out all the coherency-related code that is not needed on the majority of ARM systems. Note that we do not check for coherency in the dma_alloc_writecombine() function as that still requires a special PTE setting. We also don't touch dma_mmap_coherent() as that is a special ARM-only API that is by definition only used on non-coherent system. Signed-off-by: Deepak Saxena <dsaxena@plexity.net> Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--arch/arm/mach-ixp23xx/pci.c6
-rw-r--r--arch/arm/mm/consistent.c17
-rw-r--r--arch/arm/mm/mm-armv.c11
-rw-r--r--arch/arm/mm/proc-xsc3.S2
5 files changed, 38 insertions, 1 deletions
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7cd280bfd63..437528403959 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -252,6 +252,9 @@ static void __init dump_cpu_info(int cpu)
252 dump_cache("cache", cpu, CACHE_ISIZE(info)); 252 dump_cache("cache", cpu, CACHE_ISIZE(info));
253 } 253 }
254 } 254 }
255
256 if (arch_is_coherent())
257 printk("Cache coherency enabled\n");
255} 258}
256 259
257int cpu_architecture(void) 260int cpu_architecture(void)
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index ba6b4367a1d5..ac72f94c5b4d 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -219,6 +219,12 @@ static void __init ixp23xx_pci_common_init(void)
219 *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1); 219 *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
220 } else { 220 } else {
221 *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1); 221 *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
222
223 /*
224 * Enable coherency on A2 silicon.
225 */
226 if (arch_is_coherent())
227 *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
222 } 228 }
223} 229}
224 230
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 8a1bfcd50087..50e6b6bfb2e2 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -18,6 +18,7 @@
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20 20
21#include <asm/memory.h>
21#include <asm/cacheflush.h> 22#include <asm/cacheflush.h>
22#include <asm/tlbflush.h> 23#include <asm/tlbflush.h>
23#include <asm/sizes.h> 24#include <asm/sizes.h>
@@ -272,6 +273,17 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
272void * 273void *
273dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) 274dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
274{ 275{
276 if (arch_is_coherent()) {
277 void *virt;
278
279 virt = kmalloc(size, gfp);
280 if (!virt)
281 return NULL;
282 *handle = virt_to_dma(dev, virt);
283
284 return virt;
285 }
286
275 return __dma_alloc(dev, size, handle, gfp, 287 return __dma_alloc(dev, size, handle, gfp,
276 pgprot_noncached(pgprot_kernel)); 288 pgprot_noncached(pgprot_kernel));
277} 289}
@@ -350,6 +362,11 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
350 362
351 WARN_ON(irqs_disabled()); 363 WARN_ON(irqs_disabled());
352 364
365 if (arch_is_coherent()) {
366 kfree(cpu_addr);
367 return;
368 }
369
353 size = PAGE_ALIGN(size); 370 size = PAGE_ALIGN(size);
354 371
355 spin_lock_irqsave(&consistent_lock, flags); 372 spin_lock_irqsave(&consistent_lock, flags);
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 5e5d05bcad50..f14b2d0f3690 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -389,6 +389,17 @@ void __init build_mem_type_table(void)
389 kern_pgprot = user_pgprot = cp->pte; 389 kern_pgprot = user_pgprot = cp->pte;
390 390
391 /* 391 /*
392 * Enable CPU-specific coherency if supported.
393 * (Only available on XSC3 at the moment.)
394 */
395 if (arch_is_coherent()) {
396 if (cpu_is_xsc3()) {
397 mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
398 mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
399 }
400 }
401
402 /*
392 * ARMv6 and above have extended page tables. 403 * ARMv6 and above have extended page tables.
393 */ 404 */
394 if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) { 405 if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index b9dfce57c272..80873b36c3f7 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -371,7 +371,7 @@ ENTRY(cpu_xsc3_switch_mm)
371ENTRY(cpu_xsc3_set_pte) 371ENTRY(cpu_xsc3_set_pte)
372 str r1, [r0], #-2048 @ linux version 372 str r1, [r0], #-2048 @ linux version
373 373
374 bic r2, r1, #0xff0 374 bic r2, r1, #0xdf0 @ Keep C, B, coherency bits
375 orr r2, r2, #PTE_TYPE_EXT @ extended page 375 orr r2, r2, #PTE_TYPE_EXT @ extended page
376 376
377 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY 377 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY