aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2016-02-28 16:12:20 -0500
committerWim Van Sebroeck <wim@iguana.be>2016-03-16 16:11:23 -0400
commit11d7aba9ceb726d86aaaca3eb5f7d79de38989c5 (patch)
treef9863a5a49f480780f573e6d8afb206439a9f8c2
parentf29a72c24ad4927027e77e4eed431a61bc8335b2 (diff)
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: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
-rw-r--r--drivers/watchdog/imx2_wdt.c74
1 files changed, 13 insertions, 61 deletions
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 4cb59a23aab0..331aed831dac 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -25,14 +25,12 @@
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/jiffies.h>
29#include <linux/kernel.h> 28#include <linux/kernel.h>
30#include <linux/module.h> 29#include <linux/module.h>
31#include <linux/moduleparam.h> 30#include <linux/moduleparam.h>
32#include <linux/of_address.h> 31#include <linux/of_address.h>
33#include <linux/platform_device.h> 32#include <linux/platform_device.h>
34#include <linux/regmap.h> 33#include <linux/regmap.h>
35#include <linux/timer.h>
36#include <linux/watchdog.h> 34#include <linux/watchdog.h>
37 35
38#define DRIVER_NAME "imx2-wdt" 36#define DRIVER_NAME "imx2-wdt"
@@ -60,7 +58,6 @@
60struct imx2_wdt_device { 58struct imx2_wdt_device {
61 struct clk *clk; 59 struct clk *clk;
62 struct regmap *regmap; 60 struct regmap *regmap;
63 struct timer_list timer; /* Pings the watchdog when closed */
64 struct watchdog_device wdog; 61 struct watchdog_device wdog;
65}; 62};
66 63
@@ -147,16 +144,6 @@ static int imx2_wdt_ping(struct watchdog_device *wdog)
147 return 0; 144 return 0;
148} 145}
149 146
150static void imx2_wdt_timer_ping(unsigned long arg)
151{
152 struct watchdog_device *wdog = (struct watchdog_device *)arg;
153 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
154
155 /* ping it every wdog->timeout / 2 seconds to prevent reboot */
156 imx2_wdt_ping(wdog);
157 mod_timer(&wdev->timer, jiffies + wdog->timeout * HZ / 2);
158}
159
160static int imx2_wdt_set_timeout(struct watchdog_device *wdog, 147static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
161 unsigned int new_timeout) 148 unsigned int new_timeout)
162{ 149{
@@ -173,40 +160,19 @@ static int imx2_wdt_start(struct watchdog_device *wdog)
173{ 160{
174 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); 161 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
175 162
176 if (imx2_wdt_is_running(wdev)) { 163 if (imx2_wdt_is_running(wdev))
177 /* delete the timer that pings the watchdog after close */
178 del_timer_sync(&wdev->timer);
179 imx2_wdt_set_timeout(wdog, wdog->timeout); 164 imx2_wdt_set_timeout(wdog, wdog->timeout);
180 } else 165 else
181 imx2_wdt_setup(wdog); 166 imx2_wdt_setup(wdog);
182 167
183 return imx2_wdt_ping(wdog); 168 set_bit(WDOG_HW_RUNNING, &wdog->status);
184}
185
186static int imx2_wdt_stop(struct watchdog_device *wdog)
187{
188 /*
189 * We don't need a clk_disable, it cannot be disabled once started.
190 * We use a timer to ping the watchdog while /dev/watchdog is closed
191 */
192 imx2_wdt_timer_ping((unsigned long)wdog);
193 return 0;
194}
195
196static inline void imx2_wdt_ping_if_active(struct watchdog_device *wdog)
197{
198 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
199 169
200 if (imx2_wdt_is_running(wdev)) { 170 return imx2_wdt_ping(wdog);
201 imx2_wdt_set_timeout(wdog, wdog->timeout);
202 imx2_wdt_timer_ping((unsigned long)wdog);
203 }
204} 171}
205 172
206static const struct watchdog_ops imx2_wdt_ops = { 173static const struct watchdog_ops imx2_wdt_ops = {
207 .owner = THIS_MODULE, 174 .owner = THIS_MODULE,
208 .start = imx2_wdt_start, 175 .start = imx2_wdt_start,
209 .stop = imx2_wdt_stop,
210 .ping = imx2_wdt_ping, 176 .ping = imx2_wdt_ping,
211 .set_timeout = imx2_wdt_set_timeout, 177 .set_timeout = imx2_wdt_set_timeout,
212 .restart = imx2_wdt_restart, 178 .restart = imx2_wdt_restart,
@@ -254,7 +220,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
254 wdog->info = &imx2_wdt_info; 220 wdog->info = &imx2_wdt_info;
255 wdog->ops = &imx2_wdt_ops; 221 wdog->ops = &imx2_wdt_ops;
256 wdog->min_timeout = 1; 222 wdog->min_timeout = 1;
257 wdog->max_timeout = IMX2_WDT_MAX_TIME; 223 wdog->max_hw_heartbeat_ms = IMX2_WDT_MAX_TIME * 1000;
258 wdog->parent = &pdev->dev; 224 wdog->parent = &pdev->dev;
259 225
260 ret = clk_prepare_enable(wdev->clk); 226 ret = clk_prepare_enable(wdev->clk);
@@ -275,9 +241,10 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
275 watchdog_set_restart_priority(wdog, 128); 241 watchdog_set_restart_priority(wdog, 128);
276 watchdog_init_timeout(wdog, timeout, &pdev->dev); 242 watchdog_init_timeout(wdog, timeout, &pdev->dev);
277 243
278 setup_timer(&wdev->timer, imx2_wdt_timer_ping, (unsigned long)wdog); 244 if (imx2_wdt_is_running(wdev)) {
279 245 imx2_wdt_set_timeout(wdog, wdog->timeout);
280 imx2_wdt_ping_if_active(wdog); 246 set_bit(WDOG_HW_RUNNING, &wdog->status);
247 }
281 248
282 /* 249 /*
283 * Disable the watchdog power down counter at boot. Otherwise the power 250 * 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 watchdog_unregister_device(wdog); 277 watchdog_unregister_device(wdog);
311 278
312 if (imx2_wdt_is_running(wdev)) { 279 if (imx2_wdt_is_running(wdev)) {
313 del_timer_sync(&wdev->timer);
314 imx2_wdt_ping(wdog); 280 imx2_wdt_ping(wdog);
315 dev_crit(&pdev->dev, "Device removed: Expect reboot!\n"); 281 dev_crit(&pdev->dev, "Device removed: Expect reboot!\n");
316 } 282 }
@@ -324,10 +290,9 @@ static void imx2_wdt_shutdown(struct platform_device *pdev)
324 290
325 if (imx2_wdt_is_running(wdev)) { 291 if (imx2_wdt_is_running(wdev)) {
326 /* 292 /*
327 * We are running, we need to delete the timer but will 293 * We are running, configure max timeout before reboot
328 * give max timeout before reboot will take place 294 * will take place.
329 */ 295 */
330 del_timer_sync(&wdev->timer);
331 imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); 296 imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
332 imx2_wdt_ping(wdog); 297 imx2_wdt_ping(wdog);
333 dev_crit(&pdev->dev, "Device shutdown: Expect reboot!\n"); 298 dev_crit(&pdev->dev, "Device shutdown: Expect reboot!\n");
@@ -345,10 +310,6 @@ static int imx2_wdt_suspend(struct device *dev)
345 if (imx2_wdt_is_running(wdev)) { 310 if (imx2_wdt_is_running(wdev)) {
346 imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME); 311 imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
347 imx2_wdt_ping(wdog); 312 imx2_wdt_ping(wdog);
348
349 /* The watchdog is not active */
350 if (!watchdog_active(wdog))
351 del_timer_sync(&wdev->timer);
352 } 313 }
353 314
354 clk_disable_unprepare(wdev->clk); 315 clk_disable_unprepare(wdev->clk);
@@ -374,19 +335,10 @@ static int imx2_wdt_resume(struct device *dev)
374 * watchdog again. 335 * watchdog again.
375 */ 336 */
376 imx2_wdt_setup(wdog); 337 imx2_wdt_setup(wdog);
338 }
339 if (imx2_wdt_is_running(wdev)) {
377 imx2_wdt_set_timeout(wdog, wdog->timeout); 340 imx2_wdt_set_timeout(wdog, wdog->timeout);
378 imx2_wdt_ping(wdog); 341 imx2_wdt_ping(wdog);
379 } else if (imx2_wdt_is_running(wdev)) {
380 /* Resuming from non-deep sleep state. */
381 imx2_wdt_set_timeout(wdog, wdog->timeout);
382 imx2_wdt_ping(wdog);
383 /*
384 * But the watchdog is not active, then start
385 * the timer again.
386 */
387 if (!watchdog_active(wdog))
388 mod_timer(&wdev->timer,
389 jiffies + wdog->timeout * HZ / 2);
390 } 342 }
391 343
392 return 0; 344 return 0;