Skip to content

Commit

Permalink
pm: fixed RTC8M domain power issues
Browse files Browse the repository at this point in the history
introduced in e44ead5

1. The int8M power domain config by default is PD. While LEDC is using
RTC8M as clock source, this power domain will be kept on.

But when 8MD256 is used as RTC clock source, the power domain should
also be kept on.

On ESP32, there was protection for it, but broken by commit
e44ead5. Currently the power domain
will be forced on when LEDC is using RTC8M as clock source &&
!int8m_pd_en (user enable ESP_PDP_DOMAIN_RTC8M in lightsleep). Otherwise
the power domain will be powered off, regardless of RTC clock source.

In other words, int8M domain will be forced off (even when 8MD256
used as RTC clock source) if LEDC not using RTC8M as clock source, user
doesn't enable ESP_PDP_DOMAIN_RTC8M, or in deep sleep.

On later chips, there's no such protection, so 8MD256 could't be used as
RTC clock source in sleep modes.

This commit adds protection of 8MD256 clock to other chips. Fixes the
incorrect protection logic overriding on ESP32. Now the power domain
will be determiend by the logic below (order by priority):

    1. When RTC clock source uses 8MD256, power up
    2. When LEDC uses RTC8M clock source, power up
    3. In deepsleep, power down
    4. Otherwise determined by user config of ESP_PDP_DOMAIN_RTC8M,
       power down by default. (This is preferred to have highest
       priority, but it's kept as is because of current code structure.)

2. Before, after the macro `RTC_SLEEP_CONFIG_DEFAULT` decides dbias, the
protection above may force the int8m PU. This may cause the inconsistent
of dbias and the int8m PU status.

This commit lifts the logic of pd int8m/xtal fpu logic to upper layer
(sleep_modes.c).

Related: #8007, #8089

temp
  • Loading branch information
ginkgm committed May 11, 2022
1 parent 523c518 commit 2905cbb
Show file tree
Hide file tree
Showing 21 changed files with 88 additions and 25 deletions.
5 changes: 5 additions & 0 deletions components/esp_hw_support/port/esp32/rtc_clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,11 @@ void rtc_dig_clk8m_disable(void)
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}

bool rtc_dig_8m_enabled(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
}

/* Name used in libphy.a:phy_chip_v7.o
* TODO: update the library to use rtc_clk_xtal_freq_get
*/
Expand Down
9 changes: 1 addition & 8 deletions components/esp_hw_support/port/esp32/rtc_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)

REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu);

if (REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL) == RTC_SLOW_FREQ_8MD256) {
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
} else {
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
}
//Keep the RTC8M_CLK on in light_sleep mode if the ledc low-speed channel is clocked by RTC8M_CLK.
if (!cfg.int_8m_pd_en && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) {
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD);
if (!cfg.int_8m_pd_en) {
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
} else {
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
Expand Down
5 changes: 5 additions & 0 deletions components/esp_hw_support/port/esp32c3/rtc_clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,11 @@ void rtc_dig_clk8m_disable(void)
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}

bool rtc_dig_8m_enabled(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
}

static bool rtc_clk_set_bbpll_always_on(void)
{
/* We just keep the rtc bbpll clock on just under the case that
Expand Down
4 changes: 1 addition & 3 deletions components/esp_hw_support/port/esp32c3/rtc_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
cfg.int_8m_pd_en ? RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT : RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP);
}

//Keep the RTC8M_CLK on in light_sleep mode if the ledc low-speed channel is clocked by RTC8M_CLK.
if (!cfg.int_8m_pd_en && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) {
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD);
if (!cfg.int_8m_pd_en) {
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_NOGATING);
} else {
Expand Down
5 changes: 5 additions & 0 deletions components/esp_hw_support/port/esp32s2/rtc_clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,11 @@ void rtc_dig_clk8m_disable(void)
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}

bool rtc_dig_8m_enabled(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
}

/* Name used in libphy.a:phy_chip_v7.o
* TODO: update the library to use rtc_clk_xtal_freq_get
*/
Expand Down
4 changes: 1 addition & 3 deletions components/esp_hw_support/port/esp32s2/rtc_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
cfg.int_8m_pd_en ? RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT : RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP);
}

//Keep the RTC8M_CLK on in light_sleep mode if the ledc low-speed channel is clocked by RTC8M_CLK.
if (!cfg.int_8m_pd_en && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) {
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD);
if (!cfg.int_8m_pd_en) {
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
} else {
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
Expand Down
5 changes: 5 additions & 0 deletions components/esp_hw_support/port/esp32s3/rtc_clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,11 @@ void rtc_dig_clk8m_disable(void)
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
}

