[PATCH v6 2/8] watchdog: rzv2h: Drop enabling clocks in the restart handler

From: Prabhakar

Date: Wed Sep 23 2026 - 06:56:12 EST


From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>

The watchdog restart handler runs from do_kernel_restart() with
interrupts disabled and after smp_send_stop() has halted the other CPUs.
Calling clk_enable() from the !watchdog_active() path takes the clock
framework's global enable_lock. If a stopped CPU held this lock, the
CPU executing the restart handler can spin indefinitely and prevent the
watchdog from resetting the system.

Keep pclk and oscclk enabled for the lifetime of the watchdog device by
using devm_clk_get_enabled() and devm_clk_get_optional_enabled().
Remove the conditional clock enable/disable operations from the restart
handler so it does not acquire any clock framework locks.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v5->v6:
- No change

v4->v5:
- New patch
---
drivers/watchdog/rzv2h_wdt.c | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/watchdog/rzv2h_wdt.c b/drivers/watchdog/rzv2h_wdt.c
index 057b890de0b0..ee1649e0edae 100644
--- a/drivers/watchdog/rzv2h_wdt.c
+++ b/drivers/watchdog/rzv2h_wdt.c
@@ -191,22 +191,9 @@ static int rzv2h_wdt_restart(struct watchdog_device *wdev,
int ret;

if (!watchdog_active(wdev)) {
- ret = clk_enable(priv->pclk);
- if (ret)
- return ret;
-
- ret = clk_enable(priv->oscclk);
- if (ret) {
- clk_disable(priv->pclk);
- return ret;
- }
-
ret = reset_control_deassert(priv->rstc);
- if (ret) {
- clk_disable(priv->oscclk);
- clk_disable(priv->pclk);
+ if (ret)
return ret;
- }
} else {
/*
* Writing to the WDT Control Register (WDTCR) or WDT Reset
@@ -291,11 +278,11 @@ static int rzv2h_wdt_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);

- priv->pclk = devm_clk_get_prepared(dev, "pclk");
+ priv->pclk = devm_clk_get_enabled(dev, "pclk");
if (IS_ERR(priv->pclk))
return dev_err_probe(dev, PTR_ERR(priv->pclk), "Failed to get pclk\n");

- priv->oscclk = devm_clk_get_optional_prepared(dev, "oscclk");
+ priv->oscclk = devm_clk_get_optional_enabled(dev, "oscclk");
if (IS_ERR(priv->oscclk))
return dev_err_probe(dev, PTR_ERR(priv->oscclk), "Failed to get oscclk\n");

--
2.55.0