devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Grygorii Strashko <grygorii.strashko@ti.com>
To: Tony Lindgren <tony@atomide.com>, Kevin Hilman <khilman@linaro.org>
Cc: linux-arm-kernel@lists.infradead.org, linux-omap@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	devicetree-discuss@lists.ozlabs.org,
	Grygorii Strashko <grygorii.strashko@ti.com>,
	Linus Walleij <linus.walleij@linaro.org>,
	Stephen Warren <swarren@wwwdotorg.org>
Subject: [PATCH 2/3] ARM: OMAP2+: omap_device: add pinctrl handling
Date: Wed, 17 Jul 2013 14:41:51 +0300	[thread overview]
Message-ID: <1374061312-25469-3-git-send-email-grygorii.strashko@ti.com> (raw)
In-Reply-To: <1374061312-25469-1-git-send-email-grygorii.strashko@ti.com>

Before switching to DT pinctrl states of OMAP IPs have been handled by hwmod
framework. After switching to DT-boot the pinctrl handling was dropped from
hwmod framework and, as it was recommended, OMAP IP's drivers have to be updated
to handle pinctrl states by itself using pinctrl_pm_select_xx() helpers
(see http://lists.infradead.org/pipermail/linux-arm-kernel/2013-June/173514.html)

But this is not right for OMAP2+ SoC where real IPs state is controlled
by omap_device core which enables/disables modules & clocks actually.

For example, if OMAP I2C driver will handle pinctrl state during system wide
suspend the following issue may occure:
- suspend_noirq - I2C device can be still active because of PM auto-suspend
  |-_od_suspend_noirq
     |- omap_i2c_suspend_noirq
        |- PINs state set to SLEEP
  |- pm_generic_runtime_suspend
     |- omap_i2c_runtime_suspend()
        |- PINs state set to IDLE  <--- *oops* PINs state is IDLE and not SLEEP
  |- omap_device_idle()
     |- omap_hwmod_idle()
        |- _idle()
           |- disbale module (sysc&clocks)

- resume_noirq - I2C was active before suspend
  |-_od_resume_noirq
     |- omap_hwmod_enable()
        |- _enable()
           |- enable module (sysc&clocks)
     |- pm_generic_runtime_resume
        |- omap_i2c_runtime_resume()
           |- PINs state set to DEFAULT  <--- !!!!
     |- omap_i2c_resume_noirq
        |- PINs state set to DEFAULT
        |- PINs state set to IDLE  <--- *big oops* we have active module and its
                                         PINs state is IDLE
(see https://patchwork.kernel.org/patch/2642101/)

Of course, everything can be handled by adding a tons of code in ecah driver to
check PM state of device and override default behavior of omap_device core, but
this not good.

Hence, add pinctrl handling in omap_device core as shown below:
                                         +
                                         |
                                         |  .probe()
                                         |
                                   +-----v--------+
                                   |              |
                                   |  default     |
                                   |              |
                                   +----+--+------+
                                        |  |
                        pm_runtime_get()|  | pm_runtime_put()
                       +----------------+  +------------+
                       |                                |
                +------v------+ pm_runtime_put()+-------v-----+
                |             +----------------->             |
    +----------->  Active     |pm_runtime_get() |   Idle      <----------+
    |           |             <-----------------+             |          |
    |           +-------+-----+                 +-------+-----+          |
    |                   |.suspend_noirq()               |.suspend_noirq()|
    |                   |                               |                |
    |                   |                               |                |
    |                   |                               |                |
    |                   |                               |                |
    |           +-------v-----+                 +-------v-----+          |
    |           |             |                 |             |          |
    +-----------+  Sleep      ------+           |  Sleep      +----------+
.resume_noirq() |             |     |           |             |.resume_noirq()
                +-------|-----+     |           +-------------+
                        |  Idle     |
                        +-----------+
1) on PM runtime resume
- switch pinctrl state to "active"
2) on PM runtime suspend
- switch pinctrl state to "idle"
3) during system wide suspend
- switch pinctrl state to "sleep" or "idle" if omap_device core disables device
- switch pinctrl state to "sleep" if device has been disabled already
4) during system wide resume
- switch pinctrl state to "active" if omap_device core has
  disabled device during suspend
- switch pinctrl state to "idle" if device was already disabled before suspend

This will enable pinctrl for all OMAP2+ IP's drivers by default -
no changes in code is needed and only DT data will need to be updated
(add "default", "active", "idle", "sleep" states).

Related discussions:
- [3/3] i2c: nomadik: use pinctrl PM helpers
 https://patchwork.kernel.org/patch/2670291/
- mmc: omap_hsmmc: Remux pins to support SDIO interrupt and PM runtime
 https://patchwork.kernel.org/patch/2690191/
- [PATCH 00/11] drivers: Add Pinctrl PM support
 https://lkml.org/lkml/2013/5/31/210

