* [PATCH v2 1/3] watchdog: dw_wdt: use devm_reset_control_get_optional_shared_deasserted
2026-10-22 13:43 [PATCH v2 0/3] watchdog: dw_wdt: fix reset line management Artem Shimko
@ 2026-10-22 13:43 ` Artem Shimko
2026-10-23 3:05 ` Tzung-Bi Shih
2026-10-22 13:43 ` [PATCH v2 2/3] watchdog: dw_wdt: manage reset line during system suspend/resume Artem Shimko
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Artem Shimko @ 2026-10-22 13:43 UTC (permalink / raw)
To: wim, linux, p.zabel, Sergey.Semin, mika.westerberg, andi.shyti,
iav
Cc: Artem Shimko, linux-watchdog, linux-kernel
Replace devm_reset_control_get_optional_shared() with
devm_reset_control_get_optional_shared_deasserted() to let the
device-managed API handle reset line deassertion and assertion
automatically.
The driver currently manages the reset control manually: it calls
reset_control_deassert() during probe and reset_control_assert() in
error paths and remove. This is error-prone and requires explicit
cleanup in multiple places.
Switching to the _deasserted variant deasserts the reset line on
acquisition and asserts it again when the device is removed, which
allows removing the out_assert_rst label along with the related
assertions in the probe error paths and in dw_wdt_drv_remove().
Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
---
drivers/watchdog/dw_wdt.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 39031445d754..2cffe337b4ea 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -588,9 +588,9 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
if (IS_ERR(dw_wdt->pclk))
return PTR_ERR(dw_wdt->pclk);
- dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
+ dw_wdt->rst = devm_reset_control_get_optional_shared_deasserted(dev, NULL);
if (IS_ERR(dw_wdt->rst))
- return PTR_ERR(dw_wdt->rst);
+ return dev_err_probe(dev, PTR_ERR(dw_wdt->rst), "failed to acquire reset\n");
/* Enable normal reset without pre-timeout by default. */
dw_wdt_update_mode(dw_wdt, DW_WDT_RMOD_RESET);
@@ -617,11 +617,9 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
dw_wdt->wdd.info = &dw_wdt_ident;
}
- reset_control_deassert(dw_wdt->rst);
-
ret = dw_wdt_init_timeouts(dw_wdt, dev);
if (ret)
- goto out_assert_rst;
+ return ret;
wdd = &dw_wdt->wdd;
wdd->ops = &dw_wdt_ops;
@@ -655,15 +653,11 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
ret = watchdog_register_device(wdd);
if (ret)
- goto out_assert_rst;
+ return ret;
dw_wdt_dbgfs_init(dw_wdt);
return 0;
-
-out_assert_rst:
- reset_control_assert(dw_wdt->rst);
- return ret;
}
static void dw_wdt_drv_remove(struct platform_device *pdev)
@@ -673,7 +667,6 @@ static void dw_wdt_drv_remove(struct platform_device *pdev)
dw_wdt_dbgfs_clear(dw_wdt);
watchdog_unregister_device(&dw_wdt->wdd);
- reset_control_assert(dw_wdt->rst);
}
#ifdef CONFIG_OF
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 1/3] watchdog: dw_wdt: use devm_reset_control_get_optional_shared_deasserted
2026-10-22 13:43 ` [PATCH v2 1/3] watchdog: dw_wdt: use devm_reset_control_get_optional_shared_deasserted Artem Shimko
@ 2026-10-23 3:05 ` Tzung-Bi Shih
[not found] ` <CAOPX745qshBW4NPh8cNt9kGUEtp6C1Ds8HVTjFjL2=q1azrFsw@mail.gmail.com>
0 siblings, 1 reply; 9+ messages in thread
From: Tzung-Bi Shih @ 2026-10-23 3:05 UTC (permalink / raw)
To: Artem Shimko
Cc: wim, linux, p.zabel, Sergey.Semin, mika.westerberg, andi.shyti,
iav, linux-watchdog, linux-kernel
On Thu, Oct 22, 2026 at 04:43:49PM +0300, Artem Shimko wrote:
> Replace devm_reset_control_get_optional_shared() with
> devm_reset_control_get_optional_shared_deasserted() to let the
> device-managed API handle reset line deassertion and assertion
> automatically.
>
> The driver currently manages the reset control manually: it calls
> reset_control_deassert() during probe and reset_control_assert() in
> error paths and remove. This is error-prone and requires explicit
> cleanup in multiple places.
>
> Switching to the _deasserted variant deasserts the reset line on
> acquisition and asserts it again when the device is removed, which
> allows removing the out_assert_rst label along with the related
> assertions in the probe error paths and in dw_wdt_drv_remove().
>
> Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
With a minor concern shown below,
Reviewed-by: Tzung-Bi Shih <tzungbi@kernel.org>
> diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
> index 39031445d754..2cffe337b4ea 100644
> --- a/drivers/watchdog/dw_wdt.c
> +++ b/drivers/watchdog/dw_wdt.c
> @@ -588,9 +588,9 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
> if (IS_ERR(dw_wdt->pclk))
> return PTR_ERR(dw_wdt->pclk);
>
> - dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
> + dw_wdt->rst = devm_reset_control_get_optional_shared_deasserted(dev, NULL);
> if (IS_ERR(dw_wdt->rst))
> - return PTR_ERR(dw_wdt->rst);
> + return dev_err_probe(dev, PTR_ERR(dw_wdt->rst), "failed to acquire reset\n");
The driver has been "quiet" in probe(). After the change, it starts to be
less quiet.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/3] watchdog: dw_wdt: manage reset line during system suspend/resume
2026-10-22 13:43 [PATCH v2 0/3] watchdog: dw_wdt: fix reset line management Artem Shimko
2026-10-22 13:43 ` [PATCH v2 1/3] watchdog: dw_wdt: use devm_reset_control_get_optional_shared_deasserted Artem Shimko
@ 2026-10-22 13:43 ` Artem Shimko
2026-10-23 3:05 ` Tzung-Bi Shih
2026-10-22 13:43 ` [PATCH v2 3/3] watchdog: dw_wdt: clean up error paths in resume function Artem Shimko
2026-10-22 21:15 ` [PATCH v2 0/3] watchdog: dw_wdt: fix reset line management Igor Velkov
3 siblings, 1 reply; 9+ messages in thread
From: Artem Shimko @ 2026-10-22 13:43 UTC (permalink / raw)
To: wim, linux, p.zabel, Sergey.Semin, mika.westerberg, andi.shyti,
iav
Cc: Artem Shimko, linux-watchdog, linux-kernel
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. Add proper
error handling for reset control operations during resume with appropriate
cleanup path on failure.
Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
---
drivers/watchdog/dw_wdt.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 2cffe337b4ea..ec6a09673da4 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -382,6 +382,8 @@ static int dw_wdt_suspend(struct device *dev)
dw_wdt->control = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET);
dw_wdt->timeout = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
+ reset_control_assert(dw_wdt->rst);
+
clk_disable_unprepare(dw_wdt->pclk);
clk_disable_unprepare(dw_wdt->clk);
@@ -402,12 +404,22 @@ static int dw_wdt_resume(struct device *dev)
return err;
}
+ 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);
dw_wdt_ping(&dw_wdt->wdd);
return 0;
+
+unprepare_pclk:
+ clk_disable_unprepare(dw_wdt->pclk);
+ 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
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/3] watchdog: dw_wdt: manage reset line during system suspend/resume
2026-10-22 13:43 ` [PATCH v2 2/3] watchdog: dw_wdt: manage reset line during system suspend/resume Artem Shimko
@ 2026-10-23 3:05 ` Tzung-Bi Shih
0 siblings, 0 replies; 9+ messages in thread
From: Tzung-Bi Shih @ 2026-10-23 3:05 UTC (permalink / raw)
To: Artem Shimko
Cc: wim, linux, p.zabel, Sergey.Semin, mika.westerberg, andi.shyti,
iav, linux-watchdog, linux-kernel
On Thu, Oct 22, 2026 at 04:43:50PM +0300, Artem Shimko wrote:
> diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
> index 2cffe337b4ea..ec6a09673da4 100644
> --- a/drivers/watchdog/dw_wdt.c
> +++ b/drivers/watchdog/dw_wdt.c
> @@ -382,6 +382,8 @@ static int dw_wdt_suspend(struct device *dev)
> dw_wdt->control = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET);
> dw_wdt->timeout = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
>
> + reset_control_assert(dw_wdt->rst);
> +
Doesn't it need to check the return value and propagate the error just
like what dw_wdt_resume() does in the patch?
> @@ -402,12 +404,22 @@ static int dw_wdt_resume(struct device *dev)
> return err;
> }
>
> + 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);
>
> dw_wdt_ping(&dw_wdt->wdd);
>
> return 0;
> +
> +unprepare_pclk:
> + clk_disable_unprepare(dw_wdt->pclk);
> + clk_disable_unprepare(dw_wdt->clk);
> +
> + return err;
There is only one user of `unprepare_pclk`. Two options:
A) Drop the goto label and inline the cleanup within `if (err) ...`.
B) Refactor error handling for clk_prepare_enable() to use stacked goto
labels.
I just realized [PATCH v2 3/3] actually does option B. Please consider
squashing patch 3/3 into this patch.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/3] watchdog: dw_wdt: clean up error paths in resume function
2026-10-22 13:43 [PATCH v2 0/3] watchdog: dw_wdt: fix reset line management Artem Shimko
2026-10-22 13:43 ` [PATCH v2 1/3] watchdog: dw_wdt: use devm_reset_control_get_optional_shared_deasserted Artem Shimko
2026-10-22 13:43 ` [PATCH v2 2/3] watchdog: dw_wdt: manage reset line during system suspend/resume Artem Shimko
@ 2026-10-22 13:43 ` Artem Shimko
2026-10-23 3:06 ` Tzung-Bi Shih
2026-10-22 21:15 ` [PATCH v2 0/3] watchdog: dw_wdt: fix reset line management Igor Velkov
3 siblings, 1 reply; 9+ messages in thread
From: Artem Shimko @ 2026-10-22 13:43 UTC (permalink / raw)
To: wim, linux, p.zabel, Sergey.Semin, mika.westerberg, andi.shyti,
iav
Cc: Artem Shimko, linux-watchdog, linux-kernel
Clean up of dw_wdt_resume() function.
Rework the error handling to use properly named labels that match the
cleanup order. Use unprepare_clk for clock disable and unprepare_pclk
for pclk disable path.
Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
---
drivers/watchdog/dw_wdt.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index ec6a09673da4..11caf40d6771 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -393,16 +393,15 @@ 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)
@@ -417,6 +416,7 @@ static int dw_wdt_resume(struct device *dev)
unprepare_pclk:
clk_disable_unprepare(dw_wdt->pclk);
+unprepare_clk:
clk_disable_unprepare(dw_wdt->clk);
return err;
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2 3/3] watchdog: dw_wdt: clean up error paths in resume function
2026-10-22 13:43 ` [PATCH v2 3/3] watchdog: dw_wdt: clean up error paths in resume function Artem Shimko
@ 2026-10-23 3:06 ` Tzung-Bi Shih
0 siblings, 0 replies; 9+ messages in thread
From: Tzung-Bi Shih @ 2026-10-23 3:06 UTC (permalink / raw)
To: Artem Shimko
Cc: wim, linux, p.zabel, Sergey.Semin, mika.westerberg, andi.shyti,
iav, linux-watchdog, linux-kernel
On Thu, Oct 22, 2026 at 04:43:51PM +0300, Artem Shimko wrote:
> Clean up of dw_wdt_resume() function.
>
> Rework the error handling to use properly named labels that match the
> cleanup order. Use unprepare_clk for clock disable and unprepare_pclk
> for pclk disable path.
>
> Signed-off-by: Artem Shimko <a.shimko.dev@gmail.com>
See [PATCH v2 2/3]. I'd suggest squashing this patch into [v2 2/3].
> @@ -393,16 +393,15 @@ 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);
This is an additional change, but I think it's fine to squash.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 0/3] watchdog: dw_wdt: fix reset line management
2026-10-22 13:43 [PATCH v2 0/3] watchdog: dw_wdt: fix reset line management Artem Shimko
` (2 preceding siblings ...)
2026-10-22 13:43 ` [PATCH v2 3/3] watchdog: dw_wdt: clean up error paths in resume function Artem Shimko
@ 2026-10-22 21:15 ` Igor Velkov
3 siblings, 0 replies; 9+ messages in thread
From: Igor Velkov @ 2026-10-22 21:15 UTC (permalink / raw)
To: Artem Shimko
Cc: Wim Van Sebroeck, Guenter Roeck, p.zabel, Sergey.Semin,
mika.westerberg, andi.shyti, linux-watchdog, linux-kernel,
Igor Velkov
Tested on Helios64 and ROCK Pi 4A (RK3399) on top of 7.3, with
resets = <&cru SRST_P_WDT0> added to the watchdog node locally (not in
mainline yet). With the watchdog daemon at 60 s timeout, s2idle for 90 s:
3/3 on ROCK Pi 4A and 4/4 on Helios64 without a reset; after resume the
watchdog is alive (killing the daemon without magic close resets the board
after ~60 s on both).
Tested-by: Igor Velkov <iav@iav.lv>
^ permalink raw reply [flat|nested] 9+ messages in thread