diff --git a/components/esp_hw_support/port/esp32c5/include/soc/rtc.h b/components/esp_hw_support/port/esp32c5/include/soc/rtc.h index b21dcb15f06..608cceef7f8 100644 --- a/components/esp_hw_support/port/esp32c5/include/soc/rtc.h +++ b/components/esp_hw_support/port/esp32c5/include/soc/rtc.h @@ -346,6 +346,16 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config); */ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config); +#if SOC_CLK_ROOT_CLK_SWITCH_PROTECT +/** + * @brief Enable/disable root clock auto gating bypass for 240M/160M PLL switch + * @param new_config Target cpu frequency config + * @param old_config Current cpu frequency config + * @param enable true to enable, false to disable + */ +void rtc_clk_root_clk_switch_protect(const rtc_cpu_freq_config_t *new_config, const rtc_cpu_freq_config_t *old_config, bool enable); +#endif + /** * @brief Get the currently used CPU frequency configuration * @param[out] out_config Output, CPU frequency configuration structure diff --git a/components/esp_hw_support/port/esp32c5/rtc_clk.c b/components/esp_hw_support/port/esp32c5/rtc_clk.c index e984a07920d..a63b5b3b305 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c5/rtc_clk.c @@ -360,6 +360,16 @@ static void rtc_clk_update_pll_state_on_cpu_src_switching_end(soc_cpu_clk_src_t } } +#if SOC_CLK_ROOT_CLK_SWITCH_PROTECT +void rtc_clk_root_clk_switch_protect(const rtc_cpu_freq_config_t *new_config, const rtc_cpu_freq_config_t *old_config, bool enable) +{ + if ((new_config->source == SOC_CPU_CLK_SRC_PLL_F160M && old_config->source == SOC_CPU_CLK_SRC_PLL_F240M) || + (new_config->source == SOC_CPU_CLK_SRC_PLL_F240M && old_config->source == SOC_CPU_CLK_SRC_PLL_F160M)) { + clk_ll_soc_root_clk_auto_gating_bypass(enable); + } +} +#endif + void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index cc85ff17a77..b61432b1e67 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -709,7 +709,18 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode) #endif extern portMUX_TYPE s_time_update_lock; portENTER_CRITICAL_SAFE(&s_time_update_lock); +#if SOC_CLK_ROOT_CLK_SWITCH_PROTECT + /* On ESP32-C5 ECO1 and later: before switching the main system clock + * between 240 MHz and 160 MHz, clear BIT(31) of PCR_FPGA_DEBUG_REG. + * After the switch is completed, set BIT(31) back to 1. + * This operation fixes WiFi packet TX/RX abnormalities and missed interrupts. + * See WIFI-7270 for details.*/ + rtc_clk_root_clk_switch_protect(&new_config, &old_config, true); +#endif rtc_clk_cpu_freq_set_config_fast(&new_config); +#if SOC_CLK_ROOT_CLK_SWITCH_PROTECT + rtc_clk_root_clk_switch_protect(&new_config, &old_config, false); +#endif portEXIT_CRITICAL_SAFE(&s_time_update_lock); #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP esp_clk_utils_mspi_speed_mode_sync_after_cpu_freq_switching(new_config.source_freq_mhz, new_config.freq_mhz); diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index e004717e063..8e3c70aa2c1 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1787,6 +1787,10 @@ config SOC_CLK_ANA_I2C_MST_HAS_ROOT_GATE bool default y +config SOC_CLK_ROOT_CLK_SWITCH_PROTECT + bool + default y + config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 9d160fc0556..e7556b2f58c 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -688,6 +688,8 @@ #define SOC_CLK_ANA_I2C_MST_HAS_ROOT_GATE (1) /*!< Any regi2c operation needs enable the analog i2c master clock first */ +#define SOC_CLK_ROOT_CLK_SWITCH_PROTECT 1 /*!< Need to bypass root clock auto gating during 240M/160M PLL switch */ + /*-------------------------- Temperature Sensor CAPS -------------------------------------*/ #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1)