From f3cc52d2344586b36f4381c7f46cc4f839716492 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 4 Dec 2024 21:57:41 +0800 Subject: [PATCH 1/7] feat(esp_hw_support): do esp32p4 l1&l2 cache regs retention by regdma --- .../lowpower/port/esp32p4/sleep_cpu.c | 26 -------------- .../esp_hw_support/sleep_system_peripheral.c | 12 +++---- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32p4/include/soc/soc_caps.h | 1 + .../include/soc/system_periph_retention.h | 8 ++--- .../soc/esp32p4/system_retention_periph.c | 35 ++++++++++++++++--- components/soc/include/soc/regdma.h | 1 + 7 files changed, 46 insertions(+), 41 deletions(-) diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c index e7756703bc..479a14c9ee 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c @@ -20,7 +20,6 @@ #include "freertos/task.h" #include "esp_heap_caps.h" #include "riscv/csr.h" -#include "soc/cache_reg.h" #include "soc/clic_reg.h" #include "soc/rtc_periph.h" #include "soc/soc_caps.h" @@ -32,7 +31,6 @@ #include "esp32p4/rom/ets_sys.h" #include "esp32p4/rom/rtc.h" -#include "esp32p4/rom/cache.h" #include "rvsleep-frames.h" #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME @@ -76,7 +74,6 @@ typedef struct { struct { RvCoreCriticalSleepFrame *critical_frame[portNUM_PROCESSORS]; RvCoreNonCriticalSleepFrame *non_critical_frame[portNUM_PROCESSORS]; - cpu_domain_dev_sleep_frame_t *cache_config_frame; cpu_domain_dev_sleep_frame_t *clic_frame[portNUM_PROCESSORS]; } retent; } sleep_cpu_retention_t; @@ -107,15 +104,6 @@ static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_reg return frame; } -static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = CACHE_L1_ICACHE_CTRL_REG, .end = CACHE_L1_BYPASS_CACHE_CONF_REG + 4 }, - { .start = CACHE_L2_CACHE_CTRL_REG, .end = CACHE_L2_CACHE_BLOCKSIZE_CONF_REG + 4 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id) { const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][2] = { @@ -146,13 +134,6 @@ static esp_err_t esp_sleep_cpu_retention_init_impl(void) s_cpu_retention.retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame; } } - if (s_cpu_retention.retent.cache_config_frame == NULL) { - void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { if (s_cpu_retention.retent.clic_frame[core_id] == NULL) { void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id); @@ -186,10 +167,6 @@ static esp_err_t esp_sleep_cpu_retention_deinit_impl(void) s_cpu_retention.retent.non_critical_frame[core_id] = NULL; } } - if (s_cpu_retention.retent.cache_config_frame) { - heap_caps_free((void *)s_cpu_retention.retent.cache_config_frame); - s_cpu_retention.retent.cache_config_frame = NULL; - } for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { if (s_cpu_retention.retent.clic_frame[core_id]) { heap_caps_free((void *)s_cpu_retention.retent.clic_frame[core_id]); @@ -442,7 +419,6 @@ esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START); #endif cpu_domain_dev_regs_save(s_cpu_retention.retent.clic_frame[core_id]); - cpu_domain_dev_regs_save(s_cpu_retention.retent.cache_config_frame); rv_core_noncritical_regs_save(); #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME @@ -468,7 +444,6 @@ esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, #endif rv_core_noncritical_regs_restore(); - cpu_domain_dev_regs_restore(s_cpu_retention.retent.cache_config_frame); cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]); restore_mstatus(mstatus); @@ -495,7 +470,6 @@ bool cpu_domain_pd_allowed(void) allowed &= (s_cpu_retention.retent.critical_frame[core_id] != NULL); allowed &= (s_cpu_retention.retent.non_critical_frame[core_id] != NULL); } - allowed &= (s_cpu_retention.retent.cache_config_frame != NULL); for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { allowed &= (s_cpu_retention.retent.clic_frame[core_id] != NULL); } diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 4cf7a973bb..77557765e6 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -101,11 +101,11 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_systimer_retention_ini return ESP_OK; } -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE -esp_err_t sleep_sys_periph_l2_cache_retention_init(void) +#if SOC_PM_CACHE_RETENTION_BY_PAU +esp_err_t sleep_sys_periph_cache_retention_init(void) { - esp_err_t err = sleep_retention_entries_create(l2_cache_regs_retention, ARRAY_SIZE(l2_cache_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_HIGH, SLEEP_RETENTION_MODULE_SYS_PERIPH); - ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (L2 Cache) retention"); + esp_err_t err = sleep_retention_entries_create(cache_regs_retention, ARRAY_SIZE(cache_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_HIGH, SLEEP_RETENTION_MODULE_SYS_PERIPH); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (Cache) retention"); ESP_LOGI(TAG, "L2 Cache sleep retention initialization"); return ESP_OK; } @@ -128,8 +128,8 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *a if(err) goto error; err = sleep_sys_periph_hp_system_retention_init(arg); if(err) goto error; -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE - err = sleep_sys_periph_l2_cache_retention_init(); +#if SOC_PM_CACHE_RETENTION_BY_PAU + err = sleep_sys_periph_cache_retention_init(); if(err) goto error; #endif #if SOC_APM_SUPPORTED diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 2b5bea2ba3..e713b64757 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1923,6 +1923,10 @@ config SOC_PM_CPU_RETENTION_BY_SW bool default y +config SOC_PM_CACHE_RETENTION_BY_PAU + bool + default y + config SOC_PM_PAU_LINK_NUM int default 4 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index f6e92e1388..2b86319219 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -718,6 +718,7 @@ #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Wed, 11 Dec 2024 21:26:54 +0800 Subject: [PATCH 2/7] feat(esp_hw_support): do esp32p4 l1 cache invalidate by regdma --- .../lowpower/port/esp32p4/sleep_cpu_asm.S | 25 ------------------- .../esp32p4/include/esp32p4/rom/cache.h | 1 + .../include/soc/system_periph_retention.h | 2 +- .../soc/esp32p4/system_retention_periph.c | 8 ++++++ 4 files changed, 10 insertions(+), 26 deletions(-) diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_asm.S b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_asm.S index f6d8a9d6dd..1ae80231d6 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_asm.S +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_asm.S @@ -149,31 +149,6 @@ _rv_core_critical_regs_restore: /* export a strong symbol to jump to here, used nop rv_core_critical_regs_restore: - /* Invalidate L1 Cache by Core 0*/ - csrr t0, mhartid - bnez t0, start_restore -/* Core 0 is wakeup core, Invalidate L1 Cache here */ - /* Invalidate L1 cache is required here!!! */ - la t0, CACHE_SYNC_MAP_REG - li t1, CACHE_MAP_L1_CACHE_MASK /* map l1 i/dcache */ - sw t1, 0x0(t0) /* set EXTMEM_CACHE_SYNC_MAP_REG bit 4 */ - la t2, CACHE_SYNC_ADDR_REG - sw zero, 0x0(t2) /* clear EXTMEM_CACHE_SYNC_ADDR_REG */ - la t0, CACHE_SYNC_SIZE_REG - sw zero, 0x0(t0) /* clear EXTMEM_CACHE_SYNC_SIZE_REG */ - - la t1, CACHE_SYNC_CTRL_REG - lw t2, 0x0(t1) - ori t2, t2, 0x1 - sw t2, 0x0(t1) - - li t0, 0x10 /* SYNC_DONE bit */ -wait_cache_sync_done1: - lw t2, 0x0(t1) - and t2, t0, t2 - beqz t2, wait_cache_sync_done1 - -start_restore: la t0, rv_core_critical_regs_frame csrr t1, mhartid slli t1, t1, 2 diff --git a/components/esp_rom/esp32p4/include/esp32p4/rom/cache.h b/components/esp_rom/esp32p4/include/esp32p4/rom/cache.h index 49b084b3ab..0c5ba82533 100644 --- a/components/esp_rom/esp32p4/include/esp32p4/rom/cache.h +++ b/components/esp_rom/esp32p4/include/esp32p4/rom/cache.h @@ -231,6 +231,7 @@ typedef enum { #define CACHE_MAP_L2_CACHE BIT(5) #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) struct cache_internal_stub_table { diff --git a/components/soc/esp32p4/include/soc/system_periph_retention.h b/components/soc/esp32p4/include/soc/system_periph_retention.h index cbabf962f3..77fd2c3d77 100644 --- a/components/soc/esp32p4/include/soc/system_periph_retention.h +++ b/components/soc/esp32p4/include/soc/system_periph_retention.h @@ -32,7 +32,7 @@ extern const regdma_entries_config_t intr_matrix_regs_retention[INT_MTX_RETENTIO * This is an internal function of the sleep retention driver, and is not * useful for external use. */ -#define CACHE_RETENTION_LINK_LEN 2 +#define CACHE_RETENTION_LINK_LEN 8 extern const regdma_entries_config_t cache_regs_retention[CACHE_RETENTION_LINK_LEN]; /** diff --git a/components/soc/esp32p4/system_retention_periph.c b/components/soc/esp32p4/system_retention_periph.c index 0fa3ac41cd..30be755de0 100644 --- a/components/soc/esp32p4/system_retention_periph.c +++ b/components/soc/esp32p4/system_retention_periph.c @@ -22,6 +22,7 @@ #include "soc/timer_group_reg.h" #include "soc/timer_periph.h" #include "soc/uart_reg.h" +#include "esp32p4/rom/cache.h" /* Interrupt Matrix Registers Context */ #define N_REGS_INTR_CORE0() (((INTERRUPT_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1) @@ -61,6 +62,13 @@ const regdma_entries_config_t cache_regs_retention[] = { l2_cache_regs_map[2], l2_cache_regs_map[3]), \ .owner = ENTRY(0) }, + // Invalidate L1 Cache + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x02), CACHE_SYNC_ADDR_REG, 0, CACHE_SYNC_ADDR_M, 1, 0), .owner = ENTRY(0) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x03), CACHE_SYNC_SIZE_REG, 0, CACHE_SYNC_SIZE_M, 1, 0), .owner = ENTRY(0) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x04), CACHE_SYNC_MAP_REG, CACHE_MAP_L1_CACHE_MASK, CACHE_SYNC_MAP_M, 1, 0), .owner = ENTRY(0) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x05), CACHE_SYNC_CTRL_REG, 0, CACHE_SYNC_RGID_M, 1, 0), .owner = ENTRY(0) }, + [6] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_CACHE_LINK(0x06), CACHE_SYNC_CTRL_REG, CACHE_INVALIDATE_ENA, CACHE_INVALIDATE_ENA_M, 1, 0), .owner = ENTRY(0) }, + [7] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_CACHE_LINK(0x07), CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE, CACHE_SYNC_DONE_M, 1, 0), .owner = ENTRY(0) }, }; _Static_assert(ARRAY_SIZE(cache_regs_retention) == CACHE_RETENTION_LINK_LEN, "Inconsistent L2 CACHE retention link length definitions"); From ea05eba7f546e30844c1b79de7ec0c2471493ba3 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 5 Dec 2024 16:08:57 +0800 Subject: [PATCH 3/7] feat(esp_hw_support): do mstatus restore on each core --- .../esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c index 479a14c9ee..409b2495b4 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c @@ -380,6 +380,8 @@ static TCM_IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) { uint8_t core_id = esp_cpu_get_core_id(); + /* mstatus is core privated CSR, do it near the core critical regs restore */ + uint32_t mstatus = save_mstatus_and_disable_global_int(); rv_core_critical_regs_save(); RvCoreCriticalSleepFrame * frame = s_cpu_retention.retent.critical_frame[core_id]; @@ -405,7 +407,7 @@ static TCM_IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc)); } #endif - + restore_mstatus(mstatus); return pmu_sleep_finish(dslp); } @@ -413,7 +415,6 @@ esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) { esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0); - uint32_t mstatus = save_mstatus_and_disable_global_int(); uint8_t core_id = esp_cpu_get_core_id(); #if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START); @@ -443,9 +444,8 @@ esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_START); #endif - rv_core_noncritical_regs_restore(); cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]); - restore_mstatus(mstatus); + rv_core_noncritical_regs_restore(); #if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE); @@ -518,6 +518,7 @@ static TCM_IRAM_ATTR void smp_core_do_retention(void) atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START); rv_core_noncritical_regs_save(); cpu_domain_dev_regs_save(s_cpu_retention.retent.clic_frame[core_id]); + uint32_t mstatus = save_mstatus_and_disable_global_int(); rv_core_critical_regs_save(); RvCoreCriticalSleepFrame *frame_critical = s_cpu_retention.retent.critical_frame[core_id]; if ((frame_critical->pmufunc & 0x3) == 0x1) { @@ -537,6 +538,7 @@ static TCM_IRAM_ATTR void smp_core_do_retention(void) REG_CLR_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_CORE1_GLOBAL); } atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_START); + restore_mstatus(mstatus); cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]); rv_core_noncritical_regs_restore(); atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE); From 4542c463c6bf5155cabe84a0e69f7f94186db7e1 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 5 Dec 2024 16:16:58 +0800 Subject: [PATCH 4/7] change(esp_hw_support): not use ROM Cache invalidate in sleep process to avoid dirtying the L1 Cache --- .../include/esp_private/esp_pmu.h | 5 ---- .../esp_hw_support/port/esp32p4/pmu_sleep.c | 26 ++++++++++++++----- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 6d347788a2..2de08ffcca 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -279,11 +279,6 @@ void pmu_sleep_increase_ldo_volt(void); * power in the sleep and wake-up processes. */ void pmu_sleep_shutdown_dcdc(void); - -/** - * @brief DCDC has taken over power supply, shut down LDO to save power consumption - */ -void pmu_sleep_shutdown_ldo(void); #endif // SOC_DCDC_SUPPORTED /** diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index 990d343938..65ad5ca55d 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -339,17 +339,28 @@ void pmu_sleep_shutdown_dcdc(void) { pmu_ll_hp_set_regulator_dbias(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DBIAS_DEFAULT); } -void pmu_sleep_enable_dcdc(void) { +FORCE_INLINE_ATTR void pmu_sleep_enable_dcdc(void) { CLEAR_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable SET_PERI_REG_MASK(PMU_DCM_CTRL_REG, PMU_DCDC_ON_REQ); REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); } -void pmu_sleep_shutdown_ldo(void) { +FORCE_INLINE_ATTR void pmu_sleep_shutdown_ldo(void) { CLEAR_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD); } +FORCE_INLINE_ATTR void pmu_sleep_cache_sync_items(uint32_t gid, uint32_t type, uint32_t map, uint32_t addr, uint32_t bytes) +{ + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, bytes); + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_SET_FIELD(CACHE_SYNC_CTRL_REG, CACHE_SYNC_RGID, gid); + REG_SET_BIT(CACHE_SYNC_CTRL_REG, type); + 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) @@ -364,11 +375,12 @@ 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); - // For the sleep where powered down the TOP domain, the L1 cache data memory will be lost and needs to be written back here. - // For the sleep without power down the TOP domain, regdma retention may still be enabled, and dirty data in the L1 cache needs - // to be written back so that regdma can get the correct link. So we always need to write back to L1 DCache here. - // !!! Need to manually check that data in L2 memory will not be modified from now on. !!! - Cache_WriteBack_All(CACHE_MAP_L1_DCACHE); + // 1. For the sleep where powered down the TOP domain, the L1 cache data memory will be lost and needs to be written back here. + // 2. For the sleep without power down the TOP domain, regdma retention may still be enabled, and dirty data in the L1 cache needs + // to be written back so that regdma can get the correct link. + // 3. We cannot use the API provided by ROM to invalidate the cache, since it is a function calling that writes data to the stack during + // the return process, which results in dirty cachelines in L1 Cache again. + pmu_sleep_cache_sync_items(SMMU_GID_DEFAULT, CACHE_SYNC_WRITEBACK, CACHE_MAP_L1_DCACHE, 0, 0); #if CONFIG_SPIRAM psram_ctrlr_ll_wait_all_transaction_done(); From a63e9c5aef3db724052069f4ca42614a64dbfd44 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 5 Dec 2024 21:26:56 +0800 Subject: [PATCH 5/7] fix(esp_hw_support): fix DCDC switch bad software powerdown --- components/esp_hw_support/port/esp32p4/pmu_sleep.c | 9 ++++----- components/esp_hw_support/port/esp32p4/rtc_clk_init.c | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index 65ad5ca55d..e343c40234 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -333,20 +333,19 @@ void pmu_sleep_increase_ldo_volt(void) { } void pmu_sleep_shutdown_dcdc(void) { - SET_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable + REG_SET_BIT(PMU_POWER_DCDC_SWITCH_REG, PMU_FORCE_DCDC_SWITCH_PD); REG_SET_BIT(PMU_DCM_CTRL_REG, PMU_DCDC_OFF_REQ); // Decrease hp_ldo voltage. pmu_ll_hp_set_regulator_dbias(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DBIAS_DEFAULT); } FORCE_INLINE_ATTR void pmu_sleep_enable_dcdc(void) { - CLEAR_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable + REG_CLR_BIT(PMU_POWER_DCDC_SWITCH_REG, PMU_FORCE_DCDC_SWITCH_PD); SET_PERI_REG_MASK(PMU_DCM_CTRL_REG, PMU_DCDC_ON_REQ); REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); } FORCE_INLINE_ATTR void pmu_sleep_shutdown_ldo(void) { - CLEAR_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD); } @@ -441,10 +440,10 @@ TCM_IRAM_ATTR bool pmu_sleep_finish(bool dslp) #endif { pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); + pmu_sleep_enable_dcdc(); if (pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) { // If sleep is rejected, the hardware wake-up process that turns on DCDC - // is skipped, and software is used to enable DCDC here. - pmu_sleep_enable_dcdc(); + // is skipped, and wait DCDC volt rise up by software here. esp_rom_delay_us(950); } pmu_sleep_shutdown_ldo(); diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk_init.c b/components/esp_hw_support/port/esp32p4/rtc_clk_init.c index 00cb5f09a9..51b88f7548 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk_init.c @@ -58,7 +58,7 @@ void rtc_clk_init(rtc_clk_config_t cfg) // Switch to DCDC SET_PERI_REG_MASK(PMU_DCM_CTRL_REG, PMU_DCDC_ON_REQ); - CLEAR_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable + REG_CLR_BIT(PMU_POWER_DCDC_SWITCH_REG, PMU_FORCE_DCDC_SWITCH_PD); REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); esp_rom_delay_us(1000); CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD); From 8233c250deb8fe2954897adc0fa0f4ee65b8f270 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 12 Dec 2024 10:37:13 +0800 Subject: [PATCH 6/7] feat(esp_hw_support): add branch prediction config retention --- .../esp_hw_support/lowpower/port/esp32p4/rvsleep-frames.h | 1 + components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/components/esp_hw_support/lowpower/port/esp32p4/rvsleep-frames.h b/components/esp_hw_support/lowpower/port/esp32p4/rvsleep-frames.h index 0d1735bf7a..76c88a8d0b 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/rvsleep-frames.h +++ b/components/esp_hw_support/lowpower/port/esp32p4/rvsleep-frames.h @@ -113,6 +113,7 @@ STRUCT_END(RvCoreCriticalSleepFrame) STRUCT_BEGIN STRUCT_FIELD (long, 4, RV_SLP_CTX_MSCRATCH, mscratch) STRUCT_FIELD (long, 4, RV_SLP_CTX_MISA, misa) + STRUCT_FIELD (long, 4, RV_SLP_CTX_MHCR, mhcr) STRUCT_FIELD (long, 4, RV_SLP_CTX_TSELECT, tselect) STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA1, tdata1) STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA2, tdata2) diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c index 409b2495b4..79d9da85ec 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c @@ -192,6 +192,7 @@ static TCM_IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save frame->mscratch = RV_READ_CSR(mscratch); frame->misa = RV_READ_CSR(misa); + frame->mhcr = RV_READ_CSR(MHCR); frame->tselect = RV_READ_CSR(tselect); frame->tdata1 = RV_READ_CSR(tdata1); frame->tdata2 = RV_READ_CSR(tdata2); @@ -260,6 +261,7 @@ static TCM_IRAM_ATTR void rv_core_noncritical_regs_restore(void) RV_WRITE_CSR(mscratch, frame->mscratch); RV_WRITE_CSR(misa, frame->misa); + RV_WRITE_CSR(MHCR, frame->mhcr); RV_WRITE_CSR(tselect, frame->tselect); RV_WRITE_CSR(tdata1, frame->tdata1); RV_WRITE_CSR(tdata2, frame->tdata2); From b654a78646554f71d77e68ef2232acd185d656a0 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 12 Feb 2025 17:27:15 +0800 Subject: [PATCH 7/7] change(esp_hw_support): wrapper sleep dcdc/ldo ops with ll --- .../esp_hw_support/port/esp32p4/pmu_init.c | 4 ++-- .../esp_hw_support/port/esp32p4/pmu_sleep.c | 14 +++++++------- .../esp_hw_support/port/esp32p4/rtc_clk_init.c | 13 ++++++------- components/hal/esp32p4/include/hal/pmu_ll.h | 17 ++++++++++++++--- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/components/esp_hw_support/port/esp32p4/pmu_init.c b/components/esp_hw_support/port/esp32p4/pmu_init.c index ffebc6a0e2..f511dd4341 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_init.c +++ b/components/esp_hw_support/port/esp32p4/pmu_init.c @@ -149,8 +149,8 @@ static inline void pmu_power_domain_force_default(pmu_context_t *ctx) pmu_ll_lp_set_power_force_power_down(ctx->hal->dev, false); pmu_ll_lp_set_power_force_isolate (ctx->hal->dev, false); pmu_ll_lp_set_power_force_reset (ctx->hal->dev, false); - pmu_ll_set_dcdc_force_power_up(ctx->hal->dev, false); - pmu_ll_set_dcdc_force_power_down(ctx->hal->dev, false); + pmu_ll_set_dcdc_switch_force_power_up(ctx->hal->dev, false); + pmu_ll_set_dcdc_switch_force_power_down(ctx->hal->dev, false); } static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param) diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index e343c40234..8536231e23 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -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 */ @@ -333,20 +333,20 @@ void pmu_sleep_increase_ldo_volt(void) { } void pmu_sleep_shutdown_dcdc(void) { - REG_SET_BIT(PMU_POWER_DCDC_SWITCH_REG, PMU_FORCE_DCDC_SWITCH_PD); - REG_SET_BIT(PMU_DCM_CTRL_REG, PMU_DCDC_OFF_REQ); + pmu_ll_set_dcdc_switch_force_power_down(&PMU, true); + pmu_ll_set_dcdc_en(&PMU, false); // Decrease hp_ldo voltage. pmu_ll_hp_set_regulator_dbias(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DBIAS_DEFAULT); } FORCE_INLINE_ATTR void pmu_sleep_enable_dcdc(void) { - REG_CLR_BIT(PMU_POWER_DCDC_SWITCH_REG, PMU_FORCE_DCDC_SWITCH_PD); - SET_PERI_REG_MASK(PMU_DCM_CTRL_REG, PMU_DCDC_ON_REQ); - REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); + pmu_ll_set_dcdc_switch_force_power_down(&PMU, false); + pmu_ll_set_dcdc_en(&PMU, true); + pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); } FORCE_INLINE_ATTR void pmu_sleep_shutdown_ldo(void) { - CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD); + pmu_ll_hp_set_regulator_xpd(&PMU, PMU_MODE_HP_ACTIVE, 0); } FORCE_INLINE_ATTR void pmu_sleep_cache_sync_items(uint32_t gid, uint32_t type, uint32_t map, uint32_t addr, uint32_t bytes) diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk_init.c b/components/esp_hw_support/port/esp32p4/rtc_clk_init.c index 51b88f7548..2003e50066 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk_init.c @@ -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 */ @@ -54,14 +54,13 @@ void rtc_clk_init(rtc_clk_config_t cfg) REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_XPD_IPH, 0); REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_XPD_VGATE_BUF, 0); - REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS); - + pmu_ll_lp_set_regulator_dbias(&PMU, PMU_MODE_LP_ACTIVE, LP_CALI_DBIAS); // Switch to DCDC - SET_PERI_REG_MASK(PMU_DCM_CTRL_REG, PMU_DCDC_ON_REQ); - REG_CLR_BIT(PMU_POWER_DCDC_SWITCH_REG, PMU_FORCE_DCDC_SWITCH_PD); - REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); + pmu_ll_set_dcdc_en(&PMU, true); + pmu_ll_set_dcdc_switch_force_power_down(&PMU, false); + pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); esp_rom_delay_us(1000); - CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD); + pmu_ll_hp_set_regulator_xpd(&PMU, PMU_MODE_HP_ACTIVE, false); soc_xtal_freq_t xtal_freq = cfg.xtal_freq; esp_rom_output_tx_wait_idle(0); diff --git a/components/hal/esp32p4/include/hal/pmu_ll.h b/components/hal/esp32p4/include/hal/pmu_ll.h index 9084e06ab1..16ec05fb57 100644 --- a/components/hal/esp32p4/include/hal/pmu_ll.h +++ b/components/hal/esp32p4/include/hal/pmu_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 */ @@ -663,16 +663,27 @@ FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_up_wait_cycle(pmu_dev_t * return hw->power.wait_timer0.powerup_timer; } -FORCE_INLINE_ATTR void pmu_ll_set_dcdc_force_power_up(pmu_dev_t *hw, bool fpu) +FORCE_INLINE_ATTR void pmu_ll_set_dcdc_switch_force_power_up(pmu_dev_t *hw, bool fpu) { + hw->power.dcdc_switch.force_pd = 0; hw->power.dcdc_switch.force_pu = fpu; } -FORCE_INLINE_ATTR void pmu_ll_set_dcdc_force_power_down(pmu_dev_t *hw, bool fpd) +FORCE_INLINE_ATTR void pmu_ll_set_dcdc_switch_force_power_down(pmu_dev_t *hw, bool fpd) { + hw->power.dcdc_switch.force_pu = 0; hw->power.dcdc_switch.force_pd = fpd; } +FORCE_INLINE_ATTR void pmu_ll_set_dcdc_en(pmu_dev_t *hw, bool en) +{ + if (en) { + hw->dcm_ctrl.on_req = 1; + } else { + hw->dcm_ctrl.off_req = 1; + } +} + /** * @brief Get ext1 wakeup source status * @return The lower 8 bits of the returned value are the bitmap of