mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 14:04:27 -04:00
rtc: rzn1: Dynamically calculate synchronization delay based on clock rate
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@bp.renesas.com> Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Link: https://patch.msgid.link/20260821211032.13554-12-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
committed by
Alexandre Belloni
parent
6e0d7d480f
commit
afb8972b9e
@@ -70,6 +70,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)
|
||||
@@ -120,8 +121,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)
|
||||
@@ -398,10 +399,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);
|
||||
@@ -451,12 +452,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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user