mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
fix(usb_phy): Fixed USB PHY clock during low-power modes
On ESP32-S3, USB PHY is clocked from BBPLL, however if the BBPLL is not used as CPU clock source, the power management unit can turn it off. This commit registers USB as BBPLL consumer so it is not turned off. Closes https://github.com/espressif/esp-idf/issues/15451
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -35,22 +35,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_8m(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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "esp_rom_gpio.h"
|
||||
#include "driver/gpio.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"
|
||||
@@ -381,13 +384,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_set_drive_capability(usb_dwc_info.controllers[otg11_index].internal_phy_io->dm, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(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));
|
||||
@@ -403,6 +399,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_set_drive_capability(usb_dwc_info.controllers[otg11_index].internal_phy_io->dm, GPIO_DRIVE_CAP_3);
|
||||
gpio_set_drive_capability(usb_dwc_info.controllers[otg11_index].internal_phy_io->dp, GPIO_DRIVE_CAP_3);
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
cleanup:
|
||||
@@ -448,6 +454,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user