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