• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_logical_cores_per_package(void)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 
generate_T_state_entries(int core,int cores_per_package)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 
is_s0ix_enabled(const struct device * dev)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 
generate_C_state_entries(const struct device * dev)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 
calculate_power(int tdp,int p1_ratio,int ratio)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 
generate_P_state_entries(int core,int cores_per_package)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 
generate_cpu_entry(const struct device * device,int cpu,int core,int cores_per_package)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 
generate_cpu_entries(const struct device * device)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 };
369