aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2
diff options
context:
space:
mode:
authorGregory Herrero <gregory.herrero@intel.com>2015-09-22 15:16:50 +0200
committerFelipe Balbi <balbi@ti.com>2015-10-01 12:40:18 -0500
commit5634e016cf6e2e0c9651081f5c554f59e1050fc5 (patch)
treed1b86b04e1195c1cc8594ad4f1b238e11269f822 /drivers/usb/dwc2
parentusb: dwc2: host: clear pending interrupts prior hibernation (diff)
downloadlinux-dev-5634e016cf6e2e0c9651081f5c554f59e1050fc5.tar.xz
linux-dev-5634e016cf6e2e0c9651081f5c554f59e1050fc5.zip
usb: dwc2: host: wait 3ms for controller stabilization
Some high speed mass storage devices fail to enumerate with following error: Cannot enable port %i. Maybe the USB cable is bad? This happens only when the device is plugged while the controller is in hibernation state. After exiting hibernation, the controller detects the device as a low speed device and fail to enumerate it. Problem occurs only if HPRT0.PWR bit is programmed in a too short delay after exiting hibernation. Dumping hprt register in _dwc2_hcd_resume() directly after dwc2_exit_hibernation() shows that HPRT0.LNSTS (D+/D- level) becomes valid approximately 2ms after exiting hibernation. Since dwc2_exit_hibernation() is called from atomic context, move the delay out of this function. Delay value is experimental and not mentioned in Synopsys documentation. To be on the safe side 3ms delay is used. Signed-off-by: Gregory Herrero <gregory.herrero@intel.com> Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@intel.com> Tested-by: Robert Baldyga <r.baldyga@samsung.com> Tested-by: Dinh Nguyen <dinguyen@opensource.altera.com> Tested-by: John Youn <johnyoun@synopsys.com> Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r--drivers/usb/dwc2/hcd.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index de9d2e2bbf48..65044daddc13 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2472,6 +2472,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_port_resume(hsotg);
} else {
+ /* Wait for controller to correctly update D+/D- level */
+ usleep_range(3000, 5000);
+
/*
* Clear Port Enable and Port Status changes.
* Enable Port Power.
@@ -2479,7 +2482,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
dwc2_writel(HPRT0_PWR | HPRT0_CONNDET |
HPRT0_ENACHG, hsotg->regs + HPRT0);
/* Wait for controller to detect Port Connect */
- mdelay(5);
+ usleep_range(5000, 7000);
}
return ret;