Commit 15b25701b282bd761a82c6508529b2145744075f

Authored by Linus Walleij
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");