From 9cf4ddf797cfe3dbb33fd9838e7ab986d869780f Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 14 May 2025 17:57:40 +0800 Subject: [PATCH] fix(esp_hw_support): Fix deepsleep leakage after initializing USB HS phy --- .../include/esp_private/sleep_usb.h | 15 +++++++++++++-- components/esp_hw_support/sleep_usb.c | 17 +++++++++++++++-- components/hal/esp32p4/include/hal/usb_dwc_ll.h | 5 +++++ .../soc/esp32p4/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32p4/include/soc/soc_caps.h | 1 + components/usb/usb_phy.c | 11 +++++++++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/sleep_usb.h b/components/esp_hw_support/include/esp_private/sleep_usb.h index 6ad693470a..40a12d59c5 100644 --- a/components/esp_hw_support/include/esp_private/sleep_usb.h +++ b/components/esp_hw_support/include/esp_private/sleep_usb.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,7 +13,8 @@ extern "C" { #endif -#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD +#if SOC_USB_OTG_SUPPORTED +#if SOC_PM_SUPPORT_CNNT_PD /** * @brief Backup usb OTG phy bus_clock / stoppclk configuration and * before light sleep to avoid current leakage @@ -26,6 +27,16 @@ void sleep_usb_otg_phy_backup_and_disable(void); void sleep_usb_otg_phy_restore(void); #endif +#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO +/** + * @brief The DP/DM part of the UTMI PHY circuit of esp32p4 that converts logic level to digital + * has no power off isolation, which will cause leakage when entering deepsleep. + * This problem can be workarounded by enabling USB-OTG's HNP (Host negotiation protocol) + * to enable DM pull-down to suppress leakage. + */ +void sleep_usb_suppress_deepsleep_leakage(void); +#endif +#endif #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/sleep_usb.c b/components/esp_hw_support/sleep_usb.c index d6f88bd5ce..50227d1eda 100644 --- a/components/esp_hw_support/sleep_usb.c +++ b/components/esp_hw_support/sleep_usb.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,10 +9,13 @@ #include "esp_private/sleep_usb.h" #include "esp_attr.h" -#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD +#if SOC_USB_OTG_SUPPORTED && (SOC_PM_SUPPORT_CNNT_PD || SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO) #include "hal/usb_utmi_ll.h" #include "hal/usb_dwc_ll.h" +#endif +#if SOC_USB_OTG_SUPPORTED +#if SOC_PM_SUPPORT_CNNT_PD static bool s_usb_utmi_bus_clock_state, s_usb_utmi_stoppclk_state; void sleep_usb_otg_phy_backup_and_disable(void) @@ -34,3 +37,13 @@ void sleep_usb_otg_phy_restore(void) } } #endif + +#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO +void sleep_usb_suppress_deepsleep_leakage(void) +{ + if (_usb_utmi_ll_bus_clock_is_enabled()) { + usb_dwc_ll_gusbcfg_en_hnp_cap(&USB_DWC_HS); + } +} +#endif +#endif diff --git a/components/hal/esp32p4/include/hal/usb_dwc_ll.h b/components/hal/esp32p4/include/hal/usb_dwc_ll.h index 3788f147f0..6760db5637 100644 --- a/components/hal/esp32p4/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32p4/include/hal/usb_dwc_ll.h @@ -204,6 +204,11 @@ static inline void usb_dwc_ll_gusbcfg_force_host_mode(usb_dwc_dev_t *hw) hw->gusbcfg_reg.forcehstmode = 1; } +static inline void usb_dwc_ll_gusbcfg_en_hnp_cap(usb_dwc_dev_t *hw) +{ + hw->gusbcfg_reg.hnpcap = 1; +} + static inline void usb_dwc_ll_gusbcfg_dis_hnp_cap(usb_dwc_dev_t *hw) { hw->gusbcfg_reg.hnpcap = 0; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 3f20a61b83..765055e011 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1339,6 +1339,10 @@ config SOC_USB_UTMI_PHY_NUM int default 1 +config SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO + bool + default y + config SOC_PARLIO_GROUPS int default 1 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 3d54409089..185e31c1c9 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -478,6 +478,7 @@ // USB PHY Caps #define SOC_USB_UTMI_PHY_NUM (1U) +#define SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO 1 /*-------------------------- PARLIO CAPS --------------------------------------*/ #define SOC_PARLIO_GROUPS 1U /*!< Number of parallel IO peripherals */ diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index 46d5a17ed0..9432b446cb 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -20,6 +20,11 @@ #include "driver/gpio.h" #include "soc/soc_caps.h" +#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO +#include "esp_private/sleep_usb.h" +#include "esp_sleep.h" +#endif + #if !SOC_RCC_IS_INDEPENDENT #define USB_PHY_RCC_ATOMIC() PERIPH_RCC_ATOMIC() #else @@ -294,6 +299,12 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r } #endif +#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO + if (phy_target == USB_PHY_TARGET_UTMI) { + esp_deep_sleep_register_hook(&sleep_usb_suppress_deepsleep_leakage); + } +#endif + ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, USBPHY_TAG, "config argument is invalid"); ESP_RETURN_ON_FALSE(phy_target < USB_PHY_TARGET_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified PHY argument is invalid"); ESP_RETURN_ON_FALSE(config->controller < USB_PHY_CTRL_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified source argument is invalid");