CHROMIUM: usb: xhci-plat: use usb_hcd_platform_shutdown() callback
[firefly-linux-kernel-4.4.55.git] / drivers / usb / host / xhci-plat.c
index 05647e6753cd833f9b9e87924832be5d3e2c2216..87a6199dc83c9d26f10f49f44a04a9768641b9e3 100644 (file)
@@ -38,12 +38,22 @@ static const struct xhci_driver_overrides xhci_plat_overrides __initconst = {
 
 static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
 {
+       struct usb_xhci_pdata *pdata = dev_get_platdata(dev);
+
        /*
         * As of now platform drivers don't provide MSI support so we ensure
         * here that the generic code does not try to make a pci_dev from our
         * dev struct in order to setup MSI
         */
        xhci->quirks |= XHCI_PLAT;
+
+       /*
+        * On some xHCI controllers (e.g. Rockchip SoCs), it need an
+        * extraordinary delay to wait for xHCI enter the Halted state
+        * after the Run/Stop (R/S) bit is cleared to '0'.
+        */
+       if (pdata && pdata->xhci_slow_suspend)
+               xhci->quirks |= XHCI_SLOW_SUSPEND;
 }
 
 /* called during probe() after chip reset completes */
@@ -132,6 +142,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
                ret = clk_prepare_enable(clk);
                if (ret)
                        goto put_hcd;
+       } else if (PTR_ERR(clk) == -EPROBE_DEFER) {
+               ret = -EPROBE_DEFER;
+               goto put_hcd;
        }
 
        if (of_device_is_compatible(pdev->dev.of_node,
@@ -279,6 +292,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
 static struct platform_driver usb_xhci_driver = {
        .probe  = xhci_plat_probe,
        .remove = xhci_plat_remove,
+       .shutdown = usb_hcd_platform_shutdown,
        .driver = {
                .name = "xhci-hcd",
                .pm = DEV_PM_OPS,