]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: dwc3: add needs_full_reinit flag
authorXu Yang <xu.yang_2@nxp.com>
Thu, 12 Feb 2026 09:40:27 +0000 (17:40 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 25 Feb 2026 18:35:58 +0000 (10:35 -0800)
The current design assumes that the controller remains powered when wakeup
is enabled. However, some SoCs provide wakeup capability even when the
controller itself is powered down, using separate dedicated wakeup logic.
This allows additional power savings, but requires the controller to be
fully re‑initialized after system resume.

To support these SoCs, introduce a flag needs_full_reinit for the purpose.
And the glue layer needs to indicate if the controller needs this behavior
by setting a same flag needs_full_reinit in dwc3_properties.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://patch.msgid.link/20260212-add-flatten-dts-based-dwc3-imx-driver-v5-2-ff04a75ce221@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/glue.h

index 161a4d58b2cecec802a06a7670827516cf0c88b4..cacc4ec9f7ce7f7beb1fecfb1e0c1d2f96e3e7e6 100644 (file)
@@ -1675,6 +1675,9 @@ static void dwc3_get_software_properties(struct dwc3 *dwc,
        u16 gsbuscfg0_reqinfo;
        int ret;
 
+       if (properties->needs_full_reinit)
+               dwc->needs_full_reinit = true;
+
        dwc->gsbuscfg0_reqinfo = DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED;
 
        if (properties->gsbuscfg0_reqinfo !=
@@ -2479,7 +2482,8 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
                dwc3_core_exit(dwc);
                break;
        case DWC3_GCTL_PRTCAP_HOST:
-               if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) {
+               if (!PMSG_IS_AUTO(msg) &&
+                   (!device_may_wakeup(dwc->dev) || dwc->needs_full_reinit)) {
                        dwc3_core_exit(dwc);
                        break;
                }
@@ -2542,7 +2546,8 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
                dwc3_gadget_resume(dwc);
                break;
        case DWC3_GCTL_PRTCAP_HOST:
-               if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) {
+               if (!PMSG_IS_AUTO(msg) &&
+                   (!device_may_wakeup(dwc->dev) || dwc->needs_full_reinit)) {
                        ret = dwc3_core_init_for_resume(dwc);
                        if (ret)
                                return ret;
index a35b3db1f9f3e71755bace4c1bce9d67bb8a0f60..67bcc8dccc89c16fb2c8e492b99c6c12c126eb8d 100644 (file)
@@ -1119,6 +1119,8 @@ struct dwc3_glue_ops {
  * @usb3_lpm_capable: set if hadrware supports Link Power Management
  * @usb2_lpm_disable: set to disable usb2 lpm for host
  * @usb2_gadget_lpm_disable: set to disable usb2 lpm for gadget
+ * @needs_full_reinit: set to indicate the core may lose power and need full
+                       initialization during system pm
  * @disable_scramble_quirk: set if we enable the disable scramble quirk
  * @u2exit_lfps_quirk: set if we enable u2exit lfps quirk
  * @u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
@@ -1373,6 +1375,7 @@ struct dwc3 {
        unsigned                usb3_lpm_capable:1;
        unsigned                usb2_lpm_disable:1;
        unsigned                usb2_gadget_lpm_disable:1;
+       unsigned                needs_full_reinit:1;
 
        unsigned                disable_scramble_quirk:1;
        unsigned                u2exit_lfps_quirk:1;
index df86e14cb706ca509206677f644da2a7225b1b26..d738e1739ae015a1aa5fe37fd298a0ae87f0ca05 100644 (file)
 /**
  * dwc3_properties: DWC3 core properties
  * @gsbuscfg0_reqinfo: Value to be programmed in the GSBUSCFG0.REQINFO field
+ * @needs_full_reinit: indicate the controller may not remain power during system
+ *                     pm and need full initialization
  */
 struct dwc3_properties {
        u32 gsbuscfg0_reqinfo;
+       unsigned needs_full_reinit:1;
 };
 
 #define DWC3_DEFAULT_PROPERTIES ((struct dwc3_properties){             \