1/* 2 * Cadence WDT driver - Used by Xilinx Zynq 3 * 4 * Copyright (C) 2010 - 2014 Xilinx, Inc. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#include <linux/clk.h> 13#include <linux/init.h> 14#include <linux/interrupt.h> 15#include <linux/io.h> 16#include <linux/irq.h> 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/of.h> 20#include <linux/platform_device.h> 21#include <linux/reboot.h> 22#include <linux/watchdog.h> 23 24#define CDNS_WDT_DEFAULT_TIMEOUT 10 25/* Supports 1 - 516 sec */ 26#define CDNS_WDT_MIN_TIMEOUT 1 27#define CDNS_WDT_MAX_TIMEOUT 516 28 29/* Restart key */ 30#define CDNS_WDT_RESTART_KEY 0x00001999 31 32/* Counter register access key */ 33#define CDNS_WDT_REGISTER_ACCESS_KEY 0x00920000 34 35/* Counter value divisor */ 36#define CDNS_WDT_COUNTER_VALUE_DIVISOR 0x1000 37 38/* Clock prescaler value and selection */ 39#define CDNS_WDT_PRESCALE_64 64 40#define CDNS_WDT_PRESCALE_512 512 41#define CDNS_WDT_PRESCALE_4096 4096 42#define CDNS_WDT_PRESCALE_SELECT_64 1 43#define CDNS_WDT_PRESCALE_SELECT_512 2 44#define CDNS_WDT_PRESCALE_SELECT_4096 3 45 46/* Input clock frequency */ 47#define CDNS_WDT_CLK_10MHZ 10000000 48#define CDNS_WDT_CLK_75MHZ 75000000 49 50/* Counter maximum value */ 51#define CDNS_WDT_COUNTER_MAX 0xFFF 52 53static int wdt_timeout = CDNS_WDT_DEFAULT_TIMEOUT; 54static int nowayout = WATCHDOG_NOWAYOUT; 55 56module_param(wdt_timeout, int, 0); 57MODULE_PARM_DESC(wdt_timeout, 58 "Watchdog time in seconds. (default=" 59 __MODULE_STRING(CDNS_WDT_DEFAULT_TIMEOUT) ")"); 60 61module_param(nowayout, int, 0); 62MODULE_PARM_DESC(nowayout, 63 "Watchdog cannot be stopped once started (default=" 64 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 65 66/** 67 * struct cdns_wdt - Watchdog device structure 68 * @regs: baseaddress of device 69 * @rst: reset flag 70 * @clk: struct clk * of a clock source 71 * @prescaler: for saving prescaler value 72 * @ctrl_clksel: counter clock prescaler selection 73 * @io_lock: spinlock for IO register access 74 * @cdns_wdt_device: watchdog device structure 75 * @cdns_wdt_notifier: notifier structure 76 * 77 * Structure containing parameters specific to cadence watchdog. 78 */ 79struct cdns_wdt { 80 void __iomem *regs; 81 bool rst; 82 struct clk *clk; 83 u32 prescaler; 84 u32 ctrl_clksel; 85 spinlock_t io_lock; 86 struct watchdog_device cdns_wdt_device; 87 struct notifier_block cdns_wdt_notifier; 88}; 89 90/* Write access to Registers */ 91static inline void cdns_wdt_writereg(struct cdns_wdt *wdt, u32 offset, u32 val) 92{ 93 writel_relaxed(val, wdt->regs + offset); 94} 95 96/*************************Register Map**************************************/ 97 98/* Register Offsets for the WDT */ 99#define CDNS_WDT_ZMR_OFFSET 0x0 /* Zero Mode Register */ 100#define CDNS_WDT_CCR_OFFSET 0x4 /* Counter Control Register */ 101#define CDNS_WDT_RESTART_OFFSET 0x8 /* Restart Register */ 102#define CDNS_WDT_SR_OFFSET 0xC /* Status Register */ 103 104/* 105 * Zero Mode Register - This register controls how the time out is indicated 106 * and also contains the access code to allow writes to the register (0xABC). 107 */ 108#define CDNS_WDT_ZMR_WDEN_MASK 0x00000001 /* Enable the WDT */ 109#define CDNS_WDT_ZMR_RSTEN_MASK 0x00000002 /* Enable the reset output */ 110#define CDNS_WDT_ZMR_IRQEN_MASK 0x00000004 /* Enable IRQ output */ 111#define CDNS_WDT_ZMR_RSTLEN_16 0x00000030 /* Reset pulse of 16 pclk cycles */ 112#define CDNS_WDT_ZMR_ZKEY_VAL 0x00ABC000 /* Access key, 0xABC << 12 */ 113/* 114 * Counter Control register - This register controls how fast the timer runs 115 * and the reset value and also contains the access code to allow writes to 116 * the register. 117 */ 118#define CDNS_WDT_CCR_CRV_MASK 0x00003FFC /* Counter reset value */ 119 120/** 121 * cdns_wdt_stop - Stop the watchdog. 122 * 123 * @wdd: watchdog device 124 * 125 * Read the contents of the ZMR register, clear the WDEN bit 126 * in the register and set the access key for successful write. 127 * 128 * Return: always 0 129 */ 130static int cdns_wdt_stop(struct watchdog_device *wdd) 131{ 132 struct cdns_wdt *wdt = watchdog_get_drvdata(wdd); 133 134 spin_lock(&wdt->io_lock); 135 cdns_wdt_writereg(wdt, CDNS_WDT_ZMR_OFFSET, 136 CDNS_WDT_ZMR_ZKEY_VAL & (~CDNS_WDT_ZMR_WDEN_MASK)); 137 spin_unlock(&wdt->io_lock); 138 139 return 0; 140} 141 142/** 143 * cdns_wdt_reload - Reload the watchdog timer (i.e. pat the watchdog). 144 * 145 * @wdd: watchdog device 146 * 147 * Write the restart key value (0x00001999) to the restart register. 148 * 149 * Return: always 0 150 */ 151static int cdns_wdt_reload(struct watchdog_device *wdd) 152{ 153 struct cdns_wdt *wdt = watchdog_get_drvdata(wdd); 154 155 spin_lock(&wdt->io_lock); 156 cdns_wdt_writereg(wdt, CDNS_WDT_RESTART_OFFSET, 157 CDNS_WDT_RESTART_KEY); 158 spin_unlock(&wdt->io_lock); 159 160 return 0; 161} 162 163/** 164 * cdns_wdt_start - Enable and start the watchdog. 165 * 166 * @wdd: watchdog device 167 * 168 * The counter value is calculated according to the formula: 169 * calculated count = (timeout * clock) / prescaler + 1. 170 * The calculated count is divided by 0x1000 to obtain the field value 171 * to write to counter control register. 172 * Clears the contents of prescaler and counter reset value. Sets the 173 * prescaler to 4096 and the calculated count and access key 174 * to write to CCR Register. 175 * Sets the WDT (WDEN bit) and either the Reset signal(RSTEN bit) 176 * or Interrupt signal(IRQEN) with a specified cycles and the access 177 * key to write to ZMR Register. 178 * 179 * Return: always 0 180 */ 181static int cdns_wdt_start(struct watchdog_device *wdd) 182{ 183 struct cdns_wdt *wdt = watchdog_get_drvdata(wdd); 184 unsigned int data = 0; 185 unsigned short count; 186 unsigned long clock_f = clk_get_rate(wdt->clk); 187 188 /* 189 * Counter value divisor to obtain the value of 190 * counter reset to be written to control register. 191 */ 192 count = (wdd->timeout * (clock_f / wdt->prescaler)) / 193 CDNS_WDT_COUNTER_VALUE_DIVISOR + 1; 194 195 if (count > CDNS_WDT_COUNTER_MAX) 196 count = CDNS_WDT_COUNTER_MAX; 197 198 spin_lock(&wdt->io_lock); 199 cdns_wdt_writereg(wdt, CDNS_WDT_ZMR_OFFSET, 200 CDNS_WDT_ZMR_ZKEY_VAL); 201 202 count = (count << 2) & CDNS_WDT_CCR_CRV_MASK; 203 204 /* Write counter access key first to be able write to register */ 205 data = count | CDNS_WDT_REGISTER_ACCESS_KEY | wdt->ctrl_clksel; 206 cdns_wdt_writereg(wdt, CDNS_WDT_CCR_OFFSET, data); 207 data = CDNS_WDT_ZMR_WDEN_MASK | CDNS_WDT_ZMR_RSTLEN_16 | 208 CDNS_WDT_ZMR_ZKEY_VAL; 209 210 /* Reset on timeout if specified in device tree. */ 211 if (wdt->rst) { 212 data |= CDNS_WDT_ZMR_RSTEN_MASK; 213 data &= ~CDNS_WDT_ZMR_IRQEN_MASK; 214 } else { 215 data &= ~CDNS_WDT_ZMR_RSTEN_MASK; 216 data |= CDNS_WDT_ZMR_IRQEN_MASK; 217 } 218 cdns_wdt_writereg(wdt, CDNS_WDT_ZMR_OFFSET, data); 219 cdns_wdt_writereg(wdt, CDNS_WDT_RESTART_OFFSET, 220 CDNS_WDT_RESTART_KEY); 221 spin_unlock(&wdt->io_lock); 222 223 return 0; 224} 225 226/** 227 * cdns_wdt_settimeout - Set a new timeout value for the watchdog device. 228 * 229 * @wdd: watchdog device 230 * @new_time: new timeout value that needs to be set 231 * Return: 0 on success 232 * 233 * Update the watchdog_device timeout with new value which is used when 234 * cdns_wdt_start is called. 235 */ 236static int cdns_wdt_settimeout(struct watchdog_device *wdd, 237 unsigned int new_time) 238{ 239 wdd->timeout = new_time; 240 241 return cdns_wdt_start(wdd); 242} 243 244/** 245 * cdns_wdt_irq_handler - Notifies of watchdog timeout. 246 * 247 * @irq: interrupt number 248 * @dev_id: pointer to a platform device structure 249 * Return: IRQ_HANDLED 250 * 251 * The handler is invoked when the watchdog times out and a 252 * reset on timeout has not been enabled. 253 */ 254static irqreturn_t cdns_wdt_irq_handler(int irq, void *dev_id) 255{ 256 struct platform_device *pdev = dev_id; 257 258 dev_info(&pdev->dev, 259 "Watchdog timed out. Internal reset not enabled\n"); 260 261 return IRQ_HANDLED; 262} 263 264/* 265 * Info structure used to indicate the features supported by the device 266 * to the upper layers. This is defined in watchdog.h header file. 267 */ 268static struct watchdog_info cdns_wdt_info = { 269 .identity = "cdns_wdt watchdog", 270 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | 271 WDIOF_MAGICCLOSE, 272}; 273 274/* Watchdog Core Ops */ 275static struct watchdog_ops cdns_wdt_ops = { 276 .owner = THIS_MODULE, 277 .start = cdns_wdt_start, 278 .stop = cdns_wdt_stop, 279 .ping = cdns_wdt_reload, 280 .set_timeout = cdns_wdt_settimeout, 281}; 282 283/** 284 * cdns_wdt_notify_sys - Notifier for reboot or shutdown. 285 * 286 * @this: handle to notifier block 287 * @code: turn off indicator 288 * @unused: unused 289 * Return: NOTIFY_DONE 290 * 291 * This notifier is invoked whenever the system reboot or shutdown occur 292 * because we need to disable the WDT before system goes down as WDT might 293 * reset on the next boot. 294 */ 295static int cdns_wdt_notify_sys(struct notifier_block *this, unsigned long code, 296 void *unused) 297{ 298 struct cdns_wdt *wdt = container_of(this, struct cdns_wdt, 299 cdns_wdt_notifier); 300 if (code == SYS_DOWN || code == SYS_HALT) 301 cdns_wdt_stop(&wdt->cdns_wdt_device); 302 303 return NOTIFY_DONE; 304} 305 306/************************Platform Operations*****************************/ 307/** 308 * cdns_wdt_probe - Probe call for the device. 309 * 310 * @pdev: handle to the platform device structure. 311 * Return: 0 on success, negative error otherwise. 312 * 313 * It does all the memory allocation and registration for the device. 314 */ 315static int cdns_wdt_probe(struct platform_device *pdev) 316{ 317 struct resource *res; 318 int ret, irq; 319 unsigned long clock_f; 320 struct cdns_wdt *wdt; 321 struct watchdog_device *cdns_wdt_device; 322 323 wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); 324 if (!wdt) 325 return -ENOMEM; 326 327 cdns_wdt_device = &wdt->cdns_wdt_device; 328 cdns_wdt_device->info = &cdns_wdt_info; 329 cdns_wdt_device->ops = &cdns_wdt_ops; 330 cdns_wdt_device->timeout = CDNS_WDT_DEFAULT_TIMEOUT; 331 cdns_wdt_device->min_timeout = CDNS_WDT_MIN_TIMEOUT; 332 cdns_wdt_device->max_timeout = CDNS_WDT_MAX_TIMEOUT; 333 334 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 335 wdt->regs = devm_ioremap_resource(&pdev->dev, res); 336 if (IS_ERR(wdt->regs)) 337 return PTR_ERR(wdt->regs); 338 339 /* Register the interrupt */ 340 wdt->rst = of_property_read_bool(pdev->dev.of_node, "reset-on-timeout"); 341 irq = platform_get_irq(pdev, 0); 342 if (!wdt->rst && irq >= 0) { 343 ret = devm_request_irq(&pdev->dev, irq, cdns_wdt_irq_handler, 0, 344 pdev->name, pdev); 345 if (ret) { 346 dev_err(&pdev->dev, 347 "cannot register interrupt handler err=%d\n", 348 ret); 349 return ret; 350 } 351 } 352 353 /* Initialize the members of cdns_wdt structure */ 354 cdns_wdt_device->parent = &pdev->dev; 355 356 ret = watchdog_init_timeout(cdns_wdt_device, wdt_timeout, &pdev->dev); 357 if (ret) { 358 dev_err(&pdev->dev, "unable to set timeout value\n"); 359 return ret; 360 } 361 362 watchdog_set_nowayout(cdns_wdt_device, nowayout); 363 watchdog_set_drvdata(cdns_wdt_device, wdt); 364 365 wdt->clk = devm_clk_get(&pdev->dev, NULL); 366 if (IS_ERR(wdt->clk)) { 367 dev_err(&pdev->dev, "input clock not found\n"); 368 ret = PTR_ERR(wdt->clk); 369 return ret; 370 } 371 372 ret = clk_prepare_enable(wdt->clk); 373 if (ret) { 374 dev_err(&pdev->dev, "unable to enable clock\n"); 375 return ret; 376 } 377 378 clock_f = clk_get_rate(wdt->clk); 379 if (clock_f <= CDNS_WDT_CLK_75MHZ) { 380 wdt->prescaler = CDNS_WDT_PRESCALE_512; 381 wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_512; 382 } else { 383 wdt->prescaler = CDNS_WDT_PRESCALE_4096; 384 wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_4096; 385 } 386 387 spin_lock_init(&wdt->io_lock); 388 389 wdt->cdns_wdt_notifier.notifier_call = &cdns_wdt_notify_sys; 390 ret = register_reboot_notifier(&wdt->cdns_wdt_notifier); 391 if (ret != 0) { 392 dev_err(&pdev->dev, "cannot register reboot notifier err=%d)\n", 393 ret); 394 goto err_clk_disable; 395 } 396 397 ret = watchdog_register_device(cdns_wdt_device); 398 if (ret) { 399 dev_err(&pdev->dev, "Failed to register wdt device\n"); 400 goto err_clk_disable; 401 } 402 platform_set_drvdata(pdev, wdt); 403 404 dev_dbg(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds%s\n", 405 wdt->regs, cdns_wdt_device->timeout, 406 nowayout ? ", nowayout" : ""); 407 408 return 0; 409 410err_clk_disable: 411 clk_disable_unprepare(wdt->clk); 412 413 return ret; 414} 415 416/** 417 * cdns_wdt_remove - Probe call for the device. 418 * 419 * @pdev: handle to the platform device structure. 420 * Return: 0 on success, otherwise negative error. 421 * 422 * Unregister the device after releasing the resources. 423 */ 424static int cdns_wdt_remove(struct platform_device *pdev) 425{ 426 struct cdns_wdt *wdt = platform_get_drvdata(pdev); 427 428 cdns_wdt_stop(&wdt->cdns_wdt_device); 429 watchdog_unregister_device(&wdt->cdns_wdt_device); 430 unregister_reboot_notifier(&wdt->cdns_wdt_notifier); 431 clk_disable_unprepare(wdt->clk); 432 433 return 0; 434} 435 436/** 437 * cdns_wdt_shutdown - Stop the device. 438 * 439 * @pdev: handle to the platform structure. 440 * 441 */ 442static void cdns_wdt_shutdown(struct platform_device *pdev) 443{ 444 struct cdns_wdt *wdt = platform_get_drvdata(pdev); 445 446 cdns_wdt_stop(&wdt->cdns_wdt_device); 447 clk_disable_unprepare(wdt->clk); 448} 449 450/** 451 * cdns_wdt_suspend - Stop the device. 452 * 453 * @dev: handle to the device structure. 454 * Return: 0 always. 455 */ 456static int __maybe_unused cdns_wdt_suspend(struct device *dev) 457{ 458 struct platform_device *pdev = container_of(dev, 459 struct platform_device, dev); 460 struct cdns_wdt *wdt = platform_get_drvdata(pdev); 461 462 cdns_wdt_stop(&wdt->cdns_wdt_device); 463 clk_disable_unprepare(wdt->clk); 464 465 return 0; 466} 467 468/** 469 * cdns_wdt_resume - Resume the device. 470 * 471 * @dev: handle to the device structure. 472 * Return: 0 on success, errno otherwise. 473 */ 474static int __maybe_unused cdns_wdt_resume(struct device *dev) 475{ 476 int ret; 477 struct platform_device *pdev = container_of(dev, 478 struct platform_device, dev); 479 struct cdns_wdt *wdt = platform_get_drvdata(pdev); 480 481 ret = clk_prepare_enable(wdt->clk); 482 if (ret) { 483 dev_err(dev, "unable to enable clock\n"); 484 return ret; 485 } 486 cdns_wdt_start(&wdt->cdns_wdt_device); 487 488 return 0; 489} 490 491static SIMPLE_DEV_PM_OPS(cdns_wdt_pm_ops, cdns_wdt_suspend, cdns_wdt_resume); 492 493static struct of_device_id cdns_wdt_of_match[] = { 494 { .compatible = "cdns,wdt-r1p2", }, 495 { /* end of table */ } 496}; 497MODULE_DEVICE_TABLE(of, cdns_wdt_of_match); 498 499/* Driver Structure */ 500static struct platform_driver cdns_wdt_driver = { 501 .probe = cdns_wdt_probe, 502 .remove = cdns_wdt_remove, 503 .shutdown = cdns_wdt_shutdown, 504 .driver = { 505 .name = "cdns-wdt", 506 .of_match_table = cdns_wdt_of_match, 507 .pm = &cdns_wdt_pm_ops, 508 }, 509}; 510 511module_platform_driver(cdns_wdt_driver); 512 513MODULE_AUTHOR("Xilinx, Inc."); 514MODULE_DESCRIPTION("Watchdog driver for Cadence WDT"); 515MODULE_LICENSE("GPL"); 516