x86: Allow a hardcoded TSC frequency provided by Kconfig
authorBin Meng <bmeng.cn@gmail.com>
Tue, 6 Jan 2015 14:14:14 +0000 (22:14 +0800)
committerSimon Glass <sjg@chromium.org>
Tue, 13 Jan 2015 15:25:02 +0000 (07:25 -0800)
By default U-Boot automatically calibrates TSC running frequency via
MSR and PIT. The calibration may not work on every x86 processor, so
a new Kconfig option CONFIG_TSC_CALIBRATION_BYPASS is introduced to
allow bypassing the calibration and assign a hardcoded TSC frequency
CONFIG_TSC_FREQ_IN_MHZ.

Normally the bypass should be turned on in a simulation environment
like qemu.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
arch/x86/Kconfig
arch/x86/lib/tsc_timer.c

index e992e647cca3453011e22829d755efbcb2813288..ffcb4cb665968463746073f5c353702be42f55c5 100644 (file)
@@ -313,6 +313,26 @@ config FRAMEBUFFER_VESA_MODE
 
 endmenu
 
+config TSC_CALIBRATION_BYPASS
+       bool "Bypass Time-Stamp Counter (TSC) calibration"
+       default n
+       help
+         By default U-Boot automatically calibrates Time-Stamp Counter (TSC)
+         running frequency via Model-Specific Register (MSR) and Programmable
+         Interval Timer (PIT). If the calibration does not work on your board,
+         select this option and provide a hardcoded TSC running frequency with
+         CONFIG_TSC_FREQ_IN_MHZ below.
+
+         Normally this option should be turned on in a simulation environment
+         like qemu.
+
+config TSC_FREQ_IN_MHZ
+       int "Time-Stamp Counter (TSC) running frequency in MHz"
+       depends on TSC_CALIBRATION_BYPASS
+       default 1000
+       help
+         The running frequency in MHz of Time-Stamp Counter (TSC).
+
 source "arch/x86/cpu/ivybridge/Kconfig"
 
 source "arch/x86/cpu/queensbay/Kconfig"
index fb9afed18fda9d64da3fb84259cb59f4dbbad906..7f5ba2ca6f1dd69f2d461723fec4536fc92a4523 100644 (file)
@@ -78,7 +78,7 @@ static int match_cpu(u8 family, u8 model)
  *
  * Returns the calibration value or 0 if MSR calibration failed.
  */
-static unsigned long try_msr_calibrate_tsc(void)
+static unsigned long __maybe_unused try_msr_calibrate_tsc(void)
 {
        u32 lo, hi, ratio, freq_id, freq;
        unsigned long res;
@@ -199,7 +199,7 @@ static inline int pit_expect_msb(unsigned char val, u64 *tscp,
 #define MAX_QUICK_PIT_MS 50
 #define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
 
-static unsigned long quick_pit_calibrate(void)
+static unsigned long __maybe_unused quick_pit_calibrate(void)
 {
        int i;
        u64 tsc, delta;
@@ -306,6 +306,9 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
        if (gd->arch.tsc_mhz)
                return gd->arch.tsc_mhz;
 
+#ifdef CONFIG_TSC_CALIBRATION_BYPASS
+       fast_calibrate = CONFIG_TSC_FREQ_IN_MHZ;
+#else
        fast_calibrate = try_msr_calibrate_tsc();
        if (!fast_calibrate) {
 
@@ -313,6 +316,7 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
                if (!fast_calibrate)
                        panic("TSC frequency is ZERO");
        }
+#endif
 
        gd->arch.tsc_mhz = fast_calibrate;
        return fast_calibrate;