Commit 761b4f69 authored by Guo Ren's avatar Guo Ren

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: default avatarGuo Ren <guoren@linux.alibaba.com>
parent a736fa1e
...@@ -231,6 +231,10 @@ config CPU_HAS_FPU ...@@ -231,6 +231,10 @@ config CPU_HAS_FPU
bool "CPU has FPU coprocessor" bool "CPU has FPU coprocessor"
depends on CPU_CK807 || CPU_CK810 || CPU_CK860 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 config CPU_HAS_TEE
bool "CPU has Trusted Execution Environment" bool "CPU has Trusted Execution Environment"
depends on CPU_CK810 depends on CPU_CK810
......
...@@ -16,6 +16,7 @@ void dcache_wb_line(unsigned long start); ...@@ -16,6 +16,7 @@ void dcache_wb_line(unsigned long start);
void icache_inv_range(unsigned long start, unsigned long end); void icache_inv_range(unsigned long start, unsigned long end);
void icache_inv_all(void); void icache_inv_all(void);
void local_icache_inv_all(void *priv);
void dcache_wb_range(unsigned long start, unsigned long end); void dcache_wb_range(unsigned long start, unsigned long end);
void dcache_wbinv_all(void); void dcache_wbinv_all(void);
......
...@@ -94,6 +94,11 @@ void icache_inv_all(void) ...@@ -94,6 +94,11 @@ void icache_inv_all(void)
cache_op_all(INS_CACHE|CACHE_INV, 0); 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) void dcache_wb_range(unsigned long start, unsigned long end)
{ {
cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0); cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0);
......
...@@ -3,15 +3,25 @@ ...@@ -3,15 +3,25 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/mm.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/barrier.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(); 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) void icache_inv_range(unsigned long start, unsigned long end)
{ {
unsigned long i = start & ~(L1_CACHE_BYTES - 1); unsigned long i = start & ~(L1_CACHE_BYTES - 1);
...@@ -20,10 +30,16 @@ void icache_inv_range(unsigned long start, unsigned long end) ...@@ -20,10 +30,16 @@ void icache_inv_range(unsigned long start, unsigned long end)
asm volatile("icache.iva %0\n"::"r"(i):"memory"); asm volatile("icache.iva %0\n"::"r"(i):"memory");
sync_is(); 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(); sync_is();
} }
...@@ -53,10 +69,7 @@ void cache_wbinv_range(unsigned long start, unsigned long end) ...@@ -53,10 +69,7 @@ void cache_wbinv_range(unsigned long start, unsigned long end)
asm volatile("dcache.cval1 %0\n"::"r"(i):"memory"); asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
sync_is(); sync_is();
i = start & ~(L1_CACHE_BYTES - 1); icache_inv_range(start, end);
for (; i < end; i += L1_CACHE_BYTES)
asm volatile("icache.iva %0\n"::"r"(i):"memory");
sync_is();
} }
EXPORT_SYMBOL(cache_wbinv_range); EXPORT_SYMBOL(cache_wbinv_range);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment