2 * drivers/watchdog/ubi32_wdt.c
3 * Ubicom32 Watchdog Driver
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.
11 * This file is part of the Ubicom32 Linux Kernel Port.
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.
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.
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/>.
27 * Ubicom32 implementation derived from (with many thanks):
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>
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>
47 #define WATCHDOG_NAME "ubi32-wdt"
48 #define PFX WATCHDOG_NAME ": "
50 #define OSC1_FREQ 12000000
51 #define WATCHDOG_SEC_TO_CYC(x) (OSC1_FREQ * (x))
52 #define WATCHDOG_MAX_SEC (0xffffffff / OSC1_FREQ)
54 #define MIN_PROCESSOR_ADDRESS 0x03000000
56 static DEFINE_SPINLOCK(ubi32_wdt_spinlock
);
58 #define WATCHDOG_TIMEOUT 20
60 #if defined(CONFIG_WATCHDOG_NOWAYOUT)
61 #define WATCHDOG_NOWAYOUT 1
63 #define WATCHDOG_NOWAYOUT 0
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
;
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()
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));
83 * ubi32_wdt_remaining()
84 * Return the approximate number of seconds remaining
86 static int ubi32_wdt_remaining(void)
91 UBI32_WDT_LOCK_CHECK();
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
;
102 * ubi32_wdt_keepalive()
103 * Keep the Userspace Watchdog Alive
105 * The Userspace watchdog got a KeepAlive: schedule the next timeout.
107 static int ubi32_wdt_keepalive(void)
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);
120 * Stop the on-chip Watchdog
122 static int ubi32_wdt_stop(void)
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);
133 * Start the on-chip Watchdog
135 static int ubi32_wdt_start(void)
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);
148 * ubi32_wdt_running()
149 * Return true if the watchdog is configured
151 static int ubi32_wdt_running(void)
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);
163 * ubi32_wdt_set_timeout()
164 * Set the Userspace Watchdog timeout
166 * - @t: new timeout value (in seconds)
168 static int ubi32_wdt_set_timeout(unsigned long t
)
170 UBI32_WDT_LOCK_CHECK();
172 if (t
> WATCHDOG_MAX_SEC
) {
173 printk(KERN_WARNING PFX
"request to large: %ld [1-%d] sec)\n", t
, WATCHDOG_MAX_SEC
);
178 * If we are running, then reset the time value so
179 * that the new value has an immediate effect.
182 if (ubi32_wdt_running()) {
183 ubi32_wdt_keepalive();
192 static int ubi32_wdt_open(struct inode
*inode
, struct file
*file
)
196 if (test_and_set_bit(0, &open_check
))
200 __module_get(THIS_MODULE
);
202 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
204 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
206 return nonseekable_open(inode
, file
);
213 static int ubi32_wdt_release(struct inode
*inode
, struct file
*file
)
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
223 if (expect_close
!= 42) {
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
);
230 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
232 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
236 clear_bit(0, &open_check
);
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.
248 static ssize_t
ubi32_wdt_write(struct file
*file
, const char __user
*data
,
249 size_t len
, loff_t
*ppos
)
255 * Every write resets the expect_close. The last write
256 * must be a V to allow shutdown on close.
261 * Empty writes still ping.
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
277 * See if the program wrote a 'V' and if so disable
278 * the watchdog on release.
280 for (i
= 0; i
< len
; i
++) {
282 if (get_user(c
, data
+ i
)) {
292 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
293 ubi32_wdt_keepalive();
294 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
300 * Query the watchdog device.
302 * Query basic information from the device or ping it, as outlined by the
305 static long ubi32_wdt_ioctl(struct file
*file
,
306 unsigned int cmd
, unsigned long arg
)
308 void __user
*argp
= (void __user
*)arg
;
309 int __user
*p
= argp
;
312 case WDIOC_GETSUPPORT
:
313 if (copy_to_user(argp
, &ubi32_wdt_info
, sizeof(ubi32_wdt_info
))) {
318 case WDIOC_GETSTATUS
: {
322 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
323 running
= ubi32_wdt_running();
324 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
328 case WDIOC_GETBOOTSTATUS
:
329 return ubicom32_get_reset_reason();
331 case WDIOC_SETOPTIONS
: {
333 int options
, ret
= -EINVAL
;
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.
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.
345 * TODO: Examine this code for future chips.
346 * TODO: Report the sample code defect.
348 if ((int)p
< MIN_PROCESSOR_ADDRESS
) {
351 if (get_user(options
, p
))
355 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
356 if (options
& WDIOS_DISABLECARD
) {
360 if (options
& WDIOS_ENABLECARD
) {
364 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
368 case WDIOC_KEEPALIVE
: {
371 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
372 ubi32_wdt_keepalive();
373 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
377 case WDIOC_SETTIMEOUT
: {
382 if (get_user(new_timeout
, p
))
385 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
386 ret
= ubi32_wdt_set_timeout(new_timeout
);
387 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
392 case WDIOC_GETTIMEOUT
:
393 return put_user(timeout
, p
);
395 case WDIOC_GETTIMELEFT
: {
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
);
411 * ubi32_wdt_notify_sys()
412 * Notification callback function for system events.
414 * Turn off the watchdog during a SYS_DOWN or SYS_HALT.
416 static int ubi32_wdt_notify_sys(struct notifier_block
*this,
417 unsigned long code
, void *unused
)
419 if (code
== SYS_DOWN
|| code
== SYS_HALT
) {
422 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
424 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
431 static int state_before_suspend
;
434 * ubi32_wdt_suspend()
435 * suspend the watchdog
437 * Remember if the watchdog was running and stop it.
439 static int ubi32_wdt_suspend(struct platform_device
*pdev
, pm_message_t state
)
442 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
443 state_before_suspend
= ubi32_wdt_running();
445 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
452 * Resume the watchdog
454 * If the watchdog was running, turn it back on.
456 static int ubi32_wdt_resume(struct platform_device
*pdev
)
458 if (state_before_suspend
) {
460 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
461 ubi32_wdt_set_timeout(timeout
);
463 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
469 # define ubi32_wdt_suspend NULL
470 # define ubi32_wdt_resume NULL
473 static const struct file_operations ubi32_wdt_fops
= {
474 .owner
= THIS_MODULE
,
476 .write
= ubi32_wdt_write
,
477 .unlocked_ioctl
= ubi32_wdt_ioctl
,
478 .open
= ubi32_wdt_open
,
479 .release
= ubi32_wdt_release
,
482 static struct miscdevice ubi32_wdt_miscdev
= {
483 .minor
= WATCHDOG_MINOR
,
485 .fops
= &ubi32_wdt_fops
,
488 static struct watchdog_info ubi32_wdt_info
= {
489 .identity
= "Ubicom32 Watchdog",
490 .options
= WDIOF_SETTIMEOUT
|
491 WDIOF_KEEPALIVEPING
|
495 static struct notifier_block ubi32_wdt_notifier
= {
496 .notifier_call
= ubi32_wdt_notify_sys
,
501 * Probe/register the watchdog module
503 * Registers the misc device and notifier handler. Actual device
504 * initialization is handled by ubi32_wdt_open().
506 static int __devinit
ubi32_wdt_probe(struct platform_device
*pdev
)
510 ret
= register_reboot_notifier(&ubi32_wdt_notifier
);
513 "cannot register reboot notifier (err=%d)\n", ret
);
517 ret
= misc_register(&ubi32_wdt_miscdev
);
520 "cannot register miscdev on minor=%d (err=%d)\n",
521 WATCHDOG_MINOR
, ret
);
522 unregister_reboot_notifier(&ubi32_wdt_notifier
);
526 printk(KERN_INFO PFX
"initialized: timeout=%d sec (nowayout=%d)\n",
534 * Uninstall the module
536 * Unregisters the misc device and notifier handler. Actual device
537 * deinitialization is handled by ubi32_wdt_close().
539 static int __devexit
ubi32_wdt_remove(struct platform_device
*pdev
)
541 misc_deregister(&ubi32_wdt_miscdev
);
542 unregister_reboot_notifier(&ubi32_wdt_notifier
);
546 static struct platform_device
*ubi32_wdt_device
;
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
,
554 .name
= WATCHDOG_NAME
,
555 .owner
= THIS_MODULE
,
561 * Initialize the watchdog.
563 * Checks the module params and registers the platform device & driver.
564 * Real work is in the platform probe function.
566 static int __init
ubi32_wdt_init(void)
572 * Check that the timeout value is within range
574 spin_lock_irqsave(&ubi32_wdt_spinlock
, flags
);
575 ret
= ubi32_wdt_set_timeout(timeout
);
576 spin_unlock_irqrestore(&ubi32_wdt_spinlock
, flags
);
582 * Since this is an on-chip device and needs no board-specific
583 * resources, we'll handle all the platform device stuff here.
585 ret
= platform_driver_register(&ubi32_wdt_driver
);
587 printk(KERN_ERR PFX
"unable to register driver\n");
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
);
603 * Deinitialize module
605 * Back out the platform device & driver steps. Real work is in the
606 * platform remove function.
608 static void __exit
ubi32_wdt_exit(void)
610 platform_device_unregister(ubi32_wdt_device
);
611 platform_driver_unregister(&ubi32_wdt_driver
);
614 module_init(ubi32_wdt_init
);
615 module_exit(ubi32_wdt_exit
);
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
);
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
) ")");
627 module_param(nowayout
, int, 0);
628 MODULE_PARM_DESC(nowayout
,
629 "Watchdog cannot be stopped once started (default="
630 __MODULE_STRING(WATCHDOG_NOWAYOUT
) ")");