kernel: bump to 4.4.35
[openwrt/openwrt.git] / target / linux / ipq806x / patches-4.4 / 096-06-usb-dwc3-core-improve-reset-sequence.patch
1 From f59dcab176293b646e1358144c93c58c3cda2813 Mon Sep 17 00:00:00 2001
2 From: Felipe Balbi <felipe.balbi@linux.intel.com>
3 Date: Fri, 11 Mar 2016 10:51:52 +0200
4 Subject: usb: dwc3: core: improve reset sequence
5
6 According to Synopsys Databook, we shouldn't be
7 relying on GCTL.CORESOFTRESET bit as that's only for
8 debugging purposes. Instead, let's use DCTL.CSFTRST
9 if we're OTG or PERIPHERAL mode.
10
11 Host side block will be reset by XHCI driver if
12 necessary. Note that this reduces amount of time
13 spent on dwc3_probe() by a long margin.
14
15 We're still gonna wait for reset to finish for a
16 long time (default to 1ms max), but tests show that
17 the reset polling loop executed at most 19 times
18 (modprobe dwc3 && modprobe -r dwc3 executed 1000
19 times in a row).
20
21 Suggested-by: Mian Yousaf Kaukab <yousaf.kaukab@intel.com>
22 Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
23 ---
24 drivers/usb/dwc3/core.c | 48 ++++++++++++++++++------------------------------
25 1 file changed, 18 insertions(+), 30 deletions(-)
26
27 --- a/drivers/usb/dwc3/core.c
28 +++ b/drivers/usb/dwc3/core.c
29 @@ -67,23 +67,9 @@ void dwc3_set_mode(struct dwc3 *dwc, u32
30 static int dwc3_core_soft_reset(struct dwc3 *dwc)
31 {
32 u32 reg;
33 + int retries = 1000;
34 int ret;
35
36 - /* Before Resetting PHY, put Core in Reset */
37 - reg = dwc3_readl(dwc->regs, DWC3_GCTL);
38 - reg |= DWC3_GCTL_CORESOFTRESET;
39 - dwc3_writel(dwc->regs, DWC3_GCTL, reg);
40 -
41 - /* Assert USB3 PHY reset */
42 - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
43 - reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
44 - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
45 -
46 - /* Assert USB2 PHY reset */
47 - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
48 - reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
49 - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
50 -
51 usb_phy_init(dwc->usb2_phy);
52 usb_phy_init(dwc->usb3_phy);
53 ret = phy_init(dwc->usb2_generic_phy);
54 @@ -95,26 +81,28 @@ static int dwc3_core_soft_reset(struct d
55 phy_exit(dwc->usb2_generic_phy);
56 return ret;
57 }
58 - mdelay(100);
59
60 - /* Clear USB3 PHY reset */
61 - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
62 - reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
63 - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
64 -
65 - /* Clear USB2 PHY reset */
66 - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
67 - reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
68 - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
69 -
70 - mdelay(100);
71 -
72 - /* After PHYs are stable we can take Core out of reset state */
73 - reg = dwc3_readl(dwc->regs, DWC3_GCTL);
74 - reg &= ~DWC3_GCTL_CORESOFTRESET;
75 - dwc3_writel(dwc->regs, DWC3_GCTL, reg);
76 + /*
77 + * We're resetting only the device side because, if we're in host mode,
78 + * XHCI driver will reset the host block. If dwc3 was configured for
79 + * host-only mode, then we can return early.
80 + */
81 + if (dwc->dr_mode == USB_DR_MODE_HOST)
82 + return 0;
83 +
84 + reg = dwc3_readl(dwc->regs, DWC3_DCTL);
85 + reg |= DWC3_DCTL_CSFTRST;
86 + dwc3_writel(dwc->regs, DWC3_DCTL, reg);
87 +
88 + do {
89 + reg = dwc3_readl(dwc->regs, DWC3_DCTL);
90 + if (!(reg & DWC3_DCTL_CSFTRST))
91 + return 0;
92 +
93 + udelay(1);
94 + } while (--retries);
95
96 - return 0;
97 + return -ETIMEDOUT;
98 }
99
100 /**