linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFT PATCH v2 0/4] usb: dwc2: Fix core reset and force mode delays
@ 2016-08-24 23:19 John Youn
  2016-08-24 23:19 ` [RFT PATCH v2 1/4] usb: dwc2: gadget: Only initialize device if in device mode John Youn
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: John Youn @ 2016-08-24 23:19 UTC (permalink / raw)
  To: linux-usb
  Cc: johnyoun, Stefan Wahren, Michael Niewoehner, Felipe Balbi,
	Tao Huang, Julius Werner, linux-kernel, Caesar Wang,
	Heiko Stuebner, Remi Pommarel, Kever Yang, Doug Anderson,
	Stephen Warren, linux-rpi-kernel, linux-arm-kernel

The following patch series addresses the core reset and force mode
delay problems seen on some platforms.

It is basically the same as this series of patches sent earlier this
year:

http://marc.info/?l=linux-usb&m=145921907525708&w=2

Except the first patch is omitted (already upstream) and the last
patch is broken up into two patches.

This series is trying to account for a variable delay from the IDDIG
debounce filter when switching modes. This delay is a function of the
PHY clock speed and can range from 5-50 ms. This delay must be taken
into account on core reset and force modes. A full explanation is
provided in the patch commit log and code comments.

Patch 1 is a prerequisite to this fix.

Patch 2 implements the delay for core reset.

Patch 3 implements the delay for set/clear force modes.

Patch 4 makes further optimizations to remove unnecessary calls to
reset and force mode and avoid extra delays in the driver.

RK3188 platforms:

Michael Niewoehner reported problems with the previous set of patches
that I suspect have to do with the last patch of this series.

On Raspberry PI platforms:

Stefan Wahren reported problems that should be solved by patches 1-3
of this series.

Appreciate testing on these and any other platforms.

Patch 1-2 can probably be merged right now as they shouldn't break
anything.

Patch 3 should solve the RPI problems and shouldn't have any issues on
rk3188 either.

Patch 4 likely will have the same issue as with rk3188 and will need
to be investigated at a later time.

Regards,
John

John Youn (4):
  usb: dwc2: gadget: Only initialize device if in device mode
  usb: dwc2: Add delay to core soft reset
  usb: dwc2: Properly account for the force mode delays
  usb: dwc2: Force mode optimizations

 drivers/usb/dwc2/core.c     | 195 ++++++++++++++++++++++++++++----------------
 drivers/usb/dwc2/core.h     |   2 +-
 drivers/usb/dwc2/gadget.c   |   7 +-
 drivers/usb/dwc2/hcd.c      |   6 +-
 drivers/usb/dwc2/hw.h       |   1 +
 drivers/usb/dwc2/platform.c |   9 +-
 6 files changed, 143 insertions(+), 77 deletions(-)

-- 
2.9.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RFT PATCH v2 1/4] usb: dwc2: gadget: Only initialize device if in device mode
  2016-08-24 23:19 [RFT PATCH v2 0/4] usb: dwc2: Fix core reset and force mode delays John Youn
@ 2016-08-24 23:19 ` John Youn
  2016-08-24 23:19 ` [RFT PATCH v2 2/4] usb: dwc2: Add delay to core soft reset John Youn
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: John Youn @ 2016-08-24 23:19 UTC (permalink / raw)
  To: linux-usb
  Cc: johnyoun, Stefan Wahren, Michael Niewoehner, Felipe Balbi,
	Tao Huang, Julius Werner, linux-kernel, Caesar Wang,
	Heiko Stuebner, Remi Pommarel, Kever Yang, Doug Anderson,
	Stephen Warren, linux-rpi-kernel, linux-arm-kernel

In dwc2_hsotg_udc_start(), don't initialize the controller for device
mode unless we are actually in device mode.

Signed-off-by: John Youn <johnyoun@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index af46adf..358ba5a 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3475,8 +3475,11 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
 		otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget);
 
 	spin_lock_irqsave(&hsotg->lock, flags);
-	dwc2_hsotg_init(hsotg);
-	dwc2_hsotg_core_init_disconnected(hsotg, false);
+	if (dwc2_hw_is_device(hsotg)) {
+		dwc2_hsotg_init(hsotg);
+		dwc2_hsotg_core_init_disconnected(hsotg, false);
+	}
+
 	hsotg->enabled = 0;
 	spin_unlock_irqrestore(&hsotg->lock, flags);
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFT PATCH v2 2/4] usb: dwc2: Add delay to core soft reset
  2016-08-24 23:19 [RFT PATCH v2 0/4] usb: dwc2: Fix core reset and force mode delays John Youn
  2016-08-24 23:19 ` [RFT PATCH v2 1/4] usb: dwc2: gadget: Only initialize device if in device mode John Youn
