diff --git a/tools/power/x86/intel-speed-select/Build b/tools/power/x86/intel-speed-select/Build
index 81e36bd578b1c11d7159c40cbbe8b40e2f368d93..5a9637e1678c559176fc76b38613ae839e30ad61 100644
--- a/tools/power/x86/intel-speed-select/Build
+++ b/tools/power/x86/intel-speed-select/Build
@@ -1 +1 @@
-intel-speed-select-y +=  isst-config.o isst-core.o isst-display.o isst-daemon.o hfi-events.o
+intel-speed-select-y +=  isst-config.o isst-core.o isst-display.o isst-daemon.o hfi-events.o isst-core-mbox.o isst-core-tpmi.o
diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c
index 55d0a35df41cc0fc89df95b21cc3477d10d8c31e..2ca0cedd418f0605793ce340060afd64d21628a1 100644
--- a/tools/power/x86/intel-speed-select/isst-config.c
+++ b/tools/power/x86/intel-speed-select/isst-config.c
@@ -15,9 +15,9 @@ struct process_cmd_struct {
 	int arg;
 };
 
-static const char *version_str = "v1.14";
+static const char *version_str = "v1.15";
 
-static const int supported_api_ver = 1;
+static const int supported_api_ver = 2;
 static struct isst_if_platform_info isst_platform_info;
 static char *progname;
 static int debug_flag;
@@ -44,9 +44,7 @@ static int cmd_help;
 static int force_online_offline;
 static int auto_mode;
 static int fact_enable_fail;
-
-static int mbox_delay;
-static int mbox_retries = 3;
+static int cgroupv2;
 
 /* clos related */
 static int current_clos = -1;
@@ -61,6 +59,7 @@ struct _cpu_map {
 	unsigned short core_id;
 	unsigned short pkg_id;
 	unsigned short die_id;
+	unsigned short punit_id;
 	unsigned short punit_cpu;
 	unsigned short punit_cpu_core;
 	unsigned short initialized;
@@ -79,6 +78,11 @@ FILE *get_output_file(void)
 	return outf;
 }
 
+int is_debug_enabled(void)
+{
+	return debug_flag;
+}
+
 void debug_printf(const char *format, ...)
 {
 	va_list args;
@@ -110,12 +114,21 @@ int is_skx_based_platform(void)
 
 int is_spr_platform(void)
 {
-	if (cpu_model == 0x8F || cpu_model == 0xCF)
+	if (cpu_model == 0x8F)
+		return 1;
+
+	return 0;
+}
+
+int is_emr_platform(void)
+{
+	if (cpu_model == 0xCF)
 		return 1;
 
 	return 0;
 }
 
+
 int is_icx_platform(void)
 {
 	if (cpu_model == 0x6A || cpu_model == 0x6C)
@@ -163,6 +176,11 @@ static int update_cpu_model(void)
 	return 0;
 }
 
+int api_version(void)
+{
+        return isst_platform_info.api_version;
+}
+
 /* Open a file, and exit on failure */
 static FILE *fopen_or_exit(const char *path, const char *mode)
 {
@@ -378,6 +396,17 @@ static int get_physical_die_id(int cpu)
 	return ret;
 }
 
+static int get_physical_punit_id(int cpu)
+{
+	if (cpu < 0)
+		return -1;
+
+	if (cpu_map && cpu_map[cpu].initialized)
+		return cpu_map[cpu].punit_id;
+
+	return -1;
+}
+
 void set_isst_id(struct isst_id *id, int cpu)
 {
 	id->cpu = cpu;
@@ -389,6 +418,10 @@ void set_isst_id(struct isst_id *id, int cpu)
 	id->die = get_physical_die_id(cpu);
 	if (id->die >= MAX_DIE_PER_PACKAGE)
 		id->die = -1;
+
+	id->punit = get_physical_punit_id(cpu);
+	if (id->punit >= MAX_PUNIT_PER_DIE)
+		id->punit = -1;
 }
 
 int is_cpu_in_power_domain(int cpu, struct isst_id *id)
@@ -397,7 +430,7 @@ int is_cpu_in_power_domain(int cpu, struct isst_id *id)
 
 	set_isst_id(&tid, cpu);
 
-	if (id->pkg == tid.pkg && id->die == tid.die)
+	if (id->pkg == tid.pkg && id->die == tid.die && id->punit == tid.punit)
 		return 1;
 
 	return 0;
@@ -481,51 +514,59 @@ static void force_all_cpus_online(void)
 	unlink("/var/run/isst_cpu_topology.dat");
 }
 
-void for_each_online_package_in_set(void (*callback)(struct isst_id *, void *, void *,
+void for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void *, void *,
 						     void *, void *),
 				    void *arg1, void *arg2, void *arg3,
 				    void *arg4)
 {
-	int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
-	int pkg_index = 0, i;
 	struct isst_id id;
+	int cpus[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
+	int valid_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE] = {0};
+	int i, j, k;
+
+	memset(cpus, -1, sizeof(cpus));
 
-	memset(max_packages, 0xff, sizeof(max_packages));
 	for (i = 0; i < topo_max_cpus; ++i) {
-		int j, online, pkg_id, die_id = 0, skip = 0;
+		int online;
 
 		if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
 			continue;
-		if (i)
-			online = parse_int_file(
-				1, "/sys/devices/system/cpu/cpu%d/online", i);
-		else
-			online =
-				1; /* online entry for CPU 0 needs some special configs */
 
-		die_id = get_physical_die_id(i);
-		if (die_id < 0)
-			die_id = 0;
+		online = parse_int_file(
+			i != 0, "/sys/devices/system/cpu/cpu%d/online", i);
+		if (online < 0)
+			online = 1; /* online entry for CPU 0 needs some special configs */
 
-		pkg_id = parse_int_file(0,
-			"/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
-		if (pkg_id < 0)
+		if (!online)
 			continue;
 
-		/* Create an unique id for package, die combination to store */
-		pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
+		set_isst_id(&id, i);
 
-		for (j = 0; j < pkg_index; ++j) {
-			if (max_packages[j] == pkg_id) {
-				skip = 1;
-				break;
-			}
-		}
+		if (id.pkg < 0 || id.die < 0 || id.punit < 0)
+			continue;
 
-		set_isst_id(&id, i);
-		if (!skip && online && callback) {
-			callback(&id, arg1, arg2, arg3, arg4);
-			max_packages[pkg_index++] = pkg_id;
+		valid_mask[id.pkg][id.die] = 1;
+
+		if (cpus[id.pkg][id.die][id.punit] == -1)
+			cpus[id.pkg][id.die][id.punit] = i;
+	}
+
+	for (i = 0; i < MAX_PACKAGE_COUNT; i++) {
+		for (j = 0; j < MAX_DIE_PER_PACKAGE; j++) {
+			/*
+			 * Fix me:
+			 * How to check a non-cpu die for a package/die with all cpu offlined?
+			 */
+			if (!valid_mask[i][j])
+				continue;
+			for (k = 0; k < MAX_PUNIT_PER_DIE; k++) {
+				id.cpu = cpus[i][j][k];
+				id.pkg = i;
+				id.die = j;
+				id.punit = k;
+				if (isst_is_punit_valid(&id))
+					callback(&id, arg1, arg2, arg3, arg4);
+			}
 		}
 	}
 }
@@ -610,7 +651,7 @@ void free_cpu_set(cpu_set_t *cpu_set)
 	CPU_FREE(cpu_set);
 }
 
-static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
+static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
 
 int get_max_punit_core_id(struct isst_id *id)
 {
@@ -632,10 +673,50 @@ int get_max_punit_core_id(struct isst_id *id)
 
 int get_cpu_count(struct isst_id *id)
 {
-	if (id->pkg < 0 || id->die < 0)
+	if (id->pkg < 0 || id->die < 0 || id->punit < 0)
 		return 0;
 
-	return cpu_cnt[id->pkg][id->die];
+	return cpu_cnt[id->pkg][id->die][id->punit];
+}
+
+static void update_punit_cpu_info(__u32 physical_cpu, struct _cpu_map *cpu_map)
+{
+	if (api_version() > 1) {
+		/*
+		 * MSR 0x54 format
+		 *	[15:11] PM_DOMAIN_ID
+		 *	[10:3] MODULE_ID (aka IDI_AGENT_ID)
+		 *	[2:0] LP_ID (We don't care about these bits we only
+		 *		care die and core id
+		 *	For Atom:
+		 *	[2] Always 0
+		 *	[1:0] core ID within module
+		 *	For Core
+		 *	[2:1] Always 0
+		 *	[0] thread ID
+		 */
+		cpu_map->punit_id = (physical_cpu >> 11) & 0x1f;
+		cpu_map->punit_cpu_core = (physical_cpu >> 3) & 0xff;
+		cpu_map->punit_cpu = physical_cpu & 0x7ff;
+	} else {
+		int punit_id;
+
+		/*
+		 * MSR 0x53 format
+		 * Format
+		 *      Bit 0 – thread ID
+		 *      Bit 8:1 – core ID
+		 *      Bit 13:9 – punit ID
+		 */
+		cpu_map->punit_cpu = physical_cpu & 0x1ff;
+		cpu_map->punit_cpu_core = (cpu_map->punit_cpu >> 1); // shift to get core id
+		punit_id = (physical_cpu >> 9) & 0x1f;
+
+		if (punit_id >= MAX_PUNIT_PER_DIE)
+			punit_id = 0;
+
+		cpu_map->punit_id = punit_id;
+	}
 }
 
 static void create_cpu_map(void)
@@ -660,7 +741,7 @@ static void create_cpu_map(void)
 
 	for (i = 0; i < topo_max_cpus; ++i) {
 		char buffer[256];
-		int pkg_id, die_id, core_id;
+		int pkg_id, die_id, core_id, punit_id;
 
 		/* check if CPU is online */
 		snprintf(buffer, sizeof(buffer),
@@ -682,31 +763,32 @@ static void create_cpu_map(void)
 		cpu_map[i].pkg_id = pkg_id;
 		cpu_map[i].die_id = die_id;
 		cpu_map[i].core_id = core_id;
-		cpu_map[i].initialized = 1;
 
-		cpu_cnt[pkg_id][die_id]++;
 
-		if (fd < 0)
-			continue;
-		map.cmd_count = 1;
-		map.cpu_map[0].logical_cpu = i;
-		debug_printf(" map logical_cpu:%d\n",
-			     map.cpu_map[0].logical_cpu);
-		if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
-			perror("ISST_IF_GET_PHY_ID");
-			fprintf(outf, "Error: map logical_cpu:%d\n",
-				map.cpu_map[0].logical_cpu);
-			continue;
+		punit_id = 0;
+
+		if (fd >= 0) {
+			map.cmd_count = 1;
+			map.cpu_map[0].logical_cpu = i;
+			debug_printf(" map logical_cpu:%d\n",
+				     map.cpu_map[0].logical_cpu);
+			if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
+				perror("ISST_IF_GET_PHY_ID");
+				fprintf(outf, "Error: map logical_cpu:%d\n",
+					map.cpu_map[0].logical_cpu);
+			} else {
+				update_punit_cpu_info(map.cpu_map[0].physical_cpu, &cpu_map[i]);
+			}
 		}
-		cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu;
-		cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >>
-					     1); // shift to get core id
+		cpu_map[i].initialized = 1;
+
+		cpu_cnt[pkg_id][die_id][punit_id]++;
 
 		debug_printf(
-			"map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
+			"map logical_cpu:%d core: %d die:%d pkg:%d punit:%d punit_cpu:%d punit_core:%d\n",
 			i, cpu_map[i].core_id, cpu_map[i].die_id,
-			cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
-			cpu_map[i].punit_cpu_core);
+			cpu_map[i].pkg_id, cpu_map[i].punit_id,
+			cpu_map[i].punit_cpu, cpu_map[i].punit_cpu_core);
 	}
 	if (fd >= 0)
 		close(fd);
