From aac59ed5ec5fac8c05c7520cc2000785f3034d6c Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 6 Sep 2021 14:17:43 +0800 Subject: [PATCH] Power Management: add XTAL power domain to control whether external 40MHz xtal is powered down during sleep --- components/esp_hw_support/port/esp32c3/rtc_sleep.c | 4 ++-- components/esp_hw_support/port/esp32s2/rtc_sleep.c | 2 ++ components/esp_system/sleep_modes.c | 13 ++++++------- components/soc/esp32c3/include/soc/rtc.h | 3 +++ components/soc/esp32s2/include/soc/rtc.h | 3 +++ components/soc/esp32s3/include/soc/rtc.h | 1 + 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/components/esp_hw_support/port/esp32c3/rtc_sleep.c b/components/esp_hw_support/port/esp32c3/rtc_sleep.c index 3136e78fe0..5599e382d1 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c3/rtc_sleep.c @@ -137,8 +137,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject); REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); - /* gating XTAL clock */ - REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING); + REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING, cfg.xtal_fpu); } void rtc_sleep_low_init(uint32_t slowclk_period) diff --git a/components/esp_hw_support/port/esp32s2/rtc_sleep.c b/components/esp_hw_support/port/esp32s2/rtc_sleep.c index 34ee00aa83..eb028d269a 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32s2/rtc_sleep.c @@ -136,6 +136,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject); REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); + + REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu); } void rtc_sleep_low_init(uint32_t slowclk_period) diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index 3534d6571a..7deb35e5f7 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -1320,9 +1320,9 @@ static uint32_t get_power_down_flags(void) } #endif - if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] == ESP_PD_OPTION_AUTO) { - s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; - } +#ifdef CONFIG_IDF_TARGET_ESP32 + s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; +#endif const char *option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */}; ESP_LOGD(TAG, "RTC_PERIPH: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]]); @@ -1353,10 +1353,9 @@ static uint32_t get_power_down_flags(void) if (s_config.pd_options[ESP_PD_DOMAIN_RTC8M] != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_INT_8M; } - -#ifdef CONFIG_IDF_TARGET_ESP32 - pd_flags |= RTC_SLEEP_PD_XTAL; -#endif + if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) { + pd_flags |= RTC_SLEEP_PD_XTAL; + } /** * VDD_SDIO power domain shall be kept on during the light sleep diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index d60c99cd1f..5b45270627 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -649,6 +649,7 @@ typedef struct { uint32_t rtc_dbias_wak : 5; //!< set bias for RTC domain, in active mode uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator + uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep uint32_t deep_slp_reject : 1; uint32_t light_slp_reject : 1; } rtc_sleep_config_t; @@ -684,6 +685,7 @@ typedef struct { : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ : RTC_CNTL_DBIAS_SLP, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .xtal_fpu = is_dslp(sleep_flags) ? 0 : ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ .deep_slp_reject = 1, \ .light_slp_reject = 1 \ }; @@ -699,6 +701,7 @@ typedef struct { #define RTC_SLEEP_PD_CPU BIT(8) //!< Power down CPU when in lightsleep, but not restart #define RTC_SLEEP_PD_DIG_PERIPH BIT(9) //!< Power down DIG peripherals #define RTC_SLEEP_PD_INT_8M BIT(10) //!< Power down Internal 8M oscillator +#define RTC_SLEEP_PD_XTAL BIT(11) //!< Power down main XTAL /** * @brief Prepare the chip to enter sleep mode diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index 8ac39f6030..e415bc8331 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -663,6 +663,7 @@ typedef struct { uint32_t rtc_dbias_wak : 3; //!< set bias for RTC domain, in active mode uint32_t rtc_dbias_slp : 3; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator + uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep uint32_t deep_slp_reject : 1; uint32_t light_slp_reject : 1; } rtc_sleep_config_t; @@ -695,6 +696,7 @@ typedef struct { : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ : RTC_CNTL_DBIAS_1V00, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .xtal_fpu = is_dslp(sleep_flags) ? 0 : ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ .deep_slp_reject = 1, \ .light_slp_reject = 1 \ }; @@ -707,6 +709,7 @@ typedef struct { #define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator #define RTC_SLEEP_PD_WIFI BIT(6) #define RTC_SLEEP_PD_INT_8M BIT(7) //!< Power down Internal 8M oscillator +#define RTC_SLEEP_PD_XTAL BIT(8) //!< Power down main XTAL /** * @brief Prepare the chip to enter sleep mode diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index 56ad508d58..7ca1d44201 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -673,6 +673,7 @@ typedef struct { #define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator #define RTC_SLEEP_PD_WIFI BIT(6) #define RTC_SLEEP_PD_INT_8M BIT(10) //!< Power down Internal 8M oscillator +#define RTC_SLEEP_PD_XTAL BIT(11) //!< Power down main XTAL /** * @brief Prepare the chip to enter sleep mode