1 /* 2 * Copyright 2020 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_v13_0.h" 29 #include "smu13_driver_if_v13_0_5.h" 30 #include "smu_v13_0_5_ppt.h" 31 #include "smu_v13_0_5_ppsmc.h" 32 #include "smu_v13_0_5_pmfw.h" 33 #include "smu_cmn.h" 34 35 /* 36 * DO NOT use these for err/warn/info/debug messages. 37 * Use dev_err, dev_warn, dev_info and dev_dbg instead. 38 * They are more MGPU friendly. 39 */ 40 #undef pr_err 41 #undef pr_warn 42 #undef pr_info 43 #undef pr_debug 44 45 #define FEATURE_MASK(feature) (1ULL << feature) 46 #define SMC_DPM_FEATURE ( \ 47 FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \ 48 FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ 49 FEATURE_MASK(FEATURE_LCLK_DPM_BIT) | \ 50 FEATURE_MASK(FEATURE_GFX_DPM_BIT) | \ 51 FEATURE_MASK(FEATURE_VCN_DPM_BIT) | \ 52 FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT) | \ 53 FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT)| \ 54 FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT)| \ 55 FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT)) 56 57 static struct cmn2asic_msg_mapping smu_v13_0_5_message_map[SMU_MSG_MAX_COUNT] = { 58 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), 59 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), 60 MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1), 61 MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 1), 62 MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 1), 63 MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxclk, 1), 64 MSG_MAP(Spare0, PPSMC_MSG_Spare0, 1), 65 MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 1), 66 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), 67 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), 68 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), 69 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu , 1), 70 MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 1), 71 MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 1), 72 MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 1), 73 MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1), 74 MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 1), 75 MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1), 76 MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 1), 77 MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 1), 78 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 1), 79 MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 1), 80 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), 81 MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1), 82 }; 83 84 static struct cmn2asic_mapping smu_v13_0_5_feature_mask_map[SMU_FEATURE_COUNT] = { 85 FEA_MAP(DATA_CALCULATION), 86 FEA_MAP(PPT), 87 FEA_MAP(TDC), 88 FEA_MAP(THERMAL), 89 FEA_MAP(PROCHOT), 90 FEA_MAP(CCLK_DPM), 91 FEA_MAP_REVERSE(FCLK), 92 FEA_MAP(LCLK_DPM), 93 FEA_MAP(DF_CSTATES), 94 FEA_MAP(FAN_CONTROLLER), 95 FEA_MAP(CPPC), 96 FEA_MAP_HALF_REVERSE(GFX), 97 FEA_MAP(DS_GFXCLK), 98 FEA_MAP(S0I3), 99 FEA_MAP(VCN_DPM), 100 FEA_MAP(DS_VCN), 101 FEA_MAP(DCFCLK_DPM), 102 FEA_MAP(ATHUB_PG), 103 FEA_MAP_REVERSE(SOCCLK), 104 FEA_MAP(SHUBCLK_DPM), 105 FEA_MAP(GFXOFF), 106 }; 107 108 static struct cmn2asic_mapping smu_v13_0_5_table_map[SMU_TABLE_COUNT] = { 109 TAB_MAP_VALID(WATERMARKS), 110 TAB_MAP_VALID(SMU_METRICS), 111 TAB_MAP_VALID(CUSTOM_DPM), 112 TAB_MAP_VALID(DPMCLOCKS), 113 }; 114 115 static int smu_v13_0_5_init_smc_tables(struct smu_context *smu) 116 { 117 struct smu_table_context *smu_table = &smu->smu_table; 118 struct smu_table *tables = smu_table->tables; 119 120 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), 121 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 122 SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), 123 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 124 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), 125 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 126 127 smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); 128 if (!smu_table->clocks_table) 129 goto err0_out; 130 131 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); 132 if (!smu_table->metrics_table) 133 goto err1_out; 134 smu_table->metrics_time = 0; 135 136 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); 137 if (!smu_table->watermarks_table) 138 goto err2_out; 139 140 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_1); 141 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 142 if (!smu_table->gpu_metrics_table) 143 goto err3_out; 144 145 return 0; 146 147 err3_out: 148 kfree(smu_table->watermarks_table); 149 err2_out: 150 kfree(smu_table->metrics_table); 151 err1_out: 152 kfree(smu_table->clocks_table); 153 err0_out: 154 return -ENOMEM; 155 } 156 157 static int smu_v13_0_5_fini_smc_tables(struct smu_context *smu) 158 { 159 struct smu_table_context *smu_table = &smu->smu_table; 160 161 kfree(smu_table->clocks_table); 162 smu_table->clocks_table = NULL; 163 164 kfree(smu_table->metrics_table); 165 smu_table->metrics_table = NULL; 166 167 kfree(smu_table->watermarks_table); 168 smu_table->watermarks_table = NULL; 169 170 return 0; 171 } 172 173 static int smu_v13_0_5_system_features_control(struct smu_context *smu, bool en) 174 { 175 struct amdgpu_device *adev = smu->adev; 176 int ret = 0; 177 178 if (!en && !adev->in_s0ix) 179 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL); 180 181 return ret; 182 } 183 184 static int smu_v13_0_5_dpm_set_vcn_enable(struct smu_context *smu, bool enable) 185 { 186 int ret = 0; 187 188 /* vcn dpm on is a prerequisite for vcn power gate messages */ 189 if (enable) 190 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 191 0, NULL); 192 else 193 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 194 0, NULL); 195 196 return ret; 197 } 198 199 static int smu_v13_0_5_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) 200 { 201 int ret = 0; 202 203 if (enable) 204 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 205 0, NULL); 206 else 207 ret = smu_cmn_send_smc_msg_with_param(smu, 208 SMU_MSG_PowerDownJpeg, 0, 209 NULL); 210 211 return ret; 212 } 213 214 215 static bool smu_v13_0_5_is_dpm_running(struct smu_context *smu) 216 { 217 int ret = 0; 218 uint64_t feature_enabled; 219 220 ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); 221 222 if (ret) 223 return false; 224 225 return !!(feature_enabled & SMC_DPM_FEATURE); 226 } 227 228 static int smu_v13_0_5_mode_reset(struct smu_context *smu, int type) 229 { 230 int ret = 0; 231 232 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, type, NULL); 233 if (ret) 234 dev_err(smu->adev->dev, "Failed to mode reset!\n"); 235 236 return ret; 237 } 238 239 static int smu_v13_0_5_mode2_reset(struct smu_context *smu) 240 { 241 return smu_v13_0_5_mode_reset(smu, SMU_RESET_MODE_2); 242 } 243 244 static int smu_v13_0_5_get_smu_metrics_data(struct smu_context *smu, 245 MetricsMember_t member, 246 uint32_t *value) 247 { 248 struct smu_table_context *smu_table = &smu->smu_table; 249 250 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; 251 int ret = 0; 252 253 ret = smu_cmn_get_metrics_table(smu, NULL, false); 254 if (ret) 255 return ret; 256 257 switch (member) { 258 case METRICS_AVERAGE_GFXCLK: 259 *value = metrics->GfxclkFrequency; 260 break; 261 case METRICS_AVERAGE_SOCCLK: 262 *value = metrics->SocclkFrequency; 263 break; 264 case METRICS_AVERAGE_VCLK: 265 *value = metrics->VclkFrequency; 266 break; 267 case METRICS_AVERAGE_DCLK: 268 *value = metrics->DclkFrequency; 269 break; 270 case METRICS_AVERAGE_UCLK: 271 *value = metrics->MemclkFrequency; 272 break; 273 case METRICS_AVERAGE_GFXACTIVITY: 274 *value = metrics->GfxActivity / 100; 275 break; 276 case METRICS_AVERAGE_VCNACTIVITY: 277 *value = metrics->UvdActivity; 278 break; 279 case METRICS_AVERAGE_SOCKETPOWER: 280 *value = (metrics->CurrentSocketPower << 8) / 1000; 281 break; 282 case METRICS_TEMPERATURE_EDGE: 283 *value = metrics->GfxTemperature / 100 * 284 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 285 break; 286 case METRICS_TEMPERATURE_HOTSPOT: 287 *value = metrics->SocTemperature / 100 * 288 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 289 break; 290 case METRICS_THROTTLER_STATUS: 291 *value = metrics->ThrottlerStatus; 292 break; 293 case METRICS_VOLTAGE_VDDGFX: 294 *value = metrics->Voltage[0]; 295 break; 296 case METRICS_VOLTAGE_VDDSOC: 297 *value = metrics->Voltage[1]; 298 break; 299 default: 300 *value = UINT_MAX; 301 break; 302 } 303 304 return ret; 305 } 306 307 static int smu_v13_0_5_read_sensor(struct smu_context *smu, 308 enum amd_pp_sensors sensor, 309 void *data, uint32_t *size) 310 { 311 int ret = 0; 312 313 if (!data || !size) 314 return -EINVAL; 315 316 switch (sensor) { 317 case AMDGPU_PP_SENSOR_GPU_LOAD: 318 ret = smu_v13_0_5_get_smu_metrics_data(smu, 319 METRICS_AVERAGE_GFXACTIVITY, 320 (uint32_t *)data); 321 *size = 4; 322 break; 323 case AMDGPU_PP_SENSOR_GPU_POWER: 324 ret = smu_v13_0_5_get_smu_metrics_data(smu, 325 METRICS_AVERAGE_SOCKETPOWER, 326 (uint32_t *)data); 327 *size = 4; 328 break; 329 case AMDGPU_PP_SENSOR_EDGE_TEMP: 330 ret = smu_v13_0_5_get_smu_metrics_data(smu, 331 METRICS_TEMPERATURE_EDGE, 332 (uint32_t *)data); 333 *size = 4; 334 break; 335 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 336 ret = smu_v13_0_5_get_smu_metrics_data(smu, 337 METRICS_TEMPERATURE_HOTSPOT, 338 (uint32_t *)data); 339 *size = 4; 340 break; 341 case AMDGPU_PP_SENSOR_GFX_MCLK: 342 ret = smu_v13_0_5_get_smu_metrics_data(smu, 343 METRICS_AVERAGE_UCLK, 344 (uint32_t *)data); 345 *(uint32_t *)data *= 100; 346 *size = 4; 347 break; 348 case AMDGPU_PP_SENSOR_GFX_SCLK: 349 ret = smu_v13_0_5_get_smu_metrics_data(smu, 350 METRICS_AVERAGE_GFXCLK, 351 (uint32_t *)data); 352 *(uint32_t *)data *= 100; 353 *size = 4; 354 break; 355 case AMDGPU_PP_SENSOR_VDDGFX: 356 ret = smu_v13_0_5_get_smu_metrics_data(smu, 357 METRICS_VOLTAGE_VDDGFX, 358 (uint32_t *)data); 359 *size = 4; 360 break; 361 case AMDGPU_PP_SENSOR_VDDNB: 362 ret = smu_v13_0_5_get_smu_metrics_data(smu, 363 METRICS_VOLTAGE_VDDSOC, 364 (uint32_t *)data); 365 *size = 4; 366 break; 367 case AMDGPU_PP_SENSOR_SS_APU_SHARE: 368 ret = smu_v13_0_5_get_smu_metrics_data(smu, 369 METRICS_SS_APU_SHARE, 370 (uint32_t *)data); 371 *size = 4; 372 break; 373 case AMDGPU_PP_SENSOR_SS_DGPU_SHARE: 374 ret = smu_v13_0_5_get_smu_metrics_data(smu, 375 METRICS_SS_DGPU_SHARE, 376 (uint32_t *)data); 377 *size = 4; 378 break; 379 default: 380 ret = -EOPNOTSUPP; 381 break; 382 } 383 384 return ret; 385 } 386 387 static int smu_v13_0_5_set_watermarks_table(struct smu_context *smu, 388 struct pp_smu_wm_range_sets *clock_ranges) 389 { 390 int i; 391 int ret = 0; 392 Watermarks_t *table = smu->smu_table.watermarks_table; 393 394 if (!table || !clock_ranges) 395 return -EINVAL; 396 397 if (clock_ranges) { 398 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || 399 clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) 400 return -EINVAL; 401 402 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { 403 table->WatermarkRow[WM_DCFCLK][i].MinClock = 404 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; 405 table->WatermarkRow[WM_DCFCLK][i].MaxClock = 406 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; 407 table->WatermarkRow[WM_DCFCLK][i].MinMclk = 408 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; 409 table->WatermarkRow[WM_DCFCLK][i].MaxMclk = 410 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; 411 412 table->WatermarkRow[WM_DCFCLK][i].WmSetting = 413 clock_ranges->reader_wm_sets[i].wm_inst; 414 } 415 416 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { 417 table->WatermarkRow[WM_SOCCLK][i].MinClock = 418 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; 419 table->WatermarkRow[WM_SOCCLK][i].MaxClock = 420 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; 421 table->WatermarkRow[WM_SOCCLK][i].MinMclk = 422 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; 423 table->WatermarkRow[WM_SOCCLK][i].MaxMclk = 424 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; 425 426 table->WatermarkRow[WM_SOCCLK][i].WmSetting = 427 clock_ranges->writer_wm_sets[i].wm_inst; 428 } 429 430 smu->watermarks_bitmap |= WATERMARKS_EXIST; 431 } 432 433 /* pass data to smu controller */ 434 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 435 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { 436 ret = smu_cmn_write_watermarks_table(smu); 437 if (ret) { 438 dev_err(smu->adev->dev, "Failed to update WMTABLE!"); 439 return ret; 440 } 441 smu->watermarks_bitmap |= WATERMARKS_LOADED; 442 } 443 444 return 0; 445 } 446 447 static ssize_t smu_v13_0_5_get_gpu_metrics(struct smu_context *smu, 448 void **table) 449 { 450 struct smu_table_context *smu_table = &smu->smu_table; 451 struct gpu_metrics_v2_1 *gpu_metrics = 452 (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table; 453 SmuMetrics_t metrics; 454 int ret = 0; 455 456 ret = smu_cmn_get_metrics_table(smu, &metrics, true); 457 if (ret) 458 return ret; 459 460 smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1); 461 462 gpu_metrics->temperature_gfx = metrics.GfxTemperature; 463 gpu_metrics->temperature_soc = metrics.SocTemperature; 464 465 gpu_metrics->average_gfx_activity = metrics.GfxActivity; 466 gpu_metrics->average_mm_activity = metrics.UvdActivity; 467 468 gpu_metrics->average_socket_power = metrics.CurrentSocketPower; 469 gpu_metrics->average_gfx_power = metrics.Power[0]; 470 gpu_metrics->average_soc_power = metrics.Power[1]; 471 gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency; 472 gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency; 473 gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency; 474 gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency; 475 gpu_metrics->average_vclk_frequency = metrics.VclkFrequency; 476 gpu_metrics->average_dclk_frequency = metrics.DclkFrequency; 477 gpu_metrics->throttle_status = metrics.ThrottlerStatus; 478 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 479 480 *table = (void *)gpu_metrics; 481 482 return sizeof(struct gpu_metrics_v2_1); 483 } 484 485 static int smu_v13_0_5_set_default_dpm_tables(struct smu_context *smu) 486 { 487 struct smu_table_context *smu_table = &smu->smu_table; 488 489 return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); 490 } 491 492 static int smu_v13_0_5_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, 493 long input[], uint32_t size) 494 { 495 struct smu_dpm_context *smu_dpm = &(smu->smu_dpm); 496 int ret = 0; 497 498 /* Only allowed in manual mode */ 499 if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) 500 return -EINVAL; 501 502 switch (type) { 503 case PP_OD_EDIT_SCLK_VDDC_TABLE: 504 if (size != 2) { 505 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 506 return -EINVAL; 507 } 508 509 if (input[0] == 0) { 510 if (input[1] < smu->gfx_default_hard_min_freq) { 511 dev_warn(smu->adev->dev, 512 "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", 513 input[1], smu->gfx_default_hard_min_freq); 514 return -EINVAL; 515 } 516 smu->gfx_actual_hard_min_freq = input[1]; 517 } else if (input[0] == 1) { 518 if (input[1] > smu->gfx_default_soft_max_freq) { 519 dev_warn(smu->adev->dev, 520 "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", 521 input[1], smu->gfx_default_soft_max_freq); 522 return -EINVAL; 523 } 524 smu->gfx_actual_soft_max_freq = input[1]; 525 } else { 526 return -EINVAL; 527 } 528 break; 529 case PP_OD_RESTORE_DEFAULT_TABLE: 530 if (size != 0) { 531 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 532 return -EINVAL; 533 } else { 534 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 535 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 536 } 537 break; 538 case PP_OD_COMMIT_DPM_TABLE: 539 if (size != 0) { 540 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 541 return -EINVAL; 542 } else { 543 if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { 544 dev_err(smu->adev->dev, 545 "The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", 546 smu->gfx_actual_hard_min_freq, 547 smu->gfx_actual_soft_max_freq); 548 return -EINVAL; 549 } 550 551 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 552 smu->gfx_actual_hard_min_freq, NULL); 553 if (ret) { 554 dev_err(smu->adev->dev, "Set hard min sclk failed!"); 555 return ret; 556 } 557 558 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 559 smu->gfx_actual_soft_max_freq, NULL); 560 if (ret) { 561 dev_err(smu->adev->dev, "Set soft max sclk failed!"); 562 return ret; 563 } 564 } 565 break; 566 default: 567 return -ENOSYS; 568 } 569 570 return ret; 571 } 572 573 static int smu_v13_0_5_get_current_clk_freq(struct smu_context *smu, 574 enum smu_clk_type clk_type, 575 uint32_t *value) 576 { 577 MetricsMember_t member_type; 578 579 switch (clk_type) { 580 case SMU_SOCCLK: 581 member_type = METRICS_AVERAGE_SOCCLK; 582 break; 583 case SMU_VCLK: 584 member_type = METRICS_AVERAGE_VCLK; 585 break; 586 case SMU_DCLK: 587 member_type = METRICS_AVERAGE_DCLK; 588 break; 589 case SMU_MCLK: 590 member_type = METRICS_AVERAGE_UCLK; 591 break; 592 case SMU_GFXCLK: 593 case SMU_SCLK: 594 return smu_cmn_send_smc_msg_with_param(smu, 595 SMU_MSG_GetGfxclkFrequency, 0, value); 596 break; 597 default: 598 return -EINVAL; 599 } 600 601 return smu_v13_0_5_get_smu_metrics_data(smu, member_type, value); 602 } 603 604 static int smu_v13_0_5_get_dpm_level_count(struct smu_context *smu, 605 enum smu_clk_type clk_type, 606 uint32_t *count) 607 { 608 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 609 610 switch (clk_type) { 611 case SMU_SOCCLK: 612 *count = clk_table->NumSocClkLevelsEnabled; 613 break; 614 case SMU_VCLK: 615 *count = clk_table->VcnClkLevelsEnabled; 616 break; 617 case SMU_DCLK: 618 *count = clk_table->VcnClkLevelsEnabled; 619 break; 620 case SMU_MCLK: 621 *count = clk_table->NumDfPstatesEnabled; 622 break; 623 case SMU_FCLK: 624 *count = clk_table->NumDfPstatesEnabled; 625 break; 626 default: 627 break; 628 } 629 630 return 0; 631 } 632 633 static int smu_v13_0_5_get_dpm_freq_by_index(struct smu_context *smu, 634 enum smu_clk_type clk_type, 635 uint32_t dpm_level, 636 uint32_t *freq) 637 { 638 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 639 640 if (!clk_table || clk_type >= SMU_CLK_COUNT) 641 return -EINVAL; 642 643 switch (clk_type) { 644 case SMU_SOCCLK: 645 if (dpm_level >= clk_table->NumSocClkLevelsEnabled) 646 return -EINVAL; 647 *freq = clk_table->SocClocks[dpm_level]; 648 break; 649 case SMU_VCLK: 650 if (dpm_level >= clk_table->VcnClkLevelsEnabled) 651 return -EINVAL; 652 *freq = clk_table->VClocks[dpm_level]; 653 break; 654 case SMU_DCLK: 655 if (dpm_level >= clk_table->VcnClkLevelsEnabled) 656 return -EINVAL; 657 *freq = clk_table->DClocks[dpm_level]; 658 break; 659 case SMU_UCLK: 660 case SMU_MCLK: 661 if (dpm_level >= clk_table->NumDfPstatesEnabled) 662 return -EINVAL; 663 *freq = clk_table->DfPstateTable[dpm_level].MemClk; 664 break; 665 case SMU_FCLK: 666 if (dpm_level >= clk_table->NumDfPstatesEnabled) 667 return -EINVAL; 668 *freq = clk_table->DfPstateTable[dpm_level].FClk; 669 break; 670 default: 671 return -EINVAL; 672 } 673 674 return 0; 675 } 676 677 static bool smu_v13_0_5_clk_dpm_is_enabled(struct smu_context *smu, 678 enum smu_clk_type clk_type) 679 { 680 enum smu_feature_mask feature_id = 0; 681 682 switch (clk_type) { 683 case SMU_MCLK: 684 case SMU_UCLK: 685 case SMU_FCLK: 686 feature_id = SMU_FEATURE_DPM_FCLK_BIT; 687 break; 688 case SMU_GFXCLK: 689 case SMU_SCLK: 690 feature_id = SMU_FEATURE_DPM_GFXCLK_BIT; 691 break; 692 case SMU_SOCCLK: 693 feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; 694 break; 695 case SMU_VCLK: 696 case SMU_DCLK: 697 feature_id = SMU_FEATURE_VCN_DPM_BIT; 698 break; 699 default: 700 return true; 701 } 702 703 return smu_cmn_feature_is_enabled(smu, feature_id); 704 } 705 706 static int smu_v13_0_5_get_dpm_ultimate_freq(struct smu_context *smu, 707 enum smu_clk_type clk_type, 708 uint32_t *min, 709 uint32_t *max) 710 { 711 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 712 uint32_t clock_limit; 713 uint32_t max_dpm_level, min_dpm_level; 714 int ret = 0; 715 716 if (!smu_v13_0_5_clk_dpm_is_enabled(smu, clk_type)) { 717 switch (clk_type) { 718 case SMU_MCLK: 719 case SMU_UCLK: 720 clock_limit = smu->smu_table.boot_values.uclk; 721 break; 722 case SMU_FCLK: 723 clock_limit = smu->smu_table.boot_values.fclk; 724 break; 725 case SMU_GFXCLK: 726 case SMU_SCLK: 727 clock_limit = smu->smu_table.boot_values.gfxclk; 728 break; 729 case SMU_SOCCLK: 730 clock_limit = smu->smu_table.boot_values.socclk; 731 break; 732 case SMU_VCLK: 733 clock_limit = smu->smu_table.boot_values.vclk; 734 break; 735 case SMU_DCLK: 736 clock_limit = smu->smu_table.boot_values.dclk; 737 break; 738 default: 739 clock_limit = 0; 740 break; 741 } 742 743 /* clock in Mhz unit */ 744 if (min) 745 *min = clock_limit / 100; 746 if (max) 747 *max = clock_limit / 100; 748 749 return 0; 750 } 751 752 if (max) { 753 switch (clk_type) { 754 case SMU_GFXCLK: 755 case SMU_SCLK: 756 *max = clk_table->MaxGfxClk; 757 break; 758 case SMU_MCLK: 759 case SMU_UCLK: 760 case SMU_FCLK: 761 max_dpm_level = 0; 762 break; 763 case SMU_SOCCLK: 764 max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1; 765 break; 766 case SMU_VCLK: 767 case SMU_DCLK: 768 max_dpm_level = clk_table->VcnClkLevelsEnabled - 1; 769 break; 770 default: 771 ret = -EINVAL; 772 goto failed; 773 } 774 775 if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { 776 ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max); 777 if (ret) 778 goto failed; 779 } 780 } 781 782 if (min) { 783 switch (clk_type) { 784 case SMU_GFXCLK: 785 case SMU_SCLK: 786 *min = clk_table->MinGfxClk; 787 break; 788 case SMU_MCLK: 789 case SMU_UCLK: 790 case SMU_FCLK: 791 min_dpm_level = clk_table->NumDfPstatesEnabled - 1; 792 break; 793 case SMU_SOCCLK: 794 min_dpm_level = 0; 795 break; 796 case SMU_VCLK: 797 case SMU_DCLK: 798 min_dpm_level = 0; 799 break; 800 default: 801 ret = -EINVAL; 802 goto failed; 803 } 804 805 if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { 806 ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min); 807 if (ret) 808 goto failed; 809 } 810 } 811 812 failed: 813 return ret; 814 } 815 816 static int smu_v13_0_5_set_soft_freq_limited_range(struct smu_context *smu, 817 enum smu_clk_type clk_type, 818 uint32_t min, 819 uint32_t max) 820 { 821 enum smu_message_type msg_set_min, msg_set_max; 822 int ret = 0; 823 824 if (!smu_v13_0_5_clk_dpm_is_enabled(smu, clk_type)) 825 return -EINVAL; 826 827 switch (clk_type) { 828 case SMU_GFXCLK: 829 case SMU_SCLK: 830 msg_set_min = SMU_MSG_SetHardMinGfxClk; 831 msg_set_max = SMU_MSG_SetSoftMaxGfxClk; 832 break; 833 case SMU_VCLK: 834 case SMU_DCLK: 835 msg_set_min = SMU_MSG_SetHardMinVcn; 836 msg_set_max = SMU_MSG_SetSoftMaxVcn; 837 break; 838 default: 839 return -EINVAL; 840 } 841 842 ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min, NULL); 843 if (ret) 844 goto out; 845 846 ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max, NULL); 847 if (ret) 848 goto out; 849 850 out: 851 return ret; 852 } 853 854 static int smu_v13_0_5_print_clk_levels(struct smu_context *smu, 855 enum smu_clk_type clk_type, char *buf) 856 { 857 int i, size = 0, ret = 0; 858 uint32_t cur_value = 0, value = 0, count = 0; 859 uint32_t min = 0, max = 0; 860 861 smu_cmn_get_sysfs_buf(&buf, &size); 862 863 switch (clk_type) { 864 case SMU_OD_SCLK: 865 size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); 866 size += sysfs_emit_at(buf, size, "0: %10uMhz\n", 867 (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); 868 size += sysfs_emit_at(buf, size, "1: %10uMhz\n", 869 (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); 870 break; 871 case SMU_OD_RANGE: 872 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 873 size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", 874 smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); 875 break; 876 case SMU_SOCCLK: 877 case SMU_VCLK: 878 case SMU_DCLK: 879 case SMU_MCLK: 880 ret = smu_v13_0_5_get_current_clk_freq(smu, clk_type, &cur_value); 881 if (ret) 882 goto print_clk_out; 883 884 ret = smu_v13_0_5_get_dpm_level_count(smu, clk_type, &count); 885 if (ret) 886 goto print_clk_out; 887 888 for (i = 0; i < count; i++) { 889 ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, i, &value); 890 if (ret) 891 goto print_clk_out; 892 893 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value, 894 cur_value == value ? "*" : ""); 895 } 896 break; 897 case SMU_GFXCLK: 898 case SMU_SCLK: 899 ret = smu_v13_0_5_get_current_clk_freq(smu, clk_type, &cur_value); 900 if (ret) 901 goto print_clk_out; 902 min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq; 903 max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq; 904 if (cur_value == max) 905 i = 2; 906 else if (cur_value == min) 907 i = 0; 908 else 909 i = 1; 910 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min, 911 i == 0 ? "*" : ""); 912 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", 913 i == 1 ? cur_value : SMU_13_0_5_UMD_PSTATE_GFXCLK, 914 i == 1 ? "*" : ""); 915 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max, 916 i == 2 ? "*" : ""); 917 break; 918 default: 919 break; 920 } 921 922 print_clk_out: 923 return size; 924 } 925 926 927 static int smu_v13_0_5_force_clk_levels(struct smu_context *smu, 928 enum smu_clk_type clk_type, uint32_t mask) 929 { 930 uint32_t soft_min_level = 0, soft_max_level = 0; 931 uint32_t min_freq = 0, max_freq = 0; 932 int ret = 0; 933 934 soft_min_level = mask ? (ffs(mask) - 1) : 0; 935 soft_max_level = mask ? (fls(mask) - 1) : 0; 936 937 switch (clk_type) { 938 case SMU_VCLK: 939 case SMU_DCLK: 940 ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); 941 if (ret) 942 goto force_level_out; 943 944 ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); 945 if (ret) 946 goto force_level_out; 947 948 ret = smu_v13_0_5_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); 949 if (ret) 950 goto force_level_out; 951 break; 952 default: 953 ret = -EINVAL; 954 break; 955 } 956 957 force_level_out: 958 return ret; 959 } 960 961 static int smu_v13_0_5_set_performance_level(struct smu_context *smu, 962 enum amd_dpm_forced_level level) 963 { 964 struct amdgpu_device *adev = smu->adev; 965 uint32_t sclk_min = 0, sclk_max = 0; 966 int ret = 0; 967 968 switch (level) { 969 case AMD_DPM_FORCED_LEVEL_HIGH: 970 smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max); 971 sclk_min = sclk_max; 972 break; 973 case AMD_DPM_FORCED_LEVEL_LOW: 974 smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL); 975 sclk_max = sclk_min; 976 break; 977 case AMD_DPM_FORCED_LEVEL_AUTO: 978 smu_v13_0_5_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max); 979 break; 980 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 981 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 982 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 983 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 984 /* Temporarily do nothing since the optimal clocks haven't been provided yet */ 985 break; 986 case AMD_DPM_FORCED_LEVEL_MANUAL: 987 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 988 return 0; 989 default: 990 dev_err(adev->dev, "Invalid performance level %d\n", level); 991 return -EINVAL; 992 } 993 994 if (sclk_min && sclk_max) { 995 ret = smu_v13_0_5_set_soft_freq_limited_range(smu, 996 SMU_SCLK, 997 sclk_min, 998 sclk_max); 999 if (ret) 1000 return ret; 1001 1002 smu->gfx_actual_hard_min_freq = sclk_min; 1003 smu->gfx_actual_soft_max_freq = sclk_max; 1004 } 1005 1006 return ret; 1007 } 1008 1009 static int smu_v13_0_5_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) 1010 { 1011 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 1012 1013 smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; 1014 smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; 1015 smu->gfx_actual_hard_min_freq = 0; 1016 smu->gfx_actual_soft_max_freq = 0; 1017 1018 return 0; 1019 } 1020 1021 static const struct pptable_funcs smu_v13_0_5_ppt_funcs = { 1022 .check_fw_status = smu_v13_0_check_fw_status, 1023 .check_fw_version = smu_v13_0_check_fw_version, 1024 .init_smc_tables = smu_v13_0_5_init_smc_tables, 1025 .fini_smc_tables = smu_v13_0_5_fini_smc_tables, 1026 .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values, 1027 .system_features_control = smu_v13_0_5_system_features_control, 1028 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 1029 .send_smc_msg = smu_cmn_send_smc_msg, 1030 .dpm_set_vcn_enable = smu_v13_0_5_dpm_set_vcn_enable, 1031 .dpm_set_jpeg_enable = smu_v13_0_5_dpm_set_jpeg_enable, 1032 .set_default_dpm_table = smu_v13_0_5_set_default_dpm_tables, 1033 .read_sensor = smu_v13_0_5_read_sensor, 1034 .is_dpm_running = smu_v13_0_5_is_dpm_running, 1035 .set_watermarks_table = smu_v13_0_5_set_watermarks_table, 1036 .get_gpu_metrics = smu_v13_0_5_get_gpu_metrics, 1037 .get_enabled_mask = smu_cmn_get_enabled_mask, 1038 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 1039 .set_driver_table_location = smu_v13_0_set_driver_table_location, 1040 .gfx_off_control = smu_v13_0_gfx_off_control, 1041 .mode2_reset = smu_v13_0_5_mode2_reset, 1042 .get_dpm_ultimate_freq = smu_v13_0_5_get_dpm_ultimate_freq, 1043 .od_edit_dpm_table = smu_v13_0_5_od_edit_dpm_table, 1044 .print_clk_levels = smu_v13_0_5_print_clk_levels, 1045 .force_clk_levels = smu_v13_0_5_force_clk_levels, 1046 .set_performance_level = smu_v13_0_5_set_performance_level, 1047 .set_fine_grain_gfx_freq_parameters = smu_v13_0_5_set_fine_grain_gfx_freq_parameters, 1048 }; 1049 1050 void smu_v13_0_5_set_ppt_funcs(struct smu_context *smu) 1051 { 1052 smu->ppt_funcs = &smu_v13_0_5_ppt_funcs; 1053 smu->message_map = smu_v13_0_5_message_map; 1054 smu->feature_map = smu_v13_0_5_feature_mask_map; 1055 smu->table_map = smu_v13_0_5_table_map; 1056 smu->is_apu = true; 1057 } 1058