public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] add DWC3 i.MX driver based on flatten devicetree
@ 2026-02-02 10:27 Xu Yang
  2026-02-02 10:27 ` [PATCH 1/3] dt-bindings: usb: introduce fsl,imx-dwc3 Xu Yang
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-02 10:27 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen
  Cc: linux-usb, devicetree, imx, linux-arm-kernel, linux-kernel,
	Xu Yang

The i.MX USB glue and DWC3 core are closely coupled. Describe the i.MX
USB block in a single block will bring more benefits than a parent-
child relation.

Now DWC3 USB common driver already support to do more key jobs in glue
driver, such as power management and core initialization. Now let's
make a step and add a flatten devicetree based driver.

The first one add a new "fsl,imx-dwc3" binding to describe all i.MX
related USB controller.

Then, to support wakeup capability even when controller experienced
power lost, a fix patch is added to make controller work after system
resume back.

---
Xu Yang (3):
      dt-bindings: usb: introduce fsl,imx-dwc3
      usb: dwc3: add may_lose_power flag
      usb: dwc3: introduce flatten model driver of i.MX Soc

 .../devicetree/bindings/usb/fsl,imx-dwc3.yaml      | 131 +++++++
 .../devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml   |  13 +
 drivers/usb/dwc3/Kconfig                           |  12 +
 drivers/usb/dwc3/Makefile                          |   1 +
 drivers/usb/dwc3/core.c                            |   9 +-
 drivers/usb/dwc3/core.h                            |   2 +
 drivers/usb/dwc3/dwc3-imx.c                        | 428 +++++++++++++++++++++
 drivers/usb/dwc3/glue.h                            |   3 +
 8 files changed, 597 insertions(+), 2 deletions(-)
---
base-commit: 0a06917432a762d6233f88963c0b53e48dbac6b4
change-id: 20260202-add-flatten-dts-based-dwc3-imx-driver-96e4a4af9570

Best regards,
-- 
Xu Yang <xu.yang_2@nxp.com>


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/3] dt-bindings: usb: introduce fsl,imx-dwc3
  2026-02-02 10:27 [PATCH 0/3] add DWC3 i.MX driver based on flatten devicetree Xu Yang
@ 2026-02-02 10:27 ` Xu Yang
  2026-02-03  7:19   ` Alexander Stein
  2026-02-02 10:27 ` [PATCH 2/3] usb: dwc3: add may_lose_power flag Xu Yang
  2026-02-02 10:27 ` [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc Xu Yang
  2 siblings, 1 reply; 20+ messages in thread
From: Xu Yang @ 2026-02-02 10:27 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen
  Cc: linux-usb, devicetree, imx, linux-arm-kernel, linux-kernel,
	Xu Yang

The i.MX USB glue and DWC3 core are closely coupled. Describe the i.MX
USB block in a single block will bring more benefits than a parent-
child relation. The new binding is a copy of fsl,imx8mp-dwc3.yaml with
the needed modifications.

Add the common compatible string "fsl,imx-dwc3" to indicate that the
flattened module should be selected. This compatible is also used by
"select" to inform the DeviceTree validator to apply this binding.

To avoid redefining all the platform-specific compatibles, "select" is
used to tell the DeviceTree validator which binding to use solely on the
generic compatible.

Mark fsl,imx8mp-dwc3 deprecated, to favor expressing future platforms
using the new combined binding.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
 .../devicetree/bindings/usb/fsl,imx-dwc3.yaml      | 131 +++++++++++++++++++++
 .../devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml   |  13 ++
 2 files changed, 144 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..bc6b9743396e8f6b698706caae71241b0512ce8b
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml
@@ -0,0 +1,131 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2026 NXP
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/fsl,imx-dwc3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX Soc USB Controller
+
+maintainers:
+  - Xu Yang <xu.yang_2@nxp.com>
+
+select:
+  properties:
+    compatible:
+      contains:
+        const: fsl,imx-dwc3
+  required:
+    - compatible
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - fsl,imx95-dwc3
+          - fsl,imx943-dwc3
+          - fsl,imx8mp-dwc3
+      - const: fsl,imx-dwc3
+
+  reg:
+    items:
+      - description: DWC3 core registers.
+      - description: HSIO Block Control registers.
+      - description: Wrapper registers of dwc3 core.
+
+  reg-names:
+    items:
+      - const: core
+      - const: blkctl
+      - const: glue
+
+  interrupts:
+    items:
+      - description: DWC3 controller interrupt.
+      - description: Wakeup interrupt from glue logic.
+
+  interrupt-names:
+    items:
+      - const: dwc_usb3
+      - const: wakeup
+
+  iommus:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: System hsio root clock
+      - description: SoC Bus Clock for AHB/AXI/Native
+      - description: Reference clock for generating ITP when UTMI/ULPI PHY is suspended
+      - description: Suspend clock used for usb wakeup logic.
+
+  clock-names:
+    items:
+      - const: hsio
+      - const: bus_early
+      - const: ref
+      - const: suspend
+
+  fsl,permanently-attached:
+    type: boolean
+    description:
+      Indicates if the device attached to a downstream port is
+      permanently attached.
+
+  fsl,disable-port-power-control:
+    type: boolean
+    description:
+      Indicates whether the host controller implementation includes port
+      power control. Defines Bit 3 in capability register (HCCPARAMS).
+
+  fsl,over-current-active-low:
+    type: boolean
+    description:
+      Over current signal polarity is active low.
+
+  fsl,power-active-low:
+    type: boolean
+    description:
+      Power pad (PWR) polarity is active low.
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - power-domains
+
+allOf:
+  - $ref: snps,dwc3-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    usb@4c100000 {
+      compatible = "fsl,imx943-dwc3", "fsl,imx-dwc3";
+      reg = <0x4c100000 0x10000>,
+            <0x4c010010 0x04>,
+            <0x4c1f0000 0x20>;
+      reg-names = "core", "blkctl", "glue";
+      clocks = <&scmi_clk 74>,    //IMX94_CLK_HSIO
+               <&scmi_clk 74>,    //IMX94_CLK_HSIO
+               <&scmi_clk 2>,     //IMX94_CLK_24M
+               <&scmi_clk 1>;     //IMX94_CLK_32K
+      clock-names = "hsio", "bus_early", "ref", "suspend";
+      interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>,
+                   <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>;
+      interrupt-names = "dwc_usb3", "wakeup";
+      power-domains = <&scmi_devpd 13>;   //IMX94_PD_HSIO_TOP
+      phys = <&usb3_phy>, <&usb3_phy>;
+      phy-names = "usb2-phy", "usb3-phy";
+      snps,gfladj-refclk-lpm-sel-quirk;
+      snps,parkmode-disable-ss-quirk;
+      status = "disabled";
+    };
diff --git a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
index 73e7a60a0060dee6417b9469251e121704b7a148..fd23c345149e0dba1ed3919a25195edf247cfc08 100644
--- a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
@@ -10,6 +10,19 @@ title: NXP iMX8MP Soc USB Controller
 maintainers:
   - Li Jun <jun.li@nxp.com>
 
+deprecated: true
+
+select:
+  properties:
+    compatible:
+      oneOf:
+        - items:
+            - const: fsl,imx95-dwc3
+            - const: fsl,imx8mp-dwc3
+        - const: fsl,imx8mp-dwc3
+  required:
+    - compatible
+
 properties:
   compatible:
     oneOf:

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/3] usb: dwc3: add may_lose_power flag
  2026-02-02 10:27 [PATCH 0/3] add DWC3 i.MX driver based on flatten devicetree Xu Yang
  2026-02-02 10:27 ` [PATCH 1/3] dt-bindings: usb: introduce fsl,imx-dwc3 Xu Yang
@ 2026-02-02 10:27 ` Xu Yang
  2026-02-02 15:36   ` Frank Li
  2026-02-03  0:24   ` Thinh Nguyen
  2026-02-02 10:27 ` [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc Xu Yang
  2 siblings, 2 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-02 10:27 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen
  Cc: linux-usb, devicetree, imx, linux-arm-kernel, linux-kernel,
	Xu Yang

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 to track the controller’s
power state and use it throughout the suspend/resume flow.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
 drivers/usb/dwc3/core.c | 9 +++++++--
 drivers/usb/dwc3/core.h | 2 ++
 drivers/usb/dwc3/glue.h | 3 +++
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index c07ffe82c85049364c38c7ba152aab0ff764d95e..9d4326da5ec7669fa714707fb24556723cab51b8 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -2314,6 +2314,9 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
 			goto err_exit_debugfs;
 	}
 
+	if (data->core_may_lose_power)
+		dwc->may_lose_power = true;
+
 	pm_runtime_put(dev);
 
 	dma_set_max_seg_size(dev, UINT_MAX);
@@ -2462,7 +2465,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->may_lose_power)) {
 			dwc3_core_exit(dwc);
 			break;
 		}
