Merge branch 'bugfix/idf_13957' into 'master'

bugfix: fix wifi loss packet and missing interrupt issues when switching root clock source

Closes WIFI-7270, IDF-13957, and IDF-11064

See merge request espressif/esp-idf!46459
This commit is contained in:
Jiang Jiang Jian
2026-05-07 20:57:31 +08:00
8 changed files with 39 additions and 31 deletions

View File

@@ -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;
}

View File

@@ -296,6 +296,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

View File

@@ -349,6 +349,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();

View File

@@ -676,9 +676,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
@@ -752,9 +749,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 ADC_LL_ANA_CALI_REG_PD_WORKAROUND
adc_hal_i2c_saradc_reg_restore();

View File

@@ -682,7 +682,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);

View File

@@ -19,9 +19,7 @@
#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"
#endif
@@ -233,13 +231,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};

View File

@@ -1487,6 +1487,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

View File

@@ -603,6 +603,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 -------------------------------------*/