Commit 11d7aba9 authored by Guenter Roeck's avatar Guenter Roeck Committed by Wim Van Sebroeck

watchdog: imx2: Convert to use infrastructure triggered keepalives

The watchdog infrastructure now supports handling watchdog keepalive
if the watchdog is running while the watchdog device is closed.
Convert the driver to use this infrastructure.
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarWim Van Sebroeck <wim@iguana.be>
parent f29a72c2
...@@ -25,14 +25,12 @@ ...@@ -25,14 +25,12 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/timer.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#define DRIVER_NAME "imx2-wdt" #define DRIVER_NAME "imx2-wdt"
...@@ -60,7 +58,6 @@ ...@@ -60,7 +58,6 @@
struct imx2_wdt_device { struct imx2_wdt_device {
struct clk *clk; struct clk *clk;
struct regmap *regmap; struct regmap *regmap;
struct timer_list timer; /* Pings the watchdog when closed */
struct watchdog_device wdog; struct watchdog_device wdog;
}; };
...@@ -147,16 +144,6 @@ static int imx2_wdt_ping(struct watchdog_device *wdog) ...@@ -147,16 +144,6 @@ static int imx2_wdt_ping(struct watchdog_device *wdog)
return 0; return 0;
} }
static void imx2_wdt_timer_ping(unsigned long arg)
{
struct watchdog_device *wdog = (struct watchdog_device *)arg;
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
/* ping it every wdog->timeout / 2 seconds to prevent reboot */
imx2_wdt_ping(wdog);
mod_timer(&wdev->timer, jiffies + wdog->timeout * HZ / 2);
}
static int imx2_wdt_set_timeout(struct watchdog_device *wdog, static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
unsigned int new_timeout) unsigned int new_timeout)
{ {
...@@ -173,40 +160,19 @@ static int imx2_wdt_start(struct watchdog_device *wdog) ...@@ -173,40 +160,19 @@ static int imx2_wdt_start(struct watchdog_device *wdog)
{ {
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
if (imx2_wdt_is_running(wdev)) { if (imx2_wdt_is_running(wdev))
/* delete the timer that pings the watchdog after close */
del_timer_sync(&wdev->timer);
imx2_wdt_set_timeout(wdog, wdog->timeout); imx2_wdt_set_timeout(wdog, wdog->timeout);
} else else
imx2_wdt_setup(wdog); imx2_wdt_setup(wdog);
return imx2_wdt_ping(wdog); set_bit(WDOG_HW_RUNNING, &wdog->status);
}
static int imx2_wdt_stop(struct watchdog_device *wdog)
{
/*
* We don't need a clk_disable, it cannot be disabled once started.
* We use a timer to ping the watchdog while /dev/watchdog is closed
*/
imx2_wdt_timer_ping((unsigned long)wdog);
return 0;
}
static inline void imx2_wdt_ping_if_active(struct watchdog_device *wdog)
{
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
if (imx2_wdt_is_running(wdev)) { return imx2_wdt_ping(wdog);
imx2_wdt_set_timeout(wdog, wdog->timeout);
imx2_wdt_timer_ping((unsigned long)wdog);
}
} }
static const struct watchdog_ops imx2_wdt_ops = { static const struct watchdog_ops imx2_wdt_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.start = imx2_wdt_start, .start = imx2_wdt_start,
.stop = imx2_wdt_stop,
.ping = imx2_wdt_ping, .ping = imx2_wdt_ping,
.set_timeout = imx2_wdt_set_timeout, .set_timeout = imx2_wdt_set_timeout,
.restart = imx2_wdt_restart, .restart = imx2_wdt_restart,
...@@ -254,7 +220,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) ...@@ -254,7 +220,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
wdog->info = &imx2_wdt_info; wdog->info = &imx2_wdt_info;
wdog->ops = &imx2_wdt_ops; wdog->ops = &imx2_wdt_ops;
wdog->min_timeout = 1; wdog->min_timeout = 1;
wdog->max_timeout = IMX2_WDT_MAX_TIME; wdog->max_hw_heartbeat_ms = IMX2_WDT_MAX_TIME * 1000;
wdog->parent = &pdev->dev; wdog->parent = &pdev->dev;
ret = clk_prepare_enable(wdev->clk); ret = clk_prepare_enable(wdev->clk);
...@@ -275,9 +241,10 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) ...@@ -275,9 +241,10 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
watchdog_set_restart_priority(wdog, 128); watchdog_set_restart_priority(wdog, 128);
watchdog_init_timeout(wdog, timeout, &pdev->dev); watchdog_init_timeout(wdog, timeout, &pdev->dev);
setup_timer(&wdev->timer, imx2_wdt_timer_ping, (unsigned long)wdog); if (imx2_wdt_is_running(wdev)) {
imx2_wdt_set_timeout(wdog, wdog->timeout);
imx2_wdt_ping_if_active(wdog); set_bit(WDOG_HW_RUNNING, &wdog->status);
}
/* /*
* Disable the watchdog power down counter at boot. Otherwise the power * Disable the watchdog power down counter at boot. Otherwise the power
...@@ -310,7 +277,6 @@ static int __exit imx2_wdt_remove(struct platform_device *pdev) ...@@ -310,7 +277,6 @@ static int __exit imx2_wdt_remove(struct platform_device *pdev)
watchdog_unregister_device(wdog); watchdog_unregister_device(wdog);
if (imx2_wdt_is_running(wdev)) { if (imx2_wdt_is_running(wdev)) {
del_timer_sync(&wdev->timer);
imx2_wdt_ping(wdog); imx2_wdt_ping(wdog);
dev_crit(&pdev->dev, "Device removed: Expect reboot!\n"); dev_crit(&pdev->dev, "Device removed: Expect reboot!\n");
} }
...@@ -324,10 +290,9 @@ static void imx2_wdt_shutdown(struct platform_device *pdev) ...@@ -324,10 +290,9 @@ static void imx2_wdt_shutdown(struct platform_device *pdev)
if (imx2_wdt_is_running(wdev)) { if (imx2_wdt_is_running(wdev)) {
/* /*
* We are running, we need to delete the timer but will * We are running, configure max timeout before reboot
* give max timeout before reboot will take place * will take place.
*/ */
del_timer_sync(&wdev->timer);
imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
imx2_wdt_ping(wdog); imx2_wdt_ping(wdog);
dev_crit(&pdev->dev, "Device shutdown: Expect reboot!\n"); dev_crit(&pdev->dev, "Device shutdown: Expect reboot!\n");
...@@ -345,10 +310,6 @@ static int imx2_wdt_suspend(struct device *dev) ...@@ -345,10 +310,6 @@ static int imx2_wdt_suspend(struct device *dev)
if (imx2_wdt_is_running(wdev)) { if (imx2_wdt_is_running(wdev)) {
imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
imx2_wdt_ping(wdog); imx2_wdt_ping(wdog);
/* The watchdog is not active */
if (!watchdog_active(wdog))
del_timer_sync(&wdev->timer);
} }
clk_disable_unprepare(wdev->clk); clk_disable_unprepare(wdev->clk);
...@@ -374,19 +335,10 @@ static int imx2_wdt_resume(struct device *dev) ...@@ -374,19 +335,10 @@ static int imx2_wdt_resume(struct device *dev)
* watchdog again. * watchdog again.
*/ */
imx2_wdt_setup(wdog); imx2_wdt_setup(wdog);
}
if (imx2_wdt_is_running(wdev)) {
imx2_wdt_set_timeout(wdog, wdog->timeout); imx2_wdt_set_timeout(wdog, wdog->timeout);
imx2_wdt_ping(wdog); imx2_wdt_ping(wdog);
} else if (imx2_wdt_is_running(wdev)) {
/* Resuming from non-deep sleep state. */
imx2_wdt_set_timeout(wdog, wdog->timeout);
imx2_wdt_ping(wdog);
/*
* But the watchdog is not active, then start
* the timer again.
*/
if (!watchdog_active(wdog))
mod_timer(&wdev->timer,
jiffies + wdog->timeout * HZ / 2);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment