aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2017-10-31 18:17:28 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-10-31 18:17:28 -0400
commitfb56d689fb1c8f13d4d7168abf3838657b042885 (patch)
treea7e75f65e440d6c078c8e8eb25a2186c3c685261 /drivers
parent6c1e272f962da249f289846cec944bcd1c162a49 (diff)
parent6546911ed369af8d747215ff8b6144618e91c6ab (diff)
Merge branch 'fortglx/4.15/time' of https://git.linaro.org/people/john.stultz/linux into timers/core
Pull timekeeping updates from John Stultz: - More y2038 work from Arnd Bergmann - A new mechanism to allow RTC drivers to specify the resolution of the RTC so the suspend/resume code can make informed decisions whether to inject the suspended time or not in case of fast suspend/resume cycles.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/rtc/class.c3
-rw-r--r--drivers/rtc/systohc.c53
2 files changed, 41 insertions, 15 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 2ed970d61da1..722d683e0b0f 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -161,6 +161,9 @@ static struct rtc_device *rtc_allocate_device(void)
161 161
162 device_initialize(&rtc->dev); 162 device_initialize(&rtc->dev);
163 163
164 /* Drivers can revise this default after allocating the device. */
165 rtc->set_offset_nsec = NSEC_PER_SEC / 2;
166
164 rtc->irq_freq = 1; 167 rtc->irq_freq = 1;
165 rtc->max_user_freq = 64; 168 rtc->max_user_freq = 64;
166 rtc->dev.class = rtc_class; 169 rtc->dev.class = rtc_class;
diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c
index b4a68ffcd06b..0c177647ea6c 100644
--- a/drivers/rtc/systohc.c
+++ b/drivers/rtc/systohc.c
@@ -10,6 +10,7 @@
10/** 10/**
11 * rtc_set_ntp_time - Save NTP synchronized time to the RTC 11 * rtc_set_ntp_time - Save NTP synchronized time to the RTC
12 * @now: Current time of day 12 * @now: Current time of day
13 * @target_nsec: pointer for desired now->tv_nsec value
13 * 14 *
14 * Replacement for the NTP platform function update_persistent_clock64 15 * Replacement for the NTP platform function update_persistent_clock64
15 * that stores time for later retrieval by rtc_hctosys. 16 * that stores time for later retrieval by rtc_hctosys.
@@ -18,30 +19,52 @@
18 * possible at all, and various other -errno for specific temporary failure 19 * possible at all, and various other -errno for specific temporary failure
19 * cases. 20 * cases.
20 * 21 *
22 * -EPROTO is returned if now.tv_nsec is not close enough to *target_nsec.
23 (
21 * If temporary failure is indicated the caller should try again 'soon' 24 * If temporary failure is indicated the caller should try again 'soon'
22 */ 25 */
23int rtc_set_ntp_time(struct timespec64 now) 26int rtc_set_ntp_time(struct timespec64 now, unsigned long *target_nsec)
24{ 27{
25 struct rtc_device *rtc; 28 struct rtc_device *rtc;
26 struct rtc_time tm; 29 struct rtc_time tm;
30 struct timespec64 to_set;
27 int err = -ENODEV; 31 int err = -ENODEV;
28 32 bool ok;
29 if (now.tv_nsec < (NSEC_PER_SEC >> 1))
30 rtc_time64_to_tm(now.tv_sec, &tm);
31 else
32 rtc_time64_to_tm(now.tv_sec + 1, &tm);
33 33
34 rtc = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE); 34 rtc = rtc_class_open(CONFIG_RTC_SYSTOHC_DEVICE);
35 if (rtc) { 35 if (!rtc)
36 /* rtc_hctosys exclusively uses UTC, so we call set_time here, 36 goto out_err;
37 * not set_mmss. */ 37
38 if (rtc->ops && 38 if (!rtc->ops || (!rtc->ops->set_time && !rtc->ops->set_mmss64 &&
39 (rtc->ops->set_time || 39 !rtc->ops->set_mmss))
40 rtc->ops->set_mmss64 || 40 goto out_close;
41 rtc->ops->set_mmss)) 41
42 err = rtc_set_time(rtc, &tm); 42 /* Compute the value of tv_nsec we require the caller to supply in
43 rtc_class_close(rtc); 43 * now.tv_nsec. This is the value such that (now +
44 * set_offset_nsec).tv_nsec == 0.
45 */
46 set_normalized_timespec64(&to_set, 0, -rtc->set_offset_nsec);
47 *target_nsec = to_set.tv_nsec;
48
49 /* The ntp code must call this with the correct value in tv_nsec, if
50 * it does not we update target_nsec and return EPROTO to make the ntp
51 * code try again later.
52 */
53 ok = rtc_tv_nsec_ok(rtc->set_offset_nsec, &to_set, &now);
54 if (!ok) {
55 err = -EPROTO;
56 goto out_close;
44 } 57 }
45 58
59 rtc_time64_to_tm(to_set.tv_sec, &tm);
60
61 /* rtc_hctosys exclusively uses UTC, so we call set_time here, not
62 * set_mmss.
63 */
64 err = rtc_set_time(rtc, &tm);
65
66out_close:
67 rtc_class_close(rtc);
68out_err:
46 return err; 69 return err;
47} 70}