coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
timer.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/cpu.h>
4 #include <cpu/x86/msr.h>
5 #include <cpu/x86/tsc.h>
6 #include <intelblocks/msr.h>
7 
8 /* Goldmont Microserver */
9 #define CPU_MODEL_INTEL_ATOM_DENVERTON 0x5F
10 
11 static int get_processor_model(void)
12 {
13  struct cpuinfo_x86 c;
14 
15  get_fms(&c, cpuid_eax(1));
16 
17  return c.x86_model;
18 }
19 
20 static unsigned long get_hardcoded_crystal_freq(void)
21 {
22  unsigned long core_crystal_nominal_freq_khz = 0;
23 
24  /*
25  * Denverton SoCs don't report crystal clock, and also don't support
26  * CPUID.0x16, so hardcode the 25MHz crystal clock.
27  */
28  switch (get_processor_model()) {
30  core_crystal_nominal_freq_khz = 25000;
31  break;
32  }
33 
34  return core_crystal_nominal_freq_khz;
35 }
36 
37 /*
38  * Nominal TSC frequency = "core crystal clock frequency" *
39  * CPUID_15h.EBX/CPUID_15h.EAX
40  *
41  * Time Stamp Counter
42  * CPUID Initial EAX value = 0x15
43  * EAX Bit 31-0 : An unsigned integer which is the denominator of the
44  * TSC/"core crystal clock" ratio
45  * EBX Bit 31-0 : An unsigned integer which is the numerator of the
46  * TSC/"core crystal clock" ratio
47  * ECX Bit 31-0 : An unsigned integer which is the nominal frequency of the
48  * core crystal clock in Hz.
49  * EDX Bit 31-0 : Reserved = 0
50  *
51  */
52 static unsigned long calculate_tsc_freq_from_core_crystal(void)
53 {
54  unsigned long core_crystal_nominal_freq_khz;
55  struct cpuid_result cpuidr_15h;
56 
57  if (cpuid_get_max_func() < 0x15)
58  return 0;
59 
60  /* CPUID 15H TSC/Crystal ratio, plus optionally Crystal Hz */
61  cpuidr_15h = cpuid(0x15);
62 
63  if (!cpuidr_15h.ebx || !cpuidr_15h.eax)
64  return 0;
65 
66  core_crystal_nominal_freq_khz = cpuidr_15h.ecx / 1000;
67 
68  if (!core_crystal_nominal_freq_khz)
69  core_crystal_nominal_freq_khz = get_hardcoded_crystal_freq();
70 
71  return (core_crystal_nominal_freq_khz * cpuidr_15h.ebx /
72  cpuidr_15h.eax) / 1000;
73 }
74 
75 /*
76  * Processor Frequency Information
77  * CPUID Initial EAX value = 0x16
78  * EAX Bit 31-0 : An unsigned integer which has the processor base frequency
79  * information
80  * EBX Bit 31-0 : An unsigned integer which has maximum frequency information
81  * ECX Bit 31-0 : An unsigned integer which has bus frequency information
82  * EDX Bit 31-0 : Reserved = 0
83  *
84  * Refer to Intel SDM Jan 2019 Vol 3B Section 18.7.3
85  */
86 static unsigned long get_freq_from_cpuid16h(void)
87 {
88  if (cpuid_get_max_func() < 0x16)
89  return 0;
90 
91  return cpuid_eax(0x16);
92 }
93 
94 unsigned long tsc_freq_mhz(void)
95 {
96  unsigned long tsc_freq;
97 
99 
100  if (tsc_freq)
101  return tsc_freq;
102 
103  /*
104  * Some Intel SoCs like Skylake, Kabylake and Cometlake don't report
105  * the crystal clock, in that case return bus frequency using CPUID.16h
106  */
107  return get_freq_from_cpuid16h();
108 }
static unsigned int cpuid_get_max_func(void)
Definition: cpu.h:132
static unsigned int cpuid_eax(unsigned int op)
Definition: cpu.h:79
static void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
Definition: cpu.h:278
u32 cpuid
unsigned long tsc_freq_mhz(void)
Definition: timer.c:94
static unsigned long get_hardcoded_crystal_freq(void)
Definition: timer.c:20
static unsigned long get_freq_from_cpuid16h(void)
Definition: timer.c:86
#define CPU_MODEL_INTEL_ATOM_DENVERTON
Definition: timer.c:9
static unsigned long calculate_tsc_freq_from_core_crystal(void)
Definition: timer.c:52
static int get_processor_model(void)
Definition: timer.c:11
uint32_t ecx
Definition: cpu.h:32
uint32_t ebx
Definition: cpu.h:31
uint32_t eax
Definition: cpu.h:30
#define c(value, pmcreg, dst_bits)