Merge branch 'fix/usb_bbpll_light_sleep_backport_v6.0' into 'release/v6.0'

fix(usb_phy): Fixed USB PHY clock during low-power modes (backport v6.0)

See merge request espressif/esp-idf!52781
This commit is contained in:
morris
2026-09-17 09:47:04 +08:00
4 changed files with 39 additions and 14 deletions

View File

@@ -17,6 +17,7 @@
/* ----------------------------- Macros & Types ----------------------------- */
#define USB_WRAP_LL_EXT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY
#define USB_WRAP_LL_DEPENDS_ON_BBPLL 1 // USB PHY depends on BBPLL
#ifdef __cplusplus
extern "C" {

View File

@@ -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
*/
@@ -43,9 +43,10 @@ void rtc_clk_cpu_freq_set_xtal_for_sleep(void);
/**
* @brief Notify that the BBPLL has a new in-use consumer
*
* Currently, this function is only used for tracking whether USB Serial/JTAG is using the 48MHz PHY clock
* Currently, this function is used for tracking whether USB PHY is using the 48MHz PHY clock.
*
* Note: Calling this function only helps to not disable the BBPLL clock in `rtc_clk_cpu_freq_set_config`.
* The first consumer enables BBPLL analog power. Later `rtc_clk_cpu_freq_set_config` will not
* disable BBPLL while any consumer remains.
*/
void rtc_clk_bbpll_add_consumer(void);

View File

@@ -36,22 +36,36 @@ static uint32_t s_apb_freq;
void rtc_clk_cpu_freq_to_xtal(int freq, int div);
static void rtc_clk_cpu_freq_to_rc_fast(void);
static void rtc_clk_bbpll_enable(void);
static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq);
extern uint32_t g_dig_dbias_pvt_240m;
extern uint32_t g_rtc_dbias_pvt_240m;
extern uint32_t g_dig_dbias_pvt_non_240m;
extern uint32_t g_rtc_dbias_pvt_non_240m;
static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG
static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it tracks whether the 48MHz PHY clock is in-use by USB
void rtc_clk_bbpll_add_consumer(void)
{
s_bbpll_digi_consumers_ref_count += 1;
// Should be refactored in PM-653
if (s_bbpll_digi_consumers_ref_count == 0) {
if (s_cur_pll_freq == 0) {
rtc_clk_bbpll_enable();
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
}
}
s_bbpll_digi_consumers_ref_count++;
}
void rtc_clk_bbpll_remove_consumer(void)
{
s_bbpll_digi_consumers_ref_count -= 1;
// Should be refactored in PM-653
if (s_bbpll_digi_consumers_ref_count > 0) {
s_bbpll_digi_consumers_ref_count--;
} else {
ESP_HW_LOGW(TAG, "bbpll clk ref cnt mismatched!");
}
}
void rtc_clk_32k_enable(bool enable)

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -19,6 +19,9 @@
#include "hal/usb_utmi_hal.h"
#include "hal/gpio_ll.h"
#include "soc/soc_caps.h"
#if USB_WRAP_LL_DEPENDS_ON_BBPLL
#include "esp_private/rtc_clk.h"
#endif
#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO
#include "esp_private/sleep_usb.h"
@@ -322,13 +325,6 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r
}
#endif
// For FSLS PHY that shares pads with GPIO peripheral, we must set drive capability to 3 (40mA)
if (phy_target == USB_PHY_TARGET_INT) {
assert(usb_dwc_info.controllers[otg11_index].internal_phy_io);
gpio_ll_set_drive_capability(GPIO_LL_GET_HW(0), usb_dwc_info.controllers[otg11_index].internal_phy_io->dm, GPIO_DRIVE_CAP_3);
gpio_ll_set_drive_capability(GPIO_LL_GET_HW(0), usb_dwc_info.controllers[otg11_index].internal_phy_io->dp, GPIO_DRIVE_CAP_3);
}
*handle_ret = (usb_phy_handle_t) phy_context;
if (phy_target == USB_PHY_TARGET_EXT) {
phy_context->iopins = (usb_phy_ext_io_conf_t *) calloc(1, sizeof(usb_phy_ext_io_conf_t));
@@ -344,6 +340,16 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r
const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[otg11_index].otg_signals;
ESP_ERROR_CHECK(phy_otg_iopins_configure(config->otg_io_conf, otg_sig));
}
if (phy_target == USB_PHY_TARGET_INT) {
#if USB_WRAP_LL_DEPENDS_ON_BBPLL
// PHY clock is derived from BBPLL. Do not turn off BBPLL during low-power modes
rtc_clk_bbpll_add_consumer();
#endif
// For FSLS internal PHY that shares pads with GPIO peripheral, we must set drive capability to 3 (40mA)
assert(usb_dwc_info.controllers[otg11_index].internal_phy_io);
gpio_ll_set_drive_capability(GPIO_LL_GET_HW(0), usb_dwc_info.controllers[otg11_index].internal_phy_io->dm, GPIO_DRIVE_CAP_3);
gpio_ll_set_drive_capability(GPIO_LL_GET_HW(0), usb_dwc_info.controllers[otg11_index].internal_phy_io->dp, GPIO_DRIVE_CAP_3);
}
return ESP_OK;
cleanup:
@@ -389,6 +395,9 @@ esp_err_t usb_del_phy(usb_phy_handle_t handle)
// Clear pullup and pulldown loads on D+ / D-, and disable the pads
usb_wrap_hal_phy_disable_pull_override(&handle->wrap_hal);
p_phy_ctrl_obj->fsls_phy = NULL;
#if USB_WRAP_LL_DEPENDS_ON_BBPLL
rtc_clk_bbpll_remove_consumer();
#endif
} else { // USB_PHY_TARGET_UTMI
p_phy_ctrl_obj->utmi_phy = NULL;
}