linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [6/6] usb: dwc2: Force mode optimizations
@ 2018-01-16 12:05 Grigor Tovmasyan
  0 siblings, 0 replies; 5+ messages in thread
From: Grigor Tovmasyan @ 2018-01-16 12:05 UTC (permalink / raw)
  To: John Youn, Felipe Balbi, Greg Kroah-Hartman, linux-usb
  Cc: Grigor Tovmasyan, Stefan Wahren

From: Vardan Mikayelyan <mvardan@synopsys.com>

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 persist 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().

Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Vardan Mikayelyan <mvardan@synopsys.com>
Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com>
---
 drivers/usb/dwc2/core.c     | 61 +++++++++++----------------------------------
 drivers/usb/dwc2/core.h     |  4 +--
 drivers/usb/dwc2/hcd.c      |  6 ++---
 drivers/usb/dwc2/params.c   | 12 ++-------
 drivers/usb/dwc2/platform.c |  9 ++++++-
 5 files changed, 28 insertions(+), 64 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 82a7d98c3436..dbca3b8890da 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -376,14 +376,14 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
 	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
@@ -400,7 +400,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
  * 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)
+void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
 {
 	u32 gusbcfg;
 	u32 set;
@@ -412,17 +412,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);
 
@@ -434,7 +434,7 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
 	dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
 
 	dwc2_wait_for_mode(hsotg, host);
-	return true;
+	return;
 }
 
 /**
@@ -450,6 +450,11 @@ 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;
@@ -464,16 +469,13 @@ void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
  */
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
 {
-	bool ret;
-
 	switch (hsotg->dr_mode) {
 	case USB_DR_MODE_HOST:
-		ret = dwc2_force_mode(hsotg, true);
 		/*
 		 * NOTE: This is required for some rockchip soc based
 		 * platforms on their host-only dwc2.
 		 */
-		if (!ret)
+		if (!dwc2_hw_is_otg(hsotg))
 			msleep(50);
 
 		break;
@@ -490,25 +492,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, false);
-	if (retval)
-		return retval;
-
-	dwc2_force_dr_mode(hsotg);
-	return 0;
-}
-
 /**
  * dwc2_dump_host_registers() - Prints the host registers
  *
@@ -736,22 +719,6 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
 	udelay(1);
 }
 
-/*
- * Forces either host or device mode if the controller is not
- * currently in that mode.
- *
- * Returns true if the mode was forced.
- */
-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);
-}
-
 bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
 {
 	if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 232a3aa8c9b1..7439aa6e35f6 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1105,12 +1105,10 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg *hsotg)
  * and the DWC_otg controller
  */
 int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
-int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
 int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
 int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
 
-bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host);
-void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg);
+void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
 
 bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 7b6eb0ad513b..614bb9603def 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -138,7 +138,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, false);
 
 			if (retval) {
 				dev_err(hsotg->dev,
@@ -236,7 +236,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, false);
 		if (retval) {
 			dev_err(hsotg->dev,
 				"%s: Reset failed, aborting", __func__);
@@ -2256,7 +2256,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, false);
 		if (retval) {
 			dev_err(hsotg->dev, "%s(): Reset failed, aborting\n",
 				__func__);
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 7c20c8e31179..fc4d93d78ec3 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -580,19 +580,15 @@ 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);
 
-	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) >>
@@ -607,19 +603,15 @@ 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);
 
-	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/platform.c b/drivers/usb/dwc2/platform.c
index 74be91c559c8..1a733b9ddab0 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -415,13 +415,20 @@ 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, false);
+	if (retval)
+		goto error;
 
 	/* Detect config values from hardware */
 	retval = dwc2_get_hwparams(hsotg);
 	if (retval)
 		goto error;
 
