File Index
Files and directories
Sign in
FILE

isst-core-mbox.c

File preview with syntax highlighting.

linux-6.19.14/tools/power/x86/intel-speed-select/isst-core-mbox.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Intel Speed Select -- Enumerate and control features for Mailbox Interface
   4 * Copyright (c) 2023 Intel Corporation.
   5 */
   6#include "isst.h"
   7
   8static int mbox_delay;
   9static int mbox_retries = 3;
  10
  11#define MAX_TRL_LEVELS_EMR	5
  12
  13static int mbox_get_disp_freq_multiplier(void)
  14{
  15        return DISP_FREQ_MULTIPLIER;
  16}
  17
  18static int mbox_get_trl_max_levels(void)
  19{
  20	if (is_emr_platform())
  21		return MAX_TRL_LEVELS_EMR;
  22
  23        return 3;
  24}
  25
  26static char *mbox_get_trl_level_name(int level)
  27{
  28	if (is_emr_platform()) {
  29		static char level_str[18];
  30
  31		if (level >= MAX_TRL_LEVELS_EMR)
  32			return NULL;
  33
  34		snprintf(level_str, sizeof(level_str), "level-%d", level);
  35		return level_str;
  36	}
  37
  38        switch (level) {
  39        case 0:
  40                return "sse";
  41        case 1:
  42                return "avx2";
  43        case 2:
  44                return "avx512";
  45        default:
  46                return NULL;
  47        }
  48}
  49
  50static void mbox_update_platform_param(enum isst_platform_param param, int value)
  51{
  52	switch (param) {
  53	case ISST_PARAM_MBOX_DELAY:
  54		mbox_delay = value;
  55		break;
  56	case ISST_PARAM_MBOX_RETRIES:
  57		mbox_retries = value;
  58		break;
  59	default:
  60		break;
  61	}
  62}
  63
  64static int mbox_is_punit_valid(struct isst_id *id)
  65{
  66	if (id->cpu < 0)
  67		return 0;
  68
  69	if (id->pkg < 0 || id->die < 0 || id->punit)
  70		return 0;
  71
  72	return 1;
  73}
  74
  75static int _send_mmio_command(unsigned int cpu, unsigned int reg, int write,
  76				  unsigned int *value)
  77{
  78	struct isst_if_io_regs io_regs;
  79	const char *pathname = "/dev/isst_interface";
  80	int cmd;
  81	FILE *outf = get_output_file();
  82	int fd;
  83
  84	debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
  85
  86	fd = open(pathname, O_RDWR);
  87	if (fd < 0)
  88		err(-1, "%s open failed", pathname);
  89
  90	io_regs.req_count = 1;
  91	io_regs.io_reg[0].logical_cpu = cpu;
  92	io_regs.io_reg[0].reg = reg;
  93	cmd = ISST_IF_IO_CMD;
  94	if (write) {
  95		io_regs.io_reg[0].read_write = 1;
  96		io_regs.io_reg[0].value = *value;
  97	} else {
  98		io_regs.io_reg[0].read_write = 0;
  99	}
 100
 101	if (ioctl(fd, cmd, &io_regs) == -1) {
 102		if (errno == ENOTTY) {
 103			perror("ISST_IF_IO_COMMAND\n");
 104			fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
 105			exit(0);
 106		}
 107		fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
 108			cpu, reg, write);
 109	} else {
 110		if (!write)
 111			*value = io_regs.io_reg[0].value;
 112
 113		debug_printf(
 114			"mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
 115			cpu, reg, write, *value);
 116	}
 117
 118	close(fd);
 119
 120	return 0;
 121}
 122
 123int _send_mbox_command(unsigned int cpu, unsigned char command,
 124			   unsigned char sub_command, unsigned int parameter,
 125			   unsigned int req_data, unsigned int *resp)
 126{
 127	const char *pathname = "/dev/isst_interface";
 128	int fd, retry;
 129	struct isst_if_mbox_cmds mbox_cmds = { 0 };
 130
 131	debug_printf(
 132		"mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
 133		cpu, command, sub_command, parameter, req_data);
 134
 135	if (!is_skx_based_platform() && command == CONFIG_CLOS &&
 136	    sub_command != CLOS_PM_QOS_CONFIG) {
 137		unsigned int value;
 138		int write = 0;
 139		int clos_id, core_id, ret = 0;
 140
 141		debug_printf("CPU %d\n", cpu);
 142
 143		if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
 144			value = req_data;
 145			write = 1;
 146		}
 147
 148		switch (sub_command) {
 149		case CLOS_PQR_ASSOC:
 150			core_id = parameter & 0xff;
 151			ret = _send_mmio_command(
 152				cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
 153				&value);
 154			if (!ret && !write)
 155				*resp = value;
 156			break;
 157		case CLOS_PM_CLOS:
 158			clos_id = parameter & 0x03;
 159			ret = _send_mmio_command(
 160				cpu, PM_CLOS_OFFSET + clos_id * 4, write,
 161				&value);
 162			if (!ret && !write)
 163				*resp = value;
 164			break;
 165		case CLOS_STATUS:
 166			break;
 167		default:
 168			break;
 169		}
 170		return ret;
 171	}
 172
 173	mbox_cmds.cmd_count = 1;
 174	mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
 175	mbox_cmds.mbox_cmd[0].command = command;
 176	mbox_cmds.mbox_cmd[0].sub_command = sub_command;
 177	mbox_cmds.mbox_cmd[0].parameter = parameter;
 178	mbox_cmds.mbox_cmd[0].req_data = req_data;
 179
 180	if (mbox_delay)
 181		usleep(mbox_delay * 1000);
 182
 183	fd = open(pathname, O_RDWR);
 184	if (fd < 0)
 185		err(-1, "%s open failed", pathname);
 186
 187	retry = mbox_retries;
 188	do {
 189		if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
 190			if (errno == ENOTTY) {
 191				perror("ISST_IF_MBOX_COMMAND\n");
 192				fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
 193				exit(0);
 194			}
 195			debug_printf(
 196				"Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
 197				cpu, command, sub_command, parameter, req_data, errno);
 198			--retry;
 199		} else {
 200			*resp = mbox_cmds.mbox_cmd[0].resp_data;
 201			debug_printf(
 202				"mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
 203				cpu, command, sub_command, parameter, req_data, *resp);
 204			break;
 205		}
 206	} while (retry);
 207
 208	close(fd);
 209
 210	if (!retry) {
 211		debug_printf("Failed mbox command even after retries\n");
 212		return -1;
 213
 214	}
 215
 216	return 0;
 217}
 218
 219static int mbox_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
 220{
 221	unsigned int resp;
 222	int ret;
 223
 224	ret = _send_mbox_command(id->cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
 225					&resp);
 226	if (ret)
 227		return ret;
 228
 229	debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", id->cpu, resp);
 230
 231	*cp_state = resp & BIT(16);
 232	*cp_cap = resp & BIT(0) ? 1 : 0;
 233
 234	return 0;
 235}
 236
 237static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
 238{
 239	unsigned int resp;
 240	int ret;
 241
 242	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 243				     CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
 244	if (ret) {
 245		pkg_dev->levels = 0;
 246		pkg_dev->locked = 1;
 247		pkg_dev->current_level = 0;
 248		pkg_dev->version = 0;
 249		pkg_dev->enabled = 0;
 250		return 0;
 251	}
 252
 253	debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
 254
 255	pkg_dev->version = resp & 0xff;
 256	pkg_dev->levels = (resp >> 8) & 0xff;
 257	pkg_dev->current_level = (resp >> 16) & 0xff;
 258	pkg_dev->locked = !!(resp & BIT(24));
 259	pkg_dev->enabled = !!(resp & BIT(31));
 260
 261	return 0;
 262}
 263
 264static int mbox_get_ctdp_control(struct isst_id *id, int config_index,
 265			  struct isst_pkg_ctdp_level_info *ctdp_level)
 266{
 267	int cp_state, cp_cap;
 268	unsigned int resp;
 269	int ret;
 270
 271	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 272				     CONFIG_TDP_GET_TDP_CONTROL, 0,
 273				     config_index, &resp);
 274	if (ret)
 275		return ret;
 276
 277	ctdp_level->fact_support = resp & BIT(0);
 278	ctdp_level->pbf_support = !!(resp & BIT(1));
 279	ctdp_level->fact_enabled = !!(resp & BIT(16));
 280	ctdp_level->pbf_enabled = !!(resp & BIT(17));
 281
 282	ret = isst_read_pm_config(id, &cp_state, &cp_cap);
 283	if (ret) {
 284		debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
 285	} else {
 286		debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
 287		ctdp_level->sst_cp_support = cp_cap;
 288		ctdp_level->sst_cp_enabled = cp_state;
 289	}
 290
 291	debug_printf(
 292		"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
 293		id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
 294		ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
 295
 296	return 0;
 297}
 298
 299static void _get_uncore_p0_p1_info(struct isst_id *id, int config_index,
 300				struct isst_pkg_ctdp_level_info *ctdp_level)
 301{
 302	unsigned int resp;
 303	int ret;
 304
 305	ctdp_level->uncore_pm = 0;
 306	ctdp_level->uncore_p0 = 0;
 307	ctdp_level->uncore_p1 = 0;
 308
 309	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 310				     CONFIG_TDP_GET_RATIO_INFO, 0,
 311				     (BIT(16) | config_index) , &resp);
 312	if (ret) {
 313		goto try_uncore_mbox;
 314	}
 315
 316	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
 317	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
 318	ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24;
 319
 320	debug_printf(
 321		"cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n",
 322		id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1,
 323		ctdp_level->uncore_pm);
 324
 325	return;
 326
 327try_uncore_mbox:
 328	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 329				     CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
 330				     config_index, &resp);
 331	if (ret) {
 332		ctdp_level->uncore_p0 = 0;
 333		ctdp_level->uncore_p1 = 0;
 334		return;
 335	}
 336
 337	ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
 338	ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
 339	debug_printf(
 340		"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
 341		id->cpu, config_index, resp, ctdp_level->uncore_p0,
 342		ctdp_level->uncore_p1);
 343}
 344
 345static int _set_uncore_min_max(struct isst_id *id, int max, int freq)
 346{
 347	char buffer[128], freq_str[16];
 348	int fd, ret, len;
 349
 350	if (max)
 351		snprintf(buffer, sizeof(buffer),
 352			 "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/max_freq_khz", id->pkg, id->die);
 353	else
 354	        snprintf(buffer, sizeof(buffer),
 355			 "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/min_freq_khz", id->pkg, id->die);
 356
 357	fd = open(buffer, O_WRONLY);
 358	if (fd < 0)
 359		return fd;
 360
 361	snprintf(freq_str, sizeof(freq_str), "%d", freq);
 362	len = strlen(freq_str);
 363	ret = write(fd, freq_str, len);
 364	if (ret == -1) {
 365		close(fd);
 366		return ret;
 367	}
 368	close(fd);
 369
 370	return 0;
 371}
 372
 373static void mbox_adjust_uncore_freq(struct isst_id *id, int config_index,
 374				struct isst_pkg_ctdp_level_info *ctdp_level)
 375{
 376	_get_uncore_p0_p1_info(id, config_index, ctdp_level);
 377	if (ctdp_level->uncore_pm)
 378		_set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
 379
 380	if (ctdp_level->uncore_p0)
 381		_set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
 382}
 383
 384static void _get_p1_info(struct isst_id *id, int config_index,
 385		      struct isst_pkg_ctdp_level_info *ctdp_level)
 386{
 387	unsigned int resp;
 388	int ret;
 389	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
 390				     config_index, &resp);
 391	if (ret) {
 392		ctdp_level->sse_p1 = 0;
 393		ctdp_level->avx2_p1 = 0;
 394		ctdp_level->avx512_p1 = 0;
 395		return;
 396	}
 397
 398	ctdp_level->sse_p1 = resp & GENMASK(7, 0);
 399	ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
 400	ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
 401	ctdp_level->amx_p1 = (resp & GENMASK(31, 24)) >> 24;
 402	debug_printf(
 403		"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d amx_p1:%d\n",
 404		id->cpu, config_index, resp, ctdp_level->sse_p1,
 405		ctdp_level->avx2_p1, ctdp_level->avx512_p1, ctdp_level->amx_p1);
 406}
 407
 408static void _get_uncore_mem_freq(struct isst_id *id, int config_index,
 409			      struct isst_pkg_ctdp_level_info *ctdp_level)
 410{
 411	unsigned int resp;
 412	int ret;
 413
 414	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
 415				     0, config_index, &resp);
 416	if (ret) {
 417		ctdp_level->mem_freq = 0;
 418		return;
 419	}
 420
 421	ctdp_level->mem_freq = resp & GENMASK(7, 0);
 422	if (is_spr_platform() || is_emr_platform()) {
 423		ctdp_level->mem_freq *= 200;
 424	} else if (is_icx_platform()) {
 425		if (ctdp_level->mem_freq < 7) {
 426			ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
 427			ctdp_level->mem_freq /= 10;
 428			if (ctdp_level->mem_freq % 10 > 5)
 429				ctdp_level->mem_freq++;
 430		} else {
 431			ctdp_level->mem_freq = 0;
 432		}
 433	} else {
 434		ctdp_level->mem_freq = 0;
 435	}
 436	debug_printf(
 437		"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
 438		id->cpu, config_index, resp, ctdp_level->mem_freq);
 439}
 440
 441static int mbox_get_tdp_info(struct isst_id *id, int config_index,
 442		      struct isst_pkg_ctdp_level_info *ctdp_level)
 443{
 444	unsigned int resp;
 445	int ret;
 446
 447	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
 448				     0, config_index, &resp);
 449	if (ret) {
 450		isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
 451		return ret;
 452	}
 453
 454	ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
 455	ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
 456
 457	debug_printf(
 458		"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
 459		id->cpu, config_index, resp, ctdp_level->tdp_ratio,
 460		ctdp_level->pkg_tdp);
 461
 462	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
 463				     0, config_index, &resp);
 464	if (ret)
 465		return ret;
 466
 467	ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
 468
 469	_get_uncore_p0_p1_info(id, config_index, ctdp_level);
 470	_get_p1_info(id, config_index, ctdp_level);
 471	_get_uncore_mem_freq(id, config_index, ctdp_level);
 472
 473	debug_printf(
 474		"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
 475		id->cpu, config_index, resp, ctdp_level->t_proc_hot);
 476
 477	return 0;
 478}
 479
 480static int mbox_get_pwr_info(struct isst_id *id, int config_index,
 481		      struct isst_pkg_ctdp_level_info *ctdp_level)
 482{
 483	unsigned int resp;
 484	int ret;
 485
 486	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
 487				     0, config_index, &resp);
 488	if (ret)
 489		return ret;
 490
 491	ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
 492	ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
 493
 494	debug_printf(
 495		"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
 496		id->cpu, config_index, resp, ctdp_level->pkg_max_power,
 497		ctdp_level->pkg_min_power);
 498
 499	return 0;
 500}
 501
 502static int mbox_get_coremask_info(struct isst_id *id, int config_index,
 503			   struct isst_pkg_ctdp_level_info *ctdp_level)
 504{
 505	unsigned int resp;
 506	int i, ret;
 507
 508	ctdp_level->cpu_count = 0;
 509	for (i = 0; i < 2; ++i) {
 510		unsigned long long mask;
 511		int cpu_count = 0;
 512
 513		ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 514					     CONFIG_TDP_GET_CORE_MASK, 0,
 515					     (i << 8) | config_index, &resp);
 516		if (ret)
 517			return ret;
 518
 519		debug_printf(
 520			"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
 521			id->cpu, config_index, i, resp);
 522
 523		mask = (unsigned long long)resp << (32 * i);
 524		set_cpu_mask_from_punit_coremask(id, mask,
 525						 ctdp_level->core_cpumask_size,
 526						 ctdp_level->core_cpumask,
 527						 &cpu_count);
 528		ctdp_level->cpu_count += cpu_count;
 529		debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
 530			     config_index, i, ctdp_level->cpu_count);
 531	}
 532
 533	return 0;
 534}
 535
 536static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
 537{
 538	unsigned int req, resp;
 539	int ret;
 540
 541	req = level | (avx_level << 16);
 542	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 543				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
 544				     &resp);
 545	if (ret)
 546		return ret;
 547
 548	debug_printf(
 549		"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
 550		id->cpu, req, resp);
 551
 552	trl[0] = resp & GENMASK(7, 0);
 553	trl[1] = (resp & GENMASK(15, 8)) >> 8;
 554	trl[2] = (resp & GENMASK(23, 16)) >> 16;
 555	trl[3] = (resp & GENMASK(31, 24)) >> 24;
 556
 557	req = level | BIT(8) | (avx_level << 16);
 558	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 559				     CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
 560				     &resp);
 561	if (ret)
 562		return ret;
 563
 564	debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
 565		     req, resp);
 566
 567	trl[4] = resp & GENMASK(7, 0);
 568	trl[5] = (resp & GENMASK(15, 8)) >> 8;
 569	trl[6] = (resp & GENMASK(23, 16)) >> 16;
 570	trl[7] = (resp & GENMASK(31, 24)) >> 24;
 571
 572	return 0;
 573}
 574
 575static int mbox_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
 576{
 577	int trl_max_levels = isst_get_trl_max_levels();
 578	int i, ret;
 579
 580	for (i = 0; i < trl_max_levels; i++) {
 581		ret = mbox_get_get_trl(id, level, i, ctdp_level->trl_ratios[i]);
 582		if (ret)
 583			return ret;
 584	}
 585	return 0;
 586}
 587
 588static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
 589{
 590	int ret;
 591
 592	debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
 593
 594	*buckets_info = 0;
 595
 596	ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);
 597	if (ret)
 598		return ret;
 599
 600	debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
 601		     *buckets_info);
 602
 603	return 0;
 604}
 605
 606static int mbox_set_tdp_level(struct isst_id *id, int tdp_level)
 607{
 608	unsigned int resp;
 609	int ret;
 610
 611
 612	if (isst_get_config_tdp_lock_status(id)) {
 613		isst_display_error_info_message(1, "TDP is locked", 0, 0);
 614		return -1;
 615
 616	}
 617
 618	ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
 619				     tdp_level, &resp);
 620	if (ret) {
 621		isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
 622		return ret;
 623	}
 624
 625	return 0;
 626}
 627
 628static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
 629{
 630	int max_punit_core, max_mask_index;
 631	unsigned int req, resp;
 632	int i, ret;
 633
 634	max_punit_core = get_max_punit_core_id(id);
 635	max_mask_index = max_punit_core > 32 ? 2 : 1;
 636
 637	for (i = 0; i < max_mask_index; ++i) {
 638		unsigned long long mask;
 639		int count;
 640
 641		ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 642					     CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
 643					     0, (i << 8) | level, &resp);
 644		if (ret)
 645			break;
 646
 647		debug_printf(
 648			"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
 649			id->cpu, resp);
 650
 651		mask = (unsigned long long)resp << (32 * i);
 652		set_cpu_mask_from_punit_coremask(id, mask,
 653						 pbf_info->core_cpumask_size,
 654						 pbf_info->core_cpumask,
 655						 &count);
 656	}
 657
 658	req = level;
 659	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 660				     CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
 661				     &resp);
 662	if (ret)
 663		return ret;
 664
 665	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
 666		     resp);
 667
 668	pbf_info->p1_low = resp & 0xff;
 669	pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
 670
 671	req = level;
 672	ret = _send_mbox_command(
 673		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
 674	if (ret)
 675		return ret;
 676
 677	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);
 678
 679	pbf_info->tdp = resp & 0xffff;
 680
 681	req = level;
 682	ret = _send_mbox_command(
 683		id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
 684	if (ret)
 685		return ret;
 686
 687	debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,
 688		     resp);
 689	pbf_info->t_control = (resp >> 8) & 0xff;
 690	pbf_info->t_prochot = resp & 0xff;
 691
 692	return 0;
 693}
 694
 695static int mbox_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
 696{
 697	struct isst_pkg_ctdp pkg_dev;
 698	struct isst_pkg_ctdp_level_info ctdp_level;
 699	int current_level;
 700	unsigned int req = 0, resp;
 701	int ret;
 702
 703	ret = isst_get_ctdp_levels(id, &pkg_dev);
 704	if (ret)
 705		debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
 706
 707	current_level = pkg_dev.current_level;
 708
 709	ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
 710	if (ret)
 711		return ret;
 712
 713	if (pbf) {
 714		if (ctdp_level.fact_enabled)
 715			req = BIT(16);
 716
 717		if (enable)
 718			req |= BIT(17);
 719		else
 720			req &= ~BIT(17);
 721	} else {
 722
 723		if (enable && !ctdp_level.sst_cp_enabled)
 724			isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
 725
 726		if (ctdp_level.pbf_enabled)
 727			req = BIT(17);
 728
 729		if (enable)
 730			req |= BIT(16);
 731		else
 732			req &= ~BIT(16);
 733	}
 734
 735	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 736				     CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
 737	if (ret)
 738		return ret;
 739
 740	debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
 741		     id->cpu, pbf, req);
 742
 743	return 0;
 744}
 745
 746static int _get_fact_bucket_info(struct isst_id *id, int level,
 747			      struct isst_fact_bucket_info *bucket_info)
 748{
 749	int trl_max_levels = isst_get_trl_max_levels();
 750	unsigned int resp;
 751	int i, k, ret;
 752
 753	for (i = 0; i < 2; ++i) {
 754		int j;
 755
 756		ret = _send_mbox_command(
 757			id->cpu, CONFIG_TDP,
 758			CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
 759			(i << 8) | level, &resp);
 760		if (ret)
 761			return ret;
 762
 763		debug_printf(
 764			"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
 765			id->cpu, i, level, resp);
 766
 767		for (j = 0; j < 4; ++j) {
 768			bucket_info[j + (i * 4)].hp_cores =
 769				(resp >> (j * 8)) & 0xff;
 770		}
 771	}
 772
 773	for (k = 0; k < trl_max_levels; ++k) {
 774		for (i = 0; i < 2; ++i) {
 775			int j;
 776
 777			ret = _send_mbox_command(
 778				id->cpu, CONFIG_TDP,
 779				CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
 780				(k << 16) | (i << 8) | level, &resp);
 781			if (ret)
 782				return ret;
 783
 784			debug_printf(
 785				"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
 786				id->cpu, i, level, k, resp);
 787
 788			for (j = 0; j < 4; ++j) {
 789				bucket_info[j + (i * 4)].hp_ratios[k] =
 790					(resp >> (j * 8)) & 0xff;
 791			}
 792		}
 793	}
 794
 795	return 0;
 796}
 797
 798static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
 799{
 800	unsigned int resp;
 801	int j, ret, print;
 802
 803	ret = _send_mbox_command(id->cpu, CONFIG_TDP,
 804				     CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
 805				     level, &resp);
 806	if (ret)
 807		return ret;
 808
 809	debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
 810		     id->cpu, resp);
 811
 812	fact_info->lp_ratios[0] = resp & 0xff;
 813	fact_info->lp_ratios[1] = (resp >> 8) & 0xff;
 814	fact_info->lp_ratios[2] = (resp >> 16) & 0xff;
 815
 816	ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);
 817	if (ret)
 818		return ret;
 819
 820	print = 0;
 821	for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
 822		if (fact_bucket != 0xff && fact_bucket != j)
 823			continue;
 824
 825		if (!fact_info->bucket_info[j].hp_cores)
 826			break;
 827
 828		print = 1;
 829	}
 830	if (!print) {
 831		isst_display_error_info_message(1, "Invalid bucket", 0, 0);
 832		return -1;
 833	}
 834
 835	return 0;
 836}
 837
 838static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)
 839{
 840	unsigned int resp;
 841	int ret;
 842
 843	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
 844				     &resp);
 845	if (ret)
 846		return ret;
 847
 848	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
 849
 850	if (resp & BIT(1))
 851		*enable = 1;
 852	else
 853		*enable = 0;
 854
 855	if (resp & BIT(2))
 856		*type = 1;
 857	else
 858		*type = 0;
 859
 860	return 0;
 861}
 862
 863static int _write_pm_config(struct isst_id *id, int cp_state)
 864{
 865	unsigned int req, resp;
 866	int ret;
 867
 868	if (cp_state)
 869		req = BIT(16);
 870	else
 871		req = 0;
 872
 873	ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
 874				     &resp);
 875	if (ret)
 876		return ret;
 877
 878	debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
 879
 880	return 0;
 881}
 882
 883static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
 884{
 885	unsigned int req, resp;
 886	int ret;
 887
 888	if (!enable_clos) {
 889		struct isst_pkg_ctdp pkg_dev;
 890		struct isst_pkg_ctdp_level_info ctdp_level;
 891
 892		ret = isst_get_ctdp_levels(id, &pkg_dev);
 893		if (ret) {
 894			debug_printf("isst_get_ctdp_levels\n");
 895			return ret;
 896		}
 897
 898		ret = isst_get_ctdp_control(id, pkg_dev.current_level,
 899					    &ctdp_level);
 900		if (ret)
 901			return ret;
 902
 903		if (ctdp_level.fact_enabled) {
 904			isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
 905			return -EINVAL;
 906		}
 907		ret = _write_pm_config(id, 0);
 908		if (ret)
 909			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
 910	} else {
 911		ret = _write_pm_config(id, 1);
 912		if (ret)
 913			isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
 914	}
 915
 916	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
 917				     &resp);
 918	if (ret) {
 919		isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
 920		return ret;
 921	}
 922
 923	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
 924
 925	req = resp;
 926
 927	if (enable_clos)
 928		req = req | BIT(1);
 929	else
 930		req = req & ~BIT(1);
 931
 932	if (priority_type > 1)
 933		isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
 934
 935	if (priority_type)
 936		req = req | BIT(2);
 937	else
 938		req = req & ~BIT(2);
 939
 940	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
 941				     BIT(MBOX_CMD_WRITE_BIT), req, &resp);
 942	if (ret)
 943		return ret;
 944
 945	debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
 946		     priority_type, req);
 947
 948	return 0;
 949}
 950
 951static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
 952{
 953	unsigned int resp;
 954	int ret;
 955
 956	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
 957				     &resp);
 958	if (ret)
 959		return ret;
 960
 961	clos_config->epp = resp & 0x0f;
 962	clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
 963	clos_config->clos_min = (resp >> 8) & 0xff;
 964	clos_config->clos_max = (resp >> 16) & 0xff;
 965	clos_config->clos_desired = (resp >> 24) & 0xff;
 966
 967	return 0;
 968}
 969
 970static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
 971{
 972	unsigned int req, resp;
 973	unsigned int param;
 974	int ret;
 975
 976	req = clos_config->epp & 0x0f;
 977	req |= (clos_config->clos_prop_prio & 0x0f) << 4;
 978	req |= (clos_config->clos_min & 0xff) << 8;
 979	req |= (clos_config->clos_max & 0xff) << 16;
 980	req |= (clos_config->clos_desired & 0xff) << 24;
 981
 982	param = BIT(MBOX_CMD_WRITE_BIT) | clos;
 983
 984	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
 985				     &resp);
 986	if (ret)
 987		return ret;
 988
 989	debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
 990
 991	return 0;
 992}
 993
 994static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)
 995{
 996	unsigned int resp;
 997	unsigned int param;
 998	int core_id, ret;
 999
1000	core_id = find_phy_core_num(id->cpu);
1001	param = core_id;
1002
1003	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
1004				     &resp);
1005	if (ret)
1006		return ret;
1007
1008	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
1009		     resp);
1010	*clos_id = (resp >> 16) & 0x03;
1011
1012	return 0;
1013}
1014
1015static int mbox_clos_associate(struct isst_id *id, int clos_id)
1016{
1017	unsigned int req, resp;
1018	unsigned int param;
1019	int core_id, ret;
1020
1021	req = (clos_id & 0x03) << 16;
1022	core_id = find_phy_core_num(id->cpu);
1023	param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
1024
1025	ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
1026				     req, &resp);
1027	if (ret)
1028		return ret;
1029
1030	debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
1031		     req);
1032
1033	return 0;
1034}
1035
1036static struct isst_platform_ops mbox_ops = {
1037	.get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
1038	.get_trl_max_levels = mbox_get_trl_max_levels,
1039	.get_trl_level_name = mbox_get_trl_level_name,
1040	.update_platform_param = mbox_update_platform_param,
1041	.is_punit_valid = mbox_is_punit_valid,
1042	.read_pm_config = mbox_read_pm_config,
1043	.get_config_levels = mbox_get_config_levels,
1044	.get_ctdp_control = mbox_get_ctdp_control,
1045	.get_tdp_info = mbox_get_tdp_info,
1046	.get_pwr_info = mbox_get_pwr_info,
1047	.get_coremask_info = mbox_get_coremask_info,
1048	.get_get_trl = mbox_get_get_trl,
1049	.get_get_trls = mbox_get_get_trls,
1050	.get_trl_bucket_info = mbox_get_trl_bucket_info,
1051	.set_tdp_level = mbox_set_tdp_level,
1052	.get_pbf_info = mbox_get_pbf_info,
1053	.set_pbf_fact_status = mbox_set_pbf_fact_status,
1054	.get_fact_info = mbox_get_fact_info,
1055	.adjust_uncore_freq = mbox_adjust_uncore_freq,
1056	.get_clos_information = mbox_get_clos_information,
1057	.pm_qos_config = mbox_pm_qos_config,
1058	.pm_get_clos = mbox_pm_get_clos,
1059	.set_clos = mbox_set_clos,
1060	.clos_get_assoc_status = mbox_clos_get_assoc_status,
1061	.clos_associate = mbox_clos_associate,
1062};
1063
1064struct isst_platform_ops *mbox_get_platform_ops(void)
1065{
1066	return &mbox_ops;
1067}
~/ Read-only file preview.