aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/class.c')
-rw-r--r--drivers/rtc/class.c23
1 files changed, 9 insertions, 14 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 39013867cbd6..4194e59e14cd 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -41,26 +41,21 @@ static void rtc_device_release(struct device *dev)
41 * system's wall clock; restore it on resume(). 41 * system's wall clock; restore it on resume().
42 */ 42 */
43 43
44static struct timespec delta;
45static time_t oldtime; 44static time_t oldtime;
45static struct timespec oldts;
46 46
47static int rtc_suspend(struct device *dev, pm_message_t mesg) 47static int rtc_suspend(struct device *dev, pm_message_t mesg)
48{ 48{
49 struct rtc_device *rtc = to_rtc_device(dev); 49 struct rtc_device *rtc = to_rtc_device(dev);
50 struct rtc_time tm; 50 struct rtc_time tm;
51 struct timespec ts = current_kernel_time();
52 51
53 if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) 52 if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
54 return 0; 53 return 0;
55 54
56 rtc_read_time(rtc, &tm); 55 rtc_read_time(rtc, &tm);
56 ktime_get_ts(&oldts);
57 rtc_tm_to_time(&tm, &oldtime); 57 rtc_tm_to_time(&tm, &oldtime);
58 58
59 /* RTC precision is 1 second; adjust delta for avg 1/2 sec err */
60 set_normalized_timespec(&delta,
61 ts.tv_sec - oldtime,
62 ts.tv_nsec - (NSEC_PER_SEC >> 1));
63
64 return 0; 59 return 0;
65} 60}
66 61
@@ -70,10 +65,12 @@ static int rtc_resume(struct device *dev)
70 struct rtc_time tm; 65 struct rtc_time tm;
71 time_t newtime; 66 time_t newtime;
72 struct timespec time; 67 struct timespec time;
68 struct timespec newts;
73 69
74 if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) 70 if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
75 return 0; 71 return 0;
76 72
73 ktime_get_ts(&newts);
77 rtc_read_time(rtc, &tm); 74 rtc_read_time(rtc, &tm);
78 if (rtc_valid_tm(&tm) != 0) { 75 if (rtc_valid_tm(&tm) != 0) {
79 pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); 76 pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev));
@@ -85,15 +82,13 @@ static int rtc_resume(struct device *dev)
85 pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); 82 pr_debug("%s: time travel!\n", dev_name(&rtc->dev));
86 return 0; 83 return 0;
87 } 84 }
85 /* calculate the RTC time delta */
86 set_normalized_timespec(&time, newtime - oldtime, 0);
88 87
89 /* restore wall clock using delta against this RTC; 88 /* subtract kernel time between rtc_suspend to rtc_resume */
90 * adjust again for avg 1/2 second RTC sampling error 89 time = timespec_sub(time, timespec_sub(newts, oldts));
91 */
92 set_normalized_timespec(&time,
93 newtime + delta.tv_sec,
94 (NSEC_PER_SEC >> 1) + delta.tv_nsec);
95 do_settimeofday(&time);
96 90
91 timekeeping_inject_sleeptime(&time);
97 return 0; 92 return 0;
98} 93}
99 94