xref: /rk3399_ARM-atf/lib/aarch64/cache_helpers.S (revision a078134e2305ca5695731bc275a5ca892cc38880)
1/*
2 * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <asm_macros.S>
9
10	.globl	flush_dcache_range
11	.globl	clean_dcache_range
12	.globl	inv_dcache_range
13	.globl	dcsw_op_louis
14	.globl	dcsw_op_all
15	.globl	dcsw_op_level1
16	.globl	dcsw_op_level2
17	.globl	dcsw_op_level3
18
19/*
20 * This macro can be used for implementing various data cache operations `op`
21 */
22.macro do_dcache_maintenance_by_mva op
23	/* Exit early if size is zero */
24	cbz	x1, exit_loop_\op
25	dcache_line_size x2, x3
26	add	x1, x0, x1
27	sub	x3, x2, #1
28	bic	x0, x0, x3
29loop_\op:
30	dc	\op, x0
31	add	x0, x0, x2
32	cmp	x0, x1
33	b.lo	loop_\op
34	dsb	sy
35exit_loop_\op:
36	ret
37.endm
38	/* ------------------------------------------
39	 * Clean+Invalidate from base address till
40	 * size. 'x0' = addr, 'x1' = size
41	 * ------------------------------------------
42	 */
43func flush_dcache_range
44	do_dcache_maintenance_by_mva civac
45endfunc flush_dcache_range
46
47	/* ------------------------------------------
48	 * Clean from base address till size.
49	 * 'x0' = addr, 'x1' = size
50	 * ------------------------------------------
51	 */
52func clean_dcache_range
53	do_dcache_maintenance_by_mva cvac
54endfunc clean_dcache_range
55
56	/* ------------------------------------------
57	 * Invalidate from base address till
58	 * size. 'x0' = addr, 'x1' = size
59	 * ------------------------------------------
60	 */
61func inv_dcache_range
62	do_dcache_maintenance_by_mva ivac
63endfunc inv_dcache_range
64
65
66	/* ---------------------------------------------------------------
67	 * Data cache operations by set/way to the level specified
68	 *
69	 * The main function, do_dcsw_op requires:
70	 * x0: The operation type (0-2), as defined in arch.h
71	 * x3: The last cache level to operate on
72	 * x9: clidr_el1
73	 * x10: The cache level to begin operation from
74	 * and will carry out the operation on each data cache from level 0
75	 * to the level in x3 in sequence
76	 *
77	 * The dcsw_op macro sets up the x3 and x9 parameters based on
78	 * clidr_el1 cache information before invoking the main function
79	 * ---------------------------------------------------------------
80	 */
81
82	.macro	dcsw_op shift, fw, ls
83	mrs	x9, clidr_el1
84	ubfx	x3, x9, \shift, \fw
85	lsl	x3, x3, \ls
86	mov	x10, xzr
87	b	do_dcsw_op
88	.endm
89
90func do_dcsw_op
91	cbz	x3, exit
92	mrs	x12, ID_AA64MMFR2_EL1	// stash FEAT_CCIDX identifier in x12
93	ubfx	x12, x12, #ID_AA64MMFR2_EL1_CCIDX_SHIFT, #ID_AA64MMFR2_EL1_CCIDX_LENGTH
94	adr	x14, dcsw_loop_table	// compute inner loop address
95	add	x14, x14, x0, lsl #5	// inner loop is 8x32-bit instructions
96#if ENABLE_BTI
97	add	x14, x14, x0, lsl #2	// inner loop is + "bti j" instruction
98#endif
99	mov	x0, x9
100	mov	w8, #1
101loop1:
102	add	x2, x10, x10, lsr #1	// work out 3x current cache level
103	lsr	x1, x0, x2		// extract cache type bits from clidr
104	and	x1, x1, #7		// mask the bits for current cache only
105	cmp	x1, #2			// see what cache we have at this level
106	b.lo	level_done		// nothing to do if no cache or icache
107
108	msr	csselr_el1, x10		// select current cache level in csselr
109	isb				// isb to sych the new cssr&csidr
110	mrs	x1, ccsidr_el1		// read the new ccsidr
111	and	x2, x1, #7		// extract the length of the cache lines
112	add	x2, x2, #4		// add 4 (line length offset)
113
114	cbz	x12, 1f			// check for FEAT_CCIDX for Associativity
115	ubfx	x4, x1, #3, #21 	// x4 = associativity CCSIDR_EL1[23:3]
116	b 	2f
1171:
118	ubfx	x4, x1, #3, #10 	// x4 = associativity CCSIDR_EL1[12:3]
1192:
120	clz	w5, w4			// bit position of way size increment
121	lsl	w9, w4, w5		// w9 = aligned max way number
122	lsl	w16, w8, w5		// w16 = way number loop decrement
123	orr	w9, w10, w9		// w9 = combine way and cache number
124
125	cbz	x12, 3f			// check for FEAT_CCIDX for NumSets
126	ubfx	x6, x1, #32, #24	// x6 (w6) = numsets CCSIDR_EL1[55:32]
127					// ISA will not allow x->w ubfx
128	b	4f
1293:
130	ubfx	w6, w1, #13, #15	// w6 = numsets CCSIDR_EL1[27:13]
1314:
132	lsl	w17, w8, w2		// w17 = set number loop decrement
133	dsb	sy			// barrier before we start this level
134	br	x14			// jump to DC operation specific loop
135
136	.macro	dcsw_loop _op
137#if ENABLE_BTI
138	bti	j
139#endif
140loop2_\_op:
141	lsl	w7, w6, w2		// w7 = aligned max set number
142
143loop3_\_op:
144	orr	w11, w9, w7		// combine cache, way and set number
145	dc	\_op, x11
146	subs	w7, w7, w17		// decrement set number
147	b.hs	loop3_\_op
148
149	subs	x9, x9, x16		// decrement way number
150	b.hs	loop2_\_op
151
152	b	level_done
153	.endm
154
155level_done:
156	add	x10, x10, #2		// increment cache number
157	cmp	x3, x10
158	b.hi	loop1
159	msr	csselr_el1, xzr		// select cache level 0 in csselr
160	dsb	sy			// barrier to complete final cache operation
161	isb
162exit:
163	ret
164endfunc do_dcsw_op
165
166dcsw_loop_table:
167	dcsw_loop isw
168	dcsw_loop cisw
169	dcsw_loop csw
170
171
172func dcsw_op_louis
173	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
174endfunc dcsw_op_louis
175
176
177func dcsw_op_all
178	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
179endfunc dcsw_op_all
180
181	/* ---------------------------------------------------------------
182	 *  Helper macro for data cache operations by set/way for the
183	 *  level specified
184	 * ---------------------------------------------------------------
185	 */
186	.macro dcsw_op_level level
187	mrs	x9, clidr_el1
188	mov	x3, \level
189	sub	x10, x3, #2
190	b	do_dcsw_op
191	.endm
192
193	/* ---------------------------------------------------------------
194	 * Data cache operations by set/way for level 1 cache
195	 *
196	 * The main function, do_dcsw_op requires:
197	 * x0: The operation type (0-2), as defined in arch.h
198	 * ---------------------------------------------------------------
199	 */
200func dcsw_op_level1
201	dcsw_op_level #(1 << LEVEL_SHIFT)
202endfunc dcsw_op_level1
203
204	/* ---------------------------------------------------------------
205	 * Data cache operations by set/way for level 2 cache
206	 *
207	 * The main function, do_dcsw_op requires:
208	 * x0: The operation type (0-2), as defined in arch.h
209	 * ---------------------------------------------------------------
210	 */
211func dcsw_op_level2
212	dcsw_op_level #(2 << LEVEL_SHIFT)
213endfunc dcsw_op_level2
214
215	/* ---------------------------------------------------------------
216	 * Data cache operations by set/way for level 3 cache
217	 *
218	 * The main function, do_dcsw_op requires:
219	 * x0: The operation type (0-2), as defined in arch.h
220	 * ---------------------------------------------------------------
221	 */
222func dcsw_op_level3
223	dcsw_op_level #(3 << LEVEL_SHIFT)
224endfunc dcsw_op_level3
225