public inbox for devicetree@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support
@ 2026-01-26 23:38 Elson Serrao
  2026-01-26 23:38 ` [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware Elson Serrao
                   ` (8 more replies)
  0 siblings, 9 replies; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

The Embedded USB Debugger (EUD) is a High-Speed USB on-chip hub that
provides debug and trace capabilities on Qualcomm platforms. The current
EUD driver, however, lacks essential hardware resources such as PHY
references and support for multi-port configurations. This series
addresses those gaps and introduces the necessary device tree updates
to enable testing and validation of the enhanced functionality.

This work builds upon an earlier EUD driver submission:
https://lore.kernel.org/all/20240730222439.3469-1-quic_eserrao@quicinc.com/
and extends it with support for multi-port use cases and proper handling
of EUD operation across different USB roles.

The series has been validated on the Qualcomm Dragonwing Q6 platform
(RB3 Gen2 board), confirming successful OpenOCD connectivity to the EUD
interface. For detailed usage instructions, refer to Qualcomm’s Linux
kernel debugging guide:
https://docs.qualcomm.com/bundle/publicresource/topics/80-70020-12/debugging_linux_kernel.html#debug-using-openocd

---
Changes in v2:
- Improved commit message of patch 0001 and 0003 with historical context
  on why EUD worked without PHY references on single-path systems.
  Expanded the usb-role-switch property description in the bindings file.
- Link to v1: https://lore.kernel.org/all/20260116232106.2234978-1-elson.serrao@oss.qualcomm.com/
---

Elson Serrao (9):
  dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware
  usb: misc: qcom_eud: add sysfs attribute for port selection
  usb: misc: qcom_eud: add per-path High-Speed PHY control
  usb: misc: qcom_eud: add per-path role switch support
  usb: misc: qcom_eud: improve enable_store API
  usb: misc: qcom_eud: add host mode coordination
  usb: misc: qcom_eud: fix virtual attach/detach event handling
  arm64: dts: qcom: kodiak: Align EUD node with binding
  arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality

 Documentation/ABI/testing/sysfs-driver-eud    |  16 +
 .../bindings/soc/qcom/qcom,eud.yaml           | 100 +++--
 arch/arm64/boot/dts/qcom/kodiak.dtsi          |  33 +-
 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts  |  20 +-
 drivers/usb/misc/qcom_eud.c                   | 365 +++++++++++++++++-
 5 files changed, 477 insertions(+), 57 deletions(-)

-- 
2.34.1

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

