diff options
Diffstat (limited to 'drivers/watchdog/dw_wdt.c')
-rw-r--r-- | drivers/watchdog/dw_wdt.c | 32 |
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 | |||
54 | static bool nowayout = WATCHDOG_NOWAYOUT; | 56 | static bool nowayout = WATCHDOG_NOWAYOUT; |
55 | module_param(nowayout, bool, 0); | 57 | module_param(nowayout, bool, 0); |
56 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | 58 | MODULE_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 | ||
101 | static void dw_wdt_keepalive(void) | ||
102 | { | ||
103 | writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs + | ||
104 | WDOG_COUNTER_RESTART_REG_OFFSET); | ||
105 | } | ||
106 | |||
99 | static int dw_wdt_set_top(unsigned top_s) | 107 | static 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 | ||
122 | static void dw_wdt_keepalive(void) | ||
123 | { | ||
124 | writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs + | ||
125 | WDOG_COUNTER_RESTART_REG_OFFSET); | ||
126 | } | ||
127 | |||
128 | static int dw_wdt_restart_handle(struct notifier_block *this, | 142 | static 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 | } |