@ 2016-08-24 23:19 ` John Youn
  2016-08-24 23:20 ` [RFT PATCH v2 3/4] usb: dwc2: Properly account for the force mode delays John Youn
  2016-08-24 23:20 ` [RFT PATCH v2 4/4] usb: dwc2: Force mode optimizations John Youn
  3 siblings, 0 replies; 5+ messages in thread
From: John Youn @ 2016-08-24 23:19 UTC (permalink / raw)
  To: linux-usb
  Cc: johnyoun, Stefan Wahren, Michael Niewoehner, Felipe Balbi,
	Tao Huang, Julius Werner, linux-kernel, Caesar Wang,
	Heiko Stuebner, Remi Pommarel, Kever Yang, Doug Anderson,
	Stephen Warren, linux-rpi-kernel, linux-arm-kernel

Add a delay to the core soft reset function to account for the IDDIG
debounce filter.

If the current mode is host, either due to the force mode bit being
set (which persists after core reset) or the connector id pin, a core
soft reset will temporarily reset the mode to device and a delay from
the IDDIG debounce filter will occur before going back to host mode.

Signed-off-by: John Youn <johnyoun@synopsys.com>
---
 drivers/usb/dwc2/core.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/dwc2/core.h |  1 +
 drivers/usb/dwc2/hw.h   |  1 +
 3 files changed, 99 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 4135a5f..bb903e2 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -238,6 +238,78 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
 	return ret;
 }
 
+/**
+ * dwc2_wait_for_mode() - Waits for the controller mode.
+ * @hsotg:	Programming view of the DWC_otg controller.
+ * @host_mode:	If true, waits for host mode, otherwise device mode.
+ * @timeout:	Time to wait in ms.
+ */
+static void dwc2_wait_for_mode(struct dwc2_hsotg *hsotg,
+			       bool host_mode,
+			       unsigned int timeout)
+{
+	ktime_t start;
+	ktime_t end;
+
+	dev_vdbg(hsotg->dev, "Waiting for %s mode\n",
+		 host_mode ? "host" : "device");
+
+	start = ktime_get();
+
+	while (1) {
+		s64 ms;
+
+		if (dwc2_is_host_mode(hsotg) == host_mode) {
+			dev_vdbg(hsotg->dev, "%s mode set\n",
+				 host_mode ? "Host" : "Device");
+			break;
+		}
+
+		end = ktime_get();
+		ms = ktime_to_ms(ktime_sub(end, start));
+
+		if (ms >= (s64)timeout) {
+			dev_warn(hsotg->dev, "%s: Couldn't set %s mode\n",
+				 __func__, host_mode ? "host" : "device");
+			break;
+		}
+
+		usleep_range(1000, 2000);
+	}
+}
+
+/**
+ * dwc2_iddig_filter_enabled() - Returns true if the IDDIG debounce
+ * filter is enabled.
+ */
+static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg)
+{
+	u32 gsnpsid;
+	u32 ghwcfg4;
+
+	if (!dwc2_hw_is_otg(hsotg))
+		return false;
+
+	/* Check if core configuration includes the IDDIG filter. */
+	ghwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
+	if (!(ghwcfg4 & GHWCFG4_IDDIG_FILT_EN))
+		return false;
+
+	/*
+	 * Check if the IDDIG debounce filter is bypassed. Available
+	 * in core version >= 3.10a.
+	 */
+	gsnpsid = dwc2_readl(hsotg->regs + GSNPSID);
+	if (gsnpsid >= DWC2_CORE_REV_3_10a) {
+		u32 gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+
+		if (gotgctl & GOTGCTL_DBNCE_FLTR_BYPASS)
+			return false;
+	}
+
+	return true;
+}
+
 /*
  * Do core a soft reset of the core.  Be careful with this because it
  * resets all the internal state machines of the core.
@@ -246,9 +318,30 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
 {
 	u32 greset;
 	int count = 0;
+	bool wait_for_host_mode = false;
 
 	dev_vdbg(hsotg->dev, "%s()\n", __func__);
 
+	/*
+	 * If the current mode is host, either due to the force mode
+	 * bit being set (which persists after core reset) or the
+	 * connector id pin, a core soft reset will temporarily reset
+	 * the mode to device. A delay from the IDDIG debounce filter
+	 * will occur before going back to host mode.
+	 *
+	 * Determine whether we will go back into host mode after a
+	 * reset and account for this delay after the reset.
+	 */
+	if (dwc2_iddig_filter_enabled(hsotg)) {
+		u32 gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+		u32 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+
+		if (!(gotgctl & GOTGCTL_CONID_B) ||
+		    (gusbcfg & GUSBCFG_FORCEHOSTMODE)) {
+			wait_for_host_mode = true;
+		}
+	}
+
 	/* Core Soft Reset */
 	greset = dwc2_readl(hsotg->regs + GRSTCTL);
 	greset |= GRSTCTL_CSFTRST;
@@ -277,6 +370,10 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
 		}
 	} while (!(greset & GRSTCTL_AHBIDLE));
 
+	/* Wait up to 50 ms for the IDDIG debounce filter. */
+	if (wait_for_host_mode)
+		dwc2_wait_for_mode(hsotg, true, 50);
+
 	return 0;
 }
 
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index d645512..2a21a04 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -890,6 +890,7 @@ struct dwc2_hsotg {
 #define DWC2_CORE_REV_2_92a	0x4f54292a
 #define DWC2_CORE_REV_2_94a	0x4f54294a
 #define DWC2_CORE_REV_3_00a	0x4f54300a
+#define DWC2_CORE_REV_3_10a	0x4f54310a
 
 #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
 	union dwc2_hcd_internal_flags {
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
index efc3bcd..9105844 100644
--- a/drivers/usb/dwc2/hw.h
+++ b/drivers/usb/dwc2/hw.h
@@ -48,6 +48,7 @@
 #define GOTGCTL_ASESVLD			(1 << 18)
 #define GOTGCTL_DBNC_SHORT		(1 << 17)
 #define GOTGCTL_CONID_B			(1 << 16)
+#define GOTGCTL_DBNCE_FLTR_BYPASS	(1 << 15)
 #define GOTGCTL_DEVHNPEN		(1 << 11)
 #define GOTGCTL_HSTSETHNPEN		(1 << 10)
 #define GOTGCTL_HNPREQ			(1 << 9)
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFT PATCH v2 3/4] usb: dwc2: Properly account for the force mode delays
  2016-08-24 23:19 [RFT PATCH v2 0/4] usb: dwc2: Fix core reset and force mode delays John Youn
  2016-08-24 23:19 ` [RFT PATCH v2 1/4] usb: dwc2: gadget: Only initialize device if in device mode John Youn
  2016-08-24 23:19 ` [RFT PATCH v2 2/4] usb: dwc2: Add delay to core soft reset John Youn
@ 2016-08-24 23:20 ` John Youn
  2016-08-24 23:20 ` [RFT PATCH v2 4/4] usb: dwc2: Force mode optimizations John Youn
  3 siblings, 0 replies; 5+ messages in thread
From: John Youn @ 2016-08-24 23:20 UTC (permalink / raw)
  To: linux-usb
  Cc: johnyoun, Stefan Wahren, Michael Niewoehner, Felipe Balbi,
	Tao Huang, Julius Werner, linux-kernel, Caesar Wang,
	Heiko Stuebner, Remi Pommarel, Kever Yang, Doug Anderson,
	Stephen Warren, linux-rpi-kernel, linux-arm-kernel

When a force mode bit is set and the IDDIG debounce filter is enabled,
there is a delay for the forced mode to take effect. This delay is due
to the IDDIG debounce filter and is variable depending on the platform's
PHY clock speed. To account for this delay we can poll for the expected
mode.

On a clear force mode, since we don't know what mode to poll for, delay
for a fixed 50 ms. This is the maximum delay based on the slowest PHY
clock speed.

Signed-off-by: John Youn <johnyoun@synopsys.com>
---
 drivers/usb/dwc2/core.c | 32 ++++++++++++++------------------
 1 file changed, 14 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index bb903e2..caad6121 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -397,9 +397,9 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
  * Checks are done in this function to determine whether doing a force
  * would be valid or not.
  *
- * If a force is done, it requires a 25ms delay to take effect.
- *
- * Returns true if the mode was forced.
+ * If a force is done, it requires a IDDIG debounce filter delay if
+ * the filter is configured and enabled. We poll the current mode of
+ * the controller to account for this delay.
  */
 static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
 {
@@ -434,12 +434,17 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
 	gusbcfg |= set;
 	dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
 
-	msleep(25);
-	return true;
+	dwc2_wait_for_mode(hsotg, host, 50);
 }
 
-/*
- * Clears the force mode bits.
+/**
+ * dwc2_clear_force_mode() - Clears the force mode bits.
+ *
+ * After clearing the bits, wait up to 50 ms to account for any
+ * potential IDDIG filter delay. We can't know if we expect this delay
+ * or not because the value of the connector ID status is affected by
+ * the force mode. We only need to call this once during probe if
+ * dr_mode == OTG.
  */
 static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
 {
@@ -450,11 +455,8 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
 	gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
 	dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
 
-	/*
-	 * NOTE: This long sleep is _very_ important, otherwise the core will
-	 * not stay in host mode after a connector ID change!
-	 */
-	msleep(25);
+	if (dwc2_iddig_filter_enabled(hsotg))
+		msleep(50);
 }
 
 /*
@@ -477,12 +479,6 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
 			 __func__, hsotg->dr_mode);
 		break;
 	}
-
-	/*
-	 * NOTE: This is required for some rockchip soc based
-	 * platforms.
-	 */
-	msleep(50);
 }
 
 /*
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFT PATCH v2 4/4] usb: dwc2: Force mode optimizations
  2016-08-24 23:19 [RFT PATCH v2 0/4] usb: dwc2: Fix core reset and force mode delays John Youn
                   ` (2 preceding siblings ...)
  2016-08-24 23:20 ` [RFT PATCH v2 3/4] usb: dwc2: Properly account for the force mode delays John Youn
@ 2016-08-24 23:20 ` John Youn
  3 siblings, 0 replies; 5+ messages in thread
