[PATCH v4 2/2] watchdog: dw_wdt: manage reset line during system suspend/resume

From: Artem Shimko

Date: Sat Oct 24 2026 - 10:10:01 EST


The watchdog controller reset line is not currently managed during system
suspend/resume. This can lead to an inconsistent hardware state when
resuming from suspend, as the controller may not be properly reinitialized.

Assert the reset line before disabling clocks during suspend to ensure
the controller is held in reset while power is gated. During resume,
deassert the reset after clocks are enabled and before restoring register
state to guarantee the controller is properly initialized.

Tested-by: Igor Velkov <iav@xxxxxx>
Reviewed-by: Tzung-Bi Shih <tzungbi@xxxxxxxxxx>
Signed-off-by: Artem Shimko <a.shimko.dev@xxxxxxxxx>
---
drivers/watchdog/dw_wdt.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index ebd27ee684d1..684e0cb104c3 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -378,10 +378,15 @@ static irqreturn_t dw_wdt_irq(int irq, void *devid)
static int dw_wdt_suspend(struct device *dev)
{
struct dw_wdt *dw_wdt = dev_get_drvdata(dev);
+ int err;

dw_wdt->control = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET);
dw_wdt->timeout = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);

+ err = reset_control_assert(dw_wdt->rst);
+ if (err)
+ return err;
+
clk_disable_unprepare(dw_wdt->pclk);
clk_disable_unprepare(dw_wdt->clk);

@@ -391,16 +396,19 @@ static int dw_wdt_suspend(struct device *dev)
static int dw_wdt_resume(struct device *dev)
{
struct dw_wdt *dw_wdt = dev_get_drvdata(dev);
- int err = clk_prepare_enable(dw_wdt->clk);
+ int err;

+ err = clk_prepare_enable(dw_wdt->clk);
if (err)
return err;

err = clk_prepare_enable(dw_wdt->pclk);
- if (err) {
- clk_disable_unprepare(dw_wdt->clk);
- return err;
- }
+ if (err)
+ goto unprepare_clk;
+
+ err = reset_control_deassert(dw_wdt->rst);
+ if (err)
+ goto unprepare_pclk;

writel(dw_wdt->timeout, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
writel(dw_wdt->control, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET);
@@ -408,6 +416,13 @@ static int dw_wdt_resume(struct device *dev)
dw_wdt_ping(&dw_wdt->wdd);

return 0;
+
+unprepare_pclk:
+ clk_disable_unprepare(dw_wdt->pclk);
+unprepare_clk:
+ clk_disable_unprepare(dw_wdt->clk);
+
+ return err;
}

static DEFINE_SIMPLE_DEV_PM_OPS(dw_wdt_pm_ops, dw_wdt_suspend, dw_wdt_resume);
--
2.43.0