aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Youn <johnyoun@synopsys.com>2016-09-07 22:39:40 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2016-09-08 07:02:52 -0400
commitfef6bc37dbafe0d6d71c808c8867a8c5ab4b9816 (patch)
tree49ce6e8972a41b8ed336dffc1c8dce912cc79b5e
parentd0f0ac56b34b28e80223d7086b4decdf027c27ed (diff)
usb: dwc2: Add delay to core soft reset
Add a delay to the core soft reset function to account for the IDDIG debounce filter. If the current mode is host, either due to the force mode bit being set (which persists after core reset) or the connector id pin, a core soft reset will temporarily reset the mode to device and a delay from the IDDIG debounce filter will occur before going back to host mode. Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/dwc2/core.c95
-rw-r--r--drivers/usb/dwc2/core.h1
-rw-r--r--drivers/usb/dwc2/hw.h1
3 files changed, 97 insertions, 0 deletions
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 4135a5ff67ca..a3068e01c609 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -238,6 +238,77 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
238 return ret; 238 return ret;
239} 239}
240 240
241/**
242 * dwc2_wait_for_mode() - Waits for the controller mode.
243 * @hsotg: Programming view of the DWC_otg controller.
244 * @host_mode: If true, waits for host mode, otherwise device mode.
245 */
246static void dwc2_wait_for_mode(struct dwc2_hsotg *hsotg,
247 bool host_mode)
248{
249 ktime_t start;
250 ktime_t end;
251 unsigned int timeout = 110;
252
253 dev_vdbg(hsotg->dev, "Waiting for %s mode\n",
254 host_mode ? "host" : "device");
255
256 start = ktime_get();
257
258 while (1) {
259 s64 ms;
260
261 if (dwc2_is_host_mode(hsotg) == host_mode) {
262 dev_vdbg(hsotg->dev, "%s mode set\n",
263 host_mode ? "Host" : "Device");
264 break;
265 }
266
267 end = ktime_get();
268 ms = ktime_to_ms(ktime_sub(end, start));
269
270 if (ms >= (s64)timeout) {
271 dev_warn(hsotg->dev, "%s: Couldn't set %s mode\n",
272 __func__, host_mode ? "host" : "device");
273 break;
274 }
275
276 usleep_range(1000, 2000);
277 }
278}
279
280/**
281 * dwc2_iddig_filter_enabled() - Returns true if the IDDIG debounce
282 * filter is enabled.
283 */
284static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg)
285{
286 u32 gsnpsid;
287 u32 ghwcfg4;
288
289 if (!dwc2_hw_is_otg(hsotg))
290 return false;
291
292 /* Check if core configuration includes the IDDIG filter. */
293 ghwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
294 if (!(ghwcfg4 & GHWCFG4_IDDIG_FILT_EN))
295 return false;
296
297 /*
298 * Check if the IDDIG debounce filter is bypassed. Available
299 * in core version >= 3.10a.
300 */
301 gsnpsid = dwc2_readl(hsotg->regs + GSNPSID);
302 if (gsnpsid >= DWC2_CORE_REV_3_10a) {
303 u32 gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
304
305 if (gotgctl & GOTGCTL_DBNCE_FLTR_BYPASS)
306 return false;
307 }
308
309 return true;
310}
311
241/* 312/*
242 * Do core a soft reset of the core. Be careful with this because it 313 * Do core a soft reset of the core. Be careful with this because it
243 * resets all the internal state machines of the core. 314 * resets all the internal state machines of the core.
@@ -246,9 +317,30 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
246{ 317{
247 u32 greset; 318 u32 greset;
248 int count = 0; 319 int count = 0;
320 bool wait_for_host_mode = false;
249 321
250 dev_vdbg(hsotg->dev, "%s()\n", __func__); 322 dev_vdbg(hsotg->dev, "%s()\n", __func__);
251 323
324 /*
325 * If the current mode is host, either due to the force mode
326 * bit being set (which persists after core reset) or the
327 * connector id pin, a core soft reset will temporarily reset
328 * the mode to device. A delay from the IDDIG debounce filter
329 * will occur before going back to host mode.
330 *
331 * Determine whether we will go back into host mode after a
332 * reset and account for this delay after the reset.
333 */
334 if (dwc2_iddig_filter_enabled(hsotg)) {
335 u32 gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
336 u32 gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
337
338 if (!(gotgctl & GOTGCTL_CONID_B) ||
339 (gusbcfg & GUSBCFG_FORCEHOSTMODE)) {
340 wait_for_host_mode = true;
341 }
342 }
343
252 /* Core Soft Reset */ 344 /* Core Soft Reset */
253 greset = dwc2_readl(hsotg->regs + GRSTCTL); 345 greset = dwc2_readl(hsotg->regs + GRSTCTL);
254 greset |= GRSTCTL_CSFTRST; 346 greset |= GRSTCTL_CSFTRST;
@@ -277,6 +369,9 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
277 } 369 }
278 } while (!(greset & GRSTCTL_AHBIDLE)); 370 } while (!(greset & GRSTCTL_AHBIDLE));
279 371
372 if (wait_for_host_mode)
373 dwc2_wait_for_mode(hsotg, true);
374
280 return 0; 375 return 0;
281} 376}
282 377
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 78526eedf519..466c220914d4 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -882,6 +882,7 @@ struct dwc2_hsotg {
882#define DWC2_CORE_REV_2_92a 0x4f54292a 882#define DWC2_CORE_REV_2_92a 0x4f54292a
883#define DWC2_CORE_REV_2_94a 0x4f54294a 883#define DWC2_CORE_REV_2_94a 0x4f54294a
884#define DWC2_CORE_REV_3_00a 0x4f54300a 884#define DWC2_CORE_REV_3_00a 0x4f54300a
885#define DWC2_CORE_REV_3_10a 0x4f54310a
885 886
886#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) 887#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
887 union dwc2_hcd_internal_flags { 888 union dwc2_hcd_internal_flags {
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
index efc3bcde2822..91058441e62a 100644
--- a/drivers/usb/dwc2/hw.h
+++ b/drivers/usb/dwc2/hw.h
@@ -48,6 +48,7 @@
48#define GOTGCTL_ASESVLD (1 << 18) 48#define GOTGCTL_ASESVLD (1 << 18)
49#define GOTGCTL_DBNC_SHORT (1 << 17) 49#define GOTGCTL_DBNC_SHORT (1 << 17)
50#define GOTGCTL_CONID_B (1 << 16) 50#define GOTGCTL_CONID_B (1 << 16)
51#define GOTGCTL_DBNCE_FLTR_BYPASS (1 << 15)
51#define GOTGCTL_DEVHNPEN (1 << 11) 52#define GOTGCTL_DEVHNPEN (1 << 11)
52#define GOTGCTL_HSTSETHNPEN (1 << 10) 53#define GOTGCTL_HSTSETHNPEN (1 << 10)
53#define GOTGCTL_HNPREQ (1 << 9) 54#define GOTGCTL_HNPREQ (1 << 9)