linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Roger Quadros <rogerq@ti.com>
To: <stern@rowland.harvard.edu>, <tony@atomide.com>
Cc: <balbi@ti.com>, <ruslan.bilovol@ti.com>,
	<linux-usb@vger.kernel.org>, <linux-omap@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	Roger Quadros <rogerq@ti.com>
Subject: [RFC PATCH 4/6] USB: ehci-omap: Suspend the controller during bus suspend
Date: Wed, 19 Jun 2013 17:05:51 +0300	[thread overview]
Message-ID: <1371650753-11452-5-git-send-email-rogerq@ti.com> (raw)
In-Reply-To: <1371650753-11452-1-git-send-email-rogerq@ti.com>

Runtime suspend the controller during bus suspend and resume it
during bus resume. This will ensure that the USB Host power domain
enters lower power state and does not prevent the SoC from
endering deeper sleep states.

Remote wakeup will come up as an interrupt while the controller
is suspended, so tackle it carefully using a workqueue.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/usb/host/ehci-omap.c |   82 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 16d7150..91f14f1 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -44,6 +44,8 @@
 #include <linux/usb/hcd.h>
 #include <linux/of.h>
 #include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
 
 #include "ehci.h"
 
@@ -69,6 +71,7 @@ static const char hcd_name[] = "ehci-omap";
 struct omap_hcd {
 	struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */
 	int nports;
+	struct work_struct work;
 };
 
 static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
@@ -81,6 +84,76 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
 	return __raw_readl(base + reg);
 }
 
