rzn1_wdt.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Renesas RZ/N1 Watchdog timer.
  4. * This is a 12-bit timer driver from a (62.5/16384) MHz clock. It can't even
  5. * cope with 2 seconds.
  6. *
  7. * Copyright 2018 Renesas Electronics Europe Ltd.
  8. *
  9. * Derived from Ralink RT288x watchdog timer.
  10. */
  11. #include <linux/clk.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/of_address.h>
  16. #include <linux/of_irq.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/reboot.h>
  19. #include <linux/watchdog.h>
  20. #define DEFAULT_TIMEOUT 60
  21. #define RZN1_WDT_RETRIGGER 0x0
  22. #define RZN1_WDT_RETRIGGER_RELOAD_VAL 0
  23. #define RZN1_WDT_RETRIGGER_RELOAD_VAL_MASK 0xfff
  24. #define RZN1_WDT_RETRIGGER_PRESCALE BIT(12)
  25. #define RZN1_WDT_RETRIGGER_ENABLE BIT(13)
  26. #define RZN1_WDT_RETRIGGER_WDSI (0x2 << 14)
  27. #define RZN1_WDT_PRESCALER 16384
  28. #define RZN1_WDT_MAX 4095
  29. struct rzn1_watchdog {
  30. struct watchdog_device wdtdev;
  31. void __iomem *base;
  32. unsigned long clk_rate_khz;
  33. };
  34. static inline uint32_t max_heart_beat_ms(unsigned long clk_rate_khz)
  35. {
  36. return (RZN1_WDT_MAX * RZN1_WDT_PRESCALER) / clk_rate_khz;
  37. }
  38. static inline uint32_t compute_reload_value(uint32_t tick_ms,
  39. unsigned long clk_rate_khz)
  40. {
  41. return (tick_ms * clk_rate_khz) / RZN1_WDT_PRESCALER;
  42. }
  43. static int rzn1_wdt_ping(struct watchdog_device *w)
  44. {
  45. struct rzn1_watchdog *wdt = watchdog_get_drvdata(w);
  46. /* Any value retrigggers the watchdog */
  47. writel(0, wdt->base + RZN1_WDT_RETRIGGER);
  48. return 0;
  49. }
  50. static int rzn1_wdt_start(struct watchdog_device *w)
  51. {
  52. struct rzn1_watchdog *wdt = watchdog_get_drvdata(w);
  53. u32 val;
  54. /*
  55. * The hardware allows you to write to this reg only once.
  56. * Since this includes the reload value, there is no way to change the
  57. * timeout once started. Also note that the WDT clock is half the bus
  58. * fabric clock rate, so if the bus fabric clock rate is changed after
  59. * the WDT is started, the WDT interval will be wrong.
  60. */
  61. val = RZN1_WDT_RETRIGGER_WDSI;
  62. val |= RZN1_WDT_RETRIGGER_ENABLE;
  63. val |= RZN1_WDT_RETRIGGER_PRESCALE;
  64. val |= compute_reload_value(w->max_hw_heartbeat_ms, wdt->clk_rate_khz);
  65. writel(val, wdt->base + RZN1_WDT_RETRIGGER);
  66. return 0;
  67. }
  68. static irqreturn_t rzn1_wdt_irq(int irq, void *_wdt)
  69. {
  70. pr_crit("RZN1 Watchdog. Initiating system reboot\n");
  71. emergency_restart();
  72. return IRQ_HANDLED;
  73. }
  74. static struct watchdog_info rzn1_wdt_info = {
  75. .identity = "RZ/N1 Watchdog",
  76. .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
  77. };
  78. static const struct watchdog_ops rzn1_wdt_ops = {
  79. .owner = THIS_MODULE,
  80. .start = rzn1_wdt_start,
  81. .ping = rzn1_wdt_ping,
  82. };
  83. static void rzn1_wdt_clk_disable_unprepare(void *data)
  84. {
  85. clk_disable_unprepare(data);
  86. }
  87. static int rzn1_wdt_probe(struct platform_device *pdev)
  88. {
  89. struct device *dev = &pdev->dev;
  90. struct rzn1_watchdog *wdt;
  91. struct device_node *np = dev->of_node;
  92. struct clk *clk;
  93. unsigned long clk_rate;
  94. int ret;
  95. int irq;
  96. wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
  97. if (!wdt)
  98. return -ENOMEM;
  99. wdt->base = devm_platform_ioremap_resource(pdev, 0);
  100. if (IS_ERR(wdt->base))
  101. return PTR_ERR(wdt->base);
  102. irq = platform_get_irq(pdev, 0);
  103. if (irq < 0)
  104. return irq;
  105. ret = devm_request_irq(dev, irq, rzn1_wdt_irq, 0,
  106. np->name, wdt);
  107. if (ret) {
  108. dev_err(dev, "failed to request irq %d\n", irq);
  109. return ret;
  110. }
  111. clk = devm_clk_get(dev, NULL);
  112. if (IS_ERR(clk)) {
  113. dev_err(dev, "failed to get the clock\n");
  114. return PTR_ERR(clk);
  115. }
  116. ret = clk_prepare_enable(clk);
  117. if (ret) {
  118. dev_err(dev, "failed to prepare/enable the clock\n");
  119. return ret;
  120. }
  121. ret = devm_add_action_or_reset(dev, rzn1_wdt_clk_disable_unprepare,
  122. clk);
  123. if (ret)
  124. return ret;
  125. clk_rate = clk_get_rate(clk);
  126. if (!clk_rate) {
  127. dev_err(dev, "failed to get the clock rate\n");
  128. return -EINVAL;
  129. }
  130. wdt->clk_rate_khz = clk_rate / 1000;
  131. wdt->wdtdev.info = &rzn1_wdt_info,
  132. wdt->wdtdev.ops = &rzn1_wdt_ops,
  133. wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS,
  134. wdt->wdtdev.parent = dev;
  135. /*
  136. * The period of the watchdog cannot be changed once set
  137. * and is limited to a very short period.
  138. * Configure it for a 1s period once and for all, and
  139. * rely on the heart-beat provided by the watchdog core
  140. * to make this usable by the user-space.
  141. */
  142. wdt->wdtdev.max_hw_heartbeat_ms = max_heart_beat_ms(wdt->clk_rate_khz);
  143. if (wdt->wdtdev.max_hw_heartbeat_ms > 1000)
  144. wdt->wdtdev.max_hw_heartbeat_ms = 1000;
  145. wdt->wdtdev.timeout = DEFAULT_TIMEOUT;
  146. ret = watchdog_init_timeout(&wdt->wdtdev, 0, dev);
  147. if (ret)
  148. return ret;
  149. watchdog_set_drvdata(&wdt->wdtdev, wdt);
  150. return devm_watchdog_register_device(dev, &wdt->wdtdev);
  151. }
  152. static const struct of_device_id rzn1_wdt_match[] = {
  153. { .compatible = "renesas,rzn1-wdt" },
  154. {},
  155. };
  156. MODULE_DEVICE_TABLE(of, rzn1_wdt_match);
  157. static struct platform_driver rzn1_wdt_driver = {
  158. .probe = rzn1_wdt_probe,
  159. .driver = {
  160. .name = KBUILD_MODNAME,
  161. .of_match_table = rzn1_wdt_match,
  162. },
  163. };
  164. module_platform_driver(rzn1_wdt_driver);
  165. MODULE_DESCRIPTION("Renesas RZ/N1 hardware watchdog");
  166. MODULE_AUTHOR("Phil Edworthy <[email protected]>");
  167. MODULE_LICENSE("GPL");