xref: /openbmc/u-boot/arch/arc/lib/cache.c (revision 379b3280)
1660d5f0dSAlexey Brodkin /*
2660d5f0dSAlexey Brodkin  * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
3660d5f0dSAlexey Brodkin  *
4660d5f0dSAlexey Brodkin  * SPDX-License-Identifier:	GPL-2.0+
5660d5f0dSAlexey Brodkin  */
6660d5f0dSAlexey Brodkin 
7660d5f0dSAlexey Brodkin #include <config.h>
8*379b3280SAlexey Brodkin #include <common.h>
9ef639e6fSAlexey Brodkin #include <linux/compiler.h>
10ef639e6fSAlexey Brodkin #include <linux/kernel.h>
11660d5f0dSAlexey Brodkin #include <asm/arcregs.h>
12205e7a7bSAlexey Brodkin #include <asm/cache.h>
13660d5f0dSAlexey Brodkin 
14660d5f0dSAlexey Brodkin /* Bit values in IC_CTRL */
15660d5f0dSAlexey Brodkin #define IC_CTRL_CACHE_DISABLE	(1 << 0)
16660d5f0dSAlexey Brodkin 
17660d5f0dSAlexey Brodkin /* Bit values in DC_CTRL */
18660d5f0dSAlexey Brodkin #define DC_CTRL_CACHE_DISABLE	(1 << 0)
19660d5f0dSAlexey Brodkin #define DC_CTRL_INV_MODE_FLUSH	(1 << 6)
20660d5f0dSAlexey Brodkin #define DC_CTRL_FLUSH_STATUS	(1 << 8)
21660d5f0dSAlexey Brodkin #define CACHE_VER_NUM_MASK	0xF
226eb15e50SAlexey Brodkin #define SLC_CTRL_SB		(1 << 2)
23660d5f0dSAlexey Brodkin 
24ef639e6fSAlexey Brodkin #define OP_INV		0x1
25ef639e6fSAlexey Brodkin #define OP_FLUSH	0x2
26ef639e6fSAlexey Brodkin #define OP_INV_IC	0x3
27ef639e6fSAlexey Brodkin 
28ef639e6fSAlexey Brodkin /*
29ef639e6fSAlexey Brodkin  * By default that variable will fall into .bss section.
30ef639e6fSAlexey Brodkin  * But .bss section is not relocated and so it will be initilized before
31ef639e6fSAlexey Brodkin  * relocation but will be used after being zeroed.
32ef639e6fSAlexey Brodkin  */
33*379b3280SAlexey Brodkin int l1_line_sz __section(".data");
34*379b3280SAlexey Brodkin int dcache_exists __section(".data");
35*379b3280SAlexey Brodkin int icache_exists __section(".data");
36*379b3280SAlexey Brodkin 
37*379b3280SAlexey Brodkin #define CACHE_LINE_MASK		(~(l1_line_sz - 1))
38*379b3280SAlexey Brodkin 
39*379b3280SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2
40ef639e6fSAlexey Brodkin int slc_line_sz __section(".data");
41ef639e6fSAlexey Brodkin int slc_exists __section(".data");
42ef639e6fSAlexey Brodkin 
43ef639e6fSAlexey Brodkin static unsigned int __before_slc_op(const int op)
44ef639e6fSAlexey Brodkin {
45ef639e6fSAlexey Brodkin 	unsigned int reg = reg;
46ef639e6fSAlexey Brodkin 
47ef639e6fSAlexey Brodkin 	if (op == OP_INV) {
48ef639e6fSAlexey Brodkin 		/*
49ef639e6fSAlexey Brodkin 		 * IM is set by default and implies Flush-n-inv
50ef639e6fSAlexey Brodkin 		 * Clear it here for vanilla inv
51ef639e6fSAlexey Brodkin 		 */
52ef639e6fSAlexey Brodkin 		reg = read_aux_reg(ARC_AUX_SLC_CTRL);
53ef639e6fSAlexey Brodkin 		write_aux_reg(ARC_AUX_SLC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH);
54ef639e6fSAlexey Brodkin 	}
55ef639e6fSAlexey Brodkin 
56ef639e6fSAlexey Brodkin 	return reg;
57ef639e6fSAlexey Brodkin }
58ef639e6fSAlexey Brodkin 
59ef639e6fSAlexey Brodkin static void __after_slc_op(const int op, unsigned int reg)
60ef639e6fSAlexey Brodkin {
61ef639e6fSAlexey Brodkin 	if (op & OP_FLUSH)	/* flush / flush-n-inv both wait */
62ef639e6fSAlexey Brodkin 		while (read_aux_reg(ARC_AUX_SLC_CTRL) &
63ef639e6fSAlexey Brodkin 		       DC_CTRL_FLUSH_STATUS)
64ef639e6fSAlexey Brodkin 			;
65ef639e6fSAlexey Brodkin 
66ef639e6fSAlexey Brodkin 	/* Switch back to default Invalidate mode */
67ef639e6fSAlexey Brodkin 	if (op == OP_INV)
68ef639e6fSAlexey Brodkin 		write_aux_reg(ARC_AUX_SLC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH);
69ef639e6fSAlexey Brodkin }
70ef639e6fSAlexey Brodkin 
71ef639e6fSAlexey Brodkin static inline void __slc_line_loop(unsigned long paddr, unsigned long sz,
72ef639e6fSAlexey Brodkin 				   const int op)
73ef639e6fSAlexey Brodkin {
74ef639e6fSAlexey Brodkin 	unsigned int aux_cmd;
75ef639e6fSAlexey Brodkin 	int num_lines;
76ef639e6fSAlexey Brodkin 
77ef639e6fSAlexey Brodkin #define SLC_LINE_MASK	(~(slc_line_sz - 1))
78ef639e6fSAlexey Brodkin 
79ef639e6fSAlexey Brodkin 	aux_cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL;
80ef639e6fSAlexey Brodkin 
81ef639e6fSAlexey Brodkin 	sz += paddr & ~SLC_LINE_MASK;
82ef639e6fSAlexey Brodkin 	paddr &= SLC_LINE_MASK;
83ef639e6fSAlexey Brodkin 
84ef639e6fSAlexey Brodkin 	num_lines = DIV_ROUND_UP(sz, slc_line_sz);
85ef639e6fSAlexey Brodkin 
86ef639e6fSAlexey Brodkin 	while (num_lines-- > 0) {
87ef639e6fSAlexey Brodkin 		write_aux_reg(aux_cmd, paddr);
88ef639e6fSAlexey Brodkin 		paddr += slc_line_sz;
89ef639e6fSAlexey Brodkin 	}
90ef639e6fSAlexey Brodkin }
91ef639e6fSAlexey Brodkin 
92ef639e6fSAlexey Brodkin static inline void __slc_entire_op(const int cacheop)
93ef639e6fSAlexey Brodkin {
94ef639e6fSAlexey Brodkin 	int aux;
95ef639e6fSAlexey Brodkin 	unsigned int ctrl_reg = __before_slc_op(cacheop);
96ef639e6fSAlexey Brodkin 
97ef639e6fSAlexey Brodkin 	if (cacheop & OP_INV)	/* Inv or flush-n-inv use same cmd reg */
98ef639e6fSAlexey Brodkin 		aux = ARC_AUX_SLC_INVALIDATE;
99ef639e6fSAlexey Brodkin 	else
100ef639e6fSAlexey Brodkin 		aux = ARC_AUX_SLC_FLUSH;
101ef639e6fSAlexey Brodkin 
102ef639e6fSAlexey Brodkin 	write_aux_reg(aux, 0x1);
103ef639e6fSAlexey Brodkin 
104ef639e6fSAlexey Brodkin 	__after_slc_op(cacheop, ctrl_reg);
105ef639e6fSAlexey Brodkin }
106ef639e6fSAlexey Brodkin 
107ef639e6fSAlexey Brodkin static inline void __slc_line_op(unsigned long paddr, unsigned long sz,
108ef639e6fSAlexey Brodkin 				 const int cacheop)
109ef639e6fSAlexey Brodkin {
110ef639e6fSAlexey Brodkin 	unsigned int ctrl_reg = __before_slc_op(cacheop);
111ef639e6fSAlexey Brodkin 	__slc_line_loop(paddr, sz, cacheop);
112ef639e6fSAlexey Brodkin 	__after_slc_op(cacheop, ctrl_reg);
113ef639e6fSAlexey Brodkin }
114ef639e6fSAlexey Brodkin #else
115ef639e6fSAlexey Brodkin #define __slc_entire_op(cacheop)
116ef639e6fSAlexey Brodkin #define __slc_line_op(paddr, sz, cacheop)
117ef639e6fSAlexey Brodkin #endif
118ef639e6fSAlexey Brodkin 
119*379b3280SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2
120*379b3280SAlexey Brodkin static void read_decode_cache_bcr_arcv2(void)
121ef639e6fSAlexey Brodkin {
122*379b3280SAlexey Brodkin 	union {
123*379b3280SAlexey Brodkin 		struct {
124*379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN
125*379b3280SAlexey Brodkin 			unsigned int pad:24, way:2, lsz:2, sz:4;
126*379b3280SAlexey Brodkin #else
127*379b3280SAlexey Brodkin 			unsigned int sz:4, lsz:2, way:2, pad:24;
128*379b3280SAlexey Brodkin #endif
129*379b3280SAlexey Brodkin 		} fields;
130*379b3280SAlexey Brodkin 		unsigned int word;
131*379b3280SAlexey Brodkin 	} slc_cfg;
132*379b3280SAlexey Brodkin 
133*379b3280SAlexey Brodkin 	union {
134*379b3280SAlexey Brodkin 		struct {
135*379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN
136*379b3280SAlexey Brodkin 			unsigned int pad:24, ver:8;
137*379b3280SAlexey Brodkin #else
138*379b3280SAlexey Brodkin 			unsigned int ver:8, pad:24;
139*379b3280SAlexey Brodkin #endif
140*379b3280SAlexey Brodkin 		} fields;
141*379b3280SAlexey Brodkin 		unsigned int word;
142*379b3280SAlexey Brodkin 	} sbcr;
143*379b3280SAlexey Brodkin 
144*379b3280SAlexey Brodkin 	sbcr.word = read_aux_reg(ARC_BCR_SLC);
145*379b3280SAlexey Brodkin 	if (sbcr.fields.ver) {
146*379b3280SAlexey Brodkin 		slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG);
147*379b3280SAlexey Brodkin 		slc_exists = 1;
148*379b3280SAlexey Brodkin 		slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64;
149*379b3280SAlexey Brodkin 	}
150*379b3280SAlexey Brodkin }
151*379b3280SAlexey Brodkin #endif
152*379b3280SAlexey Brodkin 
153*379b3280SAlexey Brodkin void read_decode_cache_bcr(void)
154*379b3280SAlexey Brodkin {
155*379b3280SAlexey Brodkin 	int dc_line_sz = 0, ic_line_sz = 0;
156*379b3280SAlexey Brodkin 
157*379b3280SAlexey Brodkin 	union {
158*379b3280SAlexey Brodkin 		struct {
159*379b3280SAlexey Brodkin #ifdef CONFIG_CPU_BIG_ENDIAN
160*379b3280SAlexey Brodkin 			unsigned int pad:12, line_len:4, sz:4, config:4, ver:8;
161*379b3280SAlexey Brodkin #else
162*379b3280SAlexey Brodkin 			unsigned int ver:8, config:4, sz:4, line_len:4, pad:12;
163*379b3280SAlexey Brodkin #endif
164*379b3280SAlexey Brodkin 		} fields;
165*379b3280SAlexey Brodkin 		unsigned int word;
166*379b3280SAlexey Brodkin 	} ibcr, dbcr;
167*379b3280SAlexey Brodkin 
168*379b3280SAlexey Brodkin 	ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
169*379b3280SAlexey Brodkin 	if (ibcr.fields.ver) {
170*379b3280SAlexey Brodkin 		icache_exists = 1;
171*379b3280SAlexey Brodkin 		l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len;
172*379b3280SAlexey Brodkin 		if (!ic_line_sz)
173*379b3280SAlexey Brodkin 			panic("Instruction exists but line length is 0\n");
174ef639e6fSAlexey Brodkin 	}
175ef639e6fSAlexey Brodkin 
176*379b3280SAlexey Brodkin 	dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
177*379b3280SAlexey Brodkin 	if (dbcr.fields.ver){
178*379b3280SAlexey Brodkin 		dcache_exists = 1;
179*379b3280SAlexey Brodkin 		l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len;
180*379b3280SAlexey Brodkin 		if (!dc_line_sz)
181*379b3280SAlexey Brodkin 			panic("Data cache exists but line length is 0\n");
182*379b3280SAlexey Brodkin 	}
183*379b3280SAlexey Brodkin 
184*379b3280SAlexey Brodkin 	if (ic_line_sz && dc_line_sz && (ic_line_sz != dc_line_sz))
185*379b3280SAlexey Brodkin 		panic("Instruction and data cache line lengths differ\n");
186ef639e6fSAlexey Brodkin }
187ef639e6fSAlexey Brodkin 
188ef639e6fSAlexey Brodkin void cache_init(void)
189ef639e6fSAlexey Brodkin {
190*379b3280SAlexey Brodkin 	read_decode_cache_bcr();
191*379b3280SAlexey Brodkin 
192ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2
193*379b3280SAlexey Brodkin 	read_decode_cache_bcr_arcv2();
194ef639e6fSAlexey Brodkin #endif
195ef639e6fSAlexey Brodkin }
196ef639e6fSAlexey Brodkin 
197660d5f0dSAlexey Brodkin int icache_status(void)
198660d5f0dSAlexey Brodkin {
199*379b3280SAlexey Brodkin 	if (!icache_exists)
200660d5f0dSAlexey Brodkin 		return 0;
201660d5f0dSAlexey Brodkin 
202ef639e6fSAlexey Brodkin 	if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE)
203ef639e6fSAlexey Brodkin 		return 0;
204ef639e6fSAlexey Brodkin 	else
205ef639e6fSAlexey Brodkin 		return 1;
206660d5f0dSAlexey Brodkin }
207660d5f0dSAlexey Brodkin 
208660d5f0dSAlexey Brodkin void icache_enable(void)
209660d5f0dSAlexey Brodkin {
210*379b3280SAlexey Brodkin 	if (icache_exists)
211660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
212660d5f0dSAlexey Brodkin 			      ~IC_CTRL_CACHE_DISABLE);
213660d5f0dSAlexey Brodkin }
214660d5f0dSAlexey Brodkin 
215660d5f0dSAlexey Brodkin void icache_disable(void)
216660d5f0dSAlexey Brodkin {
217*379b3280SAlexey Brodkin 	if (icache_exists)
218660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
219660d5f0dSAlexey Brodkin 			      IC_CTRL_CACHE_DISABLE);
220660d5f0dSAlexey Brodkin }
221660d5f0dSAlexey Brodkin 
222ef639e6fSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
223660d5f0dSAlexey Brodkin void invalidate_icache_all(void)
224660d5f0dSAlexey Brodkin {
225660d5f0dSAlexey Brodkin 	/* Any write to IC_IVIC register triggers invalidation of entire I$ */
226ef639e6fSAlexey Brodkin 	if (icache_status()) {
227660d5f0dSAlexey Brodkin 		write_aux_reg(ARC_AUX_IC_IVIC, 1);
228ef639e6fSAlexey Brodkin 		read_aux_reg(ARC_AUX_IC_CTRL);	/* blocks */
229660d5f0dSAlexey Brodkin 	}
230ef639e6fSAlexey Brodkin }
231ef639e6fSAlexey Brodkin #else
232ef639e6fSAlexey Brodkin void invalidate_icache_all(void)
233ef639e6fSAlexey Brodkin {
234ef639e6fSAlexey Brodkin }
235ef639e6fSAlexey Brodkin #endif
236660d5f0dSAlexey Brodkin 
237660d5f0dSAlexey Brodkin int dcache_status(void)
238660d5f0dSAlexey Brodkin {
239*379b3280SAlexey Brodkin 	if (!dcache_exists)
240660d5f0dSAlexey Brodkin 		return 0;
241660d5f0dSAlexey Brodkin 
242ef639e6fSAlexey Brodkin 	if (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE)
243ef639e6fSAlexey Brodkin 		return 0;
244ef639e6fSAlexey Brodkin 	else
245ef639e6fSAlexey Brodkin 		return 1;
246660d5f0dSAlexey Brodkin }
247660d5f0dSAlexey Brodkin 
248660d5f0dSAlexey Brodkin void dcache_enable(void)
249660d5f0dSAlexey Brodkin {
250*379b3280SAlexey Brodkin 	if (!dcache_exists)
251660d5f0dSAlexey Brodkin 		return;
252660d5f0dSAlexey Brodkin 
253660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
254660d5f0dSAlexey Brodkin 		      ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
255660d5f0dSAlexey Brodkin }
256660d5f0dSAlexey Brodkin 
257660d5f0dSAlexey Brodkin void dcache_disable(void)
258660d5f0dSAlexey Brodkin {
259*379b3280SAlexey Brodkin 	if (!dcache_exists)
260660d5f0dSAlexey Brodkin 		return;
261660d5f0dSAlexey Brodkin 
262660d5f0dSAlexey Brodkin 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
263660d5f0dSAlexey Brodkin 		      DC_CTRL_CACHE_DISABLE);
264660d5f0dSAlexey Brodkin }
265660d5f0dSAlexey Brodkin 
266660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF
267660d5f0dSAlexey Brodkin /*
268ef639e6fSAlexey Brodkin  * Common Helper for Line Operations on {I,D}-Cache
269660d5f0dSAlexey Brodkin  */
270ef639e6fSAlexey Brodkin static inline void __cache_line_loop(unsigned long paddr, unsigned long sz,
271ef639e6fSAlexey Brodkin 				     const int cacheop)
272660d5f0dSAlexey Brodkin {
273ef639e6fSAlexey Brodkin 	unsigned int aux_cmd;
274ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
275ef639e6fSAlexey Brodkin 	unsigned int aux_tag;
276ef639e6fSAlexey Brodkin #endif
277ef639e6fSAlexey Brodkin 	int num_lines;
278660d5f0dSAlexey Brodkin 
279ef639e6fSAlexey Brodkin 	if (cacheop == OP_INV_IC) {
280ef639e6fSAlexey Brodkin 		aux_cmd = ARC_AUX_IC_IVIL;
281ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
282ef639e6fSAlexey Brodkin 		aux_tag = ARC_AUX_IC_PTAG;
283ef639e6fSAlexey Brodkin #endif
284ef639e6fSAlexey Brodkin 	} else {
285ef639e6fSAlexey Brodkin 		/* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
286ef639e6fSAlexey Brodkin 		aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL;
287ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
288ef639e6fSAlexey Brodkin 		aux_tag = ARC_AUX_DC_PTAG;
289ef639e6fSAlexey Brodkin #endif
290660d5f0dSAlexey Brodkin 	}
291660d5f0dSAlexey Brodkin 
292ef639e6fSAlexey Brodkin 	sz += paddr & ~CACHE_LINE_MASK;
293ef639e6fSAlexey Brodkin 	paddr &= CACHE_LINE_MASK;
294ef639e6fSAlexey Brodkin 
295*379b3280SAlexey Brodkin 	num_lines = DIV_ROUND_UP(sz, l1_line_sz);
296ef639e6fSAlexey Brodkin 
297ef639e6fSAlexey Brodkin 	while (num_lines-- > 0) {
298ef639e6fSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3)
299ef639e6fSAlexey Brodkin 		write_aux_reg(aux_tag, paddr);
300ef639e6fSAlexey Brodkin #endif
301ef639e6fSAlexey Brodkin 		write_aux_reg(aux_cmd, paddr);
302*379b3280SAlexey Brodkin 		paddr += l1_line_sz;
303ef639e6fSAlexey Brodkin 	}
304ef639e6fSAlexey Brodkin }
305ef639e6fSAlexey Brodkin 
306ef639e6fSAlexey Brodkin static unsigned int __before_dc_op(const int op)
307ef639e6fSAlexey Brodkin {
308ef639e6fSAlexey Brodkin 	unsigned int reg;
309ef639e6fSAlexey Brodkin 
310ef639e6fSAlexey Brodkin 	if (op == OP_INV) {
311ef639e6fSAlexey Brodkin 		/*
312ef639e6fSAlexey Brodkin 		 * IM is set by default and implies Flush-n-inv
313ef639e6fSAlexey Brodkin 		 * Clear it here for vanilla inv
314ef639e6fSAlexey Brodkin 		 */
315ef639e6fSAlexey Brodkin 		reg = read_aux_reg(ARC_AUX_DC_CTRL);
316ef639e6fSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH);
317ef639e6fSAlexey Brodkin 	}
318ef639e6fSAlexey Brodkin 
319ef639e6fSAlexey Brodkin 	return reg;
320ef639e6fSAlexey Brodkin }
321ef639e6fSAlexey Brodkin 
322ef639e6fSAlexey Brodkin static void __after_dc_op(const int op, unsigned int reg)
323ef639e6fSAlexey Brodkin {
324ef639e6fSAlexey Brodkin 	if (op & OP_FLUSH)	/* flush / flush-n-inv both wait */
325ef639e6fSAlexey Brodkin 		while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
326ef639e6fSAlexey Brodkin 			;
327ef639e6fSAlexey Brodkin 
328ef639e6fSAlexey Brodkin 	/* Switch back to default Invalidate mode */
329ef639e6fSAlexey Brodkin 	if (op == OP_INV)
330ef639e6fSAlexey Brodkin 		write_aux_reg(ARC_AUX_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH);
331ef639e6fSAlexey Brodkin }
332ef639e6fSAlexey Brodkin 
333ef639e6fSAlexey Brodkin static inline void __dc_entire_op(const int cacheop)
334ef639e6fSAlexey Brodkin {
335ef639e6fSAlexey Brodkin 	int aux;
336ef639e6fSAlexey Brodkin 	unsigned int ctrl_reg = __before_dc_op(cacheop);
337ef639e6fSAlexey Brodkin 
338ef639e6fSAlexey Brodkin 	if (cacheop & OP_INV)	/* Inv or flush-n-inv use same cmd reg */
339ef639e6fSAlexey Brodkin 		aux = ARC_AUX_DC_IVDC;
340ef639e6fSAlexey Brodkin 	else
341ef639e6fSAlexey Brodkin 		aux = ARC_AUX_DC_FLSH;
342ef639e6fSAlexey Brodkin 
343ef639e6fSAlexey Brodkin 	write_aux_reg(aux, 0x1);
344ef639e6fSAlexey Brodkin 
345ef639e6fSAlexey Brodkin 	__after_dc_op(cacheop, ctrl_reg);
346ef639e6fSAlexey Brodkin }
347ef639e6fSAlexey Brodkin 
348ef639e6fSAlexey Brodkin static inline void __dc_line_op(unsigned long paddr, unsigned long sz,
349ef639e6fSAlexey Brodkin 				const int cacheop)
350ef639e6fSAlexey Brodkin {
351ef639e6fSAlexey Brodkin 	unsigned int ctrl_reg = __before_dc_op(cacheop);
352ef639e6fSAlexey Brodkin 	__cache_line_loop(paddr, sz, cacheop);
353ef639e6fSAlexey Brodkin 	__after_dc_op(cacheop, ctrl_reg);
354ef639e6fSAlexey Brodkin }
355ef639e6fSAlexey Brodkin #else
356ef639e6fSAlexey Brodkin #define __dc_entire_op(cacheop)
357ef639e6fSAlexey Brodkin #define __dc_line_op(paddr, sz, cacheop)
358ef639e6fSAlexey Brodkin #endif /* !CONFIG_SYS_DCACHE_OFF */
359ef639e6fSAlexey Brodkin 
360660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end)
361660d5f0dSAlexey Brodkin {
362ef639e6fSAlexey Brodkin 	__dc_line_op(start, end - start, OP_INV);
363ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2
364ef639e6fSAlexey Brodkin 	if (slc_exists)
365ef639e6fSAlexey Brodkin 		__slc_line_op(start, end - start, OP_INV);
366660d5f0dSAlexey Brodkin #endif
367660d5f0dSAlexey Brodkin }
368660d5f0dSAlexey Brodkin 
369ef639e6fSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end)
370660d5f0dSAlexey Brodkin {
371ef639e6fSAlexey Brodkin 	__dc_line_op(start, end - start, OP_FLUSH);
372ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2
373ef639e6fSAlexey Brodkin 	if (slc_exists)
374ef639e6fSAlexey Brodkin 		__slc_line_op(start, end - start, OP_FLUSH);
375ef639e6fSAlexey Brodkin #endif
376660d5f0dSAlexey Brodkin }
377660d5f0dSAlexey Brodkin 
378660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size)
379660d5f0dSAlexey Brodkin {
380660d5f0dSAlexey Brodkin 	flush_dcache_range(start, start + size);
381660d5f0dSAlexey Brodkin }
3826eb15e50SAlexey Brodkin 
383ef639e6fSAlexey Brodkin void invalidate_dcache_all(void)
384ef639e6fSAlexey Brodkin {
385ef639e6fSAlexey Brodkin 	__dc_entire_op(OP_INV);
3866eb15e50SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2
387ef639e6fSAlexey Brodkin 	if (slc_exists)
388ef639e6fSAlexey Brodkin 		__slc_entire_op(OP_INV);
389ef639e6fSAlexey Brodkin #endif
3906eb15e50SAlexey Brodkin }
3916eb15e50SAlexey Brodkin 
392ef639e6fSAlexey Brodkin void flush_dcache_all(void)
3936eb15e50SAlexey Brodkin {
394ef639e6fSAlexey Brodkin 	__dc_entire_op(OP_FLUSH);
395ef639e6fSAlexey Brodkin #ifdef CONFIG_ISA_ARCV2
396ef639e6fSAlexey Brodkin 	if (slc_exists)
397ef639e6fSAlexey Brodkin 		__slc_entire_op(OP_FLUSH);
398ef639e6fSAlexey Brodkin #endif
3996eb15e50SAlexey Brodkin }
400