From: John Youn @ 2016-08-24 23:20 UTC (permalink / raw)
  To: linux-usb
  Cc: johnyoun, Stefan Wahren, Michael Niewoehner, Felipe Balbi,
	Tao Huang, Julius Werner, linux-kernel, Caesar Wang,
	Heiko Stuebner, Remi Pommarel, Kever Yang, Doug Anderson,
	Stephen Warren, linux-rpi-kernel, linux-arm-kernel

If the dr_mode is USB_DR_MODE_OTG, forcing the mode is needed during
driver probe to get the host and device specific HW parameters. Then we
clear the force mode bits so that the core operates in OTG mode.

The force mode bits should not be touched at any other time during the
driver lifetime and they should be preserved whenever the GUSBCFG
register is written to. The force mode bit values will presist across
soft resets of the core.

If the dr_mode is either USB_DR_MODE_HOST or USB_DR_MODE_PERIPHERAL, the
force mode is set just once at probe to configure the core as either a
host or peripheral.

Given the above, we no longer need any other reset delays, force delays,
or any forced modes anywhere else in the driver. So replace all calls to
dwc2_core_reset_and_force_dr_mode() with dwc2_core_reset() and remove
all other unnecessary delays.

Also remove the dwc2_force_mode_if_needed() function since the "if
needed" part is already taken care of by the polling in
dwc2_force_mode().

