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 = kempld_prescaler[PRESCALER_21]; 144 u64 stage_timeout64; 145 u32 stage_timeout; 146 u32 remainder; 147 u8 stage_cfg; 148 149 if (!stage) 150 return -EINVAL; 151 152 stage_timeout64 = (u64)timeout * pld->pld_clock; 153 remainder = do_div(stage_timeout64, prescaler); 154 if (remainder) 155 stage_timeout64++; 156 157 if (stage_timeout64 > stage->mask) 158 return -EINVAL; 159 160 stage_timeout = stage_timeout64 & stage->mask; 161 162 kempld_get_mutex(pld); 163 stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id)); 164 stage_cfg &= ~STAGE_CFG_PRESCALER_MASK; 165 stage_cfg |= STAGE_CFG_SET_PRESCALER(PRESCALER_21); 166 kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg); 167 kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id), 168 stage_timeout); 169 kempld_release_mutex(pld); 170 171 return 0; 172 } 173 174 /* 175 * kempld_get_mutex must be called prior to calling this function. 176 */ 177 static unsigned int kempld_wdt_get_timeout(struct kempld_wdt_data *wdt_data, 178 struct kempld_wdt_stage *stage) 179 { 180 struct kempld_device_data *pld = wdt_data->pld; 181 unsigned int timeout; 182 u64 stage_timeout; 183 u32 prescaler; 184 u32 remainder; 185 u8 stage_cfg; 186 187 if (!stage->mask) 188 return 0; 189 190 stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id)); 191 stage_timeout = kempld_read32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id)); 192 prescaler = kempld_prescaler[STAGE_CFG_GET_PRESCALER(stage_cfg)]; 193 194 stage_timeout = (stage_timeout & stage->mask) * prescaler; 195 remainder = do_div(stage_timeout, pld->pld_clock); 196 if (remainder) 197 stage_timeout++; 198 199 timeout = stage_timeout; 200 WARN_ON_ONCE(timeout != stage_timeout); 201 202 return timeout; 203 } 204 205 static int kempld_wdt_set_timeout(struct watchdog_device *wdd, 206 unsigned int timeout) 207 { 208 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 209 struct kempld_wdt_stage *pretimeout_stage; 210 struct kempld_wdt_stage *timeout_stage; 211 int ret; 212 213 timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; 214 pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; 215 216 if (pretimeout_stage->mask && wdt_data->pretimeout > 0) 217 timeout = wdt_data->pretimeout; 218 219 ret = kempld_wdt_set_stage_action(wdt_data, timeout_stage, 220 ACTION_RESET); 221 if (ret) 222 return ret; 223 ret = kempld_wdt_set_stage_timeout(wdt_data, timeout_stage, 224 timeout); 225 if (ret) 226 return ret; 227 228 wdd->timeout = timeout; 229 return 0; 230 } 231 232 static int kempld_wdt_set_pretimeout(struct watchdog_device *wdd, 233 unsigned int pretimeout) 234 { 235 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 236 struct kempld_wdt_stage *pretimeout_stage; 237 u8 action = ACTION_NONE; 238 int ret; 239 240 pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; 241 242 if (!pretimeout_stage->mask) 243 return -ENXIO; 244 245 if (pretimeout > wdd->timeout) 246 return -EINVAL; 247 248 if (pretimeout > 0) 249 action = ACTION_NMI; 250 251 ret = kempld_wdt_set_stage_action(wdt_data, pretimeout_stage, 252 action); 253 if (ret) 254 return ret; 255 ret = kempld_wdt_set_stage_timeout(wdt_data, pretimeout_stage, 256 wdd->timeout - pretimeout); 257 if (ret) 258 return ret; 259 260 wdt_data->pretimeout = pretimeout; 261 return 0; 262 } 263 264 static void kempld_wdt_update_timeouts(struct kempld_wdt_data *wdt_data) 265 { 266 struct kempld_device_data *pld = wdt_data->pld; 267 struct kempld_wdt_stage *pretimeout_stage; 268 struct kempld_wdt_stage *timeout_stage; 269 unsigned int pretimeout, timeout; 270 271 pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; 272 timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; 273 274 kempld_get_mutex(pld); 275 pretimeout = kempld_wdt_get_timeout(wdt_data, pretimeout_stage); 276 timeout = kempld_wdt_get_timeout(wdt_data, timeout_stage); 277 kempld_release_mutex(pld); 278 279 if (pretimeout) 280 wdt_data->pretimeout = timeout; 281 else 282 wdt_data->pretimeout = 0; 283 284 wdt_data->wdd.timeout = pretimeout + timeout; 285 } 286 287 static int kempld_wdt_start(struct watchdog_device *wdd) 288 { 289 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 290 struct kempld_device_data *pld = wdt_data->pld; 291 u8 status; 292 int ret; 293 294 ret = kempld_wdt_set_timeout(wdd, wdd->timeout); 295 if (ret) 296 return ret; 297 298 kempld_get_mutex(pld); 299 status = kempld_read8(pld, KEMPLD_WDT_CFG); 300 status |= KEMPLD_WDT_CFG_ENABLE; 301 kempld_write8(pld, KEMPLD_WDT_CFG, status); 302 status = kempld_read8(pld, KEMPLD_WDT_CFG); 303 kempld_release_mutex(pld); 304 305 /* Check if the watchdog was enabled */ 306 if (!(status & KEMPLD_WDT_CFG_ENABLE)) 307 return -EACCES; 308 309 return 0; 310 } 311 312 static int kempld_wdt_stop(struct watchdog_device *wdd) 313 { 314 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 315 struct kempld_device_data *pld = wdt_data->pld; 316 u8 status; 317 318 kempld_get_mutex(pld); 319 status = kempld_read8(pld, KEMPLD_WDT_CFG); 320 status &= ~KEMPLD_WDT_CFG_ENABLE; 321 kempld_write8(pld, KEMPLD_WDT_CFG, status); 322 status = kempld_read8(pld, KEMPLD_WDT_CFG); 323 kempld_release_mutex(pld); 324 325 /* Check if the watchdog was disabled */ 326 if (status & KEMPLD_WDT_CFG_ENABLE) 327 return -EACCES; 328 329 return 0; 330 } 331 332 static int kempld_wdt_keepalive(struct watchdog_device *wdd) 333 { 334 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 335 struct kempld_device_data *pld = wdt_data->pld; 336 337 kempld_get_mutex(pld); 338 kempld_write8(pld, KEMPLD_WDT_KICK, 'K'); 339 kempld_release_mutex(pld); 340 341 return 0; 342 } 343 344 static long kempld_wdt_ioctl(struct watchdog_device *wdd, unsigned int cmd, 345 unsigned long arg) 346 { 347 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 348 void __user *argp = (void __user *)arg; 349 int ret = -ENOIOCTLCMD; 350 int __user *p = argp; 351 int new_value; 352 353 switch (cmd) { 354 case WDIOC_SETPRETIMEOUT: 355 if (get_user(new_value, p)) 356 return -EFAULT; 357 ret = kempld_wdt_set_pretimeout(wdd, new_value); 358 if (ret) 359 return ret; 360 ret = kempld_wdt_keepalive(wdd); 361 break; 362 case WDIOC_GETPRETIMEOUT: 363 ret = put_user(wdt_data->pretimeout, (int __user *)arg); 364 break; 365 } 366 367 return ret; 368 } 369 370 static int kempld_wdt_probe_stages(struct watchdog_device *wdd) 371 { 372 struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); 373 struct kempld_device_data *pld = wdt_data->pld; 374 struct kempld_wdt_stage *pretimeout_stage; 375 struct kempld_wdt_stage *timeout_stage; 376 u8 index, data, data_orig; 377 u32 mask; 378 int i, j; 379 380 pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; 381 timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; 382 383 pretimeout_stage->mask = 0; 384 timeout_stage->mask = 0; 385 386 for (i = 0; i < 3; i++) { 387 index = KEMPLD_WDT_STAGE_TIMEOUT(i); 388 mask = 0; 389 390 kempld_get_mutex(pld); 391 /* Probe each byte individually. */ 392 for (j = 0; j < 4; j++) { 393 data_orig = kempld_read8(pld, index + j); 394 kempld_write8(pld, index + j, 0x00); 395 data = kempld_read8(pld, index + j); 396 /* A failed write means this byte is reserved */ 397 if (data != 0x00) 398 break; 399 kempld_write8(pld, index + j, data_orig); 400 mask |= 0xff << (j * 8); 401 } 402 kempld_release_mutex(pld); 403 404 /* Assign available stages to timeout and pretimeout */ 405 if (!timeout_stage->mask) { 406 timeout_stage->mask = mask; 407 timeout_stage->id = i; 408 } else { 409 if (pld->feature_mask & KEMPLD_FEATURE_BIT_NMI) { 410 pretimeout_stage->mask = timeout_stage->mask; 411 timeout_stage->mask = mask; 412 pretimeout_stage->id = timeout_stage->id; 413 timeout_stage->id = i; 414 } 415 break; 416 } 417 } 418 419 if (!timeout_stage->mask) 420 return -ENODEV; 421 422 return 0; 423 } 424 425 static struct watchdog_info kempld_wdt_info = { 426 .identity = "KEMPLD Watchdog", 427 .options = WDIOF_SETTIMEOUT | 428 WDIOF_KEEPALIVEPING | 429 WDIOF_MAGICCLOSE | 430 WDIOF_PRETIMEOUT 431 }; 432 433 static const struct watchdog_ops kempld_wdt_ops = { 434 .owner = THIS_MODULE, 435 .start = kempld_wdt_start, 436 .stop = kempld_wdt_stop, 437 .ping = kempld_wdt_keepalive, 438 .set_timeout = kempld_wdt_set_timeout, 439 .ioctl = kempld_wdt_ioctl, 440 }; 441 442 static int kempld_wdt_probe(struct platform_device *pdev) 443 { 444 struct kempld_device_data *pld = dev_get_drvdata(pdev->dev.parent); 445 struct kempld_wdt_data *wdt_data; 446 struct device *dev = &pdev->dev; 447 struct watchdog_device *wdd; 448 u8 status; 449 int ret = 0; 450 451 wdt_data = devm_kzalloc(dev, sizeof(*wdt_data), GFP_KERNEL); 452 if (!wdt_data) 453 return -ENOMEM; 454 455 wdt_data->pld = pld; 456 wdd = &wdt_data->wdd; 457 wdd->parent = dev; 458 459 kempld_get_mutex(pld); 460 status = kempld_read8(pld, KEMPLD_WDT_CFG); 461 kempld_release_mutex(pld); 462 463 /* Enable nowayout if watchdog is already locked */ 464 if (status & (KEMPLD_WDT_CFG_ENABLE_LOCK | 465 KEMPLD_WDT_CFG_GLOBAL_LOCK)) { 466 if (!nowayout) 467 dev_warn(dev, 468 "Forcing nowayout - watchdog lock enabled!\n"); 469 nowayout = true; 470 } 471 472 wdd->info = &kempld_wdt_info; 473 wdd->ops = &kempld_wdt_ops; 474 475 watchdog_set_drvdata(wdd, wdt_data); 476 watchdog_set_nowayout(wdd, nowayout); 477 478 ret = kempld_wdt_probe_stages(wdd); 479 if (ret) 480 return ret; 481 482 kempld_wdt_set_timeout(wdd, timeout); 483 kempld_wdt_set_pretimeout(wdd, pretimeout); 484 485 /* Check if watchdog is already enabled */ 486 if (status & KEMPLD_WDT_CFG_ENABLE) { 487 /* Get current watchdog settings */ 488 kempld_wdt_update_timeouts(wdt_data); 489 dev_info(dev, "Watchdog was already enabled\n"); 490 } 491 492 platform_set_drvdata(pdev, wdt_data); 493 ret = watchdog_register_device(wdd); 494 if (ret) 495 return ret; 496 497 dev_info(dev, "Watchdog registered with %ds timeout\n", wdd->timeout); 498 499 return 0; 500 } 501 502 static void kempld_wdt_shutdown(struct platform_device *pdev) 503 { 504 struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); 505 506 kempld_wdt_stop(&wdt_data->wdd); 507 } 508 509 static int kempld_wdt_remove(struct platform_device *pdev) 510 { 511 struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); 512 struct watchdog_device *wdd = &wdt_data->wdd; 513 int ret = 0; 514 515 if (!nowayout) 516 ret = kempld_wdt_stop(wdd); 517 watchdog_unregister_device(wdd); 518 519 return ret; 520 } 521 522 #ifdef CONFIG_PM 523 /* Disable watchdog if it is active during suspend */ 524 static int kempld_wdt_suspend(struct platform_device *pdev, 525 pm_message_t message) 526 { 527 struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); 528 struct kempld_device_data *pld = wdt_data->pld; 529 struct watchdog_device *wdd = &wdt_data->wdd; 530 531 kempld_get_mutex(pld); 532 wdt_data->pm_status_store = kempld_read8(pld, KEMPLD_WDT_CFG); 533 kempld_release_mutex(pld); 534 535 kempld_wdt_update_timeouts(wdt_data); 536 537 if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE) 538 return kempld_wdt_stop(wdd); 539 540 return 0; 541 } 542 543 /* Enable watchdog and configure it if necessary */ 544 static int kempld_wdt_resume(struct platform_device *pdev) 545 { 546 struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); 547 struct watchdog_device *wdd = &wdt_data->wdd; 548 549 /* 550 * If watchdog was stopped before suspend be sure it gets disabled 551 * again, for the case BIOS has enabled it during resume 552 */ 553 if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE) 554 return kempld_wdt_start(wdd); 555 else 556 return kempld_wdt_stop(wdd); 557 } 558 #else 559 #define kempld_wdt_suspend NULL 560 #define kempld_wdt_resume NULL 561 #endif 562 563 static struct platform_driver kempld_wdt_driver = { 564 .driver = { 565 .name = "kempld-wdt", 566 }, 567 .probe = kempld_wdt_probe, 568 .remove = kempld_wdt_remove, 569 .shutdown = kempld_wdt_shutdown, 570 .suspend = kempld_wdt_suspend, 571 .resume = kempld_wdt_resume, 572 }; 573 574 module_platform_driver(kempld_wdt_driver); 575 576 MODULE_DESCRIPTION("KEM PLD Watchdog Driver"); 577 MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>"); 578 MODULE_LICENSE("GPL"); 579