xhci_dbg(xhci, "reset stuck port %d\n", port_index);
continue;
}
+
+ /*
+ * Workaround for missing CCS and CSC on resume if controller
+ * is powered down in S3 with device plugged in.
+ */
+ if ((xhci->quirks & XHCI_WARM_RESET_ON_RESUME) &&
+ (hcd->speed >= HCD_USB3) &&
+ !(temp & (PORT_CSC | PORT_CONNECT))) {
+ /* clear wakeup/change bits, and do a warm port reset */
+ temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
+ temp |= PORT_WR;
+ writel(temp, port_array[port_index]);
+ /* flush write */
+ readl(port_array[port_index]);
+ continue;
+ }
+
if (DEV_SUPERSPEED_ANY(temp))
temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
else
*/
if (pdata && pdata->xhci_slow_suspend)
xhci->quirks |= XHCI_SLOW_SUSPEND;
+
+ if (pdata && pdata->usb3_warm_reset_on_resume)
+ xhci->quirks |= XHCI_WARM_RESET_ON_RESUME;
}
/* called during probe() after chip reset completes */
#define XHCI_PME_STUCK_QUIRK (1 << 20)
#define XHCI_DIS_AUTOSUSPEND (1 << 21)
#define XHCI_MISSING_CAS (1 << 24)
+#define XHCI_WARM_RESET_ON_RESUME (1 << 25)
unsigned int num_active_eps;
unsigned int limit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */
* after the Run/Stop (R/S) bit is cleared to '0'.
* @usb3_disable_autosuspend: determines if this xhci platform supports
* USB3 autosuspend capability
+ * @usb3_warm_reset_on_resume: determines if it need warm reset on resume.
*
*/
struct usb_xhci_pdata {
unsigned usb3_lpm_capable:1;
unsigned xhci_slow_suspend:1;
unsigned usb3_disable_autosuspend:1;
+ unsigned usb3_warm_reset_on_resume:1;
};
#endif /* __USB_CORE_XHCI_PDRIVER_H */