Finally, remove all other calls to dwc2_clear_force_mode().

Signed-off-by: John Youn <johnyoun@synopsys.com>
---
 drivers/usb/dwc2/core.c     | 66 ++++++++++-----------------------------------
 drivers/usb/dwc2/core.h     |  1 -
 drivers/usb/dwc2/hcd.c      |  6 ++---
 drivers/usb/dwc2/platform.c |  9 ++++++-
 4 files changed, 25 insertions(+), 57 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index caad6121..9b83b20 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -377,14 +377,14 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
 	return 0;
 }
 
-/*
- * Force the mode of the controller.
+/**
+ * dwc2_force_mode() - Force the mode of the controller.
  *
  * Forcing the mode is needed for two cases:
  *
  * 1) If the dr_mode is set to either HOST or PERIPHERAL we force the
  * controller to stay in a particular mode regardless of ID pin
- * changes. We do this usually after a core reset.
+ * changes. We do this once during probe.
  *
  * 2) During probe we want to read reset values of the hw
  * configuration registers that are only available in either host or
@@ -401,7 +401,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
  * the filter is configured and enabled. We poll the current mode of
  * the controller to account for this delay.
  */
-static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
+static void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
 {
 	u32 gusbcfg;
 	u32 set;
@@ -413,17 +413,17 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
 	 * Force mode has no effect if the hardware is not OTG.
 	 */
 	if (!dwc2_hw_is_otg(hsotg))
-		return false;
+		return;
 
 	/*
 	 * If dr_mode is either peripheral or host only, there is no
 	 * need to ever force the mode to the opposite mode.
 	 */
 	if (WARN_ON(host && hsotg->dr_mode == USB_DR_MODE_PERIPHERAL))
-		return false;
+		return;
 
 	if (WARN_ON(!host && hsotg->dr_mode == USB_DR_MODE_HOST))
-		return false;
+		return;
 
 	gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
 
@@ -450,6 +450,11 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
 {
 	u32 gusbcfg;
 
+	if (!dwc2_hw_is_otg(hsotg))
+		return;
+
+	dev_dbg(hsotg->dev, "Clearing force mode bits\n");
+
 	gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
 	gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
 	gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
@@ -481,25 +486,6 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
 	}
 }
 
