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