@@ -139,19 +139,92 @@ static ALWAYS_INLINE int arm64_dcache_range(void *addr, size_t size, int op)
139
139
return 0 ;
140
140
}
141
141
142
+ /*
143
+ * operation for all data cache
144
+ * ops: K_CACHE_INVD: invalidate
145
+ * K_CACHE_WB: clean
146
+ * K_CACHE_WB_INVD: clean and invalidate
147
+ */
148
+ static ALWAYS_INLINE int arm64_dcache_all (int op )
149
+ {
150
+ uint32_t clidr_el1 , csselr_el1 , ccsidr_el1 ;
151
+ uint8_t loc , ctype , cache_level , line_size , way_pos ;
152
+ uint32_t max_ways , max_sets , dc_val , set , way ;
153
+
154
+ if (op != K_CACHE_INVD && op != K_CACHE_WB && op != K_CACHE_WB_INVD ) {
155
+ return - ENOTSUP ;
156
+ }
157
+
158
+ /* Data barrier before start */
159
+ barrier_dsync_fence_full ();
160
+
161
+ clidr_el1 = read_clidr_el1 ();
162
+
163
+ loc = (clidr_el1 >> CLIDR_EL1_LOC_SHIFT ) & CLIDR_EL1_LOC_MASK ;
164
+ if (!loc ) {
165
+ return 0 ;
166
+ }
167
+
168
+ for (cache_level = 0 ; cache_level < loc ; cache_level ++ ) {
169
+ ctype = (clidr_el1 >> CLIDR_EL1_CTYPE_SHIFT (cache_level )) & CLIDR_EL1_CTYPE_MASK ;
170
+ /* No data cache, continue */
171
+ if (ctype < 2 ) {
172
+ continue ;
173
+ }
174
+
175
+ /* select cache level */
176
+ csselr_el1 = cache_level << 1 ;
177
+ write_csselr_el1 (csselr_el1 );
178
+ barrier_isync_fence_full ();
179
+
180
+ ccsidr_el1 = read_ccsidr_el1 ();
181
+ line_size = (ccsidr_el1 >> CCSIDR_EL1_LN_SZ_SHIFT & CCSIDR_EL1_LN_SZ_MASK ) + 4 ;
182
+ max_ways = (ccsidr_el1 >> CCSIDR_EL1_WAYS_SHIFT ) & CCSIDR_EL1_WAYS_MASK ;
183
+ max_sets = (ccsidr_el1 >> CCSIDR_EL1_SETS_SHIFT ) & CCSIDR_EL1_SETS_MASK ;
184
+ /* 32-log2(ways), bit position of way in DC operand */
185
+ way_pos = __builtin_clz (max_ways );
186
+
187
+ for (set = 0 ; set <= max_sets ; set ++ ) {
188
+ for (way = 0 ; way <= max_ways ; way ++ ) {
189
+ /* way number, aligned to pos in DC operand */
190
+ dc_val = way << way_pos ;
191
+ /* cache level, aligned to pos in DC operand */
192
+ dc_val |= csselr_el1 ;
193
+ /* set number, aligned to pos in DC operand */
194
+ dc_val |= set << line_size ;
195
+
196
+ if (op == K_CACHE_INVD ) {
197
+ dc_ops ("isw" , dc_val );
198
+ } else if (op == K_CACHE_WB_INVD ) {
199
+ dc_ops ("cisw" , dc_val );
200
+ } else if (op == K_CACHE_WB ) {
201
+ dc_ops ("csw" , dc_val );
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ /* Restore csselr_el1 to level 0 */
208
+ write_csselr_el1 (0 );
209
+ barrier_dsync_fence_full ();
210
+ barrier_isync_fence_full ();
211
+
212
+ return 0 ;
213
+ }
214
+
142
215
static ALWAYS_INLINE int arch_dcache_flush_all (void )
143
216
{
144
- return - ENOTSUP ;
217
+ return arm64_dcache_all ( K_CACHE_WB ) ;
145
218
}
146
219
147
220
static ALWAYS_INLINE int arch_dcache_invd_all (void )
148
221
{
149
- return - ENOTSUP ;
222
+ return arm64_dcache_all ( K_CACHE_INVD ) ;
150
223
}
151
224
152
225
static ALWAYS_INLINE int arch_dcache_flush_and_invd_all (void )
153
226
{
154
- return - ENOTSUP ;
227
+ return arm64_dcache_all ( K_CACHE_WB_INVD ) ;
155
228
}
156
229
157
230
static ALWAYS_INLINE int arch_dcache_flush_range (void * addr , size_t size )
0 commit comments