008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. From 293903b9dfe43520f01374dc1661be11d6838c49 Mon Sep 17 00:00:00 2001
  2. From: Sander Vanheule <[email protected]>
  3. Date: Thu, 18 Nov 2021 17:29:52 +0100
  4. Subject: watchdog: Add Realtek Otto watchdog timer
  5. Realtek MIPS SoCs (platform name Otto) have a watchdog timer with
  6. pretimeout notifitication support. The WDT can (partially) hard reset,
  7. or soft reset the SoC.
  8. This driver implements all features as described in the devicetree
  9. binding, except the phase2 interrupt, and also functions as a restart
  10. handler. The cpu reset mode is considered to be a "warm" restart, since
  11. this mode does not reset all peripherals. Being an embedded system
  12. though, the "cpu" and "software" modes will still cause the bootloader
  13. to run on restart.
  14. It is not known how a forced system reset can be disabled on the
  15. supported platforms. This means that the phase2 interrupt will only fire
  16. at the same time as reset, so implementing phase2 is of little use.
  17. Signed-off-by: Sander Vanheule <[email protected]>
  18. Reviewed-by: Guenter Roeck <[email protected]>
  19. Link: https://lore.kernel.org/r/6d060bccbdcc709cfa79203485db85aad3c3beb5.1637252610.git.sander@svanheule.net
  20. Signed-off-by: Guenter Roeck <[email protected]>
  21. ---
  22. MAINTAINERS | 7 +
  23. drivers/watchdog/Kconfig | 13 ++
  24. drivers/watchdog/Makefile | 1 +
  25. drivers/watchdog/realtek_otto_wdt.c | 384 ++++++++++++++++++++++++++++++++++++
  26. 4 files changed, 405 insertions(+)
  27. create mode 100644 drivers/watchdog/realtek_otto_wdt.c
  28. --- a/MAINTAINERS
  29. +++ b/MAINTAINERS
  30. @@ -14816,6 +14816,13 @@ S: Maintained
  31. F: include/sound/rt*.h
  32. F: sound/soc/codecs/rt*
  33. +REALTEK OTTO WATCHDOG
  34. +M: Sander Vanheule <[email protected]>
  35. +L: [email protected]
  36. +S: Maintained
  37. +F: Documentation/devicetree/bindings/watchdog/realtek,otto-wdt.yaml
  38. +F: driver/watchdog/realtek_otto_wdt.c
  39. +
  40. REALTEK RTL83xx SMI DSA ROUTER CHIPS
  41. M: Linus Walleij <[email protected]>
  42. S: Maintained
  43. --- a/drivers/watchdog/Kconfig
  44. +++ b/drivers/watchdog/Kconfig
  45. @@ -995,6 +995,19 @@ config RTD119X_WATCHDOG
  46. Say Y here to include support for the watchdog timer in
  47. Realtek RTD1295 SoCs.
  48. +config REALTEK_OTTO_WDT
  49. + tristate "Realtek Otto MIPS watchdog support"
  50. + depends on MACH_REALTEK_RTL || COMPILE_TEST
  51. + depends on COMMON_CLK
  52. + select WATCHDOG_CORE
  53. + default MACH_REALTEK_RTL
  54. + help
  55. + Say Y here to include support for the watchdog timer on Realtek
  56. + RTL838x, RTL839x, RTL930x SoCs. This watchdog has pretimeout
  57. + notifications and system reset on timeout.
  58. +
  59. + When built as a module this will be called realtek_otto_wdt.
  60. +
  61. config SPRD_WATCHDOG
  62. tristate "Spreadtrum watchdog support"
  63. depends on ARCH_SPRD || COMPILE_TEST
  64. --- a/drivers/watchdog/Makefile
  65. +++ b/drivers/watchdog/Makefile
  66. @@ -174,6 +174,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
  67. obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
  68. obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
  69. obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
  70. +obj-$(CONFIG_REALTEK_OTTO_WDT) += realtek_otto_wdt.o
  71. # PARISC Architecture
  72. --- /dev/null
  73. +++ b/drivers/watchdog/realtek_otto_wdt.c
  74. @@ -0,0 +1,384 @@
  75. +// SPDX-License-Identifier: GPL-2.0-only
  76. +
  77. +/*
  78. + * Realtek Otto MIPS platform watchdog
  79. + *
  80. + * Watchdog timer that will reset the system after timeout, using the selected
  81. + * reset mode.
  82. + *
  83. + * Counter scaling and timeouts:
  84. + * - Base prescale of (2 << 25), providing tick duration T_0: 168ms @ 200MHz
  85. + * - PRESCALE: logarithmic prescaler adding a factor of {1, 2, 4, 8}
  86. + * - Phase 1: Times out after (PHASE1 + 1) × PRESCALE × T_0
  87. + * Generates an interrupt, WDT cannot be stopped after phase 1
  88. + * - Phase 2: starts after phase 1, times out after (PHASE2 + 1) × PRESCALE × T_0
  89. + * Resets the system according to RST_MODE
  90. + */
  91. +
  92. +#include <linux/bits.h>
  93. +#include <linux/bitfield.h>
  94. +#include <linux/clk.h>
  95. +#include <linux/delay.h>
  96. +#include <linux/interrupt.h>
  97. +#include <linux/io.h>
  98. +#include <linux/math.h>
  99. +#include <linux/minmax.h>
  100. +#include <linux/module.h>
  101. +#include <linux/mod_devicetable.h>
  102. +#include <linux/platform_device.h>
  103. +#include <linux/property.h>
  104. +#include <linux/reboot.h>
  105. +#include <linux/watchdog.h>
  106. +
  107. +#define OTTO_WDT_REG_CNTR 0x0
  108. +#define OTTO_WDT_CNTR_PING BIT(31)
  109. +
  110. +#define OTTO_WDT_REG_INTR 0x4
  111. +#define OTTO_WDT_INTR_PHASE_1 BIT(31)
  112. +#define OTTO_WDT_INTR_PHASE_2 BIT(30)
  113. +
  114. +#define OTTO_WDT_REG_CTRL 0x8
  115. +#define OTTO_WDT_CTRL_ENABLE BIT(31)
  116. +#define OTTO_WDT_CTRL_PRESCALE GENMASK(30, 29)
  117. +#define OTTO_WDT_CTRL_PHASE1 GENMASK(26, 22)
  118. +#define OTTO_WDT_CTRL_PHASE2 GENMASK(19, 15)
  119. +#define OTTO_WDT_CTRL_RST_MODE GENMASK(1, 0)
  120. +#define OTTO_WDT_MODE_SOC 0
  121. +#define OTTO_WDT_MODE_CPU 1
  122. +#define OTTO_WDT_MODE_SOFTWARE 2
  123. +#define OTTO_WDT_CTRL_DEFAULT OTTO_WDT_MODE_CPU
  124. +
  125. +#define OTTO_WDT_PRESCALE_MAX 3
  126. +
  127. +/*
  128. + * One higher than the max values contained in PHASE{1,2}, since a value of 0
  129. + * corresponds to one tick.
  130. + */
  131. +#define OTTO_WDT_PHASE_TICKS_MAX 32
  132. +
  133. +/*
  134. + * The maximum reset delay is actually 2×32 ticks, but that would require large
  135. + * pretimeout values for timeouts longer than 32 ticks. Limit the maximum timeout
  136. + * to 32 + 1 to ensure small pretimeout values can be configured as expected.
  137. + */
  138. +#define OTTO_WDT_TIMEOUT_TICKS_MAX (OTTO_WDT_PHASE_TICKS_MAX + 1)
  139. +
  140. +struct otto_wdt_ctrl {
  141. + struct watchdog_device wdev;
  142. + struct device *dev;
  143. + void __iomem *base;
  144. + unsigned int clk_rate_khz;
  145. + int irq_phase1;
  146. +};
  147. +
  148. +static int otto_wdt_start(struct watchdog_device *wdev)
  149. +{
  150. + struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
  151. + u32 v;
  152. +
  153. + v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
  154. + v |= OTTO_WDT_CTRL_ENABLE;
  155. + iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
  156. +
  157. + return 0;
  158. +}
  159. +
  160. +static int otto_wdt_stop(struct watchdog_device *wdev)
  161. +{
  162. + struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
  163. + u32 v;
  164. +
  165. + v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
  166. + v &= ~OTTO_WDT_CTRL_ENABLE;
  167. + iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
  168. +
  169. + return 0;
  170. +}
  171. +
  172. +static int otto_wdt_ping(struct watchdog_device *wdev)
  173. +{
  174. + struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
  175. +
  176. + iowrite32(OTTO_WDT_CNTR_PING, ctrl->base + OTTO_WDT_REG_CNTR);
  177. +
  178. + return 0;
  179. +}
  180. +
  181. +static int otto_wdt_tick_ms(struct otto_wdt_ctrl *ctrl, int prescale)
  182. +{
  183. + return DIV_ROUND_CLOSEST(1 << (25 + prescale), ctrl->clk_rate_khz);
  184. +}
  185. +
  186. +/*
  187. + * The timer asserts the PHASE1/PHASE2 IRQs when the number of ticks exceeds
  188. + * the value stored in those fields. This means each phase will run for at least
  189. + * one tick, so small values need to be clamped to correctly reflect the timeout.
  190. + */
  191. +static inline unsigned int div_round_ticks(unsigned int val, unsigned int tick_duration,
  192. + unsigned int min_ticks)
  193. +{
  194. + return max(min_ticks, DIV_ROUND_UP(val, tick_duration));
  195. +}
  196. +
  197. +static int otto_wdt_determine_timeouts(struct watchdog_device *wdev, unsigned int timeout,
  198. + unsigned int pretimeout)
  199. +{
  200. + struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
  201. + unsigned int pretimeout_ms = pretimeout * 1000;
  202. + unsigned int timeout_ms = timeout * 1000;
  203. + unsigned int prescale_next = 0;
  204. + unsigned int phase1_ticks;
  205. + unsigned int phase2_ticks;
  206. + unsigned int total_ticks;
  207. + unsigned int prescale;
  208. + unsigned int tick_ms;
  209. + u32 v;
  210. +
  211. + do {
  212. + prescale = prescale_next;
  213. + if (prescale > OTTO_WDT_PRESCALE_MAX)
  214. + return -EINVAL;
  215. +
  216. + tick_ms = otto_wdt_tick_ms(ctrl, prescale);
  217. + total_ticks = div_round_ticks(timeout_ms, tick_ms, 2);
  218. + phase1_ticks = div_round_ticks(timeout_ms - pretimeout_ms, tick_ms, 1);
  219. + phase2_ticks = total_ticks - phase1_ticks;
  220. +
  221. + prescale_next++;
  222. + } while (phase1_ticks > OTTO_WDT_PHASE_TICKS_MAX
  223. + || phase2_ticks > OTTO_WDT_PHASE_TICKS_MAX);
  224. +
  225. + v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
  226. +
  227. + v &= ~(OTTO_WDT_CTRL_PRESCALE | OTTO_WDT_CTRL_PHASE1 | OTTO_WDT_CTRL_PHASE2);
  228. + v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE1, phase1_ticks - 1);
  229. + v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE2, phase2_ticks - 1);
  230. + v |= FIELD_PREP(OTTO_WDT_CTRL_PRESCALE, prescale);
  231. +
  232. + iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
  233. +
  234. + timeout_ms = total_ticks * tick_ms;
  235. + ctrl->wdev.timeout = timeout_ms / 1000;
  236. +
  237. + pretimeout_ms = phase2_ticks * tick_ms;
  238. + ctrl->wdev.pretimeout = pretimeout_ms / 1000;
  239. +
  240. + return 0;
  241. +}
  242. +
  243. +static int otto_wdt_set_timeout(struct watchdog_device *wdev, unsigned int val)
  244. +{
  245. + return otto_wdt_determine_timeouts(wdev, val, min(wdev->pretimeout, val - 1));
  246. +}
  247. +
  248. +static int otto_wdt_set_pretimeout(struct watchdog_device *wdev, unsigned int val)
  249. +{
  250. + return otto_wdt_determine_timeouts(wdev, wdev->timeout, val);
  251. +}
  252. +
  253. +static int otto_wdt_restart(struct watchdog_device *wdev, unsigned long reboot_mode,
  254. + void *data)
  255. +{
  256. + struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
  257. + u32 reset_mode;
  258. + u32 v;
  259. +
  260. + disable_irq(ctrl->irq_phase1);
  261. +
  262. + switch (reboot_mode) {
  263. + case REBOOT_SOFT:
  264. + reset_mode = OTTO_WDT_MODE_SOFTWARE;
  265. + break;
  266. + case REBOOT_WARM:
  267. + reset_mode = OTTO_WDT_MODE_CPU;
  268. + break;
  269. + default:
  270. + reset_mode = OTTO_WDT_MODE_SOC;
  271. + break;
  272. + }
  273. +
  274. + /* Configure for shortest timeout and wait for reset to occur */
  275. + v = FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, reset_mode) | OTTO_WDT_CTRL_ENABLE;
  276. + iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
  277. +
  278. + mdelay(3 * otto_wdt_tick_ms(ctrl, 0));
  279. +
  280. + return 0;
  281. +}
  282. +
  283. +static irqreturn_t otto_wdt_phase1_isr(int irq, void *dev_id)
  284. +{
  285. + struct otto_wdt_ctrl *ctrl = dev_id;
  286. +
  287. + iowrite32(OTTO_WDT_INTR_PHASE_1, ctrl->base + OTTO_WDT_REG_INTR);
  288. + dev_crit(ctrl->dev, "phase 1 timeout\n");
  289. + watchdog_notify_pretimeout(&ctrl->wdev);
  290. +
  291. + return IRQ_HANDLED;
  292. +}
  293. +
  294. +static const struct watchdog_ops otto_wdt_ops = {
  295. + .owner = THIS_MODULE,
  296. + .start = otto_wdt_start,
  297. + .stop = otto_wdt_stop,
  298. + .ping = otto_wdt_ping,
  299. + .set_timeout = otto_wdt_set_timeout,
  300. + .set_pretimeout = otto_wdt_set_pretimeout,
  301. + .restart = otto_wdt_restart,
  302. +};
  303. +
  304. +static const struct watchdog_info otto_wdt_info = {
  305. + .identity = "Realtek Otto watchdog timer",
  306. + .options = WDIOF_KEEPALIVEPING |
  307. + WDIOF_MAGICCLOSE |
  308. + WDIOF_SETTIMEOUT |
  309. + WDIOF_PRETIMEOUT,
  310. +};
  311. +
  312. +static void otto_wdt_clock_action(void *data)
  313. +{
  314. + clk_disable_unprepare(data);
  315. +}
  316. +
  317. +static int otto_wdt_probe_clk(struct otto_wdt_ctrl *ctrl)
  318. +{
  319. + struct clk *clk = devm_clk_get(ctrl->dev, NULL);
  320. + int ret;
  321. +
  322. + if (IS_ERR(clk))
  323. + return dev_err_probe(ctrl->dev, PTR_ERR(clk), "Failed to get clock\n");
  324. +
  325. + ret = clk_prepare_enable(clk);
  326. + if (ret)
  327. + return dev_err_probe(ctrl->dev, ret, "Failed to enable clock\n");
  328. +
  329. + ret = devm_add_action_or_reset(ctrl->dev, otto_wdt_clock_action, clk);
  330. + if (ret)
  331. + return ret;
  332. +
  333. + ctrl->clk_rate_khz = clk_get_rate(clk) / 1000;
  334. + if (ctrl->clk_rate_khz == 0)
  335. + return dev_err_probe(ctrl->dev, -ENXIO, "Failed to get clock rate\n");
  336. +
  337. + return 0;
  338. +}
  339. +
  340. +static int otto_wdt_probe_reset_mode(struct otto_wdt_ctrl *ctrl)
  341. +{
  342. + static const char *mode_property = "realtek,reset-mode";
  343. + const struct fwnode_handle *node = ctrl->dev->fwnode;
  344. + int mode_count;
  345. + u32 mode;
  346. + u32 v;
  347. +
  348. + if (!node)
  349. + return -ENXIO;
  350. +
  351. + mode_count = fwnode_property_string_array_count(node, mode_property);
  352. + if (mode_count < 0)
  353. + return mode_count;
  354. + else if (mode_count == 0)
  355. + return 0;
  356. + else if (mode_count != 1)
  357. + return -EINVAL;
  358. +
  359. + if (fwnode_property_match_string(node, mode_property, "soc") == 0)
  360. + mode = OTTO_WDT_MODE_SOC;
  361. + else if (fwnode_property_match_string(node, mode_property, "cpu") == 0)
  362. + mode = OTTO_WDT_MODE_CPU;
  363. + else if (fwnode_property_match_string(node, mode_property, "software") == 0)
  364. + mode = OTTO_WDT_MODE_SOFTWARE;
  365. + else
  366. + return -EINVAL;
  367. +
  368. + v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
  369. + v &= ~OTTO_WDT_CTRL_RST_MODE;
  370. + v |= FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, mode);
  371. + iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
  372. +
  373. + return 0;
  374. +}
  375. +
  376. +static int otto_wdt_probe(struct platform_device *pdev)
  377. +{
  378. + struct device *dev = &pdev->dev;
  379. + struct otto_wdt_ctrl *ctrl;
  380. + unsigned int max_tick_ms;
  381. + int ret;
  382. +
  383. + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
  384. + if (!ctrl)
  385. + return -ENOMEM;
  386. +
  387. + ctrl->dev = dev;
  388. + ctrl->base = devm_platform_ioremap_resource(pdev, 0);
  389. + if (IS_ERR(ctrl->base))
  390. + return PTR_ERR(ctrl->base);
  391. +
  392. + /* Clear any old interrupts and reset initial state */
  393. + iowrite32(OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2,
  394. + ctrl->base + OTTO_WDT_REG_INTR);
  395. + iowrite32(OTTO_WDT_CTRL_DEFAULT, ctrl->base + OTTO_WDT_REG_CTRL);
  396. +
  397. + ret = otto_wdt_probe_clk(ctrl);
  398. + if (ret)
  399. + return ret;
  400. +
  401. + ctrl->irq_phase1 = platform_get_irq_byname(pdev, "phase1");
  402. + if (ctrl->irq_phase1 < 0)
  403. + return ctrl->irq_phase1;
  404. +
  405. + ret = devm_request_irq(dev, ctrl->irq_phase1, otto_wdt_phase1_isr, 0,
  406. + "realtek-otto-wdt", ctrl);
  407. + if (ret)
  408. + return dev_err_probe(dev, ret, "Failed to get IRQ for phase1\n");
  409. +
  410. + ret = otto_wdt_probe_reset_mode(ctrl);
  411. + if (ret)
  412. + return dev_err_probe(dev, ret, "Invalid reset mode specified\n");
  413. +
  414. + ctrl->wdev.parent = dev;
  415. + ctrl->wdev.info = &otto_wdt_info;
  416. + ctrl->wdev.ops = &otto_wdt_ops;
  417. +
  418. + /*
  419. + * Since pretimeout cannot be disabled, min. timeout is twice the
  420. + * subsystem resolution. Max. timeout is ca. 43s at a bus clock of 200MHz.
  421. + */
  422. + ctrl->wdev.min_timeout = 2;
  423. + max_tick_ms = otto_wdt_tick_ms(ctrl, OTTO_WDT_PRESCALE_MAX);
  424. + ctrl->wdev.max_hw_heartbeat_ms = max_tick_ms * OTTO_WDT_TIMEOUT_TICKS_MAX;
  425. + ctrl->wdev.timeout = min(30U, ctrl->wdev.max_hw_heartbeat_ms / 1000);
  426. +
  427. + watchdog_set_drvdata(&ctrl->wdev, ctrl);
  428. + watchdog_init_timeout(&ctrl->wdev, 0, dev);
  429. + watchdog_stop_on_reboot(&ctrl->wdev);
  430. + watchdog_set_restart_priority(&ctrl->wdev, 128);
  431. +
  432. + ret = otto_wdt_determine_timeouts(&ctrl->wdev, ctrl->wdev.timeout, 1);
  433. + if (ret)
  434. + return dev_err_probe(dev, ret, "Failed to set timeout\n");
  435. +
  436. + return devm_watchdog_register_device(dev, &ctrl->wdev);
  437. +}
  438. +
  439. +static const struct of_device_id otto_wdt_ids[] = {
  440. + { .compatible = "realtek,rtl8380-wdt" },
  441. + { .compatible = "realtek,rtl8390-wdt" },
  442. + { .compatible = "realtek,rtl9300-wdt" },
  443. + { }
  444. +};
  445. +MODULE_DEVICE_TABLE(of, otto_wdt_ids);
  446. +
  447. +static struct platform_driver otto_wdt_driver = {
  448. + .probe = otto_wdt_probe,
  449. + .driver = {
  450. + .name = "realtek-otto-watchdog",
  451. + .of_match_table = otto_wdt_ids,
  452. + },
  453. +};
  454. +module_platform_driver(otto_wdt_driver);
  455. +
  456. +MODULE_LICENSE("GPL v2");
  457. +MODULE_AUTHOR("Sander Vanheule <[email protected]>");
  458. +MODULE_DESCRIPTION("Realtek Otto watchdog timer driver");