diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-04 20:38:01 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-04 20:38:01 +0300 |
commit | bdabb68931b9360bf18b498062f1ac90bec46633 (patch) | |
tree | 67fef8fc22d5bb8fbd4bef4281afb76310dd34d3 /drivers/rtc/class.c | |
parent | 828907ef25e0133f50c346ef5a3c79a707a9b100 (diff) | |
parent | 1821b79d6a7d6973d1630e71380da8bb5e95f3a5 (diff) | |
download | linux-bdabb68931b9360bf18b498062f1ac90bec46633.tar.xz |
Merge tag 'rtc-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"More cleanup this cycle, with the final goal of removing the
rtc_time_to_tm and rtc_tm_to_time wrappers. All the drivers that have
been modified for this now are ready for the end of times (whether it
happens in 2033, 2038, 2106, 2127 or even 4052). There is also a
single new driver and the usual fixes and features.
Summary:
Subsystem:
- The rtc_time_to_tm and rtc_tm_to_time wrappers have finally been
removed and only the 64bit version remain.
- hctosys now works with drivers compiled as modules
New driver:
- MediaTek MT2712 SoC based RTC
Drivers:
- set range for 88pm860x, au1xxx, cpcap, da9052, davinci, ds1305,
ds1374, mcp5121, pl030, pl031, pm8xxx, puv3, sa1100, sirfsoc,
starfire, sun6i
- ds1307: DS1388 oscillator failure detection and watchdog support
- jz4740: JZ4760 support
- pcf85063: clock out pin support
- sun6i: external 32k oscillator is now optional, the range is now
handled by the core, providing a solution for 2034"
* tag 'rtc-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (87 commits)
rtc: ds1307: check for failed memory allocation on wdt
rtc: class: remove redundant assignment to variable err
rtc: remove rtc_time_to_tm and rtc_tm_to_time
rtc: sun6i: let the core handle rtc range
rtc: sun6i: switch to rtc_time64_to_tm/rtc_tm_to_time64
rtc: ds1307: add support for watchdog timer on ds1388
rtc: da9052: switch to rtc_time64_to_tm/rtc_tm_to_time64
rtc: da9052: set range
rtc: da9052: convert to devm_rtc_allocate_device
rtc: imx-sc: Align imx sc msg structs to 4
rtc: fsl-ftm-alarm: report alarm to core
rtc: pcf85063: Add pcf85063 clkout control to common clock framework
rtc: make definitions in include/uapi/linux/rtc.h actually useful for user space
rtc: class: avoid unnecessary lookup in hctosys
dt-bindings: rtc: Convert and update jz4740-rtc doc to YAML
rtc: jz4740: Rename vendor-specific DT properties
rtc: jz4740: Add support for JZ4760 SoC
rtc: class: support hctosys from modular RTC drivers
rtc: pm8xxx: clear alarm register when alarm is not enabled
rtc: omap: drop unused dt-bindings header
...
Diffstat (limited to 'drivers/rtc/class.c')
-rw-r--r-- | drivers/rtc/class.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 9458e6d6686a..7c88d190c51f 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -34,6 +34,50 @@ static void rtc_device_release(struct device *dev) #ifdef CONFIG_RTC_HCTOSYS_DEVICE /* Result of the last RTC to system clock attempt. */ int rtc_hctosys_ret = -ENODEV; + +/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary + * whether it stores the most close value or the value with partial + * seconds truncated. However, it is important that we use it to store + * the truncated value. This is because otherwise it is necessary, + * in an rtc sync function, to read both xtime.tv_sec and + * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read + * of >32bits is not possible. So storing the most close value would + * slow down the sync API. So here we have the truncated value and + * the best guess is to add 0.5s. + */ + +static void rtc_hctosys(struct rtc_device *rtc) +{ + int err; + struct rtc_time tm; + struct timespec64 tv64 = { + .tv_nsec = NSEC_PER_SEC >> 1, + }; + + err = rtc_read_time(rtc, &tm); + if (err) { + dev_err(rtc->dev.parent, + "hctosys: unable to read the hardware clock\n"); + goto err_read; + } + + tv64.tv_sec = rtc_tm_to_time64(&tm); + +#if BITS_PER_LONG == 32 + if (tv64.tv_sec > INT_MAX) { + err = -ERANGE; + goto err_read; + } +#endif + + err = do_settimeofday64(&tv64); + + dev_info(rtc->dev.parent, "setting system clock to %ptR UTC (%lld)\n", + &tm, (long long)tv64.tv_sec); + +err_read: + rtc_hctosys_ret = err; +} #endif #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_RTC_HCTOSYS_DEVICE) @@ -375,6 +419,11 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc) dev_info(rtc->dev.parent, "registered as %s\n", dev_name(&rtc->dev)); +#ifdef CONFIG_RTC_HCTOSYS_DEVICE + if (!strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE)) + rtc_hctosys(rtc); +#endif + return 0; } EXPORT_SYMBOL_GPL(__rtc_register_device); |