/* * Common code to keep time when machine suspends. * * Copyright 2007 Johannes Berg * * GPLv2 */ #include #include #include 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);