X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=lib_blackfin%2Fcache.c;h=0a321a448f4abda2faf9c727db50dec607fbb682;hb=4c94f6c54bbc4dc5f418da01d8ec01e2adf636be;hp=41e2a62d12d3d587b9d42e5e0f9c761e0df341b9;hpb=50f0d211912a648e31aa9123b4665a0444bb8ca9;p=u-boot diff --git a/lib_blackfin/cache.c b/lib_blackfin/cache.c index 41e2a62d12..0a321a448f 100644 --- a/lib_blackfin/cache.c +++ b/lib_blackfin/cache.c @@ -15,16 +15,64 @@ void flush_cache(unsigned long addr, unsigned long size) { + void *start_addr, *end_addr; + int istatus, dstatus; + /* no need to flush stuff in on chip memory (L1/L2/etc...) */ if (addr >= 0xE0000000) return; - if (icache_status()) - blackfin_icache_flush_range((void *)addr, (void *)(addr + size)); + start_addr = (void *)addr; + end_addr = (void *)(addr + size); + istatus = icache_status(); + dstatus = dcache_status(); + + if (istatus) { + if (dstatus) + blackfin_icache_dcache_flush_range(start_addr, end_addr); + else + blackfin_icache_flush_range(start_addr, end_addr); + } else if (dstatus) + blackfin_dcache_flush_range(start_addr, end_addr); +} + +#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); - if (dcache_status()) - blackfin_dcache_flush_range((void *)addr, (void *)(addr + size)); + /* flush it */ + __asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr)); + } + } } +#endif void icache_enable(void) { @@ -40,7 +88,7 @@ void icache_disable(void) int icache_status(void) { - return bfin_read_IMEM_CONTROL() & ENICPLB; + return bfin_read_IMEM_CONTROL() & IMC; } void dcache_enable(void) @@ -51,11 +99,15 @@ void dcache_enable(void) 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; + return bfin_read_DMEM_CONTROL() & ACACHE_BCACHE; }