FILE
smu_v14_0_2_ppt.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
1/* 2 * Copyright 2023 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 <linux/firmware.h> 27#include <linux/pci.h> 28#include <linux/i2c.h> 29#include "amdgpu.h" 30#include "amdgpu_smu.h" 31#include "atomfirmware.h" 32#include "amdgpu_atomfirmware.h" 33#include "amdgpu_atombios.h" 34#include "smu_v14_0.h" 35#include "smu14_driver_if_v14_0.h" 36#include "soc15_common.h" 37#include "atom.h" 38#include "smu_v14_0_2_ppt.h" 39#include "smu_v14_0_2_pptable.h" 40#include "smu_v14_0_2_ppsmc.h" 41#include "mp/mp_14_0_2_offset.h" 42#include "mp/mp_14_0_2_sh_mask.h" 43 44#include "smu_cmn.h" 45#include "amdgpu_ras.h" 46 47/* 48 * DO NOT use these for err/warn/info/debug messages. 49 * Use dev_err, dev_warn, dev_info and dev_dbg instead. 50 * They are more MGPU friendly. 51 */ 52#undef pr_err 53#undef pr_warn 54#undef pr_info 55#undef pr_debug 56 57#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) 58 59#define FEATURE_MASK(feature) (1ULL << feature) 60#define SMC_DPM_FEATURE ( \ 61 FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ 62 FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ 63 FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ 64 FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ 65 FEATURE_MASK(FEATURE_DPM_FCLK_BIT)) 66 67#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000 68#define DEBUGSMC_MSG_Mode1Reset 2 69#define LINK_SPEED_MAX 3 70 71#define PP_OD_FEATURE_GFXCLK_FMIN 0 72#define PP_OD_FEATURE_GFXCLK_FMAX 1 73#define PP_OD_FEATURE_UCLK_FMIN 2 74#define PP_OD_FEATURE_UCLK_FMAX 3 75#define PP_OD_FEATURE_GFX_VF_CURVE 4 76#define PP_OD_FEATURE_FAN_CURVE_TEMP 5 77#define PP_OD_FEATURE_FAN_CURVE_PWM 6 78#define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT 7 79#define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET 8 80#define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE 9 81#define PP_OD_FEATURE_FAN_MINIMUM_PWM 10 82#define PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE 11 83 84static struct cmn2asic_msg_mapping smu_v14_0_2_message_map[SMU_MSG_MAX_COUNT] = { 85 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), 86 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), 87 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), 88 MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0), 89 MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0), 90 MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0), 91 MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0), 92 MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1), 93 MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1), 94 MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1), 95 MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1), 96 MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetRunningSmuFeaturesLow, 1), 97 MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetRunningSmuFeaturesHigh, 1), 98 MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1), 99 MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), 100 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), 101 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), 102 MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), 103 MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), 104 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), 105 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), 106 MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), 107 MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0), 108 MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), 109 MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), 110 MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 1), 111 MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1), 112 MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1), 113 MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0), 114 MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), 115 MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), 116 MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), 117 MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), 118 MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0), 119 MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0), 120 MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0), 121 MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1), 122 MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0), 123 MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), 124 MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), 125 MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), 126 MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0), 127 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0), 128 MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), 129 MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), 130 MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0), 131 MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0), 132 MSG_MAP(DFCstateControl, PPSMC_MSG_SetExternalClientDfCstateAllow, 0), 133 MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), 134 MSG_MAP(SetNumBadMemoryPagesRetired, PPSMC_MSG_SetNumBadMemoryPagesRetired, 0), 135 MSG_MAP(SetBadMemoryPagesRetiredFlagsPerChannel, 136 PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel, 0), 137 MSG_MAP(AllowIHHostInterrupt, PPSMC_MSG_AllowIHHostInterrupt, 0), 138 MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 0), 139}; 140 141static struct cmn2asic_mapping smu_v14_0_2_clk_map[SMU_CLK_COUNT] = { 142 CLK_MAP(GFXCLK, PPCLK_GFXCLK), 143 CLK_MAP(SCLK, PPCLK_GFXCLK), 144 CLK_MAP(SOCCLK, PPCLK_SOCCLK), 145 CLK_MAP(FCLK, PPCLK_FCLK), 146 CLK_MAP(UCLK, PPCLK_UCLK), 147 CLK_MAP(MCLK, PPCLK_UCLK), 148 CLK_MAP(VCLK, PPCLK_VCLK_0), 149 CLK_MAP(DCLK, PPCLK_DCLK_0), 150 CLK_MAP(DCEFCLK, PPCLK_DCFCLK), 151}; 152 153static struct cmn2asic_mapping smu_v14_0_2_feature_mask_map[SMU_FEATURE_COUNT] = { 154 FEA_MAP(FW_DATA_READ), 155 FEA_MAP(DPM_GFXCLK), 156 FEA_MAP(DPM_GFX_POWER_OPTIMIZER), 157 FEA_MAP(DPM_UCLK), 158 FEA_MAP(DPM_FCLK), 159 FEA_MAP(DPM_SOCCLK), 160 FEA_MAP(DPM_LINK), 161 FEA_MAP(DPM_DCN), 162 FEA_MAP(VMEMP_SCALING), 163 FEA_MAP(VDDIO_MEM_SCALING), 164 FEA_MAP(DS_GFXCLK), 165 FEA_MAP(DS_SOCCLK), 166 FEA_MAP(DS_FCLK), 167 FEA_MAP(DS_LCLK), 168 FEA_MAP(DS_DCFCLK), 169 FEA_MAP(DS_UCLK), 170 FEA_MAP(GFX_ULV), 171 FEA_MAP(FW_DSTATE), 172 FEA_MAP(GFXOFF), 173 FEA_MAP(BACO), 174 FEA_MAP(MM_DPM), 175 FEA_MAP(SOC_MPCLK_DS), 176 FEA_MAP(BACO_MPCLK_DS), 177 FEA_MAP(THROTTLERS), 178 FEA_MAP(SMARTSHIFT), 179 FEA_MAP(GTHR), 180 FEA_MAP(ACDC), 181 FEA_MAP(VR0HOT), 182 FEA_MAP(FW_CTF), 183 FEA_MAP(FAN_CONTROL), 184 FEA_MAP(GFX_DCS), 185 FEA_MAP(GFX_READ_MARGIN), 186 FEA_MAP(LED_DISPLAY), 187 FEA_MAP(GFXCLK_SPREAD_SPECTRUM), 188 FEA_MAP(OUT_OF_BAND_MONITOR), 189 FEA_MAP(OPTIMIZED_VMIN), 190 FEA_MAP(GFX_IMU), 191 FEA_MAP(BOOT_TIME_CAL), 192 FEA_MAP(GFX_PCC_DFLL), 193 FEA_MAP(SOC_CG), 194 FEA_MAP(DF_CSTATE), 195 FEA_MAP(GFX_EDC), 196 FEA_MAP(BOOT_POWER_OPT), 197 FEA_MAP(CLOCK_POWER_DOWN_BYPASS), 198 FEA_MAP(DS_VCN), 199 FEA_MAP(BACO_CG), 200 FEA_MAP(MEM_TEMP_READ), 201 FEA_MAP(ATHUB_MMHUB_PG), 202 FEA_MAP(SOC_PCC), 203 FEA_MAP(EDC_PWRBRK), 204 FEA_MAP(SOC_EDC_XVMIN), 205 FEA_MAP(GFX_PSM_DIDT), 206 FEA_MAP(APT_ALL_ENABLE), 207 FEA_MAP(APT_SQ_THROTTLE), 208 FEA_MAP(APT_PF_DCS), 209 FEA_MAP(GFX_EDC_XVMIN), 210 FEA_MAP(GFX_DIDT_XVMIN), 211 FEA_MAP(FAN_ABNORMAL), 212 [SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT}, 213 [SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT}, 214 [SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT}, 215}; 216 217static struct cmn2asic_mapping smu_v14_0_2_table_map[SMU_TABLE_COUNT] = { 218 TAB_MAP(PPTABLE), 219 TAB_MAP(WATERMARKS), 220 TAB_MAP(AVFS_PSM_DEBUG), 221 TAB_MAP(PMSTATUSLOG), 222 TAB_MAP(SMU_METRICS), 223 TAB_MAP(DRIVER_SMU_CONFIG), 224 TAB_MAP(ACTIVITY_MONITOR_COEFF), 225 [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE}, 226 TAB_MAP(I2C_COMMANDS), 227 TAB_MAP(ECCINFO), 228 TAB_MAP(OVERDRIVE), 229}; 230 231static struct cmn2asic_mapping smu_v14_0_2_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { 232 PWR_MAP(AC), 233 PWR_MAP(DC), 234}; 235 236static struct cmn2asic_mapping smu_v14_0_2_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { 237 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), 238 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), 239 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), 240 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), 241 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), 242 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), 243 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), 244 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_WINDOW3D, WORKLOAD_PPLIB_WINDOW_3D_BIT), 245}; 246 247static const uint8_t smu_v14_0_2_throttler_map[] = { 248 [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT), 249 [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT), 250 [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT), 251 [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT), 252 [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT), 253 [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT), 254 [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT), 255 [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT), 256 [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT), 257 [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT), 258 [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT), 259 [THROTTLER_TEMP_VR_MEM0_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT), 260 [THROTTLER_TEMP_VR_MEM1_BIT] = (SMU_THROTTLER_TEMP_VR_MEM1_BIT), 261 [THROTTLER_TEMP_LIQUID0_BIT] = (SMU_THROTTLER_TEMP_LIQUID0_BIT), 262 [THROTTLER_TEMP_LIQUID1_BIT] = (SMU_THROTTLER_TEMP_LIQUID1_BIT), 263 [THROTTLER_GFX_APCC_PLUS_BIT] = (SMU_THROTTLER_APCC_BIT), 264 [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT), 265}; 266 267static int 268smu_v14_0_2_get_allowed_feature_mask(struct smu_context *smu, 269 uint32_t *feature_mask, uint32_t num) 270{ 271 struct amdgpu_device *adev = smu->adev; 272 /*u32 smu_version;*/ 273 274 if (num > 2) 275 return -EINVAL; 276 277 memset(feature_mask, 0xff, sizeof(uint32_t) * num); 278 279 if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) { 280 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT); 281 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT); 282 } 283#if 0 284 if (!(adev->pg_flags & AMD_PG_SUPPORT_ATHUB) || 285 !(adev->pg_flags & AMD_PG_SUPPORT_MMHUB)) 286 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT); 287 288 if (!(adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)) 289 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); 290 291 /* PMFW 78.58 contains a critical fix for gfxoff feature */ 292 smu_cmn_get_smc_version(smu, NULL, &smu_version); 293 if ((smu_version < 0x004e3a00) || 294 !(adev->pm.pp_feature & PP_GFXOFF_MASK)) 295 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFXOFF_BIT); 296 297 if (!(adev->pm.pp_feature & PP_MCLK_DPM_MASK)) { 298 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_UCLK_BIT); 299 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT); 300 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT); 301 } 302 303 if (!(adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)) 304 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_GFXCLK_BIT); 305 306 if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK)) { 307 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_LINK_BIT); 308 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_LCLK_BIT); 309 } 310 311 if (!(adev->pm.pp_feature & PP_ULV_MASK)) 312 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFX_ULV_BIT); 313#endif 314 315 return 0; 316} 317 318static int smu_v14_0_2_check_powerplay_table(struct smu_context *smu) 319{ 320 struct smu_table_context *table_context = &smu->smu_table; 321 struct smu_14_0_2_powerplay_table *powerplay_table = 322 table_context->power_play_table; 323 struct smu_baco_context *smu_baco = &smu->smu_baco; 324 PPTable_t *pptable = smu->smu_table.driver_pptable; 325 const OverDriveLimits_t * const overdrive_upperlimits = 326 &pptable->SkuTable.OverDriveLimitsBasicMax; 327 const OverDriveLimits_t * const overdrive_lowerlimits = 328 &pptable->SkuTable.OverDriveLimitsBasicMin; 329 330 if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_HARDWAREDC) 331 smu->dc_controlled_by_gpio = true; 332 333 if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_BACO) { 334 smu_baco->platform_support = true; 335 336 if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_MACO) 337 smu_baco->maco_support = true; 338 } 339 340 if (!overdrive_lowerlimits->FeatureCtrlMask || 341 !overdrive_upperlimits->FeatureCtrlMask) 342 smu->od_enabled = false; 343 344 table_context->thermal_controller_type = 345 powerplay_table->thermal_controller_type; 346 347 /* 348 * Instead of having its own buffer space and get overdrive_table copied, 349 * smu->od_settings just points to the actual overdrive_table 350 */ 351 smu->od_settings = &powerplay_table->overdrive_table; 352 353 smu->adev->pm.no_fan = 354 !(pptable->PFE_Settings.FeaturesToRun[0] & (1 << FEATURE_FAN_CONTROL_BIT)); 355 356 return 0; 357} 358 359static int smu_v14_0_2_store_powerplay_table(struct smu_context *smu) 360{ 361 struct smu_table_context *table_context = &smu->smu_table; 362 struct smu_14_0_2_powerplay_table *powerplay_table = 363 table_context->power_play_table; 364 365 memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, 366 sizeof(PPTable_t)); 367 368 return 0; 369} 370 371static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu, 372 void **table, 373 uint32_t *size) 374{ 375 struct smu_table_context *smu_table = &smu->smu_table; 376 void *combo_pptable = smu_table->combo_pptable; 377 int ret = 0; 378 379 ret = smu_cmn_get_combo_pptable(smu); 380 if (ret) 381 return ret; 382 383 *table = combo_pptable; 384 *size = sizeof(struct smu_14_0_2_powerplay_table); 385 386 return 0; 387} 388 389static int smu_v14_0_2_setup_pptable(struct smu_context *smu) 390{ 391 struct smu_table_context *smu_table = &smu->smu_table; 392 int ret = 0; 393 394 if (amdgpu_sriov_vf(smu->adev)) 395 return 0; 396 397 ret = smu_v14_0_2_get_pptable_from_pmfw(smu, 398 &smu_table->power_play_table, 399 &smu_table->power_play_table_size); 400 if (ret) 401 return ret; 402 403 ret = smu_v14_0_2_store_powerplay_table(smu); 404 if (ret) 405 return ret; 406 407 ret = smu_v14_0_2_check_powerplay_table(smu); 408 if (ret) 409 return ret; 410 411 return ret; 412} 413 414static int smu_v14_0_2_tables_init(struct smu_context *smu) 415{ 416 struct smu_table_context *smu_table = &smu->smu_table; 417 struct smu_table *tables = smu_table->tables; 418 419 SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), 420 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 421 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), 422 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 423 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t), 424 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 425 SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), 426 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 427 SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), 428 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 429 SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU14_TOOL_SIZE, 430 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 431 SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, 432 sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE, 433 AMDGPU_GEM_DOMAIN_VRAM); 434 SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE, 435 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 436 SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t), 437 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 438 439 smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL); 440 if (!smu_table->metrics_table) 441 goto err0_out; 442 smu_table->metrics_time = 0; 443 444 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3); 445 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 446 if (!smu_table->gpu_metrics_table) 447 goto err1_out; 448 449 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); 450 if (!smu_table->watermarks_table) 451 goto err2_out; 452 453 smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL); 454 if (!smu_table->ecc_table) 455 goto err3_out; 456 457 return 0; 458 459err3_out: 460 kfree(smu_table->watermarks_table); 461err2_out: 462 kfree(smu_table->gpu_metrics_table); 463err1_out: 464 kfree(smu_table->metrics_table); 465err0_out: 466 return -ENOMEM; 467} 468 469static int smu_v14_0_2_allocate_dpm_context(struct smu_context *smu) 470{ 471 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 472 473 smu_dpm->dpm_context = kzalloc(sizeof(struct smu_14_0_dpm_context), 474 GFP_KERNEL); 475 if (!smu_dpm->dpm_context) 476 return -ENOMEM; 477 478 smu_dpm->dpm_context_size = sizeof(struct smu_14_0_dpm_context); 479 480 return 0; 481} 482 483static int smu_v14_0_2_init_smc_tables(struct smu_context *smu) 484{ 485 int ret = 0; 486 487 ret = smu_v14_0_2_tables_init(smu); 488 if (ret) 489 return ret; 490 491 ret = smu_v14_0_2_allocate_dpm_context(smu); 492 if (ret) 493 return ret; 494 495 return smu_v14_0_init_smc_tables(smu); 496} 497 498static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) 499{ 500 struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; 501 struct smu_table_context *table_context = &smu->smu_table; 502 PPTable_t *pptable = table_context->driver_pptable; 503 SkuTable_t *skutable = &pptable->SkuTable; 504 struct smu_14_0_dpm_table *dpm_table; 505 int ret = 0; 506 507 /* socclk dpm table setup */ 508 dpm_table = &dpm_context->dpm_tables.soc_table; 509 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { 510 ret = smu_v14_0_set_single_dpm_table(smu, 511 SMU_SOCCLK, 512 dpm_table); 513 if (ret) 514 return ret; 515 } else { 516 dpm_table->count = 1; 517 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; 518 dpm_table->dpm_levels[0].enabled = true; 519 dpm_table->min = dpm_table->dpm_levels[0].value; 520 dpm_table->max = dpm_table->dpm_levels[0].value; 521 } 522 523 /* gfxclk dpm table setup */ 524 dpm_table = &dpm_context->dpm_tables.gfx_table; 525 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { 526 ret = smu_v14_0_set_single_dpm_table(smu, 527 SMU_GFXCLK, 528 dpm_table); 529 if (ret) 530 return ret; 531 532 /* 533 * Update the reported maximum shader clock to the value 534 * which can be guarded to be achieved on all cards. This 535 * is aligned with Window setting. And considering that value 536 * might be not the peak frequency the card can achieve, it 537 * is normal some real-time clock frequency can overtake this 538 * labelled maximum clock frequency(for example in pp_dpm_sclk 539 * sysfs output). 540 */ 541 if (skutable->DriverReportedClocks.GameClockAc && 542 (dpm_table->dpm_levels[dpm_table->count - 1].value > 543 skutable->DriverReportedClocks.GameClockAc)) { 544 dpm_table->dpm_levels[dpm_table->count - 1].value = 545 skutable->DriverReportedClocks.GameClockAc; 546 dpm_table->max = skutable->DriverReportedClocks.GameClockAc; 547 } 548 } else { 549 dpm_table->count = 1; 550 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; 551 dpm_table->dpm_levels[0].enabled = true; 552 dpm_table->min = dpm_table->dpm_levels[0].value; 553 dpm_table->max = dpm_table->dpm_levels[0].value; 554 } 555 556 /* uclk dpm table setup */ 557 dpm_table = &dpm_context->dpm_tables.uclk_table; 558 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { 559 ret = smu_v14_0_set_single_dpm_table(smu, 560 SMU_UCLK, 561 dpm_table); 562 if (ret) 563 return ret; 564 } else { 565 dpm_table->count = 1; 566 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; 567 dpm_table->dpm_levels[0].enabled = true; 568 dpm_table->min = dpm_table->dpm_levels[0].value; 569 dpm_table->max = dpm_table->dpm_levels[0].value; 570 } 571 572 /* fclk dpm table setup */ 573 dpm_table = &dpm_context->dpm_tables.fclk_table; 574 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { 575 ret = smu_v14_0_set_single_dpm_table(smu, 576 SMU_FCLK, 577 dpm_table); 578 if (ret) 579 return ret; 580 } else { 581 dpm_table->count = 1; 582 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; 583 dpm_table->dpm_levels[0].enabled = true; 584 dpm_table->min = dpm_table->dpm_levels[0].value; 585 dpm_table->max = dpm_table->dpm_levels[0].value; 586 } 587 588 /* vclk dpm table setup */ 589 dpm_table = &dpm_context->dpm_tables.vclk_table; 590 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) { 591 ret = smu_v14_0_set_single_dpm_table(smu, 592 SMU_VCLK, 593 dpm_table); 594 if (ret) 595 return ret; 596 } else { 597 dpm_table->count = 1; 598 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; 599 dpm_table->dpm_levels[0].enabled = true; 600 dpm_table->min = dpm_table->dpm_levels[0].value; 601 dpm_table->max = dpm_table->dpm_levels[0].value; 602 } 603 604 /* dclk dpm table setup */ 605 dpm_table = &dpm_context->dpm_tables.dclk_table; 606 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) { 607 ret = smu_v14_0_set_single_dpm_table(smu, 608 SMU_DCLK, 609 dpm_table); 610 if (ret) 611 return ret; 612 } else { 613 dpm_table->count = 1; 614 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; 615 dpm_table->dpm_levels[0].enabled = true; 616 dpm_table->min = dpm_table->dpm_levels[0].value; 617 dpm_table->max = dpm_table->dpm_levels[0].value; 618 } 619 620 /* dcefclk dpm table setup */ 621 dpm_table = &dpm_context->dpm_tables.dcef_table; 622 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCN_BIT)) { 623 ret = smu_v14_0_set_single_dpm_table(smu, 624 SMU_DCEFCLK, 625 dpm_table); 626 if (ret) 627 return ret; 628 } else { 629 dpm_table->count = 1; 630 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; 631 dpm_table->dpm_levels[0].enabled = true; 632 dpm_table->min = dpm_table->dpm_levels[0].value; 633 dpm_table->max = dpm_table->dpm_levels[0].value; 634 } 635 636 return 0; 637} 638 639static bool smu_v14_0_2_is_dpm_running(struct smu_context *smu) 640{ 641 int ret = 0; 642 uint64_t feature_enabled; 643 644 ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); 645 if (ret) 646 return false; 647 648 return !!(feature_enabled & SMC_DPM_FEATURE); 649} 650 651static uint32_t smu_v14_0_2_get_throttler_status(SmuMetrics_t *metrics) 652{ 653 uint32_t throttler_status = 0; 654 int i; 655 656 for (i = 0; i < THROTTLER_COUNT; i++) 657 throttler_status |= 658 (metrics->ThrottlingPercentage[i] ? 1U << i : 0); 659 660 return throttler_status; 661} 662 663#define SMU_14_0_2_BUSY_THRESHOLD 5 664static int smu_v14_0_2_get_smu_metrics_data(struct smu_context *smu, 665 MetricsMember_t member, 666 uint32_t *value) 667{ 668 struct smu_table_context *smu_table = &smu->smu_table; 669 SmuMetrics_t *metrics = 670 &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics); 671 int ret = 0; 672 673 ret = smu_cmn_get_metrics_table(smu, 674 NULL, 675 false); 676 if (ret) 677 return ret; 678 679 switch (member) { 680 case METRICS_CURR_GFXCLK: 681 *value = metrics->CurrClock[PPCLK_GFXCLK]; 682 break; 683 case METRICS_CURR_SOCCLK: 684 *value = metrics->CurrClock[PPCLK_SOCCLK]; 685 break; 686 case METRICS_CURR_UCLK: 687 *value = metrics->CurrClock[PPCLK_UCLK]; 688 break; 689 case METRICS_CURR_VCLK: 690 *value = metrics->CurrClock[PPCLK_VCLK_0]; 691 break; 692 case METRICS_CURR_DCLK: 693 *value = metrics->CurrClock[PPCLK_DCLK_0]; 694 break; 695 case METRICS_CURR_FCLK: 696 *value = metrics->CurrClock[PPCLK_FCLK]; 697 break; 698 case METRICS_CURR_DCEFCLK: 699 *value = metrics->CurrClock[PPCLK_DCFCLK]; 700 break; 701 case METRICS_AVERAGE_GFXCLK: 702 if (metrics->AverageGfxActivity <= SMU_14_0_2_BUSY_THRESHOLD) 703 *value = metrics->AverageGfxclkFrequencyPostDs; 704 else 705 *value = metrics->AverageGfxclkFrequencyPreDs; 706 break; 707 case METRICS_AVERAGE_FCLK: 708 if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD) 709 *value = metrics->AverageFclkFrequencyPostDs; 710 else 711 *value = metrics->AverageFclkFrequencyPreDs; 712 break; 713 case METRICS_AVERAGE_UCLK: 714 if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD) 715 *value = metrics->AverageMemclkFrequencyPostDs; 716 else 717 *value = metrics->AverageMemclkFrequencyPreDs; 718 break; 719 case METRICS_AVERAGE_VCLK: 720 *value = metrics->AverageVclk0Frequency; 721 break; 722 case METRICS_AVERAGE_DCLK: 723 *value = metrics->AverageDclk0Frequency; 724 break; 725 case METRICS_AVERAGE_VCLK1: 726 *value = metrics->AverageVclk1Frequency; 727 break; 728 case METRICS_AVERAGE_DCLK1: 729 *value = metrics->AverageDclk1Frequency; 730 break; 731 case METRICS_AVERAGE_GFXACTIVITY: 732 *value = metrics->AverageGfxActivity; 733 break; 734 case METRICS_AVERAGE_MEMACTIVITY: 735 *value = metrics->AverageUclkActivity; 736 break; 737 case METRICS_AVERAGE_VCNACTIVITY: 738 *value = max(metrics->AverageVcn0ActivityPercentage, 739 metrics->Vcn1ActivityPercentage); 740 break; 741 case METRICS_AVERAGE_SOCKETPOWER: 742 *value = metrics->AverageSocketPower << 8; 743 break; 744 case METRICS_TEMPERATURE_EDGE: 745 *value = metrics->AvgTemperature[TEMP_EDGE] * 746 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 747 break; 748 case METRICS_TEMPERATURE_HOTSPOT: 749 *value = metrics->AvgTemperature[TEMP_HOTSPOT] * 750 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 751 break; 752 case METRICS_TEMPERATURE_MEM: 753 *value = metrics->AvgTemperature[TEMP_MEM] * 754 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 755 break; 756 case METRICS_TEMPERATURE_VRGFX: 757 *value = metrics->AvgTemperature[TEMP_VR_GFX] * 758 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 759 break; 760 case METRICS_TEMPERATURE_VRSOC: 761 *value = metrics->AvgTemperature[TEMP_VR_SOC] * 762 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 763 break; 764 case METRICS_THROTTLER_STATUS: 765 *value = smu_v14_0_2_get_throttler_status(metrics); 766 break; 767 case METRICS_CURR_FANSPEED: 768 *value = metrics->AvgFanRpm; 769 break; 770 case METRICS_CURR_FANPWM: 771 *value = metrics->AvgFanPwm; 772 break; 773 case METRICS_VOLTAGE_VDDGFX: 774 *value = metrics->AvgVoltage[SVI_PLANE_VDD_GFX]; 775 break; 776 case METRICS_PCIE_RATE: 777 *value = metrics->PcieRate; 778 break; 779 case METRICS_PCIE_WIDTH: 780 *value = metrics->PcieWidth; 781 break; 782 default: 783 *value = UINT_MAX; 784 break; 785 } 786 787 return ret; 788} 789 790static int smu_v14_0_2_get_dpm_ultimate_freq(struct smu_context *smu, 791 enum smu_clk_type clk_type, 792 uint32_t *min, 793 uint32_t *max) 794{ 795 struct smu_14_0_dpm_context *dpm_context = 796 smu->smu_dpm.dpm_context; 797 struct smu_14_0_dpm_table *dpm_table; 798 799 switch (clk_type) { 800 case SMU_MCLK: 801 case SMU_UCLK: 802 /* uclk dpm table */ 803 dpm_table = &dpm_context->dpm_tables.uclk_table; 804 break; 805 case SMU_GFXCLK: 806 case SMU_SCLK: 807 /* gfxclk dpm table */ 808 dpm_table = &dpm_context->dpm_tables.gfx_table; 809 break; 810 case SMU_SOCCLK: 811 /* socclk dpm table */ 812 dpm_table = &dpm_context->dpm_tables.soc_table; 813 break; 814 case SMU_FCLK: 815 /* fclk dpm table */ 816 dpm_table = &dpm_context->dpm_tables.fclk_table; 817 break; 818 case SMU_VCLK: 819 case SMU_VCLK1: 820 /* vclk dpm table */ 821 dpm_table = &dpm_context->dpm_tables.vclk_table; 822 break; 823 case SMU_DCLK: 824 case SMU_DCLK1: 825 /* dclk dpm table */ 826 dpm_table = &dpm_context->dpm_tables.dclk_table; 827 break; 828 default: 829 dev_err(smu->adev->dev, "Unsupported clock type!\n"); 830 return -EINVAL; 831 } 832 833 if (min) 834 *min = dpm_table->min; 835 if (max) 836 *max = dpm_table->max; 837 838 return 0; 839} 840 841static int smu_v14_0_2_read_sensor(struct smu_context *smu, 842 enum amd_pp_sensors sensor, 843 void *data, 844 uint32_t *size) 845{ 846 struct smu_table_context *table_context = &smu->smu_table; 847 PPTable_t *smc_pptable = table_context->driver_pptable; 848 int ret = 0; 849 850 switch (sensor) { 851 case AMDGPU_PP_SENSOR_MAX_FAN_RPM: 852 *(uint16_t *)data = smc_pptable->CustomSkuTable.FanMaximumRpm; 853 *size = 4; 854 break; 855 case AMDGPU_PP_SENSOR_MEM_LOAD: 856 ret = smu_v14_0_2_get_smu_metrics_data(smu, 857 METRICS_AVERAGE_MEMACTIVITY, 858 (uint32_t *)data); 859 *size = 4; 860 break; 861 case AMDGPU_PP_SENSOR_GPU_LOAD: 862 ret = smu_v14_0_2_get_smu_metrics_data(smu, 863 METRICS_AVERAGE_GFXACTIVITY, 864 (uint32_t *)data); 865 *size = 4; 866 break; 867 case AMDGPU_PP_SENSOR_VCN_LOAD: 868 ret = smu_v14_0_2_get_smu_metrics_data(smu, 869 METRICS_AVERAGE_VCNACTIVITY, 870 (uint32_t *)data); 871 *size = 4; 872 break; 873 case AMDGPU_PP_SENSOR_GPU_AVG_POWER: 874 ret = smu_v14_0_2_get_smu_metrics_data(smu, 875 METRICS_AVERAGE_SOCKETPOWER, 876 (uint32_t *)data); 877 *size = 4; 878 break; 879 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 880 ret = smu_v14_0_2_get_smu_metrics_data(smu, 881 METRICS_TEMPERATURE_HOTSPOT, 882 (uint32_t *)data); 883 *size = 4; 884 break; 885 case AMDGPU_PP_SENSOR_EDGE_TEMP: 886 ret = smu_v14_0_2_get_smu_metrics_data(smu, 887 METRICS_TEMPERATURE_EDGE, 888 (uint32_t *)data); 889 *size = 4; 890 break; 891 case AMDGPU_PP_SENSOR_MEM_TEMP: 892 ret = smu_v14_0_2_get_smu_metrics_data(smu, 893 METRICS_TEMPERATURE_MEM, 894 (uint32_t *)data); 895 *size = 4; 896 break; 897 case AMDGPU_PP_SENSOR_GFX_MCLK: 898 ret = smu_v14_0_2_get_smu_metrics_data(smu, 899 METRICS_CURR_UCLK, 900 (uint32_t *)data); 901 *(uint32_t *)data *= 100; 902 *size = 4; 903 break; 904 case AMDGPU_PP_SENSOR_GFX_SCLK: 905 ret = smu_v14_0_2_get_smu_metrics_data(smu, 906 METRICS_AVERAGE_GFXCLK, 907 (uint32_t *)data); 908 *(uint32_t *)data *= 100; 909 *size = 4; 910 break; 911 case AMDGPU_PP_SENSOR_VDDGFX: 912 ret = smu_v14_0_2_get_smu_metrics_data(smu, 913 METRICS_VOLTAGE_VDDGFX, 914 (uint32_t *)data); 915 *size = 4; 916 break; 917 default: 918 ret = -EOPNOTSUPP; 919 break; 920 } 921 922 return ret; 923} 924 925static int smu_v14_0_2_get_current_clk_freq_by_table(struct smu_context *smu, 926 enum smu_clk_type clk_type, 927 uint32_t *value) 928{ 929 MetricsMember_t member_type; 930 int clk_id = 0; 931 932 clk_id = smu_cmn_to_asic_specific_index(smu, 933 CMN2ASIC_MAPPING_CLK, 934 clk_type); 935 if (clk_id < 0) 936 return -EINVAL; 937 938 switch (clk_id) { 939 case PPCLK_GFXCLK: 940 member_type = METRICS_AVERAGE_GFXCLK; 941 break; 942 case PPCLK_UCLK: 943 member_type = METRICS_CURR_UCLK; 944 break; 945 case PPCLK_FCLK: 946 member_type = METRICS_CURR_FCLK; 947 break; 948 case PPCLK_SOCCLK: 949 member_type = METRICS_CURR_SOCCLK; 950 break; 951 case PPCLK_VCLK_0: 952 member_type = METRICS_AVERAGE_VCLK; 953 break; 954 case PPCLK_DCLK_0: 955 member_type = METRICS_AVERAGE_DCLK; 956 break; 957 case PPCLK_DCFCLK: 958 member_type = METRICS_CURR_DCEFCLK; 959 break; 960 default: 961 return -EINVAL; 962 } 963 964 return smu_v14_0_2_get_smu_metrics_data(smu, 965 member_type, 966 value); 967} 968 969static bool smu_v14_0_2_is_od_feature_supported(struct smu_context *smu, 970 int od_feature_bit) 971{ 972 PPTable_t *pptable = smu->smu_table.driver_pptable; 973 const OverDriveLimits_t * const overdrive_upperlimits = 974 &pptable->SkuTable.OverDriveLimitsBasicMax; 975 976 return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit); 977} 978 979static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu, 980 int od_feature_bit, 981 int32_t *min, 982 int32_t *max) 983{ 984 PPTable_t *pptable = smu->smu_table.driver_pptable; 985 const OverDriveLimits_t * const overdrive_upperlimits = 986 &pptable->SkuTable.OverDriveLimitsBasicMax; 987 const OverDriveLimits_t * const overdrive_lowerlimits = 988 &pptable->SkuTable.OverDriveLimitsBasicMin; 989 int32_t od_min_setting, od_max_setting; 990 991 switch (od_feature_bit) { 992 case PP_OD_FEATURE_GFXCLK_FMIN: 993 case PP_OD_FEATURE_GFXCLK_FMAX: 994 od_min_setting = overdrive_lowerlimits->GfxclkFoffset; 995 od_max_setting = overdrive_upperlimits->GfxclkFoffset; 996 break; 997 case PP_OD_FEATURE_UCLK_FMIN: 998 od_min_setting = overdrive_lowerlimits->UclkFmin; 999 od_max_setting = overdrive_upperlimits->UclkFmin; 1000 break; 1001 case PP_OD_FEATURE_UCLK_FMAX: 1002 od_min_setting = overdrive_lowerlimits->UclkFmax; 1003 od_max_setting = overdrive_upperlimits->UclkFmax; 1004 break; 1005 case PP_OD_FEATURE_GFX_VF_CURVE: 1006 od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary[0]; 1007 od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary[0]; 1008 break; 1009 case PP_OD_FEATURE_FAN_CURVE_TEMP: 1010 od_min_setting = overdrive_lowerlimits->FanLinearTempPoints[0]; 1011 od_max_setting = overdrive_upperlimits->FanLinearTempPoints[0]; 1012 break; 1013 case PP_OD_FEATURE_FAN_CURVE_PWM: 1014 od_min_setting = overdrive_lowerlimits->FanLinearPwmPoints[0]; 1015 od_max_setting = overdrive_upperlimits->FanLinearPwmPoints[0]; 1016 break; 1017 case PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT: 1018 od_min_setting = overdrive_lowerlimits->AcousticLimitRpmThreshold; 1019 od_max_setting = overdrive_upperlimits->AcousticLimitRpmThreshold; 1020 break; 1021 case PP_OD_FEATURE_FAN_ACOUSTIC_TARGET: 1022 od_min_setting = overdrive_lowerlimits->AcousticTargetRpmThreshold; 1023 od_max_setting = overdrive_upperlimits->AcousticTargetRpmThreshold; 1024 break; 1025 case PP_OD_FEATURE_FAN_TARGET_TEMPERATURE: 1026 od_min_setting = overdrive_lowerlimits->FanTargetTemperature; 1027 od_max_setting = overdrive_upperlimits->FanTargetTemperature; 1028 break; 1029 case PP_OD_FEATURE_FAN_MINIMUM_PWM: 1030 od_min_setting = overdrive_lowerlimits->FanMinimumPwm; 1031 od_max_setting = overdrive_upperlimits->FanMinimumPwm; 1032 break; 1033 case PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE: 1034 od_min_setting = overdrive_lowerlimits->FanZeroRpmEnable; 1035 od_max_setting = overdrive_upperlimits->FanZeroRpmEnable; 1036 break; 1037 default: 1038 od_min_setting = od_max_setting = INT_MAX; 1039 break; 1040 } 1041 1042 if (min) 1043 *min = od_min_setting; 1044 if (max) 1045 *max = od_max_setting; 1046} 1047 1048static int smu_v14_0_2_print_clk_levels(struct smu_context *smu, 1049 enum smu_clk_type clk_type, 1050 char *buf) 1051{ 1052 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 1053 struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context; 1054 OverDriveTableExternal_t *od_table = 1055 (OverDriveTableExternal_t *)smu->smu_table.overdrive_table; 1056 struct smu_14_0_dpm_table *single_dpm_table; 1057 struct smu_14_0_pcie_table *pcie_table; 1058 uint32_t gen_speed, lane_width; 1059 int i, curr_freq, size = 0, start_offset = 0; 1060 int32_t min_value, max_value; 1061 int ret = 0; 1062 1063 smu_cmn_get_sysfs_buf(&buf, &size); 1064 start_offset = size; 1065 1066 if (amdgpu_ras_intr_triggered()) { 1067 size += sysfs_emit_at(buf, size, "unavailable\n"); 1068 return size - start_offset; 1069 } 1070 1071 switch (clk_type) { 1072 case SMU_SCLK: 1073 single_dpm_table = &(dpm_context->dpm_tables.gfx_table); 1074 break; 1075 case SMU_MCLK: 1076 single_dpm_table = &(dpm_context->dpm_tables.uclk_table); 1077 break; 1078 case SMU_SOCCLK: 1079 single_dpm_table = &(dpm_context->dpm_tables.soc_table); 1080 break; 1081 case SMU_FCLK: 1082 single_dpm_table = &(dpm_context->dpm_tables.fclk_table); 1083 break; 1084 case SMU_VCLK: 1085 case SMU_VCLK1: 1086 single_dpm_table = &(dpm_context->dpm_tables.vclk_table); 1087 break; 1088 case SMU_DCLK: 1089 case SMU_DCLK1: 1090 single_dpm_table = &(dpm_context->dpm_tables.dclk_table); 1091 break; 1092 case SMU_DCEFCLK: 1093 single_dpm_table = &(dpm_context->dpm_tables.dcef_table); 1094 break; 1095 default: 1096 break; 1097 } 1098 1099 switch (clk_type) { 1100 case SMU_SCLK: 1101 case SMU_MCLK: 1102 case SMU_SOCCLK: 1103 case SMU_FCLK: 1104 case SMU_VCLK: 1105 case SMU_VCLK1: 1106 case SMU_DCLK: 1107 case SMU_DCLK1: 1108 case SMU_DCEFCLK: 1109 ret = smu_v14_0_2_get_current_clk_freq_by_table(smu, clk_type, &curr_freq); 1110 if (ret) { 1111 dev_err(smu->adev->dev, "Failed to get current clock freq!"); 1112 return ret; 1113 } 1114 1115 if (single_dpm_table->is_fine_grained) { 1116 /* 1117 * For fine grained dpms, there are only two dpm levels: 1118 * - level 0 -> min clock freq 1119 * - level 1 -> max clock freq 1120 * And the current clock frequency can be any value between them. 1121 * So, if the current clock frequency is not at level 0 or level 1, 1122 * we will fake it as three dpm levels: 1123 * - level 0 -> min clock freq 1124 * - level 1 -> current actual clock freq 1125 * - level 2 -> max clock freq 1126 */ 1127 if ((single_dpm_table->dpm_levels[0].value != curr_freq) && 1128 (single_dpm_table->dpm_levels[1].value != curr_freq)) { 1129 size += sysfs_emit_at(buf, size, "0: %uMhz\n", 1130 single_dpm_table->dpm_levels[0].value); 1131 size += sysfs_emit_at(buf, size, "1: %uMhz *\n", 1132 curr_freq); 1133 size += sysfs_emit_at(buf, size, "2: %uMhz\n", 1134 single_dpm_table->dpm_levels[1].value); 1135 } else { 1136 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", 1137 single_dpm_table->dpm_levels[0].value, 1138 single_dpm_table->dpm_levels[0].value == curr_freq ? "*" : ""); 1139 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", 1140 single_dpm_table->dpm_levels[1].value, 1141 single_dpm_table->dpm_levels[1].value == curr_freq ? "*" : ""); 1142 } 1143 } else { 1144 for (i = 0; i < single_dpm_table->count; i++) 1145 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", 1146 i, single_dpm_table->dpm_levels[i].value, 1147 single_dpm_table->dpm_levels[i].value == curr_freq ? "*" : ""); 1148 } 1149 break; 1150 case SMU_PCIE: 1151 ret = smu_v14_0_2_get_smu_metrics_data(smu, 1152 METRICS_PCIE_RATE, 1153 &gen_speed); 1154 if (ret) 1155 return ret; 1156 1157 ret = smu_v14_0_2_get_smu_metrics_data(smu, 1158 METRICS_PCIE_WIDTH, 1159 &lane_width); 1160 if (ret) 1161 return ret; 1162 1163 pcie_table = &(dpm_context->dpm_tables.pcie_table); 1164 for (i = 0; i < pcie_table->num_of_link_levels; i++) 1165 size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i, 1166 (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," : 1167 (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," : 1168 (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," : 1169 (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : 1170 (pcie_table->pcie_gen[i] == 4) ? "32.0GT/s," : "", 1171 (pcie_table->pcie_lane[i] == 1) ? "x1" : 1172 (pcie_table->pcie_lane[i] == 2) ? "x2" : 1173 (pcie_table->pcie_lane[i] == 3) ? "x4" : 1174 (pcie_table->pcie_lane[i] == 4) ? "x8" : 1175 (pcie_table->pcie_lane[i] == 5) ? "x12" : 1176 (pcie_table->pcie_lane[i] == 6) ? "x16" : 1177 (pcie_table->pcie_lane[i] == 7) ? "x32" : "", 1178 pcie_table->clk_freq[i], 1179 (gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) && 1180 (lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ? 1181 "*" : ""); 1182 break; 1183 1184 case SMU_OD_SCLK: 1185 if (!smu_v14_0_2_is_od_feature_supported(smu, 1186 PP_OD_FEATURE_GFXCLK_BIT)) 1187 break; 1188 1189 size += sysfs_emit_at(buf, size, "OD_SCLK_OFFSET:\n"); 1190 size += sysfs_emit_at(buf, size, "%dMhz\n", 1191 od_table->OverDriveTable.GfxclkFoffset); 1192 break; 1193 1194 case SMU_OD_MCLK: 1195 if (!smu_v14_0_2_is_od_feature_supported(smu, 1196 PP_OD_FEATURE_UCLK_BIT)) 1197 break; 1198 1199 size += sysfs_emit_at(buf, size, "OD_MCLK:\n"); 1200 size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMHz\n", 1201 od_table->OverDriveTable.UclkFmin, 1202 od_table->OverDriveTable.UclkFmax); 1203 break; 1204 1205 case SMU_OD_VDDGFX_OFFSET: 1206 if (!smu_v14_0_2_is_od_feature_supported(smu, 1207 PP_OD_FEATURE_GFX_VF_CURVE_BIT)) 1208 break; 1209 1210 size += sysfs_emit_at(buf, size, "OD_VDDGFX_OFFSET:\n"); 1211 size += sysfs_emit_at(buf, size, "%dmV\n", 1212 od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[0]); 1213 break; 1214 1215 case SMU_OD_FAN_CURVE: 1216 if (!smu_v14_0_2_is_od_feature_supported(smu, 1217 PP_OD_FEATURE_FAN_CURVE_BIT)) 1218 break; 1219 1220 size += sysfs_emit_at(buf, size, "OD_FAN_CURVE:\n"); 1221 for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) 1222 size += sysfs_emit_at(buf, size, "%d: %dC %d%%\n", 1223 i, 1224 (int)od_table->OverDriveTable.FanLinearTempPoints[i], 1225 (int)od_table->OverDriveTable.FanLinearPwmPoints[i]); 1226 1227 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1228 smu_v14_0_2_get_od_setting_limits(smu, 1229 PP_OD_FEATURE_FAN_CURVE_TEMP, 1230 &min_value, 1231 &max_value); 1232 size += sysfs_emit_at(buf, size, "FAN_CURVE(hotspot temp): %uC %uC\n", 1233 min_value, max_value); 1234 1235 smu_v14_0_2_get_od_setting_limits(smu, 1236 PP_OD_FEATURE_FAN_CURVE_PWM, 1237 &min_value, 1238 &max_value); 1239 size += sysfs_emit_at(buf, size, "FAN_CURVE(fan speed): %u%% %u%%\n", 1240 min_value, max_value); 1241 1242 break; 1243 1244 case SMU_OD_ACOUSTIC_LIMIT: 1245 if (!smu_v14_0_2_is_od_feature_supported(smu, 1246 PP_OD_FEATURE_FAN_CURVE_BIT)) 1247 break; 1248 1249 size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_LIMIT:\n"); 1250 size += sysfs_emit_at(buf, size, "%d\n", 1251 (int)od_table->OverDriveTable.AcousticLimitRpmThreshold); 1252 1253 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1254 smu_v14_0_2_get_od_setting_limits(smu, 1255 PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT, 1256 &min_value, 1257 &max_value); 1258 size += sysfs_emit_at(buf, size, "ACOUSTIC_LIMIT: %u %u\n", 1259 min_value, max_value); 1260 break; 1261 1262 case SMU_OD_ACOUSTIC_TARGET: 1263 if (!smu_v14_0_2_is_od_feature_supported(smu, 1264 PP_OD_FEATURE_FAN_CURVE_BIT)) 1265 break; 1266 1267 size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_TARGET:\n"); 1268 size += sysfs_emit_at(buf, size, "%d\n", 1269 (int)od_table->OverDriveTable.AcousticTargetRpmThreshold); 1270 1271 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1272 smu_v14_0_2_get_od_setting_limits(smu, 1273 PP_OD_FEATURE_FAN_ACOUSTIC_TARGET, 1274 &min_value, 1275 &max_value); 1276 size += sysfs_emit_at(buf, size, "ACOUSTIC_TARGET: %u %u\n", 1277 min_value, max_value); 1278 break; 1279 1280 case SMU_OD_FAN_TARGET_TEMPERATURE: 1281 if (!smu_v14_0_2_is_od_feature_supported(smu, 1282 PP_OD_FEATURE_FAN_CURVE_BIT)) 1283 break; 1284 1285 size += sysfs_emit_at(buf, size, "FAN_TARGET_TEMPERATURE:\n"); 1286 size += sysfs_emit_at(buf, size, "%d\n", 1287 (int)od_table->OverDriveTable.FanTargetTemperature); 1288 1289 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1290 smu_v14_0_2_get_od_setting_limits(smu, 1291 PP_OD_FEATURE_FAN_TARGET_TEMPERATURE, 1292 &min_value, 1293 &max_value); 1294 size += sysfs_emit_at(buf, size, "TARGET_TEMPERATURE: %u %u\n", 1295 min_value, max_value); 1296 break; 1297 1298 case SMU_OD_FAN_MINIMUM_PWM: 1299 if (!smu_v14_0_2_is_od_feature_supported(smu, 1300 PP_OD_FEATURE_FAN_CURVE_BIT)) 1301 break; 1302 1303 size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n"); 1304 size += sysfs_emit_at(buf, size, "%d\n", 1305 (int)od_table->OverDriveTable.FanMinimumPwm); 1306 1307 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1308 smu_v14_0_2_get_od_setting_limits(smu, 1309 PP_OD_FEATURE_FAN_MINIMUM_PWM, 1310 &min_value, 1311 &max_value); 1312 size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %u %u\n", 1313 min_value, max_value); 1314 break; 1315 1316 case SMU_OD_FAN_ZERO_RPM_ENABLE: 1317 if (!smu_v14_0_2_is_od_feature_supported(smu, 1318 PP_OD_FEATURE_ZERO_FAN_BIT)) 1319 break; 1320 1321 size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_ENABLE:\n"); 1322 size += sysfs_emit_at(buf, size, "%d\n", 1323 (int)od_table->OverDriveTable.FanZeroRpmEnable); 1324 1325 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1326 smu_v14_0_2_get_od_setting_limits(smu, 1327 PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE, 1328 &min_value, 1329 &max_value); 1330 size += sysfs_emit_at(buf, size, "ZERO_RPM_ENABLE: %u %u\n", 1331 min_value, max_value); 1332 break; 1333 1334 case SMU_OD_RANGE: 1335 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) && 1336 !smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) && 1337 !smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) 1338 break; 1339 1340 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1341 1342 if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) { 1343 smu_v14_0_2_get_od_setting_limits(smu, 1344 PP_OD_FEATURE_GFXCLK_FMAX, 1345 &min_value, 1346 &max_value); 1347 size += sysfs_emit_at(buf, size, "SCLK_OFFSET: %7dMhz %10uMhz\n", 1348 min_value, max_value); 1349 } 1350 1351 if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) { 1352 smu_v14_0_2_get_od_setting_limits(smu, 1353 PP_OD_FEATURE_UCLK_FMIN, 1354 &min_value, 1355 NULL); 1356 smu_v14_0_2_get_od_setting_limits(smu, 1357 PP_OD_FEATURE_UCLK_FMAX, 1358 NULL, 1359 &max_value); 1360 size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n", 1361 min_value, max_value); 1362 } 1363 1364 if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) { 1365 smu_v14_0_2_get_od_setting_limits(smu, 1366 PP_OD_FEATURE_GFX_VF_CURVE, 1367 &min_value, 1368 &max_value); 1369 size += sysfs_emit_at(buf, size, "VDDGFX_OFFSET: %7dmv %10dmv\n", 1370 min_value, max_value); 1371 } 1372 break; 1373 1374 default: 1375 break; 1376 } 1377 1378 return size - start_offset; 1379} 1380 1381static int smu_v14_0_2_force_clk_levels(struct smu_context *smu, 1382 enum smu_clk_type clk_type, 1383 uint32_t mask) 1384{ 1385 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 1386 struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context; 1387 struct smu_14_0_dpm_table *single_dpm_table; 1388 uint32_t soft_min_level, soft_max_level; 1389 uint32_t min_freq, max_freq; 1390 int ret = 0; 1391 1392 soft_min_level = mask ? (ffs(mask) - 1) : 0; 1393 soft_max_level = mask ? (fls(mask) - 1) : 0; 1394 1395 switch (clk_type) { 1396 case SMU_GFXCLK: 1397 case SMU_SCLK: 1398 single_dpm_table = &(dpm_context->dpm_tables.gfx_table); 1399 break; 1400 case SMU_MCLK: 1401 case SMU_UCLK: 1402 single_dpm_table = &(dpm_context->dpm_tables.uclk_table); 1403 break; 1404 case SMU_SOCCLK: 1405 single_dpm_table = &(dpm_context->dpm_tables.soc_table); 1406 break; 1407 case SMU_FCLK: 1408 single_dpm_table = &(dpm_context->dpm_tables.fclk_table); 1409 break; 1410 case SMU_VCLK: 1411 case SMU_VCLK1: 1412 single_dpm_table = &(dpm_context->dpm_tables.vclk_table); 1413 break; 1414 case SMU_DCLK: 1415 case SMU_DCLK1: 1416 single_dpm_table = &(dpm_context->dpm_tables.dclk_table); 1417 break; 1418 default: 1419 break; 1420 } 1421 1422 switch (clk_type) { 1423 case SMU_GFXCLK: 1424 case SMU_SCLK: 1425 case SMU_MCLK: 1426 case SMU_UCLK: 1427 case SMU_SOCCLK: 1428 case SMU_FCLK: 1429 case SMU_VCLK: 1430 case SMU_VCLK1: 1431 case SMU_DCLK: 1432 case SMU_DCLK1: 1433 if (single_dpm_table->is_fine_grained) { 1434 /* There is only 2 levels for fine grained DPM */ 1435 soft_max_level = (soft_max_level >= 1 ? 1 : 0); 1436 soft_min_level = (soft_min_level >= 1 ? 1 : 0); 1437 } else { 1438 if ((soft_max_level >= single_dpm_table->count) || 1439 (soft_min_level >= single_dpm_table->count)) 1440 return -EINVAL; 1441 } 1442 1443 min_freq = single_dpm_table->dpm_levels[soft_min_level].value; 1444 max_freq = single_dpm_table->dpm_levels[soft_max_level].value; 1445 1446 ret = smu_v14_0_set_soft_freq_limited_range(smu, 1447 clk_type, 1448 min_freq, 1449 max_freq, 1450 false); 1451 break; 1452 case SMU_DCEFCLK: 1453 case SMU_PCIE: 1454 default: 1455 break; 1456 } 1457 1458 return ret; 1459} 1460 1461static int smu_v14_0_2_update_pcie_parameters(struct smu_context *smu, 1462 uint8_t pcie_gen_cap, 1463 uint8_t pcie_width_cap) 1464{ 1465 struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; 1466 struct smu_14_0_pcie_table *pcie_table = 1467 &dpm_context->dpm_tables.pcie_table; 1468 int num_of_levels; 1469 uint32_t smu_pcie_arg; 1470 uint32_t link_level; 1471 struct smu_table_context *table_context = &smu->smu_table; 1472 PPTable_t *pptable = table_context->driver_pptable; 1473 SkuTable_t *skutable = &pptable->SkuTable; 1474 int ret = 0; 1475 int i; 1476 1477 pcie_table->num_of_link_levels = 0; 1478 for (link_level = 0; link_level < NUM_LINK_LEVELS; link_level++) { 1479 if (!skutable->PcieGenSpeed[link_level] && 1480 !skutable->PcieLaneCount[link_level] && 1481 !skutable->LclkFreq[link_level]) 1482 continue; 1483 1484 pcie_table->pcie_gen[pcie_table->num_of_link_levels] = 1485 skutable->PcieGenSpeed[link_level]; 1486 pcie_table->pcie_lane[pcie_table->num_of_link_levels] = 1487 skutable->PcieLaneCount[link_level]; 1488 pcie_table->clk_freq[pcie_table->num_of_link_levels] = 1489 skutable->LclkFreq[link_level]; 1490 pcie_table->num_of_link_levels++; 1491 } 1492 num_of_levels = pcie_table->num_of_link_levels; 1493 if (!num_of_levels) 1494 return 0; 1495 1496 if (!(smu->adev->pm.pp_feature & PP_PCIE_DPM_MASK)) { 1497 if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap) 1498 pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1]; 1499 1500 if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap) 1501 pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1]; 1502 1503 /* Force all levels to use the same settings */ 1504 for (i = 0; i < num_of_levels; i++) { 1505 pcie_table->pcie_gen[i] = pcie_gen_cap; 1506 pcie_table->pcie_lane[i] = pcie_width_cap; 1507 smu_pcie_arg = i << 16; 1508 smu_pcie_arg |= pcie_table->pcie_gen[i] << 8; 1509 smu_pcie_arg |= pcie_table->pcie_lane[i]; 1510 1511 ret = smu_cmn_send_smc_msg_with_param(smu, 1512 SMU_MSG_OverridePcieParameters, 1513 smu_pcie_arg, 1514 NULL); 1515 if (ret) 1516 break; 1517 } 1518 } else { 1519 for (i = 0; i < num_of_levels; i++) { 1520 if (pcie_table->pcie_gen[i] > pcie_gen_cap || 1521 pcie_table->pcie_lane[i] > pcie_width_cap) { 1522 pcie_table->pcie_gen[i] = pcie_table->pcie_gen[i] > pcie_gen_cap ? 1523 pcie_gen_cap : pcie_table->pcie_gen[i]; 1524 pcie_table->pcie_lane[i] = pcie_table->pcie_lane[i] > pcie_width_cap ? 1525 pcie_width_cap : pcie_table->pcie_lane[i]; 1526 smu_pcie_arg = i << 16; 1527 smu_pcie_arg |= pcie_table->pcie_gen[i] << 8; 1528 smu_pcie_arg |= pcie_table->pcie_lane[i]; 1529 1530 ret = smu_cmn_send_smc_msg_with_param(smu, 1531 SMU_MSG_OverridePcieParameters, 1532 smu_pcie_arg, 1533 NULL); 1534 if (ret) 1535 break; 1536 } 1537 } 1538 } 1539 1540 return ret; 1541} 1542 1543static const struct smu_temperature_range smu14_thermal_policy[] = { 1544 {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, 1545 { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000}, 1546}; 1547 1548static int smu_v14_0_2_get_thermal_temperature_range(struct smu_context *smu, 1549 struct smu_temperature_range *range) 1550{ 1551 struct smu_table_context *table_context = &smu->smu_table; 1552 struct smu_14_0_2_powerplay_table *powerplay_table = 1553 table_context->power_play_table; 1554 PPTable_t *pptable = smu->smu_table.driver_pptable; 1555 1556 if (amdgpu_sriov_vf(smu->adev)) 1557 return 0; 1558 1559 if (!range) 1560 return -EINVAL; 1561 1562 memcpy(range, &smu14_thermal_policy[0], sizeof(struct smu_temperature_range)); 1563 1564 range->max = pptable->CustomSkuTable.TemperatureLimit[TEMP_EDGE] * 1565 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 1566 range->edge_emergency_max = (pptable->CustomSkuTable.TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) * 1567 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 1568 range->hotspot_crit_max = pptable->CustomSkuTable.TemperatureLimit[TEMP_HOTSPOT] * 1569 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 1570 range->hotspot_emergency_max = (pptable->CustomSkuTable.TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) * 1571 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 1572 range->mem_crit_max = pptable->CustomSkuTable.TemperatureLimit[TEMP_MEM] * 1573 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 1574 range->mem_emergency_max = (pptable->CustomSkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)* 1575 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 1576 range->software_shutdown_temp = powerplay_table->software_shutdown_temp; 1577 range->software_shutdown_temp_offset = pptable->CustomSkuTable.FanAbnormalTempLimitOffset; 1578 1579 return 0; 1580} 1581 1582static int smu_v14_0_2_populate_umd_state_clk(struct smu_context *smu) 1583{ 1584 struct smu_14_0_dpm_context *dpm_context = 1585 smu->smu_dpm.dpm_context; 1586 struct smu_14_0_dpm_table *gfx_table = 1587 &dpm_context->dpm_tables.gfx_table; 1588 struct smu_14_0_dpm_table *mem_table = 1589 &dpm_context->dpm_tables.uclk_table; 1590 struct smu_14_0_dpm_table *soc_table = 1591 &dpm_context->dpm_tables.soc_table; 1592 struct smu_14_0_dpm_table *vclk_table = 1593 &dpm_context->dpm_tables.vclk_table; 1594 struct smu_14_0_dpm_table *dclk_table = 1595 &dpm_context->dpm_tables.dclk_table; 1596 struct smu_14_0_dpm_table *fclk_table = 1597 &dpm_context->dpm_tables.fclk_table; 1598 struct smu_umd_pstate_table *pstate_table = 1599 &smu->pstate_table; 1600 struct smu_table_context *table_context = &smu->smu_table; 1601 PPTable_t *pptable = table_context->driver_pptable; 1602 DriverReportedClocks_t driver_clocks = 1603 pptable->SkuTable.DriverReportedClocks; 1604 1605 pstate_table->gfxclk_pstate.min = gfx_table->min; 1606 if (driver_clocks.GameClockAc && 1607 (driver_clocks.GameClockAc < gfx_table->max)) 1608 pstate_table->gfxclk_pstate.peak = driver_clocks.GameClockAc; 1609 else 1610 pstate_table->gfxclk_pstate.peak = gfx_table->max; 1611 1612 pstate_table->uclk_pstate.min = mem_table->min; 1613 pstate_table->uclk_pstate.peak = mem_table->max; 1614 1615 pstate_table->socclk_pstate.min = soc_table->min; 1616 pstate_table->socclk_pstate.peak = soc_table->max; 1617 1618 pstate_table->vclk_pstate.min = vclk_table->min; 1619 pstate_table->vclk_pstate.peak = vclk_table->max; 1620 1621 pstate_table->dclk_pstate.min = dclk_table->min; 1622 pstate_table->dclk_pstate.peak = dclk_table->max; 1623 1624 pstate_table->fclk_pstate.min = fclk_table->min; 1625 pstate_table->fclk_pstate.peak = fclk_table->max; 1626 1627 if (driver_clocks.BaseClockAc && 1628 driver_clocks.BaseClockAc < gfx_table->max) 1629 pstate_table->gfxclk_pstate.standard = driver_clocks.BaseClockAc; 1630 else 1631 pstate_table->gfxclk_pstate.standard = gfx_table->max; 1632 pstate_table->uclk_pstate.standard = mem_table->max; 1633 pstate_table->socclk_pstate.standard = soc_table->min; 1634 pstate_table->vclk_pstate.standard = vclk_table->min; 1635 pstate_table->dclk_pstate.standard = dclk_table->min; 1636 pstate_table->fclk_pstate.standard = fclk_table->min; 1637 1638 return 0; 1639} 1640 1641static void smu_v14_0_2_get_unique_id(struct smu_context *smu) 1642{ 1643 struct smu_table_context *smu_table = &smu->smu_table; 1644 SmuMetrics_t *metrics = 1645 &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics); 1646 struct amdgpu_device *adev = smu->adev; 1647 uint32_t upper32 = 0, lower32 = 0; 1648 int ret; 1649 1650 ret = smu_cmn_get_metrics_table(smu, NULL, false); 1651 if (ret) 1652 goto out; 1653 1654 upper32 = metrics->PublicSerialNumberUpper; 1655 lower32 = metrics->PublicSerialNumberLower; 1656 1657out: 1658 adev->unique_id = ((uint64_t)upper32 << 32) | lower32; 1659} 1660 1661static int smu_v14_0_2_get_fan_speed_pwm(struct smu_context *smu, 1662 uint32_t *speed) 1663{ 1664 int ret; 1665 1666 if (!speed) 1667 return -EINVAL; 1668 1669 ret = smu_v14_0_2_get_smu_metrics_data(smu, 1670 METRICS_CURR_FANPWM, 1671 speed); 1672 if (ret) { 1673 dev_err(smu->adev->dev, "Failed to get fan speed(PWM)!"); 1674 return ret; 1675 } 1676 1677 /* Convert the PMFW output which is in percent to pwm(255) based */ 1678 *speed = min(*speed * 255 / 100, (uint32_t)255); 1679 1680 return 0; 1681} 1682 1683static int smu_v14_0_2_get_fan_speed_rpm(struct smu_context *smu, 1684 uint32_t *speed) 1685{ 1686 if (!speed) 1687 return -EINVAL; 1688 1689 return smu_v14_0_2_get_smu_metrics_data(smu, 1690 METRICS_CURR_FANSPEED, 1691 speed); 1692} 1693 1694static int smu_v14_0_2_get_power_limit(struct smu_context *smu, 1695 uint32_t *current_power_limit, 1696 uint32_t *default_power_limit, 1697 uint32_t *max_power_limit, 1698 uint32_t *min_power_limit) 1699{ 1700 struct smu_table_context *table_context = &smu->smu_table; 1701 struct smu_14_0_2_powerplay_table *powerplay_table = 1702 table_context->power_play_table; 1703 PPTable_t *pptable = table_context->driver_pptable; 1704 CustomSkuTable_t *skutable = &pptable->CustomSkuTable; 1705 int16_t od_percent_upper = 0, od_percent_lower = 0; 1706 uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; 1707 uint32_t power_limit; 1708 1709 if (smu_v14_0_get_current_power_limit(smu, &power_limit)) 1710 power_limit = smu->adev->pm.ac_power ? 1711 skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] : 1712 skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0]; 1713 1714 if (current_power_limit) 1715 *current_power_limit = power_limit; 1716 if (default_power_limit) 1717 *default_power_limit = power_limit; 1718 1719 if (powerplay_table) { 1720 if (smu->od_enabled && 1721 smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { 1722 od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt; 1723 od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; 1724 } else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { 1725 od_percent_upper = 0; 1726 od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; 1727 } 1728 } 1729 1730 dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n", 1731 od_percent_upper, od_percent_lower, power_limit); 1732 1733 if (max_power_limit) { 1734 *max_power_limit = msg_limit * (100 + od_percent_upper); 1735 *max_power_limit /= 100; 1736 } 1737 1738 if (min_power_limit) { 1739 *min_power_limit = power_limit * (100 + od_percent_lower); 1740 *min_power_limit /= 100; 1741 } 1742 1743 return 0; 1744} 1745 1746static int smu_v14_0_2_get_power_profile_mode(struct smu_context *smu, 1747 char *buf) 1748{ 1749 DpmActivityMonitorCoeffIntExternal_t activity_monitor_external; 1750 DpmActivityMonitorCoeffInt_t *activity_monitor = 1751 &(activity_monitor_external.DpmActivityMonitorCoeffInt); 1752 static const char *title[] = { 1753 "PROFILE_INDEX(NAME)", 1754 "CLOCK_TYPE(NAME)", 1755 "FPS", 1756 "MinActiveFreqType", 1757 "MinActiveFreq", 1758 "BoosterFreqType", 1759 "BoosterFreq", 1760 "PD_Data_limit_c", 1761 "PD_Data_error_coeff", 1762 "PD_Data_error_rate_coeff"}; 1763 int16_t workload_type = 0; 1764 uint32_t i, size = 0; 1765 int result = 0; 1766 1767 if (!buf) 1768 return -EINVAL; 1769 1770 size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s\n", 1771 title[0], title[1], title[2], title[3], title[4], title[5], 1772 title[6], title[7], title[8], title[9]); 1773 1774 for (i = 0; i < PP_SMC_POWER_PROFILE_COUNT; i++) { 1775 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 1776 workload_type = smu_cmn_to_asic_specific_index(smu, 1777 CMN2ASIC_MAPPING_WORKLOAD, 1778 i); 1779 if (workload_type == -ENOTSUPP) 1780 continue; 1781 else if (workload_type < 0) 1782 return -EINVAL; 1783 1784 result = smu_cmn_update_table(smu, 1785 SMU_TABLE_ACTIVITY_MONITOR_COEFF, 1786 workload_type, 1787 (void *)(&activity_monitor_external), 1788 false); 1789 if (result) { 1790 dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); 1791 return result; 1792 } 1793 1794 size += sysfs_emit_at(buf, size, "%2d %14s%s:\n", 1795 i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); 1796 1797 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n", 1798 " ", 1799 0, 1800 "GFXCLK", 1801 activity_monitor->Gfx_FPS, 1802 activity_monitor->Gfx_MinActiveFreqType, 1803 activity_monitor->Gfx_MinActiveFreq, 1804 activity_monitor->Gfx_BoosterFreqType, 1805 activity_monitor->Gfx_BoosterFreq, 1806 activity_monitor->Gfx_PD_Data_limit_c, 1807 activity_monitor->Gfx_PD_Data_error_coeff, 1808 activity_monitor->Gfx_PD_Data_error_rate_coeff); 1809 1810 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n", 1811 " ", 1812 1, 1813 "FCLK", 1814 activity_monitor->Fclk_FPS, 1815 activity_monitor->Fclk_MinActiveFreqType, 1816 activity_monitor->Fclk_MinActiveFreq, 1817 activity_monitor->Fclk_BoosterFreqType, 1818 activity_monitor->Fclk_BoosterFreq, 1819 activity_monitor->Fclk_PD_Data_limit_c, 1820 activity_monitor->Fclk_PD_Data_error_coeff, 1821 activity_monitor->Fclk_PD_Data_error_rate_coeff); 1822 } 1823 1824 return size; 1825} 1826 1827#define SMU_14_0_2_CUSTOM_PARAMS_COUNT 9 1828#define SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT 2 1829#define SMU_14_0_2_CUSTOM_PARAMS_SIZE (SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT * SMU_14_0_2_CUSTOM_PARAMS_COUNT * sizeof(long)) 1830 1831static int smu_v14_0_2_set_power_profile_mode_coeff(struct smu_context *smu, 1832 long *input) 1833{ 1834 DpmActivityMonitorCoeffIntExternal_t activity_monitor_external; 1835 DpmActivityMonitorCoeffInt_t *activity_monitor = 1836 &(activity_monitor_external.DpmActivityMonitorCoeffInt); 1837 int ret, idx; 1838 1839 ret = smu_cmn_update_table(smu, 1840 SMU_TABLE_ACTIVITY_MONITOR_COEFF, 1841 WORKLOAD_PPLIB_CUSTOM_BIT, 1842 (void *)(&activity_monitor_external), 1843 false); 1844 if (ret) { 1845 dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); 1846 return ret; 1847 } 1848 1849 idx = 0 * SMU_14_0_2_CUSTOM_PARAMS_COUNT; 1850 if (input[idx]) { 1851 /* Gfxclk */ 1852 activity_monitor->Gfx_FPS = input[idx + 1]; 1853 activity_monitor->Gfx_MinActiveFreqType = input[idx + 2]; 1854 activity_monitor->Gfx_MinActiveFreq = input[idx + 3]; 1855 activity_monitor->Gfx_BoosterFreqType = input[idx + 4]; 1856 activity_monitor->Gfx_BoosterFreq = input[idx + 5]; 1857 activity_monitor->Gfx_PD_Data_limit_c = input[idx + 6]; 1858 activity_monitor->Gfx_PD_Data_error_coeff = input[idx + 7]; 1859 activity_monitor->Gfx_PD_Data_error_rate_coeff = input[idx + 8]; 1860 } 1861 idx = 1 * SMU_14_0_2_CUSTOM_PARAMS_COUNT; 1862 if (input[idx]) { 1863 /* Fclk */ 1864 activity_monitor->Fclk_FPS = input[idx + 1]; 1865 activity_monitor->Fclk_MinActiveFreqType = input[idx + 2]; 1866 activity_monitor->Fclk_MinActiveFreq = input[idx + 3]; 1867 activity_monitor->Fclk_BoosterFreqType = input[idx + 4]; 1868 activity_monitor->Fclk_BoosterFreq = input[idx + 5]; 1869 activity_monitor->Fclk_PD_Data_limit_c = input[idx + 6]; 1870 activity_monitor->Fclk_PD_Data_error_coeff = input[idx + 7]; 1871 activity_monitor->Fclk_PD_Data_error_rate_coeff = input[idx + 8]; 1872 } 1873 1874 ret = smu_cmn_update_table(smu, 1875 SMU_TABLE_ACTIVITY_MONITOR_COEFF, 1876 WORKLOAD_PPLIB_CUSTOM_BIT, 1877 (void *)(&activity_monitor_external), 1878 true); 1879 if (ret) { 1880 dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); 1881 return ret; 1882 } 1883 1884 return ret; 1885} 1886 1887static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu, 1888 u32 workload_mask, 1889 long *custom_params, 1890 u32 custom_params_max_idx) 1891{ 1892 u32 backend_workload_mask = 0; 1893 int ret, idx = -1, i; 1894 1895 smu_cmn_get_backend_workload_mask(smu, workload_mask, 1896 &backend_workload_mask); 1897 1898 /* disable deep sleep if compute is enabled */ 1899 if (workload_mask & (1 << PP_SMC_POWER_PROFILE_COMPUTE)) 1900 smu_v14_0_deep_sleep_control(smu, false); 1901 else 1902 smu_v14_0_deep_sleep_control(smu, true); 1903 1904 if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) { 1905 if (!smu->custom_profile_params) { 1906 smu->custom_profile_params = 1907 kzalloc(SMU_14_0_2_CUSTOM_PARAMS_SIZE, GFP_KERNEL); 1908 if (!smu->custom_profile_params) 1909 return -ENOMEM; 1910 } 1911 if (custom_params && custom_params_max_idx) { 1912 if (custom_params_max_idx != SMU_14_0_2_CUSTOM_PARAMS_COUNT) 1913 return -EINVAL; 1914 if (custom_params[0] >= SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT) 1915 return -EINVAL; 1916 idx = custom_params[0] * SMU_14_0_2_CUSTOM_PARAMS_COUNT; 1917 smu->custom_profile_params[idx] = 1; 1918 for (i = 1; i < custom_params_max_idx; i++) 1919 smu->custom_profile_params[idx + i] = custom_params[i]; 1920 } 1921 ret = smu_v14_0_2_set_power_profile_mode_coeff(smu, 1922 smu->custom_profile_params); 1923 if (ret) { 1924 if (idx != -1) 1925 smu->custom_profile_params[idx] = 0; 1926 return ret; 1927 } 1928 } else if (smu->custom_profile_params) { 1929 memset(smu->custom_profile_params, 0, SMU_14_0_2_CUSTOM_PARAMS_SIZE); 1930 } 1931 1932 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, 1933 backend_workload_mask, NULL); 1934 if (ret) { 1935 dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n", 1936 workload_mask); 1937 if (idx != -1) 1938 smu->custom_profile_params[idx] = 0; 1939 return ret; 1940 } 1941 1942 return ret; 1943} 1944 1945static int smu_v14_0_2_baco_enter(struct smu_context *smu) 1946{ 1947 struct smu_baco_context *smu_baco = &smu->smu_baco; 1948 struct amdgpu_device *adev = smu->adev; 1949 1950 if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) 1951 return smu_v14_0_baco_set_armd3_sequence(smu, 1952 smu_baco->maco_support ? BACO_SEQ_BAMACO : BACO_SEQ_BACO); 1953 else 1954 return smu_v14_0_baco_enter(smu); 1955} 1956 1957static int smu_v14_0_2_baco_exit(struct smu_context *smu) 1958{ 1959 struct amdgpu_device *adev = smu->adev; 1960 1961 if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { 1962 /* Wait for PMFW handling for the Dstate change */ 1963 usleep_range(10000, 11000); 1964 return smu_v14_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); 1965 } else { 1966 return smu_v14_0_baco_exit(smu); 1967 } 1968} 1969 1970static bool smu_v14_0_2_is_mode1_reset_supported(struct smu_context *smu) 1971{ 1972 // TODO 1973 1974 return true; 1975} 1976 1977static int smu_v14_0_2_i2c_xfer(struct i2c_adapter *i2c_adap, 1978 struct i2c_msg *msg, int num_msgs) 1979{ 1980 struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); 1981 struct amdgpu_device *adev = smu_i2c->adev; 1982 struct smu_context *smu = adev->powerplay.pp_handle; 1983 struct smu_table_context *smu_table = &smu->smu_table; 1984 struct smu_table *table = &smu_table->driver_table; 1985 SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; 1986 int i, j, r, c; 1987 u16 dir; 1988 1989 if (!adev->pm.dpm_enabled) 1990 return -EBUSY; 1991 1992 req = kzalloc(sizeof(*req), GFP_KERNEL); 1993 if (!req) 1994 return -ENOMEM; 1995 1996 req->I2CcontrollerPort = smu_i2c->port; 1997 req->I2CSpeed = I2C_SPEED_FAST_400K; 1998 req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ 1999 dir = msg[0].flags & I2C_M_RD; 2000 2001 for (c = i = 0; i < num_msgs; i++) { 2002 for (j = 0; j < msg[i].len; j++, c++) { 2003 SwI2cCmd_t *cmd = &req->SwI2cCmds[c]; 2004 2005 if (!(msg[i].flags & I2C_M_RD)) { 2006 /* write */ 2007 cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK; 2008 cmd->ReadWriteData = msg[i].buf[j]; 2009 } 2010 2011 if ((dir ^ msg[i].flags) & I2C_M_RD) { 2012 /* The direction changes. 2013 */ 2014 dir = msg[i].flags & I2C_M_RD; 2015 cmd->CmdConfig |= CMDCONFIG_RESTART_MASK; 2016 } 2017 2018 req->NumCmds++; 2019 2020 /* 2021 * Insert STOP if we are at the last byte of either last 2022 * message for the transaction or the client explicitly 2023 * requires a STOP at this particular message. 2024 */ 2025 if ((j == msg[i].len - 1) && 2026 ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) { 2027 cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK; 2028 cmd->CmdConfig |= CMDCONFIG_STOP_MASK; 2029 } 2030 } 2031 } 2032 mutex_lock(&adev->pm.mutex); 2033 r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); 2034 mutex_unlock(&adev->pm.mutex); 2035 if (r) 2036 goto fail; 2037 2038 for (c = i = 0; i < num_msgs; i++) { 2039 if (!(msg[i].flags & I2C_M_RD)) { 2040 c += msg[i].len; 2041 continue; 2042 } 2043 for (j = 0; j < msg[i].len; j++, c++) { 2044 SwI2cCmd_t *cmd = &res->SwI2cCmds[c]; 2045 2046 msg[i].buf[j] = cmd->ReadWriteData; 2047 } 2048 } 2049 r = num_msgs; 2050fail: 2051 kfree(req); 2052 return r; 2053} 2054 2055static u32 smu_v14_0_2_i2c_func(struct i2c_adapter *adap) 2056{ 2057 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 2058} 2059 2060static const struct i2c_algorithm smu_v14_0_2_i2c_algo = { 2061 .master_xfer = smu_v14_0_2_i2c_xfer, 2062 .functionality = smu_v14_0_2_i2c_func, 2063}; 2064 2065static const struct i2c_adapter_quirks smu_v14_0_2_i2c_control_quirks = { 2066 .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN, 2067 .max_read_len = MAX_SW_I2C_COMMANDS, 2068 .max_write_len = MAX_SW_I2C_COMMANDS, 2069 .max_comb_1st_msg_len = 2, 2070 .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, 2071}; 2072 2073static int smu_v14_0_2_i2c_control_init(struct smu_context *smu) 2074{ 2075 struct amdgpu_device *adev = smu->adev; 2076 int res, i; 2077 2078 for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { 2079 struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; 2080 struct i2c_adapter *control = &smu_i2c->adapter; 2081 2082 smu_i2c->adev = adev; 2083 smu_i2c->port = i; 2084 mutex_init(&smu_i2c->mutex); 2085 control->owner = THIS_MODULE; 2086 control->dev.parent = &adev->pdev->dev; 2087 control->algo = &smu_v14_0_2_i2c_algo; 2088 snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i); 2089 control->quirks = &smu_v14_0_2_i2c_control_quirks; 2090 i2c_set_adapdata(control, smu_i2c); 2091 2092 res = devm_i2c_add_adapter(adev->dev, control); 2093 if (res) { 2094 DRM_ERROR("Failed to register hw i2c, err: %d\n", res); 2095 return res; 2096 } 2097 } 2098 2099 /* assign the buses used for the FRU EEPROM and RAS EEPROM */ 2100 /* XXX ideally this would be something in a vbios data table */ 2101 adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter; 2102 adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; 2103 2104 return 0; 2105} 2106 2107static void smu_v14_0_2_i2c_control_fini(struct smu_context *smu) 2108{ 2109 struct amdgpu_device *adev = smu->adev; 2110 2111 adev->pm.ras_eeprom_i2c_bus = NULL; 2112 adev->pm.fru_eeprom_i2c_bus = NULL; 2113} 2114 2115static int smu_v14_0_2_set_mp1_state(struct smu_context *smu, 2116 enum pp_mp1_state mp1_state) 2117{ 2118 int ret; 2119 2120 switch (mp1_state) { 2121 case PP_MP1_STATE_UNLOAD: 2122 ret = smu_cmn_set_mp1_state(smu, mp1_state); 2123 break; 2124 default: 2125 /* Ignore others */ 2126 ret = 0; 2127 } 2128 2129 return ret; 2130} 2131 2132static int smu_v14_0_2_set_df_cstate(struct smu_context *smu, 2133 enum pp_df_cstate state) 2134{ 2135 return smu_cmn_send_smc_msg_with_param(smu, 2136 SMU_MSG_DFCstateControl, 2137 state, 2138 NULL); 2139} 2140 2141static int smu_v14_0_2_mode1_reset(struct smu_context *smu) 2142{ 2143 int ret = 0; 2144 2145 ret = smu_cmn_send_debug_smc_msg(smu, DEBUGSMC_MSG_Mode1Reset); 2146 if (!ret) { 2147 if (amdgpu_emu_mode == 1) { 2148 msleep(50000); 2149 } else { 2150 /* disable mmio access while doing mode 1 reset*/ 2151 smu->adev->no_hw_access = true; 2152 /* ensure no_hw_access is globally visible before any MMIO */ 2153 smp_mb(); 2154 msleep(1000); 2155 } 2156 } 2157 2158 return ret; 2159} 2160 2161static int smu_v14_0_2_mode2_reset(struct smu_context *smu) 2162{ 2163 int ret = 0; 2164 2165 // TODO 2166 2167 return ret; 2168} 2169 2170static int smu_v14_0_2_enable_gfx_features(struct smu_context *smu) 2171{ 2172 struct amdgpu_device *adev = smu->adev; 2173 2174 if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 2)) 2175 return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnableAllSmuFeatures, 2176 FEATURE_PWR_GFX, NULL); 2177 else 2178 return -EOPNOTSUPP; 2179} 2180 2181static void smu_v14_0_2_set_smu_mailbox_registers(struct smu_context *smu) 2182{ 2183 struct amdgpu_device *adev = smu->adev; 2184 2185 smu->param_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_82); 2186 smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_66); 2187 smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_90); 2188 2189 smu->debug_param_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_53); 2190 smu->debug_msg_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_75); 2191 smu->debug_resp_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_54); 2192} 2193 2194static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu, 2195 void **table) 2196{ 2197 struct smu_table_context *smu_table = &smu->smu_table; 2198 struct gpu_metrics_v1_3 *gpu_metrics = 2199 (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table; 2200 SmuMetricsExternal_t metrics_ext; 2201 SmuMetrics_t *metrics = &metrics_ext.SmuMetrics; 2202 int ret = 0; 2203 2204 ret = smu_cmn_get_metrics_table(smu, 2205 &metrics_ext, 2206 true); 2207 if (ret) 2208 return ret; 2209 2210 smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); 2211 2212 gpu_metrics->temperature_edge = metrics->AvgTemperature[TEMP_EDGE]; 2213 gpu_metrics->temperature_hotspot = metrics->AvgTemperature[TEMP_HOTSPOT]; 2214 gpu_metrics->temperature_mem = metrics->AvgTemperature[TEMP_MEM]; 2215 gpu_metrics->temperature_vrgfx = metrics->AvgTemperature[TEMP_VR_GFX]; 2216 gpu_metrics->temperature_vrsoc = metrics->AvgTemperature[TEMP_VR_SOC]; 2217 gpu_metrics->temperature_vrmem = max(metrics->AvgTemperature[TEMP_VR_MEM0], 2218 metrics->AvgTemperature[TEMP_VR_MEM1]); 2219 2220 gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity; 2221 gpu_metrics->average_umc_activity = metrics->AverageUclkActivity; 2222 gpu_metrics->average_mm_activity = max(metrics->AverageVcn0ActivityPercentage, 2223 metrics->Vcn1ActivityPercentage); 2224 2225 gpu_metrics->average_socket_power = metrics->AverageSocketPower; 2226 gpu_metrics->energy_accumulator = metrics->EnergyAccumulator; 2227 2228 if (metrics->AverageGfxActivity <= SMU_14_0_2_BUSY_THRESHOLD) 2229 gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs; 2230 else 2231 gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs; 2232 2233 if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD) 2234 gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs; 2235 else 2236 gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs; 2237 2238 gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency; 2239 gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency; 2240 gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency; 2241 gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency; 2242 2243 gpu_metrics->current_gfxclk = gpu_metrics->average_gfxclk_frequency; 2244 gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK]; 2245 gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK]; 2246 gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0]; 2247 gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0]; 2248 gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_0]; 2249 gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_0]; 2250 2251 gpu_metrics->throttle_status = 2252 smu_v14_0_2_get_throttler_status(metrics); 2253 gpu_metrics->indep_throttle_status = 2254 smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status, 2255 smu_v14_0_2_throttler_map); 2256 2257 gpu_metrics->current_fan_speed = metrics->AvgFanRpm; 2258 2259 gpu_metrics->pcie_link_width = metrics->PcieWidth; 2260 if ((metrics->PcieRate - 1) > LINK_SPEED_MAX) 2261 gpu_metrics->pcie_link_speed = pcie_gen_to_speed(1); 2262 else 2263 gpu_metrics->pcie_link_speed = pcie_gen_to_speed(metrics->PcieRate); 2264 2265 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 2266 2267 gpu_metrics->voltage_gfx = metrics->AvgVoltage[SVI_PLANE_VDD_GFX]; 2268 gpu_metrics->voltage_soc = metrics->AvgVoltage[SVI_PLANE_VDD_SOC]; 2269 gpu_metrics->voltage_mem = metrics->AvgVoltage[SVI_PLANE_VDDIO_MEM]; 2270 2271 *table = (void *)gpu_metrics; 2272 2273 return sizeof(struct gpu_metrics_v1_3); 2274} 2275 2276static void smu_v14_0_2_dump_od_table(struct smu_context *smu, 2277 OverDriveTableExternal_t *od_table) 2278{ 2279 struct amdgpu_device *adev = smu->adev; 2280 2281 dev_dbg(adev->dev, "OD: Gfxclk offset: (%d)\n", od_table->OverDriveTable.GfxclkFoffset); 2282 dev_dbg(adev->dev, "OD: Uclk: (%d, %d)\n", od_table->OverDriveTable.UclkFmin, 2283 od_table->OverDriveTable.UclkFmax); 2284} 2285 2286static int smu_v14_0_2_upload_overdrive_table(struct smu_context *smu, 2287 OverDriveTableExternal_t *od_table) 2288{ 2289 int ret; 2290 ret = smu_cmn_update_table(smu, 2291 SMU_TABLE_OVERDRIVE, 2292 0, 2293 (void *)od_table, 2294 true); 2295 if (ret) 2296 dev_err(smu->adev->dev, "Failed to upload overdrive table!\n"); 2297 2298 return ret; 2299} 2300 2301static void smu_v14_0_2_set_supported_od_feature_mask(struct smu_context *smu) 2302{ 2303 struct amdgpu_device *adev = smu->adev; 2304 2305 if (smu_v14_0_2_is_od_feature_supported(smu, 2306 PP_OD_FEATURE_FAN_CURVE_BIT)) 2307 adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE | 2308 OD_OPS_SUPPORT_FAN_CURVE_SET | 2309 OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE | 2310 OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET | 2311 OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE | 2312 OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET | 2313 OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE | 2314 OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET | 2315 OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE | 2316 OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET | 2317 OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE | 2318 OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET; 2319} 2320 2321static int smu_v14_0_2_get_overdrive_table(struct smu_context *smu, 2322 OverDriveTableExternal_t *od_table) 2323{ 2324 int ret; 2325 ret = smu_cmn_update_table(smu, 2326 SMU_TABLE_OVERDRIVE, 2327 0, 2328 (void *)od_table, 2329 false); 2330 if (ret) 2331 dev_err(smu->adev->dev, "Failed to get overdrive table!\n"); 2332 2333 return ret; 2334} 2335 2336static int smu_v14_0_2_set_default_od_settings(struct smu_context *smu) 2337{ 2338 OverDriveTableExternal_t *od_table = 2339 (OverDriveTableExternal_t *)smu->smu_table.overdrive_table; 2340 OverDriveTableExternal_t *boot_od_table = 2341 (OverDriveTableExternal_t *)smu->smu_table.boot_overdrive_table; 2342 OverDriveTableExternal_t *user_od_table = 2343 (OverDriveTableExternal_t *)smu->smu_table.user_overdrive_table; 2344 OverDriveTableExternal_t user_od_table_bak; 2345 int ret; 2346 int i; 2347 2348 ret = smu_v14_0_2_get_overdrive_table(smu, boot_od_table); 2349 if (ret) 2350 return ret; 2351 2352 smu_v14_0_2_dump_od_table(smu, boot_od_table); 2353 2354 memcpy(od_table, 2355 boot_od_table, 2356 sizeof(OverDriveTableExternal_t)); 2357 2358 /* 2359 * For S3/S4/Runpm resume, we need to setup those overdrive tables again, 2360 * but we have to preserve user defined values in "user_od_table". 2361 */ 2362 if (!smu->adev->in_suspend) { 2363 memcpy(user_od_table, 2364 boot_od_table, 2365 sizeof(OverDriveTableExternal_t)); 2366 smu->user_dpm_profile.user_od = false; 2367 } else if (smu->user_dpm_profile.user_od) { 2368 memcpy(&user_od_table_bak, 2369 user_od_table, 2370 sizeof(OverDriveTableExternal_t)); 2371 memcpy(user_od_table, 2372 boot_od_table, 2373 sizeof(OverDriveTableExternal_t)); 2374 user_od_table->OverDriveTable.GfxclkFoffset = 2375 user_od_table_bak.OverDriveTable.GfxclkFoffset; 2376 user_od_table->OverDriveTable.UclkFmin = 2377 user_od_table_bak.OverDriveTable.UclkFmin; 2378 user_od_table->OverDriveTable.UclkFmax = 2379 user_od_table_bak.OverDriveTable.UclkFmax; 2380 for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++) 2381 user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] = 2382 user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i]; 2383 for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) { 2384 user_od_table->OverDriveTable.FanLinearTempPoints[i] = 2385 user_od_table_bak.OverDriveTable.FanLinearTempPoints[i]; 2386 user_od_table->OverDriveTable.FanLinearPwmPoints[i] = 2387 user_od_table_bak.OverDriveTable.FanLinearPwmPoints[i]; 2388 } 2389 user_od_table->OverDriveTable.AcousticLimitRpmThreshold = 2390 user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold; 2391 user_od_table->OverDriveTable.AcousticTargetRpmThreshold = 2392 user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold; 2393 user_od_table->OverDriveTable.FanTargetTemperature = 2394 user_od_table_bak.OverDriveTable.FanTargetTemperature; 2395 user_od_table->OverDriveTable.FanMinimumPwm = 2396 user_od_table_bak.OverDriveTable.FanMinimumPwm; 2397 user_od_table->OverDriveTable.FanZeroRpmEnable = 2398 user_od_table_bak.OverDriveTable.FanZeroRpmEnable; 2399 } 2400 2401 smu_v14_0_2_set_supported_od_feature_mask(smu); 2402 2403 return 0; 2404} 2405 2406static int smu_v14_0_2_restore_user_od_settings(struct smu_context *smu) 2407{ 2408 struct smu_table_context *table_context = &smu->smu_table; 2409 OverDriveTableExternal_t *od_table = table_context->overdrive_table; 2410 OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table; 2411 int res; 2412 2413 user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | 2414 BIT(PP_OD_FEATURE_UCLK_BIT) | 2415 BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | 2416 BIT(PP_OD_FEATURE_FAN_CURVE_BIT) | 2417 BIT(PP_OD_FEATURE_ZERO_FAN_BIT); 2418 res = smu_v14_0_2_upload_overdrive_table(smu, user_od_table); 2419 user_od_table->OverDriveTable.FeatureCtrlMask = 0; 2420 if (res == 0) 2421 memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t)); 2422 2423 return res; 2424} 2425 2426static int smu_v14_0_2_od_restore_table_single(struct smu_context *smu, long input) 2427{ 2428 struct smu_table_context *table_context = &smu->smu_table; 2429 OverDriveTableExternal_t *boot_overdrive_table = 2430 (OverDriveTableExternal_t *)table_context->boot_overdrive_table; 2431 OverDriveTableExternal_t *od_table = 2432 (OverDriveTableExternal_t *)table_context->overdrive_table; 2433 struct amdgpu_device *adev = smu->adev; 2434 int i; 2435 2436 switch (input) { 2437 case PP_OD_EDIT_FAN_CURVE: 2438 for (i = 0; i < NUM_OD_FAN_MAX_POINTS; i++) { 2439 od_table->OverDriveTable.FanLinearTempPoints[i] = 2440 boot_overdrive_table->OverDriveTable.FanLinearTempPoints[i]; 2441 od_table->OverDriveTable.FanLinearPwmPoints[i] = 2442 boot_overdrive_table->OverDriveTable.FanLinearPwmPoints[i]; 2443 } 2444 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2445 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2446 break; 2447 case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE: 2448 od_table->OverDriveTable.FanZeroRpmEnable = 2449 boot_overdrive_table->OverDriveTable.FanZeroRpmEnable; 2450 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT); 2451 break; 2452 case PP_OD_EDIT_ACOUSTIC_LIMIT: 2453 od_table->OverDriveTable.AcousticLimitRpmThreshold = 2454 boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold; 2455 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2456 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2457 break; 2458 case PP_OD_EDIT_ACOUSTIC_TARGET: 2459 od_table->OverDriveTable.AcousticTargetRpmThreshold = 2460 boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold; 2461 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2462 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2463 break; 2464 case PP_OD_EDIT_FAN_TARGET_TEMPERATURE: 2465 od_table->OverDriveTable.FanTargetTemperature = 2466 boot_overdrive_table->OverDriveTable.FanTargetTemperature; 2467 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2468 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2469 break; 2470 case PP_OD_EDIT_FAN_MINIMUM_PWM: 2471 od_table->OverDriveTable.FanMinimumPwm = 2472 boot_overdrive_table->OverDriveTable.FanMinimumPwm; 2473 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2474 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2475 break; 2476 default: 2477 dev_info(adev->dev, "Invalid table index: %ld\n", input); 2478 return -EINVAL; 2479 } 2480 2481 return 0; 2482} 2483 2484static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu, 2485 enum PP_OD_DPM_TABLE_COMMAND type, 2486 long input[], 2487 uint32_t size) 2488{ 2489 struct smu_table_context *table_context = &smu->smu_table; 2490 OverDriveTableExternal_t *od_table = 2491 (OverDriveTableExternal_t *)table_context->overdrive_table; 2492 struct amdgpu_device *adev = smu->adev; 2493 uint32_t offset_of_voltageoffset; 2494 int32_t minimum, maximum; 2495 uint32_t feature_ctrlmask; 2496 int i, ret = 0; 2497 2498 switch (type) { 2499 case PP_OD_EDIT_SCLK_VDDC_TABLE: 2500 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) { 2501 dev_warn(adev->dev, "GFXCLK_LIMITS setting not supported!\n"); 2502 return -ENOTSUPP; 2503 } 2504 2505 if (size != 1) { 2506 dev_info(adev->dev, "invalid number of input parameters %d\n", size); 2507 return -EINVAL; 2508 } 2509 2510 smu_v14_0_2_get_od_setting_limits(smu, 2511 PP_OD_FEATURE_GFXCLK_FMAX, 2512 &minimum, 2513 &maximum); 2514 if (input[0] < minimum || 2515 input[0] > maximum) { 2516 dev_info(adev->dev, "GfxclkFoffset must be within [%d, %u]!\n", 2517 minimum, maximum); 2518 return -EINVAL; 2519 } 2520 2521 od_table->OverDriveTable.GfxclkFoffset = input[0]; 2522 od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT; 2523 break; 2524 2525 case PP_OD_EDIT_MCLK_VDDC_TABLE: 2526 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) { 2527 dev_warn(adev->dev, "UCLK_LIMITS setting not supported!\n"); 2528 return -ENOTSUPP; 2529 } 2530 2531 for (i = 0; i < size; i += 2) { 2532 if (i + 2 > size) { 2533 dev_info(adev->dev, "invalid number of input parameters %d\n", size); 2534 return -EINVAL; 2535 } 2536 2537 switch (input[i]) { 2538 case 0: 2539 smu_v14_0_2_get_od_setting_limits(smu, 2540 PP_OD_FEATURE_UCLK_FMIN, 2541 &minimum, 2542 &maximum); 2543 if (input[i + 1] < minimum || 2544 input[i + 1] > maximum) { 2545 dev_info(adev->dev, "UclkFmin (%ld) must be within [%u, %u]!\n", 2546 input[i + 1], minimum, maximum); 2547 return -EINVAL; 2548 } 2549 2550 od_table->OverDriveTable.UclkFmin = input[i + 1]; 2551 od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT; 2552 break; 2553 2554 case 1: 2555 smu_v14_0_2_get_od_setting_limits(smu, 2556 PP_OD_FEATURE_UCLK_FMAX, 2557 &minimum, 2558 &maximum); 2559 if (input[i + 1] < minimum || 2560 input[i + 1] > maximum) { 2561 dev_info(adev->dev, "UclkFmax (%ld) must be within [%u, %u]!\n", 2562 input[i + 1], minimum, maximum); 2563 return -EINVAL; 2564 } 2565 2566 od_table->OverDriveTable.UclkFmax = input[i + 1]; 2567 od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT; 2568 break; 2569 2570 default: 2571 dev_info(adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[i]); 2572 dev_info(adev->dev, "Supported indices: [0:min,1:max]\n"); 2573 return -EINVAL; 2574 } 2575 } 2576 2577 if (od_table->OverDriveTable.UclkFmin > od_table->OverDriveTable.UclkFmax) { 2578 dev_err(adev->dev, 2579 "Invalid setting: UclkFmin(%u) is bigger than UclkFmax(%u)\n", 2580 (uint32_t)od_table->OverDriveTable.UclkFmin, 2581 (uint32_t)od_table->OverDriveTable.UclkFmax); 2582 return -EINVAL; 2583 } 2584 break; 2585 2586 case PP_OD_EDIT_VDDGFX_OFFSET: 2587 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) { 2588 dev_warn(adev->dev, "Gfx offset setting not supported!\n"); 2589 return -ENOTSUPP; 2590 } 2591 2592 smu_v14_0_2_get_od_setting_limits(smu, 2593 PP_OD_FEATURE_GFX_VF_CURVE, 2594 &minimum, 2595 &maximum); 2596 if (input[0] < minimum || 2597 input[0] > maximum) { 2598 dev_info(adev->dev, "Voltage offset (%ld) must be within [%d, %d]!\n", 2599 input[0], minimum, maximum); 2600 return -EINVAL; 2601 } 2602 2603 for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++) 2604 od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] = input[0]; 2605 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT); 2606 break; 2607 2608 case PP_OD_EDIT_FAN_CURVE: 2609 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { 2610 dev_warn(adev->dev, "Fan curve setting not supported!\n"); 2611 return -ENOTSUPP; 2612 } 2613 2614 if (input[0] >= NUM_OD_FAN_MAX_POINTS - 1 || 2615 input[0] < 0) 2616 return -EINVAL; 2617 2618 smu_v14_0_2_get_od_setting_limits(smu, 2619 PP_OD_FEATURE_FAN_CURVE_TEMP, 2620 &minimum, 2621 &maximum); 2622 if (input[1] < minimum || 2623 input[1] > maximum) { 2624 dev_info(adev->dev, "Fan curve temp setting(%ld) must be within [%d, %d]!\n", 2625 input[1], minimum, maximum); 2626 return -EINVAL; 2627 } 2628 2629 smu_v14_0_2_get_od_setting_limits(smu, 2630 PP_OD_FEATURE_FAN_CURVE_PWM, 2631 &minimum, 2632 &maximum); 2633 if (input[2] < minimum || 2634 input[2] > maximum) { 2635 dev_info(adev->dev, "Fan curve pwm setting(%ld) must be within [%d, %d]!\n", 2636 input[2], minimum, maximum); 2637 return -EINVAL; 2638 } 2639 2640 od_table->OverDriveTable.FanLinearTempPoints[input[0]] = input[1]; 2641 od_table->OverDriveTable.FanLinearPwmPoints[input[0]] = input[2]; 2642 od_table->OverDriveTable.FanMode = FAN_MODE_MANUAL_LINEAR; 2643 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2644 break; 2645 2646 case PP_OD_EDIT_ACOUSTIC_LIMIT: 2647 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { 2648 dev_warn(adev->dev, "Fan curve setting not supported!\n"); 2649 return -ENOTSUPP; 2650 } 2651 2652 smu_v14_0_2_get_od_setting_limits(smu, 2653 PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT, 2654 &minimum, 2655 &maximum); 2656 if (input[0] < minimum || 2657 input[0] > maximum) { 2658 dev_info(adev->dev, "acoustic limit threshold setting(%ld) must be within [%d, %d]!\n", 2659 input[0], minimum, maximum); 2660 return -EINVAL; 2661 } 2662 2663 od_table->OverDriveTable.AcousticLimitRpmThreshold = input[0]; 2664 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2665 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2666 break; 2667 2668 case PP_OD_EDIT_ACOUSTIC_TARGET: 2669 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { 2670 dev_warn(adev->dev, "Fan curve setting not supported!\n"); 2671 return -ENOTSUPP; 2672 } 2673 2674 smu_v14_0_2_get_od_setting_limits(smu, 2675 PP_OD_FEATURE_FAN_ACOUSTIC_TARGET, 2676 &minimum, 2677 &maximum); 2678 if (input[0] < minimum || 2679 input[0] > maximum) { 2680 dev_info(adev->dev, "acoustic target threshold setting(%ld) must be within [%d, %d]!\n", 2681 input[0], minimum, maximum); 2682 return -EINVAL; 2683 } 2684 2685 od_table->OverDriveTable.AcousticTargetRpmThreshold = input[0]; 2686 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2687 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2688 break; 2689 2690 case PP_OD_EDIT_FAN_TARGET_TEMPERATURE: 2691 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { 2692 dev_warn(adev->dev, "Fan curve setting not supported!\n"); 2693 return -ENOTSUPP; 2694 } 2695 2696 smu_v14_0_2_get_od_setting_limits(smu, 2697 PP_OD_FEATURE_FAN_TARGET_TEMPERATURE, 2698 &minimum, 2699 &maximum); 2700 if (input[0] < minimum || 2701 input[0] > maximum) { 2702 dev_info(adev->dev, "fan target temperature setting(%ld) must be within [%d, %d]!\n", 2703 input[0], minimum, maximum); 2704 return -EINVAL; 2705 } 2706 2707 od_table->OverDriveTable.FanTargetTemperature = input[0]; 2708 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2709 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2710 break; 2711 2712 case PP_OD_EDIT_FAN_MINIMUM_PWM: 2713 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { 2714 dev_warn(adev->dev, "Fan curve setting not supported!\n"); 2715 return -ENOTSUPP; 2716 } 2717 2718 smu_v14_0_2_get_od_setting_limits(smu, 2719 PP_OD_FEATURE_FAN_MINIMUM_PWM, 2720 &minimum, 2721 &maximum); 2722 if (input[0] < minimum || 2723 input[0] > maximum) { 2724 dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n", 2725 input[0], minimum, maximum); 2726 return -EINVAL; 2727 } 2728 2729 od_table->OverDriveTable.FanMinimumPwm = input[0]; 2730 od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; 2731 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); 2732 break; 2733 2734 case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE: 2735 if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) { 2736 dev_warn(adev->dev, "Zero RPM setting not supported!\n"); 2737 return -ENOTSUPP; 2738 } 2739 2740 smu_v14_0_2_get_od_setting_limits(smu, 2741 PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE, 2742 &minimum, 2743 &maximum); 2744 if (input[0] < minimum || 2745 input[0] > maximum) { 2746 dev_info(adev->dev, "zero RPM enable setting(%ld) must be within [%d, %d]!\n", 2747 input[0], minimum, maximum); 2748 return -EINVAL; 2749 } 2750 2751 od_table->OverDriveTable.FanZeroRpmEnable = input[0]; 2752 od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT); 2753 break; 2754 2755 case PP_OD_RESTORE_DEFAULT_TABLE: 2756 if (size == 1) { 2757 ret = smu_v14_0_2_od_restore_table_single(smu, input[0]); 2758 if (ret) 2759 return ret; 2760 } else { 2761 feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask; 2762 memcpy(od_table, 2763 table_context->boot_overdrive_table, 2764 sizeof(OverDriveTableExternal_t)); 2765 od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask; 2766 } 2767 fallthrough; 2768 case PP_OD_COMMIT_DPM_TABLE: 2769 /* 2770 * The member below instructs PMFW the settings focused in 2771 * this single operation. 2772 * `uint32_t FeatureCtrlMask;` 2773 * It does not contain actual informations about user's custom 2774 * settings. Thus we do not cache it. 2775 */ 2776 offset_of_voltageoffset = offsetof(OverDriveTable_t, VoltageOffsetPerZoneBoundary); 2777 if (memcmp((u8 *)od_table + offset_of_voltageoffset, 2778 table_context->user_overdrive_table + offset_of_voltageoffset, 2779 sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset)) { 2780 smu_v14_0_2_dump_od_table(smu, od_table); 2781 2782 ret = smu_v14_0_2_upload_overdrive_table(smu, od_table); 2783 if (ret) { 2784 dev_err(adev->dev, "Failed to upload overdrive table!\n"); 2785 return ret; 2786 } 2787 2788 od_table->OverDriveTable.FeatureCtrlMask = 0; 2789 memcpy(table_context->user_overdrive_table + offset_of_voltageoffset, 2790 (u8 *)od_table + offset_of_voltageoffset, 2791 sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset); 2792 2793 if (!memcmp(table_context->user_overdrive_table, 2794 table_context->boot_overdrive_table, 2795 sizeof(OverDriveTableExternal_t))) 2796 smu->user_dpm_profile.user_od = false; 2797 else 2798 smu->user_dpm_profile.user_od = true; 2799 } 2800 break; 2801 2802 default: 2803 return -ENOSYS; 2804 } 2805 2806 return ret; 2807} 2808 2809static int smu_v14_0_2_set_power_limit(struct smu_context *smu, 2810 enum smu_ppt_limit_type limit_type, 2811 uint32_t limit) 2812{ 2813 PPTable_t *pptable = smu->smu_table.driver_pptable; 2814 uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; 2815 struct smu_table_context *table_context = &smu->smu_table; 2816 OverDriveTableExternal_t *od_table = 2817 (OverDriveTableExternal_t *)table_context->overdrive_table; 2818 int ret = 0; 2819 2820 if (limit_type != SMU_DEFAULT_PPT_LIMIT) 2821 return -EINVAL; 2822 2823 if (limit <= msg_limit) { 2824 if (smu->current_power_limit > msg_limit) { 2825 od_table->OverDriveTable.Ppt = 0; 2826 od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT; 2827 2828 ret = smu_v14_0_2_upload_overdrive_table(smu, od_table); 2829 if (ret) { 2830 dev_err(smu->adev->dev, "Failed to upload overdrive table!\n"); 2831 return ret; 2832 } 2833 } 2834 return smu_v14_0_set_power_limit(smu, limit_type, limit); 2835 } else if (smu->od_enabled) { 2836 ret = smu_v14_0_set_power_limit(smu, limit_type, msg_limit); 2837 if (ret) 2838 return ret; 2839 2840 od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100; 2841 od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT; 2842 2843 ret = smu_v14_0_2_upload_overdrive_table(smu, od_table); 2844 if (ret) { 2845 dev_err(smu->adev->dev, "Failed to upload overdrive table!\n"); 2846 return ret; 2847 } 2848 2849 smu->current_power_limit = limit; 2850 } else { 2851 return -EINVAL; 2852 } 2853 2854 return 0; 2855} 2856 2857static const struct pptable_funcs smu_v14_0_2_ppt_funcs = { 2858 .get_allowed_feature_mask = smu_v14_0_2_get_allowed_feature_mask, 2859 .set_default_dpm_table = smu_v14_0_2_set_default_dpm_table, 2860 .i2c_init = smu_v14_0_2_i2c_control_init, 2861 .i2c_fini = smu_v14_0_2_i2c_control_fini, 2862 .is_dpm_running = smu_v14_0_2_is_dpm_running, 2863 .init_microcode = smu_v14_0_init_microcode, 2864 .load_microcode = smu_v14_0_load_microcode, 2865 .fini_microcode = smu_v14_0_fini_microcode, 2866 .init_smc_tables = smu_v14_0_2_init_smc_tables, 2867 .fini_smc_tables = smu_v14_0_fini_smc_tables, 2868 .init_power = smu_v14_0_init_power, 2869 .fini_power = smu_v14_0_fini_power, 2870 .check_fw_status = smu_v14_0_check_fw_status, 2871 .setup_pptable = smu_v14_0_2_setup_pptable, 2872 .check_fw_version = smu_v14_0_check_fw_version, 2873 .set_driver_table_location = smu_v14_0_set_driver_table_location, 2874 .system_features_control = smu_v14_0_system_features_control, 2875 .set_allowed_mask = smu_v14_0_set_allowed_mask, 2876 .get_enabled_mask = smu_cmn_get_enabled_mask, 2877 .dpm_set_vcn_enable = smu_v14_0_set_vcn_enable, 2878 .dpm_set_jpeg_enable = smu_v14_0_set_jpeg_enable, 2879 .get_dpm_ultimate_freq = smu_v14_0_2_get_dpm_ultimate_freq, 2880 .get_vbios_bootup_values = smu_v14_0_get_vbios_bootup_values, 2881 .read_sensor = smu_v14_0_2_read_sensor, 2882 .feature_is_enabled = smu_cmn_feature_is_enabled, 2883 .print_clk_levels = smu_v14_0_2_print_clk_levels, 2884 .force_clk_levels = smu_v14_0_2_force_clk_levels, 2885 .update_pcie_parameters = smu_v14_0_2_update_pcie_parameters, 2886 .get_thermal_temperature_range = smu_v14_0_2_get_thermal_temperature_range, 2887 .register_irq_handler = smu_v14_0_register_irq_handler, 2888 .enable_thermal_alert = smu_v14_0_enable_thermal_alert, 2889 .disable_thermal_alert = smu_v14_0_disable_thermal_alert, 2890 .notify_memory_pool_location = smu_v14_0_notify_memory_pool_location, 2891 .get_gpu_metrics = smu_v14_0_2_get_gpu_metrics, 2892 .set_soft_freq_limited_range = smu_v14_0_set_soft_freq_limited_range, 2893 .set_default_od_settings = smu_v14_0_2_set_default_od_settings, 2894 .restore_user_od_settings = smu_v14_0_2_restore_user_od_settings, 2895 .od_edit_dpm_table = smu_v14_0_2_od_edit_dpm_table, 2896 .init_pptable_microcode = smu_v14_0_init_pptable_microcode, 2897 .populate_umd_state_clk = smu_v14_0_2_populate_umd_state_clk, 2898 .set_performance_level = smu_v14_0_set_performance_level, 2899 .gfx_off_control = smu_v14_0_gfx_off_control, 2900 .get_unique_id = smu_v14_0_2_get_unique_id, 2901 .get_fan_speed_pwm = smu_v14_0_2_get_fan_speed_pwm, 2902 .get_fan_speed_rpm = smu_v14_0_2_get_fan_speed_rpm, 2903 .get_power_limit = smu_v14_0_2_get_power_limit, 2904 .set_power_limit = smu_v14_0_2_set_power_limit, 2905 .get_power_profile_mode = smu_v14_0_2_get_power_profile_mode, 2906 .set_power_profile_mode = smu_v14_0_2_set_power_profile_mode, 2907 .run_btc = smu_v14_0_run_btc, 2908 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 2909 .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, 2910 .set_tool_table_location = smu_v14_0_set_tool_table_location, 2911 .deep_sleep_control = smu_v14_0_deep_sleep_control, 2912 .gfx_ulv_control = smu_v14_0_gfx_ulv_control, 2913 .get_bamaco_support = smu_v14_0_get_bamaco_support, 2914 .baco_get_state = smu_v14_0_baco_get_state, 2915 .baco_set_state = smu_v14_0_baco_set_state, 2916 .baco_enter = smu_v14_0_2_baco_enter, 2917 .baco_exit = smu_v14_0_2_baco_exit, 2918 .mode1_reset_is_support = smu_v14_0_2_is_mode1_reset_supported, 2919 .mode1_reset = smu_v14_0_2_mode1_reset, 2920 .mode2_reset = smu_v14_0_2_mode2_reset, 2921 .enable_gfx_features = smu_v14_0_2_enable_gfx_features, 2922 .set_mp1_state = smu_v14_0_2_set_mp1_state, 2923 .set_df_cstate = smu_v14_0_2_set_df_cstate, 2924#if 0 2925 .gpo_control = smu_v14_0_gpo_control, 2926#endif 2927}; 2928 2929void smu_v14_0_2_set_ppt_funcs(struct smu_context *smu) 2930{ 2931 smu->ppt_funcs = &smu_v14_0_2_ppt_funcs; 2932 smu->message_map = smu_v14_0_2_message_map; 2933 smu->clock_map = smu_v14_0_2_clk_map; 2934 smu->feature_map = smu_v14_0_2_feature_mask_map; 2935 smu->table_map = smu_v14_0_2_table_map; 2936 smu->pwr_src_map = smu_v14_0_2_pwr_src_map; 2937 smu->workload_map = smu_v14_0_2_workload_map; 2938 smu_v14_0_2_set_smu_mailbox_registers(smu); 2939}
~/
Read-only file preview.