* [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-02-03 13:35   ` Konrad Dybcio
                     ` (2 more replies)
  2026-01-26 23:38 ` [PATCH v2 2/9] usb: misc: qcom_eud: add sysfs attribute for port selection Elson Serrao
                   ` (7 subsequent siblings)
  8 siblings, 3 replies; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

The Qualcomm Embedded USB Debugger (EUD) can intercept one or two
independent High-Speed UTMI paths, depending on the SoC. Each path is
distinct with its own HS-PHY interface, connector/controller wiring, and
UTMI routing behavior. The EUD hardware sits between the USB2 PHY and
the USB controller on each path.

The existing binding models only a single UTMI path and does not provide
a way to associate the required High-Speed USB PHY. EUD relies on the
HS-PHY on the selected UTMI path for link signalling and correct operation
of the hardware.

Historically, EUD has worked on platforms that use a single UTMI path
because the USB controller maintains ownership of the PHY during
enumeration and normal operation. This implicit relationship allowed
EUD to function even though the dependency on the PHY was not described
in the binding. However, this behavior is not guaranteed by hardware.
The current binding description is not sufficient for SoCs that expose
two independent UTMI paths, where the PHY association and port wiring
must be explicitly described.

Introduce per-path eud-path child nodes so each UTMI path can describe
its HS-PHY, port connections, and the role‑switching capability of its
associated USB port.

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 .../bindings/soc/qcom/qcom,eud.yaml           | 100 +++++++++++++-----
 1 file changed, 74 insertions(+), 26 deletions(-)

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml
index 84218636c0d8..0507252dbf27 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml
@@ -10,8 +10,11 @@ maintainers:
   - Souradeep Chowdhury <quic_schowdhu@quicinc.com>
 
 description:
-  This binding is used to describe the Qualcomm Embedded USB Debugger, which is
-  mini USB-hub implemented on chip to support USB-based debug capabilities.
+  This binding describes the Qualcomm Embedded USB Debugger (EUD), an on-chip
+  mini USB hub that enables USB-based debug capabilities. The EUD block is
+  positioned between the High-Speed USB PHY and the USB controller, where it
+  intercepts the UTMI interface to support debug and bypass modes. EUD can be
+  supported on up to two High-Speed USB ports.
 
 properties:
   compatible:
@@ -29,26 +32,62 @@ properties:
     description: EUD interrupt
     maxItems: 1
 
-  ports:
-    $ref: /schemas/graph.yaml#/properties/ports
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+patternProperties:
+  "^eud-path@[0-1]$":
+    type: object
     description:
-      These ports is to be attached to the endpoint of the DWC3 controller node
-      and type C connector node. The controller has the "usb-role-switch"
-      property.
+      Represents one High-Speed UTMI path that EUD intercepts. This node models
+      the physical data path intercepted by EUD and provides graph endpoints to
+      link the USB controller and the external connector associated with this path.
 
     properties:
-      port@0:
-        $ref: /schemas/graph.yaml#/properties/port
-        description: This port is to be attached to the DWC3 controller.
+      reg:
+        maxItems: 1
+        description: Path number
+
+      phys:
+        maxItems: 1
+        description: High-Speed USB PHY associated with this data path.
+
+      usb-role-switch:
+        type: boolean
+        description:
+          Set this property if the USB port on this path is role switch capable.
+          In device role, debug mode inserts the EUD hub into the UTMI path. In
+          host role, the EUD hub is bypassed and UTMI traffic flows directly
+          between the PHY and the USB controller.
+
+      ports:
+        $ref: /schemas/graph.yaml#/properties/ports
+        description:
+          These ports are to be attached to the endpoint of the USB controller node
+          and USB connector node.
+
+        properties:
+          port@0:
+            $ref: /schemas/graph.yaml#/properties/port
+            description: This port is to be attached to the USB controller.
 
-      port@1:
-        $ref: /schemas/graph.yaml#/properties/port
-        description: This port is to be attached to the type C connector.
+          port@1:
+            $ref: /schemas/graph.yaml#/properties/port
+            description: This port is to be attached to the USB connector.
+
+    required:
+      - reg
+      - phys
+      - ports
+
+    additionalProperties: false
 
 required:
   - compatible
   - reg
-  - ports
 
 additionalProperties: false
 
@@ -58,21 +97,30 @@ examples:
         compatible = "qcom,sc7280-eud", "qcom,eud";
         reg = <0x88e0000 0x2000>,
               <0x88e2000 0x1000>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        eud-path@0 {
+            reg = <0>;
+            phys = <&usb_1_hsphy>;
+            usb-role-switch;
 
-        ports {
-            #address-cells = <1>;
-            #size-cells = <0>;
-            port@0 {
-                reg = <0>;
-                eud_ep: endpoint {
-                    remote-endpoint = <&usb2_role_switch>;
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@0 {
+                    reg = <0>;
+                    eud_ep: endpoint {
+                        remote-endpoint = <&usb2_role_switch>;
+                    };
                 };
-            };
 
-            port@1 {
-                reg = <1>;
-                eud_con: endpoint {
-                    remote-endpoint = <&con_eud>;
+                port@1 {
+                    reg = <1>;
+                    eud_con: endpoint {
+                        remote-endpoint = <&con_eud>;
+                    };
                 };
             };
         };
-- 
2.34.1


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

* [PATCH v2 2/9] usb: misc: qcom_eud: add sysfs attribute for port selection
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
  2026-01-26 23:38 ` [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-01-27 13:31   ` Konrad Dybcio
  2026-01-26 23:38 ` [PATCH v2 3/9] usb: misc: qcom_eud: add per-path High-Speed PHY control Elson Serrao
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

EUD can be mapped to either the primary USB port or the secondary USB port
depending on the value of the EUD_PORT_SEL register. Add a 'port' sysfs
attribute to allow userspace to select which port EUD should operate on
and update the ABI documentation. This is needed for systems with dual
USB ports where EUD needs to be accessible on either port depending on the
system configuration and use case.

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 Documentation/ABI/testing/sysfs-driver-eud | 16 ++++++++
 drivers/usb/misc/qcom_eud.c                | 43 ++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-eud b/Documentation/ABI/testing/sysfs-driver-eud
index 2bab0db2d2f0..67223f73ee60 100644
--- a/Documentation/ABI/testing/sysfs-driver-eud
+++ b/Documentation/ABI/testing/sysfs-driver-eud
@@ -7,3 +7,19 @@ Description:
 		EUD based on a 1 or a 0 value. By enabling EUD,
 		the user is able to activate the mini-usb hub of
 		EUD for debug and trace capabilities.
+
+What:		/sys/bus/platform/drivers/qcom_eud/.../port
+Date:		January 2026
+Contact:	Elson Serrao <elson.serrao@oss.qualcomm.com>
+Description:
+		Selects which USB port the Embedded USB Debugger (EUD)
+		is mapped to on platforms providing multiple High-Speed
+		USB ports.
+
+		Valid values:
+		  0 - Primary USB port
+		  1 - Secondary USB port
+
+		The attribute is writable only while EUD is disabled.
+		Reading the attribute returns the currently selected
+		USB port number.
diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index 926419ca560f..1a136f8f1ae5 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -23,8 +23,11 @@
 #define EUD_REG_VBUS_INT_CLR	0x0080
 #define EUD_REG_CSR_EUD_EN	0x1014
 #define EUD_REG_SW_ATTACH_DET	0x1018
+#define EUD_REG_PORT_SEL	0x1028
 #define EUD_REG_EUD_EN2		0x0000
 
+#define EUD_MAX_PORTS		2
+
 #define EUD_ENABLE		BIT(0)
 #define EUD_INT_PET_EUD		BIT(0)
 #define EUD_INT_VBUS		BIT(2)
@@ -40,6 +43,7 @@ struct eud_chip {
 	int				irq;
 	bool				enabled;
 	bool				usb_attached;
+	u8				port_idx;
 };
 
 static int enable_eud(struct eud_chip *priv)
@@ -104,8 +108,47 @@ static ssize_t enable_store(struct device *dev,
 
 static DEVICE_ATTR_RW(enable);
 
+static ssize_t port_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct eud_chip *chip = dev_get_drvdata(dev);
+
+	return sysfs_emit(buf, "%u\n", chip->port_idx);
+}
+
+static ssize_t port_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct eud_chip *chip = dev_get_drvdata(dev);
+	u8 port;
+	int ret;
+
+	ret = kstrtou8(buf, 0, &port);
+	if (ret)
+		return ret;
+
+	/* Only port 0 and port 1 are valid */
+	if (port >= EUD_MAX_PORTS)
+		return -EINVAL;
+
+	/* Port selection must be done before enabling EUD */
+	if (chip->enabled) {
+		dev_err(chip->dev, "Cannot change port while EUD is enabled\n");
+		return -EBUSY;
+	}
+
+	writel(port, chip->base + EUD_REG_PORT_SEL);
+	chip->port_idx = port;
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(port);
+
 static struct attribute *eud_attrs[] = {
 	&dev_attr_enable.attr,
+	&dev_attr_port.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(eud);
-- 
2.34.1


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

* [PATCH v2 3/9] usb: misc: qcom_eud: add per-path High-Speed PHY control
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
  2026-01-26 23:38 ` [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware Elson Serrao
  2026-01-26 23:38 ` [PATCH v2 2/9] usb: misc: qcom_eud: add sysfs attribute for port selection Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-02-04 13:21   ` Konrad Dybcio
  2026-01-26 23:38 ` [PATCH v2 4/9] usb: misc: qcom_eud: add per-path role switch support Elson Serrao
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

EUD hardware can support multiple High-Speed USB paths, each routed
through its own PHY. The active path is selected in hardware via the
EUD_PORT_SEL register. As a High-Speed hub, EUD requires access to the
High-Speed PHY associated with the active UTMI path. To support this
multi-path capability, the driver must manage PHY resources on a per-path
basis, ensuring that the PHY for the currently selected path is properly
initialized and powered.

This patch restructures the driver to implement per-path PHY management.
The driver now powers the appropriate PHY based on the selected and
enabled UTMI path, ensuring correct operation when EUD is enabled.

Supporting this requires describing the available UTMI paths and their
corresponding PHYs in Device Tree. This updates DT requirements and is
not backward compatible with older DTs that lacked this description.
Historically, EUD appeared to work on single-path systems because the
USB controller kept the PHY initialized. However, EUD is designed to
operate independently of the USB controller and therefore requires
explicit PHY control.

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 drivers/usb/misc/qcom_eud.c | 130 +++++++++++++++++++++++++++++++++++-
 1 file changed, 129 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index 1a136f8f1ae5..5cebb64f4a67 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
@@ -34,26 +35,96 @@
 #define EUD_INT_SAFE_MODE	BIT(4)
 #define EUD_INT_ALL		(EUD_INT_VBUS | EUD_INT_SAFE_MODE)
 
+struct eud_path {
+	struct eud_chip		*chip;
+	struct phy		*phy;
+	u8			num;
+};
+
 struct eud_chip {
 	struct device			*dev;
 	struct usb_role_switch		*role_sw;
 	void __iomem			*base;
+	struct eud_path			*paths[EUD_MAX_PORTS];
 	phys_addr_t			mode_mgr;
 	unsigned int			int_status;
 	int				irq;
 	bool				enabled;
 	bool				usb_attached;
+	bool				phy_enabled;
 	u8				port_idx;
 };
 
+static int eud_phy_enable(struct eud_chip *chip)
+{
+	struct eud_path *path;
+	struct phy *phy;
+	int ret;
+
+	if (chip->phy_enabled)
+		return 0;
+
+	path = chip->paths[chip->port_idx];
+	if (!path || !path->phy) {
+		dev_err(chip->dev, "No PHY configured for port %u\n", chip->port_idx);
+		return -ENODEV;
+	}
+
+	phy = path->phy;
+
+	ret = phy_init(phy);
+	if (ret) {
+		dev_err(chip->dev, "Failed to initialize USB2 PHY for port %u: %d\n",
+			chip->port_idx, ret);
+		return ret;
+	}
+
+	ret = phy_power_on(phy);
+	if (ret) {
+		dev_err(chip->dev, "Failed to power on USB2 PHY for port %u: %d\n",
+			chip->port_idx, ret);
+		phy_exit(phy);
+		return ret;
+	}
+
+	chip->phy_enabled = true;
+
+	return 0;
+}
+
+static void eud_phy_disable(struct eud_chip *chip)
+{
+	struct eud_path *path;
+	struct phy *phy;
+
+	if (!chip->phy_enabled)
+		return;
+
+	path = chip->paths[chip->port_idx];
+	if (!path || !path->phy)
+		return;
+
+	phy = path->phy;
+
+	phy_power_off(phy);
+	phy_exit(phy);
+	chip->phy_enabled = false;
+}
+
 static int enable_eud(struct eud_chip *priv)
 {
 	int ret;
 
-	ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1);
+	ret = eud_phy_enable(priv);
 	if (ret)
 		return ret;
 
+	ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1);
+	if (ret) {
+		eud_phy_disable(priv);
+		return ret;
+	}
+
 	writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN);
 	writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE,
 			priv->base + EUD_REG_INT1_EN_MASK);
@@ -70,6 +141,8 @@ static int disable_eud(struct eud_chip *priv)
 		return ret;
 
 	writel(0, priv->base + EUD_REG_CSR_EUD_EN);
+	eud_phy_disable(priv);
+
 	return 0;
 }
 
@@ -132,6 +205,12 @@ static ssize_t port_store(struct device *dev,
 	if (port >= EUD_MAX_PORTS)
 		return -EINVAL;
 
+	/* Check if the corresponding path is available */
+	if (!chip->paths[port]) {
+		dev_err(chip->dev, "EUD not supported on selected port\n");
+		return -EOPNOTSUPP;
+	}
+
 	/* Port selection must be done before enabling EUD */
 	if (chip->enabled) {
 		dev_err(chip->dev, "Cannot change port while EUD is enabled\n");
@@ -231,8 +310,45 @@ static void eud_role_switch_release(void *data)
 	usb_role_switch_put(chip->role_sw);
 }
 
+static int eud_init_path(struct eud_chip *chip, struct device_node *np)
+{
+	struct eud_path *path;
+	u32 path_num;
+	int ret;
+
+	ret = of_property_read_u32(np, "reg", &path_num);
+	if (ret) {
+		dev_err(chip->dev, "Missing 'reg' property in path node\n");
+		return ret;
+	}
+
+	if (path_num >= EUD_MAX_PORTS) {
+		dev_err(chip->dev, "Invalid path number: %u (max %d)\n",
+			path_num, EUD_MAX_PORTS - 1);
+		return -EINVAL;
+	}
+
+	path = devm_kzalloc(chip->dev, sizeof(*path), GFP_KERNEL);
+	if (!path)
+		return -ENOMEM;
+
+	path->chip = chip;
+	path->num = path_num;
+
+	path->phy = devm_of_phy_get(chip->dev, np, NULL);
+	if (IS_ERR(path->phy))
+		return dev_err_probe(chip->dev, PTR_ERR(path->phy),
+				     "Failed to get PHY for path %d\n", path_num);
+
+	chip->paths[path_num] = path;
+
+	return 0;
+}
+
 static int eud_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
 	struct eud_chip *chip;
 	struct resource *res;
 	int ret;
@@ -252,6 +368,18 @@ static int eud_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	for_each_child_of_node(np, child) {
+		ret = eud_init_path(chip, child);
+		if (ret) {
+			of_node_put(child);
+			return ret;
+		}
+	}
+
+	/* Primary path is mandatory. Secondary is optional */
+	if (!chip->paths[0])
+		return -ENODEV;
+
 	chip->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(chip->base))
 		return PTR_ERR(chip->base);
-- 
2.34.1


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

* [PATCH v2 4/9] usb: misc: qcom_eud: add per-path role switch support
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
                   ` (2 preceding siblings ...)
  2026-01-26 23:38 ` [PATCH v2 3/9] usb: misc: qcom_eud: add per-path High-Speed PHY control Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-01-26 23:38 ` [PATCH v2 5/9] usb: misc: qcom_eud: improve enable_store API Elson Serrao
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

The EUD hardware can support multiple High-Speed USB paths, each connected
to different USB controllers. The current implementation uses a single
chip-level role switch, which cannot properly handle multi-path
configurations where each path needs independent role management. Since
EUD is physically present between the USB connector and the controller,
it should also relay the role change requests from the connector.

Restructure the driver to support per-path role switches and remove the
chip-level role switch. Additionally, as EUD need not modify the USB
role upon enabling, remove the unnecessary role switch call from
enable_eud().

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 drivers/usb/misc/qcom_eud.c | 80 ++++++++++++++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index 5cebb64f4a67..a58022f50484 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -38,12 +38,15 @@
 struct eud_path {
 	struct eud_chip		*chip;
 	struct phy		*phy;
+	struct usb_role_switch	*controller_sw;
+	struct usb_role_switch	*eud_sw;
+	enum usb_role		curr_role;
+	char			name[16];
 	u8			num;
 };
 
 struct eud_chip {
 	struct device			*dev;
-	struct usb_role_switch		*role_sw;
 	void __iomem			*base;
 	struct eud_path			*paths[EUD_MAX_PORTS];
 	phys_addr_t			mode_mgr;
@@ -129,7 +132,7 @@ static int enable_eud(struct eud_chip *priv)
 	writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE,
 			priv->base + EUD_REG_INT1_EN_MASK);
 
-	return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE);
+	return 0;
 }
 
 static int disable_eud(struct eud_chip *priv)
@@ -287,15 +290,21 @@ static irqreturn_t handle_eud_irq(int irq, void *data)
 static irqreturn_t handle_eud_irq_thread(int irq, void *data)
 {
 	struct eud_chip *chip = data;
+	struct eud_path *path;
 	int ret;
 
+	path = chip->paths[chip->port_idx];
+	if (!path || !path->controller_sw)
+		goto clear_irq;
+
 	if (chip->usb_attached)
-		ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE);
+		ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE);
 	else
-		ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST);
+		ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST);
 	if (ret)
 		dev_err(chip->dev, "failed to set role switch\n");
 
+clear_irq:
 	/* set and clear vbus_int_clr[0] to clear interrupt */
 	writel(BIT(0), chip->base + EUD_REG_VBUS_INT_CLR);
 	writel(0, chip->base + EUD_REG_VBUS_INT_CLR);
