[PATCH v2] rtc: zynqmp: Add clock framework support with calibration fallback
Vinay Tilak, Pranav
Pranav.VinayTilak at amd.com
Mon Jan 19 13:33:36 CET 2026
[Public]
Hi @Tomas Melin,
> -----Original Message-----
> From: Tomas Melin <tomas.melin at vaisala.com>
> Sent: Friday, January 16, 2026 11:12 AM
> To: u-boot at lists.denx.de; Vinay Tilak, Pranav <Pranav.VinayTilak at amd.com>
> Cc: git (AMD-Xilinx) <git at amd.com>; Simek, Michal
> <michal.simek at amd.com>; Begari, Padmarao
> <Padmarao.Begari at amd.com>
> Subject: Re: [PATCH v2] rtc: zynqmp: Add clock framework support with
> calibration fallback
>
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
>
>
> Hi,
>
>
> On 14/01/2026 13:25, Pranav Tilak wrote:
> > [Some people who received this message don't often get email from
> > pranav.vinaytilak at amd.com. Learn why this is important at
> > https://aka.ms/LearnAboutSenderIdentification ]
> >
> > Add support for reading RTC clock from device tree using clock
> > framework also update the default calibration value to 0x7FFF as per
> > RTC specifications.
> > Falls back to 'calibration' property if clock unavailable, and uses
> > default calibration if neither is present. Only writes calibration
> > when hardware register reads zero.
> >
> > Signed-off-by: Pranav Tilak <pranav.vinaytilak at amd.com>
> > ---
> > Changes in v2:
> > - Rename variable from clk_freq to calibval
> > - Handle case where clock node exists but has no clock-frequency
> > property
> > - Treat invalid clock frequency as error instead of warning
> > - Move calibration validation outside if-else to apply to all code
> > paths
> >
> > drivers/rtc/zynqmp_rtc.c | 64
> > +++++++++++++++++++++++++++-------------
> > 1 file changed, 44 insertions(+), 20 deletions(-)
> >
> > diff --git a/drivers/rtc/zynqmp_rtc.c b/drivers/rtc/zynqmp_rtc.c index
> > 15122a04838..938da4c0569 100644
> > --- a/drivers/rtc/zynqmp_rtc.c
> > +++ b/drivers/rtc/zynqmp_rtc.c
> > @@ -8,23 +8,27 @@
> > #include <dm.h>
> > #include <rtc.h>
> > #include <asm/io.h>
> > +#include <clk.h>
> > +#include <dm/device_compat.h>
> Please keep include statements alpanumerically sorted.
Okay will update in v3.
>
> >
> > /* RTC Registers */
> > #define RTC_SET_TM_WR 0x00
> > #define RTC_SET_TM_RD 0x04
> > #define RTC_CALIB_WR 0x08
> > +#define RTC_CALIB_RD 0x0C
> > #define RTC_CUR_TM 0x10
> > #define RTC_INT_STS 0x20
> > #define RTC_CTRL 0x40
> >
> > #define RTC_INT_SEC BIT(0)
> > #define RTC_BATT_EN BIT(31)
> > -#define RTC_CALIB_DEF 0x198233
> > +#define RTC_CALIB_DEF 0x7FFF
> > +#define RTC_FREQ_MAX 0x10000
> > #define RTC_CALIB_MASK 0x1FFFFF
> >
> > struct zynqmp_rtc_priv {
> > fdt_addr_t base;
> > - unsigned int calibval;
> > + unsigned long calibval;
> > };
> >
> > static int zynqmp_rtc_get(struct udevice *dev, struct rtc_time *tm)
> > @@ -70,13 +74,6 @@ static int zynqmp_rtc_set(struct udevice *dev, const
> struct rtc_time *tm)
> > */
> > new_time = rtc_mktime(tm) + 1;
> >
> > - /*
> > - * Writing into calibration register will clear the Tick Counter and
> > - * force the next second to be signaled exactly in 1 second period
> > - */
> > - priv->calibval &= RTC_CALIB_MASK;
> > - writel(priv->calibval, (priv->base + RTC_CALIB_WR));
> > -
> Is this change directly related to adding clock framework support or should it
> be split to separate patch? Atleast needs mention in commit message why this
> change is done, looking at the comment it looks like it has handled special
> case.
This change is directly related to the clock framework support. The old code wrote calibration on every time set, but since calibration is now dynamically sourced from clock framework or DT during probe, it only needs to be written once at initialization.
I'll update the commit message in v3 to mention this change.
>
> Thanks,
> Tomas
>
> > writel(new_time, priv->base + RTC_SET_TM_WR);
> >
> > /*
> > @@ -107,15 +104,6 @@ static int zynqmp_rtc_init(struct udevice *dev)
> > rtc_ctrl |= RTC_BATT_EN;
> > writel(rtc_ctrl, priv->base + RTC_CTRL);
> >
> > - /*
> > - * Based on crystal freq of 33.330 KHz
> > - * set the seconds counter and enable, set fractions counter
> > - * to default value suggested as per design spec
> > - * to correct RTC delay in frequency over period of time.
> > - */
> > - priv->calibval &= RTC_CALIB_MASK;
> > - writel(priv->calibval, (priv->base + RTC_CALIB_WR));
> > -
> > return 0;
> > }
> >
> > @@ -128,8 +116,44 @@ static int zynqmp_rtc_probe(struct udevice *dev)
> > if (priv->base == FDT_ADDR_T_NONE)
> > return -EINVAL;
> >
> > - priv->calibval = dev_read_u32_default(dev, "calibration",
> > - RTC_CALIB_DEF);
> > + ret = readl(priv->base + RTC_CALIB_RD);
> > + if (!ret) {
> > + struct clk rtc_clk;
> > + unsigned long clk_rate;
> > +
> > + /* Get the RTC clock rate */
> > + ret = clk_get_by_name_optional(dev, "rtc", &rtc_clk);
> > + if (!ret) {
> > + clk_rate = clk_get_rate(&rtc_clk);
> > + /* Use clock frequency if valid, fallback to calibration value */
> > + if (clk_rate > 0 && clk_rate <= RTC_FREQ_MAX) {
> > + /* Valid clock frequency */
> > + priv->calibval = clk_rate - 1;
> > + } else if (clk_rate == 0) {
> > + priv->calibval = dev_read_u32_default(dev, "calibration",
> > + RTC_CALIB_DEF);
> > + } else {
> > + dev_err(dev, "Invalid clock frequency 0x%lx\n",
> > + clk_rate);
> > + return -EINVAL;
> > + }
> > + } else {
> > + /* Clock framework unavailable, use DT calibration */
> > + priv->calibval = dev_read_u32_default(dev, "calibration",
> > + RTC_CALIB_DEF);
> > + }
> > +
> > + /* Validate final calibration value */
> > + if (priv->calibval > RTC_FREQ_MAX) {
> > + dev_err(dev, "Invalid calibration 0x%lx\n",
> > + priv->calibval);
> > + return -EINVAL;
> > + }
> > +
> > + writel(priv->calibval, (priv->base + RTC_CALIB_WR));
> > + } else {
> > + priv->calibval = ret & RTC_CALIB_MASK;
> > + }
> >
> > ret = zynqmp_rtc_init(dev);
> >
> > --
> > 2.34.1
> >
Thanks,
Pranav Tilak
More information about the U-Boot
mailing list