82 строки
1.7 KiB
C
82 строки
1.7 KiB
C
/*
|
|
* Common code to keep time when machine suspends.
|
|
*
|
|
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
|
*
|
|
* GPLv2
|
|
*/
|
|
|
|
#include <linux/time.h>
|
|
#include <linux/sysdev.h>
|
|
#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);
|
|
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);
|
|
|
|
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);
|
|
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);
|
|
|
|
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);
|