1/* 2 * coh901327_wdt.c 3 * 4 * Copyright (C) 2008-2009 ST-Ericsson AB 5 * License terms: GNU General Public License (GPL) version 2 6 * Watchdog driver for the ST-Ericsson AB COH 901 327 IP core 7 * Author: Linus Walleij <linus.walleij@stericsson.com> 8 */ 9#include <linux/module.h> 10#include <linux/types.h> 11#include <linux/fs.h> 12#include <linux/miscdevice.h> 13#include <linux/watchdog.h> 14#include <linux/interrupt.h> 15#include <linux/pm.h> 16#include <linux/platform_device.h> 17#include <linux/io.h> 18#include <linux/bitops.h> 19#include <linux/uaccess.h> 20#include <linux/clk.h> 21#include <linux/delay.h> 22 23#define DRV_NAME "WDOG COH 901 327" 24 25/* 26 * COH 901 327 register definitions 27 */ 28 29/* WDOG_FEED Register 32bit (-/W) */ 30#define U300_WDOG_FR 0x00 31#define U300_WDOG_FR_FEED_RESTART_TIMER 0xFEEDU 32/* WDOG_TIMEOUT Register 32bit (R/W) */ 33#define U300_WDOG_TR 0x04 34#define U300_WDOG_TR_TIMEOUT_MASK 0x7FFFU 35/* WDOG_DISABLE1 Register 32bit (-/W) */ 36#define U300_WDOG_D1R 0x08 37#define U300_WDOG_D1R_DISABLE1_DISABLE_TIMER 0x2BADU 38/* WDOG_DISABLE2 Register 32bit (R/W) */ 39#define U300_WDOG_D2R 0x0C 40#define U300_WDOG_D2R_DISABLE2_DISABLE_TIMER 0xCAFEU 41#define U300_WDOG_D2R_DISABLE_STATUS_DISABLED 0xDABEU 42#define U300_WDOG_D2R_DISABLE_STATUS_ENABLED 0x0000U 43/* WDOG_STATUS Register 32bit (R/W) */ 44#define U300_WDOG_SR 0x10 45#define U300_WDOG_SR_STATUS_TIMED_OUT 0xCFE8U 46#define U300_WDOG_SR_STATUS_NORMAL 0x0000U 47#define U300_WDOG_SR_RESET_STATUS_RESET 0xE8B4U 48/* WDOG_COUNT Register 32bit (R/-) */ 49#define U300_WDOG_CR 0x14 50#define U300_WDOG_CR_VALID_IND 0x8000U 51#define U300_WDOG_CR_VALID_STABLE 0x0000U 52#define U300_WDOG_CR_COUNT_VALUE_MASK 0x7FFFU 53/* WDOG_JTAGOVR Register 32bit (R/W) */ 54#define U300_WDOG_JOR 0x18 55#define U300_WDOG_JOR_JTAG_MODE_IND 0x0002U 56#define U300_WDOG_JOR_JTAG_WATCHDOG_ENABLE 0x0001U 57/* WDOG_RESTART Register 32bit (-/W) */ 58#define U300_WDOG_RR 0x1C 59#define U300_WDOG_RR_RESTART_VALUE_RESUME 0xACEDU 60/* WDOG_IRQ_EVENT Register 32bit (R/W) */ 61#define U300_WDOG_IER 0x20 62#define U300_WDOG_IER_WILL_BARK_IRQ_EVENT_IND 0x0001U 63#define U300_WDOG_IER_WILL_BARK_IRQ_ACK_ENABLE 0x0001U 64/* WDOG_IRQ_MASK Register 32bit (R/W) */ 65#define U300_WDOG_IMR 0x24 66#define U300_WDOG_IMR_WILL_BARK_IRQ_ENABLE 0x0001U 67/* WDOG_IRQ_FORCE Register 32bit (R/W) */ 68#define U300_WDOG_IFR 0x28 69#define U300_WDOG_IFR_WILL_BARK_IRQ_FORCE_ENABLE 0x0001U 70 71/* Default timeout in seconds = 1 minute */ 72static int margin = 60; 73static resource_size_t phybase; 74static resource_size_t physize; 75static int irq; 76static void __iomem *virtbase; 77static unsigned long coh901327_users; 78static unsigned long boot_status; 79static struct device *parent; 80 81/* 82 * The watchdog block is of course always clocked, the 83 * clk_enable()/clk_disable() calls are mainly for performing reference 84 * counting higher up in the clock hierarchy. 85 */ 86static struct clk *clk; 87 88/* 89 * Enabling and disabling functions. 90 */ 91static void coh901327_enable(u16 timeout) 92{ 93 u16 val; 94 unsigned long freq; 95 unsigned long delay_ns; 96 97 clk_enable(clk); 98 /* Restart timer if it is disabled */ 99 val = readw(virtbase + U300_WDOG_D2R); 100 if (val == U300_WDOG_D2R_DISABLE_STATUS_DISABLED) 101 writew(U300_WDOG_RR_RESTART_VALUE_RESUME, 102 virtbase + U300_WDOG_RR); 103 /* Acknowledge any pending interrupt so it doesn't just fire off */ 104 writew(U300_WDOG_IER_WILL_BARK_IRQ_ACK_ENABLE, 105 virtbase + U300_WDOG_IER); 106 /* 107 * The interrupt is cleared in the 32 kHz clock domain. 108 * Wait 3 32 kHz cycles for it to take effect 109 */ 110 freq = clk_get_rate(clk); 111 delay_ns = DIV_ROUND_UP(1000000000, freq); /* Freq to ns and round up */ 112 delay_ns = 3 * delay_ns; /* Wait 3 cycles */ 113 ndelay(delay_ns); 114 /* Enable the watchdog interrupt */ 115 writew(U300_WDOG_IMR_WILL_BARK_IRQ_ENABLE, virtbase + U300_WDOG_IMR); 116 /* Activate the watchdog timer */ 117 writew(timeout, virtbase + U300_WDOG_TR); 118 /* Start the watchdog timer */ 119 writew(U300_WDOG_FR_FEED_RESTART_TIMER, virtbase + U300_WDOG_FR); 120 /* 121 * Extra read so that this change propagate in the watchdog. 122 */ 123 (void) readw(virtbase + U300_WDOG_CR); 124 val = readw(virtbase + U300_WDOG_D2R); 125 clk_disable(clk); 126 if (val != U300_WDOG_D2R_DISABLE_STATUS_ENABLED) 127 dev_err(parent, 128 "%s(): watchdog not enabled! D2R value %04x\n", 129 __func__, val); 130} 131 132static void coh901327_disable(void) 133{ 134 u16 val; 135 136 clk_enable(clk); 137 /* Disable the watchdog interrupt if it is active */ 138 writew(0x0000U, virtbase + U300_WDOG_IMR); 139 /* If the watchdog is currently enabled, attempt to disable it */ 140 val = readw(virtbase + U300_WDOG_D2R); 141 if (val != U300_WDOG_D2R_DISABLE_STATUS_DISABLED) { 142 writew(U300_WDOG_D1R_DISABLE1_DISABLE_TIMER, 143 virtbase + U300_WDOG_D1R); 144 writew(U300_WDOG_D2R_DISABLE2_DISABLE_TIMER, 145 virtbase + U300_WDOG_D2R); 146 /* Write this twice (else problems occur) */ 147 writew(U300_WDOG_D2R_DISABLE2_DISABLE_TIMER, 148 virtbase + U300_WDOG_D2R); 149 } 150 val = readw(virtbase + U300_WDOG_D2R); 151 clk_disable(clk); 152 if (val != U300_WDOG_D2R_DISABLE_STATUS_DISABLED) 153 dev_err(parent, 154 "%s(): watchdog not disabled! D2R value %04x\n", 155 __func__, val); 156} 157 158static void coh901327_start(void) 159{ 160 coh901327_enable(margin * 100); 161} 162 163static void coh901327_keepalive(void) 164{ 165 clk_enable(clk); 166 /* Feed the watchdog */ 167 writew(U300_WDOG_FR_FEED_RESTART_TIMER, 168 virtbase + U300_WDOG_FR); 169 clk_disable(clk); 170} 171 172static int coh901327_settimeout(int time) 173{ 174 /* 175 * Max margin is 327 since the 10ms 176 * timeout register is max 177 * 0x7FFF = 327670ms ~= 327s. 178 */ 179 if (time <= 0 || time > 327) 180 return -EINVAL; 181 182 margin = time; 183 clk_enable(clk); 184 /* Set new timeout value */ 185 writew(margin * 100, virtbase + U300_WDOG_TR); 186 /* Feed the dog */ 187 writew(U300_WDOG_FR_FEED_RESTART_TIMER, 188 virtbase + U300_WDOG_FR); 189 clk_disable(clk); 190 return 0; 191} 192 193/* 194 * This interrupt occurs 10 ms before the watchdog WILL bark. 195 */ 196static irqreturn_t coh901327_interrupt(int irq, void *data) 197{ 198 u16 val; 199 200 /* 201 * Ack IRQ? If this occurs we're FUBAR anyway, so 202 * just acknowledge, disable the interrupt and await the imminent end. 203 * If you at some point need a host of callbacks to be called 204 * when the system is about to watchdog-reset, add them here! 205 * 206 * NOTE: on future versions of this IP-block, it will be possible 207 * to prevent a watchdog reset by feeding the watchdog at this 208 * point. 209 */ 210 clk_enable(clk); 211 val = readw(virtbase + U300_WDOG_IER); 212 if (val == U300_WDOG_IER_WILL_BARK_IRQ_EVENT_IND) 213 writew(U300_WDOG_IER_WILL_BARK_IRQ_ACK_ENABLE, 214 virtbase + U300_WDOG_IER); 215 writew(0x0000U, virtbase + U300_WDOG_IMR); 216 clk_disable(clk); 217 dev_crit(parent, "watchdog is barking!\n"); 218 return IRQ_HANDLED; 219} 220 221/* 222 * Allow only one user (daemon) to open the watchdog 223 */ 224static int coh901327_open(struct inode *inode, struct file *file) 225{ 226 if (test_and_set_bit(1, &coh901327_users)) 227 return -EBUSY; 228 coh901327_start(); 229 return nonseekable_open(inode, file); 230} 231 232static int coh901327_release(struct inode *inode, struct file *file) 233{ 234 clear_bit(1, &coh901327_users); 235 coh901327_disable(); 236 return 0; 237} 238 239static ssize_t coh901327_write(struct file *file, const char __user *data, 240 size_t len, loff_t *ppos) 241{ 242 if (len) 243 coh901327_keepalive(); 244 return len; 245} 246 247static long coh901327_ioctl(struct file *file, unsigned int cmd, 248 unsigned long arg) 249{ 250 int ret = -ENOTTY; 251 u16 val; 252 int time; 253 int new_options; 254 union { 255 struct watchdog_info __user *ident; 256 int __user *i; 257 } uarg; 258 static const struct watchdog_info ident = { 259 .options = WDIOF_CARDRESET | 260 WDIOF_SETTIMEOUT | 261 WDIOF_KEEPALIVEPING, 262 .identity = "COH 901 327 Watchdog", 263 .firmware_version = 1, 264 }; 265 uarg.i = (int __user *)arg; 266 267 switch (cmd) { 268 case WDIOC_GETSUPPORT: 269 ret = copy_to_user(uarg.ident, &ident, 270 sizeof(ident)) ? -EFAULT : 0; 271 break; 272 273 case WDIOC_GETSTATUS: 274 ret = put_user(0, uarg.i); 275 break; 276 277 case WDIOC_GETBOOTSTATUS: 278 ret = put_user(boot_status, uarg.i); 279 break; 280 281 case WDIOC_SETOPTIONS: 282 ret = get_user(new_options, uarg.i); 283 if (ret) 284 break; 285 if (new_options & WDIOS_DISABLECARD) 286 coh901327_disable(); 287 if (new_options & WDIOS_ENABLECARD) 288 coh901327_start(); 289 ret = 0; 290 break; 291 292 case WDIOC_KEEPALIVE: 293 coh901327_keepalive(); 294 ret = 0; 295 break; 296 297 case WDIOC_SETTIMEOUT: 298 ret = get_user(time, uarg.i); 299 if (ret) 300 break; 301 302 ret = coh901327_settimeout(time); 303 if (ret) 304 break; 305 /* Then fall through to return set value */ 306 307 case WDIOC_GETTIMEOUT: 308 ret = put_user(margin, uarg.i); 309 break; 310 311 case WDIOC_GETTIMELEFT: 312 clk_enable(clk); 313 /* Read repeatedly until the value is stable! */ 314 val = readw(virtbase + U300_WDOG_CR); 315 while (val & U300_WDOG_CR_VALID_IND) 316 val = readw(virtbase + U300_WDOG_CR); 317 val &= U300_WDOG_CR_COUNT_VALUE_MASK; 318 clk_disable(clk); 319 if (val != 0) 320 val /= 100; 321 ret = put_user(val, uarg.i); 322 break; 323 } 324 return ret; 325} 326 327static const struct file_operations coh901327_fops = { 328 .owner = THIS_MODULE, 329 .llseek = no_llseek, 330 .write = coh901327_write, 331 .unlocked_ioctl = coh901327_ioctl, 332 .open = coh901327_open, 333 .release = coh901327_release, 334}; 335 336static struct miscdevice coh901327_miscdev = { 337 .minor = WATCHDOG_MINOR, 338 .name = "watchdog", 339 .fops = &coh901327_fops, 340}; 341 342static int __exit coh901327_remove(struct platform_device *pdev) 343{ 344 misc_deregister(&coh901327_miscdev); 345 coh901327_disable(); 346 free_irq(irq, pdev); 347 clk_put(clk); 348 iounmap(virtbase); 349 release_mem_region(phybase, physize); 350 return 0; 351} 352 353 354static int __init coh901327_probe(struct platform_device *pdev) 355{ 356 int ret; 357 u16 val; 358 struct resource *res; 359 360 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 361 if (!res) 362 return -ENOENT; 363 364 parent = &pdev->dev; 365 physize = resource_size(res); 366 phybase = res->start; 367 368 if (request_mem_region(phybase, physize, DRV_NAME) == NULL) { 369 ret = -EBUSY; 370 goto out; 371 } 372 373 virtbase = ioremap(phybase, physize); 374 if (!virtbase) { 375 ret = -ENOMEM; 376 goto out_no_remap; 377 } 378 379 clk = clk_get(&pdev->dev, NULL); 380 if (IS_ERR(clk)) { 381 ret = PTR_ERR(clk); 382 dev_err(&pdev->dev, "could not get clock\n"); 383 goto out_no_clk; 384 } 385 ret = clk_enable(clk); 386 if (ret) { 387 dev_err(&pdev->dev, "could not enable clock\n"); 388 goto out_no_clk_enable; 389 } 390 391 val = readw(virtbase + U300_WDOG_SR); 392 switch (val) { 393 case U300_WDOG_SR_STATUS_TIMED_OUT: 394 dev_info(&pdev->dev, 395 "watchdog timed out since last chip reset!\n"); 396 boot_status = WDIOF_CARDRESET; 397 /* Status will be cleared below */ 398 break; 399 case U300_WDOG_SR_STATUS_NORMAL: 400 dev_info(&pdev->dev, 401 "in normal status, no timeouts have occurred.\n"); 402 break; 403 default: 404 dev_info(&pdev->dev, 405 "contains an illegal status code (%08x)\n", val); 406 break; 407 } 408 409 val = readw(virtbase + U300_WDOG_D2R); 410 switch (val) { 411 case U300_WDOG_D2R_DISABLE_STATUS_DISABLED: 412 dev_info(&pdev->dev, "currently disabled.\n"); 413 break; 414 case U300_WDOG_D2R_DISABLE_STATUS_ENABLED: 415 dev_info(&pdev->dev, 416 "currently enabled! (disabling it now)\n"); 417 coh901327_disable(); 418 break; 419 default: 420 dev_err(&pdev->dev, 421 "contains an illegal enable/disable code (%08x)\n", 422 val); 423 break; 424 } 425 426 /* Reset the watchdog */ 427 writew(U300_WDOG_SR_RESET_STATUS_RESET, virtbase + U300_WDOG_SR); 428 429 irq = platform_get_irq(pdev, 0); 430 if (request_irq(irq, coh901327_interrupt, 0, 431 DRV_NAME " Bark", pdev)) { 432 ret = -EIO; 433 goto out_no_irq; 434 } 435 436 clk_disable(clk); 437 438 ret = misc_register(&coh901327_miscdev); 439 if (ret == 0) 440 dev_info(&pdev->dev, 441 "initialized. timer margin=%d sec\n", margin); 442 else 443 goto out_no_wdog; 444 445 return 0; 446 447out_no_wdog: 448 free_irq(irq, pdev); 449out_no_irq: 450 clk_disable(clk); 451out_no_clk_enable: 452 clk_put(clk); 453out_no_clk: 454 iounmap(virtbase); 455out_no_remap: 456 release_mem_region(phybase, SZ_4K); 457out: 458 return ret; 459} 460 461#ifdef CONFIG_PM 462 463static u16 wdogenablestore; 464static u16 irqmaskstore; 465 466static int coh901327_suspend(struct platform_device *pdev, pm_message_t state) 467{ 468 irqmaskstore = readw(virtbase + U300_WDOG_IMR) & 0x0001U; 469 wdogenablestore = readw(virtbase + U300_WDOG_D2R); 470 /* If watchdog is on, disable it here and now */ 471 if (wdogenablestore == U300_WDOG_D2R_DISABLE_STATUS_ENABLED) 472 coh901327_disable(); 473 return 0; 474} 475 476static int coh901327_resume(struct platform_device *pdev) 477{ 478 /* Restore the watchdog interrupt */ 479 writew(irqmaskstore, virtbase + U300_WDOG_IMR); 480 if (wdogenablestore == U300_WDOG_D2R_DISABLE_STATUS_ENABLED) { 481 /* Restart the watchdog timer */ 482 writew(U300_WDOG_RR_RESTART_VALUE_RESUME, 483 virtbase + U300_WDOG_RR); 484 writew(U300_WDOG_FR_FEED_RESTART_TIMER, 485 virtbase + U300_WDOG_FR); 486 } 487 return 0; 488} 489#else 490#define coh901327_suspend NULL 491#define coh901327_resume NULL 492#endif 493 494/* 495 * Mistreating the watchdog is the only way to perform a software reset of the 496 * system on EMP platforms. So we implement this and export a symbol for it. 497 */ 498void coh901327_watchdog_reset(void) 499{ 500 /* Enable even if on JTAG too */ 501 writew(U300_WDOG_JOR_JTAG_WATCHDOG_ENABLE, 502 virtbase + U300_WDOG_JOR); 503 /* 504 * Timeout = 5s, we have to wait for the watchdog reset to 505 * actually take place: the watchdog will be reloaded with the 506 * default value immediately, so we HAVE to reboot and get back 507 * into the kernel in 30s, or the device will reboot again! 508 * The boot loader will typically deactivate the watchdog, so we 509 * need time enough for the boot loader to get to the point of 510 * deactivating the watchdog before it is shut down by it. 511 * 512 * NOTE: on future versions of the watchdog, this restriction is 513 * gone: the watchdog will be reloaded with a default value (1 min) 514 * instead of last value, and you can conveniently set the watchdog 515 * timeout to 10ms (value = 1) without any problems. 516 */ 517 coh901327_enable(500); 518 /* Return and await doom */ 519} 520 521static struct platform_driver coh901327_driver = { 522 .driver = { 523 .owner = THIS_MODULE, 524 .name = "coh901327_wdog", 525 }, 526 .remove = __exit_p(coh901327_remove), 527 .suspend = coh901327_suspend, 528 .resume = coh901327_resume, 529}; 530 531static int __init coh901327_init(void) 532{ 533 return platform_driver_probe(&coh901327_driver, coh901327_probe); 534} 535module_init(coh901327_init); 536 537static void __exit coh901327_exit(void) 538{ 539 platform_driver_unregister(&coh901327_driver); 540} 541module_exit(coh901327_exit); 542 543MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); 544MODULE_DESCRIPTION("COH 901 327 Watchdog"); 545 546module_param(margin, int, 0); 547MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); 548 549MODULE_LICENSE("GPL"); 550MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 551