xref: /rk3399_ARM-atf/lib/aarch32/cache_helpers.S (revision e1d24114a6ca11d4896986202c2467fca5a4e62a)
1f24307deSSoby Mathew/*
2*d0ec1cc4Sjohpow01 * Copyright (c) 2016-2021, Arm Limited and Contributors. All rights reserved.
3f24307deSSoby Mathew *
482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
5f24307deSSoby Mathew */
6f24307deSSoby Mathew
7f24307deSSoby Mathew#include <arch.h>
8f24307deSSoby Mathew#include <asm_macros.S>
9f24307deSSoby Mathew
10f24307deSSoby Mathew	.globl	flush_dcache_range
11f24307deSSoby Mathew	.globl	clean_dcache_range
12f24307deSSoby Mathew	.globl	inv_dcache_range
13f24307deSSoby Mathew	.globl	dcsw_op_louis
14f24307deSSoby Mathew	.globl	dcsw_op_all
15f24307deSSoby Mathew	.globl	dcsw_op_level1
16f24307deSSoby Mathew	.globl	dcsw_op_level2
17f24307deSSoby Mathew	.globl	dcsw_op_level3
18f24307deSSoby Mathew
19f24307deSSoby Mathew/*
20f24307deSSoby Mathew * This macro can be used for implementing various data cache operations `op`
21f24307deSSoby Mathew */
22f24307deSSoby Mathew.macro do_dcache_maintenance_by_mva op, coproc, opc1, CRn, CRm, opc2
233ec5204cSSoby Mathew	/* Exit early if size is zero */
243ec5204cSSoby Mathew	cmp	r1, #0
253ec5204cSSoby Mathew	beq	exit_loop_\op
26f24307deSSoby Mathew	dcache_line_size r2, r3
27f24307deSSoby Mathew	add	r1, r0, r1
28f24307deSSoby Mathew	sub	r3, r2, #1
29f24307deSSoby Mathew	bic	r0, r0, r3
30f24307deSSoby Mathewloop_\op:
31f24307deSSoby Mathew	stcopr	r0, \coproc, \opc1, \CRn, \CRm, \opc2
32f24307deSSoby Mathew	add	r0, r0, r2
33f24307deSSoby Mathew	cmp	r0, r1
34f24307deSSoby Mathew	blo	loop_\op
35f24307deSSoby Mathew	dsb	sy
363ec5204cSSoby Mathewexit_loop_\op:
37f24307deSSoby Mathew	bx	lr
38f24307deSSoby Mathew.endm
39f24307deSSoby Mathew
40f24307deSSoby Mathew	/* ------------------------------------------
41f24307deSSoby Mathew	 * Clean+Invalidate from base address till
42f24307deSSoby Mathew	 * size. 'r0' = addr, 'r1' = size
43f24307deSSoby Mathew	 * ------------------------------------------
44f24307deSSoby Mathew	 */
45f24307deSSoby Mathewfunc flush_dcache_range
46f24307deSSoby Mathew	do_dcache_maintenance_by_mva cimvac, DCCIMVAC
47f24307deSSoby Mathewendfunc flush_dcache_range
48f24307deSSoby Mathew
49f24307deSSoby Mathew	/* ------------------------------------------
50f24307deSSoby Mathew	 * Clean from base address till size.
51f24307deSSoby Mathew	 * 'r0' = addr, 'r1' = size
52f24307deSSoby Mathew	 * ------------------------------------------
53f24307deSSoby Mathew	 */
54f24307deSSoby Mathewfunc clean_dcache_range
55f24307deSSoby Mathew	do_dcache_maintenance_by_mva cmvac, DCCMVAC
56f24307deSSoby Mathewendfunc clean_dcache_range
57f24307deSSoby Mathew
58f24307deSSoby Mathew	/* ------------------------------------------
59f24307deSSoby Mathew	 * Invalidate from base address till
60f24307deSSoby Mathew	 * size. 'r0' = addr, 'r1' = size
61f24307deSSoby Mathew	 * ------------------------------------------
62f24307deSSoby Mathew	 */
63f24307deSSoby Mathewfunc inv_dcache_range
64f24307deSSoby Mathew	do_dcache_maintenance_by_mva imvac, DCIMVAC
65f24307deSSoby Mathewendfunc inv_dcache_range
66f24307deSSoby Mathew
67f24307deSSoby Mathew	/* ----------------------------------------------------------------
68f24307deSSoby Mathew	 * Data cache operations by set/way to the level specified
69f24307deSSoby Mathew	 *
70f24307deSSoby Mathew	 * The main function, do_dcsw_op requires:
71f24307deSSoby Mathew	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
72f24307deSSoby Mathew	 * as defined in arch.h
73f24307deSSoby Mathew	 * r1: The cache level to begin operation from
74f24307deSSoby Mathew	 * r2: clidr_el1
75f24307deSSoby Mathew	 * r3: The last cache level to operate on
76f24307deSSoby Mathew	 * and will carry out the operation on each data cache from level 0
77f24307deSSoby Mathew	 * to the level in r3 in sequence
78f24307deSSoby Mathew	 *
79f24307deSSoby Mathew	 * The dcsw_op macro sets up the r2 and r3 parameters based on
80f24307deSSoby Mathew	 * clidr_el1 cache information before invoking the main function
81f24307deSSoby Mathew	 * ----------------------------------------------------------------
82f24307deSSoby Mathew	 */
83f24307deSSoby Mathew
84f24307deSSoby Mathew	.macro	dcsw_op shift, fw, ls
85f24307deSSoby Mathew	ldcopr	r2, CLIDR
86f24307deSSoby Mathew	ubfx	r3, r2, \shift, \fw
87f24307deSSoby Mathew	lsl	r3, r3, \ls
88f24307deSSoby Mathew	mov	r1, #0
89f24307deSSoby Mathew	b	do_dcsw_op
90f24307deSSoby Mathew	.endm
91f24307deSSoby Mathew
92f24307deSSoby Mathewfunc do_dcsw_op
93f24307deSSoby Mathew	push	{r4-r12, lr}
94*d0ec1cc4Sjohpow01	ldcopr	r8, ID_MMFR4		// stash FEAT_CCIDX identifier in r8
95*d0ec1cc4Sjohpow01	ubfx	r8, r8, #ID_MMFR4_CCIDX_SHIFT, #ID_MMFR4_CCIDX_LENGTH
96f24307deSSoby Mathew	adr	r11, dcsw_loop_table	// compute cache op based on the operation type
97f24307deSSoby Mathew	add	r6, r11, r0, lsl #3	// cache op is 2x32-bit instructions
98f24307deSSoby Mathewloop1:
99f24307deSSoby Mathew	add	r10, r1, r1, LSR #1	// Work out 3x current cache level
100f24307deSSoby Mathew	mov	r12, r2, LSR r10	// extract cache type bits from clidr
101f24307deSSoby Mathew	and	r12, r12, #7		// mask the bits for current cache only
102f24307deSSoby Mathew	cmp	r12, #2			// see what cache we have at this level
103355a5d03SDouglas Raillard	blo	level_done		// no cache or only instruction cache at this level
104f24307deSSoby Mathew
105f24307deSSoby Mathew	stcopr	r1, CSSELR		// select current cache level in csselr
106f24307deSSoby Mathew	isb				// isb to sych the new cssr&csidr
107f24307deSSoby Mathew	ldcopr	r12, CCSIDR		// read the new ccsidr
108f24307deSSoby Mathew	and	r10, r12, #7		// extract the length of the cache lines
109f24307deSSoby Mathew	add	r10, r10, #4		// add 4 (r10 = line length offset)
110*d0ec1cc4Sjohpow01
111*d0ec1cc4Sjohpow01	cmp	r8, #0			// check for FEAT_CCIDX for Associativity
112*d0ec1cc4Sjohpow01	beq	1f
113*d0ec1cc4Sjohpow01	ubfx	r4, r12, #3, #21 	// r4 = associativity CCSIDR[23:3]
114*d0ec1cc4Sjohpow01	b	2f
115*d0ec1cc4Sjohpow011:
116*d0ec1cc4Sjohpow01	ubfx	r4, r12, #3, #10 	// r4 = associativity CCSIDR[12:3]
117*d0ec1cc4Sjohpow012:
118f24307deSSoby Mathew	clz	r5, r4			// r5 = the bit position of the way size increment
119f24307deSSoby Mathew	mov	r9, r4			// r9 working copy of the aligned max way number
120f24307deSSoby Mathew
121f24307deSSoby Mathewloop2:
122*d0ec1cc4Sjohpow01	cmp	r8, #0			// check for FEAT_CCIDX for NumSets
123*d0ec1cc4Sjohpow01	beq	3f
124*d0ec1cc4Sjohpow01	ldcopr	r12, CCSIDR2		// FEAT_CCIDX numsets is in CCSIDR2
125*d0ec1cc4Sjohpow01	ubfx	r7, r12, #0, #24	// r7 = numsets CCSIDR2[23:0]
126*d0ec1cc4Sjohpow01	b	loop3
127*d0ec1cc4Sjohpow013:
128*d0ec1cc4Sjohpow01	ubfx	r7, r12, #13, #15	// r7 = numsets CCSIDR[27:13]
129f24307deSSoby Mathewloop3:
130f24307deSSoby Mathew	orr	r0, r1, r9, LSL r5	// factor in the way number and cache level into r0
131f24307deSSoby Mathew	orr	r0, r0, r7, LSL r10	// factor in the set number
132f24307deSSoby Mathew
133f24307deSSoby Mathew	blx	r6
134f24307deSSoby Mathew	subs	r7, r7, #1		// decrement the set number
135355a5d03SDouglas Raillard	bhs	loop3
136f24307deSSoby Mathew	subs	r9, r9, #1		// decrement the way number
137355a5d03SDouglas Raillard	bhs	loop2
138f24307deSSoby Mathewlevel_done:
139f24307deSSoby Mathew	add	r1, r1, #2		// increment the cache number
140f24307deSSoby Mathew	cmp	r3, r1
141f999facaSJoel Hutton	// Ensure completion of previous cache maintenance instruction. Note
142f999facaSJoel Hutton	// this also mitigates erratum 814220 on Cortex-A7
143f999facaSJoel Hutton	dsb	sy
144355a5d03SDouglas Raillard	bhi	loop1
145f24307deSSoby Mathew
146f24307deSSoby Mathew	mov	r6, #0
147f24307deSSoby Mathew	stcopr	r6, CSSELR		//select cache level 0 in csselr
148f24307deSSoby Mathew	dsb	sy
149f24307deSSoby Mathew	isb
150f24307deSSoby Mathew	pop	{r4-r12, pc}
151f24307deSSoby Mathew
152f24307deSSoby Mathewdcsw_loop_table:
153f24307deSSoby Mathew	stcopr	r0, DCISW
154f24307deSSoby Mathew	bx	lr
155f24307deSSoby Mathew	stcopr	r0, DCCISW
156f24307deSSoby Mathew	bx	lr
157f24307deSSoby Mathew	stcopr	r0, DCCSW
158f24307deSSoby Mathew	bx	lr
159f24307deSSoby Mathew
160f24307deSSoby Mathewendfunc do_dcsw_op
161f24307deSSoby Mathew
162f24307deSSoby Mathew	/* ---------------------------------------------------------------
163f24307deSSoby Mathew	 * Data cache operations by set/way till PoU.
164f24307deSSoby Mathew	 *
165f24307deSSoby Mathew	 * The function requires :
166f24307deSSoby Mathew	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
167f24307deSSoby Mathew	 * as defined in arch.h
168f24307deSSoby Mathew	 * ---------------------------------------------------------------
169f24307deSSoby Mathew	 */
170f24307deSSoby Mathewfunc dcsw_op_louis
171f24307deSSoby Mathew	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
172f24307deSSoby Mathewendfunc	dcsw_op_louis
173f24307deSSoby Mathew
174f24307deSSoby Mathew	/* ---------------------------------------------------------------
175f24307deSSoby Mathew	 * Data cache operations by set/way till PoC.
176f24307deSSoby Mathew	 *
177f24307deSSoby Mathew	 * The function requires :
178f24307deSSoby Mathew	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
179f24307deSSoby Mathew	 * as defined in arch.h
180f24307deSSoby Mathew	 * ---------------------------------------------------------------
181f24307deSSoby Mathew	 */
182f24307deSSoby Mathewfunc dcsw_op_all
183f24307deSSoby Mathew	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
184f24307deSSoby Mathewendfunc	dcsw_op_all
185f24307deSSoby Mathew
186f24307deSSoby Mathew
187f24307deSSoby Mathew	/* ---------------------------------------------------------------
188f24307deSSoby Mathew	 *  Helper macro for data cache operations by set/way for the
189f24307deSSoby Mathew	 *  level specified
190f24307deSSoby Mathew	 * ---------------------------------------------------------------
191f24307deSSoby Mathew	 */
192f24307deSSoby Mathew	.macro	dcsw_op_level level
193f24307deSSoby Mathew	ldcopr	r2, CLIDR
194f24307deSSoby Mathew	mov	r3, \level
195f24307deSSoby Mathew	sub	r1, r3, #2
196f24307deSSoby Mathew	b	do_dcsw_op
197f24307deSSoby Mathew	.endm
198f24307deSSoby Mathew
199f24307deSSoby Mathew	/* ---------------------------------------------------------------
200f24307deSSoby Mathew	 * Data cache operations by set/way for level 1 cache
201f24307deSSoby Mathew	 *
202f24307deSSoby Mathew	 * The main function, do_dcsw_op requires:
203f24307deSSoby Mathew	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
204f24307deSSoby Mathew	 * as defined in arch.h
205f24307deSSoby Mathew	 * ---------------------------------------------------------------
206f24307deSSoby Mathew	 */
207f24307deSSoby Mathewfunc dcsw_op_level1
208f24307deSSoby Mathew	dcsw_op_level #(1 << LEVEL_SHIFT)
209f24307deSSoby Mathewendfunc dcsw_op_level1
210f24307deSSoby Mathew
211f24307deSSoby Mathew	/* ---------------------------------------------------------------
212f24307deSSoby Mathew	 * Data cache operations by set/way for level 2 cache
213f24307deSSoby Mathew	 *
214f24307deSSoby Mathew	 * The main function, do_dcsw_op requires:
215f24307deSSoby Mathew	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
216f24307deSSoby Mathew	 * as defined in arch.h
217f24307deSSoby Mathew	 * ---------------------------------------------------------------
218f24307deSSoby Mathew	 */
219f24307deSSoby Mathewfunc dcsw_op_level2
220f24307deSSoby Mathew	dcsw_op_level #(2 << LEVEL_SHIFT)
221f24307deSSoby Mathewendfunc dcsw_op_level2
222f24307deSSoby Mathew
223f24307deSSoby Mathew	/* ---------------------------------------------------------------
224f24307deSSoby Mathew	 * Data cache operations by set/way for level 3 cache
225f24307deSSoby Mathew	 *
226f24307deSSoby Mathew	 * The main function, do_dcsw_op requires:
227f24307deSSoby Mathew	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
228f24307deSSoby Mathew	 * as defined in arch.h
229f24307deSSoby Mathew	 * ---------------------------------------------------------------
230f24307deSSoby Mathew	 */
231f24307deSSoby Mathewfunc dcsw_op_level3
232f24307deSSoby Mathew	dcsw_op_level #(3 << LEVEL_SHIFT)
233f24307deSSoby Mathewendfunc dcsw_op_level3
234