133965Sjdp// SPDX-License-Identifier: GPL-2.0
2218822Sdim/*
378828Sobrien * Intel Speed Select -- Enumerate and control features for TPMI Interface
433965Sjdp * Copyright (c) 2022 Intel Corporation.
5130561Sobrien */
633965Sjdp
7130561Sobrien#include <linux/isst_if.h>
8130561Sobrien#include "isst.h"
9130561Sobrien
10130561Sobrienint tpmi_process_ioctl(int ioctl_no, void *info)
1133965Sjdp{
12130561Sobrien	const char *pathname = "/dev/isst_interface";
13130561Sobrien	int fd;
14130561Sobrien
15130561Sobrien	if (is_debug_enabled()) {
1633965Sjdp		debug_printf("Issue IOCTL: ");
17130561Sobrien		switch (ioctl_no) {
18130561Sobrien		case ISST_IF_CORE_POWER_STATE:
19218822Sdim			debug_printf("ISST_IF_CORE_POWER_STATE\n");
2033965Sjdp			break;
2160484Sobrien		case ISST_IF_CLOS_PARAM:
22130561Sobrien			debug_printf("ISST_IF_CLOS_PARAM\n");
2333965Sjdp			break;
2460484Sobrien		case ISST_IF_CLOS_ASSOC:
2533965Sjdp			debug_printf("ISST_IF_CLOS_ASSOC\n");
2633965Sjdp			break;
2733965Sjdp		case ISST_IF_PERF_LEVELS:
28130561Sobrien			debug_printf("ISST_IF_PERF_LEVELS\n");
2933965Sjdp			break;
3060484Sobrien		case ISST_IF_PERF_SET_LEVEL:
3133965Sjdp			debug_printf("ISST_IF_PERF_SET_LEVEL\n");
3233965Sjdp			break;
33130561Sobrien		case ISST_IF_PERF_SET_FEATURE:
34130561Sobrien			debug_printf("ISST_IF_PERF_SET_FEATURE\n");
3533965Sjdp			break;
3660484Sobrien		case ISST_IF_GET_PERF_LEVEL_INFO:
3733965Sjdp			debug_printf("ISST_IF_GET_PERF_LEVEL_INFO\n");
3877298Sobrien			break;
3933965Sjdp		case ISST_IF_GET_PERF_LEVEL_CPU_MASK:
4033965Sjdp			debug_printf("ISST_IF_GET_PERF_LEVEL_CPU_MASK\n");
4133965Sjdp			break;
4233965Sjdp		case ISST_IF_GET_BASE_FREQ_INFO:
43130561Sobrien			debug_printf("ISST_IF_GET_BASE_FREQ_INFO\n");
4433965Sjdp			break;
4533965Sjdp		case ISST_IF_GET_BASE_FREQ_CPU_MASK:
4677298Sobrien			debug_printf("ISST_IF_GET_BASE_FREQ_CPU_MASK\n");
4760484Sobrien			break;
4860484Sobrien		case ISST_IF_GET_TURBO_FREQ_INFO:
4933965Sjdp			debug_printf("ISST_IF_GET_TURBO_FREQ_INFO\n");
5060484Sobrien			break;
51130561Sobrien		case ISST_IF_COUNT_TPMI_INSTANCES:
5260484Sobrien			debug_printf("ISST_IF_COUNT_TPMI_INSTANCES\n");
5333965Sjdp			break;
54130561Sobrien		default:
55130561Sobrien			debug_printf("%d\n", ioctl_no);
5633965Sjdp			break;
5733965Sjdp		}
58130561Sobrien	}
5933965Sjdp
6033965Sjdp	fd = open(pathname, O_RDWR);
6133965Sjdp	if (fd < 0)
6233965Sjdp		return -1;
6333965Sjdp
6433965Sjdp	if (ioctl(fd, ioctl_no, info) == -1) {
6533965Sjdp		debug_printf("IOCTL %d Failed\n", ioctl_no);
6633965Sjdp		close(fd);
6733965Sjdp		return -1;
6833965Sjdp	}
6933965Sjdp
70130561Sobrien	close(fd);
7133965Sjdp
7233965Sjdp	return 0;
73130561Sobrien}
7433965Sjdp
75130561Sobrienstatic int tpmi_get_disp_freq_multiplier(void)
76130561Sobrien{
77130561Sobrien	return 1;
7833965Sjdp}
79130561Sobrien
8089857Sobrienstatic int tpmi_get_trl_max_levels(void)
8189857Sobrien{
8233965Sjdp	return TRL_MAX_LEVELS;
83130561Sobrien}
8489857Sobrien
8533965Sjdpstatic char *tpmi_get_trl_level_name(int level)
86130561Sobrien{
8733965Sjdp	switch (level) {
8833965Sjdp	case 0:
89130561Sobrien		return "level-0";
90130561Sobrien	case 1:
91130561Sobrien		return "level-1";
9233965Sjdp	case 2:
9333965Sjdp		return "level-2";
9477298Sobrien	case 3:
95104834Sobrien		return "level-3";
9677298Sobrien	case 4:
9733965Sjdp		return "level-4";
98130561Sobrien	case 5:
9933965Sjdp		return "level-5";
10077298Sobrien	case 6:
10160484Sobrien		return "level-6";
10260484Sobrien	case 7:
10333965Sjdp		return "level-7";
10477298Sobrien	default:
10533965Sjdp		return NULL;
10633965Sjdp	}
107130561Sobrien}
10833965Sjdp
10933965Sjdp
11033965Sjdpstatic void tpmi_update_platform_param(enum isst_platform_param param, int value)
111130561Sobrien{
11233965Sjdp	/* No params need to be updated for now */
11333965Sjdp}
11433965Sjdp
11560484Sobrienstatic int tpmi_is_punit_valid(struct isst_id *id)
11633965Sjdp{
11733965Sjdp	struct isst_tpmi_instance_count info;
11833965Sjdp	int ret;
119130561Sobrien
120130561Sobrien	if (id->punit < 0)
121130561Sobrien		return 0;
12277298Sobrien
123130561Sobrien	info.socket_id = id->pkg;
12489857Sobrien	ret = tpmi_process_ioctl(ISST_IF_COUNT_TPMI_INSTANCES, &info);
125130561Sobrien	if (ret == -1)
12689857Sobrien		return 0;
12777298Sobrien
12833965Sjdp	if (info.valid_mask & BIT(id->punit))
12933965Sjdp		return 1;
13060484Sobrien
13133965Sjdp	return 0;
13233965Sjdp}
13333965Sjdp
13433965Sjdpstatic int tpmi_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
13533965Sjdp{
13633965Sjdp	struct isst_core_power info;
13733965Sjdp	int ret;
13833965Sjdp
13960484Sobrien	info.get_set = 0;
14033965Sjdp	info.socket_id = id->pkg;
14160484Sobrien	info.power_domain_id = id->punit;
14260484Sobrien	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
14360484Sobrien	if (ret == -1)
14460484Sobrien		return ret;
14533965Sjdp
14633965Sjdp	*cp_state = info.enable;
14733965Sjdp	*cp_cap = info.supported;
14833965Sjdp
14933965Sjdp	return 0;
15033965Sjdp}
15133965Sjdp
15233965Sjdpint tpmi_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
15360484Sobrien{
15433965Sjdp	struct isst_perf_level_info info;
15533965Sjdp	int ret;
156130561Sobrien
15733965Sjdp	info.socket_id = id->pkg;
15833965Sjdp	info.power_domain_id = id->punit;
15933965Sjdp
160130561Sobrien	ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
161130561Sobrien	if (ret == -1)
162130561Sobrien		return ret;
163130561Sobrien
164130561Sobrien	pkg_dev->version = info.feature_rev;
165130561Sobrien	pkg_dev->levels = info.max_level;
16633965Sjdp	pkg_dev->locked = info.locked;
16733965Sjdp	pkg_dev->current_level = info.current_level;
16833965Sjdp	pkg_dev->locked = info.locked;
16933965Sjdp	pkg_dev->enabled = info.enabled;
17033965Sjdp
17133965Sjdp	return 0;
17233965Sjdp}
17333965Sjdp
17433965Sjdpstatic int tpmi_get_ctdp_control(struct isst_id *id, int config_index,
17577298Sobrien				 struct isst_pkg_ctdp_level_info *ctdp_level)
17633965Sjdp{
17733965Sjdp	struct isst_core_power core_power_info;
17833965Sjdp	struct isst_perf_level_info info;
17960484Sobrien	int level_mask;
18060484Sobrien	int ret;
18160484Sobrien
18260484Sobrien	info.socket_id = id->pkg;
18333965Sjdp	info.power_domain_id = id->punit;
18477298Sobrien
18589857Sobrien	ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
18677298Sobrien	if (ret == -1)
18777298Sobrien		return -1;
18877298Sobrien
18989857Sobrien	if (config_index != 0xff)
190130561Sobrien		level_mask = 1 << config_index;
19133965Sjdp	else
19277298Sobrien		level_mask = config_index;
19360484Sobrien
19460484Sobrien	if (!(info.level_mask & level_mask))
19560484Sobrien		return -1;
19677298Sobrien
19760484Sobrien	ctdp_level->fact_support = info.sst_tf_support;
19833965Sjdp	ctdp_level->pbf_support = info.sst_bf_support;
19960484Sobrien	ctdp_level->fact_enabled = !!(info.feature_state & BIT(1));
200130561Sobrien	ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0));
201130561Sobrien
20277298Sobrien	core_power_info.get_set = 0;
20360484Sobrien	core_power_info.socket_id = id->pkg;
20433965Sjdp	core_power_info.power_domain_id = id->punit;
20533965Sjdp
20633965Sjdp	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info);
20791041Sobrien	if (ret == -1)
20891041Sobrien		return ret;
20991041Sobrien
210218822Sdim	ctdp_level->sst_cp_support = core_power_info.supported;
21191041Sobrien	ctdp_level->sst_cp_enabled = core_power_info.enable;
212218822Sdim
213218822Sdim	debug_printf
21433965Sjdp	    ("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
215218822Sdim	     id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support,
216218822Sdim	     ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
217218822Sdim
218218822Sdim	return 0;
219218822Sdim}
220218822Sdim
221218822Sdimstatic int tpmi_get_tdp_info(struct isst_id *id, int config_index,
222218822Sdim			     struct isst_pkg_ctdp_level_info *ctdp_level)
223218822Sdim{
22491041Sobrien	struct isst_perf_level_data_info info;
22591041Sobrien	int ret;
226130561Sobrien
227130561Sobrien	info.socket_id = id->pkg;
22833965Sjdp	info.power_domain_id = id->punit;
22977298Sobrien	info.level = config_index;
23033965Sjdp
23133965Sjdp	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
232130561Sobrien	if (ret == -1)
23333965Sjdp		return ret;
23477298Sobrien
23577298Sobrien	ctdp_level->pkg_tdp = info.thermal_design_power_w;
23689857Sobrien	ctdp_level->tdp_ratio = info.tdp_ratio;
23789857Sobrien	ctdp_level->sse_p1 = info.base_freq_mhz;
23889857Sobrien	ctdp_level->avx2_p1 = info.base_freq_avx2_mhz;
23989857Sobrien	ctdp_level->avx512_p1 = info.base_freq_avx512_mhz;
24089857Sobrien	ctdp_level->amx_p1 = info.base_freq_amx_mhz;
24189857Sobrien
24289857Sobrien	ctdp_level->t_proc_hot = info.tjunction_max_c;
24389857Sobrien	ctdp_level->mem_freq = info.max_memory_freq_mhz;
24489857Sobrien	ctdp_level->cooling_type = info.cooling_type;
24577298Sobrien
24689857Sobrien	ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
24777298Sobrien	ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
248130561Sobrien	ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
249130561Sobrien
25077298Sobrien	debug_printf
25133965Sjdp	    ("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
258static 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
273int 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
299static 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
326static 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
343static 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
370static 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
386static 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
411static 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
437static 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
491static 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
527static 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
591end:
592	closedir(dir);
593}
594
595static 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
622static 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
640static 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 i, ret, saved_punit;
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
652	saved_punit = id->punit;
653
654	/* Set for all other dies also. This is per package setting */
655	for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
656		id->punit = i;
657		if (isst_is_punit_valid(id)) {
658			info.power_domain_id = i;
659			ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
660			if (ret == -1) {
661				id->punit = saved_punit;
662				return ret;
663			}
664		}
665	}
666
667	id->punit = saved_punit;
668
669	return 0;
670}
671
672int tpmi_pm_get_clos(struct isst_id *id, int clos,
673		     struct isst_clos_config *clos_config)
674{
675	struct isst_clos_param info;
676	int ret;
677
678	info.get_set = 0;
679	info.socket_id = id->pkg;
680	info.power_domain_id = id->punit;
681	info.clos = clos;
682
683	ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
684	if (ret == -1)
685		return ret;
686
687	clos_config->epp = 0;
688	clos_config->clos_prop_prio = info.prop_prio;
689	clos_config->clos_min = info.min_freq_mhz;
690	clos_config->clos_max = info.max_freq_mhz;
691	clos_config->clos_desired = 0;
692
693	debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
694		     clos_config->clos_min, clos_config->clos_max);
695
696	return 0;
697}
698
699int tpmi_set_clos(struct isst_id *id, int clos,
700		  struct isst_clos_config *clos_config)
701{
702	struct isst_clos_param info;
703	int i, ret, saved_punit;
704
705	info.get_set = 1;
706	info.socket_id = id->pkg;
707	info.power_domain_id = id->punit;
708	info.clos = clos;
709	info.prop_prio = clos_config->clos_prop_prio;
710
711	info.min_freq_mhz = clos_config->clos_min;
712	info.max_freq_mhz = clos_config->clos_max;
713
714	if (info.min_freq_mhz <= 0xff)
715		info.min_freq_mhz *= 100;
716	if (info.max_freq_mhz <= 0xff)
717		info.max_freq_mhz *= 100;
718
719	saved_punit = id->punit;
720
721	/* Set for all other dies also. This is per package setting */
722	for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
723		id->punit = i;
724		if (isst_is_punit_valid(id)) {
725			info.power_domain_id = i;
726			ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
727			if (ret == -1) {
728				id->punit = saved_punit;
729				return ret;
730			}
731		}
732	}
733
734	id->punit = saved_punit;
735
736	debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
737		     clos_config->clos_min, clos_config->clos_max);
738
739	return 0;
740}
741
742static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id)
743{
744	struct isst_if_clos_assoc_cmds assoc_cmds;
745	int ret;
746
747	assoc_cmds.cmd_count = 1;
748	assoc_cmds.get_set = 0;
749	assoc_cmds.punit_cpu_map = 1;
750	assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
751	assoc_cmds.assoc_info[0].socket_id = id->pkg;
752	assoc_cmds.assoc_info[0].power_domain_id = id->punit;
753
754	ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
755	if (ret == -1)
756		return ret;
757
758	*clos_id = assoc_cmds.assoc_info[0].clos;
759
760	return 0;
761}
762
763static int tpmi_clos_associate(struct isst_id *id, int clos_id)
764{
765	struct isst_if_clos_assoc_cmds assoc_cmds;
766	int ret;
767
768	assoc_cmds.cmd_count = 1;
769	assoc_cmds.get_set = 1;
770	assoc_cmds.punit_cpu_map = 1;
771	assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
772	assoc_cmds.assoc_info[0].clos = clos_id;
773	assoc_cmds.assoc_info[0].socket_id = id->pkg;
774	assoc_cmds.assoc_info[0].power_domain_id = id->punit;
775
776	ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
777	if (ret == -1)
778		return ret;
779
780	return 0;
781}
782
783static struct isst_platform_ops tpmi_ops = {
784	.get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier,
785	.get_trl_max_levels = tpmi_get_trl_max_levels,
786	.get_trl_level_name = tpmi_get_trl_level_name,
787	.update_platform_param = tpmi_update_platform_param,
788	.is_punit_valid = tpmi_is_punit_valid,
789	.read_pm_config = tpmi_read_pm_config,
790	.get_config_levels = tpmi_get_config_levels,
791	.get_ctdp_control = tpmi_get_ctdp_control,
792	.get_tdp_info = tpmi_get_tdp_info,
793	.get_pwr_info = tpmi_get_pwr_info,
794	.get_coremask_info = tpmi_get_coremask_info,
795	.get_get_trl = tpmi_get_get_trl,
796	.get_get_trls = tpmi_get_get_trls,
797	.get_trl_bucket_info = tpmi_get_trl_bucket_info,
798	.set_tdp_level = tpmi_set_tdp_level,
799	.get_pbf_info = tpmi_get_pbf_info,
800	.set_pbf_fact_status = tpmi_set_pbf_fact_status,
801	.get_fact_info = tpmi_get_fact_info,
802	.adjust_uncore_freq = tpmi_adjust_uncore_freq,
803	.get_clos_information = tpmi_get_clos_information,
804	.pm_qos_config = tpmi_pm_qos_config,
805	.pm_get_clos = tpmi_pm_get_clos,
806	.set_clos = tpmi_set_clos,
807	.clos_get_assoc_status = tpmi_clos_get_assoc_status,
808	.clos_associate = tpmi_clos_associate,
809};
810
811struct isst_platform_ops *tpmi_get_platform_ops(void)
812{
813	return &tpmi_ops;
814}
815