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