/ src / cpu / intel / haswell / acpi.c
acpi.c
  1  /* SPDX-License-Identifier: GPL-2.0-only */
  2  
  3  #include <acpi/acpi.h>
  4  #include <acpi/acpigen.h>
  5  #include <console/console.h>
  6  #include <cpu/cpu.h>
  7  #include <cpu/intel/speedstep.h>
  8  #include <cpu/intel/turbo.h>
  9  #include <cpu/x86/msr.h>
 10  #include <device/device.h>
 11  #include <types.h>
 12  
 13  #include "haswell.h"
 14  #include "chip.h"
 15  
 16  #include <southbridge/intel/lynxpoint/pch.h>
 17  
 18  #define MWAIT_RES(state, sub_state)                         \
 19  	{                                                   \
 20  		.addrl = (((state) << 4) | (sub_state)),    \
 21  		.space_id = ACPI_ADDRESS_SPACE_FIXED,       \
 22  		.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,    \
 23  		.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,    \
 24  		.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
 25  	}
 26  
 27  static acpi_cstate_t cstate_map[NUM_C_STATES] = {
 28  	[C_STATE_C0] = { },
 29  	[C_STATE_C1] = {
 30  		.latency = 0,
 31  		.power = 1000,
 32  		.resource = MWAIT_RES(0, 0),
 33  	},
 34  	[C_STATE_C1E] = {
 35  		.latency = 0,
 36  		.power = 1000,
 37  		.resource = MWAIT_RES(0, 1),
 38  	},
 39  	[C_STATE_C3] = {
 40  		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
 41  		.power = 900,
 42  		.resource = MWAIT_RES(1, 0),
 43  	},
 44  	[C_STATE_C6_SHORT_LAT] = {
 45  		.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
 46  		.power = 800,
 47  		.resource = MWAIT_RES(2, 0),
 48  	},
 49  	[C_STATE_C6_LONG_LAT] = {
 50  		.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
 51  		.power = 800,
 52  		.resource = MWAIT_RES(2, 1),
 53  	},
 54  	[C_STATE_C7_SHORT_LAT] = {
 55  		.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
 56  		.power = 700,
 57  		.resource = MWAIT_RES(3, 0),
 58  	},
 59  	[C_STATE_C7_LONG_LAT] = {
 60  		.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
 61  		.power = 700,
 62  		.resource = MWAIT_RES(3, 1),
 63  	},
 64  	[C_STATE_C7S_SHORT_LAT] = {
 65  		.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
 66  		.power = 700,
 67  		.resource = MWAIT_RES(3, 2),
 68  	},
 69  	[C_STATE_C7S_LONG_LAT] = {
 70  		.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
 71  		.power = 700,
 72  		.resource = MWAIT_RES(3, 3),
 73  	},
 74  	[C_STATE_C8] = {
 75  		.latency = C_STATE_LATENCY_FROM_LAT_REG(3),
 76  		.power = 600,
 77  		.resource = MWAIT_RES(4, 0),
 78  	},
 79  	[C_STATE_C9] = {
 80  		.latency = C_STATE_LATENCY_FROM_LAT_REG(4),
 81  		.power = 500,
 82  		.resource = MWAIT_RES(5, 0),
 83  	},
 84  	[C_STATE_C10] = {
 85  		.latency = C_STATE_LATENCY_FROM_LAT_REG(5),
 86  		.power = 400,
 87  		.resource = MWAIT_RES(6, 0),
 88  	},
 89  };
 90  
 91  static const int cstate_set_s0ix[3] = {
 92  	C_STATE_C1E,
 93  	C_STATE_C7S_LONG_LAT,
 94  	C_STATE_C10,
 95  };
 96  
 97  static const int cstate_set_lp[3] = {
 98  	C_STATE_C1E,
 99  	C_STATE_C3,
100  	C_STATE_C7S_LONG_LAT,
101  };
102  
103  static const int cstate_set_trad[3] = {
104  	C_STATE_C1,
105  	C_STATE_C3,
106  	C_STATE_C6_LONG_LAT,
107  };
108  
109  static int get_logical_cores_per_package(void)
110  {
111  	msr_t msr = rdmsr(MSR_CORE_THREAD_COUNT);
112  	return msr.lo & 0xffff;
113  }
114  
115  static acpi_tstate_t tss_table_fine[] = {
116  	{ 100, 1000, 0, 0x00, 0 },
117  	{ 94, 940, 0, 0x1f, 0 },
118  	{ 88, 880, 0, 0x1e, 0 },
119  	{ 82, 820, 0, 0x1d, 0 },
120  	{ 75, 760, 0, 0x1c, 0 },
121  	{ 69, 700, 0, 0x1b, 0 },
122  	{ 63, 640, 0, 0x1a, 0 },
123  	{ 57, 580, 0, 0x19, 0 },
124  	{ 50, 520, 0, 0x18, 0 },
125  	{ 44, 460, 0, 0x17, 0 },
126  	{ 38, 400, 0, 0x16, 0 },
127  	{ 32, 340, 0, 0x15, 0 },
128  	{ 25, 280, 0, 0x14, 0 },
129  	{ 19, 220, 0, 0x13, 0 },
130  	{ 13, 160, 0, 0x12, 0 },
131  };
132  
133  static acpi_tstate_t tss_table_coarse[] = {
134  	{ 100, 1000, 0, 0x00, 0 },
135  	{ 88, 875, 0, 0x1f, 0 },
136  	{ 75, 750, 0, 0x1e, 0 },
137  	{ 63, 625, 0, 0x1d, 0 },
138  	{ 50, 500, 0, 0x1c, 0 },
139  	{ 38, 375, 0, 0x1b, 0 },
140  	{ 25, 250, 0, 0x1a, 0 },
141  	{ 13, 125, 0, 0x19, 0 },
142  };
143  
144  static void generate_T_state_entries(int core, int cores_per_package)
145  {
146  	/* Indicate SW_ALL coordination for T-states */
147  	acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
148  
149  	/* Indicate FFixedHW so OS will use MSR */
150  	acpigen_write_empty_PTC();
151  
152  	/* Set a T-state limit that can be modified in NVS */
153  	acpigen_write_TPC("\\TLVL");
154  
155  	/*
156  	 * CPUID.(EAX=6):EAX[5] indicates support
157  	 * for extended throttle levels.
158  	 */
159  	if (cpuid_eax(6) & (1 << 5))
160  		acpigen_write_TSS_package(
161  			ARRAY_SIZE(tss_table_fine), tss_table_fine);
162  	else
163  		acpigen_write_TSS_package(
164  			ARRAY_SIZE(tss_table_coarse), tss_table_coarse);
165  }
166  
167  static bool is_s0ix_enabled(const struct device *dev)
168  {
169  	if (!haswell_is_ult())
170  		return false;
171  
172  	const struct cpu_intel_haswell_config *conf = dev->chip_info;
173  	return conf->s0ix_enable;
174  }
175  
176  static void generate_C_state_entries(const struct device *dev)
177  {
178  	acpi_cstate_t acpi_cstate_map[3] = {0};
179  
180  	const int *acpi_cstates;
181  
182  	if (is_s0ix_enabled(dev))
183  		acpi_cstates = cstate_set_s0ix;
184  	else if (haswell_is_ult())
185  		acpi_cstates = cstate_set_lp;
186  	else
187  		acpi_cstates = cstate_set_trad;
188  
189  	/* Count number of active C-states */
190  	int count = 0;
191  
192  	for (int i = 0; i < ARRAY_SIZE(acpi_cstate_map); i++) {
193  		if (acpi_cstates[i] > 0 && acpi_cstates[i] < ARRAY_SIZE(cstate_map)) {
194  			acpi_cstate_map[count] = cstate_map[acpi_cstates[i]];
195  			acpi_cstate_map[count].ctype = i + 1;
196  			count++;
197  		}
198  	}
199  	acpigen_write_CST_package(acpi_cstate_map, count);
200  }
201  
202  static int calculate_power(int tdp, int p1_ratio, int ratio)
203  {
204  	u32 m;
205  	u32 power;
206  
207  	/*
208  	 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
209  	 *
210  	 * Power = (ratio / p1_ratio) * m * tdp
211  	 */
212  
213  	m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
214  	m = (m * m) / 1000;
215  
216  	power = ((ratio * 100000 / p1_ratio) / 100);
217  	power *= (m / 100) * (tdp / 1000);
218  	power /= 1000;
219  
220  	return (int)power;
221  }
222  
223  static void generate_P_state_entries(int core, int cores_per_package)
224  {
225  	int ratio_min, ratio_max, ratio_turbo, ratio_step;
226  	int coord_type, power_max, power_unit, num_entries;
227  	int ratio, power, clock, clock_max;
228  	msr_t msr;
229  
230  	/* Determine P-state coordination type from MISC_PWR_MGMT[0] */
231  	msr = rdmsr(MSR_MISC_PWR_MGMT);
232  	if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
233  		coord_type = SW_ANY;
234  	else
235  		coord_type = HW_ALL;
236  
237  	/* Get bus ratio limits and calculate clock speeds */
238  	msr = rdmsr(MSR_PLATFORM_INFO);
239  	ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */
240  
241  	/* Determine if this CPU has configurable TDP */
242  	if (cpu_config_tdp_levels()) {
243  		/* Set max ratio to nominal TDP ratio */
244  		msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
245  		ratio_max = msr.lo & 0xff;
246  	} else {
247  		/* Max Non-Turbo Ratio */
248  		ratio_max = (msr.lo >> 8) & 0xff;
249  	}
250  	clock_max = ratio_max * CPU_BCLK;
251  
252  	/* Calculate CPU TDP in mW */
253  	msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
254  	power_unit = 2 << ((msr.lo & 0xf) - 1);
255  	msr = rdmsr(MSR_PKG_POWER_SKU);
256  	power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
257  
258  	/* Write _PCT indicating use of FFixedHW */
259  	acpigen_write_empty_PCT();
260  
261  	/* Write _PPC with no limit on supported P-state */
262  	acpigen_write_PPC_NVS();
263  
264  	/* Write PSD indicating configured coordination type */
265  	acpigen_write_PSD_package(core, 1, coord_type);
266  
267  	/* Add P-state entries in _PSS table */
268  	acpigen_write_name("_PSS");
269  
270  	/* Determine ratio points */
271  	ratio_step = PSS_RATIO_STEP;
272  	num_entries = (ratio_max - ratio_min) / ratio_step;
273  	while (num_entries > PSS_MAX_ENTRIES-1) {
274  		ratio_step <<= 1;
275  		num_entries >>= 1;
276  	}
277  
278  	/* P[T] is Turbo state if enabled */
279  	if (get_turbo_state() == TURBO_ENABLED) {
280  		/* _PSS package count including Turbo */
281  		acpigen_write_package(num_entries + 2);
282  
283  		msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
284  		ratio_turbo = msr.lo & 0xff;
285  
286  		/* Add entry for Turbo ratio */
287  		acpigen_write_PSS_package(
288  			clock_max + 1,		/*MHz*/
289  			power_max,		/*mW*/
290  			PSS_LATENCY_TRANSITION,	/*lat1*/
291  			PSS_LATENCY_BUSMASTER,	/*lat2*/
292  			ratio_turbo << 8,	/*control*/
293  			ratio_turbo << 8);	/*status*/
294  	} else {
295  		/* _PSS package count without Turbo */
296  		acpigen_write_package(num_entries + 1);
297  	}
298  
299  	/* First regular entry is max non-turbo ratio */
300  	acpigen_write_PSS_package(
301  		clock_max,		/*MHz*/
302  		power_max,		/*mW*/
303  		PSS_LATENCY_TRANSITION,	/*lat1*/
304  		PSS_LATENCY_BUSMASTER,	/*lat2*/
305  		ratio_max << 8,		/*control*/
306  		ratio_max << 8);	/*status*/
307  
308  	/* Generate the remaining entries */
309  	for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
310  	     ratio >= ratio_min; ratio -= ratio_step) {
311  		/* Calculate power at this ratio */
312  		power = calculate_power(power_max, ratio_max, ratio);
313  		clock = ratio * CPU_BCLK;
314  
315  		acpigen_write_PSS_package(
316  			clock,			/*MHz*/
317  			power,			/*mW*/
318  			PSS_LATENCY_TRANSITION,	/*lat1*/
319  			PSS_LATENCY_BUSMASTER,	/*lat2*/
320  			ratio << 8,		/*control*/
321  			ratio << 8);		/*status*/
322  	}
323  
324  	/* Fix package length */
325  	acpigen_pop_len();
326  }
327  
328  static void generate_cpu_entry(const struct device *device, int cpu, int core, int cores_per_package)
329  {
330  	/* Generate Scope(\_SB) { Device(CPUx */
331  	acpigen_write_processor_device(cpu * cores_per_package + core);
332  
333  	/* Generate P-state tables */
334  	generate_P_state_entries(core, cores_per_package);
335  
336  	/* Generate C-state tables */
337  	generate_C_state_entries(device);
338  
339  	/* Generate T-state tables */
340  	generate_T_state_entries(cpu, cores_per_package);
341  
342  	acpigen_write_processor_device_end();
343  }
344  
345  void generate_cpu_entries(const struct device *device)
346  {
347  	int totalcores = dev_count_cpu();
348  	int cores_per_package = get_logical_cores_per_package();
349  	int numcpus = totalcores / cores_per_package;
350  
351  	printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each.\n",
352  	       numcpus, cores_per_package);
353  
354  	for (int cpu_id = 0; cpu_id < numcpus; cpu_id++)
355  		for (int core_id = 0; core_id < cores_per_package; core_id++)
356  			generate_cpu_entry(device, cpu_id, core_id, cores_per_package);
357  
358  	/* PPKG is usually used for thermal management
359  	   of the first and only package. */
360  	acpigen_write_processor_package("PPKG", 0, cores_per_package);
361  
362  	/* Add a method to notify processor nodes */
363  	acpigen_write_processor_cnot(cores_per_package);
364  }
365  
366  struct chip_operations cpu_intel_haswell_ops = {
367  	.name = "Intel Haswell CPU",
368  };