@@ -303,15 +312,45 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role)
+{
+	struct eud_path *path = usb_role_switch_get_drvdata(sw);
+	int ret;
+
+	/* Forward the role request to the USB controller */
+	ret = usb_role_switch_set_role(path->controller_sw, role);
+	if (ret) {
+		dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n",
+			usb_role_string(role), path->num, ret);
+		return ret;
+	}
+
+	path->curr_role = role;
+
+	return 0;
+}
+
 static void eud_role_switch_release(void *data)
 {
 	struct eud_chip *chip = data;
+	int i;
 
-	usb_role_switch_put(chip->role_sw);
+	for (i = 0; i < EUD_MAX_PORTS; i++) {
+		struct eud_path *path = chip->paths[i];
+
+		if (!path)
+			continue;
+
+		if (path->eud_sw)
+			usb_role_switch_unregister(path->eud_sw);
+		if (path->controller_sw)
+			usb_role_switch_put(path->controller_sw);
+	}
 }
 
 static int eud_init_path(struct eud_chip *chip, struct device_node *np)
 {
+	struct usb_role_switch_desc role_sw_desc = {};
 	struct eud_path *path;
 	u32 path_num;
 	int ret;
@@ -342,6 +381,32 @@ static int eud_init_path(struct eud_chip *chip, struct device_node *np)
 
 	chip->paths[path_num] = path;
 
+	path->curr_role = USB_ROLE_NONE;
+
+	if (!of_property_read_bool(np, "usb-role-switch"))
+		return 0;
+
+	/* Fetch the USB controller's role switch */
+	path->controller_sw = fwnode_usb_role_switch_get(of_fwnode_handle(np));
+	if (IS_ERR(path->controller_sw))
+		return dev_err_probe(chip->dev, PTR_ERR(path->controller_sw),
+				     "Failed to get controller role switch for path %d\n",
+				     path_num);
+
+	/* Create a role switch */
+	role_sw_desc.fwnode = of_fwnode_handle(np);
+	role_sw_desc.set = eud_role_switch_set;
+	role_sw_desc.driver_data = path;
+	snprintf(path->name, sizeof(path->name), "eud-path%u", path_num);
+	role_sw_desc.name = path->name;
+
+	path->eud_sw = usb_role_switch_register(chip->dev, &role_sw_desc);
+	if (IS_ERR(path->eud_sw)) {
+		dev_err(chip->dev, "Failed to register EUD role switch for path %d: %ld\n",
+			path_num, PTR_ERR(path->eud_sw));
+		return PTR_ERR(path->eud_sw);
+	}
+
 	return 0;
 }
 
@@ -359,11 +424,6 @@ static int eud_probe(struct platform_device *pdev)
 
 	chip->dev = &pdev->dev;
 
-	chip->role_sw = usb_role_switch_get(&pdev->dev);
-	if (IS_ERR(chip->role_sw))
-		return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw),
-					"failed to get role switch\n");
-
 	ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip);
 	if (ret)
 		return ret;
-- 
2.34.1


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

* [PATCH v2 5/9] usb: misc: qcom_eud: improve enable_store API
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
                   ` (3 preceding siblings ...)
  2026-01-26 23:38 ` [PATCH v2 4/9] usb: misc: qcom_eud: add per-path role switch support Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-02-04 13:24   ` Konrad Dybcio
  2026-01-26 23:38 ` [PATCH v2 6/9] usb: misc: qcom_eud: add host mode coordination Elson Serrao
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

Currently enable_store() allows operations irrespective of the EUD state,
which can result in redundant operations. Avoid this by adding duplicate
state checks to skip requests when EUD is already in the desired state.
Additionally, improve error handling with explicit logging to provide
better feedback.

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 drivers/usb/misc/qcom_eud.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index a58022f50484..0ea6491f963c 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -168,18 +168,27 @@ static ssize_t enable_store(struct device *dev,
 	if (kstrtobool(buf, &enable))
 		return -EINVAL;
 
+	/* Skip operation if already in desired state */
+	if (chip->enabled == enable)
+		return count;
+
 	if (enable) {
 		ret = enable_eud(chip);
-		if (!ret)
-			chip->enabled = enable;
-		else
-			disable_eud(chip);
-
+		if (ret) {
+			dev_err(chip->dev, "failed to enable eud\n");
+			return ret;
+		}
 	} else {
 		ret = disable_eud(chip);
+		if (ret) {
+			dev_err(chip->dev, "failed to disable eud\n");
+			return ret;
+		}
 	}
 
-	return ret < 0 ? ret : count;
+	chip->enabled = enable;
+
+	return count;
 }
 
 static DEVICE_ATTR_RW(enable);
-- 
2.34.1


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

* [PATCH v2 6/9] usb: misc: qcom_eud: add host mode coordination
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
                   ` (4 preceding siblings ...)
  2026-01-26 23:38 ` [PATCH v2 5/9] usb: misc: qcom_eud: improve enable_store API Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-02-04 13:29   ` Konrad Dybcio
  2026-01-26 23:38 ` [PATCH v2 7/9] usb: misc: qcom_eud: fix virtual attach/detach event handling Elson Serrao
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

EUD functions by presenting itself as a USB device to the host PC for
debugging, making it incompatible in USB host mode configurations.
Enabling EUD, when in host mode can also cause the USB controller to
misbehave as the EUD hub can only have one upstream facing port.

Handle below two scenarios to prevent these conflicts:
1. Prevent user from enabling EUD via sysfs when the USB port is
   in host mode.
2. Automatically disable EUD when USB port switches to host mode
   and re-enable it when exiting host mode.

This ensures consistent state management without creating conflicts
between the EUD debug hub and the USB controller.

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 drivers/usb/misc/qcom_eud.c | 79 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index 0ea6491f963c..3f1cc7ea2a6a 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -49,12 +49,15 @@ struct eud_chip {
 	struct device			*dev;
 	void __iomem			*base;
 	struct eud_path			*paths[EUD_MAX_PORTS];
+	/* serializes EUD control operations */
+	struct mutex			state_lock;
 	phys_addr_t			mode_mgr;
 	unsigned int			int_status;
 	int				irq;
 	bool				enabled;
 	bool				usb_attached;
 	bool				phy_enabled;
+	bool				eud_disabled_for_host;
 	u8				port_idx;
 };
 
@@ -162,32 +165,66 @@ static ssize_t enable_store(struct device *dev,
 		const char *buf, size_t count)
 {
 	struct eud_chip *chip = dev_get_drvdata(dev);
+	struct eud_path *path;
 	bool enable;
 	int ret;
 
 	if (kstrtobool(buf, &enable))
 		return -EINVAL;
 
+	mutex_lock(&chip->state_lock);
+
 	/* Skip operation if already in desired state */
-	if (chip->enabled == enable)
+	if (chip->enabled == enable) {
+		mutex_unlock(&chip->state_lock);
 		return count;
+	}
+
+	/*
+	 * Handle double-disable scenario: User is disabling EUD that was already
+	 * disabled due to host mode. Since the hardware is already disabled, we
+	 * only need to clear the host-disabled flag to prevent unwanted re-enabling
+	 * when exiting host mode. This respects the user's explicit disable request.
+	 */
+	if (!enable && chip->eud_disabled_for_host) {
+		chip->eud_disabled_for_host = false;
+		chip->enabled = false;
+		mutex_unlock(&chip->state_lock);
+		return count;
+	}
 
 	if (enable) {
+		/*
+		 * EUD functions by presenting itself as a USB device to the host PC for
+		 * debugging, making it incompatible in USB host mode configuration.
+		 * Prevent enabling EUD in this configuration to avoid hardware conflicts.
+		 */
+		path = chip->paths[chip->port_idx];
+		if (path && path->curr_role == USB_ROLE_HOST) {
+			dev_err(chip->dev, "EUD not usable in host mode configuration\n");
+			mutex_unlock(&chip->state_lock);
+			return -EBUSY;
+		}
+
 		ret = enable_eud(chip);
 		if (ret) {
 			dev_err(chip->dev, "failed to enable eud\n");
+			mutex_unlock(&chip->state_lock);
 			return ret;
 		}
 	} else {
 		ret = disable_eud(chip);
 		if (ret) {
 			dev_err(chip->dev, "failed to disable eud\n");
+			mutex_unlock(&chip->state_lock);
 			return ret;
 		}
 	}
 
 	chip->enabled = enable;
 
+	mutex_unlock(&chip->state_lock);
+
 	return count;
 }
 
@@ -324,18 +361,56 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data)
 static int eud_role_switch_set(struct usb_role_switch *sw, enum usb_role role)
 {
 	struct eud_path *path = usb_role_switch_get_drvdata(sw);
+	struct eud_chip *chip = path->chip;
 	int ret;
 
+	mutex_lock(&chip->state_lock);
+
+	/*
+	 * EUD must be disabled when USB operates in host mode. EUD functions by
+	 * presenting itself as a USB device to the host PC for debugging, making
+	 * it incompatible in host mode configuration.
+	 *
+	 * chip->enabled preserves user's sysfs configuration and is not modified
+	 * during host mode transitions to maintain user intent.
+	 */
+
+	/* Only act if EUD is enabled and this is the active path */
+	if (chip->enabled && path->num == chip->port_idx) {
+		if (role == USB_ROLE_HOST && !chip->eud_disabled_for_host) {
+			ret = disable_eud(chip);
+			if (ret) {
+				dev_err(chip->dev, "Failed to disable EUD for host mode: %d\n",
+					ret);
+				mutex_unlock(&chip->state_lock);
+				return ret;
+			}
+			chip->eud_disabled_for_host = true;
+		} else if (role != USB_ROLE_HOST && chip->eud_disabled_for_host) {
+			ret = enable_eud(chip);
+			if (ret) {
+				dev_err(chip->dev, "Failed to re-enable EUD after host mode: %d\n",
+					ret);
+				mutex_unlock(&chip->state_lock);
+				return ret;
+			}
+			chip->eud_disabled_for_host = false;
+		}
+	}
+
 	/* Forward the role request to the USB controller */
 	ret = usb_role_switch_set_role(path->controller_sw, role);
 	if (ret) {
 		dev_err(path->chip->dev, "Failed to set role %s for port %u: %d\n",
 			usb_role_string(role), path->num, ret);
+		mutex_unlock(&chip->state_lock);
 		return ret;
 	}
 
 	path->curr_role = role;
 
+	mutex_unlock(&chip->state_lock);
+
 	return 0;
 }
 
@@ -433,6 +508,8 @@ static int eud_probe(struct platform_device *pdev)
 
 	chip->dev = &pdev->dev;
 
+	mutex_init(&chip->state_lock);
+
 	ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip);
 	if (ret)
 		return ret;
-- 
2.34.1


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

