coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
fsb.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 <cpu/intel/speedstep.h>
7 #include <cpu/intel/fsb.h>
8 #include <console/console.h>
9 #include <commonlib/helpers.h>
10 #include <delay.h>
11 
12 static u32 timer_fsb;
13 static u32 timer_tsc;
14 
15 /* This is not an architectural MSR. */
16 #define MSR_PLATFORM_INFO 0xce
17 
18 static int get_fsb_tsc(int *fsb, int *ratio)
19 {
20  struct cpuinfo_x86 c;
21  static const short core_fsb[8] = { -1, 133, -1, 166, -1, 100, -1, -1 };
22  static const short core2_fsb[8] = { 266, 133, 200, 166, 333, 100, 400, -1 };
23  static const short f2x_fsb[8] = { 100, 133, 200, 166, 333, -1, -1, -1 };
24  static const short rangeley_fsb[4] = { 83, 100, 133, 116 };
25  msr_t msr;
26 
27  get_fms(&c, cpuid_eax(1));
28  switch (c.x86) {
29  case 0x6:
30  switch (c.x86_model) {
31  case 0xe: /* Core Solo/Duo */
32  case 0x1c: /* Atom */
33  *fsb = core_fsb[rdmsr(MSR_FSB_FREQ).lo & 7];
34  *ratio = (rdmsr(IA32_PERF_STATUS).hi >> 8) & 0x1f;
35  break;
36  case 0xf: /* Core 2 or Xeon */
37  case 0x17: /* Enhanced Core */
38  *fsb = core2_fsb[rdmsr(MSR_FSB_FREQ).lo & 7];
39  *ratio = (rdmsr(IA32_PERF_STATUS).hi >> 8) & 0x1f;
40  break;
41  case 0x25: /* Arrandale BCLK fixed at 133MHz */
42  *fsb = 133;
43  *ratio = (rdmsr(MSR_PLATFORM_INFO).lo >> 8) & 0xff;
44  break;
45  case 0x2a: /* SandyBridge BCLK fixed at 100MHz */
46  case 0x3a: /* IvyBridge BCLK fixed at 100MHz */
47  case 0x3c: /* Haswell BCLK fixed at 100MHz */
48  case 0x3d: /* Broadwell-ULT BCLK fixed at 100MHz */
49  case 0x45: /* Haswell-ULT BCLK fixed at 100MHz */
50  case 0x46: /* Haswell-GT3e BCLK fixed at 100MHz */
51  case 0x47: /* Broadwell BCLK fixed at 100MHz */
52  *fsb = 100;
53  *ratio = (rdmsr(MSR_PLATFORM_INFO).lo >> 8) & 0xff;
54  break;
55  case 0x4d: /* Rangeley */
56  *fsb = rangeley_fsb[rdmsr(MSR_FSB_FREQ).lo & 3];
57  *ratio = (rdmsr(MSR_PLATFORM_INFO).lo >> 8) & 0xff;
58  break;
59  default:
60  return -2;
61  }
62  break;
63  case 0xf: /* Netburst */
65  *ratio = msr.lo >> 24;
66  switch (c.x86_model) {
67  case 0x2:
68  *fsb = f2x_fsb[(msr.lo >> 16) & 7];
69  break;
70  case 0x3:
71  case 0x4:
72  case 0x6:
73  *fsb = core2_fsb[(msr.lo >> 16) & 7];
74  break;
75  default:
76  return -2;
77  }
78  break;
79  default:
80  return -2;
81  }
82  if (*fsb > 0)
83  return 0;
84  return -1;
85 }
86 
87 static void resolve_timebase(void)
88 {
89  int ret, fsb, ratio;
90 
91  ret = get_fsb_tsc(&fsb, &ratio);
92  if (ret == 0) {
93  u32 tsc = 100 * DIV_ROUND_CLOSEST(ratio * fsb, 100);
94  timer_fsb = fsb;
95  timer_tsc = tsc;
96  return;
97  }
98 
99  if (ret == -1)
100  printk(BIOS_ERR, "FSB not found\n");
101  if (ret == -2)
102  printk(BIOS_ERR, "CPU not supported\n");
103 
104  /* Set some semi-ridiculous defaults. */
105  timer_fsb = 500;
106  timer_tsc = 5000;
107 }
108 
110 {
111  if (timer_fsb > 0)
112  return timer_fsb;
113 
115  return timer_fsb;
116 }
117 
118 unsigned long tsc_freq_mhz(void)
119 {
120  if (timer_tsc > 0)
121  return timer_tsc;
122 
124  return timer_tsc;
125 }
126 
127 /**
128  * @brief Returns three times the FSB clock in MHz
129  *
130  * The result of calculations with the returned value shall be divided by 3.
131  * This helps to avoid rounding errors.
132  */
134 {
135  const int fsb = get_timer_fsb();
136 
137  if (fsb > 0)
138  return 100 * DIV_ROUND_CLOSEST(3 * fsb, 100);
139 
140  printk(BIOS_ERR, "FSB not supported or not found\n");
141  return -1;
142 }
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
#define printk(level,...)
Definition: stdlib.h:16
static u32 timer_tsc
Definition: fsb.c:13
unsigned long tsc_freq_mhz(void)
Definition: fsb.c:118
#define MSR_PLATFORM_INFO
Definition: fsb.c:16
static u32 timer_fsb
Definition: fsb.c:12
u32 get_timer_fsb(void)
Definition: fsb.c:109
static void resolve_timebase(void)
Definition: fsb.c:87
static int get_fsb_tsc(int *fsb, int *ratio)
Definition: fsb.c:18
int get_ia32_fsb_x3(void)
Returns three times the FSB clock in MHz.
Definition: fsb.c:133
#define DIV_ROUND_CLOSEST(x, divisor)
Definition: helpers.h:17
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define IA32_PERF_STATUS
Definition: msr.h:42
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define MSR_FSB_FREQ
Definition: speedstep.h:24
#define MSR_EBC_FREQUENCY_ID
Definition: speedstep.h:23
uint32_t u32
Definition: stdint.h:51
unsigned int hi
Definition: msr.h:112
unsigned int lo
Definition: msr.h:111
#define c(value, pmcreg, dst_bits)