aboutsummaryrefslogtreecommitdiff
path: root/lib_blackfin
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2008-08-07 15:33:09 -0400
committerMike Frysinger <vapier@gentoo.org>2009-03-23 15:14:53 -0400
commit1c7a79a04eb916f685f7275520b5eea6968a1559 (patch)
treeb0829990cf0958f317be53ef6268f9dade1365c4 /lib_blackfin
parentc06f2b13022703611bc3e512bd34f9014a46f448 (diff)
Blackfin: safely flush data caches when in writeback mode
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'lib_blackfin')
-rw-r--r--lib_blackfin/cache.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/lib_blackfin/cache.c b/lib_blackfin/cache.c
index 1557864f9..0a321a448 100644
--- a/lib_blackfin/cache.c
+++ b/lib_blackfin/cache.c
@@ -36,6 +36,44 @@ void flush_cache(unsigned long addr, unsigned long size)
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);
+
+ /* flush it */
+ __asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr));
+ }
+ }
+}
+#endif
+
void icache_enable(void)
{
bfin_write_IMEM_CONTROL(IMC | ENICPLB);
@@ -61,6 +99,10 @@ 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();
}