@@ -2525,7 +2529,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->may_lose_power)) {
 			ret = dwc3_core_init_for_resume(dwc);
 			if (ret)
 				return ret;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 08cc6f2b5c23631a752c77fd7394e5876c929f0a..5b1358f36490a001bc9e68139224f7be70a57995 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1117,6 +1117,7 @@ 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
+ * @may_lose_power: set to indicate the core may lose power during pm suspend
  * @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
@@ -1369,6 +1370,7 @@ struct dwc3 {
 	unsigned		usb3_lpm_capable:1;
 	unsigned		usb2_lpm_disable:1;
 	unsigned		usb2_gadget_lpm_disable:1;
+	unsigned		may_lose_power:1;
 
 	unsigned		disable_scramble_quirk:1;
 	unsigned		u2exit_lfps_quirk:1;
diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h
index df86e14cb706ca509206677f644da2a7225b1b26..b428a9f4a32625e7331f8492a408f7c20c915825 100644
--- a/drivers/usb/dwc3/glue.h
+++ b/drivers/usb/dwc3/glue.h
@@ -29,6 +29,8 @@ struct dwc3_properties {
  *		be ignored by the DWC3 core, as they are managed by the glue
  * @skip_core_init_mode: Skip the finial initialization of the target mode, as
  *		it must be managed by the glue
+ * @core_may_lose_power: indicate the controller may not remain power during
+ *		system suspend/resume
  * @properties: dwc3 software manage properties
  */
 struct dwc3_probe_data {
@@ -36,6 +38,7 @@ struct dwc3_probe_data {
 	struct resource *res;
 	bool ignore_clocks_and_resets;
 	bool skip_core_init_mode;
+	bool core_may_lose_power;
 	struct dwc3_properties properties;
 };
 

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc
  2026-02-02 10:27 [PATCH 0/3] add DWC3 i.MX driver based on flatten devicetree Xu Yang
  2026-02-02 10:27 ` [PATCH 1/3] dt-bindings: usb: introduce fsl,imx-dwc3 Xu Yang
  2026-02-02 10:27 ` [PATCH 2/3] usb: dwc3: add may_lose_power flag Xu Yang
@ 2026-02-02 10:27 ` Xu Yang
  2026-02-02 15:42   ` Frank Li
  2026-02-03  1:38   ` Peng Fan
  2 siblings, 2 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-02 10:27 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen
  Cc: linux-usb, devicetree, imx, linux-arm-kernel, linux-kernel,
	Xu Yang

To support flatten dwc3 devicetree model, introduce a new driver.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
 drivers/usb/dwc3/Kconfig    |  12 ++
 drivers/usb/dwc3/Makefile   |   1 +
 drivers/usb/dwc3/dwc3-imx.c | 428 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 441 insertions(+)

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 240b15bc52cbd5d5c9d08d9fddd8c63202de1a3c..18169727a413ee72405a89f477e4da16946e1764 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -150,6 +150,18 @@ config USB_DWC3_IMX8MP
 	  functionality.
 	  Say 'Y' or 'M' if you have one such device.
 
+config USB_DWC3_IMX
+	tristate "NXP iMX Platform"
+	depends on OF && COMMON_CLK
+	depends on (ARCH_MXC && ARM64) || COMPILE_TEST
+	default USB_DWC3
+	help
+	  NXP iMX SoC use DesignWare Core IP for USB2/3
+	  functionality.
+	  This driver also handles the wakeup feature outside
+	  of DesignWare Core.
+	  Say 'Y' or 'M' if you have one such device.
+
 config USB_DWC3_XILINX
 	tristate "Xilinx Platforms"
 	depends on (ARCH_ZYNQMP || COMPILE_TEST) && OF
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 073bef5309b5b5d381c8c4690221091b4df7904a..f37971197203e1379d554da9d60860360ea9c3fe 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
 obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
 obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom-legacy.o
 obj-$(CONFIG_USB_DWC3_IMX8MP)		+= dwc3-imx8mp.o
+obj-$(CONFIG_USB_DWC3_IMX)		+= dwc3-imx.o
 obj-$(CONFIG_USB_DWC3_XILINX)		+= dwc3-xilinx.o
 obj-$(CONFIG_USB_DWC3_OCTEON)		+= dwc3-octeon.o
 obj-$(CONFIG_USB_DWC3_RTK)		+= dwc3-rtk.o
diff --git a/drivers/usb/dwc3/dwc3-imx.c b/drivers/usb/dwc3/dwc3-imx.c
new file mode 100644
index 0000000000000000000000000000000000000000..57b175e929d7e163df5af7e2265ab7117fa1dc9a
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-imx.c
@@ -0,0 +1,428 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dwc3-imx.c - NXP i.MX Soc USB3 Specific Glue layer
+ *
+ * Copyright 2026 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include "core.h"
+#include "glue.h"
+
+/* USB wakeup registers */
+#define USB_WAKEUP_CTRL			0x00
+
+/* Global wakeup interrupt enable, also used to clear interrupt */
+#define USB_WAKEUP_EN			BIT(31)
+/* Wakeup from connect or disconnect, only for superspeed */
+#define USB_WAKEUP_SS_CONN		BIT(5)
+/* 0 select vbus_valid, 1 select sessvld */
+#define USB_WAKEUP_VBUS_SRC_SESS_VAL	BIT(4)
+/* Enable signal for wake up from u3 state */
+#define USB_WAKEUP_U3_EN		BIT(3)
+/* Enable signal for wake up from id change */
+#define USB_WAKEUP_ID_EN		BIT(2)
+/* Enable signal for wake up from vbus change */
+#define	USB_WAKEUP_VBUS_EN		BIT(1)
+/* Enable signal for wake up from dp/dm change */
+#define USB_WAKEUP_DPDM_EN		BIT(0)
+
+#define USB_WAKEUP_EN_MASK		GENMASK(5, 0)
+
+/* USB glue registers */
+#define USB_CTRL0		0x00
+#define USB_CTRL1		0x04
+
+#define USB_CTRL0_PORTPWR_EN	BIT(12) /* 1 - PPC enabled (default) */
+#define USB_CTRL0_USB3_FIXED	BIT(22) /* 1 - USB3 permanent attached */
+#define USB_CTRL0_USB2_FIXED	BIT(23) /* 1 - USB2 permanent attached */
+
+#define USB_CTRL1_OC_POLARITY	BIT(16) /* 0 - HIGH / 1 - LOW */
+#define USB_CTRL1_PWR_POLARITY	BIT(17) /* 0 - HIGH / 1 - LOW */
+
+struct dwc3_imx {
+	struct dwc3	dwc;
+	struct device	*dev;
+	void __iomem	*blkctl_base;
+	void __iomem	*glue_base;
+	struct clk	*hsio_clk;
+	struct clk	*suspend_clk;
+	int		irq;
+	bool		pm_suspended;
+	bool		wakeup_pending;
+};
+
+#define to_dwc3_imx(d) container_of((d), struct dwc3_imx, dwc)
+
+static void dwc3_imx_configure_glue(struct dwc3_imx *dwc_imx)
+{
+	struct device *dev = dwc_imx->dev;
+	u32 value;
+
+	if (!dwc_imx->glue_base)
+		return;
+
+	value = readl(dwc_imx->glue_base + USB_CTRL0);
+
+	if (device_property_read_bool(dev, "fsl,permanently-attached"))
+		value |= (USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
+	else
+		value &= ~(USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
+
+	if (device_property_read_bool(dev, "fsl,disable-port-power-control"))
+		value &= ~(USB_CTRL0_PORTPWR_EN);
+	else
+		value |= USB_CTRL0_PORTPWR_EN;
+
+	writel(value, dwc_imx->glue_base + USB_CTRL0);
+
+	value = readl(dwc_imx->glue_base + USB_CTRL1);
+	if (device_property_read_bool(dev, "fsl,over-current-active-low"))
+		value |= USB_CTRL1_OC_POLARITY;
+	else
+		value &= ~USB_CTRL1_OC_POLARITY;
+
+	if (device_property_read_bool(dev, "fsl,power-active-low"))
+		value |= USB_CTRL1_PWR_POLARITY;
+	else
+		value &= ~USB_CTRL1_PWR_POLARITY;
+
+	writel(value, dwc_imx->glue_base + USB_CTRL1);
+}
+
+static void dwc3_imx_wakeup_enable(struct dwc3_imx *dwc_imx, pm_message_t msg)
+{
+	struct dwc3	*dwc = &dwc_imx->dwc;
+	u32		val;
+
+	val = readl(dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
+
+	if ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc->xhci) {
+		val |= USB_WAKEUP_EN | USB_WAKEUP_DPDM_EN;
+		if (PMSG_IS_AUTO(msg))
+			val |= USB_WAKEUP_SS_CONN | USB_WAKEUP_U3_EN;
+	} else {
+		val |= USB_WAKEUP_EN | USB_WAKEUP_VBUS_EN |
+		       USB_WAKEUP_VBUS_SRC_SESS_VAL;
+	}
+
+	writel(val, dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
+}
+
+static void dwc3_imx_wakeup_disable(struct dwc3_imx *dwc_imx)
+{
+	u32	val;
+
+	val = readl(dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
+	val &= ~(USB_WAKEUP_EN | USB_WAKEUP_EN_MASK);
+	writel(val, dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
+}
+
+static irqreturn_t dwc3_imx_interrupt(int irq, void *data)
+{
+	struct dwc3_imx		*dwc_imx = data;
+	struct dwc3		*dwc = &dwc_imx->dwc;
+
+	if (!dwc_imx->pm_suspended)
+		return IRQ_HANDLED;
+
+	disable_irq_nosync(dwc_imx->irq);
+	dwc_imx->wakeup_pending = true;
+
+	if ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc->xhci)
+		pm_runtime_resume(&dwc->xhci->dev);
+	else if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE)
+		pm_runtime_get(dwc->dev);
+
+	return IRQ_HANDLED;
+}
+
+static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
+{
+	if (role == USB_ROLE_HOST)
+		/*
+		 * For xhci host, we need disable dwc core auto
+		 * suspend, because during this auto suspend delay(5s),
+		 * xhci host RUN_STOP is cleared and wakeup is not
+		 * enabled, if device is inserted, xhci host can't
+		 * response the connection.
+		 */
+		pm_runtime_dont_use_autosuspend(dwc->dev);
+	else
+		pm_runtime_use_autosuspend(dwc->dev);
+}
+
+static struct dwc3_glue_ops dwc3_imx_glue_ops = {
+	.pre_set_role   = dwc3_imx_pre_set_role,
+};
+
+static const struct property_entry dwc3_imx_properties[] = {
+	PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
+	PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
+	{},
+};
+
+static const struct software_node dwc3_imx_swnode = {
+	.properties = dwc3_imx_properties,
+};
+
+static int dwc3_imx_probe(struct platform_device *pdev)
+{
+	struct device		*dev = &pdev->dev;
+	struct dwc3_imx		*dwc_imx;
+	struct dwc3		*dwc;
+	struct resource		*res;
+	const char		*irq_name;
+	struct dwc3_probe_data	probe_data = {};
+	int			ret, irq;
+
+	dwc_imx = devm_kzalloc(dev, sizeof(*dwc_imx), GFP_KERNEL);
+	if (!dwc_imx)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, dwc_imx);
+	dwc_imx->dev = dev;
+
+	dwc_imx->blkctl_base = devm_platform_ioremap_resource_byname(pdev, "blkctl");
+	if (IS_ERR(dwc_imx->blkctl_base))
+		return PTR_ERR(dwc_imx->blkctl_base);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "glue");
+	if (!res) {
+		dev_warn(dev, "Base address for glue layer missing\n");
+	} else {
+		dwc_imx->glue_base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(dwc_imx->glue_base))
+			return PTR_ERR(dwc_imx->glue_base);
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
+	if (!res)
+		return dev_err_probe(dev, -ENODEV, "missing core memory resource\n");
+
+	dwc_imx->hsio_clk = devm_clk_get_enabled(dev, "hsio");
+	if (IS_ERR(dwc_imx->hsio_clk))
+		return dev_err_probe(dev, PTR_ERR(dwc_imx->hsio_clk),
+				     "Failed to get hsio clk\n");
+
+	dwc_imx->suspend_clk = devm_clk_get_enabled(dev, "suspend");
+	if (IS_ERR(dwc_imx->suspend_clk))
+		return dev_err_probe(dev, PTR_ERR(dwc_imx->suspend_clk),
+				     "Failed to get suspend clk\n");
+
+	irq = platform_get_irq_byname(pdev, "wakeup");
+	if (irq < 0)
+		return irq;
+	dwc_imx->irq = irq;
+
+	irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s:wakeup", dev_name(dev));
+	if (!irq_name)
+		return dev_err_probe(dev, -ENOMEM, "failed to create irq_name\n");
+
+	ret = devm_request_threaded_irq(dev, irq, NULL, dwc3_imx_interrupt,
+					IRQF_ONESHOT, irq_name, dwc_imx);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to request IRQ #%d\n", irq);
+
+	ret = device_add_software_node(dev, &dwc3_imx_swnode);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to add software node\n");
+
+	dwc = &dwc_imx->dwc;
+	dwc->dev = dev;
+	dwc->glue_ops = &dwc3_imx_glue_ops;
+
+	probe_data.res = res;
+	probe_data.dwc = dwc;
+	probe_data.core_may_lose_power = true;
+
+	ret = dwc3_core_probe(&probe_data);
+	if (ret) {
+		device_remove_software_node(dev);
+		return ret;
+	}
+
+	device_set_wakeup_capable(dev, true);
+	return 0;
+}
+
+static void dwc3_imx_remove(struct platform_device *pdev)
+{
+	struct device	*dev = &pdev->dev;
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+
+	if (pm_runtime_resume_and_get(dev) < 0)
+		return;
+
+	dwc3_core_remove(dwc);
+	device_remove_software_node(dev);
+	pm_runtime_put_noidle(dev);
+}
+
+static void dwc3_imx_suspend(struct dwc3_imx *dwc_imx, pm_message_t msg)
+{
+	if (PMSG_IS_AUTO(msg) || device_may_wakeup(dwc_imx->dev))
+		dwc3_imx_wakeup_enable(dwc_imx, msg);
+	dwc_imx->pm_suspended = true;
+}
+
+static void dwc3_imx_resume(struct dwc3_imx *dwc_imx, pm_message_t msg)
+{
+	struct dwc3	*dwc = &dwc_imx->dwc;
+
+	dwc_imx->pm_suspended = false;
+	dwc3_imx_wakeup_disable(dwc_imx);
+
+	/* Upon power loss any previous configuration is lost, restore it */
+	dwc3_imx_configure_glue(dwc_imx);
+
+	if (dwc_imx->wakeup_pending) {
+		dwc_imx->wakeup_pending = false;
+		if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE)
+			pm_runtime_put_autosuspend(dwc->dev);
+		else
+			/*
+			 * Add wait for xhci switch from suspend
+			 * clock to normal clock to detect connection.
+			 */
+			usleep_range(9000, 10000);
+		enable_irq(dwc_imx->irq);
+	}
+}
+
+static int dwc3_imx_runtime_suspend(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	struct dwc3_imx	*dwc_imx = to_dwc3_imx(dwc);
+	int		ret;
+
+	dev_dbg(dev, "at %s\n", __func__);
+
+	ret = dwc3_runtime_suspend(dwc);
+	if (ret)
+		return ret;
+
+	dwc3_imx_suspend(dwc_imx, PMSG_AUTO_SUSPEND);
+	return 0;
+}
+
+static int dwc3_imx_runtime_resume(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	struct dwc3_imx	*dwc_imx = to_dwc3_imx(dwc);
+
+	dev_dbg(dev, "at %s\n", __func__);
+
+	dwc3_imx_resume(dwc_imx, PMSG_AUTO_RESUME);
+	return dwc3_runtime_resume(dwc);
+}
+
+static int dwc3_imx_runtime_idle(struct device *dev)
+{
+	return dwc3_runtime_idle(dev_get_drvdata(dev));
+}
+
+static int dwc3_imx_pm_suspend(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	struct dwc3_imx *dwc_imx = to_dwc3_imx(dwc);
+	int		ret;
+
+	dev_dbg(dev, "at %s\n", __func__);
+
+	ret = dwc3_pm_suspend(dwc);
+	if (ret)
+		return ret;
+
+	dwc3_imx_suspend(dwc_imx, PMSG_SUSPEND);
+
+	if (device_may_wakeup(dev)) {
+		enable_irq_wake(dwc_imx->irq);
+		if (device_is_compatible(dev, "fsl,imx95-dwc3"))
+			device_set_out_band_wakeup(dev);
+	} else {
+		clk_disable_unprepare(dwc_imx->suspend_clk);
+	}
+
+	clk_disable_unprepare(dwc_imx->hsio_clk);
+
+	return 0;
+}
+
+static int dwc3_imx_pm_resume(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	struct dwc3_imx *dwc_imx = to_dwc3_imx(dwc);
+	int		ret;
+
+	dev_dbg(dev, "at %s\n", __func__);
+
+	if (device_may_wakeup(dwc_imx->dev)) {
+		disable_irq_wake(dwc_imx->irq);
+	} else {
+		ret = clk_prepare_enable(dwc_imx->suspend_clk);
+		if (ret)
+			return ret;
+	}
+
+	ret = clk_prepare_enable(dwc_imx->hsio_clk);
+	if (ret) {
+		clk_disable_unprepare(dwc_imx->suspend_clk);
+		return ret;
+	}
+
+	dwc3_imx_resume(dwc_imx, PMSG_RESUME);
+
+	ret = dwc3_pm_resume(dwc);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void dwc3_imx_complete(struct device *dev)
+{
+	dwc3_pm_complete(dev_get_drvdata(dev));
+}
+
+static int dwc3_imx_prepare(struct device *dev)
+{
+	return dwc3_pm_prepare(dev_get_drvdata(dev));
+}
+
+static const struct dev_pm_ops dwc3_imx_dev_pm_ops = {
+	SYSTEM_SLEEP_PM_OPS(dwc3_imx_pm_suspend, dwc3_imx_pm_resume)
+	RUNTIME_PM_OPS(dwc3_imx_runtime_suspend, dwc3_imx_runtime_resume,
+		       dwc3_imx_runtime_idle)
+	.complete = pm_sleep_ptr(dwc3_imx_complete),
+	.prepare = pm_sleep_ptr(dwc3_imx_prepare),
+};
+
+static const struct of_device_id dwc3_imx_of_match[] = {
+	{ .compatible = "fsl,imx-dwc3", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dwc3_imx_of_match);
+
+static struct platform_driver dwc3_imx_driver = {
+	.probe		= dwc3_imx_probe,
+	.remove		= dwc3_imx_remove,
+	.driver		= {
+		.name	= "imx-dwc3",
+		.pm	= pm_ptr(&dwc3_imx_dev_pm_ops),
+		.of_match_table	= dwc3_imx_of_match,
+	},
+};
+
+module_platform_driver(dwc3_imx_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DesignWare USB3 i.MX Glue Layer");

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/3] usb: dwc3: add may_lose_power flag
  2026-02-02 10:27 ` [PATCH 2/3] usb: dwc3: add may_lose_power flag Xu Yang
@ 2026-02-02 15:36   ` Frank Li
  2026-02-04  5:44     ` Xu Yang
  2026-02-03  0:24   ` Thinh Nguyen
  1 sibling, 1 reply; 20+ messages in thread
From: Frank Li @ 2026-02-02 15:36 UTC (permalink / raw)
  To: Xu Yang
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Li Jun, Thinh Nguyen, linux-usb, devicetree, imx,
	linux-arm-kernel, linux-kernel

On Mon, Feb 02, 2026 at 06:27:46PM +0800, Xu Yang wrote:
> 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 to track the controller’s
> power state and use it throughout the suspend/resume flow.

Nit: next time, wrap at pos 75 to reduce some lines.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> ---
>  drivers/usb/dwc3/core.c | 9 +++++++--
>  drivers/usb/dwc3/core.h | 2 ++
>  drivers/usb/dwc3/glue.h | 3 +++
>  3 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index c07ffe82c85049364c38c7ba152aab0ff764d95e..9d4326da5ec7669fa714707fb24556723cab51b8 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -2314,6 +2314,9 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
>  			goto err_exit_debugfs;
>  	}
>
> +	if (data->core_may_lose_power)
> +		dwc->may_lose_power = true;
> +
>  	pm_runtime_put(dev);
>
>  	dma_set_max_seg_size(dev, UINT_MAX);
> @@ -2462,7 +2465,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->may_lose_power)) {
>  			dwc3_core_exit(dwc);
>  			break;
>  		}
> @@ -2525,7 +2529,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->may_lose_power)) {
>  			ret = dwc3_core_init_for_resume(dwc);
>  			if (ret)
>  				return ret;
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 08cc6f2b5c23631a752c77fd7394e5876c929f0a..5b1358f36490a001bc9e68139224f7be70a57995 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -1117,6 +1117,7 @@ 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
> + * @may_lose_power: set to indicate the core may lose power during pm suspend
>   * @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
> @@ -1369,6 +1370,7 @@ struct dwc3 {
>  	unsigned		usb3_lpm_capable:1;
>  	unsigned		usb2_lpm_disable:1;
>  	unsigned		usb2_gadget_lpm_disable:1;
> +	unsigned		may_lose_power:1;
>
>  	unsigned		disable_scramble_quirk:1;
>  	unsigned		u2exit_lfps_quirk:1;
> diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h
> index df86e14cb706ca509206677f644da2a7225b1b26..b428a9f4a32625e7331f8492a408f7c20c915825 100644
> --- a/drivers/usb/dwc3/glue.h
> +++ b/drivers/usb/dwc3/glue.h
> @@ -29,6 +29,8 @@ struct dwc3_properties {
>   *		be ignored by the DWC3 core, as they are managed by the glue
>   * @skip_core_init_mode: Skip the finial initialization of the target mode, as
>   *		it must be managed by the glue
> + * @core_may_lose_power: indicate the controller may not remain power during
> + *		system suspend/resume
>   * @properties: dwc3 software manage properties
>   */
>  struct dwc3_probe_data {
> @@ -36,6 +38,7 @@ struct dwc3_probe_data {
>  	struct resource *res;
>  	bool ignore_clocks_and_resets;
>  	bool skip_core_init_mode;
> +	bool core_may_lose_power;
>  	struct dwc3_properties properties;
>  };
>
>
> --
> 2.34.1
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc
  2026-02-02 10:27 ` [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc Xu Yang
@ 2026-02-02 15:42   ` Frank Li
  2026-02-03  0:44     ` Thinh Nguyen
  2026-02-04  6:16     ` Xu Yang
  2026-02-03  1:38   ` Peng Fan
  1 sibling, 2 replies; 20+ messages in thread
From: Frank Li @ 2026-02-02 15:42 UTC (permalink / raw)
  To: Xu Yang
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Li Jun, Thinh Nguyen, linux-usb, devicetree, imx,
	linux-arm-kernel, linux-kernel

On Mon, Feb 02, 2026 at 06:27:47PM +0800, Xu Yang wrote:
> To support flatten dwc3 devicetree model, introduce a new driver.
>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> ---
>  drivers/usb/dwc3/Kconfig    |  12 ++
>  drivers/usb/dwc3/Makefile   |   1 +
>  drivers/usb/dwc3/dwc3-imx.c | 428 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 441 insertions(+)
>
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index 240b15bc52cbd5d5c9d08d9fddd8c63202de1a3c..18169727a413ee72405a89f477e4da16946e1764 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -150,6 +150,18 @@ config USB_DWC3_IMX8MP
>  	  functionality.
>  	  Say 'Y' or 'M' if you have one such device.
>
> +config USB_DWC3_IMX
> +	tristate "NXP iMX Platform"
> +	depends on OF && COMMON_CLK
> +	depends on (ARCH_MXC && ARM64) || COMPILE_TEST
> +	default USB_DWC3
> +	help
> +	  NXP iMX SoC use DesignWare Core IP for USB2/3
> +	  functionality.
> +	  This driver also handles the wakeup feature outside
> +	  of DesignWare Core.
> +	  Say 'Y' or 'M' if you have one such device.
> +
>  config USB_DWC3_XILINX
>  	tristate "Xilinx Platforms"
>  	depends on (ARCH_ZYNQMP || COMPILE_TEST) && OF
> diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
> index 073bef5309b5b5d381c8c4690221091b4df7904a..f37971197203e1379d554da9d60860360ea9c3fe 100644
> --- a/drivers/usb/dwc3/Makefile
> +++ b/drivers/usb/dwc3/Makefile
> @@ -55,6 +55,7 @@ obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
>  obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
>  obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom-legacy.o
>  obj-$(CONFIG_USB_DWC3_IMX8MP)		+= dwc3-imx8mp.o
> +obj-$(CONFIG_USB_DWC3_IMX)		+= dwc3-imx.o
>  obj-$(CONFIG_USB_DWC3_XILINX)		+= dwc3-xilinx.o
>  obj-$(CONFIG_USB_DWC3_OCTEON)		+= dwc3-octeon.o
>  obj-$(CONFIG_USB_DWC3_RTK)		+= dwc3-rtk.o
> diff --git a/drivers/usb/dwc3/dwc3-imx.c b/drivers/usb/dwc3/dwc3-imx.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..57b175e929d7e163df5af7e2265ab7117fa1dc9a
> --- /dev/null
> +++ b/drivers/usb/dwc3/dwc3-imx.c
> @@ -0,0 +1,428 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * dwc3-imx.c - NXP i.MX Soc USB3 Specific Glue layer
> + *
> + * Copyright 2026 NXP
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +#include "core.h"
> +#include "glue.h"
> +
> +/* USB wakeup registers */
> +#define USB_WAKEUP_CTRL			0x00
> +
> +/* Global wakeup interrupt enable, also used to clear interrupt */
> +#define USB_WAKEUP_EN			BIT(31)
> +/* Wakeup from connect or disconnect, only for superspeed */
> +#define USB_WAKEUP_SS_CONN		BIT(5)
> +/* 0 select vbus_valid, 1 select sessvld */
> +#define USB_WAKEUP_VBUS_SRC_SESS_VAL	BIT(4)
> +/* Enable signal for wake up from u3 state */
> +#define USB_WAKEUP_U3_EN		BIT(3)
> +/* Enable signal for wake up from id change */
> +#define USB_WAKEUP_ID_EN		BIT(2)
> +/* Enable signal for wake up from vbus change */
> +#define	USB_WAKEUP_VBUS_EN		BIT(1)
> +/* Enable signal for wake up from dp/dm change */
> +#define USB_WAKEUP_DPDM_EN		BIT(0)
> +
> +#define USB_WAKEUP_EN_MASK		GENMASK(5, 0)
> +
> +/* USB glue registers */
> +#define USB_CTRL0		0x00
> +#define USB_CTRL1		0x04
> +
> +#define USB_CTRL0_PORTPWR_EN	BIT(12) /* 1 - PPC enabled (default) */
> +#define USB_CTRL0_USB3_FIXED	BIT(22) /* 1 - USB3 permanent attached */
> +#define USB_CTRL0_USB2_FIXED	BIT(23) /* 1 - USB2 permanent attached */
> +
> +#define USB_CTRL1_OC_POLARITY	BIT(16) /* 0 - HIGH / 1 - LOW */
> +#define USB_CTRL1_PWR_POLARITY	BIT(17) /* 0 - HIGH / 1 - LOW */
> +
> +struct dwc3_imx {
> +	struct dwc3	dwc;
> +	struct device	*dev;
> +	void __iomem	*blkctl_base;
> +	void __iomem	*glue_base;
> +	struct clk	*hsio_clk;
> +	struct clk	*suspend_clk;
> +	int		irq;
> +	bool		pm_suspended;
> +	bool		wakeup_pending;
> +};
> +
> +#define to_dwc3_imx(d) container_of((d), struct dwc3_imx, dwc)
> +
> +static void dwc3_imx_configure_glue(struct dwc3_imx *dwc_imx)
> +{
> +	struct device *dev = dwc_imx->dev;
> +	u32 value;
> +
> +	if (!dwc_imx->glue_base)
> +		return;
> +
> +	value = readl(dwc_imx->glue_base + USB_CTRL0);
> +
> +	if (device_property_read_bool(dev, "fsl,permanently-attached"))
> +		value |= (USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
> +	else
> +		value &= ~(USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
> +
> +	if (device_property_read_bool(dev, "fsl,disable-port-power-control"))
> +		value &= ~(USB_CTRL0_PORTPWR_EN);
> +	else
> +		value |= USB_CTRL0_PORTPWR_EN;
> +
> +	writel(value, dwc_imx->glue_base + USB_CTRL0);
> +
> +	value = readl(dwc_imx->glue_base + USB_CTRL1);
> +	if (device_property_read_bool(dev, "fsl,over-current-active-low"))
> +		value |= USB_CTRL1_OC_POLARITY;
> +	else
> +		value &= ~USB_CTRL1_OC_POLARITY;
> +
> +	if (device_property_read_bool(dev, "fsl,power-active-low"))
> +		value |= USB_CTRL1_PWR_POLARITY;
> +	else
> +		value &= ~USB_CTRL1_PWR_POLARITY;
> +
> +	writel(value, dwc_imx->glue_base + USB_CTRL1);
> +}
> +
> +static void dwc3_imx_wakeup_enable(struct dwc3_imx *dwc_imx, pm_message_t msg)
> +{
> +	struct dwc3	*dwc = &dwc_imx->dwc;
> +	u32		val;
> +
> +	val = readl(dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
> +
> +	if ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc->xhci) {
> +		val |= USB_WAKEUP_EN | USB_WAKEUP_DPDM_EN;
> +		if (PMSG_IS_AUTO(msg))
> +			val |= USB_WAKEUP_SS_CONN | USB_WAKEUP_U3_EN;
> +	} else {
> +		val |= USB_WAKEUP_EN | USB_WAKEUP_VBUS_EN |
> +		       USB_WAKEUP_VBUS_SRC_SESS_VAL;
> +	}
> +
> +	writel(val, dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
> +}
> +
> +static void dwc3_imx_wakeup_disable(struct dwc3_imx *dwc_imx)
> +{
> +	u32	val;
> +
> +	val = readl(dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
> +	val &= ~(USB_WAKEUP_EN | USB_WAKEUP_EN_MASK);
> +	writel(val, dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
> +}
> +
> +static irqreturn_t dwc3_imx_interrupt(int irq, void *data)
> +{
> +	struct dwc3_imx		*dwc_imx = data;
> +	struct dwc3		*dwc = &dwc_imx->dwc;
> +
> +	if (!dwc_imx->pm_suspended)
> +		return IRQ_HANDLED;
> +
> +	disable_irq_nosync(dwc_imx->irq);
> +	dwc_imx->wakeup_pending = true;
> +
> +	if ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc->xhci)
> +		pm_runtime_resume(&dwc->xhci->dev);
> +	else if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE)
> +		pm_runtime_get(dwc->dev);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
> +{
> +	if (role == USB_ROLE_HOST)
> +		/*
> +		 * For xhci host, we need disable dwc core auto
> +		 * suspend, because during this auto suspend delay(5s),
> +		 * xhci host RUN_STOP is cleared and wakeup is not
> +		 * enabled, if device is inserted, xhci host can't
> +		 * response the connection.
> +		 */
> +		pm_runtime_dont_use_autosuspend(dwc->dev);
> +	else
> +		pm_runtime_use_autosuspend(dwc->dev);
> +}
> +
> +static struct dwc3_glue_ops dwc3_imx_glue_ops = {
> +	.pre_set_role   = dwc3_imx_pre_set_role,
> +};
> +
> +static const struct property_entry dwc3_imx_properties[] = {
> +	PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
> +	PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
> +	{},
> +};
> +
> +static const struct software_node dwc3_imx_swnode = {
> +	.properties = dwc3_imx_properties,
> +};

I met similar case for layerscape dwc. because already use flatten,
directly use probe_data pass these information to core library.

Frank

> +
> +static int dwc3_imx_probe(struct platform_device *pdev)
> +{
> +	struct device		*dev = &pdev->dev;
> +	struct dwc3_imx		*dwc_imx;
> +	struct dwc3		*dwc;
> +	struct resource		*res;
> +	const char		*irq_name;
> +	struct dwc3_probe_data	probe_data = {};
> +	int			ret, irq;
> +
> +	dwc_imx = devm_kzalloc(dev, sizeof(*dwc_imx), GFP_KERNEL);
> +	if (!dwc_imx)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, dwc_imx);
> +	dwc_imx->dev = dev;
> +
> +	dwc_imx->blkctl_base = devm_platform_ioremap_resource_byname(pdev, "blkctl");
> +	if (IS_ERR(dwc_imx->blkctl_base))
> +		return PTR_ERR(dwc_imx->blkctl_base);
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "glue");
> +	if (!res) {
> +		dev_warn(dev, "Base address for glue layer missing\n");
> +	} else {
> +		dwc_imx->glue_base = devm_ioremap_resource(dev, res);
> +		if (IS_ERR(dwc_imx->glue_base))
> +			return PTR_ERR(dwc_imx->glue_base);
> +	}
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
> +	if (!res)
> +		return dev_err_probe(dev, -ENODEV, "missing core memory resource\n");
> +
> +	dwc_imx->hsio_clk = devm_clk_get_enabled(dev, "hsio");
> +	if (IS_ERR(dwc_imx->hsio_clk))
> +		return dev_err_probe(dev, PTR_ERR(dwc_imx->hsio_clk),
> +				     "Failed to get hsio clk\n");
> +
> +	dwc_imx->suspend_clk = devm_clk_get_enabled(dev, "suspend");
> +	if (IS_ERR(dwc_imx->suspend_clk))
> +		return dev_err_probe(dev, PTR_ERR(dwc_imx->suspend_clk),
> +				     "Failed to get suspend clk\n");
> +
> +	irq = platform_get_irq_byname(pdev, "wakeup");
> +	if (irq < 0)
> +		return irq;
> +	dwc_imx->irq = irq;
> +
> +	irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s:wakeup", dev_name(dev));
> +	if (!irq_name)
> +		return dev_err_probe(dev, -ENOMEM, "failed to create irq_name\n");
> +
> +	ret = devm_request_threaded_irq(dev, irq, NULL, dwc3_imx_interrupt,
> +					IRQF_ONESHOT, irq_name, dwc_imx);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "failed to request IRQ #%d\n", irq);
> +
> +	ret = device_add_software_node(dev, &dwc3_imx_swnode);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "failed to add software node\n");
> +
> +	dwc = &dwc_imx->dwc;
> +	dwc->dev = dev;
> +	dwc->glue_ops = &dwc3_imx_glue_ops;
> +
> +	probe_data.res = res;
> +	probe_data.dwc = dwc;
> +	probe_data.core_may_lose_power = true;
> +
> +	ret = dwc3_core_probe(&probe_data);
> +	if (ret) {
> +		device_remove_software_node(dev);
> +		return ret;
> +	}
> +
> +	device_set_wakeup_capable(dev, true);
> +	return 0;
> +}
> +
> +static void dwc3_imx_remove(struct platform_device *pdev)
> +{
> +	struct device	*dev = &pdev->dev;
> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> +
> +	if (pm_runtime_resume_and_get(dev) < 0)
> +		return;
> +
> +	dwc3_core_remove(dwc);
> +	device_remove_software_node(dev);
> +	pm_runtime_put_noidle(dev);
> +}
> +
> +static void dwc3_imx_suspend(struct dwc3_imx *dwc_imx, pm_message_t msg)
> +{
> +	if (PMSG_IS_AUTO(msg) || device_may_wakeup(dwc_imx->dev))
> +		dwc3_imx_wakeup_enable(dwc_imx, msg);
> +	dwc_imx->pm_suspended = true;
> +}
> +
> +static void dwc3_imx_resume(struct dwc3_imx *dwc_imx, pm_message_t msg)
> +{
> +	struct dwc3	*dwc = &dwc_imx->dwc;
> +
> +	dwc_imx->pm_suspended = false;
> +	dwc3_imx_wakeup_disable(dwc_imx);
> +
> +	/* Upon power loss any previous configuration is lost, restore it */
> +	dwc3_imx_configure_glue(dwc_imx);
> +
> +	if (dwc_imx->wakeup_pending) {
> +		dwc_imx->wakeup_pending = false;
> +		if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE)
> +			pm_runtime_put_autosuspend(dwc->dev);
> +		else
> +			/*
> +			 * Add wait for xhci switch from suspend
> +			 * clock to normal clock to detect connection.
> +			 */
> +			usleep_range(9000, 10000);
> +		enable_irq(dwc_imx->irq);
> +	}
> +}
> +
> +static int dwc3_imx_runtime_suspend(struct device *dev)
> +{
> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> +	struct dwc3_imx	*dwc_imx = to_dwc3_imx(dwc);
> +	int		ret;
> +
> +	dev_dbg(dev, "at %s\n", __func__);
> +
> +	ret = dwc3_runtime_suspend(dwc);
> +	if (ret)
> +		return ret;
> +
> +	dwc3_imx_suspend(dwc_imx, PMSG_AUTO_SUSPEND);
> +	return 0;
> +}
> +
> +static int dwc3_imx_runtime_resume(struct device *dev)
> +{
> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> +	struct dwc3_imx	*dwc_imx = to_dwc3_imx(dwc);
> +
> +	dev_dbg(dev, "at %s\n", __func__);
> +
> +	dwc3_imx_resume(dwc_imx, PMSG_AUTO_RESUME);
> +	return dwc3_runtime_resume(dwc);
> +}
> +
> +static int dwc3_imx_runtime_idle(struct device *dev)
> +{
> +	return dwc3_runtime_idle(dev_get_drvdata(dev));
> +}
> +
> +static int dwc3_imx_pm_suspend(struct device *dev)
> +{
> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> +	struct dwc3_imx *dwc_imx = to_dwc3_imx(dwc);
> +	int		ret;
> +
> +	dev_dbg(dev, "at %s\n", __func__);
> +
> +	ret = dwc3_pm_suspend(dwc);
> +	if (ret)
> +		return ret;
> +
> +	dwc3_imx_suspend(dwc_imx, PMSG_SUSPEND);
> +
> +	if (device_may_wakeup(dev)) {
> +		enable_irq_wake(dwc_imx->irq);
> +		if (device_is_compatible(dev, "fsl,imx95-dwc3"))
> +			device_set_out_band_wakeup(dev);
> +	} else {
> +		clk_disable_unprepare(dwc_imx->suspend_clk);
> +	}
> +
> +	clk_disable_unprepare(dwc_imx->hsio_clk);
> +
> +	return 0;
> +}
> +
> +static int dwc3_imx_pm_resume(struct device *dev)
> +{
> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> +	struct dwc3_imx *dwc_imx = to_dwc3_imx(dwc);
> +	int		ret;
> +
> +	dev_dbg(dev, "at %s\n", __func__);
> +
> +	if (device_may_wakeup(dwc_imx->dev)) {
> +		disable_irq_wake(dwc_imx->irq);
> +	} else {
> +		ret = clk_prepare_enable(dwc_imx->suspend_clk);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	ret = clk_prepare_enable(dwc_imx->hsio_clk);
> +	if (ret) {
> +		clk_disable_unprepare(dwc_imx->suspend_clk);
> +		return ret;
> +	}
> +
> +	dwc3_imx_resume(dwc_imx, PMSG_RESUME);
> +
> +	ret = dwc3_pm_resume(dwc);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static void dwc3_imx_complete(struct device *dev)
> +{
> +	dwc3_pm_complete(dev_get_drvdata(dev));
> +}
> +
> +static int dwc3_imx_prepare(struct device *dev)
> +{
> +	return dwc3_pm_prepare(dev_get_drvdata(dev));
> +}
> +
> +static const struct dev_pm_ops dwc3_imx_dev_pm_ops = {
> +	SYSTEM_SLEEP_PM_OPS(dwc3_imx_pm_suspend, dwc3_imx_pm_resume)
> +	RUNTIME_PM_OPS(dwc3_imx_runtime_suspend, dwc3_imx_runtime_resume,
> +		       dwc3_imx_runtime_idle)
> +	.complete = pm_sleep_ptr(dwc3_imx_complete),
> +	.prepare = pm_sleep_ptr(dwc3_imx_prepare),
> +};
> +
> +static const struct of_device_id dwc3_imx_of_match[] = {
> +	{ .compatible = "fsl,imx-dwc3", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dwc3_imx_of_match);
> +
> +static struct platform_driver dwc3_imx_driver = {
> +	.probe		= dwc3_imx_probe,
> +	.remove		= dwc3_imx_remove,
> +	.driver		= {
> +		.name	= "imx-dwc3",
> +		.pm	= pm_ptr(&dwc3_imx_dev_pm_ops),
> +		.of_match_table	= dwc3_imx_of_match,
> +	},
> +};
> +
> +module_platform_driver(dwc3_imx_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("DesignWare USB3 i.MX Glue Layer");
>
> --
> 2.34.1
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/3] usb: dwc3: add may_lose_power flag
  2026-02-02 10:27 ` [PATCH 2/3] usb: dwc3: add may_lose_power flag Xu Yang
  2026-02-02 15:36   ` Frank Li
@ 2026-02-03  0:24   ` Thinh Nguyen
  2026-02-03  1:16     ` Peng Fan
  2026-02-04  5:47     ` Xu Yang
  1 sibling, 2 replies; 20+ messages in thread
From: Thinh Nguyen @ 2026-02-03  0:24 UTC (permalink / raw)
  To: Xu Yang
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen,
	linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
	imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org

On Mon, Feb 02, 2026, Xu Yang wrote:
> 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 to track the controller’s
> power state and use it throughout the suspend/resume flow.
> 
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> ---
>  drivers/usb/dwc3/core.c | 9 +++++++--
>  drivers/usb/dwc3/core.h | 2 ++
>  drivers/usb/dwc3/glue.h | 3 +++
>  3 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index c07ffe82c85049364c38c7ba152aab0ff764d95e..9d4326da5ec7669fa714707fb24556723cab51b8 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -2314,6 +2314,9 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
>  			goto err_exit_debugfs;
>  	}
>  
> +	if (data->core_may_lose_power)

Can this be passed down as part of the dwc3_properties within the
probe_data? I'm trying to consolidate all the dwc3 properties to one
place.

> +		dwc->may_lose_power = true;
> +
>  	pm_runtime_put(dev);
>  
>  	dma_set_max_seg_size(dev, UINT_MAX);
> @@ -2462,7 +2465,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->may_lose_power)) {
>  			dwc3_core_exit(dwc);
>  			break;
>  		}
> @@ -2525,7 +2529,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->may_lose_power)) {
>  			ret = dwc3_core_init_for_resume(dwc);
>  			if (ret)
>  				return ret;
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 08cc6f2b5c23631a752c77fd7394e5876c929f0a..5b1358f36490a001bc9e68139224f7be70a57995 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -1117,6 +1117,7 @@ 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
> + * @may_lose_power: set to indicate the core may lose power during pm suspend
>   * @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
> @@ -1369,6 +1370,7 @@ struct dwc3 {
>  	unsigned		usb3_lpm_capable:1;
>  	unsigned		usb2_lpm_disable:1;
>  	unsigned		usb2_gadget_lpm_disable:1;
> +	unsigned		may_lose_power:1;

This name sounds like a quirk of a broken SoC.

Perhaps rename this to something such as power_lost_on_suspend or
needs_full_reinit?

BR,
Thinh

>  
>  	unsigned		disable_scramble_quirk:1;
>  	unsigned		u2exit_lfps_quirk:1;
> diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h
> index df86e14cb706ca509206677f644da2a7225b1b26..b428a9f4a32625e7331f8492a408f7c20c915825 100644
> --- a/drivers/usb/dwc3/glue.h
> +++ b/drivers/usb/dwc3/glue.h
> @@ -29,6 +29,8 @@ struct dwc3_properties {
>   *		be ignored by the DWC3 core, as they are managed by the glue
>   * @skip_core_init_mode: Skip the finial initialization of the target mode, as
>   *		it must be managed by the glue
> + * @core_may_lose_power: indicate the controller may not remain power during
> + *		system suspend/resume
>   * @properties: dwc3 software manage properties
>   */
>  struct dwc3_probe_data {
> @@ -36,6 +38,7 @@ struct dwc3_probe_data {
>  	struct resource *res;
>  	bool ignore_clocks_and_resets;
>  	bool skip_core_init_mode;
> +	bool core_may_lose_power;
>  	struct dwc3_properties properties;
>  };
>  
> 
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc
  2026-02-02 15:42   ` Frank Li
@ 2026-02-03  0:44     ` Thinh Nguyen
  2026-02-04  6:19       ` Xu Yang
  2026-02-04  6:16     ` Xu Yang
  1 sibling, 1 reply; 20+ messages in thread
From: Thinh Nguyen @ 2026-02-03  0:44 UTC (permalink / raw)
  To: Frank Li
  Cc: Xu Yang, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Li Jun, Thinh Nguyen, linux-usb@vger.kernel.org,
	devicetree@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org

On Mon, Feb 02, 2026, Frank Li wrote:
> On Mon, Feb 02, 2026 at 06:27:47PM +0800, Xu Yang wrote:
> > To support flatten dwc3 devicetree model, introduce a new driver.
> >
> > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>

Can you include additional info to describe why this was needed
(written in your cover letter).

Also note any new feature supported by this glue that's not currently
available in the old driver.

Thanks,
Thinh

(ps. I'm thinking of creating a legacy_glues directory to start moving
all the legacy glue drivers there)

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/3] usb: dwc3: add may_lose_power flag
  2026-02-03  0:24   ` Thinh Nguyen
@ 2026-02-03  1:16     ` Peng Fan
  2026-02-04  1:52       ` Thinh Nguyen
  2026-02-04  5:47     ` Xu Yang
  1 sibling, 1 reply; 20+ messages in thread
From: Peng Fan @ 2026-02-03  1:16 UTC (permalink / raw)
  To: Thinh Nguyen
  Cc: Xu Yang, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, linux-usb@vger.kernel.org,
	devicetree@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org

On Tue, Feb 03, 2026 at 12:24:08AM +0000, Thinh Nguyen wrote:
>On Mon, Feb 02, 2026, Xu Yang wrote:
>> 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 to track the controller’s
>> power state and use it throughout the suspend/resume flow.
>> 
>> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
>> ---
>>  drivers/usb/dwc3/core.c | 9 +++++++--
>>  drivers/usb/dwc3/core.h | 2 ++
>>  drivers/usb/dwc3/glue.h | 3 +++
>>  3 files changed, 12 insertions(+), 2 deletions(-)
>> 
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index c07ffe82c85049364c38c7ba152aab0ff764d95e..9d4326da5ec7669fa714707fb24556723cab51b8 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -2314,6 +2314,9 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
>>  			goto err_exit_debugfs;
>>  	}
>>  
>> +	if (data->core_may_lose_power)
>
>Can this be passed down as part of the dwc3_properties within the
>probe_data? I'm trying to consolidate all the dwc3 properties to one
>place.
>
>> +		dwc->may_lose_power = true;
>> +
>>  	pm_runtime_put(dev);
>>  
>>  	dma_set_max_seg_size(dev, UINT_MAX);
>> @@ -2462,7 +2465,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->may_lose_power)) {
>>  			dwc3_core_exit(dwc);
>>  			break;
>>  		}
>> @@ -2525,7 +2529,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->may_lose_power)) {
>>  			ret = dwc3_core_init_for_resume(dwc);
>>  			if (ret)
>>  				return ret;
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index 08cc6f2b5c23631a752c77fd7394e5876c929f0a..5b1358f36490a001bc9e68139224f7be70a57995 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -1117,6 +1117,7 @@ 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
>> + * @may_lose_power: set to indicate the core may lose power during pm suspend
>>   * @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
>> @@ -1369,6 +1370,7 @@ struct dwc3 {
>>  	unsigned		usb3_lpm_capable:1;
>>  	unsigned		usb2_lpm_disable:1;
>>  	unsigned		usb2_gadget_lpm_disable:1;
>> +	unsigned		may_lose_power:1;
>
>This name sounds like a quirk of a broken SoC.
>
>Perhaps rename this to something such as power_lost_on_suspend or
>needs_full_reinit?

How about out_band_wakeup?

Regards
Peng

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc
  2026-02-02 10:27 ` [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc Xu Yang
  2026-02-02 15:42   ` Frank Li
@ 2026-02-03  1:38   ` Peng Fan
  2026-02-04  2:27     ` Thinh Nguyen
  2026-02-04  6:30     ` Xu Yang
  1 sibling, 2 replies; 20+ messages in thread
From: Peng Fan @ 2026-02-03  1:38 UTC (permalink / raw)
  To: Xu Yang
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen, linux-usb,
	devicetree, imx, linux-arm-kernel, linux-kernel

On Mon, Feb 02, 2026 at 06:27:47PM +0800, Xu Yang wrote:
>To support flatten dwc3 devicetree model, introduce a new driver.
>
>Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
>---
> drivers/usb/dwc3/Kconfig    |  12 ++
> drivers/usb/dwc3/Makefile   |   1 +
> drivers/usb/dwc3/dwc3-imx.c | 428 ++++++++++++++++++++++++++++++++++++++++++++
...
>diff --git a/drivers/usb/dwc3/dwc3-imx.c b/drivers/usb/dwc3/dwc3-imx.c
>new file mode 100644
>index 0000000000000000000000000000000000000000..57b175e929d7e163df5af7e2265ab7117fa1dc9a
>--- /dev/null
>+++ b/drivers/usb/dwc3/dwc3-imx.c
>@@ -0,0 +1,428 @@
>+// SPDX-License-Identifier: GPL-2.0
>+/*
>+ * dwc3-imx.c - NXP i.MX Soc USB3 Specific Glue layer
>+ *
>+ * Copyright 2026 NXP
>+ */
>+
>+#include <linux/clk.h>
>+#include <linux/interrupt.h>
>+#include <linux/io.h>
>+#include <linux/kernel.h>
>+#include <linux/module.h>
>+#include <linux/of_platform.h>
>+#include <linux/platform_device.h>
>+#include <linux/pm_runtime.h>
>+
>+#include "core.h"
>+#include "glue.h"
>+
>+/* USB wakeup registers */
>+#define USB_WAKEUP_CTRL			0x00
>+
>+/* Global wakeup interrupt enable, also used to clear interrupt */
>+#define USB_WAKEUP_EN			BIT(31)
>+/* Wakeup from connect or disconnect, only for superspeed */
>+#define USB_WAKEUP_SS_CONN		BIT(5)
>+/* 0 select vbus_valid, 1 select sessvld */
>+#define USB_WAKEUP_VBUS_SRC_SESS_VAL	BIT(4)
>+/* Enable signal for wake up from u3 state */
>+#define USB_WAKEUP_U3_EN		BIT(3)
>+/* Enable signal for wake up from id change */
>+#define USB_WAKEUP_ID_EN		BIT(2)
>+/* Enable signal for wake up from vbus change */
>+#define	USB_WAKEUP_VBUS_EN		BIT(1)
>+/* Enable signal for wake up from dp/dm change */
>+#define USB_WAKEUP_DPDM_EN		BIT(0)
>+
>+#define USB_WAKEUP_EN_MASK		GENMASK(5, 0)
>+
>+/* USB glue registers */
>+#define USB_CTRL0		0x00
>+#define USB_CTRL1		0x04
>+
>+#define USB_CTRL0_PORTPWR_EN	BIT(12) /* 1 - PPC enabled (default) */
>+#define USB_CTRL0_USB3_FIXED	BIT(22) /* 1 - USB3 permanent attached */
>+#define USB_CTRL0_USB2_FIXED	BIT(23) /* 1 - USB2 permanent attached */
>+
>+#define USB_CTRL1_OC_POLARITY	BIT(16) /* 0 - HIGH / 1 - LOW */
>+#define USB_CTRL1_PWR_POLARITY	BIT(17) /* 0 - HIGH / 1 - LOW */
>+
>+struct dwc3_imx {
>+	struct dwc3	dwc;
>+	struct device	*dev;
>+	void __iomem	*blkctl_base;
>+	void __iomem	*glue_base;
>+	struct clk	*hsio_clk;
>+	struct clk	*suspend_clk;
>+	int		irq;
>+	bool		pm_suspended;
>+	bool		wakeup_pending;
>+};
>+
>+#define to_dwc3_imx(d) container_of((d), struct dwc3_imx, dwc)
>+
>+static void dwc3_imx_configure_glue(struct dwc3_imx *dwc_imx)
>+{
>+	struct device *dev = dwc_imx->dev;
>+	u32 value;
>+
>+	if (!dwc_imx->glue_base)
>+		return;
>+
>+	value = readl(dwc_imx->glue_base + USB_CTRL0);
>+
>+	if (device_property_read_bool(dev, "fsl,permanently-attached"))
>+		value |= (USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);

No need parentheses.

>+	else
>+		value &= ~(USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
>+
>+	if (device_property_read_bool(dev, "fsl,disable-port-power-control"))
>+		value &= ~(USB_CTRL0_PORTPWR_EN);

Ditto.

>+	else
>+		value |= USB_CTRL0_PORTPWR_EN;
>+
>+	writel(value, dwc_imx->glue_base + USB_CTRL0);
>+
>+	value = readl(dwc_imx->glue_base + USB_CTRL1);
>+	if (device_property_read_bool(dev, "fsl,over-current-active-low"))
>+		value |= USB_CTRL1_OC_POLARITY;
>+	else
>+		value &= ~USB_CTRL1_OC_POLARITY;
>+
>+	if (device_property_read_bool(dev, "fsl,power-active-low"))
>+		value |= USB_CTRL1_PWR_POLARITY;
>+	else
>+		value &= ~USB_CTRL1_PWR_POLARITY;
>+
>+	writel(value, dwc_imx->glue_base + USB_CTRL1);
>+}
>+
>+static void dwc3_imx_wakeup_enable(struct dwc3_imx *dwc_imx, pm_message_t msg)
>+{
>+	struct dwc3	*dwc = &dwc_imx->dwc;
>+	u32		val;

In dwc3_imx_configure_glue, space is used. while here, tab is used.

>+
>+	val = readl(dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
>+
>+	if ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc->xhci) {
>+		val |= USB_WAKEUP_EN | USB_WAKEUP_DPDM_EN;
>+		if (PMSG_IS_AUTO(msg))
>+			val |= USB_WAKEUP_SS_CONN | USB_WAKEUP_U3_EN;
>+	} else {
>+		val |= USB_WAKEUP_EN | USB_WAKEUP_VBUS_EN |
>+		       USB_WAKEUP_VBUS_SRC_SESS_VAL;
>+	}
>+
>+	writel(val, dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
>+}
>+
>+static void dwc3_imx_wakeup_disable(struct dwc3_imx *dwc_imx)
>+{
>+	u32	val;

Ditto.

>+
>+	val = readl(dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
>+	val &= ~(USB_WAKEUP_EN | USB_WAKEUP_EN_MASK);
>+	writel(val, dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
>+}
>+
>+static irqreturn_t dwc3_imx_interrupt(int irq, void *data)
>+{
>+	struct dwc3_imx		*dwc_imx = data;
>+	struct dwc3		*dwc = &dwc_imx->dwc;

Ditto.

>+
>+	if (!dwc_imx->pm_suspended)
>+		return IRQ_HANDLED;
>+
>+	disable_irq_nosync(dwc_imx->irq);
>+	dwc_imx->wakeup_pending = true;
>+
>+	if ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc->xhci)
>+		pm_runtime_resume(&dwc->xhci->dev);
>+	else if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE)
>+		pm_runtime_get(dwc->dev);
>+
>+	return IRQ_HANDLED;
>+}
>+
>+static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
>+{
>+	if (role == USB_ROLE_HOST)
>+		/*
>+		 * For xhci host, we need disable dwc core auto
>+		 * suspend, because during this auto suspend delay(5s),
>+		 * xhci host RUN_STOP is cleared and wakeup is not
>+		 * enabled, if device is inserted, xhci host can't
>+		 * response the connection.
>+		 */
>+		pm_runtime_dont_use_autosuspend(dwc->dev);
>+	else
>+		pm_runtime_use_autosuspend(dwc->dev);
>+}
>+
>+static struct dwc3_glue_ops dwc3_imx_glue_ops = {
>+	.pre_set_role   = dwc3_imx_pre_set_role,
>+};
>+
>+static const struct property_entry dwc3_imx_properties[] = {
>+	PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
>+	PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
>+	{},
>+};
>+
>+static const struct software_node dwc3_imx_swnode = {
>+	.properties = dwc3_imx_properties,
>+};
>+
>+static int dwc3_imx_probe(struct platform_device *pdev)
>+{
>+	struct device		*dev = &pdev->dev;
>+	struct dwc3_imx		*dwc_imx;
>+	struct dwc3		*dwc;
>+	struct resource		*res;
>+	const char		*irq_name;
>+	struct dwc3_probe_data	probe_data = {};
>+	int			ret, irq;

As written above, unify the format.

>+
>+	dwc_imx = devm_kzalloc(dev, sizeof(*dwc_imx), GFP_KERNEL);
>+	if (!dwc_imx)
>+		return -ENOMEM;
>+
>+	platform_set_drvdata(pdev, dwc_imx);
>+	dwc_imx->dev = dev;
>+
>+	dwc_imx->blkctl_base = devm_platform_ioremap_resource_byname(pdev, "blkctl");
>+	if (IS_ERR(dwc_imx->blkctl_base))
>+		return PTR_ERR(dwc_imx->blkctl_base);
>+
>+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "glue");
>+	if (!res) {
>+		dev_warn(dev, "Base address for glue layer missing\n");
>+	} else {
>+		dwc_imx->glue_base = devm_ioremap_resource(dev, res);
>+		if (IS_ERR(dwc_imx->glue_base))
>+			return PTR_ERR(dwc_imx->glue_base);
>+	}
>+
>+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
>+	if (!res)
>+		return dev_err_probe(dev, -ENODEV, "missing core memory resource\n");

-ENOENT should be better.

>+
>+	dwc_imx->hsio_clk = devm_clk_get_enabled(dev, "hsio");
>+	if (IS_ERR(dwc_imx->hsio_clk))
>+		return dev_err_probe(dev, PTR_ERR(dwc_imx->hsio_clk),
>+				     "Failed to get hsio clk\n");
>+
>+	dwc_imx->suspend_clk = devm_clk_get_enabled(dev, "suspend");
>+	if (IS_ERR(dwc_imx->suspend_clk))
>+		return dev_err_probe(dev, PTR_ERR(dwc_imx->suspend_clk),
>+				     "Failed to get suspend clk\n");
>+
>+	irq = platform_get_irq_byname(pdev, "wakeup");
>+	if (irq < 0)
>+		return irq;
>+	dwc_imx->irq = irq;
>+
>+	irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s:wakeup", dev_name(dev));
>+	if (!irq_name)
>+		return dev_err_probe(dev, -ENOMEM, "failed to create irq_name\n");
>+
>+	ret = devm_request_threaded_irq(dev, irq, NULL, dwc3_imx_interrupt,
>+					IRQF_ONESHOT, irq_name, dwc_imx);
>+	if (ret)
>+		return dev_err_probe(dev, ret, "failed to request IRQ #%d\n", irq);

Should this be moved to end after all are initialized?

>+
>+	ret = device_add_software_node(dev, &dwc3_imx_swnode);
>+	if (ret)
>+		return dev_err_probe(dev, ret, "failed to add software node\n");
>+
>+	dwc = &dwc_imx->dwc;
>+	dwc->dev = dev;
>+	dwc->glue_ops = &dwc3_imx_glue_ops;
>+
>+	probe_data.res = res;
>+	probe_data.dwc = dwc;
>+	probe_data.core_may_lose_power = true;
>+
>+	ret = dwc3_core_probe(&probe_data);
>+	if (ret) {
>+		device_remove_software_node(dev);
>+		return ret;
>+	}
>+
>+	device_set_wakeup_capable(dev, true);
>+	return 0;
>+}
>+
>+static void dwc3_imx_remove(struct platform_device *pdev)
>+{
>+	struct device	*dev = &pdev->dev;
>+	struct dwc3	*dwc = dev_get_drvdata(dev);
>+
>+	if (pm_runtime_resume_and_get(dev) < 0)

print a error message.

when this fail return, there is no chance to probe success again I think,
because resource not freed.

>+		return;
>+
>+	dwc3_core_remove(dwc);
>+	device_remove_software_node(dev);
>+	pm_runtime_put_noidle(dev);
>+}
>+

Regards
Peng

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/3] dt-bindings: usb: introduce fsl,imx-dwc3
  2026-02-02 10:27 ` [PATCH 1/3] dt-bindings: usb: introduce fsl,imx-dwc3 Xu Yang
@ 2026-02-03  7:19   ` Alexander Stein
  2026-02-04  5:41     ` Xu Yang
  0 siblings, 1 reply; 20+ messages in thread
From: Alexander Stein @ 2026-02-03  7:19 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen, Xu Yang
  Cc: linux-usb, devicetree, imx, linux-arm-kernel, linux-kernel,
	Xu Yang

Am Montag, 2. Februar 2026, 11:27:45 CET schrieb Xu Yang:
> The i.MX USB glue and DWC3 core are closely coupled. Describe the i.MX
> USB block in a single block will bring more benefits than a parent-
> child relation. The new binding is a copy of fsl,imx8mp-dwc3.yaml with
> the needed modifications.
> 
> Add the common compatible string "fsl,imx-dwc3" to indicate that the
> flattened module should be selected. This compatible is also used by
> "select" to inform the DeviceTree validator to apply this binding.
> 
> To avoid redefining all the platform-specific compatibles, "select" is
> used to tell the DeviceTree validator which binding to use solely on the
> generic compatible.
> 
> Mark fsl,imx8mp-dwc3 deprecated, to favor expressing future platforms
> using the new combined binding.
> 
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> ---
>  .../devicetree/bindings/usb/fsl,imx-dwc3.yaml      | 131 +++++++++++++++++++++
>  .../devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml   |  13 ++
>  2 files changed, 144 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..bc6b9743396e8f6b698706caae71241b0512ce8b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml
> @@ -0,0 +1,131 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +# Copyright 2026 NXP
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/usb/fsl,imx-dwc3.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NXP i.MX Soc USB Controller
> +
> +maintainers:
> +  - Xu Yang <xu.yang_2@nxp.com>
> +
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        const: fsl,imx-dwc3
> +  required:
> +    - compatible
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +          - fsl,imx95-dwc3
> +          - fsl,imx943-dwc3
> +          - fsl,imx8mp-dwc3

Can you please sort this? I would have expected the exact reverse ordering.

> +      - const: fsl,imx-dwc3
> +
> +  reg:
> +    items:
> +      - description: DWC3 core registers.
> +      - description: HSIO Block Control registers.
> +      - description: Wrapper registers of dwc3 core.
> +
> +  reg-names:
> +    items:
> +      - const: core
> +      - const: blkctl
> +      - const: glue
> +
> +  interrupts:
> +    items:
> +      - description: DWC3 controller interrupt.
> +      - description: Wakeup interrupt from glue logic.
> +
> +  interrupt-names:
> +    items:
> +      - const: dwc_usb3
> +      - const: wakeup
> +
> +  iommus:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: System hsio root clock
> +      - description: SoC Bus Clock for AHB/AXI/Native
> +      - description: Reference clock for generating ITP when UTMI/ULPI PHY is suspended
> +      - description: Suspend clock used for usb wakeup logic.
> +
> +  clock-names:
> +    items:
> +      - const: hsio
> +      - const: bus_early
> +      - const: ref
> +      - const: suspend
> +
> +  fsl,permanently-attached:
> +    type: boolean
> +    description:
> +      Indicates if the device attached to a downstream port is
> +      permanently attached.
> +
> +  fsl,disable-port-power-control:
> +    type: boolean
> +    description:
> +      Indicates whether the host controller implementation includes port
> +      power control. Defines Bit 3 in capability register (HCCPARAMS).
> +
> +  fsl,over-current-active-low:
> +    type: boolean
> +    description:
> +      Over current signal polarity is active low.
> +
> +  fsl,power-active-low:
> +    type: boolean
> +    description:
> +      Power pad (PWR) polarity is active low.
> +
> +  power-domains:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +  - interrupts
> +  - power-domains
> +
> +allOf:
> +  - $ref: snps,dwc3-common.yaml#
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    usb@4c100000 {
> +      compatible = "fsl,imx943-dwc3", "fsl,imx-dwc3";
> +      reg = <0x4c100000 0x10000>,
> +            <0x4c010010 0x04>,
> +            <0x4c1f0000 0x20>;
> +      reg-names = "core", "blkctl", "glue";
> +      clocks = <&scmi_clk 74>,    //IMX94_CLK_HSIO
> +               <&scmi_clk 74>,    //IMX94_CLK_HSIO
> +               <&scmi_clk 2>,     //IMX94_CLK_24M
> +               <&scmi_clk 1>;     //IMX94_CLK_32K
> +      clock-names = "hsio", "bus_early", "ref", "suspend";
> +      interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>,
> +                   <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>;
> +      interrupt-names = "dwc_usb3", "wakeup";
> +      power-domains = <&scmi_devpd 13>;   //IMX94_PD_HSIO_TOP
> +      phys = <&usb3_phy>, <&usb3_phy>;
> +      phy-names = "usb2-phy", "usb3-phy";
> +      snps,gfladj-refclk-lpm-sel-quirk;
> +      snps,parkmode-disable-ss-quirk;
> +      status = "disabled";
> +    };
> diff --git a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
> index 73e7a60a0060dee6417b9469251e121704b7a148..fd23c345149e0dba1ed3919a25195edf247cfc08 100644
> --- a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
> +++ b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
> @@ -10,6 +10,19 @@ title: NXP iMX8MP Soc USB Controller
>  maintainers:
>    - Li Jun <jun.li@nxp.com>
>  
> +deprecated: true
> +
> +select:
> +  properties:
> +    compatible:
> +      oneOf:
> +        - items:
> +            - const: fsl,imx95-dwc3
> +            - const: fsl,imx8mp-dwc3

Same here.

Best regards,
Alexander

> +        - const: fsl,imx8mp-dwc3
> +  required:
> +    - compatible
> +
>  properties:
>    compatible:
>      oneOf:
> 
> 


-- 
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
http://www.tq-group.com/



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/3] usb: dwc3: add may_lose_power flag
  2026-02-03  1:16     ` Peng Fan
@ 2026-02-04  1:52       ` Thinh Nguyen
  2026-02-04  5:55         ` Xu Yang
  0 siblings, 1 reply; 20+ messages in thread
From: Thinh Nguyen @ 2026-02-04  1:52 UTC (permalink / raw)
  To: Peng Fan
  Cc: Thinh Nguyen, Xu Yang, Greg Kroah-Hartman, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Frank Li, Li Jun,
	linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
	imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org

On Tue, Feb 03, 2026, Peng Fan wrote:
> On Tue, Feb 03, 2026 at 12:24:08AM +0000, Thinh Nguyen wrote:
> >On Mon, Feb 02, 2026, Xu Yang wrote:
> >> 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 to track the controller’s
> >> power state and use it throughout the suspend/resume flow.
> >> 
> >> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> >> ---
> >>  drivers/usb/dwc3/core.c | 9 +++++++--
> >>  drivers/usb/dwc3/core.h | 2 ++
> >>  drivers/usb/dwc3/glue.h | 3 +++
> >>  3 files changed, 12 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> >> index c07ffe82c85049364c38c7ba152aab0ff764d95e..9d4326da5ec7669fa714707fb24556723cab51b8 100644
> >> --- a/drivers/usb/dwc3/core.c
> >> +++ b/drivers/usb/dwc3/core.c
> >> @@ -2314,6 +2314,9 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
> >>  			goto err_exit_debugfs;
> >>  	}
> >>  
> >> +	if (data->core_may_lose_power)
> >
> >Can this be passed down as part of the dwc3_properties within the
> >probe_data? I'm trying to consolidate all the dwc3 properties to one
> >place.
> >
> >> +		dwc->may_lose_power = true;
> >> +
> >>  	pm_runtime_put(dev);
> >>  
> >>  	dma_set_max_seg_size(dev, UINT_MAX);
> >> @@ -2462,7 +2465,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->may_lose_power)) {
> >>  			dwc3_core_exit(dwc);
> >>  			break;
> >>  		}
> >> @@ -2525,7 +2529,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->may_lose_power)) {
> >>  			ret = dwc3_core_init_for_resume(dwc);
> >>  			if (ret)
> >>  				return ret;
> >> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> >> index 08cc6f2b5c23631a752c77fd7394e5876c929f0a..5b1358f36490a001bc9e68139224f7be70a57995 100644
> >> --- a/drivers/usb/dwc3/core.h
> >> +++ b/drivers/usb/dwc3/core.h
> >> @@ -1117,6 +1117,7 @@ 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
> >> + * @may_lose_power: set to indicate the core may lose power during pm suspend
> >>   * @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
> >> @@ -1369,6 +1370,7 @@ struct dwc3 {
> >>  	unsigned		usb3_lpm_capable:1;
> >>  	unsigned		usb2_lpm_disable:1;
> >>  	unsigned		usb2_gadget_lpm_disable:1;
> >> +	unsigned		may_lose_power:1;
> >
> >This name sounds like a quirk of a broken SoC.
> >
> >Perhaps rename this to something such as power_lost_on_suspend or
> >needs_full_reinit?
> 
> How about out_band_wakeup?
> 

IMHO, it's not as clear. It doesn't describe the problem or the action
to take. Can we use needs_full_reinit?

Thanks,
Thinh

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc
  2026-02-03  1:38   ` Peng Fan
@ 2026-02-04  2:27     ` Thinh Nguyen
  2026-02-04  6:30     ` Xu Yang
  1 sibling, 0 replies; 20+ messages in thread
From: Thinh Nguyen @ 2026-02-04  2:27 UTC (permalink / raw)
  To: Peng Fan
  Cc: Xu Yang, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen,
	linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
	imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org

On Tue, Feb 03, 2026, Peng Fan wrote:
> On Mon, Feb 02, 2026 at 06:27:47PM +0800, Xu Yang wrote:
> >+
> >+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
> >+	if (!res)
> >+		return dev_err_probe(dev, -ENODEV, "missing core memory resource\n");
> 
> -ENOENT should be better.

Hm... that's for file or directory, and doesn't seem to fit here well.

BR,
Thinh

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/3] dt-bindings: usb: introduce fsl,imx-dwc3
  2026-02-03  7:19   ` Alexander Stein
@ 2026-02-04  5:41     ` Xu Yang
  0 siblings, 0 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-04  5:41 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen, linux-usb,
	devicetree, imx, linux-arm-kernel, linux-kernel

On Tue, Feb 03, 2026 at 08:19:13AM +0100, Alexander Stein wrote:
> Am Montag, 2. Februar 2026, 11:27:45 CET schrieb Xu Yang:
> > The i.MX USB glue and DWC3 core are closely coupled. Describe the i.MX
> > USB block in a single block will bring more benefits than a parent-
> > child relation. The new binding is a copy of fsl,imx8mp-dwc3.yaml with
> > the needed modifications.
> > 
> > Add the common compatible string "fsl,imx-dwc3" to indicate that the
> > flattened module should be selected. This compatible is also used by
> > "select" to inform the DeviceTree validator to apply this binding.
> > 
> > To avoid redefining all the platform-specific compatibles, "select" is
> > used to tell the DeviceTree validator which binding to use solely on the
> > generic compatible.
> > 
> > Mark fsl,imx8mp-dwc3 deprecated, to favor expressing future platforms
> > using the new combined binding.
> > 
> > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> > ---
> >  .../devicetree/bindings/usb/fsl,imx-dwc3.yaml      | 131 +++++++++++++++++++++
> >  .../devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml   |  13 ++
> >  2 files changed, 144 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..bc6b9743396e8f6b698706caae71241b0512ce8b
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/usb/fsl,imx-dwc3.yaml
> > @@ -0,0 +1,131 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +# Copyright 2026 NXP
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/usb/fsl,imx-dwc3.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: NXP i.MX Soc USB Controller
> > +
> > +maintainers:
> > +  - Xu Yang <xu.yang_2@nxp.com>
> > +
> > +select:
> > +  properties:
> > +    compatible:
> > +      contains:
> > +        const: fsl,imx-dwc3
> > +  required:
> > +    - compatible
> > +
> > +properties:
> > +  compatible:
> > +    items:
> > +      - enum:
> > +          - fsl,imx95-dwc3
> > +          - fsl,imx943-dwc3
> > +          - fsl,imx8mp-dwc3
> 
> Can you please sort this? I would have expected the exact reverse ordering.

OK

> 
> > +      - const: fsl,imx-dwc3
> > +
> > +  reg:
> > +    items:
> > +      - description: DWC3 core registers.
> > +      - description: HSIO Block Control registers.
> > +      - description: Wrapper registers of dwc3 core.
> > +
> > +  reg-names:
> > +    items:
> > +      - const: core
> > +      - const: blkctl
> > +      - const: glue
> > +
> > +  interrupts:
> > +    items:
> > +      - description: DWC3 controller interrupt.
> > +      - description: Wakeup interrupt from glue logic.
> > +
> > +  interrupt-names:
> > +    items:
> > +      - const: dwc_usb3
> > +      - const: wakeup
> > +
> > +  iommus:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    items:
> > +      - description: System hsio root clock
> > +      - description: SoC Bus Clock for AHB/AXI/Native
> > +      - description: Reference clock for generating ITP when UTMI/ULPI PHY is suspended
> > +      - description: Suspend clock used for usb wakeup logic.
> > +
> > +  clock-names:
> > +    items:
> > +      - const: hsio
> > +      - const: bus_early
> > +      - const: ref
> > +      - const: suspend
> > +
> > +  fsl,permanently-attached:
> > +    type: boolean
> > +    description:
> > +      Indicates if the device attached to a downstream port is
> > +      permanently attached.
> > +
> > +  fsl,disable-port-power-control:
> > +    type: boolean
> > +    description:
> > +      Indicates whether the host controller implementation includes port
> > +      power control. Defines Bit 3 in capability register (HCCPARAMS).
> > +
> > +  fsl,over-current-active-low:
> > +    type: boolean
> > +    description:
> > +      Over current signal polarity is active low.
> > +
> > +  fsl,power-active-low:
> > +    type: boolean
> > +    description:
> > +      Power pad (PWR) polarity is active low.
> > +
> > +  power-domains:
> > +    maxItems: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +  - interrupts
> > +  - power-domains
> > +
> > +allOf:
> > +  - $ref: snps,dwc3-common.yaml#
> > +
> > +unevaluatedProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +
> > +    usb@4c100000 {
> > +      compatible = "fsl,imx943-dwc3", "fsl,imx-dwc3";
> > +      reg = <0x4c100000 0x10000>,
> > +            <0x4c010010 0x04>,
> > +            <0x4c1f0000 0x20>;
> > +      reg-names = "core", "blkctl", "glue";
> > +      clocks = <&scmi_clk 74>,    //IMX94_CLK_HSIO
> > +               <&scmi_clk 74>,    //IMX94_CLK_HSIO
> > +               <&scmi_clk 2>,     //IMX94_CLK_24M
> > +               <&scmi_clk 1>;     //IMX94_CLK_32K
> > +      clock-names = "hsio", "bus_early", "ref", "suspend";
> > +      interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>,
> > +                   <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>;
> > +      interrupt-names = "dwc_usb3", "wakeup";
> > +      power-domains = <&scmi_devpd 13>;   //IMX94_PD_HSIO_TOP
> > +      phys = <&usb3_phy>, <&usb3_phy>;
> > +      phy-names = "usb2-phy", "usb3-phy";
> > +      snps,gfladj-refclk-lpm-sel-quirk;
> > +      snps,parkmode-disable-ss-quirk;
> > +      status = "disabled";
> > +    };
> > diff --git a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
> > index 73e7a60a0060dee6417b9469251e121704b7a148..fd23c345149e0dba1ed3919a25195edf247cfc08 100644
> > --- a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
> > +++ b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
> > @@ -10,6 +10,19 @@ title: NXP iMX8MP Soc USB Controller
> >  maintainers:
> >    - Li Jun <jun.li@nxp.com>
> >  
> > +deprecated: true
> > +
> > +select:
> > +  properties:
> > +    compatible:
> > +      oneOf:
> > +        - items:
> > +            - const: fsl,imx95-dwc3
> > +            - const: fsl,imx8mp-dwc3
> 
> Same here.

It's not enum here. So the order is fixed to match:
    compatible = "fsl,imx95-dwc3", "fsl,imx8mp-dwc3";

Thanks,
Xu Yang

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/3] usb: dwc3: add may_lose_power flag
  2026-02-02 15:36   ` Frank Li
@ 2026-02-04  5:44     ` Xu Yang
  0 siblings, 0 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-04  5:44 UTC (permalink / raw)
  To: Frank Li
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Li Jun, Thinh Nguyen, linux-usb, devicetree, imx,
	linux-arm-kernel, linux-kernel

On Mon, Feb 02, 2026 at 10:36:15AM -0500, Frank Li wrote:
> On Mon, Feb 02, 2026 at 06:27:46PM +0800, Xu Yang wrote:
> > 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 to track the controller’s
> > power state and use it throughout the suspend/resume flow.
> 
> Nit: next time, wrap at pos 75 to reduce some lines.

OK.

> 
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> >
> > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/3] usb: dwc3: add may_lose_power flag
  2026-02-03  0:24   ` Thinh Nguyen
  2026-02-03  1:16     ` Peng Fan
@ 2026-02-04  5:47     ` Xu Yang
  1 sibling, 0 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-04  5:47 UTC (permalink / raw)
  To: Thinh Nguyen
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, linux-usb@vger.kernel.org,
	devicetree@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org

On Tue, Feb 03, 2026 at 12:24:08AM +0000, Thinh Nguyen wrote:
> On Mon, Feb 02, 2026, Xu Yang wrote:
> > 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 to track the controller’s
> > power state and use it throughout the suspend/resume flow.
> > 
> > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> > ---
> >  drivers/usb/dwc3/core.c | 9 +++++++--
> >  drivers/usb/dwc3/core.h | 2 ++
> >  drivers/usb/dwc3/glue.h | 3 +++
> >  3 files changed, 12 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> > index c07ffe82c85049364c38c7ba152aab0ff764d95e..9d4326da5ec7669fa714707fb24556723cab51b8 100644
> > --- a/drivers/usb/dwc3/core.c
> > +++ b/drivers/usb/dwc3/core.c
> > @@ -2314,6 +2314,9 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
> >  			goto err_exit_debugfs;
> >  	}
> >  
> > +	if (data->core_may_lose_power)
> 
> Can this be passed down as part of the dwc3_properties within the
> probe_data? I'm trying to consolidate all the dwc3 properties to one
> place.

Sure. Will do.

> 
> > +		dwc->may_lose_power = true;
> > +
> >  	pm_runtime_put(dev);
> >  
> >  	dma_set_max_seg_size(dev, UINT_MAX);
> > @@ -2462,7 +2465,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->may_lose_power)) {
> >  			dwc3_core_exit(dwc);
> >  			break;
> >  		}
> > @@ -2525,7 +2529,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->may_lose_power)) {
> >  			ret = dwc3_core_init_for_resume(dwc);
> >  			if (ret)
> >  				return ret;
> > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> > index 08cc6f2b5c23631a752c77fd7394e5876c929f0a..5b1358f36490a001bc9e68139224f7be70a57995 100644
> > --- a/drivers/usb/dwc3/core.h
> > +++ b/drivers/usb/dwc3/core.h
> > @@ -1117,6 +1117,7 @@ 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
> > + * @may_lose_power: set to indicate the core may lose power during pm suspend
> >   * @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
> > @@ -1369,6 +1370,7 @@ struct dwc3 {
> >  	unsigned		usb3_lpm_capable:1;
> >  	unsigned		usb2_lpm_disable:1;
> >  	unsigned		usb2_gadget_lpm_disable:1;
> > +	unsigned		may_lose_power:1;
> 
> This name sounds like a quirk of a broken SoC.
> 
> Perhaps rename this to something such as power_lost_on_suspend or
> needs_full_reinit?

OK. will use needs_full_reinit.

Thanks,
Xu Yang

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/3] usb: dwc3: add may_lose_power flag
  2026-02-04  1:52       ` Thinh Nguyen
@ 2026-02-04  5:55         ` Xu Yang
  0 siblings, 0 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-04  5:55 UTC (permalink / raw)
  To: Thinh Nguyen
  Cc: Peng Fan, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, linux-usb@vger.kernel.org,
	devicetree@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org

On Wed, Feb 04, 2026 at 01:52:15AM +0000, Thinh Nguyen wrote:
> On Tue, Feb 03, 2026, Peng Fan wrote:
> > On Tue, Feb 03, 2026 at 12:24:08AM +0000, Thinh Nguyen wrote:
> > >On Mon, Feb 02, 2026, Xu Yang wrote:
> > >> 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 to track the controller’s
> > >> power state and use it throughout the suspend/resume flow.
> > >> 
> > >> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> > >> ---
> > >>  drivers/usb/dwc3/core.c | 9 +++++++--
> > >>  drivers/usb/dwc3/core.h | 2 ++
> > >>  drivers/usb/dwc3/glue.h | 3 +++
> > >>  3 files changed, 12 insertions(+), 2 deletions(-)
> > >> 
> > >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> > >> index c07ffe82c85049364c38c7ba152aab0ff764d95e..9d4326da5ec7669fa714707fb24556723cab51b8 100644
> > >> --- a/drivers/usb/dwc3/core.c
> > >> +++ b/drivers/usb/dwc3/core.c
> > >> @@ -2314,6 +2314,9 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
> > >>  			goto err_exit_debugfs;
> > >>  	}
> > >>  
> > >> +	if (data->core_may_lose_power)
> > >
> > >Can this be passed down as part of the dwc3_properties within the
> > >probe_data? I'm trying to consolidate all the dwc3 properties to one
> > >place.
> > >
> > >> +		dwc->may_lose_power = true;
> > >> +
> > >>  	pm_runtime_put(dev);
> > >>  
> > >>  	dma_set_max_seg_size(dev, UINT_MAX);
> > >> @@ -2462,7 +2465,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->may_lose_power)) {
> > >>  			dwc3_core_exit(dwc);
> > >>  			break;
> > >>  		}
> > >> @@ -2525,7 +2529,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->may_lose_power)) {
> > >>  			ret = dwc3_core_init_for_resume(dwc);
> > >>  			if (ret)
> > >>  				return ret;
> > >> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> > >> index 08cc6f2b5c23631a752c77fd7394e5876c929f0a..5b1358f36490a001bc9e68139224f7be70a57995 100644
> > >> --- a/drivers/usb/dwc3/core.h
> > >> +++ b/drivers/usb/dwc3/core.h
> > >> @@ -1117,6 +1117,7 @@ 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
> > >> + * @may_lose_power: set to indicate the core may lose power during pm suspend
> > >>   * @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
> > >> @@ -1369,6 +1370,7 @@ struct dwc3 {
> > >>  	unsigned		usb3_lpm_capable:1;
> > >>  	unsigned		usb2_lpm_disable:1;
> > >>  	unsigned		usb2_gadget_lpm_disable:1;
> > >> +	unsigned		may_lose_power:1;
> > >
> > >This name sounds like a quirk of a broken SoC.
> > >
> > >Perhaps rename this to something such as power_lost_on_suspend or
> > >needs_full_reinit?
> > 
> > How about out_band_wakeup?
> > 
> 
> IMHO, it's not as clear. It doesn't describe the problem or the action
> to take. Can we use needs_full_reinit?

Thanks for the suggestion.

Agree with Thinh. And checking out_band_wakeup flag during system suspend 
implies that a wakeup event was triggered.

Sure, will user needs_full_reinit.

Thanks,
Xu Yang


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc
  2026-02-02 15:42   ` Frank Li
  2026-02-03  0:44     ` Thinh Nguyen
@ 2026-02-04  6:16     ` Xu Yang
  1 sibling, 0 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-04  6:16 UTC (permalink / raw)
  To: Frank Li
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Li Jun, Thinh Nguyen, linux-usb, devicetree, imx,
	linux-arm-kernel, linux-kernel

On Mon, Feb 02, 2026 at 10:42:33AM -0500, Frank Li wrote:
> On Mon, Feb 02, 2026 at 06:27:47PM +0800, Xu Yang wrote:
> > +
> > +static const struct property_entry dwc3_imx_properties[] = {
> > +	PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
> > +	PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
> > +	{},
> > +};
> > +
> > +static const struct software_node dwc3_imx_swnode = {
> > +	.properties = dwc3_imx_properties,
> > +};
> 
> I met similar case for layerscape dwc. because already use flatten,
> directly use probe_data pass these information to core library.

"xhci-missing-cas-quirk" and "xhci-skip-phy-init-quirk" are used by xhci
driver instead of dwc3 core driver. So they are needed here.

Thanks,
Xu Yang

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc
  2026-02-03  0:44     ` Thinh Nguyen
@ 2026-02-04  6:19       ` Xu Yang
  0 siblings, 0 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-04  6:19 UTC (permalink / raw)
  To: Thinh Nguyen
  Cc: Frank Li, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Li Jun, linux-usb@vger.kernel.org,
	devicetree@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org

On Tue, Feb 03, 2026 at 12:44:57AM +0000, Thinh Nguyen wrote:
> On Mon, Feb 02, 2026, Frank Li wrote:
> > On Mon, Feb 02, 2026 at 06:27:47PM +0800, Xu Yang wrote:
> > > To support flatten dwc3 devicetree model, introduce a new driver.
> > >
> > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> 
> Can you include additional info to describe why this was needed
> (written in your cover letter).

Sure.

> 
> Also note any new feature supported by this glue that's not currently
> available in the old driver.

OK. No new feature in this driver.

> 
> Thanks,
> Thinh
> 
> (ps. I'm thinking of creating a legacy_glues directory to start moving
> all the legacy glue drivers there)

Got it. Thanks for sharing the info.

Thanks,
Xu Yang

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc
  2026-02-03  1:38   ` Peng Fan
  2026-02-04  2:27     ` Thinh Nguyen
@ 2026-02-04  6:30     ` Xu Yang
  1 sibling, 0 replies; 20+ messages in thread
From: Xu Yang @ 2026-02-04  6:30 UTC (permalink / raw)
  To: Peng Fan
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Frank Li, Li Jun, Thinh Nguyen, linux-usb,
	devicetree, imx, linux-arm-kernel, linux-kernel

On Tue, Feb 03, 2026 at 09:38:54AM +0800, Peng Fan wrote:
> On Mon, Feb 02, 2026 at 06:27:47PM +0800, Xu Yang wrote:
> >To support flatten dwc3 devicetree model, introduce a new driver.
> >
> >Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> >---
> > drivers/usb/dwc3/Kconfig    |  12 ++
> > drivers/usb/dwc3/Makefile   |   1 +
> > drivers/usb/dwc3/dwc3-imx.c | 428 ++++++++++++++++++++++++++++++++++++++++++++
> ...
> >diff --git a/drivers/usb/dwc3/dwc3-imx.c b/drivers/usb/dwc3/dwc3-imx.c
> >new file mode 100644
> >index 0000000000000000000000000000000000000000..57b175e929d7e163df5af7e2265ab7117fa1dc9a
> >--- /dev/null
> >+++ b/drivers/usb/dwc3/dwc3-imx.c
> >@@ -0,0 +1,428 @@
> >+// SPDX-License-Identifier: GPL-2.0
> >+/*
> >+ * dwc3-imx.c - NXP i.MX Soc USB3 Specific Glue layer
> >+ *
> >+ * Copyright 2026 NXP
> >+ */
> >+
> >+#include <linux/clk.h>
> >+#include <linux/interrupt.h>
> >+#include <linux/io.h>
> >+#include <linux/kernel.h>
> >+#include <linux/module.h>
> >+#include <linux/of_platform.h>
> >+#include <linux/platform_device.h>
> >+#include <linux/pm_runtime.h>
> >+
> >+#include "core.h"
> >+#include "glue.h"
> >+
> >+/* USB wakeup registers */
> >+#define USB_WAKEUP_CTRL			0x00
> >+
> >+/* Global wakeup interrupt enable, also used to clear interrupt */
> >+#define USB_WAKEUP_EN			BIT(31)
> >+/* Wakeup from connect or disconnect, only for superspeed */
> >+#define USB_WAKEUP_SS_CONN		BIT(5)
> >+/* 0 select vbus_valid, 1 select sessvld */
> >+#define USB_WAKEUP_VBUS_SRC_SESS_VAL	BIT(4)
> >+/* Enable signal for wake up from u3 state */
> >+#define USB_WAKEUP_U3_EN		BIT(3)
> >+/* Enable signal for wake up from id change */
> >+#define USB_WAKEUP_ID_EN		BIT(2)
> >+/* Enable signal for wake up from vbus change */
> >+#define	USB_WAKEUP_VBUS_EN		BIT(1)
> >+/* Enable signal for wake up from dp/dm change */
> >+#define USB_WAKEUP_DPDM_EN		BIT(0)
> >+
> >+#define USB_WAKEUP_EN_MASK		GENMASK(5, 0)
> >+
> >+/* USB glue registers */
> >+#define USB_CTRL0		0x00
> >+#define USB_CTRL1		0x04
> >+
> >+#define USB_CTRL0_PORTPWR_EN	BIT(12) /* 1 - PPC enabled (default) */
> >+#define USB_CTRL0_USB3_FIXED	BIT(22) /* 1 - USB3 permanent attached */
> >+#define USB_CTRL0_USB2_FIXED	BIT(23) /* 1 - USB2 permanent attached */
> >+
> >+#define USB_CTRL1_OC_POLARITY	BIT(16) /* 0 - HIGH / 1 - LOW */
> >+#define USB_CTRL1_PWR_POLARITY	BIT(17) /* 0 - HIGH / 1 - LOW */
> >+
> >+struct dwc3_imx {
> >+	struct dwc3	dwc;
> >+	struct device	*dev;
> >+	void __iomem	*blkctl_base;
> >+	void __iomem	*glue_base;
> >+	struct clk	*hsio_clk;
> >+	struct clk	*suspend_clk;
> >+	int		irq;
> >+	bool		pm_suspended;
> >+	bool		wakeup_pending;
> >+};
> >+
> >+#define to_dwc3_imx(d) container_of((d), struct dwc3_imx, dwc)
> >+
> >+static void dwc3_imx_configure_glue(struct dwc3_imx *dwc_imx)
> >+{
> >+	struct device *dev = dwc_imx->dev;
> >+	u32 value;
> >+
> >+	if (!dwc_imx->glue_base)
> >+		return;
> >+
> >+	value = readl(dwc_imx->glue_base + USB_CTRL0);
> >+
> >+	if (device_property_read_bool(dev, "fsl,permanently-attached"))
> >+		value |= (USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
> 
> No need parentheses.

OK.

> 
> >+	else
> >+		value &= ~(USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
> >+
> >+	if (device_property_read_bool(dev, "fsl,disable-port-power-control"))
> >+		value &= ~(USB_CTRL0_PORTPWR_EN);
> 
> Ditto.

OK.

> 
> >+	else
> >+		value |= USB_CTRL0_PORTPWR_EN;
> >+
> >+	writel(value, dwc_imx->glue_base + USB_CTRL0);
> >+
> >+	value = readl(dwc_imx->glue_base + USB_CTRL1);
> >+	if (device_property_read_bool(dev, "fsl,over-current-active-low"))
> >+		value |= USB_CTRL1_OC_POLARITY;
> >+	else
> >+		value &= ~USB_CTRL1_OC_POLARITY;
> >+
> >+	if (device_property_read_bool(dev, "fsl,power-active-low"))
> >+		value |= USB_CTRL1_PWR_POLARITY;
> >+	else
> >+		value &= ~USB_CTRL1_PWR_POLARITY;
> >+
> >+	writel(value, dwc_imx->glue_base + USB_CTRL1);
> >+}
> >+
> >+static void dwc3_imx_wakeup_enable(struct dwc3_imx *dwc_imx, pm_message_t msg)
> >+{
> >+	struct dwc3	*dwc = &dwc_imx->dwc;
> >+	u32		val;
> 
> In dwc3_imx_configure_glue, space is used. while here, tab is used.

OK.

> 
> >+
> >+	val = readl(dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
> >+
> >+	if ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc->xhci) {
> >+		val |= USB_WAKEUP_EN | USB_WAKEUP_DPDM_EN;
> >+		if (PMSG_IS_AUTO(msg))
> >+			val |= USB_WAKEUP_SS_CONN | USB_WAKEUP_U3_EN;
> >+	} else {
> >+		val |= USB_WAKEUP_EN | USB_WAKEUP_VBUS_EN |
> >+		       USB_WAKEUP_VBUS_SRC_SESS_VAL;
> >+	}
> >+
> >+	writel(val, dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
> >+}
> >+
> >+static void dwc3_imx_wakeup_disable(struct dwc3_imx *dwc_imx)
> >+{
> >+	u32	val;
> 
> Ditto.
> 
> >+
> >+	val = readl(dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
> >+	val &= ~(USB_WAKEUP_EN | USB_WAKEUP_EN_MASK);
> >+	writel(val, dwc_imx->blkctl_base + USB_WAKEUP_CTRL);
> >+}
> >+
> >+static irqreturn_t dwc3_imx_interrupt(int irq, void *data)
> >+{
> >+	struct dwc3_imx		*dwc_imx = data;
> >+	struct dwc3		*dwc = &dwc_imx->dwc;
> 
> Ditto.
> 
> >+
> >+	if (!dwc_imx->pm_suspended)
> >+		return IRQ_HANDLED;
> >+
> >+	disable_irq_nosync(dwc_imx->irq);
> >+	dwc_imx->wakeup_pending = true;
> >+
> >+	if ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc->xhci)
> >+		pm_runtime_resume(&dwc->xhci->dev);
> >+	else if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE)
> >+		pm_runtime_get(dwc->dev);
> >+
> >+	return IRQ_HANDLED;
> >+}
> >+
> >+static void dwc3_imx_pre_set_role(struct dwc3 *dwc, enum usb_role role)
> >+{
> >+	if (role == USB_ROLE_HOST)
> >+		/*
> >+		 * For xhci host, we need disable dwc core auto
> >+		 * suspend, because during this auto suspend delay(5s),
> >+		 * xhci host RUN_STOP is cleared and wakeup is not
> >+		 * enabled, if device is inserted, xhci host can't
> >+		 * response the connection.
> >+		 */
> >+		pm_runtime_dont_use_autosuspend(dwc->dev);
> >+	else
> >+		pm_runtime_use_autosuspend(dwc->dev);
> >+}
> >+
> >+static struct dwc3_glue_ops dwc3_imx_glue_ops = {
> >+	.pre_set_role   = dwc3_imx_pre_set_role,
> >+};
> >+
> >+static const struct property_entry dwc3_imx_properties[] = {
> >+	PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
> >+	PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
> >+	{},
> >+};
> >+
> >+static const struct software_node dwc3_imx_swnode = {
> >+	.properties = dwc3_imx_properties,
> >+};
> >+
> >+static int dwc3_imx_probe(struct platform_device *pdev)
> >+{
> >+	struct device		*dev = &pdev->dev;
> >+	struct dwc3_imx		*dwc_imx;
> >+	struct dwc3		*dwc;
> >+	struct resource		*res;
> >+	const char		*irq_name;
> >+	struct dwc3_probe_data	probe_data = {};
> >+	int			ret, irq;
> 
> As written above, unify the format.
> 
> >+
> >+	dwc_imx = devm_kzalloc(dev, sizeof(*dwc_imx), GFP_KERNEL);
> >+	if (!dwc_imx)
> >+		return -ENOMEM;
> >+
> >+	platform_set_drvdata(pdev, dwc_imx);
> >+	dwc_imx->dev = dev;
> >+
> >+	dwc_imx->blkctl_base = devm_platform_ioremap_resource_byname(pdev, "blkctl");
> >+	if (IS_ERR(dwc_imx->blkctl_base))
> >+		return PTR_ERR(dwc_imx->blkctl_base);
> >+
> >+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "glue");
> >+	if (!res) {
> >+		dev_warn(dev, "Base address for glue layer missing\n");
> >+	} else {
> >+		dwc_imx->glue_base = devm_ioremap_resource(dev, res);
> >+		if (IS_ERR(dwc_imx->glue_base))
> >+			return PTR_ERR(dwc_imx->glue_base);
> >+	}
> >+
> >+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
> >+	if (!res)
> >+		return dev_err_probe(dev, -ENODEV, "missing core memory resource\n");
> 
> -ENOENT should be better.

As Thinh's comment, will keep ENODEV.

> 
> >+
> >+	dwc_imx->hsio_clk = devm_clk_get_enabled(dev, "hsio");
> >+	if (IS_ERR(dwc_imx->hsio_clk))
> >+		return dev_err_probe(dev, PTR_ERR(dwc_imx->hsio_clk),
> >+				     "Failed to get hsio clk\n");
> >+
> >+	dwc_imx->suspend_clk = devm_clk_get_enabled(dev, "suspend");
> >+	if (IS_ERR(dwc_imx->suspend_clk))
> >+		return dev_err_probe(dev, PTR_ERR(dwc_imx->suspend_clk),
> >+				     "Failed to get suspend clk\n");
> >+
> >+	irq = platform_get_irq_byname(pdev, "wakeup");
> >+	if (irq < 0)
> >+		return irq;
> >+	dwc_imx->irq = irq;
> >+
> >+	irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s:wakeup", dev_name(dev));
> >+	if (!irq_name)
> >+		return dev_err_probe(dev, -ENOMEM, "failed to create irq_name\n");
> >+
> >+	ret = devm_request_threaded_irq(dev, irq, NULL, dwc3_imx_interrupt,
> >+					IRQF_ONESHOT, irq_name, dwc_imx);
> >+	if (ret)
> >+		return dev_err_probe(dev, ret, "failed to request IRQ #%d\n", irq);
> 
> Should this be moved to end after all are initialized?

Thanks for the suggestion.

I prefer to setup all glue layer setting before initialize core parts. So
the logic will be a bit clear. To avoid accident, I will disable wakeup
irq by default and enable it during system suspend. So IRQF_NO_AUTOEN
will be added in v2.

> 
> >+
> >+	ret = device_add_software_node(dev, &dwc3_imx_swnode);
> >+	if (ret)
> >+		return dev_err_probe(dev, ret, "failed to add software node\n");
> >+
> >+	dwc = &dwc_imx->dwc;
> >+	dwc->dev = dev;
> >+	dwc->glue_ops = &dwc3_imx_glue_ops;
> >+
> >+	probe_data.res = res;
> >+	probe_data.dwc = dwc;
> >+	probe_data.core_may_lose_power = true;
> >+
> >+	ret = dwc3_core_probe(&probe_data);
> >+	if (ret) {
> >+		device_remove_software_node(dev);
> >+		return ret;
> >+	}
> >+
> >+	device_set_wakeup_capable(dev, true);
> >+	return 0;
> >+}
> >+
> >+static void dwc3_imx_remove(struct platform_device *pdev)
> >+{
> >+	struct device	*dev = &pdev->dev;
> >+	struct dwc3	*dwc = dev_get_drvdata(dev);
> >+
> >+	if (pm_runtime_resume_and_get(dev) < 0)
> 
> print a error message.
> 
> when this fail return, there is no chance to probe success again I think,
> because resource not freed.

I just double check the driver logic here, dwc3_core_remove() will do all
above pm_runtime_* things. So these runtime PM operations are redundent
here. I will remove them in v2.

Thanks,
Xu Yang

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2026-02-04  6:37 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-02 10:27 [PATCH 0/3] add DWC3 i.MX driver based on flatten devicetree Xu Yang
2026-02-02 10:27 ` [PATCH 1/3] dt-bindings: usb: introduce fsl,imx-dwc3 Xu Yang
2026-02-03  7:19   ` Alexander Stein
2026-02-04  5:41     ` Xu Yang
2026-02-02 10:27 ` [PATCH 2/3] usb: dwc3: add may_lose_power flag Xu Yang
2026-02-02 15:36   ` Frank Li
2026-02-04  5:44     ` Xu Yang
2026-02-03  0:24   ` Thinh Nguyen
2026-02-03  1:16     ` Peng Fan
2026-02-04  1:52       ` Thinh Nguyen
2026-02-04  5:55         ` Xu Yang
2026-02-04  5:47     ` Xu Yang
2026-02-02 10:27 ` [PATCH 3/3] usb: dwc3: introduce flatten model driver of i.MX Soc Xu Yang
2026-02-02 15:42   ` Frank Li
2026-02-03  0:44     ` Thinh Nguyen
2026-02-04  6:19       ` Xu Yang
2026-02-04  6:16     ` Xu Yang
2026-02-03  1:38   ` Peng Fan
2026-02-04  2:27     ` Thinh Nguyen
2026-02-04  6:30     ` Xu Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox