20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22 #include <linux/bitops.h>
24 #include <linux/device.h>
28 #include <linux/kernel.h>
30 #include <linux/module.h>
37 #include <linux/watchdog.h>
39 #define WDOG_CONTROL_REG_OFFSET 0x00
40 #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01
41 #define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04
42 #define WDOG_CURRENT_COUNT_REG_OFFSET 0x08
43 #define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c
44 #define WDOG_COUNTER_RESTART_KICK_VALUE 0x76
47 #define DW_WDT_MAX_TOP 15
54 #define WDT_TIMEOUT (HZ / 2)
66 static inline int dw_wdt_is_enabled(
void)
72 static inline int dw_wdt_top_in_seconds(
unsigned top)
81 static int dw_wdt_get_top(
void)
85 return dw_wdt_top_in_seconds(top);
88 static inline void dw_wdt_set_next_heartbeat(
void)
90 dw_wdt.next_heartbeat =
jiffies + dw_wdt_get_top() *
HZ;
93 static int dw_wdt_set_top(
unsigned top_s)
102 if (dw_wdt_top_in_seconds(i) >= top_s) {
110 dw_wdt_set_next_heartbeat();
112 return dw_wdt_top_in_seconds(top_val);
115 static void dw_wdt_keepalive(
void)
121 static void dw_wdt_ping(
unsigned long data)
124 (!nowayout && !dw_wdt.in_use)) {
128 pr_crit(
"keepalive missed, machine will reset\n");
139 spin_lock(&dw_wdt.lock);
140 if (!dw_wdt_is_enabled()) {
150 dw_wdt_set_next_heartbeat();
152 spin_unlock(&dw_wdt.lock);
166 dw_wdt.expect_close = 0;
168 for (i = 0; i < len; ++
i) {
175 dw_wdt.expect_close = 1;
181 dw_wdt_set_next_heartbeat();
187 static u32 dw_wdt_time_left(
void)
196 .identity =
"Synopsys DesignWare Watchdog",
199 static long dw_wdt_ioctl(
struct file *filp,
unsigned int cmd,
unsigned long arg)
207 sizeof(dw_wdt_ident)) ? -
EFAULT : 0;
214 dw_wdt_set_next_heartbeat();
218 if (
get_user(val, (
int __user *)arg))
220 timeout = dw_wdt_set_top(val);
221 return put_user(timeout , (
int __user *)arg);
224 return put_user(dw_wdt_get_top(), (
int __user *)arg);
228 if (
get_user(val, (
int __user *)arg))
230 return put_user(dw_wdt_time_left(), (
int __user *)arg);
237 static int dw_wdt_release(
struct inode *inode,
struct file *filp)
241 if (!dw_wdt.expect_close) {
245 pr_crit(
"unexpected close, system will reboot soon\n");
247 pr_crit(
"watchdog cannot be disabled, system will reboot soon\n");
250 dw_wdt.expect_close = 0;
256 static int dw_wdt_suspend(
struct device *
dev)
263 static int dw_wdt_resume(
struct device *
dev)
275 static const struct dev_pm_ops dw_wdt_pm_ops = {
277 .resume = dw_wdt_resume,
286 .unlocked_ioctl = dw_wdt_ioctl,
287 .release = dw_wdt_release
309 if (IS_ERR(dw_wdt.clk))
310 return PTR_ERR(dw_wdt.clk);
320 goto out_disable_clk;
322 dw_wdt_set_next_heartbeat();
347 .probe = dw_wdt_drv_probe,
353 .pm = &dw_wdt_pm_ops,