1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Intel Speed Select -- Enumerate and control features for TPMI Interface
4  * Copyright (c) 2022 Intel Corporation.
5  */
6 
7 #include <linux/isst_if.h>
8 #include "isst.h"
9 
10 int tpmi_process_ioctl(int ioctl_no, void *info)
11 {
12 	const char *pathname = "/dev/isst_interface";
13 	int fd;
14 
15 	if (is_debug_enabled()) {
16 		debug_printf("Issue IOCTL: ");
17 		switch (ioctl_no) {
18 		case ISST_IF_CORE_POWER_STATE:
19 			debug_printf("ISST_IF_CORE_POWER_STATE\n");
20 			break;
21 		case ISST_IF_CLOS_PARAM:
22 			debug_printf("ISST_IF_CLOS_PARAM\n");
23 			break;
24 		case ISST_IF_CLOS_ASSOC:
25 			debug_printf("ISST_IF_CLOS_ASSOC\n");
26 			break;
27 		case ISST_IF_PERF_LEVELS:
28 			debug_printf("ISST_IF_PERF_LEVELS\n");
29 			break;
30 		case ISST_IF_PERF_SET_LEVEL:
31 			debug_printf("ISST_IF_PERF_SET_LEVEL\n");
32 			break;
33 		case ISST_IF_PERF_SET_FEATURE:
34 			debug_printf("ISST_IF_PERF_SET_FEATURE\n");
35 			break;
36 		case ISST_IF_GET_PERF_LEVEL_INFO:
37 			debug_printf("ISST_IF_GET_PERF_LEVEL_INFO\n");
38 			break;
39 		case ISST_IF_GET_PERF_LEVEL_CPU_MASK:
40 			debug_printf("ISST_IF_GET_PERF_LEVEL_CPU_MASK\n");
41 			break;
42 		case ISST_IF_GET_BASE_FREQ_INFO:
43 			debug_printf("ISST_IF_GET_BASE_FREQ_INFO\n");
44 			break;
45 		case ISST_IF_GET_BASE_FREQ_CPU_MASK:
46 			debug_printf("ISST_IF_GET_BASE_FREQ_CPU_MASK\n");
47 			break;
48 		case ISST_IF_GET_TURBO_FREQ_INFO:
49 			debug_printf("ISST_IF_GET_TURBO_FREQ_INFO\n");
50 			break;
51 		case ISST_IF_COUNT_TPMI_INSTANCES:
52 			debug_printf("ISST_IF_COUNT_TPMI_INSTANCES\n");
53 			break;
54 		default:
55 			debug_printf("%d\n", ioctl_no);
56 			break;
57 		}
58 	}
59 
60 	fd = open(pathname, O_RDWR);
61 	if (fd < 0)
62 		return -1;
63 
64 	if (ioctl(fd, ioctl_no, info) == -1) {
65 		debug_printf("IOCTL %d Failed\n", ioctl_no);
66 		close(fd);
67 		return -1;
68 	}
69 
70 	close(fd);
71 
72 	return 0;
73 }
74 
75 static int tpmi_get_disp_freq_multiplier(void)
76 {
77 	return 1;
78 }
79 
80 static int tpmi_get_trl_max_levels(void)
81 {
82 	return TRL_MAX_LEVELS;
83 }
84 
85 static char *tpmi_get_trl_level_name(int level)
86 {
87 	switch (level) {
88 	case 0:
89 		return "level-0";
90 	case 1:
91 		return "level-1";
92 	case 2:
93 		return "level-2";
94 	case 3:
95 		return "level-3";
96 	case 4:
97 		return "level-4";
98 	case 5:
99 		return "level-5";
100 	case 6:
101 		return "level-6";
102 	case 7:
103 		return "level-7";
104 	default:
105 		return NULL;
106 	}
107 }
108 
109 
110 static void tpmi_update_platform_param(enum isst_platform_param param, int value)
111 {
112 	/* No params need to be updated for now */
113 }
114 
115 static int tpmi_is_punit_valid(struct isst_id *id)
116 {
117 	struct isst_tpmi_instance_count info;
118 	int ret;
119 
120 	if (id->punit < 0)
121 		return 0;
122 
123 	info.socket_id = id->pkg;
124 	ret = tpmi_process_ioctl(ISST_IF_COUNT_TPMI_INSTANCES, &info);
125 	if (ret == -1)
126 		return 0;
127 
128 	if (info.valid_mask & BIT(id->punit))
129 		return 1;
130 
131 	return 0;
132 }
133 
134 static int tpmi_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
135 {
136 	struct isst_core_power info;
137 	int ret;
138 
139 	info.get_set = 0;
140 	info.socket_id = id->pkg;
141 	info.power_domain_id = id->punit;
142 	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
143 	if (ret == -1)
144 		return ret;
145 
146 	*cp_state = info.enable;
147 	*cp_cap = info.supported;
148 
149 	return 0;
150 }
151 
152 int tpmi_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
153 {
154 	struct isst_perf_level_info info;
155 	int ret;
156 
157 	info.socket_id = id->pkg;
158 	info.power_domain_id = id->punit;
159 
160 	ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
161 	if (ret == -1)
162 		return ret;
163 
164 	pkg_dev->version = info.feature_rev;
165 	pkg_dev->levels = info.max_level;
166 	pkg_dev->locked = info.locked;
167 	pkg_dev->current_level = info.current_level;
168 	pkg_dev->locked = info.locked;
169 	pkg_dev->enabled = info.enabled;
170 
171 	return 0;
172 }
173 
174 static int tpmi_get_ctdp_control(struct isst_id *id, int config_index,
175 				 struct isst_pkg_ctdp_level_info *ctdp_level)
176 {
177 	struct isst_core_power core_power_info;
178 	struct isst_perf_level_info info;
179 	int level_mask;
180 	int ret;
181 
182 	info.socket_id = id->pkg;
183 	info.power_domain_id = id->punit;
184 
185 	ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
186 	if (ret == -1)
187 		return -1;
188 
189 	if (config_index != 0xff)
190 		level_mask = 1 << config_index;
191 	else
192 		level_mask = config_index;
193 
194 	if (!(info.level_mask & level_mask))
195 		return -1;
196 
197 	ctdp_level->fact_support = info.sst_tf_support;
198 	ctdp_level->pbf_support = info.sst_bf_support;
199 	ctdp_level->fact_enabled = !!(info.feature_state & BIT(1));
200 	ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0));
201 
202 	core_power_info.get_set = 0;
203 	core_power_info.socket_id = id->pkg;
204 	core_power_info.power_domain_id = id->punit;
205 
206 	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info);
207 	if (ret == -1)
208 		return ret;
209 
210 	ctdp_level->sst_cp_support = core_power_info.supported;
211 	ctdp_level->sst_cp_enabled = core_power_info.enable;
212 
213 	debug_printf
214 	    ("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
215 	     id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support,
216 	     ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
217 
218 	return 0;
219 }
220 
221 static int tpmi_get_tdp_info(struct isst_id *id, int config_index,
222 			     struct isst_pkg_ctdp_level_info *ctdp_level)
223 {
224 	struct isst_perf_level_data_info info;
225 	int ret;
226 
227 	info.socket_id = id->pkg;
228 	info.power_domain_id = id->punit;
229 	info.level = config_index;
230 
231 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
232 	if (ret == -1)
233 		return ret;
234 
235 	ctdp_level->pkg_tdp = info.thermal_design_power_w;
236 	ctdp_level->tdp_ratio = info.tdp_ratio;
237 	ctdp_level->sse_p1 = info.base_freq_mhz;
238 	ctdp_level->avx2_p1 = info.base_freq_avx2_mhz;
239 	ctdp_level->avx512_p1 = info.base_freq_avx512_mhz;
240 	ctdp_level->amx_p1 = info.base_freq_amx_mhz;
241 
242 	ctdp_level->t_proc_hot = info.tjunction_max_c;
243 	ctdp_level->mem_freq = info.max_memory_freq_mhz;
244 	ctdp_level->cooling_type = info.cooling_type;
245 
246 	ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
247 	ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
248 	ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
249 
250 	debug_printf
251 	    ("cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO tdp_ratio:%d pkg_tdp:%d ctdp_level->t_proc_hot:%d\n",
252 	     id->cpu, config_index, ctdp_level->tdp_ratio, ctdp_level->pkg_tdp,
253 	     ctdp_level->t_proc_hot);
254 
255 	return 0;
256 }
257 
258 static int tpmi_get_pwr_info(struct isst_id *id, int config_index,
259 			     struct isst_pkg_ctdp_level_info *ctdp_level)
260 {
261 	/* TBD */
262 	ctdp_level->pkg_max_power = 0;
263 	ctdp_level->pkg_min_power = 0;
264 
265 	debug_printf
266 	    ("cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO pkg_max_power:%d pkg_min_power:%d\n",
267 	     id->cpu, config_index, ctdp_level->pkg_max_power,
268 	     ctdp_level->pkg_min_power);
269 
270 	return 0;
271 }
272 
273 int tpmi_get_coremask_info(struct isst_id *id, int config_index,
274 			   struct isst_pkg_ctdp_level_info *ctdp_level)
275 {
276 	struct isst_perf_level_cpu_mask info;
277 	int ret, cpu_count;
278 
279 	info.socket_id = id->pkg;
280 	info.power_domain_id = id->punit;
281 	info.level = config_index;
282 	info.punit_cpu_map = 1;
283 
284 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_CPU_MASK, &info);
285 	if (ret == -1)
286 		return ret;
287 
288 	set_cpu_mask_from_punit_coremask(id, info.mask,
289 					 ctdp_level->core_cpumask_size,
290 					 ctdp_level->core_cpumask, &cpu_count);
291 	ctdp_level->cpu_count = cpu_count;
292 
293 	debug_printf("cpu:%d ctdp:%d core_mask ino cpu count:%d\n",
294 		     id->cpu, config_index, ctdp_level->cpu_count);
295 
296 	return 0;
297 }
298 
299 static int tpmi_get_get_trls(struct isst_id *id, int config_index,
300 			     struct isst_pkg_ctdp_level_info *ctdp_level)
301 {
302 	struct isst_perf_level_data_info info;
303 	int ret, i, j;
304 
305 	info.socket_id = id->pkg;
306 	info.power_domain_id = id->punit;
307 	info.level = config_index;
308 
309 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
310 	if (ret == -1)
311 		return ret;
312 
313 	if (info.max_buckets > TRL_MAX_BUCKETS)
314 		info.max_buckets = TRL_MAX_BUCKETS;
315 
316 	if (info.max_trl_levels > TRL_MAX_LEVELS)
317 		info.max_trl_levels = TRL_MAX_LEVELS;
318 
319 	for (i = 0; i < info.max_trl_levels; ++i)
320 		for (j = 0; j < info.max_buckets; ++j)
321 			ctdp_level->trl_ratios[i][j] = info.trl_freq_mhz[i][j];
322 
323 	return 0;
324 }
325 
326 static int tpmi_get_get_trl(struct isst_id *id, int level, int config_index,
327 			    int *trl)
328 {
329 	struct isst_pkg_ctdp_level_info ctdp_level;
330 	int ret, i;
331 
332 	ret = tpmi_get_get_trls(id, config_index, &ctdp_level);
333 	if (ret)
334 		return ret;
335 
336 	/* FIX ME: Just return for level 0 */
337 	for (i = 0; i < 8; ++i)
338 		trl[i] = ctdp_level.trl_ratios[0][i];
339 
340 	return 0;
341 }
342 
343 static int tpmi_get_trl_bucket_info(struct isst_id *id, int config_index,
344 				    unsigned long long *buckets_info)
345 {
346 	struct isst_perf_level_data_info info;
347 	unsigned char *mask = (unsigned char *)buckets_info;
348 	int ret, i;
349 
350 	info.socket_id = id->pkg;
351 	info.power_domain_id = id->punit;
352 	info.level = config_index;
353 
354 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
355 	if (ret == -1)
356 		return ret;
357 
358 	if (info.max_buckets > TRL_MAX_BUCKETS)
359 		info.max_buckets = TRL_MAX_BUCKETS;
360 
361 	for (i = 0; i < info.max_buckets; ++i)
362 		mask[i] = info.bucket_core_counts[i];
363 
364 	debug_printf("cpu:%d TRL bucket info: 0x%llx\n", id->cpu,
365 		     *buckets_info);
366 
367 	return 0;
368 }
369 
370 static int tpmi_set_tdp_level(struct isst_id *id, int tdp_level)
371 {
372 	struct isst_perf_level_control info;
373 	int ret;
374 
375 	info.socket_id = id->pkg;
376 	info.power_domain_id = id->punit;
377 	info.level = tdp_level;
378 
379 	ret = tpmi_process_ioctl(ISST_IF_PERF_SET_LEVEL, &info);
380 	if (ret == -1)
381 		return ret;
382 
383 	return 0;
384 }
385 
386 static int _pbf_get_coremask_info(struct isst_id *id, int config_index,
387 				  struct isst_pbf_info *pbf_info)
388 {
389 	struct isst_perf_level_cpu_mask info;
390 	int ret, cpu_count;
391 
392 	info.socket_id = id->pkg;
393 	info.power_domain_id = id->punit;
394 	info.level = config_index;
395 	info.punit_cpu_map = 1;
396 
397 	ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_CPU_MASK, &info);
398 	if (ret == -1)
399 		return ret;
400 
401 	set_cpu_mask_from_punit_coremask(id, info.mask,
402 					 pbf_info->core_cpumask_size,
403 					 pbf_info->core_cpumask, &cpu_count);
404 
405 	debug_printf("cpu:%d ctdp:%d pbf core_mask info cpu count:%d\n",
406 		     id->cpu, config_index, cpu_count);
407 
408 	return 0;
409 }
410 
411 static int tpmi_get_pbf_info(struct isst_id *id, int level,
412 			     struct isst_pbf_info *pbf_info)
413 {
414 	struct isst_base_freq_info info;
415 	int ret;
416 
417 	info.socket_id = id->pkg;
418 	info.power_domain_id = id->punit;
419 	info.level = level;
420 
421 	ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_INFO, &info);
422 	if (ret == -1)
423 		return ret;
424 
425 	pbf_info->p1_low = info.low_base_freq_mhz;
426 	pbf_info->p1_high = info.high_base_freq_mhz;
427 	pbf_info->tdp = info.thermal_design_power_w;
428 	pbf_info->t_prochot = info.tjunction_max_c;
429 
430 	debug_printf("cpu:%d ctdp:%d pbf info:%d:%d:%d:%d\n",
431 		     id->cpu, level, pbf_info->p1_low, pbf_info->p1_high,
432 		     pbf_info->tdp, pbf_info->t_prochot);
433 
434 	return _pbf_get_coremask_info(id, level, pbf_info);
435 }
436 
437 static int tpmi_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
438 {
439 	struct isst_pkg_ctdp pkg_dev;
440 	struct isst_pkg_ctdp_level_info ctdp_level;
441 	int current_level;
442 	struct isst_perf_feature_control info;
443 	int ret;
444 
445 	ret = isst_get_ctdp_levels(id, &pkg_dev);
446 	if (ret)
447 		debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
448 
449 	current_level = pkg_dev.current_level;
450 
451 	ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
452 	if (ret)
453 		return ret;
454 
455 	info.socket_id = id->pkg;
456 	info.power_domain_id = id->punit;
457 
458 	info.feature = 0;
459 
460 	if (pbf) {
461 		if (ctdp_level.fact_enabled)
462 			info.feature |= BIT(1);
463 
464 		if (enable)
465 			info.feature |= BIT(0);
466 		else
467 			info.feature &= ~BIT(0);
468 	} else {
469 
470 		if (enable && !ctdp_level.sst_cp_enabled)
471 			isst_display_error_info_message(0,
472 							"Make sure to execute before: core-power enable",
473 							0, 0);
474 
475 		if (ctdp_level.pbf_enabled)
476 			info.feature |= BIT(0);
477 
478 		if (enable)
479 			info.feature |= BIT(1);
480 		else
481 			info.feature &= ~BIT(1);
482 	}
483 
484 	ret = tpmi_process_ioctl(ISST_IF_PERF_SET_FEATURE, &info);
485 	if (ret == -1)
486 		return ret;
487 
488 	return 0;
489 }
490 
491 static int tpmi_get_fact_info(struct isst_id *id, int level, int fact_bucket,
492 			      struct isst_fact_info *fact_info)
493 {
494 	struct isst_turbo_freq_info info;
495 	int i, j;
496 	int ret;
497 
498 	info.socket_id = id->pkg;
499 	info.power_domain_id = id->punit;
500 	info.level = level;
501 
502 	ret = tpmi_process_ioctl(ISST_IF_GET_TURBO_FREQ_INFO, &info);
503 	if (ret == -1)
504 		return ret;
505 
506 	for (i = 0; i < info.max_clip_freqs; ++i)
507 		fact_info->lp_ratios[i] = info.lp_clip_freq_mhz[i];
508 
509 	if (info.max_buckets > TRL_MAX_BUCKETS)
510 		info.max_buckets = TRL_MAX_BUCKETS;
511 
512 	if (info.max_trl_levels > TRL_MAX_LEVELS)
513 		info.max_trl_levels = TRL_MAX_LEVELS;
514 
515 	for (i = 0; i < info.max_trl_levels; ++i) {
516 		for (j = 0; j < info.max_buckets; ++j)
517 			fact_info->bucket_info[j].hp_ratios[i] =
518 			    info.trl_freq_mhz[i][j];
519 	}
520 
521 	for (i = 0; i < info.max_buckets; ++i)
522 		fact_info->bucket_info[i].hp_cores = info.bucket_core_counts[i];
523 
524 	return 0;
525 }
526 
527 static void _set_uncore_min_max(struct isst_id *id, int max, int freq)
528 {
529 	DIR *dir;
530 	FILE *filep;
531 	struct dirent *entry;
532 	char buffer[512];
533 	unsigned int tmp_id;
534 	int ret;
535 
536 	dir = opendir("/sys/devices/system/cpu/intel_uncore_frequency/");
537 	if (!dir)
538 		return;
539 
540 	while ((entry = readdir(dir)) != NULL ) {
541 		/* Check domain_id */
542 		snprintf(buffer, sizeof(buffer),
543 			 "/sys/devices/system/cpu/intel_uncore_frequency/%s/domain_id", entry->d_name);
544 
545 		filep = fopen(buffer, "r");
546 		if (!filep)
547 			goto end;
548 
549 		ret = fscanf(filep, "%u", &tmp_id);
550 		fclose(filep);
551 		if (ret != 1)
552 			goto end;
553 
554 		if (tmp_id != id->punit)
555 			continue;
556 
557 		/* Check package_id */
558 		snprintf(buffer, sizeof(buffer),
559 			 "/sys/devices/system/cpu/intel_uncore_frequency/%s/package_id", entry->d_name);
560 
561 		filep = fopen(buffer, "r");
562 		if (!filep)
563 			goto end;
564 
565 		ret = fscanf(filep, "%u", &tmp_id);
566 		fclose(filep);
567 
568 		if (ret != 1)
569 			goto end;
570 
571 		if (tmp_id != id->pkg)
572 			continue;
573 
574 		/* Found the right sysfs path, adjust and quit */
575 		if (max)
576 			snprintf(buffer, sizeof(buffer),
577 				 "/sys/devices/system/cpu/intel_uncore_frequency/%s/max_freq_khz", entry->d_name);
578 		 else
579 			snprintf(buffer, sizeof(buffer),
580 				 "/sys/devices/system/cpu/intel_uncore_frequency/%s/min_freq_khz", entry->d_name);
581 
582 		filep = fopen(buffer, "w");
583 		if (!filep)
584 			goto end;
585 
586 		fprintf(filep, "%d\n", freq);
587 		fclose(filep);
588 		break;
589 	}
590 
591 end:
592 	closedir(dir);
593 }
594 
595 static void tpmi_adjust_uncore_freq(struct isst_id *id, int config_index,
596 				struct isst_pkg_ctdp_level_info *ctdp_level)
597 {
598 	struct isst_perf_level_data_info info;
599 	int ret;
600 
601 	info.socket_id = id->pkg;
602 	info.power_domain_id = id->punit;
603 	info.level = config_index;
604 
605 	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
606 	if (ret == -1)
607 		return;
608 
609 	ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
610 	ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
611 	ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
612 
613 	if (ctdp_level->uncore_pm)
614 		_set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
615 
616 	if (ctdp_level->uncore_p0)
617 		_set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
618 
619 	return;
620 }
621 
622 static int tpmi_get_clos_information(struct isst_id *id, int *enable, int *type)
623 {
624 	struct isst_core_power info;
625 	int ret;
626 
627 	info.get_set = 0;
628 	info.socket_id = id->pkg;
629 	info.power_domain_id = id->punit;
630 	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
631 	if (ret == -1)
632 		return ret;
633 
634 	*enable = info.enable;
635 	*type = info.priority_type;
636 
637 	return 0;
638 }
639 
640 static int tpmi_pm_qos_config(struct isst_id *id, int enable_clos,
641 			      int priority_type)
642 {
643 	struct isst_core_power info;
644 	int ret;
645 
646 	info.get_set = 1;
647 	info.socket_id = id->pkg;
648 	info.power_domain_id = id->punit;
649 	info.enable = enable_clos;
650 	info.priority_type = priority_type;
651 	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
652 	if (ret == -1)
653 		return ret;
654 
655 	return 0;
656 }
657 
658 int tpmi_pm_get_clos(struct isst_id *id, int clos,
659 		     struct isst_clos_config *clos_config)
660 {
661 	struct isst_clos_param info;
662 	int ret;
663 
664 	info.get_set = 0;
665 	info.socket_id = id->pkg;
666 	info.power_domain_id = id->punit;
667 	info.clos = clos;
668 
669 	ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
670 	if (ret == -1)
671 		return ret;
672 
673 	clos_config->epp = 0;
674 	clos_config->clos_prop_prio = info.prop_prio;
675 	clos_config->clos_min = info.min_freq_mhz;
676 	clos_config->clos_max = info.max_freq_mhz;
677 	clos_config->clos_desired = 0;
678 
679 	debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
680 		     clos_config->clos_min, clos_config->clos_max);
681 
682 	return 0;
683 }
684 
685 int tpmi_set_clos(struct isst_id *id, int clos,
686 		  struct isst_clos_config *clos_config)
687 {
688 	struct isst_clos_param info;
689 	int ret;
690 
691 	info.get_set = 1;
692 	info.socket_id = id->pkg;
693 	info.power_domain_id = id->punit;
694 	info.clos = clos;
695 	info.prop_prio = clos_config->clos_prop_prio;
696 
697 	info.min_freq_mhz = clos_config->clos_min;
698 	info.max_freq_mhz = clos_config->clos_max;
699 
700 	if (info.min_freq_mhz <= 0xff)
701 		info.min_freq_mhz *= 100;
702 	if (info.max_freq_mhz <= 0xff)
703 		info.max_freq_mhz *= 100;
704 
705 	ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
706 	if (ret == -1)
707 		return ret;
708 
709 	debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
710 		     clos_config->clos_min, clos_config->clos_max);
711 
712 	return 0;
713 }
714 
715 static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id)
716 {
717 	struct isst_if_clos_assoc_cmds assoc_cmds;
718 	int ret;
719 
720 	assoc_cmds.cmd_count = 1;
721 	assoc_cmds.get_set = 0;
722 	assoc_cmds.punit_cpu_map = 1;
723 	assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
724 	assoc_cmds.assoc_info[0].socket_id = id->pkg;
725 	assoc_cmds.assoc_info[0].power_domain_id = id->punit;
726 
727 	ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
728 	if (ret == -1)
729 		return ret;
730 
731 	*clos_id = assoc_cmds.assoc_info[0].clos;
732 
733 	return 0;
734 }
735 
736 static int tpmi_clos_associate(struct isst_id *id, int clos_id)
737 {
738 	struct isst_if_clos_assoc_cmds assoc_cmds;
739 	int ret;
740 
741 	assoc_cmds.cmd_count = 1;
742 	assoc_cmds.get_set = 1;
743 	assoc_cmds.punit_cpu_map = 1;
744 	assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
745 	assoc_cmds.assoc_info[0].clos = clos_id;
746 	assoc_cmds.assoc_info[0].socket_id = id->pkg;
747 	assoc_cmds.assoc_info[0].power_domain_id = id->punit;
748 
749 	ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
750 	if (ret == -1)
751 		return ret;
752 
753 	return 0;
754 }
755 
756 static struct isst_platform_ops tpmi_ops = {
757 	.get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier,
758 	.get_trl_max_levels = tpmi_get_trl_max_levels,
759 	.get_trl_level_name = tpmi_get_trl_level_name,
760 	.update_platform_param = tpmi_update_platform_param,
761 	.is_punit_valid = tpmi_is_punit_valid,
762 	.read_pm_config = tpmi_read_pm_config,
763 	.get_config_levels = tpmi_get_config_levels,
764 	.get_ctdp_control = tpmi_get_ctdp_control,
765 	.get_tdp_info = tpmi_get_tdp_info,
766 	.get_pwr_info = tpmi_get_pwr_info,
767 	.get_coremask_info = tpmi_get_coremask_info,
768 	.get_get_trl = tpmi_get_get_trl,
769 	.get_get_trls = tpmi_get_get_trls,
770 	.get_trl_bucket_info = tpmi_get_trl_bucket_info,
771 	.set_tdp_level = tpmi_set_tdp_level,
772 	.get_pbf_info = tpmi_get_pbf_info,
773 	.set_pbf_fact_status = tpmi_set_pbf_fact_status,
774 	.get_fact_info = tpmi_get_fact_info,
775 	.adjust_uncore_freq = tpmi_adjust_uncore_freq,
776 	.get_clos_information = tpmi_get_clos_information,
777 	.pm_qos_config = tpmi_pm_qos_config,
778 	.pm_get_clos = tpmi_pm_get_clos,
779 	.set_clos = tpmi_set_clos,
780 	.clos_get_assoc_status = tpmi_clos_get_assoc_status,
781 	.clos_associate = tpmi_clos_associate,
782 };
783 
784 struct isst_platform_ops *tpmi_get_platform_ops(void)
785 {
786 	return &tpmi_ops;
787 }
788