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