]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
OMAP: PM: omap_device: add system PM methods for PM domain handling
authorKevin Hilman <khilman@ti.com>
Tue, 12 Jul 2011 20:48:19 +0000 (22:48 +0200)
committerRafael J. Wysocki <rjw@sisk.pl>
Tue, 12 Jul 2011 20:48:19 +0000 (22:48 +0200)
In the omap_device PM domain callbacks, use omap_device idle/enable to
automatically manage device idle states during system suspend/resume.

If an omap_device has not already been runtime suspended, the
->suspend_noirq() method of the PM domain will use omap_device_idle()
to idle the HW after calling the driver's ->runtime_suspend()
callback.  Similarily, upon resume, if the device was suspended during
->suspend_noirq(), the ->resume_noirq() method of the PM domain will
use omap_device_enable() to enable the HW and then call the driver's
->runtime_resume() callback.

If a device has already been runtime suspended, the noirq methods of
the PM domain leave the device runtime suspended by default.

However, if a driver needs to runtime resume a device during suspend
(for example, to change its wakeup settings), it may do so using
pm_runtime_get* in it's ->suspend() callback.

Signed-off-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
arch/arm/plat-omap/include/plat/omap_device.h
arch/arm/plat-omap/omap_device.c

index e4c349ff9fd8ef1a77e071db608a2c75610ecc38..bc36d05e13e4f12c5e7201abb35edce11d3e964d 100644 (file)
@@ -44,6 +44,9 @@ extern struct device omap_device_parent;
 #define OMAP_DEVICE_STATE_IDLE         2
 #define OMAP_DEVICE_STATE_SHUTDOWN     3
 
+/* omap_device.flags values */
+#define OMAP_DEVICE_SUSPENDED BIT(0)
+
 /**
  * struct omap_device - omap_device wrapper for platform_devices
  * @pdev: platform_device
@@ -73,6 +76,7 @@ struct omap_device {
        s8                              pm_lat_level;
        u8                              hwmods_cnt;
        u8                              _state;
+       u8                              flags;
 };
 
 /* Device driver interface (call via platform_data fn ptrs) */
index f7d2ff77008aed77f3753359fafd2ccf7a57eb9f..b93cfdc9a36658a2040fe4b5bb5edd4fdbd78c8e 100644 (file)
@@ -566,11 +566,47 @@ static int _od_runtime_resume(struct device *dev)
 }
 #endif
 
+#ifdef CONFIG_SUSPEND
+static int _od_suspend_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_device *od = to_omap_device(pdev);
+       int ret;
+
+       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;
+               }
+       }
+
+       return ret;
+}
+
+static int _od_resume_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_device *od = to_omap_device(pdev);
+
+       if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
+           !pm_runtime_status_suspended(dev)) {
+               od->flags &= ~OMAP_DEVICE_SUSPENDED;
+               omap_device_enable(pdev);
+               pm_generic_runtime_resume(dev);
+       }
+
+       return pm_generic_resume_noirq(dev);
+}
+#endif
+
 static struct dev_pm_domain omap_device_pm_domain = {
        .ops = {
                SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
                                   _od_runtime_idle)
                USE_PLATFORM_PM_SLEEP_OPS
+               SET_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq, _od_resume_noirq)
        }
 };