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