@@ -728,6 +810,9 @@ void set_cpu_mask_from_punit_coremask(struct isst_id *id, unsigned long long cor
 {
 	int i, cnt = 0;
 
+	if (id->cpu < 0)
+		return;
+
 	*cpu_cnt = 0;
 
 	for (i = 0; i < 64; ++i) {
@@ -759,182 +844,135 @@ int find_phy_core_num(int logical_cpu)
 	return -EINVAL;
 }
 
-static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
-				  unsigned int *value)
+int use_cgroupv2(void)
 {
-	struct isst_if_io_regs io_regs;
-	const char *pathname = "/dev/isst_interface";
-	int cmd;
-	int fd;
-
-	debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
+	return cgroupv2;
+}
 
-	fd = open(pathname, O_RDWR);
-	if (fd < 0)
-		err(-1, "%s open failed", pathname);
+int enable_cpuset_controller(void)
+{
+	int fd, ret;
 
-	io_regs.req_count = 1;
-	io_regs.io_reg[0].logical_cpu = cpu;
-	io_regs.io_reg[0].reg = reg;
-	cmd = ISST_IF_IO_CMD;
-	if (write) {
-		io_regs.io_reg[0].read_write = 1;
-		io_regs.io_reg[0].value = *value;
-	} else {
-		io_regs.io_reg[0].read_write = 0;
+	fd = open("/sys/fs/cgroup/cgroup.subtree_control", O_RDWR, 0);
+	if (fd < 0) {
+		debug_printf("Can't activate cpuset controller\n");
+		debug_printf("Either you are not root user or CGroup v2 is not supported\n");
+		return fd;
 	}
 
-	if (ioctl(fd, cmd, &io_regs) == -1) {
-		if (errno == ENOTTY) {
-			perror("ISST_IF_IO_COMMAND\n");
-			fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
-			exit(0);
-		}
-		fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
-			cpu, reg, write);
-	} else {
-		if (!write)
-			*value = io_regs.io_reg[0].value;
+	ret = write(fd, " +cpuset", strlen(" +cpuset"));
+	close(fd);
 
-		debug_printf(
-			"mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
-			cpu, reg, write, *value);
+	if (ret == -1) {
+		debug_printf("Can't activate cpuset controller: Write failed\n");
+		return ret;
 	}
 
-	close(fd);
-
 	return 0;
 }
 
-int isst_send_mbox_command(unsigned int cpu, unsigned char command,
-			   unsigned char sub_command, unsigned int parameter,
-			   unsigned int req_data, unsigned int *resp)
+int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level)
 {
-	const char *pathname = "/dev/isst_interface";
-	int fd, retry;
-	struct isst_if_mbox_cmds mbox_cmds = { 0 };
-
-	debug_printf(
-		"mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
-		cpu, command, sub_command, parameter, req_data);
+	int i, first, curr_index, index, ret, fd;
+	static char str[512], dir_name[64];
+	static char cpuset_cpus[128];
+	int str_len = sizeof(str);
+	DIR *dir;
 
-	if (!is_skx_based_platform() && command == CONFIG_CLOS &&
-	    sub_command != CLOS_PM_QOS_CONFIG) {
-		unsigned int value;
-		int write = 0;
-		int clos_id, core_id, ret = 0;
+	snprintf(dir_name, sizeof(dir_name), "/sys/fs/cgroup/%d-%d-%d", id->pkg, id->die, id->punit);
+	dir = opendir(dir_name);
+	if (!dir) {
+		ret = mkdir(dir_name, 0744);
+		if (ret) {
+			debug_printf("Can't create dir:%s errno:%d\n", dir_name, errno);
+			return ret;
+		}
+	}
+	closedir(dir);
 
-		debug_printf("CPU %d\n", cpu);
+	if (!level) {
+		sprintf(cpuset_cpus, "%s/cpuset.cpus.partition", dir_name);
 
-		if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
-			value = req_data;
-			write = 1;
+		fd = open(cpuset_cpus, O_RDWR, 0);
+		if (fd < 0) {
+			return fd;
 		}
 
-		switch (sub_command) {
-		case CLOS_PQR_ASSOC:
-			core_id = parameter & 0xff;
-			ret = isst_send_mmio_command(
-				cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
-				&value);
-			if (!ret && !write)
-				*resp = value;
-			break;
-		case CLOS_PM_CLOS:
-			clos_id = parameter & 0x03;
-			ret = isst_send_mmio_command(
-				cpu, PM_CLOS_OFFSET + clos_id * 4, write,
-				&value);
-			if (!ret && !write)
-				*resp = value;
-			break;
-		case CLOS_STATUS:
-			break;
-		default:
-			break;
+		ret = write(fd, "member", strlen("member"));
+		if (ret == -1) {
+			printf("Can't update to member\n");
+			return ret;
 		}
-		return ret;
-	}
 
-	mbox_cmds.cmd_count = 1;
-	mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
-	mbox_cmds.mbox_cmd[0].command = command;
-	mbox_cmds.mbox_cmd[0].sub_command = sub_command;
-	mbox_cmds.mbox_cmd[0].parameter = parameter;
-	mbox_cmds.mbox_cmd[0].req_data = req_data;
+		return 0;
+	}
 
-	if (mbox_delay)
-		usleep(mbox_delay * 1000);
+	if (!CPU_COUNT_S(mask_size, cpu_mask)) {
+		return -1;
+	}
 
-	fd = open(pathname, O_RDWR);
-	if (fd < 0)
-		err(-1, "%s open failed", pathname);
+	curr_index = 0;
+	first = 1;
+	str[0] = '\0';
+	for (i = 0; i < get_topo_max_cpus(); ++i) {
+		if (!is_cpu_in_power_domain(i, id))
+			continue;
 
-	retry = mbox_retries;
+		if (CPU_ISSET_S(i, mask_size, cpu_mask))
+			continue;
 
-	do {
-		if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
-			if (errno == ENOTTY) {
-				perror("ISST_IF_MBOX_COMMAND\n");
-				fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
-				exit(0);
-			}
-			debug_printf(
-				"Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
-				cpu, command, sub_command, parameter, req_data, errno);
-			--retry;
-		} else {
-			*resp = mbox_cmds.mbox_cmd[0].resp_data;
-			debug_printf(
-				"mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
-				cpu, command, sub_command, parameter, req_data, *resp);
-			break;
+		if (!first) {
+			index = snprintf(&str[curr_index],
+					 str_len - curr_index, ",");
+			curr_index += index;
+			if (curr_index >= str_len)
+				break;
 		}
-	} while (retry);
+		index = snprintf(&str[curr_index], str_len - curr_index, "%d",
+				 i);
+		curr_index += index;
+		if (curr_index >= str_len)
+			break;
+		first = 0;
+	}
 
-	close(fd);
+	debug_printf("isolated CPUs list: package:%d curr_index:%d [%s]\n", id->pkg, curr_index ,str);
 
-	if (!retry) {
-		debug_printf("Failed mbox command even after retries\n");
-		return -1;
+	snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus", dir_name);
 
+	fd = open(cpuset_cpus, O_RDWR, 0);
+	if (fd < 0) {
+		return fd;
 	}
-	return 0;
-}
 
-int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
-			  unsigned long long *req_resp)
-{
-	struct isst_if_msr_cmds msr_cmds;
-	const char *pathname = "/dev/isst_interface";
-	int fd;
+	ret = write(fd, str, strlen(str));
+	close(fd);
 
-	fd = open(pathname, O_RDWR);
-	if (fd < 0)
-		err(-1, "%s open failed", pathname);
+	if (ret == -1) {
+		debug_printf("Can't activate cpuset controller: Write failed\n");
+		return ret;
+	}
 
-	msr_cmds.cmd_count = 1;
-	msr_cmds.msr_cmd[0].logical_cpu = cpu;
-	msr_cmds.msr_cmd[0].msr = msr;
-	msr_cmds.msr_cmd[0].read_write = write;
-	if (write)
-		msr_cmds.msr_cmd[0].data = *req_resp;
-
-	if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
-		perror("ISST_IF_MSR_COMMAND");
-		fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
-			cpu, msr, write);
-	} else {
-		if (!write)
-			*req_resp = msr_cmds.msr_cmd[0].data;
+	snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus.partition", dir_name);
 
-		debug_printf(
-			"msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
-			cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
+	fd = open(cpuset_cpus, O_RDWR, 0);
+	if (fd < 0) {
+		return fd;
+	}
+
+	ret = write(fd, "isolated", strlen("isolated"));
+	if (ret == -1) {
+		debug_printf("Can't update to isolated\n");
+		ret = write(fd, "root", strlen("root"));
+		if (ret == -1)
+			debug_printf("Can't update to root\n");
 	}
 
 	close(fd);
 
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -943,6 +981,11 @@ static int isst_fill_platform_info(void)
 	const char *pathname = "/dev/isst_interface";
 	int fd;
 
+	if (is_clx_n_platform()) {
+		isst_platform_info.api_version = 1;
+		goto set_platform_ops;
+	}
+
 	fd = open(pathname, O_RDWR);
 	if (fd < 0)
 		err(-1, "%s open failed", pathname);
@@ -959,77 +1002,96 @@ static int isst_fill_platform_info(void)
 		printf("Incompatible API versions; Upgrade of tool is required\n");
 		return -1;
 	}
+
+set_platform_ops:
+	if (isst_set_platform_ops(isst_platform_info.api_version)) {
+		fprintf(stderr, "Failed to set platform callbacks\n");
+		exit(0);
+	}
 	return 0;
 }
 
-static void isst_print_extended_platform_info(void)
+void get_isst_status(struct isst_id *id, void *arg1, void *arg2, void *arg3, void *arg4)
 {
-	int cp_state, cp_cap, fact_support = 0, pbf_support = 0;
-	struct isst_pkg_ctdp_level_info ctdp_level;
 	struct isst_pkg_ctdp pkg_dev;
-	int ret, i, j;
-	FILE *filep;
-	struct isst_id id;
-
-	for (i = 0; i < 256; ++i) {
-		char path[256];
-
-		snprintf(path, sizeof(path),
-			 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
-		filep = fopen(path, "r");
-		if (filep)
-			break;
-	}
+	struct isst_id *tid = (struct isst_id *)arg2;
+	int *mask = (int *)arg3;
+	int *max_level = (int *)arg4;
+	int j, ret;
 
-	if (!filep)
+	/* Only check the first cpu power domain */
+	if (id->cpu < 0 || tid->cpu >= 0)
 		return;
 
-	fclose(filep);
-
-	set_isst_id(&id, i);
-	ret = isst_get_ctdp_levels(&id, &pkg_dev);
+	ret = isst_get_ctdp_levels(id, &pkg_dev);
 	if (ret)
 		return;
 
-	if (pkg_dev.enabled) {
-		fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
-	} else {
-		fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
-		fprintf(outf, "Only performance level 0 (base level) is present\n");
-	}
+	if (pkg_dev.enabled)
+		*mask |= BIT(0);
 
 	if (pkg_dev.locked)
-		fprintf(outf, "TDP level change control is locked\n");
-	else
-		fprintf(outf, "TDP level change control is unlocked, max level: %d \n", pkg_dev.levels);
+		*mask |= BIT(1);
+
+	if (*max_level < pkg_dev.levels)
+		*max_level = pkg_dev.levels;
 
 	for (j = 0; j <= pkg_dev.levels; ++j) {
-		ret = isst_get_ctdp_control(&id, j, &ctdp_level);
+		struct isst_pkg_ctdp_level_info ctdp_level;
+
+		ret = isst_get_ctdp_control(id, j, &ctdp_level);
 		if (ret)
 			continue;
 
-		if (!fact_support && ctdp_level.fact_support)
-			fact_support = 1;
+		if (ctdp_level.fact_support)
+			*mask |= BIT(2);
+
+		if (ctdp_level.pbf_support)
+			*mask |= BIT(3);
+	}
+
+	tid->cpu = id->cpu;
+	tid->pkg = id->pkg;
+	tid->die = id->die;
+	tid->punit = id->punit;
+}
+
+static void isst_print_extended_platform_info(void)
+{
+	int cp_state, cp_cap;
+	struct isst_id id;
+	int mask = 0, max_level = 0;
 
-		if (!pbf_support && ctdp_level.pbf_support)
-			pbf_support = 1;
+	id.cpu = -1;
+	for_each_online_power_domain_in_set(get_isst_status, NULL, &id, &mask, &max_level);
+
+	if (mask & BIT(0)) {
+		fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
+	} else {
+		fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
+		fprintf(outf, "Only performance level 0 (base level) is present\n");
 	}
 
-	if (fact_support)
+	if (mask & BIT(1))
+		fprintf(outf, "TDP level change control is locked\n");
+	else
+		fprintf(outf, "TDP level change control is unlocked, max level: %d\n", max_level);
+
+	if (mask & BIT(2))
 		fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n");
 	else
 		fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n");
 
-	if (pbf_support)
+	if (mask & BIT(3))
 		fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n");
 	else
 		fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n");
 
-	ret = isst_read_pm_config(&id, &cp_state, &cp_cap);
-	if (ret) {
+	if (isst_read_pm_config(&id, &cp_state, &cp_cap)) {
 		fprintf(outf, "Intel(R) SST-CP (feature core-power) status is unknown\n");
 		return;
 	}
+
 	if (cp_cap)
 		fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n");
 	else
@@ -1038,10 +1100,6 @@ static void isst_print_extended_platform_info(void)
 
 static void isst_print_platform_information(void)
 {
-	struct isst_if_platform_info platform_info;
-	const char *pathname = "/dev/isst_interface";
-	int fd;
-
 	if (is_clx_n_platform()) {
 		fprintf(stderr, "\nThis option in not supported on this platform\n");
 		exit(0);
@@ -1051,25 +1109,15 @@ static void isst_print_platform_information(void)
 	set_max_cpu_num();
 	create_cpu_map();
 
-	fd = open(pathname, O_RDWR);
-	if (fd < 0)
-		err(-1, "%s open failed", pathname);
-
-	if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
-		perror("ISST_IF_GET_PLATFORM_INFO");
-	} else {
-		fprintf(outf, "Platform: API version : %d\n",
-			platform_info.api_version);
-		fprintf(outf, "Platform: Driver version : %d\n",
-			platform_info.driver_version);
-		fprintf(outf, "Platform: mbox supported : %d\n",
-			platform_info.mbox_supported);
-		fprintf(outf, "Platform: mmio supported : %d\n",
-			platform_info.mmio_supported);
-		isst_print_extended_platform_info();
-	}
-
-	close(fd);
+	fprintf(outf, "Platform: API version : %d\n",
+		isst_platform_info.api_version);
+	fprintf(outf, "Platform: Driver version : %d\n",
+		isst_platform_info.driver_version);
+	fprintf(outf, "Platform: mbox supported : %d\n",
+		isst_platform_info.mbox_supported);
+	fprintf(outf, "Platform: mmio supported : %d\n",
+		isst_platform_info.mmio_supported);
+	isst_print_extended_platform_info();
 
 	exit(0);
 }
@@ -1110,7 +1158,7 @@ static void exec_on_get_ctdp_cpu(struct isst_id *id, void *arg1, void *arg2, voi
 				exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix,     \
 				&ctdp, desc, &ctdp.object);                       \
 		else                                                              \
-			for_each_online_package_in_set(exec_on_get_ctdp_cpu,      \
+			for_each_online_power_domain_in_set(exec_on_get_ctdp_cpu,      \
 						       isst_get_ctdp_##suffix,    \
 						       &ctdp, desc,               \
 						       &ctdp.object);             \
@@ -1314,92 +1362,91 @@ static void dump_isst_config(int arg)
 	if (max_target_cpus)
 		for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
 	else
-		for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
+		for_each_online_power_domain_in_set(fn, NULL, NULL, NULL, NULL);
 
 	isst_ctdp_display_information_end(outf);
 }
 
-static int set_uncore_min_max(struct isst_id *id, int max, int freq)
-{
-	char buffer[128], freq_str[16];
-	int fd, ret, len;
-
-	if (max)
-		snprintf(buffer, sizeof(buffer),
-			 "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/max_freq_khz", id->pkg, id->die);
-	else
-		snprintf(buffer, sizeof(buffer),
-			 "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/min_freq_khz", id->pkg, id->die);
-
-	fd = open(buffer, O_WRONLY);
-	if (fd < 0)
-		return fd;
-
-	snprintf(freq_str, sizeof(freq_str), "%d", freq);
-	len = strlen(freq_str);
-	ret = write(fd, freq_str, len);
-	if (ret == -1) {
-		close(fd);
-		return ret;
-	}
-	close(fd);
-
-	return 0;
-}
-
 static void adjust_scaling_max_from_base_freq(int cpu);
 
 static void set_tdp_level_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
 				  void *arg4)
 {
+	struct isst_pkg_ctdp pkg_dev;
 	int ret;
 
+	ret = isst_get_ctdp_levels(id, &pkg_dev);
+	if (ret) {
+		isst_display_error_info_message(1, "Get TDP level failed", 0, 0);
+		isst_ctdp_display_information_end(outf);
+		exit(1);
+	}
+
+	if (pkg_dev.current_level == tdp_level) {
+		debug_printf("TDP level already set. Skipped\n");
+		goto display_result;
+	}
+
 	ret = isst_set_tdp_level(id, tdp_level);
 	if (ret) {
 		isst_display_error_info_message(1, "Set TDP level failed", 0, 0);
 		isst_ctdp_display_information_end(outf);
 		exit(1);
-	} else {
-		isst_display_result(id, outf, "perf-profile", "set_tdp_level",
-				    ret);
-		if (force_online_offline) {
-			struct isst_pkg_ctdp_level_info ctdp_level;
-
-			/* Wait for updated base frequencies */
-			usleep(2000);
-
-			/* Adjusting uncore freq */
-			isst_get_uncore_p0_p1_info(id, tdp_level, &ctdp_level);
-			if (ctdp_level.uncore_pm)
-				set_uncore_min_max(id, 0, ctdp_level.uncore_pm * 100000);
-
-			if (ctdp_level.uncore_p0)
-				set_uncore_min_max(id, 1, ctdp_level.uncore_p0 * 100000);
-
-			fprintf(stderr, "Option is set to online/offline\n");
-			ctdp_level.core_cpumask_size =
-				alloc_cpu_set(&ctdp_level.core_cpumask);
-			ret = isst_get_coremask_info(id, tdp_level, &ctdp_level);
-			if (ret) {
-				isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
-				return;
-			}
-			if (ctdp_level.cpu_count) {
-				int i, max_cpus = get_topo_max_cpus();
-				for (i = 0; i < max_cpus; ++i) {
-					if (!is_cpu_in_power_domain(i, id))
-						continue;
-					if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
-						fprintf(stderr, "online cpu %d\n", i);
-						set_cpu_online_offline(i, 1);
-						adjust_scaling_max_from_base_freq(i);
-					} else {
-						fprintf(stderr, "offline cpu %d\n", i);
-						set_cpu_online_offline(i, 0);
-					}
+	}
+
+display_result:
+	isst_display_result(id, outf, "perf-profile", "set_tdp_level", ret);
+	if (force_online_offline && id->cpu >= 0) {
+		struct isst_pkg_ctdp_level_info ctdp_level;
+
+		/* Wait for updated base frequencies */
+		usleep(2000);
+
+		/* Adjusting uncore freq */
+		isst_adjust_uncore_freq(id, tdp_level, &ctdp_level);
+
+		fprintf(stderr, "Option is set to online/offline\n");
+		ctdp_level.core_cpumask_size =
+			alloc_cpu_set(&ctdp_level.core_cpumask);
+		ret = isst_get_coremask_info(id, tdp_level, &ctdp_level);
+		if (ret) {
+			isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
+			goto free_mask;
+		}
+
+		if (use_cgroupv2()) {
+			int ret;
+
+			fprintf(stderr, "Using cgroup v2 in lieu of online/offline\n");
+			ret = enable_cpuset_controller();
+			if (ret)
+				goto use_offline;
+
+			ret = isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, tdp_level);
+			if (ret)
+				goto use_offline;
+
+			goto free_mask;
+		}
+
+use_offline:
+		if (ctdp_level.cpu_count) {
+			int i, max_cpus = get_topo_max_cpus();
+			for (i = 0; i < max_cpus; ++i) {
+				if (!is_cpu_in_power_domain(i, id))
+					continue;
+				if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
+					fprintf(stderr, "online cpu %d\n", i);
+					set_cpu_online_offline(i, 1);
+					adjust_scaling_max_from_base_freq(i);
+				} else {
+					fprintf(stderr, "offline cpu %d\n", i);
+					set_cpu_online_offline(i, 0);
 				}
 			}
 		}
+free_mask:
+		free_cpu_set(ctdp_level.core_cpumask);
 	}
 }
 
@@ -1425,7 +1472,7 @@ static void set_tdp_level(int arg)
 		for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
 						  NULL, NULL, NULL);
 	else
-		for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
+		for_each_online_power_domain_in_set(set_tdp_level_for_cpu, NULL,
 					       NULL, NULL, NULL);
 	isst_ctdp_display_information_end(outf);
 }
@@ -1463,7 +1510,7 @@ static void dump_pbf_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
 		exit(1);
 	} else {
 		isst_pbf_display_information(id, outf, tdp_level, &pbf_info);
-		isst_get_pbf_info_complete(&pbf_info);
+		free_cpu_set(pbf_info.core_cpumask);
 	}
 }
 
@@ -1494,7 +1541,7 @@ static void dump_pbf_config(int arg)
 	if (max_target_cpus)
 		for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
 	else
-		for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
+		for_each_online_power_domain_in_set(fn, NULL, NULL, NULL, NULL);
 
 	isst_ctdp_display_information_end(outf);
 }
@@ -1662,6 +1709,9 @@ static void set_scaling_min_to_cpuinfo_max(struct isst_id *id)
 {
 	int i;
 
+	if (id->cpu < 0)
+		return;
+
 	for (i = 0; i < get_topo_max_cpus(); ++i) {
 		if (!is_cpu_in_power_domain(i, id))
 			continue;
@@ -1679,6 +1729,9 @@ static void set_scaling_min_to_cpuinfo_min(struct isst_id *id)
 {
 	int i;
 
+	if (id->cpu < 0)
+		return;
+
 	for (i = 0; i < get_topo_max_cpus(); ++i) {
 		if (!is_cpu_in_power_domain(i, id))
 			continue;
@@ -1758,6 +1811,9 @@ static int set_pbf_core_power(struct isst_id *id)
 	struct isst_pkg_ctdp pkg_dev;
 	int ret;
 
+	if (id->cpu < 0)
+		return 0;
+
 	ret = isst_get_ctdp_levels(id, &pkg_dev);
 	if (ret) {
 		debug_printf("isst_get_ctdp_levels failed");
@@ -1900,7 +1956,7 @@ static void set_pbf_enable(int arg)
 		for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
 						  NULL, &enable);
 	else
-		for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
+		for_each_online_power_domain_in_set(set_pbf_for_cpu, NULL, NULL,
 					       NULL, &enable);
 	isst_ctdp_display_information_end(outf);
 }
@@ -1946,7 +2002,7 @@ static void dump_fact_config(int arg)
 		for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
 						  NULL, NULL, NULL, NULL);
 	else
-		for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
+		for_each_online_power_domain_in_set(dump_fact_config_for_cpu, NULL,
 					       NULL, NULL, NULL);
 	isst_ctdp_display_information_end(outf);
 }
@@ -2003,7 +2059,7 @@ static void set_fact_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *a
 		struct isst_pkg_ctdp pkg_dev;
 
 		ret = isst_get_ctdp_levels(id, &pkg_dev);
-		if (!ret)
+		if (!ret && id->cpu >= 0)
 			ret = isst_set_trl(id, fact_trl);
 		if (ret && auto_mode)
 			isst_pm_qos_config(id, 0, 0);
@@ -2055,7 +2111,7 @@ static void set_fact_enable(int arg)
 		for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
 						  NULL, &enable);
 	else
-		for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
+		for_each_online_power_domain_in_set(set_fact_for_cpu, NULL, NULL,
 					       NULL, &enable);
 	isst_ctdp_display_information_end(outf);
 
@@ -2194,7 +2250,7 @@ static void set_clos_enable(int arg)
 		for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
 						  NULL, NULL, &enable);
 	else
-		for_each_online_package_in_set(enable_clos_qos_config, NULL,
+		for_each_online_power_domain_in_set(enable_clos_qos_config, NULL,
 					       NULL, NULL, &enable);
 	isst_ctdp_display_information_end(outf);
 }
@@ -2205,6 +2261,9 @@ static void dump_clos_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
 	struct isst_clos_config clos_config;
 	int ret;
 
+	if (id->cpu < 0)
+		return;
+
 	ret = isst_pm_get_clos(id, current_clos, &clos_config);
 	if (ret)
 		isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
@@ -2233,7 +2292,7 @@ static void dump_clos_config(int arg)
 		for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
 						  NULL, NULL, NULL, NULL);
 	else
-		for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
+		for_each_online_power_domain_in_set(dump_clos_config_for_cpu, NULL,
 					       NULL, NULL, NULL);
 	isst_ctdp_display_information_end(outf);
 }
@@ -2269,7 +2328,7 @@ static void dump_clos_info(int arg)
 		for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
 						  NULL, NULL, NULL);
 	else
