Message ID | 20220512143920.238987-5-miquel.raynal@bootlin.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Geert Uytterhoeven |
Headers | show |
Series | RZ/N1 RTC support | expand |
Hi Miquel, I love your patch! Perhaps something to improve: [auto build test WARNING on abelloni/rtc-next] [also build test WARNING on robh/for-next linus/master v5.18-rc6] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/intel-lab-lkp/linux/commits/Miquel-Raynal/RZ-N1-RTC-support/20220512-224022 base: https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next config: mips-allyesconfig (https://download.01.org/0day-ci/archive/20220513/202205130445.mjHjgcBv-lkp@intel.com/config) compiler: mips-linux-gcc (GCC) 11.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/1b2c010278819d2c7aab406d9718a659ead047cf git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Miquel-Raynal/RZ-N1-RTC-support/20220512-224022 git checkout 1b2c010278819d2c7aab406d9718a659ead047cf # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=mips SHELL=/bin/bash drivers/rtc/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/rtc/rtc-rzn1.c: In function 'rzn1_rtc_set_offset': >> drivers/rtc/rtc-rzn1.c:275:29: warning: variable 'ppb_per_step' set but not used [-Wunused-but-set-variable] 275 | unsigned int steps, ppb_per_step; | ^~~~~~~~~~~~ vim +/ppb_per_step +275 drivers/rtc/rtc-rzn1.c 271 272 static int rzn1_rtc_set_offset(struct device *dev, long offset) 273 { 274 struct rzn1_rtc *rtc = dev_get_drvdata(dev); > 275 unsigned int steps, ppb_per_step; 276 int stepsh, stepsl; 277 u32 val; 278 int ret; 279 280 /* 281 * Check which resolution mode (every 20 or 60s) can be used. 282 * Between 2 and 124 clock pulses can be added or substracted. 283 * 284 * In 20s mode, the minimum resolution is 2 / (32768 * 20) which is 285 * close to 3051 ppb. In 60s mode, the resolution is closer to 1017. 286 */ 287 stepsh = DIV_ROUND_CLOSEST(offset, 1017); 288 stepsl = DIV_ROUND_CLOSEST(offset, 3051); 289 290 if (stepsh >= -0x3E && stepsh <= 0x3E) { 291 ppb_per_step = 1017; 292 steps = stepsh; 293 val |= RZN1_RTC_SUBU_DEV; 294 } else if (stepsl >= -0x3E && stepsl <= 0x3E) { 295 ppb_per_step = 3051; 296 steps = stepsl; 297 } else { 298 return -ERANGE; 299 } 300 301 if (!steps) 302 return 0; 303 304 if (steps > 0) { 305 val |= steps + 1; 306 } else { 307 val |= RZN1_RTC_SUBU_DECR; 308 val |= (~(-steps - 1)) & 0x3F; 309 } 310 311 ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, val, 312 !(val & RZN1_RTC_CTL2_WUST), 100, 2000000); 313 if (ret) 314 return ret; 315 316 writel(val, rtc->base + RZN1_RTC_SUBU); 317 318 return 0; 319 } 320
diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c index 7ee190daa651..79b72488231c 100644 --- a/drivers/rtc/rtc-rzn1.c +++ b/drivers/rtc/rtc-rzn1.c @@ -247,12 +247,85 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) return 0; } +static int rzn1_rtc_read_offset(struct device *dev, long *offset) +{ + struct rzn1_rtc *rtc = dev_get_drvdata(dev); + unsigned int ppb_per_step; + bool subtract; + u32 val; + + val = readl(rtc->base + RZN1_RTC_SUBU); + ppb_per_step = val & RZN1_RTC_SUBU_DEV ? 1017 : 3051; + subtract = val & RZN1_RTC_SUBU_DECR; + val &= 0x3F; + + if (!val) + *offset = 0; + else if (subtract) + *offset = -(((~val) & 0x3F) + 1) * ppb_per_step; + else + *offset = (val - 1) * ppb_per_step; + + return 0; +} + +static int rzn1_rtc_set_offset(struct device *dev, long offset) +{ + struct rzn1_rtc *rtc = dev_get_drvdata(dev); + unsigned int steps, ppb_per_step; + int stepsh, stepsl; + u32 val; + int ret; + + /* + * Check which resolution mode (every 20 or 60s) can be used. + * Between 2 and 124 clock pulses can be added or substracted. + * + * In 20s mode, the minimum resolution is 2 / (32768 * 20) which is + * close to 3051 ppb. In 60s mode, the resolution is closer to 1017. + */ + stepsh = DIV_ROUND_CLOSEST(offset, 1017); + stepsl = DIV_ROUND_CLOSEST(offset, 3051); + + if (stepsh >= -0x3E && stepsh <= 0x3E) { + ppb_per_step = 1017; + steps = stepsh; + val |= RZN1_RTC_SUBU_DEV; + } else if (stepsl >= -0x3E && stepsl <= 0x3E) { + ppb_per_step = 3051; + steps = stepsl; + } else { + return -ERANGE; + } + + if (!steps) + return 0; + + if (steps > 0) { + val |= steps + 1; + } else { + val |= RZN1_RTC_SUBU_DECR; + val |= (~(-steps - 1)) & 0x3F; + } + + ret = readl_poll_timeout(rtc->base + RZN1_RTC_CTL2, val, + !(val & RZN1_RTC_CTL2_WUST), 100, 2000000); + if (ret) + return ret; + + writel(val, rtc->base + RZN1_RTC_SUBU); + + return 0; +} + static const struct rtc_class_ops rzn1_rtc_ops = { .read_time = rzn1_rtc_read_time, .set_time = rzn1_rtc_set_time, .read_alarm = rzn1_rtc_read_alarm, .set_alarm = rzn1_rtc_set_alarm, .alarm_irq_enable = rzn1_rtc_alarm_irq_enable, + .read_offset = rzn1_rtc_read_offset, + .set_offset = rzn1_rtc_set_offset, }; static int rzn1_rtc_probe(struct platform_device *pdev)
The RZN1 RTC can compensate the imprecision of the oscillator up to approximately 190ppm. Seconds can last slightly shorter or longer depending on the configuration. Below ~65ppm of correction, we can change the time spent in a second every minute, which is the most accurate compensation that the RTC can offer. Above, the compensation will be active every 20s. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> --- drivers/rtc/rtc-rzn1.c | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+)