* [PATCH v2 7/9] usb: misc: qcom_eud: fix virtual attach/detach event handling
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
                   ` (5 preceding siblings ...)
  2026-01-26 23:38 ` [PATCH v2 6/9] usb: misc: qcom_eud: add host mode coordination Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-02-04 13:32   ` Konrad Dybcio
  2026-01-26 23:38 ` [PATCH v2 8/9] arm64: dts: qcom: kodiak: Align EUD node with binding Elson Serrao
  2026-01-26 23:38 ` [PATCH v2 9/9] arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality Elson Serrao
  8 siblings, 1 reply; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

EUD provides virtual USB attach/detach events to simulate cable
plug/unplug while maintaining the physical debug connection. However,
the current implementation incorrectly sets the USB role to HOST on
virtual detach, which doesn't represent the disconnected state.

Fix the virtual detach handling by setting the USB role to NONE
instead of HOST, correctly representing the disconnected state.

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 drivers/usb/misc/qcom_eud.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index 3f1cc7ea2a6a..60f566427abe 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -343,10 +343,26 @@ static irqreturn_t handle_eud_irq_thread(int irq, void *data)
 	if (!path || !path->controller_sw)
 		goto clear_irq;
 
+	/*
+	 * EUD virtual attach/detach event handling for low power debugging:
+	 *
+	 * When EUD is enabled in debug mode, the device remains physically
+	 * connected to the PC throughout the debug session, keeping the USB
+	 * controller active. This prevents testing of low power scenarios that
+	 * require USB disconnection.
+	 *
+	 * EUD solves this by providing virtual USB attach/detach events while
+	 * maintaining the physical connection. These events are triggered from
+	 * the Host PC via the enumerated EUD control interface and delivered
+	 * to the EUD driver as interrupts.
+	 *
+	 * These notifications are forwarded to the USB controller through role
+	 * switch framework.
+	 */
 	if (chip->usb_attached)
 		ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_DEVICE);
 	else
-		ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_HOST);
+		ret = usb_role_switch_set_role(path->controller_sw, USB_ROLE_NONE);
 	if (ret)
 		dev_err(chip->dev, "failed to set role switch\n");
 
-- 
2.34.1


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

* [PATCH v2 8/9] arm64: dts: qcom: kodiak: Align EUD node with binding
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
                   ` (6 preceding siblings ...)
  2026-01-26 23:38 ` [PATCH v2 7/9] usb: misc: qcom_eud: fix virtual attach/detach event handling Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-01-26 23:38 ` [PATCH v2 9/9] arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality Elson Serrao
  8 siblings, 0 replies; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

The EUD node does not match the current binding and maps USB endpoints
to the secondary controller. This SoC supports EUD only on the primary
High-Speed USB path. The binding also requires a per-path PHY reference.

