summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/common/block/timer/timer.c105
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();
}