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