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 56 static struct gfx_user_settings { 57 uint32_t sclk; 58 uint32_t vddc; 59 } cyan_skillfish_user_settings; 60 61 static 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 69 static 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 83 static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = { 84 TAB_MAP_VALID(SMU_METRICS), 85 }; 86 87 static 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 110 err1_out: 111 smu_table->gpu_metrics_table_size = 0; 112 kfree(smu_table->metrics_table); 113 err0_out: 114 return -ENOMEM; 115 } 116 117 static 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 128 static int cyan_skillfish_finit_smc_tables(struct smu_context *smu) 129 { 130 struct smu_table_context *smu_table = &smu->smu_table; 131 132 kfree(smu_table->metrics_table); 133 smu_table->metrics_table = NULL; 134 135 kfree(smu_table->gpu_metrics_table); 136 smu_table->gpu_metrics_table = NULL; 137 smu_table->gpu_metrics_table_size = 0; 138 139 smu_table->metrics_time = 0; 140 141 return 0; 142 } 143 144 static int 145 cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, 146 MetricsMember_t member, 147 uint32_t *value) 148 { 149 struct smu_table_context *smu_table = &smu->smu_table; 150 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; 151 int ret = 0; 152 153 mutex_lock(&smu->metrics_lock); 154 155 ret = smu_cmn_get_metrics_table_locked(smu, NULL, false); 156 if (ret) { 157 mutex_unlock(&smu->metrics_lock); 158 return ret; 159 } 160 161 switch (member) { 162 case METRICS_CURR_GFXCLK: 163 *value = metrics->Current.GfxclkFrequency; 164 break; 165 case METRICS_CURR_SOCCLK: 166 *value = metrics->Current.SocclkFrequency; 167 break; 168 case METRICS_CURR_VCLK: 169 *value = metrics->Current.VclkFrequency; 170 break; 171 case METRICS_CURR_DCLK: 172 *value = metrics->Current.DclkFrequency; 173 break; 174 case METRICS_CURR_UCLK: 175 *value = metrics->Current.MemclkFrequency; 176 break; 177 case METRICS_AVERAGE_SOCKETPOWER: 178 *value = (metrics->Current.CurrentSocketPower << 8) / 179 1000; 180 break; 181 case METRICS_TEMPERATURE_EDGE: 182 *value = metrics->Current.GfxTemperature / 100 * 183 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 184 break; 185 case METRICS_TEMPERATURE_HOTSPOT: 186 *value = metrics->Current.SocTemperature / 100 * 187 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 188 break; 189 case METRICS_VOLTAGE_VDDSOC: 190 *value = metrics->Current.Voltage[0]; 191 break; 192 case METRICS_VOLTAGE_VDDGFX: 193 *value = metrics->Current.Voltage[1]; 194 break; 195 case METRICS_THROTTLER_STATUS: 196 *value = metrics->Current.ThrottlerStatus; 197 break; 198 default: 199 *value = UINT_MAX; 200 break; 201 } 202 203 mutex_unlock(&smu->metrics_lock); 204 205 return ret; 206 } 207 208 static int cyan_skillfish_read_sensor(struct smu_context *smu, 209 enum amd_pp_sensors sensor, 210 void *data, 211 uint32_t *size) 212 { 213 int ret = 0; 214 215 if (!data || !size) 216 return -EINVAL; 217 218 mutex_lock(&smu->sensor_lock); 219 220 switch (sensor) { 221 case AMDGPU_PP_SENSOR_GFX_SCLK: 222 ret = cyan_skillfish_get_smu_metrics_data(smu, 223 METRICS_CURR_GFXCLK, 224 (uint32_t *)data); 225 *(uint32_t *)data *= 100; 226 *size = 4; 227 break; 228 case AMDGPU_PP_SENSOR_GFX_MCLK: 229 ret = cyan_skillfish_get_smu_metrics_data(smu, 230 METRICS_CURR_UCLK, 231 (uint32_t *)data); 232 *(uint32_t *)data *= 100; 233 *size = 4; 234 break; 235 case AMDGPU_PP_SENSOR_GPU_POWER: 236 ret = cyan_skillfish_get_smu_metrics_data(smu, 237 METRICS_AVERAGE_SOCKETPOWER, 238 (uint32_t *)data); 239 *size = 4; 240 break; 241 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 242 ret = cyan_skillfish_get_smu_metrics_data(smu, 243 METRICS_TEMPERATURE_HOTSPOT, 244 (uint32_t *)data); 245 *size = 4; 246 break; 247 case AMDGPU_PP_SENSOR_EDGE_TEMP: 248 ret = cyan_skillfish_get_smu_metrics_data(smu, 249 METRICS_TEMPERATURE_EDGE, 250 (uint32_t *)data); 251 *size = 4; 252 break; 253 case AMDGPU_PP_SENSOR_VDDNB: 254 ret = cyan_skillfish_get_smu_metrics_data(smu, 255 METRICS_VOLTAGE_VDDSOC, 256 (uint32_t *)data); 257 *size = 4; 258 break; 259 case AMDGPU_PP_SENSOR_VDDGFX: 260 ret = cyan_skillfish_get_smu_metrics_data(smu, 261 METRICS_VOLTAGE_VDDGFX, 262 (uint32_t *)data); 263 *size = 4; 264 break; 265 default: 266 ret = -EOPNOTSUPP; 267 break; 268 } 269 270 mutex_unlock(&smu->sensor_lock); 271 272 return ret; 273 } 274 275 static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu, 276 enum smu_clk_type clk_type, 277 uint32_t *value) 278 { 279 MetricsMember_t member_type; 280 281 switch (clk_type) { 282 case SMU_GFXCLK: 283 case SMU_SCLK: 284 member_type = METRICS_CURR_GFXCLK; 285 break; 286 case SMU_FCLK: 287 case SMU_MCLK: 288 member_type = METRICS_CURR_UCLK; 289 break; 290 case SMU_SOCCLK: 291 member_type = METRICS_CURR_SOCCLK; 292 break; 293 case SMU_VCLK: 294 member_type = METRICS_CURR_VCLK; 295 break; 296 case SMU_DCLK: 297 member_type = METRICS_CURR_DCLK; 298 break; 299 default: 300 return -EINVAL; 301 } 302 303 return cyan_skillfish_get_smu_metrics_data(smu, member_type, value); 304 } 305 306 static int cyan_skillfish_print_clk_levels(struct smu_context *smu, 307 enum smu_clk_type clk_type, 308 char *buf) 309 { 310 int ret = 0, size = 0; 311 uint32_t cur_value = 0; 312 int i; 313 314 smu_cmn_get_sysfs_buf(&buf, &size); 315 316 switch (clk_type) { 317 case SMU_OD_SCLK: 318 ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value); 319 if (ret) 320 return ret; 321 size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK"); 322 size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); 323 break; 324 case SMU_OD_VDDC_CURVE: 325 ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value); 326 if (ret) 327 return ret; 328 size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC"); 329 size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value); 330 break; 331 case SMU_OD_RANGE: 332 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 333 size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", 334 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 335 size += sysfs_emit_at(buf, size, "VDDC: %7umV %10umV\n", 336 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 337 break; 338 case SMU_FCLK: 339 case SMU_MCLK: 340 case SMU_SOCCLK: 341 case SMU_VCLK: 342 case SMU_DCLK: 343 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); 344 if (ret) 345 return ret; 346 size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); 347 break; 348 case SMU_SCLK: 349 case SMU_GFXCLK: 350 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); 351 if (ret) 352 return ret; 353 if (cur_value == CYAN_SKILLFISH_SCLK_MAX) 354 i = 2; 355 else if (cur_value == CYAN_SKILLFISH_SCLK_MIN) 356 i = 0; 357 else 358 i = 1; 359 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MIN, 360 i == 0 ? "*" : ""); 361 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", 362 i == 1 ? cur_value : cyan_skillfish_sclk_default, 363 i == 1 ? "*" : ""); 364 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MAX, 365 i == 2 ? "*" : ""); 366 break; 367 default: 368 dev_warn(smu->adev->dev, "Unsupported clock type\n"); 369 return ret; 370 } 371 372 return size; 373 } 374 375 static bool cyan_skillfish_is_dpm_running(struct smu_context *smu) 376 { 377 struct amdgpu_device *adev = smu->adev; 378 int ret = 0; 379 uint32_t feature_mask[2]; 380 uint64_t feature_enabled; 381 382 /* we need to re-init after suspend so return false */ 383 if (adev->in_suspend) 384 return false; 385 386 ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); 387 if (ret) 388 return false; 389 390 feature_enabled = (uint64_t)feature_mask[0] | 391 ((uint64_t)feature_mask[1] << 32); 392 393 /* 394 * cyan_skillfish specific, query default sclk inseted of hard code. 395 */ 396 if (!cyan_skillfish_sclk_default) 397 cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, 398 &cyan_skillfish_sclk_default); 399 400 return !!(feature_enabled & SMC_DPM_FEATURE); 401 } 402 403 static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu, 404 void **table) 405 { 406 struct smu_table_context *smu_table = &smu->smu_table; 407 struct gpu_metrics_v2_2 *gpu_metrics = 408 (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; 409 SmuMetrics_t metrics; 410 int i, ret = 0; 411 412 ret = smu_cmn_get_metrics_table(smu, &metrics, true); 413 if (ret) 414 return ret; 415 416 smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); 417 418 gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; 419 gpu_metrics->temperature_soc = metrics.Current.SocTemperature; 420 421 gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower; 422 gpu_metrics->average_soc_power = metrics.Current.Power[0]; 423 gpu_metrics->average_gfx_power = metrics.Current.Power[1]; 424 425 gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency; 426 gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency; 427 gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency; 428 gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency; 429 gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency; 430 gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency; 431 432 gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency; 433 gpu_metrics->current_socclk = metrics.Current.SocclkFrequency; 434 gpu_metrics->current_uclk = metrics.Current.MemclkFrequency; 435 gpu_metrics->current_fclk = metrics.Current.MemclkFrequency; 436 gpu_metrics->current_vclk = metrics.Current.VclkFrequency; 437 gpu_metrics->current_dclk = metrics.Current.DclkFrequency; 438 439 for (i = 0; i < 6; i++) { 440 gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i]; 441 gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i]; 442 gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i]; 443 } 444 445 for (i = 0; i < 2; i++) { 446 gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i]; 447 gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i]; 448 } 449 450 gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus; 451 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 452 453 *table = (void *)gpu_metrics; 454 455 return sizeof(struct gpu_metrics_v2_2); 456 } 457 458 static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu, 459 enum PP_OD_DPM_TABLE_COMMAND type, 460 long input[], uint32_t size) 461 { 462 int ret = 0; 463 uint32_t vid; 464 465 switch (type) { 466 case PP_OD_EDIT_VDDC_CURVE: 467 if (size != 3 || input[0] != 0) { 468 dev_err(smu->adev->dev, "Invalid parameter!\n"); 469 return -EINVAL; 470 } 471 472 if (input[1] < CYAN_SKILLFISH_SCLK_MIN || 473 input[1] > CYAN_SKILLFISH_SCLK_MAX) { 474 dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", 475 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 476 return -EINVAL; 477 } 478 479 if (input[2] < CYAN_SKILLFISH_VDDC_MIN || 480 input[2] > CYAN_SKILLFISH_VDDC_MAX) { 481 dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", 482 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 483 return -EINVAL; 484 } 485 486 cyan_skillfish_user_settings.sclk = input[1]; 487 cyan_skillfish_user_settings.vddc = input[2]; 488 489 break; 490 case PP_OD_RESTORE_DEFAULT_TABLE: 491 if (size != 0) { 492 dev_err(smu->adev->dev, "Invalid parameter!\n"); 493 return -EINVAL; 494 } 495 496 cyan_skillfish_user_settings.sclk = cyan_skillfish_sclk_default; 497 cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC; 498 499 break; 500 case PP_OD_COMMIT_DPM_TABLE: 501 if (size != 0) { 502 dev_err(smu->adev->dev, "Invalid parameter!\n"); 503 return -EINVAL; 504 } 505 506 if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN || 507 cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) { 508 dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", 509 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 510 return -EINVAL; 511 } 512 513 if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) && 514 (cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN || 515 cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) { 516 dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", 517 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 518 return -EINVAL; 519 } 520 521 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk, 522 cyan_skillfish_user_settings.sclk, NULL); 523 if (ret) { 524 dev_err(smu->adev->dev, "Set sclk failed!\n"); 525 return ret; 526 } 527 528 if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) { 529 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL); 530 if (ret) { 531 dev_err(smu->adev->dev, "Unforce vddc failed!\n"); 532 return ret; 533 } 534 } else { 535 /* 536 * PMFW accepts SVI2 VID code, convert voltage to VID: 537 * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001) 538 */ 539 vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000; 540 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL); 541 if (ret) { 542 dev_err(smu->adev->dev, "Force vddc failed!\n"); 543 return ret; 544 } 545 } 546 547 break; 548 default: 549 return -EOPNOTSUPP; 550 } 551 552 return ret; 553 } 554 555 static const struct pptable_funcs cyan_skillfish_ppt_funcs = { 556 557 .check_fw_status = smu_v11_0_check_fw_status, 558 .check_fw_version = smu_v11_0_check_fw_version, 559 .init_power = smu_v11_0_init_power, 560 .fini_power = smu_v11_0_fini_power, 561 .init_smc_tables = cyan_skillfish_init_smc_tables, 562 .fini_smc_tables = cyan_skillfish_finit_smc_tables, 563 .read_sensor = cyan_skillfish_read_sensor, 564 .print_clk_levels = cyan_skillfish_print_clk_levels, 565 .is_dpm_running = cyan_skillfish_is_dpm_running, 566 .get_gpu_metrics = cyan_skillfish_get_gpu_metrics, 567 .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table, 568 .register_irq_handler = smu_v11_0_register_irq_handler, 569 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, 570 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 571 .send_smc_msg = smu_cmn_send_smc_msg, 572 .set_driver_table_location = smu_v11_0_set_driver_table_location, 573 .interrupt_work = smu_v11_0_interrupt_work, 574 }; 575 576 void cyan_skillfish_set_ppt_funcs(struct smu_context *smu) 577 { 578 smu->ppt_funcs = &cyan_skillfish_ppt_funcs; 579 smu->message_map = cyan_skillfish_message_map; 580 smu->table_map = cyan_skillfish_table_map; 581 smu->is_apu = true; 582 } 583