diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 889fdc0c77d..4382022d5ae 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -34,6 +34,7 @@ if(NOT non_os_build) "sleep_usb.c" "sleep_gpio.c" "sleep_event.c" + "sleep_mspi.c" "regi2c_ctrl.c" "esp_gpio_reserve.c" "sar_periph_ctrl_common.c" diff --git a/components/esp_hw_support/include/esp_private/esp_pau.h b/components/esp_hw_support/include/esp_private/esp_pau.h index ba975b7b8dd..f82d0f7dbbe 100644 --- a/components/esp_hw_support/include/esp_private/esp_pau.h +++ b/components/esp_hw_support/include/esp_private/esp_pau.h @@ -83,8 +83,10 @@ void pau_regdma_trigger_extra_link_restore(void); * link entry configuration in always-on domain * * @param enable Set true to use always-on domain link configuration instead + * + * @return The origin aon link bypass enable status */ -void pau_regdma_enable_aon_link_entry(bool enable); +bool pau_regdma_enable_aon_link_entry(bool enable); #endif #ifdef __cplusplus diff --git a/components/esp_hw_support/include/esp_private/sleep_flash.h b/components/esp_hw_support/include/esp_private/sleep_flash.h new file mode 100644 index 00000000000..ab8c95e0986 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_flash.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) +/** + * Workaround for esp32p4 v3 MPSI access failure after power up. + */ +void sleep_flash_p4_rev3_workaround(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index a30384a17b1..b210d0462f6 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -22,6 +22,7 @@ entries: rtc_time (noflash_text) if SOC_PMU_SUPPORTED = y && SOC_LIGHT_SLEEP_SUPPORTED = y: pmu_sleep (noflash) + sleep_mspi (noflash) if SPIRAM_FLASH_LOAD_TO_PSRAM = y: pmu_init (noflash) pmu_param (noflash) diff --git a/components/esp_hw_support/port/pau_regdma.c b/components/esp_hw_support/port/pau_regdma.c index 40696e33e8f..4c992d34231 100644 --- a/components/esp_hw_support/port/pau_regdma.c +++ b/components/esp_hw_support/port/pau_regdma.c @@ -137,8 +137,10 @@ void IRAM_ATTR pau_regdma_trigger_extra_link_restore(void) } #if SOC_PAU_IN_TOP_DOMAIN -void pau_regdma_enable_aon_link_entry(bool enable) +bool IRAM_ATTR pau_regdma_enable_aon_link_entry(bool enable) { + bool origin_bypass_en = lp_sys_ll_get_pau_aon_bypass(); lp_sys_ll_set_pau_aon_bypass(enable); + return origin_bypass_en; } #endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index cd84eb8ad07..ef51be58998 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -23,6 +23,7 @@ #include "soc/rtc.h" #include "esp_private/sleep_event.h" #include "esp_private/system_internal.h" +#include "esp_private/sleep_retention.h" #include "esp_private/io_mux.h" #include "esp_log.h" #include "esp_newlib.h" @@ -79,6 +80,7 @@ #include "esp_private/sleep_console.h" #include "esp_private/sleep_cpu.h" #include "esp_private/sleep_modem.h" +#include "esp_private/sleep_flash.h" #include "esp_private/sleep_usb.h" #include "esp_private/esp_clk.h" #include "esp_private/esp_task_wdt.h" @@ -1039,12 +1041,18 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_mode_ } #endif -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP if (sleep_flags & PMU_SLEEP_PD_TOP) { +#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD esp_sleep_mmu_retention(true); +#endif +#if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) + sleep_retention_do_extra_retention(true); +#endif } #endif + #if SOC_PMU_SUPPORTED #if SOC_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0); @@ -1064,9 +1072,15 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_mode_ result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep); #endif -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP if (sleep_flags & PMU_SLEEP_PD_TOP) { +#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD esp_sleep_mmu_retention(false); +#endif +#if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) + sleep_flash_p4_rev3_workaround(); + sleep_retention_do_extra_retention(false); +#endif } #endif diff --git a/components/esp_hw_support/sleep_mspi.c b/components/esp_hw_support/sleep_mspi.c new file mode 100644 index 00000000000..5f0f8bf3c85 --- /dev/null +++ b/components/esp_hw_support/sleep_mspi.c @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "sdkconfig.h" + +#if CONFIG_IDF_TARGET_ESP32P4 && (CONFIG_ESP_REV_MIN_FULL == 300) +#include "soc/hp_system_reg.h" +#include "hal/mmu_ll.h" +#include "hal/mspi_timing_tuning_ll.h" + +void sleep_flash_p4_rev3_workaround(void) +{ + REG_CLR_BIT(SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_CLOSE_AXI_INF_EN); + REG_SET_BIT(SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_AXI_REQ_EN); + REG_SET_FIELD(HP_SYSTEM_CORE_ERR_RESP_DIS_REG, HP_SYSTEM_CORE_ERR_RESP_DIS, 0x7); + REG_WRITE(SPI_MEM_C_MMU_ITEM_INDEX_REG, 0); + uint32_t mmu_backup = mmu_ll_read_entry(MMU_LL_FLASH_MMU_ID, 0); + mmu_ll_write_entry(MMU_LL_FLASH_MMU_ID, 0, 0, MMU_TARGET_FLASH0); + __attribute__((unused)) volatile uint32_t val = 0; + val = REG_READ(0x80000000); + val = REG_READ(0x80000080); + mmu_ll_write_entry(MMU_LL_FLASH_MMU_ID, 0, mmu_backup, MMU_TARGET_FLASH0); + _mspi_timing_ll_reset_mspi(); + _mspi_timing_ll_reset_mspi_apb(); + REG_SET_FIELD(HP_SYSTEM_CORE_ERR_RESP_DIS_REG, HP_SYSTEM_CORE_ERR_RESP_DIS, 0); +} +#endif diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index d7b63cb63fb..4237d28b616 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -962,7 +962,7 @@ void IRAM_ATTR sleep_retention_do_extra_retention(bool backup_or_restore) return; } #if SOC_PAU_IN_TOP_DOMAIN - pau_regdma_enable_aon_link_entry(false); + bool origin_bypass_en = pau_regdma_enable_aon_link_entry(false); #endif // Set extra linked list head pointer to hardware pau_regdma_set_extra_link_addr(s_retention.lists[s_retention.highpri].entries[EXTRA_LINK_NUM]); @@ -976,6 +976,9 @@ void IRAM_ATTR sleep_retention_do_extra_retention(bool backup_or_restore) } else { pau_regdma_trigger_extra_link_restore(); } +#if SOC_PAU_IN_TOP_DOMAIN + pau_regdma_enable_aon_link_entry(origin_bypass_en); +#endif } #if SOC_PM_RETENTION_SW_TRIGGER_REGDMA diff --git a/components/hal/esp32p4/include/hal/lp_sys_ll.h b/components/hal/esp32p4/include/hal/lp_sys_ll.h index e28a69a6783..510e1158b1e 100644 --- a/components/hal/esp32p4/include/hal/lp_sys_ll.h +++ b/components/hal/esp32p4/include/hal/lp_sys_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,6 +40,11 @@ FORCE_INLINE_ATTR void lp_sys_ll_set_pau_aon_bypass(bool bypass) LP_SYS.backup_dma_cfg1.aon_bypass = bypass ? 1 : 0; } +FORCE_INLINE_ATTR bool lp_sys_ll_get_pau_aon_bypass(void) +{ + return LP_SYS.backup_dma_cfg1.aon_bypass; +} + FORCE_INLINE_ATTR void lp_sys_ll_set_pau_link_tout_thres(uint32_t tout) { LP_SYS.backup_dma_cfg0.link_tout_thres_aon = tout; diff --git a/components/hal/esp32p4/include/hal/mspi_timing_tuning_ll.h b/components/hal/esp32p4/include/hal/mspi_timing_tuning_ll.h index 6b84ef3c263..848bc5ea86f 100644 --- a/components/hal/esp32p4/include/hal/mspi_timing_tuning_ll.h +++ b/components/hal/esp32p4/include/hal/mspi_timing_tuning_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -86,6 +86,17 @@ static inline void _mspi_timing_ll_reset_mspi(void) /// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance #define mspi_timing_ll_reset_mspi(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _mspi_timing_ll_reset_mspi(__VA_ARGS__) +__attribute__((always_inline)) +static inline void _mspi_timing_ll_reset_mspi_apb(void) +{ + REG_SET_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB); + REG_CLR_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define mspi_timing_ll_reset_mspi_apb(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _mspi_timing_ll_reset_mspi_apb(__VA_ARGS__) + /** * Set all MSPI DQS phase * diff --git a/components/soc/esp32p4/system_retention_periph.c b/components/soc/esp32p4/system_retention_periph.c index 2a9d3ddc1cd..c563717c12c 100644 --- a/components/soc/esp32p4/system_retention_periph.c +++ b/components/soc/esp32p4/system_retention_periph.c @@ -134,19 +134,23 @@ _Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "In #define N_REGS_SPI0_C_MEM_1() (((SPI_MEM_C_SMEM_AC_REG - SPI_MEM_C_FMEM__PMS0_ATTR_REG) / 4) + 1) #define N_REGS_SPI0_C_MEM_2() (1) #define N_REGS_SPI0_C_MEM_3() (((SPI_MEM_C_DPA_CTRL_REG - SPI_MEM_C_MMU_POWER_CTRL_REG) / 4) + 1) - +#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 +#define FLASH_SPIMEM_RETENTION_ENTRY (ENTRY(0) | REGDMA_SW_TRIGGER_ENTRY) +#else +#define FLASH_SPIMEM_RETENTION_ENTRY ENTRY(0) +#endif const regdma_entries_config_t flash_spimem_regs_retention[] = { /* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */ - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), DR_REG_FLASH_SPI1_BASE, DR_REG_FLASH_SPI1_BASE, N_REGS_SPI1_C_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi1_mem */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI1_MEM_C_INT_ENA_REG, SPI1_MEM_C_INT_ENA_REG, N_REGS_SPI1_C_MEM_1(), 0, 0), .owner = ENTRY(0) }, - [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI_REG, N_REGS_SPI1_C_MEM_2(), 0, 0), .owner = ENTRY(0) }, + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), DR_REG_FLASH_SPI1_BASE, DR_REG_FLASH_SPI1_BASE, N_REGS_SPI1_C_MEM_0(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, /* spi1_mem */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI1_MEM_C_INT_ENA_REG, SPI1_MEM_C_INT_ENA_REG, N_REGS_SPI1_C_MEM_1(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI_REG, N_REGS_SPI1_C_MEM_2(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, /* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */ - [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), DR_REG_FLASH_SPI0_BASE, DR_REG_FLASH_SPI0_BASE, N_REGS_SPI0_C_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi0_mem */ - [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_C_FMEM__PMS0_ATTR_REG, SPI_MEM_C_FMEM__PMS0_ATTR_REG, N_REGS_SPI0_C_MEM_1(), 0, 0), .owner = ENTRY(0) }, - [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_C_CLOCK_GATE_REG, SPI_MEM_C_CLOCK_GATE_REG, N_REGS_SPI0_C_MEM_2(), 0, 0), .owner = ENTRY(0) }, - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_C_MMU_POWER_CTRL_REG, SPI_MEM_C_MMU_POWER_CTRL_REG, N_REGS_SPI0_C_MEM_3(), 0, 0), .owner = ENTRY(0) }, - [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SPIMEM_LINK(0x08), SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE, SPI_MEM_C_TIMING_CALI_UPDATE_M, 1, 0), .owner = ENTRY(0) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), DR_REG_FLASH_SPI0_BASE, DR_REG_FLASH_SPI0_BASE, N_REGS_SPI0_C_MEM_0(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, /* spi0_mem */ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_C_FMEM__PMS0_ATTR_REG, SPI_MEM_C_FMEM__PMS0_ATTR_REG, N_REGS_SPI0_C_MEM_1(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_C_CLOCK_GATE_REG, SPI_MEM_C_CLOCK_GATE_REG, N_REGS_SPI0_C_MEM_2(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_C_MMU_POWER_CTRL_REG, SPI_MEM_C_MMU_POWER_CTRL_REG, N_REGS_SPI0_C_MEM_3(), 0, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, + [7] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x08), SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE, SPI_MEM_C_TIMING_CALI_UPDATE_M, 1, 0), .owner = FLASH_SPIMEM_RETENTION_ENTRY }, }; _Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_FLASH_RETENTION_LINK_LEN, "Inconsistent Flash SPI Mem retention link length definitions");