1 /* 2 * Kontron PLD watchdog driver 3 * 4 * Copyright (c) 2010-2013 Kontron Europe GmbH 5 * Author: Michael Brunner <michael.brunner@kontron.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License 2 as published 9 * by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * Note: From the PLD watchdog point of view timeout and pretimeout are 17 * defined differently than in the kernel. 18 * First the pretimeout stage runs out before the timeout stage gets 19 * active. 20 * 21 * Kernel/API: P-----| pretimeout 22 * |-----------------------T timeout 23 * Watchdog: |-----------------P pretimeout_stage 24 * |-----T timeout_stage 25 */ 26 27 #include <linux/module.h> 28 #include <linux/moduleparam.h> 29 #include <linux/miscdevice.h> 30 #include <linux/uaccess.h> 31 #include <linux/watchdog.h> 32 #include <linux/platform_device.h> 33 #include <linux/mfd/kempld.h> 34 35 #define KEMPLD_WDT_STAGE_TIMEOUT(x) (0x1b + (x) * 4) 36 #define KEMPLD_WDT_STAGE_CFG(x) (0x18 + (x)) 37 #define STAGE_CFG_GET_PRESCALER(x) (((x) & 0x30) >> 4) 38 #define STAGE_CFG_SET_PRESCALER(x) (((x) & 0x3) << 4) 39 #define STAGE_CFG_PRESCALER_MASK 0x30 40 #define STAGE_CFG_ACTION_MASK 0x7 41 #define STAGE_CFG_ASSERT (1 << 3) 42 43 #define KEMPLD_WDT_MAX_STAGES 2 44 #define KEMPLD_WDT_KICK 0x16 45 #define KEMPLD_WDT_CFG 0x17 46 #define KEMPLD_WDT_CFG_ENABLE 0x10 47 #define KEMPLD_WDT_CFG_ENABLE_LOCK 0x8 48 #define KEMPLD_WDT_CFG_GLOBAL_LOCK 0x80 49 50 enum { 51 ACTION_NONE = 0, 52 ACTION_RESET, 53 ACTION_NMI, 54 ACTION_SMI, 55 ACTION_SCI, 56 ACTION_DELAY, 57 }; 58 59 enum { 60 STAGE_TIMEOUT = 0, 61 STAGE_PRETIMEOUT, 62 }; 63 64 enum { 65 PRESCALER_21 = 0, 66 PRESCALER_17, 67 PRESCALER_12, 68 }; 69 70 static const u32 kempld_prescaler[] = { 71 [PRESCALER_21] = (1 << 21) - 1, 72 [PRESCALER_17] = (1 << 17) - 1, 73 [PRESCALER_12] = (1 << 12) - 1, 74 0, 75 }; 76 77 struct kempld_wdt_stage { 78 unsigned int id; 79 u32 mask; 80 }; 81 82 struct kempld_wdt_data { 83 struct kempld_device_data *pld; 84 struct watchdog_device wdd; 85 unsigned int pretimeout; 86 struct kempld_wdt_stage stage[KEMPLD_WDT_MAX_STAGES]; 87 #ifdef CONFIG_PM 88 u8 pm_status_store; 89 #endif 90 }; 91 92 #define DEFAULT_TIMEOUT 30 /* seconds */ 93 #define DEFAULT_PRETIMEOUT 0 94 95 static unsigned int timeout = DEFAULT_TIMEOUT; 96 module_param(timeout, uint, 0); 97 MODULE_PARM_DESC(timeout, 98 "Watchdog timeout in seconds. (>=0, default=" 99 __MODULE_STRING(DEFAULT_TIMEOUT) ")"); 100 101 static unsigned int pretimeout = DEFAULT_PRETIMEOUT; 102 module_param(pretimeout, uint, 0); 103 MODULE_PARM_DESC(pretimeout, 104 "Watchdog pretimeout in seconds. (>=0, default=" 105 __MODULE_STRING(DEFAULT_PRETIMEOUT) ")"); 106 107 static bool nowayout = WATCHDOG_NOWAYOUT; 108 module_param(nowayout, bool, 0); 109 MODULE_PARM_DESC(nowayout, 110 "Watchdog cannot be stopped once started (default=" 111 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 112 113 static int kempld_wdt_set_stage_action(struct kempld_wdt_data *wdt_data, 114 struct kempld_wdt_stage *stage, 115 u8 action) 116 { 117 struct kempld_device_data *pld = wdt_data->pld; 118 u8 stage_cfg; 119 120 if (!stage || !stage->mask) 121 return -EINVAL; 122 123 kempld_get_mutex(pld); 124 stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id)); 125 stage_cfg &= ~STAGE_CFG_ACTION_MASK; 126 stage_cfg |= (action & STAGE_CFG_ACTION_MASK); 127 128 if (action == ACTION_RESET) 129 stage_cfg |= STAGE_CFG_ASSERT; 130 else 131 stage_cfg &= ~STAGE_CFG_ASSERT; 132 133 kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg); 134 kempld_release_mutex(pld); 135 136 return 0; 137 } 138 139 static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data, 140 struct kempld_wdt_stage *stage, 141 unsigned int timeout) 142 { 143 struct kempld_device_data *pld = wdt_data->pld; 144 u32 prescaler = kempld_prescaler[PRESCALER_21]; 145 u64 stage_timeout64; 146 u32 stage_timeout; 147 u32 remainder; 148 u8 stage_cfg; 149 150 if (!stage) 151 return -EINVAL; 152 153 stage_timeout64 = (u64)timeout * pld->pld_clock; 154 remainder = do_div(stage_timeout64, prescaler); 155 if (remainder) 156 stage_timeout64++; 157 158 if (stage_timeout64 > stage->mask) 159 return -EINVAL; 160 161 stage_timeout = stage_timeout64 & stage->mask; 162 163 kempld_get_mutex(pld); 164 stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id)); 165 stage_cfg &= ~STAGE_CFG_PRESCALER_MASK; 166 stage_cfg |= STAGE_CFG_SET_PRESCALER(prescaler); 167 kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg); 168 kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id), 169 stage_timeout); 170 kempld_release_mutex(pld); 171 172 return 0; 173 } 174 175 /* 176 * kempld_get_mutex must be called prior to calling this function. 177 */ 178 static unsigned int kempld_wdt_get_timeout(struct kempld_wdt_data *wdt_data, 179 struct kempld_wdt_stage *stage) 180 { 181 struct kempld_device_data *pld = wdt_data->pld; 182 unsigned int timeout; 183 u64 stage_timeout; 184 u32 prescaler; 185 u32 remainder; 186 u8 stage_cfg; 187 188 if (!stage->mask) 189 return 0; 190 191 stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id)); 192 stage_timeout = kempld_read32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id)); 193 prescaler = kempld_prescaler[STAGE_CFG_GET_PRESCALER(stage_cfg)]; 194 195 stage_timeout = (stage_timeout & stage->mask) * prescaler; 196 remainder = do_div(stage_timeout, pld->pld_clock); 197 if (remainder) 198 stage_timeout++; 199 200 timeout = stage_timeout; 201 WARN_ON_ONCE(timeout != stage_timeout); 202 203 return timeout; 204 } 205 206 static int kempld_wdt_set_timeout(struct watchdog_device *wdd, 207 unsigned int timeout) 208 { 209 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 210 struct kempld_wdt_stage *pretimeout_stage; 211 struct kempld_wdt_stage *timeout_stage; 212 int ret; 213 214 timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; 215 pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; 216 217 if (pretimeout_stage->mask && wdt_data->pretimeout > 0) 218 timeout = wdt_data->pretimeout; 219 220 ret = kempld_wdt_set_stage_action(wdt_data, timeout_stage, 221 ACTION_RESET); 222 if (ret) 223 return ret; 224 ret = kempld_wdt_set_stage_timeout(wdt_data, timeout_stage, 225 timeout); 226 if (ret) 227 return ret; 228 229 wdd->timeout = timeout; 230 return 0; 231 } 232 233 static int kempld_wdt_set_pretimeout(struct watchdog_device *wdd, 234 unsigned int pretimeout) 235 { 236 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 237 struct kempld_wdt_stage *pretimeout_stage; 238 u8 action = ACTION_NONE; 239 int ret; 240 241 pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; 242 243 if (!pretimeout_stage->mask) 244 return -ENXIO; 245 246 if (pretimeout > wdd->timeout) 247 return -EINVAL; 248 249 if (pretimeout > 0) 250 action = ACTION_NMI; 251 252 ret = kempld_wdt_set_stage_action(wdt_data, pretimeout_stage, 253 action); 254 if (ret) 255 return ret; 256 ret = kempld_wdt_set_stage_timeout(wdt_data, pretimeout_stage, 257 wdd->timeout - pretimeout); 258 if (ret) 259 return ret; 260 261 wdt_data->pretimeout = pretimeout; 262 return 0; 263 } 264 265 static void kempld_wdt_update_timeouts(struct kempld_wdt_data *wdt_data) 266 { 267 struct kempld_device_data *pld = wdt_data->pld; 268 struct kempld_wdt_stage *pretimeout_stage; 269 struct kempld_wdt_stage *timeout_stage; 270 unsigned int pretimeout, timeout; 271 272 pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; 273 timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; 274 275 kempld_get_mutex(pld); 276 pretimeout = kempld_wdt_get_timeout(wdt_data, pretimeout_stage); 277 timeout = kempld_wdt_get_timeout(wdt_data, timeout_stage); 278 kempld_release_mutex(pld); 279 280 if (pretimeout) 281 wdt_data->pretimeout = timeout; 282 else 283 wdt_data->pretimeout = 0; 284 285 wdt_data->wdd.timeout = pretimeout + timeout; 286 } 287 288 static int kempld_wdt_start(struct watchdog_device *wdd) 289 { 290 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 291 struct kempld_device_data *pld = wdt_data->pld; 292 u8 status; 293 int ret; 294 295 ret = kempld_wdt_set_timeout(wdd, wdd->timeout); 296 if (ret) 297 return ret; 298 299 kempld_get_mutex(pld); 300 status = kempld_read8(pld, KEMPLD_WDT_CFG); 301 status |= KEMPLD_WDT_CFG_ENABLE; 302 kempld_write8(pld, KEMPLD_WDT_CFG, status); 303 status = kempld_read8(pld, KEMPLD_WDT_CFG); 304 kempld_release_mutex(pld); 305 306 /* Check if the watchdog was enabled */ 307 if (!(status & KEMPLD_WDT_CFG_ENABLE)) 308 return -EACCES; 309 310 return 0; 311 } 312 313 static int kempld_wdt_stop(struct watchdog_device *wdd) 314 { 315 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 316 struct kempld_device_data *pld = wdt_data->pld; 317 u8 status; 318 319 kempld_get_mutex(pld); 320 status = kempld_read8(pld, KEMPLD_WDT_CFG); 321 status &= ~KEMPLD_WDT_CFG_ENABLE; 322 kempld_write8(pld, KEMPLD_WDT_CFG, status); 323 status = kempld_read8(pld, KEMPLD_WDT_CFG); 324 kempld_release_mutex(pld); 325 326 /* Check if the watchdog was disabled */ 327 if (status & KEMPLD_WDT_CFG_ENABLE) 328 return -EACCES; 329 330 return 0; 331 } 332 333 static int kempld_wdt_keepalive(struct watchdog_device *wdd) 334 { 335 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 336 struct kempld_device_data *pld = wdt_data->pld; 337 338 kempld_get_mutex(pld); 339 kempld_write8(pld, KEMPLD_WDT_KICK, 'K'); 340 kempld_release_mutex(pld); 341 342 return 0; 343 } 344 345 static long kempld_wdt_ioctl(struct watchdog_device *wdd, unsigned int cmd, 346 unsigned long arg) 347 { 348 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 349 void __user *argp = (void __user *)arg; 350 int ret = -ENOIOCTLCMD; 351 int __user *p = argp; 352 int new_value; 353 354 switch (cmd) { 355 case WDIOC_SETPRETIMEOUT: 356 if (get_user(new_value, p)) 357 return -EFAULT; 358 ret = kempld_wdt_set_pretimeout(wdd, new_value); 359 if (ret) 360 return ret; 361 ret = kempld_wdt_keepalive(wdd); 362 break; 363 case WDIOC_GETPRETIMEOUT: 364 ret = put_user(wdt_data->pretimeout, (int __user *)arg); 365 break; 366 } 367 368 return ret; 369 } 370 371 static int kempld_wdt_probe_stages(struct watchdog_device *wdd) 372 { 373 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 374 struct kempld_device_data *pld = wdt_data->pld; 375 struct kempld_wdt_stage *pretimeout_stage; 376 struct kempld_wdt_stage *timeout_stage; 377 u8 index, data, data_orig; 378 u32 mask; 379 int i, j; 380 381 pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; 382 timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; 383 384 pretimeout_stage->mask = 0; 385 timeout_stage->mask = 0; 386 387 for (i = 0; i < 3; i++) { 388 index = KEMPLD_WDT_STAGE_TIMEOUT(i); 389 mask = 0; 390 391 kempld_get_mutex(pld); 392 /* Probe each byte individually. */ 393 for (j = 0; j < 4; j++) { 394 data_orig = kempld_read8(pld, index + j); 395 kempld_write8(pld, index + j, 0x00); 396 data = kempld_read8(pld, index + j); 397 /* A failed write means this byte is reserved */ 398 if (data != 0x00) 399 break; 400 kempld_write8(pld, index + j, data_orig); 401 mask |= 0xff << (j * 8); 402 } 403 kempld_release_mutex(pld); 404 405 /* Assign available stages to timeout and pretimeout */ 406 if (!timeout_stage->mask) { 407 timeout_stage->mask = mask; 408 timeout_stage->id = i; 409 } else { 410 if (pld->feature_mask & KEMPLD_FEATURE_BIT_NMI) { 411 pretimeout_stage->mask = timeout_stage->mask; 412 timeout_stage->mask = mask; 413 pretimeout_stage->id = timeout_stage->id; 414 timeout_stage->id = i; 415 } 416 break; 417 } 418 } 419 420 if (!timeout_stage->mask) 421 return -ENODEV; 422 423 return 0; 424 } 425 426 static struct watchdog_info kempld_wdt_info = { 427 .identity = "KEMPLD Watchdog", 428 .options = WDIOF_SETTIMEOUT | 429 WDIOF_KEEPALIVEPING | 430 WDIOF_MAGICCLOSE | 431 WDIOF_PRETIMEOUT 432 }; 433 434 static struct watchdog_ops kempld_wdt_ops = { 435 .owner = THIS_MODULE, 436 .start = kempld_wdt_start, 437 .stop = kempld_wdt_stop, 438 .ping = kempld_wdt_keepalive, 439 .set_timeout = kempld_wdt_set_timeout, 440 .ioctl = kempld_wdt_ioctl, 441 }; 442 443 static int kempld_wdt_probe(struct platform_device *pdev) 444 { 445 struct kempld_device_data *pld = dev_get_drvdata(pdev->dev.parent); 446 struct kempld_wdt_data *wdt_data; 447 struct device *dev = &pdev->dev; 448 struct watchdog_device *wdd; 449 u8 status; 450 int ret = 0; 451 452 wdt_data = devm_kzalloc(dev, sizeof(*wdt_data), GFP_KERNEL); 453 if (!wdt_data) 454 return -ENOMEM; 455 456 wdt_data->pld = pld; 457 wdd = &wdt_data->wdd; 458 wdd->parent = dev; 459 460 kempld_get_mutex(pld); 461 status = kempld_read8(pld, KEMPLD_WDT_CFG); 462 kempld_release_mutex(pld); 463 464 /* Enable nowayout if watchdog is already locked */ 465 if (status & (KEMPLD_WDT_CFG_ENABLE_LOCK | 466 KEMPLD_WDT_CFG_GLOBAL_LOCK)) { 467 if (!nowayout) 468 dev_warn(dev, 469 "Forcing nowayout - watchdog lock enabled!\n"); 470 nowayout = true; 471 } 472 473 wdd->info = &kempld_wdt_info; 474 wdd->ops = &kempld_wdt_ops; 475 476 watchdog_set_drvdata(wdd, wdt_data); 477 watchdog_set_nowayout(wdd, nowayout); 478 479 ret = kempld_wdt_probe_stages(wdd); 480 if (ret) 481 return ret; 482 483 kempld_wdt_set_timeout(wdd, timeout); 484 kempld_wdt_set_pretimeout(wdd, pretimeout); 485 486 /* Check if watchdog is already enabled */ 487 if (status & KEMPLD_WDT_CFG_ENABLE) { 488 /* Get current watchdog settings */ 489 kempld_wdt_update_timeouts(wdt_data); 490 dev_info(dev, "Watchdog was already enabled\n"); 491 } 492 493 platform_set_drvdata(pdev, wdt_data); 494 ret = watchdog_register_device(wdd); 495 if (ret) 496 return ret; 497 498 dev_info(dev, "Watchdog registered with %ds timeout\n", wdd->timeout); 499 500 return 0; 501 } 502 503 static void kempld_wdt_shutdown(struct platform_device *pdev) 504 { 505 struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); 506 507 kempld_wdt_stop(&wdt_data->wdd); 508 } 509 510 static int kempld_wdt_remove(struct platform_device *pdev) 511 { 512 struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); 513 struct watchdog_device *wdd = &wdt_data->wdd; 514 int ret = 0; 515 516 if (!nowayout) 517 ret = kempld_wdt_stop(wdd); 518 watchdog_unregister_device(wdd); 519 520 return ret; 521 } 522 523 #ifdef CONFIG_PM 524 /* Disable watchdog if it is active during suspend */ 525 static int kempld_wdt_suspend(struct platform_device *pdev, 526 pm_message_t message) 527 { 528 struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); 529 struct kempld_device_data *pld = wdt_data->pld; 530 struct watchdog_device *wdd = &wdt_data->wdd; 531 532 kempld_get_mutex(pld); 533 wdt_data->pm_status_store = kempld_read8(pld, KEMPLD_WDT_CFG); 534 kempld_release_mutex(pld); 535 536 kempld_wdt_update_timeouts(wdt_data); 537 538 if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE) 539 return kempld_wdt_stop(wdd); 540 541 return 0; 542 } 543 544 /* Enable watchdog and configure it if necessary */ 545 static int kempld_wdt_resume(struct platform_device *pdev) 546 { 547 struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); 548 struct watchdog_device *wdd = &wdt_data->wdd; 549 550 /* 551 * If watchdog was stopped before suspend be sure it gets disabled 552 * again, for the case BIOS has enabled it during resume 553 */ 554 if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE) 555 return kempld_wdt_start(wdd); 556 else 557 return kempld_wdt_stop(wdd); 558 } 559 #else 560 #define kempld_wdt_suspend NULL 561 #define kempld_wdt_resume NULL 562 #endif 563 564 static struct platform_driver kempld_wdt_driver = { 565 .driver = { 566 .name = "kempld-wdt", 567 .owner = THIS_MODULE, 568 }, 569 .probe = kempld_wdt_probe, 570 .remove = kempld_wdt_remove, 571 .shutdown = kempld_wdt_shutdown, 572 .suspend = kempld_wdt_suspend, 573 .resume = kempld_wdt_resume, 574 }; 575 576 module_platform_driver(kempld_wdt_driver); 577 578 MODULE_DESCRIPTION("KEM PLD Watchdog Driver"); 579 MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>"); 580 MODULE_LICENSE("GPL"); 581