X-Git-Url: http://plrg.eecs.uci.edu/git/?p=firefly-linux-kernel-4.4.55.git;a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fxhci-plat.c;h=cf809492d3893d79381982cb560bba47bdbc8a91;hp=05647e6753cd833f9b9e87924832be5d3e2c2216;hb=77bab04357900ac51406698753fbcdca95caa01e;hpb=d441fe25e7de576e36a3cd96f22b737d2f15372a diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 05647e6753cd..cf809492d389 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -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, @@ -159,8 +172,17 @@ static int xhci_plat_probe(struct platform_device *pdev) (pdata && pdata->usb3_lpm_capable)) xhci->quirks |= XHCI_LPM_SUPPORT; - if (HCC_MAX_PSA(xhci->hcc_params) >= 4) - xhci->shared_hcd->can_do_streams = 1; + if (pdata && pdata->usb3_disable_autosuspend) + xhci->quirks |= XHCI_DIS_AUTOSUSPEND; + + xhci->shared_hcd->usb_phy = devm_usb_get_phy(&pdev->dev, + USB_PHY_TYPE_USB3); + if (IS_ERR(xhci->shared_hcd->usb_phy)) { + ret = PTR_ERR(xhci->shared_hcd->usb_phy); + if (ret == -EPROBE_DEFER) + goto put_usb3_hcd; + xhci->shared_hcd->usb_phy = NULL; + } hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); if (IS_ERR(hcd->usb_phy)) { @@ -178,10 +200,16 @@ static int xhci_plat_probe(struct platform_device *pdev) if (ret) goto disable_usb_phy; + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) + xhci->shared_hcd->can_do_streams = 1; + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) + xhci->shared_hcd->can_do_streams = 1; + return 0; @@ -210,6 +238,8 @@ static int xhci_plat_remove(struct platform_device *dev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct clk *clk = xhci->clk; + xhci->xhc_state |= XHCI_STATE_REMOVING; + usb_remove_hcd(xhci->shared_hcd); usb_phy_shutdown(hcd->usb_phy); @@ -279,6 +309,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,