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_get_disp_freq_multiplier(void) 9 { 10 return DISP_FREQ_MULTIPLIER; 11 } 12 13 static int mbox_get_trl_max_levels(void) 14 { 15 return 3; 16 } 17 18 static char *mbox_get_trl_level_name(int level) 19 { 20 switch (level) { 21 case 0: 22 return "sse"; 23 case 1: 24 return "avx2"; 25 case 2: 26 return "avx512"; 27 default: 28 return NULL; 29 } 30 } 31 32 static int mbox_is_punit_valid(struct isst_id *id) 33 { 34 if (id->cpu < 0) 35 return 0; 36 37 if (id->pkg < 0 || id->die < 0 || id->punit) 38 return 0; 39 40 return 1; 41 } 42 43 static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev) 44 { 45 unsigned int resp; 46 int ret; 47 48 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 49 CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp); 50 if (ret) { 51 pkg_dev->levels = 0; 52 pkg_dev->locked = 1; 53 pkg_dev->current_level = 0; 54 pkg_dev->version = 0; 55 pkg_dev->enabled = 0; 56 return 0; 57 } 58 59 debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp); 60 61 pkg_dev->version = resp & 0xff; 62 pkg_dev->levels = (resp >> 8) & 0xff; 63 pkg_dev->current_level = (resp >> 16) & 0xff; 64 pkg_dev->locked = !!(resp & BIT(24)); 65 pkg_dev->enabled = !!(resp & BIT(31)); 66 67 return 0; 68 } 69 70 static int mbox_get_ctdp_control(struct isst_id *id, int config_index, 71 struct isst_pkg_ctdp_level_info *ctdp_level) 72 { 73 int cp_state, cp_cap; 74 unsigned int resp; 75 int ret; 76 77 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 78 CONFIG_TDP_GET_TDP_CONTROL, 0, 79 config_index, &resp); 80 if (ret) 81 return ret; 82 83 ctdp_level->fact_support = resp & BIT(0); 84 ctdp_level->pbf_support = !!(resp & BIT(1)); 85 ctdp_level->fact_enabled = !!(resp & BIT(16)); 86 ctdp_level->pbf_enabled = !!(resp & BIT(17)); 87 88 ret = isst_read_pm_config(id, &cp_state, &cp_cap); 89 if (ret) { 90 debug_printf("cpu:%d pm_config is not supported\n", id->cpu); 91 } else { 92 debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap); 93 ctdp_level->sst_cp_support = cp_cap; 94 ctdp_level->sst_cp_enabled = cp_state; 95 } 96 97 debug_printf( 98 "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n", 99 id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support, 100 ctdp_level->fact_enabled, ctdp_level->pbf_enabled); 101 102 return 0; 103 } 104 105 static void mbox_get_uncore_p0_p1_info(struct isst_id *id, int config_index, 106 struct isst_pkg_ctdp_level_info *ctdp_level) 107 { 108 unsigned int resp; 109 int ret; 110 111 ctdp_level->uncore_pm = 0; 112 ctdp_level->uncore_p0 = 0; 113 ctdp_level->uncore_p1 = 0; 114 115 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 116 CONFIG_TDP_GET_RATIO_INFO, 0, 117 (BIT(16) | config_index) , &resp); 118 if (ret) { 119 goto try_uncore_mbox; 120 } 121 122 ctdp_level->uncore_p0 = resp & GENMASK(7, 0); 123 ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8; 124 ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24; 125 126 debug_printf( 127 "cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n", 128 id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1, 129 ctdp_level->uncore_pm); 130 131 return; 132 133 try_uncore_mbox: 134 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 135 CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0, 136 config_index, &resp); 137 if (ret) { 138 ctdp_level->uncore_p0 = 0; 139 ctdp_level->uncore_p1 = 0; 140 return; 141 } 142 143 ctdp_level->uncore_p0 = resp & GENMASK(7, 0); 144 ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8; 145 debug_printf( 146 "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n", 147 id->cpu, config_index, resp, ctdp_level->uncore_p0, 148 ctdp_level->uncore_p1); 149 } 150 151 static void _get_p1_info(struct isst_id *id, int config_index, 152 struct isst_pkg_ctdp_level_info *ctdp_level) 153 { 154 unsigned int resp; 155 int ret; 156 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0, 157 config_index, &resp); 158 if (ret) { 159 ctdp_level->sse_p1 = 0; 160 ctdp_level->avx2_p1 = 0; 161 ctdp_level->avx512_p1 = 0; 162 return; 163 } 164 165 ctdp_level->sse_p1 = resp & GENMASK(7, 0); 166 ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8; 167 ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16; 168 debug_printf( 169 "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n", 170 id->cpu, config_index, resp, ctdp_level->sse_p1, 171 ctdp_level->avx2_p1, ctdp_level->avx512_p1); 172 } 173 174 static void _get_uncore_mem_freq(struct isst_id *id, int config_index, 175 struct isst_pkg_ctdp_level_info *ctdp_level) 176 { 177 unsigned int resp; 178 int ret; 179 180 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ, 181 0, config_index, &resp); 182 if (ret) { 183 ctdp_level->mem_freq = 0; 184 return; 185 } 186 187 ctdp_level->mem_freq = resp & GENMASK(7, 0); 188 if (is_spr_platform()) { 189 ctdp_level->mem_freq *= 200; 190 } else if (is_icx_platform()) { 191 if (ctdp_level->mem_freq < 7) { 192 ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10; 193 ctdp_level->mem_freq /= 10; 194 if (ctdp_level->mem_freq % 10 > 5) 195 ctdp_level->mem_freq++; 196 } else { 197 ctdp_level->mem_freq = 0; 198 } 199 } else { 200 ctdp_level->mem_freq = 0; 201 } 202 debug_printf( 203 "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n", 204 id->cpu, config_index, resp, ctdp_level->mem_freq); 205 } 206 207 static int mbox_get_tdp_info(struct isst_id *id, int config_index, 208 struct isst_pkg_ctdp_level_info *ctdp_level) 209 { 210 unsigned int resp; 211 int ret; 212 213 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO, 214 0, config_index, &resp); 215 if (ret) { 216 isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index); 217 return ret; 218 } 219 220 ctdp_level->pkg_tdp = resp & GENMASK(14, 0); 221 ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16; 222 223 debug_printf( 224 "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n", 225 id->cpu, config_index, resp, ctdp_level->tdp_ratio, 226 ctdp_level->pkg_tdp); 227 228 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO, 229 0, config_index, &resp); 230 if (ret) 231 return ret; 232 233 ctdp_level->t_proc_hot = resp & GENMASK(7, 0); 234 235 mbox_get_uncore_p0_p1_info(id, config_index, ctdp_level); 236 _get_p1_info(id, config_index, ctdp_level); 237 _get_uncore_mem_freq(id, config_index, ctdp_level); 238 239 debug_printf( 240 "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n", 241 id->cpu, config_index, resp, ctdp_level->t_proc_hot); 242 243 return 0; 244 } 245 246 static int mbox_get_pwr_info(struct isst_id *id, int config_index, 247 struct isst_pkg_ctdp_level_info *ctdp_level) 248 { 249 unsigned int resp; 250 int ret; 251 252 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO, 253 0, config_index, &resp); 254 if (ret) 255 return ret; 256 257 ctdp_level->pkg_max_power = resp & GENMASK(14, 0); 258 ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16; 259 260 debug_printf( 261 "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n", 262 id->cpu, config_index, resp, ctdp_level->pkg_max_power, 263 ctdp_level->pkg_min_power); 264 265 return 0; 266 } 267 268 static int mbox_get_coremask_info(struct isst_id *id, int config_index, 269 struct isst_pkg_ctdp_level_info *ctdp_level) 270 { 271 unsigned int resp; 272 int i, ret; 273 274 ctdp_level->cpu_count = 0; 275 for (i = 0; i < 2; ++i) { 276 unsigned long long mask; 277 int cpu_count = 0; 278 279 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 280 CONFIG_TDP_GET_CORE_MASK, 0, 281 (i << 8) | config_index, &resp); 282 if (ret) 283 return ret; 284 285 debug_printf( 286 "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n", 287 id->cpu, config_index, i, resp); 288 289 mask = (unsigned long long)resp << (32 * i); 290 set_cpu_mask_from_punit_coremask(id, mask, 291 ctdp_level->core_cpumask_size, 292 ctdp_level->core_cpumask, 293 &cpu_count); 294 ctdp_level->cpu_count += cpu_count; 295 debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu, 296 config_index, i, ctdp_level->cpu_count); 297 } 298 299 return 0; 300 } 301 302 static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl) 303 { 304 unsigned int req, resp; 305 int ret; 306 307 req = level | (avx_level << 16); 308 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 309 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req, 310 &resp); 311 if (ret) 312 return ret; 313 314 debug_printf( 315 "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n", 316 id->cpu, req, resp); 317 318 trl[0] = resp & GENMASK(7, 0); 319 trl[1] = (resp & GENMASK(15, 8)) >> 8; 320 trl[2] = (resp & GENMASK(23, 16)) >> 16; 321 trl[3] = (resp & GENMASK(31, 24)) >> 24; 322 323 req = level | BIT(8) | (avx_level << 16); 324 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 325 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req, 326 &resp); 327 if (ret) 328 return ret; 329 330 debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu, 331 req, resp); 332 333 trl[4] = resp & GENMASK(7, 0); 334 trl[5] = (resp & GENMASK(15, 8)) >> 8; 335 trl[6] = (resp & GENMASK(23, 16)) >> 16; 336 trl[7] = (resp & GENMASK(31, 24)) >> 24; 337 338 return 0; 339 } 340 341 static int mbox_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level) 342 { 343 int trl_max_levels = isst_get_trl_max_levels(); 344 int i, ret; 345 346 for (i = 0; i < trl_max_levels; i++) { 347 ret = mbox_get_get_trl(id, level, i, ctdp_level->trl_ratios[i]); 348 if (ret) 349 return ret; 350 } 351 return 0; 352 } 353 354 static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info) 355 { 356 int ret; 357 358 debug_printf("cpu:%d bucket info via MSR\n", id->cpu); 359 360 *buckets_info = 0; 361 362 ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info); 363 if (ret) 364 return ret; 365 366 debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu, 367 *buckets_info); 368 369 return 0; 370 } 371 372 static int mbox_set_tdp_level(struct isst_id *id, int tdp_level) 373 { 374 unsigned int resp; 375 int ret; 376 377 378 if (isst_get_config_tdp_lock_status(id)) { 379 isst_display_error_info_message(1, "TDP is locked", 0, 0); 380 return -1; 381 382 } 383 384 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0, 385 tdp_level, &resp); 386 if (ret) { 387 isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level); 388 return ret; 389 } 390 391 return 0; 392 } 393 394 static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info) 395 { 396 int max_punit_core, max_mask_index; 397 unsigned int req, resp; 398 int i, ret; 399 400 max_punit_core = get_max_punit_core_id(id); 401 max_mask_index = max_punit_core > 32 ? 2 : 1; 402 403 for (i = 0; i < max_mask_index; ++i) { 404 unsigned long long mask; 405 int count; 406 407 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 408 CONFIG_TDP_PBF_GET_CORE_MASK_INFO, 409 0, (i << 8) | level, &resp); 410 if (ret) 411 break; 412 413 debug_printf( 414 "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n", 415 id->cpu, resp); 416 417 mask = (unsigned long long)resp << (32 * i); 418 set_cpu_mask_from_punit_coremask(id, mask, 419 pbf_info->core_cpumask_size, 420 pbf_info->core_cpumask, 421 &count); 422 } 423 424 req = level; 425 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 426 CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req, 427 &resp); 428 if (ret) 429 return ret; 430 431 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu, 432 resp); 433 434 pbf_info->p1_low = resp & 0xff; 435 pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8; 436 437 req = level; 438 ret = isst_send_mbox_command( 439 id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp); 440 if (ret) 441 return ret; 442 443 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp); 444 445 pbf_info->tdp = resp & 0xffff; 446 447 req = level; 448 ret = isst_send_mbox_command( 449 id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp); 450 if (ret) 451 return ret; 452 453 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu, 454 resp); 455 pbf_info->t_control = (resp >> 8) & 0xff; 456 pbf_info->t_prochot = resp & 0xff; 457 458 return 0; 459 } 460 461 static int mbox_set_pbf_fact_status(struct isst_id *id, int pbf, int enable) 462 { 463 struct isst_pkg_ctdp pkg_dev; 464 struct isst_pkg_ctdp_level_info ctdp_level; 465 int current_level; 466 unsigned int req = 0, resp; 467 int ret; 468 469 ret = isst_get_ctdp_levels(id, &pkg_dev); 470 if (ret) 471 debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu); 472 473 current_level = pkg_dev.current_level; 474 475 ret = isst_get_ctdp_control(id, current_level, &ctdp_level); 476 if (ret) 477 return ret; 478 479 if (pbf) { 480 if (ctdp_level.fact_enabled) 481 req = BIT(16); 482 483 if (enable) 484 req |= BIT(17); 485 else 486 req &= ~BIT(17); 487 } else { 488 489 if (enable && !ctdp_level.sst_cp_enabled) 490 isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0); 491 492 if (ctdp_level.pbf_enabled) 493 req = BIT(17); 494 495 if (enable) 496 req |= BIT(16); 497 else 498 req &= ~BIT(16); 499 } 500 501 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 502 CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp); 503 if (ret) 504 return ret; 505 506 debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n", 507 id->cpu, pbf, req); 508 509 return 0; 510 } 511 512 static int _get_fact_bucket_info(struct isst_id *id, int level, 513 struct isst_fact_bucket_info *bucket_info) 514 { 515 unsigned int resp; 516 int i, k, ret; 517 518 for (i = 0; i < 2; ++i) { 519 int j; 520 521 ret = isst_send_mbox_command( 522 id->cpu, CONFIG_TDP, 523 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0, 524 (i << 8) | level, &resp); 525 if (ret) 526 return ret; 527 528 debug_printf( 529 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n", 530 id->cpu, i, level, resp); 531 532 for (j = 0; j < 4; ++j) { 533 bucket_info[j + (i * 4)].hp_cores = 534 (resp >> (j * 8)) & 0xff; 535 } 536 } 537 538 for (k = 0; k < 3; ++k) { 539 for (i = 0; i < 2; ++i) { 540 int j; 541 542 ret = isst_send_mbox_command( 543 id->cpu, CONFIG_TDP, 544 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0, 545 (k << 16) | (i << 8) | level, &resp); 546 if (ret) 547 return ret; 548 549 debug_printf( 550 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n", 551 id->cpu, i, level, k, resp); 552 553 for (j = 0; j < 4; ++j) { 554 bucket_info[j + (i * 4)].hp_ratios[k] = 555 (resp >> (j * 8)) & 0xff; 556 } 557 } 558 } 559 560 return 0; 561 } 562 563 static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info) 564 { 565 unsigned int resp; 566 int j, ret, print; 567 568 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 569 CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0, 570 level, &resp); 571 if (ret) 572 return ret; 573 574 debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n", 575 id->cpu, resp); 576 577 fact_info->lp_ratios[0] = resp & 0xff; 578 fact_info->lp_ratios[1] = (resp >> 8) & 0xff; 579 fact_info->lp_ratios[2] = (resp >> 16) & 0xff; 580 581 ret = _get_fact_bucket_info(id, level, fact_info->bucket_info); 582 if (ret) 583 return ret; 584 585 print = 0; 586 for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) { 587 if (fact_bucket != 0xff && fact_bucket != j) 588 continue; 589 590 if (!fact_info->bucket_info[j].hp_cores) 591 break; 592 593 print = 1; 594 } 595 if (!print) { 596 isst_display_error_info_message(1, "Invalid bucket", 0, 0); 597 return -1; 598 } 599 600 return 0; 601 } 602 603 static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type) 604 { 605 unsigned int resp; 606 int ret; 607 608 ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, 609 &resp); 610 if (ret) 611 return ret; 612 613 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp); 614 615 if (resp & BIT(1)) 616 *enable = 1; 617 else 618 *enable = 0; 619 620 if (resp & BIT(2)) 621 *type = 1; 622 else 623 *type = 0; 624 625 return 0; 626 } 627 628 static int _write_pm_config(struct isst_id *id, int cp_state) 629 { 630 unsigned int req, resp; 631 int ret; 632 633 if (cp_state) 634 req = BIT(16); 635 else 636 req = 0; 637 638 ret = isst_send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req, 639 &resp); 640 if (ret) 641 return ret; 642 643 debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp); 644 645 return 0; 646 } 647 648 static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type) 649 { 650 unsigned int req, resp; 651 int ret; 652 653 if (!enable_clos) { 654 struct isst_pkg_ctdp pkg_dev; 655 struct isst_pkg_ctdp_level_info ctdp_level; 656 657 ret = isst_get_ctdp_levels(id, &pkg_dev); 658 if (ret) { 659 debug_printf("isst_get_ctdp_levels\n"); 660 return ret; 661 } 662 663 ret = isst_get_ctdp_control(id, pkg_dev.current_level, 664 &ctdp_level); 665 if (ret) 666 return ret; 667 668 if (ctdp_level.fact_enabled) { 669 isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0); 670 return -EINVAL; 671 } 672 ret = _write_pm_config(id, 0); 673 if (ret) 674 isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0); 675 } else { 676 ret = _write_pm_config(id, 1); 677 if (ret) 678 isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0); 679 } 680 681 ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0, 682 &resp); 683 if (ret) { 684 isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0); 685 return ret; 686 } 687 688 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp); 689 690 req = resp; 691 692 if (enable_clos) 693 req = req | BIT(1); 694 else 695 req = req & ~BIT(1); 696 697 if (priority_type > 1) 698 isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0); 699 700 if (priority_type) 701 req = req | BIT(2); 702 else 703 req = req & ~BIT(2); 704 705 ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 706 BIT(MBOX_CMD_WRITE_BIT), req, &resp); 707 if (ret) 708 return ret; 709 710 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu, 711 priority_type, req); 712 713 return 0; 714 } 715 716 static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config) 717 { 718 unsigned int resp; 719 int ret; 720 721 ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0, 722 &resp); 723 if (ret) 724 return ret; 725 726 clos_config->epp = resp & 0x0f; 727 clos_config->clos_prop_prio = (resp >> 4) & 0x0f; 728 clos_config->clos_min = (resp >> 8) & 0xff; 729 clos_config->clos_max = (resp >> 16) & 0xff; 730 clos_config->clos_desired = (resp >> 24) & 0xff; 731 732 return 0; 733 } 734 735 static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config) 736 { 737 unsigned int req, resp; 738 unsigned int param; 739 int ret; 740 741 req = clos_config->epp & 0x0f; 742 req |= (clos_config->clos_prop_prio & 0x0f) << 4; 743 req |= (clos_config->clos_min & 0xff) << 8; 744 req |= (clos_config->clos_max & 0xff) << 16; 745 req |= (clos_config->clos_desired & 0xff) << 24; 746 747 param = BIT(MBOX_CMD_WRITE_BIT) | clos; 748 749 ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req, 750 &resp); 751 if (ret) 752 return ret; 753 754 debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req); 755 756 return 0; 757 } 758 759 static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id) 760 { 761 unsigned int resp; 762 unsigned int param; 763 int core_id, ret; 764 765 core_id = find_phy_core_num(id->cpu); 766 param = core_id; 767 768 ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0, 769 &resp); 770 if (ret) 771 return ret; 772 773 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param, 774 resp); 775 *clos_id = (resp >> 16) & 0x03; 776 777 return 0; 778 } 779 780 static int mbox_clos_associate(struct isst_id *id, int clos_id) 781 { 782 unsigned int req, resp; 783 unsigned int param; 784 int core_id, ret; 785 786 req = (clos_id & 0x03) << 16; 787 core_id = find_phy_core_num(id->cpu); 788 param = BIT(MBOX_CMD_WRITE_BIT) | core_id; 789 790 ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 791 req, &resp); 792 if (ret) 793 return ret; 794 795 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param, 796 req); 797 798 return 0; 799 } 800 801 static struct isst_platform_ops mbox_ops = { 802 .get_disp_freq_multiplier = mbox_get_disp_freq_multiplier, 803 .get_trl_max_levels = mbox_get_trl_max_levels, 804 .get_trl_level_name = mbox_get_trl_level_name, 805 .is_punit_valid = mbox_is_punit_valid, 806 .get_config_levels = mbox_get_config_levels, 807 .get_ctdp_control = mbox_get_ctdp_control, 808 .get_tdp_info = mbox_get_tdp_info, 809 .get_pwr_info = mbox_get_pwr_info, 810 .get_coremask_info = mbox_get_coremask_info, 811 .get_get_trl = mbox_get_get_trl, 812 .get_get_trls = mbox_get_get_trls, 813 .get_trl_bucket_info = mbox_get_trl_bucket_info, 814 .set_tdp_level = mbox_set_tdp_level, 815 .get_pbf_info = mbox_get_pbf_info, 816 .set_pbf_fact_status = mbox_set_pbf_fact_status, 817 .get_fact_info = mbox_get_fact_info, 818 .get_uncore_p0_p1_info = mbox_get_uncore_p0_p1_info, 819 .get_clos_information = mbox_get_clos_information, 820 .pm_qos_config = mbox_pm_qos_config, 821 .pm_get_clos = mbox_pm_get_clos, 822 .set_clos = mbox_set_clos, 823 .clos_get_assoc_status = mbox_clos_get_assoc_status, 824 .clos_associate = mbox_clos_associate, 825 }; 826 827 struct isst_platform_ops *mbox_get_platform_ops(void) 828 { 829 return &mbox_ops; 830 } 831