+	/*
+	 * 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);
 
 	retval = dwc2_init_params(hsotg);

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

* [6/6] usb: dwc2: Force mode optimizations
@ 2018-02-15 16:34 Grigor Tovmasyan
  0 siblings, 0 replies; 5+ messages in thread
From: Grigor Tovmasyan @ 2018-02-15 16:34 UTC (permalink / raw)
  To: John Youn, Felipe Balbi, Greg Kroah-Hartman,
	linux-usb@vger.kernel.org
  Cc: Stefan Wahren

Hi Balbi,

I rebased this commit to your testing/next (see below).

Please skip 05/06 patch in this series, it was already applied via 
"[PATCH v2 00/49] usb: dwc2: fixes, enhancements and new features " 
patch series.

Please ignore "[PATCH v2 00/49] usb: dwc2: fixes, enhancements and new 
features " patch series.

Please apply this rebased patch.
Also, please, reapply "[PATCH 09/17] usb: dwc2: Make dwc2_force_mode() 
static" which was dropped because of having dependancy from this pacth.

Thanks a lot.


On 1/16/2018 16:05, Grigor Tovmasyan wrote:
> From: Vardan Mikayelyan <mvardan@synopsys.com>
> 
> 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 persist 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().
> 
> Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
> Signed-off-by: John Youn <johnyoun@synopsys.com>
> Signed-off-by: Vardan Mikayelyan <mvardan@synopsys.com>
> Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com>
> ---
>   drivers/usb/dwc2/core.c     | 61 +++++++++++----------------------------------
>   drivers/usb/dwc2/core.h     |  4 +--
>   drivers/usb/dwc2/hcd.c      |  6 ++---
>   drivers/usb/dwc2/params.c   | 12 ++-------
>   drivers/usb/dwc2/platform.c |  9 ++++++-
>   5 files changed, 28 insertions(+), 64 deletions(-)
> 
> diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
> index 82a7d98c3436..dbca3b8890da 100644
> --- a/drivers/usb/dwc2/core.c
> +++ b/drivers/usb/dwc2/core.c
> @@ -376,14 +376,14 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
>   	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
> @@ -400,7 +400,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
>    * 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)
> +void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
>   {
>   	u32 gusbcfg;
>   	u32 set;
> @@ -412,17 +412,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);
>   
> @@ -434,7 +434,7 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
>   	dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
>   
>   	dwc2_wait_for_mode(hsotg, host);
> -	return true;
> +	return;
>   }
>   
>   /**
> @@ -450,6 +450,11 @@ 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;
> @@ -464,16 +469,13 @@ void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
>    */
>   void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
>   {
> -	bool ret;
> -
>   	switch (hsotg->dr_mode) {
>   	case USB_DR_MODE_HOST:
> -		ret = dwc2_force_mode(hsotg, true);
>   		/*
>   		 * NOTE: This is required for some rockchip soc based
>   		 * platforms on their host-only dwc2.
>   		 */
> -		if (!ret)
> +		if (!dwc2_hw_is_otg(hsotg))
>   			msleep(50);
>   
>   		break;
> @@ -490,25 +492,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, false);
> -	if (retval)
> -		return retval;
> -
> -	dwc2_force_dr_mode(hsotg);
> -	return 0;
> -}
> -
>   /**
>    * dwc2_dump_host_registers() - Prints the host registers
>    *
> @@ -736,22 +719,6 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
>   	udelay(1);
>   }
>   
> -/*
> - * Forces either host or device mode if the controller is not
> - * currently in that mode.
> - *
> - * Returns true if the mode was forced.
> - */
> -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);
> -}
> -
>   bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
>   {
>   	if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> index 232a3aa8c9b1..7439aa6e35f6 100644
> --- a/drivers/usb/dwc2/core.h
> +++ b/drivers/usb/dwc2/core.h
> @@ -1105,12 +1105,10 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg *hsotg)
>    * and the DWC_otg controller
>    */
>   int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
> -int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
>   int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
>   int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
>   
> -bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host);
> -void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg);
> +void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
>   void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
>   
>   bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg);
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index 7b6eb0ad513b..614bb9603def 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -138,7 +138,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, false);
>   
>   			if (retval) {
>   				dev_err(hsotg->dev,
> @@ -236,7 +236,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, false);
>   		if (retval) {
>   			dev_err(hsotg->dev,
>   				"%s: Reset failed, aborting", __func__);
> @@ -2256,7 +2256,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, false);
>   		if (retval) {
>   			dev_err(hsotg->dev, "%s(): Reset failed, aborting\n",
>   				__func__);
> diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
> index 7c20c8e31179..fc4d93d78ec3 100644
> --- a/drivers/usb/dwc2/params.c
> +++ b/drivers/usb/dwc2/params.c
> @@ -580,19 +580,15 @@ 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);
>   
> -	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) >>
> @@ -607,19 +603,15 @@ 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);
>   
> -	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/platform.c b/drivers/usb/dwc2/platform.c
> index 74be91c559c8..1a733b9ddab0 100644
> --- a/drivers/usb/dwc2/platform.c
> +++ b/drivers/usb/dwc2/platform.c
> @@ -415,13 +415,20 @@ 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, false);
> +	if (retval)
> +		goto error;
>   
>   	/* Detect config values from hardware */
>   	retval = dwc2_get_hwparams(hsotg);
>   	if (retval)
>   		goto error;
>   
> +	/*
> +	 * 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);
>   
>   	retval = dwc2_init_params(hsotg);
> 

From: Vardan Mikayelyan <mvardan@synopsys.com>

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 persist 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().

Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Vardan Mikayelyan <mvardan@synopsys.com>
Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com>
---
  drivers/usb/dwc2/core.c     | 60 
+++++++++++----------------------------------
  drivers/usb/dwc2/core.h     |  4 +--
  drivers/usb/dwc2/hcd.c      |  6 ++---
  drivers/usb/dwc2/params.c   | 12 ++-------
  drivers/usb/dwc2/platform.c |  9 ++++++-
  5 files changed, 28 insertions(+), 63 deletions(-)

  	retval = dwc2_init_params(hsotg);

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 346150922dbd..67987c338ed2 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -367,14 +367,14 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool 
skip_wait)
  	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
@@ -391,7 +391,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool 
skip_wait)
   * 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)
+void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
  {
  	u32 gusbcfg;
  	u32 set;
@@ -403,17 +403,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);

@@ -425,7 +425,7 @@ static bool dwc2_force_mode(struct dwc2_hsotg 
*hsotg, bool host)
  	dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);

  	dwc2_wait_for_mode(hsotg, host);
-	return true;
+	return;
  }

  /**
@@ -441,6 +441,11 @@ 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;
@@ -455,16 +460,13 @@ void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
   */
  void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
  {
-	bool ret;
-
  	switch (hsotg->dr_mode) {
  	case USB_DR_MODE_HOST:
-		ret = dwc2_force_mode(hsotg, true);
  		/*
  		 * NOTE: This is required for some rockchip soc based
  		 * platforms on their host-only dwc2.
  		 */
-		if (!ret)
+		if (!dwc2_hw_is_otg(hsotg))
  			msleep(50);

  		break;
@@ -481,24 +483,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, false);
-	if (retval)
-		return retval;
-
-	dwc2_force_dr_mode(hsotg);
-	return 0;
-}

  /*
   * dwc2_enable_acg - enable active clock gating feature
@@ -736,22 +720,6 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
  	udelay(1);
  }

-/*
- * Forces either host or device mode if the controller is not
- * currently in that mode.
- *
- * Returns true if the mode was forced.
- */
-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);
-}
-
  bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
  {
  	if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 96799a399393..eb16a0d95e07 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1116,12 +1116,10 @@ static inline bool dwc2_is_hs_iot(struct 
dwc2_hsotg *hsotg)
   * and the DWC_otg controller
   */
  int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
-int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
  int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
  int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);

-bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host);
-void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg);
+void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
  void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);

  bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index bbd3185a7364..1acfd082c358 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -141,7 +141,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, false);

  			if (retval) {
  				dev_err(hsotg->dev,
@@ -239,7 +239,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, false);
  		if (retval) {
  			dev_err(hsotg->dev,
  				"%s: Reset failed, aborting", __func__);
@@ -2270,7 +2270,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, false);
  		if (retval) {
  			dev_err(hsotg->dev, "%s(): Reset failed, aborting\n",
  				__func__);
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 827f7f81a27c..e7c23cb25e84 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -593,19 +593,15 @@ 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);

-	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) >>
@@ -620,14 +616,13 @@ 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;
  	int fifo, fifo_count;

  	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);

@@ -639,9 +634,6 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg 
*hsotg)
  			 FIFOSIZE_DEPTH_MASK) >> FIFOSIZE_DEPTH_SHIFT;
  	}

-	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/platform.c b/drivers/usb/dwc2/platform.c
index 65e1af5e491a..e4e1eee2f40a 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -427,13 +427,20 @@ 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, false);
+	if (retval)
+		goto error;

  	/* Detect config values from hardware */
  	retval = dwc2_get_hwparams(hsotg);
  	if (retval)
  		goto error;

+	/*
+	 * 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);


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

* [6/6] usb: dwc2: Force mode optimizations
@ 2018-02-16  7:08 Felipe Balbi
  0 siblings, 0 replies; 5+ messages in thread
From: Felipe Balbi @ 2018-02-16  7:08 UTC (permalink / raw)
  To: Grigor Tovmasyan, John Youn, Greg Kroah-Hartman,
	linux-usb@vger.kernel.org
  Cc: Stefan Wahren

Hi,

Grigor Tovmasyan <Grigor.Tovmasyan@synopsys.com> writes:

> Hi Balbi,
>
> I rebased this commit to your testing/next (see below).

Are you sure you did?

checking file drivers/usb/dwc2/core.c
Hunk #1 FAILED at 367.
Hunk #2 FAILED at 391.
Hunk #3 FAILED at 403.
Hunk #4 FAILED at 425.
Hunk #5 FAILED at 441.
Hunk #6 FAILED at 455.
Hunk #7 succeeded at 481 with fuzz 2.
Hunk #8 FAILED at 718.
7 out of 8 hunks FAILED
checking file drivers/usb/dwc2/core.h
Hunk #1 FAILED at 1116.
1 out of 1 hunk FAILED
checking file drivers/usb/dwc2/hcd.c
Hunk #1 FAILED at 141.
Hunk #2 FAILED at 239.
Hunk #3 FAILED at 2270.
3 out of 3 hunks FAILED
checking file drivers/usb/dwc2/params.c
Hunk #1 FAILED at 593.
Hunk #2 FAILED at 620.
Hunk #3 FAILED at 639.
3 out of 3 hunks FAILED
checking file drivers/usb/dwc2/platform.c
Hunk #1 FAILED at 427.
1 out of 1 hunk FAILED

And this is after fixing your malformed patch with mangled lines. Please
rebase again and use git send-email. For reference, My testing/next is @
08900d3304bb787164e79a8942112208917d1ddd

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

* [6/6] usb: dwc2: Force mode optimizations
@ 2018-02-16  8:18 Grigor Tovmasyan
  0 siblings, 0 replies; 5+ messages in thread
From: Grigor Tovmasyan @ 2018-02-16  8:18 UTC (permalink / raw)
  To: Felipe Balbi, Grigor Tovmasyan, John Youn, Greg Kroah-Hartman,
	linux-usb@vger.kernel.org
  Cc: Stefan Wahren

Hi Balbi,


On 2/16/2018 11:09, Felipe Balbi wrote:
> 
> Hi,
> 
> Grigor Tovmasyan <Grigor.Tovmasyan@synopsys.com> writes:
> 
>> Hi Balbi,
>>
>> I rebased this commit to your testing/next (see below).
> 
> Are you sure you did?

Yes. I checked my version of your testing/next, it also was 
@08900d3304bb787164e79a8942112208917d1ddd

I tried to "git apply" this patch and also get errors. But via "git 
cherry-pick" patch applying without any errors.

I will try again rebase this patch.

> 
> checking file drivers/usb/dwc2/core.c
> Hunk #1 FAILED at 367.
> Hunk #2 FAILED at 391.
> Hunk #3 FAILED at 403.
> Hunk #4 FAILED at 425.
> Hunk #5 FAILED at 441.
> Hunk #6 FAILED at 455.
> Hunk #7 succeeded at 481 with fuzz 2.
> Hunk #8 FAILED at 718.
> 7 out of 8 hunks FAILED
> checking file drivers/usb/dwc2/core.h
> Hunk #1 FAILED at 1116.
> 1 out of 1 hunk FAILED
> checking file drivers/usb/dwc2/hcd.c
> Hunk #1 FAILED at 141.
> Hunk #2 FAILED at 239.
> Hunk #3 FAILED at 2270.
> 3 out of 3 hunks FAILED
> checking file drivers/usb/dwc2/params.c
> Hunk #1 FAILED at 593.
> Hunk #2 FAILED at 620.
> Hunk #3 FAILED at 639.
> 3 out of 3 hunks FAILED
> checking file drivers/usb/dwc2/platform.c
> Hunk #1 FAILED at 427.
> 1 out of 1 hunk FAILED
> 
> And this is after fixing your malformed patch with mangled lines. Please
> rebase again and use git send-email. For reference, My testing/next is @
> 08900d3304bb787164e79a8942112208917d1ddd
> 

Sorry for that.

Thanks,
Grigor.
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [6/6] usb: dwc2: Force mode optimizations
@ 2018-02-16  8:56 Grigor Tovmasyan
  0 siblings, 0 replies; 5+ messages in thread
From: Grigor Tovmasyan @ 2018-02-16  8:56 UTC (permalink / raw)
  To: John Youn, Felipe Balbi, Greg Kroah-Hartman, linux-usb
  Cc: Vardan Mikayelyan, Grigor Tovmasyan, Stefan Wahren

From: Vardan Mikayelyan <mvardan@synopsys.com>

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 persist 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().

Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Vardan Mikayelyan <mvardan@synopsys.com>
Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com>
---
 drivers/usb/dwc2/core.c     | 61 +++++++++++----------------------------------
 drivers/usb/dwc2/core.h     |  4 +--
 drivers/usb/dwc2/hcd.c      |  6 ++---
 drivers/usb/dwc2/params.c   | 12 ++-------
 drivers/usb/dwc2/platform.c |  9 ++++++-
 5 files changed, 28 insertions(+), 64 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 346150922dbd..de8feb4cd4f0 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -367,14 +367,14 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
 	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
@@ -391,7 +391,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
  * 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)
+void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
 {
 	u32 gusbcfg;
 	u32 set;
@@ -403,17 +403,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);
 
@@ -425,7 +425,7 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
 	dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
 
 	dwc2_wait_for_mode(hsotg, host);
-	return true;
+	return;
 }
 
 /**
@@ -441,6 +441,11 @@ 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;
@@ -455,16 +460,13 @@ void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
  */
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
 {
-	bool ret;
-
 	switch (hsotg->dr_mode) {
 	case USB_DR_MODE_HOST:
-		ret = dwc2_force_mode(hsotg, true);
 		/*
 		 * NOTE: This is required for some rockchip soc based
 		 * platforms on their host-only dwc2.
 		 */
-		if (!ret)
+		if (!dwc2_hw_is_otg(hsotg))
 			msleep(50);
 
 		break;
@@ -481,25 +483,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, false);
-	if (retval)
-		return retval;
-
-	dwc2_force_dr_mode(hsotg);
-	return 0;
-}
-
 /*
  * dwc2_enable_acg - enable active clock gating feature
  */
@@ -736,22 +719,6 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
 	udelay(1);
 }
 
-/*
- * Forces either host or device mode if the controller is not
- * currently in that mode.
- *
- * Returns true if the mode was forced.
- */
-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);
-}
-
 bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
 {
 	if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 96799a399393..eb16a0d95e07 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1116,12 +1116,10 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg *hsotg)
  * and the DWC_otg controller
  */
 int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
-int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
 int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
 int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
 
-bool dwc2_force_mode_if_needed(struct dwc2_hsotg *hsotg, bool host);
-void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg);
+void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
 
 bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index bbd3185a7364..1acfd082c358 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -141,7 +141,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, false);
 
 			if (retval) {
 				dev_err(hsotg->dev,
@@ -239,7 +239,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, false);
 		if (retval) {
 			dev_err(hsotg->dev,
 				"%s: Reset failed, aborting", __func__);
@@ -2270,7 +2270,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, false);
 		if (retval) {
 			dev_err(hsotg->dev, "%s(): Reset failed, aborting\n",
 				__func__);
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 827f7f81a27c..e7c23cb25e84 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -593,19 +593,15 @@ 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);
 
-	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) >>
@@ -620,14 +616,13 @@ 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;
 	int fifo, fifo_count;
 
 	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);
 
@@ -639,9 +634,6 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
 			 FIFOSIZE_DEPTH_MASK) >> FIFOSIZE_DEPTH_SHIFT;
 	}
 
-	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/platform.c b/drivers/usb/dwc2/platform.c
index 65e1af5e491a..e4e1eee2f40a 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -427,13 +427,20 @@ 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, false);
+	if (retval)
+		goto error;
 
 	/* Detect config values from hardware */
 	retval = dwc2_get_hwparams(hsotg);
 	if (retval)
 		goto error;
 
+	/*
+	 * 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);
 
 	retval = dwc2_init_params(hsotg);

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

end of thread, other threads:[~2018-02-16  8:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-16  7:08 [6/6] usb: dwc2: Force mode optimizations Felipe Balbi
  -- strict thread matches above, loose matches on Subject: below --
2018-02-16  8:56 Grigor Tovmasyan
2018-02-16  8:18 Grigor Tovmasyan
2018-02-15 16:34 Grigor Tovmasyan
2018-01-16 12:05 Grigor Tovmasyan

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).