[PATCH v4 13/15] rtc: rzn1: Add OF match data to gate SUBU register access

From: Prabhakar

Date: Wed Aug 19 2026 - 06:44:02 EST


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

The RZ/N1 RTC driver selects SCMP mode only when an optional xtal clock
is provided at a valid rate other than 32768 Hz. Without an xtal clock,
or when it runs at 32768 Hz, the driver uses SUBU mode.

However, the RTCA0SUBU register used by SUBU mode is not present on all
SoCs that integrate a similar variant of the RTC block. Allowing SUBU
mode on those variants would expose RTC offset operations that access a
non-existent register.

Add OF match data to describe whether the RTC supports the SUBU register.
Reject probe with -EOPNOTSUPP when SUBU mode would be selected on a
variant without SUBU support.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v3->v4:
- New patch
---
drivers/rtc/rtc-rzn1.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c
index 02cff5fe117a..202840eb86a6 100644
--- a/drivers/rtc/rtc-rzn1.c
+++ b/drivers/rtc/rtc-rzn1.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/iopoll.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/rtc.h>
@@ -65,6 +66,10 @@
#define RZN1_RTC_TIMEC 0x68
#define RZN1_RTC_CALC 0x6c

+struct rzn1_rtc_data {
+ bool has_subu;
+};
+
struct rzn1_rtc {
struct rtc_device *rtcdev;
void __iomem *base;
@@ -391,6 +396,7 @@ static void rzn1_rtc_disable_hardware(void *data)

static int rzn1_rtc_probe(struct platform_device *pdev)
{
+ const struct rzn1_rtc_data *data;
struct device *dev = &pdev->dev;
unsigned long rate = 32768;
struct rzn1_rtc *rtc;
@@ -398,6 +404,10 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
struct clk *xtal;
int irq, ret;

+ data = of_device_get_match_data(dev);
+ if (!data)
+ return -ENODEV;
+
rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
@@ -445,6 +455,9 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
scmp_val = RZN1_RTC_CTL0_SLSB_SCMP;
}

+ if (!scmp_val && !data->has_subu)
+ return -EOPNOTSUPP;
+
/* Calculate the duration of two RTC_PCLK clock cycles */
rtc->sync_time = DIV_ROUND_UP(2 * USEC_PER_SEC, rate);

@@ -495,8 +508,12 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
return devm_rtc_register_device(rtc->rtcdev);
}

+static const struct rzn1_rtc_data rzn1_data = {
+ .has_subu = true,
+};
+
static const struct of_device_id rzn1_rtc_of_match[] = {
- { .compatible = "renesas,rzn1-rtc" },
+ { .compatible = "renesas,rzn1-rtc", .data = &rzn1_data },
{},
};
MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match);
--
2.43.0