xref: /linux/tools/power/x86/intel-speed-select/isst-core-mbox.c (revision ea5f6ad9ad9645733b72ab53a98e719b460d36a6)
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 
mbox_get_disp_freq_multiplier(void)13 static int mbox_get_disp_freq_multiplier(void)
14 {
15         return DISP_FREQ_MULTIPLIER;
16 }
17 
mbox_get_trl_max_levels(void)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 
mbox_get_trl_level_name(int level)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 
mbox_update_platform_param(enum isst_platform_param param,int value)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 
mbox_is_punit_valid(struct isst_id * id)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 
_send_mmio_command(unsigned int cpu,unsigned int reg,int write,unsigned int * value)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 
_send_mbox_command(unsigned int cpu,unsigned char command,unsigned char sub_command,unsigned int parameter,unsigned int req_data,unsigned int * resp)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 
mbox_read_pm_config(struct isst_id * id,int * cp_state,int * cp_cap)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 
mbox_get_config_levels(struct isst_id * id,struct isst_pkg_ctdp * pkg_dev)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 
mbox_get_ctdp_control(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)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 
_get_uncore_p0_p1_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)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 
_set_uncore_min_max(struct isst_id * id,int max,int freq)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 
mbox_adjust_uncore_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)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 
_get_p1_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)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 
_get_uncore_mem_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)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 
mbox_get_tdp_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)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 
mbox_get_pwr_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)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 
mbox_get_coremask_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)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 
mbox_get_get_trl(struct isst_id * id,int level,int avx_level,int * trl)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 
mbox_get_get_trls(struct isst_id * id,int level,struct isst_pkg_ctdp_level_info * ctdp_level)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 
mbox_get_trl_bucket_info(struct isst_id * id,int level,unsigned long long * buckets_info)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 
mbox_set_tdp_level(struct isst_id * id,int tdp_level)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 
mbox_get_pbf_info(struct isst_id * id,int level,struct isst_pbf_info * pbf_info)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 
mbox_set_pbf_fact_status(struct isst_id * id,int pbf,int enable)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 
_get_fact_bucket_info(struct isst_id * id,int level,struct isst_fact_bucket_info * bucket_info)746 static int _get_fact_bucket_info(struct isst_id *id, int level,
747 			      struct isst_fact_bucket_info *bucket_info)
748 {
749 	int trl_max_levels = isst_get_trl_max_levels();
750 	unsigned int resp;
751 	int i, k, ret;
752 
753 	for (i = 0; i < 2; ++i) {
754 		int j;
755 
756 		ret = _send_mbox_command(
757 			id->cpu, CONFIG_TDP,
758 			CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
759 			(i << 8) | level, &resp);
760 		if (ret)
761 			return ret;
762 
763 		debug_printf(
764 			"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
765 			id->cpu, i, level, resp);
766 
767 		for (j = 0; j < 4; ++j) {
768 			bucket_info[j + (i * 4)].hp_cores =
769 				(resp >> (j * 8)) & 0xff;
770 		}
771 	}
772 
773 	for (k = 0; k < trl_max_levels; ++k) {
774 		for (i = 0; i < 2; ++i) {
775 			int j;
776 
777 			ret = _send_mbox_command(
778 				id->cpu, CONFIG_TDP,
779 				CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
780 				(k << 16) | (i << 8) | level, &resp);
781 			if (ret)
782 				return ret;
783 
784 			debug_printf(
785 				"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
786 				id->cpu, i, level, k, resp);
787 
788 			for (j = 0; j < 4; ++j) {
789 				bucket_info[j + (i * 4)].hp_ratios[k] =
790 					(resp >> (j * 8)) & 0xff;
791 			}
792 		}
793 	}
794 
795 	return 0;
796 }
797 
mbox_get_fact_info(struct isst_id * id,int level,int fact_bucket,struct isst_fact_info * fact_info)798 static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
799 {
800 	unsigned int resp;
801 	int j, ret, print;
802 
803 	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
804 				     CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
805 				     level, &resp);
806 	if (ret)
807 		return ret;
808 
809 	debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
810 		     id->cpu, resp);
811 
812 	fact_info->lp_ratios[0] = resp & 0xff;
813 	fact_info->lp_ratios[1] = (resp >> 8) & 0xff;
814 	fact_info->lp_ratios[2] = (resp >> 16) & 0xff;
815 
816 	ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);
817 	if (ret)
818 		return ret;
819 
820 	print = 0;
821 	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
822 		if (fact_bucket != 0xff && fact_bucket != j)
823 			continue;
824 
825 		if (!fact_info->bucket_info[j].hp_cores)
826 			break;
827 
828 		print = 1;
829 	}
830 	if (!print) {
831 		isst_display_error_info_message(1, "Invalid bucket", 0, 0);
832 		return -1;
833 	}
834 
835 	return 0;
836 }
837 
mbox_get_clos_information(struct isst_id * id,int * enable,int * type)838 static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)
839 {
840 	unsigned int resp;
841 	int ret;
842 
843 	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
844 				     &resp);
845 	if (ret)
846 		return ret;
847 
848 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
849 
850 	if (resp & BIT(1))
851 		*enable = 1;
852 	else
853 		*enable = 0;
854 
855 	if (resp & BIT(2))
856 		*type = 1;
857 	else
858 		*type = 0;
859 
860 	return 0;
861 }
862 
_write_pm_config(struct isst_id * id,int cp_state)863 static int _write_pm_config(struct isst_id *id, int cp_state)
864 {
865 	unsigned int req, resp;
866 	int ret;
867 
868 	if (cp_state)
869 		req = BIT(16);
870 	else
871 		req = 0;
872 
873 	ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
874 				     &resp);
875 	if (ret)
876 		return ret;
877 
878 	debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
879 
880 	return 0;
881 }
882 
mbox_pm_qos_config(struct isst_id * id,int enable_clos,int priority_type)883 static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
884 {
885 	unsigned int req, resp;
886 	int ret;
887 
888 	if (!enable_clos) {
889 		struct isst_pkg_ctdp pkg_dev;
890 		struct isst_pkg_ctdp_level_info ctdp_level;
891 
892 		ret = isst_get_ctdp_levels(id, &pkg_dev);
893 		if (ret) {
894 			debug_printf("isst_get_ctdp_levels\n");
895 			return ret;
896 		}
897 
898 		ret = isst_get_ctdp_control(id, pkg_dev.current_level,
899 					    &ctdp_level);
900 		if (ret)
901 			return ret;
902 
903 		if (ctdp_level.fact_enabled) {
904 			isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
905 			return -EINVAL;
906 		}
907 		ret = _write_pm_config(id, 0);
908 		if (ret)
909 			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
910 	} else {
911 		ret = _write_pm_config(id, 1);
912 		if (ret)
913 			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
914 	}
915 
916 	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
917 				     &resp);
918 	if (ret) {
919 		isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
920 		return ret;
921 	}
922 
923 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
924 
925 	req = resp;
926 
927 	if (enable_clos)
928 		req = req | BIT(1);
929 	else
930 		req = req & ~BIT(1);
931 
932 	if (priority_type > 1)
933 		isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
934 
935 	if (priority_type)
936 		req = req | BIT(2);
937 	else
938 		req = req & ~BIT(2);
939 
940 	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
941 				     BIT(MBOX_CMD_WRITE_BIT), req, &resp);
942 	if (ret)
943 		return ret;
944 
945 	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
946 		     priority_type, req);
947 
948 	return 0;
949 }
950 
mbox_pm_get_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)951 static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
952 {
953 	unsigned int resp;
954 	int ret;
955 
956 	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
957 				     &resp);
958 	if (ret)
959 		return ret;
960 
961 	clos_config->epp = resp & 0x0f;
962 	clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
963 	clos_config->clos_min = (resp >> 8) & 0xff;
964 	clos_config->clos_max = (resp >> 16) & 0xff;
965 	clos_config->clos_desired = (resp >> 24) & 0xff;
966 
967 	return 0;
968 }
969 
mbox_set_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)970 static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
971 {
972 	unsigned int req, resp;
973 	unsigned int param;
974 	int ret;
975 
976 	req = clos_config->epp & 0x0f;
977 	req |= (clos_config->clos_prop_prio & 0x0f) << 4;
978 	req |= (clos_config->clos_min & 0xff) << 8;
979 	req |= (clos_config->clos_max & 0xff) << 16;
980 	req |= (clos_config->clos_desired & 0xff) << 24;
981 
982 	param = BIT(MBOX_CMD_WRITE_BIT) | clos;
983 
984 	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
985 				     &resp);
986 	if (ret)
987 		return ret;
988 
989 	debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
990 
991 	return 0;
992 }
993 
mbox_clos_get_assoc_status(struct isst_id * id,int * clos_id)994 static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)
995 {
996 	unsigned int resp;
997 	unsigned int param;
998 	int core_id, ret;
999 
1000 	core_id = find_phy_core_num(id->cpu);
1001 	param = core_id;
1002 
1003 	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
1004 				     &resp);
1005 	if (ret)
1006 		return ret;
1007 
1008 	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
1009 		     resp);
1010 	*clos_id = (resp >> 16) & 0x03;
1011 
1012 	return 0;
1013 }
1014 
mbox_clos_associate(struct isst_id * id,int clos_id)1015 static int mbox_clos_associate(struct isst_id *id, int clos_id)
1016 {
1017 	unsigned int req, resp;
1018 	unsigned int param;
1019 	int core_id, ret;
1020 
1021 	req = (clos_id & 0x03) << 16;
1022 	core_id = find_phy_core_num(id->cpu);
1023 	param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
1024 
1025 	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
1026 				     req, &resp);
1027 	if (ret)
1028 		return ret;
1029 
1030 	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
1031 		     req);
1032 
1033 	return 0;
1034 }
1035 
1036 static struct isst_platform_ops mbox_ops = {
1037 	.get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
1038 	.get_trl_max_levels = mbox_get_trl_max_levels,
1039 	.get_trl_level_name = mbox_get_trl_level_name,
1040 	.update_platform_param = mbox_update_platform_param,
1041 	.is_punit_valid = mbox_is_punit_valid,
1042 	.read_pm_config = mbox_read_pm_config,
1043 	.get_config_levels = mbox_get_config_levels,
1044 	.get_ctdp_control = mbox_get_ctdp_control,
1045 	.get_tdp_info = mbox_get_tdp_info,
1046 	.get_pwr_info = mbox_get_pwr_info,
1047 	.get_coremask_info = mbox_get_coremask_info,
1048 	.get_get_trl = mbox_get_get_trl,
1049 	.get_get_trls = mbox_get_get_trls,
1050 	.get_trl_bucket_info = mbox_get_trl_bucket_info,
1051 	.set_tdp_level = mbox_set_tdp_level,
1052 	.get_pbf_info = mbox_get_pbf_info,
1053 	.set_pbf_fact_status = mbox_set_pbf_fact_status,
1054 	.get_fact_info = mbox_get_fact_info,
1055 	.adjust_uncore_freq = mbox_adjust_uncore_freq,
1056 	.get_clos_information = mbox_get_clos_information,
1057 	.pm_qos_config = mbox_pm_qos_config,
1058 	.pm_get_clos = mbox_pm_get_clos,
1059 	.set_clos = mbox_set_clos,
1060 	.clos_get_assoc_status = mbox_clos_get_assoc_status,
1061 	.clos_associate = mbox_clos_associate,
1062 };
1063 
mbox_get_platform_ops(void)1064 struct isst_platform_ops *mbox_get_platform_ops(void)
1065 {
1066 	return &mbox_ops;
1067 }
1068