From 1d2414b4d1e80764d49db54f3dcef8c858e97afc Mon Sep 17 00:00:00 2001 From: Jianwei Zheng Date: Wed, 9 Jul 2025 09:45:32 +0800 Subject: [PATCH] usb: dwc2: platform: Fix dwc2 resume failed for RK3506 OTG1 The utmi iddig signal of RK3506 OTG1 is left floating by default. Even when the system is suspended and the logic is powered off, once the system resume and the clock is enabled, the controller's current mode will be set to Host mode by default, causing dwc2 fail to reinitialize. To resolve this issue, we found that the ForceHstMode bit in the GUSBCFG register returns to its default value of 0 after the logic is powered off. Once the logic power is restored, this bit does not automatically return to 1. Therefore, we can use this bit to determine whether the logic has been powered off when dr_mode is set to Host. Change-Id: I76c46c9ca7bb9f51f455a6835d3161a3edbeeebb Signed-off-by: Jianwei Zheng --- drivers/usb/dwc2/core.h | 5 +++++ drivers/usb/dwc2/platform.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 4a4c28083ba6..660c91ccb6dc 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -1387,6 +1387,11 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg) return (dwc2_readl(hsotg, GINTSTS) & GINTSTS_CURMODE_HOST) == 0; } +static inline int dwc2_is_force_host_mode(struct dwc2_hsotg *hsotg) +{ + return (dwc2_readl(hsotg, GUSBCFG) & GUSBCFG_FORCEHOSTMODE) != 0; +} + int dwc2_drd_init(struct dwc2_hsotg *hsotg); void dwc2_drd_suspend(struct dwc2_hsotg *hsotg); void dwc2_drd_resume(struct dwc2_hsotg *hsotg); diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 598a4e64205d..fdb989e1068e 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -796,7 +796,8 @@ static int __maybe_unused dwc2_resume(struct device *dev) dwc2_drd_resume(dwc2); } - if (dwc2->dr_mode == USB_DR_MODE_HOST && dwc2_is_device_mode(dwc2)) { + if (dwc2->dr_mode == USB_DR_MODE_HOST && (dwc2_is_device_mode(dwc2) || + !dwc2_is_force_host_mode(dwc2))) { /* Reinit for Host mode if lost power */ dwc2_force_mode(dwc2, true);