From: peter.chen@freescale.com (Peter Chen)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 01/11] usb: chipidea: Add power management support
Date: Sat, 12 Oct 2013 17:35:03 +0800 [thread overview]
Message-ID: <1381570513-24927-2-git-send-email-peter.chen@freescale.com> (raw)
In-Reply-To: <1381570513-24927-1-git-send-email-peter.chen@freescale.com>
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 <peter.chen@freescale.com>
---
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..6c16d11 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;
+ atomic_t 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..7ffb8cb 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 (atomic_read(&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);
+
+ atomic_set(&ci->in_lpm, 1);
+
+ 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 (!atomic_read(&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);
+ }
+
+ atomic_set(&ci->in_lpm, 0);
+
+ 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,
--
1.7.1
next prev parent reply other threads:[~2013-10-12 9:35 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-12 9:35 [PATCH 00/11] Add power management support for chipidea Peter Chen
2013-10-12 9:35 ` Peter Chen [this message]
2013-10-14 8:04 ` [PATCH 01/11] usb: chipidea: Add power management support Lothar Waßmann
2013-10-14 7:55 ` Peter Chen
2013-10-14 8:42 ` Sascha Hauer
2013-10-14 9:04 ` Peter Chen
2013-10-14 10:23 ` Sascha Hauer
2013-10-14 10:46 ` Russell King - ARM Linux
2013-10-14 10:44 ` Russell King - ARM Linux
2013-10-14 11:01 ` Russell King - ARM Linux
2013-10-15 2:18 ` Peter Chen
2013-10-15 11:15 ` Russell King - ARM Linux
2013-10-12 9:35 ` [PATCH 02/11] usb: chipidea: imx: add " Peter Chen
2013-10-12 9:35 ` [PATCH 03/11] usb: chipidea: usbmisc_imx: remove the controller's clock information Peter Chen
2013-10-12 9:35 ` [PATCH 04/11] usb: chipidea: add wakeup interrupt handler Peter Chen
2013-10-12 9:35 ` [PATCH 05/11] usb: chipidea: usbmisc_imx: add set_wakup API Peter Chen
2013-10-12 9:35 ` [PATCH 06/11] usb: chipidea: imx: call set_wakeup when necessary Peter Chen
2013-10-12 9:35 ` [PATCH 07/11] usb: chipidea: host: add quirk for ehci operation Peter Chen
2013-10-12 9:35 ` [PATCH 08/11] usb: chipidea: host: add ehci quirk for imx controller Peter Chen
2013-10-12 9:35 ` [PATCH 09/11] usb: chipidea: imx: Enable CI_HDRC_IMX_EHCI_QUIRK if the phy has notify APIs Peter Chen
2013-10-12 9:35 ` [PATCH 10/11] usb: chipidea: imx: add binding for supporting runtime pm Peter Chen
2013-10-12 14:40 ` Alan Stern
2013-10-14 1:22 ` Peter Chen
2013-10-14 1:39 ` Marek Vasut
2013-10-14 1:33 ` Peter Chen
2013-10-12 9:35 ` [PATCH 11/11] ARM: dts: imx6qdl-sabresd: Enable runtime pm for usbotg and usb host 1 Peter Chen
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=1381570513-24927-2-git-send-email-peter.chen@freescale.com \
--to=peter.chen@freescale.com \
--cc=linux-arm-kernel@lists.infradead.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.