+static void omap_ehci_work(struct work_struct *work)
+{
+	struct omap_hcd *omap = container_of(work, struct omap_hcd, work);
+	struct ehci_hcd *ehci = container_of((void *) omap,
+						struct ehci_hcd, priv);
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
+	struct device *dev = hcd->self.controller;
+
+	pm_runtime_get_sync(dev);
+	enable_irq(hcd->irq);
+	/*
+	 * enable_irq() should preempt us with a pending IRQ
+	 * so we can be sure that IRQ handler completes before
+	 * we call pm_runtime_put_sync()
+	 */
+	pm_runtime_put_sync(dev);
+}
+
+static irqreturn_t omap_ehci_irq(struct usb_hcd *hcd)
+{
+	struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+	struct device *dev = hcd->self.controller;
+	irqreturn_t ret;
+
+	if (pm_runtime_suspended(dev)) {
+		schedule_work(&omap->work);
+		disable_irq_nosync(hcd->irq);
+		ret = IRQ_HANDLED;
+	} else
+		ret = ehci_irq(hcd);
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int omap_ehci_bus_suspend(struct usb_hcd *hcd)
+{
+	struct device *dev;
+	int ret;
+
+	dev = hcd->self.controller;
+	ret = ehci_bus_suspend(hcd);
+	if (ret)
+		return ret;
+
+	ret = pm_runtime_put_sync(dev);
+	if (ret < 0 && !(ret == -EBUSY || ret == -EAGAIN)) {
+		dev_err(dev, "Failed to runtime suspend :%d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int omap_ehci_bus_resume(struct usb_hcd *hcd)
+{
+	struct device *dev;
+	int ret;
+
+	dev = hcd->self.controller;
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		dev_err(dev, "Failed to runtime resume :%d\n", ret);
+		return ret;
+	}
+
+	return ehci_bus_resume(hcd);
+}
+#endif /* CONFIG_PM */
+
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -88,6 +161,11 @@ static struct hc_driver __read_mostly ehci_omap_hc_driver;
 
 static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
 	.extra_priv_size = sizeof(struct omap_hcd),
+#ifdef CONFIG_PM
+	.bus_suspend = omap_ehci_bus_suspend,
+	.bus_resume = omap_ehci_bus_resume,
+#endif
+	.irq = omap_ehci_irq,
 };
 
 /**
@@ -163,6 +241,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
 
 	omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
 	omap->nports = pdata->nports;
+	INIT_WORK(&omap->work, omap_ehci_work);
 
 	platform_set_drvdata(pdev, hcd);
 
@@ -257,6 +336,9 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
 	struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
 	int i;
 
+	if (pm_runtime_suspended(dev))
+		pm_runtime_get_sync(dev);
+
 	usb_remove_hcd(hcd);
 
 	for (i = 0; i < omap->nports; i++) {
-- 
1.7.4.1


  parent reply	other threads:[~2013-06-19 14:06 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-19 14:05 [RFC PATCH 0/6] Suspend USB Host controller on bus suspend Roger Quadros
2013-06-19 14:05 ` [RFC PATCH 1/6] mfd: omap-usb-host: move initialization to module_init() Roger Quadros
2013-06-20 12:07   ` Felipe Balbi
2013-06-20 12:29     ` Roger Quadros
2013-06-19 14:05 ` [RFC PATCH 2/6] mfd: omap-usb-host: Put pins in IDLE state on suspend Roger Quadros
2013-06-19 17:23   ` Kevin Hilman
2013-06-20  7:21     ` Tony Lindgren
2013-06-20 12:30     ` Roger Quadros
2013-06-19 14:05 ` [RFC PATCH 3/6] USB: ehci: allow controller drivers to override irq & bus_suspend/resume Roger Quadros
2013-06-19 14:05 ` Roger Quadros [this message]
2013-06-19 17:39   ` [RFC PATCH 4/6] USB: ehci-omap: Suspend the controller during bus suspend Kevin Hilman
2013-06-20 12:32     ` Roger Quadros
2013-06-20 12:11   ` Felipe Balbi
2013-06-20 12:35     ` Roger Quadros
2013-06-20 17:33       ` Alan Stern
2013-06-24 15:09         ` Roger Quadros
2013-06-24 19:34           ` Alan Stern
2013-06-25 13:59             ` Roger Quadros
2013-06-25 17:38               ` Alan Stern
2013-06-26 13:38                 ` Roger Quadros
2013-06-27 15:40                   ` Alan Stern
2013-06-28 12:20                     ` Roger Quadros
2013-06-28 13:57                       ` Roger Quadros
2013-06-28 19:18                         ` Alan Stern
2013-07-01  8:33                           ` Roger Quadros
2013-06-28 19:06                       ` Alan Stern
2013-07-01  8:16                         ` Roger Quadros
2013-07-01 16:24                           ` Alan Stern
2013-07-01 16:49                             ` Felipe Balbi
2013-07-01 21:01                               ` Alan Stern
2013-07-02  8:22                                 ` Roger Quadros
2013-07-02 17:17                                   ` Alan Stern
2013-07-03  9:13                                     ` Roger Quadros
2013-07-03 12:57                                     ` Felipe Balbi
2013-07-03 13:06                                       ` Roger Quadros
2013-07-03 13:15                                         ` Felipe Balbi
2013-07-03 14:30                                           ` Alan Stern
2013-07-09 13:58                         ` Roger Quadros
2013-06-19 14:05 ` [RFC PATCH 5/6] ARM: dts: omap3beagle-xm: Add idle state pins for USB host Roger Quadros
2013-06-19 18:42   ` Kevin Hilman
2013-06-20 11:55     ` Roger Quadros
2013-06-20 12:02       ` Roger Quadros
2013-06-20 13:02         ` Roger Quadros
2013-06-19 14:05 ` [RFC PATCH 6/6] ARM: OMAP3: Enable Hardware Save and Restore for USB Host Roger Quadros
2013-06-19 17:30   ` Sergei Shtylyov
2013-06-20 12:42     ` Roger Quadros
2013-06-19 15:23 ` [RFC PATCH 0/6] Suspend USB Host controller on bus suspend Alan Stern
2013-06-20 12:39   ` Roger Quadros
2013-06-20 17:19     ` Alan Stern

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1371650753-11452-5-git-send-email-rogerq@ti.com \
    --to=rogerq@ti.com \
    --cc=balbi@ti.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=ruslan.bilovol@ti.com \
    --cc=stern@rowland.harvard.edu \
    --cc=tony@atomide.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).