x86: Allow a hardcoded TSC frequency provided by Kconfig
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>
This commit is contained in:
@@ -313,6 +313,26 @@ config FRAMEBUFFER_VESA_MODE
|
|||||||
|
|
||||||
endmenu
|
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/ivybridge/Kconfig"
|
||||||
|
|
||||||
source "arch/x86/cpu/queensbay/Kconfig"
|
source "arch/x86/cpu/queensbay/Kconfig"
|
||||||
|
@@ -78,7 +78,7 @@ static int match_cpu(u8 family, u8 model)
|
|||||||
*
|
*
|
||||||
* Returns the calibration value or 0 if MSR calibration failed.
|
* 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;
|
u32 lo, hi, ratio, freq_id, freq;
|
||||||
unsigned long res;
|
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_MS 50
|
||||||
#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
|
#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;
|
int i;
|
||||||
u64 tsc, delta;
|
u64 tsc, delta;
|
||||||
@@ -306,6 +306,9 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
|
|||||||
if (gd->arch.tsc_mhz)
|
if (gd->arch.tsc_mhz)
|
||||||
return 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();
|
fast_calibrate = try_msr_calibrate_tsc();
|
||||||
if (!fast_calibrate) {
|
if (!fast_calibrate) {
|
||||||
|
|
||||||
@@ -313,6 +316,7 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
|
|||||||
if (!fast_calibrate)
|
if (!fast_calibrate)
|
||||||
panic("TSC frequency is ZERO");
|
panic("TSC frequency is ZERO");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
gd->arch.tsc_mhz = fast_calibrate;
|
gd->arch.tsc_mhz = fast_calibrate;
|
||||||
return fast_calibrate;
|
return fast_calibrate;
|
||||||
|
Reference in New Issue
Block a user