aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2007-02-05 08:48:08 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-02-08 09:49:40 -0500
commit953233dc9958ba2b29753d0f24e37a33a076a5f6 (patch)
treeb9cc9ddc82722dc79a72a8c6f4977566ec2e0384
parent7f8e33546d17c7d8849be3a6623c3b6b3c9b588b (diff)
[ARM] 4134/1: Add generic support for outer caches
The outer cache can be L2 as on RealView/EB MPCore platform or even L3 or further on ARMv7 cores. This patch adds the generic support for flushing the outer cache in the DMA operations. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/common/dmabounce.c1
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--arch/arm/mm/Kconfig3
-rw-r--r--arch/arm/mm/consistent.c6
-rw-r--r--include/asm-arm/cacheflush.h37
5 files changed, 50 insertions, 0 deletions
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 272702accd8b..b4748e3171c6 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -338,6 +338,7 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
338 */ 338 */
339 ptr = (unsigned long)buf->ptr; 339 ptr = (unsigned long)buf->ptr;
340 dmac_clean_range(ptr, ptr + size); 340 dmac_clean_range(ptr, ptr + size);
341 outer_clean_range(__pa(ptr), __pa(ptr) + size);
341 } 342 }
342 free_safe_buffer(device_info, buf); 343 free_safe_buffer(device_info, buf);
343 } 344 }
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index bbab134cd82d..243aea458057 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -88,6 +88,9 @@ struct cpu_user_fns cpu_user;
88#ifdef MULTI_CACHE 88#ifdef MULTI_CACHE
89struct cpu_cache_fns cpu_cache; 89struct cpu_cache_fns cpu_cache;
90#endif 90#endif
91#ifdef CONFIG_OUTER_CACHE
92struct outer_cache_fns outer_cache;
93#endif
91 94
92struct stack { 95struct stack {
93 u32 irq[3]; 96 u32 irq[3];
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index aade2f72c920..a84eed9f8542 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -609,3 +609,6 @@ config NEEDS_SYSCALL_FOR_CMPXCHG
609 Forget about fast user space cmpxchg support. 609 Forget about fast user space cmpxchg support.
610 It is just not possible. 610 It is just not possible.
611 611
612config OUTER_CACHE
613 bool
614 default n
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 6a9c362fef5e..83bd035c7d5e 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -208,6 +208,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
208 unsigned long kaddr = (unsigned long)page_address(page); 208 unsigned long kaddr = (unsigned long)page_address(page);
209 memset(page_address(page), 0, size); 209 memset(page_address(page), 0, size);
210 dmac_flush_range(kaddr, kaddr + size); 210 dmac_flush_range(kaddr, kaddr + size);
211 outer_flush_range(__pa(kaddr), __pa(kaddr) + size);
211 } 212 }
212 213
213 /* 214 /*
@@ -485,15 +486,20 @@ void consistent_sync(void *vaddr, size_t size, int direction)
485 unsigned long start = (unsigned long)vaddr; 486 unsigned long start = (unsigned long)vaddr;
486 unsigned long end = start + size; 487 unsigned long end = start + size;
487 488
489 BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end));
490
488 switch (direction) { 491 switch (direction) {
489 case DMA_FROM_DEVICE: /* invalidate only */ 492 case DMA_FROM_DEVICE: /* invalidate only */
490 dmac_inv_range(start, end); 493 dmac_inv_range(start, end);
494 outer_inv_range(__pa(start), __pa(end));
491 break; 495 break;
492 case DMA_TO_DEVICE: /* writeback only */ 496 case DMA_TO_DEVICE: /* writeback only */
493 dmac_clean_range(start, end); 497 dmac_clean_range(start, end);
498 outer_clean_range(__pa(start), __pa(end));
494 break; 499 break;
495 case DMA_BIDIRECTIONAL: /* writeback and invalidate */ 500 case DMA_BIDIRECTIONAL: /* writeback and invalidate */
496 dmac_flush_range(start, end); 501 dmac_flush_range(start, end);
502 outer_flush_range(__pa(start), __pa(end));
497 break; 503 break;
498 default: 504 default:
499 BUG(); 505 BUG();
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 5f531ea03059..ce60b3702ba5 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -190,6 +190,12 @@ struct cpu_cache_fns {
190 void (*dma_flush_range)(unsigned long, unsigned long); 190 void (*dma_flush_range)(unsigned long, unsigned long);
191}; 191};
192 192
193struct outer_cache_fns {
194 void (*inv_range)(unsigned long, unsigned long);
195 void (*clean_range)(unsigned long, unsigned long);
196 void (*flush_range)(unsigned long, unsigned long);
197};
198
193/* 199/*
194 * Select the calling method 200 * Select the calling method
195 */ 201 */
@@ -246,6 +252,37 @@ extern void dmac_flush_range(unsigned long, unsigned long);
246 252
247#endif 253#endif
248 254
255#ifdef CONFIG_OUTER_CACHE
256
257extern struct outer_cache_fns outer_cache;
258
259static inline void outer_inv_range(unsigned long start, unsigned long end)
260{
261 if (outer_cache.inv_range)
262 outer_cache.inv_range(start, end);
263}
264static inline void outer_clean_range(unsigned long start, unsigned long end)
265{
266 if (outer_cache.clean_range)
267 outer_cache.clean_range(start, end);
268}
269static inline void outer_flush_range(unsigned long start, unsigned long end)
270{
271 if (outer_cache.flush_range)
272 outer_cache.flush_range(start, end);
273}
274
275#else
276
277static inline void outer_inv_range(unsigned long start, unsigned long end)
278{ }
279static inline void outer_clean_range(unsigned long start, unsigned long end)
280{ }
281static inline void outer_flush_range(unsigned long start, unsigned long end)
282{ }
283
284#endif
285
249/* 286/*
250 * flush_cache_vmap() is used when creating mappings (eg, via vmap, 287 * flush_cache_vmap() is used when creating mappings (eg, via vmap,
251 * vmalloc, ioremap etc) in kernel space for pages. Since the 288 * vmalloc, ioremap etc) in kernel space for pages. Since the