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(RlcPowerNotify, PPSMC_MSG_RlcPowerNotify, 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 << 8) / 256 1000 ; 257 break; 258 case METRICS_TEMPERATURE_EDGE: 259 *value = metrics->GfxTemperature / 100 * 260 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 261 break; 262 case METRICS_TEMPERATURE_HOTSPOT: 263 *value = metrics->SocTemperature / 100 * 264 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 265 break; 266 case METRICS_THROTTLER_STATUS: 267 *value = metrics->ThrottlerStatus; 268 break; 269 case METRICS_VOLTAGE_VDDGFX: 270 *value = metrics->Voltage[2]; 271 break; 272 case METRICS_VOLTAGE_VDDSOC: 273 *value = metrics->Voltage[1]; 274 break; 275 default: 276 *value = UINT_MAX; 277 break; 278 } 279 280 mutex_unlock(&smu->metrics_lock); 281 282 return ret; 283 } 284 285 static int vangogh_allocate_dpm_context(struct smu_context *smu) 286 { 287 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 288 289 smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), 290 GFP_KERNEL); 291 if (!smu_dpm->dpm_context) 292 return -ENOMEM; 293 294 smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); 295 296 return 0; 297 } 298 299 static int vangogh_init_smc_tables(struct smu_context *smu) 300 { 301 int ret = 0; 302 303 ret = vangogh_tables_init(smu); 304 if (ret) 305 return ret; 306 307 ret = vangogh_allocate_dpm_context(smu); 308 if (ret) 309 return ret; 310 311 return smu_v11_0_init_smc_tables(smu); 312 } 313 314 static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable) 315 { 316 int ret = 0; 317 318 if (enable) { 319 /* vcn dpm on is a prerequisite for vcn power gate messages */ 320 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { 321 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); 322 if (ret) 323 return ret; 324 } 325 } else { 326 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { 327 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); 328 if (ret) 329 return ret; 330 } 331 } 332 333 return ret; 334 } 335 336 static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) 337 { 338 int ret = 0; 339 340 if (enable) { 341 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { 342 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); 343 if (ret) 344 return ret; 345 } 346 } else { 347 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { 348 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); 349 if (ret) 350 return ret; 351 } 352 } 353 354 return ret; 355 } 356 357 static int vangogh_get_allowed_feature_mask(struct smu_context *smu, 358 uint32_t *feature_mask, 359 uint32_t num) 360 { 361 struct amdgpu_device *adev = smu->adev; 362 363 if (num > 2) 364 return -EINVAL; 365 366 memset(feature_mask, 0, sizeof(uint32_t) * num); 367 368 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_DPM_BIT) 369 | FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) 370 | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) 371 | FEATURE_MASK(FEATURE_PPT_BIT) 372 | FEATURE_MASK(FEATURE_TDC_BIT) 373 | FEATURE_MASK(FEATURE_FAN_CONTROLLER_BIT) 374 | FEATURE_MASK(FEATURE_DS_LCLK_BIT) 375 | FEATURE_MASK(FEATURE_DS_DCFCLK_BIT); 376 377 if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) 378 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT); 379 380 if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK) 381 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT); 382 383 if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) 384 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT); 385 386 return 0; 387 } 388 389 static bool vangogh_is_dpm_running(struct smu_context *smu) 390 { 391 int ret = 0; 392 uint32_t feature_mask[2]; 393 uint64_t feature_enabled; 394 395 ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); 396 397 if (ret) 398 return false; 399 400 feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | 401 ((uint64_t)feature_mask[1] << 32)); 402 403 return !!(feature_enabled & SMC_DPM_FEATURE); 404 } 405 406 static int vangogh_print_fine_grain_clk(struct smu_context *smu, 407 enum smu_clk_type clk_type, char *buf) 408 { 409 int size = 0; 410 411 switch (clk_type) { 412 case SMU_OD_SCLK: 413 if (smu->od_enabled) { 414 size = sprintf(buf, "%s:\n", "OD_SCLK"); 415 size += sprintf(buf + size, "0: %10uMhz\n", 416 (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); 417 size += sprintf(buf + size, "1: %10uMhz\n", 418 (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); 419 } 420 break; 421 case SMU_OD_RANGE: 422 if (smu->od_enabled) { 423 size = sprintf(buf, "%s:\n", "OD_RANGE"); 424 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", 425 smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); 426 } 427 break; 428 default: 429 break; 430 } 431 432 return size; 433 } 434 435 static int vangogh_read_sensor(struct smu_context *smu, 436 enum amd_pp_sensors sensor, 437 void *data, uint32_t *size) 438 { 439 int ret = 0; 440 441 if (!data || !size) 442 return -EINVAL; 443 444 mutex_lock(&smu->sensor_lock); 445 switch (sensor) { 446 case AMDGPU_PP_SENSOR_GPU_LOAD: 447 ret = vangogh_get_smu_metrics_data(smu, 448 METRICS_AVERAGE_GFXACTIVITY, 449 (uint32_t *)data); 450 *size = 4; 451 break; 452 case AMDGPU_PP_SENSOR_GPU_POWER: 453 ret = vangogh_get_smu_metrics_data(smu, 454 METRICS_AVERAGE_SOCKETPOWER, 455 (uint32_t *)data); 456 *size = 4; 457 break; 458 case AMDGPU_PP_SENSOR_EDGE_TEMP: 459 ret = vangogh_get_smu_metrics_data(smu, 460 METRICS_TEMPERATURE_EDGE, 461 (uint32_t *)data); 462 *size = 4; 463 break; 464 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 465 ret = vangogh_get_smu_metrics_data(smu, 466 METRICS_TEMPERATURE_HOTSPOT, 467 (uint32_t *)data); 468 *size = 4; 469 break; 470 case AMDGPU_PP_SENSOR_GFX_MCLK: 471 ret = vangogh_get_smu_metrics_data(smu, 472 METRICS_AVERAGE_UCLK, 473 (uint32_t *)data); 474 *(uint32_t *)data *= 100; 475 *size = 4; 476 break; 477 case AMDGPU_PP_SENSOR_GFX_SCLK: 478 ret = vangogh_get_smu_metrics_data(smu, 479 METRICS_AVERAGE_GFXCLK, 480 (uint32_t *)data); 481 *(uint32_t *)data *= 100; 482 *size = 4; 483 break; 484 case AMDGPU_PP_SENSOR_VDDGFX: 485 ret = vangogh_get_smu_metrics_data(smu, 486 METRICS_VOLTAGE_VDDGFX, 487 (uint32_t *)data); 488 *size = 4; 489 break; 490 case AMDGPU_PP_SENSOR_VDDNB: 491 ret = vangogh_get_smu_metrics_data(smu, 492 METRICS_VOLTAGE_VDDSOC, 493 (uint32_t *)data); 494 *size = 4; 495 break; 496 default: 497 ret = -EOPNOTSUPP; 498 break; 499 } 500 mutex_unlock(&smu->sensor_lock); 501 502 return ret; 503 } 504 505 static int vangogh_set_watermarks_table(struct smu_context *smu, 506 struct pp_smu_wm_range_sets *clock_ranges) 507 { 508 int i; 509 int ret = 0; 510 Watermarks_t *table = smu->smu_table.watermarks_table; 511 512 if (!table || !clock_ranges) 513 return -EINVAL; 514 515 if (clock_ranges) { 516 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || 517 clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) 518 return -EINVAL; 519 520 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { 521 table->WatermarkRow[WM_DCFCLK][i].MinClock = 522 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; 523 table->WatermarkRow[WM_DCFCLK][i].MaxClock = 524 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; 525 table->WatermarkRow[WM_DCFCLK][i].MinMclk = 526 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; 527 table->WatermarkRow[WM_DCFCLK][i].MaxMclk = 528 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; 529 530 table->WatermarkRow[WM_DCFCLK][i].WmSetting = 531 clock_ranges->reader_wm_sets[i].wm_inst; 532 } 533 534 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { 535 table->WatermarkRow[WM_SOCCLK][i].MinClock = 536 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; 537 table->WatermarkRow[WM_SOCCLK][i].MaxClock = 538 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; 539 table->WatermarkRow[WM_SOCCLK][i].MinMclk = 540 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; 541 table->WatermarkRow[WM_SOCCLK][i].MaxMclk = 542 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; 543 544 table->WatermarkRow[WM_SOCCLK][i].WmSetting = 545 clock_ranges->writer_wm_sets[i].wm_inst; 546 } 547 548 smu->watermarks_bitmap |= WATERMARKS_EXIST; 549 } 550 551 /* pass data to smu controller */ 552 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 553 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { 554 ret = smu_cmn_write_watermarks_table(smu); 555 if (ret) { 556 dev_err(smu->adev->dev, "Failed to update WMTABLE!"); 557 return ret; 558 } 559 smu->watermarks_bitmap |= WATERMARKS_LOADED; 560 } 561 562 return 0; 563 } 564 565 static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, 566 void **table) 567 { 568 struct smu_table_context *smu_table = &smu->smu_table; 569 struct gpu_metrics_v2_0 *gpu_metrics = 570 (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; 571 SmuMetrics_t metrics; 572 int ret = 0; 573 574 ret = smu_cmn_get_metrics_table(smu, &metrics, true); 575 if (ret) 576 return ret; 577 578 smu_v11_0_init_gpu_metrics_v2_0(gpu_metrics); 579 580 gpu_metrics->temperature_gfx = metrics.GfxTemperature; 581 gpu_metrics->temperature_soc = metrics.SocTemperature; 582 memcpy(&gpu_metrics->temperature_core[0], 583 &metrics.CoreTemperature[0], 584 sizeof(uint16_t) * 8); 585 gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; 586 gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; 587 588 gpu_metrics->average_gfx_activity = metrics.GfxActivity; 589 gpu_metrics->average_mm_activity = metrics.UvdActivity; 590 591 gpu_metrics->average_socket_power = metrics.CurrentSocketPower; 592 gpu_metrics->average_cpu_power = metrics.Power[0]; 593 gpu_metrics->average_soc_power = metrics.Power[1]; 594 memcpy(&gpu_metrics->average_core_power[0], 595 &metrics.CorePower[0], 596 sizeof(uint16_t) * 8); 597 598 gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency; 599 gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency; 600 gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency; 601 gpu_metrics->average_vclk_frequency = metrics.VclkFrequency; 602 603 memcpy(&gpu_metrics->current_coreclk[0], 604 &metrics.CoreFrequency[0], 605 sizeof(uint16_t) * 8); 606 gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; 607 gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; 608 609 gpu_metrics->throttle_status = metrics.ThrottlerStatus; 610 611 *table = (void *)gpu_metrics; 612 613 return sizeof(struct gpu_metrics_v2_0); 614 } 615 616 static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, 617 long input[], uint32_t size) 618 { 619 int ret = 0; 620 621 if (!smu->od_enabled) { 622 dev_warn(smu->adev->dev, "Fine grain is not enabled!\n"); 623 return -EINVAL; 624 } 625 626 switch (type) { 627 case PP_OD_EDIT_SCLK_VDDC_TABLE: 628 if (size != 2) { 629 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 630 return -EINVAL; 631 } 632 633 if (input[0] == 0) { 634 if (input[1] < smu->gfx_default_hard_min_freq) { 635 dev_warn(smu->adev->dev, "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", 636 input[1], smu->gfx_default_hard_min_freq); 637 return -EINVAL; 638 } 639 smu->gfx_actual_hard_min_freq = input[1]; 640 } else if (input[0] == 1) { 641 if (input[1] > smu->gfx_default_soft_max_freq) { 642 dev_warn(smu->adev->dev, "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", 643 input[1], smu->gfx_default_soft_max_freq); 644 return -EINVAL; 645 } 646 smu->gfx_actual_soft_max_freq = input[1]; 647 } else { 648 return -EINVAL; 649 } 650 break; 651 case PP_OD_RESTORE_DEFAULT_TABLE: 652 if (size != 0) { 653 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 654 return -EINVAL; 655 } else { 656 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 657 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 658 659 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 660 smu->gfx_actual_hard_min_freq, NULL); 661 if (ret) { 662 dev_err(smu->adev->dev, "Restore the default hard min sclk failed!"); 663 return ret; 664 } 665 666 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 667 smu->gfx_actual_soft_max_freq, NULL); 668 if (ret) { 669 dev_err(smu->adev->dev, "Restore the default soft max sclk failed!"); 670 return ret; 671 } 672 } 673 break; 674 case PP_OD_COMMIT_DPM_TABLE: 675 if (size != 0) { 676 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 677 return -EINVAL; 678 } else { 679 if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { 680 dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", 681 smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq); 682 return -EINVAL; 683 } 684 685 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 686 smu->gfx_actual_hard_min_freq, NULL); 687 if (ret) { 688 dev_err(smu->adev->dev, "Set hard min sclk failed!"); 689 return ret; 690 } 691 692 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 693 smu->gfx_actual_soft_max_freq, NULL); 694 if (ret) { 695 dev_err(smu->adev->dev, "Set soft max sclk failed!"); 696 return ret; 697 } 698 } 699 break; 700 default: 701 return -ENOSYS; 702 } 703 704 return ret; 705 } 706 707 static int vangogh_set_default_dpm_tables(struct smu_context *smu) 708 { 709 struct smu_table_context *smu_table = &smu->smu_table; 710 711 return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); 712 } 713 714 static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) 715 { 716 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 717 718 smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; 719 smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; 720 smu->gfx_actual_hard_min_freq = 0; 721 smu->gfx_actual_soft_max_freq = 0; 722 723 return 0; 724 } 725 726 static int vangogh_system_features_control(struct smu_context *smu, bool en) 727 { 728 struct amdgpu_device *adev = smu->adev; 729 730 if (adev->pm.fw_version >= 0x43f1700) 731 return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RlcPowerNotify, 732 en ? RLC_STATUS_NORMAL : RLC_STATUS_OFF, NULL); 733 else 734 return 0; 735 } 736 737 static const struct pptable_funcs vangogh_ppt_funcs = { 738 739 .check_fw_status = smu_v11_0_check_fw_status, 740 .check_fw_version = smu_v11_0_check_fw_version, 741 .init_smc_tables = vangogh_init_smc_tables, 742 .fini_smc_tables = smu_v11_0_fini_smc_tables, 743 .init_power = smu_v11_0_init_power, 744 .fini_power = smu_v11_0_fini_power, 745 .register_irq_handler = smu_v11_0_register_irq_handler, 746 .get_allowed_feature_mask = vangogh_get_allowed_feature_mask, 747 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, 748 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 749 .send_smc_msg = smu_cmn_send_smc_msg, 750 .dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable, 751 .dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable, 752 .is_dpm_running = vangogh_is_dpm_running, 753 .read_sensor = vangogh_read_sensor, 754 .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask, 755 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 756 .set_watermarks_table = vangogh_set_watermarks_table, 757 .set_driver_table_location = smu_v11_0_set_driver_table_location, 758 .interrupt_work = smu_v11_0_interrupt_work, 759 .get_gpu_metrics = vangogh_get_gpu_metrics, 760 .od_edit_dpm_table = vangogh_od_edit_dpm_table, 761 .print_clk_levels = vangogh_print_fine_grain_clk, 762 .set_default_dpm_table = vangogh_set_default_dpm_tables, 763 .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters, 764 .system_features_control = vangogh_system_features_control, 765 }; 766 767 void vangogh_set_ppt_funcs(struct smu_context *smu) 768 { 769 smu->ppt_funcs = &vangogh_ppt_funcs; 770 smu->message_map = vangogh_message_map; 771 smu->feature_map = vangogh_feature_mask_map; 772 smu->table_map = vangogh_table_map; 773 smu->is_apu = true; 774 } 775