return ret;
 }
 
+/**
+ * read_persistent_clock -  Return time in seconds from the persistent clock.
+ *
+ * Weak dummy function for arches that do not yet support it.
+ * Returns seconds from epoch using the battery backed persistent clock.
+ * Returns zero if unsupported.
+ *
+ *  XXX - Do be sure to remove it once all arches implement it.
+ */
+unsigned long __attribute__((weak)) read_persistent_clock(void)
+{
+       return 0;
+}
+
 /*
  * timekeeping_init - Initializes the clocksource and common timekeeping values
  */
 void __init timekeeping_init(void)
 {
        unsigned long flags;
+       unsigned long sec = read_persistent_clock();
 
        write_seqlock_irqsave(&xtime_lock, flags);
 
        clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
        clock->cycle_last = clocksource_read(clock);
 
+       xtime.tv_sec = sec;
+       xtime.tv_nsec = 0;
+       set_normalized_timespec(&wall_to_monotonic,
+               -xtime.tv_sec, -xtime.tv_nsec);
+
        write_sequnlock_irqrestore(&xtime_lock, flags);
 }
 
 
+/* flag for if timekeeping is suspended */
 static int timekeeping_suspended;
+/* time in seconds when suspend began */
+static unsigned long timekeeping_suspend_time;
+
 /**
  * timekeeping_resume - Resumes the generic timekeeping subsystem.
  * @dev:       unused
 static int timekeeping_resume(struct sys_device *dev)
 {
        unsigned long flags;
+       unsigned long now = read_persistent_clock();
 
        write_seqlock_irqsave(&xtime_lock, flags);
-       /* restart the last cycle value */
+
+       if (now && (now > timekeeping_suspend_time)) {
+               unsigned long sleep_length = now - timekeeping_suspend_time;
+
+               xtime.tv_sec += sleep_length;
+               wall_to_monotonic.tv_sec -= sleep_length;
+       }
+       /* re-base the last cycle value */
        clock->cycle_last = clocksource_read(clock);
        clock->error = 0;
        timekeeping_suspended = 0;
        write_sequnlock_irqrestore(&xtime_lock, flags);
+
+       touch_softlockup_watchdog();
+       hrtimer_notify_resume();
+
        return 0;
 }
 
 
        write_seqlock_irqsave(&xtime_lock, flags);
        timekeeping_suspended = 1;
+       timekeeping_suspend_time = read_persistent_clock();
        write_sequnlock_irqrestore(&xtime_lock, flags);
        return 0;
 }