diff --git a/components/esp_hal_usb/esp32h4/include/hal/usb_wrap_ll.h b/components/esp_hal_usb/esp32h4/include/hal/usb_wrap_ll.h index d233ed52ffd..23367f09424 100644 --- a/components/esp_hal_usb/esp32h4/include/hal/usb_wrap_ll.h +++ b/components/esp_hal_usb/esp32h4/include/hal/usb_wrap_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -172,6 +172,20 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_set_tx_edge(usb_wrap_dev_t *hw, bool clk_ (void)clk_neg_edge; } +/** + * @brief Route internal FSLS PHY AHB/PHY clock gating to DWC2 + * + * Clears clock force-on bits so DWC2 can gate the internal PHY clocks during + * port suspend and internal clock gating. + * + * @param hw Start address of the USB Wrap registers + */ +FORCE_INLINE_ATTR void usb_wrap_ll_enable_automatic_phy_control(usb_wrap_dev_t *hw) +{ + hw->wrap_otg_conf.wrap_ahb_clk_force_on = 0; + hw->wrap_otg_conf.wrap_phy_clk_force_on = 0; +} + /* ------------------------------ USB PHY Test ------------------------------ */ /** diff --git a/components/esp_hal_usb/esp32p4/include/hal/usb_wrap_ll.h b/components/esp_hal_usb/esp32p4/include/hal/usb_wrap_ll.h index 75d2c440d2f..90ff6fb6d10 100644 --- a/components/esp_hal_usb/esp32p4/include/hal/usb_wrap_ll.h +++ b/components/esp_hal_usb/esp32p4/include/hal/usb_wrap_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -233,6 +233,20 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, hw->test_conf.val = test_conf.val; } +/** + * @brief Route internal FSLS PHY AHB/PHY clock gating to DWC2 + * + * Clears clock force-on bits so DWC2 can gate the internal PHY clocks during + * port suspend and internal clock gating. + * + * @param hw Start address of the USB Wrap registers + */ +FORCE_INLINE_ATTR void usb_wrap_ll_enable_automatic_phy_control(usb_wrap_dev_t *hw) +{ + hw->otg_conf.ahb_clk_force_on = 0; + hw->otg_conf.phy_clk_force_on = 0; +} + /* ----------------------------- RCC Functions ----------------------------- */ /** diff --git a/components/esp_hal_usb/esp32s2/include/hal/usb_wrap_ll.h b/components/esp_hal_usb/esp32s2/include/hal/usb_wrap_ll.h index a9619fcaa51..1768162c126 100644 --- a/components/esp_hal_usb/esp32s2/include/hal/usb_wrap_ll.h +++ b/components/esp_hal_usb/esp32s2/include/hal/usb_wrap_ll.h @@ -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 */ @@ -200,6 +200,20 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, hw->test_conf.val = test_conf.val; } +/** + * @brief Route internal FSLS PHY AHB/PHY clock gating to DWC2 + * + * Clears clock force-on bits so DWC2 can gate the internal PHY clocks during + * port suspend and internal clock gating. + * + * @param hw Start address of the USB Wrap registers + */ +FORCE_INLINE_ATTR void usb_wrap_ll_enable_automatic_phy_control(usb_wrap_dev_t *hw) +{ + hw->otg_conf.ahb_clk_force_on = 0; + hw->otg_conf.phy_clk_force_on = 0; +} + /* ----------------------------- RCC Functions ----------------------------- */ /** diff --git a/components/esp_hal_usb/esp32s3/include/hal/usb_wrap_ll.h b/components/esp_hal_usb/esp32s3/include/hal/usb_wrap_ll.h index 42a557b2a22..23a02a83441 100644 --- a/components/esp_hal_usb/esp32s3/include/hal/usb_wrap_ll.h +++ b/components/esp_hal_usb/esp32s3/include/hal/usb_wrap_ll.h @@ -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 */ @@ -209,6 +209,20 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, hw->test_conf.val = test_conf.val; } +/** + * @brief Route internal FSLS PHY AHB/PHY clock gating to DWC2 + * + * Clears clock force-on bits so DWC2 can gate the internal PHY clocks during + * port suspend and internal clock gating. + * + * @param hw Start address of the USB Wrap registers + */ +FORCE_INLINE_ATTR void usb_wrap_ll_enable_automatic_phy_control(usb_wrap_dev_t *hw) +{ + hw->otg_conf.ahb_clk_force_on = 0; + hw->otg_conf.phy_clk_force_on = 0; +} + /* ----------------------------- RCC Functions ----------------------------- */ /** diff --git a/components/esp_hal_usb/usb_wrap_hal.c b/components/esp_hal_usb/usb_wrap_hal.c index 94cfd15c542..662a4a83b52 100644 --- a/components/esp_hal_usb/usb_wrap_hal.c +++ b/components/esp_hal_usb/usb_wrap_hal.c @@ -11,6 +11,7 @@ void _usb_wrap_hal_init(usb_wrap_hal_context_t *hal) hal->dev = &USB_WRAP; _usb_wrap_ll_enable_bus_clock(true); _usb_wrap_ll_reset_register(); + usb_wrap_ll_enable_automatic_phy_control(hal->dev); #if !USB_WRAP_LL_EXT_PHY_SUPPORTED usb_wrap_ll_phy_set_defaults(hal->dev); #endif