Commit 32a4a135 authored by Felipe Balbi's avatar Felipe Balbi

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: default avatarFelipe Balbi <balbi@ti.com>
parent 183ca111
...@@ -314,7 +314,25 @@ static int dwc3_core_init(struct dwc3 *dwc) ...@@ -314,7 +314,25 @@ static int dwc3_core_init(struct dwc3 *dwc)
switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 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; break;
default: default:
dev_dbg(dwc->dev, "No power optimization available\n"); dev_dbg(dwc->dev, "No power optimization available\n");
...@@ -479,6 +497,14 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -479,6 +497,14 @@ static int dwc3_probe(struct platform_device *pdev)
goto err0; 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); ret = dwc3_core_init(dwc);
if (ret) { if (ret) {
dev_err(dev, "failed to initialize core\n"); dev_err(dev, "failed to initialize core\n");
...@@ -494,14 +520,6 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -494,14 +520,6 @@ static int dwc3_probe(struct platform_device *pdev)
goto err1; 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) { switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL: case USB_DR_MODE_PERIPHERAL:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
......
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