1 /*
2 * Copyright (c) 2015 Wind River Systems, Inc.
3 * Copyright (c) 2022 Carlo Caione <ccaione@baylibre.com>
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #ifndef ZEPHYR_INCLUDE_CACHE_H_
9 #define ZEPHYR_INCLUDE_CACHE_H_
10
11 /**
12 * @file
13 * @brief cache API interface
14 */
15
16 #include <zephyr/kernel.h>
17 #include <zephyr/arch/cpu.h>
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 #if defined(CONFIG_EXTERNAL_CACHE)
24 #include <zephyr/drivers/cache.h>
25
26 #elif defined(CONFIG_ARCH_CACHE)
27 #include <zephyr/arch/cache.h>
28
29 #endif
30
31 /**
32 * @defgroup cache_interface Cache Interface
33 * @ingroup os_services
34 * @{
35 */
36
37 /**
38 * @cond INTERNAL_HIDDEN
39 *
40 */
41
42 #define _CPU DT_PATH(cpus, cpu_0)
43
44 /** @endcond */
45
46 /**
47 * @brief Enable the d-cache
48 *
49 * Enable the data cache
50 *
51 */
sys_cache_data_enable(void)52 static ALWAYS_INLINE void sys_cache_data_enable(void)
53 {
54 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
55 cache_data_enable();
56 #endif
57 }
58
59 /**
60 * @brief Disable the d-cache
61 *
62 * Disable the data cache
63 *
64 */
sys_cache_data_disable(void)65 static ALWAYS_INLINE void sys_cache_data_disable(void)
66 {
67 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
68 cache_data_disable();
69 #endif
70 }
71
72 /**
73 * @brief Enable the i-cache
74 *
75 * Enable the instruction cache
76 *
77 */
sys_cache_instr_enable(void)78 static ALWAYS_INLINE void sys_cache_instr_enable(void)
79 {
80 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
81 cache_instr_enable();
82 #endif
83 }
84
85 /**
86 * @brief Disable the i-cache
87 *
88 * Disable the instruction cache
89 *
90 */
sys_cache_instr_disable(void)91 static ALWAYS_INLINE void sys_cache_instr_disable(void)
92 {
93 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
94 cache_instr_disable();
95 #endif
96 }
97
98 /**
99 * @brief Flush the d-cache
100 *
101 * Flush the whole data cache.
102 *
103 * @retval 0 If succeeded.
104 * @retval -ENOTSUP If not supported.
105 * @retval -errno Negative errno for other failures.
106 */
sys_cache_data_flush_all(void)107 static ALWAYS_INLINE int sys_cache_data_flush_all(void)
108 {
109 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
110 return cache_data_flush_all();
111 #endif
112 return -ENOTSUP;
113 }
114
115 /**
116 * @brief Flush the i-cache
117 *
118 * Flush the whole instruction cache.
119 *
120 * @retval 0 If succeeded.
121 * @retval -ENOTSUP If not supported.
122 * @retval -errno Negative errno for other failures.
123 */
sys_cache_instr_flush_all(void)124 static ALWAYS_INLINE int sys_cache_instr_flush_all(void)
125 {
126 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
127 return cache_instr_flush_all();
128 #endif
129 return -ENOTSUP;
130 }
131
132 /**
133 * @brief Invalidate the d-cache
134 *
135 * Invalidate the whole data cache.
136 *
137 * @retval 0 If succeeded.
138 * @retval -ENOTSUP If not supported.
139 * @retval -errno Negative errno for other failures.
140 */
sys_cache_data_invd_all(void)141 static ALWAYS_INLINE int sys_cache_data_invd_all(void)
142 {
143 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
144 return cache_data_invd_all();
145 #endif
146 return -ENOTSUP;
147 }
148
149 /**
150 * @brief Invalidate the i-cache
151 *
152 * Invalidate the whole instruction cache.
153 *
154 * @retval 0 If succeeded.
155 * @retval -ENOTSUP If not supported.
156 * @retval -errno Negative errno for other failures.
157 */
sys_cache_instr_invd_all(void)158 static ALWAYS_INLINE int sys_cache_instr_invd_all(void)
159 {
160 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
161 return cache_instr_invd_all();
162 #endif
163 return -ENOTSUP;
164 }
165
166 /**
167 * @brief Flush and Invalidate the d-cache
168 *
169 * Flush and Invalidate the whole data cache.
170 *
171 * @retval 0 If succeeded.
172 * @retval -ENOTSUP If not supported.
173 * @retval -errno Negative errno for other failures.
174 */
sys_cache_data_flush_and_invd_all(void)175 static ALWAYS_INLINE int sys_cache_data_flush_and_invd_all(void)
176 {
177 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
178 return cache_data_flush_and_invd_all();
179 #endif
180 return -ENOTSUP;
181 }
182
183 /**
184 * @brief Flush and Invalidate the i-cache
185 *
186 * Flush and Invalidate the whole instruction cache.
187 *
188 * @retval 0 If succeeded.
189 * @retval -ENOTSUP If not supported.
190 * @retval -errno Negative errno for other failures.
191 */
sys_cache_instr_flush_and_invd_all(void)192 static ALWAYS_INLINE int sys_cache_instr_flush_and_invd_all(void)
193 {
194 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
195 return cache_instr_flush_and_invd_all();
196 #endif
197 return -ENOTSUP;
198 }
199
200 /**
201 * @brief Flush an address range in the d-cache
202 *
203 * Flush the specified address range of the data cache.
204 *
205 * @param addr Starting address to flush.
206 * @param size Range size.
207 *
208 * @retval 0 If succeeded.
209 * @retval -ENOTSUP If not supported.
210 * @retval -errno Negative errno for other failures.
211 */
212 __syscall_always_inline int sys_cache_data_flush_range(void *addr, size_t size);
213
z_impl_sys_cache_data_flush_range(void * addr,size_t size)214 static ALWAYS_INLINE int z_impl_sys_cache_data_flush_range(void *addr, size_t size)
215 {
216 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
217 return cache_data_flush_range(addr, size);
218 #endif
219 ARG_UNUSED(addr);
220 ARG_UNUSED(size);
221
222 return -ENOTSUP;
223 }
224
225 /**
226 * @brief Flush an address range in the i-cache
227 *
228 * Flush the specified address range of the instruction cache.
229 *
230 * @param addr Starting address to flush.
231 * @param size Range size.
232 *
233 * @retval 0 If succeeded.
234 * @retval -ENOTSUP If not supported.
235 * @retval -errno Negative errno for other failures.
236 */
sys_cache_instr_flush_range(void * addr,size_t size)237 static ALWAYS_INLINE int sys_cache_instr_flush_range(void *addr, size_t size)
238 {
239 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
240 return cache_instr_flush_range(addr, size);
241 #endif
242 ARG_UNUSED(addr);
243 ARG_UNUSED(size);
244
245 return -ENOTSUP;
246 }
247
248 /**
249 * @brief Invalidate an address range in the d-cache
250 *
251 * Invalidate the specified address range of the data cache.
252 *
253 * @param addr Starting address to invalidate.
254 * @param size Range size.
255 *
256 * @retval 0 If succeeded.
257 * @retval -ENOTSUP If not supported.
258 * @retval -errno Negative errno for other failures.
259 */
260 __syscall_always_inline int sys_cache_data_invd_range(void *addr, size_t size);
261
z_impl_sys_cache_data_invd_range(void * addr,size_t size)262 static ALWAYS_INLINE int z_impl_sys_cache_data_invd_range(void *addr, size_t size)
263 {
264 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
265 return cache_data_invd_range(addr, size);
266 #endif
267 ARG_UNUSED(addr);
268 ARG_UNUSED(size);
269
270 return -ENOTSUP;
271 }
272
273 /**
274 * @brief Invalidate an address range in the i-cache
275 *
276 * Invalidate the specified address range of the instruction cache.
277 *
278 * @param addr Starting address to invalidate.
279 * @param size Range size.
280 *
281 * @retval 0 If succeeded.
282 * @retval -ENOTSUP If not supported.
283 * @retval -errno Negative errno for other failures.
284 */
sys_cache_instr_invd_range(void * addr,size_t size)285 static ALWAYS_INLINE int sys_cache_instr_invd_range(void *addr, size_t size)
286 {
287 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
288 return cache_instr_invd_range(addr, size);
289 #endif
290 ARG_UNUSED(addr);
291 ARG_UNUSED(size);
292
293 return -ENOTSUP;
294 }
295
296 /**
297 * @brief Flush and Invalidate an address range in the d-cache
298 *
299 * Flush and Invalidate the specified address range of the data cache.
300 *
301 * @param addr Starting address to flush and invalidate.
302 * @param size Range size.
303 *
304 * @retval 0 If succeeded.
305 * @retval -ENOTSUP If not supported.
306 * @retval -errno Negative errno for other failures.
307 */
308 __syscall_always_inline int sys_cache_data_flush_and_invd_range(void *addr, size_t size);
309
z_impl_sys_cache_data_flush_and_invd_range(void * addr,size_t size)310 static ALWAYS_INLINE int z_impl_sys_cache_data_flush_and_invd_range(void *addr, size_t size)
311 {
312 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_DCACHE)
313 return cache_data_flush_and_invd_range(addr, size);
314 #endif
315 ARG_UNUSED(addr);
316 ARG_UNUSED(size);
317
318 return -ENOTSUP;
319 }
320
321 /**
322 * @brief Flush and Invalidate an address range in the i-cache
323 *
324 * Flush and Invalidate the specified address range of the instruction cache.
325 *
326 * @param addr Starting address to flush and invalidate.
327 * @param size Range size.
328 *
329 * @retval 0 If succeeded.
330 * @retval -ENOTSUP If not supported.
331 * @retval -errno Negative errno for other failures.
332 */
sys_cache_instr_flush_and_invd_range(void * addr,size_t size)333 static ALWAYS_INLINE int sys_cache_instr_flush_and_invd_range(void *addr, size_t size)
334 {
335 #if defined(CONFIG_CACHE_MANAGEMENT) && defined(CONFIG_ICACHE)
336 return cache_instr_flush_and_invd_range(addr, size);
337 #endif
338 ARG_UNUSED(addr);
339 ARG_UNUSED(size);
340
341 return -ENOTSUP;
342 }
343
344 /**
345 *
346 * @brief Get the the d-cache line size.
347 *
348 * The API is provided to get the data cache line.
349 *
350 * The cache line size is calculated (in order of priority):
351 *
352 * - At run-time when @kconfig{CONFIG_DCACHE_LINE_SIZE_DETECT} is set.
353 * - At compile time using the value set in @kconfig{CONFIG_DCACHE_LINE_SIZE}.
354 * - At compile time using the `d-cache-line-size` CPU0 property of the DT.
355 * - 0 otherwise
356 *
357 * @retval size Size of the d-cache line.
358 * @retval 0 If the d-cache is not enabled.
359 */
sys_cache_data_line_size_get(void)360 static ALWAYS_INLINE size_t sys_cache_data_line_size_get(void)
361 {
362 #ifdef CONFIG_DCACHE_LINE_SIZE_DETECT
363 return cache_data_line_size_get();
364 #elif (CONFIG_DCACHE_LINE_SIZE != 0)
365 return CONFIG_DCACHE_LINE_SIZE;
366 #else
367 return DT_PROP_OR(_CPU, d_cache_line_size, 0);
368 #endif
369 }
370
371 /**
372 *
373 * @brief Get the the i-cache line size.
374 *
375 * The API is provided to get the instruction cache line.
376 *
377 * The cache line size is calculated (in order of priority):
378 *
379 * - At run-time when @kconfig{CONFIG_ICACHE_LINE_SIZE_DETECT} is set.
380 * - At compile time using the value set in @kconfig{CONFIG_ICACHE_LINE_SIZE}.
381 * - At compile time using the `i-cache-line-size` CPU0 property of the DT.
382 * - 0 otherwise
383 *
384 * @retval size Size of the d-cache line.
385 * @retval 0 If the d-cache is not enabled.
386 */
sys_cache_instr_line_size_get(void)387 static ALWAYS_INLINE size_t sys_cache_instr_line_size_get(void)
388 {
389 #ifdef CONFIG_ICACHE_LINE_SIZE_DETECT
390 return cache_instr_line_size_get();
391 #elif (CONFIG_ICACHE_LINE_SIZE != 0)
392 return CONFIG_ICACHE_LINE_SIZE;
393 #else
394 return DT_PROP_OR(_CPU, i_cache_line_size, 0);
395 #endif
396 }
397
398 #ifdef CONFIG_LIBMETAL
sys_cache_flush(void * addr,size_t size)399 static ALWAYS_INLINE void sys_cache_flush(void *addr, size_t size)
400 {
401 sys_cache_data_flush_range(addr, size);
402 }
403 #endif
404
405 #include <syscalls/cache.h>
406 #ifdef __cplusplus
407 }
408 #endif
409
410 /**
411 * @}
412 */
413
414 #endif /* ZEPHYR_INCLUDE_CACHE_H_ */
415