diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2017-10-31 18:17:28 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-10-31 18:17:28 -0400 |
commit | fb56d689fb1c8f13d4d7168abf3838657b042885 (patch) | |
tree | a7e75f65e440d6c078c8e8eb25a2186c3c685261 /drivers | |
parent | 6c1e272f962da249f289846cec944bcd1c162a49 (diff) | |
parent | 6546911ed369af8d747215ff8b6144618e91c6ab (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.c | 3 | ||||
-rw-r--r-- | drivers/rtc/systohc.c | 53 |
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 | */ |
23 | int rtc_set_ntp_time(struct timespec64 now) | 26 | int 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 | |||
66 | out_close: | ||
67 | rtc_class_close(rtc); | ||
68 | out_err: | ||
46 | return err; | 69 | return err; |
47 | } | 70 | } |