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

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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);
+21 −8
Original line number Diff line number Diff line
@@ -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);