xref: /rk3399_ARM-atf/lib/aarch64/cache_helpers.S (revision 6a00e9b0c8c37fc446f83ef63e95a75353e31e8b)
14ecca339SDan Handley/*
2*6a00e9b0SRobert 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
11*6a00e9b0SRobert 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
394ecca339SDan Handley	/* ------------------------------------------
404ecca339SDan Handley	 * Clean+Invalidate from base address till
414ecca339SDan Handley	 * size. 'x0' = addr, 'x1' = size
424ecca339SDan Handley	 * ------------------------------------------
434ecca339SDan Handley	 */
444ecca339SDan Handleyfunc flush_dcache_range
4554dc71e7SAchin Gupta	do_dcache_maintenance_by_mva civac
468b779620SKévin Petitendfunc flush_dcache_range
474ecca339SDan Handley
4854dc71e7SAchin Gupta	/* ------------------------------------------
4954dc71e7SAchin Gupta	 * Clean from base address till size.
5054dc71e7SAchin Gupta	 * 'x0' = addr, 'x1' = size
5154dc71e7SAchin Gupta	 * ------------------------------------------
5254dc71e7SAchin Gupta	 */
5354dc71e7SAchin Guptafunc clean_dcache_range
5454dc71e7SAchin Gupta	do_dcache_maintenance_by_mva cvac
5554dc71e7SAchin Guptaendfunc clean_dcache_range
564ecca339SDan Handley
574ecca339SDan Handley	/* ------------------------------------------
584ecca339SDan Handley	 * Invalidate from base address till
594ecca339SDan Handley	 * size. 'x0' = addr, 'x1' = size
604ecca339SDan Handley	 * ------------------------------------------
614ecca339SDan Handley	 */
624ecca339SDan Handleyfunc inv_dcache_range
6354dc71e7SAchin Gupta	do_dcache_maintenance_by_mva ivac
648b779620SKévin Petitendfunc inv_dcache_range
654ecca339SDan Handley
664ecca339SDan Handley
67*6a00e9b0SRobert Wakim	/*
68*6a00e9b0SRobert Wakim	 * On implementations with FEAT_MTE2,
69*6a00e9b0SRobert Wakim	 * Root firmware must issue DC_CIGDPAPA instead of DC_CIPAPA ,
70*6a00e9b0SRobert Wakim	 * in order to additionally clean and invalidate Allocation Tags
71*6a00e9b0SRobert Wakim	 * associated with the affected locations.
72*6a00e9b0SRobert Wakim	 *
73*6a00e9b0SRobert Wakim	 * ------------------------------------------
74*6a00e9b0SRobert Wakim	 * Clean+Invalidate by PA to POPA
75*6a00e9b0SRobert Wakim	 * from base address till size.
76*6a00e9b0SRobert Wakim	 * 'x0' = addr, 'x1' = size
77*6a00e9b0SRobert Wakim	 * ------------------------------------------
78*6a00e9b0SRobert Wakim	 */
79*6a00e9b0SRobert Wakimfunc flush_dcache_to_popa_range
80*6a00e9b0SRobert Wakim	/* Exit early if size is zero */
81*6a00e9b0SRobert Wakim	cbz	x1, exit_loop_dc_cipapa
82*6a00e9b0SRobert Wakim	dcache_line_size x2, x3
83*6a00e9b0SRobert Wakim	sub	x3, x2, #1
84*6a00e9b0SRobert Wakim	bic	x0, x0, x3
85*6a00e9b0SRobert Wakim	add	x1, x1, x0
86*6a00e9b0SRobert Wakimloop_dc_cipapa:
87*6a00e9b0SRobert Wakim	sys	#6, c7, c14, #1, x0 /* DC CIPAPA,<Xt> */
88*6a00e9b0SRobert Wakim	add	x0, x0, x2
89*6a00e9b0SRobert Wakim	cmp	x0, x1
90*6a00e9b0SRobert Wakim	b.lo	loop_dc_cipapa
91*6a00e9b0SRobert Wakim	dsb	osh
92*6a00e9b0SRobert Wakimexit_loop_dc_cipapa:
93*6a00e9b0SRobert Wakim	ret
94*6a00e9b0SRobert Wakimendfunc	flush_dcache_to_popa_range
95*6a00e9b0SRobert Wakim
965f6032a8SAndrew Thoelke	/* ---------------------------------------------------------------
975f6032a8SAndrew Thoelke	 * Data cache operations by set/way to the level specified
985f6032a8SAndrew Thoelke	 *
995f6032a8SAndrew Thoelke	 * The main function, do_dcsw_op requires:
1005f6032a8SAndrew Thoelke	 * x0: The operation type (0-2), as defined in arch.h
1015f6032a8SAndrew Thoelke	 * x3: The last cache level to operate on
1025f6032a8SAndrew Thoelke	 * x9: clidr_el1
1038e857916SSoby Mathew	 * x10: The cache level to begin operation from
1045f6032a8SAndrew Thoelke	 * and will carry out the operation on each data cache from level 0
1055f6032a8SAndrew Thoelke	 * to the level in x3 in sequence
1065f6032a8SAndrew Thoelke	 *
1075f6032a8SAndrew Thoelke	 * The dcsw_op macro sets up the x3 and x9 parameters based on
1085f6032a8SAndrew Thoelke	 * clidr_el1 cache information before invoking the main function
1095f6032a8SAndrew Thoelke	 * ---------------------------------------------------------------
1104ecca339SDan Handley	 */
1115f6032a8SAndrew Thoelke
1125f6032a8SAndrew Thoelke	.macro	dcsw_op shift, fw, ls
1135f6032a8SAndrew Thoelke	mrs	x9, clidr_el1
1145f6032a8SAndrew Thoelke	ubfx	x3, x9, \shift, \fw
1155f6032a8SAndrew Thoelke	lsl	x3, x3, \ls
1168e857916SSoby Mathew	mov	x10, xzr
1175f6032a8SAndrew Thoelke	b	do_dcsw_op
1185f6032a8SAndrew Thoelke	.endm
1195f6032a8SAndrew Thoelke
1205f6032a8SAndrew Thoelkefunc do_dcsw_op
1215f6032a8SAndrew Thoelke	cbz	x3, exit
122d0ec1cc4Sjohpow01	mrs	x12, ID_AA64MMFR2_EL1	// stash FEAT_CCIDX identifier in x12
123d0ec1cc4Sjohpow01	ubfx	x12, x12, #ID_AA64MMFR2_EL1_CCIDX_SHIFT, #ID_AA64MMFR2_EL1_CCIDX_LENGTH
1245f6032a8SAndrew Thoelke	adr	x14, dcsw_loop_table	// compute inner loop address
1255f6032a8SAndrew Thoelke	add	x14, x14, x0, lsl #5	// inner loop is 8x32-bit instructions
1269fc59639SAlexei Fedorov#if ENABLE_BTI
1279fc59639SAlexei Fedorov	add	x14, x14, x0, lsl #2	// inner loop is + "bti j" instruction
1289fc59639SAlexei Fedorov#endif
1295f6032a8SAndrew Thoelke	mov	x0, x9
1305f6032a8SAndrew Thoelke	mov	w8, #1
1315f6032a8SAndrew Thoelkeloop1:
1324ecca339SDan Handley	add	x2, x10, x10, lsr #1	// work out 3x current cache level
1334ecca339SDan Handley	lsr	x1, x0, x2		// extract cache type bits from clidr
1345f6032a8SAndrew Thoelke	and	x1, x1, #7		// mask the bits for current cache only
1354ecca339SDan Handley	cmp	x1, #2			// see what cache we have at this level
136355a5d03SDouglas Raillard	b.lo	level_done		// nothing to do if no cache or icache
1375f6032a8SAndrew Thoelke
1384ecca339SDan Handley	msr	csselr_el1, x10		// select current cache level in csselr
1394ecca339SDan Handley	isb				// isb to sych the new cssr&csidr
1404ecca339SDan Handley	mrs	x1, ccsidr_el1		// read the new ccsidr
1414ecca339SDan Handley	and	x2, x1, #7		// extract the length of the cache lines
1424ecca339SDan Handley	add	x2, x2, #4		// add 4 (line length offset)
143d0ec1cc4Sjohpow01
144d0ec1cc4Sjohpow01	cbz	x12, 1f			// check for FEAT_CCIDX for Associativity
145d0ec1cc4Sjohpow01	ubfx	x4, x1, #3, #21 	// x4 = associativity CCSIDR_EL1[23:3]
146d0ec1cc4Sjohpow01	b 	2f
147d0ec1cc4Sjohpow011:
148d0ec1cc4Sjohpow01	ubfx	x4, x1, #3, #10 	// x4 = associativity CCSIDR_EL1[12:3]
149d0ec1cc4Sjohpow012:
1505f6032a8SAndrew Thoelke	clz	w5, w4			// bit position of way size increment
1515f6032a8SAndrew Thoelke	lsl	w9, w4, w5		// w9 = aligned max way number
1525f6032a8SAndrew Thoelke	lsl	w16, w8, w5		// w16 = way number loop decrement
1535f6032a8SAndrew Thoelke	orr	w9, w10, w9		// w9 = combine way and cache number
154d0ec1cc4Sjohpow01
155d0ec1cc4Sjohpow01	cbz	x12, 3f			// check for FEAT_CCIDX for NumSets
156d0ec1cc4Sjohpow01	ubfx	x6, x1, #32, #24	// x6 (w6) = numsets CCSIDR_EL1[55:32]
157d0ec1cc4Sjohpow01					// ISA will not allow x->w ubfx
158d0ec1cc4Sjohpow01	b	4f
159d0ec1cc4Sjohpow013:
160d0ec1cc4Sjohpow01	ubfx	w6, w1, #13, #15	// w6 = numsets CCSIDR_EL1[27:13]
161d0ec1cc4Sjohpow014:
1625f6032a8SAndrew Thoelke	lsl	w17, w8, w2		// w17 = set number loop decrement
1635f6032a8SAndrew Thoelke	dsb	sy			// barrier before we start this level
1645f6032a8SAndrew Thoelke	br	x14			// jump to DC operation specific loop
1655f6032a8SAndrew Thoelke
1665f6032a8SAndrew Thoelke	.macro	dcsw_loop _op
1679fc59639SAlexei Fedorov#if ENABLE_BTI
1689fc59639SAlexei Fedorov	bti	j
1699fc59639SAlexei Fedorov#endif
1705f6032a8SAndrew Thoelkeloop2_\_op:
1715f6032a8SAndrew Thoelke	lsl	w7, w6, w2		// w7 = aligned max set number
1725f6032a8SAndrew Thoelke
1735f6032a8SAndrew Thoelkeloop3_\_op:
1745f6032a8SAndrew Thoelke	orr	w11, w9, w7		// combine cache, way and set number
1755f6032a8SAndrew Thoelke	dc	\_op, x11
1765f6032a8SAndrew Thoelke	subs	w7, w7, w17		// decrement set number
177355a5d03SDouglas Raillard	b.hs	loop3_\_op
1785f6032a8SAndrew Thoelke
1795f6032a8SAndrew Thoelke	subs	x9, x9, x16		// decrement way number
180355a5d03SDouglas Raillard	b.hs	loop2_\_op
1815f6032a8SAndrew Thoelke
1825f6032a8SAndrew Thoelke	b	level_done
1835f6032a8SAndrew Thoelke	.endm
1845f6032a8SAndrew Thoelke
1855f6032a8SAndrew Thoelkelevel_done:
1864ecca339SDan Handley	add	x10, x10, #2		// increment cache number
1874ecca339SDan Handley	cmp	x3, x10
188355a5d03SDouglas Raillard	b.hi	loop1
1895f6032a8SAndrew Thoelke	msr	csselr_el1, xzr		// select cache level 0 in csselr
1905f6032a8SAndrew Thoelke	dsb	sy			// barrier to complete final cache operation
1914ecca339SDan Handley	isb
1924ecca339SDan Handleyexit:
1934ecca339SDan Handley	ret
1948b779620SKévin Petitendfunc do_dcsw_op
1954ecca339SDan Handley
1965f6032a8SAndrew Thoelkedcsw_loop_table:
1975f6032a8SAndrew Thoelke	dcsw_loop isw
1985f6032a8SAndrew Thoelke	dcsw_loop cisw
1995f6032a8SAndrew Thoelke	dcsw_loop csw
2005f6032a8SAndrew Thoelke
2014ecca339SDan Handley
2024ecca339SDan Handleyfunc dcsw_op_louis
2035f6032a8SAndrew Thoelke	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
2048b779620SKévin Petitendfunc dcsw_op_louis
2054ecca339SDan Handley
2064ecca339SDan Handley
2074ecca339SDan Handleyfunc dcsw_op_all
2085f6032a8SAndrew Thoelke	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
2098b779620SKévin Petitendfunc dcsw_op_all
2108e857916SSoby Mathew
2118e857916SSoby Mathew	/* ---------------------------------------------------------------
2128e857916SSoby Mathew	 *  Helper macro for data cache operations by set/way for the
2138e857916SSoby Mathew	 *  level specified
2148e857916SSoby Mathew	 * ---------------------------------------------------------------
2158e857916SSoby Mathew	 */
2168e857916SSoby Mathew	.macro dcsw_op_level level
2178e857916SSoby Mathew	mrs	x9, clidr_el1
2188e857916SSoby Mathew	mov	x3, \level
2198e857916SSoby Mathew	sub	x10, x3, #2
2208e857916SSoby Mathew	b	do_dcsw_op
2218e857916SSoby Mathew	.endm
2228e857916SSoby Mathew
2238e857916SSoby Mathew	/* ---------------------------------------------------------------
2248e857916SSoby Mathew	 * Data cache operations by set/way for level 1 cache
2258e857916SSoby Mathew	 *
2268e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2278e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2288e857916SSoby Mathew	 * ---------------------------------------------------------------
2298e857916SSoby Mathew	 */
2308e857916SSoby Mathewfunc dcsw_op_level1
2318e857916SSoby Mathew	dcsw_op_level #(1 << LEVEL_SHIFT)
2328b779620SKévin Petitendfunc dcsw_op_level1
2338e857916SSoby Mathew
2348e857916SSoby Mathew	/* ---------------------------------------------------------------
2358e857916SSoby Mathew	 * Data cache operations by set/way for level 2 cache
2368e857916SSoby Mathew	 *
2378e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2388e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2398e857916SSoby Mathew	 * ---------------------------------------------------------------
2408e857916SSoby Mathew	 */
2418e857916SSoby Mathewfunc dcsw_op_level2
2428e857916SSoby Mathew	dcsw_op_level #(2 << LEVEL_SHIFT)
2438b779620SKévin Petitendfunc dcsw_op_level2
2448e857916SSoby Mathew
2458e857916SSoby Mathew	/* ---------------------------------------------------------------
2468e857916SSoby Mathew	 * Data cache operations by set/way for level 3 cache
2478e857916SSoby Mathew	 *
2488e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2498e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2508e857916SSoby Mathew	 * ---------------------------------------------------------------
2518e857916SSoby Mathew	 */
2528e857916SSoby Mathewfunc dcsw_op_level3
2538e857916SSoby Mathew	dcsw_op_level #(3 << LEVEL_SHIFT)
2548b779620SKévin Petitendfunc dcsw_op_level3
255