Files
pmaports-rtwo/device/community/linux-pine64-pinephonepro/megi_patches/0082-usb-dwc3-Set-the-PHY-mode-before-starting-the-host.patch
T

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