1 /*
2 * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "sdkconfig.h"
8 #include <stdint.h>
9 #include "soc/soc_caps.h"
10 #include "esp_rom_caps.h"
11 #include "soc/extmem_reg.h"
12 #include "xtensa/xtruntime.h"
13 #if CONFIG_IDF_TARGET_ESP32S3
14 #include "esp32s3/rom/cache.h"
15 #endif
16
17 #define ALIGN_UP(addr, align) (((addr) + (align)-1) & ~((align)-1))
18 #define ALIGN_DOWN(addr, align) ((addr) & ~((align) - 1))
19
20 // this api is renamed for patch
21 extern uint32_t rom_Cache_Count_Flash_Pages(uint32_t bus, uint32_t * page0_mapped);
Cache_Count_Flash_Pages(uint32_t bus,uint32_t * page0_mapped)22 uint32_t Cache_Count_Flash_Pages(uint32_t bus, uint32_t * page0_mapped)
23 {
24 uint32_t page0_before_count = *page0_mapped;
25 uint32_t flash_pages = 0;
26 flash_pages = rom_Cache_Count_Flash_Pages(bus, page0_mapped);
27
28 /* No page mapped to page0, in this condition, the rom api will return
29 * unexpected value + 1.
30 */
31 if (page0_before_count == *page0_mapped) {
32 flash_pages--;
33 }
34 return flash_pages;
35 }
36 extern uint32_t Cache_Count_Flash_Pages(uint32_t bus, uint32_t * page0_mapped);
37
38 #if ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG
Cache_Wait_Idle(int icache)39 static inline void Cache_Wait_Idle(int icache)
40 {
41 if (icache) {
42 while (REG_GET_FIELD(EXTMEM_CACHE_STATE_REG, EXTMEM_ICACHE_STATE) != 1) {
43 ;
44 }
45 } else {
46 while (REG_GET_FIELD(EXTMEM_CACHE_STATE_REG, EXTMEM_DCACHE_STATE) != 1) {
47 ;
48 }
49 }
50 }
51 // renamed for patch
52 extern uint32_t rom_Cache_Suspend_ICache(void);
Cache_Suspend_ICache(void)53 uint32_t Cache_Suspend_ICache(void)
54 {
55 uint32_t ret = rom_Cache_Suspend_ICache();
56 Cache_Wait_Idle(1);
57 return ret;
58 }
59 extern uint32_t Cache_Suspend_ICache(void);
60
61 // renamed for patch
62 extern uint32_t rom_Cache_Suspend_DCache(void);
Cache_Suspend_DCache(void)63 uint32_t Cache_Suspend_DCache(void)
64 {
65 uint32_t ret = rom_Cache_Suspend_DCache();
66 Cache_Wait_Idle(0);
67 return ret;
68 }
69 extern uint32_t Cache_Suspend_DCache(void);
70
71 #if SOC_CACHE_FREEZE_SUPPORTED
72 // renamed for patch
73 extern void rom_Cache_Freeze_ICache_Enable(cache_freeze_mode_t mode);
Cache_Freeze_ICache_Enable(cache_freeze_mode_t mode)74 void Cache_Freeze_ICache_Enable(cache_freeze_mode_t mode)
75 {
76 rom_Cache_Freeze_ICache_Enable(mode);
77 Cache_Wait_Idle(1);
78 }
79 extern void Cache_Freeze_ICache_Enable(cache_freeze_mode_t mode);
80
81 // renamed for patch
82 extern void rom_Cache_Freeze_DCache_Enable(cache_freeze_mode_t mode);
Cache_Freeze_DCache_Enable(cache_freeze_mode_t mode)83 void Cache_Freeze_DCache_Enable(cache_freeze_mode_t mode)
84 {
85 rom_Cache_Freeze_DCache_Enable(mode);
86 Cache_Wait_Idle(0);
87 }
88 extern void Cache_Freeze_DCache_Enable(cache_freeze_mode_t mode);
89 #endif //#if SOC_CACHE_FREEZE_SUPPORTED
90 #endif //#if ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG
91
92 #if ESP_ROM_HAS_CACHE_WRITEBACK_BUG
93 /* Defined in esp_rom_cache_writeback_esp32s3.S */
94 extern void cache_writeback_items_freeze(uint32_t addr, uint32_t items);
95 // renamed for patch
96 extern int rom_Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
Cache_WriteBack_Addr(uint32_t addr,uint32_t size)97 int Cache_WriteBack_Addr(uint32_t addr, uint32_t size)
98 {
99 /* Do special processing for unaligned memory at the start and end of the cache writeback memory.
100 * 1. Disable the interrupt to prevent the current CPU accessing the same cacheline.
101 * 2. Enable dcache freeze to prevent the another CPU accessing the same cacheline.
102 */
103 uint32_t irq_status;
104 uint32_t start_len, end_len;
105 uint32_t start, end;
106 uint32_t dcache_line_size;
107 uint32_t autoload;
108 int ret = 0;
109 start = addr;
110 end = addr + size;
111 dcache_line_size = Cache_Get_DCache_Line_Size();
112
113 if (size == 0) {
114 return 0;
115 }
116
117 /*the start address is unaligned*/
118 if (start & (dcache_line_size -1)) {
119 addr = ALIGN_UP(start, dcache_line_size);
120 start_len = addr - start;
121 size = (size < start_len) ? 0 : (size - start_len);
122
123 /*writeback start unaligned mem, one cacheline*/
124 irq_status = XTOS_SET_INTLEVEL(XCHAL_NMILEVEL);//mask all interrupts
125 cache_writeback_items_freeze(start, 1);
126 XTOS_RESTORE_INTLEVEL(irq_status);
127
128 if (size == 0) {
129 return 0;
130 }
131 }
132
133 /*the end address is unaligned*/
134 if (end & (dcache_line_size -1)) {
135 end = ALIGN_DOWN(end, dcache_line_size);
136 end_len = addr + size - end;
137 size = (size - end_len);
138
139 /*writeback end unaligned mem, one cacheline*/
140 irq_status = XTOS_SET_INTLEVEL(XCHAL_NMILEVEL);//mask all interrupts
141 cache_writeback_items_freeze(end, 1);
142 XTOS_RESTORE_INTLEVEL(irq_status);
143
144 if (size == 0) {
145 return 0;
146 }
147 }
148
149 /*suspend autoload, avoid load cachelines being written back*/
150 autoload = Cache_Suspend_DCache_Autoload();
151 ret = rom_Cache_WriteBack_Addr(addr, size);
152 Cache_Resume_DCache_Autoload(autoload);
153
154 return ret;
155 }
156 extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
157 #endif //#if ESP_ROM_HAS_CACHE_WRITEBACK_BUG
158