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