summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikhil Badola <nikhil.badola@freescale.com>2015-09-04 04:45:58 (GMT)
committerXie Xiaobo <xiaobo.xie@nxp.com>2017-09-25 07:25:50 (GMT)
commit2edcc4c298119b54bcc71b60392cd6be5eadf003 (patch)
treeb05378ce451fd00c56f493e3a546352dccf19550
parent34eab549367bdaed96487fc8470ed2da4ba1070c (diff)
downloadlinux-2edcc4c298119b54bcc71b60392cd6be5eadf003.tar.xz
usb: dwc3: Add frame length adjustment quirk
Add adjust_frame_length_quirk for writing to fladj register which adjusts (micro)frame length to value provided by "snps,quirk-frame-length-adjustment" property thus avoiding USB 2.0 devices to time-out over a longer run Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/dwc3/core.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 8e2e7a7..e34ef90 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -215,6 +215,32 @@ static int dwc3_soft_reset(struct dwc3 *dwc)
return 0;
}
+/*
+ * dwc3_frame_length_adjustment - Adjusts frame length if required
+ * @dwc3: Pointer to our controller context structure
+ */
+static void dwc3_frame_length_adjustment(struct dwc3 *dwc)
+{
+ u32 reg;
+ u32 dft;
+
+ if (dwc->revision < DWC3_REVISION_250A)
+ return;
+
+ if (dwc->fladj == 0)
+ return;
+
+ reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
+ dft = reg & DWC3_GFLADJ_30MHZ_MASK;
+ if (dft == dwc->fladj) {
+ dev_warn(dwc->dev, "request value same as default, ignoring\n");
+ } else {
+ reg &= ~DWC3_GFLADJ_30MHZ_MASK;
+ reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;
+ dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
+ }
+}
+
/**
* dwc3_free_one_event_buffer - Frees one event buffer
* @dwc: Pointer to our controller context structure
@@ -810,6 +836,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_set_soc_bus_cfg(dwc);
+ /* Adjust Frame Length */
+ dwc3_frame_length_adjustment(dwc);
+
usb_phy_set_suspend(dwc->usb2_phy, 0);
usb_phy_set_suspend(dwc->usb3_phy, 0);
ret = phy_power_on(dwc->usb2_generic_phy);
@@ -1107,7 +1136,6 @@ static void dwc3_get_properties(struct dwc3 *dwc)
static int dwc3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct dwc3_platform_data *pdata = dev_get_platdata(dev);
struct device_node *node = dev->of_node;
struct resource *res;
struct dwc3 *dwc;