[ubicom32]: move new files out from platform support patch
[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) ")");