[PATCH v5 3/8] watchdog: rzv2h: Propagate WDTDCR access errors
From: Prabhakar
Date: Fri Sep 11 2026 - 07:18:50 EST
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
The WDTDCR helpers access the register directly using readl()/writel() and
therefore cannot report failures to their callers. WDTDCR is located in a
shared syscon region and will be accessed through regmap in a subsequent
change, where register accesses can fail.
Make rzt2h_wdt_wdtdcr_count_start() and rzt2h_wdt_wdtdcr_count_stop()
return an error so their callers can propagate failures.
Handle these errors in the watchdog start and stop paths and unwind the
resources acquired before the WDTDCR access, restoring the reset state.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v4->v5:
- Dropped checking rzt2h_wdt_wdtdcr_count_start() return value in
restart path.
v2->v3:
- New patch, split from v2 patch #1 to make thing easier to review.
---
drivers/watchdog/rzv2h_wdt.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/drivers/watchdog/rzv2h_wdt.c b/drivers/watchdog/rzv2h_wdt.c
index 7c6a4855bd8a..cbf414e0c9a3 100644
--- a/drivers/watchdog/rzv2h_wdt.c
+++ b/drivers/watchdog/rzv2h_wdt.c
@@ -87,18 +87,22 @@ static int rzv2h_wdt_ping(struct watchdog_device *wdev)
return 0;
}
-static void rzt2h_wdt_wdtdcr_count_stop(struct rzv2h_wdt_priv *priv)
+static int rzt2h_wdt_wdtdcr_count_stop(struct rzv2h_wdt_priv *priv)
{
u32 reg = readl(priv->wdtdcr + WDTDCR);
writel(reg | WDTDCR_WDTSTOPCTRL, priv->wdtdcr + WDTDCR);
+
+ return 0;
}
-static void rzt2h_wdt_wdtdcr_count_start(struct rzv2h_wdt_priv *priv)
+static int rzt2h_wdt_wdtdcr_count_start(struct rzv2h_wdt_priv *priv)
{
u32 reg = readl(priv->wdtdcr + WDTDCR);
writel(reg & ~WDTDCR_WDTSTOPCTRL, priv->wdtdcr + WDTDCR);
+
+ return 0;
}
static void rzv2h_wdt_setup(struct watchdog_device *wdev, u16 wdtcr)
@@ -148,8 +152,14 @@ static int rzv2h_wdt_start(struct watchdog_device *wdev)
rzv2h_wdt_setup(wdev, of_data->cks_max | WDTCR_RPSS_100 |
WDTCR_RPES_0 | of_data->tops);
- if (priv->of_data->wdtdcr)
- rzt2h_wdt_wdtdcr_count_start(priv);
+ if (priv->of_data->wdtdcr) {
+ ret = rzt2h_wdt_wdtdcr_count_start(priv);
+ if (ret) {
+ reset_control_assert(priv->rstc);
+ pm_runtime_put(wdev->parent);
+ return ret;
+ }
+ }
/*
* Down counting starts after writing the sequence 00h -> FFh to the
@@ -169,8 +179,13 @@ static int rzv2h_wdt_stop(struct watchdog_device *wdev)
if (ret)
return ret;
- if (priv->of_data->wdtdcr)
- rzt2h_wdt_wdtdcr_count_stop(priv);
+ if (priv->of_data->wdtdcr) {
+ ret = rzt2h_wdt_wdtdcr_count_stop(priv);
+ if (ret) {
+ reset_control_deassert(priv->rstc);
+ return ret;
+ }
+ }
pm_runtime_put(wdev->parent);
@@ -219,8 +234,10 @@ static int rzv2h_wdt_restart(struct watchdog_device *wdev,
rzv2h_wdt_setup(wdev, priv->of_data->cks_min | WDTCR_RPSS_25 |
WDTCR_RPES_75 | WDTCR_TOPS_1024);
- if (priv->of_data->wdtdcr)
+ if (priv->of_data->wdtdcr) {
+ /* best effort, ignore ret */
rzt2h_wdt_wdtdcr_count_start(priv);
+ }
rzv2h_wdt_ping(wdev);
@@ -251,11 +268,11 @@ static int rzt2h_wdt_wdtdcr_init(struct platform_device *pdev,
if (ret)
return ret;
- rzt2h_wdt_wdtdcr_count_stop(priv);
+ ret = rzt2h_wdt_wdtdcr_count_stop(priv);
pm_runtime_put(&pdev->dev);
- return 0;
+ return ret;
}
static int rzv2h_wdt_probe(struct platform_device *pdev)
--
2.55.0