1f46a221bSXiaojian Du /* 2f46a221bSXiaojian Du * Copyright 2020 Advanced Micro Devices, Inc. 3f46a221bSXiaojian Du * 4f46a221bSXiaojian Du * Permission is hereby granted, free of charge, to any person obtaining a 5f46a221bSXiaojian Du * copy of this software and associated documentation files (the "Software"), 6f46a221bSXiaojian Du * to deal in the Software without restriction, including without limitation 7f46a221bSXiaojian Du * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f46a221bSXiaojian Du * and/or sell copies of the Software, and to permit persons to whom the 9f46a221bSXiaojian Du * Software is furnished to do so, subject to the following conditions: 10f46a221bSXiaojian Du * 11f46a221bSXiaojian Du * The above copyright notice and this permission notice shall be included in 12f46a221bSXiaojian Du * all copies or substantial portions of the Software. 13f46a221bSXiaojian Du * 14f46a221bSXiaojian Du * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15f46a221bSXiaojian Du * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16f46a221bSXiaojian Du * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17f46a221bSXiaojian Du * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18f46a221bSXiaojian Du * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19f46a221bSXiaojian Du * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20f46a221bSXiaojian Du * OTHER DEALINGS IN THE SOFTWARE. 21f46a221bSXiaojian Du * 22f46a221bSXiaojian Du */ 23f46a221bSXiaojian Du 24f46a221bSXiaojian Du #define SWSMU_CODE_LAYER_L2 25f46a221bSXiaojian Du 26f46a221bSXiaojian Du #include "amdgpu.h" 27f46a221bSXiaojian Du #include "amdgpu_smu.h" 28f46a221bSXiaojian Du #include "smu_v11_0.h" 29f46a221bSXiaojian Du #include "smu11_driver_if_vangogh.h" 30f46a221bSXiaojian Du #include "vangogh_ppt.h" 31f46a221bSXiaojian Du #include "smu_v11_5_ppsmc.h" 32f46a221bSXiaojian Du #include "smu_v11_5_pmfw.h" 33f46a221bSXiaojian Du #include "smu_cmn.h" 34eefdf047SJinzhou Su #include "soc15_common.h" 35eefdf047SJinzhou Su #include "asic_reg/gc/gc_10_3_0_offset.h" 36eefdf047SJinzhou Su #include "asic_reg/gc/gc_10_3_0_sh_mask.h" 37f46a221bSXiaojian Du 38f46a221bSXiaojian Du /* 39f46a221bSXiaojian Du * DO NOT use these for err/warn/info/debug messages. 40f46a221bSXiaojian Du * Use dev_err, dev_warn, dev_info and dev_dbg instead. 41f46a221bSXiaojian Du * They are more MGPU friendly. 42f46a221bSXiaojian Du */ 43f46a221bSXiaojian Du #undef pr_err 44f46a221bSXiaojian Du #undef pr_warn 45f46a221bSXiaojian Du #undef pr_info 46f46a221bSXiaojian Du #undef pr_debug 47f46a221bSXiaojian Du 48f46a221bSXiaojian Du #define FEATURE_MASK(feature) (1ULL << feature) 49f46a221bSXiaojian Du #define SMC_DPM_FEATURE ( \ 50f46a221bSXiaojian Du FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \ 51f46a221bSXiaojian Du FEATURE_MASK(FEATURE_VCN_DPM_BIT) | \ 52f46a221bSXiaojian Du FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ 53f46a221bSXiaojian Du FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT) | \ 54f46a221bSXiaojian Du FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) | \ 55f46a221bSXiaojian Du FEATURE_MASK(FEATURE_LCLK_DPM_BIT) | \ 56f46a221bSXiaojian Du FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT) | \ 57f46a221bSXiaojian Du FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \ 58271ab489SXiaojian Du FEATURE_MASK(FEATURE_GFX_DPM_BIT)) 59f46a221bSXiaojian Du 60f46a221bSXiaojian Du static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = { 61271ab489SXiaojian Du MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), 62271ab489SXiaojian Du MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0), 63271ab489SXiaojian Du MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 0), 64271ab489SXiaojian Du MSG_MAP(EnableGfxOff, PPSMC_MSG_EnableGfxOff, 0), 65271ab489SXiaojian Du MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisableGfxOff, 0), 66271ab489SXiaojian Du MSG_MAP(PowerDownIspByTile, PPSMC_MSG_PowerDownIspByTile, 0), 67271ab489SXiaojian Du MSG_MAP(PowerUpIspByTile, PPSMC_MSG_PowerUpIspByTile, 0), 68271ab489SXiaojian Du MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0), 69271ab489SXiaojian Du MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), 70a0f55287SXiaomeng Hou MSG_MAP(RlcPowerNotify, PPSMC_MSG_RlcPowerNotify, 0), 71271ab489SXiaojian Du MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 0), 72271ab489SXiaojian Du MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxclk, 0), 73271ab489SXiaojian Du MSG_MAP(ActiveProcessNotify, PPSMC_MSG_ActiveProcessNotify, 0), 74271ab489SXiaojian Du MSG_MAP(SetHardMinIspiclkByFreq, PPSMC_MSG_SetHardMinIspiclkByFreq, 0), 75271ab489SXiaojian Du MSG_MAP(SetHardMinIspxclkByFreq, PPSMC_MSG_SetHardMinIspxclkByFreq, 0), 76271ab489SXiaojian Du MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 0), 77271ab489SXiaojian Du MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 0), 78271ab489SXiaojian Du MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), 79271ab489SXiaojian Du MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), 80271ab489SXiaojian Du MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 0), 81271ab489SXiaojian Du MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 0), 82271ab489SXiaojian Du MSG_MAP(Spare1, PPSMC_MSG_spare1, 0), 83271ab489SXiaojian Du MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 0), 84271ab489SXiaojian Du MSG_MAP(SetSoftMinFclk, PPSMC_MSG_SetSoftMinFclk, 0), 85271ab489SXiaojian Du MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 0), 86271ab489SXiaojian Du MSG_MAP(EnablePostCode, PPSMC_MSG_EnablePostCode, 0), 87271ab489SXiaojian Du MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 0), 88271ab489SXiaojian Du MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 0), 89271ab489SXiaojian Du MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 0), 90271ab489SXiaojian Du MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 0), 91271ab489SXiaojian Du MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 0), 92271ab489SXiaojian Du MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 0), 93271ab489SXiaojian Du MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 0), 94271ab489SXiaojian Du MSG_MAP(Spare2, PPSMC_MSG_spare2, 0), 95271ab489SXiaojian Du MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 0), 96271ab489SXiaojian Du MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0), 97271ab489SXiaojian Du MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0), 98271ab489SXiaojian Du MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 0), 99271ab489SXiaojian Du MSG_MAP(SetSoftMinSocclkByFreq, PPSMC_MSG_SetSoftMinSocclkByFreq, 0), 100271ab489SXiaojian Du MSG_MAP(PowerUpCvip, PPSMC_MSG_PowerUpCvip, 0), 101271ab489SXiaojian Du MSG_MAP(PowerDownCvip, PPSMC_MSG_PowerDownCvip, 0), 102271ab489SXiaojian Du MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), 103271ab489SXiaojian Du MSG_MAP(GetThermalLimit, PPSMC_MSG_GetThermalLimit, 0), 104271ab489SXiaojian Du MSG_MAP(GetCurrentTemperature, PPSMC_MSG_GetCurrentTemperature, 0), 105271ab489SXiaojian Du MSG_MAP(GetCurrentPower, PPSMC_MSG_GetCurrentPower, 0), 106271ab489SXiaojian Du MSG_MAP(GetCurrentVoltage, PPSMC_MSG_GetCurrentVoltage, 0), 107271ab489SXiaojian Du MSG_MAP(GetCurrentCurrent, PPSMC_MSG_GetCurrentCurrent, 0), 108271ab489SXiaojian Du MSG_MAP(GetAverageCpuActivity, PPSMC_MSG_GetAverageCpuActivity, 0), 109271ab489SXiaojian Du MSG_MAP(GetAverageGfxActivity, PPSMC_MSG_GetAverageGfxActivity, 0), 110271ab489SXiaojian Du MSG_MAP(GetAveragePower, PPSMC_MSG_GetAveragePower, 0), 111271ab489SXiaojian Du MSG_MAP(GetAverageTemperature, PPSMC_MSG_GetAverageTemperature, 0), 112271ab489SXiaojian Du MSG_MAP(SetAveragePowerTimeConstant, PPSMC_MSG_SetAveragePowerTimeConstant, 0), 113271ab489SXiaojian Du MSG_MAP(SetAverageActivityTimeConstant, PPSMC_MSG_SetAverageActivityTimeConstant, 0), 114271ab489SXiaojian Du MSG_MAP(SetAverageTemperatureTimeConstant, PPSMC_MSG_SetAverageTemperatureTimeConstant, 0), 115271ab489SXiaojian Du MSG_MAP(SetMitigationEndHysteresis, PPSMC_MSG_SetMitigationEndHysteresis, 0), 116271ab489SXiaojian Du MSG_MAP(GetCurrentFreq, PPSMC_MSG_GetCurrentFreq, 0), 117271ab489SXiaojian Du MSG_MAP(SetReducedPptLimit, PPSMC_MSG_SetReducedPptLimit, 0), 118271ab489SXiaojian Du MSG_MAP(SetReducedThermalLimit, PPSMC_MSG_SetReducedThermalLimit, 0), 119271ab489SXiaojian Du MSG_MAP(DramLogSetDramAddr, PPSMC_MSG_DramLogSetDramAddr, 0), 120271ab489SXiaojian Du MSG_MAP(StartDramLogging, PPSMC_MSG_StartDramLogging, 0), 121271ab489SXiaojian Du MSG_MAP(StopDramLogging, PPSMC_MSG_StopDramLogging, 0), 122271ab489SXiaojian Du MSG_MAP(SetSoftMinCclk, PPSMC_MSG_SetSoftMinCclk, 0), 123271ab489SXiaojian Du MSG_MAP(SetSoftMaxCclk, PPSMC_MSG_SetSoftMaxCclk, 0), 124eefdf047SJinzhou Su MSG_MAP(RequestActiveWgp, PPSMC_MSG_RequestActiveWgp, 0), 125f46a221bSXiaojian Du }; 126f46a221bSXiaojian Du 127f46a221bSXiaojian Du static struct cmn2asic_mapping vangogh_feature_mask_map[SMU_FEATURE_COUNT] = { 128f46a221bSXiaojian Du FEA_MAP(PPT), 129f46a221bSXiaojian Du FEA_MAP(TDC), 130f46a221bSXiaojian Du FEA_MAP(THERMAL), 131f46a221bSXiaojian Du FEA_MAP(DS_GFXCLK), 132f46a221bSXiaojian Du FEA_MAP(DS_SOCCLK), 133f46a221bSXiaojian Du FEA_MAP(DS_LCLK), 134f46a221bSXiaojian Du FEA_MAP(DS_FCLK), 135f46a221bSXiaojian Du FEA_MAP(DS_MP1CLK), 136f46a221bSXiaojian Du FEA_MAP(DS_MP0CLK), 137f46a221bSXiaojian Du FEA_MAP(ATHUB_PG), 138f46a221bSXiaojian Du FEA_MAP(CCLK_DPM), 139f46a221bSXiaojian Du FEA_MAP(FAN_CONTROLLER), 140f46a221bSXiaojian Du FEA_MAP(ULV), 141f46a221bSXiaojian Du FEA_MAP(VCN_DPM), 142f46a221bSXiaojian Du FEA_MAP(LCLK_DPM), 143f46a221bSXiaojian Du FEA_MAP(SHUBCLK_DPM), 144f46a221bSXiaojian Du FEA_MAP(DCFCLK_DPM), 145f46a221bSXiaojian Du FEA_MAP(DS_DCFCLK), 146f46a221bSXiaojian Du FEA_MAP(S0I2), 147f46a221bSXiaojian Du FEA_MAP(SMU_LOW_POWER), 148f46a221bSXiaojian Du FEA_MAP(GFX_DEM), 149f46a221bSXiaojian Du FEA_MAP(PSI), 150f46a221bSXiaojian Du FEA_MAP(PROCHOT), 151f46a221bSXiaojian Du FEA_MAP(CPUOFF), 152f46a221bSXiaojian Du FEA_MAP(STAPM), 153f46a221bSXiaojian Du FEA_MAP(S0I3), 154f46a221bSXiaojian Du FEA_MAP(DF_CSTATES), 155f46a221bSXiaojian Du FEA_MAP(PERF_LIMIT), 156f46a221bSXiaojian Du FEA_MAP(CORE_DLDO), 157f46a221bSXiaojian Du FEA_MAP(RSMU_LOW_POWER), 158f46a221bSXiaojian Du FEA_MAP(SMN_LOW_POWER), 159f46a221bSXiaojian Du FEA_MAP(THM_LOW_POWER), 160f46a221bSXiaojian Du FEA_MAP(SMUIO_LOW_POWER), 161f46a221bSXiaojian Du FEA_MAP(MP1_LOW_POWER), 162f46a221bSXiaojian Du FEA_MAP(DS_VCN), 163f46a221bSXiaojian Du FEA_MAP(CPPC), 164f46a221bSXiaojian Du FEA_MAP(OS_CSTATES), 165f46a221bSXiaojian Du FEA_MAP(ISP_DPM), 166f46a221bSXiaojian Du FEA_MAP(A55_DPM), 167f46a221bSXiaojian Du FEA_MAP(CVIP_DSP_DPM), 168f46a221bSXiaojian Du FEA_MAP(MSMU_LOW_POWER), 16954800b58SXiaojian Du FEA_MAP_REVERSE(SOCCLK), 17054800b58SXiaojian Du FEA_MAP_REVERSE(FCLK), 17154800b58SXiaojian Du FEA_MAP_HALF_REVERSE(GFX), 172f46a221bSXiaojian Du }; 173f46a221bSXiaojian Du 174f46a221bSXiaojian Du static struct cmn2asic_mapping vangogh_table_map[SMU_TABLE_COUNT] = { 175f46a221bSXiaojian Du TAB_MAP_VALID(WATERMARKS), 176f46a221bSXiaojian Du TAB_MAP_VALID(SMU_METRICS), 177f46a221bSXiaojian Du TAB_MAP_VALID(CUSTOM_DPM), 178f46a221bSXiaojian Du TAB_MAP_VALID(DPMCLOCKS), 179f46a221bSXiaojian Du }; 180f46a221bSXiaojian Du 181f46a221bSXiaojian Du static int vangogh_tables_init(struct smu_context *smu) 182f46a221bSXiaojian Du { 183f46a221bSXiaojian Du struct smu_table_context *smu_table = &smu->smu_table; 184f46a221bSXiaojian Du struct smu_table *tables = smu_table->tables; 185f46a221bSXiaojian Du 186f46a221bSXiaojian Du SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), 187f46a221bSXiaojian Du PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 188f46a221bSXiaojian Du SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), 189f46a221bSXiaojian Du PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 190f46a221bSXiaojian Du SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), 191f46a221bSXiaojian Du PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 192f46a221bSXiaojian Du SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, 193f46a221bSXiaojian Du PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 194f46a221bSXiaojian Du SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t), 195f46a221bSXiaojian Du PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 196f46a221bSXiaojian Du smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); 197f46a221bSXiaojian Du if (!smu_table->metrics_table) 198f46a221bSXiaojian Du goto err0_out; 199f46a221bSXiaojian Du smu_table->metrics_time = 0; 200f46a221bSXiaojian Du 201f46a221bSXiaojian Du smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0); 202f46a221bSXiaojian Du smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 203f46a221bSXiaojian Du if (!smu_table->gpu_metrics_table) 204f46a221bSXiaojian Du goto err1_out; 205f46a221bSXiaojian Du 206f46a221bSXiaojian Du smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); 207f46a221bSXiaojian Du if (!smu_table->watermarks_table) 208f46a221bSXiaojian Du goto err2_out; 209f46a221bSXiaojian Du 210c98ee897SXiaojian Du smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); 211c98ee897SXiaojian Du if (!smu_table->clocks_table) 212c98ee897SXiaojian Du goto err3_out; 213c98ee897SXiaojian Du 214f46a221bSXiaojian Du return 0; 215f46a221bSXiaojian Du 216c98ee897SXiaojian Du err3_out: 217c98ee897SXiaojian Du kfree(smu_table->clocks_table); 218f46a221bSXiaojian Du err2_out: 219f46a221bSXiaojian Du kfree(smu_table->gpu_metrics_table); 220f46a221bSXiaojian Du err1_out: 221f46a221bSXiaojian Du kfree(smu_table->metrics_table); 222f46a221bSXiaojian Du err0_out: 223f46a221bSXiaojian Du return -ENOMEM; 224f46a221bSXiaojian Du } 225f46a221bSXiaojian Du 226271ab489SXiaojian Du static int vangogh_get_smu_metrics_data(struct smu_context *smu, 227271ab489SXiaojian Du MetricsMember_t member, 228271ab489SXiaojian Du uint32_t *value) 229271ab489SXiaojian Du { 230271ab489SXiaojian Du struct smu_table_context *smu_table = &smu->smu_table; 231271ab489SXiaojian Du 232271ab489SXiaojian Du SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; 233271ab489SXiaojian Du int ret = 0; 234271ab489SXiaojian Du 235271ab489SXiaojian Du mutex_lock(&smu->metrics_lock); 236271ab489SXiaojian Du 237271ab489SXiaojian Du ret = smu_cmn_get_metrics_table_locked(smu, 238271ab489SXiaojian Du NULL, 239271ab489SXiaojian Du false); 240271ab489SXiaojian Du if (ret) { 241271ab489SXiaojian Du mutex_unlock(&smu->metrics_lock); 242271ab489SXiaojian Du return ret; 243271ab489SXiaojian Du } 244271ab489SXiaojian Du 245271ab489SXiaojian Du switch (member) { 246271ab489SXiaojian Du case METRICS_AVERAGE_GFXCLK: 247271ab489SXiaojian Du *value = metrics->GfxclkFrequency; 248271ab489SXiaojian Du break; 249271ab489SXiaojian Du case METRICS_AVERAGE_SOCCLK: 250271ab489SXiaojian Du *value = metrics->SocclkFrequency; 251271ab489SXiaojian Du break; 252f02c7336SXiaojian Du case METRICS_AVERAGE_VCLK: 253f02c7336SXiaojian Du *value = metrics->VclkFrequency; 254f02c7336SXiaojian Du break; 255f02c7336SXiaojian Du case METRICS_AVERAGE_DCLK: 256f02c7336SXiaojian Du *value = metrics->DclkFrequency; 257f02c7336SXiaojian Du break; 258271ab489SXiaojian Du case METRICS_AVERAGE_UCLK: 259271ab489SXiaojian Du *value = metrics->MemclkFrequency; 260271ab489SXiaojian Du break; 261271ab489SXiaojian Du case METRICS_AVERAGE_GFXACTIVITY: 262271ab489SXiaojian Du *value = metrics->GfxActivity / 100; 263271ab489SXiaojian Du break; 264271ab489SXiaojian Du case METRICS_AVERAGE_VCNACTIVITY: 265271ab489SXiaojian Du *value = metrics->UvdActivity; 266271ab489SXiaojian Du break; 267271ab489SXiaojian Du case METRICS_AVERAGE_SOCKETPOWER: 26823289a22SXiaojian Du *value = (metrics->CurrentSocketPower << 8) / 26923289a22SXiaojian Du 1000 ; 270271ab489SXiaojian Du break; 271271ab489SXiaojian Du case METRICS_TEMPERATURE_EDGE: 272271ab489SXiaojian Du *value = metrics->GfxTemperature / 100 * 273271ab489SXiaojian Du SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 274271ab489SXiaojian Du break; 275271ab489SXiaojian Du case METRICS_TEMPERATURE_HOTSPOT: 276271ab489SXiaojian Du *value = metrics->SocTemperature / 100 * 277271ab489SXiaojian Du SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 278271ab489SXiaojian Du break; 279271ab489SXiaojian Du case METRICS_THROTTLER_STATUS: 280271ab489SXiaojian Du *value = metrics->ThrottlerStatus; 281271ab489SXiaojian Du break; 2822139d12bSAlex Deucher case METRICS_VOLTAGE_VDDGFX: 2832139d12bSAlex Deucher *value = metrics->Voltage[2]; 2842139d12bSAlex Deucher break; 2852139d12bSAlex Deucher case METRICS_VOLTAGE_VDDSOC: 2862139d12bSAlex Deucher *value = metrics->Voltage[1]; 2872139d12bSAlex Deucher break; 288271ab489SXiaojian Du default: 289271ab489SXiaojian Du *value = UINT_MAX; 290271ab489SXiaojian Du break; 291271ab489SXiaojian Du } 292271ab489SXiaojian Du 293271ab489SXiaojian Du mutex_unlock(&smu->metrics_lock); 294271ab489SXiaojian Du 295271ab489SXiaojian Du return ret; 296271ab489SXiaojian Du } 297271ab489SXiaojian Du 298f46a221bSXiaojian Du static int vangogh_allocate_dpm_context(struct smu_context *smu) 299f46a221bSXiaojian Du { 300f46a221bSXiaojian Du struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 301f46a221bSXiaojian Du 302f46a221bSXiaojian Du smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), 303f46a221bSXiaojian Du GFP_KERNEL); 304f46a221bSXiaojian Du if (!smu_dpm->dpm_context) 305f46a221bSXiaojian Du return -ENOMEM; 306f46a221bSXiaojian Du 307f46a221bSXiaojian Du smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); 308f46a221bSXiaojian Du 309f46a221bSXiaojian Du return 0; 310f46a221bSXiaojian Du } 311f46a221bSXiaojian Du 312f46a221bSXiaojian Du static int vangogh_init_smc_tables(struct smu_context *smu) 313f46a221bSXiaojian Du { 314f46a221bSXiaojian Du int ret = 0; 315f46a221bSXiaojian Du 316f46a221bSXiaojian Du ret = vangogh_tables_init(smu); 317f46a221bSXiaojian Du if (ret) 318f46a221bSXiaojian Du return ret; 319f46a221bSXiaojian Du 320f46a221bSXiaojian Du ret = vangogh_allocate_dpm_context(smu); 321f46a221bSXiaojian Du if (ret) 322f46a221bSXiaojian Du return ret; 323f46a221bSXiaojian Du 324f46a221bSXiaojian Du return smu_v11_0_init_smc_tables(smu); 325f46a221bSXiaojian Du } 326f46a221bSXiaojian Du 327f46a221bSXiaojian Du static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable) 328f46a221bSXiaojian Du { 329f46a221bSXiaojian Du int ret = 0; 330f46a221bSXiaojian Du 331f46a221bSXiaojian Du if (enable) { 332f46a221bSXiaojian Du /* vcn dpm on is a prerequisite for vcn power gate messages */ 333271ab489SXiaojian Du if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { 334f46a221bSXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); 335f46a221bSXiaojian Du if (ret) 336f46a221bSXiaojian Du return ret; 337f46a221bSXiaojian Du } 338f46a221bSXiaojian Du } else { 339271ab489SXiaojian Du if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { 340f46a221bSXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); 341f46a221bSXiaojian Du if (ret) 342f46a221bSXiaojian Du return ret; 343f46a221bSXiaojian Du } 344f46a221bSXiaojian Du } 345f46a221bSXiaojian Du 346f46a221bSXiaojian Du return ret; 347f46a221bSXiaojian Du } 348f46a221bSXiaojian Du 349f46a221bSXiaojian Du static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) 350f46a221bSXiaojian Du { 351f46a221bSXiaojian Du int ret = 0; 352f46a221bSXiaojian Du 353f46a221bSXiaojian Du if (enable) { 354271ab489SXiaojian Du if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { 355f46a221bSXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); 356f46a221bSXiaojian Du if (ret) 357f46a221bSXiaojian Du return ret; 358f46a221bSXiaojian Du } 359f46a221bSXiaojian Du } else { 360271ab489SXiaojian Du if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { 361f46a221bSXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); 362f46a221bSXiaojian Du if (ret) 363f46a221bSXiaojian Du return ret; 364f46a221bSXiaojian Du } 365f46a221bSXiaojian Du } 366f46a221bSXiaojian Du 367f46a221bSXiaojian Du return ret; 368f46a221bSXiaojian Du } 369f46a221bSXiaojian Du 370f46a221bSXiaojian Du static int vangogh_get_allowed_feature_mask(struct smu_context *smu, 371f46a221bSXiaojian Du uint32_t *feature_mask, 372f46a221bSXiaojian Du uint32_t num) 373f46a221bSXiaojian Du { 374f46a221bSXiaojian Du struct amdgpu_device *adev = smu->adev; 375f46a221bSXiaojian Du 376f46a221bSXiaojian Du if (num > 2) 377f46a221bSXiaojian Du return -EINVAL; 378f46a221bSXiaojian Du 379f46a221bSXiaojian Du memset(feature_mask, 0, sizeof(uint32_t) * num); 380f46a221bSXiaojian Du 381f46a221bSXiaojian Du *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_DPM_BIT) 382f46a221bSXiaojian Du | FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) 38354800b58SXiaojian Du | FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT) 38454800b58SXiaojian Du | FEATURE_MASK(FEATURE_VCN_DPM_BIT) 38554800b58SXiaojian Du | FEATURE_MASK(FEATURE_FCLK_DPM_BIT) 38654800b58SXiaojian Du | FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT) 387f46a221bSXiaojian Du | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) 388f46a221bSXiaojian Du | FEATURE_MASK(FEATURE_PPT_BIT) 389f46a221bSXiaojian Du | FEATURE_MASK(FEATURE_TDC_BIT) 390f46a221bSXiaojian Du | FEATURE_MASK(FEATURE_FAN_CONTROLLER_BIT) 391f46a221bSXiaojian Du | FEATURE_MASK(FEATURE_DS_LCLK_BIT) 392f46a221bSXiaojian Du | FEATURE_MASK(FEATURE_DS_DCFCLK_BIT); 393f46a221bSXiaojian Du 394f46a221bSXiaojian Du if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) 395f46a221bSXiaojian Du *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT); 396f46a221bSXiaojian Du 397f46a221bSXiaojian Du if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK) 398f46a221bSXiaojian Du *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT); 399f46a221bSXiaojian Du 40054800b58SXiaojian Du if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) 40154800b58SXiaojian Du *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FCLK_DPM_BIT); 40254800b58SXiaojian Du 40354800b58SXiaojian Du if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) 40454800b58SXiaojian Du *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_DPM_BIT); 40554800b58SXiaojian Du 406f46a221bSXiaojian Du if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) 407f46a221bSXiaojian Du *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT); 408f46a221bSXiaojian Du 409f46a221bSXiaojian Du return 0; 410f46a221bSXiaojian Du } 411f46a221bSXiaojian Du 412f46a221bSXiaojian Du static bool vangogh_is_dpm_running(struct smu_context *smu) 413f46a221bSXiaojian Du { 414271ab489SXiaojian Du int ret = 0; 415271ab489SXiaojian Du uint32_t feature_mask[2]; 416271ab489SXiaojian Du uint64_t feature_enabled; 417f46a221bSXiaojian Du 418271ab489SXiaojian Du ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); 419271ab489SXiaojian Du 420271ab489SXiaojian Du if (ret) 421f46a221bSXiaojian Du return false; 422f46a221bSXiaojian Du 423271ab489SXiaojian Du feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | 424271ab489SXiaojian Du ((uint64_t)feature_mask[1] << 32)); 425271ab489SXiaojian Du 426271ab489SXiaojian Du return !!(feature_enabled & SMC_DPM_FEATURE); 427271ab489SXiaojian Du } 428271ab489SXiaojian Du 429ae7b32e7SXiaojian Du static int vangogh_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type, 430ae7b32e7SXiaojian Du uint32_t dpm_level, uint32_t *freq) 431ae7b32e7SXiaojian Du { 432ae7b32e7SXiaojian Du DpmClocks_t *clk_table = smu->smu_table.clocks_table; 433ae7b32e7SXiaojian Du 434ae7b32e7SXiaojian Du if (!clk_table || clk_type >= SMU_CLK_COUNT) 435ae7b32e7SXiaojian Du return -EINVAL; 436ae7b32e7SXiaojian Du 437ae7b32e7SXiaojian Du switch (clk_type) { 438ae7b32e7SXiaojian Du case SMU_SOCCLK: 439ae7b32e7SXiaojian Du if (dpm_level >= clk_table->NumSocClkLevelsEnabled) 440ae7b32e7SXiaojian Du return -EINVAL; 441ae7b32e7SXiaojian Du *freq = clk_table->SocClocks[dpm_level]; 442ae7b32e7SXiaojian Du break; 443f02c7336SXiaojian Du case SMU_VCLK: 444f02c7336SXiaojian Du if (dpm_level >= clk_table->VcnClkLevelsEnabled) 445f02c7336SXiaojian Du return -EINVAL; 446f02c7336SXiaojian Du *freq = clk_table->VcnClocks[dpm_level].vclk; 447f02c7336SXiaojian Du break; 448f02c7336SXiaojian Du case SMU_DCLK: 449f02c7336SXiaojian Du if (dpm_level >= clk_table->VcnClkLevelsEnabled) 450f02c7336SXiaojian Du return -EINVAL; 451f02c7336SXiaojian Du *freq = clk_table->VcnClocks[dpm_level].dclk; 452f02c7336SXiaojian Du break; 453ae7b32e7SXiaojian Du case SMU_UCLK: 454ae7b32e7SXiaojian Du case SMU_MCLK: 455ae7b32e7SXiaojian Du if (dpm_level >= clk_table->NumDfPstatesEnabled) 456ae7b32e7SXiaojian Du return -EINVAL; 457ae7b32e7SXiaojian Du *freq = clk_table->DfPstateTable[dpm_level].memclk; 458ae7b32e7SXiaojian Du 459ae7b32e7SXiaojian Du break; 460ae7b32e7SXiaojian Du case SMU_FCLK: 461ae7b32e7SXiaojian Du if (dpm_level >= clk_table->NumDfPstatesEnabled) 462ae7b32e7SXiaojian Du return -EINVAL; 463ae7b32e7SXiaojian Du *freq = clk_table->DfPstateTable[dpm_level].fclk; 464ae7b32e7SXiaojian Du break; 465ae7b32e7SXiaojian Du default: 466ae7b32e7SXiaojian Du return -EINVAL; 467ae7b32e7SXiaojian Du } 468ae7b32e7SXiaojian Du 469ae7b32e7SXiaojian Du return 0; 470ae7b32e7SXiaojian Du } 471ae7b32e7SXiaojian Du 472c98ee897SXiaojian Du static int vangogh_print_fine_grain_clk(struct smu_context *smu, 473c98ee897SXiaojian Du enum smu_clk_type clk_type, char *buf) 474c98ee897SXiaojian Du { 475ae7b32e7SXiaojian Du DpmClocks_t *clk_table = smu->smu_table.clocks_table; 476ae7b32e7SXiaojian Du SmuMetrics_t metrics; 477ae7b32e7SXiaojian Du int i, size = 0, ret = 0; 478ae7b32e7SXiaojian Du uint32_t cur_value = 0, value = 0, count = 0; 479ae7b32e7SXiaojian Du bool cur_value_match_level = false; 480ae7b32e7SXiaojian Du 481ae7b32e7SXiaojian Du memset(&metrics, 0, sizeof(metrics)); 482ae7b32e7SXiaojian Du 483ae7b32e7SXiaojian Du ret = smu_cmn_get_metrics_table(smu, &metrics, false); 484ae7b32e7SXiaojian Du if (ret) 485ae7b32e7SXiaojian Du return ret; 486c98ee897SXiaojian Du 487c98ee897SXiaojian Du switch (clk_type) { 488c98ee897SXiaojian Du case SMU_OD_SCLK: 489c98ee897SXiaojian Du if (smu->od_enabled) { 490c98ee897SXiaojian Du size = sprintf(buf, "%s:\n", "OD_SCLK"); 491c98ee897SXiaojian Du size += sprintf(buf + size, "0: %10uMhz\n", 492c98ee897SXiaojian Du (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); 493c98ee897SXiaojian Du size += sprintf(buf + size, "1: %10uMhz\n", 494c98ee897SXiaojian Du (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); 495c98ee897SXiaojian Du } 496c98ee897SXiaojian Du break; 497c98ee897SXiaojian Du case SMU_OD_RANGE: 498c98ee897SXiaojian Du if (smu->od_enabled) { 499c98ee897SXiaojian Du size = sprintf(buf, "%s:\n", "OD_RANGE"); 500c98ee897SXiaojian Du size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", 501c98ee897SXiaojian Du smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); 502c98ee897SXiaojian Du } 503c98ee897SXiaojian Du break; 504ae7b32e7SXiaojian Du case SMU_SOCCLK: 505ae7b32e7SXiaojian Du /* the level 3 ~ 6 of socclk use the same frequency for vangogh */ 506ae7b32e7SXiaojian Du count = clk_table->NumSocClkLevelsEnabled; 507ae7b32e7SXiaojian Du cur_value = metrics.SocclkFrequency; 508ae7b32e7SXiaojian Du break; 509f02c7336SXiaojian Du case SMU_VCLK: 510f02c7336SXiaojian Du count = clk_table->VcnClkLevelsEnabled; 511f02c7336SXiaojian Du cur_value = metrics.VclkFrequency; 512f02c7336SXiaojian Du break; 513f02c7336SXiaojian Du case SMU_DCLK: 514f02c7336SXiaojian Du count = clk_table->VcnClkLevelsEnabled; 515f02c7336SXiaojian Du cur_value = metrics.DclkFrequency; 516f02c7336SXiaojian Du break; 517ae7b32e7SXiaojian Du case SMU_MCLK: 518ae7b32e7SXiaojian Du count = clk_table->NumDfPstatesEnabled; 519ae7b32e7SXiaojian Du cur_value = metrics.MemclkFrequency; 520ae7b32e7SXiaojian Du break; 521ae7b32e7SXiaojian Du case SMU_FCLK: 522ae7b32e7SXiaojian Du count = clk_table->NumDfPstatesEnabled; 523ae7b32e7SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetFclkFrequency, 0, &cur_value); 524ae7b32e7SXiaojian Du if (ret) 525ae7b32e7SXiaojian Du return ret; 526ae7b32e7SXiaojian Du break; 527ae7b32e7SXiaojian Du default: 528ae7b32e7SXiaojian Du break; 529ae7b32e7SXiaojian Du } 530ae7b32e7SXiaojian Du 531ae7b32e7SXiaojian Du switch (clk_type) { 532ae7b32e7SXiaojian Du case SMU_SOCCLK: 533f02c7336SXiaojian Du case SMU_VCLK: 534f02c7336SXiaojian Du case SMU_DCLK: 535ae7b32e7SXiaojian Du case SMU_MCLK: 536ae7b32e7SXiaojian Du case SMU_FCLK: 537ae7b32e7SXiaojian Du for (i = 0; i < count; i++) { 538ae7b32e7SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value); 539ae7b32e7SXiaojian Du if (ret) 540ae7b32e7SXiaojian Du return ret; 541ae7b32e7SXiaojian Du if (!value) 542ae7b32e7SXiaojian Du continue; 543ae7b32e7SXiaojian Du size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, 544ae7b32e7SXiaojian Du cur_value == value ? "*" : ""); 545ae7b32e7SXiaojian Du if (cur_value == value) 546ae7b32e7SXiaojian Du cur_value_match_level = true; 547ae7b32e7SXiaojian Du } 548ae7b32e7SXiaojian Du 549ae7b32e7SXiaojian Du if (!cur_value_match_level) 550ae7b32e7SXiaojian Du size += sprintf(buf + size, " %uMhz *\n", cur_value); 551ae7b32e7SXiaojian Du break; 552c98ee897SXiaojian Du default: 553c98ee897SXiaojian Du break; 554c98ee897SXiaojian Du } 555c98ee897SXiaojian Du 556c98ee897SXiaojian Du return size; 557c98ee897SXiaojian Du } 558c98ee897SXiaojian Du 559d0e4e112SXiaojian Du static int vangogh_get_profiling_clk_mask(struct smu_context *smu, 560d0e4e112SXiaojian Du enum amd_dpm_forced_level level, 561d0e4e112SXiaojian Du uint32_t *vclk_mask, 562d0e4e112SXiaojian Du uint32_t *dclk_mask, 563d0e4e112SXiaojian Du uint32_t *mclk_mask, 564d0e4e112SXiaojian Du uint32_t *fclk_mask, 565d0e4e112SXiaojian Du uint32_t *soc_mask) 566d0e4e112SXiaojian Du { 567d0e4e112SXiaojian Du DpmClocks_t *clk_table = smu->smu_table.clocks_table; 568d0e4e112SXiaojian Du 569d0e4e112SXiaojian Du if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 570d0e4e112SXiaojian Du if (soc_mask) 571d0e4e112SXiaojian Du *soc_mask = 0; 572d0e4e112SXiaojian Du } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 573d0e4e112SXiaojian Du if (mclk_mask) 574d0e4e112SXiaojian Du /* mclk levels are in reverse order */ 575d0e4e112SXiaojian Du *mclk_mask = clk_table->NumDfPstatesEnabled - 1; 576d0e4e112SXiaojian Du /* fclk levels are in reverse order */ 577d0e4e112SXiaojian Du if (fclk_mask) 578d0e4e112SXiaojian Du *fclk_mask = clk_table->NumDfPstatesEnabled - 1; 579d0e4e112SXiaojian Du } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 580d0e4e112SXiaojian Du if (mclk_mask) 581d0e4e112SXiaojian Du /* mclk levels are in reverse order */ 582d0e4e112SXiaojian Du *mclk_mask = 0; 583d0e4e112SXiaojian Du /* fclk levels are in reverse order */ 584d0e4e112SXiaojian Du if (fclk_mask) 585d0e4e112SXiaojian Du *fclk_mask = 0; 586d0e4e112SXiaojian Du 587d0e4e112SXiaojian Du if (soc_mask) 588d0e4e112SXiaojian Du *soc_mask = clk_table->NumSocClkLevelsEnabled - 1; 589d0e4e112SXiaojian Du } 590d0e4e112SXiaojian Du 591d0e4e112SXiaojian Du return 0; 592d0e4e112SXiaojian Du } 593d0e4e112SXiaojian Du 594d0e4e112SXiaojian Du bool vangogh_clk_dpm_is_enabled(struct smu_context *smu, 595d0e4e112SXiaojian Du enum smu_clk_type clk_type) 596d0e4e112SXiaojian Du { 597d0e4e112SXiaojian Du enum smu_feature_mask feature_id = 0; 598d0e4e112SXiaojian Du 599d0e4e112SXiaojian Du switch (clk_type) { 600d0e4e112SXiaojian Du case SMU_MCLK: 601d0e4e112SXiaojian Du case SMU_UCLK: 602d0e4e112SXiaojian Du case SMU_FCLK: 603d0e4e112SXiaojian Du feature_id = SMU_FEATURE_DPM_FCLK_BIT; 604d0e4e112SXiaojian Du break; 605d0e4e112SXiaojian Du case SMU_GFXCLK: 606d0e4e112SXiaojian Du case SMU_SCLK: 607d0e4e112SXiaojian Du feature_id = SMU_FEATURE_DPM_GFXCLK_BIT; 608d0e4e112SXiaojian Du break; 609d0e4e112SXiaojian Du case SMU_SOCCLK: 610d0e4e112SXiaojian Du feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; 611d0e4e112SXiaojian Du break; 612d0e4e112SXiaojian Du case SMU_VCLK: 613d0e4e112SXiaojian Du case SMU_DCLK: 614d0e4e112SXiaojian Du feature_id = SMU_FEATURE_VCN_DPM_BIT; 615d0e4e112SXiaojian Du break; 616d0e4e112SXiaojian Du default: 617d0e4e112SXiaojian Du return true; 618d0e4e112SXiaojian Du } 619d0e4e112SXiaojian Du 620d0e4e112SXiaojian Du if (!smu_cmn_feature_is_enabled(smu, feature_id)) 621d0e4e112SXiaojian Du return false; 622d0e4e112SXiaojian Du 623d0e4e112SXiaojian Du return true; 624d0e4e112SXiaojian Du } 625d0e4e112SXiaojian Du 626d0e4e112SXiaojian Du static int vangogh_get_dpm_ultimate_freq(struct smu_context *smu, 627d0e4e112SXiaojian Du enum smu_clk_type clk_type, 628d0e4e112SXiaojian Du uint32_t *min, 629d0e4e112SXiaojian Du uint32_t *max) 630d0e4e112SXiaojian Du { 631d0e4e112SXiaojian Du int ret = 0; 632d0e4e112SXiaojian Du uint32_t soc_mask; 633d0e4e112SXiaojian Du uint32_t vclk_mask; 634d0e4e112SXiaojian Du uint32_t dclk_mask; 635d0e4e112SXiaojian Du uint32_t mclk_mask; 636d0e4e112SXiaojian Du uint32_t fclk_mask; 637d0e4e112SXiaojian Du uint32_t clock_limit; 638d0e4e112SXiaojian Du 639d0e4e112SXiaojian Du if (!vangogh_clk_dpm_is_enabled(smu, clk_type)) { 640d0e4e112SXiaojian Du switch (clk_type) { 641d0e4e112SXiaojian Du case SMU_MCLK: 642d0e4e112SXiaojian Du case SMU_UCLK: 643d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.uclk; 644d0e4e112SXiaojian Du break; 645d0e4e112SXiaojian Du case SMU_FCLK: 646d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.fclk; 647d0e4e112SXiaojian Du break; 648d0e4e112SXiaojian Du case SMU_GFXCLK: 649d0e4e112SXiaojian Du case SMU_SCLK: 650d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.gfxclk; 651d0e4e112SXiaojian Du break; 652d0e4e112SXiaojian Du case SMU_SOCCLK: 653d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.socclk; 654d0e4e112SXiaojian Du break; 655d0e4e112SXiaojian Du case SMU_VCLK: 656d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.vclk; 657d0e4e112SXiaojian Du break; 658d0e4e112SXiaojian Du case SMU_DCLK: 659d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.dclk; 660d0e4e112SXiaojian Du break; 661d0e4e112SXiaojian Du default: 662d0e4e112SXiaojian Du clock_limit = 0; 663d0e4e112SXiaojian Du break; 664d0e4e112SXiaojian Du } 665d0e4e112SXiaojian Du 666d0e4e112SXiaojian Du /* clock in Mhz unit */ 667d0e4e112SXiaojian Du if (min) 668d0e4e112SXiaojian Du *min = clock_limit / 100; 669d0e4e112SXiaojian Du if (max) 670d0e4e112SXiaojian Du *max = clock_limit / 100; 671d0e4e112SXiaojian Du 672d0e4e112SXiaojian Du return 0; 673d0e4e112SXiaojian Du } 674d0e4e112SXiaojian Du if (max) { 675d0e4e112SXiaojian Du ret = vangogh_get_profiling_clk_mask(smu, 676d0e4e112SXiaojian Du AMD_DPM_FORCED_LEVEL_PROFILE_PEAK, 677d0e4e112SXiaojian Du &vclk_mask, 678d0e4e112SXiaojian Du &dclk_mask, 679d0e4e112SXiaojian Du &mclk_mask, 680d0e4e112SXiaojian Du &fclk_mask, 681d0e4e112SXiaojian Du &soc_mask); 682d0e4e112SXiaojian Du if (ret) 683d0e4e112SXiaojian Du goto failed; 684d0e4e112SXiaojian Du 685d0e4e112SXiaojian Du switch (clk_type) { 686d0e4e112SXiaojian Du case SMU_UCLK: 687d0e4e112SXiaojian Du case SMU_MCLK: 688d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, max); 689d0e4e112SXiaojian Du if (ret) 690d0e4e112SXiaojian Du goto failed; 691d0e4e112SXiaojian Du break; 692d0e4e112SXiaojian Du case SMU_SOCCLK: 693d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, max); 694d0e4e112SXiaojian Du if (ret) 695d0e4e112SXiaojian Du goto failed; 696d0e4e112SXiaojian Du break; 697d0e4e112SXiaojian Du case SMU_FCLK: 698d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, max); 699d0e4e112SXiaojian Du if (ret) 700d0e4e112SXiaojian Du goto failed; 701d0e4e112SXiaojian Du break; 702d0e4e112SXiaojian Du case SMU_VCLK: 703d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, max); 704d0e4e112SXiaojian Du if (ret) 705d0e4e112SXiaojian Du goto failed; 706d0e4e112SXiaojian Du break; 707d0e4e112SXiaojian Du case SMU_DCLK: 708d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, max); 709d0e4e112SXiaojian Du if (ret) 710d0e4e112SXiaojian Du goto failed; 711d0e4e112SXiaojian Du break; 712d0e4e112SXiaojian Du default: 713d0e4e112SXiaojian Du ret = -EINVAL; 714d0e4e112SXiaojian Du goto failed; 715d0e4e112SXiaojian Du } 716d0e4e112SXiaojian Du } 717d0e4e112SXiaojian Du if (min) { 718d0e4e112SXiaojian Du switch (clk_type) { 719d0e4e112SXiaojian Du case SMU_UCLK: 720d0e4e112SXiaojian Du case SMU_MCLK: 721d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, min); 722d0e4e112SXiaojian Du if (ret) 723d0e4e112SXiaojian Du goto failed; 724d0e4e112SXiaojian Du break; 725d0e4e112SXiaojian Du case SMU_SOCCLK: 726d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, min); 727d0e4e112SXiaojian Du if (ret) 728d0e4e112SXiaojian Du goto failed; 729d0e4e112SXiaojian Du break; 730d0e4e112SXiaojian Du case SMU_FCLK: 731d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, min); 732d0e4e112SXiaojian Du if (ret) 733d0e4e112SXiaojian Du goto failed; 734d0e4e112SXiaojian Du break; 735d0e4e112SXiaojian Du case SMU_VCLK: 736d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, min); 737d0e4e112SXiaojian Du if (ret) 738d0e4e112SXiaojian Du goto failed; 739d0e4e112SXiaojian Du break; 740d0e4e112SXiaojian Du case SMU_DCLK: 741d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, min); 742d0e4e112SXiaojian Du if (ret) 743d0e4e112SXiaojian Du goto failed; 744d0e4e112SXiaojian Du break; 745d0e4e112SXiaojian Du default: 746d0e4e112SXiaojian Du ret = -EINVAL; 747d0e4e112SXiaojian Du goto failed; 748d0e4e112SXiaojian Du } 749d0e4e112SXiaojian Du } 750d0e4e112SXiaojian Du failed: 751d0e4e112SXiaojian Du return ret; 752d0e4e112SXiaojian Du } 753d0e4e112SXiaojian Du 754d0e4e112SXiaojian Du static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) 755d0e4e112SXiaojian Du { 756d0e4e112SXiaojian Du int workload_type, ret; 757d0e4e112SXiaojian Du uint32_t profile_mode = input[size]; 758d0e4e112SXiaojian Du 759d0e4e112SXiaojian Du if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { 760d0e4e112SXiaojian Du dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode); 761d0e4e112SXiaojian Du return -EINVAL; 762d0e4e112SXiaojian Du } 763d0e4e112SXiaojian Du 764d0e4e112SXiaojian Du /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 765d0e4e112SXiaojian Du workload_type = smu_cmn_to_asic_specific_index(smu, 766d0e4e112SXiaojian Du CMN2ASIC_MAPPING_WORKLOAD, 767d0e4e112SXiaojian Du profile_mode); 768d0e4e112SXiaojian Du if (workload_type < 0) { 769d0e4e112SXiaojian Du dev_err_once(smu->adev->dev, "Unsupported power profile mode %d on VANGOGH\n", 770d0e4e112SXiaojian Du profile_mode); 771d0e4e112SXiaojian Du return -EINVAL; 772d0e4e112SXiaojian Du } 773d0e4e112SXiaojian Du 774d0e4e112SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify, 775d0e4e112SXiaojian Du 1 << workload_type, 776d0e4e112SXiaojian Du NULL); 777d0e4e112SXiaojian Du if (ret) { 778d0e4e112SXiaojian Du dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", 779d0e4e112SXiaojian Du workload_type); 780d0e4e112SXiaojian Du return ret; 781d0e4e112SXiaojian Du } 782d0e4e112SXiaojian Du 783d0e4e112SXiaojian Du smu->power_profile_mode = profile_mode; 784d0e4e112SXiaojian Du 785d0e4e112SXiaojian Du return 0; 786d0e4e112SXiaojian Du } 787d0e4e112SXiaojian Du 788dd9e0b21SXiaojian Du static int vangogh_set_soft_freq_limited_range(struct smu_context *smu, 789dd9e0b21SXiaojian Du enum smu_clk_type clk_type, 790dd9e0b21SXiaojian Du uint32_t min, 791dd9e0b21SXiaojian Du uint32_t max) 792dd9e0b21SXiaojian Du { 793dd9e0b21SXiaojian Du int ret = 0; 794dd9e0b21SXiaojian Du 795dd9e0b21SXiaojian Du if (!vangogh_clk_dpm_is_enabled(smu, clk_type)) 796dd9e0b21SXiaojian Du return 0; 797dd9e0b21SXiaojian Du 798dd9e0b21SXiaojian Du switch (clk_type) { 799dd9e0b21SXiaojian Du case SMU_GFXCLK: 800dd9e0b21SXiaojian Du case SMU_SCLK: 801dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 802dd9e0b21SXiaojian Du SMU_MSG_SetHardMinGfxClk, 803dd9e0b21SXiaojian Du min, NULL); 804dd9e0b21SXiaojian Du if (ret) 805dd9e0b21SXiaojian Du return ret; 806dd9e0b21SXiaojian Du 807dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 808dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxGfxClk, 809dd9e0b21SXiaojian Du max, NULL); 810dd9e0b21SXiaojian Du if (ret) 811dd9e0b21SXiaojian Du return ret; 812dd9e0b21SXiaojian Du break; 813dd9e0b21SXiaojian Du case SMU_FCLK: 814dd9e0b21SXiaojian Du case SMU_MCLK: 815dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 816dd9e0b21SXiaojian Du SMU_MSG_SetHardMinFclkByFreq, 817dd9e0b21SXiaojian Du min, NULL); 818dd9e0b21SXiaojian Du if (ret) 819dd9e0b21SXiaojian Du return ret; 820dd9e0b21SXiaojian Du 821dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 822dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxFclkByFreq, 823dd9e0b21SXiaojian Du max, NULL); 824dd9e0b21SXiaojian Du if (ret) 825dd9e0b21SXiaojian Du return ret; 826dd9e0b21SXiaojian Du break; 827dd9e0b21SXiaojian Du case SMU_SOCCLK: 828dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 829dd9e0b21SXiaojian Du SMU_MSG_SetHardMinSocclkByFreq, 830dd9e0b21SXiaojian Du min, NULL); 831dd9e0b21SXiaojian Du if (ret) 832dd9e0b21SXiaojian Du return ret; 833dd9e0b21SXiaojian Du 834dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 835dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxSocclkByFreq, 836dd9e0b21SXiaojian Du max, NULL); 837dd9e0b21SXiaojian Du if (ret) 838dd9e0b21SXiaojian Du return ret; 839dd9e0b21SXiaojian Du break; 840dd9e0b21SXiaojian Du case SMU_VCLK: 841dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 842dd9e0b21SXiaojian Du SMU_MSG_SetHardMinVcn, 843dd9e0b21SXiaojian Du min << 16, NULL); 844dd9e0b21SXiaojian Du if (ret) 845dd9e0b21SXiaojian Du return ret; 846dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 847dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxVcn, 848dd9e0b21SXiaojian Du max << 16, NULL); 849dd9e0b21SXiaojian Du if (ret) 850dd9e0b21SXiaojian Du return ret; 851dd9e0b21SXiaojian Du break; 852dd9e0b21SXiaojian Du case SMU_DCLK: 853dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 854dd9e0b21SXiaojian Du SMU_MSG_SetHardMinVcn, 855dd9e0b21SXiaojian Du min, NULL); 856dd9e0b21SXiaojian Du if (ret) 857dd9e0b21SXiaojian Du return ret; 858dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 859dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxVcn, 860dd9e0b21SXiaojian Du max, NULL); 861dd9e0b21SXiaojian Du if (ret) 862dd9e0b21SXiaojian Du return ret; 863dd9e0b21SXiaojian Du break; 864dd9e0b21SXiaojian Du default: 865dd9e0b21SXiaojian Du return -EINVAL; 866dd9e0b21SXiaojian Du } 867dd9e0b21SXiaojian Du 868dd9e0b21SXiaojian Du return ret; 869dd9e0b21SXiaojian Du } 870dd9e0b21SXiaojian Du 871dd9e0b21SXiaojian Du static int vangogh_force_clk_levels(struct smu_context *smu, 872dd9e0b21SXiaojian Du enum smu_clk_type clk_type, uint32_t mask) 873dd9e0b21SXiaojian Du { 874dd9e0b21SXiaojian Du uint32_t soft_min_level = 0, soft_max_level = 0; 875dd9e0b21SXiaojian Du uint32_t min_freq = 0, max_freq = 0; 876dd9e0b21SXiaojian Du int ret = 0 ; 877dd9e0b21SXiaojian Du 878dd9e0b21SXiaojian Du soft_min_level = mask ? (ffs(mask) - 1) : 0; 879dd9e0b21SXiaojian Du soft_max_level = mask ? (fls(mask) - 1) : 0; 880dd9e0b21SXiaojian Du 881dd9e0b21SXiaojian Du switch (clk_type) { 882dd9e0b21SXiaojian Du case SMU_SOCCLK: 883dd9e0b21SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, 884dd9e0b21SXiaojian Du soft_min_level, &min_freq); 885dd9e0b21SXiaojian Du if (ret) 886dd9e0b21SXiaojian Du return ret; 887dd9e0b21SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, 888dd9e0b21SXiaojian Du soft_max_level, &max_freq); 889dd9e0b21SXiaojian Du if (ret) 890dd9e0b21SXiaojian Du return ret; 891dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 892dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxSocclkByFreq, 893dd9e0b21SXiaojian Du max_freq, NULL); 894dd9e0b21SXiaojian Du if (ret) 895dd9e0b21SXiaojian Du return ret; 896dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 897dd9e0b21SXiaojian Du SMU_MSG_SetHardMinSocclkByFreq, 898dd9e0b21SXiaojian Du min_freq, NULL); 899dd9e0b21SXiaojian Du if (ret) 900dd9e0b21SXiaojian Du return ret; 901dd9e0b21SXiaojian Du break; 902dd9e0b21SXiaojian Du case SMU_MCLK: 903dd9e0b21SXiaojian Du case SMU_FCLK: 904dd9e0b21SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, 905dd9e0b21SXiaojian Du clk_type, soft_min_level, &min_freq); 906dd9e0b21SXiaojian Du if (ret) 907dd9e0b21SXiaojian Du return ret; 908dd9e0b21SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, 909dd9e0b21SXiaojian Du clk_type, soft_max_level, &max_freq); 910dd9e0b21SXiaojian Du if (ret) 911dd9e0b21SXiaojian Du return ret; 912dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 913dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxFclkByFreq, 914dd9e0b21SXiaojian Du max_freq, NULL); 915dd9e0b21SXiaojian Du if (ret) 916dd9e0b21SXiaojian Du return ret; 917dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 918dd9e0b21SXiaojian Du SMU_MSG_SetHardMinFclkByFreq, 919dd9e0b21SXiaojian Du min_freq, NULL); 920dd9e0b21SXiaojian Du if (ret) 921dd9e0b21SXiaojian Du return ret; 922dd9e0b21SXiaojian Du break; 923dd9e0b21SXiaojian Du case SMU_VCLK: 924dd9e0b21SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, 925dd9e0b21SXiaojian Du clk_type, soft_min_level, &min_freq); 926dd9e0b21SXiaojian Du if (ret) 927dd9e0b21SXiaojian Du return ret; 928dd9e0b21SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, 929dd9e0b21SXiaojian Du clk_type, soft_max_level, &max_freq); 930dd9e0b21SXiaojian Du if (ret) 931dd9e0b21SXiaojian Du return ret; 932dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 933dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxVcn, 934dd9e0b21SXiaojian Du max_freq << 16, NULL); 935dd9e0b21SXiaojian Du if (ret) 936dd9e0b21SXiaojian Du return ret; 937dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 938dd9e0b21SXiaojian Du SMU_MSG_SetHardMinVcn, 939dd9e0b21SXiaojian Du min_freq << 16, NULL); 940dd9e0b21SXiaojian Du if (ret) 941dd9e0b21SXiaojian Du return ret; 942dd9e0b21SXiaojian Du break; 943dd9e0b21SXiaojian Du case SMU_DCLK: 944dd9e0b21SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, 945dd9e0b21SXiaojian Du clk_type, soft_min_level, &min_freq); 946dd9e0b21SXiaojian Du if (ret) 947dd9e0b21SXiaojian Du return ret; 948dd9e0b21SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, 949dd9e0b21SXiaojian Du clk_type, soft_max_level, &max_freq); 950dd9e0b21SXiaojian Du if (ret) 951dd9e0b21SXiaojian Du return ret; 952dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 953dd9e0b21SXiaojian Du SMU_MSG_SetSoftMaxVcn, 954dd9e0b21SXiaojian Du max_freq, NULL); 955dd9e0b21SXiaojian Du if (ret) 956dd9e0b21SXiaojian Du return ret; 957dd9e0b21SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, 958dd9e0b21SXiaojian Du SMU_MSG_SetHardMinVcn, 959dd9e0b21SXiaojian Du min_freq, NULL); 960dd9e0b21SXiaojian Du if (ret) 961dd9e0b21SXiaojian Du return ret; 962dd9e0b21SXiaojian Du break; 963dd9e0b21SXiaojian Du default: 964dd9e0b21SXiaojian Du break; 965dd9e0b21SXiaojian Du } 966dd9e0b21SXiaojian Du 967dd9e0b21SXiaojian Du return ret; 968dd9e0b21SXiaojian Du } 969dd9e0b21SXiaojian Du 970dd9e0b21SXiaojian Du static int vangogh_force_dpm_limit_value(struct smu_context *smu, bool highest) 971dd9e0b21SXiaojian Du { 972dd9e0b21SXiaojian Du int ret = 0, i = 0; 973dd9e0b21SXiaojian Du uint32_t min_freq, max_freq, force_freq; 974dd9e0b21SXiaojian Du enum smu_clk_type clk_type; 975dd9e0b21SXiaojian Du 976dd9e0b21SXiaojian Du enum smu_clk_type clks[] = { 977dd9e0b21SXiaojian Du SMU_SOCCLK, 978dd9e0b21SXiaojian Du SMU_VCLK, 979dd9e0b21SXiaojian Du SMU_DCLK, 980dd9e0b21SXiaojian Du SMU_MCLK, 981dd9e0b21SXiaojian Du SMU_FCLK, 982dd9e0b21SXiaojian Du }; 983dd9e0b21SXiaojian Du 984dd9e0b21SXiaojian Du for (i = 0; i < ARRAY_SIZE(clks); i++) { 985dd9e0b21SXiaojian Du clk_type = clks[i]; 986dd9e0b21SXiaojian Du ret = vangogh_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); 987dd9e0b21SXiaojian Du if (ret) 988dd9e0b21SXiaojian Du return ret; 989dd9e0b21SXiaojian Du 990dd9e0b21SXiaojian Du force_freq = highest ? max_freq : min_freq; 991dd9e0b21SXiaojian Du ret = vangogh_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq); 992dd9e0b21SXiaojian Du if (ret) 993dd9e0b21SXiaojian Du return ret; 994dd9e0b21SXiaojian Du } 995dd9e0b21SXiaojian Du 996dd9e0b21SXiaojian Du return ret; 997dd9e0b21SXiaojian Du } 998dd9e0b21SXiaojian Du 999dd9e0b21SXiaojian Du static int vangogh_unforce_dpm_levels(struct smu_context *smu) 1000dd9e0b21SXiaojian Du { 1001dd9e0b21SXiaojian Du int ret = 0, i = 0; 1002dd9e0b21SXiaojian Du uint32_t min_freq, max_freq; 1003dd9e0b21SXiaojian Du enum smu_clk_type clk_type; 1004dd9e0b21SXiaojian Du 1005dd9e0b21SXiaojian Du struct clk_feature_map { 1006dd9e0b21SXiaojian Du enum smu_clk_type clk_type; 1007dd9e0b21SXiaojian Du uint32_t feature; 1008dd9e0b21SXiaojian Du } clk_feature_map[] = { 1009dd9e0b21SXiaojian Du {SMU_MCLK, SMU_FEATURE_DPM_FCLK_BIT}, 1010dd9e0b21SXiaojian Du {SMU_FCLK, SMU_FEATURE_DPM_FCLK_BIT}, 1011dd9e0b21SXiaojian Du {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT}, 1012*b0eec124SXiaojian Du {SMU_VCLK, SMU_FEATURE_VCN_DPM_BIT}, 1013*b0eec124SXiaojian Du {SMU_DCLK, SMU_FEATURE_VCN_DPM_BIT}, 1014dd9e0b21SXiaojian Du }; 1015dd9e0b21SXiaojian Du 1016dd9e0b21SXiaojian Du for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) { 1017dd9e0b21SXiaojian Du 1018dd9e0b21SXiaojian Du if (!smu_cmn_feature_is_enabled(smu, clk_feature_map[i].feature)) 1019dd9e0b21SXiaojian Du continue; 1020dd9e0b21SXiaojian Du 1021dd9e0b21SXiaojian Du clk_type = clk_feature_map[i].clk_type; 1022dd9e0b21SXiaojian Du 1023dd9e0b21SXiaojian Du ret = vangogh_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); 1024dd9e0b21SXiaojian Du 1025dd9e0b21SXiaojian Du if (ret) 1026dd9e0b21SXiaojian Du return ret; 1027dd9e0b21SXiaojian Du 1028dd9e0b21SXiaojian Du ret = vangogh_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); 1029dd9e0b21SXiaojian Du 1030dd9e0b21SXiaojian Du if (ret) 1031dd9e0b21SXiaojian Du return ret; 1032dd9e0b21SXiaojian Du } 1033dd9e0b21SXiaojian Du 1034dd9e0b21SXiaojian Du return ret; 1035dd9e0b21SXiaojian Du } 1036dd9e0b21SXiaojian Du 1037dd9e0b21SXiaojian Du static int vangogh_set_peak_clock_by_device(struct smu_context *smu) 1038dd9e0b21SXiaojian Du { 1039dd9e0b21SXiaojian Du int ret = 0; 1040dd9e0b21SXiaojian Du uint32_t socclk_freq = 0, fclk_freq = 0; 1041dd9e0b21SXiaojian Du 1042dd9e0b21SXiaojian Du ret = vangogh_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_freq); 1043dd9e0b21SXiaojian Du if (ret) 1044dd9e0b21SXiaojian Du return ret; 1045dd9e0b21SXiaojian Du 1046dd9e0b21SXiaojian Du ret = vangogh_set_soft_freq_limited_range(smu, SMU_FCLK, fclk_freq, fclk_freq); 1047dd9e0b21SXiaojian Du if (ret) 1048dd9e0b21SXiaojian Du return ret; 1049dd9e0b21SXiaojian Du 1050dd9e0b21SXiaojian Du ret = vangogh_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_freq); 1051dd9e0b21SXiaojian Du if (ret) 1052dd9e0b21SXiaojian Du return ret; 1053dd9e0b21SXiaojian Du 1054dd9e0b21SXiaojian Du ret = vangogh_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk_freq, socclk_freq); 1055dd9e0b21SXiaojian Du if (ret) 1056dd9e0b21SXiaojian Du return ret; 1057dd9e0b21SXiaojian Du 1058dd9e0b21SXiaojian Du return ret; 1059dd9e0b21SXiaojian Du } 1060dd9e0b21SXiaojian Du 1061ea173d15SXiaojian Du static int vangogh_set_performance_level(struct smu_context *smu, 1062ea173d15SXiaojian Du enum amd_dpm_forced_level level) 1063ea173d15SXiaojian Du { 1064ea173d15SXiaojian Du int ret = 0; 1065ea173d15SXiaojian Du uint32_t soc_mask, mclk_mask, fclk_mask; 1066ea173d15SXiaojian Du 1067ea173d15SXiaojian Du switch (level) { 1068ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_HIGH: 1069ea173d15SXiaojian Du ret = vangogh_force_dpm_limit_value(smu, true); 1070ea173d15SXiaojian Du break; 1071ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_LOW: 1072ea173d15SXiaojian Du ret = vangogh_force_dpm_limit_value(smu, false); 1073ea173d15SXiaojian Du break; 1074ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_AUTO: 1075ea173d15SXiaojian Du ret = vangogh_unforce_dpm_levels(smu); 1076ea173d15SXiaojian Du break; 1077ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 1078ea173d15SXiaojian Du break; 1079ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 1080ea173d15SXiaojian Du break; 1081ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 1082ea173d15SXiaojian Du ret = vangogh_get_profiling_clk_mask(smu, level, 1083ea173d15SXiaojian Du NULL, 1084ea173d15SXiaojian Du NULL, 1085ea173d15SXiaojian Du &mclk_mask, 1086ea173d15SXiaojian Du &fclk_mask, 1087ea173d15SXiaojian Du &soc_mask); 1088ea173d15SXiaojian Du if (ret) 1089ea173d15SXiaojian Du return ret; 1090ea173d15SXiaojian Du vangogh_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask); 1091ea173d15SXiaojian Du vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask); 1092ea173d15SXiaojian Du vangogh_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask); 1093ea173d15SXiaojian Du break; 1094ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 1095ea173d15SXiaojian Du ret = vangogh_set_peak_clock_by_device(smu); 1096ea173d15SXiaojian Du break; 1097ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_MANUAL: 1098ea173d15SXiaojian Du case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 1099ea173d15SXiaojian Du default: 1100ea173d15SXiaojian Du break; 1101ea173d15SXiaojian Du } 1102ea173d15SXiaojian Du return ret; 1103ea173d15SXiaojian Du } 1104ea173d15SXiaojian Du 1105271ab489SXiaojian Du static int vangogh_read_sensor(struct smu_context *smu, 1106271ab489SXiaojian Du enum amd_pp_sensors sensor, 1107271ab489SXiaojian Du void *data, uint32_t *size) 1108271ab489SXiaojian Du { 1109271ab489SXiaojian Du int ret = 0; 1110271ab489SXiaojian Du 1111271ab489SXiaojian Du if (!data || !size) 1112271ab489SXiaojian Du return -EINVAL; 1113271ab489SXiaojian Du 1114271ab489SXiaojian Du mutex_lock(&smu->sensor_lock); 1115271ab489SXiaojian Du switch (sensor) { 1116271ab489SXiaojian Du case AMDGPU_PP_SENSOR_GPU_LOAD: 11176cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 11186cc24d8dSAlex Deucher METRICS_AVERAGE_GFXACTIVITY, 11196cc24d8dSAlex Deucher (uint32_t *)data); 1120271ab489SXiaojian Du *size = 4; 1121271ab489SXiaojian Du break; 1122271ab489SXiaojian Du case AMDGPU_PP_SENSOR_GPU_POWER: 11236cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 11246cc24d8dSAlex Deucher METRICS_AVERAGE_SOCKETPOWER, 11256cc24d8dSAlex Deucher (uint32_t *)data); 1126271ab489SXiaojian Du *size = 4; 1127271ab489SXiaojian Du break; 1128271ab489SXiaojian Du case AMDGPU_PP_SENSOR_EDGE_TEMP: 11296cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 11306cc24d8dSAlex Deucher METRICS_TEMPERATURE_EDGE, 11316cc24d8dSAlex Deucher (uint32_t *)data); 11326cc24d8dSAlex Deucher *size = 4; 11336cc24d8dSAlex Deucher break; 1134271ab489SXiaojian Du case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 11356cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 11366cc24d8dSAlex Deucher METRICS_TEMPERATURE_HOTSPOT, 11376cc24d8dSAlex Deucher (uint32_t *)data); 1138271ab489SXiaojian Du *size = 4; 1139271ab489SXiaojian Du break; 1140271ab489SXiaojian Du case AMDGPU_PP_SENSOR_GFX_MCLK: 11416cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 11426cc24d8dSAlex Deucher METRICS_AVERAGE_UCLK, 11436cc24d8dSAlex Deucher (uint32_t *)data); 1144271ab489SXiaojian Du *(uint32_t *)data *= 100; 1145271ab489SXiaojian Du *size = 4; 1146271ab489SXiaojian Du break; 1147271ab489SXiaojian Du case AMDGPU_PP_SENSOR_GFX_SCLK: 11486cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 11496cc24d8dSAlex Deucher METRICS_AVERAGE_GFXCLK, 11506cc24d8dSAlex Deucher (uint32_t *)data); 1151271ab489SXiaojian Du *(uint32_t *)data *= 100; 1152271ab489SXiaojian Du *size = 4; 1153271ab489SXiaojian Du break; 1154271ab489SXiaojian Du case AMDGPU_PP_SENSOR_VDDGFX: 11552139d12bSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 11562139d12bSAlex Deucher METRICS_VOLTAGE_VDDGFX, 11572139d12bSAlex Deucher (uint32_t *)data); 11582139d12bSAlex Deucher *size = 4; 11592139d12bSAlex Deucher break; 11602139d12bSAlex Deucher case AMDGPU_PP_SENSOR_VDDNB: 11612139d12bSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 11622139d12bSAlex Deucher METRICS_VOLTAGE_VDDSOC, 11632139d12bSAlex Deucher (uint32_t *)data); 1164271ab489SXiaojian Du *size = 4; 1165271ab489SXiaojian Du break; 1166271ab489SXiaojian Du default: 1167271ab489SXiaojian Du ret = -EOPNOTSUPP; 1168271ab489SXiaojian Du break; 1169271ab489SXiaojian Du } 1170271ab489SXiaojian Du mutex_unlock(&smu->sensor_lock); 1171271ab489SXiaojian Du 1172271ab489SXiaojian Du return ret; 1173271ab489SXiaojian Du } 1174271ab489SXiaojian Du 1175271ab489SXiaojian Du static int vangogh_set_watermarks_table(struct smu_context *smu, 1176271ab489SXiaojian Du struct pp_smu_wm_range_sets *clock_ranges) 1177271ab489SXiaojian Du { 1178271ab489SXiaojian Du int i; 1179271ab489SXiaojian Du int ret = 0; 1180271ab489SXiaojian Du Watermarks_t *table = smu->smu_table.watermarks_table; 1181271ab489SXiaojian Du 1182271ab489SXiaojian Du if (!table || !clock_ranges) 1183271ab489SXiaojian Du return -EINVAL; 1184271ab489SXiaojian Du 1185271ab489SXiaojian Du if (clock_ranges) { 1186271ab489SXiaojian Du if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || 1187271ab489SXiaojian Du clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) 1188271ab489SXiaojian Du return -EINVAL; 1189271ab489SXiaojian Du 1190271ab489SXiaojian Du for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { 1191271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].MinClock = 1192271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; 1193271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].MaxClock = 1194271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; 1195271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].MinMclk = 1196271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; 1197271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].MaxMclk = 1198271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; 1199271ab489SXiaojian Du 1200271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].WmSetting = 1201271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].wm_inst; 1202271ab489SXiaojian Du } 1203271ab489SXiaojian Du 1204271ab489SXiaojian Du for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { 1205271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].MinClock = 1206271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; 1207271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].MaxClock = 1208271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; 1209271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].MinMclk = 1210271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; 1211271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].MaxMclk = 1212271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; 1213271ab489SXiaojian Du 1214271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].WmSetting = 1215271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].wm_inst; 1216271ab489SXiaojian Du } 1217271ab489SXiaojian Du 1218271ab489SXiaojian Du smu->watermarks_bitmap |= WATERMARKS_EXIST; 1219271ab489SXiaojian Du } 1220271ab489SXiaojian Du 1221271ab489SXiaojian Du /* pass data to smu controller */ 1222271ab489SXiaojian Du if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 1223271ab489SXiaojian Du !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { 1224271ab489SXiaojian Du ret = smu_cmn_write_watermarks_table(smu); 1225271ab489SXiaojian Du if (ret) { 1226271ab489SXiaojian Du dev_err(smu->adev->dev, "Failed to update WMTABLE!"); 1227271ab489SXiaojian Du return ret; 1228271ab489SXiaojian Du } 1229271ab489SXiaojian Du smu->watermarks_bitmap |= WATERMARKS_LOADED; 1230271ab489SXiaojian Du } 1231271ab489SXiaojian Du 1232271ab489SXiaojian Du return 0; 1233f46a221bSXiaojian Du } 1234f46a221bSXiaojian Du 1235fd253334SXiaojian Du static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, 1236fd253334SXiaojian Du void **table) 1237fd253334SXiaojian Du { 1238fd253334SXiaojian Du struct smu_table_context *smu_table = &smu->smu_table; 1239fd253334SXiaojian Du struct gpu_metrics_v2_0 *gpu_metrics = 1240fd253334SXiaojian Du (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; 1241fd253334SXiaojian Du SmuMetrics_t metrics; 1242fd253334SXiaojian Du int ret = 0; 1243fd253334SXiaojian Du 1244fd253334SXiaojian Du ret = smu_cmn_get_metrics_table(smu, &metrics, true); 1245fd253334SXiaojian Du if (ret) 1246fd253334SXiaojian Du return ret; 1247fd253334SXiaojian Du 1248fd253334SXiaojian Du smu_v11_0_init_gpu_metrics_v2_0(gpu_metrics); 1249fd253334SXiaojian Du 1250fd253334SXiaojian Du gpu_metrics->temperature_gfx = metrics.GfxTemperature; 1251fd253334SXiaojian Du gpu_metrics->temperature_soc = metrics.SocTemperature; 1252fd253334SXiaojian Du memcpy(&gpu_metrics->temperature_core[0], 1253fd253334SXiaojian Du &metrics.CoreTemperature[0], 1254fd253334SXiaojian Du sizeof(uint16_t) * 8); 1255fd253334SXiaojian Du gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; 1256fd253334SXiaojian Du gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; 1257fd253334SXiaojian Du 1258fd253334SXiaojian Du gpu_metrics->average_gfx_activity = metrics.GfxActivity; 1259fd253334SXiaojian Du gpu_metrics->average_mm_activity = metrics.UvdActivity; 1260fd253334SXiaojian Du 1261fd253334SXiaojian Du gpu_metrics->average_socket_power = metrics.CurrentSocketPower; 1262fd253334SXiaojian Du gpu_metrics->average_cpu_power = metrics.Power[0]; 1263fd253334SXiaojian Du gpu_metrics->average_soc_power = metrics.Power[1]; 1264fd253334SXiaojian Du memcpy(&gpu_metrics->average_core_power[0], 1265fd253334SXiaojian Du &metrics.CorePower[0], 1266fd253334SXiaojian Du sizeof(uint16_t) * 8); 1267fd253334SXiaojian Du 1268fd253334SXiaojian Du gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency; 1269fd253334SXiaojian Du gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency; 1270fd253334SXiaojian Du gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency; 1271fd253334SXiaojian Du gpu_metrics->average_vclk_frequency = metrics.VclkFrequency; 1272fd253334SXiaojian Du 1273fd253334SXiaojian Du memcpy(&gpu_metrics->current_coreclk[0], 1274fd253334SXiaojian Du &metrics.CoreFrequency[0], 1275fd253334SXiaojian Du sizeof(uint16_t) * 8); 1276fd253334SXiaojian Du gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; 1277fd253334SXiaojian Du gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; 1278fd253334SXiaojian Du 1279fd253334SXiaojian Du gpu_metrics->throttle_status = metrics.ThrottlerStatus; 1280fd253334SXiaojian Du 1281fd253334SXiaojian Du *table = (void *)gpu_metrics; 1282fd253334SXiaojian Du 1283fd253334SXiaojian Du return sizeof(struct gpu_metrics_v2_0); 1284fd253334SXiaojian Du } 1285fd253334SXiaojian Du 1286c98ee897SXiaojian Du static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, 1287c98ee897SXiaojian Du long input[], uint32_t size) 1288c98ee897SXiaojian Du { 1289c98ee897SXiaojian Du int ret = 0; 1290c98ee897SXiaojian Du 1291c98ee897SXiaojian Du if (!smu->od_enabled) { 1292c98ee897SXiaojian Du dev_warn(smu->adev->dev, "Fine grain is not enabled!\n"); 1293c98ee897SXiaojian Du return -EINVAL; 1294c98ee897SXiaojian Du } 1295c98ee897SXiaojian Du 1296c98ee897SXiaojian Du switch (type) { 1297c98ee897SXiaojian Du case PP_OD_EDIT_SCLK_VDDC_TABLE: 1298c98ee897SXiaojian Du if (size != 2) { 1299c98ee897SXiaojian Du dev_err(smu->adev->dev, "Input parameter number not correct\n"); 1300c98ee897SXiaojian Du return -EINVAL; 1301c98ee897SXiaojian Du } 1302c98ee897SXiaojian Du 1303c98ee897SXiaojian Du if (input[0] == 0) { 1304c98ee897SXiaojian Du if (input[1] < smu->gfx_default_hard_min_freq) { 130517863170SColin Ian King dev_warn(smu->adev->dev, "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", 1306c98ee897SXiaojian Du input[1], smu->gfx_default_hard_min_freq); 1307c98ee897SXiaojian Du return -EINVAL; 1308c98ee897SXiaojian Du } 1309c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq = input[1]; 1310c98ee897SXiaojian Du } else if (input[0] == 1) { 1311c98ee897SXiaojian Du if (input[1] > smu->gfx_default_soft_max_freq) { 131217863170SColin Ian King dev_warn(smu->adev->dev, "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", 1313c98ee897SXiaojian Du input[1], smu->gfx_default_soft_max_freq); 1314c98ee897SXiaojian Du return -EINVAL; 1315c98ee897SXiaojian Du } 1316c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq = input[1]; 1317c98ee897SXiaojian Du } else { 1318c98ee897SXiaojian Du return -EINVAL; 1319c98ee897SXiaojian Du } 1320c98ee897SXiaojian Du break; 1321c98ee897SXiaojian Du case PP_OD_RESTORE_DEFAULT_TABLE: 1322c98ee897SXiaojian Du if (size != 0) { 1323c98ee897SXiaojian Du dev_err(smu->adev->dev, "Input parameter number not correct\n"); 1324c98ee897SXiaojian Du return -EINVAL; 1325c98ee897SXiaojian Du } else { 1326c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 1327c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 1328c98ee897SXiaojian Du 1329c98ee897SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 1330c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq, NULL); 1331c98ee897SXiaojian Du if (ret) { 1332c98ee897SXiaojian Du dev_err(smu->adev->dev, "Restore the default hard min sclk failed!"); 1333c98ee897SXiaojian Du return ret; 1334c98ee897SXiaojian Du } 1335c98ee897SXiaojian Du 1336c98ee897SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 1337c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq, NULL); 1338c98ee897SXiaojian Du if (ret) { 1339c98ee897SXiaojian Du dev_err(smu->adev->dev, "Restore the default soft max sclk failed!"); 1340c98ee897SXiaojian Du return ret; 1341c98ee897SXiaojian Du } 1342c98ee897SXiaojian Du } 1343c98ee897SXiaojian Du break; 1344c98ee897SXiaojian Du case PP_OD_COMMIT_DPM_TABLE: 1345c98ee897SXiaojian Du if (size != 0) { 1346c98ee897SXiaojian Du dev_err(smu->adev->dev, "Input parameter number not correct\n"); 1347c98ee897SXiaojian Du return -EINVAL; 1348c98ee897SXiaojian Du } else { 1349c98ee897SXiaojian Du if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { 1350c98ee897SXiaojian Du dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", 1351c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq); 1352c98ee897SXiaojian Du return -EINVAL; 1353c98ee897SXiaojian Du } 1354c98ee897SXiaojian Du 1355c98ee897SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 1356c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq, NULL); 1357c98ee897SXiaojian Du if (ret) { 1358c98ee897SXiaojian Du dev_err(smu->adev->dev, "Set hard min sclk failed!"); 1359c98ee897SXiaojian Du return ret; 1360c98ee897SXiaojian Du } 1361c98ee897SXiaojian Du 1362c98ee897SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 1363c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq, NULL); 1364c98ee897SXiaojian Du if (ret) { 1365c98ee897SXiaojian Du dev_err(smu->adev->dev, "Set soft max sclk failed!"); 1366c98ee897SXiaojian Du return ret; 1367c98ee897SXiaojian Du } 1368c98ee897SXiaojian Du } 1369c98ee897SXiaojian Du break; 1370c98ee897SXiaojian Du default: 1371c98ee897SXiaojian Du return -ENOSYS; 1372c98ee897SXiaojian Du } 1373c98ee897SXiaojian Du 1374c98ee897SXiaojian Du return ret; 1375c98ee897SXiaojian Du } 1376c98ee897SXiaojian Du 1377fce8a4acSJinzhou Su static int vangogh_set_default_dpm_tables(struct smu_context *smu) 1378c98ee897SXiaojian Du { 1379c98ee897SXiaojian Du struct smu_table_context *smu_table = &smu->smu_table; 1380c98ee897SXiaojian Du 1381c98ee897SXiaojian Du return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); 1382c98ee897SXiaojian Du } 1383c98ee897SXiaojian Du 1384c98ee897SXiaojian Du static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) 1385c98ee897SXiaojian Du { 1386c98ee897SXiaojian Du DpmClocks_t *clk_table = smu->smu_table.clocks_table; 1387c98ee897SXiaojian Du 1388c98ee897SXiaojian Du smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; 1389c98ee897SXiaojian Du smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; 1390c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq = 0; 1391c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq = 0; 1392c98ee897SXiaojian Du 1393c98ee897SXiaojian Du return 0; 1394c98ee897SXiaojian Du } 1395c98ee897SXiaojian Du 1396ae7b32e7SXiaojian Du static int vangogh_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table) 1397ae7b32e7SXiaojian Du { 1398ae7b32e7SXiaojian Du DpmClocks_t *table = smu->smu_table.clocks_table; 1399ae7b32e7SXiaojian Du int i; 1400ae7b32e7SXiaojian Du 1401ae7b32e7SXiaojian Du if (!clock_table || !table) 1402ae7b32e7SXiaojian Du return -EINVAL; 1403ae7b32e7SXiaojian Du 1404ae7b32e7SXiaojian Du for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) { 1405ae7b32e7SXiaojian Du clock_table->SocClocks[i].Freq = table->SocClocks[i]; 1406ae7b32e7SXiaojian Du clock_table->SocClocks[i].Vol = table->SocVoltage[i]; 1407ae7b32e7SXiaojian Du } 1408ae7b32e7SXiaojian Du 1409ae7b32e7SXiaojian Du for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { 1410ae7b32e7SXiaojian Du clock_table->FClocks[i].Freq = table->DfPstateTable[i].fclk; 1411ae7b32e7SXiaojian Du clock_table->FClocks[i].Vol = table->DfPstateTable[i].voltage; 1412ae7b32e7SXiaojian Du } 1413ae7b32e7SXiaojian Du 1414ae7b32e7SXiaojian Du for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { 1415ae7b32e7SXiaojian Du clock_table->MemClocks[i].Freq = table->DfPstateTable[i].memclk; 1416ae7b32e7SXiaojian Du clock_table->MemClocks[i].Vol = table->DfPstateTable[i].voltage; 1417ae7b32e7SXiaojian Du } 1418ae7b32e7SXiaojian Du 1419ae7b32e7SXiaojian Du return 0; 1420ae7b32e7SXiaojian Du } 1421ae7b32e7SXiaojian Du 1422ae7b32e7SXiaojian Du 1423a0f55287SXiaomeng Hou static int vangogh_system_features_control(struct smu_context *smu, bool en) 1424a0f55287SXiaomeng Hou { 14259e3a6ab7SXiaomeng Hou struct amdgpu_device *adev = smu->adev; 14269e3a6ab7SXiaomeng Hou 14279e3a6ab7SXiaomeng Hou if (adev->pm.fw_version >= 0x43f1700) 1428a0f55287SXiaomeng Hou return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RlcPowerNotify, 1429a0f55287SXiaomeng Hou en ? RLC_STATUS_NORMAL : RLC_STATUS_OFF, NULL); 14309e3a6ab7SXiaomeng Hou else 14319e3a6ab7SXiaomeng Hou return 0; 1432a0f55287SXiaomeng Hou } 1433a0f55287SXiaomeng Hou 1434eefdf047SJinzhou Su static int vangogh_post_smu_init(struct smu_context *smu) 1435eefdf047SJinzhou Su { 1436eefdf047SJinzhou Su struct amdgpu_device *adev = smu->adev; 1437eefdf047SJinzhou Su uint32_t tmp; 1438eefdf047SJinzhou Su uint8_t aon_bits = 0; 1439eefdf047SJinzhou Su /* Two CUs in one WGP */ 1440eefdf047SJinzhou Su uint32_t req_active_wgps = adev->gfx.cu_info.number/2; 1441eefdf047SJinzhou Su uint32_t total_cu = adev->gfx.config.max_cu_per_sh * 1442eefdf047SJinzhou Su adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines; 1443eefdf047SJinzhou Su 1444eefdf047SJinzhou Su /* if all CUs are active, no need to power off any WGPs */ 1445eefdf047SJinzhou Su if (total_cu == adev->gfx.cu_info.number) 1446eefdf047SJinzhou Su return 0; 1447eefdf047SJinzhou Su 1448eefdf047SJinzhou Su /* 1449eefdf047SJinzhou Su * Calculate the total bits number of always on WGPs for all SA/SEs in 1450eefdf047SJinzhou Su * RLC_PG_ALWAYS_ON_WGP_MASK. 1451eefdf047SJinzhou Su */ 1452eefdf047SJinzhou Su tmp = RREG32_KIQ(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_ALWAYS_ON_WGP_MASK)); 1453eefdf047SJinzhou Su tmp &= RLC_PG_ALWAYS_ON_WGP_MASK__AON_WGP_MASK_MASK; 1454eefdf047SJinzhou Su 1455eefdf047SJinzhou Su aon_bits = hweight32(tmp) * adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines; 1456eefdf047SJinzhou Su 1457eefdf047SJinzhou Su /* Do not request any WGPs less than set in the AON_WGP_MASK */ 1458eefdf047SJinzhou Su if (aon_bits > req_active_wgps) { 1459eefdf047SJinzhou Su dev_info(adev->dev, "Number of always on WGPs greater than active WGPs: WGP power save not requested.\n"); 1460eefdf047SJinzhou Su return 0; 1461eefdf047SJinzhou Su } else { 1462eefdf047SJinzhou Su return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestActiveWgp, req_active_wgps, NULL); 1463eefdf047SJinzhou Su } 1464eefdf047SJinzhou Su } 1465eefdf047SJinzhou Su 1466f46a221bSXiaojian Du static const struct pptable_funcs vangogh_ppt_funcs = { 1467271ab489SXiaojian Du 1468f46a221bSXiaojian Du .check_fw_status = smu_v11_0_check_fw_status, 1469f46a221bSXiaojian Du .check_fw_version = smu_v11_0_check_fw_version, 1470f46a221bSXiaojian Du .init_smc_tables = vangogh_init_smc_tables, 1471f46a221bSXiaojian Du .fini_smc_tables = smu_v11_0_fini_smc_tables, 1472f46a221bSXiaojian Du .init_power = smu_v11_0_init_power, 1473f46a221bSXiaojian Du .fini_power = smu_v11_0_fini_power, 1474f46a221bSXiaojian Du .register_irq_handler = smu_v11_0_register_irq_handler, 1475f46a221bSXiaojian Du .get_allowed_feature_mask = vangogh_get_allowed_feature_mask, 1476f46a221bSXiaojian Du .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, 1477f46a221bSXiaojian Du .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 1478f46a221bSXiaojian Du .send_smc_msg = smu_cmn_send_smc_msg, 1479271ab489SXiaojian Du .dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable, 1480271ab489SXiaojian Du .dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable, 1481f46a221bSXiaojian Du .is_dpm_running = vangogh_is_dpm_running, 1482271ab489SXiaojian Du .read_sensor = vangogh_read_sensor, 1483271ab489SXiaojian Du .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask, 1484f46a221bSXiaojian Du .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 1485271ab489SXiaojian Du .set_watermarks_table = vangogh_set_watermarks_table, 1486271ab489SXiaojian Du .set_driver_table_location = smu_v11_0_set_driver_table_location, 1487f46a221bSXiaojian Du .interrupt_work = smu_v11_0_interrupt_work, 1488fd253334SXiaojian Du .get_gpu_metrics = vangogh_get_gpu_metrics, 1489c98ee897SXiaojian Du .od_edit_dpm_table = vangogh_od_edit_dpm_table, 1490c98ee897SXiaojian Du .print_clk_levels = vangogh_print_fine_grain_clk, 1491c98ee897SXiaojian Du .set_default_dpm_table = vangogh_set_default_dpm_tables, 1492c98ee897SXiaojian Du .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters, 1493a0f55287SXiaomeng Hou .system_features_control = vangogh_system_features_control, 1494d0e4e112SXiaojian Du .feature_is_enabled = smu_cmn_feature_is_enabled, 1495d0e4e112SXiaojian Du .set_power_profile_mode = vangogh_set_power_profile_mode, 1496ae7b32e7SXiaojian Du .get_dpm_clock_table = vangogh_get_dpm_clock_table, 1497dd9e0b21SXiaojian Du .force_clk_levels = vangogh_force_clk_levels, 1498ea173d15SXiaojian Du .set_performance_level = vangogh_set_performance_level, 1499eefdf047SJinzhou Su .post_init = vangogh_post_smu_init, 1500f46a221bSXiaojian Du }; 1501f46a221bSXiaojian Du 1502f46a221bSXiaojian Du void vangogh_set_ppt_funcs(struct smu_context *smu) 1503f46a221bSXiaojian Du { 1504f46a221bSXiaojian Du smu->ppt_funcs = &vangogh_ppt_funcs; 1505f46a221bSXiaojian Du smu->message_map = vangogh_message_map; 1506f46a221bSXiaojian Du smu->feature_map = vangogh_feature_mask_map; 1507f46a221bSXiaojian Du smu->table_map = vangogh_table_map; 1508f46a221bSXiaojian Du smu->is_apu = true; 1509f46a221bSXiaojian Du } 1510