aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/time.c
diff options
context:
space:
mode:
authorJohn Stultz <johnstul@us.ibm.com>2007-02-16 04:27:31 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:13:57 -0500
commitc1d370e167d66b10bca3b602d3740405469383de (patch)
tree493ed9821cad0b2b035337da152cc11cc2223eb1 /arch/i386/kernel/time.c
parent411187fb05cd11676b0979d9fbf3291db69dbce2 (diff)
[PATCH] i386: use GTOD persistent clock support
Persistent clock support: do proper timekeeping across suspend/resume, i386 arch support. [bunk@stusta.de: cleanup] Build-fixes-from: Andrew Morton <akpm@osdl.org> Signed-off-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: Roman Zippel <zippel@linux-m68k.org> Cc: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/kernel/time.c')
-rw-r--r--arch/i386/kernel/time.c54
1 files changed, 1 insertions, 53 deletions
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index a4f67a6e6821..044c17572eef 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -212,7 +212,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
212} 212}
213 213
214/* not static: needed by APM */ 214/* not static: needed by APM */
215unsigned long get_cmos_time(void) 215unsigned long read_persistent_clock(void)
216{ 216{
217 unsigned long retval; 217 unsigned long retval;
218 unsigned long flags; 218 unsigned long flags;
@@ -225,7 +225,6 @@ unsigned long get_cmos_time(void)
225 225
226 return retval; 226 return retval;
227} 227}
228EXPORT_SYMBOL(get_cmos_time);
229 228
230static void sync_cmos_clock(unsigned long dummy); 229static void sync_cmos_clock(unsigned long dummy);
231 230
@@ -278,58 +277,19 @@ void notify_arch_cmos_timer(void)
278 mod_timer(&sync_cmos_timer, jiffies + 1); 277 mod_timer(&sync_cmos_timer, jiffies + 1);
279} 278}
280 279
281static long clock_cmos_diff;
282static unsigned long sleep_start;
283
284static int timer_suspend(struct sys_device *dev, pm_message_t state)
285{
286 /*
287 * Estimate time zone so that set_time can update the clock
288 */
289 unsigned long ctime = get_cmos_time();
290
291 clock_cmos_diff = -ctime;
292 clock_cmos_diff += get_seconds();
293 sleep_start = ctime;
294 return 0;
295}
296
297static int timer_resume(struct sys_device *dev) 280static int timer_resume(struct sys_device *dev)
298{ 281{
299 unsigned long flags;
300 unsigned long sec;
301 unsigned long ctime = get_cmos_time();
302 long sleep_length = (ctime - sleep_start) * HZ;
303 struct timespec ts;
304
305 if (sleep_length < 0) {
306 printk(KERN_WARNING "CMOS clock skew detected in timer resume!\n");
307 /* The time after the resume must not be earlier than the time
308 * before the suspend or some nasty things will happen
309 */
310 sleep_length = 0;
311 ctime = sleep_start;
312 }
313#ifdef CONFIG_HPET_TIMER 282#ifdef CONFIG_HPET_TIMER
314 if (is_hpet_enabled()) 283 if (is_hpet_enabled())
315 hpet_reenable(); 284 hpet_reenable();
316#endif 285#endif
317 setup_pit_timer(); 286 setup_pit_timer();
318
319 sec = ctime + clock_cmos_diff;
320 ts.tv_sec = sec;
321 ts.tv_nsec = 0;
322 do_settimeofday(&ts);
323 write_seqlock_irqsave(&xtime_lock, flags);
324 jiffies_64 += sleep_length;
325 write_sequnlock_irqrestore(&xtime_lock, flags);
326 touch_softlockup_watchdog(); 287 touch_softlockup_watchdog();
327 return 0; 288 return 0;
328} 289}
329 290
330static struct sysdev_class timer_sysclass = { 291static struct sysdev_class timer_sysclass = {
331 .resume = timer_resume, 292 .resume = timer_resume,
332 .suspend = timer_suspend,
333 set_kset_name("timer"), 293 set_kset_name("timer"),
334}; 294};
335 295
@@ -355,12 +315,6 @@ extern void (*late_time_init)(void);
355/* Duplicate of time_init() below, with hpet_enable part added */ 315/* Duplicate of time_init() below, with hpet_enable part added */
356static void __init hpet_time_init(void) 316static void __init hpet_time_init(void)
357{ 317{
358 struct timespec ts;
359 ts.tv_sec = get_cmos_time();
360 ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
361
362 do_settimeofday(&ts);
363
364 if ((hpet_enable() >= 0) && hpet_use_timer) { 318 if ((hpet_enable() >= 0) && hpet_use_timer) {
365 printk("Using HPET for base-timer\n"); 319 printk("Using HPET for base-timer\n");
366 } 320 }
@@ -371,7 +325,6 @@ static void __init hpet_time_init(void)
371 325
372void __init time_init(void) 326void __init time_init(void)
373{ 327{
374 struct timespec ts;
375#ifdef CONFIG_HPET_TIMER 328#ifdef CONFIG_HPET_TIMER
376 if (is_hpet_capable()) { 329 if (is_hpet_capable()) {
377 /* 330 /*
@@ -382,10 +335,5 @@ void __init time_init(void)
382 return; 335 return;
383 } 336 }
384#endif 337#endif
385 ts.tv_sec = get_cmos_time();
386 ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
387
388 do_settimeofday(&ts);
389
390 do_time_init(); 338 do_time_init();
391} 339}