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_v11_0.h" 29 #include "smu11_driver_if_vangogh.h" 30 #include "vangogh_ppt.h" 31 #include "smu_v11_5_ppsmc.h" 32 #include "smu_v11_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_VCN_DPM_BIT) | \ 49 FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ 50 FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT) | \ 51 FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) | \ 52 FEATURE_MASK(FEATURE_LCLK_DPM_BIT) | \ 53 FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT) | \ 54 FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \ 55 FEATURE_MASK(FEATURE_GFX_DPM_BIT)) 56 57 static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = { 58 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), 59 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0), 60 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 0), 61 MSG_MAP(EnableGfxOff, PPSMC_MSG_EnableGfxOff, 0), 62 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisableGfxOff, 0), 63 MSG_MAP(PowerDownIspByTile, PPSMC_MSG_PowerDownIspByTile, 0), 64 MSG_MAP(PowerUpIspByTile, PPSMC_MSG_PowerUpIspByTile, 0), 65 MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0), 66 MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), 67 MSG_MAP(Spare, PPSMC_MSG_spare, 0), 68 MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 0), 69 MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxclk, 0), 70 MSG_MAP(ActiveProcessNotify, PPSMC_MSG_ActiveProcessNotify, 0), 71 MSG_MAP(SetHardMinIspiclkByFreq, PPSMC_MSG_SetHardMinIspiclkByFreq, 0), 72 MSG_MAP(SetHardMinIspxclkByFreq, PPSMC_MSG_SetHardMinIspxclkByFreq, 0), 73 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 0), 74 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 0), 75 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), 76 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), 77 MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 0), 78 MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 0), 79 MSG_MAP(Spare1, PPSMC_MSG_spare1, 0), 80 MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 0), 81 MSG_MAP(SetSoftMinFclk, PPSMC_MSG_SetSoftMinFclk, 0), 82 MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 0), 83 MSG_MAP(EnablePostCode, PPSMC_MSG_EnablePostCode, 0), 84 MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 0), 85 MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 0), 86 MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 0), 87 MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 0), 88 MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 0), 89 MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 0), 90 MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 0), 91 MSG_MAP(Spare2, PPSMC_MSG_spare2, 0), 92 MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 0), 93 MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0), 94 MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0), 95 MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 0), 96 MSG_MAP(SetSoftMinSocclkByFreq, PPSMC_MSG_SetSoftMinSocclkByFreq, 0), 97 MSG_MAP(PowerUpCvip, PPSMC_MSG_PowerUpCvip, 0), 98 MSG_MAP(PowerDownCvip, PPSMC_MSG_PowerDownCvip, 0), 99 MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), 100 MSG_MAP(GetThermalLimit, PPSMC_MSG_GetThermalLimit, 0), 101 MSG_MAP(GetCurrentTemperature, PPSMC_MSG_GetCurrentTemperature, 0), 102 MSG_MAP(GetCurrentPower, PPSMC_MSG_GetCurrentPower, 0), 103 MSG_MAP(GetCurrentVoltage, PPSMC_MSG_GetCurrentVoltage, 0), 104 MSG_MAP(GetCurrentCurrent, PPSMC_MSG_GetCurrentCurrent, 0), 105 MSG_MAP(GetAverageCpuActivity, PPSMC_MSG_GetAverageCpuActivity, 0), 106 MSG_MAP(GetAverageGfxActivity, PPSMC_MSG_GetAverageGfxActivity, 0), 107 MSG_MAP(GetAveragePower, PPSMC_MSG_GetAveragePower, 0), 108 MSG_MAP(GetAverageTemperature, PPSMC_MSG_GetAverageTemperature, 0), 109 MSG_MAP(SetAveragePowerTimeConstant, PPSMC_MSG_SetAveragePowerTimeConstant, 0), 110 MSG_MAP(SetAverageActivityTimeConstant, PPSMC_MSG_SetAverageActivityTimeConstant, 0), 111 MSG_MAP(SetAverageTemperatureTimeConstant, PPSMC_MSG_SetAverageTemperatureTimeConstant, 0), 112 MSG_MAP(SetMitigationEndHysteresis, PPSMC_MSG_SetMitigationEndHysteresis, 0), 113 MSG_MAP(GetCurrentFreq, PPSMC_MSG_GetCurrentFreq, 0), 114 MSG_MAP(SetReducedPptLimit, PPSMC_MSG_SetReducedPptLimit, 0), 115 MSG_MAP(SetReducedThermalLimit, PPSMC_MSG_SetReducedThermalLimit, 0), 116 MSG_MAP(DramLogSetDramAddr, PPSMC_MSG_DramLogSetDramAddr, 0), 117 MSG_MAP(StartDramLogging, PPSMC_MSG_StartDramLogging, 0), 118 MSG_MAP(StopDramLogging, PPSMC_MSG_StopDramLogging, 0), 119 MSG_MAP(SetSoftMinCclk, PPSMC_MSG_SetSoftMinCclk, 0), 120 MSG_MAP(SetSoftMaxCclk, PPSMC_MSG_SetSoftMaxCclk, 0), 121 }; 122 123 static struct cmn2asic_mapping vangogh_feature_mask_map[SMU_FEATURE_COUNT] = { 124 FEA_MAP(PPT), 125 FEA_MAP(TDC), 126 FEA_MAP(THERMAL), 127 FEA_MAP(DS_GFXCLK), 128 FEA_MAP(DS_SOCCLK), 129 FEA_MAP(DS_LCLK), 130 FEA_MAP(DS_FCLK), 131 FEA_MAP(DS_MP1CLK), 132 FEA_MAP(DS_MP0CLK), 133 FEA_MAP(ATHUB_PG), 134 FEA_MAP(CCLK_DPM), 135 FEA_MAP(FAN_CONTROLLER), 136 FEA_MAP(ULV), 137 FEA_MAP(VCN_DPM), 138 FEA_MAP(LCLK_DPM), 139 FEA_MAP(SHUBCLK_DPM), 140 FEA_MAP(DCFCLK_DPM), 141 FEA_MAP(DS_DCFCLK), 142 FEA_MAP(S0I2), 143 FEA_MAP(SMU_LOW_POWER), 144 FEA_MAP(GFX_DEM), 145 FEA_MAP(PSI), 146 FEA_MAP(PROCHOT), 147 FEA_MAP(CPUOFF), 148 FEA_MAP(STAPM), 149 FEA_MAP(S0I3), 150 FEA_MAP(DF_CSTATES), 151 FEA_MAP(PERF_LIMIT), 152 FEA_MAP(CORE_DLDO), 153 FEA_MAP(RSMU_LOW_POWER), 154 FEA_MAP(SMN_LOW_POWER), 155 FEA_MAP(THM_LOW_POWER), 156 FEA_MAP(SMUIO_LOW_POWER), 157 FEA_MAP(MP1_LOW_POWER), 158 FEA_MAP(DS_VCN), 159 FEA_MAP(CPPC), 160 FEA_MAP(OS_CSTATES), 161 FEA_MAP(ISP_DPM), 162 FEA_MAP(A55_DPM), 163 FEA_MAP(CVIP_DSP_DPM), 164 FEA_MAP(MSMU_LOW_POWER), 165 }; 166 167 static struct cmn2asic_mapping vangogh_table_map[SMU_TABLE_COUNT] = { 168 TAB_MAP_VALID(WATERMARKS), 169 TAB_MAP_VALID(SMU_METRICS), 170 TAB_MAP_VALID(CUSTOM_DPM), 171 TAB_MAP_VALID(DPMCLOCKS), 172 }; 173 174 static int vangogh_tables_init(struct smu_context *smu) 175 { 176 struct smu_table_context *smu_table = &smu->smu_table; 177 struct smu_table *tables = smu_table->tables; 178 179 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), 180 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 181 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), 182 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 183 SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), 184 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 185 SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, 186 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 187 SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t), 188 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 189 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); 190 if (!smu_table->metrics_table) 191 goto err0_out; 192 smu_table->metrics_time = 0; 193 194 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0); 195 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 196 if (!smu_table->gpu_metrics_table) 197 goto err1_out; 198 199 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); 200 if (!smu_table->watermarks_table) 201 goto err2_out; 202 203 smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); 204 if (!smu_table->clocks_table) 205 goto err3_out; 206 207 return 0; 208 209 err3_out: 210 kfree(smu_table->clocks_table); 211 err2_out: 212 kfree(smu_table->gpu_metrics_table); 213 err1_out: 214 kfree(smu_table->metrics_table); 215 err0_out: 216 return -ENOMEM; 217 } 218 219 static int vangogh_get_smu_metrics_data(struct smu_context *smu, 220 MetricsMember_t member, 221 uint32_t *value) 222 { 223 struct smu_table_context *smu_table = &smu->smu_table; 224 225 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; 226 int ret = 0; 227 228 mutex_lock(&smu->metrics_lock); 229 230 ret = smu_cmn_get_metrics_table_locked(smu, 231 NULL, 232 false); 233 if (ret) { 234 mutex_unlock(&smu->metrics_lock); 235 return ret; 236 } 237 238 switch (member) { 239 case METRICS_AVERAGE_GFXCLK: 240 *value = metrics->GfxclkFrequency; 241 break; 242 case METRICS_AVERAGE_SOCCLK: 243 *value = metrics->SocclkFrequency; 244 break; 245 case METRICS_AVERAGE_UCLK: 246 *value = metrics->MemclkFrequency; 247 break; 248 case METRICS_AVERAGE_GFXACTIVITY: 249 *value = metrics->GfxActivity / 100; 250 break; 251 case METRICS_AVERAGE_VCNACTIVITY: 252 *value = metrics->UvdActivity; 253 break; 254 case METRICS_AVERAGE_SOCKETPOWER: 255 *value = metrics->CurrentSocketPower; 256 break; 257 case METRICS_TEMPERATURE_EDGE: 258 *value = metrics->GfxTemperature / 100 * 259 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 260 break; 261 case METRICS_TEMPERATURE_HOTSPOT: 262 *value = metrics->SocTemperature / 100 * 263 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 264 break; 265 case METRICS_THROTTLER_STATUS: 266 *value = metrics->ThrottlerStatus; 267 break; 268 default: 269 *value = UINT_MAX; 270 break; 271 } 272 273 mutex_unlock(&smu->metrics_lock); 274 275 return ret; 276 } 277 278 static int vangogh_allocate_dpm_context(struct smu_context *smu) 279 { 280 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 281 282 smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), 283 GFP_KERNEL); 284 if (!smu_dpm->dpm_context) 285 return -ENOMEM; 286 287 smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); 288 289 return 0; 290 } 291 292 static int vangogh_init_smc_tables(struct smu_context *smu) 293 { 294 int ret = 0; 295 296 ret = vangogh_tables_init(smu); 297 if (ret) 298 return ret; 299 300 ret = vangogh_allocate_dpm_context(smu); 301 if (ret) 302 return ret; 303 304 return smu_v11_0_init_smc_tables(smu); 305 } 306 307 static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable) 308 { 309 int ret = 0; 310 311 if (enable) { 312 /* vcn dpm on is a prerequisite for vcn power gate messages */ 313 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { 314 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); 315 if (ret) 316 return ret; 317 } 318 } else { 319 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { 320 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); 321 if (ret) 322 return ret; 323 } 324 } 325 326 return ret; 327 } 328 329 static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) 330 { 331 int ret = 0; 332 333 if (enable) { 334 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { 335 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); 336 if (ret) 337 return ret; 338 } 339 } else { 340 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { 341 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); 342 if (ret) 343 return ret; 344 } 345 } 346 347 return ret; 348 } 349 350 static int vangogh_get_allowed_feature_mask(struct smu_context *smu, 351 uint32_t *feature_mask, 352 uint32_t num) 353 { 354 struct amdgpu_device *adev = smu->adev; 355 356 if (num > 2) 357 return -EINVAL; 358 359 memset(feature_mask, 0, sizeof(uint32_t) * num); 360 361 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_DPM_BIT) 362 | FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) 363 | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) 364 | FEATURE_MASK(FEATURE_PPT_BIT) 365 | FEATURE_MASK(FEATURE_TDC_BIT) 366 | FEATURE_MASK(FEATURE_FAN_CONTROLLER_BIT) 367 | FEATURE_MASK(FEATURE_DS_LCLK_BIT) 368 | FEATURE_MASK(FEATURE_DS_DCFCLK_BIT); 369 370 if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) 371 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT); 372 373 if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK) 374 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT); 375 376 if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) 377 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT); 378 379 return 0; 380 } 381 382 static bool vangogh_is_dpm_running(struct smu_context *smu) 383 { 384 int ret = 0; 385 uint32_t feature_mask[2]; 386 uint64_t feature_enabled; 387 388 ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); 389 390 if (ret) 391 return false; 392 393 feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | 394 ((uint64_t)feature_mask[1] << 32)); 395 396 return !!(feature_enabled & SMC_DPM_FEATURE); 397 } 398 399 static int vangogh_get_current_activity_percent(struct smu_context *smu, 400 enum amd_pp_sensors sensor, 401 uint32_t *value) 402 { 403 int ret = 0; 404 405 if (!value) 406 return -EINVAL; 407 408 switch (sensor) { 409 case AMDGPU_PP_SENSOR_GPU_LOAD: 410 ret = vangogh_get_smu_metrics_data(smu, 411 METRICS_AVERAGE_GFXACTIVITY, 412 value); 413 break; 414 default: 415 dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); 416 return -EINVAL; 417 } 418 419 return 0; 420 } 421 422 static int vangogh_get_gpu_power(struct smu_context *smu, uint32_t *value) 423 { 424 if (!value) 425 return -EINVAL; 426 427 return vangogh_get_smu_metrics_data(smu, 428 METRICS_AVERAGE_SOCKETPOWER, 429 value); 430 } 431 432 static int vangogh_thermal_get_temperature(struct smu_context *smu, 433 enum amd_pp_sensors sensor, 434 uint32_t *value) 435 { 436 int ret = 0; 437 438 if (!value) 439 return -EINVAL; 440 441 switch (sensor) { 442 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 443 ret = vangogh_get_smu_metrics_data(smu, 444 METRICS_TEMPERATURE_HOTSPOT, 445 value); 446 break; 447 case AMDGPU_PP_SENSOR_EDGE_TEMP: 448 ret = vangogh_get_smu_metrics_data(smu, 449 METRICS_TEMPERATURE_EDGE, 450 value); 451 break; 452 default: 453 dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); 454 return -EINVAL; 455 } 456 457 return ret; 458 } 459 460 static int vangogh_get_current_clk_freq_by_table(struct smu_context *smu, 461 enum smu_clk_type clk_type, 462 uint32_t *value) 463 { 464 MetricsMember_t member_type; 465 466 switch (clk_type) { 467 case SMU_GFXCLK: 468 member_type = METRICS_AVERAGE_GFXCLK; 469 break; 470 case SMU_MCLK: 471 case SMU_UCLK: 472 member_type = METRICS_AVERAGE_UCLK; 473 break; 474 case SMU_SOCCLK: 475 member_type = METRICS_AVERAGE_SOCCLK; 476 break; 477 default: 478 return -EINVAL; 479 } 480 481 return vangogh_get_smu_metrics_data(smu, 482 member_type, 483 value); 484 } 485 486 static int vangogh_print_fine_grain_clk(struct smu_context *smu, 487 enum smu_clk_type clk_type, char *buf) 488 { 489 int size = 0; 490 491 switch (clk_type) { 492 case SMU_OD_SCLK: 493 if (smu->od_enabled) { 494 size = sprintf(buf, "%s:\n", "OD_SCLK"); 495 size += sprintf(buf + size, "0: %10uMhz\n", 496 (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); 497 size += sprintf(buf + size, "1: %10uMhz\n", 498 (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); 499 } 500 break; 501 case SMU_OD_RANGE: 502 if (smu->od_enabled) { 503 size = sprintf(buf, "%s:\n", "OD_RANGE"); 504 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", 505 smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); 506 } 507 break; 508 default: 509 break; 510 } 511 512 return size; 513 } 514 515 static int vangogh_read_sensor(struct smu_context *smu, 516 enum amd_pp_sensors sensor, 517 void *data, uint32_t *size) 518 { 519 int ret = 0; 520 521 if (!data || !size) 522 return -EINVAL; 523 524 mutex_lock(&smu->sensor_lock); 525 switch (sensor) { 526 case AMDGPU_PP_SENSOR_GPU_LOAD: 527 ret = vangogh_get_current_activity_percent(smu, sensor, (uint32_t *)data); 528 *size = 4; 529 break; 530 case AMDGPU_PP_SENSOR_GPU_POWER: 531 ret = vangogh_get_gpu_power(smu, (uint32_t *)data); 532 *size = 4; 533 break; 534 case AMDGPU_PP_SENSOR_EDGE_TEMP: 535 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 536 ret = vangogh_thermal_get_temperature(smu, sensor, (uint32_t *)data); 537 *size = 4; 538 break; 539 case AMDGPU_PP_SENSOR_GFX_MCLK: 540 ret = vangogh_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); 541 *(uint32_t *)data *= 100; 542 *size = 4; 543 break; 544 case AMDGPU_PP_SENSOR_GFX_SCLK: 545 ret = vangogh_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); 546 *(uint32_t *)data *= 100; 547 *size = 4; 548 break; 549 case AMDGPU_PP_SENSOR_VDDGFX: 550 ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); 551 *size = 4; 552 break; 553 default: 554 ret = -EOPNOTSUPP; 555 break; 556 } 557 mutex_unlock(&smu->sensor_lock); 558 559 return ret; 560 } 561 562 static int vangogh_set_watermarks_table(struct smu_context *smu, 563 struct pp_smu_wm_range_sets *clock_ranges) 564 { 565 int i; 566 int ret = 0; 567 Watermarks_t *table = smu->smu_table.watermarks_table; 568 569 if (!table || !clock_ranges) 570 return -EINVAL; 571 572 if (clock_ranges) { 573 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || 574 clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) 575 return -EINVAL; 576 577 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { 578 table->WatermarkRow[WM_DCFCLK][i].MinClock = 579 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; 580 table->WatermarkRow[WM_DCFCLK][i].MaxClock = 581 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; 582 table->WatermarkRow[WM_DCFCLK][i].MinMclk = 583 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; 584 table->WatermarkRow[WM_DCFCLK][i].MaxMclk = 585 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; 586 587 table->WatermarkRow[WM_DCFCLK][i].WmSetting = 588 clock_ranges->reader_wm_sets[i].wm_inst; 589 } 590 591 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { 592 table->WatermarkRow[WM_SOCCLK][i].MinClock = 593 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; 594 table->WatermarkRow[WM_SOCCLK][i].MaxClock = 595 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; 596 table->WatermarkRow[WM_SOCCLK][i].MinMclk = 597 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; 598 table->WatermarkRow[WM_SOCCLK][i].MaxMclk = 599 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; 600 601 table->WatermarkRow[WM_SOCCLK][i].WmSetting = 602 clock_ranges->writer_wm_sets[i].wm_inst; 603 } 604 605 smu->watermarks_bitmap |= WATERMARKS_EXIST; 606 } 607 608 /* pass data to smu controller */ 609 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 610 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { 611 ret = smu_cmn_write_watermarks_table(smu); 612 if (ret) { 613 dev_err(smu->adev->dev, "Failed to update WMTABLE!"); 614 return ret; 615 } 616 smu->watermarks_bitmap |= WATERMARKS_LOADED; 617 } 618 619 return 0; 620 } 621 622 static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, 623 void **table) 624 { 625 struct smu_table_context *smu_table = &smu->smu_table; 626 struct gpu_metrics_v2_0 *gpu_metrics = 627 (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; 628 SmuMetrics_t metrics; 629 int ret = 0; 630 631 ret = smu_cmn_get_metrics_table(smu, &metrics, true); 632 if (ret) 633 return ret; 634 635 smu_v11_0_init_gpu_metrics_v2_0(gpu_metrics); 636 637 gpu_metrics->temperature_gfx = metrics.GfxTemperature; 638 gpu_metrics->temperature_soc = metrics.SocTemperature; 639 memcpy(&gpu_metrics->temperature_core[0], 640 &metrics.CoreTemperature[0], 641 sizeof(uint16_t) * 8); 642 gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; 643 gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; 644 645 gpu_metrics->average_gfx_activity = metrics.GfxActivity; 646 gpu_metrics->average_mm_activity = metrics.UvdActivity; 647 648 gpu_metrics->average_socket_power = metrics.CurrentSocketPower; 649 gpu_metrics->average_cpu_power = metrics.Power[0]; 650 gpu_metrics->average_soc_power = metrics.Power[1]; 651 memcpy(&gpu_metrics->average_core_power[0], 652 &metrics.CorePower[0], 653 sizeof(uint16_t) * 8); 654 655 gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency; 656 gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency; 657 gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency; 658 gpu_metrics->average_vclk_frequency = metrics.VclkFrequency; 659 660 memcpy(&gpu_metrics->current_coreclk[0], 661 &metrics.CoreFrequency[0], 662 sizeof(uint16_t) * 8); 663 gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; 664 gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; 665 666 gpu_metrics->throttle_status = metrics.ThrottlerStatus; 667 668 *table = (void *)gpu_metrics; 669 670 return sizeof(struct gpu_metrics_v2_0); 671 } 672 673 static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, 674 long input[], uint32_t size) 675 { 676 int ret = 0; 677 678 if (!smu->od_enabled) { 679 dev_warn(smu->adev->dev, "Fine grain is not enabled!\n"); 680 return -EINVAL; 681 } 682 683 switch (type) { 684 case PP_OD_EDIT_SCLK_VDDC_TABLE: 685 if (size != 2) { 686 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 687 return -EINVAL; 688 } 689 690 if (input[0] == 0) { 691 if (input[1] < smu->gfx_default_hard_min_freq) { 692 dev_warn(smu->adev->dev, "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", 693 input[1], smu->gfx_default_hard_min_freq); 694 return -EINVAL; 695 } 696 smu->gfx_actual_hard_min_freq = input[1]; 697 } else if (input[0] == 1) { 698 if (input[1] > smu->gfx_default_soft_max_freq) { 699 dev_warn(smu->adev->dev, "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", 700 input[1], smu->gfx_default_soft_max_freq); 701 return -EINVAL; 702 } 703 smu->gfx_actual_soft_max_freq = input[1]; 704 } else { 705 return -EINVAL; 706 } 707 break; 708 case PP_OD_RESTORE_DEFAULT_TABLE: 709 if (size != 0) { 710 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 711 return -EINVAL; 712 } else { 713 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 714 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 715 716 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 717 smu->gfx_actual_hard_min_freq, NULL); 718 if (ret) { 719 dev_err(smu->adev->dev, "Restore the default hard min sclk failed!"); 720 return ret; 721 } 722 723 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 724 smu->gfx_actual_soft_max_freq, NULL); 725 if (ret) { 726 dev_err(smu->adev->dev, "Restore the default soft max sclk failed!"); 727 return ret; 728 } 729 } 730 break; 731 case PP_OD_COMMIT_DPM_TABLE: 732 if (size != 0) { 733 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 734 return -EINVAL; 735 } else { 736 if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { 737 dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", 738 smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq); 739 return -EINVAL; 740 } 741 742 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 743 smu->gfx_actual_hard_min_freq, NULL); 744 if (ret) { 745 dev_err(smu->adev->dev, "Set hard min sclk failed!"); 746 return ret; 747 } 748 749 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 750 smu->gfx_actual_soft_max_freq, NULL); 751 if (ret) { 752 dev_err(smu->adev->dev, "Set soft max sclk failed!"); 753 return ret; 754 } 755 } 756 break; 757 default: 758 return -ENOSYS; 759 } 760 761 return ret; 762 } 763 764 static int vangogh_set_default_dpm_tables(struct smu_context *smu) 765 { 766 struct smu_table_context *smu_table = &smu->smu_table; 767 768 return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); 769 } 770 771 static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) 772 { 773 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 774 775 smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; 776 smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; 777 smu->gfx_actual_hard_min_freq = 0; 778 smu->gfx_actual_soft_max_freq = 0; 779 780 return 0; 781 } 782 783 static const struct pptable_funcs vangogh_ppt_funcs = { 784 785 .check_fw_status = smu_v11_0_check_fw_status, 786 .check_fw_version = smu_v11_0_check_fw_version, 787 .init_smc_tables = vangogh_init_smc_tables, 788 .fini_smc_tables = smu_v11_0_fini_smc_tables, 789 .init_power = smu_v11_0_init_power, 790 .fini_power = smu_v11_0_fini_power, 791 .register_irq_handler = smu_v11_0_register_irq_handler, 792 .get_allowed_feature_mask = vangogh_get_allowed_feature_mask, 793 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, 794 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 795 .send_smc_msg = smu_cmn_send_smc_msg, 796 .dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable, 797 .dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable, 798 .is_dpm_running = vangogh_is_dpm_running, 799 .read_sensor = vangogh_read_sensor, 800 .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask, 801 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 802 .set_watermarks_table = vangogh_set_watermarks_table, 803 .set_driver_table_location = smu_v11_0_set_driver_table_location, 804 .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, 805 .interrupt_work = smu_v11_0_interrupt_work, 806 .get_gpu_metrics = vangogh_get_gpu_metrics, 807 .od_edit_dpm_table = vangogh_od_edit_dpm_table, 808 .print_clk_levels = vangogh_print_fine_grain_clk, 809 .set_default_dpm_table = vangogh_set_default_dpm_tables, 810 .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters, 811 }; 812 813 void vangogh_set_ppt_funcs(struct smu_context *smu) 814 { 815 smu->ppt_funcs = &vangogh_ppt_funcs; 816 smu->message_map = vangogh_message_map; 817 smu->feature_map = vangogh_feature_mask_map; 818 smu->table_map = vangogh_table_map; 819 smu->is_apu = true; 820 } 821