-		for_each_online_package_in_set(get_clos_info_for_cpu, NULL,
+		for_each_online_power_domain_in_set(get_clos_info_for_cpu, NULL,
 					       NULL, NULL, NULL);
 	isst_ctdp_display_information_end(outf);
 
@@ -2281,6 +2340,9 @@ static void set_clos_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
 	struct isst_clos_config clos_config;
 	int ret;
 
+	if (id->cpu < 0)
+		return;
+
 	clos_config.epp = clos_epp;
 	clos_config.clos_prop_prio = clos_prop_prio;
 	clos_config.clos_min = clos_min;
@@ -2341,7 +2403,7 @@ static void set_clos_config(int arg)
 		for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
 						  NULL, NULL, NULL);
 	else
-		for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
+		for_each_online_power_domain_in_set(set_clos_config_for_cpu, NULL,
 					       NULL, NULL, NULL);
 	isst_ctdp_display_information_end(outf);
 }
@@ -2508,7 +2570,7 @@ static void process_trl(int arg)
 		for_each_online_target_cpu_in_set(get_set_trl, NULL,
 						  NULL, NULL, &arg);
 	else
-		for_each_online_package_in_set(get_set_trl, NULL,
+		for_each_online_power_domain_in_set(get_set_trl, NULL,
 					       NULL, NULL, &arg);
 	isst_ctdp_display_information_end(outf);
 }
@@ -2683,7 +2745,7 @@ static void parse_cmd_args(int argc, int start, char **argv)
 			break;
 		case 'd':
 			clos_desired = atoi(optarg);
-			clos_desired /= DISP_FREQ_MULTIPLIER;
+			clos_desired /= isst_get_disp_freq_multiplier();
 			break;
 		case 'e':
 			clos_epp = atoi(optarg);
@@ -2694,11 +2756,11 @@ static void parse_cmd_args(int argc, int start, char **argv)
 			break;
 		case 'n':
 			clos_min = atoi(optarg);
-			clos_min /= DISP_FREQ_MULTIPLIER;
+			clos_min /= isst_get_disp_freq_multiplier();
 			break;
 		case 'm':
 			clos_max = atoi(optarg);
-			clos_max /= DISP_FREQ_MULTIPLIER;
+			clos_max /= isst_get_disp_freq_multiplier();
 			break;
 		case 'p':
 			clos_priority_type = atoi(optarg);
@@ -2882,6 +2944,7 @@ static void usage(void)
 	printf("\t[-b|--oob : Start a daemon to process HFI events for perf profile change from Out of Band agent.\n");
 	printf("\t[-n|--no-daemon : Don't run as daemon. By default --oob will turn on daemon mode\n");
 	printf("\t[-w|--delay : Delay for reading config level state change in OOB poll mode.\n");
+	printf("\t[-g|--cgroupv2 : Try to use cgroup v2 CPU isolation instead of CPU online/offline.\n");
 	printf("\nResult format\n");
 	printf("\tResult display uses a common format for each command:\n");
 	printf("\tResults are formatted in text/JSON with\n");
@@ -2918,6 +2981,7 @@ static void cmdline(int argc, char **argv)
 	int oob_mode = 0;
 	int poll_interval = -1;
 	int no_daemon = 0;
+	int mbox_delay = 0, mbox_retries = 3;
 
 	static struct option long_options[] = {
 		{ "all-cpus-online", no_argument, 0, 'a' },
@@ -2933,6 +2997,7 @@ static void cmdline(int argc, char **argv)
 		{ "oob", no_argument, 0, 'b' },
 		{ "no-daemon", no_argument, 0, 'n' },
 		{ "poll-interval", required_argument, 0, 'w' },
+		{ "cgroupv2", required_argument, 0, 'g' },
 		{ 0, 0, 0, 0 }
 	};
 
@@ -2958,8 +3023,12 @@ static void cmdline(int argc, char **argv)
 		fclose(fp);
 	}
 
+	ret = isst_fill_platform_info();
+	if (ret)
+		goto out;
+
 	progname = argv[0];
-	while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:n", long_options,
+	while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:ng", long_options,
 				       &option_index)) != -1) {
 		switch (opt) {
 		case 'a':
@@ -3018,6 +3087,9 @@ static void cmdline(int argc, char **argv)
 			}
 			poll_interval = ret;
 			break;
+		case 'g':
+			cgroupv2 = 1;
+			break;
 		default:
 			usage();
 		}
@@ -3027,6 +3099,10 @@ static void cmdline(int argc, char **argv)
 		usage();
 		exit(0);
 	}
+
+	isst_update_platform_param(ISST_PARAM_MBOX_DELAY, mbox_delay);
+	isst_update_platform_param(ISST_PARAM_MBOX_RETRIES, mbox_retries);
+
 	set_max_cpu_num();
 	if (force_cpus_online)
 		force_all_cpus_online();
