diff options
author | Subrata Banik <subrata.banik@intel.com> | 2019-08-29 13:43:30 +0530 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2019-09-02 20:08:20 +0000 |
commit | 809b7513a21e04f087eaab4bc06be9978826b4a3 (patch) | |
tree | 3bfcb9b68696eecec17b4580bb5e615c87681a20 /src/soc/intel | |
parent | c54dcf499b62ae48c5b8322f3ea9714ebd4d1108 (diff) |
soc/intel/common/timer: Make TSC frequency calculation dynamically
tsc_freq_mhz() had a static table of Intel CPU families and crystal
clock, but it is possible to calculate the crystal clock speed dynamically,
and this is preferred over hardcoded table.
On SKL/KBL/CML CPUID.15h.ecx = nominal core crystal clock = 0 Hz
hence we had to use static table to calculate crystal clock.
Recommendation is to make use of CPUID.16h where crystal clock frequency
was not reported by CPUID.15h to calculate the crystal clock.
BUG=b:139798422, b:129839774
TEST=Able to build and boot KBL/CML/ICL.
Change-Id: If660a4b8d12e54b39252bce62bcc0ffcc967f5da
Signed-off-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/35148
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Reviewed-by: V Sowmya <v.sowmya@intel.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc/intel')
-rw-r--r-- | src/soc/intel/common/block/timer/timer.c | 105 |
1 files changed, 75 insertions, 30 deletions
diff --git a/src/soc/intel/common/block/timer/timer.c b/src/soc/intel/common/block/timer/timer.c index e60ac4d26d..8fde5419d3 100644 --- a/src/soc/intel/common/block/timer/timer.c +++ b/src/soc/intel/common/block/timer/timer.c @@ -14,12 +14,14 @@ */ #include <arch/cpu.h> -#include <arch/intel-family.h> #include <cpu/cpu.h> #include <cpu/x86/msr.h> #include <cpu/x86/tsc.h> #include <intelblocks/msr.h> +/* Goldmont Microserver */ +#define CPU_MODEL_INTEL_ATOM_DENVERTON 0x5F + static int get_processor_model(void) { struct cpuinfo_x86 c; @@ -29,8 +31,31 @@ static int get_processor_model(void) return c.x86_model; } +static unsigned int get_max_cpuid_func(void) +{ + return cpuid_eax(0); +} + +static unsigned long get_hardcoded_crystal_freq(void) +{ + unsigned int core_crystal_nominal_freq_khz; + + /* + * Denverton SoCs don't report crystal clock, and also don't support + * CPUID.0x16, so hardcode the 25MHz crystal clock. + */ + switch (get_processor_model()) { + case CPU_MODEL_INTEL_ATOM_DENVERTON: + core_crystal_nominal_freq_khz = 25000; + break; + } + + return core_crystal_nominal_freq_khz; +} + /* - * Nominal TSC frequency = "core crystal clock frequency" * EBX/EAX + * Nominal TSC frequency = "core crystal clock frequency" * + * CPUID_15h.EBX/CPUID_15h.EAX * * Time Stamp Counter * CPUID Initial EAX value = 0x15 @@ -42,41 +67,61 @@ static int get_processor_model(void) * core crystal clock in Hz. * EDX Bit 31-0 : Reserved = 0 * - * Refer to Intel SDM Jan 2019 Vol 3B Section 18.7.3 */ -unsigned long tsc_freq_mhz(void) +static unsigned long calculate_tsc_freq_from_core_crystal(void) { unsigned int core_crystal_nominal_freq_khz; - struct cpuid_result cpuidr; + struct cpuid_result cpuidr_15h; + + if (get_max_cpuid_func() < 0x15) + return 0; /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */ - cpuidr = cpuid(0x15); + cpuidr_15h = cpuid(0x15); - if (!cpuidr.ebx || !cpuidr.eax) + if (!cpuidr_15h.ebx || !cpuidr_15h.eax) return 0; - core_crystal_nominal_freq_khz = cpuidr.ecx / 1000; - - if (!core_crystal_nominal_freq_khz) { - switch (get_processor_model()) { - case CPU_MODEL_INTEL_SKYLAKE_MOBILE: - case CPU_MODEL_INTEL_SKYLAKE_DESKTOP: - case CPU_MODEL_INTEL_KABYLAKE_MOBILE: - case CPU_MODEL_INTEL_KABYLAKE_DESKTOP: - case CPU_MODEL_INTEL_CANNONLAKE_MOBILE: - case CPU_MODEL_INTEL_ICELAKE_MOBILE: - core_crystal_nominal_freq_khz = 24000; - break; - case CPU_MODEL_INTEL_ATOM_DENVERTON: - core_crystal_nominal_freq_khz = 25000; - break; - case CPU_MODEL_INTEL_ATOM_GOLDMONT: - case CPU_MODEL_INTEL_ATOM_GEMINI_LAKE: - core_crystal_nominal_freq_khz = 19200; - break; - } - } + core_crystal_nominal_freq_khz = cpuidr_15h.ecx / 1000; + + if (!core_crystal_nominal_freq_khz) + core_crystal_nominal_freq_khz = get_hardcoded_crystal_freq(); + + return (core_crystal_nominal_freq_khz * cpuidr_15h.ebx / + cpuidr_15h.eax) / 1000; +} + +/* + * Processor Frequency Information + * CPUID Initial EAX value = 0x16 + * EAX Bit 31-0 : An unsigned integer which has the processor base frequency + * information + * EBX Bit 31-0 : An unsigned integer which has maximum frequency information + * ECX Bit 31-0 : An unsigned integer which has bus frequency information + * EDX Bit 31-0 : Reserved = 0 + * + * Refer to Intel SDM Jan 2019 Vol 3B Section 18.7.3 + */ +static unsigned long get_freq_from_cpuid16h(void) +{ + if (get_max_cpuid_func() < 0x16) + return 0; + + return cpuid_eax(0x16); +} + +unsigned long tsc_freq_mhz(void) +{ + unsigned long tsc_freq; + + tsc_freq = calculate_tsc_freq_from_core_crystal(); + + if (tsc_freq) + return tsc_freq; - return (core_crystal_nominal_freq_khz * cpuidr.ebx / cpuidr.eax) / - 1000; + /* + * Some Intel SoCs like Skylake, Kabylake and Cometlake don't report + * the crystal clock, in that case return bus frequency using CPUID.16h + */ + return get_freq_from_cpuid16h(); } |