USB: dwc3_otg: Reset hardware before starting peripheral
USB endpoints can be configured either in DBM or non-DBM mode.
DBM mode is used for BAM to BAM uses case e.g. QDSS, and
non-DBM mode is used for normal device use.
Once an endpoint is configured DBM mode mode, hardware has
to be RESET and re-initialized if endpoint has to be used in
non-DBM mode e.g. changing USB composition from QDSS to non-QDSS.
Currently hardware is RESET as part of moving from host to
peripheral mode. Move this RESET from stop_host to start_peripheral.
Additionally, user is required to reconnect USB cable for RESET to
take place.
CRs-Fixed: 432474
Change-Id: I12fe7d8a2523ba02f454e01191275fc71c3f0091
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 361aa32..eb879e3 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -179,16 +179,6 @@
return ret;
}
dwc3_otg_notify_host_mode(otg, on);
-
- /* Do block reset for Host <-> peripheral switching to work */
- if (ext_xceiv && ext_xceiv->otg_capability &&
- ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset();
-
- /* re-init core and OTG register as XHCI reset clears it */
- dwc3_post_host_reset_core_init(dwc);
- if (ext_xceiv && !ext_xceiv->otg_capability)
- dwc3_otg_reset(dotg);
}
return 0;
@@ -235,6 +225,8 @@
static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on)
{
struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
+ struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
+ struct dwc3 *dwc = dotg->dwc;
if (!otg->gadget)
return -EINVAL;
@@ -242,6 +234,22 @@
if (on) {
dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n",
__func__, otg->gadget->name);
+
+ /*
+ * Hardware reset is required to support below scenarios:
+ * 1. Host <-> peripheral switching
+ * 2. Once an endpoint is configured in DBM (BAM) mode, it
+ * can be unconfigured only after RESET
+ */
+ if (ext_xceiv && ext_xceiv->otg_capability &&
+ ext_xceiv->ext_block_reset)
+ ext_xceiv->ext_block_reset();
+
+ /* re-init core and OTG registers as block reset clears these */
+ dwc3_post_host_reset_core_init(dwc);
+ if (ext_xceiv && !ext_xceiv->otg_capability)
+ dwc3_otg_reset(dotg);
+
dwc3_otg_set_peripheral_regs(dotg);
usb_gadget_vbus_connect(otg->gadget);
} else {