-/*
- * Do core a soft reset of the core.  Be careful with this because it
- * resets all the internal state machines of the core.
- *
- * Additionally this will apply force mode as per the hsotg->dr_mode
- * parameter.
- */
-int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg)
-{
-	int retval;
-
-	retval = dwc2_core_reset(hsotg);
-	if (retval)
-		return retval;
-
-	dwc2_force_dr_mode(hsotg);
-	return 0;
-}
-
 /**
  * dwc2_dump_host_registers() - Prints the host registers
  *
@@ -1418,22 +1404,6 @@ void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
 	dwc2_set_param_hibernation(hsotg, params->hibernation);
 }
 
-/*
- * Forces either host or device mode if the controller is not
- * currently in that mode.
- *
- * Returns true if the mode was forced.
- */
-static bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host)
-{
-	if (host && dwc2_is_host_mode(hsotg))
-		return false;
-	else if (!host && dwc2_is_device_mode(hsotg))
-		return false;
-
-	return dwc2_force_mode(hsotg, host);
-}
-
 /*
  * Gets host hardware parameters. Forces host mode if not currently in
  * host mode. Should be called immediately after a core soft reset in
@@ -1444,21 +1414,17 @@ static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg)
 	struct dwc2_hw_params *hw = &hsotg->hw_params;
 	u32 gnptxfsiz;
 	u32 hptxfsiz;
-	bool forced;
 
 	if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
 		return;
 
-	forced = dwc2_force_mode_if_needed(hsotg, true);
+	dwc2_force_mode(hsotg, true);
 
 	gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
 	hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
 	dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
 	dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz);
 
-	if (forced)
-		dwc2_clear_force_mode(hsotg);
-
 	hw->host_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
 				       FIFOSIZE_DEPTH_SHIFT;
 	hw->host_perio_tx_fifo_size = (hptxfsiz & FIFOSIZE_DEPTH_MASK) >>
@@ -1473,20 +1439,16 @@ static void dwc2_get_host_hwparams(struct dwc2_hsotg *hsotg)
 static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
 {
 	struct dwc2_hw_params *hw = &hsotg->hw_params;
-	bool forced;
 	u32 gnptxfsiz;
 
 	if (hsotg->dr_mode == USB_DR_MODE_HOST)
 		return;
 
-	forced = dwc2_force_mode_if_needed(hsotg, false);
+	dwc2_force_mode(hsotg, false);
 
 	gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
 	dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
 
-	if (forced)
-		dwc2_clear_force_mode(hsotg);
-
 	hw->dev_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >>
 				       FIFOSIZE_DEPTH_SHIFT;
 }
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 2a21a04..b7ff083 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1021,7 +1021,6 @@ enum dwc2_halt_status {
  * and the DWC_otg controller
  */
 extern int dwc2_core_reset(struct dwc2_hsotg *hsotg);
