#include <linux/sysdev.h>
#include <linux/bcd.h>
#include <linux/efi.h>
+#include <linux/mca.h>
#include <asm/io.h>
#include <asm/smp.h>
extern unsigned long wall_jiffies;
-spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(rtc_lock);
-spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(i8253_lock);
EXPORT_SYMBOL(i8253_lock);
struct timer_opts *cur_timer = &timer_none;
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
}
-#ifdef CONFIG_MCA
- if( MCA_bus ) {
+ if (MCA_bus) {
/* The PS/2 uses level-triggered interrupts. You can't
turn them off, nor would you want to (any attempt to
enable edge-triggered interrupts usually gets intercepted by a
irq = inb_p( 0x61 ); /* read the current state */
outb_p( irq|0x80, 0x61 ); /* reset the IRQ */
}
-#endif
}
/*
return retval;
}
-static long clock_cmos_diff;
+static long clock_cmos_diff, sleep_start;
-static int time_suspend(struct sys_device *dev, u32 state)
+static int timer_suspend(struct sys_device *dev, u32 state)
{
/*
* Estimate time zone so that set_time can update the clock
*/
clock_cmos_diff = -get_cmos_time();
clock_cmos_diff += get_seconds();
+ sleep_start = get_cmos_time();
return 0;
}
-static int time_resume(struct sys_device *dev)
+static int timer_resume(struct sys_device *dev)
{
unsigned long flags;
- unsigned long sec = get_cmos_time() + clock_cmos_diff;
+ unsigned long sec;
+ unsigned long sleep_length;
+
+#ifdef CONFIG_HPET_TIMER
+ if (is_hpet_enabled())
+ hpet_reenable();
+#endif
+ sec = get_cmos_time() + clock_cmos_diff;
+ sleep_length = (get_cmos_time() - sleep_start) * HZ;
write_seqlock_irqsave(&xtime_lock, flags);
xtime.tv_sec = sec;
xtime.tv_nsec = 0;
write_sequnlock_irqrestore(&xtime_lock, flags);
+ jiffies += sleep_length;
+ wall_jiffies += sleep_length;
return 0;
}
-static struct sysdev_class pit_sysclass = {
- .resume = time_resume,
- .suspend = time_suspend,
- set_kset_name("pit"),
+static struct sysdev_class timer_sysclass = {
+ .resume = timer_resume,
+ .suspend = timer_suspend,
+ set_kset_name("timer"),
};
/* XXX this driverfs stuff should probably go elsewhere later -john */
-static struct sys_device device_i8253 = {
+static struct sys_device device_timer = {
.id = 0,
- .cls = &pit_sysclass,
+ .cls = &timer_sysclass,
};
static int time_init_device(void)
{
- int error = sysdev_class_register(&pit_sysclass);
+ int error = sysdev_class_register(&timer_sysclass);
if (!error)
- error = sysdev_register(&device_i8253);
+ error = sysdev_register(&device_timer);
return error;
}
void __init hpet_time_init(void)
{
xtime.tv_sec = get_cmos_time();
- wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
if (hpet_enable() >= 0) {
printk("Using HPET for base-timer\n");
}
#endif
xtime.tv_sec = get_cmos_time();
- wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
- wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
cur_timer = select_timer();
printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);