From eac2c210886cfa2b187027e9e6fd6d1d993d3fe0 Mon Sep 17 00:00:00 2001 From: "peter.marcisovsky" Date: Wed, 20 May 2026 11:53:41 +0200 Subject: [PATCH] fix(esp_hal_usb): Fix UTMI PHY default settings: - Allow automatic UTMI PHY suspend/resume controlled by the DWC2 suspend/resume - Correctly set precise detection --- .../esp32s31/include/hal/usb_utmi_ll.h | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/components/esp_hal_usb/esp32s31/include/hal/usb_utmi_ll.h b/components/esp_hal_usb/esp32s31/include/hal/usb_utmi_ll.h index 25b64f7d033..3ad7538e0f4 100644 --- a/components/esp_hal_usb/esp32s31/include/hal/usb_utmi_ll.h +++ b/components/esp_hal_usb/esp32s31/include/hal/usb_utmi_ll.h @@ -37,6 +37,22 @@ FORCE_INLINE_ATTR void usb_utmi_ll_configure_ls(usb_utmi_dev_t *hw, bool paralle /* ----------------------------- RCC Functions ----------------------------- */ +/** + * @brief Route UTMI PHY suspendm and PLL control to DWC2 + * + * Clears the software force bits so DWC2 can drive PHY suspend/resume and PLL + * during port suspend and internal clock gating. + * + * @note reg_usb_otghs_phy_suspendm_force_en resets to 1 on ESP32-S31 and must be + * cleared before automatic DWC-linked PHY suspend/resume works. + * @note reg_usb_otghs_phy_pll_force_en resets to 0 and is cleared here just for clarity + */ +FORCE_INLINE_ATTR void _usb_utmi_ll_enable_automatic_phy_control(void) +{ + HP_ALIVE_SYS.usb_otghs_ctrl.reg_usb_otghs_phy_suspendm_force_en = 0; + HP_ALIVE_SYS.usb_otghs_ctrl.reg_usb_otghs_phy_pll_force_en = 0; +} + /** * @brief Enable/disable bus clock for USB UTMI PHY and USB OTG HS controller * @@ -54,9 +70,9 @@ FORCE_INLINE_ATTR void _usb_utmi_ll_enable_bus_clock(bool clk_en) sys_usb_otg20_ctrl.sys_usb_otg20_phyref_clk_en = clk_en; USB_UTMI_LL_CNNT_SYS_REG->sys_usb_otg20_ctrl.val = sys_usb_otg20_ctrl.val; - // Enable/disable PHY PLL (must be force-enabled on ESP32-S31, as the default is off) - HP_ALIVE_SYS.usb_otghs_ctrl.reg_usb_otghs_phy_pll_force_en = clk_en; - HP_ALIVE_SYS.usb_otghs_ctrl.reg_usb_otghs_phy_pll_en = clk_en; + if (clk_en) { + _usb_utmi_ll_enable_automatic_phy_control(); + } } // HP_SYS_CLKRST.usb_otghs_ctrl0 and sys_usb_otg20_ctrl only contain USB OTG fields, no atomic wrapper needed @@ -128,7 +144,6 @@ FORCE_INLINE_ATTR void usb_utmi_ll_enable_data_pulldowns(bool enable) FORCE_INLINE_ATTR void usb_utmi_ll_enable_precise_detection(bool enable) { HP_ALIVE_SYS.usb_otghs_ctrl.reg_usb_otghs_phy_otg_suspendm = enable; - HP_ALIVE_SYS.usb_otghs_ctrl.reg_usb_otghs_phy_suspendm = enable; } #ifdef __cplusplus