
Unify all of the cache handling code in the same place and add support for properly clearing write back data caches.
Signed-off-by: Mike Frysinger vapier@gentoo.org --- cpu/blackfin/cpu.c | 35 ---------------------- lib_blackfin/cache.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 35 deletions(-)
diff --git a/cpu/blackfin/cpu.c b/cpu/blackfin/cpu.c index 53de5ab..5ae8875 100644 --- a/cpu/blackfin/cpu.c +++ b/cpu/blackfin/cpu.c @@ -14,46 +14,11 @@ #include <asm/blackfin.h> #include <asm/cplb.h> #include <asm/mach-common/bits/core.h> -#include <asm/mach-common/bits/mpu.h> #include <asm/mach-common/bits/trace.h>
#include "cpu.h" #include "serial.h"
-void icache_enable(void) -{ - bfin_write_IMEM_CONTROL(bfin_read_IMEM_CONTROL() | (IMC | ENICPLB)); - SSYNC(); -} - -void icache_disable(void) -{ - bfin_write_IMEM_CONTROL(bfin_read_IMEM_CONTROL() & ~(IMC | ENICPLB)); - SSYNC(); -} - -int icache_status(void) -{ - return bfin_read_IMEM_CONTROL() & ENICPLB; -} - -void dcache_enable(void) -{ - bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() | (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)); - SSYNC(); -} - -void dcache_disable(void) -{ - bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() & ~(ACACHE_BCACHE | ENDCPLB | PORT_PREF0)); - SSYNC(); -} - -int dcache_status(void) -{ - return bfin_read_DMEM_CONTROL() & ENDCPLB; -} - __attribute__ ((__noreturn__)) void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) { diff --git a/lib_blackfin/cache.c b/lib_blackfin/cache.c index c2f6e28..dcc0e8d 100644 --- a/lib_blackfin/cache.c +++ b/lib_blackfin/cache.c @@ -11,6 +11,7 @@
#include <common.h> #include <asm/blackfin.h> +#include <asm/mach-common/bits/mpu.h>
void flush_cache(unsigned long addr, unsigned long size) { @@ -24,3 +25,79 @@ void flush_cache(unsigned long addr, unsigned long size) if (dcache_status()) blackfin_dcache_flush_range((void *)addr, (void *)(addr + size)); } + +#ifdef CONFIG_DCACHE_WB +static void flushinv_all_dcache(void) +{ + u32 way, bank, subbank, set; + u32 status, addr; + u32 dmem_ctl = bfin_read_DMEM_CONTROL(); + + for (bank = 0; bank < 2; ++bank) { + if (!(dmem_ctl & (1 << (DMC1_P - bank)))) + continue; + + for (way = 0; way < 2; ++way) + for (subbank = 0; subbank < 4; ++subbank) + for (set = 0; set < 64; ++set) { + + bfin_write_DTEST_COMMAND( + way << 26 | + bank << 23 | + subbank << 16 | + set << 5 + ); + CSYNC(); + status = bfin_read_DTEST_DATA0(); + + /* only worry about valid/dirty entries */ + if ((status & 0x3) != 0x3) + continue; + + /* construct the address using the tag */ + addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5); + + /* flush it */ + __asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr)); + } + } +} +#endif + +void icache_enable(void) +{ + bfin_write_IMEM_CONTROL(IMC | ENICPLB); + SSYNC(); +} + +void icache_disable(void) +{ + bfin_write_IMEM_CONTROL(0); + SSYNC(); +} + +int icache_status(void) +{ + return bfin_read_IMEM_CONTROL() & ENICPLB; +} + +void dcache_enable(void) +{ + bfin_write_DMEM_CONTROL(ACACHE_BCACHE | ENDCPLB | PORT_PREF0); + SSYNC(); +} + +void dcache_disable(void) +{ +#ifdef CONFIG_DCACHE_WB + bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() & ~(ENDCPLB)); + flushinv_all_dcache(); +#endif + bfin_write_DMEM_CONTROL(0); + SSYNC(); +} + +int dcache_status(void) +{ + return bfin_read_DMEM_CONTROL() & ENDCPLB; +}