1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Speed Select -- Enumerate and control features for Mailbox Interface
4  * Copyright (c) 2023 Intel Corporation.
5  */
6 #include "isst.h"
7 
8 static int mbox_get_disp_freq_multiplier(void)
9 {
10         return DISP_FREQ_MULTIPLIER;
11 }
12 
13 static int mbox_get_trl_max_levels(void)
14 {
15         return 3;
16 }
17 
18 static char *mbox_get_trl_level_name(int level)
19 {
20         switch (level) {
21         case 0:
22                 return "sse";
23         case 1:
24                 return "avx2";
25         case 2:
26                 return "avx512";
27         default:
28                 return NULL;
29         }
30 }
31 
32 static int mbox_is_punit_valid(struct isst_id *id)
33 {
34 	if (id->cpu < 0)
35 		return 0;
36 
37 	if (id->pkg < 0 || id->die < 0 || id->punit)
38 		return 0;
39 
40 	return 1;
41 }
42 
43 static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
44 {
45 	unsigned int resp;
46 	int ret;
47 
48 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
49 				     CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
50 	if (ret) {
51 		pkg_dev->levels = 0;
52 		pkg_dev->locked = 1;
53 		pkg_dev->current_level = 0;
54 		pkg_dev->version = 0;
55 		pkg_dev->enabled = 0;
56 		return 0;
57 	}
58 
59 	debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
60 
61 	pkg_dev->version = resp & 0xff;
62 	pkg_dev->levels = (resp >> 8) & 0xff;
63 	pkg_dev->current_level = (resp >> 16) & 0xff;
64 	pkg_dev->locked = !!(resp & BIT(24));
65 	pkg_dev->enabled = !!(resp & BIT(31));
66 
67 	return 0;
68 }
69 
70 static int mbox_get_ctdp_control(struct isst_id *id, int config_index,
71 			  struct isst_pkg_ctdp_level_info *ctdp_level)
72 {
73 	int cp_state, cp_cap;
74 	unsigned int resp;
75 	int ret;
76 
77 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
78 				     CONFIG_TDP_GET_TDP_CONTROL, 0,
79 				     config_index, &resp);
80 	if (ret)
81 		return ret;
82 
83 	ctdp_level->fact_support = resp & BIT(0);
84 	ctdp_level->pbf_support = !!(resp & BIT(1));
85 	ctdp_level->fact_enabled = !!(resp & BIT(16));
86 	ctdp_level->pbf_enabled = !!(resp & BIT(17));
87 
88 	ret = isst_read_pm_config(id, &cp_state, &cp_cap);
89 	if (ret) {
90 		debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
91 	} else {
92 		debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
93 		ctdp_level->sst_cp_support = cp_cap;
94 		ctdp_level->sst_cp_enabled = cp_state;
95 	}
96 
97 	debug_printf(
98 		"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
99 		id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
100 		ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
101 
102 	return 0;
103 }
104 
105 static void mbox_get_uncore_p0_p1_info(struct isst_id *id, int config_index,
106 				struct isst_pkg_ctdp_level_info *ctdp_level)
107 {
108 	unsigned int resp;
109 	int ret;
110 
111 	ctdp_level->uncore_pm = 0;
112 	ctdp_level->uncore_p0 = 0;
113 	ctdp_level->uncore_p1 = 0;
114 
115 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
116 				     CONFIG_TDP_GET_RATIO_INFO, 0,
117 				     (BIT(16) | config_index) , &resp);
118 	if (ret) {
119 		goto try_uncore_mbox;
120 	}
121 
122 	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
123 	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
124 	ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24;
125 
126 	debug_printf(
127 		"cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n",
128 		id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1,
129 		ctdp_level->uncore_pm);
130 
131 	return;
132 
133 try_uncore_mbox:
134 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
135 				     CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
136 				     config_index, &resp);
137 	if (ret) {
138 		ctdp_level->uncore_p0 = 0;
139 		ctdp_level->uncore_p1 = 0;
140 		return;
141 	}
142 
143 	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
144 	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
145 	debug_printf(
146 		"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
147 		id->cpu, config_index, resp, ctdp_level->uncore_p0,
148 		ctdp_level->uncore_p1);
149 }
150 
151 static void _get_p1_info(struct isst_id *id, int config_index,
152 		      struct isst_pkg_ctdp_level_info *ctdp_level)
153 {
154 	unsigned int resp;
155 	int ret;
156 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
157 				     config_index, &resp);
158 	if (ret) {
159 		ctdp_level->sse_p1 = 0;
160 		ctdp_level->avx2_p1 = 0;
161 		ctdp_level->avx512_p1 = 0;
162 		return;
163 	}
164 
165 	ctdp_level->sse_p1 = resp & GENMASK(7, 0);
166 	ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
167 	ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
168 	debug_printf(
169 		"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
170 		id->cpu, config_index, resp, ctdp_level->sse_p1,
171 		ctdp_level->avx2_p1, ctdp_level->avx512_p1);
172 }
173 
174 static void _get_uncore_mem_freq(struct isst_id *id, int config_index,
175 			      struct isst_pkg_ctdp_level_info *ctdp_level)
176 {
177 	unsigned int resp;
178 	int ret;
179 
180 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
181 				     0, config_index, &resp);
182 	if (ret) {
183 		ctdp_level->mem_freq = 0;
184 		return;
185 	}
186 
187 	ctdp_level->mem_freq = resp & GENMASK(7, 0);
188 	if (is_spr_platform()) {
189 		ctdp_level->mem_freq *= 200;
190 	} else if (is_icx_platform()) {
191 		if (ctdp_level->mem_freq < 7) {
192 			ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
193 			ctdp_level->mem_freq /= 10;
194 			if (ctdp_level->mem_freq % 10 > 5)
195 				ctdp_level->mem_freq++;
196 		} else {
197 			ctdp_level->mem_freq = 0;
198 		}
199 	} else {
200 		ctdp_level->mem_freq = 0;
201 	}
202 	debug_printf(
203 		"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
204 		id->cpu, config_index, resp, ctdp_level->mem_freq);
205 }
206 
207 static int mbox_get_tdp_info(struct isst_id *id, int config_index,
208 		      struct isst_pkg_ctdp_level_info *ctdp_level)
209 {
210 	unsigned int resp;
211 	int ret;
212 
213 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
214 				     0, config_index, &resp);
215 	if (ret) {
216 		isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
217 		return ret;
218 	}
219 
220 	ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
221 	ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
222 
223 	debug_printf(
224 		"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
225 		id->cpu, config_index, resp, ctdp_level->tdp_ratio,
226 		ctdp_level->pkg_tdp);
227 
228 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
229 				     0, config_index, &resp);
230 	if (ret)
231 		return ret;
232 
233 	ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
234 
235 	mbox_get_uncore_p0_p1_info(id, config_index, ctdp_level);
236 	_get_p1_info(id, config_index, ctdp_level);
237 	_get_uncore_mem_freq(id, config_index, ctdp_level);
238 
239 	debug_printf(
240 		"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
241 		id->cpu, config_index, resp, ctdp_level->t_proc_hot);
242 
243 	return 0;
244 }
245 
246 static int mbox_get_pwr_info(struct isst_id *id, int config_index,
247 		      struct isst_pkg_ctdp_level_info *ctdp_level)
248 {
249 	unsigned int resp;
250 	int ret;
251 
252 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
253 				     0, config_index, &resp);
254 	if (ret)
255 		return ret;
256 
257 	ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
258 	ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
259 
260 	debug_printf(
261 		"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
262 		id->cpu, config_index, resp, ctdp_level->pkg_max_power,
263 		ctdp_level->pkg_min_power);
264 
265 	return 0;
266 }
267 
268 static int mbox_get_coremask_info(struct isst_id *id, int config_index,
269 			   struct isst_pkg_ctdp_level_info *ctdp_level)
270 {
271 	unsigned int resp;
272 	int i, ret;
273 
274 	ctdp_level->cpu_count = 0;
275 	for (i = 0; i < 2; ++i) {
276 		unsigned long long mask;
277 		int cpu_count = 0;
278 
279 		ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
280 					     CONFIG_TDP_GET_CORE_MASK, 0,
281 					     (i << 8) | config_index, &resp);
282 		if (ret)
283 			return ret;
284 
285 		debug_printf(
286 			"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
287 			id->cpu, config_index, i, resp);
288 
289 		mask = (unsigned long long)resp << (32 * i);
290 		set_cpu_mask_from_punit_coremask(id, mask,
291 						 ctdp_level->core_cpumask_size,
292 						 ctdp_level->core_cpumask,
293 						 &cpu_count);
294 		ctdp_level->cpu_count += cpu_count;
295 		debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
296 			     config_index, i, ctdp_level->cpu_count);
297 	}
298 
299 	return 0;
300 }
301 
302 static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
303 {
304 	unsigned int req, resp;
305 	int ret;
306 
307 	req = level | (avx_level << 16);
308 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
309 				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
310 				     &resp);
311 	if (ret)
312 		return ret;
313 
314 	debug_printf(
315 		"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
316 		id->cpu, req, resp);
317 
318 	trl[0] = resp & GENMASK(7, 0);
319 	trl[1] = (resp & GENMASK(15, 8)) >> 8;
320 	trl[2] = (resp & GENMASK(23, 16)) >> 16;
321 	trl[3] = (resp & GENMASK(31, 24)) >> 24;
322 
323 	req = level | BIT(8) | (avx_level << 16);
324 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
325 				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
326 				     &resp);
327 	if (ret)
328 		return ret;
329 
330 	debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
331 		     req, resp);
332 
333 	trl[4] = resp & GENMASK(7, 0);
334 	trl[5] = (resp & GENMASK(15, 8)) >> 8;
335 	trl[6] = (resp & GENMASK(23, 16)) >> 16;
336 	trl[7] = (resp & GENMASK(31, 24)) >> 24;
337 
338 	return 0;
339 }
340 
341 static int mbox_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
342 {
343 	int trl_max_levels = isst_get_trl_max_levels();
344 	int i, ret;
345 
346 	for (i = 0; i < trl_max_levels; i++) {
347 		ret = mbox_get_get_trl(id, level, i, ctdp_level->trl_ratios[i]);
348 		if (ret)
349 			return ret;
350 	}
351 	return 0;
352 }
353 
354 static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
355 {
356 	int ret;
357 
358 	debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
359 
360 	*buckets_info = 0;
361 
362 	ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);
363 	if (ret)
364 		return ret;
365 
366 	debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
367 		     *buckets_info);
368 
369 	return 0;
370 }
371 
372 static int mbox_set_tdp_level(struct isst_id *id, int tdp_level)
373 {
374 	unsigned int resp;
375 	int ret;
376 
377 
378 	if (isst_get_config_tdp_lock_status(id)) {
379 		isst_display_error_info_message(1, "TDP is locked", 0, 0);
380 		return -1;
381 
382 	}
383 
384 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
385 				     tdp_level, &resp);
386 	if (ret) {
387 		isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
388 		return ret;
389 	}
390 
391 	return 0;
392 }
393 
394 static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
395 {
396 	int max_punit_core, max_mask_index;
397 	unsigned int req, resp;
398 	int i, ret;
399 
400 	max_punit_core = get_max_punit_core_id(id);
401 	max_mask_index = max_punit_core > 32 ? 2 : 1;
402 
403 	for (i = 0; i < max_mask_index; ++i) {
404 		unsigned long long mask;
405 		int count;
406 
407 		ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
408 					     CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
409 					     0, (i << 8) | level, &resp);
410 		if (ret)
411 			break;
412 
413 		debug_printf(
414 			"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
415 			id->cpu, resp);
416 
417 		mask = (unsigned long long)resp << (32 * i);
418 		set_cpu_mask_from_punit_coremask(id, mask,
419 						 pbf_info->core_cpumask_size,
420 						 pbf_info->core_cpumask,
421 						 &count);
422 	}
423 
424 	req = level;
425 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
426 				     CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
427 				     &resp);
428 	if (ret)
429 		return ret;
430 
431 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
432 		     resp);
433 
434 	pbf_info->p1_low = resp & 0xff;
435 	pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
436 
437 	req = level;
438 	ret = isst_send_mbox_command(
439 		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
440 	if (ret)
441 		return ret;
442 
443 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);
444 
445 	pbf_info->tdp = resp & 0xffff;
446 
447 	req = level;
448 	ret = isst_send_mbox_command(
449 		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
450 	if (ret)
451 		return ret;
452 
453 	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,
454 		     resp);
455 	pbf_info->t_control = (resp >> 8) & 0xff;
456 	pbf_info->t_prochot = resp & 0xff;
457 
458 	return 0;
459 }
460 
461 static int mbox_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
462 {
463 	struct isst_pkg_ctdp pkg_dev;
464 	struct isst_pkg_ctdp_level_info ctdp_level;
465 	int current_level;
466 	unsigned int req = 0, resp;
467 	int ret;
468 
469 	ret = isst_get_ctdp_levels(id, &pkg_dev);
470 	if (ret)
471 		debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
472 
473 	current_level = pkg_dev.current_level;
474 
475 	ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
476 	if (ret)
477 		return ret;
478 
479 	if (pbf) {
480 		if (ctdp_level.fact_enabled)
481 			req = BIT(16);
482 
483 		if (enable)
484 			req |= BIT(17);
485 		else
486 			req &= ~BIT(17);
487 	} else {
488 
489 		if (enable && !ctdp_level.sst_cp_enabled)
490 			isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
491 
492 		if (ctdp_level.pbf_enabled)
493 			req = BIT(17);
494 
495 		if (enable)
496 			req |= BIT(16);
497 		else
498 			req &= ~BIT(16);
499 	}
500 
501 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
502 				     CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
503 	if (ret)
504 		return ret;
505 
506 	debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
507 		     id->cpu, pbf, req);
508 
509 	return 0;
510 }
511 
512 static int _get_fact_bucket_info(struct isst_id *id, int level,
513 			      struct isst_fact_bucket_info *bucket_info)
514 {
515 	unsigned int resp;
516 	int i, k, ret;
517 
518 	for (i = 0; i < 2; ++i) {
519 		int j;
520 
521 		ret = isst_send_mbox_command(
522 			id->cpu, CONFIG_TDP,
523 			CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
524 			(i << 8) | level, &resp);
525 		if (ret)
526 			return ret;
527 
528 		debug_printf(
529 			"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
530 			id->cpu, i, level, resp);
531 
532 		for (j = 0; j < 4; ++j) {
533 			bucket_info[j + (i * 4)].hp_cores =
534 				(resp >> (j * 8)) & 0xff;
535 		}
536 	}
537 
538 	for (k = 0; k < 3; ++k) {
539 		for (i = 0; i < 2; ++i) {
540 			int j;
541 
542 			ret = isst_send_mbox_command(
543 				id->cpu, CONFIG_TDP,
544 				CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
545 				(k << 16) | (i << 8) | level, &resp);
546 			if (ret)
547 				return ret;
548 
549 			debug_printf(
550 				"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
551 				id->cpu, i, level, k, resp);
552 
553 			for (j = 0; j < 4; ++j) {
554 				bucket_info[j + (i * 4)].hp_ratios[k] =
555 					(resp >> (j * 8)) & 0xff;
556 			}
557 		}
558 	}
559 
560 	return 0;
561 }
562 
563 static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
564 {
565 	unsigned int resp;
566 	int j, ret, print;
567 
568 	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
569 				     CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
570 				     level, &resp);
571 	if (ret)
572 		return ret;
573 
574 	debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
575 		     id->cpu, resp);
576 
577 	fact_info->lp_ratios[0] = resp & 0xff;
578 	fact_info->lp_ratios[1] = (resp >> 8) & 0xff;
579 	fact_info->lp_ratios[2] = (resp >> 16) & 0xff;
580 
581 	ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);
582 	if (ret)
583 		return ret;
584 
585 	print = 0;
586 	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
587 		if (fact_bucket != 0xff && fact_bucket != j)
588 			continue;
589 
590 		if (!fact_info->bucket_info[j].hp_cores)
591 			break;
592 
593 		print = 1;
594 	}
595 	if (!print) {
596 		isst_display_error_info_message(1, "Invalid bucket", 0, 0);
597 		return -1;
598 	}
599 
600 	return 0;
601 }
602 
603 static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)
604 {
605 	unsigned int resp;
606 	int ret;
607 
608 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
609 				     &resp);
610 	if (ret)
611 		return ret;
612 
613 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
614 
615 	if (resp & BIT(1))
616 		*enable = 1;
617 	else
618 		*enable = 0;
619 
620 	if (resp & BIT(2))
621 		*type = 1;
622 	else
623 		*type = 0;
624 
625 	return 0;
626 }
627 
628 static int _write_pm_config(struct isst_id *id, int cp_state)
629 {
630 	unsigned int req, resp;
631 	int ret;
632 
633 	if (cp_state)
634 		req = BIT(16);
635 	else
636 		req = 0;
637 
638 	ret = isst_send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
639 				     &resp);
640 	if (ret)
641 		return ret;
642 
643 	debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
644 
645 	return 0;
646 }
647 
648 static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
649 {
650 	unsigned int req, resp;
651 	int ret;
652 
653 	if (!enable_clos) {
654 		struct isst_pkg_ctdp pkg_dev;
655 		struct isst_pkg_ctdp_level_info ctdp_level;
656 
657 		ret = isst_get_ctdp_levels(id, &pkg_dev);
658 		if (ret) {
659 			debug_printf("isst_get_ctdp_levels\n");
660 			return ret;
661 		}
662 
663 		ret = isst_get_ctdp_control(id, pkg_dev.current_level,
664 					    &ctdp_level);
665 		if (ret)
666 			return ret;
667 
668 		if (ctdp_level.fact_enabled) {
669 			isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
670 			return -EINVAL;
671 		}
672 		ret = _write_pm_config(id, 0);
673 		if (ret)
674 			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
675 	} else {
676 		ret = _write_pm_config(id, 1);
677 		if (ret)
678 			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
679 	}
680 
681 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
682 				     &resp);
683 	if (ret) {
684 		isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
685 		return ret;
686 	}
687 
688 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
689 
690 	req = resp;
691 
692 	if (enable_clos)
693 		req = req | BIT(1);
694 	else
695 		req = req & ~BIT(1);
696 
697 	if (priority_type > 1)
698 		isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
699 
700 	if (priority_type)
701 		req = req | BIT(2);
702 	else
703 		req = req & ~BIT(2);
704 
705 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
706 				     BIT(MBOX_CMD_WRITE_BIT), req, &resp);
707 	if (ret)
708 		return ret;
709 
710 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
711 		     priority_type, req);
712 
713 	return 0;
714 }
715 
716 static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
717 {
718 	unsigned int resp;
719 	int ret;
720 
721 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
722 				     &resp);
723 	if (ret)
724 		return ret;
725 
726 	clos_config->epp = resp & 0x0f;
727 	clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
728 	clos_config->clos_min = (resp >> 8) & 0xff;
729 	clos_config->clos_max = (resp >> 16) & 0xff;
730 	clos_config->clos_desired = (resp >> 24) & 0xff;
731 
732 	return 0;
733 }
734 
735 static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
736 {
737 	unsigned int req, resp;
738 	unsigned int param;
739 	int ret;
740 
741 	req = clos_config->epp & 0x0f;
742 	req |= (clos_config->clos_prop_prio & 0x0f) << 4;
743 	req |= (clos_config->clos_min & 0xff) << 8;
744 	req |= (clos_config->clos_max & 0xff) << 16;
745 	req |= (clos_config->clos_desired & 0xff) << 24;
746 
747 	param = BIT(MBOX_CMD_WRITE_BIT) | clos;
748 
749 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
750 				     &resp);
751 	if (ret)
752 		return ret;
753 
754 	debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
755 
756 	return 0;
757 }
758 
759 static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)
760 {
761 	unsigned int resp;
762 	unsigned int param;
763 	int core_id, ret;
764 
765 	core_id = find_phy_core_num(id->cpu);
766 	param = core_id;
767 
768 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
769 				     &resp);
770 	if (ret)
771 		return ret;
772 
773 	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
774 		     resp);
775 	*clos_id = (resp >> 16) & 0x03;
776 
777 	return 0;
778 }
779 
780 static int mbox_clos_associate(struct isst_id *id, int clos_id)
781 {
782 	unsigned int req, resp;
783 	unsigned int param;
784 	int core_id, ret;
785 
786 	req = (clos_id & 0x03) << 16;
787 	core_id = find_phy_core_num(id->cpu);
788 	param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
789 
790 	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
791 				     req, &resp);
792 	if (ret)
793 		return ret;
794 
795 	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
796 		     req);
797 
798 	return 0;
799 }
800 
801 static struct isst_platform_ops mbox_ops = {
802 	.get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
803 	.get_trl_max_levels = mbox_get_trl_max_levels,
804 	.get_trl_level_name = mbox_get_trl_level_name,
805 	.is_punit_valid = mbox_is_punit_valid,
806 	.get_config_levels = mbox_get_config_levels,
807 	.get_ctdp_control = mbox_get_ctdp_control,
808 	.get_tdp_info = mbox_get_tdp_info,
809 	.get_pwr_info = mbox_get_pwr_info,
810 	.get_coremask_info = mbox_get_coremask_info,
811 	.get_get_trl = mbox_get_get_trl,
812 	.get_get_trls = mbox_get_get_trls,
813 	.get_trl_bucket_info = mbox_get_trl_bucket_info,
814 	.set_tdp_level = mbox_set_tdp_level,
815 	.get_pbf_info = mbox_get_pbf_info,
816 	.set_pbf_fact_status = mbox_set_pbf_fact_status,
817 	.get_fact_info = mbox_get_fact_info,
818 	.get_uncore_p0_p1_info = mbox_get_uncore_p0_p1_info,
819 	.get_clos_information = mbox_get_clos_information,
820 	.pm_qos_config = mbox_pm_qos_config,
821 	.pm_get_clos = mbox_pm_get_clos,
822 	.set_clos = mbox_set_clos,
823 	.clos_get_assoc_status = mbox_clos_get_assoc_status,
824 	.clos_associate = mbox_clos_associate,
825 };
826 
827 struct isst_platform_ops *mbox_get_platform_ops(void)
828 {
829 	return &mbox_ops;
830 }
831