@@ -3044,9 +3120,6 @@ static void cmdline(int argc, char **argv)
 	}
 
 	if (!is_clx_n_platform()) {
-		ret = isst_fill_platform_info();
-		if (ret)
-			goto out;
 		process_command(argc, argv, isst_help_cmds, isst_cmds);
 	} else {
 		process_command(argc, argv, clx_n_help_cmds, clx_n_cmds);
diff --git a/tools/power/x86/intel-speed-select/isst-core-mbox.c b/tools/power/x86/intel-speed-select/isst-core-mbox.c
new file mode 100644
index 0000000000000000000000000000000000000000..24bea57f4ff535c78db87b4669a641832772f4a9
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-core-mbox.c
@@ -0,0 +1,1066 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Speed Select -- Enumerate and control features for Mailbox Interface
+ * Copyright (c) 2023 Intel Corporation.
+ */
+#include "isst.h"
+
+static int mbox_delay;
+static int mbox_retries = 3;
+
+#define MAX_TRL_LEVELS_EMR	5
+
+static int mbox_get_disp_freq_multiplier(void)
+{
+        return DISP_FREQ_MULTIPLIER;
+}
+
+static int mbox_get_trl_max_levels(void)
+{
+	if (is_emr_platform())
+		return MAX_TRL_LEVELS_EMR;
+
+        return 3;
+}
+
+static char *mbox_get_trl_level_name(int level)
+{
+	if (is_emr_platform()) {
+		static char level_str[18];
+
+		if (level >= MAX_TRL_LEVELS_EMR)
+			return NULL;
+
+		snprintf(level_str, sizeof(level_str), "level-%d", level);
+		return level_str;
+	}
+
+        switch (level) {
+        case 0:
+                return "sse";
+        case 1:
+                return "avx2";
+        case 2:
+                return "avx512";
+        default:
+                return NULL;
+        }
+}
+
+static void mbox_update_platform_param(enum isst_platform_param param, int value)
+{
+	switch (param) {
+	case ISST_PARAM_MBOX_DELAY:
+		mbox_delay = value;
+		break;
+	case ISST_PARAM_MBOX_RETRIES:
+		mbox_retries = value;
+		break;
+	default:
+		break;
+	}
+}
+
+static int mbox_is_punit_valid(struct isst_id *id)
+{
+	if (id->cpu < 0)
+		return 0;
+
+	if (id->pkg < 0 || id->die < 0 || id->punit)
+		return 0;
+
+	return 1;
+}
+
+static int _send_mmio_command(unsigned int cpu, unsigned int reg, int write,
+				  unsigned int *value)
+{
+	struct isst_if_io_regs io_regs;
+	const char *pathname = "/dev/isst_interface";
+	int cmd;
+	FILE *outf = get_output_file();
+	int fd;
+
+	debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
+
+	fd = open(pathname, O_RDWR);
+	if (fd < 0)
+		err(-1, "%s open failed", pathname);
+
+	io_regs.req_count = 1;
+	io_regs.io_reg[0].logical_cpu = cpu;
+	io_regs.io_reg[0].reg = reg;
+	cmd = ISST_IF_IO_CMD;
+	if (write) {
+		io_regs.io_reg[0].read_write = 1;
+		io_regs.io_reg[0].value = *value;
+	} else {
+		io_regs.io_reg[0].read_write = 0;
+	}
+
+	if (ioctl(fd, cmd, &io_regs) == -1) {
+		if (errno == ENOTTY) {
+			perror("ISST_IF_IO_COMMAND\n");
+			fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
+			exit(0);
+		}
+		fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
+			cpu, reg, write);
+	} else {
+		if (!write)
+			*value = io_regs.io_reg[0].value;
+
+		debug_printf(
+			"mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
+			cpu, reg, write, *value);
+	}
+
+	close(fd);
+
+	return 0;
+}
+
+int _send_mbox_command(unsigned int cpu, unsigned char command,
+			   unsigned char sub_command, unsigned int parameter,
+			   unsigned int req_data, unsigned int *resp)
+{
+	const char *pathname = "/dev/isst_interface";
+	int fd, retry;
+	struct isst_if_mbox_cmds mbox_cmds = { 0 };
+
+	debug_printf(
+		"mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
+		cpu, command, sub_command, parameter, req_data);
+
+	if (!is_skx_based_platform() && command == CONFIG_CLOS &&
+	    sub_command != CLOS_PM_QOS_CONFIG) {
+		unsigned int value;
+		int write = 0;
+		int clos_id, core_id, ret = 0;
+
+		debug_printf("CPU %d\n", cpu);
+
+		if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
+			value = req_data;
+			write = 1;
+		}
+
+		switch (sub_command) {
+		case CLOS_PQR_ASSOC:
+			core_id = parameter & 0xff;
+			ret = _send_mmio_command(
+				cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
+				&value);
+			if (!ret && !write)
+				*resp = value;
+			break;
+		case CLOS_PM_CLOS:
+			clos_id = parameter & 0x03;
+			ret = _send_mmio_command(
+				cpu, PM_CLOS_OFFSET + clos_id * 4, write,
+				&value);
+			if (!ret && !write)
+				*resp = value;
+			break;
+		case CLOS_STATUS:
+			break;
+		default:
+			break;
+		}
+		return ret;
+	}
+
+	mbox_cmds.cmd_count = 1;
+	mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
+	mbox_cmds.mbox_cmd[0].command = command;
+	mbox_cmds.mbox_cmd[0].sub_command = sub_command;
+	mbox_cmds.mbox_cmd[0].parameter = parameter;
+	mbox_cmds.mbox_cmd[0].req_data = req_data;
+
+	if (mbox_delay)
+		usleep(mbox_delay * 1000);
+
+	fd = open(pathname, O_RDWR);
+	if (fd < 0)
+		err(-1, "%s open failed", pathname);
+
+	retry = mbox_retries;
+	do {
+		if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
+			if (errno == ENOTTY) {
+				perror("ISST_IF_MBOX_COMMAND\n");
+				fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
+				exit(0);
+			}
+			debug_printf(
+				"Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
+				cpu, command, sub_command, parameter, req_data, errno);
+			--retry;
+		} else {
+			*resp = mbox_cmds.mbox_cmd[0].resp_data;
+			debug_printf(
+				"mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
+				cpu, command, sub_command, parameter, req_data, *resp);
+			break;
+		}
+	} while (retry);
+
+	close(fd);
+
+	if (!retry) {
+		debug_printf("Failed mbox command even after retries\n");
+		return -1;
+
+	}
+
+	return 0;
+}
+
+static int mbox_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
+{
+	unsigned int resp;
+	int ret;
+
+	ret = _send_mbox_command(id->cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
+					&resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", id->cpu, resp);
+
+	*cp_state = resp & BIT(16);
+	*cp_cap = resp & BIT(0) ? 1 : 0;
+
+	return 0;
+}
+
+static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
+{
+	unsigned int resp;
+	int ret;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
+	if (ret) {
+		pkg_dev->levels = 0;
+		pkg_dev->locked = 1;
+		pkg_dev->current_level = 0;
+		pkg_dev->version = 0;
+		pkg_dev->enabled = 0;
+		return 0;
+	}
+
+	debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
+
+	pkg_dev->version = resp & 0xff;
+	pkg_dev->levels = (resp >> 8) & 0xff;
+	pkg_dev->current_level = (resp >> 16) & 0xff;
+	pkg_dev->locked = !!(resp & BIT(24));
+	pkg_dev->enabled = !!(resp & BIT(31));
+
+	return 0;
+}
+
+static int mbox_get_ctdp_control(struct isst_id *id, int config_index,
+			  struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	int cp_state, cp_cap;
+	unsigned int resp;
+	int ret;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_GET_TDP_CONTROL, 0,
+				     config_index, &resp);
+	if (ret)
+		return ret;
+
+	ctdp_level->fact_support = resp & BIT(0);
+	ctdp_level->pbf_support = !!(resp & BIT(1));
+	ctdp_level->fact_enabled = !!(resp & BIT(16));
+	ctdp_level->pbf_enabled = !!(resp & BIT(17));
+
+	ret = isst_read_pm_config(id, &cp_state, &cp_cap);
+	if (ret) {
+		debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
+	} else {
+		debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
+		ctdp_level->sst_cp_support = cp_cap;
+		ctdp_level->sst_cp_enabled = cp_state;
+	}
+
+	debug_printf(
+		"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
+		id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
+		ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
+
+	return 0;
+}
+
+static void _get_uncore_p0_p1_info(struct isst_id *id, int config_index,
+				struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	unsigned int resp;
+	int ret;
+
+	ctdp_level->uncore_pm = 0;
+	ctdp_level->uncore_p0 = 0;
+	ctdp_level->uncore_p1 = 0;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_GET_RATIO_INFO, 0,
+				     (BIT(16) | config_index) , &resp);
+	if (ret) {
+		goto try_uncore_mbox;
+	}
+
+	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
+	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
+	ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24;
+
+	debug_printf(
+		"cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n",
+		id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1,
+		ctdp_level->uncore_pm);
+
+	return;
+
+try_uncore_mbox:
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
+				     config_index, &resp);
+	if (ret) {
+		ctdp_level->uncore_p0 = 0;
+		ctdp_level->uncore_p1 = 0;
+		return;
+	}
+
+	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
+	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
+	debug_printf(
+		"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
+		id->cpu, config_index, resp, ctdp_level->uncore_p0,
+		ctdp_level->uncore_p1);
+}
+
+static int _set_uncore_min_max(struct isst_id *id, int max, int freq)
+{
+	char buffer[128], freq_str[16];
+	int fd, ret, len;
+
+	if (max)
+		snprintf(buffer, sizeof(buffer),
+			 "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/max_freq_khz", id->pkg, id->die);
+	else
+	        snprintf(buffer, sizeof(buffer),
+			 "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/min_freq_khz", id->pkg, id->die);
+
+	fd = open(buffer, O_WRONLY);
+	if (fd < 0)
+		return fd;
+
+	snprintf(freq_str, sizeof(freq_str), "%d", freq);
+	len = strlen(freq_str);
+	ret = write(fd, freq_str, len);
+	if (ret == -1) {
+		close(fd);
+		return ret;
+	}
+	close(fd);
+
+	return 0;
+}
+
+static void mbox_adjust_uncore_freq(struct isst_id *id, int config_index,
+				struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	_get_uncore_p0_p1_info(id, config_index, ctdp_level);
+	if (ctdp_level->uncore_pm)
+		_set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
+
+	if (ctdp_level->uncore_p0)
+		_set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
+}
+
+static void _get_p1_info(struct isst_id *id, int config_index,
+		      struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	unsigned int resp;
+	int ret;
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
+				     config_index, &resp);
+	if (ret) {
+		ctdp_level->sse_p1 = 0;
+		ctdp_level->avx2_p1 = 0;
+		ctdp_level->avx512_p1 = 0;
+		return;
+	}
+
+	ctdp_level->sse_p1 = resp & GENMASK(7, 0);
+	ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
+	ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
+	ctdp_level->amx_p1 = (resp & GENMASK(31, 24)) >> 24;
+	debug_printf(
+		"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d amx_p1:%d\n",
+		id->cpu, config_index, resp, ctdp_level->sse_p1,
+		ctdp_level->avx2_p1, ctdp_level->avx512_p1, ctdp_level->amx_p1);
+}
+
+static void _get_uncore_mem_freq(struct isst_id *id, int config_index,
+			      struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	unsigned int resp;
+	int ret;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
+				     0, config_index, &resp);
+	if (ret) {
+		ctdp_level->mem_freq = 0;
+		return;
+	}
+
+	ctdp_level->mem_freq = resp & GENMASK(7, 0);
+	if (is_spr_platform() || is_emr_platform()) {
+		ctdp_level->mem_freq *= 200;
+	} else if (is_icx_platform()) {
+		if (ctdp_level->mem_freq < 7) {
+			ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
+			ctdp_level->mem_freq /= 10;
+			if (ctdp_level->mem_freq % 10 > 5)
+				ctdp_level->mem_freq++;
+		} else {
+			ctdp_level->mem_freq = 0;
+		}
+	} else {
+		ctdp_level->mem_freq = 0;
+	}
+	debug_printf(
+		"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
+		id->cpu, config_index, resp, ctdp_level->mem_freq);
+}
+
+static int mbox_get_tdp_info(struct isst_id *id, int config_index,
+		      struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	unsigned int resp;
+	int ret;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
+				     0, config_index, &resp);
+	if (ret) {
+		isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
+		return ret;
+	}
+
+	ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
+	ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
+
+	debug_printf(
+		"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
+		id->cpu, config_index, resp, ctdp_level->tdp_ratio,
+		ctdp_level->pkg_tdp);
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
+				     0, config_index, &resp);
+	if (ret)
+		return ret;
+
+	ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
+
+	_get_uncore_p0_p1_info(id, config_index, ctdp_level);
+	_get_p1_info(id, config_index, ctdp_level);
+	_get_uncore_mem_freq(id, config_index, ctdp_level);
+
+	debug_printf(
+		"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
+		id->cpu, config_index, resp, ctdp_level->t_proc_hot);
+
+	return 0;
+}
+
+static int mbox_get_pwr_info(struct isst_id *id, int config_index,
+		      struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	unsigned int resp;
+	int ret;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
+				     0, config_index, &resp);
+	if (ret)
+		return ret;
+
+	ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
+	ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
+
+	debug_printf(
+		"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
+		id->cpu, config_index, resp, ctdp_level->pkg_max_power,
+		ctdp_level->pkg_min_power);
+
+	return 0;
+}
+
+static int mbox_get_coremask_info(struct isst_id *id, int config_index,
+			   struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	unsigned int resp;
+	int i, ret;
+
+	ctdp_level->cpu_count = 0;
+	for (i = 0; i < 2; ++i) {
+		unsigned long long mask;
+		int cpu_count = 0;
+
+		ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+					     CONFIG_TDP_GET_CORE_MASK, 0,
+					     (i << 8) | config_index, &resp);
+		if (ret)
+			return ret;
+
+		debug_printf(
+			"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
+			id->cpu, config_index, i, resp);
+
+		mask = (unsigned long long)resp << (32 * i);
+		set_cpu_mask_from_punit_coremask(id, mask,
+						 ctdp_level->core_cpumask_size,
+						 ctdp_level->core_cpumask,
+						 &cpu_count);
+		ctdp_level->cpu_count += cpu_count;
+		debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
+			     config_index, i, ctdp_level->cpu_count);
+	}
+
+	return 0;
+}
+
+static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
+{
+	unsigned int req, resp;
+	int ret;
+
+	req = level | (avx_level << 16);
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
+				     &resp);
+	if (ret)
+		return ret;
+
+	debug_printf(
+		"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
+		id->cpu, req, resp);
+
+	trl[0] = resp & GENMASK(7, 0);
+	trl[1] = (resp & GENMASK(15, 8)) >> 8;
+	trl[2] = (resp & GENMASK(23, 16)) >> 16;
+	trl[3] = (resp & GENMASK(31, 24)) >> 24;
+
+	req = level | BIT(8) | (avx_level << 16);
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
+				     &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
+		     req, resp);
+
+	trl[4] = resp & GENMASK(7, 0);
+	trl[5] = (resp & GENMASK(15, 8)) >> 8;
+	trl[6] = (resp & GENMASK(23, 16)) >> 16;
+	trl[7] = (resp & GENMASK(31, 24)) >> 24;
+
+	return 0;
+}
+
+static int mbox_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	int trl_max_levels = isst_get_trl_max_levels();
+	int i, ret;
+
+	for (i = 0; i < trl_max_levels; i++) {
+		ret = mbox_get_get_trl(id, level, i, ctdp_level->trl_ratios[i]);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
+{
+	int ret;
+
+	debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
+
+	*buckets_info = 0;
+
+	ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
+		     *buckets_info);
+
+	return 0;
+}
+
+static int mbox_set_tdp_level(struct isst_id *id, int tdp_level)
+{
+	unsigned int resp;
+	int ret;
+
+
+	if (isst_get_config_tdp_lock_status(id)) {
+		isst_display_error_info_message(1, "TDP is locked", 0, 0);
+		return -1;
+
+	}
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
+				     tdp_level, &resp);
+	if (ret) {
+		isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
+{
+	int max_punit_core, max_mask_index;
+	unsigned int req, resp;
+	int i, ret;
+
+	max_punit_core = get_max_punit_core_id(id);
+	max_mask_index = max_punit_core > 32 ? 2 : 1;
+
+	for (i = 0; i < max_mask_index; ++i) {
+		unsigned long long mask;
+		int count;
+
+		ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+					     CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
+					     0, (i << 8) | level, &resp);
+		if (ret)
+			break;
+
+		debug_printf(
+			"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
+			id->cpu, resp);
+
+		mask = (unsigned long long)resp << (32 * i);
+		set_cpu_mask_from_punit_coremask(id, mask,
+						 pbf_info->core_cpumask_size,
+						 pbf_info->core_cpumask,
+						 &count);
+	}
+
+	req = level;
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
+				     &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
+		     resp);
+
+	pbf_info->p1_low = resp & 0xff;
+	pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
+
+	req = level;
+	ret = _send_mbox_command(
+		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);
+
+	pbf_info->tdp = resp & 0xffff;
+
+	req = level;
+	ret = _send_mbox_command(
+		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,
+		     resp);
+	pbf_info->t_control = (resp >> 8) & 0xff;
+	pbf_info->t_prochot = resp & 0xff;
+
+	return 0;
+}
+
+static int mbox_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
+{
+	struct isst_pkg_ctdp pkg_dev;
+	struct isst_pkg_ctdp_level_info ctdp_level;
+	int current_level;
+	unsigned int req = 0, resp;
+	int ret;
+
+	ret = isst_get_ctdp_levels(id, &pkg_dev);
+	if (ret)
+		debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
+
+	current_level = pkg_dev.current_level;
+
+	ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
+	if (ret)
+		return ret;
+
+	if (pbf) {
+		if (ctdp_level.fact_enabled)
+			req = BIT(16);
+
+		if (enable)
+			req |= BIT(17);
+		else
+			req &= ~BIT(17);
+	} else {
+
+		if (enable && !ctdp_level.sst_cp_enabled)
+			isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
+
+		if (ctdp_level.pbf_enabled)
+			req = BIT(17);
+
+		if (enable)
+			req |= BIT(16);
+		else
+			req &= ~BIT(16);
+	}
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
+		     id->cpu, pbf, req);
+
+	return 0;
+}
+
+static int _get_fact_bucket_info(struct isst_id *id, int level,
+			      struct isst_fact_bucket_info *bucket_info)
+{
+	unsigned int resp;
+	int i, k, ret;
+
+	for (i = 0; i < 2; ++i) {
+		int j;
+
+		ret = _send_mbox_command(
+			id->cpu, CONFIG_TDP,
+			CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
+			(i << 8) | level, &resp);
+		if (ret)
+			return ret;
+
+		debug_printf(
+			"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
+			id->cpu, i, level, resp);
+
+		for (j = 0; j < 4; ++j) {
+			bucket_info[j + (i * 4)].hp_cores =
+				(resp >> (j * 8)) & 0xff;
+		}
+	}
+
+	for (k = 0; k < 3; ++k) {
+		for (i = 0; i < 2; ++i) {
+			int j;
+
+			ret = _send_mbox_command(
+				id->cpu, CONFIG_TDP,
+				CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
+				(k << 16) | (i << 8) | level, &resp);
+			if (ret)
+				return ret;
+
+			debug_printf(
+				"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
+				id->cpu, i, level, k, resp);
+
+			for (j = 0; j < 4; ++j) {
+				bucket_info[j + (i * 4)].hp_ratios[k] =
+					(resp >> (j * 8)) & 0xff;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
+{
+	unsigned int resp;
+	int j, ret, print;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+				     CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
+				     level, &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
+		     id->cpu, resp);
+
+	fact_info->lp_ratios[0] = resp & 0xff;
+	fact_info->lp_ratios[1] = (resp >> 8) & 0xff;
+	fact_info->lp_ratios[2] = (resp >> 16) & 0xff;
+
+	ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);
+	if (ret)
+		return ret;
+
+	print = 0;
+	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
+		if (fact_bucket != 0xff && fact_bucket != j)
+			continue;
+
+		if (!fact_info->bucket_info[j].hp_cores)
+			break;
+
+		print = 1;
+	}
+	if (!print) {
+		isst_display_error_info_message(1, "Invalid bucket", 0, 0);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)
+{
+	unsigned int resp;
+	int ret;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
+				     &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
+
+	if (resp & BIT(1))
+		*enable = 1;
+	else
+		*enable = 0;
+
+	if (resp & BIT(2))
+		*type = 1;
+	else
+		*type = 0;
+
+	return 0;
+}
+
+static int _write_pm_config(struct isst_id *id, int cp_state)
+{
+	unsigned int req, resp;
+	int ret;
+
+	if (cp_state)
+		req = BIT(16);
+	else
+		req = 0;
+
+	ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
+				     &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
+
+	return 0;
+}
+
+static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
+{
+	unsigned int req, resp;
+	int ret;
+
+	if (!enable_clos) {
+		struct isst_pkg_ctdp pkg_dev;
+		struct isst_pkg_ctdp_level_info ctdp_level;
+
+		ret = isst_get_ctdp_levels(id, &pkg_dev);
+		if (ret) {
+			debug_printf("isst_get_ctdp_levels\n");
+			return ret;
+		}
+
+		ret = isst_get_ctdp_control(id, pkg_dev.current_level,
+					    &ctdp_level);
+		if (ret)
+			return ret;
+
+		if (ctdp_level.fact_enabled) {
+			isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
+			return -EINVAL;
+		}
+		ret = _write_pm_config(id, 0);
+		if (ret)
+			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
+	} else {
+		ret = _write_pm_config(id, 1);
+		if (ret)
+			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
+	}
+
+	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
+				     &resp);
+	if (ret) {
+		isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
+		return ret;
+	}
+
+	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
+
+	req = resp;
+
+	if (enable_clos)
+		req = req | BIT(1);
+	else
+		req = req & ~BIT(1);
+
+	if (priority_type > 1)
+		isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
+
+	if (priority_type)
+		req = req | BIT(2);
+	else
+		req = req & ~BIT(2);
+
+	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
+				     BIT(MBOX_CMD_WRITE_BIT), req, &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
+		     priority_type, req);
+
+	return 0;
+}
+
+static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
+{
+	unsigned int resp;
+	int ret;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
+				     &resp);
+	if (ret)
+		return ret;
+
+	clos_config->epp = resp & 0x0f;
+	clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
+	clos_config->clos_min = (resp >> 8) & 0xff;
+	clos_config->clos_max = (resp >> 16) & 0xff;
+	clos_config->clos_desired = (resp >> 24) & 0xff;
+
+	return 0;
+}
+
+static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
+{
+	unsigned int req, resp;
+	unsigned int param;
+	int ret;
+
+	req = clos_config->epp & 0x0f;
+	req |= (clos_config->clos_prop_prio & 0x0f) << 4;
+	req |= (clos_config->clos_min & 0xff) << 8;
+	req |= (clos_config->clos_max & 0xff) << 16;
+	req |= (clos_config->clos_desired & 0xff) << 24;
+
+	param = BIT(MBOX_CMD_WRITE_BIT) | clos;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
+				     &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
+
+	return 0;
+}
+
+static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)
+{
+	unsigned int resp;
+	unsigned int param;
+	int core_id, ret;
+
+	core_id = find_phy_core_num(id->cpu);
+	param = core_id;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
+				     &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
+		     resp);
+	*clos_id = (resp >> 16) & 0x03;
+
+	return 0;
+}
+
+static int mbox_clos_associate(struct isst_id *id, int clos_id)
+{
+	unsigned int req, resp;
+	unsigned int param;
+	int core_id, ret;
+
+	req = (clos_id & 0x03) << 16;
+	core_id = find_phy_core_num(id->cpu);
+	param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
+
+	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
+				     req, &resp);
+	if (ret)
+		return ret;
+
+	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
+		     req);
+
+	return 0;
+}
+
+static struct isst_platform_ops mbox_ops = {
+	.get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
+	.get_trl_max_levels = mbox_get_trl_max_levels,
+	.get_trl_level_name = mbox_get_trl_level_name,
+	.update_platform_param = mbox_update_platform_param,
+	.is_punit_valid = mbox_is_punit_valid,
+	.read_pm_config = mbox_read_pm_config,
+	.get_config_levels = mbox_get_config_levels,
+	.get_ctdp_control = mbox_get_ctdp_control,
+	.get_tdp_info = mbox_get_tdp_info,
+	.get_pwr_info = mbox_get_pwr_info,
+	.get_coremask_info = mbox_get_coremask_info,
+	.get_get_trl = mbox_get_get_trl,
+	.get_get_trls = mbox_get_get_trls,
+	.get_trl_bucket_info = mbox_get_trl_bucket_info,
+	.set_tdp_level = mbox_set_tdp_level,
+	.get_pbf_info = mbox_get_pbf_info,
+	.set_pbf_fact_status = mbox_set_pbf_fact_status,
+	.get_fact_info = mbox_get_fact_info,
+	.adjust_uncore_freq = mbox_adjust_uncore_freq,
+	.get_clos_information = mbox_get_clos_information,
+	.pm_qos_config = mbox_pm_qos_config,
+	.pm_get_clos = mbox_pm_get_clos,
+	.set_clos = mbox_set_clos,
+	.clos_get_assoc_status = mbox_clos_get_assoc_status,
+	.clos_associate = mbox_clos_associate,
+};
+
+struct isst_platform_ops *mbox_get_platform_ops(void)
+{
+	return &mbox_ops;
+}
diff --git a/tools/power/x86/intel-speed-select/isst-core-tpmi.c b/tools/power/x86/intel-speed-select/isst-core-tpmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..19caa9c78d413dac3e72be0b8e0806e90c4b96ce
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-core-tpmi.c
@@ -0,0 +1,787 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Speed Select -- Enumerate and control features for TPMI Interface
+ * Copyright (c) 2022 Intel Corporation.
+ */
+
+#include <linux/isst_if.h>
+#include "isst.h"
+
+int tpmi_process_ioctl(int ioctl_no, void *info)
+{
+	const char *pathname = "/dev/isst_interface";
+	int fd;
+
+	if (is_debug_enabled()) {
+		debug_printf("Issue IOCTL: ");
+		switch (ioctl_no) {
+		case ISST_IF_CORE_POWER_STATE:
+			debug_printf("ISST_IF_CORE_POWER_STATE\n");
+			break;
+		case ISST_IF_CLOS_PARAM:
+			debug_printf("ISST_IF_CLOS_PARAM\n");
+			break;
+		case ISST_IF_CLOS_ASSOC:
+			debug_printf("ISST_IF_CLOS_ASSOC\n");
+			break;
+		case ISST_IF_PERF_LEVELS:
+			debug_printf("ISST_IF_PERF_LEVELS\n");
+			break;
+		case ISST_IF_PERF_SET_LEVEL:
+			debug_printf("ISST_IF_PERF_SET_LEVEL\n");
+			break;
+		case ISST_IF_PERF_SET_FEATURE:
+			debug_printf("ISST_IF_PERF_SET_FEATURE\n");
+			break;
+		case ISST_IF_GET_PERF_LEVEL_INFO:
+			debug_printf("ISST_IF_GET_PERF_LEVEL_INFO\n");
+			break;
+		case ISST_IF_GET_PERF_LEVEL_CPU_MASK:
+			debug_printf("ISST_IF_GET_PERF_LEVEL_CPU_MASK\n");
+			break;
+		case ISST_IF_GET_BASE_FREQ_INFO:
+			debug_printf("ISST_IF_GET_BASE_FREQ_INFO\n");
+			break;
+		case ISST_IF_GET_BASE_FREQ_CPU_MASK:
+			debug_printf("ISST_IF_GET_BASE_FREQ_CPU_MASK\n");
+			break;
+		case ISST_IF_GET_TURBO_FREQ_INFO:
+			debug_printf("ISST_IF_GET_TURBO_FREQ_INFO\n");
+			break;
+		case ISST_IF_COUNT_TPMI_INSTANCES:
+			debug_printf("ISST_IF_COUNT_TPMI_INSTANCES\n");
+			break;
+		default:
+			debug_printf("%d\n", ioctl_no);
+			break;
+		}
+	}
+
+	fd = open(pathname, O_RDWR);
+	if (fd < 0)
+		return -1;
+
+	if (ioctl(fd, ioctl_no, info) == -1) {
+		debug_printf("IOCTL %d Failed\n", ioctl_no);
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+
+	return 0;
+}
+
+static int tpmi_get_disp_freq_multiplier(void)
+{
+	return 1;
+}
+
+static int tpmi_get_trl_max_levels(void)
+{
+	return TRL_MAX_LEVELS;
+}
+
+static char *tpmi_get_trl_level_name(int level)
+{
+	switch (level) {
+	case 0:
+		return "level-0";
+	case 1:
+		return "level-1";
+	case 2:
+		return "level-2";
+	case 3:
+		return "level-3";
+	case 4:
+		return "level-4";
+	case 5:
+		return "level-5";
+	case 6:
+		return "level-6";
+	case 7:
+		return "level-7";
+	default:
+		return NULL;
+	}
+}
+
+
+static void tpmi_update_platform_param(enum isst_platform_param param, int value)
+{
+	/* No params need to be updated for now */
+}
+
+static int tpmi_is_punit_valid(struct isst_id *id)
+{
+	struct isst_tpmi_instance_count info;
+	int ret;
+
+	if (id->punit < 0)
+		return 0;
+
+	info.socket_id = id->pkg;
+	ret = tpmi_process_ioctl(ISST_IF_COUNT_TPMI_INSTANCES, &info);
+	if (ret == -1)
+		return 0;
+
+	if (info.valid_mask & BIT(id->punit))
+		return 1;
+
+	return 0;
+}
+
+static int tpmi_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
+{
+	struct isst_core_power info;
+	int ret;
+
+	info.get_set = 0;
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
+	if (ret == -1)
+		return ret;
+
+	*cp_state = info.enable;
+	*cp_cap = info.supported;
+
+	return 0;
+}
+
+int tpmi_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
+{
+	struct isst_perf_level_info info;
+	int ret;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+
+	ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
+	if (ret == -1)
+		return ret;
+
+	pkg_dev->version = info.feature_rev;
+	pkg_dev->levels = info.max_level;
+	pkg_dev->locked = info.locked;
+	pkg_dev->current_level = info.current_level;
+	pkg_dev->locked = info.locked;
+	pkg_dev->enabled = info.enabled;
+
+	return 0;
+}
+
+static int tpmi_get_ctdp_control(struct isst_id *id, int config_index,
+				 struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	struct isst_core_power core_power_info;
+	struct isst_perf_level_info info;
+	int level_mask;
+	int ret;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+
+	ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
+	if (ret == -1)
+		return -1;
+
+	if (config_index != 0xff)
+		level_mask = 1 << config_index;
+	else
+		level_mask = config_index;
+
+	if (!(info.level_mask & level_mask))
+		return -1;
+
+	ctdp_level->fact_support = info.sst_tf_support;
+	ctdp_level->pbf_support = info.sst_bf_support;
+	ctdp_level->fact_enabled = !!(info.feature_state & BIT(1));
+	ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0));
+
+	core_power_info.get_set = 0;
+	core_power_info.socket_id = id->pkg;
+	core_power_info.power_domain_id = id->punit;
+
+	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info);
+	if (ret == -1)
+		return ret;
+
+	ctdp_level->sst_cp_support = core_power_info.supported;
+	ctdp_level->sst_cp_enabled = core_power_info.enable;
+
+	debug_printf
+	    ("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
+	     id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support,
+	     ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
+
+	return 0;
+}
+
+static int tpmi_get_tdp_info(struct isst_id *id, int config_index,
+			     struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	struct isst_perf_level_data_info info;
+	int ret;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = config_index;
+
+	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
+	if (ret == -1)
+		return ret;
+
+	ctdp_level->pkg_tdp = info.thermal_design_power_w;
+	ctdp_level->tdp_ratio = info.tdp_ratio;
+	ctdp_level->sse_p1 = info.base_freq_mhz;
+	ctdp_level->avx2_p1 = info.base_freq_avx2_mhz;
+	ctdp_level->avx512_p1 = info.base_freq_avx512_mhz;
+	ctdp_level->amx_p1 = info.base_freq_amx_mhz;
+
+	ctdp_level->t_proc_hot = info.tjunction_max_c;
+	ctdp_level->mem_freq = info.max_memory_freq_mhz;
+	ctdp_level->cooling_type = info.cooling_type;
+
+	ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
+	ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
+	ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
+
+	debug_printf
+	    ("cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO tdp_ratio:%d pkg_tdp:%d ctdp_level->t_proc_hot:%d\n",
+	     id->cpu, config_index, ctdp_level->tdp_ratio, ctdp_level->pkg_tdp,
+	     ctdp_level->t_proc_hot);
+
+	return 0;
+}
+
+static int tpmi_get_pwr_info(struct isst_id *id, int config_index,
+			     struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	/* TBD */
+	ctdp_level->pkg_max_power = 0;
+	ctdp_level->pkg_min_power = 0;
+
+	debug_printf
+	    ("cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO pkg_max_power:%d pkg_min_power:%d\n",
+	     id->cpu, config_index, ctdp_level->pkg_max_power,
+	     ctdp_level->pkg_min_power);
+
+	return 0;
+}
+
+int tpmi_get_coremask_info(struct isst_id *id, int config_index,
+			   struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	struct isst_perf_level_cpu_mask info;
+	int ret, cpu_count;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = config_index;
+	info.punit_cpu_map = 1;
+
+	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_CPU_MASK, &info);
+	if (ret == -1)
+		return ret;
+
+	set_cpu_mask_from_punit_coremask(id, info.mask,
+					 ctdp_level->core_cpumask_size,
+					 ctdp_level->core_cpumask, &cpu_count);
+	ctdp_level->cpu_count = cpu_count;
+
+	debug_printf("cpu:%d ctdp:%d core_mask ino cpu count:%d\n",
+		     id->cpu, config_index, ctdp_level->cpu_count);
+
+	return 0;
+}
+
+static int tpmi_get_get_trls(struct isst_id *id, int config_index,
+			     struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	struct isst_perf_level_data_info info;
+	int ret, i, j;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = config_index;
+
+	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
+	if (ret == -1)
+		return ret;
+
+	if (info.max_buckets > TRL_MAX_BUCKETS)
+		info.max_buckets = TRL_MAX_BUCKETS;
+
+	if (info.max_trl_levels > TRL_MAX_LEVELS)
+		info.max_trl_levels = TRL_MAX_LEVELS;
+
+	for (i = 0; i < info.max_trl_levels; ++i)
+		for (j = 0; j < info.max_buckets; ++j)
+			ctdp_level->trl_ratios[i][j] = info.trl_freq_mhz[i][j];
+
+	return 0;
+}
+
+static int tpmi_get_get_trl(struct isst_id *id, int level, int config_index,
+			    int *trl)
+{
+	struct isst_pkg_ctdp_level_info ctdp_level;
+	int ret, i;
+
+	ret = tpmi_get_get_trls(id, config_index, &ctdp_level);
+	if (ret)
+		return ret;
+
+	/* FIX ME: Just return for level 0 */
+	for (i = 0; i < 8; ++i)
+		trl[i] = ctdp_level.trl_ratios[0][i];
+
+	return 0;
+}
+
+static int tpmi_get_trl_bucket_info(struct isst_id *id, int config_index,
+				    unsigned long long *buckets_info)
+{
+	struct isst_perf_level_data_info info;
+	unsigned char *mask = (unsigned char *)buckets_info;
+	int ret, i;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = config_index;
+
+	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
+	if (ret == -1)
+		return ret;
+
+	if (info.max_buckets > TRL_MAX_BUCKETS)
+		info.max_buckets = TRL_MAX_BUCKETS;
+
+	for (i = 0; i < info.max_buckets; ++i)
+		mask[i] = info.bucket_core_counts[i];
+
+	debug_printf("cpu:%d TRL bucket info: 0x%llx\n", id->cpu,
+		     *buckets_info);
+
+	return 0;
+}
+
+static int tpmi_set_tdp_level(struct isst_id *id, int tdp_level)
+{
+	struct isst_perf_level_control info;
+	int ret;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = tdp_level;
+
+	ret = tpmi_process_ioctl(ISST_IF_PERF_SET_LEVEL, &info);
+	if (ret == -1)
+		return ret;
+
+	return 0;
+}
+
+static int _pbf_get_coremask_info(struct isst_id *id, int config_index,
+				  struct isst_pbf_info *pbf_info)
+{
+	struct isst_perf_level_cpu_mask info;
+	int ret, cpu_count;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = config_index;
+	info.punit_cpu_map = 1;
+
+	ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_CPU_MASK, &info);
+	if (ret == -1)
+		return ret;
+
+	set_cpu_mask_from_punit_coremask(id, info.mask,
+					 pbf_info->core_cpumask_size,
+					 pbf_info->core_cpumask, &cpu_count);
+
+	debug_printf("cpu:%d ctdp:%d pbf core_mask info cpu count:%d\n",
+		     id->cpu, config_index, cpu_count);
+
+	return 0;
+}
+
+static int tpmi_get_pbf_info(struct isst_id *id, int level,
+			     struct isst_pbf_info *pbf_info)
+{
+	struct isst_base_freq_info info;
+	int ret;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = level;
+
+	ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_INFO, &info);
+	if (ret == -1)
+		return ret;
+
+	pbf_info->p1_low = info.low_base_freq_mhz;
+	pbf_info->p1_high = info.high_base_freq_mhz;
+	pbf_info->tdp = info.thermal_design_power_w;
+	pbf_info->t_prochot = info.tjunction_max_c;
+
+	debug_printf("cpu:%d ctdp:%d pbf info:%d:%d:%d:%d\n",
+		     id->cpu, level, pbf_info->p1_low, pbf_info->p1_high,
+		     pbf_info->tdp, pbf_info->t_prochot);
+
+	return _pbf_get_coremask_info(id, level, pbf_info);
+}
+
+static int tpmi_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
+{
+	struct isst_pkg_ctdp pkg_dev;
+	struct isst_pkg_ctdp_level_info ctdp_level;
+	int current_level;
+	struct isst_perf_feature_control info;
+	int ret;
+
+	ret = isst_get_ctdp_levels(id, &pkg_dev);
+	if (ret)
+		debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
+
+	current_level = pkg_dev.current_level;
+
+	ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
+	if (ret)
+		return ret;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+
+	info.feature = 0;
+
+	if (pbf) {
+		if (ctdp_level.fact_enabled)
+			info.feature |= BIT(1);
+
+		if (enable)
+			info.feature |= BIT(0);
+		else
+			info.feature &= ~BIT(0);
+	} else {
+
+		if (enable && !ctdp_level.sst_cp_enabled)
+			isst_display_error_info_message(0,
+							"Make sure to execute before: core-power enable",
+							0, 0);
+
+		if (ctdp_level.pbf_enabled)
+			info.feature |= BIT(0);
+
+		if (enable)
+			info.feature |= BIT(1);
+		else
+			info.feature &= ~BIT(1);
+	}
+
+	ret = tpmi_process_ioctl(ISST_IF_PERF_SET_FEATURE, &info);
+	if (ret == -1)
+		return ret;
+
+	return 0;
+}
+
+static int tpmi_get_fact_info(struct isst_id *id, int level, int fact_bucket,
+			      struct isst_fact_info *fact_info)
+{
+	struct isst_turbo_freq_info info;
+	int i, j;
+	int ret;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = level;
+
+	ret = tpmi_process_ioctl(ISST_IF_GET_TURBO_FREQ_INFO, &info);
+	if (ret == -1)
+		return ret;
+
+	for (i = 0; i < info.max_clip_freqs; ++i)
+		fact_info->lp_ratios[i] = info.lp_clip_freq_mhz[i];
+
+	if (info.max_buckets > TRL_MAX_BUCKETS)
+		info.max_buckets = TRL_MAX_BUCKETS;
+
+	if (info.max_trl_levels > TRL_MAX_LEVELS)
+		info.max_trl_levels = TRL_MAX_LEVELS;
+
+	for (i = 0; i < info.max_trl_levels; ++i) {
+		for (j = 0; j < info.max_buckets; ++j)
+			fact_info->bucket_info[j].hp_ratios[i] =
+			    info.trl_freq_mhz[i][j];
+	}
+
+	for (i = 0; i < info.max_buckets; ++i)
+		fact_info->bucket_info[i].hp_cores = info.bucket_core_counts[i];
+
+	return 0;
+}
+
+static void _set_uncore_min_max(struct isst_id *id, int max, int freq)
+{
+	DIR *dir;
+	FILE *filep;
+	struct dirent *entry;
+	char buffer[512];
+	unsigned int tmp_id;
+	int ret;
+
+	dir = opendir("/sys/devices/system/cpu/intel_uncore_frequency/");
+	if (!dir)
+		return;
+
+	while ((entry = readdir(dir)) != NULL ) {
+		/* Check domain_id */
+		snprintf(buffer, sizeof(buffer),
+			 "/sys/devices/system/cpu/intel_uncore_frequency/%s/domain_id", entry->d_name);
+
+		filep = fopen(buffer, "r");
+		if (!filep)
+			goto end;
+
+		ret = fscanf(filep, "%u", &tmp_id);
+		fclose(filep);
+		if (ret != 1)
+			goto end;
+
+		if (tmp_id != id->punit)
+			continue;
+
+		/* Check package_id */
+		snprintf(buffer, sizeof(buffer),
+			 "/sys/devices/system/cpu/intel_uncore_frequency/%s/package_id", entry->d_name);
+
+		filep = fopen(buffer, "r");
+		if (!filep)
+			goto end;
+
+		ret = fscanf(filep, "%u", &tmp_id);
+		fclose(filep);
+
+		if (ret != 1)
+			goto end;
+
+		if (tmp_id != id->pkg)
+			continue;
+
+		/* Found the right sysfs path, adjust and quit */
+		if (max)
+			snprintf(buffer, sizeof(buffer),
+				 "/sys/devices/system/cpu/intel_uncore_frequency/%s/max_freq_khz", entry->d_name);
+		 else
+			snprintf(buffer, sizeof(buffer),
+				 "/sys/devices/system/cpu/intel_uncore_frequency/%s/min_freq_khz", entry->d_name);
+
+		filep = fopen(buffer, "w");
+		if (!filep)
+			goto end;
+
+		fprintf(filep, "%d\n", freq);
+		fclose(filep);
+		break;
+	}
+
+end:
+	closedir(dir);
+}
+
+static void tpmi_adjust_uncore_freq(struct isst_id *id, int config_index,
+				struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	struct isst_perf_level_data_info info;
+	int ret;
+
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.level = config_index;
+
+	ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
+	if (ret == -1)
+		return;
+
+	ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
+	ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
+	ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
+
+	if (ctdp_level->uncore_pm)
+		_set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
+
+	if (ctdp_level->uncore_p0)
+		_set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
+
+	return;
+}
+
+static int tpmi_get_clos_information(struct isst_id *id, int *enable, int *type)
+{
+	struct isst_core_power info;
+	int ret;
+
+	info.get_set = 0;
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
+	if (ret == -1)
+		return ret;
+
+	*enable = info.enable;
+	*type = info.priority_type;
+
+	return 0;
+}
+
+static int tpmi_pm_qos_config(struct isst_id *id, int enable_clos,
+			      int priority_type)
+{
+	struct isst_core_power info;
+	int ret;
+
+	info.get_set = 1;
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.enable = enable_clos;
+	info.priority_type = priority_type;
+	ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
+	if (ret == -1)
+		return ret;
+
+	return 0;
+}
+
+int tpmi_pm_get_clos(struct isst_id *id, int clos,
+		     struct isst_clos_config *clos_config)
+{
+	struct isst_clos_param info;
+	int ret;
+
+	info.get_set = 0;
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.clos = clos;
+
+	ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
+	if (ret == -1)
+		return ret;
+
+	clos_config->epp = 0;
+	clos_config->clos_prop_prio = info.prop_prio;
+	clos_config->clos_min = info.min_freq_mhz;
+	clos_config->clos_max = info.max_freq_mhz;
+	clos_config->clos_desired = 0;
+
+	debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
+		     clos_config->clos_min, clos_config->clos_max);
+
+	return 0;
+}
+
+int tpmi_set_clos(struct isst_id *id, int clos,
+		  struct isst_clos_config *clos_config)
+{
+	struct isst_clos_param info;
+	int ret;
+
+	info.get_set = 1;
+	info.socket_id = id->pkg;
+	info.power_domain_id = id->punit;
+	info.clos = clos;
+	info.prop_prio = clos_config->clos_prop_prio;
+
+	info.min_freq_mhz = clos_config->clos_min;
+	info.max_freq_mhz = clos_config->clos_max;
+
+	if (info.min_freq_mhz <= 0xff)
+		info.min_freq_mhz *= 100;
+	if (info.max_freq_mhz <= 0xff)
+		info.max_freq_mhz *= 100;
+
+	ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
+	if (ret == -1)
+		return ret;
+
+	debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
+		     clos_config->clos_min, clos_config->clos_max);
+
+	return 0;
+}
+
+static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id)
+{
+	struct isst_if_clos_assoc_cmds assoc_cmds;
+	int ret;
+
+	assoc_cmds.cmd_count = 1;
+	assoc_cmds.get_set = 0;
+	assoc_cmds.punit_cpu_map = 1;
+	assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
+	assoc_cmds.assoc_info[0].socket_id = id->pkg;
+	assoc_cmds.assoc_info[0].power_domain_id = id->punit;
+
+	ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
+	if (ret == -1)
+		return ret;
+
+	*clos_id = assoc_cmds.assoc_info[0].clos;
+
+	return 0;
+}
+
+static int tpmi_clos_associate(struct isst_id *id, int clos_id)
+{
+	struct isst_if_clos_assoc_cmds assoc_cmds;
+	int ret;
+
+	assoc_cmds.cmd_count = 1;
+	assoc_cmds.get_set = 1;
+	assoc_cmds.punit_cpu_map = 1;
+	assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
+	assoc_cmds.assoc_info[0].clos = clos_id;
+	assoc_cmds.assoc_info[0].socket_id = id->pkg;
+	assoc_cmds.assoc_info[0].power_domain_id = id->punit;
+
+	ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
+	if (ret == -1)
+		return ret;
+
+	return 0;
+}
+
+static struct isst_platform_ops tpmi_ops = {
+	.get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier,
+	.get_trl_max_levels = tpmi_get_trl_max_levels,
+	.get_trl_level_name = tpmi_get_trl_level_name,
+	.update_platform_param = tpmi_update_platform_param,
+	.is_punit_valid = tpmi_is_punit_valid,
+	.read_pm_config = tpmi_read_pm_config,
+	.get_config_levels = tpmi_get_config_levels,
+	.get_ctdp_control = tpmi_get_ctdp_control,
+	.get_tdp_info = tpmi_get_tdp_info,
+	.get_pwr_info = tpmi_get_pwr_info,
+	.get_coremask_info = tpmi_get_coremask_info,
+	.get_get_trl = tpmi_get_get_trl,
+	.get_get_trls = tpmi_get_get_trls,
+	.get_trl_bucket_info = tpmi_get_trl_bucket_info,
+	.set_tdp_level = tpmi_set_tdp_level,
+	.get_pbf_info = tpmi_get_pbf_info,
+	.set_pbf_fact_status = tpmi_set_pbf_fact_status,
+	.get_fact_info = tpmi_get_fact_info,
+	.adjust_uncore_freq = tpmi_adjust_uncore_freq,
+	.get_clos_information = tpmi_get_clos_information,
+	.pm_qos_config = tpmi_pm_qos_config,
+	.pm_get_clos = tpmi_pm_get_clos,
+	.set_clos = tpmi_set_clos,
+	.clos_get_assoc_status = tpmi_clos_get_assoc_status,
+	.clos_associate = tpmi_clos_associate,
+};
+
+struct isst_platform_ops *tpmi_get_platform_ops(void)
+{
+	return &tpmi_ops;
+}
diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c
index 2bfc118c4b87156d9c20a2cb720d67f74c9048c1..f55fef4c13a7a34fcce5ff4d3190b47982ba5a14 100644
--- a/tools/power/x86/intel-speed-select/isst-core.c
+++ b/tools/power/x86/intel-speed-select/isst-core.c
@@ -6,304 +6,141 @@
 
 #include "isst.h"
 
-int isst_write_pm_config(struct isst_id *id, int cp_state)
-{
-	unsigned int req, resp;
-	int ret;
-
-	if (cp_state)
-		req = BIT(16);
-	else
-		req = 0;
-
-	ret = isst_send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
-				     &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
+static struct isst_platform_ops		*isst_ops;
+
+#define CHECK_CB(_name)	\
+	do {	\
+		if (!isst_ops || !isst_ops->_name) {	\
+			fprintf(stderr, "Invalid ops\n");	\
+			exit(0);	\
+		}	\
+	} while (0)
+
+int isst_set_platform_ops(int api_version)
+{
+	switch (api_version) {
+	case 1:
+		isst_ops = mbox_get_platform_ops();
+		break;
+	case 2:
+		isst_ops = tpmi_get_platform_ops();
+		break;
+	default:
+		isst_ops = NULL;
+		break;
+	}
 
+	if (!isst_ops)
+		return -1;
 	return 0;
 }
 
-int isst_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
+void isst_update_platform_param(enum isst_platform_param param, int value)
 {
-	unsigned int resp;
-	int ret;
-
-	ret = isst_send_mbox_command(id->cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
-				     &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", id->cpu, resp);
+	CHECK_CB(update_platform_param);
 
-	*cp_state = resp & BIT(16);
-	*cp_cap = resp & BIT(0) ? 1 : 0;
-
-	return 0;
+	isst_ops->update_platform_param(param, value);
 }
 
-int isst_get_ctdp_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
+int isst_get_disp_freq_multiplier(void)
 {
-	unsigned int resp;
-	int ret;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
-	if (ret) {
-		pkg_dev->levels = 0;
-		pkg_dev->locked = 1;
-		pkg_dev->current_level = 0;
-		pkg_dev->version = 0;
-		pkg_dev->enabled = 0;
-		return 0;
-	}
+	CHECK_CB(get_disp_freq_multiplier);
+	return isst_ops->get_disp_freq_multiplier();
+}
 
-	debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
+int isst_get_trl_max_levels(void)
+{
+	CHECK_CB(get_trl_max_levels);
+	return isst_ops->get_trl_max_levels();
+}
 
-	pkg_dev->version = resp & 0xff;
-	pkg_dev->levels = (resp >> 8) & 0xff;
-	pkg_dev->current_level = (resp >> 16) & 0xff;
-	pkg_dev->locked = !!(resp & BIT(24));
-	pkg_dev->enabled = !!(resp & BIT(31));
+char *isst_get_trl_level_name(int level)
+{
+	CHECK_CB(get_trl_level_name);
+	return isst_ops->get_trl_level_name(level);
+}
 
-	return 0;
+int isst_is_punit_valid(struct isst_id *id)
+{
+	CHECK_CB(is_punit_valid);
+	return isst_ops->is_punit_valid(id);
 }
 
-int isst_get_ctdp_control(struct isst_id *id, int config_index,
-			  struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
+			  unsigned long long *req_resp)
 {
-	int cp_state, cp_cap;
-	unsigned int resp;
-	int ret;
+	struct isst_if_msr_cmds msr_cmds;
+	const char *pathname = "/dev/isst_interface";
+	FILE *outf = get_output_file();
+	int fd;
 
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_GET_TDP_CONTROL, 0,
-				     config_index, &resp);
-	if (ret)
-		return ret;
+	fd = open(pathname, O_RDWR);
+	if (fd < 0)
+		err(-1, "%s open failed", pathname);
 
-	ctdp_level->fact_support = resp & BIT(0);
-	ctdp_level->pbf_support = !!(resp & BIT(1));
-	ctdp_level->fact_enabled = !!(resp & BIT(16));
-	ctdp_level->pbf_enabled = !!(resp & BIT(17));
+	msr_cmds.cmd_count = 1;
+	msr_cmds.msr_cmd[0].logical_cpu = cpu;
+	msr_cmds.msr_cmd[0].msr = msr;
+	msr_cmds.msr_cmd[0].read_write = write;
+	if (write)
+		msr_cmds.msr_cmd[0].data = *req_resp;
 
-	ret = isst_read_pm_config(id, &cp_state, &cp_cap);
-	if (ret) {
-		debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
+	if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
+		perror("ISST_IF_MSR_COMMAND");
+		fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
+			cpu, msr, write);
 	} else {
-		debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
-		ctdp_level->sst_cp_support = cp_cap;
-		ctdp_level->sst_cp_enabled = cp_state;
-	}
-
-	debug_printf(
-		"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
-		id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
-		ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
-
-	return 0;
-}
-
-int isst_get_tdp_info(struct isst_id *id, int config_index,
-		      struct isst_pkg_ctdp_level_info *ctdp_level)
-{
-	unsigned int resp;
-	int ret;
+		if (!write)
+			*req_resp = msr_cmds.msr_cmd[0].data;
 
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
-				     0, config_index, &resp);
-	if (ret) {
-		isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
-		return ret;
+		debug_printf(
+			"msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
+			cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
 	}
 
-	ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
-	ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
+	close(fd);
 
-	debug_printf(
-		"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
-		id->cpu, config_index, resp, ctdp_level->tdp_ratio,
-		ctdp_level->pkg_tdp);
 	return 0;
 }
 
-int isst_get_pwr_info(struct isst_id *id, int config_index,
-		      struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
 {
-	unsigned int resp;
-	int ret;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
-				     0, config_index, &resp);
-	if (ret)
-		return ret;
-
-	ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
-	ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
-
-	debug_printf(
-		"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
-		id->cpu, config_index, resp, ctdp_level->pkg_max_power,
-		ctdp_level->pkg_min_power);
-
-	return 0;
+	CHECK_CB(read_pm_config);
+	return isst_ops->read_pm_config(id, cp_state, cp_cap);
 }
 
-void isst_get_uncore_p0_p1_info(struct isst_id *id, int config_index,
-				struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_get_ctdp_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
 {
-	unsigned int resp;
-	int ret;
-
-	ctdp_level->uncore_pm = 0;
-	ctdp_level->uncore_p0 = 0;
-	ctdp_level->uncore_p1 = 0;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_GET_RATIO_INFO, 0,
-				     (BIT(16) | config_index), &resp);
-	if (ret)
-		goto try_uncore_mbox;
-
-	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
-	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
-	ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24;
-
-	debug_printf(
-		"cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n",
-		id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1,
-		ctdp_level->uncore_pm);
-
-	return;
-
-try_uncore_mbox:
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
-				     config_index, &resp);
-	if (ret) {
-		ctdp_level->uncore_p0 = 0;
-		ctdp_level->uncore_p1 = 0;
-		return;
-	}
-
-	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
-	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
-	debug_printf(
-		"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
-		id->cpu, config_index, resp, ctdp_level->uncore_p0,
-		ctdp_level->uncore_p1);
+	CHECK_CB(get_config_levels);
+	return isst_ops->get_config_levels(id, pkg_dev);
 }
 
