diff mbox series

[v2,3/3] rtc: s3c: Add time range

Message ID 20211021202256.28517-4-semen.protsenko@linaro.org
State Accepted
Headers show
Series rtc: s3c: S3C driver improvements | expand

Commit Message

Sam Protsenko Oct. 21, 2021, 8:22 p.m. UTC
This RTC driver starts counting from 2000 to avoid Y2K problem. Also it
only supports 100 years range for all RTCs.  Provide that info to RTC
framework. Also remove check for 100 years range in s3c_rtc_settime(),
as RTC core won't pass any invalid values to the driver, now that
correct range is set.

Here is the rationale on 100 years range limitation. Info on different
Samsung RTCs (credit goes to Krzysztof Kozlowski):
  - All S3C chips have only 8-bit wide year register (can store 100
    years range in BCD format)
  - S5Pv210 and Exynos chips have 12-bit year register (can store 1000
    years range in BCD format)

But in reality we usually can't make use of those 12 bits either:
  - RTCs might think that both 2000 and 2100 years are leap years. So
    when the YEAR register is 0, RTC goes from 28 Feb to 29 Feb, and
    when the YEAR register is 100, RTC also goes from 28 Feb to 29 Feb.
    This is of course incorrect: RTC breaks leap year criteria, which
    breaks the time contiguity, which leads to inability to use the RTC
    after year of 2099. It was found for example on Exynos850 SoC.
  - Despite having 12 bits for holding the year value, RTC might
    overflow the year value internally much earlier. For example, on
    Exynos850 the RTC overflows when YEAR=159, making the next YEAR=0.
    This way RTC actually has range of 160 years, not 1000 as one may
    think.

All that said, there is no sense in trying to increase the time range
for more than 100 years on RTCs that seem capable of that. It also
doesn't have too much practical value -- current hardware will be
probably obsolete by 2100.

Tested manually on Exynos850 RTC:

    $ date -s "1999-12-31 23:59:50"
    $ hwclock -w -f /dev/rtc0
    $ date -s "2100-01-01 00:00:00"
    $ hwclock -w -f /dev/rtc0
    $ date -s "2000-01-01 00:00:00"
    $ hwclock -w -f /dev/rtc0
    $ hwclock -r -f /dev/rtc0
    $ date -s "2099-12-31 23:59:50"
    $ hwclock -w -f /dev/rtc0
    $ hwclock -r -f /dev/rtc0

Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
---
Changes in v2:
  - Removed check for 100 years range in s3c_rtc_settime()
  - Improved the commit message

 drivers/rtc/rtc-s3c.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

Comments

Krzysztof Kozlowski Oct. 22, 2021, 8:54 a.m. UTC | #1
On 21/10/2021 22:22, Sam Protsenko wrote:
> This RTC driver starts counting from 2000 to avoid Y2K problem. Also it
> only supports 100 years range for all RTCs.  Provide that info to RTC
> framework. Also remove check for 100 years range in s3c_rtc_settime(),
> as RTC core won't pass any invalid values to the driver, now that
> correct range is set.
> 
> Here is the rationale on 100 years range limitation. Info on different
> Samsung RTCs (credit goes to Krzysztof Kozlowski):
>   - All S3C chips have only 8-bit wide year register (can store 100
>     years range in BCD format)
>   - S5Pv210 and Exynos chips have 12-bit year register (can store 1000
>     years range in BCD format)
> 
> But in reality we usually can't make use of those 12 bits either:
>   - RTCs might think that both 2000 and 2100 years are leap years. So
>     when the YEAR register is 0, RTC goes from 28 Feb to 29 Feb, and
>     when the YEAR register is 100, RTC also goes from 28 Feb to 29 Feb.
>     This is of course incorrect: RTC breaks leap year criteria, which
>     breaks the time contiguity, which leads to inability to use the RTC
>     after year of 2099. It was found for example on Exynos850 SoC.
>   - Despite having 12 bits for holding the year value, RTC might
>     overflow the year value internally much earlier. For example, on
>     Exynos850 the RTC overflows when YEAR=159, making the next YEAR=0.
>     This way RTC actually has range of 160 years, not 1000 as one may
>     think.
> 
> All that said, there is no sense in trying to increase the time range
> for more than 100 years on RTCs that seem capable of that. It also
> doesn't have too much practical value -- current hardware will be
> probably obsolete by 2100.
> 
> Tested manually on Exynos850 RTC:
> 
>     $ date -s "1999-12-31 23:59:50"
>     $ hwclock -w -f /dev/rtc0
>     $ date -s "2100-01-01 00:00:00"
>     $ hwclock -w -f /dev/rtc0
>     $ date -s "2000-01-01 00:00:00"
>     $ hwclock -w -f /dev/rtc0
>     $ hwclock -r -f /dev/rtc0
>     $ date -s "2099-12-31 23:59:50"
>     $ hwclock -w -f /dev/rtc0
>     $ hwclock -r -f /dev/rtc0
> 
> Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
> ---
> Changes in v2:
>   - Removed check for 100 years range in s3c_rtc_settime()
>   - Improved the commit message
> 


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>


Best regards,
Krzysztof
diff mbox series

Patch

diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index d1baf655c008..db529733c9c4 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -219,11 +219,6 @@  static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
 	rtc_tm.tm_year -= 100;
 	rtc_tm.tm_mon += 1;
 
-	if (rtc_tm.tm_year < 0 || rtc_tm.tm_year >= 100) {
-		dev_err(dev, "rtc only supports 100 years\n");
-		return -EINVAL;
-	}
-
 	return s3c_rtc_write_time(info, &rtc_tm);
 }
 
@@ -478,6 +473,8 @@  static int s3c_rtc_probe(struct platform_device *pdev)
 	}
 
 	info->rtc->ops = &s3c_rtcops;
+	info->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	info->rtc->range_max = RTC_TIMESTAMP_END_2099;
 
 	ret = devm_rtc_register_device(info->rtc);
 	if (ret)