bool rtc_dig_8m_enabled(void)
{
return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
}

static bool rtc_clk_set_bbpll_always_on(void)
{
/* We just keep the rtc bbpll clock on just under the case that
Expand Down
4 changes: 1 addition & 3 deletions components/esp_hw_support/port/esp32s3/rtc_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
/* mem pd */
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU);

//Keep the RTC8M_CLK on in light_sleep mode if the ledc low-speed channel is clocked by RTC8M_CLK.
if (!cfg.int_8m_pd_en && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) {
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD);
if (!cfg.int_8m_pd_en) {
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
} else {
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
Expand Down
17 changes: 16 additions & 1 deletion components/esp_hw_support/sleep_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,20 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
suspend_uarts();
}

#if SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256
//Keep the RTC8M_CLK on if RTC clock is 8MD256.
bool rtc_using_8md256 = (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_8MD256);
#else
bool rtc_using_8md256 = false;
#endif
//Keep the RTC8M_CLK on if the ledc low-speed channel is clocked by RTC8M_CLK in lightsleep mode
bool dig_8m_enabled = !deep_sleep && rtc_dig_8m_enabled();

//Override user-configured power modes.
if (rtc_using_8md256 || dig_8m_enabled) {
pd_flags &= ~RTC_SLEEP_PD_INT_8M;
}

// Save current frequency and switch to XTAL
rtc_cpu_freq_config_t cpu_freq_config;
rtc_clk_cpu_freq_get_config(&cpu_freq_config);
Expand Down Expand Up @@ -437,6 +451,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
}
}
#endif