Model the primary UTMI path as a child node with the required PHY and an
empty ports graph. Leave endpoint mapping to board DTS files, and remove
the secondary mapping and associated ports so the description conforms
to the binding.

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/kodiak.dtsi | 33 +++++++++++++++++-----------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi
index c2ccbb67f800..35c47a6b03f7 100644
--- a/arch/arm64/boot/dts/qcom/kodiak.dtsi
+++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi
@@ -4284,12 +4284,6 @@ usb_2: usb@8c00000 {
 			phy-names = "usb2-phy";
 			maximum-speed = "high-speed";
 			usb-role-switch;
-
-			port {
-				usb2_role_switch: endpoint {
-					remote-endpoint = <&eud_ep>;
-				};
-			};
 		};
 
 		qspi: spi@88dc000 {
@@ -4610,16 +4604,29 @@ eud: eud@88e0000 {
 			      <0 0x88e2000 0 0x1000>;
 			interrupts-extended = <&pdc 11 IRQ_TYPE_LEVEL_HIGH>;
 
+			#address-cells = <1>;
+			#size-cells = <0>;
+
 			status = "disabled";
 
-			ports {
-				#address-cells = <1>;
-				#size-cells = <0>;
+			eud0: eud-path@0 {
+				reg = <0>;
+				phys = <&usb_1_hsphy>;
 
-				port@0 {
-					reg = <0>;
-					eud_ep: endpoint {
-						remote-endpoint = <&usb2_role_switch>;
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						reg = <0>;
+						eud_usb0: endpoint {
+						};
+					};
+
+					port@1 {
+						reg = <1>;
+						eud_con0: endpoint {
+						};
 					};
 				};
 			};
-- 
2.34.1


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

* [PATCH v2 9/9] arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality
  2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
                   ` (7 preceding siblings ...)
  2026-01-26 23:38 ` [PATCH v2 8/9] arm64: dts: qcom: kodiak: Align EUD node with binding Elson Serrao
@ 2026-01-26 23:38 ` Elson Serrao
  2026-02-03 13:38   ` Konrad Dybcio
  8 siblings, 1 reply; 25+ messages in thread
From: Elson Serrao @ 2026-01-26 23:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On this board, EUD resides on the primary High-Speed USB data path between
the connector and the DWC3 controller. Update the device tree connections
to correctly map the connector and controller endpoints, and describe
role-switch capability on the EUD primary path.

Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
index f29a352b0288..2fc2d0aed8dd 100644
--- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
@@ -194,7 +194,7 @@ port@0 {
 					reg = <0>;
 
 					pmic_glink_hs_in: endpoint {
-						remote-endpoint = <&usb_1_dwc3_hs>;
+						remote-endpoint = <&eud_con0>;
 					};
 				};
 
@@ -1176,13 +1176,29 @@ &usb_1 {
 };
 
 &usb_1_dwc3_hs {
-	remote-endpoint = <&pmic_glink_hs_in>;
+	remote-endpoint = <&eud_usb0>;
 };
 
 &usb_1_dwc3_ss {
 	remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
 };
 
+&eud_con0 {
+	remote-endpoint = <&pmic_glink_hs_in>;
+};
+
+&eud_usb0 {
+	remote-endpoint = <&usb_1_dwc3_hs>;
+};
+
+&eud {
+	status = "okay";
+};
+
+&eud0 {
+	usb-role-switch;
+};
+
 &usb_1_hsphy {
 	vdda-pll-supply = <&vreg_l10c_0p88>;
 	vdda33-supply = <&vreg_l2b_3p072>;
-- 
2.34.1


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

* Re: [PATCH v2 2/9] usb: misc: qcom_eud: add sysfs attribute for port selection
  2026-01-26 23:38 ` [PATCH v2 2/9] usb: misc: qcom_eud: add sysfs attribute for port selection Elson Serrao
@ 2026-01-27 13:31   ` Konrad Dybcio
  0 siblings, 0 replies; 25+ messages in thread
From: Konrad Dybcio @ 2026-01-27 13:31 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 1/27/26 12:38 AM, Elson Serrao wrote:
> EUD can be mapped to either the primary USB port or the secondary USB port
> depending on the value of the EUD_PORT_SEL register. Add a 'port' sysfs
> attribute to allow userspace to select which port EUD should operate on
> and update the ABI documentation. This is needed for systems with dual
> USB ports where EUD needs to be accessible on either port depending on the
> system configuration and use case.
> 
> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
> ---

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

Konrad

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

* Re: [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware
  2026-01-26 23:38 ` [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware Elson Serrao
@ 2026-02-03 13:35   ` Konrad Dybcio
  2026-02-04 14:01   ` Konrad Dybcio
  2026-02-06 14:55   ` Rob Herring
  2 siblings, 0 replies; 25+ messages in thread
From: Konrad Dybcio @ 2026-02-03 13:35 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 1/27/26 12:38 AM, Elson Serrao wrote:
> The Qualcomm Embedded USB Debugger (EUD) can intercept one or two
> independent High-Speed UTMI paths, depending on the SoC. Each path is
> distinct with its own HS-PHY interface, connector/controller wiring, and
> UTMI routing behavior. The EUD hardware sits between the USB2 PHY and
> the USB controller on each path.
> 
> The existing binding models only a single UTMI path and does not provide
> a way to associate the required High-Speed USB PHY. EUD relies on the
> HS-PHY on the selected UTMI path for link signalling and correct operation
> of the hardware.
> 
> Historically, EUD has worked on platforms that use a single UTMI path
> because the USB controller maintains ownership of the PHY during
> enumeration and normal operation. This implicit relationship allowed
> EUD to function even though the dependency on the PHY was not described
> in the binding. However, this behavior is not guaranteed by hardware.
> The current binding description is not sufficient for SoCs that expose
> two independent UTMI paths, where the PHY association and port wiring
> must be explicitly described.
> 
> Introduce per-path eud-path child nodes so each UTMI path can describe
> its HS-PHY, port connections, and the role‑switching capability of its
> associated USB port.
> 
> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
> ---

[...]

> +patternProperties:
> +  "^eud-path@[0-1]$":

I can't quite put it into words why I don't like this name, but I
don't like this name.. That said I don't really have any clever ideas
for a better one, so I'm not going to object, suppose I just needed
to vent my ramblings

> +    type: object
>      description:
> -      These ports is to be attached to the endpoint of the DWC3 controller node
> -      and type C connector node. The controller has the "usb-role-switch"
> -      property.
> +      Represents one High-Speed UTMI path that EUD intercepts. This node models
> +      the physical data path intercepted by EUD and provides graph endpoints to
> +      link the USB controller and the external connector associated with this path.
>  
>      properties:
> -      port@0:
> -        $ref: /schemas/graph.yaml#/properties/port
> -        description: This port is to be attached to the DWC3 controller.
> +      reg:
> +        maxItems: 1
> +        description: Path number
> +
> +      phys:
> +        maxItems: 1
> +        description: High-Speed USB PHY associated with this data path.
> +
> +      usb-role-switch:
> +        type: boolean
> +        description:
> +          Set this property if the USB port on this path is role switch capable.

This doesn't quite sound right. The EUD acts/can act as a rolesw no matter
what's connected to it.

> +          In device role, debug mode inserts the EUD hub into the UTMI path. In
> +          host role, the EUD hub is bypassed and UTMI traffic flows directly
> +          between the PHY and the USB controller.

The rest of this paragraph is good stuff, explaining the reasoning

> +
> +      ports:
> +        $ref: /schemas/graph.yaml#/properties/ports
> +        description:
> +          These ports are to be attached to the endpoint of the USB controller node
> +          and USB connector node.
> +
> +        properties:
> +          port@0:
> +            $ref: /schemas/graph.yaml#/properties/port
> +            description: This port is to be attached to the USB controller.
>  
> -      port@1:
> -        $ref: /schemas/graph.yaml#/properties/port
> -        description: This port is to be attached to the type C connector.

nit: "Type-C"

Konrad

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

* Re: [PATCH v2 9/9] arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality
  2026-01-26 23:38 ` [PATCH v2 9/9] arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality Elson Serrao
@ 2026-02-03 13:38   ` Konrad Dybcio
  2026-02-09 17:06     ` Elson Serrao
  0 siblings, 1 reply; 25+ messages in thread
From: Konrad Dybcio @ 2026-02-03 13:38 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 1/27/26 12:38 AM, Elson Serrao wrote:
> On this board, EUD resides on the primary High-Speed USB data path between
> the connector and the DWC3 controller. Update the device tree connections
> to correctly map the connector and controller endpoints, and describe
> role-switch capability on the EUD primary path.
> 
> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
> ---
>  arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 20 ++++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> index f29a352b0288..2fc2d0aed8dd 100644
> --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> @@ -194,7 +194,7 @@ port@0 {
>  					reg = <0>;
>  
>  					pmic_glink_hs_in: endpoint {
> -						remote-endpoint = <&usb_1_dwc3_hs>;
> +						remote-endpoint = <&eud_con0>;
>  					};
>  				};
>  
> @@ -1176,13 +1176,29 @@ &usb_1 {
>  };
>  
>  &usb_1_dwc3_hs {
> -	remote-endpoint = <&pmic_glink_hs_in>;
> +	remote-endpoint = <&eud_usb0>;
>  };
>  
>  &usb_1_dwc3_ss {
>  	remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;

The on-SoC links can be deferred to the common DTSI


>  };
>  
> +&eud_con0 {
> +	remote-endpoint = <&pmic_glink_hs_in>;
> +};
> +
> +&eud_usb0 {
> +	remote-endpoint = <&usb_1_dwc3_hs>;
> +};
> +
> +&eud {
> +	status = "okay";

And I think it should be okay to keep it enabled by default

Konrad

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

* Re: [PATCH v2 3/9] usb: misc: qcom_eud: add per-path High-Speed PHY control
  2026-01-26 23:38 ` [PATCH v2 3/9] usb: misc: qcom_eud: add per-path High-Speed PHY control Elson Serrao
@ 2026-02-04 13:21   ` Konrad Dybcio
  2026-02-09 17:23     ` Elson Serrao
  0 siblings, 1 reply; 25+ messages in thread
From: Konrad Dybcio @ 2026-02-04 13:21 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 1/27/26 12:38 AM, Elson Serrao wrote:
> EUD hardware can support multiple High-Speed USB paths, each routed
> through its own PHY. The active path is selected in hardware via the
> EUD_PORT_SEL register. As a High-Speed hub, EUD requires access to the
> High-Speed PHY associated with the active UTMI path. To support this
> multi-path capability, the driver must manage PHY resources on a per-path
> basis, ensuring that the PHY for the currently selected path is properly
> initialized and powered.
> 
> This patch restructures the driver to implement per-path PHY management.
> The driver now powers the appropriate PHY based on the selected and
> enabled UTMI path, ensuring correct operation when EUD is enabled.
> 
> Supporting this requires describing the available UTMI paths and their
> corresponding PHYs in Device Tree. This updates DT requirements and is
> not backward compatible with older DTs that lacked this description.
> Historically, EUD appeared to work on single-path systems because the
> USB controller kept the PHY initialized. However, EUD is designed to
> operate independently of the USB controller and therefore requires
> explicit PHY control.
> 
> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
> ---

[...]

> +static int eud_phy_enable(struct eud_chip *chip)
> +{
> +	struct eud_path *path;
> +	struct phy *phy;
> +	int ret;
> +
> +	if (chip->phy_enabled)
> +		return 0;
> +
> +	path = chip->paths[chip->port_idx];
> +	if (!path || !path->phy) {

I think neither are possible - path is != NULL since we can't enter into
this function without failing the check in _store and !path->phy would error
out in probe()->eud_init_path()

[...]

> +static void eud_phy_disable(struct eud_chip *chip)
> +{
> +	struct eud_path *path;
> +	struct phy *phy;
> +
> +	if (!chip->phy_enabled)
> +		return;
> +
> +	path = chip->paths[chip->port_idx];
> +	if (!path || !path->phy)

Likewise

[...]

> +static int eud_init_path(struct eud_chip *chip, struct device_node *np)
> +{
> +	struct eud_path *path;
> +	u32 path_num;
> +	int ret;
> +
> +	ret = of_property_read_u32(np, "reg", &path_num);
> +	if (ret) {
> +		dev_err(chip->dev, "Missing 'reg' property in path node\n");
> +		return ret;

You can use return dev_err_probe like you did a little below

> +	}
> +
> +	if (path_num >= EUD_MAX_PORTS) {
> +		dev_err(chip->dev, "Invalid path number: %u (max %d)\n",
> +			path_num, EUD_MAX_PORTS - 1);
> +		return -EINVAL;
> +	}
> +
> +	path = devm_kzalloc(chip->dev, sizeof(*path), GFP_KERNEL);
> +	if (!path)
> +		return -ENOMEM;
> +
> +	path->chip = chip;
> +	path->num = path_num;
> +
> +	path->phy = devm_of_phy_get(chip->dev, np, NULL);
> +	if (IS_ERR(path->phy))
> +		return dev_err_probe(chip->dev, PTR_ERR(path->phy),
> +				     "Failed to get PHY for path %d\n", path_num);
> +
> +	chip->paths[path_num] = path;
> +
> +	return 0;
> +}
> +
>  static int eud_probe(struct platform_device *pdev)
>  {
> +	struct device_node *np = pdev->dev.of_node;
> +	struct device_node *child;
>  	struct eud_chip *chip;
>  	struct resource *res;
>  	int ret;
> @@ -252,6 +368,18 @@ static int eud_probe(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
>  
> +	for_each_child_of_node(np, child) {

With for_each_child_of_node_scoped(), you can dispose of the manual
_put()

> +		ret = eud_init_path(chip, child);
> +		if (ret) {
> +			of_node_put(child);
> +			return ret;
> +		}
> +	}
> +
> +	/* Primary path is mandatory. Secondary is optional */
> +	if (!chip->paths[0])
> +		return -ENODEV;

I'm going to assume we don't have any funny chips that violate this :)

Konrad

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

* Re: [PATCH v2 5/9] usb: misc: qcom_eud: improve enable_store API
  2026-01-26 23:38 ` [PATCH v2 5/9] usb: misc: qcom_eud: improve enable_store API Elson Serrao
@ 2026-02-04 13:24   ` Konrad Dybcio
  0 siblings, 0 replies; 25+ messages in thread
From: Konrad Dybcio @ 2026-02-04 13:24 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 1/27/26 12:38 AM, Elson Serrao wrote:
> Currently enable_store() allows operations irrespective of the EUD state,
> which can result in redundant operations. Avoid this by adding duplicate
> state checks to skip requests when EUD is already in the desired state.
> Additionally, improve error handling with explicit logging to provide
> better feedback.
> 
> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
> ---

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

Konrad

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

* Re: [PATCH v2 6/9] usb: misc: qcom_eud: add host mode coordination
  2026-01-26 23:38 ` [PATCH v2 6/9] usb: misc: qcom_eud: add host mode coordination Elson Serrao
@ 2026-02-04 13:29   ` Konrad Dybcio
  2026-02-09 17:37     ` Elson Serrao
  0 siblings, 1 reply; 25+ messages in thread
From: Konrad Dybcio @ 2026-02-04 13:29 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 1/27/26 12:38 AM, Elson Serrao wrote:
> EUD functions by presenting itself as a USB device to the host PC for
> debugging, making it incompatible in USB host mode configurations.
> Enabling EUD, when in host mode can also cause the USB controller to
> misbehave as the EUD hub can only have one upstream facing port.

Perhaps that's a silly idea, but would the device itself see
the debug hub, being able to essentially self-debug in a way?

[...]

> @@ -162,32 +165,66 @@ static ssize_t enable_store(struct device *dev,
>  		const char *buf, size_t count)
>  {
>  	struct eud_chip *chip = dev_get_drvdata(dev);
> +	struct eud_path *path;
>  	bool enable;
>  	int ret;
>  
>  	if (kstrtobool(buf, &enable))
>  		return -EINVAL;
>  
> +	mutex_lock(&chip->state_lock);

If you use guard(mutex)(&chip->state-lock), you can waive all these
conditional mutex_unlock additions

> +
>  	/* Skip operation if already in desired state */
> -	if (chip->enabled == enable)
> +	if (chip->enabled == enable) {
> +		mutex_unlock(&chip->state_lock);
>  		return count;
> +	}
> +
> +	/*
> +	 * Handle double-disable scenario: User is disabling EUD that was already
> +	 * disabled due to host mode. Since the hardware is already disabled, we
> +	 * only need to clear the host-disabled flag to prevent unwanted re-enabling
> +	 * when exiting host mode. This respects the user's explicit disable request.
> +	 */
> +	if (!enable && chip->eud_disabled_for_host) {
> +		chip->eud_disabled_for_host = false;
> +		chip->enabled = false;
> +		mutex_unlock(&chip->state_lock);
> +		return count;
> +	}
>  
>  	if (enable) {
> +		/*
> +		 * EUD functions by presenting itself as a USB device to the host PC for
> +		 * debugging, making it incompatible in USB host mode configuration.
> +		 * Prevent enabling EUD in this configuration to avoid hardware conflicts.
> +		 */
> +		path = chip->paths[chip->port_idx];
> +		if (path && path->curr_role == USB_ROLE_HOST) {
> +			dev_err(chip->dev, "EUD not usable in host mode configuration\n");

"in USB host mode"?

[...]

> +	/*
> +	 * EUD must be disabled when USB operates in host mode. EUD functions by
> +	 * presenting itself as a USB device to the host PC for debugging, making
> +	 * it incompatible in host mode configuration.
			   ^ with

Otherwise the logic looks good, I think this may be desired default
behavior (so that the user doesn't have to constantly keep re-enabling
EUD)

Konrad

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

* Re: [PATCH v2 7/9] usb: misc: qcom_eud: fix virtual attach/detach event handling
  2026-01-26 23:38 ` [PATCH v2 7/9] usb: misc: qcom_eud: fix virtual attach/detach event handling Elson Serrao
@ 2026-02-04 13:32   ` Konrad Dybcio
  0 siblings, 0 replies; 25+ messages in thread
From: Konrad Dybcio @ 2026-02-04 13:32 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 1/27/26 12:38 AM, Elson Serrao wrote:
> EUD provides virtual USB attach/detach events to simulate cable
> plug/unplug while maintaining the physical debug connection. However,
> the current implementation incorrectly sets the USB role to HOST on
> virtual detach, which doesn't represent the disconnected state.
> 
> Fix the virtual detach handling by setting the USB role to NONE
> instead of HOST, correctly representing the disconnected state.
> 
> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
> ---

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

Konrad

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

* Re: [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware
  2026-01-26 23:38 ` [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware Elson Serrao
  2026-02-03 13:35   ` Konrad Dybcio
@ 2026-02-04 14:01   ` Konrad Dybcio
  2026-02-06 14:55   ` Rob Herring
  2 siblings, 0 replies; 25+ messages in thread
From: Konrad Dybcio @ 2026-02-04 14:01 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 1/27/26 12:38 AM, Elson Serrao wrote:
> The Qualcomm Embedded USB Debugger (EUD) can intercept one or two
> independent High-Speed UTMI paths, depending on the SoC. Each path is
> distinct with its own HS-PHY interface, connector/controller wiring, and
> UTMI routing behavior. The EUD hardware sits between the USB2 PHY and
> the USB controller on each path.
> 
> The existing binding models only a single UTMI path and does not provide
> a way to associate the required High-Speed USB PHY. EUD relies on the
> HS-PHY on the selected UTMI path for link signalling and correct operation
> of the hardware.
> 
> Historically, EUD has worked on platforms that use a single UTMI path
> because the USB controller maintains ownership of the PHY during
> enumeration and normal operation. This implicit relationship allowed
> EUD to function even though the dependency on the PHY was not described
> in the binding. However, this behavior is not guaranteed by hardware.
> The current binding description is not sufficient for SoCs that expose
> two independent UTMI paths, where the PHY association and port wiring
> must be explicitly described.
> 
> Introduce per-path eud-path child nodes so each UTMI path can describe
> its HS-PHY, port connections, and the role‑switching capability of its
> associated USB port.
> 
> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
> ---

[...]

> +patternProperties:
> +  "^eud-path@[0-1]$":

At least a since instance of this should be 'required'

Konrad

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

* Re: [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware
  2026-01-26 23:38 ` [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware Elson Serrao
  2026-02-03 13:35   ` Konrad Dybcio
  2026-02-04 14:01   ` Konrad Dybcio
@ 2026-02-06 14:55   ` Rob Herring
  2026-02-10  4:32     ` Elson Serrao
  2 siblings, 1 reply; 25+ messages in thread
From: Rob Herring @ 2026-02-06 14:55 UTC (permalink / raw)
  To: Elson Serrao
  Cc: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury,
	linux-arm-msm, devicetree, linux-usb, linux-kernel

On Mon, Jan 26, 2026 at 03:38:22PM -0800, Elson Serrao wrote:
> The Qualcomm Embedded USB Debugger (EUD) can intercept one or two
> independent High-Speed UTMI paths, depending on the SoC. Each path is
> distinct with its own HS-PHY interface, connector/controller wiring, and
> UTMI routing behavior. The EUD hardware sits between the USB2 PHY and
> the USB controller on each path.
> 
> The existing binding models only a single UTMI path and does not provide
> a way to associate the required High-Speed USB PHY. EUD relies on the
> HS-PHY on the selected UTMI path for link signalling and correct operation
> of the hardware.
> 
> Historically, EUD has worked on platforms that use a single UTMI path
> because the USB controller maintains ownership of the PHY during
> enumeration and normal operation. This implicit relationship allowed
> EUD to function even though the dependency on the PHY was not described
> in the binding. However, this behavior is not guaranteed by hardware.
> The current binding description is not sufficient for SoCs that expose
> two independent UTMI paths, where the PHY association and port wiring
> must be explicitly described.
> 
> Introduce per-path eud-path child nodes so each UTMI path can describe
> its HS-PHY, port connections, and the role‑switching capability of its
> associated USB port.
> 
> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
> ---
>  .../bindings/soc/qcom/qcom,eud.yaml           | 100 +++++++++++++-----
>  1 file changed, 74 insertions(+), 26 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml
> index 84218636c0d8..0507252dbf27 100644
> --- a/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml
> +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,eud.yaml
> @@ -10,8 +10,11 @@ maintainers:
>    - Souradeep Chowdhury <quic_schowdhu@quicinc.com>
>  
>  description:
> -  This binding is used to describe the Qualcomm Embedded USB Debugger, which is
> -  mini USB-hub implemented on chip to support USB-based debug capabilities.
> +  This binding describes the Qualcomm Embedded USB Debugger (EUD), an on-chip
> +  mini USB hub that enables USB-based debug capabilities. The EUD block is
> +  positioned between the High-Speed USB PHY and the USB controller, where it
> +  intercepts the UTMI interface to support debug and bypass modes. EUD can be
> +  supported on up to two High-Speed USB ports.
>  
>  properties:
>    compatible:
> @@ -29,26 +32,62 @@ properties:
>      description: EUD interrupt
>      maxItems: 1
>  
> -  ports:
> -    $ref: /schemas/graph.yaml#/properties/ports

You are breaking existing users.

> +  '#address-cells':
> +    const: 1
> +
> +  '#size-cells':
> +    const: 0
> +
> +patternProperties:
> +  "^eud-path@[0-1]$":
> +    type: object
>      description:
> -      These ports is to be attached to the endpoint of the DWC3 controller node
> -      and type C connector node. The controller has the "usb-role-switch"
> -      property.
> +      Represents one High-Speed UTMI path that EUD intercepts. This node models
> +      the physical data path intercepted by EUD and provides graph endpoints to
> +      link the USB controller and the external connector associated with this path.
>  
>      properties:
> -      port@0:
> -        $ref: /schemas/graph.yaml#/properties/port
> -        description: This port is to be attached to the DWC3 controller.
> +      reg:
> +        maxItems: 1
> +        description: Path number
> +
> +      phys:
> +        maxItems: 1
> +        description: High-Speed USB PHY associated with this data path.

Doesn't the DWC3 node have a phys property? You don't need it twice 
since you can walk the graph.

> +
> +      usb-role-switch:
> +        type: boolean
> +        description:
> +          Set this property if the USB port on this path is role switch capable.
> +          In device role, debug mode inserts the EUD hub into the UTMI path. In
> +          host role, the EUD hub is bypassed and UTMI traffic flows directly
> +          between the PHY and the USB controller.
> +
> +      ports:
> +        $ref: /schemas/graph.yaml#/properties/ports
> +        description:
> +          These ports are to be attached to the endpoint of the USB controller node
> +          and USB connector node.
> +
> +        properties:
> +          port@0:
> +            $ref: /schemas/graph.yaml#/properties/port
> +            description: This port is to be attached to the USB controller.
>  
> -      port@1:
> -        $ref: /schemas/graph.yaml#/properties/port
> -        description: This port is to be attached to the type C connector.
> +          port@1:
> +            $ref: /schemas/graph.yaml#/properties/port
> +            description: This port is to be attached to the USB connector.

Both port 0 and 1 are attached to the USB controller?

Why can't you just add more port nodes to the existing binding?

Rob

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

* Re: [PATCH v2 9/9] arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality
  2026-02-03 13:38   ` Konrad Dybcio
@ 2026-02-09 17:06     ` Elson Serrao
  0 siblings, 0 replies; 25+ messages in thread
From: Elson Serrao @ 2026-02-09 17:06 UTC (permalink / raw)
  To: Konrad Dybcio, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel



On 2/3/2026 5:38 AM, Konrad Dybcio wrote:
> On 1/27/26 12:38 AM, Elson Serrao wrote:
>> On this board, EUD resides on the primary High-Speed USB data path between
>> the connector and the DWC3 controller. Update the device tree connections
>> to correctly map the connector and controller endpoints, and describe
>> role-switch capability on the EUD primary path.
>>
>> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
>> ---
>>  arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 20 ++++++++++++++++++--
>>  1 file changed, 18 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
>> index f29a352b0288..2fc2d0aed8dd 100644
>> --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
>> +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
>> @@ -194,7 +194,7 @@ port@0 {
>>  					reg = <0>;
>>  
>>  					pmic_glink_hs_in: endpoint {
>> -						remote-endpoint = <&usb_1_dwc3_hs>;
>> +						remote-endpoint = <&eud_con0>;
>>  					};
>>  				};
>>  
>> @@ -1176,13 +1176,29 @@ &usb_1 {
>>  };
>>  
>>  &usb_1_dwc3_hs {
>> -	remote-endpoint = <&pmic_glink_hs_in>;
>> +	remote-endpoint = <&eud_usb0>;
>>  };
>>  
>>  &usb_1_dwc3_ss {
>>  	remote-endpoint = <&usb_dp_qmpphy_usb_ss_in>;
> 
> The on-SoC links can be deferred to the common DTSI
> 
> 

Thanks Konrad for the detailed review.
I’ll defer the on‑SoC USB controller to EUD node mapping to the common DTSI.

>>  };
>>  
>> +&eud_con0 {
>> +	remote-endpoint = <&pmic_glink_hs_in>;
>> +};
>> +
>> +&eud_usb0 {
>> +	remote-endpoint = <&usb_1_dwc3_hs>;
>> +};
>> +
>> +&eud {
>> +	status = "okay";
> 
> And I think it should be okay to keep it enabled by default
> 
Ack

Thanks
Elson

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

* Re: [PATCH v2 3/9] usb: misc: qcom_eud: add per-path High-Speed PHY control
  2026-02-04 13:21   ` Konrad Dybcio
@ 2026-02-09 17:23     ` Elson Serrao
  0 siblings, 0 replies; 25+ messages in thread
From: Elson Serrao @ 2026-02-09 17:23 UTC (permalink / raw)
  To: Konrad Dybcio, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel



On 2/4/2026 5:21 AM, Konrad Dybcio wrote:
> On 1/27/26 12:38 AM, Elson Serrao wrote:
>> EUD hardware can support multiple High-Speed USB paths, each routed
>> through its own PHY. The active path is selected in hardware via the
>> EUD_PORT_SEL register. As a High-Speed hub, EUD requires access to the
>> High-Speed PHY associated with the active UTMI path. To support this
>> multi-path capability, the driver must manage PHY resources on a per-path
>> basis, ensuring that the PHY for the currently selected path is properly
>> initialized and powered.
>>
>> This patch restructures the driver to implement per-path PHY management.
>> The driver now powers the appropriate PHY based on the selected and
>> enabled UTMI path, ensuring correct operation when EUD is enabled.
>>
>> Supporting this requires describing the available UTMI paths and their
>> corresponding PHYs in Device Tree. This updates DT requirements and is
>> not backward compatible with older DTs that lacked this description.
>> Historically, EUD appeared to work on single-path systems because the
>> USB controller kept the PHY initialized. However, EUD is designed to
>> operate independently of the USB controller and therefore requires
>> explicit PHY control.
>>
>> Signed-off-by: Elson Serrao <elson.serrao@oss.qualcomm.com>
>> ---
> 
> [...]
> 
>> +static int eud_phy_enable(struct eud_chip *chip)
>> +{
>> +	struct eud_path *path;
>> +	struct phy *phy;
>> +	int ret;
>> +
>> +	if (chip->phy_enabled)
>> +		return 0;
>> +
>> +	path = chip->paths[chip->port_idx];
>> +	if (!path || !path->phy) {
> 
> I think neither are possible - path is != NULL since we can't enter into
> this function without failing the check in _store and !path->phy would error
> out in probe()->eud_init_path()
> 
> [...]
> 
>> +static void eud_phy_disable(struct eud_chip *chip)
>> +{
>> +	struct eud_path *path;
>> +	struct phy *phy;
>> +
>> +	if (!chip->phy_enabled)
>> +		return;
>> +
>> +	path = chip->paths[chip->port_idx];
>> +	if (!path || !path->phy)
> 
> Likewise
> 
> [...]
> 
>> +static int eud_init_path(struct eud_chip *chip, struct device_node *np)
>> +{
>> +	struct eud_path *path;
>> +	u32 path_num;
>> +	int ret;
>> +
>> +	ret = of_property_read_u32(np, "reg", &path_num);
>> +	if (ret) {
>> +		dev_err(chip->dev, "Missing 'reg' property in path node\n");
>> +		return ret;
> 
> You can use return dev_err_probe like you did a little below
> 
>> +	}
>> +
>> +	if (path_num >= EUD_MAX_PORTS) {
>> +		dev_err(chip->dev, "Invalid path number: %u (max %d)\n",
>> +			path_num, EUD_MAX_PORTS - 1);
>> +		return -EINVAL;
>> +	}
>> +
>> +	path = devm_kzalloc(chip->dev, sizeof(*path), GFP_KERNEL);
>> +	if (!path)
>> +		return -ENOMEM;
>> +
>> +	path->chip = chip;
>> +	path->num = path_num;
>> +
>> +	path->phy = devm_of_phy_get(chip->dev, np, NULL);
>> +	if (IS_ERR(path->phy))
>> +		return dev_err_probe(chip->dev, PTR_ERR(path->phy),
>> +				     "Failed to get PHY for path %d\n", path_num);
>> +
>> +	chip->paths[path_num] = path;
>> +
>> +	return 0;
>> +}
>> +
>>  static int eud_probe(struct platform_device *pdev)
>>  {
>> +	struct device_node *np = pdev->dev.of_node;
>> +	struct device_node *child;
>>  	struct eud_chip *chip;
>>  	struct resource *res;
>>  	int ret;
>> @@ -252,6 +368,18 @@ static int eud_probe(struct platform_device *pdev)
>>  	if (ret)
>>  		return ret;
>>  
>> +	for_each_child_of_node(np, child) {
> 
> With for_each_child_of_node_scoped(), you can dispose of the manual
> _put()
> 
>> +		ret = eud_init_path(chip, child);
>> +		if (ret) {
>> +			of_node_put(child);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	/* Primary path is mandatory. Secondary is optional */
>> +	if (!chip->paths[0])
>> +		return -ENODEV;
> 
> I'm going to assume we don't have any funny chips that violate this :)
> 


On all current SoCs, EUD_PORT_SEL defaults to 0, and the hardware guide
defines this as mapping to USB port 0. So the primary path being mandatory
is a valid assumption for existing hardware.

Thanks,
Elson


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

* Re: [PATCH v2 6/9] usb: misc: qcom_eud: add host mode coordination
  2026-02-04 13:29   ` Konrad Dybcio
@ 2026-02-09 17:37     ` Elson Serrao
  2026-02-10 10:00       ` Konrad Dybcio
  0 siblings, 1 reply; 25+ messages in thread
From: Elson Serrao @ 2026-02-09 17:37 UTC (permalink / raw)
  To: Konrad Dybcio, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel



On 2/4/2026 5:29 AM, Konrad Dybcio wrote:
> On 1/27/26 12:38 AM, Elson Serrao wrote:
>> EUD functions by presenting itself as a USB device to the host PC for
>> debugging, making it incompatible in USB host mode configurations.
>> Enabling EUD, when in host mode can also cause the USB controller to
>> misbehave as the EUD hub can only have one upstream facing port.
> 
> Perhaps that's a silly idea, but would the device itself see
> the debug hub, being able to essentially self-debug in a way?
> 

This isn’t supported by the current hardware topology.

When EUD is enabled, it enumerates as a USB device to an external host via its
upstream-facing port, while the SoC USB controller sits behind the hub’s
downstream-facing port. As a result, the controller cannot enumerate or
interact with the EUD device itself, and host mode is mutually exclusive with
EUD debug on this path.

Thanks
Elson

> [...]
> 
>> @@ -162,32 +165,66 @@ static ssize_t enable_store(struct device *dev,
>>  		const char *buf, size_t count)
>>  {
>>  	struct eud_chip *chip = dev_get_drvdata(dev);
>> +	struct eud_path *path;
>>  	bool enable;
>>  	int ret;
>>  
>>  	if (kstrtobool(buf, &enable))
>>  		return -EINVAL;
>>  
>> +	mutex_lock(&chip->state_lock);
> 
> If you use guard(mutex)(&chip->state-lock), you can waive all these
> conditional mutex_unlock additions
> 
>> +
>>  	/* Skip operation if already in desired state */
>> -	if (chip->enabled == enable)
>> +	if (chip->enabled == enable) {
>> +		mutex_unlock(&chip->state_lock);
>>  		return count;
>> +	}
>> +
>> +	/*
>> +	 * Handle double-disable scenario: User is disabling EUD that was already
>> +	 * disabled due to host mode. Since the hardware is already disabled, we
>> +	 * only need to clear the host-disabled flag to prevent unwanted re-enabling
>> +	 * when exiting host mode. This respects the user's explicit disable request.
>> +	 */
>> +	if (!enable && chip->eud_disabled_for_host) {
>> +		chip->eud_disabled_for_host = false;
>> +		chip->enabled = false;
>> +		mutex_unlock(&chip->state_lock);
>> +		return count;
>> +	}
>>  
>>  	if (enable) {
>> +		/*
>> +		 * EUD functions by presenting itself as a USB device to the host PC for
>> +		 * debugging, making it incompatible in USB host mode configuration.
>> +		 * Prevent enabling EUD in this configuration to avoid hardware conflicts.
>> +		 */
>> +		path = chip->paths[chip->port_idx];
>> +		if (path && path->curr_role == USB_ROLE_HOST) {
>> +			dev_err(chip->dev, "EUD not usable in host mode configuration\n");
> 
> "in USB host mode"?
> 
> [...]
> 
>> +	/*
>> +	 * EUD must be disabled when USB operates in host mode. EUD functions by
>> +	 * presenting itself as a USB device to the host PC for debugging, making
>> +	 * it incompatible in host mode configuration.
> 			   ^ with
> 
> Otherwise the logic looks good, I think this may be desired default
> behavior (so that the user doesn't have to constantly keep re-enabling
> EUD)
> 
> Konrad

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

* Re: [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware
  2026-02-06 14:55   ` Rob Herring
@ 2026-02-10  4:32     ` Elson Serrao
  2026-02-10  7:24       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 25+ messages in thread
From: Elson Serrao @ 2026-02-10  4:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury,
	linux-arm-msm, devicetree, linux-usb, linux-kernel



On 2/6/2026 6:55 AM, Rob Herring wrote:
> On Mon, Jan 26, 2026 at 03:38:22PM -0800, Elson Serrao wrote:
>> The Qualcomm Embedded USB Debugger (EUD) can intercept one or two
>> independent High-Speed UTMI paths, depending on the SoC. Each path is
>> distinct with its own HS-PHY interface, connector/controller wiring, and

[...]

>> +  supported on up to two High-Speed USB ports.
>>  
>>  properties:
>>    compatible:
>> @@ -29,26 +32,62 @@ properties:
>>      description: EUD interrupt
>>      maxItems: 1
>>  
>> -  ports:
>> -    $ref: /schemas/graph.yaml#/properties/ports
> 
> You are breaking existing users.
> 

Thanks Rob for your feedback.

The original motivation for the structural change was to make the binding
encode resources/topology that were implicit before. Specifically the EUD
intercept of the UTMI path(s) between the HS-USB PHY and the controller, and
the need to represent platforms with two independent UTMI paths. That led me
to introduce per-path nodes and a per-path PHY reference.
I outlined the constraints and rationale in this earlier thread:

https://lore.kernel.org/all/5cec9127-bdc5-49d7-80e1-2ae26f81163c@oss.qualcomm.com/


>> +  '#address-cells':
>> +    const: 1
>> +
>> +  '#size-cells':
>> +    const: 0
>> +
>> +patternProperties:
>> +  "^eud-path@[0-1]$":
>> +    type: object
>>      description:
>> -      These ports is to be attached to the endpoint of the DWC3 controller node
>> -      and type C connector node. The controller has the "usb-role-switch"
>> -      property.
>> +      Represents one High-Speed UTMI path that EUD intercepts. This node models
>> +      the physical data path intercepted by EUD and provides graph endpoints to
>> +      link the USB controller and the external connector associated with this path.
>>  
>>      properties:
>> -      port@0:
>> -        $ref: /schemas/graph.yaml#/properties/port
>> -        description: This port is to be attached to the DWC3 controller.
>> +      reg:
>> +        maxItems: 1
>> +        description: Path number
>> +
>> +      phys:
>> +        maxItems: 1
>> +        description: High-Speed USB PHY associated with this data path.
> 
> Doesn't the DWC3 node have a phys property? You don't need it twice 
> since you can walk the graph.
> 

Yes, the DWC3 node does have a `phys` property. I added a PHY reference under
EUD to make the dependency explicit, since the EUD debug module is independent
and relies on the HS‑USB PHY for its operation.

If the preferred pattern is to rely on the controller’s `phys` and discover it
by walking the graph, I’m happy to drop the duplicate reference. My only
concern was whether that makes the dependency effectively implicit—i.e., EUD’s
correctness would depend on a resource not directly referenced in its own
binding. If my understanding of how this should be expressed in the binding is
not correct, please let me know and I’ll adjust v3 accordingly.



>> +
>> +      usb-role-switch:
>> +        type: boolean
>> +        description:
>> +          Set this property if the USB port on this path is role switch capable.
>> +          In device role, debug mode inserts the EUD hub into the UTMI path. In
>> +          host role, the EUD hub is bypassed and UTMI traffic flows directly
>> +          between the PHY and the USB controller.
>> +
>> +      ports:
>> +        $ref: /schemas/graph.yaml#/properties/ports
>> +        description:
>> +          These ports are to be attached to the endpoint of the USB controller node
>> +          and USB connector node.
>> +
>> +        properties:
>> +          port@0:
>> +            $ref: /schemas/graph.yaml#/properties/port
>> +            description: This port is to be attached to the USB controller.
>>  
>> -      port@1:
>> -        $ref: /schemas/graph.yaml#/properties/port
>> -        description: This port is to be attached to the type C connector.
>> +          port@1:
>> +            $ref: /schemas/graph.yaml#/properties/port
>> +            description: This port is to be attached to the USB connector.
> 
> Both port 0 and 1 are attached to the USB controller?
>

No—only port@0 is attached to the USB controller; port@1 is attached to the USB
connector.

> Why can't you just add more port nodes to the existing binding?
> 

Do you mean extending the existing top-level ports like this?

  - port@0: USB controller0
  - port@1: USB connector0
  - port@2: USB controller1
  - port@3: USB connector1

My hesitation with a flat ports list is that it doesn’t encode which
controller/connector pair belongs to which physical path through EUD.
A graph walk starting at Conn0 could also reach USB Ctrl1, even though
these are independent paths and not interchangeable.

Below is the high‑level topology of EUD connections. In the disabled state,
EUD is transparent and UTMI traffic flows directly from USB2PHY0/1 to USB
Ctrl0/1. When EUD is enabled, the debug hub is inserted on the selected path
by the internal UTMI switch, so UTMI traffic on that path traverses the hub.
The non‑selected path continues as a direct PHY↔Controller link (EUD can be
enabled on only one path at a time).



					EUD Block
			   +------------------------------+  
			   |                              |
[Conn0]-->[USB2PHY0 ]----->|  -------- Path 0 ------------|--> [ USB Ctrl0 ]
			   |                              |  
[Conn1]-->[USB2PHY1 ]----->|  -------- Path 1 ------------|--> [ USB Ctrl1 ]
			   |                              |
			   |      +------------------+    |
			   |      |  EUD Debug Hub   |    |
			   |      +------------------+    |
			   +------------------------------+



So to make the connector–controller relationships explicit, I kept the `ports`
property under the `eud-path@N` child nodes. Please let me know if there is a
preferable way to model this.

Thanks
Elson



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

* Re: [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware
  2026-02-10  4:32     ` Elson Serrao
@ 2026-02-10  7:24       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 25+ messages in thread
From: Krzysztof Kozlowski @ 2026-02-10  7:24 UTC (permalink / raw)
  To: Elson Serrao, Rob Herring
  Cc: Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Krzysztof Kozlowski, Conor Dooley, Souradeep Chowdhury,
	linux-arm-msm, devicetree, linux-usb, linux-kernel

On 10/02/2026 05:32, Elson Serrao wrote:
> 
> 
> On 2/6/2026 6:55 AM, Rob Herring wrote:
>> On Mon, Jan 26, 2026 at 03:38:22PM -0800, Elson Serrao wrote:
>>> The Qualcomm Embedded USB Debugger (EUD) can intercept one or two
>>> independent High-Speed UTMI paths, depending on the SoC. Each path is
>>> distinct with its own HS-PHY interface, connector/controller wiring, and
> 
> [...]
> 
>>> +  supported on up to two High-Speed USB ports.
>>>  
>>>  properties:
>>>    compatible:
>>> @@ -29,26 +32,62 @@ properties:
>>>      description: EUD interrupt
>>>      maxItems: 1
>>>  
>>> -  ports:
>>> -    $ref: /schemas/graph.yaml#/properties/ports
>>
>> You are breaking existing users.
>>
> 
> Thanks Rob for your feedback.
> 
> The original motivation for the structural change was to make the binding
> encode resources/topology that were implicit before. Specifically the EUD
> intercept of the UTMI path(s) between the HS-USB PHY and the controller, and
> the need to represent platforms with two independent UTMI paths. That led me
> to introduce per-path nodes and a per-path PHY reference.

I do not see how this answers at all the comment, so no, it's still NAK.

> I outlined the constraints and rationale in this earlier thread:
> 
> https://lore.kernel.org/all/5cec9127-bdc5-49d7-80e1-2ae26f81163c@oss.qualcomm.com/

And you were supposed to keep things backwards compatible. Are they? Not.

Anyway, the reasoning cannot be somewhere else. Must be here in the commit.

> 
> 
>>> +  '#address-cells':
>>> +    const: 1
>>> +
>>> +  '#size-cells':
>>> +    const: 0
>>> +
>>> +patternProperties:
>>> +  "^eud-path@[0-1]$":
>>> +    type: object
>>>      description:
>>> -      These ports is to be attached to the endpoint of the DWC3 controller node
>>> -      and type C connector node. The controller has the "usb-role-switch"
>>> -      property.
>>> +      Represents one High-Speed UTMI path that EUD intercepts. This node models
>>> +      the physical data path intercepted by EUD and provides graph endpoints to
>>> +      link the USB controller and the external connector associated with this path.
>>>  
>>>      properties:
>>> -      port@0:
>>> -        $ref: /schemas/graph.yaml#/properties/port
>>> -        description: This port is to be attached to the DWC3 controller.
>>> +      reg:
>>> +        maxItems: 1
>>> +        description: Path number
>>> +
>>> +      phys:
>>> +        maxItems: 1
>>> +        description: High-Speed USB PHY associated with this data path.
>>
>> Doesn't the DWC3 node have a phys property? You don't need it twice 
>> since you can walk the graph.
>>
> 
> Yes, the DWC3 node does have a `phys` property. I added a PHY reference under
> EUD to make the dependency explicit, since the EUD debug module is independent
> and relies on the HS‑USB PHY for its operation.
> 
> If the preferred pattern is to rely on the controller’s `phys` and discover it
> by walking the graph, I’m happy to drop the duplicate reference. My only
> concern was whether that makes the dependency effectively implicit—i.e., EUD’s
> correctness would depend on a resource not directly referenced in its own
> binding. If my understanding of how this should be expressed in the binding is
> not correct, please let me know and I’ll adjust v3 accordingly.

Binding is not for drivers, so term "implicit" used before and now is
not correct. Does the EUD has dedicated different phy? Yes or not?

> 
> 
> 
>>> +
>>> +      usb-role-switch:
>>> +        type: boolean
>>> +        description:
>>> +          Set this property if the USB port on this path is role switch capable.
>>> +          In device role, debug mode inserts the EUD hub into the UTMI path. In
>>> +          host role, the EUD hub is bypassed and UTMI traffic flows directly
>>> +          between the PHY and the USB controller.
>>> +
>>> +      ports:
>>> +        $ref: /schemas/graph.yaml#/properties/ports
>>> +        description:
>>> +          These ports are to be attached to the endpoint of the USB controller node
>>> +          and USB connector node.
>>> +
>>> +        properties:
>>> +          port@0:
>>> +            $ref: /schemas/graph.yaml#/properties/port
>>> +            description: This port is to be attached to the USB controller.
>>>  
>>> -      port@1:
>>> -        $ref: /schemas/graph.yaml#/properties/port
>>> -        description: This port is to be attached to the type C connector.
>>> +          port@1:
>>> +            $ref: /schemas/graph.yaml#/properties/port
>>> +            description: This port is to be attached to the USB connector.
>>
>> Both port 0 and 1 are attached to the USB controller?
>>
> 
> No—only port@0 is attached to the USB controller; port@1 is attached to the USB
> connector.
> 
>> Why can't you just add more port nodes to the existing binding?
>>
> 
> Do you mean extending the existing top-level ports like this?
> 
>   - port@0: USB controller0
>   - port@1: USB connector0
>   - port@2: USB controller1
>   - port@3: USB connector1
> 
> My hesitation with a flat ports list is that it doesn’t encode which
> controller/connector pair belongs to which physical path through EUD.

What do you mean? The index defines exactly which path it is.

> A graph walk starting at Conn0 could also reach USB Ctrl1, even though
> these are independent paths and not interchangeable.
> 
> Below is the high‑level topology of EUD connections. In the disabled state,
> EUD is transparent and UTMI traffic flows directly from USB2PHY0/1 to USB
> Ctrl0/1. When EUD is enabled, the debug hub is inserted on the selected path
> by the internal UTMI switch, so UTMI traffic on that path traverses the hub.
> The non‑selected path continues as a direct PHY↔Controller link (EUD can be
> enabled on only one path at a time).
> 
> 
> 
> 					EUD Block
> 			   +------------------------------+  
> 			   |                              |
> [Conn0]-->[USB2PHY0 ]----->|  -------- Path 0 ------------|--> [ USB Ctrl0 ]
> 			   |                              |  
> [Conn1]-->[USB2PHY1 ]----->|  -------- Path 1 ------------|--> [ USB Ctrl1 ]
> 			   |                              |
> 			   |      +------------------+    |
> 			   |      |  EUD Debug Hub   |    |
> 			   |      +------------------+    |
> 			   +------------------------------+
> 
> 
> 
> So to make the connector–controller relationships explicit, I kept the `ports`
> property under the `eud-path@N` child nodes. Please let me know if there is a
> preferable way to model this.
> 
> Thanks
> Elson
> 
> 


Best regards,
Krzysztof

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

* Re: [PATCH v2 6/9] usb: misc: qcom_eud: add host mode coordination
  2026-02-09 17:37     ` Elson Serrao
@ 2026-02-10 10:00       ` Konrad Dybcio
  0 siblings, 0 replies; 25+ messages in thread
From: Konrad Dybcio @ 2026-02-10 10:00 UTC (permalink / raw)
  To: Elson Serrao, Greg Kroah-Hartman, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Souradeep Chowdhury
  Cc: linux-arm-msm, devicetree, linux-usb, linux-kernel

On 2/9/26 6:37 PM, Elson Serrao wrote:
> 
> 
> On 2/4/2026 5:29 AM, Konrad Dybcio wrote:
>> On 1/27/26 12:38 AM, Elson Serrao wrote:
>>> EUD functions by presenting itself as a USB device to the host PC for
>>> debugging, making it incompatible in USB host mode configurations.
>>> Enabling EUD, when in host mode can also cause the USB controller to
>>> misbehave as the EUD hub can only have one upstream facing port.
>>
>> Perhaps that's a silly idea, but would the device itself see
>> the debug hub, being able to essentially self-debug in a way?
>>
> 
> This isn’t supported by the current hardware topology.
> 
> When EUD is enabled, it enumerates as a USB device to an external host via its
> upstream-facing port, while the SoC USB controller sits behind the hub’s
> downstream-facing port. As a result, the controller cannot enumerate or
> interact with the EUD device itself, and host mode is mutually exclusive with
> EUD debug on this path.

OK, I see. Thanks

Konrad

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

end of thread, other threads:[~2026-02-10 10:00 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-26 23:38 [PATCH v2 0/9] Improve Qualcomm EUD driver and platform support Elson Serrao
2026-01-26 23:38 ` [PATCH v2 1/9] dt-bindings: soc: qcom: eud: Restructure to model multi-path hardware Elson Serrao
2026-02-03 13:35   ` Konrad Dybcio
2026-02-04 14:01   ` Konrad Dybcio
2026-02-06 14:55   ` Rob Herring
2026-02-10  4:32     ` Elson Serrao
2026-02-10  7:24       ` Krzysztof Kozlowski
2026-01-26 23:38 ` [PATCH v2 2/9] usb: misc: qcom_eud: add sysfs attribute for port selection Elson Serrao
2026-01-27 13:31   ` Konrad Dybcio
2026-01-26 23:38 ` [PATCH v2 3/9] usb: misc: qcom_eud: add per-path High-Speed PHY control Elson Serrao
2026-02-04 13:21   ` Konrad Dybcio
2026-02-09 17:23     ` Elson Serrao
2026-01-26 23:38 ` [PATCH v2 4/9] usb: misc: qcom_eud: add per-path role switch support Elson Serrao
2026-01-26 23:38 ` [PATCH v2 5/9] usb: misc: qcom_eud: improve enable_store API Elson Serrao
2026-02-04 13:24   ` Konrad Dybcio
2026-01-26 23:38 ` [PATCH v2 6/9] usb: misc: qcom_eud: add host mode coordination Elson Serrao
2026-02-04 13:29   ` Konrad Dybcio
2026-02-09 17:37     ` Elson Serrao
2026-02-10 10:00       ` Konrad Dybcio
2026-01-26 23:38 ` [PATCH v2 7/9] usb: misc: qcom_eud: fix virtual attach/detach event handling Elson Serrao
2026-02-04 13:32   ` Konrad Dybcio
2026-01-26 23:38 ` [PATCH v2 8/9] arm64: dts: qcom: kodiak: Align EUD node with binding Elson Serrao
2026-01-26 23:38 ` [PATCH v2 9/9] arm64: dts: qcom: qcs6490-rb3gen2: Enable EUD debug functionality Elson Serrao
2026-02-03 13:38   ` Konrad Dybcio
2026-02-09 17:06     ` Elson Serrao

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