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 56static 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 66static unsigned int timeout = WATCHDOG_TIMEOUT; 67static int nowayout = WATCHDOG_NOWAYOUT; 68static struct watchdog_info ubi32_wdt_info; 69static unsigned long open_check; 70static 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 */ 86static 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 */ 107static 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 */ 122static 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 */ 135static 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 */ 151static 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 */ 168static 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 */ 192static 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 */ 213static 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 */ 248static 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 291ping: 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 */ 305static 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 */ 416static 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 431static 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 */ 439static 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 */ 456static 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 473static 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 482static struct miscdevice ubi32_wdt_miscdev = { 483 .minor = WATCHDOG_MINOR, 484 .name = "watchdog", 485 .fops = &ubi32_wdt_fops, 486}; 487 488static struct watchdog_info ubi32_wdt_info = { 489 .identity = "Ubicom32 Watchdog", 490 .options = WDIOF_SETTIMEOUT | 491 WDIOF_KEEPALIVEPING | 492 WDIOF_MAGICCLOSE, 493}; 494 495static 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 */ 506static 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 */ 539static 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 546static struct platform_device *ubi32_wdt_device; 547 548static 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 */ 566static 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 */ 608static void __exit ubi32_wdt_exit(void) 609{ 610 platform_device_unregister(ubi32_wdt_device); 611 platform_driver_unregister(&ubi32_wdt_driver); 612} 613 614module_init(ubi32_wdt_init); 615module_exit(ubi32_wdt_exit); 616 617MODULE_AUTHOR("Sol Kavy<sol@ubicom.com>"); 618MODULE_DESCRIPTION("Ubicom32 Watchdog Device Driver"); 619MODULE_LICENSE("GPL"); 620MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 621 622module_param(timeout, uint, 0); 623MODULE_PARM_DESC(timeout, 624 "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" 625 __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 626 627module_param(nowayout, int, 0); 628MODULE_PARM_DESC(nowayout, 629 "Watchdog cannot be stopped once started (default=" 630 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 631