From d7eb829fd0e175c3c70ab106645d2a79c0c5ff8c Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 17 Jul 2024 19:17:41 +0800 Subject: [PATCH] feat(esp_hw_support): support esp32p4 psram retention --- .../port/esp32p4/mspi_timing_config.c | 3 +- .../esp_hw_support/port/esp32p4/pmu_sleep.c | 41 ++++++++-- .../esp_hw_support/sleep_system_peripheral.c | 24 ++++-- .../hal/esp32p4/include/hal/psram_ctrlr_ll.h | 48 +++++++++-- .../include/soc/system_periph_retention.h | 2 +- .../soc/esp32c6/system_retention_periph.c | 4 +- .../include/soc/system_periph_retention.h | 2 +- .../soc/esp32h2/system_retention_periph.c | 4 +- .../include/soc/system_periph_retention.h | 18 ++++- .../soc/esp32p4/system_retention_periph.c | 81 ++++++++++++++----- 10 files changed, 174 insertions(+), 53 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/mspi_timing_config.c b/components/esp_hw_support/port/esp32p4/mspi_timing_config.c index 5c2db003e6..ed209a88ad 100644 --- a/components/esp_hw_support/port/esp32p4/mspi_timing_config.c +++ b/components/esp_hw_support/port/esp32p4/mspi_timing_config.c @@ -26,7 +26,8 @@ void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_spe ESP_EARLY_LOGD(TAG, "psram_freq_mhz: %" PRIu32 " mhz, bus clock div: %" PRIu32, psram_freq_mhz, freqdiv); PERIPH_RCC_ATOMIC() { //MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here. - psram_ctrlr_ll_set_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV); + psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true); + psram_ctrlr_ll_set_core_clock_div(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV); psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, freqdiv); psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, freqdiv); } diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index bc5b231d86..5d55e3a080 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -27,6 +27,7 @@ #include "hal/lp_aon_hal.h" #include "soc/lp_system_reg.h" #include "hal/pmu_hal.h" +#include "hal/psram_ctrlr_ll.h" #include "hal/lp_sys_ll.h" #include "esp_private/esp_pmu.h" #include "pmu_param.h" @@ -135,6 +136,8 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default( return param; } +TCM_DRAM_ATTR static uint32_t s_saved_pd_flags = 0; + const pmu_sleep_config_t* pmu_sleep_config_default( pmu_sleep_config_t *config, uint32_t pd_flags, @@ -144,6 +147,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( bool dslp ) { + s_saved_pd_flags = pd_flags; pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags); uint32_t iram_pd_flags = 0; @@ -290,11 +294,6 @@ void pmu_sleep_shutdown_ldo(void) { CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD); } -FORCE_INLINE_ATTR void sleep_writeback_l1_dcache(void) { - Cache_WriteBack_All(CACHE_MAP_L1_DCACHE); - while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); -} - static TCM_DRAM_ATTR uint32_t s_mpll_freq_mhz_before_sleep = 0; TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) @@ -309,12 +308,28 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev); pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev); - // !!! Need to manually check that data in L2 memory will not be modified from now on. !!! - sleep_writeback_l1_dcache(); + if (s_saved_pd_flags & PMU_SLEEP_PD_TOP) { + // L1 Cache will be powered down during PD_TOP sleep, write it back to L2 Cache here. + // !!! Need to manually check that data in L2 memory will not be modified from now on. !!! + Cache_WriteBack_All(CACHE_MAP_L1_DCACHE); + } - // !!! Need to manually check that data in PSRAM will not be accessed from now on. !!! +#if CONFIG_SPIRAM + psram_ctrlr_ll_wait_all_transaction_done(); +#endif s_mpll_freq_mhz_before_sleep = rtc_clk_mpll_get_freq(); if (s_mpll_freq_mhz_before_sleep) { +#if CONFIG_SPIRAM + _psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_XTAL); + _psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_XTAL); + if (!s_pmu_sleep_regdma_backup_enabled) { + // MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here. + // If it's a PD_TOP sleep, psram MSPI core clock will be disabled by REGDMA + // !!! Need to manually check that data in PSRAM will not be accessed from now on. !!! + _psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, false); + _psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, false); + } +#endif rtc_clk_mpll_disable(); } @@ -353,6 +368,16 @@ TCM_IRAM_ATTR bool pmu_sleep_finish(bool dslp) if (s_mpll_freq_mhz_before_sleep) { rtc_clk_mpll_enable(); rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), s_mpll_freq_mhz_before_sleep); +#if CONFIG_SPIRAM + if (!s_pmu_sleep_regdma_backup_enabled) { + // MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here. + // If it's a PD_TOP sleep, psram MSPI core clock will be enabled by REGDMA + _psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true); + _psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true); + } + _psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_MPLL); + _psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_MPLL); +#endif } unsigned chip_version = efuse_hal_chip_revision(); diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 97cbafd73b..f3eb153a98 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -73,14 +73,24 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_iomux_retention_init(v return ESP_OK; } -static __attribute__((unused)) esp_err_t sleep_sys_periph_spimem_retention_init(void *arg) +static __attribute__((unused)) esp_err_t sleep_sys_periph_flash_spimem_retention_init(void *arg) { - esp_err_t err = sleep_retention_entries_create(spimem_regs_retention, ARRAY_SIZE(spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH); - ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "SPI mem"); - ESP_LOGD(TAG, "SPI Mem sleep retention initialization"); + esp_err_t err = sleep_retention_entries_create(flash_spimem_regs_retention, ARRAY_SIZE(flash_spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "Flash SPI mem"); + ESP_LOGD(TAG, "Flash SPI Mem sleep retention initialization"); return ESP_OK; } +#if CONFIG_SPIRAM +static __attribute__((unused)) esp_err_t sleep_sys_periph_psram_spimem_retention_init(void *arg) +{ + esp_err_t err = sleep_retention_entries_create(psram_spimem_regs_retention, ARRAY_SIZE(psram_spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "PSRAM SPI mem"); + ESP_LOGD(TAG, "PSRAM SPI Mem sleep retention initialization"); + return ESP_OK; +} +#endif + static __attribute__((unused)) esp_err_t sleep_sys_periph_systimer_retention_init(void *arg) { esp_err_t err = sleep_retention_entries_create(systimer_regs_retention, ARRAY_SIZE(systimer_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH); @@ -130,8 +140,12 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *a #endif err = sleep_sys_periph_iomux_retention_init(arg); if(err) goto error; - err = sleep_sys_periph_spimem_retention_init(arg); + err = sleep_sys_periph_flash_spimem_retention_init(arg); if(err) goto error; +#if CONFIG_SPIRAM + err = sleep_sys_periph_psram_spimem_retention_init(arg); + if(err) goto error; +#endif err = sleep_sys_periph_systimer_retention_init(arg); if(err) goto error; #if SOC_PAU_IN_TOP_DOMAIN diff --git a/components/hal/esp32p4/include/hal/psram_ctrlr_ll.h b/components/hal/esp32p4/include/hal/psram_ctrlr_ll.h index 822a4759be..7579bd674e 100644 --- a/components/hal/esp32p4/include/hal/psram_ctrlr_ll.h +++ b/components/hal/esp32p4/include/hal/psram_ctrlr_ll.h @@ -289,15 +289,16 @@ static inline void psram_ctrlr_ll_enable_rd_splice(uint32_t mspi_id, bool en) * @param en enable / disable */ __attribute__((always_inline)) -static inline void psram_ctrlr_ll_enable_module_clock(uint32_t mspi_id, bool en) +static inline void _psram_ctrlr_ll_enable_module_clock(uint32_t mspi_id, bool en) { (void)mspi_id; HP_SYS_CLKRST.soc_clk_ctrl0.reg_psram_sys_clk_en = en; + HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_pll_clk_en = en; } /// 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_ATOMIC_ENV variable in advance -#define psram_ctrlr_ll_enable_module_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; psram_ctrlr_ll_enable_module_clock(__VA_ARGS__) +#define psram_ctrlr_ll_enable_module_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _psram_ctrlr_ll_enable_module_clock(__VA_ARGS__) /** * @brief Reset PSRAM module clock @@ -325,7 +326,7 @@ static inline void psram_ctrlr_ll_reset_module_clock(uint32_t mspi_id) * @param clk_src clock source, see valid sources in type `soc_periph_psram_clk_src_t` */ __attribute__((always_inline)) -static inline void psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph_psram_clk_src_t clk_src) +static inline void _psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph_psram_clk_src_t clk_src) { (void)mspi_id; uint32_t clk_val = 0; @@ -347,13 +348,12 @@ static inline void psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph break; } - HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_pll_clk_en = 1; HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_clk_src_sel = clk_val; } /// 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_ATOMIC_ENV variable in advance -#define psram_ctrlr_ll_select_clk_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; psram_ctrlr_ll_select_clk_source(__VA_ARGS__) +#define psram_ctrlr_ll_select_clk_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; _psram_ctrlr_ll_select_clk_source(__VA_ARGS__) /** * @brief Set PSRAM core clock @@ -362,15 +362,29 @@ static inline void psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph * @param freqdiv Divider value */ __attribute__((always_inline)) -static inline void psram_ctrlr_ll_set_core_clock(uint8_t spi_num, uint32_t freqdiv) +static inline void _psram_ctrlr_ll_set_core_clock_div(uint8_t spi_num, uint32_t freqdiv) { - HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_core_clk_en = 1; HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl00, reg_psram_core_clk_div_num, freqdiv - 1); } /// 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_ATOMIC_ENV variable in advance -#define psram_ctrlr_ll_set_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; psram_ctrlr_ll_set_core_clock(__VA_ARGS__) +#define psram_ctrlr_ll_set_core_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; _psram_ctrlr_ll_set_core_clock_div(__VA_ARGS__) + +/** + * @brief Enable or disable the PSRAM core clock + * + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void _psram_ctrlr_ll_enable_core_clock(uint8_t spi_num, bool en) +{ + HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_core_clk_en = en; +} + +/// 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_ATOMIC_ENV variable in advance +#define psram_ctrlr_ll_enable_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _psram_ctrlr_ll_enable_core_clock(__VA_ARGS__) /** * @brief Set PSRAM bus clock @@ -735,6 +749,24 @@ static inline void psram_ctrlr_ll_common_transaction(uint32_t mspi_id, is_write_erase_operation); } +/** + * @brief Wait MSPI PSRAM controller transaction done + * + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_wait_all_transaction_done(void) +{ +#define ALL_TRANSACTION_DONE ( SPI_MEM_S_ALL_FIFO_EMPTY | \ + SPI_MEM_S_RDATA_AFIFO_REMPTY | \ + SPI_MEM_S_RADDR_AFIFO_REMPTY | \ + SPI_MEM_S_WDATA_AFIFO_REMPTY | \ + SPI_MEM_S_WBLEN_AFIFO_REMPTY | \ + SPI_MEM_S_ALL_AXI_TRANS_AFIFO_EMPTY) + while (SPIMEM2.smem_axi_addr_ctrl.val != ALL_TRANSACTION_DONE) { + ; + } +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c6/include/soc/system_periph_retention.h b/components/soc/esp32c6/include/soc/system_periph_retention.h index 539b3500d3..54f7c3e205 100644 --- a/components/soc/esp32c6/include/soc/system_periph_retention.h +++ b/components/soc/esp32c6/include/soc/system_periph_retention.h @@ -75,7 +75,7 @@ extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_L * useful for external use. */ #define SPIMEM_RETENTION_LINK_LEN 8 -extern const regdma_entries_config_t spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN]; +extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN]; /** * @brief Provide access to systimer configuration registers retention diff --git a/components/soc/esp32c6/system_retention_periph.c b/components/soc/esp32c6/system_retention_periph.c index 4ff06bdbcb..2d9227575a 100644 --- a/components/soc/esp32c6/system_retention_periph.c +++ b/components/soc/esp32c6/system_retention_periph.c @@ -67,7 +67,7 @@ _Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "In #define N_REGS_SPI0_MEM_1() (((SPI_MEM_SPI_SMEM_AC_REG(0) - SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(0)) / 4) + 1) #define N_REGS_SPI0_MEM_2() (1) #define N_REGS_SPI0_MEM_3() (((SPI_MEM_DATE_REG(0) - SPI_MEM_MMU_POWER_CTRL_REG(0)) / 4) + 1) -const regdma_entries_config_t spimem_regs_retention[] = { +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), REG_SPI_MEM_BASE(1), REG_SPI_MEM_BASE(1), N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi1_mem */ [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1), SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1), N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, @@ -80,7 +80,7 @@ const regdma_entries_config_t spimem_regs_retention[] = { [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLOCK_GATE_REG(0), N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_MMU_POWER_CTRL_REG(0), SPI_MEM_MMU_POWER_CTRL_REG(0), N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } }; -_Static_assert(ARRAY_SIZE(spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions"); +_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions"); /* Systimer Registers Context */ #define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1) diff --git a/components/soc/esp32h2/include/soc/system_periph_retention.h b/components/soc/esp32h2/include/soc/system_periph_retention.h index 539b3500d3..54f7c3e205 100644 --- a/components/soc/esp32h2/include/soc/system_periph_retention.h +++ b/components/soc/esp32h2/include/soc/system_periph_retention.h @@ -75,7 +75,7 @@ extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_L * useful for external use. */ #define SPIMEM_RETENTION_LINK_LEN 8 -extern const regdma_entries_config_t spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN]; +extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN]; /** * @brief Provide access to systimer configuration registers retention diff --git a/components/soc/esp32h2/system_retention_periph.c b/components/soc/esp32h2/system_retention_periph.c index d9f3c5b469..436840e682 100644 --- a/components/soc/esp32h2/system_retention_periph.c +++ b/components/soc/esp32h2/system_retention_periph.c @@ -66,7 +66,7 @@ _Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "In #define N_REGS_SPI0_MEM_1() (((SPI_MEM_SPI_SMEM_AC_REG(0) - SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(0)) / 4) + 1) #define N_REGS_SPI0_MEM_2() (1) #define N_REGS_SPI0_MEM_3() (((SPI_MEM_DATE_REG(0) - SPI_MEM_MMU_POWER_CTRL_REG(0)) / 4) + 1) -const regdma_entries_config_t spimem_regs_retention[] = { +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), REG_SPI_MEM_BASE(1), REG_SPI_MEM_BASE(1), N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi1_mem */ [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1), SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1), N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, @@ -79,7 +79,7 @@ const regdma_entries_config_t spimem_regs_retention[] = { [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLOCK_GATE_REG(0), N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_MMU_POWER_CTRL_REG(0), SPI_MEM_MMU_POWER_CTRL_REG(0), N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } }; -_Static_assert(ARRAY_SIZE(spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions"); +_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions"); /* Systimer Registers Context */ #define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1) diff --git a/components/soc/esp32p4/include/soc/system_periph_retention.h b/components/soc/esp32p4/include/soc/system_periph_retention.h index d7fd022775..45041ad49b 100644 --- a/components/soc/esp32p4/include/soc/system_periph_retention.h +++ b/components/soc/esp32p4/include/soc/system_periph_retention.h @@ -62,18 +62,28 @@ extern const regdma_entries_config_t tg_regs_retention[TIMG_RETENTION_LINK_LEN]; * This is an internal function of the sleep retention driver, and is not * useful for external use. */ -#define IOMUX_RETENTION_LINK_LEN 2 +#define IOMUX_RETENTION_LINK_LEN 3 extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN]; /** - * @brief Provide access to spimem configuration registers retention + * @brief Provide access to FLASH spimem configuration registers retention * context definition. * * This is an internal function of the sleep retention driver, and is not * useful for external use. */ -#define SPIMEM_RETENTION_LINK_LEN 8 -extern const regdma_entries_config_t spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN]; +#define SPIMEM_FLASH_RETENTION_LINK_LEN 8 +extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_FLASH_RETENTION_LINK_LEN]; + +/** + * @brief Provide access to PSRAM spimem configuration registers retention + * context definition. + * + * This is an internal function of the sleep retention driver, and is not + * useful for external use. + */ +#define SPIMEM_PSRAM_RETENTION_LINK_LEN 14 +extern const regdma_entries_config_t psram_spimem_regs_retention[SPIMEM_PSRAM_RETENTION_LINK_LEN]; /** * @brief Provide access to systimer configuration registers retention diff --git a/components/soc/esp32p4/system_retention_periph.c b/components/soc/esp32p4/system_retention_periph.c index 1cc4a49da4..18a2ea302f 100644 --- a/components/soc/esp32p4/system_retention_periph.c +++ b/components/soc/esp32p4/system_retention_periph.c @@ -7,13 +7,17 @@ #include "soc/cache_reg.h" #include "soc/gpio_reg.h" #include "soc/hp_system_reg.h" +#include "soc/hp_sys_clkrst_reg.h" #include "soc/io_mux_reg.h" +#include "soc/iomux_mspi_pin_reg.h" #include "soc/interrupt_core0_reg.h" #include "soc/interrupt_core1_reg.h" #include "soc/pau_reg.h" #include "soc/regdma.h" #include "soc/system_periph_retention.h" #include "soc/spi_mem_reg.h" +#include "soc/spi_mem_s_reg.h" +#include "soc/spi1_mem_s_reg.h" #include "soc/systimer_reg.h" #include "soc/timer_group_reg.h" #include "soc/timer_periph.h" @@ -44,36 +48,71 @@ _Static_assert(ARRAY_SIZE(hp_system_regs_retention) == HP_SYSTEM_RETENTION_LINK_ /* IO MUX Registers Context */ #define N_REGS_IOMUX_0() (((IO_MUX_GPIO54_REG - REG_IO_MUX_BASE) / 4) + 1) -#define N_REGS_IOMUX_1() (((GPIO_ZERO_DET1_FILTER_CNT_REG - DR_REG_GPIO_BASE) / 4) + 1) +#define N_REGS_GPIO_MTX() (((GPIO_ZERO_DET1_FILTER_CNT_REG - DR_REG_GPIO_BASE) / 4) + 1) +#define N_REGS_MSPI_IOMUX() (((IOMUX_MSPI_PIN_PSRAM_DQS_1_PIN0_REG - IOMUX_MSPI_PIN_CLK_EN0_REG) / 4) + 1) const regdma_entries_config_t iomux_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) }, /* io_mux */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) }, + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) }, /* io_mux */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_GPIO_MTX(), 0, 0), .owner = ENTRY(0) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), IOMUX_MSPI_PIN_CLK_EN0_REG, IOMUX_MSPI_PIN_CLK_EN0_REG, N_REGS_GPIO_MTX(), 0, 0), .owner = ENTRY(0) }, }; _Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions"); /* Memory SPI Registers Context */ -#define N_REGS_SPI1_MEM_0() (((SPI1_MEM_C_SUS_STATUS_REG - DR_REG_FLASH_SPI1_BASE) / 4) + 1) -#define N_REGS_SPI1_MEM_1() (((SPI1_MEM_C_DDR_REG - SPI1_MEM_C_INT_ENA_REG) / 4) + 1) -#define N_REGS_SPI1_MEM_2() (1) -#define N_REGS_SPI1_MEM_3() (1) -#define N_REGS_SPI0_MEM_0() ((SPI_MEM_C_SMEM_DDR_REG - DR_REG_FLASH_SPI0_BASE) / 4 + 1) -#define N_REGS_SPI0_MEM_1() (((SPI_MEM_C_SMEM_AC_REG - SPI_MEM_C_FMEM__PMS0_ATTR_REG) / 4) + 1) -#define N_REGS_SPI0_MEM_2() (1) -#define N_REGS_SPI0_MEM_3() (((SPI_MEM_C_DATE_REG - SPI_MEM_C_MMU_POWER_CTRL_REG) / 4) + 1) -const regdma_entries_config_t spimem_regs_retention[] = { +#define N_REGS_SPI1_C_MEM_0() (((SPI1_MEM_C_SUS_STATUS_REG - DR_REG_FLASH_SPI1_BASE) / 4) + 1) +#define N_REGS_SPI1_C_MEM_1() (((SPI1_MEM_C_DDR_REG - SPI1_MEM_C_INT_ENA_REG) / 4) + 1) +#define N_REGS_SPI1_C_MEM_2() (1) +#define N_REGS_SPI1_C_MEM_3() (1) +#define N_REGS_SPI0_C_MEM_0() ((SPI_MEM_C_SMEM_DDR_REG - DR_REG_FLASH_SPI0_BASE) / 4 + 1) +#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) + +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_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_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_MEM_2(), 0, 0), .owner = ENTRY(0) }, - [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x03), SPI1_MEM_C_CLOCK_GATE_REG, SPI1_MEM_C_CLOCK_GATE_REG, N_REGS_SPI1_MEM_3(), 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 = 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) }, /* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */ - [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), DR_REG_FLASH_SPI0_BASE, DR_REG_FLASH_SPI0_BASE, N_REGS_SPI0_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi0_mem */ - [5] = { .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_MEM_1(), 0, 0), .owner = ENTRY(0) }, - [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_C_CLOCK_GATE_REG, SPI_MEM_C_CLOCK_GATE_REG, N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) }, - [7] = { .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_MEM_3(), 0, 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 = 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) }, }; -_Static_assert(ARRAY_SIZE(spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions"); +_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_FLASH_RETENTION_LINK_LEN, "Inconsistent Flash SPI Mem retention link length definitions"); + +#if CONFIG_SPIRAM +#define N_REGS_SPI0_S_MEM_0() (((SPI_MEM_S_USER2_REG - SPI_MEM_S_CTRL_REG) / 4) + 1) +#define N_REGS_SPI0_S_MEM_1() (((SPI_MEM_S_FSM_REG - SPI_MEM_S_MISC_REG) / 4) + 1) +#define N_REGS_SPI0_S_MEM_2() (((SPI_MEM_S_SMEM_DDR_REG - SPI_MEM_S_INT_ENA_REG) / 4) + 1) +#define N_REGS_SPI0_S_MEM_3() (((SPI_MEM_S_SMEM_DOUT_HEX_MODE_REG - SPI_MEM_S_ECC_CTRL_REG) / 4) + 1) +#define N_REGS_SPI0_S_MEM_4() (((SPI_MEM_S_DPA_CTRL_REG - SPI_MEM_S_MMU_POWER_CTRL_REG) / 4) + 1) +#define N_REGS_SPI1_S_MEM_0() ((SPI1_MEM_S_CACHE_FCTRL_REG - SPI1_MEM_S_CMD_REG) / 4 + 1) +#define N_REGS_SPI1_S_MEM_1() (((SPI1_MEM_S_SUS_STATUS_REG - SPI1_MEM_S_FLASH_WAITI_CTRL_REG) / 4) + 1) +#define N_REGS_SPI1_S_MEM_2() (((SPI1_MEM_S_DDR_REG - SPI1_MEM_S_INT_ENA_REG) / 4) + 1) +#define N_REGS_SPI1_S_MEM_3() (1) +#define N_REGS_SPI1_S_MEM_4() (1) + +const regdma_entries_config_t psram_spimem_regs_retention[SPIMEM_PSRAM_RETENTION_LINK_LEN] = { + [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x08), HP_SYS_CLKRST_PERI_CLK_CTRL00_REG, HP_SYS_CLKRST_REG_PSRAM_CORE_CLK_EN, HP_SYS_CLKRST_REG_PSRAM_CORE_CLK_EN_M, 1, 0), .owner = ENTRY(0) }, // Enable PSRAM mspi core clock on restore + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x09), HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_PSRAM_SYS_CLK_EN, HP_SYS_CLKRST_REG_PSRAM_SYS_CLK_EN_M, 1, 0), .owner = ENTRY(0) }, // Enable PSRAM mspi core clock on restore + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0a), SPI_MEM_S_CTRL_REG, SPI_MEM_S_CTRL_REG, N_REGS_SPI0_S_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi0_mem */ + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0b), SPI_MEM_S_MISC_REG, SPI_MEM_S_MISC_REG, N_REGS_SPI0_S_MEM_1(), 0, 0), .owner = ENTRY(0) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0c), SPI_MEM_S_INT_ENA_REG, SPI_MEM_S_INT_ENA_REG, N_REGS_SPI0_S_MEM_2(), 0, 0), .owner = ENTRY(0) }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0d), SPI_MEM_S_ECC_CTRL_REG, SPI_MEM_S_ECC_CTRL_REG, N_REGS_SPI0_S_MEM_3(), 0, 0), .owner = ENTRY(0) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0e), SPI_MEM_S_MMU_POWER_CTRL_REG, SPI_MEM_S_MMU_POWER_CTRL_REG, N_REGS_SPI0_S_MEM_4(), 0, 0), .owner = ENTRY(0) }, + [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0f), SPI1_MEM_S_CMD_REG, SPI1_MEM_S_CMD_REG, N_REGS_SPI1_S_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi1_mem */ + [8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x10), SPI1_MEM_S_FLASH_WAITI_CTRL_REG, SPI1_MEM_S_FLASH_WAITI_CTRL_REG, N_REGS_SPI1_S_MEM_1(), 0, 0), .owner = ENTRY(0) }, + [9] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x11), SPI1_MEM_S_INT_ENA_REG, SPI1_MEM_S_INT_ENA_REG, N_REGS_SPI1_S_MEM_2(), 0, 0), .owner = ENTRY(0) }, + [10] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x12), SPI1_MEM_S_TIMING_CALI_REG, SPI1_MEM_S_TIMING_CALI_REG, N_REGS_SPI1_S_MEM_3(), 0, 0), .owner = ENTRY(0) }, + [11] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x13), SPI1_MEM_S_CLOCK_GATE_REG, SPI1_MEM_S_CLOCK_GATE_REG, N_REGS_SPI1_S_MEM_4(), 0, 0), .owner = ENTRY(0) }, + [12] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x14), HP_SYS_CLKRST_PERI_CLK_CTRL00_REG, 0, HP_SYS_CLKRST_REG_PSRAM_CORE_CLK_EN_M, 0, 1), .owner = ENTRY(0) }, // Enable PSRAM mspi core clock on backup + [13] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x15), HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, 0, HP_SYS_CLKRST_REG_PSRAM_SYS_CLK_EN_M, 0, 1), .owner = ENTRY(0) }, // Enable PSRAM mspi core clock on backup +}; + +_Static_assert(ARRAY_SIZE(psram_spimem_regs_retention) == SPIMEM_PSRAM_RETENTION_LINK_LEN, "Inconsistent PSRAM SPI Mem retention link length definitions"); +#endif /* Systimer Registers Context */ #define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1)