diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index f7393734c1d..d4dbb5fef54 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -82,6 +82,14 @@ if(CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG) list(APPEND sources "patches/esp_rom_cache_writeback_esp32s3.S") endif() +if(CONFIG_ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP) + list(APPEND sources "patches/esp_rom_cache_writeback_esp32p4.c") +endif() + +if(CONFIG_ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP) + list(APPEND sources "patches/esp_rom_cache_writeback_esp32c61.c") +endif() + idf_component_register(SRCS ${sources} INCLUDE_DIRS ${include_dirs} PRIV_REQUIRES ${private_required_comp} diff --git a/components/esp_rom/esp32c61/Kconfig.soc_caps.in b/components/esp_rom/esp32c61/Kconfig.soc_caps.in index f3bea7e1e6b..559c7317eac 100644 --- a/components/esp_rom/esp32c61/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c61/Kconfig.soc_caps.in @@ -90,3 +90,7 @@ config ESP_ROM_HAS_SW_FLOAT config ESP_ROM_USB_OTG_NUM int default -1 + +config ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP + bool + default y diff --git a/components/esp_rom/esp32c61/esp_rom_caps.h b/components/esp_rom/esp32c61/esp_rom_caps.h index 9bcc14320be..2ef6a1eb2e3 100644 --- a/components/esp_rom/esp32c61/esp_rom_caps.h +++ b/components/esp_rom/esp32c61/esp_rom_caps.h @@ -30,3 +30,4 @@ #define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init #define ESP_ROM_HAS_SW_FLOAT (1) // ROM has libgcc software floating point emulation functions #define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage. +#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.ld index e5489aa0136..63c7e6d1fa3 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -194,12 +194,12 @@ Cache_Sync_Items = 0x4000062c; Cache_Op_Addr = 0x40000630; Cache_Invalidate_Addr = 0x40000634; Cache_Clean_Addr = 0x40000638; -Cache_WriteBack_Addr = 0x4000063c; -Cache_WriteBack_Invalidate_Addr = 0x40000640; +PROVIDE( Cache_WriteBack_Addr = 0x4000063c ); +PROVIDE( Cache_WriteBack_Invalidate_Addr = 0x40000640 ); Cache_Invalidate_All = 0x40000644; Cache_Clean_All = 0x40000648; -Cache_WriteBack_All = 0x4000064c; -Cache_WriteBack_Invalidate_All = 0x40000650; +PROVIDE( Cache_WriteBack_All = 0x4000064c ); +PROVIDE( Cache_WriteBack_Invalidate_All = 0x40000650 ); Cache_Mask_All = 0x40000654; Cache_UnMask_Dram0 = 0x40000658; Cache_Suspend_Autoload = 0x4000065c; diff --git a/components/esp_rom/esp32p4/Kconfig.soc_caps.in b/components/esp_rom/esp32p4/Kconfig.soc_caps.in index a7a0a9c0850..a7d492ffada 100644 --- a/components/esp_rom/esp32p4/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32p4/Kconfig.soc_caps.in @@ -78,3 +78,7 @@ config ESP_ROM_HAS_VERSION config ESP_ROM_CLIC_INT_TYPE_PATCH bool default y + +config ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP + bool + default y diff --git a/components/esp_rom/esp32p4/esp_rom_caps.h b/components/esp_rom/esp32p4/esp_rom_caps.h index 8578f4401fa..b8482e63f5a 100644 --- a/components/esp_rom/esp32p4/esp_rom_caps.h +++ b/components/esp_rom/esp32p4/esp_rom_caps.h @@ -25,3 +25,4 @@ #define ESP_ROM_HAS_NEWLIB_NANO_PRINTF_FLOAT_BUG (1) // ROM has the printf float bug with newlib nano version #define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information #define ESP_ROM_CLIC_INT_TYPE_PATCH (1) // ROM api esprv_intc_int_set_type configuring edge type interrupt is invalid +#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, need map parameter diff --git a/components/esp_rom/esp32p4/ld/esp32p4.rom.ld b/components/esp_rom/esp32p4/ld/esp32p4.rom.ld index 6b8f14bf60e..3cab45e49e1 100644 --- a/components/esp_rom/esp32p4/ld/esp32p4.rom.ld +++ b/components/esp_rom/esp32p4/ld/esp32p4.rom.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -187,17 +187,17 @@ Cache_Invalidate_Addr = 0x4fc003e4; Cache_Invalidate_Addr_Gid = 0x4fc003e8; Cache_Clean_Addr = 0x4fc003ec; Cache_Clean_Addr_Gid = 0x4fc003f0; -Cache_WriteBack_Addr = 0x4fc003f4; +PROVIDE( Cache_WriteBack_Addr = 0x4fc003f4 ); Cache_WriteBack_Addr_Gid = 0x4fc003f8; -Cache_WriteBack_Invalidate_Addr = 0x4fc003fc; +PROVIDE( Cache_WriteBack_Invalidate_Addr = 0x4fc003fc ); Cache_WriteBack_Invalidate_Addr_Gid = 0x4fc00400; Cache_Invalidate_All = 0x4fc00404; Cache_Invalidate_All_Gid = 0x4fc00408; Cache_Clean_All = 0x4fc0040c; Cache_Clean_All_Gid = 0x4fc00410; -Cache_WriteBack_All = 0x4fc00414; +PROVIDE( Cache_WriteBack_All = 0x4fc00414 ); Cache_WriteBack_All_Gid = 0x4fc00418; -Cache_WriteBack_Invalidate_All = 0x4fc0041c; +PROVIDE( Cache_WriteBack_Invalidate_All = 0x4fc0041c ); Cache_WriteBack_Invalidate_All_Gid = 0x4fc00420; Cache_Mask_All = 0x4fc00424; Cache_Suspend_L1_CORE0_ICache_Autoload = 0x4fc00428; diff --git a/components/esp_rom/include/esp32p4/rom/cache.h b/components/esp_rom/include/esp32p4/rom/cache.h index f505f6f46b5..4953c00095d 100644 --- a/components/esp_rom/include/esp32p4/rom/cache.h +++ b/components/esp_rom/include/esp32p4/rom/cache.h @@ -96,6 +96,7 @@ extern "C" { #define CACHE_MAP_L1_ICACHE_MASK (CACHE_MAP_L1_ICACHE_0 | CACHE_MAP_L1_ICACHE_1) #define CACHE_MAP_L1_CACHE_MASK (CACHE_MAP_L1_ICACHE_MASK | CACHE_MAP_L1_DCACHE) #define CACHE_MAP_MASK (CACHE_MAP_L1_ICACHE_MASK | CACHE_MAP_L1_DCACHE | CACHE_MAP_L2_CACHE) +#define CACHE_MAP_DCACHE_MASK (CACHE_MAP_L1_DCACHE | CACHE_MAP_L2_CACHE) #if (!defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)) typedef enum { diff --git a/components/esp_rom/linker.lf b/components/esp_rom/linker.lf index bc708c5697b..e6287b206a0 100644 --- a/components/esp_rom/linker.lf +++ b/components/esp_rom/linker.lf @@ -12,3 +12,7 @@ entries: esp_rom_systimer (noflash) if HAL_WDT_USE_ROM_IMPL = y: esp_rom_wdt (noflash) + if ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP = y: + esp_rom_cache_writeback_esp32p4 (noflash) + if ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP = y: + esp_rom_cache_writeback_esp32c61 (noflash) diff --git a/components/esp_rom/patches/esp_rom_cache_writeback_esp32c61.c b/components/esp_rom/patches/esp_rom_cache_writeback_esp32c61.c new file mode 100644 index 00000000000..0eab6fe0b43 --- /dev/null +++ b/components/esp_rom/patches/esp_rom_cache_writeback_esp32c61.c @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "soc/cache_reg.h" +#include "rom/cache.h" + +// esp32c61 does not need msp parameters in apis. +int Cache_WriteBack_Addr(uint32_t addr, uint32_t size) +{ + uint32_t plus; + uint32_t cache_line_size = MIN_CACHE_LINE_SIZE; + + plus = addr & (cache_line_size - 1); + addr -= plus; + size += plus; + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + REG_WRITE(CACHE_SYNC_MAP_REG, CACHE_MAP_FLASH_CACHE); + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, size); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} + +#ifndef BOOTLOADER_BUILD +void Cache_WriteBack_All(void) +{ + REG_WRITE(CACHE_SYNC_MAP_REG, CACHE_MAP_FLASH_CACHE); + REG_WRITE(CACHE_SYNC_ADDR_REG, 0); + REG_WRITE(CACHE_SYNC_SIZE_REG, 0); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); +} +#endif + +int Cache_WriteBack_Invalidate_Addr(uint32_t addr, uint32_t size) +{ + uint32_t plus; + uint32_t cache_line_size = MIN_CACHE_LINE_SIZE; + + plus = addr & (cache_line_size - 1); + addr -= plus; + size += plus; + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + REG_WRITE(CACHE_SYNC_MAP_REG, CACHE_MAP_FLASH_CACHE); + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, size); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} + +void Cache_WriteBack_Invalidate_All(void) +{ + REG_WRITE(CACHE_SYNC_MAP_REG, CACHE_MAP_FLASH_CACHE); + REG_WRITE(CACHE_SYNC_ADDR_REG, 0); + REG_WRITE(CACHE_SYNC_SIZE_REG, 0); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); +} diff --git a/components/esp_rom/patches/esp_rom_cache_writeback_esp32p4.c b/components/esp_rom/patches/esp_rom_cache_writeback_esp32p4.c new file mode 100644 index 00000000000..cc67fa4f194 --- /dev/null +++ b/components/esp_rom/patches/esp_rom_cache_writeback_esp32p4.c @@ -0,0 +1,137 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "soc/cache_reg.h" +#include "rom/cache.h" +#include "esp_attr.h" +#include "esp_rom_sys.h" + +// esp32p4 needs msp parameters in apis. +int Cache_WriteBack_Addr(uint32_t map, uint32_t addr, uint32_t size) +{ + uint32_t plus; + uint32_t cache_line_size = 0; + /* writeback readonly cache is invalid */ + if (map & CACHE_MAP_L1_ICACHE_MASK) { + return ESP_ROM_ERR_INVALID_ARG; + } + + if ((map & CACHE_MAP_DCACHE_MASK) == 0) { + return ESP_ROM_ERR_INVALID_ARG; + } + + /* esp32p4 will check l2 cache */ + if (map & CACHE_MAP_L1_DCACHE) { + cache_line_size = rom_cache_internal_table_ptr->l1_dcache_line_size(); + } + if (map & CACHE_MAP_L2_CACHE) { + cache_line_size = (cache_line_size > rom_cache_internal_table_ptr->l2_cache_line_size()) ? + cache_line_size : rom_cache_internal_table_ptr->l2_cache_line_size(); + } + + plus = addr & (cache_line_size - 1); + addr -= plus; + size += plus; + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, size); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} + +#ifndef BOOTLOADER_BUILD +int Cache_WriteBack_All(uint32_t map) +{ + /* writeback readonly cache is invalid */ + if (map & CACHE_MAP_L1_ICACHE_MASK) { + return ESP_ROM_ERR_INVALID_ARG; + } + + if ((map & CACHE_MAP_DCACHE_MASK) == 0) { + return ESP_ROM_ERR_INVALID_ARG; + } + + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_WRITE(CACHE_SYNC_ADDR_REG, 0); + REG_WRITE(CACHE_SYNC_SIZE_REG, 0); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} +#endif + +int Cache_WriteBack_Invalidate_Addr(uint32_t map, uint32_t addr, uint32_t size) +{ + uint32_t plus; + uint32_t cache_line_size = 0; + /* writeback readonly cache is invalid */ + if (map & CACHE_MAP_L1_ICACHE_MASK) { + return ESP_ROM_ERR_INVALID_ARG; + } + + if ((map & CACHE_MAP_DCACHE_MASK) == 0) { + return ESP_ROM_ERR_INVALID_ARG; + } + + /* esp32p4 will check l2 cache */ + if (map & CACHE_MAP_L1_DCACHE) { + cache_line_size = rom_cache_internal_table_ptr->l1_dcache_line_size(); + } + if (map & CACHE_MAP_L2_CACHE) { + cache_line_size = (cache_line_size > rom_cache_internal_table_ptr->l2_cache_line_size()) ? + cache_line_size : rom_cache_internal_table_ptr->l2_cache_line_size(); + } + + plus = addr & (cache_line_size - 1); + addr -= plus; + size += plus; + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, size); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} + +int Cache_WriteBack_Invalidate_All(uint32_t map) +{ + /* writeback readonly cache is invalid */ + if (map & CACHE_MAP_L1_ICACHE_MASK) { + return ESP_ROM_ERR_INVALID_ARG; + } + + if ((map & CACHE_MAP_DCACHE_MASK) == 0) { + return ESP_ROM_ERR_INVALID_ARG; + } + + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_WRITE(CACHE_SYNC_ADDR_REG, 0); + REG_WRITE(CACHE_SYNC_SIZE_REG, 0); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +}