xref: /openbmc/u-boot/arch/arc/lib/cache.c (revision 5c8fd32b)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
4  */
5 
6 #include <config.h>
7 #include <common.h>
8 #include <linux/compiler.h>
9 #include <linux/kernel.h>
10 #include <linux/log2.h>
11 #include <asm/arcregs.h>
12 #include <asm/arc-bcr.h>
13 #include <asm/cache.h>
14 
15 /*
16  * [ NOTE 1 ]:
17  * Data cache (L1 D$ or SL$) entire invalidate operation or data cache disable
18  * operation may result in unexpected behavior and data loss even if we flush
19  * data cache right before invalidation. That may happens if we store any context
20  * on stack (like we store BLINK register on stack before function call).
21  * BLINK register is the register where return address is automatically saved
22  * when we do function call with instructions like 'bl'.
23  *
24  * There is the real example:
25  * We may hang in the next code as we store any BLINK register on stack in
26  * invalidate_dcache_all() function.
27  *
28  * void flush_dcache_all() {
29  *     __dc_entire_op(OP_FLUSH);
30  *     // Other code //
31  * }
32  *
33  * void invalidate_dcache_all() {
34  *     __dc_entire_op(OP_INV);
35  *     // Other code //
36  * }
37  *
38  * void foo(void) {
39  *     flush_dcache_all();
40  *     invalidate_dcache_all();
41  * }
42  *
43  * Now let's see what really happens during that code execution:
44  *
45  * foo()
46  *   |->> call flush_dcache_all
47  *     [return address is saved to BLINK register]
48  *     [push BLINK] (save to stack)              ![point 1]
49  *     |->> call __dc_entire_op(OP_FLUSH)
50  *         [return address is saved to BLINK register]
51  *         [flush L1 D$]
52  *         return [jump to BLINK]
53  *     <<------
54  *     [other flush_dcache_all code]
55  *     [pop BLINK] (get from stack)
56  *     return [jump to BLINK]
57  *   <<------
58  *   |->> call invalidate_dcache_all
59  *     [return address is saved to BLINK register]
60  *     [push BLINK] (save to stack)               ![point 2]
61  *     |->> call __dc_entire_op(OP_FLUSH)
62  *         [return address is saved to BLINK register]
63  *         [invalidate L1 D$]                 ![point 3]
64  *         // Oops!!!
65  *         // We lose return address from invalidate_dcache_all function:
66  *         // we save it to stack and invalidate L1 D$ after that!
67  *         return [jump to BLINK]
68  *     <<------
69  *     [other invalidate_dcache_all code]
70  *     [pop BLINK] (get from stack)
71  *     // we don't have this data in L1 dcache as we invalidated it in [point 3]
72  *     // so we get it from next memory level (for example DDR memory)
73  *     // but in the memory we have value which we save in [point 1], which
74  *     // is return address from flush_dcache_all function (instead of
75  *     // address from current invalidate_dcache_all function which we
76  *     // saved in [point 2] !)
77  *     return [jump to BLINK]
78  *   <<------
79  *   // As BLINK points to invalidate_dcache_all, we call it again and
80  *   // loop forever.
81  *
82  * Fortunately we may fix that by using flush & invalidation of D$ with a single
83  * one instruction (instead of flush and invalidation instructions pair) and
84  * enabling force function inline with '__attribute__((always_inline))' gcc
85  * attribute to avoid any function call (and BLINK store) between cache flush
86  * and disable.
87  *
88  *
89  * [ NOTE 2 ]:
90  * As of today we only support the following cache configurations on ARC.
91  * Other configurations may exist in HW (for example, since version 3.0 HS
92  * supports SL$ (L2 system level cache) disable) but we don't support it in SW.
93  * Configuration 1:
94  *        ______________________
95  *       |                      |
96  *       |   ARC CPU            |
97  *       |______________________|
98  *        ___|___        ___|___
99  *       |       |      |       |
100  *       | L1 I$ |      | L1 D$ |
101  *       |_______|      |_______|
102  *        on/off         on/off
103  *        ___|______________|____
104  *       |                      |
105  *       |   main memory        |
106  *       |______________________|
107  *
108  * Configuration 2:
109  *        ______________________
110  *       |                      |
111  *       |   ARC CPU            |
112  *       |______________________|
113  *        ___|___        ___|___
114  *       |       |      |       |
115  *       | L1 I$ |      | L1 D$ |
116  *       |_______|      |_______|
117  *        on/off         on/off
118  *        ___|______________|____
119  *       |                      |
120  *       |   L2 (SL$)           |
121  *       |______________________|
122  *          always must be on
123  *        ___|______________|____
124  *       |                      |
125  *       |   main memory        |
126  *       |______________________|
127  *
128  * Configuration 3:
129  *        ______________________
130  *       |                      |
131  *       |   ARC CPU            |
132  *       |______________________|
133  *        ___|___        ___|___
134  *       |       |      |       |
135  *       | L1 I$ |      | L1 D$ |
136  *       |_______|      |_______|
137  *        on/off        must be on
138  *        ___|______________|____      _______
139  *       |                      |     |       |
140  *       |   L2 (SL$)           |-----|  IOC  |
141  *       |______________________|     |_______|
142  *          always must be on          on/off
143  *        ___|______________|____
144  *       |                      |
145  *       |   main memory        |
146  *       |______________________|
147  */
148 
149 DECLARE_GLOBAL_DATA_PTR;
150 
151 /* Bit values in IC_CTRL */
152 #define IC_CTRL_CACHE_DISABLE	BIT(0)
153 
154 /* Bit values in DC_CTRL */
155 #define DC_CTRL_CACHE_DISABLE	BIT(0)
156 #define DC_CTRL_INV_MODE_FLUSH	BIT(6)
157 #define DC_CTRL_FLUSH_STATUS	BIT(8)
158 
159 #define OP_INV			BIT(0)
160 #define OP_FLUSH		BIT(1)
161 #define OP_FLUSH_N_INV		(OP_FLUSH | OP_INV)
162 
163 /* Bit val in SLC_CONTROL */
164 #define SLC_CTRL_DIS		0x001
165 #define SLC_CTRL_IM		0x040
166 #define SLC_CTRL_BUSY		0x100
167 #define SLC_CTRL_RGN_OP_INV	0x200
168 
169 #define CACHE_LINE_MASK		(~(gd->arch.l1_line_sz - 1))
170 
171 /*
172  * We don't want to use '__always_inline' macro here as it can be redefined
173  * to simple 'inline' in some cases which breaks stuff. See [ NOTE 1 ] for more
174  * details about the reasons we need to use always_inline functions.
175  */
176 #define inlined_cachefunc	 inline __attribute__((always_inline))
177 
178 static inlined_cachefunc void __ic_entire_invalidate(void);
179 static inlined_cachefunc void __dc_entire_op(const int cacheop);
180 
181 static inline bool pae_exists(void)
182 {
183 	/* TODO: should we compare mmu version from BCR and from CONFIG? */
184 #if (CONFIG_ARC_MMU_VER >= 4)
185 	union bcr_mmu_4 mmu4;
186 
187 	mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR);
188 
189 	if (mmu4.fields.pae)
190 		return true;
191 #endif /* (CONFIG_ARC_MMU_VER >= 4) */
192 
193 	return false;
194 }
195 
196 static inlined_cachefunc bool icache_exists(void)
197 {
198 	union bcr_di_cache ibcr;
199 
200 	ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
201 	return !!ibcr.fields.ver;
202 }
203 
204 static inlined_cachefunc bool icache_enabled(void)
205 {
206 	if (!icache_exists())
207 		return false;
208 
209 	return !(read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE);
210 }
211 
212 static inlined_cachefunc bool dcache_exists(void)
213 {
214 	union bcr_di_cache dbcr;
215 
216 	dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
217 	return !!dbcr.fields.ver;
218 }
219 
220 static inlined_cachefunc bool dcache_enabled(void)
221 {
222 	if (!dcache_exists())
223 		return false;
224 
225 	return !(read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE);
226 }
227 
228 static inlined_cachefunc bool slc_exists(void)
229 {
230 	if (is_isa_arcv2()) {
231 		union bcr_generic sbcr;
232 
233 		sbcr.word = read_aux_reg(ARC_BCR_SLC);
234 		return !!sbcr.fields.ver;
235 	}
236 
237 	return false;
238 }
239 
240 static inlined_cachefunc bool slc_data_bypass(void)
241 {
242 	/*
243 	 * If L1 data cache is disabled SL$ is bypassed and all load/store
244 	 * requests are sent directly to main memory.
245 	 */
246 	return !dcache_enabled();
247 }
248 
249 static inline bool ioc_exists(void)
250 {
251 	if (is_isa_arcv2()) {
252 		union bcr_clust_cfg cbcr;
253 
254 		cbcr.word = read_aux_reg(ARC_BCR_CLUSTER);
255 		return cbcr.fields.c;
256 	}
257 
258 	return false;
259 }
260 
261 static inline bool ioc_enabled(void)
262 {
263 	/*
264 	 * We check only CONFIG option instead of IOC HW state check as IOC
265 	 * must be disabled by default.
266 	 */
267 	if (is_ioc_enabled())
268 		return ioc_exists();
269 
270 	return false;
271 }
272 
273 static inlined_cachefunc void __slc_entire_op(const int op)
274 {
275 	unsigned int ctrl;
276 
277 	if (!slc_exists())
278 		return;
279 
280 	ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
281 
282 	if (!(op & OP_FLUSH))		/* i.e. OP_INV */
283 		ctrl &= ~SLC_CTRL_IM;	/* clear IM: Disable flush before Inv */
284 	else
285 		ctrl |= SLC_CTRL_IM;
286 
287 	write_aux_reg(ARC_AUX_SLC_CTRL, ctrl);
288 
289 	if (op & OP_INV)	/* Inv or flush-n-inv use same cmd reg */
290 		write_aux_reg(ARC_AUX_SLC_INVALIDATE, 0x1);
291 	else
292 		write_aux_reg(ARC_AUX_SLC_FLUSH, 0x1);
293 
294 	/* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */
295 	read_aux_reg(ARC_AUX_SLC_CTRL);
296 
297 	/* Important to wait for flush to complete */
298 	while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY);
299 }
300 
301 static void slc_upper_region_init(void)
302 {
303 	/*
304 	 * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist
305 	 * only if PAE exists in current HW. So we had to check pae_exist
306 	 * before using them.
307 	 */
308 	if (!pae_exists())
309 		return;
310 
311 	/*
312 	 * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0
313 	 * as we don't use PAE40.
314 	 */
315 	write_aux_reg(ARC_AUX_SLC_RGN_END1, 0);
316 	write_aux_reg(ARC_AUX_SLC_RGN_START1, 0);
317 }
318 
319 static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op)
320 {
321 #ifdef CONFIG_ISA_ARCV2
322 
323 	unsigned int ctrl;
324 	unsigned long end;
325 
326 	if (!slc_exists())
327 		return;
328 
329 	/*
330 	 * The Region Flush operation is specified by CTRL.RGN_OP[11..9]
331 	 *  - b'000 (default) is Flush,
332 	 *  - b'001 is Invalidate if CTRL.IM == 0
333 	 *  - b'001 is Flush-n-Invalidate if CTRL.IM == 1
334 	 */
335 	ctrl = read_aux_reg(ARC_AUX_SLC_CTRL);
336 
337 	/* Don't rely on default value of IM bit */
338 	if (!(op & OP_FLUSH))		/* i.e. OP_INV */
339 		ctrl &= ~SLC_CTRL_IM;	/* clear IM: Disable flush before Inv */
340 	else
341 		ctrl |= SLC_CTRL_IM;
342 
343 	if (op & OP_INV)
344 		ctrl |= SLC_CTRL_RGN_OP_INV;	/* Inv or flush-n-inv */
345 	else
346 		ctrl &= ~SLC_CTRL_RGN_OP_INV;
347 
348 	write_aux_reg(ARC_AUX_SLC_CTRL, ctrl);
349 
350 	/*
351 	 * Lower bits are ignored, no need to clip
352 	 * END needs to be setup before START (latter triggers the operation)
353 	 * END can't be same as START, so add (l2_line_sz - 1) to sz
354 	 */
355 	end = paddr + sz + gd->arch.slc_line_sz - 1;
356 
357 	/*
358 	 * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1)
359 	 * are always == 0 as we don't use PAE40, so we only setup lower ones
360 	 * (ARC_AUX_SLC_RGN_END and ARC_AUX_SLC_RGN_START)
361 	 */
362 	write_aux_reg(ARC_AUX_SLC_RGN_END, end);
363 	write_aux_reg(ARC_AUX_SLC_RGN_START, paddr);
364 
365 	/* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */
366 	read_aux_reg(ARC_AUX_SLC_CTRL);
367 
368 	while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY);
369 
370 #endif /* CONFIG_ISA_ARCV2 */
371 }
372 
373 static void arc_ioc_setup(void)
374 {
375 	/* IOC Aperture start is equal to DDR start */
376 	unsigned int ap_base = CONFIG_SYS_SDRAM_BASE;
377 	/* IOC Aperture size is equal to DDR size */
378 	long ap_size = CONFIG_SYS_SDRAM_SIZE;
379 
380 	/* Unsupported configuration. See [ NOTE 2 ] for more details. */
381 	if (!slc_exists())
382 		panic("Try to enable IOC but SLC is not present");
383 
384 	/* Unsupported configuration. See [ NOTE 2 ] for more details. */
385 	if (!dcache_enabled())
386 		panic("Try to enable IOC but L1 D$ is disabled");
387 
388 	if (!is_power_of_2(ap_size) || ap_size < 4096)
389 		panic("IOC Aperture size must be power of 2 and bigger 4Kib");
390 
391 	/* IOC Aperture start must be aligned to the size of the aperture */
392 	if (ap_base % ap_size != 0)
393 		panic("IOC Aperture start must be aligned to the size of the aperture");
394 
395 	flush_n_invalidate_dcache_all();
396 
397 	/*
398 	 * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB,
399 	 * so setting 0x11 implies 512M, 0x12 implies 1G...
400 	 */
401 	write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE,
402 		      order_base_2(ap_size / 1024) - 2);
403 
404 	write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12);
405 	write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1);
406 	write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1);
407 }
408 
409 static void read_decode_cache_bcr_arcv2(void)
410 {
411 #ifdef CONFIG_ISA_ARCV2
412 
413 	union bcr_slc_cfg slc_cfg;
414 
415 	if (slc_exists()) {
416 		slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG);
417 		gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64;
418 
419 		/*
420 		 * We don't support configuration where L1 I$ or L1 D$ is
421 		 * absent but SL$ exists. See [ NOTE 2 ] for more details.
422 		 */
423 		if (!icache_exists() || !dcache_exists())
424 			panic("Unsupported cache configuration: SLC exists but one of L1 caches is absent");
425 	}
426 
427 #endif /* CONFIG_ISA_ARCV2 */
428 }
429 
430 void read_decode_cache_bcr(void)
431 {
432 	int dc_line_sz = 0, ic_line_sz = 0;
433 	union bcr_di_cache ibcr, dbcr;
434 
435 	/*
436 	 * We don't care much about I$ line length really as there're
437 	 * no per-line ops on I$ instead we only do full invalidation of it
438 	 * on occasion of relocation and right before jumping to the OS.
439 	 * Still we check insane config with zero-encoded line length in
440 	 * presense of version field in I$ BCR. Just in case.
441 	 */
442 	ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD);
443 	if (ibcr.fields.ver) {
444 		ic_line_sz = 8 << ibcr.fields.line_len;
445 		if (!ic_line_sz)
446 			panic("Instruction exists but line length is 0\n");
447 	}
448 
449 	dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD);
450 	if (dbcr.fields.ver) {
451 		gd->arch.l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len;
452 		if (!dc_line_sz)
453 			panic("Data cache exists but line length is 0\n");
454 	}
455 }
456 
457 void cache_init(void)
458 {
459 	read_decode_cache_bcr();
460 
461 	if (is_isa_arcv2())
462 		read_decode_cache_bcr_arcv2();
463 
464 	if (is_isa_arcv2() && ioc_enabled())
465 		arc_ioc_setup();
466 
467 	if (is_isa_arcv2() && slc_exists())
468 		slc_upper_region_init();
469 }
470 
471 int icache_status(void)
472 {
473 	return icache_enabled();
474 }
475 
476 void icache_enable(void)
477 {
478 	if (icache_exists())
479 		write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
480 			      ~IC_CTRL_CACHE_DISABLE);
481 }
482 
483 void icache_disable(void)
484 {
485 	if (!icache_exists())
486 		return;
487 
488 	__ic_entire_invalidate();
489 
490 	write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) |
491 		      IC_CTRL_CACHE_DISABLE);
492 }
493 
494 /* IC supports only invalidation */
495 static inlined_cachefunc void __ic_entire_invalidate(void)
496 {
497 	if (!icache_enabled())
498 		return;
499 
500 	/* Any write to IC_IVIC register triggers invalidation of entire I$ */
501 	write_aux_reg(ARC_AUX_IC_IVIC, 1);
502 	/*
503 	 * As per ARC HS databook (see chapter 5.3.3.2)
504 	 * it is required to add 3 NOPs after each write to IC_IVIC.
505 	 */
506 	__builtin_arc_nop();
507 	__builtin_arc_nop();
508 	__builtin_arc_nop();
509 	read_aux_reg(ARC_AUX_IC_CTRL);  /* blocks */
510 }
511 
512 void invalidate_icache_all(void)
513 {
514 	__ic_entire_invalidate();
515 
516 	/*
517 	 * If SL$ is bypassed for data it is used only for instructions,
518 	 * so we need to invalidate it too.
519 	 * TODO: HS 3.0 supports SLC disable so we need to check slc
520 	 * enable/disable status here.
521 	 */
522 	if (is_isa_arcv2() && slc_data_bypass())
523 		__slc_entire_op(OP_INV);
524 }
525 
526 int dcache_status(void)
527 {
528 	return dcache_enabled();
529 }
530 
531 void dcache_enable(void)
532 {
533 	if (!dcache_exists())
534 		return;
535 
536 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) &
537 		      ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE));
538 }
539 
540 void dcache_disable(void)
541 {
542 	if (!dcache_exists())
543 		return;
544 
545 	__dc_entire_op(OP_FLUSH_N_INV);
546 
547 	/*
548 	 * As SLC will be bypassed for data after L1 D$ disable we need to
549 	 * flush it first before L1 D$ disable. Also we invalidate SLC to
550 	 * avoid any inconsistent data problems after enabling L1 D$ again with
551 	 * dcache_enable function.
552 	 */
553 	if (is_isa_arcv2())
554 		__slc_entire_op(OP_FLUSH_N_INV);
555 
556 	write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
557 		      DC_CTRL_CACHE_DISABLE);
558 }
559 
560 /* Common Helper for Line Operations on D-cache */
561 static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz,
562 				      const int cacheop)
563 {
564 	unsigned int aux_cmd;
565 	int num_lines;
566 
567 	/* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
568 	aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL;
569 
570 	sz += paddr & ~CACHE_LINE_MASK;
571 	paddr &= CACHE_LINE_MASK;
572 
573 	num_lines = DIV_ROUND_UP(sz, gd->arch.l1_line_sz);
574 
575 	while (num_lines-- > 0) {
576 #if (CONFIG_ARC_MMU_VER == 3)
577 		write_aux_reg(ARC_AUX_DC_PTAG, paddr);
578 #endif
579 		write_aux_reg(aux_cmd, paddr);
580 		paddr += gd->arch.l1_line_sz;
581 	}
582 }
583 
584 static inlined_cachefunc void __before_dc_op(const int op)
585 {
586 	unsigned int ctrl;
587 
588 	ctrl = read_aux_reg(ARC_AUX_DC_CTRL);
589 
590 	/* IM bit implies flush-n-inv, instead of vanilla inv */
591 	if (op == OP_INV)
592 		ctrl &= ~DC_CTRL_INV_MODE_FLUSH;
593 	else
594 		ctrl |= DC_CTRL_INV_MODE_FLUSH;
595 
596 	write_aux_reg(ARC_AUX_DC_CTRL, ctrl);
597 }
598 
599 static inlined_cachefunc void __after_dc_op(const int op)
600 {
601 	if (op & OP_FLUSH)	/* flush / flush-n-inv both wait */
602 		while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
603 }
604 
605 static inlined_cachefunc void __dc_entire_op(const int cacheop)
606 {
607 	int aux;
608 
609 	if (!dcache_enabled())
610 		return;
611 
612 	__before_dc_op(cacheop);
613 
614 	if (cacheop & OP_INV)	/* Inv or flush-n-inv use same cmd reg */
615 		aux = ARC_AUX_DC_IVDC;
616 	else
617 		aux = ARC_AUX_DC_FLSH;
618 
619 	write_aux_reg(aux, 0x1);
620 
621 	__after_dc_op(cacheop);
622 }
623 
624 static inline void __dc_line_op(unsigned long paddr, unsigned long sz,
625 				const int cacheop)
626 {
627 	if (!dcache_enabled())
628 		return;
629 
630 	__before_dc_op(cacheop);
631 	__dcache_line_loop(paddr, sz, cacheop);
632 	__after_dc_op(cacheop);
633 }
634 
635 void invalidate_dcache_range(unsigned long start, unsigned long end)
636 {
637 	if (start >= end)
638 		return;
639 
640 	/*
641 	 * ARCv1                                 -> call __dc_line_op
642 	 * ARCv2 && L1 D$ disabled               -> nothing
643 	 * ARCv2 && L1 D$ enabled && IOC enabled -> nothing
644 	 * ARCv2 && L1 D$ enabled && no IOC      -> call __dc_line_op; call __slc_rgn_op
645 	 */
646 	if (!is_isa_arcv2() || !ioc_enabled())
647 		__dc_line_op(start, end - start, OP_INV);
648 
649 	if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass())
650 		__slc_rgn_op(start, end - start, OP_INV);
651 }
652 
653 void flush_dcache_range(unsigned long start, unsigned long end)
654 {
655 	if (start >= end)
656 		return;
657 
658 	/*
659 	 * ARCv1                                 -> call __dc_line_op
660 	 * ARCv2 && L1 D$ disabled               -> nothing
661 	 * ARCv2 && L1 D$ enabled && IOC enabled -> nothing
662 	 * ARCv2 && L1 D$ enabled && no IOC      -> call __dc_line_op; call __slc_rgn_op
663 	 */
664 	if (!is_isa_arcv2() || !ioc_enabled())
665 		__dc_line_op(start, end - start, OP_FLUSH);
666 
667 	if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass())
668 		__slc_rgn_op(start, end - start, OP_FLUSH);
669 }
670 
671 void flush_cache(unsigned long start, unsigned long size)
672 {
673 	flush_dcache_range(start, start + size);
674 }
675 
676 /*
677  * As invalidate_dcache_all() is not used in generic U-Boot code and as we
678  * don't need it in arch/arc code alone (invalidate without flush) we implement
679  * flush_n_invalidate_dcache_all (flush and invalidate in 1 operation) because
680  * it's much safer. See [ NOTE 1 ] for more details.
681  */
682 void flush_n_invalidate_dcache_all(void)
683 {
684 	__dc_entire_op(OP_FLUSH_N_INV);
685 
686 	if (is_isa_arcv2() && !slc_data_bypass())
687 		__slc_entire_op(OP_FLUSH_N_INV);
688 }
689 
690 void flush_dcache_all(void)
691 {
692 	__dc_entire_op(OP_FLUSH);
693 
694 	if (is_isa_arcv2() && !slc_data_bypass())
695 		__slc_entire_op(OP_FLUSH);
696 }
697 
698 /*
699  * This is function to cleanup all caches (and therefore sync I/D caches) which
700  * can be used for cleanup before linux launch or to sync caches during
701  * relocation.
702  */
703 void sync_n_cleanup_cache_all(void)
704 {
705 	__dc_entire_op(OP_FLUSH_N_INV);
706 
707 	/*
708 	 * If SL$ is bypassed for data it is used only for instructions,
709 	 * and we shouldn't flush it. So invalidate it instead of flush_n_inv.
710 	 */
711 	if (is_isa_arcv2()) {
712 		if (slc_data_bypass())
713 			__slc_entire_op(OP_INV);
714 		else
715 			__slc_entire_op(OP_FLUSH_N_INV);
716 	}
717 
718 	__ic_entire_invalidate();
719 }
720