usb: host: xhci: set xhci autosuspend quirk based on platform data
authorWilliam Wu <wulf@rock-chips.com>
Tue, 21 Feb 2017 08:41:55 +0000 (16:41 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Wed, 22 Feb 2017 06:16:41 +0000 (14:16 +0800)
Some USB controllers (such as rk3328 SoC DWC3 controller with INNO
USB 3.0 PHY) don't support autosuspend well, when receive remote
wakeup signal from autosuspend, the Port Link State training failed,
the correct PLC is Resume->Recovery->U0, but when the issue happens,
the wrong PLC is Resume->Recovery->Inactive, cause resuming SS port
fail. This issue always occurs when connect with external USB 3.0 HUB.

This patch add a quirk to disable autosuspend function, and add new
'usb3_disable_autosuspend' member in xHCI platform data to support
set the quirk based on platform data.

Change-Id: Ice01d70178206e22658660361dd3a525046cbcf5
Signed-off-by: William Wu <wulf@rock-chips.com>
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
include/linux/usb/xhci_pdriver.h

index 8f54e5b97a045c3efffd4c181d7cfb3c00b4910b..fe7de8a58ef5495638166ace19626ee7f1b42db6 100644 (file)
@@ -172,6 +172,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
                        (pdata && pdata->usb3_lpm_capable))
                xhci->quirks |= XHCI_LPM_SUPPORT;
 
+       if (pdata && pdata->usb3_disable_autosuspend)
+               xhci->quirks |= XHCI_DIS_AUTOSUSPEND;
+
        hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
        if (IS_ERR(hcd->usb_phy)) {
                ret = PTR_ERR(hcd->usb_phy);
index c4e2b1886f5d6688aee581562276f1f4e3793493..a51d88ebf0b3cd902ae8f231233f4526fd778a22 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/dmi.h>
 #include <linux/dma-mapping.h>
+#include <linux/usb/quirks.h>
 
 #include "xhci.h"
 #include "xhci-trace.h"
@@ -4903,6 +4904,10 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
                /* xHCI private pointer was set in xhci_pci_probe for the second
                 * registered roothub.
                 */
+               if (xhci->quirks & XHCI_DIS_AUTOSUSPEND)
+                       xhci->shared_hcd->self.root_hub->quirks |=
+                               USB_QUIRK_AUTO_SUSPEND;
+
                return 0;
        }
 
index 99ac2289dbf348aa2f60541121f1842a92ecc15b..8de8cdabc9551e9b11841a6b1e5f0af2c2c29995 100644 (file)
@@ -1631,6 +1631,7 @@ struct xhci_hcd {
 /* For controllers with a broken beyond repair streams implementation */
 #define XHCI_BROKEN_STREAMS    (1 << 19)
 #define XHCI_PME_STUCK_QUIRK   (1 << 20)
+#define XHCI_DIS_AUTOSUSPEND   (1 << 21)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
index 6b3c1046b8e03ae77d2dfbcfdc22209c1db19463..cd03e02f5c9a3f088820e9d11f47686926d2ec04 100644 (file)
  * @xhci_slow_suspend: set if this xhci platform need an extraordinary
  *                     delay to wait for xHC enter the Halted state
  *                     after the Run/Stop (R/S) bit is cleared to '0'.
+ * @usb3_disable_autosuspend: determines if this xhci platform supports
+ *                     USB3 autosuspend capability
  *
  */
 struct usb_xhci_pdata {
        unsigned        usb3_lpm_capable:1;
        unsigned        xhci_slow_suspend:1;
+       unsigned        usb3_disable_autosuspend:1;
 };
 
 #endif /* __USB_CORE_XHCI_PDRIVER_H */