summaryrefslogtreecommitdiff
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorAjay Agarwal <ajaya@codeaurora.org>2017-08-17 18:47:19 +0530
committerAjay Agarwal <ajaya@codeaurora.org>2017-09-27 11:13:37 +0530
commitc97f5a36d522c7848c326b69ad72e702193dbf60 (patch)
tree4f7343954db32072f142c153ec8e7f42acf277f6 /drivers/usb/host
parentcb8f9c4da75aaf6cf869ade763661704999b871a (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.c30
-rw-r--r--drivers/usb/host/xhci.c6
-rw-r--r--drivers/usb/host/xhci.h1
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
};