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