mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-01 00:49:43 +00:00
x86: tsc: Add support for native calibration of TSC freq
Add native tsc calibration function. Calibrate the tsc timer the same way as linux does in arch/x86/kernel/tsc.c. Fixes booting for Apollo Lake processors. Signed-off-by: Bernhard Messerklinger <bernhard.messerklinger@br-automation.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
2436396a11
commit
ca7db866fe
1 changed files with 55 additions and 0 deletions
|
@ -19,8 +19,59 @@
|
||||||
|
|
||||||
#define MAX_NUM_FREQS 9
|
#define MAX_NUM_FREQS 9
|
||||||
|
|
||||||
|
#define INTEL_FAM6_SKYLAKE_MOBILE 0x4E
|
||||||
|
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */
|
||||||
|
#define INTEL_FAM6_SKYLAKE_DESKTOP 0x5E
|
||||||
|
#define INTEL_FAM6_ATOM_GOLDMONT_X 0x5F /* Denverton */
|
||||||
|
#define INTEL_FAM6_KABYLAKE_MOBILE 0x8E
|
||||||
|
#define INTEL_FAM6_KABYLAKE_DESKTOP 0x9E
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* native_calibrate_tsc
|
||||||
|
* Determine TSC frequency via CPUID, else return 0.
|
||||||
|
*/
|
||||||
|
static unsigned long native_calibrate_tsc(void)
|
||||||
|
{
|
||||||
|
struct cpuid_result tsc_info;
|
||||||
|
unsigned int crystal_freq;
|
||||||
|
|
||||||
|
if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (cpuid_eax(0) < 0x15)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tsc_info = cpuid(0x15);
|
||||||
|
|
||||||
|
if (tsc_info.ebx == 0 || tsc_info.eax == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
crystal_freq = tsc_info.ecx / 1000;
|
||||||
|
|
||||||
|
if (!crystal_freq) {
|
||||||
|
switch (gd->arch.x86_model) {
|
||||||
|
case INTEL_FAM6_SKYLAKE_MOBILE:
|
||||||
|
case INTEL_FAM6_SKYLAKE_DESKTOP:
|
||||||
|
case INTEL_FAM6_KABYLAKE_MOBILE:
|
||||||
|
case INTEL_FAM6_KABYLAKE_DESKTOP:
|
||||||
|
crystal_freq = 24000; /* 24.0 MHz */
|
||||||
|
break;
|
||||||
|
case INTEL_FAM6_ATOM_GOLDMONT_X:
|
||||||
|
crystal_freq = 25000; /* 25.0 MHz */
|
||||||
|
break;
|
||||||
|
case INTEL_FAM6_ATOM_GOLDMONT:
|
||||||
|
crystal_freq = 19200; /* 19.2 MHz */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (crystal_freq * tsc_info.ebx / tsc_info.eax) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long cpu_mhz_from_cpuid(void)
|
static unsigned long cpu_mhz_from_cpuid(void)
|
||||||
{
|
{
|
||||||
if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
|
if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
|
||||||
|
@ -350,6 +401,10 @@ static void tsc_timer_ensure_setup(bool early)
|
||||||
if (!gd->arch.clock_rate) {
|
if (!gd->arch.clock_rate) {
|
||||||
unsigned long fast_calibrate;
|
unsigned long fast_calibrate;
|
||||||
|
|
||||||
|
fast_calibrate = native_calibrate_tsc();
|
||||||
|
if (fast_calibrate)
|
||||||
|
goto done;
|
||||||
|
|
||||||
fast_calibrate = cpu_mhz_from_cpuid();
|
fast_calibrate = cpu_mhz_from_cpuid();
|
||||||
if (fast_calibrate)
|
if (fast_calibrate)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
Loading…
Reference in a new issue