23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25 #include <linux/module.h>
27 #include <linux/types.h>
29 #include <linux/watchdog.h>
31 #include <linux/reboot.h>
36 #include <linux/slab.h>
53 #define TIMER_MARGIN 60
57 "MPcore timer margin in seconds. (0 < mpcore_margin < 65536, default="
63 "Watchdog cannot be stopped once started (default="
66 #define ONLY_TESTING 0
70 "set to 1 to ignore reboots, 0 to reboot (default="
84 "Triggered - Reboot ignored.\n");
99 static void mpcore_wdt_keepalive(
struct mpcore_wdt *wdt)
103 spin_lock(&wdt_lock);
106 count = (0xFFFFFFFF
U -
count) * (
HZ / 5);
107 count = (count / 256) * mpcore_margin;
112 spin_unlock(&wdt_lock);
115 static void mpcore_wdt_stop(
struct mpcore_wdt *wdt)
117 spin_lock(&wdt_lock);
121 spin_unlock(&wdt_lock);
124 static void mpcore_wdt_start(
struct mpcore_wdt *wdt)
126 dev_printk(
KERN_INFO, wdt->
dev,
"enabling watchdog.\n");
129 mpcore_wdt_keepalive(wdt);
140 static int mpcore_wdt_set_heartbeat(
int t)
142 if (t < 0x0001 || t > 0xFFFF)
154 struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_pdev);
167 mpcore_wdt_start(wdt);
172 static int mpcore_wdt_release(
struct inode *inode,
struct file *file)
181 mpcore_wdt_stop(wdt);
184 "unexpected close, not stopping watchdog!\n");
185 mpcore_wdt_keepalive(wdt);
192 static ssize_t mpcore_wdt_write(
struct file *file,
const char *
data,
193 size_t len, loff_t *ppos)
207 for (i = 0; i != len; i++) {
216 mpcore_wdt_keepalive(wdt);
225 .identity =
"MPcore Watchdog",
228 static long mpcore_wdt_ioctl(
struct file *file,
unsigned int cmd,
262 mpcore_wdt_stop(wdt);
266 mpcore_wdt_start(wdt);
272 mpcore_wdt_keepalive(wdt);
277 ret = mpcore_wdt_set_heartbeat(uarg.i);
281 mpcore_wdt_keepalive(wdt);
284 uarg.i = mpcore_margin;
306 struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
309 mpcore_wdt_stop(wdt);
318 .write = mpcore_wdt_write,
319 .unlocked_ioctl = mpcore_wdt_ioctl,
320 .open = mpcore_wdt_open,
321 .release = mpcore_wdt_release,
324 static struct miscdevice mpcore_wdt_miscdev = {
327 .fops = &mpcore_wdt_fops,
351 ret = devm_request_irq(wdt->
dev, wdt->
irq, mpcore_wdt_fire, 0,
355 "cannot register IRQ%d for watchdog\n",
369 "cannot register miscdev on minor=%d (err=%d)\n",
374 mpcore_wdt_stop(wdt);
375 platform_set_drvdata(pdev, wdt);
376 mpcore_wdt_pdev = pdev;
383 platform_set_drvdata(pdev,
NULL);
387 mpcore_wdt_pdev =
NULL;
395 struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
396 mpcore_wdt_stop(wdt);
402 struct mpcore_wdt *wdt = platform_get_drvdata(pdev);
405 mpcore_wdt_start(wdt);
409 #define mpcore_wdt_suspend NULL
410 #define mpcore_wdt_resume NULL
417 .probe = mpcore_wdt_probe,
421 .shutdown = mpcore_wdt_shutdown,
424 .name =
"mpcore_wdt",
428 static int __init mpcore_wdt_init(
void)
434 if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
436 pr_info(
"mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n",
440 pr_info(
"MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n",
441 mpcore_noboot, mpcore_margin, nowayout);
446 static void __exit mpcore_wdt_exit(
void)