Skip to content

Commit 9f5af70

Browse files
vai-tommealexandrebelloni
authored andcommitted
rtc: zynqmp: rework set_offset
set_offset was using remainder of do_div as tick_mult which resulted in wrong offset. Calibration value also assumed builtin calibration default. Update fract_offset to correctly calculate the value for negative offset and replace the for loop with division. Tested-by: Harini T <harini.t@amd.com> Signed-off-by: Tomas Melin <tomas.melin@vaisala.com> Reviewed-by: Harini T <harini.t@amd.com> Acked-by: Michal Simek <michal.simek@amd.com> Link: https://patch.msgid.link/20260122-zynqmp-rtc-updates-v4-4-d4edb966b499@vaisala.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
1 parent 0f99894 commit 9f5af70

1 file changed

Lines changed: 13 additions & 20 deletions

File tree

drivers/rtc/rtc-zynqmp.c

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,13 @@ static int xlnx_rtc_read_offset(struct device *dev, long *offset)
208208
static int xlnx_rtc_set_offset(struct device *dev, long offset)
209209
{
210210
struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
211-
unsigned long long rtc_ppb = RTC_PPB;
212-
unsigned int tick_mult = do_div(rtc_ppb, xrtcdev->freq);
213-
unsigned char fract_tick = 0;
211+
int max_tick, tick_mult, fract_offset, fract_part;
212+
int freq = xrtcdev->freq;
214213
unsigned int calibval;
215-
short int max_tick;
216-
int fract_offset;
214+
int fract_data = 0;
217215

216+
/* Tick to offset multiplier */
217+
tick_mult = DIV_ROUND_CLOSEST(RTC_PPB, freq);
218218
if (offset < RTC_MIN_OFFSET || offset > RTC_MAX_OFFSET)
219219
return -ERANGE;
220220

@@ -223,29 +223,22 @@ static int xlnx_rtc_set_offset(struct device *dev, long offset)
223223

224224
/* Number fractional ticks for given offset */
225225
if (fract_offset) {
226-
if (fract_offset < 0) {
227-
fract_offset = fract_offset + tick_mult;
226+
fract_part = DIV_ROUND_UP(tick_mult, RTC_FR_MAX_TICKS);
227+
fract_data = fract_offset / fract_part;
228+
/* Subtract one from max_tick while adding fract_offset */
229+
if (fract_offset < 0 && fract_data) {
228230
max_tick--;
229-
}
230-
if (fract_offset > (tick_mult / RTC_FR_MAX_TICKS)) {
231-
for (fract_tick = 1; fract_tick < 16; fract_tick++) {
232-
if (fract_offset <=
233-
(fract_tick *
234-
(tick_mult / RTC_FR_MAX_TICKS)))
235-
break;
236-
}
231+
fract_data += RTC_FR_MAX_TICKS;
237232
}
238233
}
239234

240235
/* Zynqmp RTC uses second and fractional tick
241236
* counters for compensation
242237
*/
243-
calibval = max_tick + RTC_CALIB_DEF;
244-
245-
if (fract_tick)
246-
calibval |= RTC_FR_EN;
238+
calibval = max_tick + freq;
247239

248-
calibval |= (fract_tick << RTC_FR_DATSHIFT);
240+
if (fract_data)
241+
calibval |= (RTC_FR_EN | (fract_data << RTC_FR_DATSHIFT));
249242

250243
writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
251244

0 commit comments

Comments
 (0)