1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Speed Select -- Enumerate and control features
4  * Copyright (c) 2019 Intel Corporation.
5  */
6 
7 #include "isst.h"
8 
9 int isst_write_pm_config(int cpu, int cp_state)
10 {
11 	unsigned int req, resp;
12 	int ret;
13 
14 	if (cp_state)
15 		req = BIT(16);
16 	else
17 		req = 0;
18 
19 	ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
20 				     &resp);
21 	if (ret)
22 		return ret;
23 
24 	debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", cpu, resp);
25 
26 	return 0;
27 }
28 
29 int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
30 {
31 	unsigned int resp;
32 	int ret;
33 
34 	ret = isst_send_mbox_command(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
35 				     &resp);
36 	if (ret)
37 		return ret;
38 
39 	debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", cpu, resp);
40 
41 	*cp_state = resp & BIT(16);
42 	*cp_cap = resp & BIT(0) ? 1 : 0;
43 
44 	return 0;
45 }
46 
47 int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
48 {
49 	unsigned int resp;
50 	int ret;
51 
52 	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
53 				     CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
54 	if (ret) {
55 		pkg_dev->levels = 0;
56 		pkg_dev->locked = 1;
57 		pkg_dev->current_level = 0;
58 		pkg_dev->version = 0;
59 		pkg_dev->enabled = 0;
60 		return 0;
61 	}
62 
63 	debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
64 
65 	pkg_dev->version = resp & 0xff;
66 	pkg_dev->levels = (resp >> 8) & 0xff;
67 	pkg_dev->current_level = (resp >> 16) & 0xff;
68 	pkg_dev->locked = !!(resp & BIT(24));
69 	pkg_dev->enabled = !!(resp & BIT(31));
70 
71 	return 0;
72 }
73 
74 int isst_get_ctdp_control(int cpu, int config_index,
75 			  struct isst_pkg_ctdp_level_info *ctdp_level)
76 {
77 	int cp_state, cp_cap;
78 	unsigned int resp;
79 	int ret;
80 
81 	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
82 				     CONFIG_TDP_GET_TDP_CONTROL, 0,
83 				     config_index, &resp);
84 	if (ret)
85 		return ret;
86 
87 	ctdp_level->fact_support = resp & BIT(0);
88 	ctdp_level->pbf_support = !!(resp & BIT(1));
89 	ctdp_level->fact_enabled = !!(resp & BIT(16));
90 	ctdp_level->pbf_enabled = !!(resp & BIT(17));
91 
92 	ret = isst_read_pm_config(cpu, &cp_state, &cp_cap);
93 	if (ret) {
94 		debug_printf("cpu:%d pm_config is not supported \n", cpu);
95 	} else {
96 		debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d \n", cpu, cp_state, cp_cap);
97 		ctdp_level->sst_cp_support = cp_cap;
98 		ctdp_level->sst_cp_enabled = cp_state;
99 	}
100 
101 	debug_printf(
102 		"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
103 		cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
104 		ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
105 
106 	return 0;
107 }
108 
109 int isst_get_tdp_info(int cpu, int config_index,
110 		      struct isst_pkg_ctdp_level_info *ctdp_level)
111 {
112 	unsigned int resp;
113 	int ret;
114 
115 	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
116 				     0, config_index, &resp);
117 	if (ret) {
118 		isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
119 		return ret;
120 	}
121 
122 	ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
123 	ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
124 
125 	debug_printf(
126 		"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
127 		cpu, config_index, resp, ctdp_level->tdp_ratio,
128 		ctdp_level->pkg_tdp);
129 	return 0;
130 }
131 
132 int isst_get_pwr_info(int cpu, int config_index,
133 		      struct isst_pkg_ctdp_level_info *ctdp_level)
134 {
135 	unsigned int resp;
136 	int ret;
137 
138 	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
139 				     0, config_index, &resp);
140 	if (ret)
141 		return ret;
142 
143 	ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
144 	ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
145 
146 	debug_printf(
147 		"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
148 		cpu, config_index, resp, ctdp_level->pkg_max_power,
149 		ctdp_level->pkg_min_power);
150 
151 	return 0;
152 }
153 
154 void isst_get_uncore_p0_p1_info(int cpu, int config_index,
155 				struct isst_pkg_ctdp_level_info *ctdp_level)
156 {
157 	unsigned int resp;
158 	int ret;
159 	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
160 				     CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
161 				     config_index, &resp);
162 	if (ret) {
163 		ctdp_level->uncore_p0 = 0;
164 		ctdp_level->uncore_p1 = 0;
165 		return;
166 	}
167 
168 	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
169 	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
170 	debug_printf(
171 		"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
172 		cpu, config_index, resp, ctdp_level->uncore_p0,
173 		ctdp_level->uncore_p1);
174 }
175 
176 void isst_get_p1_info(int cpu, int config_index,
177 		      struct isst_pkg_ctdp_level_info *ctdp_level)
178 {
179 	unsigned int resp;
180 	int ret;
181 	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
182 				     config_index, &resp);
183 	if (ret) {
184 		ctdp_level->sse_p1 = 0;
185 		ctdp_level->avx2_p1 = 0;
186 		ctdp_level->avx512_p1 = 0;
187 		return;
188 	}
189 
190 	ctdp_level->sse_p1 = resp & GENMASK(7, 0);
191 	ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
192 	ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
193 	debug_printf(
194 		"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
195 		cpu, config_index, resp, ctdp_level->sse_p1,
196 		ctdp_level->avx2_p1, ctdp_level->avx512_p1);
197 }
198 
199 void isst_get_uncore_mem_freq(int cpu, int config_index,
200 			      struct isst_pkg_ctdp_level_info *ctdp_level)
201 {
202 	unsigned int resp;
203 	int ret;
204 	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
205 				     0, config_index, &resp);
206 	if (ret) {
207 		ctdp_level->mem_freq = 0;
208 		return;
209 	}
210 
211 	ctdp_level->mem_freq = resp & GENMASK(7, 0);
212 	debug_printf(
213 		"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
214 		cpu, config_index, resp, ctdp_level->mem_freq);
215 }
216 
217 int isst_get_tjmax_info(int cpu, int config_index,
218 			struct isst_pkg_ctdp_level_info *ctdp_level)
219 {
220 	unsigned int resp;
221 	int ret;
222 
223 	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
224 				     0, config_index, &resp);
225 	if (ret)
226 		return ret;
227 
228 	ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
229 
230 	debug_printf(
231 		"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
232 		cpu, config_index, resp, ctdp_level->t_proc_hot);
233 
234 	return 0;
235 }
236 
237 int isst_get_coremask_info(int cpu, int config_index,
238 			   struct isst_pkg_ctdp_level_info *ctdp_level)
239 {
240 	unsigned int resp;
241 	int i, ret;
242 
243 	ctdp_level->cpu_count = 0;
244 	for (i = 0; i < 2; ++i) {
245 		unsigned long long mask;
246 		int cpu_count = 0;
247 
248 		ret = isst_send_mbox_command(cpu, CONFIG_TDP,
249 					     CONFIG_TDP_GET_CORE_MASK, 0,
250 					     (i << 8) | config_index, &resp);
251 		if (ret)
252 			return ret;
253 
254 		debug_printf(
255 			"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
256 			cpu, config_index, i, resp);
257 
258 		mask = (unsigned long long)resp << (32 * i);
259 		set_cpu_mask_from_punit_coremask(cpu, mask,
260 						 ctdp_level->core_cpumask_size,
261 						 ctdp_level->core_cpumask,
262 						 &cpu_count);
263 		ctdp_level->cpu_count += cpu_count;
264 		debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", cpu,
265 			     config_index, i, ctdp_level->cpu_count);
266 	}
267 
268 	return 0;
269 }
270 
271 int isst_get_get_trl_from_msr(int cpu, int *trl)
272 {
273 	unsigned long long msr_trl;
274 	int ret;
275 
276 	ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl);
277 	if (ret)
278 		return ret;
279 
280 	trl[0] = msr_trl & GENMASK(7, 0);
281 	trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
282 	trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
283 	trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
284 	trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
285 	trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
286 	trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
287 	trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
288 
289 	return 0;
290 }
291 
292 int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
293 {
294 	unsigned int req, resp;
295 	int ret;
296 
297 	req = level | (avx_level << 16);
298 	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
299 				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
300 				     &resp);
301 	if (ret)
302 		return ret;
303 
304 	debug_printf(
305 		"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
306 		cpu, req, resp);
307 
308 	trl[0] = resp & GENMASK(7, 0);
309 	trl[1] = (resp & GENMASK(15, 8)) >> 8;
310 	trl[2] = (resp & GENMASK(23, 16)) >> 16;
311 	trl[3] = (resp & GENMASK(31, 24)) >> 24;
312 
313 	req = level | BIT(8) | (avx_level << 16);
314 	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
315 				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
316 				     &resp);
317 	if (ret)
318 		return ret;
319 
320 	debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", cpu,
321 		     req, resp);
322 
323 	trl[4] = resp & GENMASK(7, 0);
324 	trl[5] = (resp & GENMASK(15, 8)) >> 8;
325 	trl[6] = (resp & GENMASK(23, 16)) >> 16;
326 	trl[7] = (resp & GENMASK(31, 24)) >> 24;
327 
328 	return 0;
329 }
330 
331 int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info)
332 {
333 	int ret;
334 
335 	debug_printf("cpu:%d bucket info via MSR\n", cpu);
336 
337 	*buckets_info = 0;
338 
339 	ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info);
340 	if (ret)
341 		return ret;
342 
343 	debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu,
344 		     *buckets_info);
345 
346 	return 0;
347 }
348 
349 int isst_set_tdp_level_msr(int cpu, int tdp_level)
350 {
351 	unsigned long long level = tdp_level;
352 	int ret;
353 
354 	debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
355 
356 	if (isst_get_config_tdp_lock_status(cpu)) {
357 		isst_display_error_info_message(1, "tdp_locked", 0, 0);
358 		return -1;
359 	}
360 
361 	if (tdp_level > 2)
362 		return -1; /* invalid value */
363 
364 	ret = isst_send_msr_command(cpu, 0x64b, 1, &level);
365 	if (ret)
366 		return ret;
367 
368 	debug_printf("cpu: tdp_level via MSR successful %d\n", cpu, tdp_level);
369 
370 	return 0;
371 }
372 
373 int isst_set_tdp_level(int cpu, int tdp_level)
374 {
375 	unsigned int resp;
376 	int ret;
377 
378 
379 	if (isst_get_config_tdp_lock_status(cpu)) {
380 		isst_display_error_info_message(1, "TDP is locked", 0, 0);
381 		return -1;
382 
383 	}
384 
385 	ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
386 				     tdp_level, &resp);
387 	if (ret) {
388 		isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
389 		return ret;
390 	}
391 
392 	return 0;
393 }
394 
395 int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
396 {
397 	struct isst_pkg_ctdp_level_info ctdp_level;
398 	struct isst_pkg_ctdp pkg_dev;
399 	int i, ret, max_punit_core, max_mask_index;
400 	unsigned int req, resp;
401 
402 	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
403 	if (ret) {
404 		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
405 		return ret;
406 	}
407 
408 	if (level > pkg_dev.levels) {
409 		isst_display_error_info_message(1, "Invalid level", 1, level);
410 		return -1;
411 	}
412 
413 	ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
414 	if (ret)
415 		return ret;
416 
417 	if (!ctdp_level.pbf_support) {
418 		isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level);
419 		return -1;
420 	}
421 
422 	pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
423 
424 	max_punit_core = get_max_punit_core_id(get_physical_package_id(cpu), get_physical_die_id(cpu));
425 	max_mask_index = max_punit_core > 32 ? 2 : 1;
426 
427 	for (i = 0; i < max_mask_index; ++i) {
428 		unsigned long long mask;
429 		int count;
430 
431 		ret = isst_send_mbox_command(cpu, CONFIG_TDP,
432 					     CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
433 					     0, (i << 8) | level, &resp);
434 		if (ret)
435 			break;
436 
437 		debug_printf(
438 			"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
439 			cpu, resp);
440 
441 		mask = (unsigned long long)resp << (32 * i);
442 		set_cpu_mask_from_punit_coremask(cpu, mask,
443 						 pbf_info->core_cpumask_size,
444 						 pbf_info->core_cpumask,
445 						 &count);
446 	}
447 
448 	req = level;
449 	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
450 				     CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
451 				     &resp);
452 	if (ret)
453 		return ret;
454 
455 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", cpu,
456 		     resp);
457 
458 	pbf_info->p1_low = resp & 0xff;
459 	pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
460 
461 	req = level;
462 	ret = isst_send_mbox_command(
463 		cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
464 	if (ret)
465 		return ret;
466 
467 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", cpu, resp);
468 
469 	pbf_info->tdp = resp & 0xffff;
470 
471 	req = level;
472 	ret = isst_send_mbox_command(
473 		cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
474 	if (ret)
475 		return ret;
476 
477 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", cpu,
478 		     resp);
479 	pbf_info->t_control = (resp >> 8) & 0xff;
480 	pbf_info->t_prochot = resp & 0xff;
481 
482 	return 0;
483 }
484 
485 void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info)
486 {
487 	free_cpu_set(pbf_info->core_cpumask);
488 }
489 
490 int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
491 {
492 	struct isst_pkg_ctdp pkg_dev;
493 	struct isst_pkg_ctdp_level_info ctdp_level;
494 	int current_level;
495 	unsigned int req = 0, resp;
496 	int ret;
497 
498 	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
499 	if (ret)
500 		debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
501 
502 	current_level = pkg_dev.current_level;
503 
504 	ret = isst_get_ctdp_control(cpu, current_level, &ctdp_level);
505 	if (ret)
506 		return ret;
507 
508 	if (pbf) {
509 		if (ctdp_level.fact_enabled)
510 			req = BIT(16);
511 
512 		if (enable)
513 			req |= BIT(17);
514 		else
515 			req &= ~BIT(17);
516 	} else {
517 
518 		if (enable && !ctdp_level.sst_cp_enabled)
519 			isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
520 
521 		if (ctdp_level.pbf_enabled)
522 			req = BIT(17);
523 
524 		if (enable)
525 			req |= BIT(16);
526 		else
527 			req &= ~BIT(16);
528 	}
529 
530 	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
531 				     CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
532 	if (ret)
533 		return ret;
534 
535 	debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
536 		     cpu, pbf, req);
537 
538 	return 0;
539 }
540 
541 int isst_get_fact_bucket_info(int cpu, int level,
542 			      struct isst_fact_bucket_info *bucket_info)
543 {
544 	unsigned int resp;
545 	int i, k, ret;
546 
547 	for (i = 0; i < 2; ++i) {
548 		int j;
549 
550 		ret = isst_send_mbox_command(
551 			cpu, CONFIG_TDP,
552 			CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
553 			(i << 8) | level, &resp);
554 		if (ret)
555 			return ret;
556 
557 		debug_printf(
558 			"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
559 			cpu, i, level, resp);
560 
561 		for (j = 0; j < 4; ++j) {
562 			bucket_info[j + (i * 4)].high_priority_cores_count =
563 				(resp >> (j * 8)) & 0xff;
564 		}
565 	}
566 
567 	for (k = 0; k < 3; ++k) {
568 		for (i = 0; i < 2; ++i) {
569 			int j;
570 
571 			ret = isst_send_mbox_command(
572 				cpu, CONFIG_TDP,
573 				CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
574 				(k << 16) | (i << 8) | level, &resp);
575 			if (ret)
576 				return ret;
577 
578 			debug_printf(
579 				"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
580 				cpu, i, level, k, resp);
581 
582 			for (j = 0; j < 4; ++j) {
583 				switch (k) {
584 				case 0:
585 					bucket_info[j + (i * 4)].sse_trl =
586 						(resp >> (j * 8)) & 0xff;
587 					break;
588 				case 1:
589 					bucket_info[j + (i * 4)].avx_trl =
590 						(resp >> (j * 8)) & 0xff;
591 					break;
592 				case 2:
593 					bucket_info[j + (i * 4)].avx512_trl =
594 						(resp >> (j * 8)) & 0xff;
595 					break;
596 				default:
597 					break;
598 				}
599 			}
600 		}
601 	}
602 
603 	return 0;
604 }
605 
606 int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_info *fact_info)
607 {
608 	struct isst_pkg_ctdp_level_info ctdp_level;
609 	struct isst_pkg_ctdp pkg_dev;
610 	unsigned int resp;
611 	int j, ret, print;
612 
613 	ret = isst_get_ctdp_levels(cpu, &pkg_dev);
614 	if (ret) {
615 		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
616 		return ret;
617 	}
618 
619 	if (level > pkg_dev.levels) {
620 		isst_display_error_info_message(1, "Invalid level", 1, level);
621 		return -1;
622 	}
623 
624 	ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
625 	if (ret)
626 		return ret;
627 
628 	if (!ctdp_level.fact_support) {
629 		isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
630 		return -1;
631 	}
632 
633 	ret = isst_send_mbox_command(cpu, CONFIG_TDP,
634 				     CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
635 				     level, &resp);
636 	if (ret)
637 		return ret;
638 
639 	debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
640 		     cpu, resp);
641 
642 	fact_info->lp_clipping_ratio_license_sse = resp & 0xff;
643 	fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff;
644 	fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
645 
646 	ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info);
647 	if (ret)
648 		return ret;
649 
650 	print = 0;
651 	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
652 		if (fact_bucket != 0xff && fact_bucket != j)
653 			continue;
654 
655 		if (!fact_info->bucket_info[j].high_priority_cores_count)
656 			break;
657 
658 		print = 1;
659 	}
660 	if (!print) {
661 		isst_display_error_info_message(1, "Invalid bucket", 0, 0);
662 		return -1;
663 	}
664 
665 	return 0;
666 }
667 
668 int isst_set_trl(int cpu, unsigned long long trl)
669 {
670 	int ret;
671 
672 	if (!trl)
673 		trl = 0xFFFFFFFFFFFFFFFFULL;
674 
675 	ret = isst_send_msr_command(cpu, 0x1AD, 1, &trl);
676 	if (ret)
677 		return ret;
678 
679 	return 0;
680 }
681 
682 int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
683 {
684 	unsigned long long msr_trl;
685 	int ret;
686 
687 	if (trl) {
688 		msr_trl = trl;
689 	} else {
690 		struct isst_pkg_ctdp pkg_dev;
691 		int trl[8];
692 		int i;
693 
694 		ret = isst_get_ctdp_levels(cpu, &pkg_dev);
695 		if (ret)
696 			return ret;
697 
698 		ret = isst_get_get_trl(cpu, pkg_dev.current_level, 0, trl);
699 		if (ret)
700 			return ret;
701 
702 		msr_trl = 0;
703 		for (i = 0; i < 8; ++i) {
704 			unsigned long long _trl = trl[i];
705 
706 			msr_trl |= (_trl << (i * 8));
707 		}
708 	}
709 	ret = isst_send_msr_command(cpu, 0x1AD, 1, &msr_trl);
710 	if (ret)
711 		return ret;
712 
713 	return 0;
714 }
715 
716 /* Return 1 if locked */
717 int isst_get_config_tdp_lock_status(int cpu)
718 {
719 	unsigned long long tdp_control = 0;
720 	int ret;
721 
722 	ret = isst_send_msr_command(cpu, 0x64b, 0, &tdp_control);
723 	if (ret)
724 		return ret;
725 
726 	ret = !!(tdp_control & BIT(31));
727 
728 	return ret;
729 }
730 
731 void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev)
732 {
733 	int i;
734 
735 	if (!pkg_dev->processed)
736 		return;
737 
738 	for (i = 0; i < pkg_dev->levels; ++i) {
739 		struct isst_pkg_ctdp_level_info *ctdp_level;
740 
741 		ctdp_level = &pkg_dev->ctdp_level[i];
742 		if (ctdp_level->pbf_support)
743 			free_cpu_set(ctdp_level->pbf_info.core_cpumask);
744 		free_cpu_set(ctdp_level->core_cpumask);
745 	}
746 }
747 
748 int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
749 {
750 	int i, ret, valid = 0;
751 
752 	if (pkg_dev->processed)
753 		return 0;
754 
755 	ret = isst_get_ctdp_levels(cpu, pkg_dev);
756 	if (ret)
757 		return ret;
758 
759 	debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n",
760 		     cpu, pkg_dev->enabled, pkg_dev->current_level,
761 		     pkg_dev->levels);
762 
763 	if (tdp_level != 0xff && tdp_level > pkg_dev->levels) {
764 		isst_display_error_info_message(1, "Invalid level", 0, 0);
765 		return -1;
766 	}
767 
768 	if (!pkg_dev->enabled)
769 		isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0);
770 
771 	for (i = 0; i <= pkg_dev->levels; ++i) {
772 		struct isst_pkg_ctdp_level_info *ctdp_level;
773 
774 		if (tdp_level != 0xff && i != tdp_level)
775 			continue;
776 
777 		debug_printf("cpu:%d Get Information for TDP level:%d\n", cpu,
778 			     i);
779 		ctdp_level = &pkg_dev->ctdp_level[i];
780 
781 		ctdp_level->level = i;
782 		ctdp_level->control_cpu = cpu;
783 		ctdp_level->pkg_id = get_physical_package_id(cpu);
784 		ctdp_level->die_id = get_physical_die_id(cpu);
785 
786 		ret = isst_get_ctdp_control(cpu, i, ctdp_level);
787 		if (ret)
788 			continue;
789 
790 		valid = 1;
791 		pkg_dev->processed = 1;
792 		ctdp_level->processed = 1;
793 
794 		if (ctdp_level->pbf_support) {
795 			ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
796 			if (!ret)
797 				ctdp_level->pbf_found = 1;
798 		}
799 
800 		if (ctdp_level->fact_support) {
801 			ret = isst_get_fact_info(cpu, i, 0xff,
802 						 &ctdp_level->fact_info);
803 			if (ret)
804 				return ret;
805 		}
806 
807 		if (!pkg_dev->enabled) {
808 			int freq;
809 
810 			freq = get_cpufreq_base_freq(cpu);
811 			if (freq > 0) {
812 				ctdp_level->sse_p1 = freq / 100000;
813 				ctdp_level->tdp_ratio = ctdp_level->sse_p1;
814 			}
815 
816 			isst_get_get_trl_from_msr(cpu, ctdp_level->trl_sse_active_cores);
817 			isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
818 			continue;
819 		}
820 
821 		ret = isst_get_tdp_info(cpu, i, ctdp_level);
822 		if (ret)
823 			return ret;
824 
825 		ret = isst_get_pwr_info(cpu, i, ctdp_level);
826 		if (ret)
827 			return ret;
828 
829 		ret = isst_get_tjmax_info(cpu, i, ctdp_level);
830 		if (ret)
831 			return ret;
832 
833 		ctdp_level->core_cpumask_size =
834 			alloc_cpu_set(&ctdp_level->core_cpumask);
835 		ret = isst_get_coremask_info(cpu, i, ctdp_level);
836 		if (ret)
837 			return ret;
838 
839 		ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
840 		if (ret)
841 			return ret;
842 
843 		ret = isst_get_get_trl(cpu, i, 0,
844 				       ctdp_level->trl_sse_active_cores);
845 		if (ret)
846 			return ret;
847 
848 		ret = isst_get_get_trl(cpu, i, 1,
849 				       ctdp_level->trl_avx_active_cores);
850 		if (ret)
851 			return ret;
852 
853 		ret = isst_get_get_trl(cpu, i, 2,
854 				       ctdp_level->trl_avx_512_active_cores);
855 		if (ret)
856 			return ret;
857 
858 		isst_get_uncore_p0_p1_info(cpu, i, ctdp_level);
859 		isst_get_p1_info(cpu, i, ctdp_level);
860 		isst_get_uncore_mem_freq(cpu, i, ctdp_level);
861 	}
862 
863 	if (!valid)
864 		isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, cpu);
865 
866 	return 0;
867 }
868 
869 int isst_clos_get_clos_information(int cpu, int *enable, int *type)
870 {
871 	unsigned int resp;
872 	int ret;
873 
874 	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
875 				     &resp);
876 	if (ret)
877 		return ret;
878 
879 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
880 
881 	if (resp & BIT(1))
882 		*enable = 1;
883 	else
884 		*enable = 0;
885 
886 	if (resp & BIT(2))
887 		*type = 1;
888 	else
889 		*type = 0;
890 
891 	return 0;
892 }
893 
894 int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
895 {
896 	unsigned int req, resp;
897 	int ret;
898 
899 	if (!enable_clos) {
900 		struct isst_pkg_ctdp pkg_dev;
901 		struct isst_pkg_ctdp_level_info ctdp_level;
902 
903 		ret = isst_get_ctdp_levels(cpu, &pkg_dev);
904 		if (ret) {
905 			debug_printf("isst_get_ctdp_levels\n");
906 			return ret;
907 		}
908 
909 		ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
910 					    &ctdp_level);
911 		if (ret)
912 			return ret;
913 
914 		if (ctdp_level.fact_enabled) {
915 			isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
916 			return -EINVAL;
917 		}
918 		ret = isst_write_pm_config(cpu, 0);
919 		if (ret)
920 			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
921 	} else {
922 		ret = isst_write_pm_config(cpu, 1);
923 		if (ret)
924 			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
925 	}
926 
927 	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
928 				     &resp);
929 	if (ret) {
930 		isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
931 		return ret;
932 	}
933 
934 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
935 
936 	req = resp;
937 
938 	if (enable_clos)
939 		req = req | BIT(1);
940 	else
941 		req = req & ~BIT(1);
942 
943 	if (priority_type > 1)
944 		isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
945 
946 	if (priority_type)
947 		req = req | BIT(2);
948 	else
949 		req = req & ~BIT(2);
950 
951 	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
952 				     BIT(MBOX_CMD_WRITE_BIT), req, &resp);
953 	if (ret)
954 		return ret;
955 
956 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", cpu,
957 		     priority_type, req);
958 
959 	return 0;
960 }
961 
962 int isst_pm_get_clos(int cpu, int clos, struct isst_clos_config *clos_config)
963 {
964 	unsigned int resp;
965 	int ret;
966 
967 	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
968 				     &resp);
969 	if (ret)
970 		return ret;
971 
972 	clos_config->pkg_id = get_physical_package_id(cpu);
973 	clos_config->die_id = get_physical_die_id(cpu);
974 
975 	clos_config->epp = resp & 0x0f;
976 	clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
977 	clos_config->clos_min = (resp >> 8) & 0xff;
978 	clos_config->clos_max = (resp >> 16) & 0xff;
979 	clos_config->clos_desired = (resp >> 24) & 0xff;
980 
981 	return 0;
982 }
983 
984 int isst_set_clos(int cpu, int clos, struct isst_clos_config *clos_config)
985 {
986 	unsigned int req, resp;
987 	unsigned int param;
988 	int ret;
989 
990 	req = clos_config->epp & 0x0f;
991 	req |= (clos_config->clos_prop_prio & 0x0f) << 4;
992 	req |= (clos_config->clos_min & 0xff) << 8;
993 	req |= (clos_config->clos_max & 0xff) << 16;
994 	req |= (clos_config->clos_desired & 0xff) << 24;
995 
996 	param = BIT(MBOX_CMD_WRITE_BIT) | clos;
997 
998 	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
999 				     &resp);
1000 	if (ret)
1001 		return ret;
1002 
1003 	debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", cpu, param, req);
1004 
1005 	return 0;
1006 }
1007 
1008 int isst_clos_get_assoc_status(int cpu, int *clos_id)
1009 {
1010 	unsigned int resp;
1011 	unsigned int param;
1012 	int core_id, ret;
1013 
1014 	core_id = find_phy_core_num(cpu);
1015 	param = core_id;
1016 
1017 	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
1018 				     &resp);
1019 	if (ret)
1020 		return ret;
1021 
1022 	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", cpu, param,
1023 		     resp);
1024 	*clos_id = (resp >> 16) & 0x03;
1025 
1026 	return 0;
1027 }
1028 
1029 int isst_clos_associate(int cpu, int clos_id)
1030 {
1031 	unsigned int req, resp;
1032 	unsigned int param;
1033 	int core_id, ret;
1034 
1035 	req = (clos_id & 0x03) << 16;
1036 	core_id = find_phy_core_num(cpu);
1037 	param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
1038 
1039 	ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
1040 				     req, &resp);
1041 	if (ret)
1042 		return ret;
1043 
1044 	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", cpu, param,
1045 		     req);
1046 
1047 	return 0;
1048 }
1049