aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/dw_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/dw_wdt.c')
-rw-r--r--drivers/watchdog/dw_wdt.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index b34a2e4e4e43..d0bb9499d12c 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -51,6 +51,8 @@
51/* The maximum TOP (timeout period) value that can be set in the watchdog. */ 51/* The maximum TOP (timeout period) value that can be set in the watchdog. */
52#define DW_WDT_MAX_TOP 15 52#define DW_WDT_MAX_TOP 15
53 53
54#define DW_WDT_DEFAULT_SECONDS 30
55
54static bool nowayout = WATCHDOG_NOWAYOUT; 56static bool nowayout = WATCHDOG_NOWAYOUT;
55module_param(nowayout, bool, 0); 57module_param(nowayout, bool, 0);
56MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " 58MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
@@ -96,6 +98,12 @@ static inline void dw_wdt_set_next_heartbeat(void)
96 dw_wdt.next_heartbeat = jiffies + dw_wdt_get_top() * HZ; 98 dw_wdt.next_heartbeat = jiffies + dw_wdt_get_top() * HZ;
97} 99}
98 100
101static void dw_wdt_keepalive(void)
102{
103 writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
104 WDOG_COUNTER_RESTART_REG_OFFSET);
105}
106
99static int dw_wdt_set_top(unsigned top_s) 107static int dw_wdt_set_top(unsigned top_s)
100{ 108{
101 int i, top_val = DW_WDT_MAX_TOP; 109 int i, top_val = DW_WDT_MAX_TOP;
@@ -110,21 +118,27 @@ static int dw_wdt_set_top(unsigned top_s)
110 break; 118 break;
111 } 119 }
112 120
113 /* Set the new value in the watchdog. */ 121 /*
122 * Set the new value in the watchdog. Some versions of dw_wdt
123 * have have TOPINIT in the TIMEOUT_RANGE register (as per
124 * CP_WDT_DUAL_TOP in WDT_COMP_PARAMS_1). On those we
125 * effectively get a pat of the watchdog right here.
126 */
114 writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT, 127 writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT,
115 dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); 128 dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
116 129
130 /*
131 * Add an explicit pat to handle versions of the watchdog that
132 * don't have TOPINIT. This won't hurt on versions that have
133 * it.
134 */
135 dw_wdt_keepalive();
136
117 dw_wdt_set_next_heartbeat(); 137 dw_wdt_set_next_heartbeat();
118 138
119 return dw_wdt_top_in_seconds(top_val); 139 return dw_wdt_top_in_seconds(top_val);
120} 140}
121 141
122static void dw_wdt_keepalive(void)
123{
124 writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
125 WDOG_COUNTER_RESTART_REG_OFFSET);
126}
127
128static int dw_wdt_restart_handle(struct notifier_block *this, 142static int dw_wdt_restart_handle(struct notifier_block *this,
129 unsigned long mode, void *cmd) 143 unsigned long mode, void *cmd)
130{ 144{
@@ -167,9 +181,9 @@ static int dw_wdt_open(struct inode *inode, struct file *filp)
167 if (!dw_wdt_is_enabled()) { 181 if (!dw_wdt_is_enabled()) {
168 /* 182 /*
169 * The watchdog is not currently enabled. Set the timeout to 183 * The watchdog is not currently enabled. Set the timeout to
170 * the maximum and then start it. 184 * something reasonable and then start it.
171 */ 185 */
172 dw_wdt_set_top(DW_WDT_MAX_TOP); 186 dw_wdt_set_top(DW_WDT_DEFAULT_SECONDS);
173 writel(WDOG_CONTROL_REG_WDT_EN_MASK, 187 writel(WDOG_CONTROL_REG_WDT_EN_MASK,
174 dw_wdt.regs + WDOG_CONTROL_REG_OFFSET); 188 dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
175 } 189 }