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