diff options
| author | Ajay Agarwal <ajaya@codeaurora.org> | 2017-08-17 18:47:19 +0530 |
|---|---|---|
| committer | Ajay Agarwal <ajaya@codeaurora.org> | 2017-09-27 11:13:37 +0530 |
| commit | c97f5a36d522c7848c326b69ad72e702193dbf60 (patch) | |
| tree | 4f7343954db32072f142c153ec8e7f42acf277f6 /drivers/usb/host | |
| parent | cb8f9c4da75aaf6cf869ade763661704999b871a (diff) | |
usb: dwc3-msm: Allow PM suspend in host mode irrespective of runtimePM
DWC3 driver uses wakeup_source and allows pm_suspend only after
entering low power mode as part of runtime suspend. This prevents
PM suspend in host mode if connected device's driver doesn't
support runtime or selective suspend.
Add support in driver where user can specify using dtsi attribute
to not use wakeup source in host mode. It will allow system to enter
deep sleep or pm_suspend irrespective of runtime PM state of XHCI.
On high level below are the changes in default behavior:
-Do not use wakeup_source for DWC3 when operating in host mode.
-For host mode, devices will suspend upon PM suspend and resumed
after PM resume.
Change-Id: Ia1d450e6dd99e094e48caf9723a355b7870b54dd
Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/xhci-plat.c | 30 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.c | 6 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.h | 1 |
3 files changed, 34 insertions, 3 deletions
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 56a9cd62f2c4..c6998f086e12 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -325,6 +325,34 @@ static int xhci_plat_remove(struct platform_device *dev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int xhci_plat_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + if (!xhci) + return 0; + + dev_dbg(dev, "xhci-plat PM suspend\n"); + + return xhci_suspend(xhci, true); +} + +static int xhci_plat_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + if (!xhci) + return 0; + + dev_dbg(dev, "xhci-plat PM resume\n"); + + return xhci_resume(xhci, false); +} +#endif + #ifdef CONFIG_PM static int xhci_plat_runtime_idle(struct device *dev) { @@ -373,7 +401,7 @@ static int xhci_plat_runtime_resume(struct device *dev) } static const struct dev_pm_ops xhci_plat_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, NULL) + SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume) SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, xhci_plat_runtime_resume, xhci_plat_runtime_idle) }; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index aab1c7903288..641e0280ad5a 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -918,7 +918,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; - if (!hcd->state) + if (!hcd->state || xhci->suspended) return 0; if (hcd->state != HC_STATE_SUSPENDED || @@ -988,6 +988,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) /* step 5: remove core well power */ /* synchronize irq when using MSI-X */ xhci_msix_sync_irqs(xhci); + xhci->suspended = true; return rc; } @@ -1007,7 +1008,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) int retval = 0; bool comp_timer_running = false; - if (!hcd->state) + if (!hcd->state || !xhci->suspended) return 0; /* Wait a bit if either of the roothubs need to settle from the @@ -1141,6 +1142,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* Re-enable port polling. */ xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + xhci->suspended = false; set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); usb_hcd_poll_rh_status(xhci->shared_hcd); set_bit(HCD_FLAG_POLL_RH, &hcd->flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8fcec1be6b1a..7fc97d930657 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1667,6 +1667,7 @@ struct xhci_hcd { /* Compliance Mode Recovery Data */ struct timer_list comp_mode_recovery_timer; u32 port_status_u0; + bool suspended; /* Compliance Mode Timer Triggered every 2 seconds */ #define COMP_MODE_RCVRY_MSECS 2000 }; |
