diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/cpu/coreboot/timestamp.c | 4 | ||||
-rw-r--r-- | arch/x86/cpu/timer.c | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/u-boot-x86.h | 2 | ||||
-rw-r--r-- | arch/x86/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/lib/tsc_timer.c | 103 |
5 files changed, 112 insertions, 1 deletions
diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c index 2ca7a57..d26718e 100644 --- a/arch/x86/cpu/coreboot/timestamp.c +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -39,7 +39,9 @@ static struct timestamp_table *ts_table __attribute__((section(".data"))); void timestamp_init(void) { ts_table = lib_sysinfo.tstamp_table; - timer_set_tsc_base(ts_table->base_time); +#ifdef CONFIG_SYS_X86_TSC_TIMER + timer_set_base(ts_table->base_time); +#endif timestamp_add_now(TS_U_BOOT_INITTED); } diff --git a/arch/x86/cpu/timer.c b/arch/x86/cpu/timer.c index 149109d..f95fce5 100644 --- a/arch/x86/cpu/timer.c +++ b/arch/x86/cpu/timer.c @@ -10,8 +10,11 @@ #include <common.h> +/* Temporary patch to maintain bisectability, removed in next commit */ +#ifndef CONFIG_SYS_X86_TSC_TIMER unsigned long timer_get_us(void) { printf("timer_get_us used but not implemented.\n"); return 0; } +#endif diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 5a59db6..bec583f 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -39,6 +39,8 @@ void panic_puts(const char *str); void timer_isr(void *); typedef void (timer_fnc_t) (void); int register_timer_isr (timer_fnc_t *isr_func); +unsigned long get_tbclk_mhz(void); +void timer_set_base(uint64_t base); /* Architecture specific - can be in arch/x86/cpu/, arch/x86/lib/, or $(BOARD)/ */ int dram_init_f(void); diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 962593d..0bc8c2f 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -37,6 +37,7 @@ COBJS-y += relocate.o COBJS-y += physmem.o COBJS-y += string.o COBJS-$(CONFIG_SYS_X86_ISR_TIMER) += timer.o +COBJS-$(CONFIG_SYS_X86_TSC_TIMER) += tsc_timer.o COBJS-$(CONFIG_VIDEO_VGA) += video.o COBJS-$(CONFIG_CMD_ZBOOT) += zimage.o diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c new file mode 100644 index 0000000..d931e5f --- /dev/null +++ b/arch/x86/lib/tsc_timer.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/i8254.h> +#include <asm/ibmpc.h> +#include <asm/msr.h> +#include <asm/u-boot-x86.h> + +DECLARE_GLOBAL_DATA_PTR; + +void timer_set_base(u64 base) +{ + gd->arch.tsc_base = base; +} + +/* + * Get the number of CPU time counter ticks since it was read first time after + * restart. This yields a free running counter guaranteed to take almost 6 + * years to wrap around even at 100GHz clock rate. + */ +u64 get_ticks(void) +{ + u64 now_tick = rdtsc(); + + /* We assume that 0 means the base hasn't been set yet */ + if (!gd->arch.tsc_base) + panic("No tick base available"); + return now_tick - gd->arch.tsc_base; +} + +#define PLATFORM_INFO_MSR 0xce + +/* Get the speed of the TSC timer in MHz */ +unsigned long get_tbclk_mhz(void) +{ + u32 ratio; + u64 platform_info = native_read_msr(PLATFORM_INFO_MSR); + + /* 100MHz times Max Non Turbo ratio */ + ratio = (platform_info >> 8) & 0xff; + return 100 * ratio; +} + +unsigned long get_tbclk(void) +{ + return get_tbclk_mhz() * 1000 * 1000; +} + +static ulong get_ms_timer(void) +{ + return (get_ticks() * 1000) / get_tbclk(); +} + +ulong get_timer(ulong base) +{ + return get_ms_timer() - base; +} + +ulong timer_get_us(void) +{ + return get_ticks() / get_tbclk_mhz(); +} + +ulong timer_get_boot_us(void) +{ + return timer_get_us(); +} + +void __udelay(unsigned long usec) +{ + u64 now = get_ticks(); + u64 stop; + + stop = now + usec * get_tbclk_mhz(); + + while ((int64_t)(stop - get_ticks()) > 0) + ; +} + +int timer_init(void) +{ + /* Nothing to do here - the timer needs no init */ + return 0; +} |