-void isst_get_p1_info(struct isst_id *id, int config_index,
-		      struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_get_ctdp_control(struct isst_id *id, int config_index,
+			  struct isst_pkg_ctdp_level_info *ctdp_level)
 {
-	unsigned int resp;
-	int ret;
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
-				     config_index, &resp);
-	if (ret) {
-		ctdp_level->sse_p1 = 0;
-		ctdp_level->avx2_p1 = 0;
-		ctdp_level->avx512_p1 = 0;
-		return;
-	}
-
-	ctdp_level->sse_p1 = resp & GENMASK(7, 0);
-	ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
-	ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
-	debug_printf(
-		"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
-		id->cpu, config_index, resp, ctdp_level->sse_p1,
-		ctdp_level->avx2_p1, ctdp_level->avx512_p1);
+	CHECK_CB(get_ctdp_control);
+	return isst_ops->get_ctdp_control(id, config_index, ctdp_level);
 }
 
-void isst_get_uncore_mem_freq(struct isst_id *id, int config_index,
-			      struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_get_tdp_info(struct isst_id *id, int config_index,
+		      struct isst_pkg_ctdp_level_info *ctdp_level)
 {
-	unsigned int resp;
-	int ret;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
-				     0, config_index, &resp);
-	if (ret) {
-		ctdp_level->mem_freq = 0;
-		return;
-	}
-
-	ctdp_level->mem_freq = resp & GENMASK(7, 0);
-	if (is_spr_platform()) {
-		ctdp_level->mem_freq *= 200;
-	} else if (is_icx_platform()) {
-		if (ctdp_level->mem_freq < 7) {
-			ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
-			ctdp_level->mem_freq /= 10;
-			if (ctdp_level->mem_freq % 10 > 5)
-				ctdp_level->mem_freq++;
-		} else {
-			ctdp_level->mem_freq = 0;
-		}
-	} else {
-		ctdp_level->mem_freq = 0;
-	}
-	debug_printf(
-		"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
-		id->cpu, config_index, resp, ctdp_level->mem_freq);
+	CHECK_CB(get_tdp_info);
+	return isst_ops->get_tdp_info(id, config_index, ctdp_level);
 }
 
-int isst_get_tjmax_info(struct isst_id *id, int config_index,
-			struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_get_pwr_info(struct isst_id *id, int config_index,
+		      struct isst_pkg_ctdp_level_info *ctdp_level)
 {
-	unsigned int resp;
-	int ret;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
-				     0, config_index, &resp);
-	if (ret)
-		return ret;
-
-	ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
-
-	debug_printf(
-		"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
-		id->cpu, config_index, resp, ctdp_level->t_proc_hot);
-
-	return 0;
+	CHECK_CB(get_pwr_info);
+	return isst_ops->get_pwr_info(id, config_index, ctdp_level);
 }
 
 int isst_get_coremask_info(struct isst_id *id, int config_index,
 			   struct isst_pkg_ctdp_level_info *ctdp_level)
 {
-	unsigned int resp;
-	int i, ret;
-
-	ctdp_level->cpu_count = 0;
-	for (i = 0; i < 2; ++i) {
-		unsigned long long mask;
-		int cpu_count = 0;
-
-		ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-					     CONFIG_TDP_GET_CORE_MASK, 0,
-					     (i << 8) | config_index, &resp);
-		if (ret)
-			return ret;
-
-		debug_printf(
-			"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
-			id->cpu, config_index, i, resp);
-
-		mask = (unsigned long long)resp << (32 * i);
-		set_cpu_mask_from_punit_coremask(id, mask,
-						 ctdp_level->core_cpumask_size,
-						 ctdp_level->core_cpumask,
-						 &cpu_count);
-		ctdp_level->cpu_count += cpu_count;
-		debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
-			     config_index, i, ctdp_level->cpu_count);
-	}
-
-	return 0;
+	CHECK_CB(get_coremask_info);
+	return isst_ops->get_coremask_info(id, config_index, ctdp_level);
 }
 
 int isst_get_get_trl_from_msr(struct isst_id *id, int *trl)
@@ -329,89 +166,33 @@ int isst_get_get_trl_from_msr(struct isst_id *id, int *trl)
 
 int isst_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
 {
-	unsigned int req, resp;
-	int ret;
-
-	req = level | (avx_level << 16);
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
-				     &resp);
-	if (ret)
-		return ret;
-
-	debug_printf(
-		"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
-		id->cpu, req, resp);
-
-	trl[0] = resp & GENMASK(7, 0);
-	trl[1] = (resp & GENMASK(15, 8)) >> 8;
-	trl[2] = (resp & GENMASK(23, 16)) >> 16;
-	trl[3] = (resp & GENMASK(31, 24)) >> 24;
-
-	req = level | BIT(8) | (avx_level << 16);
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
-				     &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
-		     req, resp);
-
-	trl[4] = resp & GENMASK(7, 0);
-	trl[5] = (resp & GENMASK(15, 8)) >> 8;
-	trl[6] = (resp & GENMASK(23, 16)) >> 16;
-	trl[7] = (resp & GENMASK(31, 24)) >> 24;
-
-	return 0;
+	CHECK_CB(get_get_trl);
+	return isst_ops->get_get_trl(id, level, avx_level, trl);
 }
 
-int isst_get_trl_bucket_info(struct isst_id *id, unsigned long long *buckets_info)
+int isst_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
 {
-	int ret;
-
-	debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
-
-	*buckets_info = 0;
-
-	ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
-		     *buckets_info);
+	CHECK_CB(get_get_trls);
+	return isst_ops->get_get_trls(id, level, ctdp_level);
+}
 
-	return 0;
+int isst_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
+{
+	CHECK_CB(get_trl_bucket_info);
+	return isst_ops->get_trl_bucket_info(id, level, buckets_info);
 }
 
 int isst_set_tdp_level(struct isst_id *id, int tdp_level)
 {
-	unsigned int resp;
-	int ret;
-
-
-	if (isst_get_config_tdp_lock_status(id)) {
-		isst_display_error_info_message(1, "TDP is locked", 0, 0);
-		return -1;
-
-	}
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
-				     tdp_level, &resp);
-	if (ret) {
-		isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
-		return ret;
-	}
-
-	return 0;
+	CHECK_CB(set_tdp_level);
+	return isst_ops->set_tdp_level(id, tdp_level);
 }
 
 int isst_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
 {
 	struct isst_pkg_ctdp_level_info ctdp_level;
 	struct isst_pkg_ctdp pkg_dev;
-	int i, ret, max_punit_core, max_mask_index;
-	unsigned int req, resp;
+	int ret;
 
 	ret = isst_get_ctdp_levels(id, &pkg_dev);
 	if (ret) {
@@ -435,194 +216,23 @@ int isst_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_i
 
 	pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
 
-	max_punit_core = get_max_punit_core_id(id);
-	max_mask_index = max_punit_core > 32 ? 2 : 1;
-
-	for (i = 0; i < max_mask_index; ++i) {
-		unsigned long long mask;
-		int count;
-
-		ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-					     CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
-					     0, (i << 8) | level, &resp);
-		if (ret)
-			break;
-
-		debug_printf(
-			"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
-			id->cpu, resp);
-
-		mask = (unsigned long long)resp << (32 * i);
-		set_cpu_mask_from_punit_coremask(id, mask,
-						 pbf_info->core_cpumask_size,
-						 pbf_info->core_cpumask,
-						 &count);
-	}
-
-	req = level;
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
-				     &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
-		     resp);
-
-	pbf_info->p1_low = resp & 0xff;
-	pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
-
-	req = level;
-	ret = isst_send_mbox_command(
-		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);
-
-	pbf_info->tdp = resp & 0xffff;
-
-	req = level;
-	ret = isst_send_mbox_command(
-		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,
-		     resp);
-	pbf_info->t_control = (resp >> 8) & 0xff;
-	pbf_info->t_prochot = resp & 0xff;
-
-	return 0;
-}
-
-void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info)
-{
-	free_cpu_set(pbf_info->core_cpumask);
+	CHECK_CB(get_pbf_info);
+	return isst_ops->get_pbf_info(id, level, pbf_info);
 }
 
 int isst_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
 {
-	struct isst_pkg_ctdp pkg_dev;
-	struct isst_pkg_ctdp_level_info ctdp_level;
-	int current_level;
-	unsigned int req = 0, resp;
-	int ret;
-
-	ret = isst_get_ctdp_levels(id, &pkg_dev);
-	if (ret)
-		debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
-
-	current_level = pkg_dev.current_level;
-
-	ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
-	if (ret)
-		return ret;
-
-	if (pbf) {
-		if (ctdp_level.fact_enabled)
-			req = BIT(16);
-
-		if (enable)
-			req |= BIT(17);
-		else
-			req &= ~BIT(17);
-	} else {
-
-		if (enable && !ctdp_level.sst_cp_enabled)
-			isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
-
-		if (ctdp_level.pbf_enabled)
-			req = BIT(17);
-
-		if (enable)
-			req |= BIT(16);
-		else
-			req &= ~BIT(16);
-	}
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
-		     id->cpu, pbf, req);
-
-	return 0;
+	CHECK_CB(set_pbf_fact_status);
+	return isst_ops->set_pbf_fact_status(id, pbf, enable);
 }
 
-int isst_get_fact_bucket_info(struct isst_id *id, int level,
-			      struct isst_fact_bucket_info *bucket_info)
-{
-	unsigned int resp;
-	int i, k, ret;
-
-	for (i = 0; i < 2; ++i) {
-		int j;
-
-		ret = isst_send_mbox_command(
-			id->cpu, CONFIG_TDP,
-			CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
-			(i << 8) | level, &resp);
-		if (ret)
-			return ret;
-
-		debug_printf(
-			"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
-			id->cpu, i, level, resp);
-
-		for (j = 0; j < 4; ++j) {
-			bucket_info[j + (i * 4)].high_priority_cores_count =
-				(resp >> (j * 8)) & 0xff;
-		}
-	}
-
-	for (k = 0; k < 3; ++k) {
-		for (i = 0; i < 2; ++i) {
-			int j;
-
-			ret = isst_send_mbox_command(
-				id->cpu, CONFIG_TDP,
-				CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
-				(k << 16) | (i << 8) | level, &resp);
-			if (ret)
-				return ret;
-
-			debug_printf(
-				"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
-				id->cpu, i, level, k, resp);
-
-			for (j = 0; j < 4; ++j) {
-				switch (k) {
-				case 0:
-					bucket_info[j + (i * 4)].sse_trl =
-						(resp >> (j * 8)) & 0xff;
-					break;
-				case 1:
-					bucket_info[j + (i * 4)].avx_trl =
-						(resp >> (j * 8)) & 0xff;
-					break;
-				case 2:
-					bucket_info[j + (i * 4)].avx512_trl =
-						(resp >> (j * 8)) & 0xff;
-					break;
-				default:
-					break;
-				}
-			}
-		}
-	}
 
-	return 0;
-}
 
 int isst_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
 {
 	struct isst_pkg_ctdp_level_info ctdp_level;
 	struct isst_pkg_ctdp pkg_dev;
-	unsigned int resp;
-	int j, ret, print;
+	int ret;
 
 	ret = isst_get_ctdp_levels(id, &pkg_dev);
 	if (ret) {
@@ -643,40 +253,8 @@ int isst_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct is
 		isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
 		return -1;
 	}
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
-				     CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
-				     level, &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
-		     id->cpu, resp);
-
-	fact_info->lp_clipping_ratio_license_sse = resp & 0xff;
-	fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff;
-	fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
-
-	ret = isst_get_fact_bucket_info(id, level, fact_info->bucket_info);
-	if (ret)
-		return ret;
-
-	print = 0;
-	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
-		if (fact_bucket != 0xff && fact_bucket != j)
-			continue;
-
-		if (!fact_info->bucket_info[j].high_priority_cores_count)
-			break;
-
-		print = 1;
-	}
-	if (!print) {
-		isst_display_error_info_message(1, "Invalid bucket", 0, 0);
-		return -1;
-	}
-
-	return 0;
+	CHECK_CB(get_fact_info);
+	return isst_ops->get_fact_info(id, level, fact_bucket, fact_info);
 }
 
 int isst_get_trl(struct isst_id *id, unsigned long long *trl)
@@ -709,6 +287,9 @@ int isst_set_trl_from_current_tdp(struct isst_id *id, unsigned long long trl)
 	unsigned long long msr_trl;
 	int ret;
 
+	if (id->cpu < 0)
+		return 0;
+
 	if (trl) {
 		msr_trl = trl;
 	} else {
@@ -770,6 +351,13 @@ void isst_get_process_ctdp_complete(struct isst_id *id, struct isst_pkg_ctdp *pk
 	}
 }
 
