xref: /rk3399_ARM-atf/lib/aarch64/cache_helpers.S (revision d0ec1cc437c59e64ecba44710dbce82a04ff892d)
14ecca339SDan Handley/*
2*d0ec1cc4Sjohpow01 * Copyright (c) 2013-2021, 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
1154dc71e7SAchin Gupta	.globl	clean_dcache_range
124ecca339SDan Handley	.globl	inv_dcache_range
134ecca339SDan Handley	.globl	dcsw_op_louis
144ecca339SDan Handley	.globl	dcsw_op_all
158e857916SSoby Mathew	.globl	dcsw_op_level1
168e857916SSoby Mathew	.globl	dcsw_op_level2
178e857916SSoby Mathew	.globl	dcsw_op_level3
184ecca339SDan Handley
1954dc71e7SAchin Gupta/*
2054dc71e7SAchin Gupta * This macro can be used for implementing various data cache operations `op`
2154dc71e7SAchin Gupta */
2254dc71e7SAchin Gupta.macro do_dcache_maintenance_by_mva op
233ec5204cSSoby Mathew	/* Exit early if size is zero */
243ec5204cSSoby Mathew	cbz	x1, exit_loop_\op
2554dc71e7SAchin Gupta	dcache_line_size x2, x3
2654dc71e7SAchin Gupta	add	x1, x0, x1
2754dc71e7SAchin Gupta	sub	x3, x2, #1
2854dc71e7SAchin Gupta	bic	x0, x0, x3
2954dc71e7SAchin Guptaloop_\op:
3054dc71e7SAchin Gupta	dc	\op, x0
3154dc71e7SAchin Gupta	add	x0, x0, x2
3254dc71e7SAchin Gupta	cmp	x0, x1
3354dc71e7SAchin Gupta	b.lo	loop_\op
3454dc71e7SAchin Gupta	dsb	sy
353ec5204cSSoby Mathewexit_loop_\op:
3654dc71e7SAchin Gupta	ret
3754dc71e7SAchin Gupta.endm
384ecca339SDan Handley	/* ------------------------------------------
394ecca339SDan Handley	 * Clean+Invalidate from base address till
404ecca339SDan Handley	 * size. 'x0' = addr, 'x1' = size
414ecca339SDan Handley	 * ------------------------------------------
424ecca339SDan Handley	 */
434ecca339SDan Handleyfunc flush_dcache_range
4454dc71e7SAchin Gupta	do_dcache_maintenance_by_mva civac
458b779620SKévin Petitendfunc flush_dcache_range
464ecca339SDan Handley
4754dc71e7SAchin Gupta	/* ------------------------------------------
4854dc71e7SAchin Gupta	 * Clean from base address till size.
4954dc71e7SAchin Gupta	 * 'x0' = addr, 'x1' = size
5054dc71e7SAchin Gupta	 * ------------------------------------------
5154dc71e7SAchin Gupta	 */
5254dc71e7SAchin Guptafunc clean_dcache_range
5354dc71e7SAchin Gupta	do_dcache_maintenance_by_mva cvac
5454dc71e7SAchin Guptaendfunc clean_dcache_range
554ecca339SDan Handley
564ecca339SDan Handley	/* ------------------------------------------
574ecca339SDan Handley	 * Invalidate from base address till
584ecca339SDan Handley	 * size. 'x0' = addr, 'x1' = size
594ecca339SDan Handley	 * ------------------------------------------
604ecca339SDan Handley	 */
614ecca339SDan Handleyfunc inv_dcache_range
6254dc71e7SAchin Gupta	do_dcache_maintenance_by_mva ivac
638b779620SKévin Petitendfunc inv_dcache_range
644ecca339SDan Handley
654ecca339SDan Handley
665f6032a8SAndrew Thoelke	/* ---------------------------------------------------------------
675f6032a8SAndrew Thoelke	 * Data cache operations by set/way to the level specified
685f6032a8SAndrew Thoelke	 *
695f6032a8SAndrew Thoelke	 * The main function, do_dcsw_op requires:
705f6032a8SAndrew Thoelke	 * x0: The operation type (0-2), as defined in arch.h
715f6032a8SAndrew Thoelke	 * x3: The last cache level to operate on
725f6032a8SAndrew Thoelke	 * x9: clidr_el1
738e857916SSoby Mathew	 * x10: The cache level to begin operation from
745f6032a8SAndrew Thoelke	 * and will carry out the operation on each data cache from level 0
755f6032a8SAndrew Thoelke	 * to the level in x3 in sequence
765f6032a8SAndrew Thoelke	 *
775f6032a8SAndrew Thoelke	 * The dcsw_op macro sets up the x3 and x9 parameters based on
785f6032a8SAndrew Thoelke	 * clidr_el1 cache information before invoking the main function
795f6032a8SAndrew Thoelke	 * ---------------------------------------------------------------
804ecca339SDan Handley	 */
815f6032a8SAndrew Thoelke
825f6032a8SAndrew Thoelke	.macro	dcsw_op shift, fw, ls
835f6032a8SAndrew Thoelke	mrs	x9, clidr_el1
845f6032a8SAndrew Thoelke	ubfx	x3, x9, \shift, \fw
855f6032a8SAndrew Thoelke	lsl	x3, x3, \ls
868e857916SSoby Mathew	mov	x10, xzr
875f6032a8SAndrew Thoelke	b	do_dcsw_op
885f6032a8SAndrew Thoelke	.endm
895f6032a8SAndrew Thoelke
905f6032a8SAndrew Thoelkefunc do_dcsw_op
915f6032a8SAndrew Thoelke	cbz	x3, exit
92*d0ec1cc4Sjohpow01	mrs	x12, ID_AA64MMFR2_EL1	// stash FEAT_CCIDX identifier in x12
93*d0ec1cc4Sjohpow01	ubfx	x12, x12, #ID_AA64MMFR2_EL1_CCIDX_SHIFT, #ID_AA64MMFR2_EL1_CCIDX_LENGTH
945f6032a8SAndrew Thoelke	adr	x14, dcsw_loop_table	// compute inner loop address
955f6032a8SAndrew Thoelke	add	x14, x14, x0, lsl #5	// inner loop is 8x32-bit instructions
969fc59639SAlexei Fedorov#if ENABLE_BTI
979fc59639SAlexei Fedorov	add	x14, x14, x0, lsl #2	// inner loop is + "bti j" instruction
989fc59639SAlexei Fedorov#endif
995f6032a8SAndrew Thoelke	mov	x0, x9
1005f6032a8SAndrew Thoelke	mov	w8, #1
1015f6032a8SAndrew Thoelkeloop1:
1024ecca339SDan Handley	add	x2, x10, x10, lsr #1	// work out 3x current cache level
1034ecca339SDan Handley	lsr	x1, x0, x2		// extract cache type bits from clidr
1045f6032a8SAndrew Thoelke	and	x1, x1, #7		// mask the bits for current cache only
1054ecca339SDan Handley	cmp	x1, #2			// see what cache we have at this level
106355a5d03SDouglas Raillard	b.lo	level_done		// nothing to do if no cache or icache
1075f6032a8SAndrew Thoelke
1084ecca339SDan Handley	msr	csselr_el1, x10		// select current cache level in csselr
1094ecca339SDan Handley	isb				// isb to sych the new cssr&csidr
1104ecca339SDan Handley	mrs	x1, ccsidr_el1		// read the new ccsidr
1114ecca339SDan Handley	and	x2, x1, #7		// extract the length of the cache lines
1124ecca339SDan Handley	add	x2, x2, #4		// add 4 (line length offset)
113*d0ec1cc4Sjohpow01
114*d0ec1cc4Sjohpow01	cbz	x12, 1f			// check for FEAT_CCIDX for Associativity
115*d0ec1cc4Sjohpow01	ubfx	x4, x1, #3, #21 	// x4 = associativity CCSIDR_EL1[23:3]
116*d0ec1cc4Sjohpow01	b 	2f
117*d0ec1cc4Sjohpow011:
118*d0ec1cc4Sjohpow01	ubfx	x4, x1, #3, #10 	// x4 = associativity CCSIDR_EL1[12:3]
119*d0ec1cc4Sjohpow012:
1205f6032a8SAndrew Thoelke	clz	w5, w4			// bit position of way size increment
1215f6032a8SAndrew Thoelke	lsl	w9, w4, w5		// w9 = aligned max way number
1225f6032a8SAndrew Thoelke	lsl	w16, w8, w5		// w16 = way number loop decrement
1235f6032a8SAndrew Thoelke	orr	w9, w10, w9		// w9 = combine way and cache number
124*d0ec1cc4Sjohpow01
125*d0ec1cc4Sjohpow01	cbz	x12, 3f			// check for FEAT_CCIDX for NumSets
126*d0ec1cc4Sjohpow01	ubfx	x6, x1, #32, #24	// x6 (w6) = numsets CCSIDR_EL1[55:32]
127*d0ec1cc4Sjohpow01					// ISA will not allow x->w ubfx
128*d0ec1cc4Sjohpow01	b	4f
129*d0ec1cc4Sjohpow013:
130*d0ec1cc4Sjohpow01	ubfx	w6, w1, #13, #15	// w6 = numsets CCSIDR_EL1[27:13]
131*d0ec1cc4Sjohpow014:
1325f6032a8SAndrew Thoelke	lsl	w17, w8, w2		// w17 = set number loop decrement
1335f6032a8SAndrew Thoelke	dsb	sy			// barrier before we start this level
1345f6032a8SAndrew Thoelke	br	x14			// jump to DC operation specific loop
1355f6032a8SAndrew Thoelke
1365f6032a8SAndrew Thoelke	.macro	dcsw_loop _op
1379fc59639SAlexei Fedorov#if ENABLE_BTI
1389fc59639SAlexei Fedorov	bti	j
1399fc59639SAlexei Fedorov#endif
1405f6032a8SAndrew Thoelkeloop2_\_op:
1415f6032a8SAndrew Thoelke	lsl	w7, w6, w2		// w7 = aligned max set number
1425f6032a8SAndrew Thoelke
1435f6032a8SAndrew Thoelkeloop3_\_op:
1445f6032a8SAndrew Thoelke	orr	w11, w9, w7		// combine cache, way and set number
1455f6032a8SAndrew Thoelke	dc	\_op, x11
1465f6032a8SAndrew Thoelke	subs	w7, w7, w17		// decrement set number
147355a5d03SDouglas Raillard	b.hs	loop3_\_op
1485f6032a8SAndrew Thoelke
1495f6032a8SAndrew Thoelke	subs	x9, x9, x16		// decrement way number
150355a5d03SDouglas Raillard	b.hs	loop2_\_op
1515f6032a8SAndrew Thoelke
1525f6032a8SAndrew Thoelke	b	level_done
1535f6032a8SAndrew Thoelke	.endm
1545f6032a8SAndrew Thoelke
1555f6032a8SAndrew Thoelkelevel_done:
1564ecca339SDan Handley	add	x10, x10, #2		// increment cache number
1574ecca339SDan Handley	cmp	x3, x10
158355a5d03SDouglas Raillard	b.hi	loop1
1595f6032a8SAndrew Thoelke	msr	csselr_el1, xzr		// select cache level 0 in csselr
1605f6032a8SAndrew Thoelke	dsb	sy			// barrier to complete final cache operation
1614ecca339SDan Handley	isb
1624ecca339SDan Handleyexit:
1634ecca339SDan Handley	ret
1648b779620SKévin Petitendfunc do_dcsw_op
1654ecca339SDan Handley
1665f6032a8SAndrew Thoelkedcsw_loop_table:
1675f6032a8SAndrew Thoelke	dcsw_loop isw
1685f6032a8SAndrew Thoelke	dcsw_loop cisw
1695f6032a8SAndrew Thoelke	dcsw_loop csw
1705f6032a8SAndrew Thoelke
1714ecca339SDan Handley
1724ecca339SDan Handleyfunc dcsw_op_louis
1735f6032a8SAndrew Thoelke	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
1748b779620SKévin Petitendfunc dcsw_op_louis
1754ecca339SDan Handley
1764ecca339SDan Handley
1774ecca339SDan Handleyfunc dcsw_op_all
1785f6032a8SAndrew Thoelke	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
1798b779620SKévin Petitendfunc dcsw_op_all
1808e857916SSoby Mathew
1818e857916SSoby Mathew	/* ---------------------------------------------------------------
1828e857916SSoby Mathew	 *  Helper macro for data cache operations by set/way for the
1838e857916SSoby Mathew	 *  level specified
1848e857916SSoby Mathew	 * ---------------------------------------------------------------
1858e857916SSoby Mathew	 */
1868e857916SSoby Mathew	.macro dcsw_op_level level
1878e857916SSoby Mathew	mrs	x9, clidr_el1
1888e857916SSoby Mathew	mov	x3, \level
1898e857916SSoby Mathew	sub	x10, x3, #2
1908e857916SSoby Mathew	b	do_dcsw_op
1918e857916SSoby Mathew	.endm
1928e857916SSoby Mathew
1938e857916SSoby Mathew	/* ---------------------------------------------------------------
1948e857916SSoby Mathew	 * Data cache operations by set/way for level 1 cache
1958e857916SSoby Mathew	 *
1968e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
1978e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
1988e857916SSoby Mathew	 * ---------------------------------------------------------------
1998e857916SSoby Mathew	 */
2008e857916SSoby Mathewfunc dcsw_op_level1
2018e857916SSoby Mathew	dcsw_op_level #(1 << LEVEL_SHIFT)
2028b779620SKévin Petitendfunc dcsw_op_level1
2038e857916SSoby Mathew
2048e857916SSoby Mathew	/* ---------------------------------------------------------------
2058e857916SSoby Mathew	 * Data cache operations by set/way for level 2 cache
2068e857916SSoby Mathew	 *
2078e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2088e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2098e857916SSoby Mathew	 * ---------------------------------------------------------------
2108e857916SSoby Mathew	 */
2118e857916SSoby Mathewfunc dcsw_op_level2
2128e857916SSoby Mathew	dcsw_op_level #(2 << LEVEL_SHIFT)
2138b779620SKévin Petitendfunc dcsw_op_level2
2148e857916SSoby Mathew
2158e857916SSoby Mathew	/* ---------------------------------------------------------------
2168e857916SSoby Mathew	 * Data cache operations by set/way for level 3 cache
2178e857916SSoby Mathew	 *
2188e857916SSoby Mathew	 * The main function, do_dcsw_op requires:
2198e857916SSoby Mathew	 * x0: The operation type (0-2), as defined in arch.h
2208e857916SSoby Mathew	 * ---------------------------------------------------------------
2218e857916SSoby Mathew	 */
2228e857916SSoby Mathewfunc dcsw_op_level3
2238e857916SSoby Mathew	dcsw_op_level #(3 << LEVEL_SHIFT)
2248b779620SKévin Petitendfunc dcsw_op_level3
225