From: Lothar Waßmann Date: Tue, 6 Mar 2012 14:12:32 +0000 (+0100) Subject: Implement cache functions for ARM-926ejs X-Git-Tag: v1.2~28 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=5f1abb05bc9c15845290f9f834f2cf62e94e968b;p=karo-tx-uboot.git Implement cache functions for ARM-926ejs --- diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c index 504f604684..cc273a7884 100644 --- a/arch/arm/cpu/arm926ejs/cache.c +++ b/arch/arm/cpu/arm926ejs/cache.c @@ -22,31 +22,114 @@ #include #include +#define DCACHE_SIZE 0x4000 // 16KB Size of data cache in bytes +#define DCACHE_LINE_SIZE 32 // Size of a data cache line +#define DCACHE_WAYS 64 // Associativity of the cache +/* + * This is the maximum size of an area which will be invalidated + * using the single invalidate entry instructions. Anything larger + * than this, and we go for the whole cache. + * + * This value should be chosen such that we choose the cheapest + * alternative. + */ +#define CACHE_DLIMIT 16384 + #ifndef CONFIG_SYS_DCACHE_OFF -static inline void dcache_noop(void) +void invalidate_dcache_all(void) { - if (dcache_status()) { - puts("WARNING: cache operations are not implemented!\n" - "WARNING: disabling D-Cache now, you can re-enable it" - "later with 'dcache on' command\n"); - dcache_disable(); - } + asm volatile ( + "mcr p15, 0, %0, c7, c6, 0\n" /* invalidate d-cache */ + "mcr p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */ + "mcr p15, 0, %0, c7, c10, 4\n" /* data write back */ + : + : "r"(0) + : "memory"); } -void invalidate_dcache_all(void) +void invalidate_dcache_range(unsigned long start, unsigned long end) { - dcache_noop(); + asm volatile ( +#ifndef CONFIG_SYS_ARM_CACHE_WRITETHROUGH + "tst %1, %4\n" + "mcrne p15, 0, %1, c7, c10, 1\n" /* clean D entry */ + "tst %2, %4\n" + "mcrne p15, 0, %2, c7, c10, 1\n" /* clean D entry */ +#endif + "bic %1, %1, %4\n" + "add %2, %2, %4\n" + "bic %2, %2, %4\n" + "1:\n" + "mcr p15, 0, %1, c7, c6, 1\n" /* invalidate D cache entry */ + "add %1, %1, %3\n" + "cmp %1, %2\n" + "blo 1b\n" + "mcr p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */ + "mcr p15, 0, %0, c7, c10, 4\n" /* data write back */ + : + : "r"(0), "r"(start), "r"(end), + "I"(DCACHE_LINE_SIZE), + "I"(DCACHE_LINE_SIZE - 1) + : "memory" + ); + } -void invalidate_dcache_range(unsigned long start, unsigned long stop) +#ifndef CONFIG_SYS_ARM_CACHE_WRITETHROUGH +void flush_dcache_range(unsigned long start, unsigned long end) { - dcache_noop(); + if (end - start > CACHE_DLIMIT) + flush_dcache_all(); + else + flush_cache(start & ~(SZ_4K - 1), ALIGN(end, SZ_4K)); } -void flush_dcache_range(unsigned long start, unsigned long stop) +void flush_cache(unsigned long start, unsigned long end) { - dcache_noop(); + asm volatile ( + "1:\n" + "mcr p15, 0, %1, c7, c14, 1\n" /* clean and invalidate D entry */ + "add %1, %1, %3\n" + "cmp %1, %2\n" + "blo 1b\n" + "mcr p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */ + "mcr p15, 0, %0, c7, c10, 4\n" /* data write back */ + : + : "r"(0), "r"(start), "r"(end), "I"(DCACHE_LINE_SIZE) + : "memory" + ); } + +void flush_dcache_all(void) +{ + asm volatile ( + "1:\n" + "mrc p15, 0, r15, c7, c14, 3\n" /* test,clean,invalidate */ + "bne 1b\n" + "mcr p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */ + "mcr p15, 0, %0, c7, c10, 4\n" /* data write back */ + : + : "r"(0) + : "memory" + ); +} +#else +void flush_dcache_range(unsigned long start, unsigned long end) +{ + invalidate_dcache_range(start, end); +} + +void flush_cache(unsigned long start, unsigned long end) +{ + invalidate_dcache_range(start, end); +} + +void flush_dcache_all(void) +{ + invalidate_dcache_all(); +} +#endif /* CONFIG_SYS_ARM_CACHE_WRITETHROUGH */ + #else /* #ifndef CONFIG_SYS_DCACHE_OFF */ void invalidate_dcache_all(void) {