[package] iwinfo: factor txpower offset into info display output, recompile if driver...
[openwrt.git] / target / linux / ubicom32 / files / drivers / watchdog / ubi32_wdt.c
1 /*
2 * drivers/watchdog/ubi32_wdt.c
3 * Ubicom32 Watchdog Driver
4 *
5 * Originally based on softdog.c
6 * Copyright 2006-2007 Analog Devices Inc.
7 * Copyright 2006-2007 Michele d'Amico
8 * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>
9 * (C) Copyright 2009, Ubicom, Inc.
10 *
11 * This file is part of the Ubicom32 Linux Kernel Port.
12 *
13 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
14 * it and/or modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, either version 2 of the
16 * License, or (at your option) any later version.
17 *
18 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
19 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
21 * the GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with the Ubicom32 Linux Kernel Port. If not,
25 * see <http://www.gnu.org/licenses/>.
26 *
27 * Ubicom32 implementation derived from (with many thanks):
28 * arch/m68knommu
29 * arch/blackfin
30 * arch/parisc
31 */
32 #include <linux/platform_device.h>
33 #include <linux/module.h>
34 #include <linux/moduleparam.h>
35 #include <linux/types.h>
36 #include <linux/timer.h>
37 #include <linux/miscdevice.h>
38 #include <linux/watchdog.h>
39 #include <linux/fs.h>
40 #include <linux/notifier.h>
41 #include <linux/reboot.h>
42 #include <linux/init.h>
43 #include <linux/interrupt.h>
44 #include <linux/uaccess.h>
45 #include <asm/ip5000.h>
46
47 #define WATCHDOG_NAME "ubi32-wdt"
48 #define PFX WATCHDOG_NAME ": "
49
50 #define OSC1_FREQ 12000000
51 #define WATCHDOG_SEC_TO_CYC(x) (OSC1_FREQ * (x))
52 #define WATCHDOG_MAX_SEC (0xffffffff / OSC1_FREQ)
53
54 #define MIN_PROCESSOR_ADDRESS 0x03000000
55
56 static DEFINE_SPINLOCK(ubi32_wdt_spinlock);
57
58 #define WATCHDOG_TIMEOUT 20
59
60 #if defined(CONFIG_WATCHDOG_NOWAYOUT)
61 #define WATCHDOG_NOWAYOUT 1
62 #else
63 #define WATCHDOG_NOWAYOUT 0
64 #endif
65
66 static unsigned int timeout = WATCHDOG_TIMEOUT;
67 static int nowayout = WATCHDOG_NOWAYOUT;
68 static struct watchdog_info ubi32_wdt_info;
69 static unsigned long open_check;
70 static char expect_close;
71
72 #if !defined(CONFIG_SMP)
73 #define UBI32_WDT_LOCK(lock, flags) local_irq_save(flags)
74 #define UBI32_WDT_UNLOCK(lock, flags) local_irq_restore(flags)
75 #define UBI32_WDT_LOCK_CHECK()
76 #else
77 #define UBI32_WDT_LOCK(lock, flags) spin_lock_irqsave((lock), (flags));
78 #define UBI32_WDT_UNLOCK(lock, flags) spin_unlock_irqrestore((lock), (flags));
79 #define UBI32_WDT_LOCK_CHECK() BUG_ON(!spin_is_locked(&ubi32_wdt_spinlock));
80 #endif
81
82 /*
83 * ubi32_wdt_remaining()
84 * Return the approximate number of seconds remaining
85 */
86 static int ubi32_wdt_remaining(void)
87 {
88 int compare;
89 int curr;
90
91 UBI32_WDT_LOCK_CHECK();
92
93 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
94 compare = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcom);
95 curr = ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval);
96 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
97 return (compare - curr) / OSC1_FREQ;
98
99 }
100
101 /*
102 * ubi32_wdt_keepalive()
103 * Keep the Userspace Watchdog Alive
104 *
105 * The Userspace watchdog got a KeepAlive: schedule the next timeout.
106 */
107 static int ubi32_wdt_keepalive(void)
108 {
109 UBI32_WDT_LOCK_CHECK();
110 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
111 ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
112 ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
113 + WATCHDOG_SEC_TO_CYC(timeout));
114 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
115 return 0;
116 }
117
118 /*
119 * ubi32_wdt_stop()
120 * Stop the on-chip Watchdog
121 */
122 static int ubi32_wdt_stop(void)
123 {
124 UBI32_WDT_LOCK_CHECK();
125 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
126 ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, TIMER_WATCHDOG_DISABLE);
127 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
128 return 0;
129 }
130
131 /*
132 * ubi32_wdt_start()
133 * Start the on-chip Watchdog
134 */
135 static int ubi32_wdt_start(void)
136 {
137 UBI32_WDT_LOCK_CHECK();
138 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
139 ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcom,
140 ubicom32_read_reg(&UBICOM32_IO_TIMER->mptval)
141 + WATCHDOG_SEC_TO_CYC(timeout));
142 ubicom32_write_reg(&UBICOM32_IO_TIMER->wdcfg, ~TIMER_WATCHDOG_DISABLE);
143 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
144 return 0;
145 }
146
147 /*
148 * ubi32_wdt_running()
149 * Return true if the watchdog is configured
150 */
151 static int ubi32_wdt_running(void)
152 {
153 int enabled;
154
155 UBI32_WDT_LOCK_CHECK();
156 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, TIMER_TKEYVAL);
157 enabled = ubicom32_read_reg(&UBICOM32_IO_TIMER->wdcfg) == ~TIMER_WATCHDOG_DISABLE;
158 ubicom32_write_reg(&UBICOM32_IO_TIMER->tkey, 0);
159 return enabled;
160 }
161
162 /*
163 * ubi32_wdt_set_timeout()
164 * Set the Userspace Watchdog timeout
165 *
166 * - @t: new timeout value (in seconds)
167 */
168 static int ubi32_wdt_set_timeout(unsigned long t)
169 {
170 UBI32_WDT_LOCK_CHECK();
171
172 if (t > WATCHDOG_MAX_SEC) {
173 printk(KERN_WARNING PFX "request to large: %ld [1-%d] sec)\n", t, WATCHDOG_MAX_SEC);
174 return -EINVAL;
175 }
176
177 /*
178 * If we are running, then reset the time value so
179 * that the new value has an immediate effect.
180 */
181 timeout = t;
182 if (ubi32_wdt_running()) {
183 ubi32_wdt_keepalive();
184 }
185 return 0;
186 }
187
188 /*
189 * ubi32_wdt_open()
190 * Open the Device
191 */
192 static int ubi32_wdt_open(struct inode *inode, struct file *file)
193 {
194 unsigned long flags;
195
196 if (test_and_set_bit(0, &open_check))
197 return -EBUSY;
198
199 if (nowayout)
200 __module_get(THIS_MODULE);
201
202 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
203 ubi32_wdt_start();
204 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
205
206 return nonseekable_open(inode, file);
207 }
208
209 /*
210 * ubi32_wdt_close()
211 * Close the Device
212 */
213 static int ubi32_wdt_release(struct inode *inode, struct file *file)
214 {
215 unsigned long flags;
216
217 /*
218 * If we don't expect a close, then the watchdog continues
219 * even though the device is closed. The caller will have
220 * a full timeout value to reopen the device and continue
221 * stroking it.
222 */
223 if (expect_close != 42) {
224 printk(KERN_CRIT PFX
225 "Unexpected close, not stopping watchdog!\n");
226 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
227 ubi32_wdt_keepalive();
228 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
229 } else {
230 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
231 ubi32_wdt_stop();
232 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
233 }
234
235 expect_close = 0;
236 clear_bit(0, &open_check);
237 return 0;
238 }
239
240 /*
241 * ubi32_wdt_write()
242 * Write to Device
243 *
244 * If the user writes nothing, nothing happens.
245 * If the user writes a V, then we expect a close and allow a release.
246 * If the user writes anything else, it is ignored.
247 */
248 static ssize_t ubi32_wdt_write(struct file *file, const char __user *data,
249 size_t len, loff_t *ppos)
250 {
251 size_t i;
252 unsigned long flags;
253
254 /*
255 * Every write resets the expect_close. The last write
256 * must be a V to allow shutdown on close.
257 */
258 expect_close = 0;
259
260 /*
261 * Empty writes still ping.
262 */
263 if (!len) {
264 goto ping;
265 }
266
267 /*
268 * If nowayout is set, it does not matter if the caller
269 * is trying to send the magic 'V' we will not allow a
270 * close to stop us.
271 */
272 if (nowayout) {
273 goto ping;
274 }
275
276 /*
277 * See if the program wrote a 'V' and if so disable
278 * the watchdog on release.
279 */
280 for (i = 0; i < len; i++) {
281 char c;
282 if (get_user(c, data + i)) {
283 return -EFAULT;
284 }
285
286 if (c == 'V') {
287 expect_close = 42;
288 }
289 }
290
291 ping:
292 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
293 ubi32_wdt_keepalive();
294 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
295 return len;
296 }
297
298 /*
299 * ubi32_wdt_ioctl()
300 * Query the watchdog device.
301 *
302 * Query basic information from the device or ping it, as outlined by the
303 * watchdog API.
304 */
305 static long ubi32_wdt_ioctl(struct file *file,
306 unsigned int cmd, unsigned long arg)
307 {
308 void __user *argp = (void __user *)arg;
309 int __user *p = argp;
310
311 switch (cmd) {
312 case WDIOC_GETSUPPORT:
313 if (copy_to_user(argp, &ubi32_wdt_info, sizeof(ubi32_wdt_info))) {
314 return -EFAULT;
315 }
316 return 0;
317
318 case WDIOC_GETSTATUS: {
319 unsigned long flags;
320 int running;
321
322 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
323 running = ubi32_wdt_running();
324 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
325 return running;
326 }
327
328 case WDIOC_GETBOOTSTATUS:
329 return ubicom32_get_reset_reason();
330
331 case WDIOC_SETOPTIONS: {
332 unsigned long flags;
333 int options, ret = -EINVAL;
334
335 /*
336 * The sample application does not pass a pointer
337 * but directly passes a value of 1 or 2; however
338 * all of the implementations (and thus probably
339 * the real applications) pass a pointer to a value.
340 *
341 * It should be noted that WDIOC_SETOPTIONS is defined as
342 * _IOR(WATCHDOG_IOCTL_BASE, 4, int), which means
343 * that it should be an int and NOT a pointer.
344 *
345 * TODO: Examine this code for future chips.
346 * TODO: Report the sample code defect.
347 */
348 if ((int)p < MIN_PROCESSOR_ADDRESS) {
349 options = (int)p;
350 } else {
351 if (get_user(options, p))
352 return -EFAULT;
353 }
354
355 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
356 if (options & WDIOS_DISABLECARD) {
357 ubi32_wdt_stop();
358 ret = 0;
359 }
360 if (options & WDIOS_ENABLECARD) {
361 ubi32_wdt_start();
362 ret = 0;
363 }
364 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
365 return ret;
366 }
367
368 case WDIOC_KEEPALIVE: {
369 unsigned long flags;
370
371 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
372 ubi32_wdt_keepalive();
373 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
374 return 0;
375 }
376
377 case WDIOC_SETTIMEOUT: {
378 int new_timeout;
379 unsigned long flags;
380 int ret = 0;
381
382 if (get_user(new_timeout, p))
383 return -EFAULT;
384
385 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
386 ret = ubi32_wdt_set_timeout(new_timeout);
387 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
388 return ret;
389
390 }
391
392 case WDIOC_GETTIMEOUT:
393 return put_user(timeout, p);
394
395 case WDIOC_GETTIMELEFT: {
396 unsigned long flags;
397 int remaining = 0;
398
399 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
400 remaining = ubi32_wdt_remaining();
401 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
402 return put_user(remaining, p);
403 }
404
405 default:
406 return -ENOTTY;
407 }
408 }
409
410 /*
411 * ubi32_wdt_notify_sys()
412 * Notification callback function for system events.
413 *
414 * Turn off the watchdog during a SYS_DOWN or SYS_HALT.
415 */
416 static int ubi32_wdt_notify_sys(struct notifier_block *this,
417 unsigned long code, void *unused)
418 {
419 if (code == SYS_DOWN || code == SYS_HALT) {
420 unsigned long flags;
421
422 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
423 ubi32_wdt_stop();
424 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
425 }
426
427 return NOTIFY_DONE;
428 }
429
430 #ifdef CONFIG_PM
431 static int state_before_suspend;
432
433 /*
434 * ubi32_wdt_suspend()
435 * suspend the watchdog
436 *
437 * Remember if the watchdog was running and stop it.
438 */
439 static int ubi32_wdt_suspend(struct platform_device *pdev, pm_message_t state)
440 {
441 unsigned long flags;
442 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
443 state_before_suspend = ubi32_wdt_running();
444 ubi32_wdt_stop();
445 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
446
447 return 0;
448 }
449
450 /*
451 * ubi32_wdt_resume()
452 * Resume the watchdog
453 *
454 * If the watchdog was running, turn it back on.
455 */
456 static int ubi32_wdt_resume(struct platform_device *pdev)
457 {
458 if (state_before_suspend) {
459 unsigned long flags;
460 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
461 ubi32_wdt_set_timeout(timeout);
462 ubi32_wdt_start();
463 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
464 }
465
466 return 0;
467 }
468 #else
469 # define ubi32_wdt_suspend NULL
470 # define ubi32_wdt_resume NULL
471 #endif
472
473 static const struct file_operations ubi32_wdt_fops = {
474 .owner = THIS_MODULE,
475 .llseek = no_llseek,
476 .write = ubi32_wdt_write,
477 .unlocked_ioctl = ubi32_wdt_ioctl,
478 .open = ubi32_wdt_open,
479 .release = ubi32_wdt_release,
480 };
481
482 static struct miscdevice ubi32_wdt_miscdev = {
483 .minor = WATCHDOG_MINOR,
484 .name = "watchdog",
485 .fops = &ubi32_wdt_fops,
486 };
487
488 static struct watchdog_info ubi32_wdt_info = {
489 .identity = "Ubicom32 Watchdog",
490 .options = WDIOF_SETTIMEOUT |
491 WDIOF_KEEPALIVEPING |
492 WDIOF_MAGICCLOSE,
493 };
494
495 static struct notifier_block ubi32_wdt_notifier = {
496 .notifier_call = ubi32_wdt_notify_sys,
497 };
498
499 /*
500 * ubi32_wdt_probe()
501 * Probe/register the watchdog module
502 *
503 * Registers the misc device and notifier handler. Actual device
504 * initialization is handled by ubi32_wdt_open().
505 */
506 static int __devinit ubi32_wdt_probe(struct platform_device *pdev)
507 {
508 int ret;
509
510 ret = register_reboot_notifier(&ubi32_wdt_notifier);
511 if (ret) {
512 printk(KERN_ERR PFX
513 "cannot register reboot notifier (err=%d)\n", ret);
514 return ret;
515 }
516
517 ret = misc_register(&ubi32_wdt_miscdev);
518 if (ret) {
519 printk(KERN_ERR PFX
520 "cannot register miscdev on minor=%d (err=%d)\n",
521 WATCHDOG_MINOR, ret);
522 unregister_reboot_notifier(&ubi32_wdt_notifier);
523 return ret;
524 }
525
526 printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n",
527 timeout, nowayout);
528
529 return 0;
530 }
531
532 /*
533 * ubi32_wdt_remove()
534 * Uninstall the module
535 *
536 * Unregisters the misc device and notifier handler. Actual device
537 * deinitialization is handled by ubi32_wdt_close().
538 */
539 static int __devexit ubi32_wdt_remove(struct platform_device *pdev)
540 {
541 misc_deregister(&ubi32_wdt_miscdev);
542 unregister_reboot_notifier(&ubi32_wdt_notifier);
543 return 0;
544 }
545
546 static struct platform_device *ubi32_wdt_device;
547
548 static struct platform_driver ubi32_wdt_driver = {
549 .probe = ubi32_wdt_probe,
550 .remove = __devexit_p(ubi32_wdt_remove),
551 .suspend = ubi32_wdt_suspend,
552 .resume = ubi32_wdt_resume,
553 .driver = {
554 .name = WATCHDOG_NAME,
555 .owner = THIS_MODULE,
556 },
557 };
558
559 /*
560 * ubi32_wdt_init()
561 * Initialize the watchdog.
562 *
563 * Checks the module params and registers the platform device & driver.
564 * Real work is in the platform probe function.
565 */
566 static int __init ubi32_wdt_init(void)
567 {
568 unsigned long flags;
569 int ret;
570
571 /*
572 * Check that the timeout value is within range
573 */
574 spin_lock_irqsave(&ubi32_wdt_spinlock, flags);
575 ret = ubi32_wdt_set_timeout(timeout);
576 spin_unlock_irqrestore(&ubi32_wdt_spinlock, flags);
577 if (ret) {
578 return ret;
579 }
580
581 /*
582 * Since this is an on-chip device and needs no board-specific
583 * resources, we'll handle all the platform device stuff here.
584 */
585 ret = platform_driver_register(&ubi32_wdt_driver);
586 if (ret) {
587 printk(KERN_ERR PFX "unable to register driver\n");
588 return ret;
589 }
590
591 ubi32_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0);
592 if (IS_ERR(ubi32_wdt_device)) {
593 printk(KERN_ERR PFX "unable to register device\n");
594 platform_driver_unregister(&ubi32_wdt_driver);
595 return PTR_ERR(ubi32_wdt_device);
596 }
597
598 return 0;
599 }
600
601 /*
602 * ubi32_wdt_exit()
603 * Deinitialize module
604 *
605 * Back out the platform device & driver steps. Real work is in the
606 * platform remove function.
607 */
608 static void __exit ubi32_wdt_exit(void)
609 {
610 platform_device_unregister(ubi32_wdt_device);
611 platform_driver_unregister(&ubi32_wdt_driver);
612 }
613
614 module_init(ubi32_wdt_init);
615 module_exit(ubi32_wdt_exit);
616
617 MODULE_AUTHOR("Sol Kavy<sol@ubicom.com>");
618 MODULE_DESCRIPTION("Ubicom32 Watchdog Device Driver");
619 MODULE_LICENSE("GPL");
620 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
621
622 module_param(timeout, uint, 0);
623 MODULE_PARM_DESC(timeout,
624 "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default="
625 __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
626
627 module_param(nowayout, int, 0);
628 MODULE_PARM_DESC(nowayout,
629 "Watchdog cannot be stopped once started (default="
630 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
This page took 0.0629 seconds and 5 git commands to generate.