1 /**************************************************************************//**
2 * @file cache_armv8a.h
3 * @brief CMSIS AARCH64 Cache API header file
4 * @version V1.0.0
5 * @date 21. January 2022
6 ******************************************************************************/
7
8 /*
9 * Copyright 2022 NXP
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 */
13
14 #if defined ( __ICCARM__ )
15 #pragma system_include /* treat file as system include file for MISRA check */
16 #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
17 #pragma clang system_header /* treat file as system include file */
18 #endif
19
20 #ifndef __CACHE_ARMV8A_H
21 #define __CACHE_ARMV8A_H
22
23 #include <stdbool.h>
24 #include <stddef.h>
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 #define dcache_ops(op, operand) \
31 ({ \
32 __asm__ volatile ("dc " __STRINGIFY(op) ", %0" \
33 ::"r" (operand): "memory"); \
34 })
35
36
37 /* Invalidate instruction cache by virtual address to PoU */
icache_invalidate_range(uintptr_t addr,size_t size)38 static inline void icache_invalidate_range(uintptr_t addr, size_t size)
39 {
40 uintptr_t cur = addr;
41 uintptr_t end_addr = cur + size;
42
43 /* Align address to line size */
44 cur &= ~(ICACHE_LINE_SIZE - 1);
45
46 do {
47 __asm__ volatile ("ic ivau, %0" ::"r" (cur): "memory");
48 cur += ICACHE_LINE_SIZE;
49 } while (cur < end_addr);
50
51 __DSB();
52 __ISB();
53 }
54
55 /* Invalidate all instruction cache to PoU */
icache_invalidate_all(void)56 static inline void icache_invalidate_all(void)
57 {
58 __asm__ volatile ("ic iallu" ::: "memory");
59 __DSB();
60 __ISB();
61 }
62
63 /* Clean data cache by virtual address to PoC */
dcache_clean_range(uintptr_t addr,size_t size)64 static inline void dcache_clean_range(uintptr_t addr, size_t size)
65 {
66 uintptr_t cur = addr;
67 uintptr_t end = addr + size;
68
69 /* Align address to line size */
70 cur &= ~(DCACHE_LINE_SIZE - 1);
71
72 while (cur < end) {
73 dcache_ops(cvac, cur);
74 cur += DCACHE_LINE_SIZE;
75 }
76
77 __DSB();
78 }
79
80 /* Invalidate data cache by virtual address to PoC */
dcache_invalidate_range(uintptr_t addr,size_t size)81 static inline void dcache_invalidate_range(uintptr_t addr, size_t size)
82 {
83 uintptr_t cur = addr;
84 uintptr_t end = addr + size;
85
86 if (end & (DCACHE_LINE_SIZE - 1)) {
87 end &= ~(DCACHE_LINE_SIZE - 1);
88 dcache_ops(civac, end);
89 }
90
91 if (cur & (DCACHE_LINE_SIZE - 1)) {
92 cur &= ~(DCACHE_LINE_SIZE - 1);
93 if (cur != end)
94 dcache_ops(civac, cur);
95 cur += DCACHE_LINE_SIZE;
96 }
97
98 while (cur < end) {
99 dcache_ops(ivac, cur);
100 cur += DCACHE_LINE_SIZE;
101 }
102
103 __DSB();
104 }
105
106 /* Clean and invalidate data cache by virtual address to PoC */
dcache_clean_invalidate_range(uintptr_t addr,size_t size)107 static inline void dcache_clean_invalidate_range(uintptr_t addr, size_t size)
108 {
109 uintptr_t cur = addr;
110 uintptr_t end = addr + size;
111
112 /* Align address to line size */
113 cur &= ~(DCACHE_LINE_SIZE - 1);
114
115 while (cur < end) {
116 dcache_ops(civac, cur);
117 cur += DCACHE_LINE_SIZE;
118 }
119
120 __DSB();
121 }
122
123 void dcache_clean_all(void);
124 void dcache_invalidate_all(void);
125 void dcache_clean_invalidate_all(void);
126
127 #ifdef __cplusplus
128 }
129 #endif
130
131 #endif /* __CACHE_ARMV8A_H */
132