Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit beb7e592 authored by Julien DELACOU's avatar Julien DELACOU Committed by Greg Kroah-Hartman
Browse files

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: default avatarJulien Delacou <julien.delacou@st.com>
Acked-by: default avatarPaul Zimmerman <paulz@synopsys.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b34085fd
Loading
Loading
Loading
Loading
+45 −13
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ static void dwc2_init_fs_ls_pclk_sel(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.
 */
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 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
			dev_warn(hsotg->dev,
				 "%s() HANG! AHB Idle GRSTCTL=%0x\n",
				 __func__, greset);
			return;
			return -EBUSY;
		}
	} while (!(greset & GRSTCTL_AHBIDLE));

@@ -144,7 +144,7 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
			dev_warn(hsotg->dev,
				 "%s() HANG! Soft Reset GRSTCTL=%0x\n",
				 __func__, greset);
			break;
			return -EBUSY;
		}
	} while (greset & GRSTCTL_CSFTRST);

@@ -153,11 +153,14 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
	 * 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 @@ static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
		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 @@ static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
		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 @@ static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
	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;
	}

static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
	return retval;
}

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 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
		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 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
	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);