1 /* 2 * drivers/watchdog/shwdt.c 3 * 4 * Watchdog driver for integrated watchdog in the SuperH processors. 5 * 6 * Copyright (C) 2001 - 2010 Paul Mundt <lethal@linux-sh.org> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com> 14 * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT 15 * 16 * 19-Apr-2002 Rob Radez <rob@osinvestor.com> 17 * Added expect close support, made emulated timeout runtime changeable 18 * general cleanups, add some ioctls 19 */ 20 21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22 23 #include <linux/module.h> 24 #include <linux/moduleparam.h> 25 #include <linux/platform_device.h> 26 #include <linux/init.h> 27 #include <linux/types.h> 28 #include <linux/miscdevice.h> 29 #include <linux/watchdog.h> 30 #include <linux/reboot.h> 31 #include <linux/notifier.h> 32 #include <linux/ioport.h> 33 #include <linux/fs.h> 34 #include <linux/mm.h> 35 #include <linux/slab.h> 36 #include <linux/io.h> 37 #include <linux/uaccess.h> 38 #include <asm/watchdog.h> 39 40 #define DRV_NAME "sh-wdt" 41 42 /* 43 * Default clock division ratio is 5.25 msecs. For an additional table of 44 * values, consult the asm-sh/watchdog.h. Overload this at module load 45 * time. 46 * 47 * In order for this to work reliably we need to have HZ set to 1000 or 48 * something quite higher than 100 (or we need a proper high-res timer 49 * implementation that will deal with this properly), otherwise the 10ms 50 * resolution of a jiffy is enough to trigger the overflow. For things like 51 * the SH-4 and SH-5, this isn't necessarily that big of a problem, though 52 * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely 53 * necssary. 54 * 55 * As a result of this timing problem, the only modes that are particularly 56 * feasible are the 4096 and the 2048 divisors, which yield 5.25 and 2.62ms 57 * overflow periods respectively. 58 * 59 * Also, since we can't really expect userspace to be responsive enough 60 * before the overflow happens, we maintain two separate timers .. One in 61 * the kernel for clearing out WOVF every 2ms or so (again, this depends on 62 * HZ == 1000), and another for monitoring userspace writes to the WDT device. 63 * 64 * As such, we currently use a configurable heartbeat interval which defaults 65 * to 30s. In this case, the userspace daemon is only responsible for periodic 66 * writes to the device before the next heartbeat is scheduled. If the daemon 67 * misses its deadline, the kernel timer will allow the WDT to overflow. 68 */ 69 static int clock_division_ratio = WTCSR_CKS_4096; 70 #define next_ping_period(cks) (jiffies + msecs_to_jiffies(cks - 4)) 71 72 static const struct watchdog_info sh_wdt_info; 73 static struct platform_device *sh_wdt_dev; 74 static DEFINE_SPINLOCK(shwdt_lock); 75 76 #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 77 static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 78 static bool nowayout = WATCHDOG_NOWAYOUT; 79 static unsigned long next_heartbeat; 80 81 struct sh_wdt { 82 void __iomem *base; 83 struct device *dev; 84 85 struct timer_list timer; 86 87 unsigned long enabled; 88 char expect_close; 89 }; 90 91 static void sh_wdt_start(struct sh_wdt *wdt) 92 { 93 unsigned long flags; 94 u8 csr; 95 96 spin_lock_irqsave(&shwdt_lock, flags); 97 98 next_heartbeat = jiffies + (heartbeat * HZ); 99 mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); 100 101 csr = sh_wdt_read_csr(); 102 csr |= WTCSR_WT | clock_division_ratio; 103 sh_wdt_write_csr(csr); 104 105 sh_wdt_write_cnt(0); 106 107 /* 108 * These processors have a bit of an inconsistent initialization 109 * process.. starting with SH-3, RSTS was moved to WTCSR, and the 110 * RSTCSR register was removed. 111 * 112 * On the SH-2 however, in addition with bits being in different 113 * locations, we must deal with RSTCSR outright.. 114 */ 115 csr = sh_wdt_read_csr(); 116 csr |= WTCSR_TME; 117 csr &= ~WTCSR_RSTS; 118 sh_wdt_write_csr(csr); 119 120 #ifdef CONFIG_CPU_SH2 121 csr = sh_wdt_read_rstcsr(); 122 csr &= ~RSTCSR_RSTS; 123 sh_wdt_write_rstcsr(csr); 124 #endif 125 spin_unlock_irqrestore(&shwdt_lock, flags); 126 } 127 128 static void sh_wdt_stop(struct sh_wdt *wdt) 129 { 130 unsigned long flags; 131 u8 csr; 132 133 spin_lock_irqsave(&shwdt_lock, flags); 134 135 del_timer(&wdt->timer); 136 137 csr = sh_wdt_read_csr(); 138 csr &= ~WTCSR_TME; 139 sh_wdt_write_csr(csr); 140 141 spin_unlock_irqrestore(&shwdt_lock, flags); 142 } 143 144 static inline void sh_wdt_keepalive(struct sh_wdt *wdt) 145 { 146 unsigned long flags; 147 148 spin_lock_irqsave(&shwdt_lock, flags); 149 next_heartbeat = jiffies + (heartbeat * HZ); 150 spin_unlock_irqrestore(&shwdt_lock, flags); 151 } 152 153 static int sh_wdt_set_heartbeat(int t) 154 { 155 unsigned long flags; 156 157 if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */ 158 return -EINVAL; 159 160 spin_lock_irqsave(&shwdt_lock, flags); 161 heartbeat = t; 162 spin_unlock_irqrestore(&shwdt_lock, flags); 163 return 0; 164 } 165 166 static void sh_wdt_ping(unsigned long data) 167 { 168 struct sh_wdt *wdt = (struct sh_wdt *)data; 169 unsigned long flags; 170 171 spin_lock_irqsave(&shwdt_lock, flags); 172 if (time_before(jiffies, next_heartbeat)) { 173 u8 csr; 174 175 csr = sh_wdt_read_csr(); 176 csr &= ~WTCSR_IOVF; 177 sh_wdt_write_csr(csr); 178 179 sh_wdt_write_cnt(0); 180 181 mod_timer(&wdt->timer, next_ping_period(clock_division_ratio)); 182 } else 183 dev_warn(wdt->dev, "Heartbeat lost! Will not ping " 184 "the watchdog\n"); 185 spin_unlock_irqrestore(&shwdt_lock, flags); 186 } 187 188 static int sh_wdt_open(struct inode *inode, struct file *file) 189 { 190 struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev); 191 192 if (test_and_set_bit(0, &wdt->enabled)) 193 return -EBUSY; 194 if (nowayout) 195 __module_get(THIS_MODULE); 196 197 file->private_data = wdt; 198 199 sh_wdt_start(wdt); 200 201 return nonseekable_open(inode, file); 202 } 203 204 static int sh_wdt_close(struct inode *inode, struct file *file) 205 { 206 struct sh_wdt *wdt = file->private_data; 207 208 if (wdt->expect_close == 42) { 209 sh_wdt_stop(wdt); 210 } else { 211 dev_crit(wdt->dev, "Unexpected close, not " 212 "stopping watchdog!\n"); 213 sh_wdt_keepalive(wdt); 214 } 215 216 clear_bit(0, &wdt->enabled); 217 wdt->expect_close = 0; 218 219 return 0; 220 } 221 222 static ssize_t sh_wdt_write(struct file *file, const char *buf, 223 size_t count, loff_t *ppos) 224 { 225 struct sh_wdt *wdt = file->private_data; 226 227 if (count) { 228 if (!nowayout) { 229 size_t i; 230 231 wdt->expect_close = 0; 232 233 for (i = 0; i != count; i++) { 234 char c; 235 if (get_user(c, buf + i)) 236 return -EFAULT; 237 if (c == 'V') 238 wdt->expect_close = 42; 239 } 240 } 241 sh_wdt_keepalive(wdt); 242 } 243 244 return count; 245 } 246 247 static long sh_wdt_ioctl(struct file *file, unsigned int cmd, 248 unsigned long arg) 249 { 250 struct sh_wdt *wdt = file->private_data; 251 int new_heartbeat; 252 int options, retval = -EINVAL; 253 254 switch (cmd) { 255 case WDIOC_GETSUPPORT: 256 return copy_to_user((struct watchdog_info *)arg, 257 &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0; 258 case WDIOC_GETSTATUS: 259 case WDIOC_GETBOOTSTATUS: 260 return put_user(0, (int *)arg); 261 case WDIOC_SETOPTIONS: 262 if (get_user(options, (int *)arg)) 263 return -EFAULT; 264 265 if (options & WDIOS_DISABLECARD) { 266 sh_wdt_stop(wdt); 267 retval = 0; 268 } 269 270 if (options & WDIOS_ENABLECARD) { 271 sh_wdt_start(wdt); 272 retval = 0; 273 } 274 275 return retval; 276 case WDIOC_KEEPALIVE: 277 sh_wdt_keepalive(wdt); 278 return 0; 279 case WDIOC_SETTIMEOUT: 280 if (get_user(new_heartbeat, (int *)arg)) 281 return -EFAULT; 282 283 if (sh_wdt_set_heartbeat(new_heartbeat)) 284 return -EINVAL; 285 286 sh_wdt_keepalive(wdt); 287 /* Fall */ 288 case WDIOC_GETTIMEOUT: 289 return put_user(heartbeat, (int *)arg); 290 default: 291 return -ENOTTY; 292 } 293 return 0; 294 } 295 296 static int sh_wdt_notify_sys(struct notifier_block *this, 297 unsigned long code, void *unused) 298 { 299 struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev); 300 301 if (code == SYS_DOWN || code == SYS_HALT) 302 sh_wdt_stop(wdt); 303 304 return NOTIFY_DONE; 305 } 306 307 static const struct file_operations sh_wdt_fops = { 308 .owner = THIS_MODULE, 309 .llseek = no_llseek, 310 .write = sh_wdt_write, 311 .unlocked_ioctl = sh_wdt_ioctl, 312 .open = sh_wdt_open, 313 .release = sh_wdt_close, 314 }; 315 316 static const struct watchdog_info sh_wdt_info = { 317 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | 318 WDIOF_MAGICCLOSE, 319 .firmware_version = 1, 320 .identity = "SH WDT", 321 }; 322 323 static struct notifier_block sh_wdt_notifier = { 324 .notifier_call = sh_wdt_notify_sys, 325 }; 326 327 static struct miscdevice sh_wdt_miscdev = { 328 .minor = WATCHDOG_MINOR, 329 .name = "watchdog", 330 .fops = &sh_wdt_fops, 331 }; 332 333 static int __devinit sh_wdt_probe(struct platform_device *pdev) 334 { 335 struct sh_wdt *wdt; 336 struct resource *res; 337 int rc; 338 339 /* 340 * As this driver only covers the global watchdog case, reject 341 * any attempts to register per-CPU watchdogs. 342 */ 343 if (pdev->id != -1) 344 return -EINVAL; 345 346 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 347 if (unlikely(!res)) 348 return -EINVAL; 349 350 if (!devm_request_mem_region(&pdev->dev, res->start, 351 resource_size(res), DRV_NAME)) 352 return -EBUSY; 353 354 wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL); 355 if (unlikely(!wdt)) { 356 rc = -ENOMEM; 357 goto out_release; 358 } 359 360 wdt->dev = &pdev->dev; 361 362 wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 363 if (unlikely(!wdt->base)) { 364 rc = -ENXIO; 365 goto out_err; 366 } 367 368 rc = register_reboot_notifier(&sh_wdt_notifier); 369 if (unlikely(rc)) { 370 dev_err(&pdev->dev, 371 "Can't register reboot notifier (err=%d)\n", rc); 372 goto out_unmap; 373 } 374 375 sh_wdt_miscdev.parent = wdt->dev; 376 377 rc = misc_register(&sh_wdt_miscdev); 378 if (unlikely(rc)) { 379 dev_err(&pdev->dev, 380 "Can't register miscdev on minor=%d (err=%d)\n", 381 sh_wdt_miscdev.minor, rc); 382 goto out_unreg; 383 } 384 385 init_timer(&wdt->timer); 386 wdt->timer.function = sh_wdt_ping; 387 wdt->timer.data = (unsigned long)wdt; 388 wdt->timer.expires = next_ping_period(clock_division_ratio); 389 390 platform_set_drvdata(pdev, wdt); 391 sh_wdt_dev = pdev; 392 393 dev_info(&pdev->dev, "initialized.\n"); 394 395 return 0; 396 397 out_unreg: 398 unregister_reboot_notifier(&sh_wdt_notifier); 399 out_unmap: 400 devm_iounmap(&pdev->dev, wdt->base); 401 out_err: 402 devm_kfree(&pdev->dev, wdt); 403 out_release: 404 devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); 405 406 return rc; 407 } 408 409 static int __devexit sh_wdt_remove(struct platform_device *pdev) 410 { 411 struct sh_wdt *wdt = platform_get_drvdata(pdev); 412 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 413 414 platform_set_drvdata(pdev, NULL); 415 416 misc_deregister(&sh_wdt_miscdev); 417 418 sh_wdt_dev = NULL; 419 420 unregister_reboot_notifier(&sh_wdt_notifier); 421 devm_release_mem_region(&pdev->dev, res->start, resource_size(res)); 422 devm_iounmap(&pdev->dev, wdt->base); 423 devm_kfree(&pdev->dev, wdt); 424 425 return 0; 426 } 427 428 static struct platform_driver sh_wdt_driver = { 429 .driver = { 430 .name = DRV_NAME, 431 .owner = THIS_MODULE, 432 }, 433 434 .probe = sh_wdt_probe, 435 .remove = __devexit_p(sh_wdt_remove), 436 }; 437 438 static int __init sh_wdt_init(void) 439 { 440 int rc; 441 442 if (unlikely(clock_division_ratio < 0x5 || 443 clock_division_ratio > 0x7)) { 444 clock_division_ratio = WTCSR_CKS_4096; 445 446 pr_info("divisor must be 0x5<=x<=0x7, using %d\n", 447 clock_division_ratio); 448 } 449 450 rc = sh_wdt_set_heartbeat(heartbeat); 451 if (unlikely(rc)) { 452 heartbeat = WATCHDOG_HEARTBEAT; 453 454 pr_info("heartbeat value must be 1<=x<=3600, using %d\n", 455 heartbeat); 456 } 457 458 pr_info("configured with heartbeat=%d sec (nowayout=%d)\n", 459 heartbeat, nowayout); 460 461 return platform_driver_register(&sh_wdt_driver); 462 } 463 464 static void __exit sh_wdt_exit(void) 465 { 466 platform_driver_unregister(&sh_wdt_driver); 467 } 468 module_init(sh_wdt_init); 469 module_exit(sh_wdt_exit); 470 471 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); 472 MODULE_DESCRIPTION("SuperH watchdog driver"); 473 MODULE_LICENSE("GPL"); 474 MODULE_ALIAS("platform:" DRV_NAME); 475 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 476 477 module_param(clock_division_ratio, int, 0); 478 MODULE_PARM_DESC(clock_division_ratio, 479 "Clock division ratio. Valid ranges are from 0x5 (1.31ms) " 480 "to 0x7 (5.25ms). (default=" __MODULE_STRING(WTCSR_CKS_4096) ")"); 481 482 module_param(heartbeat, int, 0); 483 MODULE_PARM_DESC(heartbeat, 484 "Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default=" 485 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 486 487 module_param(nowayout, bool, 0); 488 MODULE_PARM_DESC(nowayout, 489 "Watchdog cannot be stopped once started (default=" 490 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 491