#include <asm/hpet.h>
#include <asm/sections.h>
#include <linux/cpufreq.h>
-#include <linux/hpet.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/apic.h>
#endif
spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
static int nohpet __initdata = 0;
-static int notsc __initdata = 0;
#undef HPET_HACK_ENABLE_DANGEROUS
+
unsigned int cpu_khz; /* TSC clocks / usec, not used here */
unsigned long hpet_period; /* fsecs / HPET clock */
unsigned long hpet_tick; /* HPET clocks / interrupt */
print_symbol("rip %s)\n", regs->rip);
}
- if (lost_count == 1000 && !warned) {
+ if (lost_count == 100 && !warned) {
printk(KERN_WARNING
"warning: many lost ticks.\n"
KERN_WARNING "Your time source seems to be instable or "
*/
do_timer(regs);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(regs));
-#endif
/*
* In the SMP case we use the local APIC timer interrupt to do the profiling,
return (end - start) / 50;
}
-#ifdef CONFIG_HPET
-static __init int late_hpet_init(void)
+static int hpet_init(void)
{
- struct hpet_data hd;
- unsigned int ntimer;
+ unsigned int cfg, id;
if (!vxtime.hpet_address)
- return -1;
-
- memset(&hd, 0, sizeof (hd));
-
- ntimer = hpet_readl(HPET_ID);
- ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
- ntimer++;
-
- /*
- * Register with driver.
- * Timer0 and Timer1 is used by platform.
- */
- hd.hd_phys_address = vxtime.hpet_address;
- hd.hd_address = (void *)fix_to_virt(FIX_HPET_BASE);
- hd.hd_nirqs = ntimer;
- hd.hd_flags = HPET_DATA_PLATFORM;
- hpet_reserve_timer(&hd, 0);
-#ifdef CONFIG_HPET_EMULATE_RTC
- hpet_reserve_timer(&hd, 1);
-#endif
- hd.hd_irq[0] = HPET_LEGACY_8254;
- hd.hd_irq[1] = HPET_LEGACY_RTC;
- if (ntimer > 2) {
- struct hpet *hpet;
- struct hpet_timer *timer;
- int i;
+ return -1;
+ set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address);
+ __set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
- hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
+/*
+ * Read the period, compute tick and quotient.
+ */
- for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer;
- timer++, i++)
- hd.hd_irq[i] = (timer->hpet_config &
- Tn_INT_ROUTE_CNF_MASK) >>
- Tn_INT_ROUTE_CNF_SHIFT;
+ id = hpet_readl(HPET_ID);
- }
+ if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) ||
+ !(id & HPET_ID_LEGSUP))
+ return -1;
- hpet_alloc(&hd);
- return 0;
-}
-fs_initcall(late_hpet_init);
-#endif
+ hpet_period = hpet_readl(HPET_PERIOD);
+ if (hpet_period < 100000 || hpet_period > 100000000)
+ return -1;
-static int hpet_timer_stop_set_go(unsigned long tick)
-{
- unsigned int cfg;
+ hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
+ hpet_period;
/*
* Stop the timers and reset the main counter.
return 0;
}
-static int hpet_init(void)
-{
- unsigned int id;
-
- if (!vxtime.hpet_address)
- return -1;
- set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address);
- __set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
-
-/*
- * Read the period, compute tick and quotient.
- */
-
- id = hpet_readl(HPET_ID);
-
- if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) ||
- !(id & HPET_ID_LEGSUP))
- return -1;
-
- hpet_period = hpet_readl(HPET_PERIOD);
- if (hpet_period < 100000 || hpet_period > 100000000)
- return -1;
-
- hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
- hpet_period;
-
- return hpet_timer_stop_set_go(hpet_tick);
-}
-
-static int hpet_reenable(void)
-{
- return hpet_timer_stop_set_go(hpet_tick);
-}
-
void __init pit_init(void)
{
unsigned long flags;
{
char *timetype;
- /*
- * AMD systems with more than one CPU don't have fully synchronized
- * TSCs. Always use HPET gettimeofday for these, although it is slower.
- * Intel SMP systems usually have synchronized TSCs, so use always
- * the TSC.
- *
- * Exceptions:
- * IBM Summit2 checked by oem_force_hpet_timer().
- * AMD dual core may also not need HPET. Check me.
- *
- * Can be turned off with "notsc".
- */
- if (num_online_cpus() > 1 &&
- boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
- notsc = 1;
- /* Some systems will want to disable TSC and use HPET. */
- if (oem_force_hpet_timer())
- notsc = 1;
- if (vxtime.hpet_address && notsc) {
+ if (vxtime.hpet_address) {
timetype = "HPET";
vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
vxtime.mode = VXTIME_HPET;
do_gettimeoffset = do_gettimeoffset_hpet;
} else {
- timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC";
+ timetype = "PIT/TSC";
vxtime.mode = VXTIME_TSC;
}
-
printk(KERN_INFO "time.c: Using %s based timekeeping.\n", timetype);
}
static long clock_cmos_diff;
-static int timer_suspend(struct sys_device *dev, u32 state)
+static int time_suspend(struct sys_device *dev, u32 state)
{
/*
* Estimate time zone so that set_time can update the clock
return 0;
}
-static int timer_resume(struct sys_device *dev)
+static int time_resume(struct sys_device *dev)
{
unsigned long flags;
- unsigned long sec;
-
- if (vxtime.hpet_address)
- hpet_reenable();
-
- sec = get_cmos_time() + clock_cmos_diff;
+ unsigned long sec = get_cmos_time() + clock_cmos_diff;
write_seqlock_irqsave(&xtime_lock,flags);
xtime.tv_sec = sec;
xtime.tv_nsec = 0;
return 0;
}
-static struct sysdev_class timer_sysclass = {
- .resume = timer_resume,
- .suspend = timer_suspend,
- set_kset_name("timer"),
+static struct sysdev_class pit_sysclass = {
+ .resume = time_resume,
+ .suspend = time_suspend,
+ set_kset_name("pit"),
};
/* XXX this driverfs stuff should probably go elsewhere later -john */
-static struct sys_device device_timer = {
+static struct sys_device device_i8253 = {
.id = 0,
- .cls = &timer_sysclass,
+ .cls = &pit_sysclass,
};
static int time_init_device(void)
{
- int error = sysdev_class_register(&timer_sysclass);
+ int error = sysdev_class_register(&pit_sysclass);
if (!error)
- error = sysdev_register(&device_timer);
+ error = sysdev_register(&device_i8253);
return error;
}
}
__setup("nohpet", nohpet_setup);
-
-
-static int __init notsc_setup(char *s)
-{
- notsc = 1;
- return 0;
-}
-
-__setup("notsc", notsc_setup);
-
-