Message ID | 1366251228-19884-8-git-send-email-sjg@chromium.org |
---|---|
State | Accepted, archived |
Delegated to: | Simon Glass |
Headers | show |
Hi Simon, On Thu, Apr 18, 2013 at 12:13 PM, Simon Glass <sjg@chromium.org> wrote: > > This timer runs at a rate that can be calculated, well over 100MHz. It is > ideal for accurate timing and does not need interrupt servicing. > > Tidy up some old broken and unneeded implementations at the same time. > > To provide a consistent view of boot time, we use the same time > base as coreboot. Use the base timestamp supplied by coreboot > as U-Boot's base time. > > Signed-off-by: Simon Glass <sjg@chromium.org>base > Signed-off-by: Simon Glass <sjg@chromium.org> > --- > arch/x86/cpu/coreboot/timestamp.c | 4 +- > arch/x86/cpu/timer.c | 3 ++ > arch/x86/include/asm/u-boot-x86.h | 2 + > arch/x86/lib/Makefile | 1 + > arch/x86/lib/tsc_timer.c | 103 ++++++++++++++++++++++++++++++++++++++ > include/configs/coreboot.h | 4 +- > 6 files changed, 113 insertions(+), 4 deletions(-) > create mode 100644 arch/x86/lib/tsc_timer.c > > 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 Why bother? Why not just one commit 'Replace timer implementation with TSC Timer'? > 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; > +} > diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h > index 5bacc77..99408dc 100644 > --- a/include/configs/coreboot.h > +++ b/include/configs/coreboot.h > @@ -38,7 +38,6 @@ > #define CONFIG_SHOW_BOOT_PROGRESS > #define CONFIG_LAST_STAGE_INIT > #define CONFIG_SYS_VSNPRINTF > -#define CONFIG_INTEL_CORE_ARCH /* Sandy bridge and ivy bridge chipsets. */ Why this? > #define CONFIG_ZBOOT_32 > #define CONFIG_PHYSMEM > #define CONFIG_SYS_EARLY_PCI_INIT > @@ -218,7 +217,6 @@ > #define CONFIG_SYS_MEMTEST_END 0x01000000 > #define CONFIG_SYS_LOAD_ADDR 0x100000 > #define CONFIG_SYS_HZ 1000 > -#define CONFIG_SYS_X86_ISR_TIMER > > /*----------------------------------------------------------------------- > * SDRAM Configuration > @@ -235,7 +233,7 @@ > * CPU Features > */ > > -#define CONFIG_SYS_GENERIC_TIMER > +#define CONFIG_SYS_X86_TSC_TIMER > #define CONFIG_SYS_PCAT_INTERRUPTS > #define CONFIG_SYS_NUM_IRQS 16 > > -- > 1.8.2.1 > Regards, Graeme
Hi Graeme, On Wed, Apr 17, 2013 at 8:03 PM, Graeme Russ <graeme.russ@gmail.com> wrote: > Hi Simon, > > > > On Thu, Apr 18, 2013 at 12:13 PM, Simon Glass <sjg@chromium.org> wrote: >> >> This timer runs at a rate that can be calculated, well over 100MHz. It is >> ideal for accurate timing and does not need interrupt servicing. >> >> Tidy up some old broken and unneeded implementations at the same time. >> >> To provide a consistent view of boot time, we use the same time >> base as coreboot. Use the base timestamp supplied by coreboot >> as U-Boot's base time. >> >> Signed-off-by: Simon Glass <sjg@chromium.org>base >> Signed-off-by: Simon Glass <sjg@chromium.org> >> --- >> arch/x86/cpu/coreboot/timestamp.c | 4 +- >> arch/x86/cpu/timer.c | 3 ++ >> arch/x86/include/asm/u-boot-x86.h | 2 + >> arch/x86/lib/Makefile | 1 + >> arch/x86/lib/tsc_timer.c | 103 >> ++++++++++++++++++++++++++++++++++++++ >> include/configs/coreboot.h | 4 +- >> 6 files changed, 113 insertions(+), 4 deletions(-) >> create mode 100644 arch/x86/lib/tsc_timer.c >> >> 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 > > Why bother? Why not just one commit 'Replace timer implementation with TSC > Timer'? OK will do. > >> 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; >> +} >> diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h >> index 5bacc77..99408dc 100644 >> --- a/include/configs/coreboot.h >> +++ b/include/configs/coreboot.h >> @@ -38,7 +38,6 @@ >> #define CONFIG_SHOW_BOOT_PROGRESS >> #define CONFIG_LAST_STAGE_INIT >> #define CONFIG_SYS_VSNPRINTF >> -#define CONFIG_INTEL_CORE_ARCH /* Sandy bridge and ivy bridge chipsets. >> */ > > Why this? We don't need the code that is enabled by this CONFIG, and we don't need the CONFIG. I will squash this in also. Regards, Simon
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; +} diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index 5bacc77..99408dc 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -38,7 +38,6 @@ #define CONFIG_SHOW_BOOT_PROGRESS #define CONFIG_LAST_STAGE_INIT #define CONFIG_SYS_VSNPRINTF -#define CONFIG_INTEL_CORE_ARCH /* Sandy bridge and ivy bridge chipsets. */ #define CONFIG_ZBOOT_32 #define CONFIG_PHYSMEM #define CONFIG_SYS_EARLY_PCI_INIT @@ -218,7 +217,6 @@ #define CONFIG_SYS_MEMTEST_END 0x01000000 #define CONFIG_SYS_LOAD_ADDR 0x100000 #define CONFIG_SYS_HZ 1000 -#define CONFIG_SYS_X86_ISR_TIMER /*----------------------------------------------------------------------- * SDRAM Configuration @@ -235,7 +233,7 @@ * CPU Features */ -#define CONFIG_SYS_GENERIC_TIMER +#define CONFIG_SYS_X86_TSC_TIMER #define CONFIG_SYS_PCAT_INTERRUPTS #define CONFIG_SYS_NUM_IRQS 16