
On Wednesday, August 10, 2011 04:49:25 AM Hong Xu wrote:
After DMA operation, we need to maintain D-Cache coherency. So that the DCache must be invalidated (hence CPU will fetch data written by DMA controller from RAM).
Tested on AT91SAM9261EK with Peripheral DMA controller.
Hi Hong,
one more thing, not that I want to disappoint you.
Try to take a look at arch/arm/cpu/armv7/cache_v7.c
Maybe we should do the same for arm926ejs -- have arch/arm/cpu/arm926ejs/cache.c -- containing arm926ejs specific cache management functions. That way, arch/arm/lib/cache.c won't become mess.
What do you think ?
Signed-off-by: Hong Xu hong.xu@atmel.com Tested-by: Elen Song elen.song@atmel.com CC: Albert Aribaud albert.u.boot@aribaud.net CC: Aneesh V aneesh@ti.com CC: Marek Vasut marek.vasut@gmail.com CC: Reinhard Meyer u-boot@emk-elektronik.de CC: Heiko Schocher hs@denx.de
V2: Per Albert's suggestion, add invalidate_dcache_range
V3: invalidate_dcache_range emits warning when detecting unaligned buffer
invalidate_dcache_range won't clean any adjacent cache line when detecting unaligned buffer and only round up/down the buffer address
v4: invalidate_dcache_range will emit clearer warning message
Per Albert's suggestion, if not alighed to cache line size, round up start address, round down stop addres
Per Marek Vasut's suggestion, use __func__ stated in C99
arch/arm/lib/cache.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c index 92b61a2..4c8e160 100644 --- a/arch/arm/lib/cache.c +++ b/arch/arm/lib/cache.c @@ -53,3 +53,61 @@ void __flush_dcache_all(void) } void flush_dcache_all(void) __attribute__((weak, alias("__flush_dcache_all")));
+/*
- The buffer range to be invalidated is [start, stop)
- */
+void __invalidate_dcache_range(unsigned long start, unsigned long stop) +{
- int cache_line_len;
- unsigned long mva;
+#ifdef CONFIG_ARM926EJS +#ifdef CONFIG_SYS_CACHELINE_SIZE
- cache_line_len = CONFIG_SYS_CACHELINE_SIZE;
+#else
- /*
* ARM926EJ-S Technical Reference Manual, Chap 2.3.1 Table 2-9
* only b'10, aka. 32 bytes cache line len is valid
*/
- cache_line_len = 32;
+#endif
- mva = start;
- if ((mva & (cache_line_len - 1)) != 0) {
printf("WARNING: %s - start address 0x%08x not aligned to"
"cache line size(%d bytes)\n", __func__, start,
cache_line_len);
/* Round up starting address */
mva = (mva | (cache_line_len - 1)) + 1;
- }
- if ((stop & (cache_line_len - 1)) != 0) {
printf("WARNING: %s - stop address 0x%08x not aligned to"
"cache line size(%d bytes)\n", __func__, stop,
cache_line_len);
/* Round down ending address */
stop &= ~(cache_line_len - 1);
- }
- while (mva < stop) {
asm("mcr p15, 0, %0, c7, c6, 1" : : "r"(mva));
mva += cache_line_len;
- }
- /* Drain the WB */
- asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+#endif
- return;
+} +void invalidate_dcache_range(unsigned long start, unsigned long stop)
- __attribute__((weak, alias("__invalidate_dcache_range")));
+void __invalidate_dcache_all(void) +{ +#ifdef CONFIG_ARM926EJS
- asm("mcr p15, 0, %0, c7, c6, 0" : : "r" (0));
+#endif
- return;
+} +void invalidate_dcache_all(void)
- __attribute__((weak, alias("__invalidate_dcache_all")));