[PATCH v5 11/17] rtc: rzn1: Dynamically calculate synchronization delay based on clock rate
Prabhakar <[email protected]>
| Newsgroups | org.kernel.vger.linux-rtc,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel,org.kernel.vger.linux-renesas-soc |
|---|---|
| Message-ID | <[email protected]> |
From: Lad Prabhakar <[email protected]> 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 <[email protected]> Reviewed-by: Wolfram Sang <[email protected]> Tested-by: Wolfram Sang <[email protected]> --- v4->v5: - Added Reviewed-by and Tested-by tags from Wolfram. 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 02d720e95a7f..2e5d2460d79d 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) @@ -397,10 +398,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); @@ -450,12 +451,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