From 256a5435975e344b975f89c5434aa6f6eeb03fa1 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 12 Jul 2011 22:48:03 +0200 Subject: OMAP: PM: omap_device: conditionally use PM domain runtime helpers Only build and use the runtime PM helper functions only when runtime PM is actually enabled. Signed-off-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- arch/arm/plat-omap/omap_device.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index d21579b2c11..f7d2ff77008 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -537,6 +537,7 @@ int omap_early_device_register(struct omap_device *od) return 0; } +#ifdef CONFIG_PM_RUNTIME static int _od_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -563,12 +564,12 @@ static int _od_runtime_resume(struct device *dev) return pm_generic_runtime_resume(dev); } +#endif static struct dev_pm_domain omap_device_pm_domain = { .ops = { - .runtime_suspend = _od_runtime_suspend, - .runtime_idle = _od_runtime_idle, - .runtime_resume = _od_runtime_resume, + SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume, + _od_runtime_idle) USE_PLATFORM_PM_SLEEP_OPS } }; -- cgit v1.2.3 From c03f007a8bf0e092caeb6856a5c8a850df10b974 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 12 Jul 2011 22:48:19 +0200 Subject: OMAP: PM: omap_device: add system PM methods for PM domain handling 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 Signed-off-by: Rafael J. Wysocki --- arch/arm/plat-omap/include/plat/omap_device.h | 4 +++ arch/arm/plat-omap/omap_device.c | 36 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index e4c349ff9fd..bc36d05e13e 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 f7d2ff77008..b93cfdc9a36 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -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) } }; -- cgit v1.2.3 From 80c6d1e65c25fbf198b463cfaec015820fb9bcdc Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 12 Jul 2011 22:48:29 +0200 Subject: OMAP: PM: omap_device: add API to disable idle on suspend By default, omap_devices will be automatically idled on suspend (and re-enabled on resume.) Using this new API, device init code can disable this feature if desired. NOTE: any driver/device that has been runtime PM converted should not be using this API. Signed-off-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- arch/arm/plat-omap/include/plat/omap_device.h | 5 +++++ arch/arm/plat-omap/omap_device.c | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index bc36d05e13e..ee405b36df4 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h @@ -46,6 +46,7 @@ extern struct device omap_device_parent; /* omap_device.flags values */ #define OMAP_DEVICE_SUSPENDED BIT(0) +#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1) /** * struct omap_device - omap_device wrapper for platform_devices @@ -121,6 +122,10 @@ int omap_device_enable_hwmods(struct omap_device *od); int omap_device_disable_clocks(struct omap_device *od); int omap_device_enable_clocks(struct omap_device *od); +static inline void omap_device_disable_idle_on_suspend(struct omap_device *od) +{ + od->flags |= OMAP_DEVICE_NO_IDLE_ON_SUSPEND; +} /* * Entries should be kept in latency order ascending diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index b93cfdc9a36..2526fa312b8 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -573,6 +573,9 @@ static int _od_suspend_noirq(struct device *dev) struct omap_device *od = to_omap_device(pdev); int ret; + if (od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND) + return pm_generic_suspend_noirq(dev); + ret = pm_generic_suspend_noirq(dev); if (!ret && !pm_runtime_status_suspended(dev)) { @@ -590,6 +593,9 @@ 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_NO_IDLE_ON_SUSPEND) + return pm_generic_resume_noirq(dev); + if ((od->flags & OMAP_DEVICE_SUSPENDED) && !pm_runtime_status_suspended(dev)) { od->flags &= ~OMAP_DEVICE_SUSPENDED; -- cgit v1.2.3 From c8c9fda5069456eb9e0e403c19764b2e257802e1 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 12 Jul 2011 22:48:42 +0200 Subject: OMAP: PM: disable idle on suspend for GPIO and UART Until these drivers are runtime PM converted, their device power states are managed by calling custom driver hooks late in the idle/suspend path. Therefore, do not let the suspend/resume core code automatically idle these devices since they will be managed manually by the OMAP PM core very late in the idle/suspend path. Signed-off-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-omap2/gpio.c | 2 ++ arch/arm/mach-omap2/serial.c | 1 + 2 files changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 9529842ae05..48e5eced6b5 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -87,6 +87,8 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) return PTR_ERR(od); } + omap_device_disable_idle_on_suspend(od); + gpio_bank_count++; return 0; } diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 1ac361b7b8c..466fc722fa0 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -805,6 +805,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n", name, oh->name); + omap_device_disable_idle_on_suspend(od); oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); uart->irq = oh->mpu_irqs[0].irq; -- cgit v1.2.3