summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorGuo Ren <guoren@linux.alibaba.com>2020-01-22 11:15:14 +0800
committerGuo Ren <guoren@linux.alibaba.com>2020-02-21 15:43:24 +0800
commit761b4f694cb90b63ca2739ac8a8a176342636e5e (patch)
tree3af10af362b1feb39f151015ca4a96c537485745 /arch
parenta736fa1ed772e3640e1bfaab36032c5a285d6a7b (diff)
csky: Support icache flush without specific instructions
Some CPUs don't support icache specific instructions to flush icache lines in broadcast way. We use cpu control registers to flush local icache and use IPI to notify other cores. Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/csky/Kconfig4
-rw-r--r--arch/csky/include/asm/cache.h1
-rw-r--r--arch/csky/mm/cachev1.c5
-rw-r--r--arch/csky/mm/cachev2.c29
4 files changed, 31 insertions, 8 deletions
diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
index 1c723cb11cc4..111474b50f69 100644
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -231,6 +231,10 @@ config CPU_HAS_FPU
bool "CPU has FPU coprocessor"
depends on CPU_CK807 || CPU_CK810 || CPU_CK860
+config CPU_HAS_ICACHE_INS
+ bool "CPU has Icache invalidate instructions"
+ depends on CPU_HAS_CACHEV2
+
config CPU_HAS_TEE
bool "CPU has Trusted Execution Environment"
depends on CPU_CK810
diff --git a/arch/csky/include/asm/cache.h b/arch/csky/include/asm/cache.h
index 1d5fc2f78fd7..4b5c09bf1d25 100644
--- a/arch/csky/include/asm/cache.h
+++ b/arch/csky/include/asm/cache.h
@@ -16,6 +16,7 @@ void dcache_wb_line(unsigned long start);
void icache_inv_range(unsigned long start, unsigned long end);
void icache_inv_all(void);
+void local_icache_inv_all(void *priv);
void dcache_wb_range(unsigned long start, unsigned long end);
void dcache_wbinv_all(void);
diff --git a/arch/csky/mm/cachev1.c b/arch/csky/mm/cachev1.c
index 494ec912abff..5a5a9804a0e3 100644
--- a/arch/csky/mm/cachev1.c
+++ b/arch/csky/mm/cachev1.c
@@ -94,6 +94,11 @@ void icache_inv_all(void)
cache_op_all(INS_CACHE|CACHE_INV, 0);
}
+void local_icache_inv_all(void *priv)
+{
+ cache_op_all(INS_CACHE|CACHE_INV, 0);
+}
+
void dcache_wb_range(unsigned long start, unsigned long end)
{
cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0);
diff --git a/arch/csky/mm/cachev2.c b/arch/csky/mm/cachev2.c
index b61be6518e21..909fdd0f5995 100644
--- a/arch/csky/mm/cachev2.c
+++ b/arch/csky/mm/cachev2.c
@@ -3,15 +3,25 @@
#include <linux/spinlock.h>
#include <linux/smp.h>
+#include <linux/mm.h>
#include <asm/cache.h>
#include <asm/barrier.h>
-inline void dcache_wb_line(unsigned long start)
+#define INS_CACHE (1 << 0)
+#define CACHE_INV (1 << 4)
+
+void local_icache_inv_all(void *priv)
{
- asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
+ mtcr("cr17", INS_CACHE|CACHE_INV);
sync_is();
}
+void icache_inv_all(void)
+{
+ on_each_cpu(local_icache_inv_all, NULL, 1);
+}
+
+#ifdef CONFIG_CPU_HAS_ICACHE_INS
void icache_inv_range(unsigned long start, unsigned long end)
{
unsigned long i = start & ~(L1_CACHE_BYTES - 1);
@@ -20,10 +30,16 @@ void icache_inv_range(unsigned long start, unsigned long end)
asm volatile("icache.iva %0\n"::"r"(i):"memory");
sync_is();
}
+#else
+void icache_inv_range(unsigned long start, unsigned long end)
+{
+ icache_inv_all();
+}
+#endif
-void icache_inv_all(void)
+inline void dcache_wb_line(unsigned long start)
{
- asm volatile("icache.ialls\n":::"memory");
+ asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
sync_is();
}
@@ -53,10 +69,7 @@ void cache_wbinv_range(unsigned long start, unsigned long end)
asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
sync_is();
- i = start & ~(L1_CACHE_BYTES - 1);
- for (; i < end; i += L1_CACHE_BYTES)
- asm volatile("icache.iva %0\n"::"r"(i):"memory");
- sync_is();
+ icache_inv_range(start, end);
}
EXPORT_SYMBOL(cache_wbinv_range);