From aa2bd15d4614ce7ec02620dee6f04d39cd47d272 Mon Sep 17 00:00:00 2001 From: sibeibei Date: Mon, 9 Mar 2026 17:43:10 +0800 Subject: [PATCH 1/3] Revert "fix(esp_hw_support): fix the issue of wifi rx packet loss when switchng soc root clock source" This reverts commit 45ea08b9551878ce46bd7cd02555d22b0dffef6f. --- .../lowpower/port/esp32c5/sleep_clock.c | 18 ++---------------- components/esp_system/port/soc/esp32c5/clk.c | 12 ++---------- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c index 0b1a1fba57d..2d5dae4e202 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -53,6 +53,7 @@ esp_err_t sleep_clock_system_retention_init(void *arg) #if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP && CONFIG_XTAL_FREQ_AUTO uint32_t xtal_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); if (xtal_freq_mhz == SOC_XTAL_FREQ_48M) { + /* For the 48 MHz main XTAL, we need regdma to configured BBPLL by exec * the PHY_I2C_MST_CMD_TYPE_BBPLL_CFG command from PHY i2c master * command memory */ @@ -69,21 +70,6 @@ esp_err_t sleep_clock_system_retention_init(void *arg) } #endif -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP - /* On ESP32-C5 ECO1, clearing BIT(31) of PCR_FPGA_DEBUG_REG (it's - * located in TOP domain) is used to fix the issue where the modem - * module fails to transmit and receive packets due to the loss of The - * modem root clock caused by automatic clock gating during soc root - * clock source switching. For detailed information, refer to IDF-11064 */ - if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) { - const static sleep_retention_entries_config_t rootclk_workaround[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(9), PCR_FPGA_DEBUG_REG, PCR_FPGA_DEBUG_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(1) } - }; - err = sleep_retention_entries_create(rootclk_workaround, ARRAY_SIZE(rootclk_workaround), 1, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM); - ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem root clock workaround, 1 level priority"); - } -#endif - ESP_LOGI(TAG, "System Power, Clock and Reset sleep retention initialization"); return ESP_OK; } diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index d5fe762ccf0..83dc1ced905 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,9 +19,8 @@ #include "soc/rtc.h" #include "soc/rtc_periph.h" #include "soc/i2s_reg.h" -#include "soc/chip_revision.h" #include "esp_cpu.h" -#include "hal/efuse_hal.h" +#if SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED #include "hal/wdt_hal.h" #include "hal/clk_tree_ll.h" #if SOC_MODEM_CLOCK_SUPPORTED @@ -231,13 +230,6 @@ __attribute__((weak)) void esp_perip_clk_init(void) modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0); #endif - /* On ESP32-C5 ECO1, clearing BIT(31) of PCR_FPGA_DEBUG_REG is used to fix - * the issue where the modem module fails to transmit and receive packets - * due to the loss of the modem root clock caused by automatic clock gating - * during soc root clock source switching. For detailed information, refer - * to IDF-11064. */ - clk_ll_soc_root_clk_auto_gating_bypass(true); - soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); periph_ll_clk_gate_config_t clk_gate_config = {0}; From 1d16c0fbadc5fee895d9e24083b2b63b4be1042a Mon Sep 17 00:00:00 2001 From: sibeibei Date: Mon, 9 Mar 2026 16:21:49 +0800 Subject: [PATCH 2/3] bugfix: fix wifi loss packet and missing interrupt issues when switching root clock source --- .../esp_hw_support/port/esp32c5/include/soc/rtc.h | 10 ++++++++++ components/esp_hw_support/port/esp32c5/rtc_clk.c | 10 ++++++++++ components/esp_pm/pm_impl.c | 11 +++++++++++ .../soc/esp32c5/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32c5/include/soc/soc_caps.h | 2 ++ 5 files changed, 37 insertions(+) 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 11f76732ea4..f1fd4eba23e 100644 --- a/components/esp_hw_support/port/esp32c5/include/soc/rtc.h +++ b/components/esp_hw_support/port/esp32c5/include/soc/rtc.h @@ -338,6 +338,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 ca9d4849b6b..13008cac34c 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c5/rtc_clk.c @@ -350,6 +350,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 a1621d94801..f2b16c6c761 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -702,7 +702,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 66db189d042..3b80ee28e60 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1543,6 +1543,10 @@ config SOC_RCC_IS_INDEPENDENT bool default y +config SOC_CLK_ROOT_CLK_SWITCH_PROTECT + bool + default y + config SOC_CLK_ANA_I2C_MST_DEPENDS_ON_MODEM_APB bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 17264727814..ff497a8fd36 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -625,6 +625,8 @@ #define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */ +#define SOC_CLK_ROOT_CLK_SWITCH_PROTECT 1 /*!< Need to bypass root clock auto gating during 240M/160M PLL switch */ + #define SOC_CLK_ANA_I2C_MST_DEPENDS_ON_MODEM_APB (1) /*!< Analog I2C master clock depends on CLK_160M_REF on clock tree */ /*-------------------------- Temperature Sensor CAPS -------------------------------------*/ From 51775582e669b3e2e24b49f6a5c6fac71906cf43 Mon Sep 17 00:00:00 2001 From: sibeibei Date: Wed, 11 Mar 2026 13:15:15 +0800 Subject: [PATCH 3/3] bugfix(esp_hw_support):remove ESP32-C5 root clock auto gating bypass in sleep path --- components/esp_hw_support/sleep_modes.c | 6 ------ components/esp_system/port/soc/esp32c5/clk.c | 1 - 2 files changed, 7 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 27e7b022eac..41a45073cb9 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -679,9 +679,6 @@ static SLEEP_FN_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool } #endif #if CONFIG_MAC_BB_PD -# if CONFIG_IDF_TARGET_ESP32C5 - clk_ll_soc_root_clk_auto_gating_bypass(false); -# endif mac_bb_power_down_cb_execute(); #endif #if CONFIG_IDF_TARGET_ESP32 @@ -757,9 +754,6 @@ static SLEEP_FN_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags) #endif #if CONFIG_MAC_BB_PD mac_bb_power_up_cb_execute(); -# if CONFIG_IDF_TARGET_ESP32C5 - clk_ll_soc_root_clk_auto_gating_bypass(true); -# endif #endif #if REGI2C_LL_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_write(); diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index 83dc1ced905..55b80fc5219 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -20,7 +20,6 @@ #include "soc/rtc_periph.h" #include "soc/i2s_reg.h" #include "esp_cpu.h" -#if SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED #include "hal/wdt_hal.h" #include "hal/clk_tree_ll.h" #if SOC_MODEM_CLOCK_SUPPORTED