1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intel Speed Select -- Enumerate and control features for TPMI Interface 4 * Copyright (c) 2022 Intel Corporation. 5 */ 6 7 #include <linux/isst_if.h> 8 #include "isst.h" 9 10 int tpmi_process_ioctl(int ioctl_no, void *info) 11 { 12 const char *pathname = "/dev/isst_interface"; 13 int fd; 14 15 if (is_debug_enabled()) { 16 debug_printf("Issue IOCTL: "); 17 switch (ioctl_no) { 18 case ISST_IF_CORE_POWER_STATE: 19 debug_printf("ISST_IF_CORE_POWER_STATE\n"); 20 break; 21 case ISST_IF_CLOS_PARAM: 22 debug_printf("ISST_IF_CLOS_PARAM\n"); 23 break; 24 case ISST_IF_CLOS_ASSOC: 25 debug_printf("ISST_IF_CLOS_ASSOC\n"); 26 break; 27 case ISST_IF_PERF_LEVELS: 28 debug_printf("ISST_IF_PERF_LEVELS\n"); 29 break; 30 case ISST_IF_PERF_SET_LEVEL: 31 debug_printf("ISST_IF_PERF_SET_LEVEL\n"); 32 break; 33 case ISST_IF_PERF_SET_FEATURE: 34 debug_printf("ISST_IF_PERF_SET_FEATURE\n"); 35 break; 36 case ISST_IF_GET_PERF_LEVEL_INFO: 37 debug_printf("ISST_IF_GET_PERF_LEVEL_INFO\n"); 38 break; 39 case ISST_IF_GET_PERF_LEVEL_CPU_MASK: 40 debug_printf("ISST_IF_GET_PERF_LEVEL_CPU_MASK\n"); 41 break; 42 case ISST_IF_GET_BASE_FREQ_INFO: 43 debug_printf("ISST_IF_GET_BASE_FREQ_INFO\n"); 44 break; 45 case ISST_IF_GET_BASE_FREQ_CPU_MASK: 46 debug_printf("ISST_IF_GET_BASE_FREQ_CPU_MASK\n"); 47 break; 48 case ISST_IF_GET_TURBO_FREQ_INFO: 49 debug_printf("ISST_IF_GET_TURBO_FREQ_INFO\n"); 50 break; 51 case ISST_IF_COUNT_TPMI_INSTANCES: 52 debug_printf("ISST_IF_COUNT_TPMI_INSTANCES\n"); 53 break; 54 default: 55 debug_printf("%d\n", ioctl_no); 56 break; 57 } 58 } 59 60 fd = open(pathname, O_RDWR); 61 if (fd < 0) 62 return -1; 63 64 if (ioctl(fd, ioctl_no, info) == -1) { 65 debug_printf("IOCTL %d Failed\n", ioctl_no); 66 close(fd); 67 return -1; 68 } 69 70 close(fd); 71 72 return 0; 73 } 74 75 static int tpmi_get_disp_freq_multiplier(void) 76 { 77 return 1; 78 } 79 80 static int tpmi_get_trl_max_levels(void) 81 { 82 return TRL_MAX_LEVELS; 83 } 84 85 static char *tpmi_get_trl_level_name(int level) 86 { 87 switch (level) { 88 case 0: 89 return "level-0"; 90 case 1: 91 return "level-1"; 92 case 2: 93 return "level-2"; 94 case 3: 95 return "level-3"; 96 case 4: 97 return "level-4"; 98 case 5: 99 return "level-5"; 100 case 6: 101 return "level-6"; 102 case 7: 103 return "level-7"; 104 default: 105 return NULL; 106 } 107 } 108 109 110 static void tpmi_update_platform_param(enum isst_platform_param param, int value) 111 { 112 /* No params need to be updated for now */ 113 } 114 115 static int tpmi_is_punit_valid(struct isst_id *id) 116 { 117 struct isst_tpmi_instance_count info; 118 int ret; 119 120 if (id->punit < 0) 121 return 0; 122 123 info.socket_id = id->pkg; 124 ret = tpmi_process_ioctl(ISST_IF_COUNT_TPMI_INSTANCES, &info); 125 if (ret == -1) 126 return 0; 127 128 if (info.valid_mask & BIT(id->punit)) 129 return 1; 130 131 return 0; 132 } 133 134 static int tpmi_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap) 135 { 136 struct isst_core_power info; 137 int ret; 138 139 info.get_set = 0; 140 info.socket_id = id->pkg; 141 info.power_domain_id = id->punit; 142 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info); 143 if (ret == -1) 144 return ret; 145 146 *cp_state = info.enable; 147 *cp_cap = info.supported; 148 149 return 0; 150 } 151 152 int tpmi_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev) 153 { 154 struct isst_perf_level_info info; 155 int ret; 156 157 info.socket_id = id->pkg; 158 info.power_domain_id = id->punit; 159 160 ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info); 161 if (ret == -1) 162 return ret; 163 164 pkg_dev->version = info.feature_rev; 165 pkg_dev->levels = info.max_level; 166 pkg_dev->locked = info.locked; 167 pkg_dev->current_level = info.current_level; 168 pkg_dev->locked = info.locked; 169 pkg_dev->enabled = info.enabled; 170 171 return 0; 172 } 173 174 static int tpmi_get_ctdp_control(struct isst_id *id, int config_index, 175 struct isst_pkg_ctdp_level_info *ctdp_level) 176 { 177 struct isst_core_power core_power_info; 178 struct isst_perf_level_info info; 179 int level_mask; 180 int ret; 181 182 info.socket_id = id->pkg; 183 info.power_domain_id = id->punit; 184 185 ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info); 186 if (ret == -1) 187 return -1; 188 189 if (config_index != 0xff) 190 level_mask = 1 << config_index; 191 else 192 level_mask = config_index; 193 194 if (!(info.level_mask & level_mask)) 195 return -1; 196 197 if (api_version() > 2) { 198 ctdp_level->fact_support = info.sst_tf_support & BIT(config_index); 199 ctdp_level->pbf_support = info.sst_bf_support & BIT(config_index); 200 } else { 201 ctdp_level->fact_support = info.sst_tf_support; 202 ctdp_level->pbf_support = info.sst_bf_support; 203 } 204 205 ctdp_level->fact_enabled = !!(info.feature_state & BIT(1)); 206 ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0)); 207 208 core_power_info.get_set = 0; 209 core_power_info.socket_id = id->pkg; 210 core_power_info.power_domain_id = id->punit; 211 212 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info); 213 if (ret == -1) 214 return ret; 215 216 ctdp_level->sst_cp_support = core_power_info.supported; 217 ctdp_level->sst_cp_enabled = core_power_info.enable; 218 219 debug_printf 220 ("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n", 221 id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support, 222 ctdp_level->fact_enabled, ctdp_level->pbf_enabled); 223 224 return 0; 225 } 226 227 static int tpmi_get_tdp_info(struct isst_id *id, int config_index, 228 struct isst_pkg_ctdp_level_info *ctdp_level) 229 { 230 struct isst_perf_level_fabric_info fabric_info; 231 struct isst_perf_level_data_info info; 232 int ret; 233 234 info.socket_id = id->pkg; 235 info.power_domain_id = id->punit; 236 info.level = config_index; 237 238 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info); 239 if (ret == -1) 240 return ret; 241 242 ctdp_level->pkg_tdp = info.thermal_design_power_w; 243 ctdp_level->tdp_ratio = info.tdp_ratio; 244 ctdp_level->sse_p1 = info.base_freq_mhz; 245 ctdp_level->avx2_p1 = info.base_freq_avx2_mhz; 246 ctdp_level->avx512_p1 = info.base_freq_avx512_mhz; 247 ctdp_level->amx_p1 = info.base_freq_amx_mhz; 248 249 ctdp_level->t_proc_hot = info.tjunction_max_c; 250 ctdp_level->mem_freq = info.max_memory_freq_mhz; 251 ctdp_level->cooling_type = info.cooling_type; 252 253 ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz; 254 ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz; 255 ctdp_level->uncore_pm = info.pm_fabric_freq_mhz; 256 257 fabric_info.socket_id = id->pkg; 258 fabric_info.power_domain_id = id->punit; 259 fabric_info.level = config_index; 260 261 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_FABRIC_INFO, &fabric_info); 262 if (ret != -1) { 263 ctdp_level->uncore1_p0 = fabric_info.p0_fabric_freq_mhz[1]; 264 ctdp_level->uncore1_p1 = fabric_info.p1_fabric_freq_mhz[1]; 265 ctdp_level->uncore1_pm = fabric_info.pm_fabric_freq_mhz[1]; 266 } 267 268 debug_printf 269 ("cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO tdp_ratio:%d pkg_tdp:%d ctdp_level->t_proc_hot:%d\n", 270 id->cpu, config_index, ctdp_level->tdp_ratio, ctdp_level->pkg_tdp, 271 ctdp_level->t_proc_hot); 272 273 return 0; 274 } 275 276 static int tpmi_get_pwr_info(struct isst_id *id, int config_index, 277 struct isst_pkg_ctdp_level_info *ctdp_level) 278 { 279 /* TBD */ 280 ctdp_level->pkg_max_power = 0; 281 ctdp_level->pkg_min_power = 0; 282 283 debug_printf 284 ("cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO pkg_max_power:%d pkg_min_power:%d\n", 285 id->cpu, config_index, ctdp_level->pkg_max_power, 286 ctdp_level->pkg_min_power); 287 288 return 0; 289 } 290 291 int tpmi_get_coremask_info(struct isst_id *id, int config_index, 292 struct isst_pkg_ctdp_level_info *ctdp_level) 293 { 294 struct isst_perf_level_cpu_mask info; 295 int ret, cpu_count; 296 297 info.socket_id = id->pkg; 298 info.power_domain_id = id->punit; 299 info.level = config_index; 300 info.punit_cpu_map = 1; 301 302 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_CPU_MASK, &info); 303 if (ret == -1) 304 return ret; 305 306 set_cpu_mask_from_punit_coremask(id, info.mask, 307 ctdp_level->core_cpumask_size, 308 ctdp_level->core_cpumask, &cpu_count); 309 ctdp_level->cpu_count = cpu_count; 310 311 debug_printf("cpu:%d ctdp:%d core_mask ino cpu count:%d\n", 312 id->cpu, config_index, ctdp_level->cpu_count); 313 314 return 0; 315 } 316 317 static int tpmi_get_get_trls(struct isst_id *id, int config_index, 318 struct isst_pkg_ctdp_level_info *ctdp_level) 319 { 320 struct isst_perf_level_data_info info; 321 int ret, i, j; 322 323 info.socket_id = id->pkg; 324 info.power_domain_id = id->punit; 325 info.level = config_index; 326 327 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info); 328 if (ret == -1) 329 return ret; 330 331 if (info.max_buckets > TRL_MAX_BUCKETS) 332 info.max_buckets = TRL_MAX_BUCKETS; 333 334 if (info.max_trl_levels > TRL_MAX_LEVELS) 335 info.max_trl_levels = TRL_MAX_LEVELS; 336 337 for (i = 0; i < info.max_trl_levels; ++i) 338 for (j = 0; j < info.max_buckets; ++j) 339 ctdp_level->trl_ratios[i][j] = info.trl_freq_mhz[i][j]; 340 341 return 0; 342 } 343 344 static int tpmi_get_get_trl(struct isst_id *id, int config_index, int level, 345 int *trl) 346 { 347 struct isst_pkg_ctdp_level_info ctdp_level; 348 int ret, i; 349 350 ret = tpmi_get_get_trls(id, config_index, &ctdp_level); 351 if (ret) 352 return ret; 353 354 /* FIX ME: Just return for level 0 */ 355 for (i = 0; i < 8; ++i) 356 trl[i] = ctdp_level.trl_ratios[0][i]; 357 358 return 0; 359 } 360 361 static int tpmi_get_trl_bucket_info(struct isst_id *id, int config_index, 362 unsigned long long *buckets_info) 363 { 364 struct isst_perf_level_data_info info; 365 unsigned char *mask = (unsigned char *)buckets_info; 366 int ret, i; 367 368 info.socket_id = id->pkg; 369 info.power_domain_id = id->punit; 370 info.level = config_index; 371 372 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info); 373 if (ret == -1) 374 return ret; 375 376 if (info.max_buckets > TRL_MAX_BUCKETS) 377 info.max_buckets = TRL_MAX_BUCKETS; 378 379 for (i = 0; i < info.max_buckets; ++i) 380 mask[i] = info.bucket_core_counts[i]; 381 382 debug_printf("cpu:%d TRL bucket info: 0x%llx\n", id->cpu, 383 *buckets_info); 384 385 return 0; 386 } 387 388 static int tpmi_set_tdp_level(struct isst_id *id, int tdp_level) 389 { 390 struct isst_perf_level_control info; 391 int ret; 392 393 info.socket_id = id->pkg; 394 info.power_domain_id = id->punit; 395 info.level = tdp_level; 396 397 ret = tpmi_process_ioctl(ISST_IF_PERF_SET_LEVEL, &info); 398 if (ret == -1) 399 return ret; 400 401 return 0; 402 } 403 404 static int _pbf_get_coremask_info(struct isst_id *id, int config_index, 405 struct isst_pbf_info *pbf_info) 406 { 407 struct isst_perf_level_cpu_mask info; 408 int ret, cpu_count; 409 410 info.socket_id = id->pkg; 411 info.power_domain_id = id->punit; 412 info.level = config_index; 413 info.punit_cpu_map = 1; 414 415 ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_CPU_MASK, &info); 416 if (ret == -1) 417 return ret; 418 419 set_cpu_mask_from_punit_coremask(id, info.mask, 420 pbf_info->core_cpumask_size, 421 pbf_info->core_cpumask, &cpu_count); 422 423 debug_printf("cpu:%d ctdp:%d pbf core_mask info cpu count:%d\n", 424 id->cpu, config_index, cpu_count); 425 426 return 0; 427 } 428 429 static int tpmi_get_pbf_info(struct isst_id *id, int level, 430 struct isst_pbf_info *pbf_info) 431 { 432 struct isst_base_freq_info info; 433 int ret; 434 435 info.socket_id = id->pkg; 436 info.power_domain_id = id->punit; 437 info.level = level; 438 439 ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_INFO, &info); 440 if (ret == -1) 441 return ret; 442 443 pbf_info->p1_low = info.low_base_freq_mhz; 444 pbf_info->p1_high = info.high_base_freq_mhz; 445 pbf_info->tdp = info.thermal_design_power_w; 446 pbf_info->t_prochot = info.tjunction_max_c; 447 448 debug_printf("cpu:%d ctdp:%d pbf info:%d:%d:%d:%d\n", 449 id->cpu, level, pbf_info->p1_low, pbf_info->p1_high, 450 pbf_info->tdp, pbf_info->t_prochot); 451 452 return _pbf_get_coremask_info(id, level, pbf_info); 453 } 454 455 static int tpmi_set_pbf_fact_status(struct isst_id *id, int pbf, int enable) 456 { 457 struct isst_pkg_ctdp pkg_dev; 458 struct isst_pkg_ctdp_level_info ctdp_level; 459 int current_level; 460 struct isst_perf_feature_control info; 461 int ret; 462 463 ret = isst_get_ctdp_levels(id, &pkg_dev); 464 if (ret) 465 debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu); 466 467 current_level = pkg_dev.current_level; 468 469 ret = isst_get_ctdp_control(id, current_level, &ctdp_level); 470 if (ret) 471 return ret; 472 473 info.socket_id = id->pkg; 474 info.power_domain_id = id->punit; 475 476 info.feature = 0; 477 478 if (pbf) { 479 if (ctdp_level.fact_enabled) 480 info.feature |= BIT(1); 481 482 if (enable) 483 info.feature |= BIT(0); 484 else 485 info.feature &= ~BIT(0); 486 } else { 487 488 if (enable && !ctdp_level.sst_cp_enabled) 489 isst_display_error_info_message(0, 490 "Make sure to execute before: core-power enable", 491 0, 0); 492 493 if (ctdp_level.pbf_enabled) 494 info.feature |= BIT(0); 495 496 if (enable) 497 info.feature |= BIT(1); 498 else 499 info.feature &= ~BIT(1); 500 } 501 502 ret = tpmi_process_ioctl(ISST_IF_PERF_SET_FEATURE, &info); 503 if (ret == -1) 504 return ret; 505 506 return 0; 507 } 508 509 static int tpmi_get_fact_info(struct isst_id *id, int level, int fact_bucket, 510 struct isst_fact_info *fact_info) 511 { 512 struct isst_turbo_freq_info info; 513 int i, j; 514 int ret; 515 516 info.socket_id = id->pkg; 517 info.power_domain_id = id->punit; 518 info.level = level; 519 520 ret = tpmi_process_ioctl(ISST_IF_GET_TURBO_FREQ_INFO, &info); 521 if (ret == -1) 522 return ret; 523 524 for (i = 0; i < info.max_clip_freqs; ++i) 525 fact_info->lp_ratios[i] = info.lp_clip_freq_mhz[i]; 526 527 if (info.max_buckets > TRL_MAX_BUCKETS) 528 info.max_buckets = TRL_MAX_BUCKETS; 529 530 if (info.max_trl_levels > TRL_MAX_LEVELS) 531 info.max_trl_levels = TRL_MAX_LEVELS; 532 533 for (i = 0; i < info.max_trl_levels; ++i) { 534 for (j = 0; j < info.max_buckets; ++j) 535 fact_info->bucket_info[j].hp_ratios[i] = 536 info.trl_freq_mhz[i][j]; 537 } 538 539 for (i = 0; i < info.max_buckets; ++i) 540 fact_info->bucket_info[i].hp_cores = info.bucket_core_counts[i]; 541 542 return 0; 543 } 544 545 static void _set_uncore_min_max(struct isst_id *id, int max, int freq) 546 { 547 DIR *dir; 548 FILE *filep; 549 struct dirent *entry; 550 char buffer[512]; 551 unsigned int tmp_id; 552 int ret; 553 554 dir = opendir("/sys/devices/system/cpu/intel_uncore_frequency/"); 555 if (!dir) 556 return; 557 558 while ((entry = readdir(dir)) != NULL ) { 559 /* Check domain_id */ 560 snprintf(buffer, sizeof(buffer), 561 "/sys/devices/system/cpu/intel_uncore_frequency/%s/domain_id", entry->d_name); 562 563 filep = fopen(buffer, "r"); 564 if (!filep) 565 goto end; 566 567 ret = fscanf(filep, "%u", &tmp_id); 568 fclose(filep); 569 if (ret != 1) 570 goto end; 571 572 if (tmp_id != id->punit) 573 continue; 574 575 /* Check package_id */ 576 snprintf(buffer, sizeof(buffer), 577 "/sys/devices/system/cpu/intel_uncore_frequency/%s/package_id", entry->d_name); 578 579 filep = fopen(buffer, "r"); 580 if (!filep) 581 goto end; 582 583 ret = fscanf(filep, "%u", &tmp_id); 584 fclose(filep); 585 586 if (ret != 1) 587 goto end; 588 589 if (tmp_id != id->pkg) 590 continue; 591 592 /* Found the right sysfs path, adjust and quit */ 593 if (max) 594 snprintf(buffer, sizeof(buffer), 595 "/sys/devices/system/cpu/intel_uncore_frequency/%s/max_freq_khz", entry->d_name); 596 else 597 snprintf(buffer, sizeof(buffer), 598 "/sys/devices/system/cpu/intel_uncore_frequency/%s/min_freq_khz", entry->d_name); 599 600 filep = fopen(buffer, "w"); 601 if (!filep) 602 goto end; 603 604 fprintf(filep, "%d\n", freq); 605 fclose(filep); 606 break; 607 } 608 609 end: 610 closedir(dir); 611 } 612 613 static void tpmi_adjust_uncore_freq(struct isst_id *id, int config_index, 614 struct isst_pkg_ctdp_level_info *ctdp_level) 615 { 616 struct isst_perf_level_data_info info; 617 int ret; 618 619 info.socket_id = id->pkg; 620 info.power_domain_id = id->punit; 621 info.level = config_index; 622 623 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info); 624 if (ret == -1) 625 return; 626 627 ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz; 628 ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz; 629 ctdp_level->uncore_pm = info.pm_fabric_freq_mhz; 630 631 if (ctdp_level->uncore_pm) 632 _set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000); 633 634 if (ctdp_level->uncore_p0) 635 _set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000); 636 637 return; 638 } 639 640 static int tpmi_get_clos_information(struct isst_id *id, int *enable, int *type) 641 { 642 struct isst_core_power info; 643 int ret; 644 645 info.get_set = 0; 646 info.socket_id = id->pkg; 647 info.power_domain_id = id->punit; 648 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info); 649 if (ret == -1) 650 return ret; 651 652 *enable = info.enable; 653 *type = info.priority_type; 654 655 return 0; 656 } 657 658 static int tpmi_pm_qos_config(struct isst_id *id, int enable_clos, 659 int priority_type) 660 { 661 struct isst_core_power info; 662 int i, ret, saved_punit; 663 664 info.get_set = 1; 665 info.socket_id = id->pkg; 666 info.power_domain_id = id->punit; 667 info.enable = enable_clos; 668 info.priority_type = priority_type; 669 670 saved_punit = id->punit; 671 672 /* Set for all other dies also. This is per package setting */ 673 for (i = 0; i < MAX_PUNIT_PER_DIE; i++) { 674 id->punit = i; 675 if (isst_is_punit_valid(id)) { 676 info.power_domain_id = i; 677 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info); 678 if (ret == -1) { 679 id->punit = saved_punit; 680 return ret; 681 } 682 } 683 } 684 685 id->punit = saved_punit; 686 687 return 0; 688 } 689 690 int tpmi_pm_get_clos(struct isst_id *id, int clos, 691 struct isst_clos_config *clos_config) 692 { 693 struct isst_clos_param info; 694 int ret; 695 696 info.get_set = 0; 697 info.socket_id = id->pkg; 698 info.power_domain_id = id->punit; 699 info.clos = clos; 700 701 ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info); 702 if (ret == -1) 703 return ret; 704 705 clos_config->epp = 0; 706 clos_config->clos_prop_prio = info.prop_prio; 707 clos_config->clos_min = info.min_freq_mhz; 708 clos_config->clos_max = info.max_freq_mhz; 709 clos_config->clos_desired = 0; 710 711 debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos, 712 clos_config->clos_min, clos_config->clos_max); 713 714 return 0; 715 } 716 717 int tpmi_set_clos(struct isst_id *id, int clos, 718 struct isst_clos_config *clos_config) 719 { 720 struct isst_clos_param info; 721 int i, ret, saved_punit; 722 723 info.get_set = 1; 724 info.socket_id = id->pkg; 725 info.power_domain_id = id->punit; 726 info.clos = clos; 727 info.prop_prio = clos_config->clos_prop_prio; 728 729 info.min_freq_mhz = clos_config->clos_min; 730 info.max_freq_mhz = clos_config->clos_max; 731 732 if (info.min_freq_mhz <= 0xff) 733 info.min_freq_mhz *= 100; 734 if (info.max_freq_mhz <= 0xff) 735 info.max_freq_mhz *= 100; 736 737 saved_punit = id->punit; 738 739 /* Set for all other dies also. This is per package setting */ 740 for (i = 0; i < MAX_PUNIT_PER_DIE; i++) { 741 id->punit = i; 742 if (isst_is_punit_valid(id)) { 743 info.power_domain_id = i; 744 ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info); 745 if (ret == -1) { 746 id->punit = saved_punit; 747 return ret; 748 } 749 } 750 } 751 752 id->punit = saved_punit; 753 754 debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos, 755 clos_config->clos_min, clos_config->clos_max); 756 757 return 0; 758 } 759 760 static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id) 761 { 762 struct isst_if_clos_assoc_cmds assoc_cmds; 763 int ret; 764 765 assoc_cmds.cmd_count = 1; 766 assoc_cmds.get_set = 0; 767 assoc_cmds.punit_cpu_map = 1; 768 assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu); 769 assoc_cmds.assoc_info[0].socket_id = id->pkg; 770 assoc_cmds.assoc_info[0].power_domain_id = id->punit; 771 772 ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds); 773 if (ret == -1) 774 return ret; 775 776 *clos_id = assoc_cmds.assoc_info[0].clos; 777 778 return 0; 779 } 780 781 static int tpmi_clos_associate(struct isst_id *id, int clos_id) 782 { 783 struct isst_if_clos_assoc_cmds assoc_cmds; 784 int ret; 785 786 assoc_cmds.cmd_count = 1; 787 assoc_cmds.get_set = 1; 788 assoc_cmds.punit_cpu_map = 1; 789 assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu); 790 assoc_cmds.assoc_info[0].clos = clos_id; 791 assoc_cmds.assoc_info[0].socket_id = id->pkg; 792 assoc_cmds.assoc_info[0].power_domain_id = id->punit; 793 794 ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds); 795 if (ret == -1) 796 return ret; 797 798 return 0; 799 } 800 801 static struct isst_platform_ops tpmi_ops = { 802 .get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier, 803 .get_trl_max_levels = tpmi_get_trl_max_levels, 804 .get_trl_level_name = tpmi_get_trl_level_name, 805 .update_platform_param = tpmi_update_platform_param, 806 .is_punit_valid = tpmi_is_punit_valid, 807 .read_pm_config = tpmi_read_pm_config, 808 .get_config_levels = tpmi_get_config_levels, 809 .get_ctdp_control = tpmi_get_ctdp_control, 810 .get_tdp_info = tpmi_get_tdp_info, 811 .get_pwr_info = tpmi_get_pwr_info, 812 .get_coremask_info = tpmi_get_coremask_info, 813 .get_get_trl = tpmi_get_get_trl, 814 .get_get_trls = tpmi_get_get_trls, 815 .get_trl_bucket_info = tpmi_get_trl_bucket_info, 816 .set_tdp_level = tpmi_set_tdp_level, 817 .get_pbf_info = tpmi_get_pbf_info, 818 .set_pbf_fact_status = tpmi_set_pbf_fact_status, 819 .get_fact_info = tpmi_get_fact_info, 820 .adjust_uncore_freq = tpmi_adjust_uncore_freq, 821 .get_clos_information = tpmi_get_clos_information, 822 .pm_qos_config = tpmi_pm_qos_config, 823 .pm_get_clos = tpmi_pm_get_clos, 824 .set_clos = tpmi_set_clos, 825 .clos_get_assoc_status = tpmi_clos_get_assoc_status, 826 .clos_associate = tpmi_clos_associate, 827 }; 828 829 struct isst_platform_ops *tpmi_get_platform_ops(void) 830 { 831 return &tpmi_ops; 832 } 833