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