Re: [PATCH v5 5/5] usb: dwc3: qcom: Modify interrupt handling for eUSB2 Phy targets
Thinh Nguyen <[email protected]> Tue, 4 Aug 2026 22:01:08 +0000
| Newsgroups | org.kernel.vger.linux-arm-msm,org.infradead.lists.linux-phy,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel,org.kernel.vger.linux-usb |
|---|---|
| Message-ID | <anJgBMFlzHGaVNMm@vbox> |
On Thu, Jul 23, 2026, Krishna Kurapati wrote: > 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. > > Signed-off-by: Krishna Kurapati <[email protected]> > --- > drivers/usb/dwc3/dwc3-qcom.c | 53 +++++++++++++++++++++++++++++++++++--------- > 1 file changed, 43 insertions(+), 10 deletions(-) > > diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c > index f43f73ac36ff..4c559b97c627 100644 > --- a/drivers/usb/dwc3/dwc3-qcom.c > +++ b/drivers/usb/dwc3/dwc3-qcom.c > @@ -85,6 +85,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) > @@ -272,15 +273,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); > @@ -289,8 +298,10 @@ 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); > > /* > @@ -303,12 +314,20 @@ static void dwc3_qcom_enable_port_interrupts(struct dwc3_qcom_port *port) > */ > > 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); > @@ -324,7 +343,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) > @@ -332,7 +351,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) > @@ -617,6 +636,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) > @@ -683,6 +703,19 @@ static int dwc3_qcom_probe(struct platform_device *pdev) > if (ignore_pipe_clk) > dwc3_qcom_select_utmi_clk(qcom); > > + if (qcom->num_ports == 1) > + phy = devm_phy_get(dev, "usb2-phy"); > + else > + phy = devm_phy_get(dev, "usb2-0"); Looks like you're getting the first phy? If so, can we just use devm_of_phy_get_by_index(dev, dev->of_node, 0) instead of hard coding the names? Thanks, Thinh > + > + if (IS_ERR(phy)) { > + if (PTR_ERR(phy) != -ENODEV) > + return dev_err_probe(dev, PTR_ERR(phy), > + "failed to get usb2 phy\n"); > + phy = NULL; > + } > + qcom->has_eusb2_phy = phy && (phy_get_type(phy) == PHY_TYPE_EUSB2); > + > qcom->mode = usb_get_dr_mode(dev); > > if (qcom->mode == USB_DR_MODE_HOST) { > > -- > 2.34.1 >