Commit 15b25701b282bd761a82c6508529b2145744075f
Committed by
Wim Van Sebroeck
1 parent
fd7b673c92
watchdog: coh901327: convert to use watchdog core
This converts the COH901327 watchdog to use the watchdog core. I followed Wolframs document, looked at some other drivers and tested it on the U300. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Cc: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Showing 2 changed files with 56 additions and 137 deletions Side-by-side Diff
drivers/watchdog/Kconfig
... | ... | @@ -287,6 +287,7 @@ |
287 | 287 | bool "ST-Ericsson COH 901 327 watchdog" |
288 | 288 | depends on ARCH_U300 |
289 | 289 | default y if MACH_U300 |
290 | + select WATCHDOG_CORE | |
290 | 291 | help |
291 | 292 | Say Y here to include Watchdog timer support for the |
292 | 293 | watchdog embedded into the ST-Ericsson U300 series platforms. |
drivers/watchdog/coh901327_wdt.c
... | ... | @@ -8,17 +8,15 @@ |
8 | 8 | */ |
9 | 9 | #include <linux/module.h> |
10 | 10 | #include <linux/types.h> |
11 | -#include <linux/fs.h> | |
12 | -#include <linux/miscdevice.h> | |
13 | 11 | #include <linux/watchdog.h> |
14 | 12 | #include <linux/interrupt.h> |
15 | 13 | #include <linux/pm.h> |
16 | 14 | #include <linux/platform_device.h> |
17 | 15 | #include <linux/io.h> |
18 | 16 | #include <linux/bitops.h> |
19 | -#include <linux/uaccess.h> | |
20 | 17 | #include <linux/clk.h> |
21 | 18 | #include <linux/delay.h> |
19 | +#include <linux/err.h> | |
22 | 20 | |
23 | 21 | #define DRV_NAME "WDOG COH 901 327" |
24 | 22 | |
... | ... | @@ -74,8 +72,6 @@ |
74 | 72 | static resource_size_t physize; |
75 | 73 | static int irq; |
76 | 74 | static void __iomem *virtbase; |
77 | -static unsigned long coh901327_users; | |
78 | -static unsigned long boot_status; | |
79 | 75 | static struct device *parent; |
80 | 76 | |
81 | 77 | /* |
82 | 78 | |
83 | 79 | |
84 | 80 | |
85 | 81 | |
86 | 82 | |
87 | 83 | |
... | ... | @@ -155,30 +151,31 @@ |
155 | 151 | __func__, val); |
156 | 152 | } |
157 | 153 | |
158 | -static void coh901327_start(void) | |
154 | +static int coh901327_start(struct watchdog_device *wdt_dev) | |
159 | 155 | { |
160 | 156 | coh901327_enable(margin * 100); |
157 | + return 0; | |
161 | 158 | } |
162 | 159 | |
163 | -static void coh901327_keepalive(void) | |
160 | +static int coh901327_stop(struct watchdog_device *wdt_dev) | |
164 | 161 | { |
162 | + coh901327_disable(); | |
163 | + return 0; | |
164 | +} | |
165 | + | |
166 | +static int coh901327_ping(struct watchdog_device *wdd) | |
167 | +{ | |
165 | 168 | clk_enable(clk); |
166 | 169 | /* Feed the watchdog */ |
167 | 170 | writew(U300_WDOG_FR_FEED_RESTART_TIMER, |
168 | 171 | virtbase + U300_WDOG_FR); |
169 | 172 | clk_disable(clk); |
173 | + return 0; | |
170 | 174 | } |
171 | 175 | |
172 | -static int coh901327_settimeout(int time) | |
176 | +static int coh901327_settimeout(struct watchdog_device *wdt_dev, | |
177 | + unsigned int time) | |
173 | 178 | { |
174 | - /* | |
175 | - * Max margin is 327 since the 10ms | |
176 | - * timeout register is max | |
177 | - * 0x7FFF = 327670ms ~= 327s. | |
178 | - */ | |
179 | - if (time <= 0 || time > 327) | |
180 | - return -EINVAL; | |
181 | - | |
182 | 179 | margin = time; |
183 | 180 | clk_enable(clk); |
184 | 181 | /* Set new timeout value */ |
... | ... | @@ -190,6 +187,23 @@ |
190 | 187 | return 0; |
191 | 188 | } |
192 | 189 | |
190 | +static unsigned int coh901327_gettimeleft(struct watchdog_device *wdt_dev) | |
191 | +{ | |
192 | + u16 val; | |
193 | + | |
194 | + clk_enable(clk); | |
195 | + /* Read repeatedly until the value is stable! */ | |
196 | + val = readw(virtbase + U300_WDOG_CR); | |
197 | + while (val & U300_WDOG_CR_VALID_IND) | |
198 | + val = readw(virtbase + U300_WDOG_CR); | |
199 | + val &= U300_WDOG_CR_COUNT_VALUE_MASK; | |
200 | + clk_disable(clk); | |
201 | + if (val != 0) | |
202 | + val /= 100; | |
203 | + | |
204 | + return val; | |
205 | +} | |
206 | + | |
193 | 207 | /* |
194 | 208 | * This interrupt occurs 10 ms before the watchdog WILL bark. |
195 | 209 | */ |
196 | 210 | |
197 | 211 | |
198 | 212 | |
... | ... | @@ -218,130 +232,35 @@ |
218 | 232 | return IRQ_HANDLED; |
219 | 233 | } |
220 | 234 | |
221 | -/* | |
222 | - * Allow only one user (daemon) to open the watchdog | |
223 | - */ | |
224 | -static int coh901327_open(struct inode *inode, struct file *file) | |
225 | -{ | |
226 | - if (test_and_set_bit(1, &coh901327_users)) | |
227 | - return -EBUSY; | |
228 | - coh901327_start(); | |
229 | - return nonseekable_open(inode, file); | |
230 | -} | |
235 | +static const struct watchdog_info coh901327_ident = { | |
236 | + .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | |
237 | + .identity = DRV_NAME, | |
238 | +}; | |
231 | 239 | |
232 | -static int coh901327_release(struct inode *inode, struct file *file) | |
233 | -{ | |
234 | - clear_bit(1, &coh901327_users); | |
235 | - coh901327_disable(); | |
236 | - return 0; | |
237 | -} | |
238 | - | |
239 | -static ssize_t coh901327_write(struct file *file, const char __user *data, | |
240 | - size_t len, loff_t *ppos) | |
241 | -{ | |
242 | - if (len) | |
243 | - coh901327_keepalive(); | |
244 | - return len; | |
245 | -} | |
246 | - | |
247 | -static long coh901327_ioctl(struct file *file, unsigned int cmd, | |
248 | - unsigned long arg) | |
249 | -{ | |
250 | - int ret = -ENOTTY; | |
251 | - u16 val; | |
252 | - int time; | |
253 | - int new_options; | |
254 | - union { | |
255 | - struct watchdog_info __user *ident; | |
256 | - int __user *i; | |
257 | - } uarg; | |
258 | - static const struct watchdog_info ident = { | |
259 | - .options = WDIOF_CARDRESET | | |
260 | - WDIOF_SETTIMEOUT | | |
261 | - WDIOF_KEEPALIVEPING, | |
262 | - .identity = "COH 901 327 Watchdog", | |
263 | - .firmware_version = 1, | |
264 | - }; | |
265 | - uarg.i = (int __user *)arg; | |
266 | - | |
267 | - switch (cmd) { | |
268 | - case WDIOC_GETSUPPORT: | |
269 | - ret = copy_to_user(uarg.ident, &ident, | |
270 | - sizeof(ident)) ? -EFAULT : 0; | |
271 | - break; | |
272 | - | |
273 | - case WDIOC_GETSTATUS: | |
274 | - ret = put_user(0, uarg.i); | |
275 | - break; | |
276 | - | |
277 | - case WDIOC_GETBOOTSTATUS: | |
278 | - ret = put_user(boot_status, uarg.i); | |
279 | - break; | |
280 | - | |
281 | - case WDIOC_SETOPTIONS: | |
282 | - ret = get_user(new_options, uarg.i); | |
283 | - if (ret) | |
284 | - break; | |
285 | - if (new_options & WDIOS_DISABLECARD) | |
286 | - coh901327_disable(); | |
287 | - if (new_options & WDIOS_ENABLECARD) | |
288 | - coh901327_start(); | |
289 | - ret = 0; | |
290 | - break; | |
291 | - | |
292 | - case WDIOC_KEEPALIVE: | |
293 | - coh901327_keepalive(); | |
294 | - ret = 0; | |
295 | - break; | |
296 | - | |
297 | - case WDIOC_SETTIMEOUT: | |
298 | - ret = get_user(time, uarg.i); | |
299 | - if (ret) | |
300 | - break; | |
301 | - | |
302 | - ret = coh901327_settimeout(time); | |
303 | - if (ret) | |
304 | - break; | |
305 | - /* Then fall through to return set value */ | |
306 | - | |
307 | - case WDIOC_GETTIMEOUT: | |
308 | - ret = put_user(margin, uarg.i); | |
309 | - break; | |
310 | - | |
311 | - case WDIOC_GETTIMELEFT: | |
312 | - clk_enable(clk); | |
313 | - /* Read repeatedly until the value is stable! */ | |
314 | - val = readw(virtbase + U300_WDOG_CR); | |
315 | - while (val & U300_WDOG_CR_VALID_IND) | |
316 | - val = readw(virtbase + U300_WDOG_CR); | |
317 | - val &= U300_WDOG_CR_COUNT_VALUE_MASK; | |
318 | - clk_disable(clk); | |
319 | - if (val != 0) | |
320 | - val /= 100; | |
321 | - ret = put_user(val, uarg.i); | |
322 | - break; | |
323 | - } | |
324 | - return ret; | |
325 | -} | |
326 | - | |
327 | -static const struct file_operations coh901327_fops = { | |
328 | - .owner = THIS_MODULE, | |
329 | - .llseek = no_llseek, | |
330 | - .write = coh901327_write, | |
331 | - .unlocked_ioctl = coh901327_ioctl, | |
332 | - .open = coh901327_open, | |
333 | - .release = coh901327_release, | |
240 | +static struct watchdog_ops coh901327_ops = { | |
241 | + .owner = THIS_MODULE, | |
242 | + .start = coh901327_start, | |
243 | + .stop = coh901327_stop, | |
244 | + .ping = coh901327_ping, | |
245 | + .set_timeout = coh901327_settimeout, | |
246 | + .get_timeleft = coh901327_gettimeleft, | |
334 | 247 | }; |
335 | 248 | |
336 | -static struct miscdevice coh901327_miscdev = { | |
337 | - .minor = WATCHDOG_MINOR, | |
338 | - .name = "watchdog", | |
339 | - .fops = &coh901327_fops, | |
249 | +static struct watchdog_device coh901327_wdt = { | |
250 | + .info = &coh901327_ident, | |
251 | + .ops = &coh901327_ops, | |
252 | + /* | |
253 | + * Max margin is 327 since the 10ms | |
254 | + * timeout register is max | |
255 | + * 0x7FFF = 327670ms ~= 327s. | |
256 | + */ | |
257 | + .min_timeout = 0, | |
258 | + .max_timeout = 327, | |
340 | 259 | }; |
341 | 260 | |
342 | 261 | static int __exit coh901327_remove(struct platform_device *pdev) |
343 | 262 | { |
344 | - misc_deregister(&coh901327_miscdev); | |
263 | + watchdog_unregister_device(&coh901327_wdt); | |
345 | 264 | coh901327_disable(); |
346 | 265 | free_irq(irq, pdev); |
347 | 266 | clk_put(clk); |
... | ... | @@ -350,7 +269,6 @@ |
350 | 269 | return 0; |
351 | 270 | } |
352 | 271 | |
353 | - | |
354 | 272 | static int __init coh901327_probe(struct platform_device *pdev) |
355 | 273 | { |
356 | 274 | int ret; |
... | ... | @@ -393,7 +311,7 @@ |
393 | 311 | case U300_WDOG_SR_STATUS_TIMED_OUT: |
394 | 312 | dev_info(&pdev->dev, |
395 | 313 | "watchdog timed out since last chip reset!\n"); |
396 | - boot_status = WDIOF_CARDRESET; | |
314 | + coh901327_wdt.bootstatus |= WDIOF_CARDRESET; | |
397 | 315 | /* Status will be cleared below */ |
398 | 316 | break; |
399 | 317 | case U300_WDOG_SR_STATUS_NORMAL: |
... | ... | @@ -435,7 +353,7 @@ |
435 | 353 | |
436 | 354 | clk_disable(clk); |
437 | 355 | |
438 | - ret = misc_register(&coh901327_miscdev); | |
356 | + ret = watchdog_register_device(&coh901327_wdt); | |
439 | 357 | if (ret == 0) |
440 | 358 | dev_info(&pdev->dev, |
441 | 359 | "initialized. timer margin=%d sec\n", margin); |
... | ... | @@ -547,5 +465,5 @@ |
547 | 465 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); |
548 | 466 | |
549 | 467 | MODULE_LICENSE("GPL"); |
550 | -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | |
468 | +MODULE_ALIAS("platform:coh901327-watchdog"); |