+void isst_adjust_uncore_freq(struct isst_id *id, int config_index,
+				struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+	CHECK_CB(adjust_uncore_freq);
+	return isst_ops->adjust_uncore_freq(id, config_index, ctdp_level);
+}
+
 int isst_get_process_ctdp(struct isst_id *id, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
 {
 	int i, ret, valid = 0;
@@ -838,8 +426,8 @@ int isst_get_process_ctdp(struct isst_id *id, int tdp_level, struct isst_pkg_ctd
 				ctdp_level->tdp_ratio = ctdp_level->sse_p1;
 			}
 
-			isst_get_get_trl_from_msr(id, ctdp_level->trl_sse_active_cores);
-			isst_get_trl_bucket_info(id, &ctdp_level->buckets_info);
+			isst_get_get_trl_from_msr(id, ctdp_level->trl_ratios[0]);
+			isst_get_trl_bucket_info(id, i, &ctdp_level->trl_cores);
 			continue;
 		}
 
@@ -851,38 +439,19 @@ int isst_get_process_ctdp(struct isst_id *id, int tdp_level, struct isst_pkg_ctd
 		if (ret)
 			return ret;
 
-		ret = isst_get_tjmax_info(id, i, ctdp_level);
-		if (ret)
-			return ret;
-
 		ctdp_level->core_cpumask_size =
 			alloc_cpu_set(&ctdp_level->core_cpumask);
 		ret = isst_get_coremask_info(id, i, ctdp_level);
 		if (ret)
 			return ret;
 
-		ret = isst_get_trl_bucket_info(id, &ctdp_level->buckets_info);
-		if (ret)
-			return ret;
-
-		ret = isst_get_get_trl(id, i, 0,
-				       ctdp_level->trl_sse_active_cores);
+		ret = isst_get_trl_bucket_info(id, i, &ctdp_level->trl_cores);
 		if (ret)
 			return ret;
 
-		ret = isst_get_get_trl(id, i, 1,
-				       ctdp_level->trl_avx_active_cores);
+		ret = isst_get_get_trls(id, i, ctdp_level);
 		if (ret)
 			return ret;
-
-		ret = isst_get_get_trl(id, i, 2,
-				       ctdp_level->trl_avx_512_active_cores);
-		if (ret)
-			return ret;
-
-		isst_get_uncore_p0_p1_info(id, i, ctdp_level);
-		isst_get_p1_info(id, i, ctdp_level);
-		isst_get_uncore_mem_freq(id, i, ctdp_level);
 	}
 
 	if (!valid)
@@ -893,178 +462,37 @@ int isst_get_process_ctdp(struct isst_id *id, int tdp_level, struct isst_pkg_ctd
 
 int isst_clos_get_clos_information(struct isst_id *id, int *enable, int *type)
 {
-	unsigned int resp;
-	int ret;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
-				     &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
-
-	if (resp & BIT(1))
-		*enable = 1;
-	else
-		*enable = 0;
-
-	if (resp & BIT(2))
-		*type = 1;
-	else
-		*type = 0;
-
-	return 0;
+	CHECK_CB(get_clos_information);
+	return isst_ops->get_clos_information(id, enable, type);
 }
 
 int isst_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
 {
-	unsigned int req, resp;
-	int ret;
-
-	if (!enable_clos) {
-		struct isst_pkg_ctdp pkg_dev;
-		struct isst_pkg_ctdp_level_info ctdp_level;
-
-		ret = isst_get_ctdp_levels(id, &pkg_dev);
-		if (ret) {
-			debug_printf("isst_get_ctdp_levels\n");
-			return ret;
-		}
-
-		ret = isst_get_ctdp_control(id, pkg_dev.current_level,
-					    &ctdp_level);
-		if (ret)
-			return ret;
-
-		if (ctdp_level.fact_enabled) {
-			isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
-			return -EINVAL;
-		}
-		ret = isst_write_pm_config(id, 0);
-		if (ret)
-			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
-	} else {
-		ret = isst_write_pm_config(id, 1);
-		if (ret)
-			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
-	}
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
-				     &resp);
-	if (ret) {
-		isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
-		return ret;
-	}
-
-	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
-
-	req = resp;
-
-	if (enable_clos)
-		req = req | BIT(1);
-	else
-		req = req & ~BIT(1);
-
-	if (priority_type > 1)
-		isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
-
-	if (priority_type)
-		req = req | BIT(2);
-	else
-		req = req & ~BIT(2);
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
-				     BIT(MBOX_CMD_WRITE_BIT), req, &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
-		     priority_type, req);
-
-	return 0;
+	CHECK_CB(pm_qos_config);
+	return isst_ops->pm_qos_config(id, enable_clos, priority_type);
 }
 
 int isst_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
 {
-	unsigned int resp;
-	int ret;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
-				     &resp);
-	if (ret)
-		return ret;
-
-	clos_config->epp = resp & 0x0f;
-	clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
-	clos_config->clos_min = (resp >> 8) & 0xff;
-	clos_config->clos_max = (resp >> 16) & 0xff;
-	clos_config->clos_desired = (resp >> 24) & 0xff;
-
-	return 0;
+	CHECK_CB(pm_get_clos);
+	return isst_ops->pm_get_clos(id, clos, clos_config);
 }
 
 int isst_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
 {
-	unsigned int req, resp;
-	unsigned int param;
-	int ret;
-
-	req = clos_config->epp & 0x0f;
-	req |= (clos_config->clos_prop_prio & 0x0f) << 4;
-	req |= (clos_config->clos_min & 0xff) << 8;
-	req |= (clos_config->clos_max & 0xff) << 16;
-	req |= (clos_config->clos_desired & 0xff) << 24;
-
-	param = BIT(MBOX_CMD_WRITE_BIT) | clos;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
-				     &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
-
-	return 0;
+	CHECK_CB(set_clos);
+	return isst_ops->set_clos(id, clos, clos_config);
 }
 
 int isst_clos_get_assoc_status(struct isst_id *id, int *clos_id)
 {
-	unsigned int resp;
-	unsigned int param;
-	int core_id, ret;
-
-	core_id = find_phy_core_num(id->cpu);
-	param = core_id;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
-				     &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
-		     resp);
-	*clos_id = (resp >> 16) & 0x03;
-
-	return 0;
+	CHECK_CB(clos_get_assoc_status);
+	return isst_ops->clos_get_assoc_status(id, clos_id);
 }
 
 int isst_clos_associate(struct isst_id *id, int clos_id)
 {
-	unsigned int req, resp;
-	unsigned int param;
-	int core_id, ret;
+	CHECK_CB(clos_associate);
+	return isst_ops->clos_associate(id, clos_id);
 
-	req = (clos_id & 0x03) << 16;
-	core_id = find_phy_core_num(id->cpu);
-	param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
-
-	ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
-				     req, &resp);
-	if (ret)
-		return ret;
-
-	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
-		     req);
-
-	return 0;
 }
diff --git a/tools/power/x86/intel-speed-select/isst-daemon.c b/tools/power/x86/intel-speed-select/isst-daemon.c
index c2290ef0e3af1797adf02f06f2302e5e9f788765..12053fa43542901b68e248bf0a59122daea1dfb8 100644
--- a/tools/power/x86/intel-speed-select/isst-daemon.c
+++ b/tools/power/x86/intel-speed-select/isst-daemon.c
@@ -20,16 +20,17 @@
 
 #include "isst.h"
 
-static int per_package_levels_info[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
-static time_t per_package_levels_tm[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
+static int per_package_levels_info[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
+static time_t per_package_levels_tm[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
 
 static void init_levels(void)
 {
-	int i, j;
+	int i, j, k;
 
 	for (i = 0; i < MAX_PACKAGE_COUNT; ++i)
 		for (j = 0; j < MAX_DIE_PER_PACKAGE; ++j)
-			per_package_levels_info[i][j] = -1;
+			for (k = 0; k < MAX_PUNIT_PER_DIE; ++k)
+				per_package_levels_info[i][j][k] = -1;
 }
 
 void process_level_change(struct isst_id *id)
@@ -39,16 +40,16 @@ void process_level_change(struct isst_id *id)
 	time_t tm;
 	int ret;
 
-	if (id->pkg < 0 || id->die < 0) {
+	if (id->pkg < 0 || id->die < 0 || id->punit < 0) {
 		debug_printf("Invalid package/die info for cpu:%d\n", id->cpu);
 		return;
 	}
 
 	tm = time(NULL);
-	if (tm - per_package_levels_tm[id->pkg][id->die] < 2)
+	if (tm - per_package_levels_tm[id->pkg][id->die][id->punit] < 2)
 		return;
 
-	per_package_levels_tm[id->pkg][id->die] = tm;
+	per_package_levels_tm[id->pkg][id->die][id->punit] = tm;
 
 	ret = isst_get_ctdp_levels(id, &pkg_dev);
 	if (ret) {
@@ -64,14 +65,14 @@ void process_level_change(struct isst_id *id)
 		return;
 	}
 
-	if (per_package_levels_info[id->pkg][id->die] == pkg_dev.current_level)
+	if (per_package_levels_info[id->pkg][id->die][id->punit] == pkg_dev.current_level)
 		return;
 
 	debug_printf("**Config level change for cpu:%d pkg:%d die:%d from %d to %d\n",
-		      id->cpu, id->pkg, id->die, per_package_levels_info[id->pkg][id->die],
+		      id->cpu, id->pkg, id->die, per_package_levels_info[id->pkg][id->die][id->punit],
 		      pkg_dev.current_level);
 
-	per_package_levels_info[id->pkg][id->die] = pkg_dev.current_level;
+	per_package_levels_info[id->pkg][id->die][id->punit] = pkg_dev.current_level;
 
 	ctdp_level.core_cpumask_size =
 		alloc_cpu_set(&ctdp_level.core_cpumask);
@@ -82,6 +83,19 @@ void process_level_change(struct isst_id *id)
 		return;
 	}
 
+	if (use_cgroupv2()) {
+		int ret;
+
+		ret = enable_cpuset_controller();
+		if (ret)
+			goto use_offline;
+
+		isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, pkg_dev.current_level);
+
+		goto free_mask;
+	}
+
+use_offline:
 	if (ctdp_level.cpu_count) {
 		int i, max_cpus = get_topo_max_cpus();
 		for (i = 0; i < max_cpus; ++i) {
@@ -96,7 +110,7 @@ void process_level_change(struct isst_id *id)
 			}
 		}
 	}
-
+free_mask:
 	free_cpu_set(ctdp_level.core_cpumask);
 }
 
@@ -108,7 +122,7 @@ static void _poll_for_config_change(struct isst_id *id, void *arg1, void *arg2,
 
 static void poll_for_config_change(void)
 {
-	for_each_online_package_in_set(_poll_for_config_change, NULL, NULL,
+	for_each_online_power_domain_in_set(_poll_for_config_change, NULL, NULL,
 				       NULL, NULL);
 }
 
diff --git a/tools/power/x86/intel-speed-select/isst-display.c b/tools/power/x86/intel-speed-select/isst-display.c
index 7feadac04a6f5e7d36b4f23b441bca18b71ac1f5..0403d42ab1baecd2a3d9c2fe51030e646f238938 100644
--- a/tools/power/x86/intel-speed-select/isst-display.c
+++ b/tools/power/x86/intel-speed-select/isst-display.c
@@ -169,21 +169,30 @@ static void format_and_print(FILE *outf, int level, char *header, char *value)
 static int print_package_info(struct isst_id *id, FILE *outf)
 {
 	char header[256];
+	int level = 1;
 
 	if (out_format_is_json()) {
-		snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
-			 id->pkg, id->die, id->cpu);
-		format_and_print(outf, 1, header, NULL);
+		if (api_version() > 1)
+			snprintf(header, sizeof(header), "package-%d:die-%d:powerdomain-%d:cpu-%d",
+				 id->pkg, id->die, id->punit, id->cpu);
+		else
+			snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
+				 id->pkg, id->die, id->cpu);
+		format_and_print(outf, level, header, NULL);
 		return 1;
 	}
 	snprintf(header, sizeof(header), "package-%d", id->pkg);
-	format_and_print(outf, 1, header, NULL);
+	format_and_print(outf, level++, header, NULL);
 	snprintf(header, sizeof(header), "die-%d", id->die);
-	format_and_print(outf, 2, header, NULL);
+	format_and_print(outf, level++, header, NULL);
+	if (api_version() > 1) {
+		snprintf(header, sizeof(header), "powerdomain-%d", id->punit);
+		format_and_print(outf, level++, header, NULL);
+	}
 	snprintf(header, sizeof(header), "cpu-%d", id->cpu);
-	format_and_print(outf, 3, header, NULL);
+	format_and_print(outf, level, header, NULL);
 
-	return 3;
+	return level;
 }
 
 static void _isst_pbf_display_information(struct isst_id *id, FILE *outf, int level,
@@ -198,7 +207,7 @@ static void _isst_pbf_display_information(struct isst_id *id, FILE *outf, int le
 
 	snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)");
 	snprintf(value, sizeof(value), "%d",
-		 pbf_info->p1_high * DISP_FREQ_MULTIPLIER);
+		 pbf_info->p1_high * isst_get_disp_freq_multiplier());
 	format_and_print(outf, disp_level + 1, header, value);
 
 	snprintf(header, sizeof(header), "high-priority-cpu-mask");
@@ -214,7 +223,7 @@ static void _isst_pbf_display_information(struct isst_id *id, FILE *outf, int le
 
 	snprintf(header, sizeof(header), "low-priority-base-frequency(MHz)");
 	snprintf(value, sizeof(value), "%d",
-		 pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
+		 pbf_info->p1_low * isst_get_disp_freq_multiplier());
 	format_and_print(outf, disp_level + 1, header, value);
 
 	if (is_clx_n_platform())
@@ -235,6 +244,7 @@ static void _isst_fact_display_information(struct isst_id *id, FILE *outf, int l
 					   int base_level)
 {
 	struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
+	int trl_max_levels = isst_get_trl_max_levels();
 	char header[256];
 	char value[256];
 	int print = 0, j;
@@ -243,7 +253,8 @@ static void _isst_fact_display_information(struct isst_id *id, FILE *outf, int l
 		if (fact_bucket != 0xff && fact_bucket != j)
 			continue;
 
-		if (!bucket_info[j].high_priority_cores_count)
+		/* core count must be valid for CPU power domain */
+		if (!bucket_info[j].hp_cores && id->cpu >= 0)
 			break;
 
 		print = 1;
@@ -256,10 +267,12 @@ static void _isst_fact_display_information(struct isst_id *id, FILE *outf, int l
 	snprintf(header, sizeof(header), "speed-select-turbo-freq-properties");
 	format_and_print(outf, base_level, header, NULL);
 	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
+		int i;
+
 		if (fact_bucket != 0xff && fact_bucket != j)
 			continue;
 
-		if (!bucket_info[j].high_priority_cores_count)
+		if (!bucket_info[j].hp_cores)
 			break;
 
 		snprintf(header, sizeof(header), "bucket-%d", j);
@@ -267,75 +280,49 @@ static void _isst_fact_display_information(struct isst_id *id, FILE *outf, int l
 
 		snprintf(header, sizeof(header), "high-priority-cores-count");
 		snprintf(value, sizeof(value), "%d",
-			 bucket_info[j].high_priority_cores_count);
+			 bucket_info[j].hp_cores);
 		format_and_print(outf, base_level + 2, header, value);
-
-		if (fact_avx & 0x01) {
-			snprintf(header, sizeof(header),
-				 "high-priority-max-frequency(MHz)");
-			snprintf(value, sizeof(value), "%d",
-				 bucket_info[j].sse_trl * DISP_FREQ_MULTIPLIER);
-			format_and_print(outf, base_level + 2, header, value);
-		}
-
-		if (fact_avx & 0x02) {
-			snprintf(header, sizeof(header),
-				 "high-priority-max-avx2-frequency(MHz)");
-			snprintf(value, sizeof(value), "%d",
-				 bucket_info[j].avx_trl * DISP_FREQ_MULTIPLIER);
-			format_and_print(outf, base_level + 2, header, value);
-		}
-
-		if (fact_avx & 0x04) {
-			snprintf(header, sizeof(header),
-				 "high-priority-max-avx512-frequency(MHz)");
+		for (i = 0; i < trl_max_levels; i++) {
+			if (!bucket_info[j].hp_ratios[i] || (fact_avx != 0xFF && !(fact_avx & (1 << i))))
+				continue;
+			if (i == 0 && api_version() == 1 && !is_emr_platform())
+				snprintf(header, sizeof(header),
+					"high-priority-max-frequency(MHz)");
+			else
+				snprintf(header, sizeof(header),
+					"high-priority-max-%s-frequency(MHz)", isst_get_trl_level_name(i));
 			snprintf(value, sizeof(value), "%d",
-				 bucket_info[j].avx512_trl *
-					 DISP_FREQ_MULTIPLIER);
+				bucket_info[j].hp_ratios[i] * isst_get_disp_freq_multiplier());
 			format_and_print(outf, base_level + 2, header, value);
 		}
 	}
 	snprintf(header, sizeof(header),
 		 "speed-select-turbo-freq-clip-frequencies");
 	format_and_print(outf, base_level + 1, header, NULL);
-	snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)");
-	snprintf(value, sizeof(value), "%d",
-		 fact_info->lp_clipping_ratio_license_sse *
-			 DISP_FREQ_MULTIPLIER);
-	format_and_print(outf, base_level + 2, header, value);
-	snprintf(header, sizeof(header),
-		 "low-priority-max-avx2-frequency(MHz)");
-	snprintf(value, sizeof(value), "%d",
-		 fact_info->lp_clipping_ratio_license_avx2 *
-			 DISP_FREQ_MULTIPLIER);
-	format_and_print(outf, base_level + 2, header, value);
-	snprintf(header, sizeof(header),
-		 "low-priority-max-avx512-frequency(MHz)");
-	snprintf(value, sizeof(value), "%d",
-		 fact_info->lp_clipping_ratio_license_avx512 *
-			 DISP_FREQ_MULTIPLIER);
-	format_and_print(outf, base_level + 2, header, value);
+
+	for (j = 0; j < trl_max_levels; j++) {
+		if (!fact_info->lp_ratios[j])
+			continue;
+
+		/* No AVX level name for SSE to be consistent with previous formatting */
+		if (j == 0 && api_version() == 1 && !is_emr_platform())
+			snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)");
+		else
+			snprintf(header, sizeof(header), "low-priority-max-%s-frequency(MHz)",
+				isst_get_trl_level_name(j));
+		snprintf(value, sizeof(value), "%d",
+			 fact_info->lp_ratios[j] * isst_get_disp_freq_multiplier());
+		format_and_print(outf, base_level + 2, header, value);
+	}
 }
 
 void isst_ctdp_display_core_info(struct isst_id *id, FILE *outf, char *prefix,
 				 unsigned int val, char *str0, char *str1)
 {
-	char header[256];
 	char value[256];
-	int level = 1;
+	int level = print_package_info(id, outf);
 
-	if (out_format_is_json()) {
-		snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
-			 id->pkg, id->die, id->cpu);
-		format_and_print(outf, level++, header, NULL);
-	} else {
-		snprintf(header, sizeof(header), "package-%d", id->pkg);
-		format_and_print(outf, level++, header, NULL);
-		snprintf(header, sizeof(header), "die-%d", id->die);
-		format_and_print(outf, level++, header, NULL);
-		snprintf(header, sizeof(header), "cpu-%d", id->cpu);
-		format_and_print(outf, level++, header, NULL);
-	}
+	level++;
 
 	if (str0 && !val)
 		snprintf(value, sizeof(value), "%s", str0);
@@ -354,6 +341,7 @@ void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level
 	char header[256];
 	char value[512];
 	static int level;
+	int trl_max_levels = isst_get_trl_max_levels();
 	int i;
 
 	if (pkg_dev->processed)
@@ -361,7 +349,7 @@ void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level
 
 	for (i = 0; i <= pkg_dev->levels; ++i) {
 		struct isst_pkg_ctdp_level_info *ctdp_level;
-		int j;
+		int j, k;
 
 		ctdp_level = &pkg_dev->ctdp_level[i];
 		if (!ctdp_level->processed)
@@ -371,31 +359,33 @@ void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level
 			 ctdp_level->level);
 		format_and_print(outf, level + 1, header, NULL);
 
-		snprintf(header, sizeof(header), "cpu-count");
-		j = get_cpu_count(id);
-		snprintf(value, sizeof(value), "%d", j);
-		format_and_print(outf, level + 2, header, value);
-
-		j = CPU_COUNT_S(ctdp_level->core_cpumask_size,
-				ctdp_level->core_cpumask);
-		if (j) {
-			snprintf(header, sizeof(header), "enable-cpu-count");
+		if (id->cpu >= 0) {
+			snprintf(header, sizeof(header), "cpu-count");
+			j = get_cpu_count(id);
 			snprintf(value, sizeof(value), "%d", j);
 			format_and_print(outf, level + 2, header, value);
-		}
 
-		if (ctdp_level->core_cpumask_size) {
-			snprintf(header, sizeof(header), "enable-cpu-mask");
-			printcpumask(sizeof(value), value,
-				     ctdp_level->core_cpumask_size,
-				     ctdp_level->core_cpumask);
-			format_and_print(outf, level + 2, header, value);
+			j = CPU_COUNT_S(ctdp_level->core_cpumask_size,
+					ctdp_level->core_cpumask);
+			if (j) {
+				snprintf(header, sizeof(header), "enable-cpu-count");
+				snprintf(value, sizeof(value), "%d", j);
+				format_and_print(outf, level + 2, header, value);
+			}
 
-			snprintf(header, sizeof(header), "enable-cpu-list");
-			printcpulist(sizeof(value), value,
-				     ctdp_level->core_cpumask_size,
-				     ctdp_level->core_cpumask);
-			format_and_print(outf, level + 2, header, value);
+			if (ctdp_level->core_cpumask_size) {
+				snprintf(header, sizeof(header), "enable-cpu-mask");
+				printcpumask(sizeof(value), value,
+					     ctdp_level->core_cpumask_size,
+					     ctdp_level->core_cpumask);
+				format_and_print(outf, level + 2, header, value);
+
+				snprintf(header, sizeof(header), "enable-cpu-list");
+				printcpulist(sizeof(value), value,
+					     ctdp_level->core_cpumask_size,
+					     ctdp_level->core_cpumask);
+				format_and_print(outf, level + 2, header, value);
+			}
 		}
 
 		snprintf(header, sizeof(header), "thermal-design-power-ratio");
@@ -406,41 +396,48 @@ void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level
 		if (!ctdp_level->sse_p1)
 			ctdp_level->sse_p1 = ctdp_level->tdp_ratio;
 		snprintf(value, sizeof(value), "%d",
-			  ctdp_level->sse_p1 * DISP_FREQ_MULTIPLIER);
+			  ctdp_level->sse_p1 * isst_get_disp_freq_multiplier());
 		format_and_print(outf, level + 2, header, value);
 
 		if (ctdp_level->avx2_p1) {
 			snprintf(header, sizeof(header), "base-frequency-avx2(MHz)");
 			snprintf(value, sizeof(value), "%d",
-				 ctdp_level->avx2_p1 * DISP_FREQ_MULTIPLIER);
+				 ctdp_level->avx2_p1 * isst_get_disp_freq_multiplier());
 			format_and_print(outf, level + 2, header, value);
 		}
 
 		if (ctdp_level->avx512_p1) {
 			snprintf(header, sizeof(header), "base-frequency-avx512(MHz)");
 			snprintf(value, sizeof(value), "%d",
-				 ctdp_level->avx512_p1 * DISP_FREQ_MULTIPLIER);
+				 ctdp_level->avx512_p1 * isst_get_disp_freq_multiplier());
 			format_and_print(outf, level + 2, header, value);
 		}
 
 		if (ctdp_level->uncore_pm) {
 			snprintf(header, sizeof(header), "uncore-frequency-min(MHz)");
 			snprintf(value, sizeof(value), "%d",
-				 ctdp_level->uncore_pm * DISP_FREQ_MULTIPLIER);
+				 ctdp_level->uncore_pm * isst_get_disp_freq_multiplier());
 			format_and_print(outf, level + 2, header, value);
 		}
 
 		if (ctdp_level->uncore_p0) {
 			snprintf(header, sizeof(header), "uncore-frequency-max(MHz)");
 			snprintf(value, sizeof(value), "%d",
-				 ctdp_level->uncore_p0 * DISP_FREQ_MULTIPLIER);
+				 ctdp_level->uncore_p0 * isst_get_disp_freq_multiplier());
+			format_and_print(outf, level + 2, header, value);
+		}
+
+		if (ctdp_level->amx_p1) {
+			snprintf(header, sizeof(header), "base-frequency-amx(MHz)");
+			snprintf(value, sizeof(value), "%d",
+			ctdp_level->amx_p1 * isst_get_disp_freq_multiplier());
 			format_and_print(outf, level + 2, header, value);
 		}
 
 		if (ctdp_level->uncore_p1) {
 			snprintf(header, sizeof(header), "uncore-frequency-base(MHz)");
 			snprintf(value, sizeof(value), "%d",
-				 ctdp_level->uncore_p1 * DISP_FREQ_MULTIPLIER);
+				 ctdp_level->uncore_p1 * isst_get_disp_freq_multiplier());
 			format_and_print(outf, level + 2, header, value);
 		}
 
