Skip to content

Commit

Permalink
csky: Support icache flush without specific instructions
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
guoren83 committed Feb 21, 2020
1 parent a736fa1 commit 761b4f6
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 8 deletions.
4 changes: 4 additions & 0 deletions arch/csky/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions arch/csky/include/asm/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions arch/csky/mm/cachev1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 21 additions & 8 deletions arch/csky/mm/cachev2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
}

Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 761b4f6

Please sign in to comment.