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 559*d0e4e112SXiaojian Du static int vangogh_get_profiling_clk_mask(struct smu_context *smu, 560*d0e4e112SXiaojian Du enum amd_dpm_forced_level level, 561*d0e4e112SXiaojian Du uint32_t *vclk_mask, 562*d0e4e112SXiaojian Du uint32_t *dclk_mask, 563*d0e4e112SXiaojian Du uint32_t *mclk_mask, 564*d0e4e112SXiaojian Du uint32_t *fclk_mask, 565*d0e4e112SXiaojian Du uint32_t *soc_mask) 566*d0e4e112SXiaojian Du { 567*d0e4e112SXiaojian Du DpmClocks_t *clk_table = smu->smu_table.clocks_table; 568*d0e4e112SXiaojian Du 569*d0e4e112SXiaojian Du if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 570*d0e4e112SXiaojian Du if (soc_mask) 571*d0e4e112SXiaojian Du *soc_mask = 0; 572*d0e4e112SXiaojian Du } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 573*d0e4e112SXiaojian Du if (mclk_mask) 574*d0e4e112SXiaojian Du /* mclk levels are in reverse order */ 575*d0e4e112SXiaojian Du *mclk_mask = clk_table->NumDfPstatesEnabled - 1; 576*d0e4e112SXiaojian Du /* fclk levels are in reverse order */ 577*d0e4e112SXiaojian Du if (fclk_mask) 578*d0e4e112SXiaojian Du *fclk_mask = clk_table->NumDfPstatesEnabled - 1; 579*d0e4e112SXiaojian Du } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 580*d0e4e112SXiaojian Du if (mclk_mask) 581*d0e4e112SXiaojian Du /* mclk levels are in reverse order */ 582*d0e4e112SXiaojian Du *mclk_mask = 0; 583*d0e4e112SXiaojian Du /* fclk levels are in reverse order */ 584*d0e4e112SXiaojian Du if (fclk_mask) 585*d0e4e112SXiaojian Du *fclk_mask = 0; 586*d0e4e112SXiaojian Du 587*d0e4e112SXiaojian Du if (soc_mask) 588*d0e4e112SXiaojian Du *soc_mask = clk_table->NumSocClkLevelsEnabled - 1; 589*d0e4e112SXiaojian Du } 590*d0e4e112SXiaojian Du 591*d0e4e112SXiaojian Du return 0; 592*d0e4e112SXiaojian Du } 593*d0e4e112SXiaojian Du 594*d0e4e112SXiaojian Du bool vangogh_clk_dpm_is_enabled(struct smu_context *smu, 595*d0e4e112SXiaojian Du enum smu_clk_type clk_type) 596*d0e4e112SXiaojian Du { 597*d0e4e112SXiaojian Du enum smu_feature_mask feature_id = 0; 598*d0e4e112SXiaojian Du 599*d0e4e112SXiaojian Du switch (clk_type) { 600*d0e4e112SXiaojian Du case SMU_MCLK: 601*d0e4e112SXiaojian Du case SMU_UCLK: 602*d0e4e112SXiaojian Du case SMU_FCLK: 603*d0e4e112SXiaojian Du feature_id = SMU_FEATURE_DPM_FCLK_BIT; 604*d0e4e112SXiaojian Du break; 605*d0e4e112SXiaojian Du case SMU_GFXCLK: 606*d0e4e112SXiaojian Du case SMU_SCLK: 607*d0e4e112SXiaojian Du feature_id = SMU_FEATURE_DPM_GFXCLK_BIT; 608*d0e4e112SXiaojian Du break; 609*d0e4e112SXiaojian Du case SMU_SOCCLK: 610*d0e4e112SXiaojian Du feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; 611*d0e4e112SXiaojian Du break; 612*d0e4e112SXiaojian Du case SMU_VCLK: 613*d0e4e112SXiaojian Du case SMU_DCLK: 614*d0e4e112SXiaojian Du feature_id = SMU_FEATURE_VCN_DPM_BIT; 615*d0e4e112SXiaojian Du break; 616*d0e4e112SXiaojian Du default: 617*d0e4e112SXiaojian Du return true; 618*d0e4e112SXiaojian Du } 619*d0e4e112SXiaojian Du 620*d0e4e112SXiaojian Du if (!smu_cmn_feature_is_enabled(smu, feature_id)) 621*d0e4e112SXiaojian Du return false; 622*d0e4e112SXiaojian Du 623*d0e4e112SXiaojian Du return true; 624*d0e4e112SXiaojian Du } 625*d0e4e112SXiaojian Du 626*d0e4e112SXiaojian Du static int vangogh_get_dpm_ultimate_freq(struct smu_context *smu, 627*d0e4e112SXiaojian Du enum smu_clk_type clk_type, 628*d0e4e112SXiaojian Du uint32_t *min, 629*d0e4e112SXiaojian Du uint32_t *max) 630*d0e4e112SXiaojian Du { 631*d0e4e112SXiaojian Du int ret = 0; 632*d0e4e112SXiaojian Du uint32_t soc_mask; 633*d0e4e112SXiaojian Du uint32_t vclk_mask; 634*d0e4e112SXiaojian Du uint32_t dclk_mask; 635*d0e4e112SXiaojian Du uint32_t mclk_mask; 636*d0e4e112SXiaojian Du uint32_t fclk_mask; 637*d0e4e112SXiaojian Du uint32_t clock_limit; 638*d0e4e112SXiaojian Du 639*d0e4e112SXiaojian Du if (!vangogh_clk_dpm_is_enabled(smu, clk_type)) { 640*d0e4e112SXiaojian Du switch (clk_type) { 641*d0e4e112SXiaojian Du case SMU_MCLK: 642*d0e4e112SXiaojian Du case SMU_UCLK: 643*d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.uclk; 644*d0e4e112SXiaojian Du break; 645*d0e4e112SXiaojian Du case SMU_FCLK: 646*d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.fclk; 647*d0e4e112SXiaojian Du break; 648*d0e4e112SXiaojian Du case SMU_GFXCLK: 649*d0e4e112SXiaojian Du case SMU_SCLK: 650*d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.gfxclk; 651*d0e4e112SXiaojian Du break; 652*d0e4e112SXiaojian Du case SMU_SOCCLK: 653*d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.socclk; 654*d0e4e112SXiaojian Du break; 655*d0e4e112SXiaojian Du case SMU_VCLK: 656*d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.vclk; 657*d0e4e112SXiaojian Du break; 658*d0e4e112SXiaojian Du case SMU_DCLK: 659*d0e4e112SXiaojian Du clock_limit = smu->smu_table.boot_values.dclk; 660*d0e4e112SXiaojian Du break; 661*d0e4e112SXiaojian Du default: 662*d0e4e112SXiaojian Du clock_limit = 0; 663*d0e4e112SXiaojian Du break; 664*d0e4e112SXiaojian Du } 665*d0e4e112SXiaojian Du 666*d0e4e112SXiaojian Du /* clock in Mhz unit */ 667*d0e4e112SXiaojian Du if (min) 668*d0e4e112SXiaojian Du *min = clock_limit / 100; 669*d0e4e112SXiaojian Du if (max) 670*d0e4e112SXiaojian Du *max = clock_limit / 100; 671*d0e4e112SXiaojian Du 672*d0e4e112SXiaojian Du return 0; 673*d0e4e112SXiaojian Du } 674*d0e4e112SXiaojian Du if (max) { 675*d0e4e112SXiaojian Du ret = vangogh_get_profiling_clk_mask(smu, 676*d0e4e112SXiaojian Du AMD_DPM_FORCED_LEVEL_PROFILE_PEAK, 677*d0e4e112SXiaojian Du &vclk_mask, 678*d0e4e112SXiaojian Du &dclk_mask, 679*d0e4e112SXiaojian Du &mclk_mask, 680*d0e4e112SXiaojian Du &fclk_mask, 681*d0e4e112SXiaojian Du &soc_mask); 682*d0e4e112SXiaojian Du if (ret) 683*d0e4e112SXiaojian Du goto failed; 684*d0e4e112SXiaojian Du 685*d0e4e112SXiaojian Du switch (clk_type) { 686*d0e4e112SXiaojian Du case SMU_UCLK: 687*d0e4e112SXiaojian Du case SMU_MCLK: 688*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, max); 689*d0e4e112SXiaojian Du if (ret) 690*d0e4e112SXiaojian Du goto failed; 691*d0e4e112SXiaojian Du break; 692*d0e4e112SXiaojian Du case SMU_SOCCLK: 693*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, max); 694*d0e4e112SXiaojian Du if (ret) 695*d0e4e112SXiaojian Du goto failed; 696*d0e4e112SXiaojian Du break; 697*d0e4e112SXiaojian Du case SMU_FCLK: 698*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, max); 699*d0e4e112SXiaojian Du if (ret) 700*d0e4e112SXiaojian Du goto failed; 701*d0e4e112SXiaojian Du break; 702*d0e4e112SXiaojian Du case SMU_VCLK: 703*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, max); 704*d0e4e112SXiaojian Du if (ret) 705*d0e4e112SXiaojian Du goto failed; 706*d0e4e112SXiaojian Du break; 707*d0e4e112SXiaojian Du case SMU_DCLK: 708*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, max); 709*d0e4e112SXiaojian Du if (ret) 710*d0e4e112SXiaojian Du goto failed; 711*d0e4e112SXiaojian Du break; 712*d0e4e112SXiaojian Du default: 713*d0e4e112SXiaojian Du ret = -EINVAL; 714*d0e4e112SXiaojian Du goto failed; 715*d0e4e112SXiaojian Du } 716*d0e4e112SXiaojian Du } 717*d0e4e112SXiaojian Du if (min) { 718*d0e4e112SXiaojian Du switch (clk_type) { 719*d0e4e112SXiaojian Du case SMU_UCLK: 720*d0e4e112SXiaojian Du case SMU_MCLK: 721*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, min); 722*d0e4e112SXiaojian Du if (ret) 723*d0e4e112SXiaojian Du goto failed; 724*d0e4e112SXiaojian Du break; 725*d0e4e112SXiaojian Du case SMU_SOCCLK: 726*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, min); 727*d0e4e112SXiaojian Du if (ret) 728*d0e4e112SXiaojian Du goto failed; 729*d0e4e112SXiaojian Du break; 730*d0e4e112SXiaojian Du case SMU_FCLK: 731*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, min); 732*d0e4e112SXiaojian Du if (ret) 733*d0e4e112SXiaojian Du goto failed; 734*d0e4e112SXiaojian Du break; 735*d0e4e112SXiaojian Du case SMU_VCLK: 736*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, min); 737*d0e4e112SXiaojian Du if (ret) 738*d0e4e112SXiaojian Du goto failed; 739*d0e4e112SXiaojian Du break; 740*d0e4e112SXiaojian Du case SMU_DCLK: 741*d0e4e112SXiaojian Du ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, min); 742*d0e4e112SXiaojian Du if (ret) 743*d0e4e112SXiaojian Du goto failed; 744*d0e4e112SXiaojian Du break; 745*d0e4e112SXiaojian Du default: 746*d0e4e112SXiaojian Du ret = -EINVAL; 747*d0e4e112SXiaojian Du goto failed; 748*d0e4e112SXiaojian Du } 749*d0e4e112SXiaojian Du } 750*d0e4e112SXiaojian Du failed: 751*d0e4e112SXiaojian Du return ret; 752*d0e4e112SXiaojian Du } 753*d0e4e112SXiaojian Du 754*d0e4e112SXiaojian Du static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) 755*d0e4e112SXiaojian Du { 756*d0e4e112SXiaojian Du int workload_type, ret; 757*d0e4e112SXiaojian Du uint32_t profile_mode = input[size]; 758*d0e4e112SXiaojian Du 759*d0e4e112SXiaojian Du if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { 760*d0e4e112SXiaojian Du dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode); 761*d0e4e112SXiaojian Du return -EINVAL; 762*d0e4e112SXiaojian Du } 763*d0e4e112SXiaojian Du 764*d0e4e112SXiaojian Du /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 765*d0e4e112SXiaojian Du workload_type = smu_cmn_to_asic_specific_index(smu, 766*d0e4e112SXiaojian Du CMN2ASIC_MAPPING_WORKLOAD, 767*d0e4e112SXiaojian Du profile_mode); 768*d0e4e112SXiaojian Du if (workload_type < 0) { 769*d0e4e112SXiaojian Du dev_err_once(smu->adev->dev, "Unsupported power profile mode %d on VANGOGH\n", 770*d0e4e112SXiaojian Du profile_mode); 771*d0e4e112SXiaojian Du return -EINVAL; 772*d0e4e112SXiaojian Du } 773*d0e4e112SXiaojian Du 774*d0e4e112SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify, 775*d0e4e112SXiaojian Du 1 << workload_type, 776*d0e4e112SXiaojian Du NULL); 777*d0e4e112SXiaojian Du if (ret) { 778*d0e4e112SXiaojian Du dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", 779*d0e4e112SXiaojian Du workload_type); 780*d0e4e112SXiaojian Du return ret; 781*d0e4e112SXiaojian Du } 782*d0e4e112SXiaojian Du 783*d0e4e112SXiaojian Du smu->power_profile_mode = profile_mode; 784*d0e4e112SXiaojian Du 785*d0e4e112SXiaojian Du return 0; 786*d0e4e112SXiaojian Du } 787*d0e4e112SXiaojian Du 788271ab489SXiaojian Du static int vangogh_read_sensor(struct smu_context *smu, 789271ab489SXiaojian Du enum amd_pp_sensors sensor, 790271ab489SXiaojian Du void *data, uint32_t *size) 791271ab489SXiaojian Du { 792271ab489SXiaojian Du int ret = 0; 793271ab489SXiaojian Du 794271ab489SXiaojian Du if (!data || !size) 795271ab489SXiaojian Du return -EINVAL; 796271ab489SXiaojian Du 797271ab489SXiaojian Du mutex_lock(&smu->sensor_lock); 798271ab489SXiaojian Du switch (sensor) { 799271ab489SXiaojian Du case AMDGPU_PP_SENSOR_GPU_LOAD: 8006cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 8016cc24d8dSAlex Deucher METRICS_AVERAGE_GFXACTIVITY, 8026cc24d8dSAlex Deucher (uint32_t *)data); 803271ab489SXiaojian Du *size = 4; 804271ab489SXiaojian Du break; 805271ab489SXiaojian Du case AMDGPU_PP_SENSOR_GPU_POWER: 8066cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 8076cc24d8dSAlex Deucher METRICS_AVERAGE_SOCKETPOWER, 8086cc24d8dSAlex Deucher (uint32_t *)data); 809271ab489SXiaojian Du *size = 4; 810271ab489SXiaojian Du break; 811271ab489SXiaojian Du case AMDGPU_PP_SENSOR_EDGE_TEMP: 8126cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 8136cc24d8dSAlex Deucher METRICS_TEMPERATURE_EDGE, 8146cc24d8dSAlex Deucher (uint32_t *)data); 8156cc24d8dSAlex Deucher *size = 4; 8166cc24d8dSAlex Deucher break; 817271ab489SXiaojian Du case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 8186cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 8196cc24d8dSAlex Deucher METRICS_TEMPERATURE_HOTSPOT, 8206cc24d8dSAlex Deucher (uint32_t *)data); 821271ab489SXiaojian Du *size = 4; 822271ab489SXiaojian Du break; 823271ab489SXiaojian Du case AMDGPU_PP_SENSOR_GFX_MCLK: 8246cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 8256cc24d8dSAlex Deucher METRICS_AVERAGE_UCLK, 8266cc24d8dSAlex Deucher (uint32_t *)data); 827271ab489SXiaojian Du *(uint32_t *)data *= 100; 828271ab489SXiaojian Du *size = 4; 829271ab489SXiaojian Du break; 830271ab489SXiaojian Du case AMDGPU_PP_SENSOR_GFX_SCLK: 8316cc24d8dSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 8326cc24d8dSAlex Deucher METRICS_AVERAGE_GFXCLK, 8336cc24d8dSAlex Deucher (uint32_t *)data); 834271ab489SXiaojian Du *(uint32_t *)data *= 100; 835271ab489SXiaojian Du *size = 4; 836271ab489SXiaojian Du break; 837271ab489SXiaojian Du case AMDGPU_PP_SENSOR_VDDGFX: 8382139d12bSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 8392139d12bSAlex Deucher METRICS_VOLTAGE_VDDGFX, 8402139d12bSAlex Deucher (uint32_t *)data); 8412139d12bSAlex Deucher *size = 4; 8422139d12bSAlex Deucher break; 8432139d12bSAlex Deucher case AMDGPU_PP_SENSOR_VDDNB: 8442139d12bSAlex Deucher ret = vangogh_get_smu_metrics_data(smu, 8452139d12bSAlex Deucher METRICS_VOLTAGE_VDDSOC, 8462139d12bSAlex Deucher (uint32_t *)data); 847271ab489SXiaojian Du *size = 4; 848271ab489SXiaojian Du break; 849271ab489SXiaojian Du default: 850271ab489SXiaojian Du ret = -EOPNOTSUPP; 851271ab489SXiaojian Du break; 852271ab489SXiaojian Du } 853271ab489SXiaojian Du mutex_unlock(&smu->sensor_lock); 854271ab489SXiaojian Du 855271ab489SXiaojian Du return ret; 856271ab489SXiaojian Du } 857271ab489SXiaojian Du 858271ab489SXiaojian Du static int vangogh_set_watermarks_table(struct smu_context *smu, 859271ab489SXiaojian Du struct pp_smu_wm_range_sets *clock_ranges) 860271ab489SXiaojian Du { 861271ab489SXiaojian Du int i; 862271ab489SXiaojian Du int ret = 0; 863271ab489SXiaojian Du Watermarks_t *table = smu->smu_table.watermarks_table; 864271ab489SXiaojian Du 865271ab489SXiaojian Du if (!table || !clock_ranges) 866271ab489SXiaojian Du return -EINVAL; 867271ab489SXiaojian Du 868271ab489SXiaojian Du if (clock_ranges) { 869271ab489SXiaojian Du if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || 870271ab489SXiaojian Du clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) 871271ab489SXiaojian Du return -EINVAL; 872271ab489SXiaojian Du 873271ab489SXiaojian Du for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { 874271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].MinClock = 875271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; 876271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].MaxClock = 877271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; 878271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].MinMclk = 879271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; 880271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].MaxMclk = 881271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; 882271ab489SXiaojian Du 883271ab489SXiaojian Du table->WatermarkRow[WM_DCFCLK][i].WmSetting = 884271ab489SXiaojian Du clock_ranges->reader_wm_sets[i].wm_inst; 885271ab489SXiaojian Du } 886271ab489SXiaojian Du 887271ab489SXiaojian Du for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { 888271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].MinClock = 889271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; 890271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].MaxClock = 891271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; 892271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].MinMclk = 893271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; 894271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].MaxMclk = 895271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; 896271ab489SXiaojian Du 897271ab489SXiaojian Du table->WatermarkRow[WM_SOCCLK][i].WmSetting = 898271ab489SXiaojian Du clock_ranges->writer_wm_sets[i].wm_inst; 899271ab489SXiaojian Du } 900271ab489SXiaojian Du 901271ab489SXiaojian Du smu->watermarks_bitmap |= WATERMARKS_EXIST; 902271ab489SXiaojian Du } 903271ab489SXiaojian Du 904271ab489SXiaojian Du /* pass data to smu controller */ 905271ab489SXiaojian Du if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 906271ab489SXiaojian Du !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { 907271ab489SXiaojian Du ret = smu_cmn_write_watermarks_table(smu); 908271ab489SXiaojian Du if (ret) { 909271ab489SXiaojian Du dev_err(smu->adev->dev, "Failed to update WMTABLE!"); 910271ab489SXiaojian Du return ret; 911271ab489SXiaojian Du } 912271ab489SXiaojian Du smu->watermarks_bitmap |= WATERMARKS_LOADED; 913271ab489SXiaojian Du } 914271ab489SXiaojian Du 915271ab489SXiaojian Du return 0; 916f46a221bSXiaojian Du } 917f46a221bSXiaojian Du 918fd253334SXiaojian Du static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, 919fd253334SXiaojian Du void **table) 920fd253334SXiaojian Du { 921fd253334SXiaojian Du struct smu_table_context *smu_table = &smu->smu_table; 922fd253334SXiaojian Du struct gpu_metrics_v2_0 *gpu_metrics = 923fd253334SXiaojian Du (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; 924fd253334SXiaojian Du SmuMetrics_t metrics; 925fd253334SXiaojian Du int ret = 0; 926fd253334SXiaojian Du 927fd253334SXiaojian Du ret = smu_cmn_get_metrics_table(smu, &metrics, true); 928fd253334SXiaojian Du if (ret) 929fd253334SXiaojian Du return ret; 930fd253334SXiaojian Du 931fd253334SXiaojian Du smu_v11_0_init_gpu_metrics_v2_0(gpu_metrics); 932fd253334SXiaojian Du 933fd253334SXiaojian Du gpu_metrics->temperature_gfx = metrics.GfxTemperature; 934fd253334SXiaojian Du gpu_metrics->temperature_soc = metrics.SocTemperature; 935fd253334SXiaojian Du memcpy(&gpu_metrics->temperature_core[0], 936fd253334SXiaojian Du &metrics.CoreTemperature[0], 937fd253334SXiaojian Du sizeof(uint16_t) * 8); 938fd253334SXiaojian Du gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; 939fd253334SXiaojian Du gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; 940fd253334SXiaojian Du 941fd253334SXiaojian Du gpu_metrics->average_gfx_activity = metrics.GfxActivity; 942fd253334SXiaojian Du gpu_metrics->average_mm_activity = metrics.UvdActivity; 943fd253334SXiaojian Du 944fd253334SXiaojian Du gpu_metrics->average_socket_power = metrics.CurrentSocketPower; 945fd253334SXiaojian Du gpu_metrics->average_cpu_power = metrics.Power[0]; 946fd253334SXiaojian Du gpu_metrics->average_soc_power = metrics.Power[1]; 947fd253334SXiaojian Du memcpy(&gpu_metrics->average_core_power[0], 948fd253334SXiaojian Du &metrics.CorePower[0], 949fd253334SXiaojian Du sizeof(uint16_t) * 8); 950fd253334SXiaojian Du 951fd253334SXiaojian Du gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency; 952fd253334SXiaojian Du gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency; 953fd253334SXiaojian Du gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency; 954fd253334SXiaojian Du gpu_metrics->average_vclk_frequency = metrics.VclkFrequency; 955fd253334SXiaojian Du 956fd253334SXiaojian Du memcpy(&gpu_metrics->current_coreclk[0], 957fd253334SXiaojian Du &metrics.CoreFrequency[0], 958fd253334SXiaojian Du sizeof(uint16_t) * 8); 959fd253334SXiaojian Du gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; 960fd253334SXiaojian Du gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; 961fd253334SXiaojian Du 962fd253334SXiaojian Du gpu_metrics->throttle_status = metrics.ThrottlerStatus; 963fd253334SXiaojian Du 964fd253334SXiaojian Du *table = (void *)gpu_metrics; 965fd253334SXiaojian Du 966fd253334SXiaojian Du return sizeof(struct gpu_metrics_v2_0); 967fd253334SXiaojian Du } 968fd253334SXiaojian Du 969c98ee897SXiaojian Du static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, 970c98ee897SXiaojian Du long input[], uint32_t size) 971c98ee897SXiaojian Du { 972c98ee897SXiaojian Du int ret = 0; 973c98ee897SXiaojian Du 974c98ee897SXiaojian Du if (!smu->od_enabled) { 975c98ee897SXiaojian Du dev_warn(smu->adev->dev, "Fine grain is not enabled!\n"); 976c98ee897SXiaojian Du return -EINVAL; 977c98ee897SXiaojian Du } 978c98ee897SXiaojian Du 979c98ee897SXiaojian Du switch (type) { 980c98ee897SXiaojian Du case PP_OD_EDIT_SCLK_VDDC_TABLE: 981c98ee897SXiaojian Du if (size != 2) { 982c98ee897SXiaojian Du dev_err(smu->adev->dev, "Input parameter number not correct\n"); 983c98ee897SXiaojian Du return -EINVAL; 984c98ee897SXiaojian Du } 985c98ee897SXiaojian Du 986c98ee897SXiaojian Du if (input[0] == 0) { 987c98ee897SXiaojian Du if (input[1] < smu->gfx_default_hard_min_freq) { 98817863170SColin Ian King dev_warn(smu->adev->dev, "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", 989c98ee897SXiaojian Du input[1], smu->gfx_default_hard_min_freq); 990c98ee897SXiaojian Du return -EINVAL; 991c98ee897SXiaojian Du } 992c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq = input[1]; 993c98ee897SXiaojian Du } else if (input[0] == 1) { 994c98ee897SXiaojian Du if (input[1] > smu->gfx_default_soft_max_freq) { 99517863170SColin Ian King dev_warn(smu->adev->dev, "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", 996c98ee897SXiaojian Du input[1], smu->gfx_default_soft_max_freq); 997c98ee897SXiaojian Du return -EINVAL; 998c98ee897SXiaojian Du } 999c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq = input[1]; 1000c98ee897SXiaojian Du } else { 1001c98ee897SXiaojian Du return -EINVAL; 1002c98ee897SXiaojian Du } 1003c98ee897SXiaojian Du break; 1004c98ee897SXiaojian Du case PP_OD_RESTORE_DEFAULT_TABLE: 1005c98ee897SXiaojian Du if (size != 0) { 1006c98ee897SXiaojian Du dev_err(smu->adev->dev, "Input parameter number not correct\n"); 1007c98ee897SXiaojian Du return -EINVAL; 1008c98ee897SXiaojian Du } else { 1009c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 1010c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 1011c98ee897SXiaojian Du 1012c98ee897SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 1013c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq, NULL); 1014c98ee897SXiaojian Du if (ret) { 1015c98ee897SXiaojian Du dev_err(smu->adev->dev, "Restore the default hard min sclk failed!"); 1016c98ee897SXiaojian Du return ret; 1017c98ee897SXiaojian Du } 1018c98ee897SXiaojian Du 1019c98ee897SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 1020c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq, NULL); 1021c98ee897SXiaojian Du if (ret) { 1022c98ee897SXiaojian Du dev_err(smu->adev->dev, "Restore the default soft max sclk failed!"); 1023c98ee897SXiaojian Du return ret; 1024c98ee897SXiaojian Du } 1025c98ee897SXiaojian Du } 1026c98ee897SXiaojian Du break; 1027c98ee897SXiaojian Du case PP_OD_COMMIT_DPM_TABLE: 1028c98ee897SXiaojian Du if (size != 0) { 1029c98ee897SXiaojian Du dev_err(smu->adev->dev, "Input parameter number not correct\n"); 1030c98ee897SXiaojian Du return -EINVAL; 1031c98ee897SXiaojian Du } else { 1032c98ee897SXiaojian Du if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { 1033c98ee897SXiaojian Du dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", 1034c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq); 1035c98ee897SXiaojian Du return -EINVAL; 1036c98ee897SXiaojian Du } 1037c98ee897SXiaojian Du 1038c98ee897SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 1039c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq, NULL); 1040c98ee897SXiaojian Du if (ret) { 1041c98ee897SXiaojian Du dev_err(smu->adev->dev, "Set hard min sclk failed!"); 1042c98ee897SXiaojian Du return ret; 1043c98ee897SXiaojian Du } 1044c98ee897SXiaojian Du 1045c98ee897SXiaojian Du ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 1046c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq, NULL); 1047c98ee897SXiaojian Du if (ret) { 1048c98ee897SXiaojian Du dev_err(smu->adev->dev, "Set soft max sclk failed!"); 1049c98ee897SXiaojian Du return ret; 1050c98ee897SXiaojian Du } 1051c98ee897SXiaojian Du } 1052c98ee897SXiaojian Du break; 1053c98ee897SXiaojian Du default: 1054c98ee897SXiaojian Du return -ENOSYS; 1055c98ee897SXiaojian Du } 1056c98ee897SXiaojian Du 1057c98ee897SXiaojian Du return ret; 1058c98ee897SXiaojian Du } 1059c98ee897SXiaojian Du 1060fce8a4acSJinzhou Su static int vangogh_set_default_dpm_tables(struct smu_context *smu) 1061c98ee897SXiaojian Du { 1062c98ee897SXiaojian Du struct smu_table_context *smu_table = &smu->smu_table; 1063c98ee897SXiaojian Du 1064c98ee897SXiaojian Du return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); 1065c98ee897SXiaojian Du } 1066c98ee897SXiaojian Du 1067c98ee897SXiaojian Du static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) 1068c98ee897SXiaojian Du { 1069c98ee897SXiaojian Du DpmClocks_t *clk_table = smu->smu_table.clocks_table; 1070c98ee897SXiaojian Du 1071c98ee897SXiaojian Du smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; 1072c98ee897SXiaojian Du smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; 1073c98ee897SXiaojian Du smu->gfx_actual_hard_min_freq = 0; 1074c98ee897SXiaojian Du smu->gfx_actual_soft_max_freq = 0; 1075c98ee897SXiaojian Du 1076c98ee897SXiaojian Du return 0; 1077c98ee897SXiaojian Du } 1078c98ee897SXiaojian Du 1079ae7b32e7SXiaojian Du static int vangogh_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table) 1080ae7b32e7SXiaojian Du { 1081ae7b32e7SXiaojian Du DpmClocks_t *table = smu->smu_table.clocks_table; 1082ae7b32e7SXiaojian Du int i; 1083ae7b32e7SXiaojian Du 1084ae7b32e7SXiaojian Du if (!clock_table || !table) 1085ae7b32e7SXiaojian Du return -EINVAL; 1086ae7b32e7SXiaojian Du 1087ae7b32e7SXiaojian Du for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) { 1088ae7b32e7SXiaojian Du clock_table->SocClocks[i].Freq = table->SocClocks[i]; 1089ae7b32e7SXiaojian Du clock_table->SocClocks[i].Vol = table->SocVoltage[i]; 1090ae7b32e7SXiaojian Du } 1091ae7b32e7SXiaojian Du 1092ae7b32e7SXiaojian Du for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { 1093ae7b32e7SXiaojian Du clock_table->FClocks[i].Freq = table->DfPstateTable[i].fclk; 1094ae7b32e7SXiaojian Du clock_table->FClocks[i].Vol = table->DfPstateTable[i].voltage; 1095ae7b32e7SXiaojian Du } 1096ae7b32e7SXiaojian Du 1097ae7b32e7SXiaojian Du for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { 1098ae7b32e7SXiaojian Du clock_table->MemClocks[i].Freq = table->DfPstateTable[i].memclk; 1099ae7b32e7SXiaojian Du clock_table->MemClocks[i].Vol = table->DfPstateTable[i].voltage; 1100ae7b32e7SXiaojian Du } 1101ae7b32e7SXiaojian Du 1102ae7b32e7SXiaojian Du return 0; 1103ae7b32e7SXiaojian Du } 1104ae7b32e7SXiaojian Du 1105ae7b32e7SXiaojian Du 1106a0f55287SXiaomeng Hou static int vangogh_system_features_control(struct smu_context *smu, bool en) 1107a0f55287SXiaomeng Hou { 11089e3a6ab7SXiaomeng Hou struct amdgpu_device *adev = smu->adev; 11099e3a6ab7SXiaomeng Hou 11109e3a6ab7SXiaomeng Hou if (adev->pm.fw_version >= 0x43f1700) 1111a0f55287SXiaomeng Hou return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RlcPowerNotify, 1112a0f55287SXiaomeng Hou en ? RLC_STATUS_NORMAL : RLC_STATUS_OFF, NULL); 11139e3a6ab7SXiaomeng Hou else 11149e3a6ab7SXiaomeng Hou return 0; 1115a0f55287SXiaomeng Hou } 1116a0f55287SXiaomeng Hou 1117eefdf047SJinzhou Su static int vangogh_post_smu_init(struct smu_context *smu) 1118eefdf047SJinzhou Su { 1119eefdf047SJinzhou Su struct amdgpu_device *adev = smu->adev; 1120eefdf047SJinzhou Su uint32_t tmp; 1121eefdf047SJinzhou Su uint8_t aon_bits = 0; 1122eefdf047SJinzhou Su /* Two CUs in one WGP */ 1123eefdf047SJinzhou Su uint32_t req_active_wgps = adev->gfx.cu_info.number/2; 1124eefdf047SJinzhou Su uint32_t total_cu = adev->gfx.config.max_cu_per_sh * 1125eefdf047SJinzhou Su adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines; 1126eefdf047SJinzhou Su 1127eefdf047SJinzhou Su /* if all CUs are active, no need to power off any WGPs */ 1128eefdf047SJinzhou Su if (total_cu == adev->gfx.cu_info.number) 1129eefdf047SJinzhou Su return 0; 1130eefdf047SJinzhou Su 1131eefdf047SJinzhou Su /* 1132eefdf047SJinzhou Su * Calculate the total bits number of always on WGPs for all SA/SEs in 1133eefdf047SJinzhou Su * RLC_PG_ALWAYS_ON_WGP_MASK. 1134eefdf047SJinzhou Su */ 1135eefdf047SJinzhou Su tmp = RREG32_KIQ(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_ALWAYS_ON_WGP_MASK)); 1136eefdf047SJinzhou Su tmp &= RLC_PG_ALWAYS_ON_WGP_MASK__AON_WGP_MASK_MASK; 1137eefdf047SJinzhou Su 1138eefdf047SJinzhou Su aon_bits = hweight32(tmp) * adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines; 1139eefdf047SJinzhou Su 1140eefdf047SJinzhou Su /* Do not request any WGPs less than set in the AON_WGP_MASK */ 1141eefdf047SJinzhou Su if (aon_bits > req_active_wgps) { 1142eefdf047SJinzhou Su dev_info(adev->dev, "Number of always on WGPs greater than active WGPs: WGP power save not requested.\n"); 1143eefdf047SJinzhou Su return 0; 1144eefdf047SJinzhou Su } else { 1145eefdf047SJinzhou Su return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestActiveWgp, req_active_wgps, NULL); 1146eefdf047SJinzhou Su } 1147eefdf047SJinzhou Su } 1148eefdf047SJinzhou Su 1149f46a221bSXiaojian Du static const struct pptable_funcs vangogh_ppt_funcs = { 1150271ab489SXiaojian Du 1151f46a221bSXiaojian Du .check_fw_status = smu_v11_0_check_fw_status, 1152f46a221bSXiaojian Du .check_fw_version = smu_v11_0_check_fw_version, 1153f46a221bSXiaojian Du .init_smc_tables = vangogh_init_smc_tables, 1154f46a221bSXiaojian Du .fini_smc_tables = smu_v11_0_fini_smc_tables, 1155f46a221bSXiaojian Du .init_power = smu_v11_0_init_power, 1156f46a221bSXiaojian Du .fini_power = smu_v11_0_fini_power, 1157f46a221bSXiaojian Du .register_irq_handler = smu_v11_0_register_irq_handler, 1158f46a221bSXiaojian Du .get_allowed_feature_mask = vangogh_get_allowed_feature_mask, 1159f46a221bSXiaojian Du .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, 1160f46a221bSXiaojian Du .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 1161f46a221bSXiaojian Du .send_smc_msg = smu_cmn_send_smc_msg, 1162271ab489SXiaojian Du .dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable, 1163271ab489SXiaojian Du .dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable, 1164f46a221bSXiaojian Du .is_dpm_running = vangogh_is_dpm_running, 1165271ab489SXiaojian Du .read_sensor = vangogh_read_sensor, 1166271ab489SXiaojian Du .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask, 1167f46a221bSXiaojian Du .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 1168271ab489SXiaojian Du .set_watermarks_table = vangogh_set_watermarks_table, 1169271ab489SXiaojian Du .set_driver_table_location = smu_v11_0_set_driver_table_location, 1170f46a221bSXiaojian Du .interrupt_work = smu_v11_0_interrupt_work, 1171fd253334SXiaojian Du .get_gpu_metrics = vangogh_get_gpu_metrics, 1172c98ee897SXiaojian Du .od_edit_dpm_table = vangogh_od_edit_dpm_table, 1173c98ee897SXiaojian Du .print_clk_levels = vangogh_print_fine_grain_clk, 1174c98ee897SXiaojian Du .set_default_dpm_table = vangogh_set_default_dpm_tables, 1175c98ee897SXiaojian Du .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters, 1176a0f55287SXiaomeng Hou .system_features_control = vangogh_system_features_control, 1177*d0e4e112SXiaojian Du .feature_is_enabled = smu_cmn_feature_is_enabled, 1178*d0e4e112SXiaojian Du .set_power_profile_mode = vangogh_set_power_profile_mode, 1179ae7b32e7SXiaojian Du .get_dpm_clock_table = vangogh_get_dpm_clock_table, 1180eefdf047SJinzhou Su .post_init = vangogh_post_smu_init, 1181f46a221bSXiaojian Du }; 1182f46a221bSXiaojian Du 1183f46a221bSXiaojian Du void vangogh_set_ppt_funcs(struct smu_context *smu) 1184f46a221bSXiaojian Du { 1185f46a221bSXiaojian Du smu->ppt_funcs = &vangogh_ppt_funcs; 1186f46a221bSXiaojian Du smu->message_map = vangogh_message_map; 1187f46a221bSXiaojian Du smu->feature_map = vangogh_feature_mask_map; 1188f46a221bSXiaojian Du smu->table_map = vangogh_table_map; 1189f46a221bSXiaojian Du smu->is_apu = true; 1190f46a221bSXiaojian Du } 1191