Blackfin: add blackfin_invalidate_entire_icache for SMP systems
Sonic Zhang [Wed, 10 Jun 2009 08:57:08 +0000 (08:57 +0000)]
The KGDB code uses this when switching processors to make sure the icache
is in a valid state.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>

arch/blackfin/include/asm/cache.h
arch/blackfin/include/asm/cacheflush.h
arch/blackfin/include/asm/cpu.h
arch/blackfin/kernel/setup.c
arch/blackfin/mach-common/cache-c.c
arch/blackfin/mach-common/smp.c

index 8663781..2ef669e 100644 (file)
 #define L1_CACHE_SHIFT_MAX     5
 
 #if defined(CONFIG_SMP) && \
-    !defined(CONFIG_BFIN_CACHE_COHERENT) && \
-    defined(CONFIG_BFIN_DCACHE)
-#define __ARCH_SYNC_CORE_DCACHE
+    !defined(CONFIG_BFIN_CACHE_COHERENT)
+# if defined(CONFIG_BFIN_ICACHE)
+# define __ARCH_SYNC_CORE_ICACHE
+# endif
+# if defined(CONFIG_BFIN_DCACHE)
+# define __ARCH_SYNC_CORE_DCACHE
+# endif
 #ifndef __ASSEMBLY__
 asmlinkage void __raw_smp_mark_barrier_asm(void);
 asmlinkage void __raw_smp_check_barrier_asm(void);
@@ -51,6 +55,7 @@ static inline void smp_check_barrier(void)
 }
 
 void resync_core_dcache(void);
+void resync_core_icache(void);
 #endif
 #endif
 
index 18bc4f7..5c17dee 100644 (file)
@@ -37,6 +37,7 @@ extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned lo
 extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address);
 extern void blackfin_dflush_page(void *page);
 extern void blackfin_invalidate_entire_dcache(void);
+extern void blackfin_invalidate_entire_icache(void);
 
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
index c2594ef..565b813 100644 (file)
@@ -34,6 +34,7 @@ struct blackfin_cpudata {
        unsigned int dmemctl;
        unsigned long loops_per_jiffy;
        unsigned long dcache_invld_count;
+       unsigned long icache_invld_count;
 };
 
 DECLARE_PER_CPU(struct blackfin_cpudata, cpu_data);
index f5f516e..6454bab 100644 (file)
@@ -1181,6 +1181,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 #ifdef __ARCH_SYNC_CORE_DCACHE
        seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count);
 #endif
+#ifdef __ARCH_SYNC_CORE_ICACHE
+       seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count);
+#endif
 #ifdef CONFIG_BFIN_ICACHE_LOCK
        switch ((cpudata->imemctl >> 3) & WAYALL_L) {
        case WAY0_L:
index e6ab1f8..b59ce3c 100644 (file)
 void blackfin_invalidate_entire_dcache(void)
 {
        u32 dmem = bfin_read_DMEM_CONTROL();
-       SSYNC();
        bfin_write_DMEM_CONTROL(dmem & ~0xc);
        SSYNC();
        bfin_write_DMEM_CONTROL(dmem);
        SSYNC();
 }
+
+/* Invalidate the Entire Instruction cache by
+ * clearing IMC bit
+ */
+void blackfin_invalidate_entire_icache(void)
+{
+       u32 imem = bfin_read_IMEM_CONTROL();
+       bfin_write_IMEM_CONTROL(imem & ~0x4);
+       SSYNC();
+       bfin_write_IMEM_CONTROL(imem);
+       SSYNC();
+}
+
index 3b8ebae..c187da2 100644 (file)
@@ -468,6 +468,17 @@ void smp_icache_flush_range_others(unsigned long start, unsigned long end)
 }
 EXPORT_SYMBOL_GPL(smp_icache_flush_range_others);
 
+#ifdef __ARCH_SYNC_CORE_ICACHE
+void resync_core_icache(void)
+{
+       unsigned int cpu = get_cpu();
+       blackfin_invalidate_entire_icache();
+       ++per_cpu(cpu_data, cpu).icache_invld_count;
+       put_cpu();
+}
+EXPORT_SYMBOL(resync_core_icache);
+#endif
+
 #ifdef __ARCH_SYNC_CORE_DCACHE
 unsigned long barrier_mask __attribute__ ((__section__(".l2.bss")));