cadence_wdt.c 12 KB

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