1/* 2 * Copyright 2021 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24#define SWSMU_CODE_LAYER_L2 25 26#include "amdgpu.h" 27#include "amdgpu_smu.h" 28#include "smu_v11_0.h" 29#include "smu11_driver_if_cyan_skillfish.h" 30#include "cyan_skillfish_ppt.h" 31#include "smu_v11_8_ppsmc.h" 32#include "smu_v11_8_pmfw.h" 33#include "smu_cmn.h" 34#include "soc15_common.h" 35 36/* 37 * DO NOT use these for err/warn/info/debug messages. 38 * Use dev_err, dev_warn, dev_info and dev_dbg instead. 39 * They are more MGPU friendly. 40 */ 41 42#undef pr_err 43#undef pr_warn 44#undef pr_info 45#undef pr_debug 46 47/* unit: MHz */ 48#define CYAN_SKILLFISH_SCLK_MIN 1000 49#define CYAN_SKILLFISH_SCLK_MAX 2000 50 51/* unit: mV */ 52#define CYAN_SKILLFISH_VDDC_MIN 700 53#define CYAN_SKILLFISH_VDDC_MAX 1129 54#define CYAN_SKILLFISH_VDDC_MAGIC 5118 // 0x13fe 55 56static struct gfx_user_settings { 57 uint32_t sclk; 58 uint32_t vddc; 59} cyan_skillfish_user_settings; 60 61static uint32_t cyan_skillfish_sclk_default; 62 63#define FEATURE_MASK(feature) (1ULL << feature) 64#define SMC_DPM_FEATURE ( \ 65 FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ 66 FEATURE_MASK(FEATURE_SOC_DPM_BIT) | \ 67 FEATURE_MASK(FEATURE_GFX_DPM_BIT)) 68 69static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = { 70 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), 71 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0), 72 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 0), 73 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverTableDramAddrHigh, 0), 74 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverTableDramAddrLow, 0), 75 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), 76 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), 77 MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 0), 78 MSG_MAP(RequestGfxclk, PPSMC_MSG_RequestGfxclk, 0), 79 MSG_MAP(ForceGfxVid, PPSMC_MSG_ForceGfxVid, 0), 80 MSG_MAP(UnforceGfxVid, PPSMC_MSG_UnforceGfxVid, 0), 81}; 82 83static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = { 84 TAB_MAP_VALID(SMU_METRICS), 85}; 86 87static int cyan_skillfish_tables_init(struct smu_context *smu) 88{ 89 struct smu_table_context *smu_table = &smu->smu_table; 90 struct smu_table *tables = smu_table->tables; 91 92 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, 93 sizeof(SmuMetrics_t), 94 PAGE_SIZE, 95 AMDGPU_GEM_DOMAIN_VRAM); 96 97 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); 98 if (!smu_table->metrics_table) 99 goto err0_out; 100 101 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2); 102 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 103 if (!smu_table->gpu_metrics_table) 104 goto err1_out; 105 106 smu_table->metrics_time = 0; 107 108 return 0; 109 110err1_out: 111 smu_table->gpu_metrics_table_size = 0; 112 kfree(smu_table->metrics_table); 113err0_out: 114 return -ENOMEM; 115} 116 117static int cyan_skillfish_init_smc_tables(struct smu_context *smu) 118{ 119 int ret = 0; 120 121 ret = cyan_skillfish_tables_init(smu); 122 if (ret) 123 return ret; 124 125 return smu_v11_0_init_smc_tables(smu); 126} 127 128static int 129cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, 130 MetricsMember_t member, 131 uint32_t *value) 132{ 133 struct smu_table_context *smu_table = &smu->smu_table; 134 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; 135 int ret = 0; 136 137 ret = smu_cmn_get_metrics_table(smu, NULL, false); 138 if (ret) 139 return ret; 140 141 switch (member) { 142 case METRICS_CURR_GFXCLK: 143 *value = metrics->Current.GfxclkFrequency; 144 break; 145 case METRICS_CURR_SOCCLK: 146 *value = metrics->Current.SocclkFrequency; 147 break; 148 case METRICS_CURR_VCLK: 149 *value = metrics->Current.VclkFrequency; 150 break; 151 case METRICS_CURR_DCLK: 152 *value = metrics->Current.DclkFrequency; 153 break; 154 case METRICS_CURR_UCLK: 155 *value = metrics->Current.MemclkFrequency; 156 break; 157 case METRICS_CURR_SOCKETPOWER: 158 *value = (metrics->Current.CurrentSocketPower << 8) / 159 1000; 160 break; 161 case METRICS_AVERAGE_SOCKETPOWER: 162 *value = (metrics->Average.CurrentSocketPower << 8) / 163 1000; 164 break; 165 case METRICS_TEMPERATURE_EDGE: 166 *value = metrics->Current.GfxTemperature / 100 * 167 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 168 break; 169 case METRICS_TEMPERATURE_HOTSPOT: 170 *value = metrics->Current.SocTemperature / 100 * 171 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 172 break; 173 case METRICS_VOLTAGE_VDDSOC: 174 *value = metrics->Current.Voltage[0]; 175 break; 176 case METRICS_VOLTAGE_VDDGFX: 177 *value = metrics->Current.Voltage[1]; 178 break; 179 case METRICS_THROTTLER_STATUS: 180 *value = metrics->Current.ThrottlerStatus; 181 break; 182 default: 183 *value = UINT_MAX; 184 break; 185 } 186 187 return ret; 188} 189 190static int cyan_skillfish_read_sensor(struct smu_context *smu, 191 enum amd_pp_sensors sensor, 192 void *data, 193 uint32_t *size) 194{ 195 int ret = 0; 196 197 if (!data || !size) 198 return -EINVAL; 199 200 switch (sensor) { 201 case AMDGPU_PP_SENSOR_GFX_SCLK: 202 ret = cyan_skillfish_get_smu_metrics_data(smu, 203 METRICS_CURR_GFXCLK, 204 (uint32_t *)data); 205 *(uint32_t *)data *= 100; 206 *size = 4; 207 break; 208 case AMDGPU_PP_SENSOR_GFX_MCLK: 209 ret = cyan_skillfish_get_smu_metrics_data(smu, 210 METRICS_CURR_UCLK, 211 (uint32_t *)data); 212 *(uint32_t *)data *= 100; 213 *size = 4; 214 break; 215 case AMDGPU_PP_SENSOR_GPU_AVG_POWER: 216 ret = cyan_skillfish_get_smu_metrics_data(smu, 217 METRICS_AVERAGE_SOCKETPOWER, 218 (uint32_t *)data); 219 *size = 4; 220 break; 221 case AMDGPU_PP_SENSOR_GPU_INPUT_POWER: 222 ret = cyan_skillfish_get_smu_metrics_data(smu, 223 METRICS_CURR_SOCKETPOWER, 224 (uint32_t *)data); 225 *size = 4; 226 break; 227 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 228 ret = cyan_skillfish_get_smu_metrics_data(smu, 229 METRICS_TEMPERATURE_HOTSPOT, 230 (uint32_t *)data); 231 *size = 4; 232 break; 233 case AMDGPU_PP_SENSOR_EDGE_TEMP: 234 ret = cyan_skillfish_get_smu_metrics_data(smu, 235 METRICS_TEMPERATURE_EDGE, 236 (uint32_t *)data); 237 *size = 4; 238 break; 239 case AMDGPU_PP_SENSOR_VDDNB: 240 ret = cyan_skillfish_get_smu_metrics_data(smu, 241 METRICS_VOLTAGE_VDDSOC, 242 (uint32_t *)data); 243 *size = 4; 244 break; 245 case AMDGPU_PP_SENSOR_VDDGFX: 246 ret = cyan_skillfish_get_smu_metrics_data(smu, 247 METRICS_VOLTAGE_VDDGFX, 248 (uint32_t *)data); 249 *size = 4; 250 break; 251 default: 252 ret = -EOPNOTSUPP; 253 break; 254 } 255 256 return ret; 257} 258 259static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu, 260 enum smu_clk_type clk_type, 261 uint32_t *value) 262{ 263 MetricsMember_t member_type; 264 265 switch (clk_type) { 266 case SMU_GFXCLK: 267 case SMU_SCLK: 268 member_type = METRICS_CURR_GFXCLK; 269 break; 270 case SMU_FCLK: 271 case SMU_MCLK: 272 member_type = METRICS_CURR_UCLK; 273 break; 274 case SMU_SOCCLK: 275 member_type = METRICS_CURR_SOCCLK; 276 break; 277 case SMU_VCLK: 278 member_type = METRICS_CURR_VCLK; 279 break; 280 case SMU_DCLK: 281 member_type = METRICS_CURR_DCLK; 282 break; 283 default: 284 return -EINVAL; 285 } 286 287 return cyan_skillfish_get_smu_metrics_data(smu, member_type, value); 288} 289 290static int cyan_skillfish_print_clk_levels(struct smu_context *smu, 291 enum smu_clk_type clk_type, 292 char *buf) 293{ 294 int ret = 0, size = 0; 295 uint32_t cur_value = 0; 296 int i; 297 298 smu_cmn_get_sysfs_buf(&buf, &size); 299 300 switch (clk_type) { 301 case SMU_OD_SCLK: 302 ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value); 303 if (ret) 304 return ret; 305 size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK"); 306 size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); 307 break; 308 case SMU_OD_VDDC_CURVE: 309 ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value); 310 if (ret) 311 return ret; 312 size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC"); 313 size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value); 314 break; 315 case SMU_OD_RANGE: 316 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 317 size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", 318 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 319 size += sysfs_emit_at(buf, size, "VDDC: %7umV %10umV\n", 320 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 321 break; 322 case SMU_FCLK: 323 case SMU_MCLK: 324 case SMU_SOCCLK: 325 case SMU_VCLK: 326 case SMU_DCLK: 327 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); 328 if (ret) 329 return ret; 330 size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); 331 break; 332 case SMU_SCLK: 333 case SMU_GFXCLK: 334 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); 335 if (ret) 336 return ret; 337 if (cur_value == CYAN_SKILLFISH_SCLK_MAX) 338 i = 2; 339 else if (cur_value == CYAN_SKILLFISH_SCLK_MIN) 340 i = 0; 341 else 342 i = 1; 343 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MIN, 344 i == 0 ? "*" : ""); 345 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", 346 i == 1 ? cur_value : cyan_skillfish_sclk_default, 347 i == 1 ? "*" : ""); 348 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MAX, 349 i == 2 ? "*" : ""); 350 break; 351 default: 352 dev_warn(smu->adev->dev, "Unsupported clock type\n"); 353 return ret; 354 } 355 356 return size; 357} 358 359static bool cyan_skillfish_is_dpm_running(struct smu_context *smu) 360{ 361 struct amdgpu_device *adev = smu->adev; 362 int ret = 0; 363 uint64_t feature_enabled; 364 365 /* we need to re-init after suspend so return false */ 366 if (adev->in_suspend) 367 return false; 368 369 ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); 370 if (ret) 371 return false; 372 373 /* 374 * cyan_skillfish specific, query default sclk inseted of hard code. 375 */ 376 if (!cyan_skillfish_sclk_default) 377 cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, 378 &cyan_skillfish_sclk_default); 379 380 return !!(feature_enabled & SMC_DPM_FEATURE); 381} 382 383static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu, 384 void **table) 385{ 386 struct smu_table_context *smu_table = &smu->smu_table; 387 struct gpu_metrics_v2_2 *gpu_metrics = 388 (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; 389 SmuMetrics_t metrics; 390 int i, ret = 0; 391 392 ret = smu_cmn_get_metrics_table(smu, &metrics, true); 393 if (ret) 394 return ret; 395 396 smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); 397 398 gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; 399 gpu_metrics->temperature_soc = metrics.Current.SocTemperature; 400 401 gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower; 402 gpu_metrics->average_soc_power = metrics.Current.Power[0]; 403 gpu_metrics->average_gfx_power = metrics.Current.Power[1]; 404 405 gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency; 406 gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency; 407 gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency; 408 gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency; 409 gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency; 410 gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency; 411 412 gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency; 413 gpu_metrics->current_socclk = metrics.Current.SocclkFrequency; 414 gpu_metrics->current_uclk = metrics.Current.MemclkFrequency; 415 gpu_metrics->current_fclk = metrics.Current.MemclkFrequency; 416 gpu_metrics->current_vclk = metrics.Current.VclkFrequency; 417 gpu_metrics->current_dclk = metrics.Current.DclkFrequency; 418 419 for (i = 0; i < 6; i++) { 420 gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i]; 421 gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i]; 422 gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i]; 423 } 424 425 for (i = 0; i < 2; i++) { 426 gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i]; 427 gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i]; 428 } 429 430 gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus; 431 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 432 433 *table = (void *)gpu_metrics; 434 435 return sizeof(struct gpu_metrics_v2_2); 436} 437 438static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu, 439 enum PP_OD_DPM_TABLE_COMMAND type, 440 long input[], uint32_t size) 441{ 442 int ret = 0; 443 uint32_t vid; 444 445 switch (type) { 446 case PP_OD_EDIT_VDDC_CURVE: 447 if (size != 3 || input[0] != 0) { 448 dev_err(smu->adev->dev, "Invalid parameter!\n"); 449 return -EINVAL; 450 } 451 452 if (input[1] < CYAN_SKILLFISH_SCLK_MIN || 453 input[1] > CYAN_SKILLFISH_SCLK_MAX) { 454 dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", 455 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 456 return -EINVAL; 457 } 458 459 if (input[2] < CYAN_SKILLFISH_VDDC_MIN || 460 input[2] > CYAN_SKILLFISH_VDDC_MAX) { 461 dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", 462 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 463 return -EINVAL; 464 } 465 466 cyan_skillfish_user_settings.sclk = input[1]; 467 cyan_skillfish_user_settings.vddc = input[2]; 468 469 break; 470 case PP_OD_RESTORE_DEFAULT_TABLE: 471 if (size != 0) { 472 dev_err(smu->adev->dev, "Invalid parameter!\n"); 473 return -EINVAL; 474 } 475 476 cyan_skillfish_user_settings.sclk = cyan_skillfish_sclk_default; 477 cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC; 478 479 break; 480 case PP_OD_COMMIT_DPM_TABLE: 481 if (size != 0) { 482 dev_err(smu->adev->dev, "Invalid parameter!\n"); 483 return -EINVAL; 484 } 485 486 if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN || 487 cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) { 488 dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", 489 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 490 return -EINVAL; 491 } 492 493 if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) && 494 (cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN || 495 cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) { 496 dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", 497 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 498 return -EINVAL; 499 } 500 501 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk, 502 cyan_skillfish_user_settings.sclk, NULL); 503 if (ret) { 504 dev_err(smu->adev->dev, "Set sclk failed!\n"); 505 return ret; 506 } 507 508 if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) { 509 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL); 510 if (ret) { 511 dev_err(smu->adev->dev, "Unforce vddc failed!\n"); 512 return ret; 513 } 514 } else { 515 /* 516 * PMFW accepts SVI2 VID code, convert voltage to VID: 517 * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001) 518 */ 519 vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000; 520 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL); 521 if (ret) { 522 dev_err(smu->adev->dev, "Force vddc failed!\n"); 523 return ret; 524 } 525 } 526 527 break; 528 default: 529 return -EOPNOTSUPP; 530 } 531 532 return ret; 533} 534 535static int cyan_skillfish_get_dpm_ultimate_freq(struct smu_context *smu, 536 enum smu_clk_type clk_type, 537 uint32_t *min, 538 uint32_t *max) 539{ 540 int ret = 0; 541 uint32_t low, high; 542 543 switch (clk_type) { 544 case SMU_GFXCLK: 545 case SMU_SCLK: 546 low = CYAN_SKILLFISH_SCLK_MIN; 547 high = CYAN_SKILLFISH_SCLK_MAX; 548 break; 549 default: 550 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &low); 551 if (ret) 552 return ret; 553 high = low; 554 break; 555 } 556 557 if (min) 558 *min = low; 559 if (max) 560 *max = high; 561 562 return 0; 563} 564 565static int cyan_skillfish_get_enabled_mask(struct smu_context *smu, 566 uint64_t *feature_mask) 567{ 568 if (!feature_mask) 569 return -EINVAL; 570 memset(feature_mask, 0xff, sizeof(*feature_mask)); 571 572 return 0; 573} 574 575static const struct pptable_funcs cyan_skillfish_ppt_funcs = { 576 577 .check_fw_status = smu_v11_0_check_fw_status, 578 .check_fw_version = smu_v11_0_check_fw_version, 579 .init_power = smu_v11_0_init_power, 580 .fini_power = smu_v11_0_fini_power, 581 .init_smc_tables = cyan_skillfish_init_smc_tables, 582 .fini_smc_tables = smu_v11_0_fini_smc_tables, 583 .read_sensor = cyan_skillfish_read_sensor, 584 .print_clk_levels = cyan_skillfish_print_clk_levels, 585 .get_enabled_mask = cyan_skillfish_get_enabled_mask, 586 .is_dpm_running = cyan_skillfish_is_dpm_running, 587 .get_gpu_metrics = cyan_skillfish_get_gpu_metrics, 588 .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table, 589 .get_dpm_ultimate_freq = cyan_skillfish_get_dpm_ultimate_freq, 590 .register_irq_handler = smu_v11_0_register_irq_handler, 591 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, 592 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 593 .send_smc_msg = smu_cmn_send_smc_msg, 594 .set_driver_table_location = smu_v11_0_set_driver_table_location, 595 .interrupt_work = smu_v11_0_interrupt_work, 596}; 597 598void cyan_skillfish_set_ppt_funcs(struct smu_context *smu) 599{ 600 smu->ppt_funcs = &cyan_skillfish_ppt_funcs; 601 smu->message_map = cyan_skillfish_message_map; 602 smu->table_map = cyan_skillfish_table_map; 603 smu->is_apu = true; 604 smu_v11_0_set_smu_mailbox_registers(smu); 605} 606