From 01117ef986b06dad15bb2a55e9ed71c3afc064b5 Mon Sep 17 00:00:00 2001 From: jingli Date: Wed, 21 Sep 2022 17:19:27 +0800 Subject: [PATCH 1/2] soc/soc_caps: update soc caps for chips that support power-down of modem hardware Closes WIFI-4424 --- components/esp_hw_support/port/esp32/rtc_init.c | 12 +++++++++++- components/esp_hw_support/port/esp32/rtc_sleep.c | 2 ++ components/esp_hw_support/port/esp32c3/rtc_init.c | 10 ++++++++++ components/esp_hw_support/port/esp32c3/rtc_sleep.c | 4 ++++ components/esp_hw_support/port/esp32s2/rtc_init.c | 10 ++++++++++ components/esp_hw_support/port/esp32s2/rtc_sleep.c | 2 ++ components/esp_hw_support/port/esp32s3/rtc_init.c | 12 +++++++++++- 7 files changed, 50 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/port/esp32/rtc_init.c b/components/esp_hw_support/port/esp32/rtc_init.c index e4dccc6f94..a3537cacc9 100644 --- a/components/esp_hw_support/port/esp32/rtc_init.c +++ b/components/esp_hw_support/port/esp32/rtc_init.c @@ -20,6 +20,16 @@ void rtc_init(rtc_config_t cfg) { + /** + * When run rtc_init, it maybe deep sleep reset. Since we power down modem in deep sleep, after wakeup + * from deep sleep, these fields are changed and not reset. We will access two BB regs(BBPD_CTRL and + * NRXPD_CTRL) in rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these two BB regs + * and finally triggle RTC WDT. So need to clear modem Force PD. + * + * No worry about the power consumption, Because modem Force PD will be set at the end of this function. + */ + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU | RTC_CNTL_TXRF_I2C_PU | RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU); @@ -92,7 +102,7 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } - /* force power down wifi and bt power domain */ + /* force power down modem(wifi and btdm) power domain */ SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); diff --git a/components/esp_hw_support/port/esp32/rtc_sleep.c b/components/esp_hw_support/port/esp32/rtc_sleep.c index 47956eb678..31bd9d8669 100644 --- a/components/esp_hw_support/port/esp32/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32/rtc_sleep.c @@ -183,6 +183,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) } if (cfg.wifi_pd_en) { + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_WIFI_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } else { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); diff --git a/components/esp_hw_support/port/esp32c3/rtc_init.c b/components/esp_hw_support/port/esp32c3/rtc_init.c index 6e29e9008c..11c18b1032 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_init.c +++ b/components/esp_hw_support/port/esp32c3/rtc_init.c @@ -31,6 +31,16 @@ static void set_rtc_dig_dbias(void); void rtc_init(rtc_config_t cfg) { + /** + * When run rtc_init, it maybe deep sleep reset. Since we power down modem in deep sleep, after wakeup + * from deep sleep, these fields are changed and not reset. We will access two BB regs(BBPD_CTRL and + * NRXPD_CTRL) in rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these two BB regs + * and finally triggle RTC WDT. So need to clear modem Force PD. + * + * No worry about the power consumption, Because modem Force PD will be set at the end of this function. + */ + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); diff --git a/components/esp_hw_support/port/esp32c3/rtc_sleep.c b/components/esp_hw_support/port/esp32c3/rtc_sleep.c index a688d019a4..e08fb8efcf 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c3/rtc_sleep.c @@ -176,11 +176,15 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) rtc_sleep_pu(pu_cfg); } if (cfg.wifi_pd_en) { + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_WIFI_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } else { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } if (cfg.bt_pd_en) { + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_NOISO | RTC_CNTL_BT_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN); } else { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN); diff --git a/components/esp_hw_support/port/esp32s2/rtc_init.c b/components/esp_hw_support/port/esp32s2/rtc_init.c index 2b6ad6ba3e..0ae8250604 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_init.c +++ b/components/esp_hw_support/port/esp32s2/rtc_init.c @@ -29,6 +29,16 @@ static void calibrate_ocode(void); void rtc_init(rtc_config_t cfg) { + /** + * When run rtc_init, it maybe deep sleep reset. Since we power down modem in deep sleep, after wakeup + * from deep sleep, these fields are changed and not reset. We will access two BB regs(BBPD_CTRL and + * NRXPD_CTRL) in rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these two BB regs + * and finally triggle RTC WDT. So need to clear modem Force PD. + * + * No worry about the power consumption, Because modem Force PD will be set at the end of this function. + */ + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, cfg.pll_wait); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, cfg.ck8m_wait); diff --git a/components/esp_hw_support/port/esp32s2/rtc_sleep.c b/components/esp_hw_support/port/esp32s2/rtc_sleep.c index 1b9dbebf4c..7807c4eadd 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32s2/rtc_sleep.c @@ -202,6 +202,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) } if (cfg.wifi_pd_en) { + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_WIFI_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } else { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); diff --git a/components/esp_hw_support/port/esp32s3/rtc_init.c b/components/esp_hw_support/port/esp32s3/rtc_init.c index a664da698e..ce41472f8d 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_init.c +++ b/components/esp_hw_support/port/esp32s3/rtc_init.c @@ -43,6 +43,16 @@ uint32_t g_rtc_dbias_pvt_non_240m = 27; void rtc_init(rtc_config_t cfg) { + /** + * When run rtc_init, it maybe deep sleep reset. Since we power down modem in deep sleep, after wakeup + * from deep sleep, these fields are changed and not reset. We will access two BB regs(BBPD_CTRL and + * NRXPD_CTRL) in rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these two BB regs + * and finally triggle RTC WDT. So need to clear modem Force PD. + * + * No worry about the power consumption, Because modem Force PD will be set at the end of this function. + */ + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU); @@ -191,7 +201,7 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } - /* force power down wifi and bt power domain */ + /* force power down modem(wifi and ble) power domain */ SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); From 0dea8d7df8e4274061e696028d8999ad7592b06b Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 1 Apr 2024 15:21:07 +0800 Subject: [PATCH 2/2] fix(esp_hw_support): fixed modem hang caused by incorrect configuration of power and isolate signals --- components/esp_hw_support/port/esp32/rtc_init.c | 1 + components/esp_hw_support/port/esp32/rtc_sleep.c | 2 +- components/esp_hw_support/port/esp32c3/rtc_init.c | 3 ++- components/esp_hw_support/port/esp32c3/rtc_sleep.c | 4 ++-- components/esp_hw_support/port/esp32s2/rtc_init.c | 3 ++- components/esp_hw_support/port/esp32s2/rtc_sleep.c | 2 +- components/esp_hw_support/port/esp32s3/rtc_init.c | 3 ++- components/esp_hw_support/port/esp32s3/rtc_sleep.c | 2 +- 8 files changed, 12 insertions(+), 8 deletions(-) diff --git a/components/esp_hw_support/port/esp32/rtc_init.c b/components/esp_hw_support/port/esp32/rtc_init.c index a3537cacc9..3a6906dea2 100644 --- a/components/esp_hw_support/port/esp32/rtc_init.c +++ b/components/esp_hw_support/port/esp32/rtc_init.c @@ -29,6 +29,7 @@ void rtc_init(rtc_config_t cfg) * No worry about the power consumption, Because modem Force PD will be set at the end of this function. */ CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU | RTC_CNTL_TXRF_I2C_PU | RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU); diff --git a/components/esp_hw_support/port/esp32/rtc_sleep.c b/components/esp_hw_support/port/esp32/rtc_sleep.c index 31bd9d8669..34b4716a8b 100644 --- a/components/esp_hw_support/port/esp32/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32/rtc_sleep.c @@ -183,7 +183,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) } if (cfg.wifi_pd_en) { - REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_WIFI_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO); REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } else { diff --git a/components/esp_hw_support/port/esp32c3/rtc_init.c b/components/esp_hw_support/port/esp32c3/rtc_init.c index 11c18b1032..a10860a0da 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_init.c +++ b/components/esp_hw_support/port/esp32c3/rtc_init.c @@ -40,6 +40,7 @@ void rtc_init(rtc_config_t cfg) * No worry about the power consumption, Because modem Force PD will be set at the end of this function. */ CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); @@ -326,7 +327,7 @@ uint32_t get_rtc_dbias_by_efuse(uint8_t chip_version, uint32_t dig_dbias) static void set_rtc_dig_dbias() { /* - 1. a reasonable dig_dbias which by scaning pvt to make 160 CPU run successful stored in efuse; + 1. a reasonable dig_dbias which by scanning pvt to make 160 CPU run successful stored in efuse; 2. also we store some value in efuse, include: k_rtc_ldo (slope of rtc voltage & rtc_dbias); k_dig_ldo (slope of digital voltage & digital_dbias); diff --git a/components/esp_hw_support/port/esp32c3/rtc_sleep.c b/components/esp_hw_support/port/esp32c3/rtc_sleep.c index e08fb8efcf..6ef6bfd065 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c3/rtc_sleep.c @@ -176,14 +176,14 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) rtc_sleep_pu(pu_cfg); } if (cfg.wifi_pd_en) { - REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_WIFI_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO); REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } else { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } if (cfg.bt_pd_en) { - REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_NOISO | RTC_CNTL_BT_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_NOISO); REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN); } else { diff --git a/components/esp_hw_support/port/esp32s2/rtc_init.c b/components/esp_hw_support/port/esp32s2/rtc_init.c index 0ae8250604..1c33e270e6 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_init.c +++ b/components/esp_hw_support/port/esp32s2/rtc_init.c @@ -38,6 +38,7 @@ void rtc_init(rtc_config_t cfg) * No worry about the power consumption, Because modem Force PD will be set at the end of this function. */ CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, cfg.pll_wait); @@ -47,7 +48,7 @@ void rtc_init(rtc_config_t cfg) // set shortest possible sleep time limit REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, RTC_CNTL_MIN_SLP_VAL_MIN); - /* This power domian removed + /* This power domain removed * set rom&ram timer * REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_POWERUP_TIMER, ROM_RAM_POWERUP_CYCLES); * REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_WAIT_TIMER, ROM_RAM_WAIT_CYCLES); diff --git a/components/esp_hw_support/port/esp32s2/rtc_sleep.c b/components/esp_hw_support/port/esp32s2/rtc_sleep.c index 7807c4eadd..b229e0ecd7 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32s2/rtc_sleep.c @@ -202,7 +202,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) } if (cfg.wifi_pd_en) { - REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_WIFI_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO); REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } else { diff --git a/components/esp_hw_support/port/esp32s3/rtc_init.c b/components/esp_hw_support/port/esp32s3/rtc_init.c index ce41472f8d..aec6f56858 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_init.c +++ b/components/esp_hw_support/port/esp32s3/rtc_init.c @@ -52,6 +52,7 @@ void rtc_init(rtc_config_t cfg) * No worry about the power consumption, Because modem Force PD will be set at the end of this function. */ CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); @@ -413,7 +414,7 @@ static uint32_t get_dig1v3_dbias_by_efuse(uint8_t pvt_scheme_ver) static void rtc_set_stored_dbias(void) { /* - 1. a reasonable dig_dbias which by scaning pvt to make 240 CPU run successful stored in efuse; + 1. a reasonable dig_dbias which by scanning pvt to make 240 CPU run successful stored in efuse; 2. also we store some value in efuse, include: k_rtc_ldo (slope of rtc voltage & rtc_dbias); k_dig_ldo (slope of digital voltage & digital_dbias); diff --git a/components/esp_hw_support/port/esp32s3/rtc_sleep.c b/components/esp_hw_support/port/esp32s3/rtc_sleep.c index 3f33598fb3..b246ac6dee 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32s3/rtc_sleep.c @@ -181,7 +181,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) rtc_sleep_pu(pu_cfg); } if (cfg.wifi_pd_en) { - REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_WIFI_FORCE_ISO); + REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO); REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); } else {