uint32_t reject_triggers = 0;
if ((pd_flags & RTC_SLEEP_PD_DIG) == 0 && (s_config.wakeup_triggers & RTC_GPIO_TRIG_EN)) {
/* Light sleep, enable sleep reject for faster return from this function,
Expand Down Expand Up @@ -558,7 +573,7 @@ void IRAM_ATTR esp_deep_sleep_start(void)
// Correct the sleep time
s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;

uint32_t force_pd_flags = RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO;
uint32_t force_pd_flags = RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | RTC_SLEEP_PD_INT_8M | RTC_SLEEP_PD_XTAL;

#if SOC_PM_SUPPORT_WIFI_PD
force_pd_flags |= RTC_SLEEP_PD_WIFI;
Expand Down
4 changes: 4 additions & 0 deletions components/soc/esp32/include/soc/Kconfig.soc_caps.in
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ config SOC_ADC_RTC_MAX_BITWIDTH
int
default 12

config SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256
bool
default y

config SOC_SHARED_IDCACHE_SUPPORTED
bool
default y
Expand Down
7 changes: 6 additions & 1 deletion components/soc/esp32/include/soc/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,11 @@ void rtc_dig_clk8m_enable(void);
*/
void rtc_dig_clk8m_disable(void);

/**
* @brief Get whether the rtc digital 8M clock is enabled
*/
bool rtc_dig_8m_enabled(void);

/**
* @brief Calculate the real clock value after the clock calibration
*
Expand Down Expand Up @@ -534,7 +539,7 @@ typedef struct rtc_sleep_config_s {
.rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0, \
.rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0, \
.wifi_pd_en = 0, \
.int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \
.int_8m_pd_en = ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \
.rom_mem_pd_en = 0, \
.deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \
.wdt_flashboot_mod_en = 0, \
Expand Down
1 change: 1 addition & 0 deletions components/soc/esp32/include/soc/soc_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
/*!< RTC */
#define SOC_ADC_RTC_MIN_BITWIDTH (9)
#define SOC_ADC_RTC_MAX_BITWIDTH (12)
#define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256 (1)


/*-------------------------- BROWNOUT CAPS -----------------------------------*/
Expand Down
4 changes: 4 additions & 0 deletions components/soc/esp32c3/include/soc/Kconfig.soc_caps.in
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,10 @@ config SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM
int
default 108

config SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256
bool
default y

config SOC_RTCIO_PIN_COUNT
int
default 0
Expand Down
9 changes: 7 additions & 2 deletions components/soc/esp32c3/include/soc/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,11 @@ void rtc_dig_clk8m_enable(void);
*/
void rtc_dig_clk8m_disable(void);

/**
* @brief Get whether the rtc digital 8M clock is enabled
*/
bool rtc_dig_8m_enabled(void);

/**
* @brief Calculate the real clock value after the clock calibration
*
Expand Down Expand Up @@ -648,7 +653,7 @@ typedef struct {
.wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \
.bt_pd_en = ((sleep_flags) & RTC_SLEEP_PD_BT) ? 1 : 0, \
.cpu_pd_en = ((sleep_flags) & RTC_SLEEP_PD_CPU) ? 1 : 0, \
.int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \
.int_8m_pd_en = ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \
.dig_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0, \
.deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \
.wdt_flashboot_mod_en = 0, \
Expand All @@ -661,7 +666,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, \
.xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \
.deep_slp_reject = 1, \
.light_slp_reject = 1 \
};
Expand Down
2 changes: 2 additions & 0 deletions components/soc/esp32c3/include/soc/soc_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@

#define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3))

#define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256 (1)

/*-------------------------- RTCIO CAPS --------------------------------------*/
/* No dedicated RTCIO subsystem on ESP32-C3. RTC functions are still supported
* for hold, wake & 32kHz crystal functions - via rtc_cntl_reg */
Expand Down
4 changes: 4 additions & 0 deletions components/soc/esp32s2/include/soc/Kconfig.soc_caps.in
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ config SOC_ADC_RTC_MAX_BITWIDTH
int
default 13

config SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256
bool
default y

config SOC_ADC_CALIBRATION_V1_SUPPORTED
bool
default y
Expand Down
9 changes: 7 additions & 2 deletions components/soc/esp32s2/include/soc/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,11 @@ void rtc_dig_clk8m_enable(void);
*/
void rtc_dig_clk8m_disable(void);

/**
* @brief Get whether the rtc digital 8M clock is enabled
*/
bool rtc_dig_8m_enabled(void);

/**
* @brief Calculate the real clock value after the clock calibration
*
Expand Down Expand Up @@ -703,7 +708,7 @@ typedef struct {
.rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0, \
.rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0, \
.wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \
.int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \
.int_8m_pd_en = ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \
.deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \
.wdt_flashboot_mod_en = 0, \
.dig_dbias_wak = RTC_CNTL_DIG_DBIAS_1V10, \
Expand All @@ -717,7 +722,7 @@ typedef struct {
: !((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 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, \
.xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \
.deep_slp_reject = 1, \
.light_slp_reject = 1 \
};
Expand Down
1 change: 1 addition & 0 deletions components/soc/esp32s2/include/soc/soc_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
/*!< RTC */
#define SOC_ADC_RTC_MIN_BITWIDTH (13)
#define SOC_ADC_RTC_MAX_BITWIDTH (13)
#define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256 (1)

/*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
Expand Down
4 changes: 4 additions & 0 deletions components/soc/esp32s3/include/soc/Kconfig.soc_caps.in
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ config SOC_ADC_RTC_MAX_BITWIDTH
int
default 12

config SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256
bool
default y

config SOC_ADC_CALIBRATION_V1_SUPPORTED
bool
default y
Expand Down
9 changes: 7 additions & 2 deletions components/soc/esp32s3/include/soc/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,11 @@ void rtc_dig_clk8m_enable(void);
*/
void rtc_dig_clk8m_disable(void);

/**
* @brief Get whether the rtc digital 8M clock is enabled
*/
bool rtc_dig_8m_enabled(void);

/**
* @brief Calculate the real clock value after the clock calibration
*
Expand Down Expand Up @@ -655,7 +660,7 @@ typedef struct {
.wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \
.bt_pd_en = ((sleep_flags) & RTC_SLEEP_PD_BT) ? 1 : 0, \
.cpu_pd_en = ((sleep_flags) & RTC_SLEEP_PD_CPU) ? 1 : 0, \
.int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \
.int_8m_pd_en = ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \
.dig_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0, \
.deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \
.wdt_flashboot_mod_en = 0, \
Expand All @@ -668,7 +673,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, \
.xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \
.deep_slp_reject = 1, \
.light_slp_reject = 1 \
};
Expand Down
1 change: 1 addition & 0 deletions components/soc/esp32s3/include/soc/soc_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
/*!< RTC */
#define SOC_ADC_RTC_MIN_BITWIDTH (12)
#define SOC_ADC_RTC_MAX_BITWIDTH (12)
#define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256 (1)

/*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
Expand Down

0 comments on commit 2905cbb

Please sign in to comment.