[PATCH v4 09/15] rtc: rzn1: Dynamically calculate synchronization delay based on clock rate

From: Prabhakar

Date: Wed Aug 19 2026 - 06:42:27 EST


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

Replace the hardcoded hardware synchronization delays with a calculated
time window derived from the operating sub-clock frequency.

The driver currently hardcodes microsecond ranges assuming a fixed
sub-clock frequency of 32.768 kHz. Newer SoC variants, such as the
RZ/T2H, drive this hardware block using a much faster clock rate
(~195.3 kHz). Hardcoding these wait windows forces faster blocks to
over-sleep, introducing unnecessary delays during clock initialization
and register configuration.

Calculate the duration of the required clock cycles in microseconds based
on the runtime clock rate, and store this value in the driver private
structure to adjust the usleep_range() and readl_poll_timeout() boundaries
dynamically.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v3->v4:
- Shortened the comment describing the calculation of RTC_PCLK.
- Updated usleep_range() value to use 2 * rtc->sync_time.

v2->v3:
- No changes.

v1->v2:
- Initialized rate variable to 32768 to avoid timeout_us of 0.
---
drivers/rtc/rtc-rzn1.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c
index 425d9590c55b..9eceeed14486 100644
--- a/drivers/rtc/rtc-rzn1.c
+++ b/drivers/rtc/rtc-rzn1.c
@@ -69,6 +69,7 @@ struct rzn1_rtc {
*/
spinlock_t ctl1_access_lock;
struct rtc_time tm_alarm;
+ unsigned long sync_time;
};

static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm)
@@ -119,8 +120,8 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* Hold the counter if it was counting up */
writel(RZN1_RTC_CTL2_WAIT, rtc->base + RZN1_RTC_CTL2);

- /* Wait for the counter to stop: two 32k clock cycles */
- usleep_range(61, 100);
+ /* Wait 2-4 RTC_PCLK clock cycles for the counter to stop */
+ usleep_range(rtc->sync_time, rtc->sync_time * 2);
ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, val,
val & RZN1_RTC_CTL2_WST, 0, 100);
if (ret)
@@ -384,10 +385,10 @@ static void rzn1_rtc_disable_hardware(void *data)

static int rzn1_rtc_probe(struct platform_device *pdev)
{
+ unsigned long rate = 32768;
struct rzn1_rtc *rtc;
u32 val, scmp_val = 0;
struct clk *xtal;
- unsigned long rate;
int irq, ret;

rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@@ -437,12 +438,16 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
scmp_val = RZN1_RTC_CTL0_SLSB_SCMP;
}

+ /* Calculate the duration of two RTC_PCLK clock cycles */
+ rtc->sync_time = DIV_ROUND_UP(2 * USEC_PER_SEC, rate);
+
/* Disable controller during SUBU/SCMP setup */
val = readl(rtc->base + RZN1_RTC_CTL0) & ~RZN1_RTC_CTL0_CE;
writel(val, rtc->base + RZN1_RTC_CTL0);
- /* Wait 2-4 32k clock cycles for the disabled controller */
+ /* Wait 2-4 RTC_PCLK clock cycles for the disabled controller to stop */
ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL0, val,
- !(val & RZN1_RTC_CTL0_CEST), 62, 123);
+ !(val & RZN1_RTC_CTL0_CEST), rtc->sync_time,
+ rtc->sync_time * 2);
if (ret)
return ret;

--
2.43.0