Jiri Slaby 7a187a
From: Ziyang Huang <hzyitc@outlook.com>
Jiri Slaby 7a187a
Date: Tue, 21 Feb 2023 18:30:04 +0800
Jiri Slaby 7a187a
Subject: [PATCH] usb: dwc2: drd: fix inconsistent mode if
Jiri Slaby 7a187a
 role-switch-default-mode="host"
Jiri Slaby 7a187a
References: bsc#1012628
Jiri Slaby 7a187a
Patch-mainline: 6.2.9
Jiri Slaby 7a187a
Git-commit: 82f5332d3b9872ab5b287e85c57b76d8bb640cd1
Jiri Slaby 7a187a
Jiri Slaby 7a187a
commit 82f5332d3b9872ab5b287e85c57b76d8bb640cd1 upstream.
Jiri Slaby 7a187a
Jiri Slaby 7a187a
Some boards might use USB-A female connector for USB ports, however,
Jiri Slaby 7a187a
the port could be connected to a dual-mode USB controller, making it
Jiri Slaby 7a187a
also behaves as a peripheral device if male-to-male cable is connected.
Jiri Slaby 7a187a
Jiri Slaby 7a187a
In this case, the dts looks like this:
Jiri Slaby 7a187a
Jiri Slaby 7a187a
	&usb0 {
Jiri Slaby 7a187a
		status = "okay";
Jiri Slaby 7a187a
		dr_mode = "otg";
Jiri Slaby 7a187a
		usb-role-switch;
Jiri Slaby 7a187a
		role-switch-default-mode = "host";
Jiri Slaby 7a187a
	};
Jiri Slaby 7a187a
Jiri Slaby 7a187a
After boot, dwc2_ovr_init() sets GOTGCTL to GOTGCTL_AVALOVAL and call
Jiri Slaby 7a187a
dwc2_force_mode() with parameter host=false, which causes inconsistent
Jiri Slaby 7a187a
mode - The hardware is in peripheral mode while the kernel status is
Jiri Slaby 7a187a
in host mode.
Jiri Slaby 7a187a
Jiri Slaby 7a187a
What we can do now is to call dwc2_drd_role_sw_set() to switch to
Jiri Slaby 7a187a
device mode, and everything should work just fine now, even switching
Jiri Slaby 7a187a
back to none(default) mode afterwards.
Jiri Slaby 7a187a
Jiri Slaby 7a187a
Fixes: e14acb876985 ("usb: dwc2: drd: add role-switch-default-node support")
Jiri Slaby 7a187a
Cc: stable <stable@kernel.org>
Jiri Slaby 7a187a
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Jiri Slaby 7a187a
Tested-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
Jiri Slaby 7a187a
Acked-by: Minas Harutyunyan <hminas@synopsys.com>
Jiri Slaby 7a187a
Reviewed-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
Jiri Slaby 7a187a
Link: https://lore.kernel.org/r/SG2PR01MB204837BF68EDB0E343D2A375C9A59@SG2PR01MB2048.apcprd01.prod.exchangelabs.com
Jiri Slaby 7a187a
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby 7a187a
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 7a187a
---
Jiri Slaby 7a187a
 drivers/usb/dwc2/drd.c | 3 ++-
Jiri Slaby 7a187a
 1 file changed, 2 insertions(+), 1 deletion(-)
Jiri Slaby 7a187a
Jiri Slaby 7a187a
diff --git a/drivers/usb/dwc2/drd.c b/drivers/usb/dwc2/drd.c
Jiri Slaby 7a187a
index d8d6493b..a8605b02 100644
Jiri Slaby 7a187a
--- a/drivers/usb/dwc2/drd.c
Jiri Slaby 7a187a
+++ b/drivers/usb/dwc2/drd.c
Jiri Slaby 7a187a
@@ -35,7 +35,8 @@ static void dwc2_ovr_init(struct dwc2_hsotg *hsotg)
Jiri Slaby 7a187a
 
Jiri Slaby 7a187a
 	spin_unlock_irqrestore(&hsotg->lock, flags);
Jiri Slaby 7a187a
 
Jiri Slaby 7a187a
-	dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST));
Jiri Slaby 7a187a
+	dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST) ||
Jiri Slaby 7a187a
+				(hsotg->role_sw_default_mode == USB_DR_MODE_HOST));
Jiri Slaby 7a187a
 }
Jiri Slaby 7a187a
 
Jiri Slaby 7a187a
 static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid)
Jiri Slaby 7a187a
-- 
Jiri Slaby 7a187a
2.35.3
Jiri Slaby 7a187a