coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
acpi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <acpi/acpi.h>
5 #include <acpi/acpigen.h>
6 #include <arch/cpu.h>
7 #include <cpu/x86/msr.h>
8 #include <cpu/intel/speedstep.h>
9 #include <cpu/intel/turbo.h>
10 #include <device/device.h>
11 #include <stdint.h>
12 
13 #include "model_206ax.h"
14 #include "chip.h"
15 
16 /*
17  * List of supported C-states in this processor
18  *
19  * Latencies are typical worst-case package exit time in uS
20  * taken from the SandyBridge BIOS specification.
21  */
22 static const acpi_cstate_t cstate_map[] = {
23  { /* 0: C0 */
24  }, { /* 1: C1 */
25  .latency = 1,
26  .power = 1000,
27  .resource = {
28  .addrl = 0x00, /* MWAIT State 0 */
29  .space_id = ACPI_ADDRESS_SPACE_FIXED,
30  .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
31  .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
32  .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
33  }
34  },
35  { /* 2: C1E */
36  .latency = 1,
37  .power = 1000,
38  .resource = {
39  .addrl = 0x01, /* MWAIT State 0 Sub-state 1 */
40  .space_id = ACPI_ADDRESS_SPACE_FIXED,
41  .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
42  .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
43  .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
44  }
45  },
46  { /* 3: C3 */
47  .latency = 63,
48  .power = 500,
49  .resource = {
50  .addrl = 0x10, /* MWAIT State 1 */
51  .space_id = ACPI_ADDRESS_SPACE_FIXED,
52  .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
53  .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
54  .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
55  }
56  },
57  { /* 4: C6 */
58  .latency = 87,
59  .power = 350,
60  .resource = {
61  .addrl = 0x20, /* MWAIT State 2 */
62  .space_id = ACPI_ADDRESS_SPACE_FIXED,
63  .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
64  .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
65  .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
66  }
67  },
68  { /* 5: C7 */
69  .latency = 90,
70  .power = 200,
71  .resource = {
72  .addrl = 0x30, /* MWAIT State 3 */
73  .space_id = ACPI_ADDRESS_SPACE_FIXED,
74  .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
75  .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
76  .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
77  }
78  },
79  { /* 6: C7S */
80  .latency = 90,
81  .power = 200,
82  .resource = {
83  .addrl = 0x31, /* MWAIT State 3 Sub-state 1 */
84  .space_id = ACPI_ADDRESS_SPACE_FIXED,
85  .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
86  .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
87  .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
88  }
89  },
90 };
91 
93 {
95  return msr.lo & 0xffff;
96 }
97 
98 static void generate_C_state_entries(void)
99 {
100  struct device *lapic;
101  struct cpu_intel_model_206ax_config *conf = NULL;
102 
103  /* Find the SpeedStep CPU in the device tree using magic APIC ID */
105  if (!lapic)
106  return;
107  conf = lapic->chip_info;
108  if (!conf)
109  return;
110 
111  const int acpi_cstates[3] = { conf->acpi_c1, conf->acpi_c2, conf->acpi_c3 };
112 
113  acpi_cstate_t acpi_cstate_map[ARRAY_SIZE(acpi_cstates)] = { 0 };
114 
115  /* Count number of active C-states */
116  int count = 0;
117 
118  for (int i = 0; i < ARRAY_SIZE(acpi_cstates); i++) {
119  if (acpi_cstates[i] > 0 && acpi_cstates[i] < ARRAY_SIZE(cstate_map)) {
120  acpi_cstate_map[count] = cstate_map[acpi_cstates[i]];
121  acpi_cstate_map[count].ctype = i + 1;
122  count++;
123  }
124  }
125  acpigen_write_CST_package(acpi_cstate_map, count);
126 }
127 
129  { 100, 1000, 0, 0x00, 0 },
130  { 94, 940, 0, 0x1f, 0 },
131  { 88, 880, 0, 0x1e, 0 },
132  { 82, 820, 0, 0x1d, 0 },
133  { 75, 760, 0, 0x1c, 0 },
134  { 69, 700, 0, 0x1b, 0 },
135  { 63, 640, 0, 0x1a, 0 },
136  { 57, 580, 0, 0x19, 0 },
137  { 50, 520, 0, 0x18, 0 },
138  { 44, 460, 0, 0x17, 0 },
139  { 38, 400, 0, 0x16, 0 },
140  { 32, 340, 0, 0x15, 0 },
141  { 25, 280, 0, 0x14, 0 },
142  { 19, 220, 0, 0x13, 0 },
143  { 13, 160, 0, 0x12, 0 },
144 };
145 
147  { 100, 1000, 0, 0x00, 0 },
148  { 88, 875, 0, 0x1f, 0 },
149  { 75, 750, 0, 0x1e, 0 },
150  { 63, 625, 0, 0x1d, 0 },
151  { 50, 500, 0, 0x1c, 0 },
152  { 38, 375, 0, 0x1b, 0 },
153  { 25, 250, 0, 0x1a, 0 },
154  { 13, 125, 0, 0x19, 0 },
155 };
156 
157 static void generate_T_state_entries(int core, int cores_per_package)
158 {
159  /* Indicate SW_ALL coordination for T-states */
160  acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
161 
162  /* Indicate FFixedHW so OS will use MSR */
164 
165  /* Set a T-state limit that can be modified in NVS */
166  acpigen_write_TPC("\\TLVL");
167 
168  /*
169  * CPUID.(EAX=6):EAX[5] indicates support
170  * for extended throttle levels.
171  */
172  if (cpuid_eax(6) & (1 << 5))
175  else
178 }
179 
180 static int calculate_power(int tdp, int p1_ratio, int ratio)
181 {
182  u32 m;
183  u32 power;
184 
185  /*
186  * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
187  *
188  * Power = (ratio / p1_ratio) * m * tdp
189  */
190 
191  m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
192  m = (m * m) / 1000;
193 
194  power = ((ratio * 100000 / p1_ratio) / 100);
195  power *= (m / 100) * (tdp / 1000);
196  power /= 1000;
197 
198  return (int)power;
199 }
200 
201 static void generate_P_state_entries(int core, int cores_per_package)
202 {
203  int ratio_min, ratio_max, ratio_turbo, ratio_step;
204  int coord_type, power_max, power_unit, num_entries;
205  int ratio, power, clock, clock_max;
206  msr_t msr;
207 
208  /* Determine P-state coordination type from MISC_PWR_MGMT[0] */
209  msr = rdmsr(MSR_MISC_PWR_MGMT);
210  if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
211  coord_type = SW_ANY;
212  else
213  coord_type = HW_ALL;
214 
215  /* Get bus ratio limits and calculate clock speeds */
216  msr = rdmsr(MSR_PLATFORM_INFO);
217  ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */
218 
219  /* Determine if this CPU has configurable TDP */
220  if (cpu_config_tdp_levels()) {
221  /* Set max ratio to nominal TDP ratio */
223  ratio_max = msr.lo & 0xff;
224  } else {
225  /* Max Non-Turbo Ratio */
226  ratio_max = (msr.lo >> 8) & 0xff;
227  }
228  clock_max = ratio_max * SANDYBRIDGE_BCLK;
229 
230  /* Calculate CPU TDP in mW */
232  power_unit = 2 << ((msr.lo & 0xf) - 1);
233  msr = rdmsr(MSR_PKG_POWER_SKU);
234  power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
235 
236  /* Write _PCT indicating use of FFixedHW */
238 
239  /* Write _PPC with no limit on supported P-state */
241 
242  /* Write PSD indicating configured coordination type */
243  acpigen_write_PSD_package(core, cores_per_package, coord_type);
244 
245  /* Add P-state entries in _PSS table */
246  acpigen_write_name("_PSS");
247 
248  /* Determine ratio points */
249  ratio_step = PSS_RATIO_STEP;
250  num_entries = (ratio_max - ratio_min) / ratio_step;
251  while (num_entries > PSS_MAX_ENTRIES-1) {
252  ratio_step <<= 1;
253  num_entries >>= 1;
254  }
255 
256  /* P[T] is Turbo state if enabled */
257  if (get_turbo_state() == TURBO_ENABLED) {
258  /* _PSS package count including Turbo */
259  acpigen_write_package(num_entries + 2);
260 
262  ratio_turbo = msr.lo & 0xff;
263 
264  /* Add entry for Turbo ratio */
266  clock_max + 1, /*MHz*/
267  power_max, /*mW*/
268  PSS_LATENCY_TRANSITION, /*lat1*/
269  PSS_LATENCY_BUSMASTER, /*lat2*/
270  ratio_turbo << 8, /*control*/
271  ratio_turbo << 8); /*status*/
272  } else {
273  /* _PSS package count without Turbo */
274  acpigen_write_package(num_entries + 1);
275  }
276 
277  /* First regular entry is max non-turbo ratio */
279  clock_max, /*MHz*/
280  power_max, /*mW*/
281  PSS_LATENCY_TRANSITION, /*lat1*/
282  PSS_LATENCY_BUSMASTER, /*lat2*/
283  ratio_max << 8, /*control*/
284  ratio_max << 8); /*status*/
285 
286  /* Generate the remaining entries */
287  for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
288  ratio >= ratio_min; ratio -= ratio_step) {
289 
290  /* Calculate power at this ratio */
291  power = calculate_power(power_max, ratio_max, ratio);
292  clock = ratio * SANDYBRIDGE_BCLK;
293 
295  clock, /*MHz*/
296  power, /*mW*/
297  PSS_LATENCY_TRANSITION, /*lat1*/
298  PSS_LATENCY_BUSMASTER, /*lat2*/
299  ratio << 8, /*control*/
300  ratio << 8); /*status*/
301  }
302 
303  /* Fix package length */
304  acpigen_pop_len();
305 }
306 
307 void generate_cpu_entries(const struct device *device)
308 {
309  int coreID, cpuID;
310  int totalcores = dev_count_cpu();
311  int cores_per_package = get_logical_cores_per_package();
312  int numcpus = totalcores/cores_per_package;
313 
314  printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each.\n",
315  numcpus, cores_per_package);
316 
317  for (cpuID = 1; cpuID <= numcpus; cpuID++) {
318  for (coreID = 1; coreID <= cores_per_package; coreID++) {
319  /* Generate processor \_SB.CPUx */
321  (cpuID-1)*cores_per_package+coreID-1, 0, 0);
322 
323  /* Generate P-state tables */
325  cpuID-1, cores_per_package);
326 
327  /* Generate C-state tables */
329 
330  /* Generate T-state tables */
332  cpuID-1, cores_per_package);
333 
334  acpigen_pop_len();
335  }
336  }
337 
338  /* PPKG is usually used for thermal management
339  of the first and only package. */
340  acpigen_write_processor_package("PPKG", 0, cores_per_package);
341 
342  /* Add a method to notify processor nodes */
343  acpigen_write_processor_cnot(cores_per_package);
344 }
345 
347  CHIP_NAME("Intel SandyBridge/IvyBridge CPU")
348 };
void acpigen_pop_len(void)
Definition: acpigen.c:37
void acpigen_write_TSS_package(int entries, acpi_tstate_t *tstate_list)
Definition: acpigen.c:1027
void acpigen_write_empty_PTC(void)
Definition: acpigen.c:704
void acpigen_write_PPC_NVS(void)
Definition: acpigen.c:899
void acpigen_write_CST_package(const acpi_cstate_t *cstate, int nentries)
Definition: acpigen.c:998
void acpigen_write_PSS_package(u32 coreFreq, u32 power, u32 transLat, u32 busmLat, u32 control, u32 status)
Definition: acpigen.c:941
void acpigen_write_TPC(const char *gnvs_tpc_limit)
Definition: acpigen.c:914
void acpigen_write_empty_PCT(void)
Definition: acpigen.c:662
void acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len)
Definition: acpigen.c:391
char * acpigen_write_package(int nr_el)
Definition: acpigen.c:86
void acpigen_write_processor_package(const char *const name, const unsigned int first_core, const unsigned int core_count)
Definition: acpigen.c:409
void acpigen_write_processor_cnot(const unsigned int number_of_cores)
Definition: acpigen.c:425
void acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
Definition: acpigen.c:974
void acpigen_write_TSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
Definition: acpigen.c:1057
void acpigen_write_name(const char *name)
Definition: acpigen.c:320
static unsigned int cpuid_eax(unsigned int op)
Definition: cpu.h:79
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
void generate_cpu_entries(const struct device *device)
Definition: acpi.c:334
#define SPEEDSTEP_APIC_MAGIC
Definition: chip.h:4
#define MSR_MISC_PWR_MGMT
Definition: haswell.h:51
#define PSS_LATENCY_BUSMASTER
Definition: haswell.h:127
#define MSR_PKG_POWER_SKU
Definition: haswell.h:89
#define MSR_TURBO_RATIO_LIMIT
Definition: haswell.h:53
#define PSS_RATIO_STEP
Definition: haswell.h:125
#define PSS_MAX_ENTRIES
Definition: haswell.h:124
#define MSR_CORE_THREAD_COUNT
Definition: haswell.h:37
#define MSR_PKG_POWER_SKU_UNIT
Definition: haswell.h:88
#define PSS_LATENCY_TRANSITION
Definition: haswell.h:126
int cpu_config_tdp_levels(void)
Definition: haswell_init.c:300
#define MSR_CONFIG_TDP_NOMINAL
Definition: haswell.h:95
#define MISC_PWR_MGMT_EIST_HW_DIS
Definition: haswell.h:52
struct chip_operations cpu_intel_model_206ax_ops
Definition: acpi.c:346
static int calculate_power(int tdp, int p1_ratio, int ratio)
Definition: acpi.c:180
static acpi_tstate_t tss_table_fine[]
Definition: acpi.c:128
static const acpi_cstate_t cstate_map[]
Definition: acpi.c:22
static void generate_C_state_entries(void)
Definition: acpi.c:98
static void generate_T_state_entries(int core, int cores_per_package)
Definition: acpi.c:157
static void generate_P_state_entries(int core, int cores_per_package)
Definition: acpi.c:201
static acpi_tstate_t tss_table_coarse[]
Definition: acpi.c:146
static int get_logical_cores_per_package(void)
Definition: acpi.c:92
struct device * dev_find_lapic(unsigned int apic_id)
Given a Local APIC ID, find the device structure.
Definition: device_util.c:17
int dev_count_cpu(void)
Definition: device_util.c:907
#define MSR_PLATFORM_INFO
Definition: fsb.c:16
#define ACPI_FFIXEDHW_FLAG_HW_COORD
Definition: acpi.h:120
#define ACPI_FFIXEDHW_VENDOR_INTEL
Definition: acpi.h:116
#define ACPI_FFIXEDHW_CLASS_MWAIT
Definition: acpi.h:119
#define ACPI_ADDRESS_SPACE_FIXED
Definition: acpi.h:115
@ HW_ALL
Definition: acpigen.h:375
@ SW_ALL
Definition: acpigen.h:375
@ SW_ANY
Definition: acpigen.h:375
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define CHIP_NAME(X)
Definition: device.h:32
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define SANDYBRIDGE_BCLK
Definition: model_206ax.h:38
static const struct pnpconfig power[]
Definition: pnpconfig.c:14
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
u8 ctype
Definition: acpi.h:984
u16 latency
Definition: acpi.h:985
Definition: device.h:107
DEVTREE_CONST void * chip_info
Definition: device.h:164
unsigned int hi
Definition: msr.h:112
unsigned int lo
Definition: msr.h:111
#define m(clkreg, src_bits, pmcreg, dst_bits)
int get_turbo_state(void)
Definition: turbo.c:75
@ TURBO_ENABLED
Definition: turbo.h:18
#define count