summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2014-02-25 14:00:13 -0600
committerFelipe Balbi <balbi@ti.com>2014-03-05 09:44:50 -0600
commit32a4a135847b1e600c64756b7c7c7a91eb2f0aa9 (patch)
tree3194fe2ccd0c66c4895663d3473a0d7395952d4c
parent183ca11179f6d3b99e0431bae6acb84350b82dea (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>
-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 a49217ae3533..785feeeac3c1 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -314,7 +314,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");
@@ -479,6 +497,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");
@@ -494,14 +520,6 @@ static int dwc3_probe(struct platform_device *pdev)
goto err1;
}
- 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);