Commit 7d56cc26 authored by Douglas Anderson's avatar Douglas Anderson Committed by Felipe Balbi

usb: dwc2: Avoid more calls to dwc2_core_reset()

Calls to dwc2_core_reset() are currently very slow, taking at least
150ms (possibly more).  It behooves us to take as many of these calls
out as possible.

It turns out that the calls in dwc2_fs_phy_init() and dwc2_hs_phy_init()
should (as documented in the code) only be needed if we need to do a PHY
SELECT.  That means that if we see that we can avoid the PHY SELECT then
we can avoid the reset.

This patch appears to successfully bypass two resets (one per USB
device) on rk3288-based ARM Chromebooks.
Signed-off-by: default avatarDouglas Anderson <dianders@chromium.org>
Signed-off-by: default avatarJohn Youn <johnyoun@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 20bde643
...@@ -553,18 +553,22 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) ...@@ -553,18 +553,22 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
*/ */
if (select_phy) { if (select_phy) {
dev_dbg(hsotg->dev, "FS PHY selected\n"); dev_dbg(hsotg->dev, "FS PHY selected\n");
usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
if (!(usbcfg & GUSBCFG_PHYSEL)) {
usbcfg |= GUSBCFG_PHYSEL; usbcfg |= GUSBCFG_PHYSEL;
dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
/* Reset after a PHY select */ /* Reset after a PHY select */
retval = dwc2_core_reset(hsotg); retval = dwc2_core_reset(hsotg);
if (retval) { if (retval) {
dev_err(hsotg->dev, "%s() Reset failed, aborting", dev_err(hsotg->dev,
__func__); "%s: Reset failed, aborting", __func__);
return retval; return retval;
} }
} }
}
/* /*
* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
...@@ -597,13 +601,13 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) ...@@ -597,13 +601,13 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
static int 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; u32 usbcfg, usbcfg_old;
int retval = 0; int retval = 0;
if (!select_phy) if (!select_phy)
return 0; return 0;
usbcfg = dwc2_readl(hsotg->regs + GUSBCFG); usbcfg = usbcfg_old = dwc2_readl(hsotg->regs + GUSBCFG);
/* /*
* HS PHY parameters. These parameters are preserved during soft reset * HS PHY parameters. These parameters are preserved during soft reset
...@@ -631,15 +635,17 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) ...@@ -631,15 +635,17 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
break; break;
} }
if (usbcfg != usbcfg_old) {
dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
/* Reset after setting the PHY parameters */ /* Reset after setting the PHY parameters */
retval = dwc2_core_reset(hsotg); retval = dwc2_core_reset(hsotg);
if (retval) { if (retval) {
dev_err(hsotg->dev, "%s() Reset failed, aborting", dev_err(hsotg->dev,
__func__); "%s: Reset failed, aborting", __func__);
return retval; return retval;
} }
}
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment