Signed-off-by: Rudraksha Gupta <guptarud@gmail.com> Part-of: <https://gitlab.postmarketos.org/postmarketOS/pmaports/-/merge_requests/9440>
73 lines
2.7 KiB
Diff
73 lines
2.7 KiB
Diff
From 4b4a12e0628238d945c214f8d324801d710aa704 Mon Sep 17 00:00:00 2001
|
|
From: Ondrej Jirman <megi@xff.cz>
|
|
Date: Tue, 21 Jul 2026 07:43:34 +0200
|
|
Subject: [PATCH 82/90] usb: dwc3: Set the PHY mode before starting the host
|
|
|
|
The device case tells the PHYs the role before dwc3_gadget_init(), but
|
|
the host case tells them only after dwc3_host_init() has returned.
|
|
dwc3_host_init() runs the xHCI probe, which uses the PHYs and can take a
|
|
long time, so a PHY that acts on the mode does not find out until the
|
|
controller has already been using it the other way round.
|
|
|
|
On a PinePhone Pro the USB2 PHY uses the mode to know it must not run
|
|
BC1.2 charger detection, because in host mode VBUS is ours and the bus
|
|
is in use. It was told 15.7 s after VBUS came up, by which point
|
|
detection had run to completion, decided the port was a floating
|
|
charger, and powered the USB2 PHY off underneath the probe:
|
|
|
|
46.498 FUSB vbus := on
|
|
46.774 xhci-hcd: new USB bus registered, assigned bus number 8
|
|
48.514 charger = USB_DCP_CHARGER
|
|
48.534 U2PHY power_off
|
|
62.238 xhci-hcd: Host halt failed, -110
|
|
62.254 U2PHY set_mode: host=1
|
|
|
|
Move the mode setting ahead of dwc3_host_init(), which also makes the
|
|
two cases consistent.
|
|
|
|
Signed-off-by: Ondrej Jirman <megi@xff.cz>
|
|
---
|
|
drivers/usb/dwc3/core.c | 22 ++++++++++++++--------
|
|
1 file changed, 14 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
|
|
index 7e86dce3d317..3ff55af69018 100644
|
|
--- a/drivers/usb/dwc3/core.c
|
|
+++ b/drivers/usb/dwc3/core.c
|
|
@@ -314,18 +314,24 @@ static void __dwc3_set_mode(struct work_struct *work)
|
|
|
|
switch (role_changed ? desired_dr_role : 0) {
|
|
case DWC3_GCTL_PRTCAP_HOST:
|
|
+ /*
|
|
+ * Tell the PHYs the role before starting the host, the way the
|
|
+ * device case does. dwc3_host_init() runs the xHCI probe, which
|
|
+ * uses the PHYs and can take a long time, so a PHY that acts on
|
|
+ * the mode must not be told about it only afterwards.
|
|
+ */
|
|
+ if (dwc->usb2_phy)
|
|
+ otg_set_vbus(dwc->usb2_phy->otg, true);
|
|
+
|
|
+ for (i = 0; i < dwc->num_usb2_ports; i++)
|
|
+ phy_set_mode(dwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
|
|
+ for (i = 0; i < dwc->num_usb3_ports; i++)
|
|
+ phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
|
|
+
|
|
ret = dwc3_host_init(dwc);
|
|
if (ret) {
|
|
dev_err(dwc->dev, "failed to initialize host\n");
|
|
} else {
|
|
- if (dwc->usb2_phy)
|
|
- otg_set_vbus(dwc->usb2_phy->otg, true);
|
|
-
|
|
- for (i = 0; i < dwc->num_usb2_ports; i++)
|
|
- phy_set_mode(dwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
|
|
- for (i = 0; i < dwc->num_usb3_ports; i++)
|
|
- phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
|
|
-
|
|
if (dwc->dis_split_quirk) {
|
|
reg = dwc3_readl(dwc, DWC3_GUCTL3);
|
|
reg |= DWC3_GUCTL3_SPLITDISABLE;
|
|
--
|
|
2.55.0
|
|
|