[PATCH v3 6/8] watchdog: rzv2h: Add syscon support for WDTDCR

From: Prabhakar

Date: Thu Jul 16 2026 - 08:42:59 EST


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

On RZ/T2H and RZ/N2H SoCs, the WDTDCR (WDT Debug Control Register) resides
in the second register region of the CPG/MSSR block. Since this
multi-function block is shared with other peripherals, it is exposed via a
syscon regmap interface.

Look up the SYSC regmap using the optional "renesas,sysc" property and
derive the WDTDCR offset from the watchdog instance index.

Retain the existing MMIO-based access method when the "renesas,sysc"
property is absent to preserve compatibility with existing DT's.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v2->v3:
- Made use of the new "renesas,sysc" phandle-array property to access the
WDTDCR register via the CPG/MSSR syscon node.
- Updated commit message

v1->v2:
- No change.
---
drivers/watchdog/Kconfig | 1 +
drivers/watchdog/rzv2h_wdt.c | 56 +++++++++++++++++++++++++++++-------
2 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 9f013d774897..9267fd74bfb2 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1036,6 +1036,7 @@ config RENESAS_RZV2HWDT
depends on ARCH_RENESAS || COMPILE_TEST
depends on PM || COMPILE_TEST
select WATCHDOG_CORE
+ select MFD_SYSCON
help
This driver adds watchdog support for the integrated watchdogs in the
Renesas RZ/{G3E,V2H(P)} SoCs. These watchdogs can be used to reset a
diff --git a/drivers/watchdog/rzv2h_wdt.c b/drivers/watchdog/rzv2h_wdt.c
index 3c8739902ec4..58daa6b6e3e0 100644
--- a/drivers/watchdog/rzv2h_wdt.c
+++ b/drivers/watchdog/rzv2h_wdt.c
@@ -8,6 +8,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -44,6 +45,11 @@

#define WDT_DEFAULT_TIMEOUT 60U

+#define RZT2H_WDT_MAX_INSTANCES 6
+
+#define RZT2H_SYS_BLOCK1(n) (BIT(16) | (0x5100 + (n) * 4))
+#define RZT2H_WDTDCR_OFFSET(n) RZT2H_SYS_BLOCK1(n)
+
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
@@ -64,14 +70,19 @@ struct rzv2h_of_data {
bool wdtdcr;
};

+struct rzv2h_sysc_wdtdcr {
+ struct regmap *regmap;
+ unsigned int offset;
+};
+
struct rzv2h_wdt_priv {
void __iomem *base;
- struct regmap *wdtdcr_regmap;
struct clk *pclk;
struct clk *oscclk;
struct reset_control *rstc;
struct watchdog_device wdev;
const struct rzv2h_of_data *of_data;
+ struct rzv2h_sysc_wdtdcr sysc;
};

static int rzv2h_wdt_ping(struct watchdog_device *wdev)
@@ -90,12 +101,16 @@ static int rzv2h_wdt_ping(struct watchdog_device *wdev)

static int rzt2h_wdt_wdtdcr_count_stop(struct rzv2h_wdt_priv *priv)
{
- return regmap_set_bits(priv->wdtdcr_regmap, WDTDCR, WDTDCR_WDTSTOPCTRL);
+ struct rzv2h_sysc_wdtdcr *sysc = &priv->sysc;
+
+ return regmap_set_bits(sysc->regmap, sysc->offset, WDTDCR_WDTSTOPCTRL);
}

static int rzt2h_wdt_wdtdcr_count_start(struct rzv2h_wdt_priv *priv)
{
- return regmap_clear_bits(priv->wdtdcr_regmap, WDTDCR, WDTDCR_WDTSTOPCTRL);
+ struct rzv2h_sysc_wdtdcr *sysc = &priv->sysc;
+
+ return regmap_clear_bits(sysc->regmap, sysc->offset, WDTDCR_WDTSTOPCTRL);
}

static void rzv2h_wdt_setup(struct watchdog_device *wdev, u16 wdtcr)
@@ -281,17 +296,36 @@ static const struct regmap_config rzv2h_wdtdcr_regmap_config = {
static int rzt2h_wdt_wdtdcr_init(struct platform_device *pdev,
struct rzv2h_wdt_priv *priv)
{
- void __iomem *wdtdcr;
+ struct device_node *np = pdev->dev.of_node;
+ bool syscon_present = of_property_present(np, "renesas,sysc");
+ struct rzv2h_sysc_wdtdcr *sysc = &priv->sysc;
int ret;

- wdtdcr = devm_platform_ioremap_resource(pdev, 1);
- if (IS_ERR(wdtdcr))
- return PTR_ERR(wdtdcr);
+ if (syscon_present) {
+ unsigned int wdt_index;

- priv->wdtdcr_regmap = devm_regmap_init_mmio(&pdev->dev, wdtdcr,
- &rzv2h_wdtdcr_regmap_config);
- if (IS_ERR(priv->wdtdcr_regmap))
- return PTR_ERR(priv->wdtdcr_regmap);
+ sysc->regmap = syscon_regmap_lookup_by_phandle_args(np, "renesas,sysc",
+ 1, &wdt_index);
+ if (IS_ERR(sysc->regmap))
+ return PTR_ERR(sysc->regmap);
+
+ if (wdt_index >= RZT2H_WDT_MAX_INSTANCES)
+ return -EINVAL;
+
+ sysc->offset = RZT2H_WDTDCR_OFFSET(wdt_index);
+ } else {
+ void __iomem *wdtdcr;
+
+ wdtdcr = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(wdtdcr))
+ return PTR_ERR(wdtdcr);
+
+ sysc->regmap = devm_regmap_init_mmio(&pdev->dev, wdtdcr,
+ &rzv2h_wdtdcr_regmap_config);
+ if (IS_ERR(sysc->regmap))
+ return PTR_ERR(sysc->regmap);
+ sysc->offset = WDTDCR;
+ }

ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret)
--
2.54.0