* [PATCH v2] rtc: zynqmp: Enable crystal oscillator when setting time
@ 2026-09-25 5:20 Daniel Viaño
0 siblings, 0 replies; only message in thread
From: Daniel Viaño @ 2026-09-25 5:20 UTC (permalink / raw)
To: Alexandre Belloni
Cc: Michal Simek, linux-rtc, linux-arm-kernel, linux-kernel,
Daniel Viaño, stable
The RTC_OSC_EN macro was defined when the driver was originally
introduced, but was never asserted by the driver. On cold boots, after
battery exhaustion, or on platforms where firmware does not configure
RTC_CTRL, the oscillator remains disabled and the counter never ticks.
Unconditionally enabling the oscillator during driver initialization
would cause the RTC to free-run from an uninitialized or stale counter
value, reporting an untrusted time to userspace. Instead, keep the
oscillator disabled until a valid time is programmed: guard
xlnx_rtc_read_time() on RTC_OSC_EN and return -EINVAL when it is not
set, and assert RTC_OSC_EN in xlnx_rtc_set_time() once valid time is
programmed so the RTC can free-run.
Per the Zynq UltraScale+ TRM (UG1085), bit 24 (OSC_CNTRL) is a static
level enable for the crystal inverter rather than an edge-triggered reset;
asserting it from set_time() is non-destructive and will not glitch an
already-running oscillator.
Tested on Zynq UltraScale+ hardware, confirming that read_time returns
-EINVAL while the oscillator is disabled, and advances reliably after
setting time.
Fixes: 11143c19eb57 ("rtc: add xilinx zynqmp rtc driver")
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Viaño <danividanivi@gmail.com>
---
v2:
- Leave xlnx_init_rtc() unchanged so the oscillator is not enabled on probe
- Return -EINVAL in xlnx_rtc_read_time() when RTC_OSC_EN is not set
- Enable RTC_OSC_EN in xlnx_rtc_set_time() once valid time is programmed
drivers/rtc/rtc-zynqmp.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
index 5bcb7536e973..6c3ba8f1aa57 100644
--- a/drivers/rtc/rtc-zynqmp.c
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -59,6 +59,8 @@ static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
unsigned long new_time;
+ u32 rtc_ctrl;
+
/*
* The value written will be updated after 1 sec into the
* seconds read register, so we need to program time +1 sec
@@ -78,6 +80,14 @@ static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
*/
writel(RTC_INT_SEC, xrtcdev->reg_base + RTC_INT_STS);
+ /*
+ * Now that the time is valid, start the crystal oscillator so the
+ * RTC free-runs.
+ */
+ rtc_ctrl = readl(xrtcdev->reg_base + RTC_CTRL);
+ rtc_ctrl |= RTC_OSC_EN;
+ writel(rtc_ctrl, xrtcdev->reg_base + RTC_CTRL);
+
return 0;
}
@@ -87,6 +97,9 @@ static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm)
unsigned long read_time;
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+ if (!(readl(xrtcdev->reg_base + RTC_CTRL) & RTC_OSC_EN))
+ return -EINVAL;
+
status = readl(xrtcdev->reg_base + RTC_INT_STS);
if (status & RTC_INT_SEC) {
--
2.53.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-25 5:21 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-25 5:20 [PATCH v2] rtc: zynqmp: Enable crystal oscillator when setting time Daniel Viaño
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®