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 8 static int mbox_delay; 9 static int mbox_retries = 3; 10 11 #define MAX_TRL_LEVELS_EMR 5 12 13 static int mbox_get_disp_freq_multiplier(void) 14 { 15 return DISP_FREQ_MULTIPLIER; 16 } 17 18 static 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 26 static 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 50 static 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 64 static 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 75 static 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 123 int _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 219 static 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 237 static 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 264 static 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 299 static 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 327 try_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 345 static 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 373 static 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 384 static 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 408 static 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 441 static 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 480 static 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 502 static 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 536 static 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 575 static 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 588 static 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 606 static 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 628 static 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 695 static 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 746 static int _get_fact_bucket_info(struct isst_id *id, int level, 747 struct isst_fact_bucket_info *bucket_info) 748 { 749 unsigned int resp; 750 int i, k, ret; 751 752 for (i = 0; i < 2; ++i) { 753 int j; 754 755 ret = _send_mbox_command( 756 id->cpu, CONFIG_TDP, 757 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0, 758 (i << 8) | level, &resp); 759 if (ret) 760 return ret; 761 762 debug_printf( 763 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n", 764 id->cpu, i, level, resp); 765 766 for (j = 0; j < 4; ++j) { 767 bucket_info[j + (i * 4)].hp_cores = 768 (resp >> (j * 8)) & 0xff; 769 } 770 } 771 772 for (k = 0; k < 3; ++k) { 773 for (i = 0; i < 2; ++i) { 774 int j; 775 776 ret = _send_mbox_command( 777 id->cpu, CONFIG_TDP, 778 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0, 779 (k << 16) | (i << 8) | level, &resp); 780 if (ret) 781 return ret; 782 783 debug_printf( 784 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n", 785 id->cpu, i, level, k, resp); 786 787 for (j = 0; j < 4; ++j) { 788 bucket_info[j + (i * 4)].hp_ratios[k] = 789 (resp >> (j * 8)) & 0xff; 790 } 791 } 792 } 793 794 return 0; 795 } 796 797 static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info) 798 { 799 unsigned int resp; 800 int j, ret, print; 801 802 ret = _send_mbox_command(id->cpu, CONFIG_TDP, 803 CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0, 804 level, &resp); 805 if (ret) 806 return ret; 807 808 debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n", 809 id->cpu, resp); 810 811 fact_info->lp_ratios[0] = resp & 0xff; 812 fact_info->lp_ratios[1] = (resp >> 8) & 0xff; 813 fact_info->lp_ratios[2] = (resp >> 16) & 0xff; 814 815 ret = _get_fact_bucket_info(id, level, fact_info->bucket_info); 816 if (ret) 817 return ret; 818 819 print = 0; 820 for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) { 821 if (fact_bucket != 0xff && fact_bucket != j) 822 continue; 823 824 if (!fact_info->bucket_info[j].hp_cores) 825 break; 826 827 print = 1; 828 } 829 if (!print) { 830 isst_display_error_info_message(1, "Invalid bucket", 0, 0); 831 return -1; 832 } 833 834 return 0; 835 } 836 837 static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type) 838 { 839 unsigned int resp; 840 int ret; 841 842 ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, 843 &resp); 844 if (ret) 845 return ret; 846 847 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp); 848 849 if (resp & BIT(1)) 850 *enable = 1; 851 else 852 *enable = 0; 853 854 if (resp & BIT(2)) 855 *type = 1; 856 else 857 *type = 0; 858 859 return 0; 860 } 861 862 static int _write_pm_config(struct isst_id *id, int cp_state) 863 { 864 unsigned int req, resp; 865 int ret; 866 867 if (cp_state) 868 req = BIT(16); 869 else 870 req = 0; 871 872 ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req, 873 &resp); 874 if (ret) 875 return ret; 876 877 debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp); 878 879 return 0; 880 } 881 882 static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type) 883 { 884 unsigned int req, resp; 885 int ret; 886 887 if (!enable_clos) { 888 struct isst_pkg_ctdp pkg_dev; 889 struct isst_pkg_ctdp_level_info ctdp_level; 890 891 ret = isst_get_ctdp_levels(id, &pkg_dev); 892 if (ret) { 893 debug_printf("isst_get_ctdp_levels\n"); 894 return ret; 895 } 896 897 ret = isst_get_ctdp_control(id, pkg_dev.current_level, 898 &ctdp_level); 899 if (ret) 900 return ret; 901 902 if (ctdp_level.fact_enabled) { 903 isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0); 904 return -EINVAL; 905 } 906 ret = _write_pm_config(id, 0); 907 if (ret) 908 isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0); 909 } else { 910 ret = _write_pm_config(id, 1); 911 if (ret) 912 isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0); 913 } 914 915 ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, 916 &resp); 917 if (ret) { 918 isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0); 919 return ret; 920 } 921 922 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp); 923 924 req = resp; 925 926 if (enable_clos) 927 req = req | BIT(1); 928 else 929 req = req & ~BIT(1); 930 931 if (priority_type > 1) 932 isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0); 933 934 if (priority_type) 935 req = req | BIT(2); 936 else 937 req = req & ~BIT(2); 938 939 ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 940 BIT(MBOX_CMD_WRITE_BIT), req, &resp); 941 if (ret) 942 return ret; 943 944 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu, 945 priority_type, req); 946 947 return 0; 948 } 949 950 static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config) 951 { 952 unsigned int resp; 953 int ret; 954 955 ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0, 956 &resp); 957 if (ret) 958 return ret; 959 960 clos_config->epp = resp & 0x0f; 961 clos_config->clos_prop_prio = (resp >> 4) & 0x0f; 962 clos_config->clos_min = (resp >> 8) & 0xff; 963 clos_config->clos_max = (resp >> 16) & 0xff; 964 clos_config->clos_desired = (resp >> 24) & 0xff; 965 966 return 0; 967 } 968 969 static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config) 970 { 971 unsigned int req, resp; 972 unsigned int param; 973 int ret; 974 975 req = clos_config->epp & 0x0f; 976 req |= (clos_config->clos_prop_prio & 0x0f) << 4; 977 req |= (clos_config->clos_min & 0xff) << 8; 978 req |= (clos_config->clos_max & 0xff) << 16; 979 req |= (clos_config->clos_desired & 0xff) << 24; 980 981 param = BIT(MBOX_CMD_WRITE_BIT) | clos; 982 983 ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req, 984 &resp); 985 if (ret) 986 return ret; 987 988 debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req); 989 990 return 0; 991 } 992 993 static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id) 994 { 995 unsigned int resp; 996 unsigned int param; 997 int core_id, ret; 998 999 core_id = find_phy_core_num(id->cpu); 1000 param = core_id; 1001 1002 ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0, 1003 &resp); 1004 if (ret) 1005 return ret; 1006 1007 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param, 1008 resp); 1009 *clos_id = (resp >> 16) & 0x03; 1010 1011 return 0; 1012 } 1013 1014 static int mbox_clos_associate(struct isst_id *id, int clos_id) 1015 { 1016 unsigned int req, resp; 1017 unsigned int param; 1018 int core_id, ret; 1019 1020 req = (clos_id & 0x03) << 16; 1021 core_id = find_phy_core_num(id->cpu); 1022 param = BIT(MBOX_CMD_WRITE_BIT) | core_id; 1023 1024 ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 1025 req, &resp); 1026 if (ret) 1027 return ret; 1028 1029 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param, 1030 req); 1031 1032 return 0; 1033 } 1034 1035 static struct isst_platform_ops mbox_ops = { 1036 .get_disp_freq_multiplier = mbox_get_disp_freq_multiplier, 1037 .get_trl_max_levels = mbox_get_trl_max_levels, 1038 .get_trl_level_name = mbox_get_trl_level_name, 1039 .update_platform_param = mbox_update_platform_param, 1040 .is_punit_valid = mbox_is_punit_valid, 1041 .read_pm_config = mbox_read_pm_config, 1042 .get_config_levels = mbox_get_config_levels, 1043 .get_ctdp_control = mbox_get_ctdp_control, 1044 .get_tdp_info = mbox_get_tdp_info, 1045 .get_pwr_info = mbox_get_pwr_info, 1046 .get_coremask_info = mbox_get_coremask_info, 1047 .get_get_trl = mbox_get_get_trl, 1048 .get_get_trls = mbox_get_get_trls, 1049 .get_trl_bucket_info = mbox_get_trl_bucket_info, 1050 .set_tdp_level = mbox_set_tdp_level, 1051 .get_pbf_info = mbox_get_pbf_info, 1052 .set_pbf_fact_status = mbox_set_pbf_fact_status, 1053 .get_fact_info = mbox_get_fact_info, 1054 .adjust_uncore_freq = mbox_adjust_uncore_freq, 1055 .get_clos_information = mbox_get_clos_information, 1056 .pm_qos_config = mbox_pm_qos_config, 1057 .pm_get_clos = mbox_pm_get_clos, 1058 .set_clos = mbox_set_clos, 1059 .clos_get_assoc_status = mbox_clos_get_assoc_status, 1060 .clos_associate = mbox_clos_associate, 1061 }; 1062 1063 struct isst_platform_ops *mbox_get_platform_ops(void) 1064 { 1065 return &mbox_ops; 1066 } 1067