diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-05-30 18:12:02 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-05-30 18:12:02 +0100 |
commit | dc059c5b4927f773b47bc61b50cd43eb75188bd8 (patch) | |
tree | 8254dc08c0d9ff09f83055c2ff648814635cd0c1 | |
parent | 603d6a3905d975db7bd8a591a27ca9600edf4f76 (diff) | |
download | xen-dc059c5b4927f773b47bc61b50cd43eb75188bd8.tar.gz xen-dc059c5b4927f773b47bc61b50cd43eb75188bd8.tar.bz2 xen-dc059c5b4927f773b47bc61b50cd43eb75188bd8.zip |
Add support for ACPI PM Timer as platform clock source.
Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r-- | xen/arch/x86/time.c | 56 | ||||
-rw-r--r-- | xen/include/asm-x86/config.h | 1 |
2 files changed, 56 insertions, 1 deletions
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index d31fa17984..4ba868f3fe 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -511,6 +511,60 @@ static int init_cyclone(void) } /************************************************************ + * PLATFORM TIMER 4: ACPI PM TIMER + */ + +u32 pmtmr_ioport; + +/* Protected by platform_timer_lock. */ +static u64 pmtimer_counter64; +static u32 pmtimer_stamp; +static struct timer pmtimer_overflow_timer; + +/* ACPI PM timer ticks at 3.579545 MHz. */ +#define ACPI_PM_FREQUENCY 3579545 + +/* Deltas are 24-bit unsigned values, as counter may be only 24 bits wide. */ +#define pmtimer_delta(c) ((u32)(((c) - pmtimer_stamp) & ((1U<<24)-1))) + +static void pmtimer_overflow(void *unused) +{ + u32 counter; + + spin_lock_irq(&platform_timer_lock); + counter = inl(pmtmr_ioport); + pmtimer_counter64 += pmtimer_delta(counter); + pmtimer_stamp = counter; + spin_unlock_irq(&platform_timer_lock); + + /* Trigger overflow avoidance roughly when counter increments 2^23. */ + set_timer(&pmtimer_overflow_timer, NOW() + MILLISECS(2000)); +} + +static u64 read_pmtimer_count(void) +{ + return pmtimer_counter64 + pmtimer_delta(inl(pmtmr_ioport)); +} + +static int init_pmtimer(void) +{ + if ( pmtmr_ioport == 0 ) + return 0; + + read_platform_count = read_pmtimer_count; + + init_timer(&pmtimer_overflow_timer, pmtimer_overflow, NULL, 0); + pmtimer_overflow(NULL); + platform_timer_stamp = pmtimer_counter64; + set_time_scale(&platform_timer_scale, ACPI_PM_FREQUENCY); + + printk("Platform timer is %s ACPI PM Timer\n", + freq_string(ACPI_PM_FREQUENCY)); + + return 1; +} + +/************************************************************ * GENERIC PLATFORM TIMER INFRASTRUCTURE */ @@ -549,7 +603,7 @@ static void platform_time_calibration(void) static void init_platform_timer(void) { - if ( !init_cyclone() && !init_hpet() ) + if ( !init_cyclone() && !init_hpet() && !init_pmtimer() ) init_pit(); } diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index b418d5f464..3d93e91968 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -22,6 +22,7 @@ #define CONFIG_X86_LOCAL_APIC 1 #define CONFIG_X86_GOOD_APIC 1 #define CONFIG_X86_IO_APIC 1 +#define CONFIG_X86_PM_TIMER 1 #define CONFIG_HPET_TIMER 1 #define CONFIG_X86_MCE_P4THERMAL 1 #define CONFIG_ACPI_NUMA 1 |