xref: /openbmc/linux/tools/power/x86/intel-speed-select/isst-core.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
13fb4f7cdSSrinivas Pandruvada // SPDX-License-Identifier: GPL-2.0
23fb4f7cdSSrinivas Pandruvada /*
33fb4f7cdSSrinivas Pandruvada  * Intel Speed Select -- Enumerate and control features
43fb4f7cdSSrinivas Pandruvada  * Copyright (c) 2019 Intel Corporation.
53fb4f7cdSSrinivas Pandruvada  */
63fb4f7cdSSrinivas Pandruvada 
73fb4f7cdSSrinivas Pandruvada #include "isst.h"
83fb4f7cdSSrinivas Pandruvada 
9d0d1a603SZhang Rui static struct isst_platform_ops		*isst_ops;
10d0d1a603SZhang Rui 
11d0d1a603SZhang Rui #define CHECK_CB(_name)	\
12d0d1a603SZhang Rui 	do {	\
13d0d1a603SZhang Rui 		if (!isst_ops || !isst_ops->_name) {	\
14d0d1a603SZhang Rui 			fprintf(stderr, "Invalid ops\n");	\
15d0d1a603SZhang Rui 			exit(0);	\
16d0d1a603SZhang Rui 		}	\
17d0d1a603SZhang Rui 	} while (0)
18d0d1a603SZhang Rui 
isst_set_platform_ops(int api_version)1905aab5b8SZhang Rui int isst_set_platform_ops(int api_version)
20d0d1a603SZhang Rui {
2105aab5b8SZhang Rui 	switch (api_version) {
2205aab5b8SZhang Rui 	case 1:
23d0d1a603SZhang Rui 		isst_ops = mbox_get_platform_ops();
2405aab5b8SZhang Rui 		break;
2579554aaaSZhang Rui 	case 2:
2679554aaaSZhang Rui 		isst_ops = tpmi_get_platform_ops();
2779554aaaSZhang Rui 		break;
2805aab5b8SZhang Rui 	default:
2905aab5b8SZhang Rui 		isst_ops = NULL;
3005aab5b8SZhang Rui 		break;
3105aab5b8SZhang Rui 	}
32d0d1a603SZhang Rui 
33d0d1a603SZhang Rui 	if (!isst_ops)
34d0d1a603SZhang Rui 		return -1;
35d0d1a603SZhang Rui 	return 0;
36d0d1a603SZhang Rui }
37d0d1a603SZhang Rui 
isst_update_platform_param(enum isst_platform_param param,int value)382042c0abSZhang Rui void isst_update_platform_param(enum isst_platform_param param, int value)
392042c0abSZhang Rui {
402b86ed22SZhang Rui 	CHECK_CB(update_platform_param);
412b86ed22SZhang Rui 
422b86ed22SZhang Rui 	isst_ops->update_platform_param(param, value);
432042c0abSZhang Rui }
442042c0abSZhang Rui 
isst_get_disp_freq_multiplier(void)4513b868f8SZhang Rui int isst_get_disp_freq_multiplier(void)
4613b868f8SZhang Rui {
47d0d1a603SZhang Rui 	CHECK_CB(get_disp_freq_multiplier);
48d0d1a603SZhang Rui 	return isst_ops->get_disp_freq_multiplier();
4913b868f8SZhang Rui }
5013b868f8SZhang Rui 
isst_get_trl_max_levels(void)517c7e7c0dSZhang Rui int isst_get_trl_max_levels(void)
527c7e7c0dSZhang Rui {
53d0d1a603SZhang Rui 	CHECK_CB(get_trl_max_levels);
54d0d1a603SZhang Rui 	return isst_ops->get_trl_max_levels();
557c7e7c0dSZhang Rui }
567c7e7c0dSZhang Rui 
isst_get_trl_level_name(int level)577c7e7c0dSZhang Rui char *isst_get_trl_level_name(int level)
587c7e7c0dSZhang Rui {
59d0d1a603SZhang Rui 	CHECK_CB(get_trl_level_name);
60d0d1a603SZhang Rui 	return isst_ops->get_trl_level_name(level);
617c7e7c0dSZhang Rui }
627c7e7c0dSZhang Rui 
isst_is_punit_valid(struct isst_id * id)6357ef2436SZhang Rui int isst_is_punit_valid(struct isst_id *id)
6457ef2436SZhang Rui {
65143584e8SZhang Rui 	CHECK_CB(is_punit_valid);
66143584e8SZhang Rui 	return isst_ops->is_punit_valid(id);
6757ef2436SZhang Rui }
6857ef2436SZhang Rui 
isst_send_msr_command(unsigned int cpu,unsigned int msr,int write,unsigned long long * req_resp)692042c0abSZhang Rui int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
702042c0abSZhang Rui 			  unsigned long long *req_resp)
712042c0abSZhang Rui {
722042c0abSZhang Rui 	struct isst_if_msr_cmds msr_cmds;
732042c0abSZhang Rui 	const char *pathname = "/dev/isst_interface";
742042c0abSZhang Rui 	FILE *outf = get_output_file();
752042c0abSZhang Rui 	int fd;
762042c0abSZhang Rui 
772042c0abSZhang Rui 	fd = open(pathname, O_RDWR);
782042c0abSZhang Rui 	if (fd < 0)
792042c0abSZhang Rui 		err(-1, "%s open failed", pathname);
802042c0abSZhang Rui 
812042c0abSZhang Rui 	msr_cmds.cmd_count = 1;
822042c0abSZhang Rui 	msr_cmds.msr_cmd[0].logical_cpu = cpu;
832042c0abSZhang Rui 	msr_cmds.msr_cmd[0].msr = msr;
842042c0abSZhang Rui 	msr_cmds.msr_cmd[0].read_write = write;
852042c0abSZhang Rui 	if (write)
862042c0abSZhang Rui 		msr_cmds.msr_cmd[0].data = *req_resp;
872042c0abSZhang Rui 
882042c0abSZhang Rui 	if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
892042c0abSZhang Rui 		perror("ISST_IF_MSR_COMMAND");
902042c0abSZhang Rui 		fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
912042c0abSZhang Rui 			cpu, msr, write);
922042c0abSZhang Rui 	} else {
932042c0abSZhang Rui 		if (!write)
942042c0abSZhang Rui 			*req_resp = msr_cmds.msr_cmd[0].data;
952042c0abSZhang Rui 
962042c0abSZhang Rui 		debug_printf(
972042c0abSZhang Rui 			"msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
982042c0abSZhang Rui 			cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
992042c0abSZhang Rui 	}
1002042c0abSZhang Rui 
1012042c0abSZhang Rui 	close(fd);
1022042c0abSZhang Rui 
1032042c0abSZhang Rui 	return 0;
1042042c0abSZhang Rui }
1052042c0abSZhang Rui 
isst_read_pm_config(struct isst_id * id,int * cp_state,int * cp_cap)106850337ecSZhang Rui int isst_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
107645feeb2SSrinivas Pandruvada {
1088f54104fSZhang Rui 	CHECK_CB(read_pm_config);
1098f54104fSZhang Rui 	return isst_ops->read_pm_config(id, cp_state, cp_cap);
110645feeb2SSrinivas Pandruvada }
111645feeb2SSrinivas Pandruvada 
isst_get_ctdp_levels(struct isst_id * id,struct isst_pkg_ctdp * pkg_dev)112850337ecSZhang Rui int isst_get_ctdp_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
1133fb4f7cdSSrinivas Pandruvada {
11472438744SZhang Rui 	CHECK_CB(get_config_levels);
11572438744SZhang Rui 	return isst_ops->get_config_levels(id, pkg_dev);
1163fb4f7cdSSrinivas Pandruvada }
1173fb4f7cdSSrinivas Pandruvada 
isst_get_ctdp_control(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)118850337ecSZhang Rui int isst_get_ctdp_control(struct isst_id *id, int config_index,
1193fb4f7cdSSrinivas Pandruvada 			  struct isst_pkg_ctdp_level_info *ctdp_level)
1203fb4f7cdSSrinivas Pandruvada {
121bbe32d87SZhang Rui 	CHECK_CB(get_ctdp_control);
122bbe32d87SZhang Rui 	return isst_ops->get_ctdp_control(id, config_index, ctdp_level);
1233fb4f7cdSSrinivas Pandruvada }
1243fb4f7cdSSrinivas Pandruvada 
isst_get_tdp_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)125850337ecSZhang Rui int isst_get_tdp_info(struct isst_id *id, int config_index,
1263fb4f7cdSSrinivas Pandruvada 		      struct isst_pkg_ctdp_level_info *ctdp_level)
1273fb4f7cdSSrinivas Pandruvada {
128645b6605SZhang Rui 	CHECK_CB(get_tdp_info);
129645b6605SZhang Rui 	return isst_ops->get_tdp_info(id, config_index, ctdp_level);
1303fb4f7cdSSrinivas Pandruvada }
1313fb4f7cdSSrinivas Pandruvada 
isst_get_pwr_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)132850337ecSZhang Rui int isst_get_pwr_info(struct isst_id *id, int config_index,
1333fb4f7cdSSrinivas Pandruvada 		      struct isst_pkg_ctdp_level_info *ctdp_level)
1343fb4f7cdSSrinivas Pandruvada {
135e107dec9SZhang Rui 	CHECK_CB(get_pwr_info);
136e107dec9SZhang Rui 	return isst_ops->get_pwr_info(id, config_index, ctdp_level);
1373fb4f7cdSSrinivas Pandruvada }
1383fb4f7cdSSrinivas Pandruvada 
isst_get_coremask_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)139850337ecSZhang Rui int isst_get_coremask_info(struct isst_id *id, int config_index,
1403fb4f7cdSSrinivas Pandruvada 			   struct isst_pkg_ctdp_level_info *ctdp_level)
1413fb4f7cdSSrinivas Pandruvada {
142668cc16cSZhang Rui 	CHECK_CB(get_coremask_info);
143668cc16cSZhang Rui 	return isst_ops->get_coremask_info(id, config_index, ctdp_level);
1443fb4f7cdSSrinivas Pandruvada }
1453fb4f7cdSSrinivas Pandruvada 
isst_get_get_trl_from_msr(struct isst_id * id,int * trl)146850337ecSZhang Rui int isst_get_get_trl_from_msr(struct isst_id *id, int *trl)
1477af5a95bSSrinivas Pandruvada {
1487af5a95bSSrinivas Pandruvada 	unsigned long long msr_trl;
1497af5a95bSSrinivas Pandruvada 	int ret;
1507af5a95bSSrinivas Pandruvada 
151850337ecSZhang Rui 	ret = isst_send_msr_command(id->cpu, 0x1AD, 0, &msr_trl);
1527af5a95bSSrinivas Pandruvada 	if (ret)
1537af5a95bSSrinivas Pandruvada 		return ret;
1547af5a95bSSrinivas Pandruvada 
1557af5a95bSSrinivas Pandruvada 	trl[0] = msr_trl & GENMASK(7, 0);
1567af5a95bSSrinivas Pandruvada 	trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
1577af5a95bSSrinivas Pandruvada 	trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
1587af5a95bSSrinivas Pandruvada 	trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
1597af5a95bSSrinivas Pandruvada 	trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
1607af5a95bSSrinivas Pandruvada 	trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
1617af5a95bSSrinivas Pandruvada 	trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
1627af5a95bSSrinivas Pandruvada 	trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
1637af5a95bSSrinivas Pandruvada 
1647af5a95bSSrinivas Pandruvada 	return 0;
1657af5a95bSSrinivas Pandruvada }
1667af5a95bSSrinivas Pandruvada 
isst_get_get_trl(struct isst_id * id,int level,int avx_level,int * trl)167850337ecSZhang Rui int isst_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
1683fb4f7cdSSrinivas Pandruvada {
16939f768c3SZhang Rui 	CHECK_CB(get_get_trl);
17039f768c3SZhang Rui 	return isst_ops->get_get_trl(id, level, avx_level, trl);
1713fb4f7cdSSrinivas Pandruvada }
1723fb4f7cdSSrinivas Pandruvada 
isst_get_get_trls(struct isst_id * id,int level,struct isst_pkg_ctdp_level_info * ctdp_level)1734a17b291SZhang Rui int isst_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
1744a17b291SZhang Rui {
1754a17b291SZhang Rui 	CHECK_CB(get_get_trls);
1764a17b291SZhang Rui 	return isst_ops->get_get_trls(id, level, ctdp_level);
1774a17b291SZhang Rui }
1784a17b291SZhang Rui 
isst_get_trl_bucket_info(struct isst_id * id,int level,unsigned long long * buckets_info)1791e37f1b2SZhang Rui int isst_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
1801233c7b9SSrinivas Pandruvada {
1811e37f1b2SZhang Rui 	CHECK_CB(get_trl_bucket_info);
1821e37f1b2SZhang Rui 	return isst_ops->get_trl_bucket_info(id, level, buckets_info);
1831233c7b9SSrinivas Pandruvada }
1841233c7b9SSrinivas Pandruvada 
isst_set_tdp_level(struct isst_id * id,int tdp_level)185850337ecSZhang Rui int isst_set_tdp_level(struct isst_id *id, int tdp_level)
1863fb4f7cdSSrinivas Pandruvada {
187f88c3c4bSZhang Rui 	CHECK_CB(set_tdp_level);
188f88c3c4bSZhang Rui 	return isst_ops->set_tdp_level(id, tdp_level);
1893fb4f7cdSSrinivas Pandruvada }
1903fb4f7cdSSrinivas Pandruvada 
isst_get_pbf_info(struct isst_id * id,int level,struct isst_pbf_info * pbf_info)191850337ecSZhang Rui int isst_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
1923fb4f7cdSSrinivas Pandruvada {
1936c8edba3SSrinivas Pandruvada 	struct isst_pkg_ctdp_level_info ctdp_level;
19439bae0fcSSrinivas Pandruvada 	struct isst_pkg_ctdp pkg_dev;
1957a196290SZhang Rui 	int ret;
1963fb4f7cdSSrinivas Pandruvada 
197850337ecSZhang Rui 	ret = isst_get_ctdp_levels(id, &pkg_dev);
19839bae0fcSSrinivas Pandruvada 	if (ret) {
19939bae0fcSSrinivas Pandruvada 		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
20039bae0fcSSrinivas Pandruvada 		return ret;
20139bae0fcSSrinivas Pandruvada 	}
20239bae0fcSSrinivas Pandruvada 
20339bae0fcSSrinivas Pandruvada 	if (level > pkg_dev.levels) {
20439bae0fcSSrinivas Pandruvada 		isst_display_error_info_message(1, "Invalid level", 1, level);
20539bae0fcSSrinivas Pandruvada 		return -1;
20639bae0fcSSrinivas Pandruvada 	}
20739bae0fcSSrinivas Pandruvada 
208850337ecSZhang Rui 	ret = isst_get_ctdp_control(id, level, &ctdp_level);
2096c8edba3SSrinivas Pandruvada 	if (ret)
2106c8edba3SSrinivas Pandruvada 		return ret;
2116c8edba3SSrinivas Pandruvada 
2126c8edba3SSrinivas Pandruvada 	if (!ctdp_level.pbf_support) {
21339bae0fcSSrinivas Pandruvada 		isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level);
2146c8edba3SSrinivas Pandruvada 		return -1;
2156c8edba3SSrinivas Pandruvada 	}
2166c8edba3SSrinivas Pandruvada 
2173fb4f7cdSSrinivas Pandruvada 	pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
2183fb4f7cdSSrinivas Pandruvada 
2197a196290SZhang Rui 	CHECK_CB(get_pbf_info);
2207a196290SZhang Rui 	return isst_ops->get_pbf_info(id, level, pbf_info);
2213fb4f7cdSSrinivas Pandruvada }
2223fb4f7cdSSrinivas Pandruvada 
isst_set_pbf_fact_status(struct isst_id * id,int pbf,int enable)223850337ecSZhang Rui int isst_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
2243fb4f7cdSSrinivas Pandruvada {
2255843f217SZhang Rui 	CHECK_CB(set_pbf_fact_status);
2265843f217SZhang Rui 	return isst_ops->set_pbf_fact_status(id, pbf, enable);
2273fb4f7cdSSrinivas Pandruvada }
2283fb4f7cdSSrinivas Pandruvada 
2293fb4f7cdSSrinivas Pandruvada 
2303fb4f7cdSSrinivas Pandruvada 
isst_get_fact_info(struct isst_id * id,int level,int fact_bucket,struct isst_fact_info * fact_info)231850337ecSZhang Rui int isst_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
2323fb4f7cdSSrinivas Pandruvada {
2336c8edba3SSrinivas Pandruvada 	struct isst_pkg_ctdp_level_info ctdp_level;
234a9fd6ae7SSrinivas Pandruvada 	struct isst_pkg_ctdp pkg_dev;
2357b5f586dSZhang Rui 	int ret;
236a9fd6ae7SSrinivas Pandruvada 
237850337ecSZhang Rui 	ret = isst_get_ctdp_levels(id, &pkg_dev);
238a9fd6ae7SSrinivas Pandruvada 	if (ret) {
239a9fd6ae7SSrinivas Pandruvada 		isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
240a9fd6ae7SSrinivas Pandruvada 		return ret;
241a9fd6ae7SSrinivas Pandruvada 	}
242a9fd6ae7SSrinivas Pandruvada 
243a9fd6ae7SSrinivas Pandruvada 	if (level > pkg_dev.levels) {
244a9fd6ae7SSrinivas Pandruvada 		isst_display_error_info_message(1, "Invalid level", 1, level);
245a9fd6ae7SSrinivas Pandruvada 		return -1;
246a9fd6ae7SSrinivas Pandruvada 	}
2473fb4f7cdSSrinivas Pandruvada 
248850337ecSZhang Rui 	ret = isst_get_ctdp_control(id, level, &ctdp_level);
2496c8edba3SSrinivas Pandruvada 	if (ret)
2506c8edba3SSrinivas Pandruvada 		return ret;
2516c8edba3SSrinivas Pandruvada 
2526c8edba3SSrinivas Pandruvada 	if (!ctdp_level.fact_support) {
253a9fd6ae7SSrinivas Pandruvada 		isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
2546c8edba3SSrinivas Pandruvada 		return -1;
2556c8edba3SSrinivas Pandruvada 	}
2567b5f586dSZhang Rui 	CHECK_CB(get_fact_info);
2577b5f586dSZhang Rui 	return isst_ops->get_fact_info(id, level, fact_bucket, fact_info);
2583fb4f7cdSSrinivas Pandruvada }
2593fb4f7cdSSrinivas Pandruvada 
isst_get_trl(struct isst_id * id,unsigned long long * trl)260850337ecSZhang Rui int isst_get_trl(struct isst_id *id, unsigned long long *trl)
2612c7dc57eSSrinivas Pandruvada {
2622c7dc57eSSrinivas Pandruvada 	int ret;
2632c7dc57eSSrinivas Pandruvada 
264850337ecSZhang Rui 	ret = isst_send_msr_command(id->cpu, 0x1AD, 0, trl);
2652c7dc57eSSrinivas Pandruvada 	if (ret)
2662c7dc57eSSrinivas Pandruvada 		return ret;
2672c7dc57eSSrinivas Pandruvada 
2682c7dc57eSSrinivas Pandruvada 	return 0;
2692c7dc57eSSrinivas Pandruvada }
2702c7dc57eSSrinivas Pandruvada 
isst_set_trl(struct isst_id * id,unsigned long long trl)271850337ecSZhang Rui int isst_set_trl(struct isst_id *id, unsigned long long trl)
2723fb4f7cdSSrinivas Pandruvada {
2733fb4f7cdSSrinivas Pandruvada 	int ret;
2743fb4f7cdSSrinivas Pandruvada 
2753fb4f7cdSSrinivas Pandruvada 	if (!trl)
2763fb4f7cdSSrinivas Pandruvada 		trl = 0xFFFFFFFFFFFFFFFFULL;
2773fb4f7cdSSrinivas Pandruvada 
278850337ecSZhang Rui 	ret = isst_send_msr_command(id->cpu, 0x1AD, 1, &trl);
2793fb4f7cdSSrinivas Pandruvada 	if (ret)
2803fb4f7cdSSrinivas Pandruvada 		return ret;
2813fb4f7cdSSrinivas Pandruvada 
2823fb4f7cdSSrinivas Pandruvada 	return 0;
2833fb4f7cdSSrinivas Pandruvada }
2843fb4f7cdSSrinivas Pandruvada 
isst_set_trl_from_current_tdp(struct isst_id * id,unsigned long long trl)285850337ecSZhang Rui int isst_set_trl_from_current_tdp(struct isst_id *id, unsigned long long trl)
2863fb4f7cdSSrinivas Pandruvada {
2873fb4f7cdSSrinivas Pandruvada 	unsigned long long msr_trl;
2883fb4f7cdSSrinivas Pandruvada 	int ret;
2893fb4f7cdSSrinivas Pandruvada 
290*d0e12c46SZhang Rui 	if (id->cpu < 0)
291*d0e12c46SZhang Rui 		return 0;
292*d0e12c46SZhang Rui 
2933fb4f7cdSSrinivas Pandruvada 	if (trl) {
2943fb4f7cdSSrinivas Pandruvada 		msr_trl = trl;
2953fb4f7cdSSrinivas Pandruvada 	} else {
2963fb4f7cdSSrinivas Pandruvada 		struct isst_pkg_ctdp pkg_dev;
2973fb4f7cdSSrinivas Pandruvada 		int trl[8];
2983fb4f7cdSSrinivas Pandruvada 		int i;
2993fb4f7cdSSrinivas Pandruvada 
300850337ecSZhang Rui 		ret = isst_get_ctdp_levels(id, &pkg_dev);
3013fb4f7cdSSrinivas Pandruvada 		if (ret)
3023fb4f7cdSSrinivas Pandruvada 			return ret;
3033fb4f7cdSSrinivas Pandruvada 
304850337ecSZhang Rui 		ret = isst_get_get_trl(id, pkg_dev.current_level, 0, trl);
3053fb4f7cdSSrinivas Pandruvada 		if (ret)
3063fb4f7cdSSrinivas Pandruvada 			return ret;
3073fb4f7cdSSrinivas Pandruvada 
3083fb4f7cdSSrinivas Pandruvada 		msr_trl = 0;
3093fb4f7cdSSrinivas Pandruvada 		for (i = 0; i < 8; ++i) {
3103fb4f7cdSSrinivas Pandruvada 			unsigned long long _trl = trl[i];
3113fb4f7cdSSrinivas Pandruvada 
3123fb4f7cdSSrinivas Pandruvada 			msr_trl |= (_trl << (i * 8));
3133fb4f7cdSSrinivas Pandruvada 		}
3143fb4f7cdSSrinivas Pandruvada 	}
315850337ecSZhang Rui 	ret = isst_send_msr_command(id->cpu, 0x1AD, 1, &msr_trl);
3163fb4f7cdSSrinivas Pandruvada 	if (ret)
3173fb4f7cdSSrinivas Pandruvada 		return ret;
3183fb4f7cdSSrinivas Pandruvada 
3193fb4f7cdSSrinivas Pandruvada 	return 0;
3203fb4f7cdSSrinivas Pandruvada }
3213fb4f7cdSSrinivas Pandruvada 
3223fb4f7cdSSrinivas Pandruvada /* Return 1 if locked */
isst_get_config_tdp_lock_status(struct isst_id * id)323850337ecSZhang Rui int isst_get_config_tdp_lock_status(struct isst_id *id)
3243fb4f7cdSSrinivas Pandruvada {
3253fb4f7cdSSrinivas Pandruvada 	unsigned long long tdp_control = 0;
3263fb4f7cdSSrinivas Pandruvada 	int ret;
3273fb4f7cdSSrinivas Pandruvada 
328850337ecSZhang Rui 	ret = isst_send_msr_command(id->cpu, 0x64b, 0, &tdp_control);
3293fb4f7cdSSrinivas Pandruvada 	if (ret)
3303fb4f7cdSSrinivas Pandruvada 		return ret;
3313fb4f7cdSSrinivas Pandruvada 
3323fb4f7cdSSrinivas Pandruvada 	ret = !!(tdp_control & BIT(31));
3333fb4f7cdSSrinivas Pandruvada 
3343fb4f7cdSSrinivas Pandruvada 	return ret;
3353fb4f7cdSSrinivas Pandruvada }
3363fb4f7cdSSrinivas Pandruvada 
isst_get_process_ctdp_complete(struct isst_id * id,struct isst_pkg_ctdp * pkg_dev)337850337ecSZhang Rui void isst_get_process_ctdp_complete(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
3383fb4f7cdSSrinivas Pandruvada {
3393fb4f7cdSSrinivas Pandruvada 	int i;
3403fb4f7cdSSrinivas Pandruvada 
3413fb4f7cdSSrinivas Pandruvada 	if (!pkg_dev->processed)
3423fb4f7cdSSrinivas Pandruvada 		return;
3433fb4f7cdSSrinivas Pandruvada 
3443fb4f7cdSSrinivas Pandruvada 	for (i = 0; i < pkg_dev->levels; ++i) {
3453fb4f7cdSSrinivas Pandruvada 		struct isst_pkg_ctdp_level_info *ctdp_level;
3463fb4f7cdSSrinivas Pandruvada 
3473fb4f7cdSSrinivas Pandruvada 		ctdp_level = &pkg_dev->ctdp_level[i];
3483fb4f7cdSSrinivas Pandruvada 		if (ctdp_level->pbf_support)
3493fb4f7cdSSrinivas Pandruvada 			free_cpu_set(ctdp_level->pbf_info.core_cpumask);
3503fb4f7cdSSrinivas Pandruvada 		free_cpu_set(ctdp_level->core_cpumask);
3513fb4f7cdSSrinivas Pandruvada 	}
3523fb4f7cdSSrinivas Pandruvada }
3533fb4f7cdSSrinivas Pandruvada 
isst_adjust_uncore_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)35473452cccSZhang Rui void isst_adjust_uncore_freq(struct isst_id *id, int config_index,
355e4cbd0f1SZhang Rui 				struct isst_pkg_ctdp_level_info *ctdp_level)
356e4cbd0f1SZhang Rui {
35773452cccSZhang Rui 	CHECK_CB(adjust_uncore_freq);
35873452cccSZhang Rui 	return isst_ops->adjust_uncore_freq(id, config_index, ctdp_level);
359e4cbd0f1SZhang Rui }
360e4cbd0f1SZhang Rui 
isst_get_process_ctdp(struct isst_id * id,int tdp_level,struct isst_pkg_ctdp * pkg_dev)361850337ecSZhang Rui int isst_get_process_ctdp(struct isst_id *id, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
3623fb4f7cdSSrinivas Pandruvada {
363ac9d05eaSSrinivas Pandruvada 	int i, ret, valid = 0;
3643fb4f7cdSSrinivas Pandruvada 
3653fb4f7cdSSrinivas Pandruvada 	if (pkg_dev->processed)
3663fb4f7cdSSrinivas Pandruvada 		return 0;
3673fb4f7cdSSrinivas Pandruvada 
368850337ecSZhang Rui 	ret = isst_get_ctdp_levels(id, pkg_dev);
3693fb4f7cdSSrinivas Pandruvada 	if (ret)
3703fb4f7cdSSrinivas Pandruvada 		return ret;
3713fb4f7cdSSrinivas Pandruvada 
3723fb4f7cdSSrinivas Pandruvada 	debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n",
373850337ecSZhang Rui 		     id->cpu, pkg_dev->enabled, pkg_dev->current_level,
3743fb4f7cdSSrinivas Pandruvada 		     pkg_dev->levels);
3753fb4f7cdSSrinivas Pandruvada 
376ac9d05eaSSrinivas Pandruvada 	if (tdp_level != 0xff && tdp_level > pkg_dev->levels) {
377ac9d05eaSSrinivas Pandruvada 		isst_display_error_info_message(1, "Invalid level", 0, 0);
378ac9d05eaSSrinivas Pandruvada 		return -1;
379ac9d05eaSSrinivas Pandruvada 	}
380ac9d05eaSSrinivas Pandruvada 
381ac9d05eaSSrinivas Pandruvada 	if (!pkg_dev->enabled)
382ac9d05eaSSrinivas Pandruvada 		isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0);
383ac9d05eaSSrinivas Pandruvada 
3843fb4f7cdSSrinivas Pandruvada 	for (i = 0; i <= pkg_dev->levels; ++i) {
3853fb4f7cdSSrinivas Pandruvada 		struct isst_pkg_ctdp_level_info *ctdp_level;
3863fb4f7cdSSrinivas Pandruvada 
3873fb4f7cdSSrinivas Pandruvada 		if (tdp_level != 0xff && i != tdp_level)
3883fb4f7cdSSrinivas Pandruvada 			continue;
3893fb4f7cdSSrinivas Pandruvada 
390850337ecSZhang Rui 		debug_printf("cpu:%d Get Information for TDP level:%d\n", id->cpu,
3913fb4f7cdSSrinivas Pandruvada 			     i);
3923fb4f7cdSSrinivas Pandruvada 		ctdp_level = &pkg_dev->ctdp_level[i];
3933fb4f7cdSSrinivas Pandruvada 
3943fb4f7cdSSrinivas Pandruvada 		ctdp_level->level = i;
395850337ecSZhang Rui 		ctdp_level->control_cpu = id->cpu;
39656d64692SZhang Rui 		ctdp_level->pkg_id = id->pkg;
39756d64692SZhang Rui 		ctdp_level->die_id = id->die;
3983fb4f7cdSSrinivas Pandruvada 
399850337ecSZhang Rui 		ret = isst_get_ctdp_control(id, i, ctdp_level);
4003fb4f7cdSSrinivas Pandruvada 		if (ret)
40120183ccdSSrinivas Pandruvada 			continue;
40220183ccdSSrinivas Pandruvada 
403ac9d05eaSSrinivas Pandruvada 		valid = 1;
40420183ccdSSrinivas Pandruvada 		pkg_dev->processed = 1;
40520183ccdSSrinivas Pandruvada 		ctdp_level->processed = 1;
4063fb4f7cdSSrinivas Pandruvada 
4077af5a95bSSrinivas Pandruvada 		if (ctdp_level->pbf_support) {
408850337ecSZhang Rui 			ret = isst_get_pbf_info(id, i, &ctdp_level->pbf_info);
4097af5a95bSSrinivas Pandruvada 			if (!ret)
4107af5a95bSSrinivas Pandruvada 				ctdp_level->pbf_found = 1;
4117af5a95bSSrinivas Pandruvada 		}
4127af5a95bSSrinivas Pandruvada 
4137af5a95bSSrinivas Pandruvada 		if (ctdp_level->fact_support) {
414850337ecSZhang Rui 			ret = isst_get_fact_info(id, i, 0xff,
4157af5a95bSSrinivas Pandruvada 						 &ctdp_level->fact_info);
4167af5a95bSSrinivas Pandruvada 			if (ret)
4177af5a95bSSrinivas Pandruvada 				return ret;
4187af5a95bSSrinivas Pandruvada 		}
4197af5a95bSSrinivas Pandruvada 
42007f262d8SSrinivas Pandruvada 		if (!pkg_dev->enabled && is_skx_based_platform()) {
4217af5a95bSSrinivas Pandruvada 			int freq;
4227af5a95bSSrinivas Pandruvada 
423850337ecSZhang Rui 			freq = get_cpufreq_base_freq(id->cpu);
4247af5a95bSSrinivas Pandruvada 			if (freq > 0) {
4257af5a95bSSrinivas Pandruvada 				ctdp_level->sse_p1 = freq / 100000;
4267af5a95bSSrinivas Pandruvada 				ctdp_level->tdp_ratio = ctdp_level->sse_p1;
4277af5a95bSSrinivas Pandruvada 			}
4287af5a95bSSrinivas Pandruvada 
4297c7e7c0dSZhang Rui 			isst_get_get_trl_from_msr(id, ctdp_level->trl_ratios[0]);
4301e37f1b2SZhang Rui 			isst_get_trl_bucket_info(id, i, &ctdp_level->trl_cores);
4317af5a95bSSrinivas Pandruvada 			continue;
4327af5a95bSSrinivas Pandruvada 		}
4337af5a95bSSrinivas Pandruvada 
434850337ecSZhang Rui 		ret = isst_get_tdp_info(id, i, ctdp_level);
4353fb4f7cdSSrinivas Pandruvada 		if (ret)
4363fb4f7cdSSrinivas Pandruvada 			return ret;
4373fb4f7cdSSrinivas Pandruvada 
438850337ecSZhang Rui 		ret = isst_get_pwr_info(id, i, ctdp_level);
4393fb4f7cdSSrinivas Pandruvada 		if (ret)
4403fb4f7cdSSrinivas Pandruvada 			return ret;
4413fb4f7cdSSrinivas Pandruvada 
4423fb4f7cdSSrinivas Pandruvada 		ctdp_level->core_cpumask_size =
4433fb4f7cdSSrinivas Pandruvada 			alloc_cpu_set(&ctdp_level->core_cpumask);
444850337ecSZhang Rui 		ret = isst_get_coremask_info(id, i, ctdp_level);
4453fb4f7cdSSrinivas Pandruvada 		if (ret)
4463fb4f7cdSSrinivas Pandruvada 			return ret;
4473fb4f7cdSSrinivas Pandruvada 
4481e37f1b2SZhang Rui 		ret = isst_get_trl_bucket_info(id, i, &ctdp_level->trl_cores);
4491233c7b9SSrinivas Pandruvada 		if (ret)
4501233c7b9SSrinivas Pandruvada 			return ret;
4511233c7b9SSrinivas Pandruvada 
4524a17b291SZhang Rui 		ret = isst_get_get_trls(id, i, ctdp_level);
4533fb4f7cdSSrinivas Pandruvada 		if (ret)
4543fb4f7cdSSrinivas Pandruvada 			return ret;
4557c7e7c0dSZhang Rui 	}
4563fb4f7cdSSrinivas Pandruvada 
457ac9d05eaSSrinivas Pandruvada 	if (!valid)
458850337ecSZhang Rui 		isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, id->cpu);
459ac9d05eaSSrinivas Pandruvada 
4603fb4f7cdSSrinivas Pandruvada 	return 0;
4613fb4f7cdSSrinivas Pandruvada }
4623fb4f7cdSSrinivas Pandruvada 
isst_clos_get_clos_information(struct isst_id * id,int * enable,int * type)463850337ecSZhang Rui int isst_clos_get_clos_information(struct isst_id *id, int *enable, int *type)
464188afed9SSrinivas Pandruvada {
465a07bdb81SZhang Rui 	CHECK_CB(get_clos_information);
466a07bdb81SZhang Rui 	return isst_ops->get_clos_information(id, enable, type);
467188afed9SSrinivas Pandruvada }
468188afed9SSrinivas Pandruvada 
isst_pm_qos_config(struct isst_id * id,int enable_clos,int priority_type)469850337ecSZhang Rui int isst_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
4703fb4f7cdSSrinivas Pandruvada {
471904d2baaSZhang Rui 	CHECK_CB(pm_qos_config);
472904d2baaSZhang Rui 	return isst_ops->pm_qos_config(id, enable_clos, priority_type);
4733fb4f7cdSSrinivas Pandruvada }
4743fb4f7cdSSrinivas Pandruvada 
isst_pm_get_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)475850337ecSZhang Rui int isst_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
4763fb4f7cdSSrinivas Pandruvada {
47743314e79SZhang Rui 	CHECK_CB(pm_get_clos);
47843314e79SZhang Rui 	return isst_ops->pm_get_clos(id, clos, clos_config);
4793fb4f7cdSSrinivas Pandruvada }
4803fb4f7cdSSrinivas Pandruvada 
isst_set_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)481850337ecSZhang Rui int isst_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
4823fb4f7cdSSrinivas Pandruvada {
48333dbf360SZhang Rui 	CHECK_CB(set_clos);
48433dbf360SZhang Rui 	return isst_ops->set_clos(id, clos, clos_config);
4853fb4f7cdSSrinivas Pandruvada }
4863fb4f7cdSSrinivas Pandruvada 
isst_clos_get_assoc_status(struct isst_id * id,int * clos_id)487850337ecSZhang Rui int isst_clos_get_assoc_status(struct isst_id *id, int *clos_id)
4883fb4f7cdSSrinivas Pandruvada {
489b161bbadSZhang Rui 	CHECK_CB(clos_get_assoc_status);
490b161bbadSZhang Rui 	return isst_ops->clos_get_assoc_status(id, clos_id);
4913fb4f7cdSSrinivas Pandruvada }
4923fb4f7cdSSrinivas Pandruvada 
isst_clos_associate(struct isst_id * id,int clos_id)493850337ecSZhang Rui int isst_clos_associate(struct isst_id *id, int clos_id)
4943fb4f7cdSSrinivas Pandruvada {
495a59a6c0cSZhang Rui 	CHECK_CB(clos_associate);
496a59a6c0cSZhang Rui 	return isst_ops->clos_associate(id, clos_id);
4973fb4f7cdSSrinivas Pandruvada 
4983fb4f7cdSSrinivas Pandruvada }
499