2007-03-19 11:53:53 +01:00
/*
* Common code to keep time when machine suspends .
*
* Copyright 2007 Johannes Berg < johannes @ sipsolutions . net >
*
* GPLv2
*/
# include <linux/time.h>
2007-04-26 00:07:04 -07:00
# include <linux/sysdev.h>
2007-03-19 11:53:53 +01:00
# include <asm/rtc.h>
static unsigned long suspend_rtc_time ;
/*
* Reset the time after a sleep .
*/
static int timer_resume ( struct sys_device * dev )
{
struct timeval tv ;
struct timespec ts ;
struct rtc_time cur_rtc_tm ;
unsigned long cur_rtc_time , diff ;
/* get current RTC time and convert to seconds */
get_rtc_time ( & cur_rtc_tm ) ;
2007-05-03 00:25:42 +10:00
cur_rtc_time = mktime ( cur_rtc_tm . tm_year + 1900 ,
cur_rtc_tm . tm_mon + 1 ,
cur_rtc_tm . tm_mday ,
cur_rtc_tm . tm_hour ,
cur_rtc_tm . tm_min ,
cur_rtc_tm . tm_sec ) ;
2007-03-19 11:53:53 +01:00
diff = cur_rtc_time - suspend_rtc_time ;
/* adjust time of day by seconds that elapsed while
* we were suspended */
do_gettimeofday ( & tv ) ;
ts . tv_sec = tv . tv_sec + diff ;
ts . tv_nsec = tv . tv_usec * NSEC_PER_USEC ;
do_settimeofday ( & ts ) ;
return 0 ;
}
static int timer_suspend ( struct sys_device * dev , pm_message_t state )
{
struct rtc_time suspend_rtc_tm ;
WARN_ON ( ! ppc_md . get_rtc_time ) ;
get_rtc_time ( & suspend_rtc_tm ) ;
2007-05-03 00:25:42 +10:00
suspend_rtc_time = mktime ( suspend_rtc_tm . tm_year + 1900 ,
suspend_rtc_tm . tm_mon + 1 ,
suspend_rtc_tm . tm_mday ,
suspend_rtc_tm . tm_hour ,
suspend_rtc_tm . tm_min ,
suspend_rtc_tm . tm_sec ) ;
2007-03-19 11:53:53 +01:00
return 0 ;
}
static struct sysdev_class timer_sysclass = {
. resume = timer_resume ,
. suspend = timer_suspend ,
set_kset_name ( " timer " ) ,
} ;
static struct sys_device device_timer = {
. id = 0 ,
. cls = & timer_sysclass ,
} ;
static int time_init_device ( void )
{
int error = sysdev_class_register ( & timer_sysclass ) ;
if ( ! error )
error = sysdev_register ( & device_timer ) ;
return error ;
}
device_initcall ( time_init_device ) ;