xref: /rk3399_ARM-atf/lib/aarch64/cache_helpers.S (revision 04c7303b9c3d2215eebc3d59431519990abe03d0)
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
1254dc71e7SAchin Gupta	.globl	clean_dcache_range
134ecca339SDan Handley	.globl	inv_dcache_range
144ecca339SDan Handley	.globl	dcsw_op_louis
154ecca339SDan Handley	.globl	dcsw_op_all
168e857916SSoby Mathew	.globl	dcsw_op_level1
178e857916SSoby Mathew	.globl	dcsw_op_level2
188e857916SSoby Mathew	.globl	dcsw_op_level3
194ecca339SDan Handley
2054dc71e7SAchin Gupta/*
2154dc71e7SAchin Gupta * This macro can be used for implementing various data cache operations `op`
2254dc71e7SAchin Gupta */
2354dc71e7SAchin Gupta.macro do_dcache_maintenance_by_mva op
243ec5204cSSoby Mathew	/* Exit early if size is zero */
253ec5204cSSoby Mathew	cbz	x1, exit_loop_\op
2654dc71e7SAchin Gupta	dcache_line_size x2, x3
2754dc71e7SAchin Gupta	add	x1, x0, x1
2854dc71e7SAchin Gupta	sub	x3, x2, #1
2954dc71e7SAchin Gupta	bic	x0, x0, x3
3054dc71e7SAchin Guptaloop_\op:
3154dc71e7SAchin Gupta	dc	\op, x0
3254dc71e7SAchin Gupta	add	x0, x0, x2
3354dc71e7SAchin Gupta	cmp	x0, x1
3454dc71e7SAchin Gupta	b.lo	loop_\op
3554dc71e7SAchin Gupta	dsb	sy
363ec5204cSSoby Mathewexit_loop_\op:
3754dc71e7SAchin Gupta	ret
3854dc71e7SAchin Gupta.endm
39*04c7303bSOkash Khawaja
40*04c7303bSOkash Khawaja.macro check_plat_can_cmo
41*04c7303bSOkash Khawaja#if CONDITIONAL_CMO
42*04c7303bSOkash Khawaja	mov	x3, x30
43*04c7303bSOkash Khawaja	mov	x2, x0
44*04c7303bSOkash Khawaja	bl	plat_can_cmo
45*04c7303bSOkash Khawaja	mov	x30, x3
46*04c7303bSOkash Khawaja	cbnz	x0, 1f
47*04c7303bSOkash Khawaja	ret
48*04c7303bSOkash Khawaja1:
49*04c7303bSOkash Khawaja	mov	 x0, x2
50*04c7303bSOkash Khawaja#endif
51*04c7303bSOkash Khawaja.endm
524ecca339SDan Handley	/* ------------------------------------------
534ecca339SDan Handley	 * Clean+Invalidate from base address till
544ecca339SDan Handley	 * size. 'x0' = addr, 'x1' = size
554ecca339SDan Handley	 * ------------------------------------------
564ecca339SDan Handley	 */
574ecca339SDan Handleyfunc flush_dcache_range
58*04c7303bSOkash Khawaja	check_plat_can_cmo
5954dc71e7SAchin Gupta	do_dcache_maintenance_by_mva civac
608b779620SKévin Petitendfunc flush_dcache_range
614ecca339SDan Handley
6254dc71e7SAchin Gupta	/* ------------------------------------------
6354dc71e7SAchin Gupta	 * Clean from base address till size.
6454dc71e7SAchin Gupta	 * 'x0' = addr, 'x1' = size
6554dc71e7SAchin Gupta	 * ------------------------------------------
6654dc71e7SAchin Gupta	 */
6754dc71e7SAchin Guptafunc clean_dcache_range
68*04c7303bSOkash Khawaja	check_plat_can_cmo
6954dc71e7SAchin Gupta	do_dcache_maintenance_by_mva cvac
7054dc71e7SAchin Guptaendfunc clean_dcache_range
714ecca339SDan Handley
724ecca339SDan Handley	/* ------------------------------------------
734ecca339SDan Handley	 * Invalidate from base address till
744ecca339SDan Handley	 * size. 'x0' = addr, 'x1' = size
754ecca339SDan Handley	 * ------------------------------------------
764ecca339SDan Handley	 */
774ecca339SDan Handleyfunc inv_dcache_range
78*04c7303bSOkash Khawaja	check_plat_can_cmo
7954dc71e7SAchin Gupta	do_dcache_maintenance_by_mva ivac
808b779620SKévin Petitendfunc inv_dcache_range
814ecca339SDan Handley
824ecca339SDan Handley
836a00e9b0SRobert Wakim	/*
846a00e9b0SRobert Wakim	 * On implementations with FEAT_MTE2,
856a00e9b0SRobert Wakim	 * Root firmware must issue DC_CIGDPAPA instead of DC_CIPAPA ,
866a00e9b0SRobert Wakim	 * in order to additionally clean and invalidate Allocation Tags
876a00e9b0SRobert Wakim	 * associated with the affected locations.
886a00e9b0SRobert Wakim	 *
896a00e9b0SRobert Wakim	 * ------------------------------------------
906a00e9b0SRobert Wakim	 * Clean+Invalidate by PA to POPA
916a00e9b0SRobert Wakim	 * from base address till size.
926a00e9b0SRobert Wakim	 * 'x0' = addr, 'x1' = size
936a00e9b0SRobert Wakim	 * ------------------------------------------
946a00e9b0SRobert Wakim	 */
956a00e9b0SRobert Wakimfunc flush_dcache_to_popa_range
966a00e9b0SRobert Wakim	/* Exit early if size is zero */
976a00e9b0SRobert Wakim	cbz	x1, exit_loop_dc_cipapa
98*04c7303bSOkash Khawaja	check_plat_can_cmo
996a00e9b0SRobert Wakim	dcache_line_size x2, x3
1006a00e9b0SRobert Wakim	sub	x3, x2, #1
1016a00e9b0SRobert Wakim	bic	x0, x0, x3
1026a00e9b0SRobert Wakim	add	x1, x1, x0
1036a00e9b0SRobert Wakimloop_dc_cipapa:
1046a00e9b0SRobert Wakim	sys	#6, c7, c14, #1, x0 /* DC CIPAPA,<Xt> */
1056a00e9b0SRobert Wakim	add	x0, x0, x2
1066a00e9b0SRobert Wakim	cmp	x0, x1
1076a00e9b0SRobert Wakim	b.lo	loop_dc_cipapa
1086a00e9b0SRobert Wakim	dsb	osh
1096a00e9b0SRobert Wakimexit_loop_dc_cipapa:
1106a00e9b0SRobert Wakim	ret
1116a00e9b0SRobert Wakimendfunc	flush_dcache_to_popa_range
1126a00e9b0SRobert Wakim
1135f6032a8SAndrew Thoelke	/* ---------------------------------------------------------------
1145f6032a8SAndrew Thoelke	 * Data cache operations by set/way to the level specified
1155f6032a8SAndrew Thoelke	 *
1165f6032a8SAndrew Thoelke	 * The main function, do_dcsw_op requires:
1175f6032a8SAndrew Thoelke	 * x0: The operation type (0-2), as defined in arch.h
1185f6032a8SAndrew Thoelke	 * x3: The last cache level to operate on
1195f6032a8SAndrew Thoelke	 * x9: clidr_el1
1208e857916SSoby Mathew	 * x10: The cache level to begin operation from
1215f6032a8SAndrew Thoelke	 * and will carry out the operation on each data cache from level 0
1225f6032a8SAndrew Thoelke	 * to the level in x3 in sequence
1235f6032a8SAndrew Thoelke	 *
1245f6032a8SAndrew Thoelke	 * The dcsw_op macro sets up the x3 and x9 parameters based on
1255f6032a8SAndrew Thoelke	 * clidr_el1 cache information before invoking the main function
1265f6032a8SAndrew Thoelke	 * ---------------------------------------------------------------
1274ecca339SDan Handley	 */
1285f6032a8SAndrew Thoelke
1295f6032a8SAndrew Thoelke	.macro	dcsw_op shift, fw, ls
1305f6032a8SAndrew Thoelke	mrs	x9, clidr_el1
1315f6032a8SAndrew Thoelke	ubfx	x3, x9, \shift, \fw
1325f6032a8SAndrew Thoelke	lsl	x3, x3, \ls
1338e857916SSoby Mathew	mov	x10, xzr
1345f6032a8SAndrew Thoelke	b	do_dcsw_op
1355f6032a8SAndrew Thoelke	.endm
1365f6032a8SAndrew Thoelke
1375f6032a8SAndrew Thoelkefunc do_dcsw_op
1385f6032a8SAndrew Thoelke	cbz	x3, exit
139d0ec1cc4Sjohpow01	mrs	x12, ID_AA64MMFR2_EL1	// stash FEAT_CCIDX identifier in x12
140d0ec1cc4Sjohpow01	ubfx	x12, x12, #ID_AA64MMFR2_EL1_CCIDX_SHIFT, #ID_AA64MMFR2_EL1_CCIDX_LENGTH
1415f6032a8SAndrew Thoelke	adr	x14, dcsw_loop_table	// compute inner loop address
1425f6032a8SAndrew Thoelke	add	x14, x14, x0, lsl #5	// inner loop is 8x32-bit instructions
1439fc59639SAlexei Fedorov#if ENABLE_BTI
1449fc59639SAlexei Fedorov	add	x14, x14, x0, lsl #2	// inner loop is + "bti j" instruction
1459fc59639SAlexei Fedorov#endif
1465f6032a8SAndrew Thoelke	mov	x0, x9
1475f6032a8SAndrew Thoelke	mov	w8, #1
1485f6032a8SAndrew Thoelkeloop1:
1494ecca339SDan Handley	add	x2, x10, x10, lsr #1	// work out 3x current cache level
1504ecca339SDan Handley	lsr	x1, x0, x2		// extract cache type bits from clidr
1515f6032a8SAndrew Thoelke	and	x1, x1, #7		// mask the bits for current cache only
1524ecca339SDan Handley	cmp	x1, #2			// see what cache we have at this level
153355a5d03SDouglas Raillard	b.lo	level_done		// nothing to do if no cache or icache
1545f6032a8SAndrew Thoelke
1554ecca339SDan Handley	msr	csselr_el1, x10		// select current cache level in csselr
1564ecca339SDan Handley	isb				// isb to sych the new cssr&csidr
1574ecca339SDan Handley	mrs	x1, ccsidr_el1		// read the new ccsidr
1584ecca339SDan Handley	and	x2, x1, #7		// extract the length of the cache lines
1594ecca339SDan Handley	add	x2, x2, #4		// add 4 (line length offset)
160d0ec1cc4Sjohpow01
161d0ec1cc4Sjohpow01	cbz	x12, 1f			// check for FEAT_CCIDX for Associativity
162d0ec1cc4Sjohpow01	ubfx	x4, x1, #3, #21 	// x4 = associativity CCSIDR_EL1[23:3]
163d0ec1cc4Sjohpow01	b 	2f
164d0ec1cc4Sjohpow011:
165d0ec1cc4Sjohpow01	ubfx	x4, x1, #3, #10 	// x4 = associativity CCSIDR_EL1[12:3]
166d0ec1cc4Sjohpow012:
1675f6032a8SAndrew Thoelke	clz	w5, w4			// bit position of way size increment
1685f6032a8SAndrew Thoelke	lsl	w9, w4, w5		// w9 = aligned max way number
1695f6032a8SAndrew Thoelke	lsl	w16, w8, w5		// w16 = way number loop decrement
1705f6032a8SAndrew Thoelke	orr	w9, w10, w9		// w9 = combine way and cache number
171d0ec1cc4Sjohpow01
172d0ec1cc4Sjohpow01	cbz	x12, 3f			// check for FEAT_CCIDX for NumSets
173d0ec1cc4Sjohpow01	ubfx	x6, x1, #32, #24	// x6 (w6) = numsets CCSIDR_EL1[55:32]
174d0ec1cc4Sjohpow01					// ISA will not allow x->w ubfx
175d0ec1cc4Sjohpow01	b	4f
176d0ec1cc4Sjohpow013:
177d0ec1cc4Sjohpow01	ubfx	w6, w1, #13, #15	// w6 = numsets CCSIDR_EL1[27:13]
178d0ec1cc4Sjohpow014:
1795f6032a8SAndrew Thoelke	lsl	w17, w8, w2		// w17 = set number loop decrement
1805f6032a8SAndrew Thoelke	dsb	sy			// barrier before we start this level
1815f6032a8SAndrew Thoelke	br	x14			// jump to DC operation specific loop
1825f6032a8SAndrew Thoelke
1835f6032a8SAndrew Thoelke	.macro	dcsw_loop _op
1849fc59639SAlexei Fedorov#if ENABLE_BTI
1859fc59639SAlexei Fedorov	bti	j
1869fc59639SAlexei Fedorov#endif
1875f6032a8SAndrew Thoelkeloop2_\_op:
1885f6032a8SAndrew Thoelke	lsl	w7, w6, w2		// w7 = aligned max set number
1895f6032a8SAndrew Thoelke
1905f6032a8SAndrew Thoelkeloop3_\_op:
1915f6032a8SAndrew Thoelke	orr	w11, w9, w7		// combine cache, way and set number
1925f6032a8SAndrew Thoelke	dc	\_op, x11
1935f6032a8SAndrew Thoelke	subs	w7, w7, w17		// decrement set number
194355a5d03SDouglas Raillard	b.hs	loop3_\_op
1955f6032a8SAndrew Thoelke
1965f6032a8SAndrew Thoelke	subs	x9, x9, x16		// decrement way number
197355a5d03SDouglas Raillard	b.hs	loop2_\_op
1985f6032a8SAndrew Thoelke
1995f6032a8SAndrew Thoelke	b	level_done
2005f6032a8SAndrew Thoelke	.endm
2015f6032a8SAndrew Thoelke
2025f6032a8SAndrew Thoelkelevel_done:
2034ecca339SDan Handley	add	x10, x10, #2		// increment cache number
2044ecca339SDan Handley	cmp	x3, x10
205355a5d03SDouglas Raillard	b.hi	loop1
2065f6032a8SAndrew Thoelke	msr	csselr_el1, xzr		// select cache level 0 in csselr
2075f6032a8SAndrew Thoelke	dsb	sy			// barrier to complete final cache operation
2084ecca339SDan Handley	isb
2094ecca339SDan Handleyexit:
2104ecca339SDan Handley	ret
2118b779620SKévin Petitendfunc do_dcsw_op
2124ecca339SDan Handley
2135f6032a8SAndrew Thoelkedcsw_loop_table:
2145f6032a8SAndrew Thoelke	dcsw_loop isw
2155f6032a8SAndrew Thoelke	dcsw_loop cisw
2165f6032a8SAndrew Thoelke	dcsw_loop csw
2175f6032a8SAndrew Thoelke
2184ecca339SDan Handley
2194ecca339SDan Handleyfunc dcsw_op_louis
2205f6032a8SAndrew Thoelke	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
2218b779620SKévin Petitendfunc dcsw_op_louis
2224ecca339SDan Handley
2234ecca339SDan Handley
2244ecca339SDan Handleyfunc dcsw_op_all
225*04c7303bSOkash Khawaja	check_plat_can_cmo
2265f6032a8SAndrew Thoelke	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
2278b779620SKévin Petitendfunc dcsw_op_all
2288e857916SSoby Mathew
2298e857916SSoby Mathew	/* ---------------------------------------------------------------
2308e857916SSoby Mathew	 *  Helper macro for data cache operations by set/way for the
2318e857916SSoby Mathew	 *  level specified
2328e857916SSoby Mathew	 * ---------------------------------------------------------------
2338e857916SSoby Mathew	 */
2348e857916SSoby Mathew	.macro dcsw_op_level level
2358e857916SSoby Mathew	mrs	x9, clidr_el1
2368e857916SSoby Mathew	mov	x3, \level
2378e857916SSoby Mathew	sub	x10, x3, #2
2388e857916SSoby Mathew	b	do_dcsw_op
2398e857916SSoby Mathew	.endm
2408e857916SSoby Mathew
2418e857916SSoby Mathew	/* ---------------------------------------------------------------
2428e857916SSoby Mathew	 * Data cache operations by set/way for level 1 cache
2438e857916SSoby Mathew	 *
2448e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2458e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2468e857916SSoby Mathew	 * ---------------------------------------------------------------
2478e857916SSoby Mathew	 */
2488e857916SSoby Mathewfunc dcsw_op_level1
249*04c7303bSOkash Khawaja	check_plat_can_cmo
2508e857916SSoby Mathew	dcsw_op_level #(1 << LEVEL_SHIFT)
2518b779620SKévin Petitendfunc dcsw_op_level1
2528e857916SSoby Mathew
2538e857916SSoby Mathew	/* ---------------------------------------------------------------
2548e857916SSoby Mathew	 * Data cache operations by set/way for level 2 cache
2558e857916SSoby Mathew	 *
2568e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2578e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2588e857916SSoby Mathew	 * ---------------------------------------------------------------
2598e857916SSoby Mathew	 */
2608e857916SSoby Mathewfunc dcsw_op_level2
261*04c7303bSOkash Khawaja	check_plat_can_cmo
2628e857916SSoby Mathew	dcsw_op_level #(2 << LEVEL_SHIFT)
2638b779620SKévin Petitendfunc dcsw_op_level2
2648e857916SSoby Mathew
2658e857916SSoby Mathew	/* ---------------------------------------------------------------
2668e857916SSoby Mathew	 * Data cache operations by set/way for level 3 cache
2678e857916SSoby Mathew	 *
2688e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2698e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2708e857916SSoby Mathew	 * ---------------------------------------------------------------
2718e857916SSoby Mathew	 */
2728e857916SSoby Mathewfunc dcsw_op_level3
273*04c7303bSOkash Khawaja	check_plat_can_cmo
2748e857916SSoby Mathew	dcsw_op_level #(3 << LEVEL_SHIFT)
2758b779620SKévin Petitendfunc dcsw_op_level3
276