1 /*
2  * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <sys/param.h>
7 #include <stdint.h>
8 #include "sdkconfig.h"
9 #include "esp_err.h"
10 #include "esp_attr.h"
11 #include "hal/assert.h"
12 #include "hal/cache_hal.h"
13 #include "hal/cache_types.h"
14 #include "hal/cache_ll.h"
15 #include "hal/mmu_hal.h"
16 #include "hal/mmu_ll.h"
17 #include "soc/soc_caps.h"
18 #include "rom/cache.h"
19 
20 /*------------------------------------------------------------------------------
21  * Unified Cache Control
22  * See cache_hal.h for more info about these HAL APIs
23  * This file is in internal RAM.
24  * Now this file doesn't compile on ESP32
25  *----------------------------------------------------------------------------*/
26 
27 /**
28  * To know if autoload is enabled or not.
29  *
30  * We should have a unified flag for this aim, then we don't need to call following 2 functions
31  * to know the flag.
32  *
33  * Suggest ROM keeping this flag value to BIT(2). Then we can replace following lines to:
34  * #define DATA_AUTOLOAD_FLAG      BIT(2)
35  * #define INST_AUTOLOAD_FLAG      BIT(2)
36  */
37 #define DATA_AUTOLOAD_FLAG      Cache_Disable_DCache()
38 #define INST_AUTOLOAD_FLAG      Cache_Disable_ICache()
39 
40 /**
41  * Necessary hal contexts, could be maintained by upper layer in the future
42  */
43 typedef struct {
44     uint32_t data_autoload_flag;
45     uint32_t inst_autoload_flag;
46 #if CACHE_LL_ENABLE_DISABLE_STATE_SW
47     // There's no register indicating if cache is enabled on these chips, use sw flag to save this state.
48     volatile bool cache_enabled;
49 #endif
50 } cache_hal_context_t;
51 
52 static cache_hal_context_t ctx;
53 
cache_hal_init(void)54 void cache_hal_init(void)
55 {
56 #if SOC_SHARED_IDCACHE_SUPPORTED
57     ctx.data_autoload_flag = INST_AUTOLOAD_FLAG;
58     Cache_Enable_ICache(ctx.data_autoload_flag);
59 #else
60     ctx.data_autoload_flag = DATA_AUTOLOAD_FLAG;
61     Cache_Enable_DCache(ctx.data_autoload_flag);
62     ctx.inst_autoload_flag = INST_AUTOLOAD_FLAG;
63     Cache_Enable_ICache(ctx.inst_autoload_flag);
64 #endif
65 
66     cache_ll_l1_enable_bus(0, CACHE_LL_DEFAULT_DBUS_MASK);
67     cache_ll_l1_enable_bus(0, CACHE_LL_DEFAULT_IBUS_MASK);
68 
69 #if !CONFIG_FREERTOS_UNICORE
70     cache_ll_l1_enable_bus(1, CACHE_LL_DEFAULT_DBUS_MASK);
71     cache_ll_l1_enable_bus(1, CACHE_LL_DEFAULT_IBUS_MASK);
72 #endif
73 
74 #if CACHE_LL_ENABLE_DISABLE_STATE_SW
75     ctx.cache_enabled = 1;
76 #endif
77 }
78 
cache_hal_disable(cache_type_t type)79 void cache_hal_disable(cache_type_t type)
80 {
81 #if SOC_SHARED_IDCACHE_SUPPORTED
82     Cache_Disable_ICache();
83 #else
84     if (type == CACHE_TYPE_DATA) {
85         Cache_Disable_DCache();
86     } else if (type == CACHE_TYPE_INSTRUCTION) {
87         Cache_Disable_ICache();
88     } else {
89         Cache_Disable_ICache();
90         Cache_Disable_DCache();
91     }
92 #endif
93 
94 #if CACHE_LL_ENABLE_DISABLE_STATE_SW
95     ctx.cache_enabled = 0;
96 #endif
97 }
98 
cache_hal_enable(cache_type_t type)99 void cache_hal_enable(cache_type_t type)
100 {
101 #if SOC_SHARED_IDCACHE_SUPPORTED
102     Cache_Enable_ICache(ctx.inst_autoload_flag);
103 #else
104     if (type == CACHE_TYPE_DATA) {
105         Cache_Enable_DCache(ctx.data_autoload_flag);
106     } else if (type == CACHE_TYPE_INSTRUCTION) {
107         Cache_Enable_ICache(ctx.inst_autoload_flag);
108     } else {
109         Cache_Enable_ICache(ctx.inst_autoload_flag);
110         Cache_Enable_DCache(ctx.data_autoload_flag);
111     }
112 #endif
113 
114 #if CACHE_LL_ENABLE_DISABLE_STATE_SW
115     ctx.cache_enabled = 1;
116 #endif
117 }
118 
cache_hal_suspend(cache_type_t type)119 void cache_hal_suspend(cache_type_t type)
120 {
121 #if SOC_SHARED_IDCACHE_SUPPORTED
122     Cache_Suspend_ICache();
123 #else
124     if (type == CACHE_TYPE_DATA) {
125         Cache_Suspend_DCache();
126     } else if (type == CACHE_TYPE_INSTRUCTION) {
127         Cache_Suspend_ICache();
128     } else {
129         Cache_Suspend_ICache();
130         Cache_Suspend_DCache();
131     }
132 #endif
133 
134 #if CACHE_LL_ENABLE_DISABLE_STATE_SW
135     ctx.cache_enabled = 0;
136 #endif
137 }
138 
cache_hal_resume(cache_type_t type)139 void cache_hal_resume(cache_type_t type)
140 {
141 #if SOC_SHARED_IDCACHE_SUPPORTED
142     Cache_Resume_ICache(ctx.inst_autoload_flag);
143 #else
144     if (type == CACHE_TYPE_DATA) {
145         Cache_Resume_DCache(ctx.data_autoload_flag);
146     } else if (type == CACHE_TYPE_INSTRUCTION) {
147         Cache_Resume_ICache(ctx.inst_autoload_flag);
148     } else {
149         Cache_Resume_ICache(ctx.inst_autoload_flag);
150         Cache_Resume_DCache(ctx.data_autoload_flag);
151     }
152 #endif
153 
154 #if CACHE_LL_ENABLE_DISABLE_STATE_SW
155     ctx.cache_enabled = 1;
156 #endif
157 }
158 
cache_hal_is_cache_enabled(cache_type_t type)159 bool cache_hal_is_cache_enabled(cache_type_t type)
160 {
161 #if CACHE_LL_ENABLE_DISABLE_STATE_SW
162     return ctx.cache_enabled;
163 #else
164     return cache_ll_l1_is_cache_enabled(0, type);
165 #endif
166 }
167 
cache_hal_invalidate_addr(uint32_t vaddr,uint32_t size)168 void cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size)
169 {
170     //Now only esp32 has 2 MMUs, this file doesn't build on esp32
171     HAL_ASSERT(mmu_hal_check_valid_ext_vaddr_region(0, vaddr, size, MMU_VADDR_DATA | MMU_VADDR_INSTRUCTION));
172     Cache_Invalidate_Addr(vaddr, size);
173 }
174 
175 #if SOC_CACHE_WRITEBACK_SUPPORTED
cache_hal_writeback_addr(uint32_t vaddr,uint32_t size)176 void cache_hal_writeback_addr(uint32_t vaddr, uint32_t size)
177 {
178     HAL_ASSERT(mmu_hal_check_valid_ext_vaddr_region(0, vaddr, size, MMU_VADDR_DATA));
179     Cache_WriteBack_Addr(vaddr, size);
180 }
181 #endif  //#if SOC_CACHE_WRITEBACK_SUPPORTED
182 
183 
184 #if SOC_CACHE_FREEZE_SUPPORTED
cache_hal_freeze(cache_type_t type)185 void cache_hal_freeze(cache_type_t type)
186 {
187 #if SOC_SHARED_IDCACHE_SUPPORTED
188     Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY);
189 #else
190     if (type == CACHE_TYPE_DATA) {
191         Cache_Freeze_DCache_Enable(CACHE_FREEZE_ACK_BUSY);
192     } else if (type == CACHE_TYPE_INSTRUCTION) {
193         Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY);
194     } else {
195         Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY);
196         Cache_Freeze_DCache_Enable(CACHE_FREEZE_ACK_BUSY);
197     }
198 #endif
199 }
200 
cache_hal_unfreeze(cache_type_t type)201 void cache_hal_unfreeze(cache_type_t type)
202 {
203 #if SOC_SHARED_IDCACHE_SUPPORTED
204     Cache_Freeze_ICache_Disable();
205 #else
206     if (type == CACHE_TYPE_DATA) {
207         Cache_Freeze_DCache_Disable();
208     } else if (type == CACHE_TYPE_INSTRUCTION) {
209         Cache_Freeze_ICache_Disable();
210     } else {
211         Cache_Freeze_DCache_Disable();
212         Cache_Freeze_ICache_Disable();
213     }
214 #endif
215 }
216 #endif  //#if SOC_CACHE_FREEZE_SUPPORTED
217 
cache_hal_get_cache_line_size(cache_type_t type)218 uint32_t cache_hal_get_cache_line_size(cache_type_t type)
219 {
220 #if SOC_SHARED_IDCACHE_SUPPORTED
221     return Cache_Get_ICache_Line_Size();
222 #else
223     uint32_t size = 0;
224     if (type == CACHE_TYPE_DATA) {
225         size = Cache_Get_DCache_Line_Size();
226     } else if (type == CACHE_TYPE_INSTRUCTION) {
227         size = Cache_Get_ICache_Line_Size();
228     } else {
229         HAL_ASSERT(false);
230     }
231     return size;
232 #endif
233 }
234