1/* 2 * Common code to keep time when machine suspends. 3 * 4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * 6 * GPLv2 7 */ 8 9#include <linux/time.h> 10#include <linux/sysdev.h> 11#include <asm/rtc.h> 12 13static unsigned long suspend_rtc_time; 14 15/* 16 * Reset the time after a sleep. 17 */ 18static int timer_resume(struct sys_device *dev) 19{ 20 struct timeval tv; 21 struct timespec ts; 22 struct rtc_time cur_rtc_tm; 23 unsigned long cur_rtc_time, diff; 24 25 /* get current RTC time and convert to seconds */ 26 get_rtc_time(&cur_rtc_tm); 27 rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time); 28 29 diff = cur_rtc_time - suspend_rtc_time; 30 31 /* adjust time of day by seconds that elapsed while 32 * we were suspended */ 33 do_gettimeofday(&tv); 34 ts.tv_sec = tv.tv_sec + diff; 35 ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC; 36 do_settimeofday(&ts); 37 38 return 0; 39} 40 41static int timer_suspend(struct sys_device *dev, pm_message_t state) 42{ 43 struct rtc_time suspend_rtc_tm; 44 WARN_ON(!ppc_md.get_rtc_time); 45 46 get_rtc_time(&suspend_rtc_tm); 47 rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time); 48 49 return 0; 50} 51 52static struct sysdev_class timer_sysclass = { 53 .resume = timer_resume, 54 .suspend = timer_suspend, 55 set_kset_name("timer"), 56}; 57 58static struct sys_device device_timer = { 59 .id = 0, 60 .cls = &timer_sysclass, 61}; 62 63static int time_init_device(void) 64{ 65 int error = sysdev_class_register(&timer_sysclass); 66 if (!error) 67 error = sysdev_register(&device_timer); 68 return error; 69} 70 71device_initcall(time_init_device); 72