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