Re: [PATCH v2 1/2] watchdog: rzv2h: Convert WDTDCR handling to regmap
From: Guenter Roeck
Date: Mon Jul 20 2026 - 11:17:57 EST
On Wed, Jul 15, 2026 at 02:39:21PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
>
> Convert the WDTDCR register access from raw readl/writel variants over to
> the regmap framework using devm_regmap_init_mmio().
>
> This conversion serves as a preparatory refactoring step. It allows the
> driver to subsequently support syscon-based system controllers natively
> by passing along alternative regmap handles without forcing messy
> architectural branching at runtime.
>
This patch does a bit more than just converting the driver to use regmap.
It also modifies both reset control handling and runtime pm handling in
the start, stop, and restart function error handlers. Those changes need
to be implemented in separate patches and explained. When doing that,
please address Sashiko's feedback or explain why the issues it reported
are of no concern.
Thanks,
Guenter
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
> ---
> v1->v2:
> - Switched to use regmap_set/clear_bits()
> ---
> drivers/watchdog/rzv2h_wdt.c | 75 ++++++++++++++++++++++++++----------
> 1 file changed, 54 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/watchdog/rzv2h_wdt.c b/drivers/watchdog/rzv2h_wdt.c
> index 3b6abb66a1da..0f951219caf8 100644
> --- a/drivers/watchdog/rzv2h_wdt.c
> +++ b/drivers/watchdog/rzv2h_wdt.c
> @@ -12,6 +12,7 @@
> #include <linux/of.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> #include <linux/reset.h>
> #include <linux/units.h>
> #include <linux/watchdog.h>
> @@ -67,7 +68,7 @@ struct rzv2h_of_data {
>
> struct rzv2h_wdt_priv {
> void __iomem *base;
> - void __iomem *wdtdcr;
> + struct regmap *wdtdcr_regmap;
> struct clk *pclk;
> struct clk *oscclk;
> struct reset_control *rstc;
> @@ -89,18 +90,14 @@ 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 regmap_set_bits(priv->wdtdcr_regmap, WDTDCR, WDTDCR_WDTSTOPCTRL);
> }
>
> -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 regmap_clear_bits(priv->wdtdcr_regmap, WDTDCR, WDTDCR_WDTSTOPCTRL);
> }
>
> static void rzv2h_wdt_setup(struct watchdog_device *wdev, u16 wdtcr)
> @@ -150,8 +147,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
> @@ -171,8 +174,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);
>
> @@ -188,9 +196,10 @@ static int rzv2h_wdt_restart(struct watchdog_device *wdev,
> unsigned long action, void *data)
> {
> struct rzv2h_wdt_priv *priv = watchdog_get_drvdata(wdev);
> + bool active = watchdog_active(wdev);
> int ret;
>
> - if (!watchdog_active(wdev)) {
> + if (!active) {
> ret = clk_enable(priv->pclk);
> if (ret)
> return ret;
> @@ -234,8 +243,17 @@ 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)
> - rzt2h_wdt_wdtdcr_count_start(priv);
> + if (priv->of_data->wdtdcr) {
> + ret = rzt2h_wdt_wdtdcr_count_start(priv);
> + if (ret) {
> + if (!active) {
> + reset_control_assert(priv->rstc);
> + clk_disable(priv->oscclk);
> + clk_disable(priv->pclk);
> + }
> + return ret;
> + }
> + }
>
> rzv2h_wdt_ping(wdev);
>
> @@ -253,24 +271,39 @@ static const struct watchdog_ops rzv2h_wdt_ops = {
> .restart = rzv2h_wdt_restart,
> };
>
> +static const struct regmap_config rzv2h_wdtdcr_regmap_config = {
> + .name = "wdtdcr",
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = WDTDCR,
> + .fast_io = true,
> +};
> +
> static int rzt2h_wdt_wdtdcr_init(struct platform_device *pdev,
> struct rzv2h_wdt_priv *priv)
> {
> + void __iomem *wdtdcr;
> int ret;
>
> - priv->wdtdcr = devm_platform_ioremap_resource(pdev, 1);
> - if (IS_ERR(priv->wdtdcr))
> - return PTR_ERR(priv->wdtdcr);
> + wdtdcr = devm_platform_ioremap_resource(pdev, 1);
> + if (IS_ERR(wdtdcr))
> + return PTR_ERR(wdtdcr);
> +
> + 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);
>
> ret = pm_runtime_resume_and_get(&pdev->dev);
> 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)