blob: 57b6b384ed55b18f7cc997705cad2601e022b78a [file] [log] [blame]
Soby Mathewd29f67b2016-05-05 12:31:57 +01001/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soby Mathewd29f67b2016-05-05 12:31:57 +01005 */
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
Douglas Raillard9d92e8c2017-03-07 16:36:14 +000097 blo level_done // no cache or only instruction cache at this level
Soby Mathewd29f67b2016-05-05 12:31:57 +010098
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
Douglas Raillard9d92e8c2017-03-07 16:36:14 +0000117 bhs loop3
Soby Mathewd29f67b2016-05-05 12:31:57 +0100118 subs r9, r9, #1 // decrement the way number
Douglas Raillard9d92e8c2017-03-07 16:36:14 +0000119 bhs loop2
Soby Mathewd29f67b2016-05-05 12:31:57 +0100120level_done:
121 add r1, r1, #2 // increment the cache number
122 cmp r3, r1
123 dsb sy // ensure completion of previous cache maintenance instruction
Douglas Raillard9d92e8c2017-03-07 16:36:14 +0000124 bhi loop1
Soby Mathewd29f67b2016-05-05 12:31:57 +0100125
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