aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2014-02-25 14:00:13 -0600
committerMark Brown <broonie@kernel.org>2014-12-10 12:43:57 +0000
commit039388ad43fc8f5c508f565afe92c5acd8046548 (patch)
treecc9559a745fdee4692df0479a489caa8465baa95
parentad0e01151c614070518547085511cc06b1c19ba3 (diff)
usb: dwc3: workaround: clock gating issues
Revisions between 2.10a and 2.50a (included) have a known issue which may cause xHCI compliance tests to fail and/or quality issues with Isochronous transactions. Note that this issue only impacts certain configurations of those revisions, namely the ones which have clock gating enabled. The suggested workaround is to disable clock gating in known broken revisions, make sure HW LPM is disabled and set GCTL.SOFITPSYNC to 1. Signed-off-by: Felipe Balbi <balbi@ti.com> (cherry picked from commit 39fe817a9ed40af22f7289e1562329cfe9d9b20b) Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/usb/dwc3/core.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 587c375d4123..74e705e3d5c3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -328,7 +328,25 @@ static int dwc3_core_init(struct dwc3 *dwc)
switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
- reg &= ~DWC3_GCTL_DSBLCLKGTNG;
+ /**
+ * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
+ * issue which would cause xHCI compliance tests to fail.
+ *
+ * Because of that we cannot enable clock gating on such
+ * configurations.
+ *
+ * Refers to:
+ *
+ * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based
+ * SOF/ITP Mode Used
+ */
+ if ((dwc->dr_mode == USB_DR_MODE_HOST ||
+ dwc->dr_mode == USB_DR_MODE_OTG) &&
+ (dwc->revision >= DWC3_REVISION_210A &&
+ dwc->revision <= DWC3_REVISION_250A))
+ reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC;
+ else
+ reg &= ~DWC3_GCTL_DSBLCLKGTNG;
break;
default:
dev_dbg(dwc->dev, "No power optimization available\n");
@@ -515,6 +533,14 @@ static int dwc3_probe(struct platform_device *pdev)
goto err0;
}
+ if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
+ dwc->dr_mode = USB_DR_MODE_HOST;
+ else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
+ dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
+
+ if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
+ dwc->dr_mode = USB_DR_MODE_OTG;
+
ret = dwc3_core_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize core\n");
@@ -537,14 +563,6 @@ static int dwc3_probe(struct platform_device *pdev)
goto err_usb3phy_power;
}
- if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
- dwc->dr_mode = USB_DR_MODE_HOST;
- else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
- dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
-
- if (dwc->dr_mode == USB_DR_MODE_UNKNOWN)
- dwc->dr_mode = USB_DR_MODE_OTG;
-
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);