staging: dwc2: add check on dwc2_core_reset return

If the GRSTCTL_CSFTRST self-clearing bit never comes
back to 0 for any reason, the controller is under reset
state and cannot be used. It's preferable to abort
initialization in such case.

Signed-off-by: Julien Delacou <julien.delacou@st.com>
Acked-by: Paul Zimmerman <paulz@synopsys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c
index e424940..53d5408 100644
--- a/drivers/staging/dwc2/core.c
+++ b/drivers/staging/dwc2/core.c
@@ -114,7 +114,7 @@
  * Do core a soft reset of the core.  Be careful with this because it
  * resets all the internal state machines of the core.
  */
-static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
+static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
 {
 	u32 greset;
 	int count = 0;
@@ -129,7 +129,7 @@
 			dev_warn(hsotg->dev,
 				 "%s() HANG! AHB Idle GRSTCTL=%0x\n",
 				 __func__, greset);
-			return;
+			return -EBUSY;
 		}
 	} while (!(greset & GRSTCTL_AHBIDLE));
 
@@ -144,7 +144,7 @@
 			dev_warn(hsotg->dev,
 				 "%s() HANG! Soft Reset GRSTCTL=%0x\n",
 				 __func__, greset);
-			break;
+			return -EBUSY;
 		}
 	} while (greset & GRSTCTL_CSFTRST);
 
@@ -153,11 +153,14 @@
 	 * not stay in host mode after a connector ID change!
 	 */
 	usleep_range(150000, 200000);
+
+	return 0;
 }
 
-static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 {
 	u32 usbcfg, i2cctl;
+	int retval = 0;
 
 	/*
 	 * core_init() is now called on every switch so only call the
@@ -170,7 +173,12 @@
 		writel(usbcfg, hsotg->regs + GUSBCFG);
 
 		/* Reset after a PHY select */
-		dwc2_core_reset(hsotg);
+		retval = dwc2_core_reset(hsotg);
+		if (retval) {
+			dev_err(hsotg->dev, "%s() Reset failed, aborting",
+					__func__);
+			return retval;
+		}
 	}
 
 	/*
@@ -198,14 +206,17 @@
 		i2cctl |= GI2CCTL_I2CEN;
 		writel(i2cctl, hsotg->regs + GI2CCTL);
 	}
+
+	return retval;
 }
 
-static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 {
 	u32 usbcfg;
+	int retval = 0;
 
 	if (!select_phy)
-		return;
+		return -ENODEV;
 
 	usbcfg = readl(hsotg->regs + GUSBCFG);
 
@@ -238,20 +249,32 @@
 	writel(usbcfg, hsotg->regs + GUSBCFG);
 
 	/* Reset after setting the PHY parameters */
-	dwc2_core_reset(hsotg);
+	retval = dwc2_core_reset(hsotg);
+	if (retval) {
+		dev_err(hsotg->dev, "%s() Reset failed, aborting",
+				__func__);
+		return retval;
+	}
+
+	return retval;
 }
 
-static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 {
 	u32 usbcfg;
+	int retval = 0;
 
 	if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL &&
 	    hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) {
 		/* If FS mode with FS PHY */
-		dwc2_fs_phy_init(hsotg, select_phy);
+		retval = dwc2_fs_phy_init(hsotg, select_phy);
+		if (retval)
+			return retval;
 	} else {
 		/* High speed PHY */
-		dwc2_hs_phy_init(hsotg, select_phy);
+		retval = dwc2_hs_phy_init(hsotg, select_phy);
+		if (retval)
+			return retval;
 	}
 
 	if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
@@ -268,6 +291,8 @@
 		usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
 		writel(usbcfg, hsotg->regs + GUSBCFG);
 	}
+
+	return retval;
 }
 
 static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
@@ -382,12 +407,19 @@
 	writel(usbcfg, hsotg->regs + GUSBCFG);
 
 	/* Reset the Controller */
-	dwc2_core_reset(hsotg);
+	retval = dwc2_core_reset(hsotg);
+	if (retval) {
+		dev_err(hsotg->dev, "%s(): Reset failed, aborting\n",
+				__func__);
+		return retval;
+	}
 
 	/*
 	 * This needs to happen in FS mode before any other programming occurs
 	 */
-	dwc2_phy_init(hsotg, select_phy);
+	retval = dwc2_phy_init(hsotg, select_phy);
+	if (retval)
+		return retval;
 
 	/* Program the GAHBCFG Register */
 	retval = dwc2_gahbcfg_init(hsotg);