xref: /rk3399_ARM-atf/lib/aarch32/cache_helpers.S (revision 937108a04a998c9e6d6ce5734bf62c7eb8c9d42c)
1/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch.h>
32#include <asm_macros.S>
33
34	.globl	flush_dcache_range
35	.globl	clean_dcache_range
36	.globl	inv_dcache_range
37	.globl	dcsw_op_louis
38	.globl	dcsw_op_all
39	.globl	dcsw_op_level1
40	.globl	dcsw_op_level2
41	.globl	dcsw_op_level3
42
43/*
44 * This macro can be used for implementing various data cache operations `op`
45 */
46.macro do_dcache_maintenance_by_mva op, coproc, opc1, CRn, CRm, opc2
47	dcache_line_size r2, r3
48	add	r1, r0, r1
49	sub	r3, r2, #1
50	bic	r0, r0, r3
51loop_\op:
52	stcopr	r0, \coproc, \opc1, \CRn, \CRm, \opc2
53	add	r0, r0, r2
54	cmp	r0, r1
55	blo	loop_\op
56	dsb	sy
57	bx	lr
58.endm
59
60	/* ------------------------------------------
61	 * Clean+Invalidate from base address till
62	 * size. 'r0' = addr, 'r1' = size
63	 * ------------------------------------------
64	 */
65func flush_dcache_range
66	do_dcache_maintenance_by_mva cimvac, DCCIMVAC
67endfunc flush_dcache_range
68
69	/* ------------------------------------------
70	 * Clean from base address till size.
71	 * 'r0' = addr, 'r1' = size
72	 * ------------------------------------------
73	 */
74func clean_dcache_range
75	do_dcache_maintenance_by_mva cmvac, DCCMVAC
76endfunc clean_dcache_range
77
78	/* ------------------------------------------
79	 * Invalidate from base address till
80	 * size. 'r0' = addr, 'r1' = size
81	 * ------------------------------------------
82	 */
83func inv_dcache_range
84	do_dcache_maintenance_by_mva imvac, DCIMVAC
85endfunc inv_dcache_range
86
87	/* ----------------------------------------------------------------
88	 * Data cache operations by set/way to the level specified
89	 *
90	 * The main function, do_dcsw_op requires:
91	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
92	 * as defined in arch.h
93	 * r1: The cache level to begin operation from
94	 * r2: clidr_el1
95	 * r3: The last cache level to operate on
96	 * and will carry out the operation on each data cache from level 0
97	 * to the level in r3 in sequence
98	 *
99	 * The dcsw_op macro sets up the r2 and r3 parameters based on
100	 * clidr_el1 cache information before invoking the main function
101	 * ----------------------------------------------------------------
102	 */
103
104	.macro	dcsw_op shift, fw, ls
105	ldcopr	r2, CLIDR
106	ubfx	r3, r2, \shift, \fw
107	lsl	r3, r3, \ls
108	mov	r1, #0
109	b	do_dcsw_op
110	.endm
111
112func do_dcsw_op
113	push	{r4-r12,lr}
114	adr	r11, dcsw_loop_table	// compute cache op based on the operation type
115	add	r6, r11, r0, lsl #3	// cache op is 2x32-bit instructions
116loop1:
117	add	r10, r1, r1, LSR #1	// Work out 3x current cache level
118	mov	r12, r2, LSR r10	// extract cache type bits from clidr
119	and	r12, r12, #7   		// mask the bits for current cache only
120	cmp	r12, #2			// see what cache we have at this level
121	blt	level_done      	// no cache or only instruction cache at this level
122
123	stcopr	r1, CSSELR		// select current cache level in csselr
124	isb				// isb to sych the new cssr&csidr
125	ldcopr	r12, CCSIDR		// read the new ccsidr
126	and	r10, r12, #7   		// extract the length of the cache lines
127	add	r10, r10, #4        	// add 4 (r10 = line length offset)
128	ubfx	r4, r12, #3, #10	// r4 = maximum way number (right aligned)
129	clz	r5, r4            	// r5 = the bit position of the way size increment
130	mov	r9, r4			// r9 working copy of the aligned max way number
131
132loop2:
133	ubfx	r7, r12, #13, #15	// r7 = max set number (right aligned)
134
135loop3:
136	orr	r0, r1, r9, LSL r5	// factor in the way number and cache level into r0
137	orr	r0, r0, r7, LSL r10	// factor in the set number
138
139	blx	r6
140	subs	r7, r7, #1              // decrement the set number
141	bge	loop3
142	subs	r9, r9, #1              // decrement the way number
143	bge	loop2
144level_done:
145	add	r1, r1, #2		// increment the cache number
146	cmp	r3, r1
147	dsb	sy			// ensure completion of previous cache maintenance instruction
148	bgt	loop1
149
150	mov	r6, #0
151	stcopr	r6, CSSELR		//select cache level 0 in csselr
152	dsb	sy
153	isb
154	pop	{r4-r12,pc}
155
156dcsw_loop_table:
157	stcopr	r0, DCISW
158	bx	lr
159	stcopr	r0, DCCISW
160	bx	lr
161	stcopr	r0, DCCSW
162	bx	lr
163
164endfunc do_dcsw_op
165
166	/* ---------------------------------------------------------------
167	 * Data cache operations by set/way till PoU.
168	 *
169	 * The function requires :
170	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
171	 * as defined in arch.h
172	 * ---------------------------------------------------------------
173	 */
174func dcsw_op_louis
175	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
176endfunc	dcsw_op_louis
177
178	/* ---------------------------------------------------------------
179	 * Data cache operations by set/way till PoC.
180	 *
181	 * The function requires :
182	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
183	 * as defined in arch.h
184	 * ---------------------------------------------------------------
185	 */
186func dcsw_op_all
187	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
188endfunc	dcsw_op_all
189
190
191	/* ---------------------------------------------------------------
192	 *  Helper macro for data cache operations by set/way for the
193	 *  level specified
194	 * ---------------------------------------------------------------
195	 */
196	.macro	dcsw_op_level level
197	ldcopr	r2, CLIDR
198	mov	r3, \level
199	sub	r1, r3, #2
200	b	do_dcsw_op
201	.endm
202
203	/* ---------------------------------------------------------------
204	 * Data cache operations by set/way for level 1 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_level1
212	dcsw_op_level #(1 << LEVEL_SHIFT)
213endfunc dcsw_op_level1
214
215	/* ---------------------------------------------------------------
216	 * Data cache operations by set/way for level 2 cache
217	 *
218	 * The main function, do_dcsw_op requires:
219	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
220	 * as defined in arch.h
221	 * ---------------------------------------------------------------
222	 */
223func dcsw_op_level2
224	dcsw_op_level #(2 << LEVEL_SHIFT)
225endfunc dcsw_op_level2
226
227	/* ---------------------------------------------------------------
228	 * Data cache operations by set/way for level 3 cache
229	 *
230	 * The main function, do_dcsw_op requires:
231	 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW),
232	 * as defined in arch.h
233	 * ---------------------------------------------------------------
234	 */
235func dcsw_op_level3
236	dcsw_op_level #(3 << LEVEL_SHIFT)
237endfunc dcsw_op_level3
238