25 #include <linux/kernel.h>
26 #include <linux/module.h>
31 #include <linux/watchdog.h>
35 #include <linux/slab.h>
39 #define TIMEOUT_DEFAULT TIMEOUT_MAX
45 "Timeout value. Limited to be 1 or 2 seconds. (default="
50 MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default="
56 #define WDT_CTRL_PSEL 8
57 #define WDT_CTRL_KEY 24
61 #define WDT_RCAUSE 0x10
62 #define WDT_RCAUSE_POR 0
63 #define WDT_RCAUSE_EXT 2
64 #define WDT_RCAUSE_WDT 3
65 #define WDT_RCAUSE_JTAG 4
66 #define WDT_RCAUSE_SERP 5
68 #define WDT_BIT(name) (1 << WDT_##name)
69 #define WDT_BF(name, value) ((value) << WDT_##name)
71 #define wdt_readl(dev, reg) \
72 __raw_readl((dev)->regs + WDT_##reg)
73 #define wdt_writel(dev, reg, value) \
74 __raw_writel((value), (dev)->regs + WDT_##reg)
86 static char expect_release;
91 static inline void at32_wdt_stop(
void)
105 static inline void at32_wdt_start(
void)
108 unsigned long psel = (wdt->
timeout > 1) ? 0xf : 0
xe;
113 |
WDT_BF(CTRL_KEY, 0x55));
116 |
WDT_BF(CTRL_KEY, 0xaa));
123 static inline void at32_wdt_pat(
void)
145 static int at32_wdt_close(
struct inode *inode,
struct file *file)
147 if (expect_release == 42) {
151 "unexpected close, not stopping watchdog!\n");
162 static int at32_wdt_settimeout(
int time)
182 static int at32_wdt_get_status(
void)
207 .identity =
"at32ap700x watchdog",
216 static long at32_wdt_ioctl(
struct file *file,
217 unsigned int cmd,
unsigned long arg)
227 sizeof(at32_wdt_info)) ? -
EFAULT : 0;
253 ret = at32_wdt_settimeout(time);
267 static ssize_t at32_wdt_write(
struct file *file,
const char __user *
data,
268 size_t len, loff_t *ppos)
285 for (i = 0; i != len; i++) {
302 .unlocked_ioctl = at32_wdt_ioctl,
303 .open = at32_wdt_open,
304 .release = at32_wdt_close,
305 .write = at32_wdt_write,
314 dev_dbg(&pdev->
dev,
"only 1 wdt instance supported.\n");
320 dev_dbg(&pdev->
dev,
"missing mmio resource\n");
326 dev_dbg(&pdev->
dev,
"no memory for wdt structure\n");
333 dev_dbg(&pdev->
dev,
"could not map I/O memory\n");
342 dev_info(&pdev->
dev,
"CPU must be reset with external "
343 "reset or POR due to silicon errata.\n");
351 wdt->
miscdev.name =
"watchdog";
352 wdt->
miscdev.fops = &at32_wdt_fops;
355 platform_set_drvdata(pdev, wdt);
357 if (at32_wdt_settimeout(timeout)) {
360 "default timeout invalid, set to %d sec.\n",
366 dev_dbg(&pdev->
dev,
"failed to register wdt miscdev\n");
371 "AT32AP700X WDT at 0x%p, timeout %d sec (nowayout=%d)\n",
377 platform_set_drvdata(pdev,
NULL);
388 if (wdt && platform_get_drvdata(pdev) == wdt) {
397 platform_set_drvdata(pdev,
NULL);
421 #define at32_wdt_suspend NULL
422 #define at32_wdt_resume NULL
429 .remove =
__exit_p(at32_wdt_remove),
436 .shutdown = at32_wdt_shutdown,
439 static int __init at32_wdt_init(
void)
445 static void __exit at32_wdt_exit(
void)