-extern int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
 extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
 extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
 
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index df5a065..6f09254 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -134,7 +134,7 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 			dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
 
 			/* Reset after a PHY select */
-			retval = dwc2_core_reset_and_force_dr_mode(hsotg);
+			retval = dwc2_core_reset(hsotg);
 
 			if (retval) {
 				dev_err(hsotg->dev,
@@ -214,7 +214,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 		dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
 
 		/* Reset after setting the PHY parameters */
-		retval = dwc2_core_reset_and_force_dr_mode(hsotg);
+		retval = dwc2_core_reset(hsotg);
 		if (retval) {
 			dev_err(hsotg->dev,
 				"%s: Reset failed, aborting", __func__);
@@ -2204,7 +2204,7 @@ static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
 	 * needed to in order to properly detect various parameters).
 	 */
 	if (!initial_setup) {
-		retval = dwc2_core_reset_and_force_dr_mode(hsotg);
+		retval = dwc2_core_reset(hsotg);
 		if (retval) {
 			dev_err(hsotg->dev, "%s(): Reset failed, aborting\n",
 				__func__);
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 530959a..1ef8bfe 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -590,7 +590,9 @@ static int dwc2_driver_probe(struct platform_device *dev)
 	 * Reset before dwc2_get_hwparams() then it could get power-on real
 	 * reset value form registers.
 	 */
-	dwc2_core_reset_and_force_dr_mode(hsotg);
+	retval = dwc2_core_reset(hsotg);
+	if (retval)
+		goto error;
 
 	/* Detect config values from hardware */
 	retval = dwc2_get_hwparams(hsotg);
@@ -600,6 +602,11 @@ static int dwc2_driver_probe(struct platform_device *dev)
 	/* Validate parameter values */
 	dwc2_set_parameters(hsotg, params);
 
+	/*
+	 * For OTG cores, set the force mode bits to reflect the value
+	 * of dr_mode. Force mode bits should not be touched at any
+	 * other time after this.
+	 */
 	dwc2_force_dr_mode(hsotg);
 
 	if (hsotg->dr_mode != USB_DR_MODE_HOST) {
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-08-24 23:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-24 23:19 [RFT PATCH v2 0/4] usb: dwc2: Fix core reset and force mode delays John Youn
2016-08-24 23:19 ` [RFT PATCH v2 1/4] usb: dwc2: gadget: Only initialize device if in device mode John Youn
2016-08-24 23:19 ` [RFT PATCH v2 2/4] usb: dwc2: Add delay to core soft reset John Youn
2016-08-24 23:20 ` [RFT PATCH v2 3/4] usb: dwc2: Properly account for the force mode delays John Youn
2016-08-24 23:20 ` [RFT PATCH v2 4/4] usb: dwc2: Force mode optimizations John Youn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).