renoir_ppt.c (44993B)
1/* 2 * Copyright 2019 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_v12_0_ppsmc.h" 29#include "smu12_driver_if.h" 30#include "smu_v12_0.h" 31#include "renoir_ppt.h" 32#include "smu_cmn.h" 33 34/* 35 * DO NOT use these for err/warn/info/debug messages. 36 * Use dev_err, dev_warn, dev_info and dev_dbg instead. 37 * They are more MGPU friendly. 38 */ 39#undef pr_err 40#undef pr_warn 41#undef pr_info 42#undef pr_debug 43 44static struct cmn2asic_msg_mapping renoir_message_map[SMU_MSG_MAX_COUNT] = { 45 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), 46 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), 47 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), 48 MSG_MAP(PowerUpGfx, PPSMC_MSG_PowerUpGfx, 1), 49 MSG_MAP(AllowGfxOff, PPSMC_MSG_EnableGfxOff, 1), 50 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisableGfxOff, 1), 51 MSG_MAP(PowerDownIspByTile, PPSMC_MSG_PowerDownIspByTile, 1), 52 MSG_MAP(PowerUpIspByTile, PPSMC_MSG_PowerUpIspByTile, 1), 53 MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1), 54 MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 1), 55 MSG_MAP(PowerDownSdma, PPSMC_MSG_PowerDownSdma, 1), 56 MSG_MAP(PowerUpSdma, PPSMC_MSG_PowerUpSdma, 1), 57 MSG_MAP(SetHardMinIspclkByFreq, PPSMC_MSG_SetHardMinIspclkByFreq, 1), 58 MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 1), 59 MSG_MAP(SetAllowFclkSwitch, PPSMC_MSG_SetAllowFclkSwitch, 1), 60 MSG_MAP(SetMinVideoGfxclkFreq, PPSMC_MSG_SetMinVideoGfxclkFreq, 1), 61 MSG_MAP(ActiveProcessNotify, PPSMC_MSG_ActiveProcessNotify, 1), 62 MSG_MAP(SetCustomPolicy, PPSMC_MSG_SetCustomPolicy, 1), 63 MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 1), 64 MSG_MAP(NumOfDisplays, PPSMC_MSG_SetDisplayCount, 1), 65 MSG_MAP(QueryPowerLimit, PPSMC_MSG_QueryPowerLimit, 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(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 1), 71 MSG_MAP(SetGfxclkOverdriveByFreqVid, PPSMC_MSG_SetGfxclkOverdriveByFreqVid, 1), 72 MSG_MAP(SetHardMinDcfclkByFreq, PPSMC_MSG_SetHardMinDcfclkByFreq, 1), 73 MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 1), 74 MSG_MAP(ControlIgpuATS, PPSMC_MSG_ControlIgpuATS, 1), 75 MSG_MAP(SetMinVideoFclkFreq, PPSMC_MSG_SetMinVideoFclkFreq, 1), 76 MSG_MAP(SetMinDeepSleepDcfclk, PPSMC_MSG_SetMinDeepSleepDcfclk, 1), 77 MSG_MAP(ForcePowerDownGfx, PPSMC_MSG_ForcePowerDownGfx, 1), 78 MSG_MAP(SetPhyclkVoltageByFreq, PPSMC_MSG_SetPhyclkVoltageByFreq, 1), 79 MSG_MAP(SetDppclkVoltageByFreq, PPSMC_MSG_SetDppclkVoltageByFreq, 1), 80 MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 1), 81 MSG_MAP(EnablePostCode, PPSMC_MSG_EnablePostCode, 1), 82 MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 1), 83 MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 1), 84 MSG_MAP(GetMinGfxclkFrequency, PPSMC_MSG_GetMinGfxclkFrequency, 1), 85 MSG_MAP(GetMaxGfxclkFrequency, PPSMC_MSG_GetMaxGfxclkFrequency, 1), 86 MSG_MAP(SoftReset, PPSMC_MSG_SoftReset, 1), 87 MSG_MAP(SetGfxCGPG, PPSMC_MSG_SetGfxCGPG, 1), 88 MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1), 89 MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 1), 90 MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 1), 91 MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 1), 92 MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 1), 93 MSG_MAP(PowerGateMmHub, PPSMC_MSG_PowerGateMmHub, 1), 94 MSG_MAP(UpdatePmeRestore, PPSMC_MSG_UpdatePmeRestore, 1), 95 MSG_MAP(GpuChangeState, PPSMC_MSG_GpuChangeState, 1), 96 MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 1), 97 MSG_MAP(ForceGfxContentSave, PPSMC_MSG_ForceGfxContentSave, 1), 98 MSG_MAP(EnableTmdp48MHzRefclkPwrDown, PPSMC_MSG_EnableTmdp48MHzRefclkPwrDown, 1), 99 MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1), 100 MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 1), 101 MSG_MAP(PowerGateAtHub, PPSMC_MSG_PowerGateAtHub, 1), 102 MSG_MAP(SetSoftMinJpeg, PPSMC_MSG_SetSoftMinJpeg, 1), 103 MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 1), 104}; 105 106static struct cmn2asic_mapping renoir_clk_map[SMU_CLK_COUNT] = { 107 CLK_MAP(GFXCLK, CLOCK_GFXCLK), 108 CLK_MAP(SCLK, CLOCK_GFXCLK), 109 CLK_MAP(SOCCLK, CLOCK_SOCCLK), 110 CLK_MAP(UCLK, CLOCK_FCLK), 111 CLK_MAP(MCLK, CLOCK_FCLK), 112 CLK_MAP(VCLK, CLOCK_VCLK), 113 CLK_MAP(DCLK, CLOCK_DCLK), 114}; 115 116static struct cmn2asic_mapping renoir_table_map[SMU_TABLE_COUNT] = { 117 TAB_MAP_VALID(WATERMARKS), 118 TAB_MAP_INVALID(CUSTOM_DPM), 119 TAB_MAP_VALID(DPMCLOCKS), 120 TAB_MAP_VALID(SMU_METRICS), 121}; 122 123static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { 124 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), 125 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), 126 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), 127 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), 128 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), 129}; 130 131static const uint8_t renoir_throttler_map[] = { 132 [THROTTLER_STATUS_BIT_SPL] = (SMU_THROTTLER_SPL_BIT), 133 [THROTTLER_STATUS_BIT_FPPT] = (SMU_THROTTLER_FPPT_BIT), 134 [THROTTLER_STATUS_BIT_SPPT] = (SMU_THROTTLER_SPPT_BIT), 135 [THROTTLER_STATUS_BIT_SPPT_APU] = (SMU_THROTTLER_SPPT_APU_BIT), 136 [THROTTLER_STATUS_BIT_THM_CORE] = (SMU_THROTTLER_TEMP_CORE_BIT), 137 [THROTTLER_STATUS_BIT_THM_GFX] = (SMU_THROTTLER_TEMP_GPU_BIT), 138 [THROTTLER_STATUS_BIT_THM_SOC] = (SMU_THROTTLER_TEMP_SOC_BIT), 139 [THROTTLER_STATUS_BIT_TDC_VDD] = (SMU_THROTTLER_TDC_VDD_BIT), 140 [THROTTLER_STATUS_BIT_TDC_SOC] = (SMU_THROTTLER_TDC_SOC_BIT), 141 [THROTTLER_STATUS_BIT_PROCHOT_CPU] = (SMU_THROTTLER_PROCHOT_CPU_BIT), 142 [THROTTLER_STATUS_BIT_PROCHOT_GFX] = (SMU_THROTTLER_PROCHOT_GFX_BIT), 143 [THROTTLER_STATUS_BIT_EDC_CPU] = (SMU_THROTTLER_EDC_CPU_BIT), 144 [THROTTLER_STATUS_BIT_EDC_GFX] = (SMU_THROTTLER_EDC_GFX_BIT), 145}; 146 147static int renoir_init_smc_tables(struct smu_context *smu) 148{ 149 struct smu_table_context *smu_table = &smu->smu_table; 150 struct smu_table *tables = smu_table->tables; 151 152 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), 153 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 154 SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), 155 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 156 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), 157 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 158 159 smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); 160 if (!smu_table->clocks_table) 161 goto err0_out; 162 163 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); 164 if (!smu_table->metrics_table) 165 goto err1_out; 166 smu_table->metrics_time = 0; 167 168 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); 169 if (!smu_table->watermarks_table) 170 goto err2_out; 171 172 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2); 173 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 174 if (!smu_table->gpu_metrics_table) 175 goto err3_out; 176 177 return 0; 178 179err3_out: 180 kfree(smu_table->watermarks_table); 181err2_out: 182 kfree(smu_table->metrics_table); 183err1_out: 184 kfree(smu_table->clocks_table); 185err0_out: 186 return -ENOMEM; 187} 188 189/* 190 * This interface just for getting uclk ultimate freq and should't introduce 191 * other likewise function result in overmuch callback. 192 */ 193static int renoir_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type, 194 uint32_t dpm_level, uint32_t *freq) 195{ 196 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 197 198 if (!clk_table || clk_type >= SMU_CLK_COUNT) 199 return -EINVAL; 200 201 switch (clk_type) { 202 case SMU_SOCCLK: 203 if (dpm_level >= NUM_SOCCLK_DPM_LEVELS) 204 return -EINVAL; 205 *freq = clk_table->SocClocks[dpm_level].Freq; 206 break; 207 case SMU_UCLK: 208 case SMU_MCLK: 209 if (dpm_level >= NUM_FCLK_DPM_LEVELS) 210 return -EINVAL; 211 *freq = clk_table->FClocks[dpm_level].Freq; 212 break; 213 case SMU_DCEFCLK: 214 if (dpm_level >= NUM_DCFCLK_DPM_LEVELS) 215 return -EINVAL; 216 *freq = clk_table->DcfClocks[dpm_level].Freq; 217 break; 218 case SMU_FCLK: 219 if (dpm_level >= NUM_FCLK_DPM_LEVELS) 220 return -EINVAL; 221 *freq = clk_table->FClocks[dpm_level].Freq; 222 break; 223 case SMU_VCLK: 224 if (dpm_level >= NUM_VCN_DPM_LEVELS) 225 return -EINVAL; 226 *freq = clk_table->VClocks[dpm_level].Freq; 227 break; 228 case SMU_DCLK: 229 if (dpm_level >= NUM_VCN_DPM_LEVELS) 230 return -EINVAL; 231 *freq = clk_table->DClocks[dpm_level].Freq; 232 break; 233 234 default: 235 return -EINVAL; 236 } 237 238 return 0; 239} 240 241static int renoir_get_profiling_clk_mask(struct smu_context *smu, 242 enum amd_dpm_forced_level level, 243 uint32_t *sclk_mask, 244 uint32_t *mclk_mask, 245 uint32_t *soc_mask) 246{ 247 248 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 249 if (sclk_mask) 250 *sclk_mask = 0; 251 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 252 if (mclk_mask) 253 /* mclk levels are in reverse order */ 254 *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1; 255 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 256 if(sclk_mask) 257 /* The sclk as gfxclk and has three level about max/min/current */ 258 *sclk_mask = 3 - 1; 259 260 if(mclk_mask) 261 /* mclk levels are in reverse order */ 262 *mclk_mask = 0; 263 264 if(soc_mask) 265 *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1; 266 } 267 268 return 0; 269} 270 271static int renoir_get_dpm_ultimate_freq(struct smu_context *smu, 272 enum smu_clk_type clk_type, 273 uint32_t *min, 274 uint32_t *max) 275{ 276 int ret = 0; 277 uint32_t mclk_mask, soc_mask; 278 uint32_t clock_limit; 279 280 if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) { 281 switch (clk_type) { 282 case SMU_MCLK: 283 case SMU_UCLK: 284 clock_limit = smu->smu_table.boot_values.uclk; 285 break; 286 case SMU_GFXCLK: 287 case SMU_SCLK: 288 clock_limit = smu->smu_table.boot_values.gfxclk; 289 break; 290 case SMU_SOCCLK: 291 clock_limit = smu->smu_table.boot_values.socclk; 292 break; 293 default: 294 clock_limit = 0; 295 break; 296 } 297 298 /* clock in Mhz unit */ 299 if (min) 300 *min = clock_limit / 100; 301 if (max) 302 *max = clock_limit / 100; 303 304 return 0; 305 } 306 307 if (max) { 308 ret = renoir_get_profiling_clk_mask(smu, 309 AMD_DPM_FORCED_LEVEL_PROFILE_PEAK, 310 NULL, 311 &mclk_mask, 312 &soc_mask); 313 if (ret) 314 goto failed; 315 316 switch (clk_type) { 317 case SMU_GFXCLK: 318 case SMU_SCLK: 319 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMaxGfxclkFrequency, max); 320 if (ret) { 321 dev_err(smu->adev->dev, "Attempt to get max GX frequency from SMC Failed !\n"); 322 goto failed; 323 } 324 break; 325 case SMU_UCLK: 326 case SMU_FCLK: 327 case SMU_MCLK: 328 ret = renoir_get_dpm_clk_limited(smu, clk_type, mclk_mask, max); 329 if (ret) 330 goto failed; 331 break; 332 case SMU_SOCCLK: 333 ret = renoir_get_dpm_clk_limited(smu, clk_type, soc_mask, max); 334 if (ret) 335 goto failed; 336 break; 337 default: 338 ret = -EINVAL; 339 goto failed; 340 } 341 } 342 343 if (min) { 344 switch (clk_type) { 345 case SMU_GFXCLK: 346 case SMU_SCLK: 347 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMinGfxclkFrequency, min); 348 if (ret) { 349 dev_err(smu->adev->dev, "Attempt to get min GX frequency from SMC Failed !\n"); 350 goto failed; 351 } 352 break; 353 case SMU_UCLK: 354 case SMU_FCLK: 355 case SMU_MCLK: 356 ret = renoir_get_dpm_clk_limited(smu, clk_type, NUM_MEMCLK_DPM_LEVELS - 1, min); 357 if (ret) 358 goto failed; 359 break; 360 case SMU_SOCCLK: 361 ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min); 362 if (ret) 363 goto failed; 364 break; 365 default: 366 ret = -EINVAL; 367 goto failed; 368 } 369 } 370failed: 371 return ret; 372} 373 374static int renoir_od_edit_dpm_table(struct smu_context *smu, 375 enum PP_OD_DPM_TABLE_COMMAND type, 376 long input[], uint32_t size) 377{ 378 int ret = 0; 379 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); 380 381 if (!(smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)) { 382 dev_warn(smu->adev->dev, 383 "pp_od_clk_voltage is not accessible if power_dpm_force_performance_level is not in manual mode!\n"); 384 return -EINVAL; 385 } 386 387 switch (type) { 388 case PP_OD_EDIT_SCLK_VDDC_TABLE: 389 if (size != 2) { 390 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 391 return -EINVAL; 392 } 393 394 if (input[0] == 0) { 395 if (input[1] < smu->gfx_default_hard_min_freq) { 396 dev_warn(smu->adev->dev, 397 "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", 398 input[1], smu->gfx_default_hard_min_freq); 399 return -EINVAL; 400 } 401 smu->gfx_actual_hard_min_freq = input[1]; 402 } else if (input[0] == 1) { 403 if (input[1] > smu->gfx_default_soft_max_freq) { 404 dev_warn(smu->adev->dev, 405 "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", 406 input[1], smu->gfx_default_soft_max_freq); 407 return -EINVAL; 408 } 409 smu->gfx_actual_soft_max_freq = input[1]; 410 } else { 411 return -EINVAL; 412 } 413 break; 414 case PP_OD_RESTORE_DEFAULT_TABLE: 415 if (size != 0) { 416 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 417 return -EINVAL; 418 } 419 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 420 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 421 break; 422 case PP_OD_COMMIT_DPM_TABLE: 423 if (size != 0) { 424 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 425 return -EINVAL; 426 } else { 427 if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { 428 dev_err(smu->adev->dev, 429 "The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", 430 smu->gfx_actual_hard_min_freq, 431 smu->gfx_actual_soft_max_freq); 432 return -EINVAL; 433 } 434 435 ret = smu_cmn_send_smc_msg_with_param(smu, 436 SMU_MSG_SetHardMinGfxClk, 437 smu->gfx_actual_hard_min_freq, 438 NULL); 439 if (ret) { 440 dev_err(smu->adev->dev, "Set hard min sclk failed!"); 441 return ret; 442 } 443 444 ret = smu_cmn_send_smc_msg_with_param(smu, 445 SMU_MSG_SetSoftMaxGfxClk, 446 smu->gfx_actual_soft_max_freq, 447 NULL); 448 if (ret) { 449 dev_err(smu->adev->dev, "Set soft max sclk failed!"); 450 return ret; 451 } 452 } 453 break; 454 default: 455 return -ENOSYS; 456 } 457 458 return ret; 459} 460 461static int renoir_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) 462{ 463 uint32_t min = 0, max = 0; 464 uint32_t ret = 0; 465 466 ret = smu_cmn_send_smc_msg_with_param(smu, 467 SMU_MSG_GetMinGfxclkFrequency, 468 0, &min); 469 if (ret) 470 return ret; 471 ret = smu_cmn_send_smc_msg_with_param(smu, 472 SMU_MSG_GetMaxGfxclkFrequency, 473 0, &max); 474 if (ret) 475 return ret; 476 477 smu->gfx_default_hard_min_freq = min; 478 smu->gfx_default_soft_max_freq = max; 479 smu->gfx_actual_hard_min_freq = 0; 480 smu->gfx_actual_soft_max_freq = 0; 481 482 return 0; 483} 484 485static int renoir_print_clk_levels(struct smu_context *smu, 486 enum smu_clk_type clk_type, char *buf) 487{ 488 int i, size = 0, ret = 0; 489 uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0; 490 SmuMetrics_t metrics; 491 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); 492 bool cur_value_match_level = false; 493 494 memset(&metrics, 0, sizeof(metrics)); 495 496 ret = smu_cmn_get_metrics_table(smu, &metrics, false); 497 if (ret) 498 return ret; 499 500 smu_cmn_get_sysfs_buf(&buf, &size); 501 502 switch (clk_type) { 503 case SMU_OD_RANGE: 504 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { 505 ret = smu_cmn_send_smc_msg_with_param(smu, 506 SMU_MSG_GetMinGfxclkFrequency, 507 0, &min); 508 if (ret) 509 return ret; 510 ret = smu_cmn_send_smc_msg_with_param(smu, 511 SMU_MSG_GetMaxGfxclkFrequency, 512 0, &max); 513 if (ret) 514 return ret; 515 size += sysfs_emit_at(buf, size, "OD_RANGE\nSCLK: %10uMhz %10uMhz\n", min, max); 516 } 517 break; 518 case SMU_OD_SCLK: 519 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { 520 min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq; 521 max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq; 522 size += sysfs_emit_at(buf, size, "OD_SCLK\n"); 523 size += sysfs_emit_at(buf, size, "0:%10uMhz\n", min); 524 size += sysfs_emit_at(buf, size, "1:%10uMhz\n", max); 525 } 526 break; 527 case SMU_GFXCLK: 528 case SMU_SCLK: 529 /* retirve table returned paramters unit is MHz */ 530 cur_value = metrics.ClockFrequency[CLOCK_GFXCLK]; 531 ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min, &max); 532 if (!ret) { 533 /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */ 534 if (cur_value == max) 535 i = 2; 536 else if (cur_value == min) 537 i = 0; 538 else 539 i = 1; 540 541 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min, 542 i == 0 ? "*" : ""); 543 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", 544 i == 1 ? cur_value : RENOIR_UMD_PSTATE_GFXCLK, 545 i == 1 ? "*" : ""); 546 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max, 547 i == 2 ? "*" : ""); 548 } 549 return size; 550 case SMU_SOCCLK: 551 count = NUM_SOCCLK_DPM_LEVELS; 552 cur_value = metrics.ClockFrequency[CLOCK_SOCCLK]; 553 break; 554 case SMU_MCLK: 555 count = NUM_MEMCLK_DPM_LEVELS; 556 cur_value = metrics.ClockFrequency[CLOCK_FCLK]; 557 break; 558 case SMU_DCEFCLK: 559 count = NUM_DCFCLK_DPM_LEVELS; 560 cur_value = metrics.ClockFrequency[CLOCK_DCFCLK]; 561 break; 562 case SMU_FCLK: 563 count = NUM_FCLK_DPM_LEVELS; 564 cur_value = metrics.ClockFrequency[CLOCK_FCLK]; 565 break; 566 case SMU_VCLK: 567 count = NUM_VCN_DPM_LEVELS; 568 cur_value = metrics.ClockFrequency[CLOCK_VCLK]; 569 break; 570 case SMU_DCLK: 571 count = NUM_VCN_DPM_LEVELS; 572 cur_value = metrics.ClockFrequency[CLOCK_DCLK]; 573 break; 574 default: 575 break; 576 } 577 578 switch (clk_type) { 579 case SMU_GFXCLK: 580 case SMU_SCLK: 581 case SMU_SOCCLK: 582 case SMU_MCLK: 583 case SMU_DCEFCLK: 584 case SMU_FCLK: 585 case SMU_VCLK: 586 case SMU_DCLK: 587 for (i = 0; i < count; i++) { 588 ret = renoir_get_dpm_clk_limited(smu, clk_type, i, &value); 589 if (ret) 590 return ret; 591 if (!value) 592 continue; 593 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value, 594 cur_value == value ? "*" : ""); 595 if (cur_value == value) 596 cur_value_match_level = true; 597 } 598 599 if (!cur_value_match_level) 600 size += sysfs_emit_at(buf, size, " %uMhz *\n", cur_value); 601 602 break; 603 default: 604 break; 605 } 606 607 return size; 608} 609 610static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context *smu) 611{ 612 enum amd_pm_state_type pm_type; 613 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); 614 615 if (!smu_dpm_ctx->dpm_context || 616 !smu_dpm_ctx->dpm_current_power_state) 617 return -EINVAL; 618 619 switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) { 620 case SMU_STATE_UI_LABEL_BATTERY: 621 pm_type = POWER_STATE_TYPE_BATTERY; 622 break; 623 case SMU_STATE_UI_LABEL_BALLANCED: 624 pm_type = POWER_STATE_TYPE_BALANCED; 625 break; 626 case SMU_STATE_UI_LABEL_PERFORMANCE: 627 pm_type = POWER_STATE_TYPE_PERFORMANCE; 628 break; 629 default: 630 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT) 631 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT; 632 else 633 pm_type = POWER_STATE_TYPE_DEFAULT; 634 break; 635 } 636 637 return pm_type; 638} 639 640static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) 641{ 642 int ret = 0; 643 644 if (enable) { 645 /* vcn dpm on is a prerequisite for vcn power gate messages */ 646 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { 647 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); 648 if (ret) 649 return ret; 650 } 651 } else { 652 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { 653 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); 654 if (ret) 655 return ret; 656 } 657 } 658 659 return ret; 660} 661 662static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) 663{ 664 int ret = 0; 665 666 if (enable) { 667 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { 668 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); 669 if (ret) 670 return ret; 671 } 672 } else { 673 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { 674 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); 675 if (ret) 676 return ret; 677 } 678 } 679 680 return ret; 681} 682 683static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest) 684{ 685 int ret = 0, i = 0; 686 uint32_t min_freq, max_freq, force_freq; 687 enum smu_clk_type clk_type; 688 689 enum smu_clk_type clks[] = { 690 SMU_GFXCLK, 691 SMU_MCLK, 692 SMU_SOCCLK, 693 }; 694 695 for (i = 0; i < ARRAY_SIZE(clks); i++) { 696 clk_type = clks[i]; 697 ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); 698 if (ret) 699 return ret; 700 701 force_freq = highest ? max_freq : min_freq; 702 ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq); 703 if (ret) 704 return ret; 705 } 706 707 return ret; 708} 709 710static int renoir_unforce_dpm_levels(struct smu_context *smu) { 711 712 int ret = 0, i = 0; 713 uint32_t min_freq, max_freq; 714 enum smu_clk_type clk_type; 715 716 struct clk_feature_map { 717 enum smu_clk_type clk_type; 718 uint32_t feature; 719 } clk_feature_map[] = { 720 {SMU_GFXCLK, SMU_FEATURE_DPM_GFXCLK_BIT}, 721 {SMU_MCLK, SMU_FEATURE_DPM_UCLK_BIT}, 722 {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT}, 723 }; 724 725 for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) { 726 if (!smu_cmn_feature_is_enabled(smu, clk_feature_map[i].feature)) 727 continue; 728 729 clk_type = clk_feature_map[i].clk_type; 730 731 ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); 732 if (ret) 733 return ret; 734 735 ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); 736 if (ret) 737 return ret; 738 } 739 740 return ret; 741} 742 743/* 744 * This interface get dpm clock table for dc 745 */ 746static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table) 747{ 748 DpmClocks_t *table = smu->smu_table.clocks_table; 749 int i; 750 751 if (!clock_table || !table) 752 return -EINVAL; 753 754 for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) { 755 clock_table->DcfClocks[i].Freq = table->DcfClocks[i].Freq; 756 clock_table->DcfClocks[i].Vol = table->DcfClocks[i].Vol; 757 } 758 759 for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) { 760 clock_table->SocClocks[i].Freq = table->SocClocks[i].Freq; 761 clock_table->SocClocks[i].Vol = table->SocClocks[i].Vol; 762 } 763 764 for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { 765 clock_table->FClocks[i].Freq = table->FClocks[i].Freq; 766 clock_table->FClocks[i].Vol = table->FClocks[i].Vol; 767 } 768 769 for (i = 0; i< NUM_MEMCLK_DPM_LEVELS; i++) { 770 clock_table->MemClocks[i].Freq = table->MemClocks[i].Freq; 771 clock_table->MemClocks[i].Vol = table->MemClocks[i].Vol; 772 } 773 774 for (i = 0; i < NUM_VCN_DPM_LEVELS; i++) { 775 clock_table->VClocks[i].Freq = table->VClocks[i].Freq; 776 clock_table->VClocks[i].Vol = table->VClocks[i].Vol; 777 } 778 779 for (i = 0; i < NUM_VCN_DPM_LEVELS; i++) { 780 clock_table->DClocks[i].Freq = table->DClocks[i].Freq; 781 clock_table->DClocks[i].Vol = table->DClocks[i].Vol; 782 } 783 784 return 0; 785} 786 787static int renoir_force_clk_levels(struct smu_context *smu, 788 enum smu_clk_type clk_type, uint32_t mask) 789{ 790 791 int ret = 0 ; 792 uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; 793 794 soft_min_level = mask ? (ffs(mask) - 1) : 0; 795 soft_max_level = mask ? (fls(mask) - 1) : 0; 796 797 switch (clk_type) { 798 case SMU_GFXCLK: 799 case SMU_SCLK: 800 if (soft_min_level > 2 || soft_max_level > 2) { 801 dev_info(smu->adev->dev, "Currently sclk only support 3 levels on APU\n"); 802 return -EINVAL; 803 } 804 805 ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min_freq, &max_freq); 806 if (ret) 807 return ret; 808 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 809 soft_max_level == 0 ? min_freq : 810 soft_max_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : max_freq, 811 NULL); 812 if (ret) 813 return ret; 814 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 815 soft_min_level == 2 ? max_freq : 816 soft_min_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : min_freq, 817 NULL); 818 if (ret) 819 return ret; 820 break; 821 case SMU_SOCCLK: 822 ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq); 823 if (ret) 824 return ret; 825 ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq); 826 if (ret) 827 return ret; 828 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq, NULL); 829 if (ret) 830 return ret; 831 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min_freq, NULL); 832 if (ret) 833 return ret; 834 break; 835 case SMU_MCLK: 836 case SMU_FCLK: 837 ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq); 838 if (ret) 839 return ret; 840 ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq); 841 if (ret) 842 return ret; 843 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq, NULL); 844 if (ret) 845 return ret; 846 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min_freq, NULL); 847 if (ret) 848 return ret; 849 break; 850 default: 851 break; 852 } 853 854 return ret; 855} 856 857static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) 858{ 859 int workload_type, ret; 860 uint32_t profile_mode = input[size]; 861 862 if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { 863 dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode); 864 return -EINVAL; 865 } 866 867 if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT || 868 profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) 869 return 0; 870 871 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 872 workload_type = smu_cmn_to_asic_specific_index(smu, 873 CMN2ASIC_MAPPING_WORKLOAD, 874 profile_mode); 875 if (workload_type < 0) { 876 /* 877 * TODO: If some case need switch to powersave/default power mode 878 * then can consider enter WORKLOAD_COMPUTE/WORKLOAD_CUSTOM for power saving. 879 */ 880 dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on RENOIR\n", profile_mode); 881 return -EINVAL; 882 } 883 884 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify, 885 1 << workload_type, 886 NULL); 887 if (ret) { 888 dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type); 889 return ret; 890 } 891 892 smu->power_profile_mode = profile_mode; 893 894 return 0; 895} 896 897static int renoir_set_peak_clock_by_device(struct smu_context *smu) 898{ 899 int ret = 0; 900 uint32_t sclk_freq = 0, uclk_freq = 0; 901 902 ret = renoir_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_freq); 903 if (ret) 904 return ret; 905 906 ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk_freq, sclk_freq); 907 if (ret) 908 return ret; 909 910 ret = renoir_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &uclk_freq); 911 if (ret) 912 return ret; 913 914 ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_UCLK, uclk_freq, uclk_freq); 915 if (ret) 916 return ret; 917 918 return ret; 919} 920 921static int renoir_set_performance_level(struct smu_context *smu, 922 enum amd_dpm_forced_level level) 923{ 924 int ret = 0; 925 uint32_t sclk_mask, mclk_mask, soc_mask; 926 927 switch (level) { 928 case AMD_DPM_FORCED_LEVEL_HIGH: 929 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 930 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 931 932 ret = renoir_force_dpm_limit_value(smu, true); 933 break; 934 case AMD_DPM_FORCED_LEVEL_LOW: 935 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 936 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 937 938 ret = renoir_force_dpm_limit_value(smu, false); 939 break; 940 case AMD_DPM_FORCED_LEVEL_AUTO: 941 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 942 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 943 944 ret = renoir_unforce_dpm_levels(smu); 945 break; 946 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 947 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 948 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 949 950 ret = smu_cmn_send_smc_msg_with_param(smu, 951 SMU_MSG_SetHardMinGfxClk, 952 RENOIR_UMD_PSTATE_GFXCLK, 953 NULL); 954 if (ret) 955 return ret; 956 ret = smu_cmn_send_smc_msg_with_param(smu, 957 SMU_MSG_SetHardMinFclkByFreq, 958 RENOIR_UMD_PSTATE_FCLK, 959 NULL); 960 if (ret) 961 return ret; 962 ret = smu_cmn_send_smc_msg_with_param(smu, 963 SMU_MSG_SetHardMinSocclkByFreq, 964 RENOIR_UMD_PSTATE_SOCCLK, 965 NULL); 966 if (ret) 967 return ret; 968 ret = smu_cmn_send_smc_msg_with_param(smu, 969 SMU_MSG_SetHardMinVcn, 970 RENOIR_UMD_PSTATE_VCNCLK, 971 NULL); 972 if (ret) 973 return ret; 974 975 ret = smu_cmn_send_smc_msg_with_param(smu, 976 SMU_MSG_SetSoftMaxGfxClk, 977 RENOIR_UMD_PSTATE_GFXCLK, 978 NULL); 979 if (ret) 980 return ret; 981 ret = smu_cmn_send_smc_msg_with_param(smu, 982 SMU_MSG_SetSoftMaxFclkByFreq, 983 RENOIR_UMD_PSTATE_FCLK, 984 NULL); 985 if (ret) 986 return ret; 987 ret = smu_cmn_send_smc_msg_with_param(smu, 988 SMU_MSG_SetSoftMaxSocclkByFreq, 989 RENOIR_UMD_PSTATE_SOCCLK, 990 NULL); 991 if (ret) 992 return ret; 993 ret = smu_cmn_send_smc_msg_with_param(smu, 994 SMU_MSG_SetSoftMaxVcn, 995 RENOIR_UMD_PSTATE_VCNCLK, 996 NULL); 997 if (ret) 998 return ret; 999 break; 1000 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 1001 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 1002 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 1003 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 1004 1005 ret = renoir_get_profiling_clk_mask(smu, level, 1006 &sclk_mask, 1007 &mclk_mask, 1008 &soc_mask); 1009 if (ret) 1010 return ret; 1011 renoir_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask); 1012 renoir_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask); 1013 renoir_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask); 1014 break; 1015 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 1016 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 1017 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 1018 1019 ret = renoir_set_peak_clock_by_device(smu); 1020 break; 1021 case AMD_DPM_FORCED_LEVEL_MANUAL: 1022 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 1023 default: 1024 break; 1025 } 1026 return ret; 1027} 1028 1029/* save watermark settings into pplib smu structure, 1030 * also pass data to smu controller 1031 */ 1032static int renoir_set_watermarks_table( 1033 struct smu_context *smu, 1034 struct pp_smu_wm_range_sets *clock_ranges) 1035{ 1036 Watermarks_t *table = smu->smu_table.watermarks_table; 1037 int ret = 0; 1038 int i; 1039 1040 if (clock_ranges) { 1041 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || 1042 clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) 1043 return -EINVAL; 1044 1045 /* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/ 1046 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { 1047 table->WatermarkRow[WM_DCFCLK][i].MinClock = 1048 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; 1049 table->WatermarkRow[WM_DCFCLK][i].MaxClock = 1050 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; 1051 table->WatermarkRow[WM_DCFCLK][i].MinMclk = 1052 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; 1053 table->WatermarkRow[WM_DCFCLK][i].MaxMclk = 1054 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; 1055 1056 table->WatermarkRow[WM_DCFCLK][i].WmSetting = 1057 clock_ranges->reader_wm_sets[i].wm_inst; 1058 table->WatermarkRow[WM_DCFCLK][i].WmType = 1059 clock_ranges->reader_wm_sets[i].wm_type; 1060 } 1061 1062 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { 1063 table->WatermarkRow[WM_SOCCLK][i].MinClock = 1064 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; 1065 table->WatermarkRow[WM_SOCCLK][i].MaxClock = 1066 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; 1067 table->WatermarkRow[WM_SOCCLK][i].MinMclk = 1068 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; 1069 table->WatermarkRow[WM_SOCCLK][i].MaxMclk = 1070 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; 1071 1072 table->WatermarkRow[WM_SOCCLK][i].WmSetting = 1073 clock_ranges->writer_wm_sets[i].wm_inst; 1074 table->WatermarkRow[WM_SOCCLK][i].WmType = 1075 clock_ranges->writer_wm_sets[i].wm_type; 1076 } 1077 1078 smu->watermarks_bitmap |= WATERMARKS_EXIST; 1079 } 1080 1081 /* pass data to smu controller */ 1082 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 1083 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { 1084 ret = smu_cmn_write_watermarks_table(smu); 1085 if (ret) { 1086 dev_err(smu->adev->dev, "Failed to update WMTABLE!"); 1087 return ret; 1088 } 1089 smu->watermarks_bitmap |= WATERMARKS_LOADED; 1090 } 1091 1092 return 0; 1093} 1094 1095static int renoir_get_power_profile_mode(struct smu_context *smu, 1096 char *buf) 1097{ 1098 uint32_t i, size = 0; 1099 int16_t workload_type = 0; 1100 1101 if (!buf) 1102 return -EINVAL; 1103 1104 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { 1105 /* 1106 * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT 1107 * Not all profile modes are supported on arcturus. 1108 */ 1109 workload_type = smu_cmn_to_asic_specific_index(smu, 1110 CMN2ASIC_MAPPING_WORKLOAD, 1111 i); 1112 if (workload_type < 0) 1113 continue; 1114 1115 size += sysfs_emit_at(buf, size, "%2d %14s%s\n", 1116 i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); 1117 } 1118 1119 return size; 1120} 1121 1122static void renoir_get_ss_power_percent(SmuMetrics_t *metrics, 1123 uint32_t *apu_percent, uint32_t *dgpu_percent) 1124{ 1125 uint32_t apu_boost = 0; 1126 uint32_t dgpu_boost = 0; 1127 uint16_t apu_limit = 0; 1128 uint16_t dgpu_limit = 0; 1129 uint16_t apu_power = 0; 1130 uint16_t dgpu_power = 0; 1131 1132 apu_power = metrics->ApuPower; 1133 apu_limit = metrics->StapmOriginalLimit; 1134 if (apu_power > apu_limit && apu_limit != 0) 1135 apu_boost = ((apu_power - apu_limit) * 100) / apu_limit; 1136 apu_boost = (apu_boost > 100) ? 100 : apu_boost; 1137 1138 dgpu_power = metrics->dGpuPower; 1139 if (metrics->StapmCurrentLimit > metrics->StapmOriginalLimit) 1140 dgpu_limit = metrics->StapmCurrentLimit - metrics->StapmOriginalLimit; 1141 if (dgpu_power > dgpu_limit && dgpu_limit != 0) 1142 dgpu_boost = ((dgpu_power - dgpu_limit) * 100) / dgpu_limit; 1143 dgpu_boost = (dgpu_boost > 100) ? 100 : dgpu_boost; 1144 1145 if (dgpu_boost >= apu_boost) 1146 apu_boost = 0; 1147 else 1148 dgpu_boost = 0; 1149 1150 *apu_percent = apu_boost; 1151 *dgpu_percent = dgpu_boost; 1152} 1153 1154 1155static int renoir_get_smu_metrics_data(struct smu_context *smu, 1156 MetricsMember_t member, 1157 uint32_t *value) 1158{ 1159 struct smu_table_context *smu_table = &smu->smu_table; 1160 1161 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; 1162 int ret = 0; 1163 uint32_t apu_percent = 0; 1164 uint32_t dgpu_percent = 0; 1165 1166 1167 ret = smu_cmn_get_metrics_table(smu, 1168 NULL, 1169 false); 1170 if (ret) 1171 return ret; 1172 1173 switch (member) { 1174 case METRICS_AVERAGE_GFXCLK: 1175 *value = metrics->ClockFrequency[CLOCK_GFXCLK]; 1176 break; 1177 case METRICS_AVERAGE_SOCCLK: 1178 *value = metrics->ClockFrequency[CLOCK_SOCCLK]; 1179 break; 1180 case METRICS_AVERAGE_UCLK: 1181 *value = metrics->ClockFrequency[CLOCK_FCLK]; 1182 break; 1183 case METRICS_AVERAGE_GFXACTIVITY: 1184 *value = metrics->AverageGfxActivity / 100; 1185 break; 1186 case METRICS_AVERAGE_VCNACTIVITY: 1187 *value = metrics->AverageUvdActivity / 100; 1188 break; 1189 case METRICS_AVERAGE_SOCKETPOWER: 1190 *value = (metrics->CurrentSocketPower << 8) / 1000; 1191 break; 1192 case METRICS_TEMPERATURE_EDGE: 1193 *value = (metrics->GfxTemperature / 100) * 1194 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 1195 break; 1196 case METRICS_TEMPERATURE_HOTSPOT: 1197 *value = (metrics->SocTemperature / 100) * 1198 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 1199 break; 1200 case METRICS_THROTTLER_STATUS: 1201 *value = metrics->ThrottlerStatus; 1202 break; 1203 case METRICS_VOLTAGE_VDDGFX: 1204 *value = metrics->Voltage[0]; 1205 break; 1206 case METRICS_VOLTAGE_VDDSOC: 1207 *value = metrics->Voltage[1]; 1208 break; 1209 case METRICS_SS_APU_SHARE: 1210 /* return the percentage of APU power boost 1211 * with respect to APU's power limit. 1212 */ 1213 renoir_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent); 1214 *value = apu_percent; 1215 break; 1216 case METRICS_SS_DGPU_SHARE: 1217 /* return the percentage of dGPU power boost 1218 * with respect to dGPU's power limit. 1219 */ 1220 renoir_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent); 1221 *value = dgpu_percent; 1222 break; 1223 default: 1224 *value = UINT_MAX; 1225 break; 1226 } 1227 1228 return ret; 1229} 1230 1231static int renoir_read_sensor(struct smu_context *smu, 1232 enum amd_pp_sensors sensor, 1233 void *data, uint32_t *size) 1234{ 1235 int ret = 0; 1236 1237 if (!data || !size) 1238 return -EINVAL; 1239 1240 switch (sensor) { 1241 case AMDGPU_PP_SENSOR_GPU_LOAD: 1242 ret = renoir_get_smu_metrics_data(smu, 1243 METRICS_AVERAGE_GFXACTIVITY, 1244 (uint32_t *)data); 1245 *size = 4; 1246 break; 1247 case AMDGPU_PP_SENSOR_EDGE_TEMP: 1248 ret = renoir_get_smu_metrics_data(smu, 1249 METRICS_TEMPERATURE_EDGE, 1250 (uint32_t *)data); 1251 *size = 4; 1252 break; 1253 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 1254 ret = renoir_get_smu_metrics_data(smu, 1255 METRICS_TEMPERATURE_HOTSPOT, 1256 (uint32_t *)data); 1257 *size = 4; 1258 break; 1259 case AMDGPU_PP_SENSOR_GFX_MCLK: 1260 ret = renoir_get_smu_metrics_data(smu, 1261 METRICS_AVERAGE_UCLK, 1262 (uint32_t *)data); 1263 *(uint32_t *)data *= 100; 1264 *size = 4; 1265 break; 1266 case AMDGPU_PP_SENSOR_GFX_SCLK: 1267 ret = renoir_get_smu_metrics_data(smu, 1268 METRICS_AVERAGE_GFXCLK, 1269 (uint32_t *)data); 1270 *(uint32_t *)data *= 100; 1271 *size = 4; 1272 break; 1273 case AMDGPU_PP_SENSOR_VDDGFX: 1274 ret = renoir_get_smu_metrics_data(smu, 1275 METRICS_VOLTAGE_VDDGFX, 1276 (uint32_t *)data); 1277 *size = 4; 1278 break; 1279 case AMDGPU_PP_SENSOR_VDDNB: 1280 ret = renoir_get_smu_metrics_data(smu, 1281 METRICS_VOLTAGE_VDDSOC, 1282 (uint32_t *)data); 1283 *size = 4; 1284 break; 1285 case AMDGPU_PP_SENSOR_GPU_POWER: 1286 ret = renoir_get_smu_metrics_data(smu, 1287 METRICS_AVERAGE_SOCKETPOWER, 1288 (uint32_t *)data); 1289 *size = 4; 1290 break; 1291 case AMDGPU_PP_SENSOR_SS_APU_SHARE: 1292 ret = renoir_get_smu_metrics_data(smu, 1293 METRICS_SS_APU_SHARE, 1294 (uint32_t *)data); 1295 *size = 4; 1296 break; 1297 case AMDGPU_PP_SENSOR_SS_DGPU_SHARE: 1298 ret = renoir_get_smu_metrics_data(smu, 1299 METRICS_SS_DGPU_SHARE, 1300 (uint32_t *)data); 1301 *size = 4; 1302 break; 1303 default: 1304 ret = -EOPNOTSUPP; 1305 break; 1306 } 1307 1308 return ret; 1309} 1310 1311static bool renoir_is_dpm_running(struct smu_context *smu) 1312{ 1313 struct amdgpu_device *adev = smu->adev; 1314 1315 /* 1316 * Until now, the pmfw hasn't exported the interface of SMU 1317 * feature mask to APU SKU so just force on all the feature 1318 * at early initial stage. 1319 */ 1320 if (adev->in_suspend) 1321 return false; 1322 else 1323 return true; 1324 1325} 1326 1327static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, 1328 void **table) 1329{ 1330 struct smu_table_context *smu_table = &smu->smu_table; 1331 struct gpu_metrics_v2_2 *gpu_metrics = 1332 (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; 1333 SmuMetrics_t metrics; 1334 int ret = 0; 1335 1336 ret = smu_cmn_get_metrics_table(smu, &metrics, true); 1337 if (ret) 1338 return ret; 1339 1340 smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); 1341 1342 gpu_metrics->temperature_gfx = metrics.GfxTemperature; 1343 gpu_metrics->temperature_soc = metrics.SocTemperature; 1344 memcpy(&gpu_metrics->temperature_core[0], 1345 &metrics.CoreTemperature[0], 1346 sizeof(uint16_t) * 8); 1347 gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; 1348 gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; 1349 1350 gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; 1351 gpu_metrics->average_mm_activity = metrics.AverageUvdActivity; 1352 1353 gpu_metrics->average_socket_power = metrics.CurrentSocketPower; 1354 gpu_metrics->average_cpu_power = metrics.Power[0]; 1355 gpu_metrics->average_soc_power = metrics.Power[1]; 1356 memcpy(&gpu_metrics->average_core_power[0], 1357 &metrics.CorePower[0], 1358 sizeof(uint16_t) * 8); 1359 1360 gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; 1361 gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; 1362 gpu_metrics->average_fclk_frequency = metrics.AverageFclkFrequency; 1363 gpu_metrics->average_vclk_frequency = metrics.AverageVclkFrequency; 1364 1365 gpu_metrics->current_gfxclk = metrics.ClockFrequency[CLOCK_GFXCLK]; 1366 gpu_metrics->current_socclk = metrics.ClockFrequency[CLOCK_SOCCLK]; 1367 gpu_metrics->current_uclk = metrics.ClockFrequency[CLOCK_UMCCLK]; 1368 gpu_metrics->current_fclk = metrics.ClockFrequency[CLOCK_FCLK]; 1369 gpu_metrics->current_vclk = metrics.ClockFrequency[CLOCK_VCLK]; 1370 gpu_metrics->current_dclk = metrics.ClockFrequency[CLOCK_DCLK]; 1371 memcpy(&gpu_metrics->current_coreclk[0], 1372 &metrics.CoreFrequency[0], 1373 sizeof(uint16_t) * 8); 1374 gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; 1375 gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; 1376 1377 gpu_metrics->throttle_status = metrics.ThrottlerStatus; 1378 gpu_metrics->indep_throttle_status = 1379 smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus, 1380 renoir_throttler_map); 1381 1382 gpu_metrics->fan_pwm = metrics.FanPwm; 1383 1384 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 1385 1386 *table = (void *)gpu_metrics; 1387 1388 return sizeof(struct gpu_metrics_v2_2); 1389} 1390 1391static int renoir_gfx_state_change_set(struct smu_context *smu, uint32_t state) 1392{ 1393 1394 return 0; 1395} 1396 1397static int renoir_get_enabled_mask(struct smu_context *smu, 1398 uint64_t *feature_mask) 1399{ 1400 if (!feature_mask) 1401 return -EINVAL; 1402 memset(feature_mask, 0xff, sizeof(*feature_mask)); 1403 1404 return 0; 1405} 1406 1407static const struct pptable_funcs renoir_ppt_funcs = { 1408 .set_power_state = NULL, 1409 .print_clk_levels = renoir_print_clk_levels, 1410 .get_current_power_state = renoir_get_current_power_state, 1411 .dpm_set_vcn_enable = renoir_dpm_set_vcn_enable, 1412 .dpm_set_jpeg_enable = renoir_dpm_set_jpeg_enable, 1413 .force_clk_levels = renoir_force_clk_levels, 1414 .set_power_profile_mode = renoir_set_power_profile_mode, 1415 .set_performance_level = renoir_set_performance_level, 1416 .get_dpm_clock_table = renoir_get_dpm_clock_table, 1417 .set_watermarks_table = renoir_set_watermarks_table, 1418 .get_power_profile_mode = renoir_get_power_profile_mode, 1419 .read_sensor = renoir_read_sensor, 1420 .check_fw_status = smu_v12_0_check_fw_status, 1421 .check_fw_version = smu_v12_0_check_fw_version, 1422 .powergate_sdma = smu_v12_0_powergate_sdma, 1423 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 1424 .send_smc_msg = smu_cmn_send_smc_msg, 1425 .set_gfx_cgpg = smu_v12_0_set_gfx_cgpg, 1426 .gfx_off_control = smu_v12_0_gfx_off_control, 1427 .get_gfx_off_status = smu_v12_0_get_gfxoff_status, 1428 .init_smc_tables = renoir_init_smc_tables, 1429 .fini_smc_tables = smu_v12_0_fini_smc_tables, 1430 .set_default_dpm_table = smu_v12_0_set_default_dpm_tables, 1431 .get_enabled_mask = renoir_get_enabled_mask, 1432 .feature_is_enabled = smu_cmn_feature_is_enabled, 1433 .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, 1434 .get_dpm_ultimate_freq = renoir_get_dpm_ultimate_freq, 1435 .mode2_reset = smu_v12_0_mode2_reset, 1436 .set_soft_freq_limited_range = smu_v12_0_set_soft_freq_limited_range, 1437 .set_driver_table_location = smu_v12_0_set_driver_table_location, 1438 .is_dpm_running = renoir_is_dpm_running, 1439 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 1440 .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, 1441 .get_gpu_metrics = renoir_get_gpu_metrics, 1442 .gfx_state_change_set = renoir_gfx_state_change_set, 1443 .set_fine_grain_gfx_freq_parameters = renoir_set_fine_grain_gfx_freq_parameters, 1444 .od_edit_dpm_table = renoir_od_edit_dpm_table, 1445 .get_vbios_bootup_values = smu_v12_0_get_vbios_bootup_values, 1446}; 1447 1448void renoir_set_ppt_funcs(struct smu_context *smu) 1449{ 1450 smu->ppt_funcs = &renoir_ppt_funcs; 1451 smu->message_map = renoir_message_map; 1452 smu->clock_map = renoir_clk_map; 1453 smu->table_map = renoir_table_map; 1454 smu->workload_map = renoir_workload_map; 1455 smu->smc_driver_if_version = SMU12_DRIVER_IF_VERSION; 1456 smu->is_apu = true; 1457}