^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/rtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * rtc_set_ntp_time - Save NTP synchronized time to the RTC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * @now: Current time of day
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * @target_nsec: pointer for desired now->tv_nsec value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Replacement for the NTP platform function update_persistent_clock64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * that stores time for later retrieval by rtc_hctosys.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Returns 0 on successful RTC update, -ENODEV if a RTC update is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * possible at all, and various other -errno for specific temporary failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * -EPROTO is returned if now.tv_nsec is not close enough to *target_nsec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * If temporary failure is indicated the caller should try again 'soon'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct rtc_device *rtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct rtc_time tm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct timespec64 to_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) bool ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) rtc = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (!rtc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (!rtc->ops || !rtc->ops->set_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* Compute the value of tv_nsec we require the caller to supply in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * now.tv_nsec. This is the value such that (now +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * set_offset_nsec).tv_nsec == 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) set_normalized_timespec64(&to_set, 0, -rtc->set_offset_nsec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *target_nsec = to_set.tv_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* The ntp code must call this with the correct value in tv_nsec, if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * it does not we update target_nsec and return EPROTO to make the ntp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * code try again later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ok = rtc_tv_nsec_ok(rtc->set_offset_nsec, &to_set, &now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (!ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) err = -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) rtc_time64_to_tm(to_set.tv_sec, &tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) err = rtc_set_time(rtc, &tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) rtc_class_close(rtc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }