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