From 7edf9e6a06bbe557d0283c1bee43d19e27d916d3 Mon Sep 17 00:00:00 2001 From: Swapnil Jakhade Date: Mon, 12 Jan 2026 11:16:30 +0530 Subject: [PATCH 1/6] UPSTREAM: dt-bindings: phy: Add PHY_TYPE_XAUI definition XAUI (eXtended Attachment Unit Interface) is a high-speed serial interface standard for 10 Gigabit Ethernet (10GbE). It uses four lanes with each lane operating at 3.125 Gbps (totaling 10 Gbps), to extend the XGMII interface across circuit boards, commonly used in backplanes for networking switches and high-performance computing. XAUI is defined as a standardized instantiation of XGMII Extender in the IEEE 802.3 specification. Add definition for XAUI PHY type. Signed-off-by: Swapnil Jakhade [s-vadapalli: added detailed description of XAUI in the commit message] Signed-off-by: Siddharth Vadapalli Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260112054636.108027-2-s-vadapalli@ti.com Signed-off-by: Vinod Koul Signed-off-by: Krishna Kurapati --- include/dt-bindings/phy/phy.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h index 6b901b3423486..d77b372d302f5 100644 --- a/include/dt-bindings/phy/phy.h +++ b/include/dt-bindings/phy/phy.h @@ -23,5 +23,6 @@ #define PHY_TYPE_DPHY 10 #define PHY_TYPE_CPHY 11 #define PHY_TYPE_USXGMII 12 +#define PHY_TYPE_XAUI 13 #endif /* _DT_BINDINGS_PHY */ From 89321e48c855bf471218a821d7c165a365f21c61 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sun, 13 Sep 2026 20:10:44 +0530 Subject: [PATCH 2/6] FROMLIST: dt-bindings: phy: Add PHY_TYPE_EUSB2 definition eUSB2 (Embedded USB2) is a MIPI Alliance standard for chip-to-chip USB2 signaling. Unlike standard USB2, which uses 3.3V signaling, eUSB2 uses low-voltage differential signaling (~0.4V) and requires a repeater to interface with external USB2 ports. Because of these differences, eUSB2 PHY initialization sequences, voltage tuning, and register configuration are distinct from USB2. Additionally, eUSB2 targets handle wakeup interrupts differently depending on device speed when operating in host mode. According to the eUSB2 specification, remote wakeup signaling in host mode is detected via different data-line assertions based on the connected device speed: - Low-speed devices: the host repeater drives eD+ to logic '1' upon detecting a K-state on the USB lines during remote wakeup (eUSB2 spec, Section 5.5.14). - Full-speed/high-speed devices: the host repeater drives eD- to logic '1' upon detecting a K-state during remote wakeup (eUSB2 spec, Sections 5.5.15 and 5.5.18). Since the eUSB2 PHY's DP and DM lines need to be configured differently from USB2 PHYs, controllers should be able to query the PHY type and configure wakeup interrupts accordingly. Add PHY_TYPE_EUSB2 to distinguish eUSB2 PHYs from standard USB2 PHYs. Link: https://lore.kernel.org/all/20260913-eusb2-interrupt-v8-v8-1-0f505b9c394b@oss.qualcomm.com/ Acked-by: Krzysztof Kozlowski Reviewed-by: Manivannan Sadhasivam Signed-off-by: Krishna Kurapati --- include/dt-bindings/phy/phy.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h index d77b372d302f5..c9e8fa6975711 100644 --- a/include/dt-bindings/phy/phy.h +++ b/include/dt-bindings/phy/phy.h @@ -24,5 +24,6 @@ #define PHY_TYPE_CPHY 11 #define PHY_TYPE_USXGMII 12 #define PHY_TYPE_XAUI 13 +#define PHY_TYPE_EUSB2 14 #endif /* _DT_BINDINGS_PHY */ From f428fad161d7cfea5ea87ed23231ec4b709ef254 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sun, 13 Sep 2026 20:10:45 +0530 Subject: [PATCH 3/6] FROMLIST: include: linux: phy: Add phy attribute "type" and associated helpers In cases like USB High-speed phys which can be either USB2 or EUSB2, it is required to know the type of phy (rather than the operating mode) because DP and DM interrupt lines need to be configured differently for each of them. Add support to cache the PHY_TYPE and add the following helpers: - phy_set_type() for the phy drivers (like m31_eusb2 or snps-eusb2) to declare what type of PHY they are (in this case PHY_TYPE_EUSB2). - phy_get_type() for the consumers (like USB controllers) to query the type of phy connected to them. Link: https://lore.kernel.org/all/20260913-eusb2-interrupt-v8-v8-2-0f505b9c394b@oss.qualcomm.com/ Reviewed-by: Thinh Nguyen Reviewed-by: Manivannan Sadhasivam Signed-off-by: Krishna Kurapati --- include/linux/phy/phy.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 13add0c2c4072..c6003fd7b27d3 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -21,6 +21,8 @@ #include #include +#include + struct phy; enum phy_mode { @@ -141,11 +143,13 @@ struct phy_ops { * @bus_width: Data path width implemented by PHY * @max_link_rate: Maximum link rate supported by PHY (units to be decided by producer and consumer) * @mode: PHY mode + * @type: PHY type */ struct phy_attrs { u32 bus_width; u32 max_link_rate; enum phy_mode mode; + int type; }; /** @@ -251,6 +255,20 @@ static inline enum phy_mode phy_get_mode(struct phy *phy) { return phy->attrs.mode; } + +static inline int phy_get_type(struct phy *phy) +{ + if (phy) + return phy->attrs.type; + + return PHY_NONE; +} + +static inline void phy_set_type(struct phy *phy, int type) +{ + phy->attrs.type = type; +} + int phy_reset(struct phy *phy); int phy_calibrate(struct phy *phy); int phy_notify_connect(struct phy *phy, int port); @@ -384,6 +402,15 @@ static inline enum phy_mode phy_get_mode(struct phy *phy) return PHY_MODE_INVALID; } +static inline int phy_get_type(struct phy *phy) +{ + return PHY_NONE; +} + +static inline void phy_set_type(struct phy *phy, int type) +{ +} + static inline int phy_reset(struct phy *phy) { if (!phy) From 953d41af79fba130ee0ecc6dc3f2826688d73bc9 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sun, 13 Sep 2026 20:10:46 +0530 Subject: [PATCH 4/6] FROMLIST: phy: snps-eusb2: Set phy type to EUSB2 USB controllers like DWC3 are agnostic of the kind of phy (USB2/eUSB2) connected to it. Set the phy type to EUSB2 to let the controller know the phy type when queried during its probe. Link: https://lore.kernel.org/all/20260913-eusb2-interrupt-v8-v8-3-0f505b9c394b@oss.qualcomm.com/ Reviewed-by: Thinh Nguyen Reviewed-by: Manivannan Sadhasivam Signed-off-by: Krishna Kurapati --- drivers/phy/phy-snps-eusb2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/phy/phy-snps-eusb2.c b/drivers/phy/phy-snps-eusb2.c index f90bf7e95463b..fe4ce9d752f71 100644 --- a/drivers/phy/phy-snps-eusb2.c +++ b/drivers/phy/phy-snps-eusb2.c @@ -597,6 +597,8 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev) return PTR_ERR(generic_phy); } + phy_set_type(generic_phy, PHY_TYPE_EUSB2); + dev_set_drvdata(dev, phy); phy_set_drvdata(generic_phy, phy); From f83592c99309d7a75002b42994e30b58ecadfb20 Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sun, 13 Sep 2026 20:10:47 +0530 Subject: [PATCH 5/6] FROMLIST: phy: qcom: m31-eusb2: Set phy type to EUSB2 USB controllers like DWC3 are agnostic of the kind of phy (USB2/eUSB2) connected to it. Set the phy type to EUSB2 to let the controller know the phy type when queried during its probe. Link: https://lore.kernel.org/all/20260913-eusb2-interrupt-v8-v8-4-0f505b9c394b@oss.qualcomm.com/ Reviewed-by: Thinh Nguyen Reviewed-by: Manivannan Sadhasivam Signed-off-by: Krishna Kurapati --- drivers/phy/qualcomm/phy-qcom-m31-eusb2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c index 9434bd22ef32d..7e1b36e9d4ab9 100644 --- a/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c @@ -277,6 +277,8 @@ static int m31eusb2_phy_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(phy->phy), "failed to create phy\n"); + phy_set_type(phy->phy, PHY_TYPE_EUSB2); + ret = devm_regulator_bulk_get_const(dev, M31_EUSB_NUM_VREGS, m31_eusb_phy_vregs, &phy->vregs); if (ret) From 74f327c6b55940a693d128e5e9473182ef846c9c Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Sun, 13 Sep 2026 20:10:48 +0530 Subject: [PATCH 6/6] FROMLIST: usb: dwc3: qcom: Modify interrupt handling for eUSB2 Phy targets eUSB2 targets handle wakeup interrupts differently depending on device speed when operating in host mode. According to the eUSB2 specification, remote wakeup signaling in host mode is detected via different data-line assertions based on the connected device speed. When a low-speed device is connected, the host repeater drives eD+ to logic '1' upon detecting a K-state on the USB lines during remote wakeup (eUSB2 specification, Section 5.5.14). When a full-speed or high-speed device is connected, the host repeater drives eD- to logic '1' upon detecting a K-state on the USB line during remote wakeup (eUSB2 specification, Sections 5.5.15 and 5.5.18). Since the eUSB2 PHY's "DP" and "DM" interrupt lines monitor the eD+ and eD- line states, query the phy type and configure the wakeup interrupts accordingly. Link: https://lore.kernel.org/all/20260913-eusb2-interrupt-v8-v8-5-0f505b9c394b@oss.qualcomm.com/ Acked-by: Thinh Nguyen Acked-by: Konrad Dybcio Signed-off-by: Krishna Kurapati --- drivers/usb/dwc3/dwc3-qcom.c | 63 +++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 5d131a33ae5a4..f865c922f7d3f 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -86,6 +86,7 @@ struct dwc3_qcom { struct icc_path *icc_path_apps; enum usb_role current_role; + bool has_eusb2_phy; }; #define to_dwc3_qcom(d) container_of((d), struct dwc3_qcom, dwc) @@ -273,15 +274,23 @@ static void dwc3_qcom_disable_wakeup_irq(int irq) disable_irq_nosync(irq); } -static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port) +static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom *qcom, int port_index) { + struct dwc3_qcom_port *port = &qcom->ports[port_index]; + dwc3_qcom_disable_wakeup_irq(port->qusb2_phy_irq); if (port->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); + if (qcom->has_eusb2_phy) + dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); + else + dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); } else if ((port->usb2_speed == USB_SPEED_HIGH) || (port->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); + if (qcom->has_eusb2_phy) + dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); + else + dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); } else { dwc3_qcom_disable_wakeup_irq(port->dp_hs_phy_irq); dwc3_qcom_disable_wakeup_irq(port->dm_hs_phy_irq); @@ -290,26 +299,38 @@ static void dwc3_qcom_disable_port_interrupts(struct dwc3_qcom_port *port) dwc3_qcom_disable_wakeup_irq(port->ss_phy_irq); } -static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port) +static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom *qcom, int port_index) { + struct dwc3_qcom_port *port = &qcom->ports[port_index]; + dwc3_qcom_enable_wakeup_irq(port->qusb2_phy_irq, 0); /* * Configure DP/DM line interrupts based on the USB2 device attached to - * the root hub port. When HS/FS device is connected, configure the DP line - * as falling edge to detect both disconnect and remote wakeup scenarios. When - * LS device is connected, configure DM line as falling edge to detect both - * disconnect and remote wakeup. When no device is connected, configure both - * DP and DM lines as rising edge to detect HS/HS/LS device connect scenario. + * the root hub port. For non-eUSB2 targets, when HS/FS device is connected, + * configure the DP line as falling edge to detect disconnect and remote + * wakeup. When LS device is connected, configure the DM line as falling edge + * for the same. For eUSB2 targets, the lines are swapped and rising edge is + * used: DP line for LS and DM line for HS/FS device detection. When no + * device is connected, configure both DP and DM lines as rising edge to + * detect HS/FS/LS device connect scenario. */ if (port->usb2_speed == USB_SPEED_LOW) { - dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, - IRQ_TYPE_EDGE_FALLING); + if (qcom->has_eusb2_phy) + dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, + IRQ_TYPE_EDGE_RISING); + else + dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, + IRQ_TYPE_EDGE_FALLING); } else if ((port->usb2_speed == USB_SPEED_HIGH) || (port->usb2_speed == USB_SPEED_FULL)) { - dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, - IRQ_TYPE_EDGE_FALLING); + if (qcom->has_eusb2_phy) + dwc3_qcom_enable_wakeup_irq(port->dm_hs_phy_irq, + IRQ_TYPE_EDGE_RISING); + else + dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, + IRQ_TYPE_EDGE_FALLING); } else { dwc3_qcom_enable_wakeup_irq(port->dp_hs_phy_irq, IRQ_TYPE_EDGE_RISING); @@ -325,7 +346,7 @@ static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) int i; for (i = 0; i < qcom->num_ports; i++) - dwc3_qcom_disable_port_interrupts(&qcom->ports[i]); + dwc3_qcom_disable_port_interrupts(qcom, i); } static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) @@ -333,7 +354,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) int i; for (i = 0; i < qcom->num_ports; i++) - dwc3_qcom_enable_port_interrupts(&qcom->ports[i]); + dwc3_qcom_enable_port_interrupts(qcom, i); } static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) @@ -620,6 +641,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) int ret; bool ignore_pipe_clk; bool wakeup_source; + struct phy *phy; qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL); if (!qcom) @@ -686,6 +708,17 @@ static int dwc3_qcom_probe(struct platform_device *pdev) if (ignore_pipe_clk) dwc3_qcom_select_utmi_clk(qcom); + phy = devm_of_phy_get_by_index(dev, dev->of_node, 0); + if (IS_ERR(phy)) { + if (PTR_ERR(phy) != -ENODEV) { + ret = dev_err_probe(dev, PTR_ERR(phy), + "failed to get usb2 phy\n"); + goto clk_disable; + } + phy = NULL; + } + qcom->has_eusb2_phy = (phy_get_type(phy) == PHY_TYPE_EUSB2); + qcom->mode = usb_get_dr_mode(dev); if (qcom->mode == USB_DR_MODE_HOST) {