From 1956ea5ac22b651b6cd7f913f0f60200cfe0a5fa Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 18 Sep 2025 18:10:28 +0800 Subject: [PATCH] fix(esp_hw_support): fix P4 v3.0 USB leakage on PU_CNNT lightsleep --- components/esp_hw_support/sleep_usb.c | 6 ++++- .../hal/esp32p4/include/hal/usb_dwc_ll.h | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/sleep_usb.c b/components/esp_hw_support/sleep_usb.c index 50227d1edac..a1de41e0135 100644 --- a/components/esp_hw_support/sleep_usb.c +++ b/components/esp_hw_support/sleep_usb.c @@ -16,7 +16,7 @@ #if SOC_USB_OTG_SUPPORTED #if SOC_PM_SUPPORT_CNNT_PD -static bool s_usb_utmi_bus_clock_state, s_usb_utmi_stoppclk_state; +static bool s_usb_utmi_bus_clock_state, s_usb_utmi_stoppclk_state, s_usb_dwc_bvalid_override; void sleep_usb_otg_phy_backup_and_disable(void) { @@ -24,6 +24,9 @@ void sleep_usb_otg_phy_backup_and_disable(void) if (!s_usb_utmi_bus_clock_state) { _usb_utmi_ll_enable_bus_clock(true); } + // Forcing BVALID low to ignore the hardware-detected VBUS BVALID signal to suppress USB leakage. + s_usb_dwc_bvalid_override = usb_dwc_ll_get_bvalid_override(&USB_DWC_HS); + usb_dwc_ll_enable_bvalid_override(&USB_DWC_HS, true); s_usb_utmi_stoppclk_state = usb_dwc_ll_get_stoppclk_st(&USB_DWC_HS); usb_dwc_ll_set_stoppclk(&USB_DWC_HS, true); } @@ -31,6 +34,7 @@ void sleep_usb_otg_phy_backup_and_disable(void) void sleep_usb_otg_phy_restore(void) { _usb_utmi_ll_enable_bus_clock(true); + usb_dwc_ll_enable_bvalid_override(&USB_DWC_HS, s_usb_dwc_bvalid_override); usb_dwc_ll_set_stoppclk(&USB_DWC_HS, s_usb_utmi_stoppclk_state); if (!s_usb_utmi_bus_clock_state) { _usb_utmi_ll_enable_bus_clock(false); diff --git a/components/hal/esp32p4/include/hal/usb_dwc_ll.h b/components/hal/esp32p4/include/hal/usb_dwc_ll.h index 6760db56373..ff1264afc6f 100644 --- a/components/hal/esp32p4/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32p4/include/hal/usb_dwc_ll.h @@ -1011,6 +1011,28 @@ static inline void usb_dwc_ll_qtd_get_status(usb_dwc_ll_dma_qtd_t *qtd, int *rem qtd->buffer_status_val = 0; } +/** + * @brief Get the current BVALID override configuration. + * + * @param[out] Get the current BVALID override configuration. + */ +FORCE_INLINE_ATTR bool usb_dwc_ll_get_bvalid_override(usb_dwc_dev_t *hw) +{ + return hw->gotgctl_reg.bvalidoven; +} + +/** + * @brief Enable BVALID override in USB OTG controller. + * + * When enabled, the controller ignores the hardware-detected VBUS BVALID signal + * and uses the software-defined override value instead. This is typically used + * to reduce USB leakage current during sleep by forcing BVALID low. + */ +FORCE_INLINE_ATTR void usb_dwc_ll_enable_bvalid_override(usb_dwc_dev_t *hw, bool override) +{ + hw->gotgctl_reg.bvalidoven = override; +} + // ---------------------------- Power and Clock Gating Register -------------------------------- FORCE_INLINE_ATTR void usb_dwc_ll_set_stoppclk(usb_dwc_dev_t *hw, bool stop) {