CC: Linus Walleij <linus.walleij@linaro.org>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 arch/arm/mach-omap2/omap_device.c |   40 +++++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 5cc9287..4ebdbd7 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -39,6 +39,7 @@
 #include "soc.h"
 #include "omap_device.h"
 #include "omap_hwmod.h"
+#include "iomap.h"
 
 /* Private functions */
 
@@ -582,8 +583,10 @@ static int _od_runtime_suspend(struct device *dev)
 
 	ret = pm_generic_runtime_suspend(dev);
 
-	if (!ret)
+	if (!ret) {
 		omap_device_idle(pdev);
+		pinctrl_pm_select_idle_state(dev);
+	}
 
 	return ret;
 }
@@ -592,12 +595,25 @@ static int _od_runtime_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 
+	pinctrl_pm_select_active_state(dev);
+
 	omap_device_enable(pdev);
 
 	return pm_generic_runtime_resume(dev);
 }
 #endif
 
+void _od_suspend_sel_pinctrl_state(struct device *dev)
+{
+	if (!dev->pins)
+		return;
+	/* try to select *deepest* pinctrl state */
+	if (IS_ERR(dev->pins->sleep_state))
+		pinctrl_pm_select_idle_state(dev);
+	else
+		pinctrl_pm_select_sleep_state(dev);
+}
+
 #ifdef CONFIG_SUSPEND
 static int _od_suspend_noirq(struct device *dev)
 {
@@ -610,11 +626,19 @@ static int _od_suspend_noirq(struct device *dev)
 		return 0;
 
 	ret = pm_generic_suspend_noirq(dev);
-
-	if (!ret && !pm_runtime_status_suspended(dev)) {
-		if (pm_generic_runtime_suspend(dev) == 0) {
-			omap_device_idle(pdev);
-			od->flags |= OMAP_DEVICE_SUSPENDED;
+	if (!ret) {
+		if (!pm_runtime_status_suspended(dev)) {
+			if (pm_generic_runtime_suspend(dev) == 0) {
+				omap_device_idle(pdev);
+				od->flags |= OMAP_DEVICE_SUSPENDED;
+				_od_suspend_sel_pinctrl_state(dev);
+			}
+		} else {
+			/*
+			 * "idle" pinctrl state already applied -
+			 * try to set "sleep" state
+			 */
+			pinctrl_pm_select_sleep_state(dev);
 		}
 	}
 
@@ -630,7 +654,11 @@ static int _od_resume_noirq(struct device *dev)
 	    !pm_runtime_status_suspended(dev)) {
 		od->flags &= ~OMAP_DEVICE_SUSPENDED;
 		omap_device_enable(pdev);
+		pinctrl_pm_select_active_state(dev);
 		pm_generic_runtime_resume(dev);
+	} else if (pm_runtime_status_suspended(dev)) {
+		/* switch back to "idle" pinctrl state */
+		pinctrl_pm_select_idle_state(dev);
 	}
 
 	return pm_generic_resume_noirq(dev);
-- 
1.7.9.5


  parent reply	other threads:[~2013-07-17 11:41 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-17 11:41 [PATCH 0/3] ARM: OMAP2+: omap_device: add dynamic pinctrl handling Grygorii Strashko
2013-07-17 11:41 ` [PATCH 1/3] pinctrl: rollback check for !dev->pins in pinctrl_pm_select*() APIs Grygorii Strashko
2013-07-17 15:40   ` Tony Lindgren
2013-07-26 23:22     ` Linus Walleij
2013-07-17 11:41 ` Grygorii Strashko [this message]
2013-07-17 15:38   ` [PATCH 2/3] ARM: OMAP2+: omap_device: add pinctrl handling Tony Lindgren
2013-07-17 16:56     ` Grygorii Strashko
2013-07-18  8:14       ` Tony Lindgren
2013-07-18 11:22         ` Grygorii Strashko
2013-07-17 11:41 ` [PATCH 3/3] ARM: dts: omap4-sdp: add dynamic pin states for uart3/4 Grygorii Strashko
     [not found]   ` <1374061312-25469-4-git-send-email-grygorii.strashko-l0cyMroinI0@public.gmane.org>
2013-07-17 15:32     ` Tony Lindgren
2013-07-17 16:41       ` Grygorii Strashko
     [not found]         ` <51E6C939.40208-l0cyMroinI0@public.gmane.org>
2013-07-18  8:09           ` Tony Lindgren
2013-07-18  8:54             ` Grygorii Strashko
2013-07-18  9:04               ` Tony Lindgren
2013-07-18 12:01                 ` Grygorii Strashko
2013-07-17 11:57 ` [PATCH 0/3] ARM: OMAP2+: omap_device: add dynamic pinctrl handling Roger Quadros
2013-07-17 12:30   ` Grygorii Strashko
2013-07-18  6:44     ` Roger Quadros

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=1374061312-25469-3-git-send-email-grygorii.strashko@ti.com \
    --to=grygorii.strashko@ti.com \
    --cc=devicetree-discuss@lists.ozlabs.org \
    --cc=khilman@linaro.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=swarren@wwwdotorg.org \
    --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).