From patchwork Wed Jul 10 16:23:25 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Quadros X-Patchwork-Id: 2825825 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E93279F756 for ; Wed, 10 Jul 2013 16:26:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B759A201C7 for ; Wed, 10 Jul 2013 16:26:55 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2E567201C4 for ; Wed, 10 Jul 2013 16:26:54 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UwxBm-0005Il-3J; Wed, 10 Jul 2013 16:24:23 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UwxBN-0001Uj-Tk; Wed, 10 Jul 2013 16:23:57 +0000 Received: from comal.ext.ti.com ([198.47.26.152]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UwxBK-0001SW-MT for linux-arm-kernel@lists.infradead.org; Wed, 10 Jul 2013 16:23:55 +0000 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id r6AGNT4Z029272; Wed, 10 Jul 2013 11:23:29 -0500 Received: from DLEE71.ent.ti.com (dlee71.ent.ti.com [157.170.170.114]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id r6AGNT6i016450; Wed, 10 Jul 2013 11:23:29 -0500 Received: from dlelxv22.itg.ti.com (172.17.1.197) by DLEE71.ent.ti.com (157.170.170.114) with Microsoft SMTP Server id 14.2.342.3; Wed, 10 Jul 2013 11:23:29 -0500 Received: from localhost.localdomain (h0-150.vpn.ti.com [172.24.0.150]) by dlelxv22.itg.ti.com (8.13.8/8.13.8) with ESMTP id r6AGNQCa010213; Wed, 10 Jul 2013 11:23:27 -0500 From: Roger Quadros To: Subject: [PATCH 6/6] USB: ehci-omap: Implement suspend/resume Date: Wed, 10 Jul 2013 19:23:25 +0300 Message-ID: <1373473405-27589-1-git-send-email-rogerq@ti.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1373473081-27181-1-git-send-email-rogerq@ti.com> References: <1373473081-27181-1-git-send-email-rogerq@ti.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130710_122354_819230_9416C3A7 X-CRM114-Status: GOOD ( 13.71 ) X-Spam-Score: -7.2 (-------) Cc: khilman@linaro.org, sergei.shtylyov@cogentembedded.com, tony@atomide.com, gregkh@linuxfoundation.org, ruslan.bilovol@ti.com, linux-kernel@vger.kernel.org, balbi@ti.com, linux-usb@vger.kernel.org, linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Roger Quadros X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Call ehci_suspend/resume() during runtime suspend/resume as well as system suspend/resume. Use a flag "bound" to indicate that the HCD structures are valid. This is only true between usb_add_hcd() and usb_remove_hcd() calls. The flag can be used by omap_ehci_runtime_suspend/resume() handlers to avoid calling ehci_suspend/resume() when we are no longer bound to the HCD e.g. during probe() and remove(); Signed-off-by: Roger Quadros --- drivers/usb/host/ehci-omap.c | 64 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 9bd7dfe..6d1fde97 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -69,6 +69,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; + bool bound; /* HCD structures are valid */ }; static inline void ehci_write(void __iomem *base, u32 reg, u32 val) @@ -159,6 +160,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = regs; + hcd->has_wakeup_irq = true; hcd_to_ehci(hcd)->caps = regs; omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; @@ -216,6 +218,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) goto err_pm_runtime; } + omap->bound = true; + /* * Bring PHYs out of reset for non PHY modes. * Even though HSIC mode is a PHY-less mode, the reset @@ -232,6 +236,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) usb_phy_set_suspend(omap->phy[i], 0); } + pm_runtime_put_sync(dev); + return 0; err_pm_runtime: @@ -264,7 +270,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; + pm_runtime_get_sync(dev); usb_remove_hcd(hcd); + omap->bound = false; for (i = 0; i < omap->nports; i++) { if (omap->phy[i]) @@ -293,15 +301,67 @@ static const struct of_device_id omap_ehci_dt_ids[] = { MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids); +static int omap_ehci_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + + dev_dbg(dev, "%s\n", __func__); + + return ehci_suspend(hcd, true); +} + +static int omap_ehci_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + + dev_dbg(dev, "%s\n", __func__); + + return ehci_resume(hcd, false); +} + +static int omap_ehci_runtime_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; + bool do_wakeup = device_may_wakeup(dev); + + dev_dbg(dev, "%s\n", __func__); + + if (omap->bound) + ehci_suspend(hcd, do_wakeup); + + return 0; +} + +static int omap_ehci_runtime_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; + + dev_dbg(dev, "%s\n", __func__); + + if (omap->bound) + ehci_resume(hcd, false); + + return 0; +} + + +static const struct dev_pm_ops omap_ehci_pm_ops = { + .suspend = omap_ehci_suspend, + .resume = omap_ehci_resume, + .runtime_suspend = omap_ehci_runtime_suspend, + .runtime_resume = omap_ehci_runtime_resume, +}; + static struct platform_driver ehci_hcd_omap_driver = { .probe = ehci_hcd_omap_probe, .remove = ehci_hcd_omap_remove, .shutdown = ehci_hcd_omap_shutdown, - /*.suspend = ehci_hcd_omap_suspend, */ - /*.resume = ehci_hcd_omap_resume, */ .driver = { .name = hcd_name, .of_match_table = omap_ehci_dt_ids, + .pm = &omap_ehci_pm_ops, } };