aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorXiubo Li <Li.Xiubo@freescale.com>2014-10-15 23:44:15 -0400
committerWim Van Sebroeck <wim@iguana.be>2015-01-21 08:45:16 -0500
commitbbd5900935be8755b6344386373174b20cd474a2 (patch)
tree5a1d70c25a6c46e08dd578a9222971ea93e9adb2 /drivers/watchdog
parentec6f34e5b552fb0a52e6aae1a5afbbb1605cc6cc (diff)
watchdog: imx2_wdt: Improve power management support.
Improve power management operations(suspend and resume) as part of dev_pm_ops for IMX2 watchdog driver. If PM will be supported, please make sure that the wdev->clk could disable the watchdog's counter input clock source or can mask watchdog's reset request to the core. If watchdog is still used by consumers and resumes from deep sleep state, we need to restart the watchdog again without enabling the timer. If watchdog been has started --> stopped by the consumers and resumes from non-deep sleep state, then start the timer again. If watchdog has been started --> stopped by the consumers and resumes from deep sleep state, will do nothing. The watchdog will be restarted by consumers next time to be used. Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/imx2_wdt.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index d6add516a7a7..c50c7d85689f 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -327,18 +327,21 @@ static void imx2_wdt_shutdown(struct platform_device *pdev)
327} 327}
328 328
329#ifdef CONFIG_PM_SLEEP 329#ifdef CONFIG_PM_SLEEP
330/* Disable watchdog if it is active during suspend */ 330/* Disable watchdog if it is active or non-active but still running */
331static int imx2_wdt_suspend(struct device *dev) 331static int imx2_wdt_suspend(struct device *dev)
332{ 332{
333 struct watchdog_device *wdog = dev_get_drvdata(dev); 333 struct watchdog_device *wdog = dev_get_drvdata(dev);
334 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); 334 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
335 335
336 imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); 336 /* The watchdog IP block is running */
337 imx2_wdt_ping(wdog); 337 if (imx2_wdt_is_running(wdev)) {
338 imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
339 imx2_wdt_ping(wdog);
338 340
339 /* Watchdog has been stopped but IP block is still running */ 341 /* The watchdog is not active */
340 if (!watchdog_active(wdog) && imx2_wdt_is_running(wdev)) 342 if (!watchdog_active(wdog))
341 del_timer_sync(&wdev->timer); 343 del_timer_sync(&wdev->timer);
344 }
342 345
343 clk_disable_unprepare(wdev->clk); 346 clk_disable_unprepare(wdev->clk);
344 347
@@ -354,15 +357,25 @@ static int imx2_wdt_resume(struct device *dev)
354 clk_prepare_enable(wdev->clk); 357 clk_prepare_enable(wdev->clk);
355 358
356 if (watchdog_active(wdog) && !imx2_wdt_is_running(wdev)) { 359 if (watchdog_active(wdog) && !imx2_wdt_is_running(wdev)) {
357 /* Resumes from deep sleep we need restart 360 /*
358 * the watchdog again. 361 * If the watchdog is still active and resumes
362 * from deep sleep state, need to restart the
363 * watchdog again.
359 */ 364 */
360 imx2_wdt_setup(wdog); 365 imx2_wdt_setup(wdog);
361 imx2_wdt_set_timeout(wdog, wdog->timeout); 366 imx2_wdt_set_timeout(wdog, wdog->timeout);
362 imx2_wdt_ping(wdog); 367 imx2_wdt_ping(wdog);
363 } else if (imx2_wdt_is_running(wdev)) { 368 } else if (imx2_wdt_is_running(wdev)) {
369 /* Resuming from non-deep sleep state. */
370 imx2_wdt_set_timeout(wdog, wdog->timeout);
364 imx2_wdt_ping(wdog); 371 imx2_wdt_ping(wdog);
365 mod_timer(&wdev->timer, jiffies + wdog->timeout * HZ / 2); 372 /*
373 * But the watchdog is not active, then start
374 * the timer again.
375 */
376 if (!watchdog_active(wdog))
377 mod_timer(&wdev->timer,
378 jiffies + wdog->timeout * HZ / 2);
366 } 379 }
367 380
368 return 0; 381 return 0;