diff --git a/components/esp_hal_clock/esp32p4/include/hal/clk_gate_ll.h b/components/esp_hal_clock/esp32p4/include/hal/clk_gate_ll.h index 3e5d68f2bb6..3e3e1c3082e 100644 --- a/components/esp_hal_clock/esp32p4/include/hal/clk_gate_ll.h +++ b/components/esp_hal_clock/esp32p4/include/hal/clk_gate_ll.h @@ -383,6 +383,8 @@ static inline void periph_ll_clk_gate_set_default(soc_reset_reason_t rst_reason, LP_CLKRST_HP_SDIO_PLL2_CLK_EN | LP_CLKRST_HP_SDIO_PLL1_CLK_EN | LP_CLKRST_HP_SDIO_PLL0_CLK_EN); + // now, hp root clock use PMU_HP_ACTIVE/SLEEP_ICG_SYS_CLOCK_EN to control + REG_CLR_BIT(LP_CLKRST_HP_CLK_CTRL_REG, LP_CLKRST_HP_ROOT_CLK_EN); if (config->disable_spiram_boot_clk) { REG_CLR_BIT(LP_CLKRST_HP_CLK_CTRL_REG, LP_CLKRST_HP_MPLL_500M_CLK_EN); } diff --git a/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h b/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h index 0098c6da702..e4343a2e36c 100644 --- a/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h @@ -33,6 +33,14 @@ (num) == 2 ? (&UART2) : \ (num) == 3 ? (&UART3) : \ (num) == 4 ? (&UART4) : (&LP_UART)) +// Get UART sleep clock with giving uart num +#define UART_LL_SLEEP_CLOCK(num) \ + ( ((num) == UART_NUM_0) ? (ESP_SLEEP_CLOCK_UART0) \ + : ((num) == UART_NUM_1) ? (ESP_SLEEP_CLOCK_UART1) \ + : ((num) == UART_NUM_2) ? (ESP_SLEEP_CLOCK_UART2) \ + : ((num) == UART_NUM_3) ? (ESP_SLEEP_CLOCK_UART3) \ + : ((num) == UART_NUM_4) ? (ESP_SLEEP_CLOCK_UART4) \ + : (ESP_SLEEP_CLOCK_MAX)) #define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0) 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 9ad7e59ba1c..543b9c34c5a 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -87,18 +87,25 @@ typedef enum { #define RTC_WIFI_TRIG_EN 0 #endif -#if SOC_UART_SUPPORT_WAKEUP_INT #define RTC_UART0_TRIG_EN PMU_UART0_WAKEUP_EN //!< UART0 wakeup (light sleep only) #define RTC_UART1_TRIG_EN PMU_UART1_WAKEUP_EN //!< UART1 wakeup (light sleep only) +#define RTC_UART2_TRIG_EN 0 +#define RTC_UART3_TRIG_EN 0 +#define RTC_UART4_TRIG_EN 0 + #if SOC_UART_HP_NUM > 2 +#undef RTC_UART2_TRIG_EN #define RTC_UART2_TRIG_EN PMU_UART2_WAKEUP_EN //!< UART2 wakeup (light sleep only) -#else -#define RTC_UART2_TRIG_EN 0 #endif -#else -#define RTC_UART0_TRIG_EN 0 -#define RTC_UART1_TRIG_EN 0 -#define RTC_UART2_TRIG_EN 0 + +#if SOC_UART_HP_NUM > 3 +#undef RTC_UART3_TRIG_EN +#define RTC_UART3_TRIG_EN PMU_UART3_WAKEUP_EN //!< UART3 wakeup (light sleep only) +#endif + +#if SOC_UART_HP_NUM > 4 +#undef RTC_UART4_TRIG_EN +#define RTC_UART4_TRIG_EN PMU_UART4_WAKEUP_EN //!< UART4 wakeup (light sleep only) #endif #if SOC_BT_SUPPORTED @@ -149,6 +156,8 @@ typedef enum { RTC_UART0_TRIG_EN | \ RTC_UART1_TRIG_EN | \ RTC_UART2_TRIG_EN | \ + RTC_UART3_TRIG_EN | \ + RTC_UART4_TRIG_EN | \ RTC_BT_TRIG_EN | \ RTC_LP_CORE_TRIG_EN | \ RTC_TOUCH_TRIG_EN | \ @@ -187,6 +196,9 @@ typedef enum { typedef struct { pmu_hal_context_t *hal; void *mc; +#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA + void *priv; +#endif } pmu_context_t; pmu_context_t * PMU_instance(void); diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index 83b15760e4e..c2257f4c566 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -118,6 +118,12 @@ typedef enum { #if SOC_UART_HP_NUM > 2 ESP_SLEEP_CLOCK_UART2, //!< The clock ICG cell mapping of UART2 #endif +#if SOC_UART_HP_NUM > 3 + ESP_SLEEP_CLOCK_UART3, //!< The clock ICG cell mapping of UART3 +#endif +#if SOC_UART_HP_NUM > 4 + ESP_SLEEP_CLOCK_UART4, //!< The clock ICG cell mapping of UART4 +#endif #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK, //!< The clock ICG cell remapping of RETENTION #endif diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 129b0aea694..304659bf7f7 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -112,9 +112,18 @@ typedef enum { ESP_SLEEP_WAKEUP_TOUCHPAD, //!< Wakeup caused by touchpad ESP_SLEEP_WAKEUP_ULP, //!< Wakeup caused by ULP program ESP_SLEEP_WAKEUP_GPIO, //!< Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3) - ESP_SLEEP_WAKEUP_UART, //!< Wakeup caused by UART0 (light sleep only) + ESP_SLEEP_WAKEUP_UART0, //!< Wakeup caused by UART0 (light sleep only) + ESP_SLEEP_WAKEUP_UART = ESP_SLEEP_WAKEUP_UART0, ESP_SLEEP_WAKEUP_UART1, //!< Wakeup caused by UART1 (light sleep only) +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP ESP_SLEEP_WAKEUP_UART2, //!< Wakeup caused by UART2 (light sleep only) +#endif +#if (SOC_UART_HP_NUM > 3) + ESP_SLEEP_WAKEUP_UART3, //!< Wakeup caused by UART3 (light sleep only) +#endif +#if (SOC_UART_HP_NUM > 4) + ESP_SLEEP_WAKEUP_UART4, //!< Wakeup caused by UART4 (light sleep only) +#endif ESP_SLEEP_WAKEUP_WIFI, //!< Wakeup caused by WIFI (light sleep only) ESP_SLEEP_WAKEUP_COCPU, //!< Wakeup caused by COCPU int ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG, //!< Wakeup caused by COCPU crash diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 5b9cd7547ea..bc36135cc92 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -39,6 +39,8 @@ entries: rtc_sleep:rtc_sleep_pu (noflash) if SOC_PMU_SUPPORTED = y && SOC_LIGHT_SLEEP_SUPPORTED = y: pmu_sleep (noflash) + if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP != y: + pmu_sleep_clock_icg:pmu_sleep_clock_icg_config (noflash) sleep_mspi (noflash) if SPIRAM_FLASH_LOAD_TO_PSRAM = y: pmu_init (noflash) diff --git a/components/esp_hw_support/port/esp32p4/CMakeLists.txt b/components/esp_hw_support/port/esp32p4/CMakeLists.txt index 4cd7fecdbca..2ab7ced14a8 100644 --- a/components/esp_hw_support/port/esp32p4/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32p4/CMakeLists.txt @@ -11,6 +11,10 @@ set(srcs "rtc_clk_init.c" if(NOT BOOTLOADER_BUILD) list(APPEND srcs "sar_periph_ctrl.c") + + if(CONFIG_SOC_PM_SLEEP_CLK_ICG_USE_REGDMA AND NOT CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + list(APPEND srcs "pmu_sleep_clock_icg.c") + endif() endif() if(NOT BOOTLOADER_BUILD AND CONFIG_ESP_ENABLE_PVT) diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index 8b6cf1cd88f..429a2e3d3aa 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -173,7 +173,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( if (dslp) { config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period); - pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags); + pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags); config->digital = digital_default; pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags); @@ -190,7 +190,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default( } } else { // Get light sleep digital_default - pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags); + pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags); config->digital = digital_default; // Get light sleep analog default @@ -266,6 +266,11 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig) { + pmu_ll_hp_set_icg_sysclk_enable (ctx->hal->dev, HP(SLEEP), (dig->icg_func[0] != 0)); + pmu_ll_hp_set_icg_func (ctx->hal->dev, HP(SLEEP), dig->icg_func[0]); /* PMU FSM clock ICG config */ +#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA && !defined(CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + pmu_sleep_clock_icg_config (ctx->priv, dig->icg_func[1]); /* PMU REGDMA clock ICG config */ +#endif pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel); pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, HP(SLEEP), dig->syscntl.lp_pad_hold_all); pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt); diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c b/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c new file mode 100644 index 00000000000..4beca572007 --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c @@ -0,0 +1,209 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_pmu.h" +#include "esp_check.h" +#include "soc/hp_sys_clkrst_reg.h" +#include "esp_private/sleep_retention.h" +#include "esp_private/startup_internal.h" + +ESP_LOG_ATTR_TAG(TAG, "sleep_clock"); + +#define SOC_CLK_EN(peri) (HP_SYS_CLKRST_REG_ ## peri ## _CLK_EN) +#define SOC_CLK_MASK(peri) (HP_SYS_CLKRST_REG_ ## peri ## _CLK_EN_M) + +#define PERI_CLK_EN(peri) (HP_SYS_CLKRST_REG_ ## peri ## _CLK_EN) +#define PERI_CLK_MASK(peri) (HP_SYS_CLKRST_REG_ ## peri ## _CLK_EN_M) + + +#define MASK(m, bit) m ## _MASK(bit) + +#define MASK_1(m, a) MASK(m, a) +#define MASK_2(m, a, b) MASK(m, a) | MASK(m, b) +#define MASK_3(m, a, b, c) MASK(m, a) | MASK_2(m, b, c) +#define MASK_4(m, a, b, c, d) MASK(m, a) | MASK_3(m, b, c, d) +#define MASK_5(m, a, b, c, d, e) MASK(m, a) | MASK_4(m, b, c, d, e) +#define MASK_6(m, a, b, c, d, e, ...) MASK_5(m, a, b, c, d, e) | MASK_1(m, __VA_ARGS__) +#define MASK_7(m, a, b, c, d, e, ...) MASK_5(m, a, b, c, d, e) | MASK_2(m, __VA_ARGS__) +#define MASK_8(m, a, b, c, d, e, ...) MASK_5(m, a, b, c, d, e) | MASK_3(m, __VA_ARGS__) +#define MASK_9(m, a, b, c, d, e, ...) MASK_5(m, a, b, c, d, e) | MASK_4(m, __VA_ARGS__) + +#define MASK_N(n) MASK_##n +#define MASK_DISPATCH(m, n, ...) MASK_N(n)(m, __VA_ARGS__) + +#define MASK_BITS(m, ...) MASK_DISPATCH(m, ESP_VA_NARG(__VA_ARGS__), __VA_ARGS__) + + +#define SOC_CLK_MASK_BITS(...) MASK_BITS(SOC_CLK, __VA_ARGS__) +#define PERI_CLK_MASK_BITS(...) MASK_BITS(PERI_CLK, __VA_ARGS__) + + +#define SOC_CLK_CTRL2_REG_MASK0 SOC_CLK_MASK_BITS( RMT_SYS, HP_CLKRST_APB, SYSREG_APB, ICM_APB, INTRMTX_APB, ADC_APB, UHCI_APB ) +#define SOC_CLK_CTRL2_REG_MASK1 SOC_CLK_MASK_BITS( UART0_APB, UART1_APB, UART2_APB, UART3_APB, UART4_APB, I2C0_APB, I2C1_APB ) +#define SOC_CLK_CTRL2_REG_MASK2 SOC_CLK_MASK_BITS( I2S0_APB, I2S1_APB, I2S2_APB, I3C_MST_APB, I3C_SLV_APB, GPSPI2_APB, GPSPI3_APB ) +#define SOC_CLK_CTRL2_REG_MASK3 SOC_CLK_MASK_BITS( TIMERGRP0_APB, TIMERGRP1_APB, SYSTIMER_APB, TWAI0_APB, TWAI1_APB, TWAI2_APB ) +#define SOC_CLK_CTRL2_REG_MASK4 SOC_CLK_MASK_BITS( MCPWM0_APB, MCPWM1_APB, USB_DEVICE_APB, PCNT_APB, PARLIO_APB ) +#define SOC_CLK_CTRL2_REG_MASK() SOC_CLK_CTRL2_REG_MASK0 | SOC_CLK_CTRL2_REG_MASK1 | SOC_CLK_CTRL2_REG_MASK2 | SOC_CLK_CTRL2_REG_MASK3 | SOC_CLK_CTRL2_REG_MASK4 +#define SOC_CLK_CTRL3_REG_MASK() SOC_CLK_MASK_BITS( IOMUX_APB, LEDC_APB, LCDCAM_APB, ETM_APB) + +#define PERI_CLK_CTRL00_REG_MASK() PERI_CLK_MASK_BITS( FLASH_PLL, FLASH_CORE, PSRAM_PLL, PSRAM_CORE, PAD_EMAC_REF, EMAC_RMII, EMAC_RX ) +#define PERI_CLK_CTRL01_REG_MASK() PERI_CLK_MASK_BITS( EMAC_TX, EMAC_PTP_REF, EMAC_UNUSED0, EMAC_UNUSED1, SDIO_LS ) +#define PERI_CLK_CTRL02_REG_MASK() PERI_CLK_MASK_BITS( SDIO_LS_SLF, SDIO_LS_DRV, SDIO_LS_SAM ) +#define PERI_CLK_CTRL03_REG_MASK() PERI_CLK_MASK_BITS( MIPI_DSI_DPHY_CFG, MIPI_CSI_DPHY_CFG) | HP_SYS_CLKRST_REG_MIPI_DSI_DPHY_PLL_REFCLK_EN_M | HP_SYS_CLKRST_REG_MIPI_DSI_DPICLK_EN_M +#define PERI_CLK_CTRL10_REG_MASK() PERI_CLK_MASK_BITS( I2C0, I2C1 ) +#define PERI_CLK_CTRL11_REG_MASK() PERI_CLK_MASK_BITS( I2S0_RX ) +#define PERI_CLK_CTRL13_REG_MASK() PERI_CLK_MASK_BITS( I2S0_TX ) +#define PERI_CLK_CTRL14_REG_MASK() PERI_CLK_MASK_BITS( I2S1_RX ) +#define PERI_CLK_CTRL15_REG_MASK() PERI_CLK_MASK_BITS( I2S1_TX ) +#define PERI_CLK_CTRL17_REG_MASK() PERI_CLK_MASK_BITS( I2S2_RX ) +#define PERI_CLK_CTRL18_REG_MASK() PERI_CLK_MASK_BITS( I2S2_TX ) +#define PERI_CLK_CTRL19_REG_MASK() PERI_CLK_MASK_BITS( LCD ) +#define PERI_CLK_CTRL110_REG_MASK() PERI_CLK_MASK_BITS( UART0 ) +#define PERI_CLK_CTRL111_REG_MASK() PERI_CLK_MASK_BITS( UART1 ) +#define PERI_CLK_CTRL112_REG_MASK() PERI_CLK_MASK_BITS( UART2 ) +#define PERI_CLK_CTRL113_REG_MASK() PERI_CLK_MASK_BITS( UART3 ) +#define PERI_CLK_CTRL114_REG_MASK() PERI_CLK_MASK_BITS( UART4 ) +#define PERI_CLK_CTRL115_REG_MASK() PERI_CLK_MASK_BITS( TWAI0, TWAI1, TWAI2 ) +#define PERI_CLK_CTRL116_REG_MASK() PERI_CLK_MASK_BITS( GPSPI2_HS, GPSPI2_MST, GPSPI3_HS ) +#define PERI_CLK_CTRL117_REG_MASK() PERI_CLK_MASK_BITS( GPSPI3_MST, PARLIO_RX ) +#define PERI_CLK_CTRL118_REG_MASK() PERI_CLK_MASK_BITS( PARLIO_TX ) +#define PERI_CLK_CTRL119_REG_MASK() PERI_CLK_MASK_BITS( I3C_MST, CAM ) +#define PERI_CLK_CTRL20_REG_MASK() PERI_CLK_MASK_BITS( MCPWM0, MCPWM1, TIMERGRP0_T0, TIMERGRP0_T1, TIMERGRP0_WDT, TIMERGRP0_TGRT ) +#define PERI_CLK_CTRL21_REG_MASK() PERI_CLK_MASK_BITS( TIMERGRP1_T0, TIMERGRP1_T1, TIMERGRP1_WDT, SYSTIMER ) +#define PERI_CLK_CTRL22_REG_MASK() PERI_CLK_MASK_BITS( LEDC, RMT ) +#define PERI_CLK_CTRL23_REG_MASK() PERI_CLK_MASK_BITS( ADC ) +#define PERI_CLK_CTRL24_REG_MASK() PERI_CLK_MASK_BITS( PVT ) +#define PERI_CLK_CTRL25_REG_MASK0 PERI_CLK_MASK_BITS( PVT_PERI_GROUP1, PVT_PERI_GROUP2, PVT_PERI_GROUP3, PVT_PERI_GROUP4, CRYPTO_AES, CRYPTO_DS ) +#define PERI_CLK_CTRL25_REG_MASK1 PERI_CLK_MASK_BITS( CRYPTO_ECC, CRYPTO_HMAC, CRYPTO_RSA, CRYPTO_SEC, CRYPTO_SHA, CRYPTO_ECDSA, CRYPTO_KM, ISP ) +#define PERI_CLK_CTRL25_REG_MASK() PERI_CLK_CTRL25_REG_MASK0 | PERI_CLK_CTRL25_REG_MASK1 +#define PERI_CLK_CTRL26_REG_MASK() PERI_CLK_MASK_BITS( IOMUX, H264, PADBIST_RX ) +#define PERI_CLK_CTRL27_REG_MASK() PERI_CLK_MASK_BITS( PADBIST_TX ) + + +const static sleep_retention_entries_config_t clock_icg_config[] = { + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(0), HP_SYS_CLKRST_PERI_CLK_CTRL00_REG, 0x0, PERI_CLK_CTRL00_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(1), HP_SYS_CLKRST_PERI_CLK_CTRL01_REG, 0x0, PERI_CLK_CTRL01_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(2), HP_SYS_CLKRST_PERI_CLK_CTRL02_REG, 0x0, PERI_CLK_CTRL02_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(3), HP_SYS_CLKRST_PERI_CLK_CTRL03_REG, 0x0, PERI_CLK_CTRL03_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(4), HP_SYS_CLKRST_PERI_CLK_CTRL10_REG, 0x0, PERI_CLK_CTRL10_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(5), HP_SYS_CLKRST_PERI_CLK_CTRL11_REG, 0x0, PERI_CLK_CTRL11_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [6] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(6), HP_SYS_CLKRST_PERI_CLK_CTRL13_REG, 0x0, PERI_CLK_CTRL13_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(7), HP_SYS_CLKRST_PERI_CLK_CTRL14_REG, 0x0, PERI_CLK_CTRL14_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [8] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(8), HP_SYS_CLKRST_PERI_CLK_CTRL15_REG, 0x0, PERI_CLK_CTRL15_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [9] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(9), HP_SYS_CLKRST_PERI_CLK_CTRL17_REG, 0x0, PERI_CLK_CTRL17_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [10] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(10), HP_SYS_CLKRST_PERI_CLK_CTRL18_REG, 0x0, PERI_CLK_CTRL18_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [11] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(11), HP_SYS_CLKRST_PERI_CLK_CTRL19_REG, 0x0, PERI_CLK_CTRL19_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [12] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(12), HP_SYS_CLKRST_PERI_CLK_CTRL110_REG, 0x0, PERI_CLK_CTRL110_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [13] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(13), HP_SYS_CLKRST_PERI_CLK_CTRL111_REG, 0x0, PERI_CLK_CTRL111_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [14] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(14), HP_SYS_CLKRST_PERI_CLK_CTRL112_REG, 0x0, PERI_CLK_CTRL112_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [15] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(15), HP_SYS_CLKRST_PERI_CLK_CTRL113_REG, 0x0, PERI_CLK_CTRL113_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [16] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(16), HP_SYS_CLKRST_PERI_CLK_CTRL114_REG, 0x0, PERI_CLK_CTRL114_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [17] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(17), HP_SYS_CLKRST_PERI_CLK_CTRL115_REG, 0x0, PERI_CLK_CTRL115_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [18] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(18), HP_SYS_CLKRST_PERI_CLK_CTRL116_REG, 0x0, PERI_CLK_CTRL116_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [19] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(19), HP_SYS_CLKRST_PERI_CLK_CTRL117_REG, 0x0, PERI_CLK_CTRL117_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [20] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(20), HP_SYS_CLKRST_PERI_CLK_CTRL118_REG, 0x0, PERI_CLK_CTRL118_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [21] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(21), HP_SYS_CLKRST_PERI_CLK_CTRL119_REG, 0x0, PERI_CLK_CTRL119_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [22] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(22), HP_SYS_CLKRST_PERI_CLK_CTRL20_REG, 0x0, PERI_CLK_CTRL20_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [23] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(23), HP_SYS_CLKRST_PERI_CLK_CTRL21_REG, 0x0, PERI_CLK_CTRL21_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [24] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(24), HP_SYS_CLKRST_PERI_CLK_CTRL22_REG, 0x0, PERI_CLK_CTRL22_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [25] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(25), HP_SYS_CLKRST_PERI_CLK_CTRL23_REG, 0x0, PERI_CLK_CTRL23_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [26] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(26), HP_SYS_CLKRST_PERI_CLK_CTRL24_REG, 0x0, PERI_CLK_CTRL24_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [27] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(27), HP_SYS_CLKRST_PERI_CLK_CTRL25_REG, 0x0, PERI_CLK_CTRL25_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [28] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(28), HP_SYS_CLKRST_PERI_CLK_CTRL26_REG, 0x0, PERI_CLK_CTRL26_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [29] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(29), HP_SYS_CLKRST_PERI_CLK_CTRL27_REG, 0x0, PERI_CLK_CTRL27_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [30] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(30), HP_SYS_CLKRST_SOC_CLK_CTRL2_REG, 0x0, SOC_CLK_CTRL2_REG_MASK(), 0, 1), .owner = ENTRY(0) }, + [31] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_CLOCK_ICG_LINK(31), HP_SYS_CLKRST_SOC_CLK_CTRL3_REG, 0x0, SOC_CLK_CTRL3_REG_MASK(), 0, 1), .owner = ENTRY(0) } +}; + +typedef struct { + void *regdma_desc[ARRAY_SIZE(clock_icg_config)]; +} pmu_sleep_clock_icg_context_t; + +typedef struct { + const sleep_retention_entries_config_t *config; + int size; +} sleep_clock_icg_init_args_t; + +static esp_err_t sleep_clock_icg_init(void *arg) +{ + sleep_clock_icg_init_args_t *init_args = (sleep_clock_icg_init_args_t *)arg; + esp_err_t err = sleep_retention_entries_create(init_args->config, init_args->size, REGDMA_LINK_PRI_CLOCK_ICG, SLEEP_RETENTION_MODULE_CLOCK_ICG); + if (err == ESP_OK) { + sleep_retention_entries_config_t pcr_regs_retention[] = { +#define N_REGS_PCR() (((HP_SYS_CLKRST_HPCORE_WDT_RESET_SOURCE0_REG - DR_REG_HP_SYS_CLKRST_BASE) / 4) + 1) + { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_CLOCK_ICG_LINK(0xff), DR_REG_HP_SYS_CLKRST_BASE, DR_REG_HP_SYS_CLKRST_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) } +#undef N_REGS_PCR + }; + err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_CLOCK_ICG, SLEEP_RETENTION_MODULE_CLOCK_ICG); + } + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system sleep clock ICG, 1 level priority"); + ESP_LOGI(TAG, "System sleep clock ICG setting initialization"); + return ESP_OK; +} + +ESP_SYSTEM_INIT_FN(sleep_clock_icg_startup_init, SECONDARY, BIT(0), 106) +{ + sleep_clock_icg_init_args_t init_args = { .config = clock_icg_config, .size = ARRAY_SIZE(clock_icg_config) }; + sleep_retention_module_init_param_t clock_icg_init_param = { + .cbs = { .create = { .handle = sleep_clock_icg_init, .arg = (void *)&init_args } } + }; + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_ICG, &clock_icg_init_param); + if (err == ESP_OK) { + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_CLOCK_ICG); + } + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system sleep clock ICG"); + + static DRAM_ATTR pmu_sleep_clock_icg_context_t clock_icg_context; + for (int i = 0; (err == ESP_OK) && (i < ARRAY_SIZE(clock_icg_config)); i++) { + void *desc = sleep_retention_find_link_by_id(REGDMA_CLOCK_ICG_LINK(i)); + if (desc) { + clock_icg_context.regdma_desc[i] = desc; + } else { + err = ESP_ERR_NOT_FOUND; + } + } + if (err == ESP_OK) { + PMU_instance()->priv = (void *)&clock_icg_context; + } + ESP_RETURN_ON_ERROR(err, TAG, "failed to initialize system sleep clock ICG context"); + return ESP_OK; +} + + +void pmu_sleep_clock_icg_config(void *icg_context, const uint32_t icg_func) +{ + assert(icg_context); + pmu_sleep_clock_icg_context_t *clock_icg = (pmu_sleep_clock_icg_context_t *)icg_context; + /* Locking is not required here because this function is always invoked + * within esp_light_sleep_start(), where the necessary lock has already been acquired. */ + if (icg_func & BIT(PMU_ICG_FUNC_ENA_IOMUX)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[28], PERI_CLK_EN(IOMUX), PERI_CLK_MASK(IOMUX)); + } + if (icg_func & BIT(PMU_ICG_FUNC_ENA_LEDC)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[24], PERI_CLK_EN(LEDC), PERI_CLK_MASK(LEDC)); + } + if (icg_func & BIT(PMU_ICG_FUNC_ENA_UART0)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[12], PERI_CLK_EN(UART0), PERI_CLK_MASK(UART0)); + } + if (icg_func & BIT(PMU_ICG_FUNC_ENA_UART1)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[13], PERI_CLK_EN(UART1), PERI_CLK_MASK(UART1)); + } +#if SOC_UART_HP_NUM > 2 + if (icg_func & BIT(PMU_ICG_FUNC_ENA_UART2)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[14], PERI_CLK_EN(UART2), PERI_CLK_MASK(UART2)); + } +#endif +#if SOC_UART_HP_NUM > 3 + if (icg_func & BIT(PMU_ICG_FUNC_ENA_UART3)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[15], PERI_CLK_EN(UART3), PERI_CLK_MASK(UART3)); + } +#endif +#if SOC_UART_HP_NUM > 4 + if (icg_func & BIT(PMU_ICG_FUNC_ENA_UART4)) { + regdma_link_set_write_wait_content(clock_icg->regdma_desc[16], PERI_CLK_EN(UART4), PERI_CLK_MASK(UART4)); + } +#endif +} diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_icg_mapping.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_icg_mapping.h new file mode 100644 index 00000000000..057b5989252 --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_icg_mapping.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/pmu_icg_mapping.h" + +// Software-defined sleep clock ICG function (used by REGDMA) +#define PMU_ICG_APB_ENA_UART0 6 +#define PMU_ICG_APB_ENA_UART1 7 +#define PMU_ICG_APB_ENA_UART2 8 +#define PMU_ICG_APB_ENA_UART3 9 +#define PMU_ICG_APB_ENA_UART4 10 +#define PMU_ICG_APB_ENA_LEDC 27 +#define PMU_ICG_APB_ENA_IOMUX 28 +#define PMU_ICG_FUNC_ENA_UART0 6 +#define PMU_ICG_FUNC_ENA_UART1 7 +#define PMU_ICG_FUNC_ENA_UART2 8 +#define PMU_ICG_FUNC_ENA_UART3 9 +#define PMU_ICG_FUNC_ENA_UART4 10 +#define PMU_ICG_FUNC_ENA_LEDC 27 +#define PMU_ICG_FUNC_ENA_IOMUX 28 diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h index 675d7c1921b..b3ec809266c 100644 --- a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h @@ -13,6 +13,10 @@ #include "hal/pmu_hal.h" #include "sdkconfig.h" +#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA +#include "pmu_icg_mapping.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -112,6 +116,11 @@ typedef struct { const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mode_t mode); +#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA && !defined(CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) +void pmu_sleep_clock_icg_config(void *icg_context, const uint32_t icg_func); +#endif + + /* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/ typedef union { struct { @@ -328,38 +337,43 @@ typedef struct { typedef struct { pmu_hp_sys_cntl_reg_t syscntl; + uint32_t icg_func[2]; } pmu_sleep_digital_config_t; #if CONFIG_ESP32P4_SELECTS_REV_LESS_V3 -#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \ +#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ .syscntl = { \ .dig_pad_slp_sel = 0, \ .lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \ .dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \ - } \ + }, \ + .icg_func = { 0, 0 } \ } -#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \ +#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ .syscntl = { \ .dig_pad_slp_sel = 0, \ .lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \ .dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \ - } \ + }, \ + .icg_func = { 0, clk_flags } \ } #else // !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 -#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \ +#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ .syscntl = { \ .dig_pad_slp_sel = 0, \ .dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \ - } \ + }, \ + .icg_func = { 0, 0 } \ } -#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \ +#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ .syscntl = { \ .dig_pad_slp_sel = 0, \ .dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \ - } \ + }, \ + .icg_func = { 0, clk_flags } \ } #endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index ef8473c4dfb..ad9e148d2bf 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1744,31 +1744,35 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) s_config.gpio_trigger_mode = 0; #endif s_config.wakeup_triggers &= ~RTC_GPIO_TRIG_EN; -#if SOC_PMU_SUPPORTED && (SOC_UART_HP_NUM > 2) - } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN | RTC_UART2_TRIG_EN))) { - s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN | RTC_UART2_TRIG_EN); - } -#else - } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) { - s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN); - } + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART0, RTC_UART0_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART0_TRIG_EN; + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART1, RTC_UART1_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART1_TRIG_EN; +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART2, RTC_UART2_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART2_TRIG_EN; +#endif +#if (SOC_UART_HP_NUM > 3) + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART3, RTC_UART3_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART3_TRIG_EN; +#endif +#if (SOC_UART_HP_NUM > 4) + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART4, RTC_UART4_TRIG_EN)) { + s_config.wakeup_triggers &= ~RTC_UART4_TRIG_EN; #endif #if CONFIG_ULP_COPROC_TYPE_FSM - else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) { + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN; - } #endif #if SOC_LP_VAD_SUPPORTED - else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_VAD, RTC_LP_VAD_TRIG_EN)) { + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_VAD, RTC_LP_VAD_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_LP_VAD_TRIG_EN; - } #endif #if SOC_VBAT_SUPPORTED - else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_VBAT_UNDER_VOLT, RTC_VBAT_UNDER_VOLT_TRIG_EN)) { + } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_VBAT_UNDER_VOLT, RTC_VBAT_UNDER_VOLT_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_VBAT_UNDER_VOLT_TRIG_EN; - } #endif - else { + } else { ESP_LOGE(TAG, "Incorrect wakeup source (%d) to disable.", (int) source); return ESP_ERR_INVALID_STATE; } @@ -2292,18 +2296,27 @@ esp_err_t esp_sleep_enable_uart_wakeup(int uart_num) s_config.wakeup_triggers |= RTC_UART0_TRIG_EN; } else if (uart_num == UART_NUM_1) { s_config.wakeup_triggers |= RTC_UART1_TRIG_EN; -#if SOC_PMU_SUPPORTED && (SOC_UART_HP_NUM > 2) +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP } else if (uart_num == UART_NUM_2) { s_config.wakeup_triggers |= RTC_UART2_TRIG_EN; #endif -#if SOC_PM_SUPPORT_LP_UART_WAKEUP - } else if (uart_num == LP_UART_NUM_0) { - s_config.wakeup_triggers |= PMU_LP_UART_WAKEUP_EN; +#if (SOC_UART_HP_NUM > 3) + } else if (uart_num == UART_NUM_3) { + s_config.wakeup_triggers |= RTC_UART3_TRIG_EN; #endif - } else { +#if (SOC_UART_HP_NUM > 4) + } else if (uart_num == UART_NUM_4) { + s_config.wakeup_triggers |= RTC_UART4_TRIG_EN; +#endif + } else +#if SOC_PM_SUPPORT_LP_UART_WAKEUP + if (uart_num == LP_UART_NUM_0) { + s_config.wakeup_triggers |= PMU_LP_UART_WAKEUP_EN; + } else +#endif + { return ESP_ERR_INVALID_ARG; } - return ESP_OK; } @@ -2379,15 +2392,22 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause(); #endif + uint32_t uart_wakeup_mask = RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN; +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP + uart_wakeup_mask |= RTC_UART2_TRIG_EN; +#endif +#if (SOC_UART_HP_NUM > 3) + uart_wakeup_mask |= RTC_UART3_TRIG_EN; +#endif +#if (SOC_UART_HP_NUM > 4) + uart_wakeup_mask |= RTC_UART4_TRIG_EN; +#endif + if (wakeup_cause & RTC_TIMER_TRIG_EN) { return ESP_SLEEP_WAKEUP_TIMER; } else if (wakeup_cause & RTC_GPIO_TRIG_EN) { return ESP_SLEEP_WAKEUP_GPIO; -#if SOC_PMU_SUPPORTED && (SOC_UART_HP_NUM > 2) - } else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN | RTC_UART2_TRIG_EN)) { -#else - } else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) { -#endif + } else if (wakeup_cause & uart_wakeup_mask) { return ESP_SLEEP_WAKEUP_UART; #if SOC_PM_SUPPORT_EXT0_WAKEUP } else if (wakeup_cause & RTC_EXT0_TRIG_EN) { @@ -2460,16 +2480,26 @@ uint32_t esp_sleep_get_wakeup_causes(void) wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_GPIO); } if (wakeup_cause_raw & RTC_UART0_TRIG_EN) { - wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART); + wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART0); } if (wakeup_cause_raw & RTC_UART1_TRIG_EN) { wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART1); } -#if SOC_PMU_SUPPORTED && (SOC_UART_HP_NUM > 2) +#if (SOC_UART_HP_NUM > 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP if (wakeup_cause_raw & RTC_UART2_TRIG_EN) { wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART2); } #endif +#if (SOC_UART_HP_NUM > 3) + if (wakeup_cause_raw & RTC_UART3_TRIG_EN) { + wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART3); + } +#endif +#if (SOC_UART_HP_NUM > 4) + if (wakeup_cause_raw & RTC_UART4_TRIG_EN) { + wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_UART4); + } +#endif #if SOC_PM_SUPPORT_EXT0_WAKEUP if (wakeup_cause_raw & RTC_EXT0_TRIG_EN) { wakeup_cause |= BIT(ESP_SLEEP_WAKEUP_EXT0); diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index 26e07b8e552..c4a8a0af6c1 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -94,6 +94,7 @@ SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/p SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32h4/sleep_clock.c on BIT(0) SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c on BIT(0) SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32s31/sleep_clock.c on BIT(0) +SECONDARY: 106: sleep_clock_icg_startup_init in components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c on BIT(0) SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) # app_trace doesn't have init dependencies diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 42f8d282f1e..719639c3c91 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -707,6 +707,10 @@ config SOC_PM_MODEM_PD_BY_SW bool default y +config SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP + bool + default y + config SOC_CLK_APLL_SUPPORTED bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 053c82ec591..1f128eb298b 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -353,6 +353,9 @@ #define SOC_CONFIGURABLE_VDDSDIO_SUPPORTED (1) #define SOC_PM_MODEM_PD_BY_SW (1) + +#define SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP (1) + /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_APLL_SUPPORTED (1) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index dbe199007c9..858409ba5df 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1747,6 +1747,10 @@ config SOC_PM_SUPPORT_RTC_PERIPH_PD bool default y +config SOC_PM_SUPPORT_PMU_CLK_ICG + bool + default y + config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y @@ -1763,6 +1767,10 @@ config SOC_PM_CACHE_RETENTION_BY_PAU bool default y +config SOC_PM_SLEEP_CLK_ICG_USE_REGDMA + bool + default y + config SOC_PM_PAU_LINK_NUM int default 4 diff --git a/components/soc/esp32p4/include/soc/retention_periph_defs.h b/components/soc/esp32p4/include/soc/retention_periph_defs.h index bfa1570a712..be3fb879cf4 100644 --- a/components/soc/esp32p4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32p4/include/soc/retention_periph_defs.h @@ -64,10 +64,13 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_JPEG = 38, SLEEP_RETENTION_MODULE_LCDCAM = 39, + /* PMU REGDMA clock icg */ + SLEEP_RETENTION_MODULE_CLOCK_ICG = SOC_PM_RETENTION_MODULE_NUM - 2, + SLEEP_RETENTION_MODULE_MAX = SOC_PM_RETENTION_MODULE_NUM - 1 } periph_retention_module_t; -#define is_top_domain_module(m) (m <= SLEEP_RETENTION_MODULE_LCDCAM) +#define is_top_domain_module(m) (((m) <= SLEEP_RETENTION_MODULE_LCDCAM) || ((m) == SLEEP_RETENTION_MODULE_CLOCK_ICG)) #ifdef __cplusplus } diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index b5a8588133a..137d2404b84 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -667,12 +667,16 @@ #define SOC_PM_SUPPORT_CNNT_PD (1) #define SOC_PM_SUPPORT_RTC_PERIPH_PD (1) +#define SOC_PM_SUPPORT_PMU_CLK_ICG (1) + #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! 2) && !SOC_PM_RTC_NOT_SUPPORT_UART2_WAKEUP + uart_wakeup_causes |= BIT(ESP_SLEEP_WAKEUP_UART2); +#endif +#if (SOC_UART_HP_NUM > 3) + uart_wakeup_causes |= BIT(ESP_SLEEP_WAKEUP_UART3); +#endif +#if (SOC_UART_HP_NUM > 4) + uart_wakeup_causes |= BIT(ESP_SLEEP_WAKEUP_UART4); +#endif + return uart_wakeup_causes; +} + static void light_sleep_task(void *args) { while (true) { @@ -42,7 +57,7 @@ static void light_sleep_task(void *args) wakeup_reason = "timer"; } else if (wakup_causes & BIT(ESP_SLEEP_WAKEUP_GPIO)) { wakeup_reason = "pin"; - } else if (wakup_causes & (BIT(ESP_SLEEP_WAKEUP_UART) | BIT(ESP_SLEEP_WAKEUP_UART1) | BIT(ESP_SLEEP_WAKEUP_UART2))) { + } else if (wakup_causes & uart_wakeup_causes()) { wakeup_reason = "uart"; /* Hang-up for a while to switch and execute the uart task * Otherwise the chip may fall sleep again before running uart task */