[PATCH v8 1/7] clk: renesas: r9a09g077: Add helper to start WDTDCR counter
From: Prabhakar
Date: Thu Oct 01 2026 - 12:58:42 EST
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
The WDTDCRm registers are not suitable for access through the SYSC regmap
from atomic or panic context, as regmap locking can deadlock when another
CPU holding the lock has already stopped.
Add a lockless helper to clear WDTDCRm.WDTSTOPCTRL and start the watchdog
counter using the existing SYSC register accessors.
Export the helper in the RZT2H_CPG namespace for use by the watchdog
driver.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v7->v8:
- No change
v6->v7:
- New patch
---
drivers/clk/renesas/r9a09g077-cpg.c | 35 ++++++++++++++++++++++++-----
include/linux/clk/renesas.h | 6 +++++
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c
index 5a0e7df1eb06..90f0c373976f 100644
--- a/drivers/clk/renesas/r9a09g077-cpg.c
+++ b/drivers/clk/renesas/r9a09g077-cpg.c
@@ -12,6 +12,7 @@
#include <linux/clk-provider.h>
#include <linux/clk/renesas.h>
#include <linux/device.h>
+#include <linux/export.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@@ -103,10 +104,17 @@ MODULE_IMPORT_NS("RZV2H_CPG");
#define RZT2H_SYSC_BLOCK(x) FIELD_GET(RZT2H_SYSC_BLOCK_MASK, x)
#define RZT2H_SYSC_REG_OFFSET(x) FIELD_GET(RZT2H_SYSC_OFFSET_MASK, x)
+/* WDT Debug Control Registers (WDTDCRm), in the block 1 SYSC region */
+#define RZT2H_WDTDCR(n) (RZT2H_SYSC_BLOCK_MASK | (0x5100 + (n) * 4))
+#define RZT2H_WDTDCR_WDTSTOPCTRL BIT(0)
+#define RZT2H_WDT_MAX_INSTANCES 6
+
struct r9a09g077_sysc_reg {
void __iomem *base[2];
};
+static struct r9a09g077_sysc_reg *r9a09g077_sysc_regs;
+
enum rzt2h_clk_types {
CLK_TYPE_RZT2H_DIV = CLK_TYPE_CUSTOM, /* Clock with divider */
CLK_TYPE_RZT2H_MUX, /* Clock with clock source selector */
@@ -963,10 +971,25 @@ static bool r9a09g077_writeable_readable_sysc(struct device *dev, unsigned int r
}
}
+void rzt2h_cpg_wdtdcr_count_start(unsigned int wdt_index)
+{
+ struct r9a09g077_sysc_reg *sysc = r9a09g077_sysc_regs;
+ unsigned int reg, val;
+
+ /* Sanity check: ensure sysc is initialized and wdt_index is valid */
+ if (!sysc || wdt_index >= RZT2H_WDT_MAX_INSTANCES)
+ return;
+
+ reg = RZT2H_WDTDCR(wdt_index);
+ r9a09g077_regmap_read(sysc, reg, &val);
+ val &= ~RZT2H_WDTDCR_WDTSTOPCTRL;
+ r9a09g077_regmap_write(sysc, reg, val);
+}
+EXPORT_SYMBOL_NS_GPL(rzt2h_cpg_wdtdcr_count_start, "RZT2H_CPG");
+
static int r9a09g077_post_init(struct device *dev, struct cpg_mssr_pub *pub)
{
struct regmap_config *regmap_cfg __free(kfree) = kzalloc_obj(*regmap_cfg);
- struct r9a09g077_sysc_reg *sysc_reg;
struct regmap *regmap;
struct resource res;
int ret;
@@ -991,13 +1014,13 @@ static int r9a09g077_post_init(struct device *dev, struct cpg_mssr_pub *pub)
if (!regmap_cfg)
return -ENOMEM;
- sysc_reg = devm_kzalloc(dev, sizeof(*sysc_reg), GFP_KERNEL);
- if (!sysc_reg)
+ r9a09g077_sysc_regs = devm_kzalloc(dev, sizeof(*r9a09g077_sysc_regs), GFP_KERNEL);
+ if (!r9a09g077_sysc_regs)
return -ENOMEM;
/* Only allow access in the SYSC regions */
- sysc_reg->base[0] = pub->base0 + RZT2H_SYSC_OFFSET;
- sysc_reg->base[1] = pub->base1 + RZT2H_SYSC_OFFSET;
+ r9a09g077_sysc_regs->base[0] = pub->base0 + RZT2H_SYSC_OFFSET;
+ r9a09g077_sysc_regs->base[1] = pub->base1 + RZT2H_SYSC_OFFSET;
regmap_cfg->name = "rzt2h_sysc";
regmap_cfg->reg_bits = 32;
@@ -1008,7 +1031,7 @@ static int r9a09g077_post_init(struct device *dev, struct cpg_mssr_pub *pub)
regmap_cfg->readable_reg = r9a09g077_writeable_readable_sysc;
regmap_cfg->writeable_reg = r9a09g077_writeable_readable_sysc;
- regmap = devm_regmap_init(dev, &r9a09g077_sys_regmap_bus, sysc_reg, regmap_cfg);
+ regmap = devm_regmap_init(dev, &r9a09g077_sys_regmap_bus, r9a09g077_sysc_regs, regmap_cfg);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h
index c9495558cd5c..1e171db25eb7 100644
--- a/include/linux/clk/renesas.h
+++ b/include/linux/clk/renesas.h
@@ -216,4 +216,10 @@ static inline bool rzv2h_cpg_get_pll_divs_pars(const struct rzv2h_pll_limits *li
#define rzv2h_get_pll_pars rzv2h_cpg_get_pll_pars
#define rzv2h_get_pll_divs_pars rzv2h_cpg_get_pll_divs_pars
+#if defined(CONFIG_CLK_R9A09G077) || defined(CONFIG_CLK_R9A09G087)
+void rzt2h_cpg_wdtdcr_count_start(unsigned int wdt_index);
+#else
+static inline void rzt2h_cpg_wdtdcr_count_start(unsigned int wdt_index) { }
+#endif
+
#endif
--
2.55.0