Sfoglia il codice sorgente

Blackfin: safely flush data caches when in writeback mode

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Mike Frysinger 16 anni fa
parent
commit
1c7a79a04e
1 ha cambiato i file con 42 aggiunte e 0 eliminazioni
  1. 42 0
      lib_blackfin/cache.c

+ 42 - 0
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();
 }