From patchwork Tue Oct 22 06:23:30 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Chen X-Patchwork-Id: 3080941 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 84524BF924 for ; Tue, 22 Oct 2013 06:41:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6BE7820458 for ; Tue, 22 Oct 2013 06:41:02 +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 5493520457 for ; Tue, 22 Oct 2013 06:41:01 +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 1VYVdg-0003qF-5U; Tue, 22 Oct 2013 06:40:24 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VYVdW-0003WR-JJ; Tue, 22 Oct 2013 06:40:14 +0000 Received: from ch1ehsobe005.messaging.microsoft.com ([216.32.181.185] helo=ch1outboundpool.messaging.microsoft.com) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VYVdG-0003Sr-TL for linux-arm-kernel@lists.infradead.org; Tue, 22 Oct 2013 06:40:00 +0000 Received: from mail58-ch1-R.bigfish.com (10.43.68.251) by CH1EHSOBE012.bigfish.com (10.43.70.62) with Microsoft SMTP Server id 14.1.225.22; Tue, 22 Oct 2013 06:39:32 +0000 Received: from mail58-ch1 (localhost [127.0.0.1]) by mail58-ch1-R.bigfish.com (Postfix) with ESMTP id 282CD460116; Tue, 22 Oct 2013 06:39:32 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 0 X-BigFish: VS0(zzzz1f42h208ch1ee6h1de0h1fdah2073h1202h1e76h1d1ah1d2ah1fc6hzz1de098h1de097h8275bhz2dh2a8h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1b2fh1fb3h1d0ch1d2eh1d3fh1dfeh1dffh1e23h1fe8h1ff5h1155h) Received: from mail58-ch1 (localhost.localdomain [127.0.0.1]) by mail58-ch1 (MessageSwitch) id 1382423970273691_32581; Tue, 22 Oct 2013 06:39:30 +0000 (UTC) Received: from CH1EHSMHS018.bigfish.com (snatpool3.int.messaging.microsoft.com [10.43.68.226]) by mail58-ch1.bigfish.com (Postfix) with ESMTP id 329BD3C0063; Tue, 22 Oct 2013 06:39:30 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by CH1EHSMHS018.bigfish.com (10.43.70.18) with Microsoft SMTP Server (TLS) id 14.16.227.3; Tue, 22 Oct 2013 06:39:30 +0000 Received: from az84smr01.freescale.net (10.64.34.197) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server (TLS) id 14.3.158.2; Tue, 22 Oct 2013 06:39:28 +0000 Received: from shlinux1.ap.freescale.net (shlinux1.ap.freescale.net [10.192.225.216]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id r9M6dIJs020913; Mon, 21 Oct 2013 23:39:24 -0700 From: Peter Chen To: , , Subject: [Patch v2 01/10] usb: chipidea: Add power management support Date: Tue, 22 Oct 2013 14:23:30 +0800 Message-ID: <1382423019-26184-2-git-send-email-peter.chen@freescale.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1382423019-26184-1-git-send-email-peter.chen@freescale.com> References: <1382423019-26184-1-git-send-email-peter.chen@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131022_023959_065088_E1510BF0 X-CRM114-Status: GOOD ( 17.01 ) X-Spam-Score: -2.6 (--) Cc: marex@denx.de, m.grzeschik@pengutronix.de, frank.li@freescale.com, alexander.shishkin@linux.intel.com, linux-usb@vger.kernel.org, peter.chen@freescale.com, kernel@pengutronix.de, linux@arm.linux.org.uk, festevam@gmail.com, linux-arm-kernel@lists.infradead.org, lw@karo-electronics.de 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.6 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 This commit adds runtime and system power management support for chipidea core. The runtime pm support is controlled by glue layer, it can be enabled by flag CI_HDRC_SUPPORTS_RUNTIME_PM. Signed-off-by: Peter Chen --- drivers/usb/chipidea/ci.h | 2 + drivers/usb/chipidea/core.c | 119 ++++++++++++++++++++++++++++++++++++++++++ include/linux/usb/chipidea.h | 1 + 3 files changed, 122 insertions(+), 0 deletions(-) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 1c94fc5..6ea1892 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -173,6 +173,8 @@ struct ci_hdrc { struct dentry *debugfs; bool id_event; bool b_sess_valid_event; + bool supports_runtime_pm; + bool in_lpm; }; static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 87546a0..a5b8f43 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -578,6 +578,10 @@ static int ci_hdrc_probe(struct platform_device *pdev) hw_phymode_configure(ci); dr_mode = ci->platdata->dr_mode; + + ci->supports_runtime_pm = !!(ci->platdata->flags & + CI_HDRC_SUPPORTS_RUNTIME_PM); + /* initialize role(s) before the interrupt is requested */ if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { ret = ci_hdrc_host_init(ci); @@ -651,6 +655,13 @@ static int ci_hdrc_probe(struct platform_device *pdev) if (ret) goto stop; + device_set_wakeup_capable(&pdev->dev, true); + + if (ci->supports_runtime_pm) { + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + } + ret = dbg_create_files(ci); if (!ret) return 0; @@ -668,6 +679,11 @@ static int ci_hdrc_remove(struct platform_device *pdev) { struct ci_hdrc *ci = platform_get_drvdata(pdev); + if (ci->supports_runtime_pm) { + pm_runtime_get_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + } dbg_remove_files(ci); free_irq(ci->irq, ci); ci_role_destroy(ci); @@ -678,11 +694,114 @@ static int ci_hdrc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int ci_controller_suspend(struct device *dev) +{ + struct ci_hdrc *ci = dev_get_drvdata(dev); + + dev_dbg(dev, "at %s\n", __func__); + + if (ci->in_lpm) + return 0; + + disable_irq(ci->irq); + + if (ci->transceiver) + usb_phy_set_wakeup(ci->transceiver, true); + + ci_hdrc_enter_lpm(ci, true); + + if (ci->transceiver) + usb_phy_set_suspend(ci->transceiver, 1); + + ci->in_lpm = true; + + enable_irq(ci->irq); + + return 0; +} + +static int ci_controller_resume(struct device *dev) +{ + struct ci_hdrc *ci = dev_get_drvdata(dev); + + dev_dbg(dev, "at %s\n", __func__); + + if (!ci->in_lpm) + return 0; + + ci_hdrc_enter_lpm(ci, false); + + if (ci->transceiver) { + usb_phy_set_suspend(ci->transceiver, 0); + usb_phy_set_wakeup(ci->transceiver, false); + } + + ci->in_lpm = false; + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int ci_suspend(struct device *dev) +{ + struct ci_hdrc *ci = dev_get_drvdata(dev); + int ret; + + ret = ci_controller_suspend(dev); + if (ret) + return ret; + + if (device_may_wakeup(dev)) + enable_irq_wake(ci->irq); + + return ret; +} + +static int ci_resume(struct device *dev) +{ + struct ci_hdrc *ci = dev_get_drvdata(dev); + int ret; + + if (device_may_wakeup(dev)) + disable_irq_wake(ci->irq); + + ret = ci_controller_resume(dev); + if (!ret && ci->supports_runtime_pm) { + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } + + return ret; +} +#endif /* CONFIG_PM_SLEEP */ + +#ifdef CONFIG_PM_RUNTIME +static int ci_runtime_suspend(struct device *dev) +{ + return ci_controller_suspend(dev); +} + +static int ci_runtime_resume(struct device *dev) +{ + return ci_controller_resume(dev); +} +#endif /* CONFIG_PM_RUNTIME */ + +#endif /* CONFIG_PM */ +static const struct dev_pm_ops ci_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ci_suspend, ci_resume) + SET_RUNTIME_PM_OPS(ci_runtime_suspend, + ci_runtime_resume, NULL) +}; + static struct platform_driver ci_hdrc_driver = { .probe = ci_hdrc_probe, .remove = ci_hdrc_remove, .driver = { .name = "ci_hdrc", + .pm = &ci_pm_ops, }, }; diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index 7d39967..667b46c 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -18,6 +18,7 @@ struct ci_hdrc_platform_data { unsigned long flags; #define CI_HDRC_REGS_SHARED BIT(0) #define CI_HDRC_REQUIRE_TRANSCEIVER BIT(1) +#define CI_HDRC_SUPPORTS_RUNTIME_PM BIT(2) #define CI_HDRC_DISABLE_STREAMING BIT(3) /* * Only set it when DCCPARAMS.DC==1 and DCCPARAMS.HC==1,