RTEMS 5.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cache-cp15.h
1
9/*
10 * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
11 *
12 * embedded brains GmbH
13 * Dornierstr. 4
14 * 82178 Puchheim
15 * Germany
16 * <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#ifndef LIBBSP_ARM_SHARED_CACHE_L1_H
24#define LIBBSP_ARM_SHARED_CACHE_L1_H
25
26#include <bsp.h>
27#include <libcpu/arm-cp15.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif /* __cplusplus */
32
33/* These two defines also ensure that the rtems_cache_* functions have bodies */
34#define ARM_CACHE_L1_CPU_DATA_ALIGNMENT 32
35#define ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT 32
36
37#define ARM_CACHE_L1_CSS_ID_DATA \
38 (ARM_CP15_CACHE_CSS_ID_DATA | ARM_CP15_CACHE_CSS_LEVEL(0))
39#define ARM_CACHE_L1_CSS_ID_INSTRUCTION \
40 (ARM_CP15_CACHE_CSS_ID_INSTRUCTION | ARM_CP15_CACHE_CSS_LEVEL(0))
41#define ARM_CACHE_L1_DATA_LINE_MASK ( ARM_CACHE_L1_CPU_DATA_ALIGNMENT - 1 )
42#define ARM_CACHE_L1_INSTRUCTION_LINE_MASK \
43 ( ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT \
44 - 1 )
45
46/* Errata Handlers */
47static void arm_cache_l1_errata_764369_handler( void )
48{
49#ifdef RTEMS_SMP
50 _ARM_Data_synchronization_barrier();
51#endif
52}
53
54/*
55 * @param l1LineSize Number of bytes in cache line expressed as power of
56 * 2 value
57 * @param l1Associativity Associativity of cache. The associativity does not
58 * have to be a power of 2.
59 * qparam liNumSets Number of sets in cache
60 * */
61
62static inline void arm_cache_l1_properties_for_level(
63 uint32_t *l1LineSize,
64 uint32_t *l1Associativity,
65 uint32_t *l1NumSets,
66 uint32_t level_and_inst_dat
67)
68{
69 uint32_t ccsidr;
70
71 ccsidr = arm_cp15_get_cache_size_id_for_level(level_and_inst_dat);
72
73 /* Cache line size in words + 2 -> bytes) */
74 *l1LineSize = arm_ccsidr_get_line_power(ccsidr);
75 /* Number of Ways */
76 *l1Associativity = arm_ccsidr_get_associativity(ccsidr);
77 /* Number of Sets */
78 *l1NumSets = arm_ccsidr_get_num_sets(ccsidr);
79}
80
81/*
82 * @param log_2_line_bytes The number of bytes per cache line expressed in log2
83 * @param associativity The associativity of the cache beeing operated
84 * @param cache_level_idx The level of the cache beeing operated minus 1 e.g 0
85 * for cache level 1
86 * @param set Number of the set to operate on
87 * @param way Number of the way to operate on
88 * */
89
90static inline uint32_t arm_cache_l1_get_set_way_param(
91 const uint32_t log_2_line_bytes,
92 const uint32_t associativity,
93 const uint32_t cache_level_idx,
94 const uint32_t set,
95 const uint32_t way )
96{
97 uint32_t way_shift = __builtin_clz( associativity - 1 );
98
99
100 return ( 0
101 | ( way
102 << way_shift ) | ( set << log_2_line_bytes ) | ( cache_level_idx << 1 ) );
103}
104
105static inline void arm_cache_l1_flush_1_data_line( const void *d_addr )
106{
107 /* Flush the Data cache */
108 arm_cp15_data_cache_clean_and_invalidate_line( d_addr );
109
110 /* Wait for L1 flush to complete */
111 _ARM_Data_synchronization_barrier();
112}
113
114static inline void arm_cache_l1_flush_entire_data( void )
115{
116 uint32_t l1LineSize, l1Associativity, l1NumSets;
117 uint32_t s, w;
118 uint32_t set_way_param;
119
120 /* ensure ordering with previous memory accesses */
121 _ARM_Data_memory_barrier();
122
123 /* Get the L1 cache properties */
124 arm_cache_l1_properties_for_level( &l1LineSize,
125 &l1Associativity, &l1NumSets,
126 ARM_CACHE_L1_CSS_ID_DATA);
127
128 for ( w = 0; w < l1Associativity; ++w ) {
129 for ( s = 0; s < l1NumSets; ++s ) {
130 set_way_param = arm_cache_l1_get_set_way_param(
131 l1LineSize,
132 l1Associativity,
133 0,
134 s,
135 w
136 );
137 arm_cp15_data_cache_clean_line_by_set_and_way( set_way_param );
138 }
139 }
140
141 /* Wait for L1 flush to complete */
142 _ARM_Data_synchronization_barrier();
143}
144
145static inline void arm_cache_l1_invalidate_entire_data( void )
146{
147 uint32_t l1LineSize, l1Associativity, l1NumSets;
148 uint32_t s, w;
149 uint32_t set_way_param;
150
151 /* ensure ordering with previous memory accesses */
152 _ARM_Data_memory_barrier();
153
154 /* Get the L1 cache properties */
155 arm_cache_l1_properties_for_level( &l1LineSize,
156 &l1Associativity, &l1NumSets,
157 ARM_CACHE_L1_CSS_ID_DATA);
158
159 for ( w = 0; w < l1Associativity; ++w ) {
160 for ( s = 0; s < l1NumSets; ++s ) {
161 set_way_param = arm_cache_l1_get_set_way_param(
162 l1LineSize,
163 l1Associativity,
164 0,
165 s,
166 w
167 );
168 arm_cp15_data_cache_invalidate_line_by_set_and_way( set_way_param );
169 }
170 }
171
172 /* Wait for L1 invalidate to complete */
173 _ARM_Data_synchronization_barrier();
174}
175
176static inline void arm_cache_l1_clean_and_invalidate_entire_data( void )
177{
178 uint32_t l1LineSize, l1Associativity, l1NumSets;
179 uint32_t s, w;
180 uint32_t set_way_param;
181
182 /* ensure ordering with previous memory accesses */
183 _ARM_Data_memory_barrier();
184
185
186 /* Get the L1 cache properties */
187 arm_cache_l1_properties_for_level( &l1LineSize,
188 &l1Associativity, &l1NumSets,
189 ARM_CACHE_L1_CSS_ID_DATA);
190
191 for ( w = 0; w < l1Associativity; ++w ) {
192 for ( s = 0; s < l1NumSets; ++s ) {
193 set_way_param = arm_cache_l1_get_set_way_param(
194 l1LineSize,
195 l1Associativity,
196 0,
197 s,
198 w
199 );
200 arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(
201 set_way_param );
202 }
203 }
204
205 /* Wait for L1 invalidate to complete */
206 _ARM_Data_synchronization_barrier();
207}
208
209static inline void arm_cache_l1_flush_data_range(
210 const void *d_addr,
211 size_t n_bytes
212)
213{
214 if ( n_bytes != 0 ) {
215 uint32_t adx = (uint32_t) d_addr
216 & ~ARM_CACHE_L1_DATA_LINE_MASK;
217 const uint32_t ADDR_LAST =
218 (uint32_t)( (size_t) d_addr + n_bytes - 1 );
219
220 arm_cache_l1_errata_764369_handler();
221
222 for (; adx <= ADDR_LAST; adx += ARM_CACHE_L1_CPU_DATA_ALIGNMENT ) {
223 /* Store and invalidate the Data cache line */
224 arm_cp15_data_cache_clean_and_invalidate_line( (void*)adx );
225 }
226 /* Wait for L1 store to complete */
227 _ARM_Data_synchronization_barrier();
228 }
229}
230
231
232static inline void arm_cache_l1_invalidate_1_data_line(
233 const void *d_addr )
234{
235 /* Invalidate the data cache line */
236 arm_cp15_data_cache_invalidate_line( d_addr );
237
238 /* Wait for L1 invalidate to complete */
239 _ARM_Data_synchronization_barrier();
240}
241
242static inline void arm_cache_l1_freeze_data( void )
243{
244 /* To be implemented as needed, if supported by hardware at all */
245}
246
247static inline void arm_cache_l1_unfreeze_data( void )
248{
249 /* To be implemented as needed, if supported by hardware at all */
250}
251
252static inline void arm_cache_l1_invalidate_1_instruction_line(
253 const void *i_addr )
254{
255 /* Invalidate the Instruction cache line */
256 arm_cp15_instruction_cache_invalidate_line( i_addr );
257
258 /* Wait for L1 invalidate to complete */
259 _ARM_Data_synchronization_barrier();
260}
261
262static inline void arm_cache_l1_invalidate_data_range(
263 const void *d_addr,
264 size_t n_bytes
265)
266{
267 if ( n_bytes != 0 ) {
268 uint32_t adx = (uint32_t) d_addr
269 & ~ARM_CACHE_L1_DATA_LINE_MASK;
270 const uint32_t end =
271 (uint32_t)( (size_t)d_addr + n_bytes -1);
272
273 arm_cache_l1_errata_764369_handler();
274
275 /* Back starting address up to start of a line and invalidate until end */
276 for (;
277 adx <= end;
279 /* Invalidate the Instruction cache line */
280 arm_cp15_data_cache_invalidate_line( (void*)adx );
281 }
282 /* Wait for L1 invalidate to complete */
283 _ARM_Data_synchronization_barrier();
284 }
285}
286
287static inline void arm_cache_l1_invalidate_instruction_range(
288 const void *i_addr,
289 size_t n_bytes
290)
291{
292 if ( n_bytes != 0 ) {
293 uint32_t adx = (uint32_t) i_addr
294 & ~ARM_CACHE_L1_INSTRUCTION_LINE_MASK;
295 const uint32_t end =
296 (uint32_t)( (size_t)i_addr + n_bytes -1);
297
298 arm_cache_l1_errata_764369_handler();
299
300 /* Back starting address up to start of a line and invalidate until end */
301 for (;
302 adx <= end;
303 adx += ARM_CACHE_L1_CPU_INSTRUCTION_ALIGNMENT ) {
304 /* Invalidate the Instruction cache line */
305 arm_cp15_instruction_cache_invalidate_line( (void*)adx );
306 }
307 /* Wait for L1 invalidate to complete */
308 _ARM_Data_synchronization_barrier();
309 }
310}
311
312static inline void arm_cache_l1_invalidate_entire_instruction( void )
313{
314 uint32_t ctrl = arm_cp15_get_control();
315
316
317 #ifdef RTEMS_SMP
318
319 /* invalidate I-cache inner shareable */
320 arm_cp15_instruction_cache_inner_shareable_invalidate_all();
321
322 /* I+BTB cache invalidate */
323 arm_cp15_instruction_cache_invalidate();
324 #else /* RTEMS_SMP */
325 /* I+BTB cache invalidate */
326 arm_cp15_instruction_cache_invalidate();
327 #endif /* RTEMS_SMP */
328
329 if ( ( ctrl & ARM_CP15_CTRL_Z ) != 0 ) {
330 #if defined(__ARM_ARCH_7A__)
331 arm_cp15_branch_predictor_inner_shareable_invalidate_all();
332 #endif
333 #if defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_7A__)
334 arm_cp15_branch_predictor_invalidate_all();
335 #endif
336 }
337}
338
339static inline void arm_cache_l1_freeze_instruction( void )
340{
341 /* To be implemented as needed, if supported by hardware at all */
342}
343
344static inline void arm_cache_l1_unfreeze_instruction( void )
345{
346 /* To be implemented as needed, if supported by hardware at all */
347}
348
349static inline void arm_cache_l1_disable_data( void )
350{
351 /* Clean and invalidate the Data cache */
352 arm_cache_l1_flush_entire_data();
353
354 /* Disable the Data cache */
355 arm_cp15_set_control( arm_cp15_get_control() & ~ARM_CP15_CTRL_C );
356}
357
358static inline void arm_cache_l1_disable_instruction( void )
359{
360 /* Synchronize the processor */
361 _ARM_Data_synchronization_barrier();
362
363 /* Invalidate the Instruction cache */
364 arm_cache_l1_invalidate_entire_instruction();
365
366 /* Disable the Instruction cache */
367 arm_cp15_set_control( arm_cp15_get_control() & ~ARM_CP15_CTRL_I );
368}
369
370static inline size_t arm_cache_l1_get_data_cache_size( void )
371{
372 size_t size;
373 uint32_t line_size = 0;
374 uint32_t associativity = 0;
375 uint32_t num_sets = 0;
376
377 arm_cache_l1_properties_for_level( &line_size,
378 &associativity, &num_sets,
379 ARM_CACHE_L1_CSS_ID_DATA);
380
381 size = (1 << line_size) * associativity * num_sets;
382
383 return size;
384}
385
386static inline size_t arm_cache_l1_get_instruction_cache_size( void )
387{
388 size_t size;
389 uint32_t line_size = 0;
390 uint32_t associativity = 0;
391 uint32_t num_sets = 0;
392
393 arm_cache_l1_properties_for_level( &line_size,
394 &associativity, &num_sets,
395 ARM_CACHE_L1_CSS_ID_INSTRUCTION);
396
397 size = (1 << line_size) * associativity * num_sets;
398
399 return size;
400}
401
402#ifdef __cplusplus
403}
404#endif /* __cplusplus */
405
406#endif /* LIBBSP_ARM_SHARED_CACHE_L1_H */
ARM co-processor 15 (CP15) API.
#define ARM_CACHE_L1_CPU_DATA_ALIGNMENT
Level 1 Cache definitions and functions.
Definition: cache-cp15.h:34
unsigned w
Definition: tlb.h:16
unsigned size
Definition: tte.h:1