xref: /rk3399_ARM-atf/lib/aarch64/cache_helpers.S (revision 62d64652134ca1d3ea68da65ea9e4ae136f6c44e)
14ecca339SDan Handley/*
26a00e9b0SRobert Wakim * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
34ecca339SDan Handley *
482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
54ecca339SDan Handley */
64ecca339SDan Handley
797043ac9SDan Handley#include <arch.h>
84ecca339SDan Handley#include <asm_macros.S>
94ecca339SDan Handley
104ecca339SDan Handley	.globl	flush_dcache_range
116a00e9b0SRobert Wakim	.globl	flush_dcache_to_popa_range
12*62d64652SOlivier Deprez	.globl	flush_dcache_to_popa_range_mte2
1354dc71e7SAchin Gupta	.globl	clean_dcache_range
144ecca339SDan Handley	.globl	inv_dcache_range
154ecca339SDan Handley	.globl	dcsw_op_louis
164ecca339SDan Handley	.globl	dcsw_op_all
178e857916SSoby Mathew	.globl	dcsw_op_level1
188e857916SSoby Mathew	.globl	dcsw_op_level2
198e857916SSoby Mathew	.globl	dcsw_op_level3
204ecca339SDan Handley
21*62d64652SOlivier Deprez/* Opcodes for data cache maintenance by PA instructions. */
22*62d64652SOlivier Deprez
23*62d64652SOlivier Deprez/*
24*62d64652SOlivier Deprez * sys  #6, c7, c14, #1, x0
25*62d64652SOlivier Deprez * DC CIPAPA, X0
26*62d64652SOlivier Deprez */
27*62d64652SOlivier Deprez#define dc_cipapa_x0	0xd50e7e20
28*62d64652SOlivier Deprez
29*62d64652SOlivier Deprez/*
30*62d64652SOlivier Deprez * sys #6, c7, c14, #3, x0
31*62d64652SOlivier Deprez * DC CIDGPAPA, X0
32*62d64652SOlivier Deprez  */
33*62d64652SOlivier Deprez#define dc_cigdpapa_x0	0xd50e7ea0
34*62d64652SOlivier Deprez
3554dc71e7SAchin Gupta/*
3654dc71e7SAchin Gupta * This macro can be used for implementing various data cache operations `op`
3754dc71e7SAchin Gupta */
3854dc71e7SAchin Gupta.macro do_dcache_maintenance_by_mva op
393ec5204cSSoby Mathew	/* Exit early if size is zero */
403ec5204cSSoby Mathew	cbz	x1, exit_loop_\op
4154dc71e7SAchin Gupta	dcache_line_size x2, x3
4254dc71e7SAchin Gupta	add	x1, x0, x1
4354dc71e7SAchin Gupta	sub	x3, x2, #1
4454dc71e7SAchin Gupta	bic	x0, x0, x3
4554dc71e7SAchin Guptaloop_\op:
4654dc71e7SAchin Gupta	dc	\op, x0
4754dc71e7SAchin Gupta	add	x0, x0, x2
4854dc71e7SAchin Gupta	cmp	x0, x1
4954dc71e7SAchin Gupta	b.lo	loop_\op
5054dc71e7SAchin Gupta	dsb	sy
513ec5204cSSoby Mathewexit_loop_\op:
5254dc71e7SAchin Gupta	ret
5354dc71e7SAchin Gupta.endm
5404c7303bSOkash Khawaja
55*62d64652SOlivier Deprez/* op: the hexadecimal instruction opcode for the cache operation */
56*62d64652SOlivier Deprez.macro do_dcache_maintenance_instr op
57*62d64652SOlivier Deprez	/* Exit early if size is zero */
58*62d64652SOlivier Deprez	cbz	x1, exit_loop_\op
59*62d64652SOlivier Deprez	dcache_line_size x2, x3
60*62d64652SOlivier Deprez	sub	x3, x2, #1
61*62d64652SOlivier Deprez	bic	x0, x0, x3
62*62d64652SOlivier Deprez	add	x1, x1, x0
63*62d64652SOlivier Deprezloop_\op:
64*62d64652SOlivier Deprez	.inst	\op
65*62d64652SOlivier Deprez	add	x0, x0, x2
66*62d64652SOlivier Deprez	cmp	x0, x1
67*62d64652SOlivier Deprez	b.lo	loop_\op
68*62d64652SOlivier Deprez	dsb	osh
69*62d64652SOlivier Deprezexit_loop_\op:
70*62d64652SOlivier Deprez	ret
71*62d64652SOlivier Deprez.endm
72*62d64652SOlivier Deprez
7304c7303bSOkash Khawaja.macro check_plat_can_cmo
7404c7303bSOkash Khawaja#if CONDITIONAL_CMO
7504c7303bSOkash Khawaja	mov	x3, x30
7604c7303bSOkash Khawaja	mov	x2, x0
7704c7303bSOkash Khawaja	bl	plat_can_cmo
7804c7303bSOkash Khawaja	mov	x30, x3
7904c7303bSOkash Khawaja	cbnz	x0, 1f
8004c7303bSOkash Khawaja	ret
8104c7303bSOkash Khawaja1:
8204c7303bSOkash Khawaja	mov	 x0, x2
8304c7303bSOkash Khawaja#endif
8404c7303bSOkash Khawaja.endm
85*62d64652SOlivier Deprez
86*62d64652SOlivier Deprez	/* -------------------------------------------
87*62d64652SOlivier Deprez	 * DCache Clean+Invalidate by MVA from base
88*62d64652SOlivier Deprez	 * address till size. 'x0' = addr, 'x1' = size
89*62d64652SOlivier Deprez	 * -------------------------------------------
904ecca339SDan Handley	 */
914ecca339SDan Handleyfunc flush_dcache_range
9204c7303bSOkash Khawaja	check_plat_can_cmo
9354dc71e7SAchin Gupta	do_dcache_maintenance_by_mva civac
948b779620SKévin Petitendfunc flush_dcache_range
954ecca339SDan Handley
9654dc71e7SAchin Gupta	/* ------------------------------------------
97*62d64652SOlivier Deprez	 * DCache Clean by MVA from base address till
98*62d64652SOlivier Deprez	 * size. 'x0' = addr, 'x1' = size
9954dc71e7SAchin Gupta	 * ------------------------------------------
10054dc71e7SAchin Gupta	 */
10154dc71e7SAchin Guptafunc clean_dcache_range
10204c7303bSOkash Khawaja	check_plat_can_cmo
10354dc71e7SAchin Gupta	do_dcache_maintenance_by_mva cvac
10454dc71e7SAchin Guptaendfunc clean_dcache_range
1054ecca339SDan Handley
1064ecca339SDan Handley	/* ------------------------------------------
107*62d64652SOlivier Deprez	 * DCache Invalidate by MVA from base address
108*62d64652SOlivier Deprez	 * till size. 'x0' = addr, 'x1' = size
1094ecca339SDan Handley	 * ------------------------------------------
1104ecca339SDan Handley	 */
1114ecca339SDan Handleyfunc inv_dcache_range
11204c7303bSOkash Khawaja	check_plat_can_cmo
11354dc71e7SAchin Gupta	do_dcache_maintenance_by_mva ivac
1148b779620SKévin Petitendfunc inv_dcache_range
1154ecca339SDan Handley
1166a00e9b0SRobert Wakim	/*
1176a00e9b0SRobert Wakim	 * ------------------------------------------
118*62d64652SOlivier Deprez	 * DCache Clean+Invalidate by PA to POPA from
119*62d64652SOlivier Deprez	 * base address till size.
1206a00e9b0SRobert Wakim	 * 'x0' = addr, 'x1' = size
1216a00e9b0SRobert Wakim	 * ------------------------------------------
1226a00e9b0SRobert Wakim	 */
1236a00e9b0SRobert Wakimfunc flush_dcache_to_popa_range
12404c7303bSOkash Khawaja	check_plat_can_cmo
125*62d64652SOlivier Deprez	/* dc cipapa, x0 */
126*62d64652SOlivier Deprez	do_dcache_maintenance_instr dc_cipapa_x0
1276a00e9b0SRobert Wakimendfunc	flush_dcache_to_popa_range
1286a00e9b0SRobert Wakim
129*62d64652SOlivier Deprez	/*
130*62d64652SOlivier Deprez	 * ------------------------------------------
131*62d64652SOlivier Deprez	 * Clean+Invalidate by PA to POPA (MTE2)
132*62d64652SOlivier Deprez	 * from base address till size.
133*62d64652SOlivier Deprez	 * 'x0' = addr, 'x1' = size
134*62d64652SOlivier Deprez	 * ------------------------------------------
135*62d64652SOlivier Deprez	 * On implementations with FEAT_MTE2, Root firmware must issue
136*62d64652SOlivier Deprez	 * DC_CIGDPAPA instead of DC_CIPAPA, in order to additionally
137*62d64652SOlivier Deprez	 * clean and invalidate Allocation Tags associated with the
138*62d64652SOlivier Deprez	 * affected locations.
139*62d64652SOlivier Deprez	 */
140*62d64652SOlivier Deprezfunc flush_dcache_to_popa_range_mte2
141*62d64652SOlivier Deprez	check_plat_can_cmo
142*62d64652SOlivier Deprez	/* dc cigdpapa, x0 */
143*62d64652SOlivier Deprez	do_dcache_maintenance_instr dc_cigdpapa_x0
144*62d64652SOlivier Deprezendfunc	flush_dcache_to_popa_range_mte2
145*62d64652SOlivier Deprez
1465f6032a8SAndrew Thoelke	/* ---------------------------------------------------------------
1475f6032a8SAndrew Thoelke	 * Data cache operations by set/way to the level specified
1485f6032a8SAndrew Thoelke	 *
1495f6032a8SAndrew Thoelke	 * The main function, do_dcsw_op requires:
1505f6032a8SAndrew Thoelke	 * x0: The operation type (0-2), as defined in arch.h
1515f6032a8SAndrew Thoelke	 * x3: The last cache level to operate on
1525f6032a8SAndrew Thoelke	 * x9: clidr_el1
1538e857916SSoby Mathew	 * x10: The cache level to begin operation from
1545f6032a8SAndrew Thoelke	 * and will carry out the operation on each data cache from level 0
1555f6032a8SAndrew Thoelke	 * to the level in x3 in sequence
1565f6032a8SAndrew Thoelke	 *
1575f6032a8SAndrew Thoelke	 * The dcsw_op macro sets up the x3 and x9 parameters based on
1585f6032a8SAndrew Thoelke	 * clidr_el1 cache information before invoking the main function
1595f6032a8SAndrew Thoelke	 * ---------------------------------------------------------------
1604ecca339SDan Handley	 */
1615f6032a8SAndrew Thoelke
1625f6032a8SAndrew Thoelke	.macro	dcsw_op shift, fw, ls
1635f6032a8SAndrew Thoelke	mrs	x9, clidr_el1
1645f6032a8SAndrew Thoelke	ubfx	x3, x9, \shift, \fw
1655f6032a8SAndrew Thoelke	lsl	x3, x3, \ls
1668e857916SSoby Mathew	mov	x10, xzr
1675f6032a8SAndrew Thoelke	b	do_dcsw_op
1685f6032a8SAndrew Thoelke	.endm
1695f6032a8SAndrew Thoelke
1705f6032a8SAndrew Thoelkefunc do_dcsw_op
1715f6032a8SAndrew Thoelke	cbz	x3, exit
172d0ec1cc4Sjohpow01	mrs	x12, ID_AA64MMFR2_EL1	// stash FEAT_CCIDX identifier in x12
173d0ec1cc4Sjohpow01	ubfx	x12, x12, #ID_AA64MMFR2_EL1_CCIDX_SHIFT, #ID_AA64MMFR2_EL1_CCIDX_LENGTH
1745f6032a8SAndrew Thoelke	adr	x14, dcsw_loop_table	// compute inner loop address
1755f6032a8SAndrew Thoelke	add	x14, x14, x0, lsl #5	// inner loop is 8x32-bit instructions
1769fc59639SAlexei Fedorov#if ENABLE_BTI
1779fc59639SAlexei Fedorov	add	x14, x14, x0, lsl #2	// inner loop is + "bti j" instruction
1789fc59639SAlexei Fedorov#endif
1795f6032a8SAndrew Thoelke	mov	x0, x9
1805f6032a8SAndrew Thoelke	mov	w8, #1
1815f6032a8SAndrew Thoelkeloop1:
1824ecca339SDan Handley	add	x2, x10, x10, lsr #1	// work out 3x current cache level
1834ecca339SDan Handley	lsr	x1, x0, x2		// extract cache type bits from clidr
1845f6032a8SAndrew Thoelke	and	x1, x1, #7		// mask the bits for current cache only
1854ecca339SDan Handley	cmp	x1, #2			// see what cache we have at this level
186355a5d03SDouglas Raillard	b.lo	level_done		// nothing to do if no cache or icache
1875f6032a8SAndrew Thoelke
1884ecca339SDan Handley	msr	csselr_el1, x10		// select current cache level in csselr
1894ecca339SDan Handley	isb				// isb to sych the new cssr&csidr
1904ecca339SDan Handley	mrs	x1, ccsidr_el1		// read the new ccsidr
1914ecca339SDan Handley	and	x2, x1, #7		// extract the length of the cache lines
1924ecca339SDan Handley	add	x2, x2, #4		// add 4 (line length offset)
193d0ec1cc4Sjohpow01
194d0ec1cc4Sjohpow01	cbz	x12, 1f			// check for FEAT_CCIDX for Associativity
195d0ec1cc4Sjohpow01	ubfx	x4, x1, #3, #21 	// x4 = associativity CCSIDR_EL1[23:3]
196d0ec1cc4Sjohpow01	b 	2f
197d0ec1cc4Sjohpow011:
198d0ec1cc4Sjohpow01	ubfx	x4, x1, #3, #10 	// x4 = associativity CCSIDR_EL1[12:3]
199d0ec1cc4Sjohpow012:
2005f6032a8SAndrew Thoelke	clz	w5, w4			// bit position of way size increment
2015f6032a8SAndrew Thoelke	lsl	w9, w4, w5		// w9 = aligned max way number
2025f6032a8SAndrew Thoelke	lsl	w16, w8, w5		// w16 = way number loop decrement
2035f6032a8SAndrew Thoelke	orr	w9, w10, w9		// w9 = combine way and cache number
204d0ec1cc4Sjohpow01
205d0ec1cc4Sjohpow01	cbz	x12, 3f			// check for FEAT_CCIDX for NumSets
206d0ec1cc4Sjohpow01	ubfx	x6, x1, #32, #24	// x6 (w6) = numsets CCSIDR_EL1[55:32]
207d0ec1cc4Sjohpow01					// ISA will not allow x->w ubfx
208d0ec1cc4Sjohpow01	b	4f
209d0ec1cc4Sjohpow013:
210d0ec1cc4Sjohpow01	ubfx	w6, w1, #13, #15	// w6 = numsets CCSIDR_EL1[27:13]
211d0ec1cc4Sjohpow014:
2125f6032a8SAndrew Thoelke	lsl	w17, w8, w2		// w17 = set number loop decrement
2135f6032a8SAndrew Thoelke	dsb	sy			// barrier before we start this level
2145f6032a8SAndrew Thoelke	br	x14			// jump to DC operation specific loop
2155f6032a8SAndrew Thoelke
2165f6032a8SAndrew Thoelke	.macro	dcsw_loop _op
2179fc59639SAlexei Fedorov#if ENABLE_BTI
2189fc59639SAlexei Fedorov	bti	j
2199fc59639SAlexei Fedorov#endif
2205f6032a8SAndrew Thoelkeloop2_\_op:
2215f6032a8SAndrew Thoelke	lsl	w7, w6, w2		// w7 = aligned max set number
2225f6032a8SAndrew Thoelke
2235f6032a8SAndrew Thoelkeloop3_\_op:
2245f6032a8SAndrew Thoelke	orr	w11, w9, w7		// combine cache, way and set number
2255f6032a8SAndrew Thoelke	dc	\_op, x11
2265f6032a8SAndrew Thoelke	subs	w7, w7, w17		// decrement set number
227355a5d03SDouglas Raillard	b.hs	loop3_\_op
2285f6032a8SAndrew Thoelke
2295f6032a8SAndrew Thoelke	subs	x9, x9, x16		// decrement way number
230355a5d03SDouglas Raillard	b.hs	loop2_\_op
2315f6032a8SAndrew Thoelke
2325f6032a8SAndrew Thoelke	b	level_done
2335f6032a8SAndrew Thoelke	.endm
2345f6032a8SAndrew Thoelke
2355f6032a8SAndrew Thoelkelevel_done:
2364ecca339SDan Handley	add	x10, x10, #2		// increment cache number
2374ecca339SDan Handley	cmp	x3, x10
238355a5d03SDouglas Raillard	b.hi	loop1
2395f6032a8SAndrew Thoelke	msr	csselr_el1, xzr		// select cache level 0 in csselr
2405f6032a8SAndrew Thoelke	dsb	sy			// barrier to complete final cache operation
2414ecca339SDan Handley	isb
2424ecca339SDan Handleyexit:
2434ecca339SDan Handley	ret
2448b779620SKévin Petitendfunc do_dcsw_op
2454ecca339SDan Handley
2465f6032a8SAndrew Thoelkedcsw_loop_table:
2475f6032a8SAndrew Thoelke	dcsw_loop isw
2485f6032a8SAndrew Thoelke	dcsw_loop cisw
2495f6032a8SAndrew Thoelke	dcsw_loop csw
2505f6032a8SAndrew Thoelke
2514ecca339SDan Handley
2524ecca339SDan Handleyfunc dcsw_op_louis
253a2e01234SOkash Khawaja	check_plat_can_cmo
2545f6032a8SAndrew Thoelke	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
2558b779620SKévin Petitendfunc dcsw_op_louis
2564ecca339SDan Handley
2574ecca339SDan Handley
2584ecca339SDan Handleyfunc dcsw_op_all
25904c7303bSOkash Khawaja	check_plat_can_cmo
2605f6032a8SAndrew Thoelke	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
2618b779620SKévin Petitendfunc dcsw_op_all
2628e857916SSoby Mathew
2638e857916SSoby Mathew	/* ---------------------------------------------------------------
2648e857916SSoby Mathew	 *  Helper macro for data cache operations by set/way for the
2658e857916SSoby Mathew	 *  level specified
2668e857916SSoby Mathew	 * ---------------------------------------------------------------
2678e857916SSoby Mathew	 */
2688e857916SSoby Mathew	.macro dcsw_op_level level
2698e857916SSoby Mathew	mrs	x9, clidr_el1
2708e857916SSoby Mathew	mov	x3, \level
2718e857916SSoby Mathew	sub	x10, x3, #2
2728e857916SSoby Mathew	b	do_dcsw_op
2738e857916SSoby Mathew	.endm
2748e857916SSoby Mathew
2758e857916SSoby Mathew	/* ---------------------------------------------------------------
2768e857916SSoby Mathew	 * Data cache operations by set/way for level 1 cache
2778e857916SSoby Mathew	 *
2788e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2798e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2808e857916SSoby Mathew	 * ---------------------------------------------------------------
2818e857916SSoby Mathew	 */
2828e857916SSoby Mathewfunc dcsw_op_level1
28304c7303bSOkash Khawaja	check_plat_can_cmo
2848e857916SSoby Mathew	dcsw_op_level #(1 << LEVEL_SHIFT)
2858b779620SKévin Petitendfunc dcsw_op_level1
2868e857916SSoby Mathew
2878e857916SSoby Mathew	/* ---------------------------------------------------------------
2888e857916SSoby Mathew	 * Data cache operations by set/way for level 2 cache
2898e857916SSoby Mathew	 *
2908e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2918e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2928e857916SSoby Mathew	 * ---------------------------------------------------------------
2938e857916SSoby Mathew	 */
2948e857916SSoby Mathewfunc dcsw_op_level2
29504c7303bSOkash Khawaja	check_plat_can_cmo
2968e857916SSoby Mathew	dcsw_op_level #(2 << LEVEL_SHIFT)
2978b779620SKévin Petitendfunc dcsw_op_level2
2988e857916SSoby Mathew
2998e857916SSoby Mathew	/* ---------------------------------------------------------------
3008e857916SSoby Mathew	 * Data cache operations by set/way for level 3 cache
3018e857916SSoby Mathew	 *
3028e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
3038e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
3048e857916SSoby Mathew	 * ---------------------------------------------------------------
3058e857916SSoby Mathew	 */
3068e857916SSoby Mathewfunc dcsw_op_level3
30704c7303bSOkash Khawaja	check_plat_can_cmo
3088e857916SSoby Mathew	dcsw_op_level #(3 << LEVEL_SHIFT)
3098b779620SKévin Petitendfunc dcsw_op_level3
310