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