1 /*
2  * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <zephyr/kernel.h>
11 
12 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
13 #if CONFIG_SOC_SERIES_ESP32S2
14 #include "esp32s2/rom/cache.h"
15 #include <soc/extmem_reg.h>
16 #include "soc/ext_mem_defs.h"
17 #elif CONFIG_SOC_SERIES_ESP32S3
18 #include "esp32s3/rom/cache.h"
19 #include "soc/extmem_reg.h"
20 #include "soc/ext_mem_defs.h"
21 #elif CONFIG_SOC_SERIES_ESP32C2
22 #include "esp32c2/rom/cache.h"
23 #include "soc/extmem_reg.h"
24 #include "soc/ext_mem_defs.h"
25 #elif CONFIG_SOC_SERIES_ESP32C3
26 #include "esp32c3/rom/cache.h"
27 #include "soc/extmem_reg.h"
28 #include "soc/ext_mem_defs.h"
29 #elif CONFIG_SOC_SERIES_ESP32C6
30 #include "esp32c6/rom/cache.h"
31 #include "soc/extmem_reg.h"
32 #include "soc/ext_mem_defs.h"
33 #endif
34 
35 #include "esp_private/spi_flash_os.h"
36 #include "spi_flash_override.h"
37 #include "esp_rom_spiflash.h"
38 #include "hal/cache_hal.h"
39 #include "hal/cache_ll.h"
40 #include "hal/cpu_ll.h"
41 #include <soc/soc.h>
42 #include "esp_log.h"
43 
44 static __attribute__((unused)) const char *TAG = "cache";
45 
46 static void spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state);
47 static void spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
48 
49 static uint32_t s_flash_op_cache_state[2];
50 static unsigned int s_intr_saved_state;
51 
52 #ifndef CONFIG_MCUBOOT
53 
54 K_MUTEX_DEFINE(s_flash_op_mutex);
55 
spi_flash_init_lock(void)56 void spi_flash_init_lock(void)
57 {
58 
59 }
60 
spi_flash_op_lock(void)61 void spi_flash_op_lock(void)
62 {
63 	k_mutex_lock(&s_flash_op_mutex, K_FOREVER);
64 }
65 
spi_flash_op_unlock(void)66 void spi_flash_op_unlock(void)
67 {
68 	k_mutex_unlock(&s_flash_op_mutex);
69 }
70 
71 #endif
72 
spi_flash_disable_interrupts_caches_and_other_cpu(void)73 void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
74 {
75 	s_intr_saved_state = irq_lock();
76 #if !defined(CONFIG_SOC_SERIES_ESP32C2) && !defined(CONFIG_SOC_SERIES_ESP32C3) &&                  \
77 	!defined(CONFIG_SOC_SERIES_ESP32C6)
78 	esp_intr_noniram_disable();
79 #endif
80 
81 #if !defined(CONFIG_SOC_SERIES_ESP32C2) && !defined(CONFIG_SOC_SERIES_ESP32C3) &&                  \
82 	!defined(CONFIG_SOC_SERIES_ESP32C6)
83 	int cpu_id = esp_cpu_get_core_id();
84 #else
85 	int cpu_id = PRO_CPU_NUM;
86 #endif
87 	spi_flash_disable_cache(cpu_id, &s_flash_op_cache_state[cpu_id]);
88 
89 #ifdef CONFIG_SMP
90 	int other_cpu = (cpu_id == PRO_CPU_NUM) ? APP_CPU_NUM : PRO_CPU_NUM;
91 	spi_flash_disable_cache(other_cpu, &s_flash_op_cache_state[other_cpu]);
92 #endif
93 }
94 
spi_flash_enable_interrupts_caches_and_other_cpu(void)95 void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu(void)
96 {
97 #if !defined(CONFIG_SOC_SERIES_ESP32C2) && !defined(CONFIG_SOC_SERIES_ESP32C3) &&                  \
98 	!defined(CONFIG_SOC_SERIES_ESP32C6)
99 	int cpu_id = esp_cpu_get_core_id();
100 #else
101 	int cpu_id = PRO_CPU_NUM;
102 #endif
103 	spi_flash_restore_cache(cpu_id, s_flash_op_cache_state[cpu_id]);
104 
105 #if defined(CONFIG_SMP) && SOC_IDCACHE_PER_CORE
106 	int other_cpu = (cpu_id == PRO_CPU_NUM) ? APP_CPU_NUM : PRO_CPU_NUM;
107 	spi_flash_restore_cache(other_cpu, s_flash_op_cache_state[other_cpu]);
108 #endif
109 
110 #if !defined(CONFIG_SOC_SERIES_ESP32C2) && !defined(CONFIG_SOC_SERIES_ESP32C3) &&                  \
111 	!defined(CONFIG_SOC_SERIES_ESP32C6)
112 	esp_intr_noniram_enable();
113 #endif
114 	irq_unlock(s_intr_saved_state);
115 }
116 
spi_flash_enable_cache(uint32_t cpuid)117 void IRAM_ATTR spi_flash_enable_cache(uint32_t cpuid)
118 {
119 #if CONFIG_IDF_TARGET_ESP32
120 	uint32_t cache_value = cache_ll_l1_get_enabled_bus(cpuid);
121 
122 	// Re-enable cache on this CPU
123 	spi_flash_restore_cache(cpuid, cache_value);
124 #else
125 	spi_flash_restore_cache(0, 0); // TODO cache_value should be non-zero
126 #endif
127 }
128 
129 /**
130  * The following two functions are replacements for Cache_Read_Disable and Cache_Read_Enable
131  * function in ROM. They are used to work around a bug where Cache_Read_Disable requires a call to
132  * Cache_Flush before Cache_Read_Enable, even if cached data was not modified.
133  */
spi_flash_disable_cache(uint32_t cpuid,uint32_t * saved_state)134 static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state)
135 {
136 	cache_hal_suspend(CACHE_TYPE_ALL);
137 }
138 
spi_flash_restore_cache(uint32_t cpuid,uint32_t saved_state)139 static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state)
140 {
141 	cache_hal_resume(CACHE_TYPE_ALL);
142 }
143 
spi_flash_cache_enabled(void)144 bool IRAM_ATTR spi_flash_cache_enabled(void)
145 {
146 	return cache_hal_is_cache_enabled(CACHE_TYPE_ALL);
147 }
148 
149 #if CONFIG_IDF_TARGET_ESP32S2
esp_enable_cache_flash_wrap(bool icache,bool dcache)150 static IRAM_ATTR void esp_enable_cache_flash_wrap(bool icache, bool dcache)
151 {
152 	uint32_t i_autoload, d_autoload;
153 	if (icache) {
154 		i_autoload = Cache_Suspend_ICache();
155 	}
156 	if (dcache) {
157 		d_autoload = Cache_Suspend_DCache();
158 	}
159 	REG_SET_BIT(EXTMEM_PRO_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_PRO_CACHE_FLASH_WRAP_AROUND);
160 	if (icache) {
161 		Cache_Resume_ICache(i_autoload);
162 	}
163 	if (dcache) {
164 		Cache_Resume_DCache(d_autoload);
165 	}
166 }
167 
168 #if (CONFIG_IDF_TARGET_ESP32S2 && CONFIG_SPIRAM)
esp_enable_cache_spiram_wrap(bool icache,bool dcache)169 static IRAM_ATTR void esp_enable_cache_spiram_wrap(bool icache, bool dcache)
170 {
171 	uint32_t i_autoload, d_autoload;
172 	if (icache) {
173 		i_autoload = Cache_Suspend_ICache();
174 	}
175 	if (dcache) {
176 		d_autoload = Cache_Suspend_DCache();
177 	}
178 	REG_SET_BIT(EXTMEM_PRO_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_PRO_CACHE_SRAM_RD_WRAP_AROUND);
179 	if (icache) {
180 		Cache_Resume_ICache(i_autoload);
181 	}
182 	if (dcache) {
183 		Cache_Resume_DCache(d_autoload);
184 	}
185 }
186 #endif
187 
esp_enable_cache_wrap(bool icache_wrap_enable,bool dcache_wrap_enable)188 esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable)
189 {
190 	int icache_wrap_size = 0, dcache_wrap_size = 0;
191 	int flash_wrap_sizes[2] = {-1, -1}, spiram_wrap_sizes[2] = {-1, -1};
192 	int flash_wrap_size = 0, spiram_wrap_size = 0;
193 	int flash_count = 0, spiram_count = 0;
194 	int i;
195 	bool flash_spiram_wrap_together, flash_support_wrap = true, spiram_support_wrap = true;
196 	uint32_t drom0_in_icache = 1; // always 1 in esp32s2
197 #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 ||         \
198 	CONFIG_IDF_TARGET_ESP32C6
199 	drom0_in_icache = 0;
200 #endif
201 
202 	if (icache_wrap_enable) {
203 #if CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B || CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
204 		icache_wrap_size = FLASH_WRAP_SIZE_16B;
205 #else
206 		icache_wrap_size = FLASH_WRAP_SIZE_32B;
207 #endif
208 	}
209 	if (dcache_wrap_enable) {
210 #if CONFIG_ESP32S2_DATA_CACHE_LINE_16B || CONFIG_ESP32S3_DATA_CACHE_LINE_16B
211 		dcache_wrap_size = FLASH_WRAP_SIZE_16B;
212 #else
213 		dcache_wrap_size = FLASH_WRAP_SIZE_32B;
214 #endif
215 	}
216 
217 	uint32_t instruction_use_spiram = 0;
218 	uint32_t rodata_use_spiram = 0;
219 #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
220 	extern uint32_t esp_spiram_instruction_access_enabled(void);
221 	instruction_use_spiram = esp_spiram_instruction_access_enabled();
222 #endif
223 #if CONFIG_SPIRAM_RODATA
224 	extern uint32_t esp_spiram_rodata_access_enabled(void);
225 	rodata_use_spiram = esp_spiram_rodata_access_enabled();
226 #endif
227 
228 	if (instruction_use_spiram) {
229 		spiram_wrap_sizes[0] = icache_wrap_size;
230 	} else {
231 		flash_wrap_sizes[0] = icache_wrap_size;
232 	}
233 	if (rodata_use_spiram) {
234 		if (drom0_in_icache) {
235 			spiram_wrap_sizes[0] = icache_wrap_size;
236 		} else {
237 			spiram_wrap_sizes[1] = dcache_wrap_size;
238 			flash_wrap_sizes[1] = dcache_wrap_size;
239 		}
240 	} else {
241 		if (drom0_in_icache) {
242 			flash_wrap_sizes[0] = icache_wrap_size;
243 		} else {
244 			flash_wrap_sizes[1] = dcache_wrap_size;
245 		}
246 	}
247 #if (CONFIG_IDF_TARGET_ESP32S2 && CONFIG_SPIRAM)
248 	spiram_wrap_sizes[1] = dcache_wrap_size;
249 #endif
250 	for (i = 0; i < 2; i++) {
251 		if (flash_wrap_sizes[i] != -1) {
252 			flash_count++;
253 			flash_wrap_size = flash_wrap_sizes[i];
254 		}
255 	}
256 	for (i = 0; i < 2; i++) {
257 		if (spiram_wrap_sizes[i] != -1) {
258 			spiram_count++;
259 			spiram_wrap_size = spiram_wrap_sizes[i];
260 		}
261 	}
262 	if (flash_count + spiram_count <= 2) {
263 		flash_spiram_wrap_together = false;
264 	} else {
265 		flash_spiram_wrap_together = true;
266 	}
267 	ESP_EARLY_LOGI(TAG, "flash_count=%d, size=%d, spiram_count=%d, size=%d,together=%d",
268 		       flash_count, flash_wrap_size, spiram_count, spiram_wrap_size,
269 		       flash_spiram_wrap_together);
270 	if (flash_count > 1 && flash_wrap_sizes[0] != flash_wrap_sizes[1]) {
271 		ESP_EARLY_LOGW(TAG, "Flash wrap with different length %d and %d, abort wrap.",
272 			       flash_wrap_sizes[0], flash_wrap_sizes[1]);
273 		if (spiram_wrap_size == 0) {
274 			return ESP_FAIL;
275 		}
276 		if (flash_spiram_wrap_together) {
277 			ESP_EARLY_LOGE(TAG,
278 				       "Abort spiram wrap because flash wrap length not fixed.");
279 			return ESP_FAIL;
280 		}
281 	}
282 	if (spiram_count > 1 && spiram_wrap_sizes[0] != spiram_wrap_sizes[1]) {
283 		ESP_EARLY_LOGW(TAG, "SPIRAM wrap with different length %d and %d, abort wrap.",
284 			       spiram_wrap_sizes[0], spiram_wrap_sizes[1]);
285 		if (flash_wrap_size == 0) {
286 			return ESP_FAIL;
287 		}
288 		if (flash_spiram_wrap_together) {
289 			ESP_EARLY_LOGW(TAG,
290 				       "Abort flash wrap because spiram wrap length not fixed.");
291 			return ESP_FAIL;
292 		}
293 	}
294 
295 	if (flash_spiram_wrap_together && flash_wrap_size != spiram_wrap_size) {
296 		ESP_EARLY_LOGW(
297 			TAG, "SPIRAM has different wrap length with flash, %d and %d, abort wrap.",
298 			spiram_wrap_size, flash_wrap_size);
299 		return ESP_FAIL;
300 	}
301 
302 #ifdef CONFIG_ESPTOOLPY_FLASHMODE_QIO
303 	flash_support_wrap = true;
304 	spi_flash_wrap_probe();
305 	if (!spi_flash_support_wrap_size(flash_wrap_size)) {
306 		flash_support_wrap = false;
307 		ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
308 	}
309 #else
310 	ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
311 #endif
312 
313 #if (CONFIG_IDF_TARGET_ESP32S2 && CONFIG_SPIRAM)
314 	extern bool psram_support_wrap_size(uint32_t wrap_size);
315 	if (!psram_support_wrap_size(spiram_wrap_size)) {
316 		spiram_support_wrap = false;
317 		ESP_EARLY_LOGW(TAG, "SPIRAM do not support wrap size %d.", spiram_wrap_size);
318 	}
319 #endif
320 
321 	if (flash_spiram_wrap_together && !(flash_support_wrap && spiram_support_wrap)) {
322 		ESP_EARLY_LOGW(TAG, "Flash and SPIRAM should support wrap together.");
323 		return ESP_FAIL;
324 	}
325 
326 	if (flash_support_wrap && flash_wrap_size > 0) {
327 		ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
328 		spi_flash_wrap_enable(flash_wrap_size);
329 		esp_enable_cache_flash_wrap((flash_wrap_sizes[0] > 0), (flash_wrap_sizes[1] > 0));
330 	}
331 #if (CONFIG_IDF_TARGET_ESP32S2 && CONFIG_SPIRAM)
332 	extern esp_err_t psram_enable_wrap(uint32_t wrap_size);
333 	if (spiram_support_wrap && spiram_wrap_size > 0) {
334 		ESP_EARLY_LOGI(TAG, "SPIRAM wrap enabled, size = %d.", spiram_wrap_size);
335 		psram_enable_wrap(spiram_wrap_size);
336 		esp_enable_cache_spiram_wrap((spiram_wrap_sizes[0] > 0),
337 					     (spiram_wrap_sizes[1] > 0));
338 	}
339 #endif
340 
341 	return ESP_OK;
342 }
343 #endif
344 #if CONFIG_IDF_TARGET_ESP32S3
esp_enable_cache_flash_wrap(bool icache,bool dcache)345 static IRAM_ATTR void esp_enable_cache_flash_wrap(bool icache, bool dcache)
346 {
347     uint32_t i_autoload, d_autoload;
348     if (icache) {
349         i_autoload = Cache_Suspend_ICache();
350     }
351     if (dcache) {
352         d_autoload = Cache_Suspend_DCache();
353     }
354     REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_FLASH_WRAP_AROUND);
355     if (icache) {
356         Cache_Resume_ICache(i_autoload);
357     }
358     if (dcache) {
359         Cache_Resume_DCache(d_autoload);
360     }
361 }
362 
363 #if (CONFIG_IDF_TARGET_ESP32S3 && CONFIG_SPIRAM)
esp_enable_cache_spiram_wrap(bool icache,bool dcache)364 static IRAM_ATTR void esp_enable_cache_spiram_wrap(bool icache, bool dcache)
365 {
366     uint32_t i_autoload, d_autoload;
367     if (icache) {
368         i_autoload = Cache_Suspend_ICache();
369     }
370     if (dcache) {
371         d_autoload = Cache_Suspend_DCache();
372     }
373     REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_SRAM_RD_WRAP_AROUND);
374     if (icache) {
375         Cache_Resume_ICache(i_autoload);
376     }
377     if (dcache) {
378         Cache_Resume_DCache(d_autoload);
379     }
380 }
381 #endif
382 
esp_enable_cache_wrap(bool icache_wrap_enable,bool dcache_wrap_enable)383 esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable)
384 {
385     int icache_wrap_size = 0, dcache_wrap_size = 0;
386     int flash_wrap_sizes[2] = {-1, -1}, spiram_wrap_sizes[2] = {-1, -1};
387     int flash_wrap_size = 0, spiram_wrap_size = 0;
388     int flash_count = 0, spiram_count = 0;
389     int i;
390     bool flash_spiram_wrap_together, flash_support_wrap = false, spiram_support_wrap = true;
391     uint32_t drom0_in_icache = 0;//always 0 in chip7.2.4
392 
393     if (icache_wrap_enable) {
394 #if CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
395         icache_wrap_size = FLASH_WRAP_SIZE_16B;
396 #elif CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B
397         icache_wrap_size = FLASH_WRAP_SIZE_32B;
398 #else
399         icache_wrap_size = FLASH_WRAP_SIZE_64B;
400 #endif
401     }
402     if (dcache_wrap_enable) {
403 #if CONFIG_ESP32S3_DATA_CACHE_LINE_16B
404         dcache_wrap_size = FLASH_WRAP_SIZE_16B;
405 #elif CONFIG_ESP32S3_DATA_CACHE_LINE_32B
406         dcache_wrap_size = FLASH_WRAP_SIZE_32B;
407 #else
408         dcache_wrap_size = FLASH_WRAP_SIZE_64B;
409 #endif
410     }
411 
412     uint32_t instruction_use_spiram = 0;
413     uint32_t rodata_use_spiram = 0;
414 #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
415     extern uint32_t esp_spiram_instruction_access_enabled(void);
416     instruction_use_spiram = esp_spiram_instruction_access_enabled();
417 #endif
418 #if CONFIG_SPIRAM_RODATA
419     extern uint32_t esp_spiram_rodata_access_enabled(void);
420     rodata_use_spiram = esp_spiram_rodata_access_enabled();
421 #endif
422 
423     if (instruction_use_spiram) {
424         spiram_wrap_sizes[0] = icache_wrap_size;
425     } else {
426         flash_wrap_sizes[0] = icache_wrap_size;
427     }
428     if (rodata_use_spiram) {
429         if (drom0_in_icache) {
430             spiram_wrap_sizes[0] = icache_wrap_size;
431         } else {
432             spiram_wrap_sizes[1] = dcache_wrap_size;
433         }
434     } else {
435         if (drom0_in_icache) {
436             flash_wrap_sizes[0] = icache_wrap_size;
437         } else {
438             flash_wrap_sizes[1] = dcache_wrap_size;
439         }
440     }
441 #if (CONFIG_IDF_TARGET_ESP32S3 && CONFIG_SPIRAM)
442     spiram_wrap_sizes[1] = dcache_wrap_size;
443 #endif
444     for (i = 0; i < 2; i++) {
445         if (flash_wrap_sizes[i] != -1) {
446             flash_count++;
447             flash_wrap_size = flash_wrap_sizes[i];
448         }
449     }
450     for (i = 0; i < 2; i++) {
451         if (spiram_wrap_sizes[i] != -1) {
452             spiram_count++;
453             spiram_wrap_size = spiram_wrap_sizes[i];
454         }
455     }
456     if (flash_count + spiram_count <= 2) {
457         flash_spiram_wrap_together = false;
458     } else {
459         flash_spiram_wrap_together = true;
460     }
461     if (flash_count > 1 && flash_wrap_sizes[0] != flash_wrap_sizes[1]) {
462         ESP_EARLY_LOGW(TAG, "Flash wrap with different length %d and %d, abort wrap.", flash_wrap_sizes[0], flash_wrap_sizes[1]);
463         if (spiram_wrap_size == 0) {
464             return ESP_FAIL;
465         }
466         if (flash_spiram_wrap_together) {
467             ESP_EARLY_LOGE(TAG, "Abort spiram wrap because flash wrap length not fixed.");
468             return ESP_FAIL;
469         }
470     }
471     if (spiram_count > 1 && spiram_wrap_sizes[0] != spiram_wrap_sizes[1]) {
472         ESP_EARLY_LOGW(TAG, "SPIRAM wrap with different length %d and %d, abort wrap.", spiram_wrap_sizes[0], spiram_wrap_sizes[1]);
473         if (flash_wrap_size == 0) {
474             return ESP_FAIL;
475         }
476         if (flash_spiram_wrap_together) {
477             ESP_EARLY_LOGW(TAG, "Abort flash wrap because spiram wrap length not fixed.");
478             return ESP_FAIL;
479         }
480     }
481 
482     if (flash_spiram_wrap_together && flash_wrap_size != spiram_wrap_size) {
483         ESP_EARLY_LOGW(TAG, "SPIRAM has different wrap length with flash, %d and %d, abort wrap.", spiram_wrap_size, flash_wrap_size);
484         return ESP_FAIL;
485     }
486 
487 #ifdef CONFIG_ESPTOOLPY_FLASHMODE_QIO
488     flash_support_wrap = true;
489     spi_flash_wrap_probe();
490     if (!spi_flash_support_wrap_size(flash_wrap_size)) {
491         flash_support_wrap = false;
492         ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
493     }
494 #else
495     ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
496 #endif
497 
498 
499 #if (CONFIG_IDF_TARGET_ESP32S3 && CONFIG_SPIRAM)
500     extern bool psram_support_wrap_size(uint32_t wrap_size);
501     if (!psram_support_wrap_size(spiram_wrap_size)) {
502         spiram_support_wrap = false;
503         ESP_EARLY_LOGW(TAG, "SPIRAM do not support wrap size %d.", spiram_wrap_size);
504     }
505 #endif
506 
507     if (flash_spiram_wrap_together && !(flash_support_wrap && spiram_support_wrap)) {
508         ESP_EARLY_LOGW(TAG, "Flash and SPIRAM should support wrap together.");
509         return ESP_FAIL;
510     }
511 
512     if (flash_support_wrap && flash_wrap_size > 0) {
513         ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
514         spi_flash_wrap_enable(flash_wrap_size);
515         esp_enable_cache_flash_wrap((flash_wrap_sizes[0] > 0), (flash_wrap_sizes[1] > 0));
516     }
517 #if (CONFIG_IDF_TARGET_ESP32S3 && CONFIG_SPIRAM)
518     extern esp_err_t psram_enable_wrap(uint32_t wrap_size);
519     if (spiram_support_wrap && spiram_wrap_size > 0) {
520         ESP_EARLY_LOGI(TAG, "SPIRAM wrap enabled, size = %d.", spiram_wrap_size);
521         psram_enable_wrap(spiram_wrap_size);
522         esp_enable_cache_spiram_wrap((spiram_wrap_sizes[0] > 0), (spiram_wrap_sizes[1] > 0));
523     }
524 #endif
525 
526     return ESP_OK;
527 
528 }
529 #endif
530 
531 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
532 
esp_enable_cache_flash_wrap(bool icache)533 static IRAM_ATTR void esp_enable_cache_flash_wrap(bool icache)
534 {
535 	uint32_t i_autoload;
536 	if (icache) {
537 		i_autoload = Cache_Suspend_ICache();
538 	}
539 	REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_FLASH_WRAP_AROUND);
540 	if (icache) {
541 		Cache_Resume_ICache(i_autoload);
542 	}
543 }
544 
esp_enable_cache_wrap(bool icache_wrap_enable)545 esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable)
546 {
547 	int flash_wrap_size = 0;
548 	bool flash_support_wrap = false;
549 
550 	if (icache_wrap_enable) {
551 		flash_wrap_size = 32;
552 	}
553 
554 #ifdef CONFIG_ESPTOOLPY_FLASHMODE_QIO
555 	flash_support_wrap = true;
556 	spi_flash_wrap_probe();
557 	if (!spi_flash_support_wrap_size(flash_wrap_size)) {
558 		flash_support_wrap = false;
559 		ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
560 	}
561 #else
562 	ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
563 #endif // CONFIG_ESPTOOLPY_FLASHMODE_QIO
564 
565 	if (flash_support_wrap && flash_wrap_size > 0) {
566 		ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
567 		spi_flash_wrap_enable(flash_wrap_size);
568 		esp_enable_cache_flash_wrap((flash_wrap_size > 0));
569 	}
570 	return ESP_OK;
571 }
572 #endif // CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
573