[PATCH 2/3] watchdog: rzv2h: Convert WDTDCR handling to regmap
Prabhakar <[email protected]>
| Newsgroups | org.kernel.vger.linux-watchdog,org.kernel.vger.linux-kernel,org.kernel.vger.linux-renesas-soc |
|---|---|
| Message-ID | <[email protected]> |
From: Lad Prabhakar <[email protected]> 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. Signed-off-by: Lad Prabhakar <[email protected]> --- drivers/watchdog/rzv2h_wdt.c | 83 +++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/drivers/watchdog/rzv2h_wdt.c b/drivers/watchdog/rzv2h_wdt.c index e9545b8f5fd0..d0b38450cc32 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,26 +90,20 @@ static int rzv2h_wdt_ping(struct watchdog_device *wdev) return 0; } -static void rzt2h_wdt_wdtdcr_count_ctrl(struct rzv2h_wdt_priv *priv, bool start) +static int rzt2h_wdt_wdtdcr_count_ctrl(struct rzv2h_wdt_priv *priv, bool start) { - u32 reg = readl(priv->wdtdcr + WDTDCR); - - if (start) - reg &= ~WDTDCR_WDTSTOPCTRL; - else - reg |= WDTDCR_WDTSTOPCTRL; - - writel(reg, priv->wdtdcr + WDTDCR); + return regmap_update_bits(priv->wdtdcr_regmap, WDTDCR, WDTDCR_WDTSTOPCTRL, + start ? 0 : WDTDCR_WDTSTOPCTRL); } -static void rzt2h_wdt_wdtdcr_count_stop(struct rzv2h_wdt_priv *priv) +static int rzt2h_wdt_wdtdcr_count_stop(struct rzv2h_wdt_priv *priv) { - rzt2h_wdt_wdtdcr_count_ctrl(priv, false); + return rzt2h_wdt_wdtdcr_count_ctrl(priv, false); } -static void rzt2h_wdt_wdtdcr_count_start(struct rzv2h_wdt_priv *priv) +static int rzt2h_wdt_wdtdcr_count_start(struct rzv2h_wdt_priv *priv) { - rzt2h_wdt_wdtdcr_count_ctrl(priv, true); + return rzt2h_wdt_wdtdcr_count_ctrl(priv, true); } static void rzv2h_wdt_setup(struct watchdog_device *wdev, u16 wdtcr) @@ -158,8 +153,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 @@ -179,8 +180,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); @@ -196,9 +202,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; @@ -242,8 +249,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); @@ -261,24 +277,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) -- 2.54.0