[PATCH] OMAP: PM: omap_device: add system PM methods for PM domain handling

From: Kevin Hilman
Date: Tue Jun 07 2011 - 19:07:28 EST


Using PM domain callbacks, use omap_device idle/enable to
automatically suspend/resume devices. Also use pm_generic_* routines
to ensure driver's callbacks are correctly called.

Driver ->suspend callback is needed to ensure the driver is in a state
that it can be suspended.

If device is already idle (typically because of previous runtime PM
activity), there's nothing extra to do.

KJH: The omap_device_* calls should probably actually be done in the
_noirq() methods.

Not-yet-Signed-off-by: Kevin Hilman <khilman@xxxxxx>
---
arch/arm/plat-omap/include/plat/omap_device.h | 4 +++
arch/arm/plat-omap/omap_device.c | 32 +++++++++++++++++++++++++
2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index e4c349f..bc36d05 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -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) */
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 49fc0df..f2711c3 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -564,12 +564,44 @@ static int _od_runtime_resume(struct device *dev)
return pm_generic_runtime_resume(dev);
}

+static int _od_suspend(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(dev);
+
+ od->flags &= ~OMAP_DEVICE_SUSPENDED;
+
+ if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
+ omap_device_idle(pdev);
+ od->flags |= OMAP_DEVICE_SUSPENDED;
+ }
+
+ return ret;
+}
+
+static int _od_resume(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) &&
+ (od->_state == OMAP_DEVICE_STATE_IDLE))
+ omap_device_enable(pdev);
+
+ return pm_generic_resume(dev);
+}
+
static struct dev_power_domain omap_device_power_domain = {
.ops = {
.runtime_suspend = _od_runtime_suspend,
.runtime_idle = _od_runtime_idle,
.runtime_resume = _od_runtime_resume,
USE_PLATFORM_PM_SLEEP_OPS
+ .suspend = _od_suspend,
+ .resume = _od_resume,
}
};

--
1.7.6

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/