Skip to content

Commit d5441e6

Browse files
committed
Merge branch 'fix/fix_usb_hs_phy_leakage_on_deepsleep' into 'master'
fix(esp_hw_support): Fix deepsleep leakage after USB HS phy is initialized Closes PM-417 See merge request espressif/esp-idf!39144
2 parents 31a089c + 7107177 commit d5441e6

File tree

6 files changed

+49
-4
lines changed

6 files changed

+49
-4
lines changed

components/esp_hw_support/include/esp_private/sleep_usb.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -13,7 +13,8 @@
1313
extern "C" {
1414
#endif
1515

16-
#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD
16+
#if SOC_USB_OTG_SUPPORTED
17+
#if SOC_PM_SUPPORT_CNNT_PD
1718
/**
1819
* @brief Backup usb OTG phy bus_clock / stoppclk configuration and
1920
* before light sleep to avoid current leakage
@@ -26,6 +27,16 @@ void sleep_usb_otg_phy_backup_and_disable(void);
2627
void sleep_usb_otg_phy_restore(void);
2728
#endif
2829

30+
#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO
31+
/**
32+
* @brief The DP/DM part of the UTMI PHY circuit of esp32p4 that converts logic level to digital
33+
* has no power off isolation, which will cause leakage when entering deepsleep.
34+
* This problem can be workarounded by enabling USB-OTG's HNP (Host negotiation protocol)
35+
* to enable DM pull-down to suppress leakage.
36+
*/
37+
void sleep_usb_suppress_deepsleep_leakage(void);
38+
#endif
39+
#endif
2940
#ifdef __cplusplus
3041
}
3142
#endif

components/esp_hw_support/sleep_usb.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -9,10 +9,13 @@
99
#include "esp_private/sleep_usb.h"
1010
#include "esp_attr.h"
1111

12-
#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD
12+
#if SOC_USB_OTG_SUPPORTED && (SOC_PM_SUPPORT_CNNT_PD || SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO)
1313
#include "hal/usb_utmi_ll.h"
1414
#include "hal/usb_dwc_ll.h"
15+
#endif
1516

17+
#if SOC_USB_OTG_SUPPORTED
18+
#if SOC_PM_SUPPORT_CNNT_PD
1619
static bool s_usb_utmi_bus_clock_state, s_usb_utmi_stoppclk_state;
1720

1821
void sleep_usb_otg_phy_backup_and_disable(void)
@@ -34,3 +37,13 @@ void sleep_usb_otg_phy_restore(void)
3437
}
3538
}
3639
#endif
40+
41+
#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO
42+
void sleep_usb_suppress_deepsleep_leakage(void)
43+
{
44+
if (_usb_utmi_ll_bus_clock_is_enabled()) {
45+
usb_dwc_ll_gusbcfg_en_hnp_cap(&USB_DWC_HS);
46+
}
47+
}
48+
#endif
49+
#endif

components/hal/esp32p4/include/hal/usb_dwc_ll.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,11 @@ static inline void usb_dwc_ll_gusbcfg_force_host_mode(usb_dwc_dev_t *hw)
204204
hw->gusbcfg_reg.forcehstmode = 1;
205205
}
206206

207+
static inline void usb_dwc_ll_gusbcfg_en_hnp_cap(usb_dwc_dev_t *hw)
208+
{
209+
hw->gusbcfg_reg.hnpcap = 1;
210+
}
211+
207212
static inline void usb_dwc_ll_gusbcfg_dis_hnp_cap(usb_dwc_dev_t *hw)
208213
{
209214
hw->gusbcfg_reg.hnpcap = 0;

components/soc/esp32p4/include/soc/Kconfig.soc_caps.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,10 @@ config SOC_USB_UTMI_PHY_NUM
13391339
int
13401340
default 1
13411341

1342+
config SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO
1343+
bool
1344+
default y
1345+
13421346
config SOC_PARLIO_GROUPS
13431347
int
13441348
default 1

components/soc/esp32p4/include/soc/soc_caps.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@
478478

479479
// USB PHY Caps
480480
#define SOC_USB_UTMI_PHY_NUM (1U)
481+
#define SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO 1
481482

482483
/*-------------------------- PARLIO CAPS --------------------------------------*/
483484
#define SOC_PARLIO_GROUPS 1U /*!< Number of parallel IO peripherals */

components/usb/usb_phy.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
#include "driver/gpio.h"
2121
#include "soc/soc_caps.h"
2222

23+
#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO
24+
#include "esp_private/sleep_usb.h"
25+
#include "esp_sleep.h"
26+
#endif
27+
2328
#if !SOC_RCC_IS_INDEPENDENT
2429
#define USB_PHY_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
2530
#else
@@ -294,6 +299,12 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r
294299
}
295300
#endif
296301

302+
#if SOC_USB_UTMI_PHY_NO_POWER_OFF_ISO
303+
if (phy_target == USB_PHY_TARGET_UTMI) {
304+
esp_deep_sleep_register_hook(&sleep_usb_suppress_deepsleep_leakage);
305+
}
306+
#endif
307+
297308
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, USBPHY_TAG, "config argument is invalid");
298309
ESP_RETURN_ON_FALSE(phy_target < USB_PHY_TARGET_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified PHY argument is invalid");
299310
ESP_RETURN_ON_FALSE(config->controller < USB_PHY_CTRL_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified source argument is invalid");

0 commit comments

Comments
 (0)