@@ -451,6 +448,13 @@ void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level
 			format_and_print(outf, level + 2, header, value);
 		}
 
+		if (api_version() > 1) {
+			snprintf(header, sizeof(header), "cooling_type");
+			snprintf(value, sizeof(value), "%d",
+				ctdp_level->cooling_type);
+			format_and_print(outf, level + 2, header, value);
+		}
+
 		snprintf(header, sizeof(header),
 			 "speed-select-turbo-freq");
 		if (ctdp_level->fact_support) {
@@ -505,54 +509,24 @@ void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level
 			format_and_print(outf, level + 2, header, value);
 		}
 
-		snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
-		format_and_print(outf, level + 2, header, NULL);
-		for (j = 0; j < 8; ++j) {
-			snprintf(header, sizeof(header), "bucket-%d", j);
-			format_and_print(outf, level + 3, header, NULL);
+		for (k = 0; k < trl_max_levels; k++) {
+			if (!ctdp_level->trl_ratios[k][0])
+				continue;
 
-			snprintf(header, sizeof(header), "core-count");
-			snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
-			format_and_print(outf, level + 4, header, value);
-
-			snprintf(header, sizeof(header),
-				"max-turbo-frequency(MHz)");
-			snprintf(value, sizeof(value), "%d",
-				 ctdp_level->trl_sse_active_cores[j] *
-				  DISP_FREQ_MULTIPLIER);
-			format_and_print(outf, level + 4, header, value);
-		}
-
-		if (ctdp_level->trl_avx_active_cores[0]) {
-			snprintf(header, sizeof(header), "turbo-ratio-limits-avx2");
+			snprintf(header, sizeof(header), "turbo-ratio-limits-%s", isst_get_trl_level_name(k));
 			format_and_print(outf, level + 2, header, NULL);
-			for (j = 0; j < 8; ++j) {
-				snprintf(header, sizeof(header), "bucket-%d", j);
-				format_and_print(outf, level + 3, header, NULL);
 
-				snprintf(header, sizeof(header), "core-count");
-				snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
-				format_and_print(outf, level + 4, header, value);
-
-				snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
-				snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_active_cores[j] * DISP_FREQ_MULTIPLIER);
-				format_and_print(outf, level + 4, header, value);
-			}
-		}
-
-		if (ctdp_level->trl_avx_512_active_cores[0]) {
-			snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
-			format_and_print(outf, level + 2, header, NULL);
 			for (j = 0; j < 8; ++j) {
 				snprintf(header, sizeof(header), "bucket-%d", j);
 				format_and_print(outf, level + 3, header, NULL);
 
 				snprintf(header, sizeof(header), "core-count");
-				snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
+
+				snprintf(value, sizeof(value), "%llu", (ctdp_level->trl_cores >> (j * 8)) & 0xff);
 				format_and_print(outf, level + 4, header, value);
 
 				snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
-				snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_512_active_cores[j] * DISP_FREQ_MULTIPLIER);
+				snprintf(value, sizeof(value), "%d", ctdp_level->trl_ratios[k][j] * isst_get_disp_freq_multiplier());
 				format_and_print(outf, level + 4, header, value);
 			}
 		}
@@ -631,18 +605,18 @@ void isst_clos_display_information(struct isst_id *id, FILE *outf, int clos,
 	format_and_print(outf, level + 2, header, value);
 
 	snprintf(header, sizeof(header), "clos-min");
-	snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * DISP_FREQ_MULTIPLIER);
+	snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * isst_get_disp_freq_multiplier());
 	format_and_print(outf, level + 2, header, value);
 
 	snprintf(header, sizeof(header), "clos-max");
-	if (clos_config->clos_max == 0xff)
+	if ((clos_config->clos_max * isst_get_disp_freq_multiplier()) == 25500)
 		snprintf(value, sizeof(value), "Max Turbo frequency");
 	else
-		snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * DISP_FREQ_MULTIPLIER);
+		snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * isst_get_disp_freq_multiplier());
 	format_and_print(outf, level + 2, header, value);
 
 	snprintf(header, sizeof(header), "clos-desired");
-	snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * DISP_FREQ_MULTIPLIER);
+	snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * isst_get_disp_freq_multiplier());
 	format_and_print(outf, level + 2, header, value);
 
 	format_and_print(outf, level, NULL, NULL);
@@ -717,8 +691,7 @@ void isst_display_result(struct isst_id *id, FILE *outf, char *feature, char *cm
 	char value[256];
 	int level = 3;
 
-	if (id->cpu >= 0)
-		level = print_package_info(id, outf);
+	level = print_package_info(id, outf);
 
 	snprintf(header, sizeof(header), "%s", feature);
 	format_and_print(outf, level + 1, header, NULL);
diff --git a/tools/power/x86/intel-speed-select/isst.h b/tools/power/x86/intel-speed-select/isst.h
index 824876e31e2323cebf3f9c4405ca4f9c84a6506d..54fc21575d56dc023602262f9330f2f4e22225b0 100644
--- a/tools/power/x86/intel-speed-select/isst.h
+++ b/tools/power/x86/intel-speed-select/isst.h
@@ -28,6 +28,8 @@
 #include <stdarg.h>
 #include <sys/ioctl.h>
 
+#include <linux/isst_if.h>
+
 #define BIT(x) (1 << (x))
 #define BIT_ULL(nr) (1ULL << (nr))
 #define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (sizeof(long) * 8 - 1 - (h))))
@@ -77,29 +79,29 @@
 
 #define DISP_FREQ_MULTIPLIER 100
 
-#define MAX_PACKAGE_COUNT 8
-#define MAX_DIE_PER_PACKAGE 2
+#define MAX_PACKAGE_COUNT	8
+#define MAX_DIE_PER_PACKAGE	2
+#define MAX_PUNIT_PER_DIE	8
 
 /* Unified structure to specific a CPU or a Power Domain */
 struct isst_id {
 	int cpu;
 	int pkg;
 	int die;
+	int punit;
 };
 
 struct isst_clos_config {
+	unsigned int clos_min;
+	unsigned int clos_max;
 	unsigned char epp;
 	unsigned char clos_prop_prio;
-	unsigned char clos_min;
-	unsigned char clos_max;
 	unsigned char clos_desired;
 };
 
 struct isst_fact_bucket_info {
-	int high_priority_cores_count;
-	int sse_trl;
-	int avx_trl;
-	int avx512_trl;
+	int hp_cores;
+	int hp_ratios[TRL_MAX_LEVELS];
 };
 
 struct isst_pbf_info {
@@ -117,9 +119,7 @@ struct isst_pbf_info {
 #define ISST_TRL_MAX_ACTIVE_CORES	8
 #define ISST_FACT_MAX_BUCKETS		8
 struct isst_fact_info {
-	int lp_clipping_ratio_license_sse;
-	int lp_clipping_ratio_license_avx2;
-	int lp_clipping_ratio_license_avx512;
+	int lp_ratios[TRL_MAX_LEVELS];
 	struct isst_fact_bucket_info bucket_info[ISST_FACT_MAX_BUCKETS];
 };
 
@@ -143,20 +143,20 @@ struct isst_pkg_ctdp_level_info {
 	int pkg_max_power;
 	int fact;
 	int t_proc_hot;
+	int cooling_type;
 	int uncore_p0;
 	int uncore_p1;
 	int uncore_pm;
 	int sse_p1;
 	int avx2_p1;
 	int avx512_p1;
+	int amx_p1;
 	int mem_freq;
 	size_t core_cpumask_size;
 	cpu_set_t *core_cpumask;
 	int cpu_count;
-	unsigned long long buckets_info;
-	int trl_sse_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
-	int trl_avx_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
-	int trl_avx_512_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
+	unsigned long long trl_cores;	/* Buckets info */
+	int trl_ratios[TRL_MAX_LEVELS][ISST_TRL_MAX_ACTIVE_CORES];
 	int kobj_bucket_index;
 	int active_bucket;
 	int fact_max_index;
@@ -178,13 +178,48 @@ struct isst_pkg_ctdp {
 	struct isst_pkg_ctdp_level_info ctdp_level[ISST_MAX_TDP_LEVELS];
 };
 
+enum isst_platform_param {
+	ISST_PARAM_MBOX_DELAY,
+	ISST_PARAM_MBOX_RETRIES,
+};
+
+struct isst_platform_ops {
+	int (*get_disp_freq_multiplier)(void);
+	int (*get_trl_max_levels)(void);
+	char *(*get_trl_level_name)(int level);
+	void (*update_platform_param)(enum isst_platform_param param, int value);
+	int (*is_punit_valid)(struct isst_id *id);
+	int (*read_pm_config)(struct isst_id *id, int *cp_state, int *cp_cap);
+	int (*get_config_levels)(struct isst_id *id, struct isst_pkg_ctdp *pkg_ctdp);
+	int (*get_ctdp_control)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+	int (*get_tdp_info)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+	int (*get_pwr_info)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+	int (*get_coremask_info)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+	int (*get_get_trl)(struct isst_id *id, int level, int avx_level, int *trl);
+	int (*get_get_trls)(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level);
+	int (*get_trl_bucket_info)(struct isst_id *id, int level, unsigned long long *buckets_info);
+	int (*set_tdp_level)(struct isst_id *id, int tdp_level);
+	int (*get_pbf_info)(struct isst_id *id, int level, struct isst_pbf_info *pbf_info);
+	int (*set_pbf_fact_status)(struct isst_id *id, int pbf, int enable);
+	int (*get_fact_info)(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info);
+	void (*adjust_uncore_freq)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+	int (*get_clos_information)(struct isst_id *id, int *enable, int *type);
+	int (*pm_qos_config)(struct isst_id *id, int enable_clos, int priority_type);
+	int (*pm_get_clos)(struct isst_id *id, int clos, struct isst_clos_config *clos_config);
+	int (*set_clos)(struct isst_id *id, int clos, struct isst_clos_config *clos_config);
+	int (*clos_get_assoc_status)(struct isst_id *id, int *clos_id);
+	int (*clos_associate)(struct isst_id *id, int clos_id);
+};
+
 extern int is_cpu_in_power_domain(int cpu, struct isst_id *id);
 extern int get_topo_max_cpus(void);
 extern int get_cpu_count(struct isst_id *id);
 extern int get_max_punit_core_id(struct isst_id *id);
+extern int api_version(void);
 
 /* Common interfaces */
 FILE *get_output_file(void);
+extern int is_debug_enabled(void);
 extern void debug_printf(const char *format, ...);
 extern int out_format_is_json(void);
 extern void set_isst_id(struct isst_id *id, int cpu);
@@ -196,21 +231,22 @@ extern void set_cpu_mask_from_punit_coremask(struct isst_id *id,
 					     size_t core_cpumask_size,
 					     cpu_set_t *core_cpumask,
 					     int *cpu_cnt);
-
-extern int isst_send_mbox_command(unsigned int cpu, unsigned char command,
-				  unsigned char sub_command,
-				  unsigned int write,
-				  unsigned int req_data, unsigned int *resp);
-
 extern int isst_send_msr_command(unsigned int cpu, unsigned int command,
 				 int write, unsigned long long *req_resp);
 
+extern int isst_set_platform_ops(int api_version);
+extern void isst_update_platform_param(enum isst_platform_param, int vale);
+extern int isst_get_disp_freq_multiplier(void);
+extern int isst_get_trl_max_levels(void);
+extern char *isst_get_trl_level_name(int level);
+extern int isst_is_punit_valid(struct isst_id *id);
+
 extern int isst_get_ctdp_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev);
 extern int isst_get_ctdp_control(struct isst_id *id, int config_index,
 				 struct isst_pkg_ctdp_level_info *ctdp_level);
 extern int isst_get_coremask_info(struct isst_id *id, int config_index,
 			   struct isst_pkg_ctdp_level_info *ctdp_level);
-extern void isst_get_uncore_p0_p1_info(struct isst_id *id, int config_index,
+extern void isst_adjust_uncore_freq(struct isst_id *id, int config_index,
 					struct isst_pkg_ctdp_level_info *ctdp_level);
 extern int isst_get_process_ctdp(struct isst_id *id, int tdp_level,
 				 struct isst_pkg_ctdp *pkg_dev);
@@ -228,11 +264,8 @@ extern int isst_set_tdp_level(struct isst_id *id, int tdp_level);
 extern int isst_set_pbf_fact_status(struct isst_id *id, int pbf, int enable);
 extern int isst_get_pbf_info(struct isst_id *id, int level,
 			     struct isst_pbf_info *pbf_info);
-extern void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info);
 extern int isst_get_fact_info(struct isst_id *id, int level, int fact_bucket,
 			      struct isst_fact_info *fact_info);
-extern int isst_get_fact_bucket_info(struct isst_id *id, int level,
-				     struct isst_fact_bucket_info *bucket_info);
 extern void isst_fact_display_information(struct isst_id *id, FILE *outf, int level,
 					  int fact_bucket, int fact_avx,
 					  struct isst_fact_info *fact_info);
@@ -265,11 +298,12 @@ extern int isst_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap);
 extern void isst_display_error_info_message(int error, char *msg, int arg_valid, int arg);
 extern int is_skx_based_platform(void);
 extern int is_spr_platform(void);
+extern int is_emr_platform(void);
 extern int is_icx_platform(void);
 extern void isst_trl_display_information(struct isst_id *id, FILE *outf, unsigned long long trl);
 
 extern void set_cpu_online_offline(int cpu, int state);
-extern void for_each_online_package_in_set(void (*callback)(struct isst_id *, void *, void *,
+extern void for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void *, void *,
 							    void *, void *),
 					   void *arg1, void *arg2, void *arg3,
 					   void *arg4);
@@ -277,4 +311,14 @@ extern int isst_daemon(int debug_mode, int poll_interval, int no_daemon);
 extern void process_level_change(struct isst_id *id);
 extern int hfi_main(void);
 extern void hfi_exit(void);
+
+/* Interface specific callbacks */
+extern struct isst_platform_ops *mbox_get_platform_ops(void);
+extern struct isst_platform_ops *tpmi_get_platform_ops(void);
+
+/* Cgroup related interface */
+extern int enable_cpuset_controller(void);
+extern int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level);
+extern int use_cgroupv2(void);
+
 #endif