aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTzung-Bi Shih <tzungbi@kernel.org>2026-09-13 14:51:26 +0800
committerGuenter Roeck <linux@roeck-us.net>2026-09-16 17:41:17 -0700
commit22737cfced627ffcb4b5c36d63bb3d4476f63213 (patch)
tree8224a1d91e304a4ce93fda3ba7e8bd0d728d1d87
parentwatchdog: msc313e: Propagate error code in resume() (diff)
watchdog: msc313e: Fix premature reset during timeout update
Updating the 32-bit hardware timeout requires writing to two 16-bit registers sequentially. If the watchdog is actively running, this non-atomic update might trigger a premature system reset. Clear the watchdog counter before updating the registers to prevent the timer from timing out prematurely against an intermediate threshold. Fixes: e9800b799464 ("watchdog: Add Mstar MSC313e WDT driver") Cc: stable@vger.kernel.org Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org> Link: https://patch.msgid.link/20260913065126.8350-1-tzungbi@kernel.org Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/watchdog/msc313e_wdt.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/watchdog/msc313e_wdt.c b/drivers/watchdog/msc313e_wdt.c
index 9a400562d1ae..d62586f6e09d 100644
--- a/drivers/watchdog/msc313e_wdt.c
+++ b/drivers/watchdog/msc313e_wdt.c
@@ -46,6 +46,9 @@ static void msc313e_wdt_set_hw_timeout(struct msc313e_wdt_priv *priv,
{
u32 t = timeout * clk_get_rate(priv->clk);
+ /* Clear before to prevent premature reset during non-atomic updates. */
+ writew(1, priv->base + REG_WDT_CLR);
+
writew(t & 0xffff, priv->base + REG_WDT_MAX_PRD_L);
writew((t >> 16) & 0xffff, priv->base + REG_WDT_MAX_PRD_H);
writew(1, priv->base + REG_WDT_CLR);
@@ -76,6 +79,9 @@ static int msc313e_wdt_stop(struct watchdog_device *wdev)
{
struct msc313e_wdt_priv *priv = watchdog_get_drvdata(wdev);
+ /* Clear before to prevent premature reset during non-atomic updates. */
+ writew(1, priv->base + REG_WDT_CLR);
+
writew(0, priv->base + REG_WDT_MAX_PRD_L);
writew(0, priv->base + REG_WDT_MAX_PRD_H);
writew(0, priv->base + REG_WDT_CLR);