On Thu, 3 Oct 2024, Alexandre Belloni wrote:
... while you are it, can you use m48t59->rtc->start_secs and m48t59->rtc->set_start_time in probe instead of offsetting tm_year in read_time/set_time so we can later use device tree or any other mechanism to extend the range?
That didn't work out as I'd hoped. I booted a patched kernel (diff below) under qemu-system-sparc64: ~ # for yyyy in 1970 1971 1999 2000 2024 2025 2068 2069 ; do date 01010101$yyyy ; hwclock --systohc --utc && hwclock --utc ; echo ; done Thu Jan 1 01:01:00 UTC 1970 Thu Jan 1 01:01:00 1970 0.000000 seconds Fri Jan 1 01:01:00 UTC 1971 Tue Nov 24 18:32:44 1998 0.000000 seconds Fri Jan 1 01:01:00 UTC 1999 Tue Nov 24 18:32:44 2026 0.000000 seconds Sat Jan 1 01:01:00 UTC 2000 Sun Jan 2 23:29:16 2000 0.000000 seconds Mon Jan 1 01:01:00 UTC 2024 Tue Jan 2 23:29:16 2024 0.000000 seconds Wed Jan 1 01:01:00 UTC 2025 Thu Jan 2 23:29:16 2025 0.000000 seconds Sun Jan 1 01:01:00 UTC 2068 hwclock: RTC_SET_TIME: Numerical result out of range Tue Jan 1 01:01:00 UTC 2069 hwclock: RTC_SET_TIME: Numerical result out of range ~ # Here's the result from an unpatched kernel (v6.11): ~ # for yyyy in 1970 1971 1999 2000 2024 2025 2068 2069 ; do date 01010101$yyyy ; hwclock --systohc --utc && hwclock --utc ; echo ; done Thu Jan 1 01:01:00 UTC 1970 Thu Jan 1 01:01:00 1970 0.000000 seconds Fri Jan 1 01:01:00 UTC 1971 Fri Jan 1 01:01:00 1971 0.000000 seconds Fri Jan 1 01:01:00 UTC 1999 Fri Jan 1 01:01:01 1999 0.000000 seconds Sat Jan 1 01:01:00 UTC 2000 Sat Jan 1 01:01:00 2000 0.000000 seconds Mon Jan 1 01:01:00 UTC 2024 Mon Jan 1 01:01:00 2024 0.000000 seconds Wed Jan 1 01:01:00 UTC 2025 Wed Jan 1 01:01:00 2025 0.000000 seconds Sun Jan 1 01:01:00 UTC 2068 hwclock: RTC_RD_TIME: Invalid argument Tue Jan 1 01:01:00 UTC 2069 hwclock: RTC_RD_TIME: Invalid argument ~ # I'm afraid I don't see how we might avoid adding/subtracting in read_time/set_time given that we must avoid messing up the present date when users boot into an upgraded kernel. diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index 08bbdc458596..41ae3d1aa12e 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -255,6 +255,7 @@ static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) static struct m48t59_plat_data m48t59_data = { .read_byte = mostek_read_byte, .write_byte = mostek_write_byte, + .start_year = 1968, }; /* resource is set at runtime */ diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 60f1c8cc5363..eceb3fadb71a 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -544,6 +544,7 @@ static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) static struct m48t59_plat_data m48t59_data = { .read_byte = mostek_read_byte, .write_byte = mostek_write_byte, + .start_year = 1968, }; static struct platform_device m48t59_rtc = { diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index f0f6b9b6daec..d7e1f79cd52b 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -82,10 +82,6 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) dev_dbg(dev, "Century bit is enabled\n"); tm->tm_year += 100; /* one century */ } -#ifdef CONFIG_SPARC - /* Sun SPARC machines count years since 1968 */ - tm->tm_year += 68; -#endif tm->tm_wday = bcd2bin(val & 0x07); tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F); @@ -108,11 +104,6 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) u8 val = 0; int year = tm->tm_year; -#ifdef CONFIG_SPARC - /* Sun SPARC machines count years since 1968 */ - year -= 68; -#endif - dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n", year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -163,10 +154,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); -#ifdef CONFIG_SPARC - /* Sun SPARC machines count years since 1968 */ - tm->tm_year += 68; -#endif + /* tm_mon is 0-11 */ tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; @@ -199,11 +187,6 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) unsigned long flags; int year = tm->tm_year; -#ifdef CONFIG_SPARC - /* Sun SPARC machines count years since 1968 */ - year -= 68; -#endif - /* If no irq, we don't support ALARM */ if (m48t59->irq == NO_IRQ) return -EIO; @@ -458,6 +441,10 @@ static int m48t59_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, m48t59); m48t59->rtc->ops = &m48t59_rtc_ops; + m48t59->rtc->range_min = mktime64(1900, 1, 1, 0, 0, 0); + m48t59->rtc->range_max = mktime64(1999, 12, 31, 23, 59, 59); + m48t59->rtc->start_secs = mktime64(pdata->start_year, 1, 1, 0, 0, 0); + m48t59->rtc->set_start_time = true; nvmem_cfg.size = pdata->offset; ret = devm_rtc_nvmem_register(m48t59->rtc, &nvmem_cfg); diff --git a/include/linux/rtc/m48t59.h b/include/linux/rtc/m48t59.h index 9465d5405fe2..b01c514d7079 100644 --- a/include/linux/rtc/m48t59.h +++ b/include/linux/rtc/m48t59.h @@ -56,6 +56,9 @@ struct m48t59_plat_data { void __iomem *ioaddr; /* offset to RTC registers, automatically set according to the type */ unsigned int offset; + + /* value to be used to initialize rtc->start_secs */ + time64_t start_year; }; #endif /* _LINUX_RTC_M48T59_H_ */