diff options
Diffstat (limited to 'drivers/rtc/class.c')
| -rw-r--r-- | drivers/rtc/class.c | 25 |
1 files changed, 10 insertions, 15 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 09b4437b3e6..4194e59e14c 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 | ||
| 44 | static struct timespec delta; | ||
| 45 | static time_t oldtime; | 44 | static time_t oldtime; |
| 45 | static struct timespec oldts; | ||
| 46 | 46 | ||
| 47 | static int rtc_suspend(struct device *dev, pm_message_t mesg) | 47 | static 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 | ||
| @@ -171,7 +166,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
| 171 | err = __rtc_read_alarm(rtc, &alrm); | 166 | err = __rtc_read_alarm(rtc, &alrm); |
| 172 | 167 | ||
| 173 | if (!err && !rtc_valid_tm(&alrm.time)) | 168 | if (!err && !rtc_valid_tm(&alrm.time)) |
| 174 | rtc_set_alarm(rtc, &alrm); | 169 | rtc_initialize_alarm(rtc, &alrm); |
| 175 | 170 | ||
| 176 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); | 171 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); |
| 177 | dev_set_name(&rtc->dev, "rtc%d", id); | 172 | dev_set_name(&rtc->dev, "rtc%d", id); |
