Skip to content

Commit 0f99894

Browse files
vai-tommealexandrebelloni
authored andcommitted
rtc: zynqmp: rework read_offset
read_offset() was using static frequency for determining the tick offset. It was also using remainder from do_div() operation as tick_mult value which caused the offset to be incorrect. At the same time, rework function to improve readability. It is worth noting, that due to rounding errors, the offset readback will differ slightly for positive and negative calibration values. Reviewed-by: Harini T <harini.t@amd.com> Tested-by: Harini T <harini.t@amd.com> Signed-off-by: Tomas Melin <tomas.melin@vaisala.com> Acked-by: Michal Simek <michal.simek@amd.com> Link: https://patch.msgid.link/20260122-zynqmp-rtc-updates-v4-3-d4edb966b499@vaisala.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent 83b9e5e commit 0f99894

1 file changed

Lines changed: 17 additions & 10 deletions

File tree

drivers/rtc/rtc-zynqmp.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
#define RTC_MSEC 1000
4444
#define RTC_FR_MASK 0xF0000
4545
#define RTC_FR_MAX_TICKS 16
46-
#define RTC_PPB 1000000000LL
46+
#define RTC_PPB 1000000000
4747
#define RTC_MIN_OFFSET -32768000
4848
#define RTC_MAX_OFFSET 32767000
4949

@@ -178,21 +178,28 @@ static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev)
178178
static int xlnx_rtc_read_offset(struct device *dev, long *offset)
179179
{
180180
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
181-
unsigned long long rtc_ppb = RTC_PPB;
182-
unsigned int tick_mult = do_div(rtc_ppb, xrtcdev->freq);
183-
unsigned int calibval;
181+
unsigned int calibval, fract_data, fract_part;
182+
int freq = xrtcdev->freq;
183+
int max_tick, tick_mult;
184184
long offset_val;
185185

186+
/* Tick to offset multiplier */
187+
tick_mult = DIV_ROUND_CLOSEST(RTC_PPB, freq);
188+
186189
calibval = readl(xrtcdev->reg_base + RTC_CALIB_RD);
187190
/* Offset with seconds ticks */
188-
offset_val = calibval & RTC_TICK_MASK;
189-
offset_val = offset_val - RTC_CALIB_DEF;
190-
offset_val = offset_val * tick_mult;
191+
max_tick = calibval & RTC_TICK_MASK;
192+
offset_val = max_tick - freq;
193+
/* Convert to ppb */
194+
offset_val *= tick_mult;
191195

192196
/* Offset with fractional ticks */
193-
if (calibval & RTC_FR_EN)
194-
offset_val += ((calibval & RTC_FR_MASK) >> RTC_FR_DATSHIFT)
195-
* (tick_mult / RTC_FR_MAX_TICKS);
197+
if (calibval & RTC_FR_EN) {
198+
fract_data = (calibval & RTC_FR_MASK) >> RTC_FR_DATSHIFT;
199+
fract_part = DIV_ROUND_UP(tick_mult, RTC_FR_MAX_TICKS);
200+
offset_val += (fract_part * fract_data);
201+
}
202+
196203
*offset = offset_val;
197204

198205
return 0;

0 commit comments

Comments
 (0)