xref: /rk3399_rockchip-uboot/arch/nds32/lib/cache.c (revision c2774e6149a6bedb0941deefec84665119e685a4)
18d732840SMacpaul Lin /*
28d732840SMacpaul Lin  * Copyright (C) 2012 Andes Technology Corporation
38d732840SMacpaul Lin  * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
48d732840SMacpaul Lin  * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
58d732840SMacpaul Lin  *
61a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
78d732840SMacpaul Lin  */
88d732840SMacpaul Lin 
98d732840SMacpaul Lin #include <common.h>
10*b841b6e9Srick #if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF))
CACHE_SET(unsigned char cache)11*b841b6e9Srick static inline unsigned long CACHE_SET(unsigned char cache)
12*b841b6e9Srick {
13*b841b6e9Srick 	if (cache == ICACHE)
14*b841b6e9Srick 		return 64 << ((GET_ICM_CFG() & ICM_CFG_MSK_ISET) \
15*b841b6e9Srick 			>> ICM_CFG_OFF_ISET);
16*b841b6e9Srick 	else
17*b841b6e9Srick 		return 64 << ((GET_DCM_CFG() & DCM_CFG_MSK_DSET) \
18*b841b6e9Srick 			>> DCM_CFG_OFF_DSET);
19*b841b6e9Srick }
20*b841b6e9Srick 
CACHE_WAY(unsigned char cache)21*b841b6e9Srick static inline unsigned long CACHE_WAY(unsigned char cache)
22*b841b6e9Srick {
23*b841b6e9Srick 	if (cache == ICACHE)
24*b841b6e9Srick 		return 1 + ((GET_ICM_CFG() & ICM_CFG_MSK_IWAY) \
25*b841b6e9Srick 			>> ICM_CFG_OFF_IWAY);
26*b841b6e9Srick 	else
27*b841b6e9Srick 		return 1 + ((GET_DCM_CFG() & DCM_CFG_MSK_DWAY) \
28*b841b6e9Srick 			>> DCM_CFG_OFF_DWAY);
29*b841b6e9Srick }
308d732840SMacpaul Lin 
CACHE_LINE_SIZE(enum cache_t cache)318d732840SMacpaul Lin static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
328d732840SMacpaul Lin {
338d732840SMacpaul Lin 	if (cache == ICACHE)
348d732840SMacpaul Lin 		return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
358d732840SMacpaul Lin 			>> ICM_CFG_OFF_ISZ) - 1);
368d732840SMacpaul Lin 	else
378d732840SMacpaul Lin 		return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
388d732840SMacpaul Lin 			>> DCM_CFG_OFF_DSZ) - 1);
398d732840SMacpaul Lin }
40*b841b6e9Srick #endif
418d732840SMacpaul Lin 
42*b841b6e9Srick #ifndef CONFIG_SYS_ICACHE_OFF
invalidate_icache_all(void)43*b841b6e9Srick void invalidate_icache_all(void)
448d732840SMacpaul Lin {
45*b841b6e9Srick 	unsigned long end, line_size;
46*b841b6e9Srick 	line_size = CACHE_LINE_SIZE(ICACHE);
47*b841b6e9Srick 	end = line_size * CACHE_WAY(ICACHE) * CACHE_SET(ICACHE);
48*b841b6e9Srick 	do {
49*b841b6e9Srick 		end -= line_size;
50*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
518d732840SMacpaul Lin 
52*b841b6e9Srick 		end -= line_size;
53*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
548d732840SMacpaul Lin 
55*b841b6e9Srick 		end -= line_size;
56*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
57*b841b6e9Srick 		end -= line_size;
58*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
59*b841b6e9Srick 	} while (end > 0);
608d732840SMacpaul Lin }
618d732840SMacpaul Lin 
invalidate_icache_range(unsigned long start,unsigned long end)628d732840SMacpaul Lin void invalidate_icache_range(unsigned long start, unsigned long end)
638d732840SMacpaul Lin {
648d732840SMacpaul Lin 	unsigned long line_size;
658d732840SMacpaul Lin 
668d732840SMacpaul Lin 	line_size = CACHE_LINE_SIZE(ICACHE);
678d732840SMacpaul Lin 	while (end > start) {
688d732840SMacpaul Lin 		asm volatile (
698d732840SMacpaul Lin 			"\n\tcctl %0, L1I_VA_INVAL"
708d732840SMacpaul Lin 			:
718d732840SMacpaul Lin 			: "r"(start)
728d732840SMacpaul Lin 		);
738d732840SMacpaul Lin 		start += line_size;
748d732840SMacpaul Lin 	}
758d732840SMacpaul Lin }
768d732840SMacpaul Lin 
icache_enable(void)778d732840SMacpaul Lin void icache_enable(void)
788d732840SMacpaul Lin {
798d732840SMacpaul Lin 	asm volatile (
808d732840SMacpaul Lin 		"mfsr	$p0, $mr8\n\t"
818d732840SMacpaul Lin 		"ori	$p0, $p0, 0x01\n\t"
828d732840SMacpaul Lin 		"mtsr	$p0, $mr8\n\t"
838d732840SMacpaul Lin 		"isb\n\t"
848d732840SMacpaul Lin 	);
858d732840SMacpaul Lin }
868d732840SMacpaul Lin 
icache_disable(void)878d732840SMacpaul Lin void icache_disable(void)
888d732840SMacpaul Lin {
898d732840SMacpaul Lin 	asm volatile (
908d732840SMacpaul Lin 		"mfsr	$p0, $mr8\n\t"
918d732840SMacpaul Lin 		"li	$p1, ~0x01\n\t"
928d732840SMacpaul Lin 		"and	$p0, $p0, $p1\n\t"
938d732840SMacpaul Lin 		"mtsr	$p0, $mr8\n\t"
948d732840SMacpaul Lin 		"isb\n\t"
958d732840SMacpaul Lin 	);
968d732840SMacpaul Lin }
978d732840SMacpaul Lin 
icache_status(void)988d732840SMacpaul Lin int icache_status(void)
998d732840SMacpaul Lin {
1008d732840SMacpaul Lin 	int ret;
1018d732840SMacpaul Lin 
1028d732840SMacpaul Lin 	asm volatile (
1038d732840SMacpaul Lin 		"mfsr	$p0, $mr8\n\t"
1048d732840SMacpaul Lin 		"andi	%0,  $p0, 0x01\n\t"
1058d732840SMacpaul Lin 		: "=r" (ret)
1068d732840SMacpaul Lin 		:
1078d732840SMacpaul Lin 		: "memory"
1088d732840SMacpaul Lin 	);
1098d732840SMacpaul Lin 
1108d732840SMacpaul Lin 	return ret;
1118d732840SMacpaul Lin }
1128d732840SMacpaul Lin 
113*b841b6e9Srick #else
invalidate_icache_all(void)114*b841b6e9Srick void invalidate_icache_all(void)
115*b841b6e9Srick {
116*b841b6e9Srick }
117*b841b6e9Srick 
invalidate_icache_range(unsigned long start,unsigned long end)118*b841b6e9Srick void invalidate_icache_range(unsigned long start, unsigned long end)
119*b841b6e9Srick {
120*b841b6e9Srick }
121*b841b6e9Srick 
icache_enable(void)122*b841b6e9Srick void icache_enable(void)
123*b841b6e9Srick {
124*b841b6e9Srick }
125*b841b6e9Srick 
icache_disable(void)126*b841b6e9Srick void icache_disable(void)
127*b841b6e9Srick {
128*b841b6e9Srick }
129*b841b6e9Srick 
icache_status(void)130*b841b6e9Srick int icache_status(void)
131*b841b6e9Srick {
132*b841b6e9Srick 	return 0;
133*b841b6e9Srick }
134*b841b6e9Srick 
135*b841b6e9Srick #endif
136*b841b6e9Srick 
137*b841b6e9Srick #ifndef CONFIG_SYS_DCACHE_OFF
dcache_wbinval_all(void)138*b841b6e9Srick void dcache_wbinval_all(void)
139*b841b6e9Srick {
140*b841b6e9Srick 	unsigned long end, line_size;
141*b841b6e9Srick 	line_size = CACHE_LINE_SIZE(DCACHE);
142*b841b6e9Srick 	end = line_size * CACHE_WAY(DCACHE) * CACHE_SET(DCACHE);
143*b841b6e9Srick 	do {
144*b841b6e9Srick 		end -= line_size;
145*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
146*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
147*b841b6e9Srick 		end -= line_size;
148*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
149*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
150*b841b6e9Srick 		end -= line_size;
151*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
152*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
153*b841b6e9Srick 		end -= line_size;
154*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
155*b841b6e9Srick 		__asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
156*b841b6e9Srick 
157*b841b6e9Srick 	} while (end > 0);
158*b841b6e9Srick }
159*b841b6e9Srick 
flush_dcache_range(unsigned long start,unsigned long end)160*b841b6e9Srick void flush_dcache_range(unsigned long start, unsigned long end)
161*b841b6e9Srick {
162*b841b6e9Srick 	unsigned long line_size;
163*b841b6e9Srick 
164*b841b6e9Srick 	line_size = CACHE_LINE_SIZE(DCACHE);
165*b841b6e9Srick 
166*b841b6e9Srick 	while (end > start) {
167*b841b6e9Srick 		asm volatile (
168*b841b6e9Srick 			"\n\tcctl %0, L1D_VA_WB"
169*b841b6e9Srick 			"\n\tcctl %0, L1D_VA_INVAL" : : "r" (start)
170*b841b6e9Srick 		);
171*b841b6e9Srick 		start += line_size;
172*b841b6e9Srick 	}
173*b841b6e9Srick }
174*b841b6e9Srick 
invalidate_dcache_range(unsigned long start,unsigned long end)175*b841b6e9Srick void invalidate_dcache_range(unsigned long start, unsigned long end)
176*b841b6e9Srick {
177*b841b6e9Srick 	unsigned long line_size;
178*b841b6e9Srick 
179*b841b6e9Srick 	line_size = CACHE_LINE_SIZE(DCACHE);
180*b841b6e9Srick 	while (end > start) {
181*b841b6e9Srick 		asm volatile (
182*b841b6e9Srick 			"\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)
183*b841b6e9Srick 		);
184*b841b6e9Srick 		start += line_size;
185*b841b6e9Srick 	}
186*b841b6e9Srick }
187*b841b6e9Srick 
dcache_enable(void)1888d732840SMacpaul Lin void dcache_enable(void)
1898d732840SMacpaul Lin {
1908d732840SMacpaul Lin 	asm volatile (
1918d732840SMacpaul Lin 		"mfsr	$p0, $mr8\n\t"
1928d732840SMacpaul Lin 		"ori	$p0, $p0, 0x02\n\t"
1938d732840SMacpaul Lin 		"mtsr	$p0, $mr8\n\t"
1948d732840SMacpaul Lin 		"isb\n\t"
1958d732840SMacpaul Lin 	);
1968d732840SMacpaul Lin }
1978d732840SMacpaul Lin 
dcache_disable(void)1988d732840SMacpaul Lin void dcache_disable(void)
1998d732840SMacpaul Lin {
2008d732840SMacpaul Lin 	asm volatile (
2018d732840SMacpaul Lin 		"mfsr	$p0, $mr8\n\t"
2028d732840SMacpaul Lin 		"li	$p1, ~0x02\n\t"
2038d732840SMacpaul Lin 		"and	$p0, $p0, $p1\n\t"
2048d732840SMacpaul Lin 		"mtsr	$p0, $mr8\n\t"
2058d732840SMacpaul Lin 		"isb\n\t"
2068d732840SMacpaul Lin 	);
2078d732840SMacpaul Lin }
2088d732840SMacpaul Lin 
dcache_status(void)2098d732840SMacpaul Lin int dcache_status(void)
2108d732840SMacpaul Lin {
2118d732840SMacpaul Lin 	int ret;
2128d732840SMacpaul Lin 	asm volatile (
2138d732840SMacpaul Lin 		"mfsr	$p0, $mr8\n\t"
2148d732840SMacpaul Lin 		"andi	%0, $p0, 0x02\n\t"
2158d732840SMacpaul Lin 		: "=r" (ret)
2168d732840SMacpaul Lin 		:
2178d732840SMacpaul Lin 		: "memory"
2188d732840SMacpaul Lin 	);
2198d732840SMacpaul Lin 	return ret;
2208d732840SMacpaul Lin }
221*b841b6e9Srick 
222*b841b6e9Srick #else
dcache_wbinval_all(void)223*b841b6e9Srick void dcache_wbinval_all(void)
224*b841b6e9Srick {
225*b841b6e9Srick }
226*b841b6e9Srick 
flush_dcache_range(unsigned long start,unsigned long end)227*b841b6e9Srick void flush_dcache_range(unsigned long start, unsigned long end)
228*b841b6e9Srick {
229*b841b6e9Srick }
230*b841b6e9Srick 
invalidate_dcache_range(unsigned long start,unsigned long end)231*b841b6e9Srick void invalidate_dcache_range(unsigned long start, unsigned long end)
232*b841b6e9Srick {
233*b841b6e9Srick }
234*b841b6e9Srick 
dcache_enable(void)235*b841b6e9Srick void dcache_enable(void)
236*b841b6e9Srick {
237*b841b6e9Srick }
238*b841b6e9Srick 
dcache_disable(void)239*b841b6e9Srick void dcache_disable(void)
240*b841b6e9Srick {
241*b841b6e9Srick }
242*b841b6e9Srick 
dcache_status(void)243*b841b6e9Srick int dcache_status(void)
244*b841b6e9Srick {
245*b841b6e9Srick 	return 0;
246*b841b6e9Srick }
247*b841b6e9Srick 
248*b841b6e9Srick #endif
249*b841b6e9Srick 
250*b841b6e9Srick 
flush_dcache_all(void)251*b841b6e9Srick void flush_dcache_all(void)
252*b841b6e9Srick {
253*b841b6e9Srick 	dcache_wbinval_all();
254*b841b6e9Srick }
255*b841b6e9Srick 
cache_flush(void)256*b841b6e9Srick void cache_flush(void)
257*b841b6e9Srick {
258*b841b6e9Srick 	flush_dcache_all();
259*b841b6e9Srick 	invalidate_icache_all();
260*b841b6e9Srick }
261*b841b6e9Srick 
262*b841b6e9Srick 
flush_cache(unsigned long addr,unsigned long size)263*b841b6e9Srick void flush_cache(unsigned long addr, unsigned long size)
264*b841b6e9Srick {
265*b841b6e9Srick 	flush_dcache_range(addr, addr + size);
266*b841b6e9Srick 	invalidate_icache_range(addr, addr + size);
267*b841b6e9Srick }
268