Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: dwc2: Properly account for the force mode delays

When a force mode bit is set and the IDDIG debounce filter is enabled,
there is a delay for the forced mode to take effect. This delay is due
to the IDDIG debounce filter and is variable depending on the platform's
PHY clock speed. To account for this delay we can poll for the expected
mode.

On a clear force mode, since we don't know what mode to poll for, delay
for a fixed 100 ms. This is the maximum delay based on the slowest PHY
clock speed.

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>

authored by

John Youn and committed by
Felipe Balbi
2938fc63 fef6bc37

+14 -17
+14 -17
drivers/usb/dwc2/core.c
··· 395 395 * Checks are done in this function to determine whether doing a force 396 396 * would be valid or not. 397 397 * 398 - * If a force is done, it requires a 25ms delay to take effect. 399 - * 400 - * Returns true if the mode was forced. 398 + * If a force is done, it requires a IDDIG debounce filter delay if 399 + * the filter is configured and enabled. We poll the current mode of 400 + * the controller to account for this delay. 401 401 */ 402 402 static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host) 403 403 { ··· 432 432 gusbcfg |= set; 433 433 dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); 434 434 435 - msleep(25); 435 + dwc2_wait_for_mode(hsotg, host); 436 436 return true; 437 437 } 438 438 439 - /* 440 - * Clears the force mode bits. 439 + /** 440 + * dwc2_clear_force_mode() - Clears the force mode bits. 441 + * 442 + * After clearing the bits, wait up to 100 ms to account for any 443 + * potential IDDIG filter delay. We can't know if we expect this delay 444 + * or not because the value of the connector ID status is affected by 445 + * the force mode. We only need to call this once during probe if 446 + * dr_mode == OTG. 441 447 */ 442 448 static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) 443 449 { ··· 454 448 gusbcfg &= ~GUSBCFG_FORCEDEVMODE; 455 449 dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG); 456 450 457 - /* 458 - * NOTE: This long sleep is _very_ important, otherwise the core will 459 - * not stay in host mode after a connector ID change! 460 - */ 461 - msleep(25); 451 + if (dwc2_iddig_filter_enabled(hsotg)) 452 + usleep_range(100000, 110000); 462 453 } 463 454 464 455 /* ··· 478 475 __func__, hsotg->dr_mode); 479 476 break; 480 477 } 481 - 482 - /* 483 - * NOTE: This is required for some rockchip soc based 484 - * platforms. 485 - */ 486 - msleep(50); 487 478 } 488 479 489 480 /*