aboutsummaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
authorArve Hjønnevåg <arve@android.com>2008-07-25 20:58:15 -0700
committerArve Hjønnevåg <arve@android.com>2010-07-22 15:11:25 -0700
commit2e26cb0479799a33cf7bece188ae07fc2248d607 (patch)
treed10be04af72643dc29578f90cfe3d30ee47dcf27 /drivers/rtc
parent22c2535ba6e3e7d3f7d4b02d4861c33fa3ace26e (diff)
rtc: Try to prevent RTC errors from accumulating.
When we resume we only know how many whole seconds has elapsed. These errors would accumulate in delta. We now only set the delta if it would change by more than two seconds. If we drift back by by more than a second add one in resume. Signed-off-by: Arve Hjønnevåg <arve@android.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/class.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 565562ba6ac..11d7ab90a67 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -41,25 +41,32 @@ static void rtc_device_release(struct device *dev)
*/
static struct timespec delta;
+static struct timespec delta_delta;
static time_t oldtime;
static int rtc_suspend(struct device *dev, pm_message_t mesg)
{
struct rtc_device *rtc = to_rtc_device(dev);
struct rtc_time tm;
- struct timespec ts = current_kernel_time();
+ struct timespec ts;
+ struct timespec new_delta;
if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
return 0;
+ getnstimeofday(&ts);
rtc_read_time(rtc, &tm);
rtc_tm_to_time(&tm, &oldtime);
/* RTC precision is 1 second; adjust delta for avg 1/2 sec err */
- set_normalized_timespec(&delta,
+ set_normalized_timespec(&new_delta,
ts.tv_sec - oldtime,
ts.tv_nsec - (NSEC_PER_SEC >> 1));
+ /* prevent 1/2 sec errors from accumulating */
+ delta_delta = timespec_sub(new_delta, delta);
+ if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2)
+ delta = new_delta;
return 0;
}
@@ -79,6 +86,8 @@ static int rtc_resume(struct device *dev)
return 0;
}
rtc_tm_to_time(&tm, &newtime);
+ if (delta_delta.tv_sec < -1)
+ newtime++;
if (newtime <= oldtime) {
if (newtime < oldtime)
pr_debug("%s: time travel!\n", dev_name(&rtc->dev));