| From 48814bc6ea992e21c21315c5dbafc7ca723dbb0b Mon Sep 17 00:00:00 2001 |
| From: Baolin Wang <baolin.wang@linaro.org> |
| Date: Wed, 19 Apr 2017 16:55:45 +0300 |
| Subject: [PATCH 200/286] usb: host: plat: Enable xHCI plat runtime PM |
| |
| Enable the xHCI plat runtime PM for parent device to suspend/resume |
| xHCI. Also call pm_runtime_forbid() in probe() function to force users |
| to explicitly enable runtime pm using power/control in sysfs, in case |
| some parent devices didn't implement runtime PM callbacks. |
| |
| [set do_wakeup to true when runtime suspending -Mathias] |
| Signed-off-by: Baolin Wang <baolin.wang@linaro.org> |
| Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit b0c69b4bace3703a29e08dda2b5a10e1073cb9cd) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| |
| Conflicts: |
| drivers/usb/host/xhci-plat.c |
| --- |
| drivers/usb/host/xhci-plat.c | 53 +++++++++++++++++++++++++++++++++++++------ |
| 1 file changed, 46 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/usb/host/xhci-plat.c |
| +++ b/drivers/usb/host/xhci-plat.c |
| @@ -179,9 +179,15 @@ static int xhci_plat_probe(struct platfo |
| return ret; |
| } |
| |
| + pm_runtime_set_active(&pdev->dev); |
| + pm_runtime_enable(&pdev->dev); |
| + pm_runtime_get_noresume(&pdev->dev); |
| + |
| hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); |
| - if (!hcd) |
| - return -ENOMEM; |
| + if (!hcd) { |
| + ret = -ENOMEM; |
| + goto disable_runtime; |
| + } |
| |
| res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| hcd->regs = devm_ioremap_resource(&pdev->dev, res); |
| @@ -259,6 +265,13 @@ static int xhci_plat_probe(struct platfo |
| goto dealloc_usb2_hcd; |
| |
| device_enable_async_suspend(&pdev->dev); |
| + pm_runtime_put_noidle(&pdev->dev); |
| + |
| + /* |
| + * Prevent runtime pm from being on as default, users should enable |
| + * runtime pm using power/control in sysfs. |
| + */ |
| + pm_runtime_forbid(&pdev->dev); |
| |
| return 0; |
| |
| @@ -279,6 +292,10 @@ disable_clk: |
| put_hcd: |
| usb_put_hcd(hcd); |
| |
| +disable_runtime: |
| + pm_runtime_put_noidle(&pdev->dev); |
| + pm_runtime_disable(&pdev->dev); |
| + |
| return ret; |
| } |
| |
| @@ -300,6 +317,9 @@ static int xhci_plat_remove(struct platf |
| clk_disable_unprepare(clk); |
| usb_put_hcd(hcd); |
| |
| + pm_runtime_set_suspended(&dev->dev); |
| + pm_runtime_disable(&dev->dev); |
| + |
| return 0; |
| } |
| |
| @@ -327,14 +347,33 @@ static int xhci_plat_resume(struct devic |
| |
| return xhci_resume(xhci, 0); |
| } |
| +#endif /* CONFIG_PM_SLEEP */ |
| + |
| +#ifdef CONFIG_PM |
| +static int xhci_plat_runtime_suspend(struct device *dev) |
| +{ |
| + struct usb_hcd *hcd = dev_get_drvdata(dev); |
| + struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
| + |
| + return xhci_suspend(xhci, true); |
| +} |
| + |
| +static int xhci_plat_runtime_resume(struct device *dev) |
| +{ |
| + struct usb_hcd *hcd = dev_get_drvdata(dev); |
| + struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
| + |
| + return xhci_resume(xhci, 0); |
| +} |
| +#endif /* CONFIG_PM */ |
| |
| static const struct dev_pm_ops xhci_plat_pm_ops = { |
| SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume) |
| + |
| + SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, |
| + xhci_plat_runtime_resume, |
| + NULL) |
| }; |
| -#define DEV_PM_OPS (&xhci_plat_pm_ops) |
| -#else |
| -#define DEV_PM_OPS NULL |
| -#endif /* CONFIG_PM */ |
| |
| static const struct acpi_device_id usb_xhci_acpi_match[] = { |
| /* XHCI-compliant USB Controller */ |
| @@ -348,7 +387,7 @@ static struct platform_driver usb_xhci_d |
| .remove = xhci_plat_remove, |
| .driver = { |
| .name = "xhci-hcd", |
| - .pm = DEV_PM_OPS, |
| + .pm = &xhci_plat_pm_ops, |
| .of_match_table = of_match_ptr(usb_xhci_of_match), |
| .acpi_match_table = ACPI_PTR(usb_xhci_acpi_match), |
| }, |