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. Signed-off-by: Hong Xu <hong...@atmel.com> Tested-by: Elen Song <elen.s...@atmel.com> CC: Albert Aribaud <albert.u.b...@aribaud.net> CC: Aneesh V <ane...@ti.com> CC: Reinhard Meyer <u-b...@emk-elektronik.de> CC: Heiko Schocher <h...@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 arch/arm/lib/cache.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 54 insertions(+), 0 deletions(-) diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c index 92b61a2..9e6aa47 100644 --- a/arch/arm/lib/cache.c +++ b/arch/arm/lib/cache.c @@ -53,3 +53,57 @@ 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 - unaligned buffer detected, starting " + "address: 0x%08x\n", __FUNCTION__, start); + mva &= ~(cache_line_len - 1); + } + if ((stop & (cache_line_len - 1)) != 0) { + printf("WARNING: %s - unaligned buffer detected, ending " + "address: 0x%08x\n", __FUNCTION__, stop); + stop = (stop | (cache_line_len - 1)) + 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"))); -- 1.7.6 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot