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