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"
37517cb957SHuang Rui #include <asm/processor.h>
38f46a221bSXiaojian Du 
39f46a221bSXiaojian Du /*
40f46a221bSXiaojian Du  * DO NOT use these for err/warn/info/debug messages.
41f46a221bSXiaojian Du  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
42f46a221bSXiaojian Du  * They are more MGPU friendly.
43f46a221bSXiaojian Du  */
44f46a221bSXiaojian Du #undef pr_err
45f46a221bSXiaojian Du #undef pr_warn
46f46a221bSXiaojian Du #undef pr_info
47f46a221bSXiaojian Du #undef pr_debug
48f46a221bSXiaojian Du 
4943195162SAndré Almeida // Registers related to GFXOFF
5043195162SAndré Almeida // addressBlock: smuio_smuio_SmuSmuioDec
5143195162SAndré Almeida // base address: 0x5a000
5243195162SAndré Almeida #define mmSMUIO_GFX_MISC_CNTL			0x00c5
5343195162SAndré Almeida #define mmSMUIO_GFX_MISC_CNTL_BASE_IDX		0
5443195162SAndré Almeida 
5543195162SAndré Almeida //SMUIO_GFX_MISC_CNTL
5643195162SAndré Almeida #define SMUIO_GFX_MISC_CNTL__SMU_GFX_cold_vs_gfxoff__SHIFT	0x0
5743195162SAndré Almeida #define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT		0x1
5843195162SAndré Almeida #define SMUIO_GFX_MISC_CNTL__SMU_GFX_cold_vs_gfxoff_MASK	0x00000001L
5943195162SAndré Almeida #define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK		0x00000006L
6043195162SAndré Almeida 
61f46a221bSXiaojian Du #define FEATURE_MASK(feature) (1ULL << feature)
62f46a221bSXiaojian Du #define SMC_DPM_FEATURE ( \
63f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
64f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_VCN_DPM_BIT)	 | \
65f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_FCLK_DPM_BIT)	 | \
66f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT)	 | \
67f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT)	 | \
68f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_LCLK_DPM_BIT)	 | \
69f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT)	 | \
70f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \
71271ab489SXiaojian Du 	FEATURE_MASK(FEATURE_GFX_DPM_BIT))
72f46a221bSXiaojian Du 
73f46a221bSXiaojian Du static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = {
74271ab489SXiaojian Du 	MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,			0),
75271ab489SXiaojian Du 	MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,		0),
76271ab489SXiaojian Du 	MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,	0),
77271ab489SXiaojian Du 	MSG_MAP(EnableGfxOff,                   PPSMC_MSG_EnableGfxOff,			0),
78b58ce1feSJinzhou Su 	MSG_MAP(AllowGfxOff,                    PPSMC_MSG_AllowGfxOff,          0),
79b58ce1feSJinzhou Su 	MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff,		0),
80271ab489SXiaojian Du 	MSG_MAP(PowerDownIspByTile,             PPSMC_MSG_PowerDownIspByTile,	0),
81271ab489SXiaojian Du 	MSG_MAP(PowerUpIspByTile,               PPSMC_MSG_PowerUpIspByTile,		0),
82271ab489SXiaojian Du 	MSG_MAP(PowerDownVcn,                   PPSMC_MSG_PowerDownVcn,			0),
83271ab489SXiaojian Du 	MSG_MAP(PowerUpVcn,                     PPSMC_MSG_PowerUpVcn,			0),
84a0f55287SXiaomeng Hou 	MSG_MAP(RlcPowerNotify,                 PPSMC_MSG_RlcPowerNotify,		0),
85271ab489SXiaojian Du 	MSG_MAP(SetHardMinVcn,                  PPSMC_MSG_SetHardMinVcn,		0),
86271ab489SXiaojian Du 	MSG_MAP(SetSoftMinGfxclk,               PPSMC_MSG_SetSoftMinGfxclk,		0),
87271ab489SXiaojian Du 	MSG_MAP(ActiveProcessNotify,            PPSMC_MSG_ActiveProcessNotify,		0),
88271ab489SXiaojian Du 	MSG_MAP(SetHardMinIspiclkByFreq,        PPSMC_MSG_SetHardMinIspiclkByFreq,	0),
89271ab489SXiaojian Du 	MSG_MAP(SetHardMinIspxclkByFreq,        PPSMC_MSG_SetHardMinIspxclkByFreq,	0),
90271ab489SXiaojian Du 	MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh,	0),
91271ab489SXiaojian Du 	MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow,		0),
92271ab489SXiaojian Du 	MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,	0),
93271ab489SXiaojian Du 	MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,	0),
94271ab489SXiaojian Du 	MSG_MAP(GfxDeviceDriverReset,           PPSMC_MSG_GfxDeviceDriverReset,		0),
95271ab489SXiaojian Du 	MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,	0),
96271ab489SXiaojian Du 	MSG_MAP(SetHardMinSocclkByFreq,         PPSMC_MSG_SetHardMinSocclkByFreq,	0),
97271ab489SXiaojian Du 	MSG_MAP(SetSoftMinFclk,                 PPSMC_MSG_SetSoftMinFclk,		0),
98271ab489SXiaojian Du 	MSG_MAP(SetSoftMinVcn,                  PPSMC_MSG_SetSoftMinVcn,		0),
99271ab489SXiaojian Du 	MSG_MAP(EnablePostCode,                 PPSMC_MSG_EnablePostCode,		0),
100271ab489SXiaojian Du 	MSG_MAP(GetGfxclkFrequency,             PPSMC_MSG_GetGfxclkFrequency,	0),
101271ab489SXiaojian Du 	MSG_MAP(GetFclkFrequency,               PPSMC_MSG_GetFclkFrequency,		0),
102271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxGfxClk,               PPSMC_MSG_SetSoftMaxGfxClk,		0),
103271ab489SXiaojian Du 	MSG_MAP(SetHardMinGfxClk,               PPSMC_MSG_SetHardMinGfxClk,		0),
104271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxSocclkByFreq,         PPSMC_MSG_SetSoftMaxSocclkByFreq,	0),
105271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxFclkByFreq,           PPSMC_MSG_SetSoftMaxFclkByFreq,		0),
106271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxVcn,                  PPSMC_MSG_SetSoftMaxVcn,			0),
107271ab489SXiaojian Du 	MSG_MAP(SetPowerLimitPercentage,        PPSMC_MSG_SetPowerLimitPercentage,	0),
108271ab489SXiaojian Du 	MSG_MAP(PowerDownJpeg,                  PPSMC_MSG_PowerDownJpeg,			0),
109271ab489SXiaojian Du 	MSG_MAP(PowerUpJpeg,                    PPSMC_MSG_PowerUpJpeg,				0),
110271ab489SXiaojian Du 	MSG_MAP(SetHardMinFclkByFreq,           PPSMC_MSG_SetHardMinFclkByFreq,		0),
111271ab489SXiaojian Du 	MSG_MAP(SetSoftMinSocclkByFreq,         PPSMC_MSG_SetSoftMinSocclkByFreq,	0),
112271ab489SXiaojian Du 	MSG_MAP(PowerUpCvip,                    PPSMC_MSG_PowerUpCvip,				0),
113271ab489SXiaojian Du 	MSG_MAP(PowerDownCvip,                  PPSMC_MSG_PowerDownCvip,			0),
114271ab489SXiaojian Du 	MSG_MAP(GetPptLimit,                        PPSMC_MSG_GetPptLimit,			0),
115271ab489SXiaojian Du 	MSG_MAP(GetThermalLimit,                    PPSMC_MSG_GetThermalLimit,		0),
116271ab489SXiaojian Du 	MSG_MAP(GetCurrentTemperature,              PPSMC_MSG_GetCurrentTemperature, 0),
117271ab489SXiaojian Du 	MSG_MAP(GetCurrentPower,                    PPSMC_MSG_GetCurrentPower,		 0),
118271ab489SXiaojian Du 	MSG_MAP(GetCurrentVoltage,                  PPSMC_MSG_GetCurrentVoltage,	 0),
119271ab489SXiaojian Du 	MSG_MAP(GetCurrentCurrent,                  PPSMC_MSG_GetCurrentCurrent,	 0),
120271ab489SXiaojian Du 	MSG_MAP(GetAverageCpuActivity,              PPSMC_MSG_GetAverageCpuActivity, 0),
121271ab489SXiaojian Du 	MSG_MAP(GetAverageGfxActivity,              PPSMC_MSG_GetAverageGfxActivity, 0),
122271ab489SXiaojian Du 	MSG_MAP(GetAveragePower,                    PPSMC_MSG_GetAveragePower,		 0),
123271ab489SXiaojian Du 	MSG_MAP(GetAverageTemperature,              PPSMC_MSG_GetAverageTemperature, 0),
124271ab489SXiaojian Du 	MSG_MAP(SetAveragePowerTimeConstant,        PPSMC_MSG_SetAveragePowerTimeConstant,			0),
125271ab489SXiaojian Du 	MSG_MAP(SetAverageActivityTimeConstant,     PPSMC_MSG_SetAverageActivityTimeConstant,		0),
126271ab489SXiaojian Du 	MSG_MAP(SetAverageTemperatureTimeConstant,  PPSMC_MSG_SetAverageTemperatureTimeConstant,	0),
127271ab489SXiaojian Du 	MSG_MAP(SetMitigationEndHysteresis,         PPSMC_MSG_SetMitigationEndHysteresis,			0),
128271ab489SXiaojian Du 	MSG_MAP(GetCurrentFreq,                     PPSMC_MSG_GetCurrentFreq,						0),
129271ab489SXiaojian Du 	MSG_MAP(SetReducedPptLimit,                 PPSMC_MSG_SetReducedPptLimit,					0),
130271ab489SXiaojian Du 	MSG_MAP(SetReducedThermalLimit,             PPSMC_MSG_SetReducedThermalLimit,				0),
131271ab489SXiaojian Du 	MSG_MAP(DramLogSetDramAddr,                 PPSMC_MSG_DramLogSetDramAddr,					0),
132271ab489SXiaojian Du 	MSG_MAP(StartDramLogging,                   PPSMC_MSG_StartDramLogging,						0),
133271ab489SXiaojian Du 	MSG_MAP(StopDramLogging,                    PPSMC_MSG_StopDramLogging,						0),
134271ab489SXiaojian Du 	MSG_MAP(SetSoftMinCclk,                     PPSMC_MSG_SetSoftMinCclk,						0),
135271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxCclk,                     PPSMC_MSG_SetSoftMaxCclk,						0),
136eefdf047SJinzhou Su 	MSG_MAP(RequestActiveWgp,                   PPSMC_MSG_RequestActiveWgp,                     0),
137ae07970aSXiaomeng Hou 	MSG_MAP(SetFastPPTLimit,                    PPSMC_MSG_SetFastPPTLimit,						0),
138ae07970aSXiaomeng Hou 	MSG_MAP(SetSlowPPTLimit,                    PPSMC_MSG_SetSlowPPTLimit,						0),
139ae07970aSXiaomeng Hou 	MSG_MAP(GetFastPPTLimit,                    PPSMC_MSG_GetFastPPTLimit,						0),
140ae07970aSXiaomeng Hou 	MSG_MAP(GetSlowPPTLimit,                    PPSMC_MSG_GetSlowPPTLimit,						0),
1411ed5a845SAndré Almeida 	MSG_MAP(GetGfxOffStatus,		    PPSMC_MSG_GetGfxOffStatus,						0),
1421ed5a845SAndré Almeida 	MSG_MAP(GetGfxOffEntryCount,		    PPSMC_MSG_GetGfxOffEntryCount,					0),
1431ed5a845SAndré Almeida 	MSG_MAP(LogGfxOffResidency,		    PPSMC_MSG_LogGfxOffResidency,					0),
144f46a221bSXiaojian Du };
145f46a221bSXiaojian Du 
146f46a221bSXiaojian Du static struct cmn2asic_mapping vangogh_feature_mask_map[SMU_FEATURE_COUNT] = {
147f46a221bSXiaojian Du 	FEA_MAP(PPT),
148f46a221bSXiaojian Du 	FEA_MAP(TDC),
149f46a221bSXiaojian Du 	FEA_MAP(THERMAL),
150f46a221bSXiaojian Du 	FEA_MAP(DS_GFXCLK),
151f46a221bSXiaojian Du 	FEA_MAP(DS_SOCCLK),
152f46a221bSXiaojian Du 	FEA_MAP(DS_LCLK),
153f46a221bSXiaojian Du 	FEA_MAP(DS_FCLK),
154f46a221bSXiaojian Du 	FEA_MAP(DS_MP1CLK),
155f46a221bSXiaojian Du 	FEA_MAP(DS_MP0CLK),
156f46a221bSXiaojian Du 	FEA_MAP(ATHUB_PG),
157f46a221bSXiaojian Du 	FEA_MAP(CCLK_DPM),
158f46a221bSXiaojian Du 	FEA_MAP(FAN_CONTROLLER),
159f46a221bSXiaojian Du 	FEA_MAP(ULV),
160f46a221bSXiaojian Du 	FEA_MAP(VCN_DPM),
161f46a221bSXiaojian Du 	FEA_MAP(LCLK_DPM),
162f46a221bSXiaojian Du 	FEA_MAP(SHUBCLK_DPM),
163f46a221bSXiaojian Du 	FEA_MAP(DCFCLK_DPM),
164f46a221bSXiaojian Du 	FEA_MAP(DS_DCFCLK),
165f46a221bSXiaojian Du 	FEA_MAP(S0I2),
166f46a221bSXiaojian Du 	FEA_MAP(SMU_LOW_POWER),
167f46a221bSXiaojian Du 	FEA_MAP(GFX_DEM),
168f46a221bSXiaojian Du 	FEA_MAP(PSI),
169f46a221bSXiaojian Du 	FEA_MAP(PROCHOT),
170f46a221bSXiaojian Du 	FEA_MAP(CPUOFF),
171f46a221bSXiaojian Du 	FEA_MAP(STAPM),
172f46a221bSXiaojian Du 	FEA_MAP(S0I3),
173f46a221bSXiaojian Du 	FEA_MAP(DF_CSTATES),
174f46a221bSXiaojian Du 	FEA_MAP(PERF_LIMIT),
175f46a221bSXiaojian Du 	FEA_MAP(CORE_DLDO),
176f46a221bSXiaojian Du 	FEA_MAP(RSMU_LOW_POWER),
177f46a221bSXiaojian Du 	FEA_MAP(SMN_LOW_POWER),
178f46a221bSXiaojian Du 	FEA_MAP(THM_LOW_POWER),
179f46a221bSXiaojian Du 	FEA_MAP(SMUIO_LOW_POWER),
180f46a221bSXiaojian Du 	FEA_MAP(MP1_LOW_POWER),
181f46a221bSXiaojian Du 	FEA_MAP(DS_VCN),
182f46a221bSXiaojian Du 	FEA_MAP(CPPC),
183f46a221bSXiaojian Du 	FEA_MAP(OS_CSTATES),
184f46a221bSXiaojian Du 	FEA_MAP(ISP_DPM),
185f46a221bSXiaojian Du 	FEA_MAP(A55_DPM),
186f46a221bSXiaojian Du 	FEA_MAP(CVIP_DSP_DPM),
187f46a221bSXiaojian Du 	FEA_MAP(MSMU_LOW_POWER),
18854800b58SXiaojian Du 	FEA_MAP_REVERSE(SOCCLK),
18954800b58SXiaojian Du 	FEA_MAP_REVERSE(FCLK),
19054800b58SXiaojian Du 	FEA_MAP_HALF_REVERSE(GFX),
191f46a221bSXiaojian Du };
192f46a221bSXiaojian Du 
193f46a221bSXiaojian Du static struct cmn2asic_mapping vangogh_table_map[SMU_TABLE_COUNT] = {
194f46a221bSXiaojian Du 	TAB_MAP_VALID(WATERMARKS),
195f46a221bSXiaojian Du 	TAB_MAP_VALID(SMU_METRICS),
196f46a221bSXiaojian Du 	TAB_MAP_VALID(CUSTOM_DPM),
197f46a221bSXiaojian Du 	TAB_MAP_VALID(DPMCLOCKS),
198f46a221bSXiaojian Du };
199f46a221bSXiaojian Du 
200f727ebebSXiaojian Du static struct cmn2asic_mapping vangogh_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
201f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,		WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
202f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,		WORKLOAD_PPLIB_VIDEO_BIT),
203f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,			WORKLOAD_PPLIB_VR_BIT),
204f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,		WORKLOAD_PPLIB_COMPUTE_BIT),
205f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,		WORKLOAD_PPLIB_CUSTOM_BIT),
206*dc622367SPerry Yuan 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CAPPED,		WORKLOAD_PPLIB_CAPPED_BIT),
207*dc622367SPerry Yuan 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_UNCAPPED,		WORKLOAD_PPLIB_UNCAPPED_BIT),
208f727ebebSXiaojian Du };
209f727ebebSXiaojian Du 
2107cab3cffSGraham Sider static const uint8_t vangogh_throttler_map[] = {
2117cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_SPL]	= (SMU_THROTTLER_SPL_BIT),
2127cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_FPPT]	= (SMU_THROTTLER_FPPT_BIT),
2137cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_SPPT]	= (SMU_THROTTLER_SPPT_BIT),
2147cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_SPPT_APU]	= (SMU_THROTTLER_SPPT_APU_BIT),
2157cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_THM_CORE]	= (SMU_THROTTLER_TEMP_CORE_BIT),
2167cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_THM_GFX]	= (SMU_THROTTLER_TEMP_GPU_BIT),
2177cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_THM_SOC]	= (SMU_THROTTLER_TEMP_SOC_BIT),
2187cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_TDC_VDD]	= (SMU_THROTTLER_TDC_VDD_BIT),
2197cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_TDC_SOC]	= (SMU_THROTTLER_TDC_SOC_BIT),
2207cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_TDC_GFX]	= (SMU_THROTTLER_TDC_GFX_BIT),
2217cab3cffSGraham Sider 	[THROTTLER_STATUS_BIT_TDC_CVIP]	= (SMU_THROTTLER_TDC_CVIP_BIT),
2227cab3cffSGraham Sider };
2237cab3cffSGraham Sider 
224f46a221bSXiaojian Du static int vangogh_tables_init(struct smu_context *smu)
225f46a221bSXiaojian Du {
226f46a221bSXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
227f46a221bSXiaojian Du 	struct smu_table *tables = smu_table->tables;
22886c8236eSXiaojian Du 	uint32_t if_version;
2290d6516efSLi Ma 	uint32_t smu_version;
23086c8236eSXiaojian Du 	uint32_t ret = 0;
23186c8236eSXiaojian Du 
2320d6516efSLi Ma 	ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
23386c8236eSXiaojian Du 	if (ret) {
2340d6516efSLi Ma 		return ret;
23586c8236eSXiaojian Du 	}
236f46a221bSXiaojian Du 
237f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
238f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
239f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
240f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
241f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
242f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
243f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t),
244f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
24586c8236eSXiaojian Du 
24686c8236eSXiaojian Du 	if (if_version < 0x3) {
24786c8236eSXiaojian Du 		SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_legacy_t),
24886c8236eSXiaojian Du 				PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
24986c8236eSXiaojian Du 		smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_legacy_t), GFP_KERNEL);
25086c8236eSXiaojian Du 	} else {
25186c8236eSXiaojian Du 		SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
25286c8236eSXiaojian Du 				PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
253f46a221bSXiaojian Du 		smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
25486c8236eSXiaojian Du 	}
255f46a221bSXiaojian Du 	if (!smu_table->metrics_table)
256f46a221bSXiaojian Du 		goto err0_out;
257f46a221bSXiaojian Du 	smu_table->metrics_time = 0;
258f46a221bSXiaojian Du 
2590d6516efSLi Ma 	if (smu_version >= 0x043F3E00)
2600d6516efSLi Ma 		smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_3);
2610d6516efSLi Ma 	else
2627cab3cffSGraham Sider 		smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2);
263f46a221bSXiaojian Du 	smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
264f46a221bSXiaojian Du 	if (!smu_table->gpu_metrics_table)
265f46a221bSXiaojian Du 		goto err1_out;
266f46a221bSXiaojian Du 
267f46a221bSXiaojian Du 	smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
268f46a221bSXiaojian Du 	if (!smu_table->watermarks_table)
269f46a221bSXiaojian Du 		goto err2_out;
270f46a221bSXiaojian Du 
271c98ee897SXiaojian Du 	smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
272c98ee897SXiaojian Du 	if (!smu_table->clocks_table)
273c98ee897SXiaojian Du 		goto err3_out;
274c98ee897SXiaojian Du 
275f46a221bSXiaojian Du 	return 0;
276f46a221bSXiaojian Du 
277c98ee897SXiaojian Du err3_out:
278a5467ebdSChristophe JAILLET 	kfree(smu_table->watermarks_table);
279f46a221bSXiaojian Du err2_out:
280f46a221bSXiaojian Du 	kfree(smu_table->gpu_metrics_table);
281f46a221bSXiaojian Du err1_out:
282f46a221bSXiaojian Du 	kfree(smu_table->metrics_table);
283f46a221bSXiaojian Du err0_out:
284f46a221bSXiaojian Du 	return -ENOMEM;
285f46a221bSXiaojian Du }
286f46a221bSXiaojian Du 
28786c8236eSXiaojian Du static int vangogh_get_legacy_smu_metrics_data(struct smu_context *smu,
288271ab489SXiaojian Du 				       MetricsMember_t member,
289271ab489SXiaojian Du 				       uint32_t *value)
290271ab489SXiaojian Du {
291271ab489SXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
29286c8236eSXiaojian Du 	SmuMetrics_legacy_t *metrics = (SmuMetrics_legacy_t *)smu_table->metrics_table;
293271ab489SXiaojian Du 	int ret = 0;
294271ab489SXiaojian Du 
295da11407fSEvan Quan 	ret = smu_cmn_get_metrics_table(smu,
296271ab489SXiaojian Du 					NULL,
297271ab489SXiaojian Du 					false);
298da11407fSEvan Quan 	if (ret)
299271ab489SXiaojian Du 		return ret;
300271ab489SXiaojian Du 
301271ab489SXiaojian Du 	switch (member) {
302a99a5116SXiaojian Du 	case METRICS_CURR_GFXCLK:
303271ab489SXiaojian Du 		*value = metrics->GfxclkFrequency;
304271ab489SXiaojian Du 		break;
305271ab489SXiaojian Du 	case METRICS_AVERAGE_SOCCLK:
306271ab489SXiaojian Du 		*value = metrics->SocclkFrequency;
307271ab489SXiaojian Du 		break;
308f02c7336SXiaojian Du 	case METRICS_AVERAGE_VCLK:
309f02c7336SXiaojian Du 		*value = metrics->VclkFrequency;
310f02c7336SXiaojian Du 		break;
311f02c7336SXiaojian Du 	case METRICS_AVERAGE_DCLK:
312f02c7336SXiaojian Du 		*value = metrics->DclkFrequency;
313f02c7336SXiaojian Du 		break;
314a99a5116SXiaojian Du 	case METRICS_CURR_UCLK:
315271ab489SXiaojian Du 		*value = metrics->MemclkFrequency;
316271ab489SXiaojian Du 		break;
317271ab489SXiaojian Du 	case METRICS_AVERAGE_GFXACTIVITY:
318271ab489SXiaojian Du 		*value = metrics->GfxActivity / 100;
319271ab489SXiaojian Du 		break;
320271ab489SXiaojian Du 	case METRICS_AVERAGE_VCNACTIVITY:
321271ab489SXiaojian Du 		*value = metrics->UvdActivity;
322271ab489SXiaojian Du 		break;
323271ab489SXiaojian Du 	case METRICS_AVERAGE_SOCKETPOWER:
32423289a22SXiaojian Du 		*value = (metrics->CurrentSocketPower << 8) /
32523289a22SXiaojian Du 		1000 ;
326271ab489SXiaojian Du 		break;
327271ab489SXiaojian Du 	case METRICS_TEMPERATURE_EDGE:
328271ab489SXiaojian Du 		*value = metrics->GfxTemperature / 100 *
329271ab489SXiaojian Du 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
330271ab489SXiaojian Du 		break;
331271ab489SXiaojian Du 	case METRICS_TEMPERATURE_HOTSPOT:
332271ab489SXiaojian Du 		*value = metrics->SocTemperature / 100 *
333271ab489SXiaojian Du 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
334271ab489SXiaojian Du 		break;
335271ab489SXiaojian Du 	case METRICS_THROTTLER_STATUS:
336271ab489SXiaojian Du 		*value = metrics->ThrottlerStatus;
337271ab489SXiaojian Du 		break;
3382139d12bSAlex Deucher 	case METRICS_VOLTAGE_VDDGFX:
3392139d12bSAlex Deucher 		*value = metrics->Voltage[2];
3402139d12bSAlex Deucher 		break;
3412139d12bSAlex Deucher 	case METRICS_VOLTAGE_VDDSOC:
3422139d12bSAlex Deucher 		*value = metrics->Voltage[1];
3432139d12bSAlex Deucher 		break;
344517cb957SHuang Rui 	case METRICS_AVERAGE_CPUCLK:
345517cb957SHuang Rui 		memcpy(value, &metrics->CoreFrequency[0],
3464aef0ebcSHuang Rui 		       smu->cpu_core_num * sizeof(uint16_t));
347517cb957SHuang Rui 		break;
348271ab489SXiaojian Du 	default:
349271ab489SXiaojian Du 		*value = UINT_MAX;
350271ab489SXiaojian Du 		break;
351271ab489SXiaojian Du 	}
352271ab489SXiaojian Du 
353271ab489SXiaojian Du 	return ret;
354271ab489SXiaojian Du }
355271ab489SXiaojian Du 
35686c8236eSXiaojian Du static int vangogh_get_smu_metrics_data(struct smu_context *smu,
35786c8236eSXiaojian Du 				       MetricsMember_t member,
35886c8236eSXiaojian Du 				       uint32_t *value)
35986c8236eSXiaojian Du {
36086c8236eSXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
36186c8236eSXiaojian Du 	SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
36286c8236eSXiaojian Du 	int ret = 0;
36386c8236eSXiaojian Du 
364da11407fSEvan Quan 	ret = smu_cmn_get_metrics_table(smu,
36586c8236eSXiaojian Du 					NULL,
36686c8236eSXiaojian Du 					false);
367da11407fSEvan Quan 	if (ret)
36886c8236eSXiaojian Du 		return ret;
36986c8236eSXiaojian Du 
37086c8236eSXiaojian Du 	switch (member) {
371a99a5116SXiaojian Du 	case METRICS_CURR_GFXCLK:
37286c8236eSXiaojian Du 		*value = metrics->Current.GfxclkFrequency;
37386c8236eSXiaojian Du 		break;
37486c8236eSXiaojian Du 	case METRICS_AVERAGE_SOCCLK:
37586c8236eSXiaojian Du 		*value = metrics->Current.SocclkFrequency;
37686c8236eSXiaojian Du 		break;
37786c8236eSXiaojian Du 	case METRICS_AVERAGE_VCLK:
37886c8236eSXiaojian Du 		*value = metrics->Current.VclkFrequency;
37986c8236eSXiaojian Du 		break;
38086c8236eSXiaojian Du 	case METRICS_AVERAGE_DCLK:
38186c8236eSXiaojian Du 		*value = metrics->Current.DclkFrequency;
38286c8236eSXiaojian Du 		break;
383a99a5116SXiaojian Du 	case METRICS_CURR_UCLK:
38486c8236eSXiaojian Du 		*value = metrics->Current.MemclkFrequency;
38586c8236eSXiaojian Du 		break;
38686c8236eSXiaojian Du 	case METRICS_AVERAGE_GFXACTIVITY:
38786c8236eSXiaojian Du 		*value = metrics->Current.GfxActivity;
38886c8236eSXiaojian Du 		break;
38986c8236eSXiaojian Du 	case METRICS_AVERAGE_VCNACTIVITY:
39086c8236eSXiaojian Du 		*value = metrics->Current.UvdActivity;
39186c8236eSXiaojian Du 		break;
39286c8236eSXiaojian Du 	case METRICS_AVERAGE_SOCKETPOWER:
39386c8236eSXiaojian Du 		*value = (metrics->Current.CurrentSocketPower << 8) /
39486c8236eSXiaojian Du 		1000;
39586c8236eSXiaojian Du 		break;
39686c8236eSXiaojian Du 	case METRICS_TEMPERATURE_EDGE:
39786c8236eSXiaojian Du 		*value = metrics->Current.GfxTemperature / 100 *
39886c8236eSXiaojian Du 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
39986c8236eSXiaojian Du 		break;
40086c8236eSXiaojian Du 	case METRICS_TEMPERATURE_HOTSPOT:
40186c8236eSXiaojian Du 		*value = metrics->Current.SocTemperature / 100 *
40286c8236eSXiaojian Du 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
40386c8236eSXiaojian Du 		break;
40486c8236eSXiaojian Du 	case METRICS_THROTTLER_STATUS:
40586c8236eSXiaojian Du 		*value = metrics->Current.ThrottlerStatus;
40686c8236eSXiaojian Du 		break;
40786c8236eSXiaojian Du 	case METRICS_VOLTAGE_VDDGFX:
40886c8236eSXiaojian Du 		*value = metrics->Current.Voltage[2];
40986c8236eSXiaojian Du 		break;
41086c8236eSXiaojian Du 	case METRICS_VOLTAGE_VDDSOC:
41186c8236eSXiaojian Du 		*value = metrics->Current.Voltage[1];
41286c8236eSXiaojian Du 		break;
41386c8236eSXiaojian Du 	case METRICS_AVERAGE_CPUCLK:
41486c8236eSXiaojian Du 		memcpy(value, &metrics->Current.CoreFrequency[0],
41586c8236eSXiaojian Du 		       smu->cpu_core_num * sizeof(uint16_t));
41686c8236eSXiaojian Du 		break;
41786c8236eSXiaojian Du 	default:
41886c8236eSXiaojian Du 		*value = UINT_MAX;
41986c8236eSXiaojian Du 		break;
42086c8236eSXiaojian Du 	}
42186c8236eSXiaojian Du 
42286c8236eSXiaojian Du 	return ret;
42386c8236eSXiaojian Du }
42486c8236eSXiaojian Du 
42586c8236eSXiaojian Du static int vangogh_common_get_smu_metrics_data(struct smu_context *smu,
42686c8236eSXiaojian Du 				       MetricsMember_t member,
42786c8236eSXiaojian Du 				       uint32_t *value)
42886c8236eSXiaojian Du {
42986c8236eSXiaojian Du 	struct amdgpu_device *adev = smu->adev;
43086c8236eSXiaojian Du 	uint32_t if_version;
43186c8236eSXiaojian Du 	int ret = 0;
43286c8236eSXiaojian Du 
43386c8236eSXiaojian Du 	ret = smu_cmn_get_smc_version(smu, &if_version, NULL);
43486c8236eSXiaojian Du 	if (ret) {
43586c8236eSXiaojian Du 		dev_err(adev->dev, "Failed to get smu if version!\n");
43686c8236eSXiaojian Du 		return ret;
43786c8236eSXiaojian Du 	}
43886c8236eSXiaojian Du 
43986c8236eSXiaojian Du 	if (if_version < 0x3)
44086c8236eSXiaojian Du 		ret = vangogh_get_legacy_smu_metrics_data(smu, member, value);
44186c8236eSXiaojian Du 	else
44286c8236eSXiaojian Du 		ret = vangogh_get_smu_metrics_data(smu, member, value);
44386c8236eSXiaojian Du 
44486c8236eSXiaojian Du 	return ret;
44586c8236eSXiaojian Du }
44686c8236eSXiaojian Du 
447f46a221bSXiaojian Du static int vangogh_allocate_dpm_context(struct smu_context *smu)
448f46a221bSXiaojian Du {
449f46a221bSXiaojian Du 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
450f46a221bSXiaojian Du 
451f46a221bSXiaojian Du 	smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
452f46a221bSXiaojian Du 				       GFP_KERNEL);
453f46a221bSXiaojian Du 	if (!smu_dpm->dpm_context)
454f46a221bSXiaojian Du 		return -ENOMEM;
455f46a221bSXiaojian Du 
456f46a221bSXiaojian Du 	smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
457f46a221bSXiaojian Du 
458f46a221bSXiaojian Du 	return 0;
459f46a221bSXiaojian Du }
460f46a221bSXiaojian Du 
461f46a221bSXiaojian Du static int vangogh_init_smc_tables(struct smu_context *smu)
462f46a221bSXiaojian Du {
463f46a221bSXiaojian Du 	int ret = 0;
464f46a221bSXiaojian Du 
465f46a221bSXiaojian Du 	ret = vangogh_tables_init(smu);
466f46a221bSXiaojian Du 	if (ret)
467f46a221bSXiaojian Du 		return ret;
468f46a221bSXiaojian Du 
469f46a221bSXiaojian Du 	ret = vangogh_allocate_dpm_context(smu);
470f46a221bSXiaojian Du 	if (ret)
471f46a221bSXiaojian Du 		return ret;
472f46a221bSXiaojian Du 
4734aef0ebcSHuang Rui #ifdef CONFIG_X86
4744aef0ebcSHuang Rui 	/* AMD x86 APU only */
4754aef0ebcSHuang Rui 	smu->cpu_core_num = boot_cpu_data.x86_max_cores;
4764aef0ebcSHuang Rui #else
4774aef0ebcSHuang Rui 	smu->cpu_core_num = 4;
4784aef0ebcSHuang Rui #endif
4794aef0ebcSHuang Rui 
480f46a221bSXiaojian Du 	return smu_v11_0_init_smc_tables(smu);
481f46a221bSXiaojian Du }
482f46a221bSXiaojian Du 
483f46a221bSXiaojian Du static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
484f46a221bSXiaojian Du {
485f46a221bSXiaojian Du 	int ret = 0;
486f46a221bSXiaojian Du 
487f46a221bSXiaojian Du 	if (enable) {
488f46a221bSXiaojian Du 		/* vcn dpm on is a prerequisite for vcn power gate messages */
489f46a221bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL);
490f46a221bSXiaojian Du 		if (ret)
491f46a221bSXiaojian Du 			return ret;
492f46a221bSXiaojian Du 	} else {
493f46a221bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL);
494f46a221bSXiaojian Du 		if (ret)
495f46a221bSXiaojian Du 			return ret;
496f46a221bSXiaojian Du 	}
497f46a221bSXiaojian Du 
498f46a221bSXiaojian Du 	return ret;
499f46a221bSXiaojian Du }
500f46a221bSXiaojian Du 
501f46a221bSXiaojian Du static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
502f46a221bSXiaojian Du {
503f46a221bSXiaojian Du 	int ret = 0;
504f46a221bSXiaojian Du 
505f46a221bSXiaojian Du 	if (enable) {
506f46a221bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL);
507f46a221bSXiaojian Du 		if (ret)
508f46a221bSXiaojian Du 			return ret;
509f46a221bSXiaojian Du 	} else {
510f46a221bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL);
511f46a221bSXiaojian Du 		if (ret)
512f46a221bSXiaojian Du 			return ret;
513f46a221bSXiaojian Du 	}
514f46a221bSXiaojian Du 
515f46a221bSXiaojian Du 	return ret;
516f46a221bSXiaojian Du }
517f46a221bSXiaojian Du 
518f46a221bSXiaojian Du static bool vangogh_is_dpm_running(struct smu_context *smu)
519f46a221bSXiaojian Du {
5201c0f0430SAlex Deucher 	struct amdgpu_device *adev = smu->adev;
521271ab489SXiaojian Du 	int ret = 0;
522271ab489SXiaojian Du 	uint64_t feature_enabled;
523f46a221bSXiaojian Du 
5241c0f0430SAlex Deucher 	/* we need to re-init after suspend so return false */
5251c0f0430SAlex Deucher 	if (adev->in_suspend)
5261c0f0430SAlex Deucher 		return false;
5271c0f0430SAlex Deucher 
5282d282665SEvan Quan 	ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
529271ab489SXiaojian Du 
530271ab489SXiaojian Du 	if (ret)
531f46a221bSXiaojian Du 		return false;
532f46a221bSXiaojian Du 
533271ab489SXiaojian Du 	return !!(feature_enabled & SMC_DPM_FEATURE);
534271ab489SXiaojian Du }
535271ab489SXiaojian Du 
536ae7b32e7SXiaojian Du static int vangogh_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type,
537ae7b32e7SXiaojian Du 						uint32_t dpm_level, uint32_t *freq)
538ae7b32e7SXiaojian Du {
539ae7b32e7SXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
540ae7b32e7SXiaojian Du 
541ae7b32e7SXiaojian Du 	if (!clk_table || clk_type >= SMU_CLK_COUNT)
542ae7b32e7SXiaojian Du 		return -EINVAL;
543ae7b32e7SXiaojian Du 
544ae7b32e7SXiaojian Du 	switch (clk_type) {
545ae7b32e7SXiaojian Du 	case SMU_SOCCLK:
546ae7b32e7SXiaojian Du 		if (dpm_level >= clk_table->NumSocClkLevelsEnabled)
547ae7b32e7SXiaojian Du 			return -EINVAL;
548ae7b32e7SXiaojian Du 		*freq = clk_table->SocClocks[dpm_level];
549ae7b32e7SXiaojian Du 		break;
550f02c7336SXiaojian Du 	case SMU_VCLK:
551f02c7336SXiaojian Du 		if (dpm_level >= clk_table->VcnClkLevelsEnabled)
552f02c7336SXiaojian Du 			return -EINVAL;
553f02c7336SXiaojian Du 		*freq = clk_table->VcnClocks[dpm_level].vclk;
554f02c7336SXiaojian Du 		break;
555f02c7336SXiaojian Du 	case SMU_DCLK:
556f02c7336SXiaojian Du 		if (dpm_level >= clk_table->VcnClkLevelsEnabled)
557f02c7336SXiaojian Du 			return -EINVAL;
558f02c7336SXiaojian Du 		*freq = clk_table->VcnClocks[dpm_level].dclk;
559f02c7336SXiaojian Du 		break;
560ae7b32e7SXiaojian Du 	case SMU_UCLK:
561ae7b32e7SXiaojian Du 	case SMU_MCLK:
562ae7b32e7SXiaojian Du 		if (dpm_level >= clk_table->NumDfPstatesEnabled)
563ae7b32e7SXiaojian Du 			return -EINVAL;
564ae7b32e7SXiaojian Du 		*freq = clk_table->DfPstateTable[dpm_level].memclk;
565ae7b32e7SXiaojian Du 
566ae7b32e7SXiaojian Du 		break;
567ae7b32e7SXiaojian Du 	case SMU_FCLK:
568ae7b32e7SXiaojian Du 		if (dpm_level >= clk_table->NumDfPstatesEnabled)
569ae7b32e7SXiaojian Du 			return -EINVAL;
570ae7b32e7SXiaojian Du 		*freq = clk_table->DfPstateTable[dpm_level].fclk;
571ae7b32e7SXiaojian Du 		break;
572ae7b32e7SXiaojian Du 	default:
573ae7b32e7SXiaojian Du 		return -EINVAL;
574ae7b32e7SXiaojian Du 	}
575ae7b32e7SXiaojian Du 
576ae7b32e7SXiaojian Du 	return 0;
577ae7b32e7SXiaojian Du }
578ae7b32e7SXiaojian Du 
57986c8236eSXiaojian Du static int vangogh_print_legacy_clk_levels(struct smu_context *smu,
580c98ee897SXiaojian Du 			enum smu_clk_type clk_type, char *buf)
581c98ee897SXiaojian Du {
582ae7b32e7SXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
58386c8236eSXiaojian Du 	SmuMetrics_legacy_t metrics;
584d7379efaSXiaojian Du 	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
585ae7b32e7SXiaojian Du 	int i, size = 0, ret = 0;
586ae7b32e7SXiaojian Du 	uint32_t cur_value = 0, value = 0, count = 0;
587ae7b32e7SXiaojian Du 	bool cur_value_match_level = false;
588ae7b32e7SXiaojian Du 
589ae7b32e7SXiaojian Du 	memset(&metrics, 0, sizeof(metrics));
590ae7b32e7SXiaojian Du 
591ae7b32e7SXiaojian Du 	ret = smu_cmn_get_metrics_table(smu, &metrics, false);
592ae7b32e7SXiaojian Du 	if (ret)
593ae7b32e7SXiaojian Du 		return ret;
594c98ee897SXiaojian Du 
5958f48ba30SLang Yu 	smu_cmn_get_sysfs_buf(&buf, &size);
5968f48ba30SLang Yu 
597c98ee897SXiaojian Du 	switch (clk_type) {
598c98ee897SXiaojian Du 	case SMU_OD_SCLK:
599d7379efaSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
6008f48ba30SLang Yu 			size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
601fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
602c98ee897SXiaojian Du 			(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
603fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
604c98ee897SXiaojian Du 			(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
605c98ee897SXiaojian Du 		}
606c98ee897SXiaojian Du 		break;
6070d90d0ddSHuang Rui 	case SMU_OD_CCLK:
608d7379efaSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
6098f48ba30SLang Yu 			size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select);
610fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
6110d90d0ddSHuang Rui 			(smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);
612fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
6130d90d0ddSHuang Rui 			(smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq);
6140d90d0ddSHuang Rui 		}
6150d90d0ddSHuang Rui 		break;
616c98ee897SXiaojian Du 	case SMU_OD_RANGE:
617d7379efaSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
6188f48ba30SLang Yu 			size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
619fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
620c98ee897SXiaojian Du 				smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
621fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n",
6220d90d0ddSHuang Rui 				smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq);
623c98ee897SXiaojian Du 		}
624c98ee897SXiaojian Du 		break;
625ae7b32e7SXiaojian Du 	case SMU_SOCCLK:
626ae7b32e7SXiaojian Du 		/* the level 3 ~ 6 of socclk use the same frequency for vangogh */
627ae7b32e7SXiaojian Du 		count = clk_table->NumSocClkLevelsEnabled;
628ae7b32e7SXiaojian Du 		cur_value = metrics.SocclkFrequency;
629ae7b32e7SXiaojian Du 		break;
630f02c7336SXiaojian Du 	case SMU_VCLK:
631f02c7336SXiaojian Du 		count = clk_table->VcnClkLevelsEnabled;
632f02c7336SXiaojian Du 		cur_value = metrics.VclkFrequency;
633f02c7336SXiaojian Du 		break;
634f02c7336SXiaojian Du 	case SMU_DCLK:
635f02c7336SXiaojian Du 		count = clk_table->VcnClkLevelsEnabled;
636f02c7336SXiaojian Du 		cur_value = metrics.DclkFrequency;
637f02c7336SXiaojian Du 		break;
638ae7b32e7SXiaojian Du 	case SMU_MCLK:
639ae7b32e7SXiaojian Du 		count = clk_table->NumDfPstatesEnabled;
640ae7b32e7SXiaojian Du 		cur_value = metrics.MemclkFrequency;
641ae7b32e7SXiaojian Du 		break;
642ae7b32e7SXiaojian Du 	case SMU_FCLK:
643ae7b32e7SXiaojian Du 		count = clk_table->NumDfPstatesEnabled;
644ae7b32e7SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetFclkFrequency, 0, &cur_value);
645ae7b32e7SXiaojian Du 		if (ret)
646ae7b32e7SXiaojian Du 			return ret;
647ae7b32e7SXiaojian Du 		break;
648ae7b32e7SXiaojian Du 	default:
649ae7b32e7SXiaojian Du 		break;
650ae7b32e7SXiaojian Du 	}
651ae7b32e7SXiaojian Du 
652ae7b32e7SXiaojian Du 	switch (clk_type) {
653ae7b32e7SXiaojian Du 	case SMU_SOCCLK:
654f02c7336SXiaojian Du 	case SMU_VCLK:
655f02c7336SXiaojian Du 	case SMU_DCLK:
656ae7b32e7SXiaojian Du 	case SMU_MCLK:
657ae7b32e7SXiaojian Du 	case SMU_FCLK:
658ae7b32e7SXiaojian Du 		for (i = 0; i < count; i++) {
659ae7b32e7SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value);
660ae7b32e7SXiaojian Du 			if (ret)
661ae7b32e7SXiaojian Du 				return ret;
662ae7b32e7SXiaojian Du 			if (!value)
663ae7b32e7SXiaojian Du 				continue;
664fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
665ae7b32e7SXiaojian Du 					cur_value == value ? "*" : "");
666ae7b32e7SXiaojian Du 			if (cur_value == value)
667ae7b32e7SXiaojian Du 				cur_value_match_level = true;
668ae7b32e7SXiaojian Du 		}
669ae7b32e7SXiaojian Du 
670ae7b32e7SXiaojian Du 		if (!cur_value_match_level)
671fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "   %uMhz *\n", cur_value);
672ae7b32e7SXiaojian Du 		break;
673c98ee897SXiaojian Du 	default:
674c98ee897SXiaojian Du 		break;
675c98ee897SXiaojian Du 	}
676c98ee897SXiaojian Du 
677c98ee897SXiaojian Du 	return size;
678c98ee897SXiaojian Du }
679c98ee897SXiaojian Du 
68086c8236eSXiaojian Du static int vangogh_print_clk_levels(struct smu_context *smu,
68186c8236eSXiaojian Du 			enum smu_clk_type clk_type, char *buf)
68286c8236eSXiaojian Du {
68386c8236eSXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
68486c8236eSXiaojian Du 	SmuMetrics_t metrics;
68586c8236eSXiaojian Du 	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
68686c8236eSXiaojian Du 	int i, size = 0, ret = 0;
68786c8236eSXiaojian Du 	uint32_t cur_value = 0, value = 0, count = 0;
68886c8236eSXiaojian Du 	bool cur_value_match_level = false;
68948c19a95SPerry Yuan 	uint32_t min, max;
69086c8236eSXiaojian Du 
69186c8236eSXiaojian Du 	memset(&metrics, 0, sizeof(metrics));
69286c8236eSXiaojian Du 
69386c8236eSXiaojian Du 	ret = smu_cmn_get_metrics_table(smu, &metrics, false);
69486c8236eSXiaojian Du 	if (ret)
69586c8236eSXiaojian Du 		return ret;
69686c8236eSXiaojian Du 
6978f48ba30SLang Yu 	smu_cmn_get_sysfs_buf(&buf, &size);
6988f48ba30SLang Yu 
69986c8236eSXiaojian Du 	switch (clk_type) {
70086c8236eSXiaojian Du 	case SMU_OD_SCLK:
70186c8236eSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
7028f48ba30SLang Yu 			size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
703fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
70486c8236eSXiaojian Du 			(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
705fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
70686c8236eSXiaojian Du 			(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
70786c8236eSXiaojian Du 		}
70886c8236eSXiaojian Du 		break;
70986c8236eSXiaojian Du 	case SMU_OD_CCLK:
71086c8236eSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
7118f48ba30SLang Yu 			size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select);
712fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
71386c8236eSXiaojian Du 			(smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);
714fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
71586c8236eSXiaojian Du 			(smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq);
71686c8236eSXiaojian Du 		}
71786c8236eSXiaojian Du 		break;
71886c8236eSXiaojian Du 	case SMU_OD_RANGE:
71986c8236eSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
7208f48ba30SLang Yu 			size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
721fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
72286c8236eSXiaojian Du 				smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
723fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n",
72486c8236eSXiaojian Du 				smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq);
72586c8236eSXiaojian Du 		}
72686c8236eSXiaojian Du 		break;
72786c8236eSXiaojian Du 	case SMU_SOCCLK:
72886c8236eSXiaojian Du 		/* the level 3 ~ 6 of socclk use the same frequency for vangogh */
72986c8236eSXiaojian Du 		count = clk_table->NumSocClkLevelsEnabled;
73086c8236eSXiaojian Du 		cur_value = metrics.Current.SocclkFrequency;
73186c8236eSXiaojian Du 		break;
73286c8236eSXiaojian Du 	case SMU_VCLK:
73386c8236eSXiaojian Du 		count = clk_table->VcnClkLevelsEnabled;
73486c8236eSXiaojian Du 		cur_value = metrics.Current.VclkFrequency;
73586c8236eSXiaojian Du 		break;
73686c8236eSXiaojian Du 	case SMU_DCLK:
73786c8236eSXiaojian Du 		count = clk_table->VcnClkLevelsEnabled;
73886c8236eSXiaojian Du 		cur_value = metrics.Current.DclkFrequency;
73986c8236eSXiaojian Du 		break;
74086c8236eSXiaojian Du 	case SMU_MCLK:
74186c8236eSXiaojian Du 		count = clk_table->NumDfPstatesEnabled;
74286c8236eSXiaojian Du 		cur_value = metrics.Current.MemclkFrequency;
74386c8236eSXiaojian Du 		break;
74486c8236eSXiaojian Du 	case SMU_FCLK:
74586c8236eSXiaojian Du 		count = clk_table->NumDfPstatesEnabled;
74686c8236eSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetFclkFrequency, 0, &cur_value);
74786c8236eSXiaojian Du 		if (ret)
74886c8236eSXiaojian Du 			return ret;
74986c8236eSXiaojian Du 		break;
75048c19a95SPerry Yuan 	case SMU_GFXCLK:
75148c19a95SPerry Yuan 	case SMU_SCLK:
75248c19a95SPerry Yuan 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetGfxclkFrequency, 0, &cur_value);
75348c19a95SPerry Yuan 		if (ret) {
75448c19a95SPerry Yuan 			return ret;
75548c19a95SPerry Yuan 		}
75648c19a95SPerry Yuan 		break;
75786c8236eSXiaojian Du 	default:
75886c8236eSXiaojian Du 		break;
75986c8236eSXiaojian Du 	}
76086c8236eSXiaojian Du 
76186c8236eSXiaojian Du 	switch (clk_type) {
76286c8236eSXiaojian Du 	case SMU_SOCCLK:
76386c8236eSXiaojian Du 	case SMU_VCLK:
76486c8236eSXiaojian Du 	case SMU_DCLK:
76586c8236eSXiaojian Du 	case SMU_MCLK:
76686c8236eSXiaojian Du 	case SMU_FCLK:
76786c8236eSXiaojian Du 		for (i = 0; i < count; i++) {
76886c8236eSXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value);
76986c8236eSXiaojian Du 			if (ret)
77086c8236eSXiaojian Du 				return ret;
77186c8236eSXiaojian Du 			if (!value)
77286c8236eSXiaojian Du 				continue;
773fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
77486c8236eSXiaojian Du 					cur_value == value ? "*" : "");
77586c8236eSXiaojian Du 			if (cur_value == value)
77686c8236eSXiaojian Du 				cur_value_match_level = true;
77786c8236eSXiaojian Du 		}
77886c8236eSXiaojian Du 
77986c8236eSXiaojian Du 		if (!cur_value_match_level)
780fe14c285SDarren Powell 			size += sysfs_emit_at(buf, size, "   %uMhz *\n", cur_value);
78186c8236eSXiaojian Du 		break;
78248c19a95SPerry Yuan 	case SMU_GFXCLK:
78348c19a95SPerry Yuan 	case SMU_SCLK:
78448c19a95SPerry Yuan 		min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
78548c19a95SPerry Yuan 		max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
78648c19a95SPerry Yuan 		if (cur_value  == max)
78748c19a95SPerry Yuan 			i = 2;
78848c19a95SPerry Yuan 		else if (cur_value == min)
78948c19a95SPerry Yuan 			i = 0;
79048c19a95SPerry Yuan 		else
79148c19a95SPerry Yuan 			i = 1;
79248c19a95SPerry Yuan 		size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
79348c19a95SPerry Yuan 				i == 0 ? "*" : "");
79448c19a95SPerry Yuan 		size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
79548c19a95SPerry Yuan 				i == 1 ? cur_value : VANGOGH_UMD_PSTATE_STANDARD_GFXCLK,
79648c19a95SPerry Yuan 				i == 1 ? "*" : "");
79748c19a95SPerry Yuan 		size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
79848c19a95SPerry Yuan 				i == 2 ? "*" : "");
79948c19a95SPerry Yuan 		break;
80086c8236eSXiaojian Du 	default:
80186c8236eSXiaojian Du 		break;
80286c8236eSXiaojian Du 	}
80386c8236eSXiaojian Du 
80486c8236eSXiaojian Du 	return size;
80586c8236eSXiaojian Du }
80686c8236eSXiaojian Du 
80786c8236eSXiaojian Du static int vangogh_common_print_clk_levels(struct smu_context *smu,
80886c8236eSXiaojian Du 			enum smu_clk_type clk_type, char *buf)
80986c8236eSXiaojian Du {
81086c8236eSXiaojian Du 	struct amdgpu_device *adev = smu->adev;
81186c8236eSXiaojian Du 	uint32_t if_version;
81286c8236eSXiaojian Du 	int ret = 0;
81386c8236eSXiaojian Du 
81486c8236eSXiaojian Du 	ret = smu_cmn_get_smc_version(smu, &if_version, NULL);
81586c8236eSXiaojian Du 	if (ret) {
81686c8236eSXiaojian Du 		dev_err(adev->dev, "Failed to get smu if version!\n");
81786c8236eSXiaojian Du 		return ret;
81886c8236eSXiaojian Du 	}
81986c8236eSXiaojian Du 
82086c8236eSXiaojian Du 	if (if_version < 0x3)
82186c8236eSXiaojian Du 		ret = vangogh_print_legacy_clk_levels(smu, clk_type, buf);
82286c8236eSXiaojian Du 	else
82386c8236eSXiaojian Du 		ret = vangogh_print_clk_levels(smu, clk_type, buf);
82486c8236eSXiaojian Du 
82586c8236eSXiaojian Du 	return ret;
82686c8236eSXiaojian Du }
82786c8236eSXiaojian Du 
828d0e4e112SXiaojian Du static int vangogh_get_profiling_clk_mask(struct smu_context *smu,
829d0e4e112SXiaojian Du 					 enum amd_dpm_forced_level level,
830d0e4e112SXiaojian Du 					 uint32_t *vclk_mask,
831d0e4e112SXiaojian Du 					 uint32_t *dclk_mask,
832d0e4e112SXiaojian Du 					 uint32_t *mclk_mask,
833d0e4e112SXiaojian Du 					 uint32_t *fclk_mask,
834d0e4e112SXiaojian Du 					 uint32_t *soc_mask)
835d0e4e112SXiaojian Du {
836d0e4e112SXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
837d0e4e112SXiaojian Du 
838307f049bSXiaojian Du 	if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
839d0e4e112SXiaojian Du 		if (mclk_mask)
840d0e4e112SXiaojian Du 			*mclk_mask = clk_table->NumDfPstatesEnabled - 1;
841307f049bSXiaojian Du 
842d0e4e112SXiaojian Du 		if (fclk_mask)
843d0e4e112SXiaojian Du 			*fclk_mask = clk_table->NumDfPstatesEnabled - 1;
844307f049bSXiaojian Du 
845307f049bSXiaojian Du 		if (soc_mask)
846307f049bSXiaojian Du 			*soc_mask = 0;
847d0e4e112SXiaojian Du 	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
848d0e4e112SXiaojian Du 		if (mclk_mask)
849d0e4e112SXiaojian Du 			*mclk_mask = 0;
850307f049bSXiaojian Du 
851d0e4e112SXiaojian Du 		if (fclk_mask)
852d0e4e112SXiaojian Du 			*fclk_mask = 0;
853d0e4e112SXiaojian Du 
854d0e4e112SXiaojian Du 		if (soc_mask)
855307f049bSXiaojian Du 			*soc_mask = 1;
856307f049bSXiaojian Du 
857307f049bSXiaojian Du 		if (vclk_mask)
858307f049bSXiaojian Du 			*vclk_mask = 1;
859307f049bSXiaojian Du 
860307f049bSXiaojian Du 		if (dclk_mask)
861307f049bSXiaojian Du 			*dclk_mask = 1;
862307f049bSXiaojian Du 	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) {
863307f049bSXiaojian Du 		if (mclk_mask)
864307f049bSXiaojian Du 			*mclk_mask = 0;
865307f049bSXiaojian Du 
866307f049bSXiaojian Du 		if (fclk_mask)
867307f049bSXiaojian Du 			*fclk_mask = 0;
868307f049bSXiaojian Du 
869307f049bSXiaojian Du 		if (soc_mask)
870307f049bSXiaojian Du 			*soc_mask = 1;
871307f049bSXiaojian Du 
872307f049bSXiaojian Du 		if (vclk_mask)
873307f049bSXiaojian Du 			*vclk_mask = 1;
874307f049bSXiaojian Du 
875307f049bSXiaojian Du 		if (dclk_mask)
876307f049bSXiaojian Du 			*dclk_mask = 1;
877d0e4e112SXiaojian Du 	}
878d0e4e112SXiaojian Du 
879d0e4e112SXiaojian Du 	return 0;
880d0e4e112SXiaojian Du }
881d0e4e112SXiaojian Du 
8828f8150faSSouptick Joarder static bool vangogh_clk_dpm_is_enabled(struct smu_context *smu,
883d0e4e112SXiaojian Du 				enum smu_clk_type clk_type)
884d0e4e112SXiaojian Du {
885d0e4e112SXiaojian Du 	enum smu_feature_mask feature_id = 0;
886d0e4e112SXiaojian Du 
887d0e4e112SXiaojian Du 	switch (clk_type) {
888d0e4e112SXiaojian Du 	case SMU_MCLK:
889d0e4e112SXiaojian Du 	case SMU_UCLK:
890d0e4e112SXiaojian Du 	case SMU_FCLK:
891d0e4e112SXiaojian Du 		feature_id = SMU_FEATURE_DPM_FCLK_BIT;
892d0e4e112SXiaojian Du 		break;
893d0e4e112SXiaojian Du 	case SMU_GFXCLK:
894d0e4e112SXiaojian Du 	case SMU_SCLK:
895d0e4e112SXiaojian Du 		feature_id = SMU_FEATURE_DPM_GFXCLK_BIT;
896d0e4e112SXiaojian Du 		break;
897d0e4e112SXiaojian Du 	case SMU_SOCCLK:
898d0e4e112SXiaojian Du 		feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
899d0e4e112SXiaojian Du 		break;
900d0e4e112SXiaojian Du 	case SMU_VCLK:
901d0e4e112SXiaojian Du 	case SMU_DCLK:
902d0e4e112SXiaojian Du 		feature_id = SMU_FEATURE_VCN_DPM_BIT;
903d0e4e112SXiaojian Du 		break;
904d0e4e112SXiaojian Du 	default:
905d0e4e112SXiaojian Du 		return true;
906d0e4e112SXiaojian Du 	}
907d0e4e112SXiaojian Du 
908d0e4e112SXiaojian Du 	if (!smu_cmn_feature_is_enabled(smu, feature_id))
909d0e4e112SXiaojian Du 		return false;
910d0e4e112SXiaojian Du 
911d0e4e112SXiaojian Du 	return true;
912d0e4e112SXiaojian Du }
913d0e4e112SXiaojian Du 
914d0e4e112SXiaojian Du static int vangogh_get_dpm_ultimate_freq(struct smu_context *smu,
915d0e4e112SXiaojian Du 					enum smu_clk_type clk_type,
916d0e4e112SXiaojian Du 					uint32_t *min,
917d0e4e112SXiaojian Du 					uint32_t *max)
918d0e4e112SXiaojian Du {
919d0e4e112SXiaojian Du 	int ret = 0;
920d0e4e112SXiaojian Du 	uint32_t soc_mask;
921d0e4e112SXiaojian Du 	uint32_t vclk_mask;
922d0e4e112SXiaojian Du 	uint32_t dclk_mask;
923d0e4e112SXiaojian Du 	uint32_t mclk_mask;
924d0e4e112SXiaojian Du 	uint32_t fclk_mask;
925d0e4e112SXiaojian Du 	uint32_t clock_limit;
926d0e4e112SXiaojian Du 
927d0e4e112SXiaojian Du 	if (!vangogh_clk_dpm_is_enabled(smu, clk_type)) {
928d0e4e112SXiaojian Du 		switch (clk_type) {
929d0e4e112SXiaojian Du 		case SMU_MCLK:
930d0e4e112SXiaojian Du 		case SMU_UCLK:
931d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.uclk;
932d0e4e112SXiaojian Du 			break;
933d0e4e112SXiaojian Du 		case SMU_FCLK:
934d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.fclk;
935d0e4e112SXiaojian Du 			break;
936d0e4e112SXiaojian Du 		case SMU_GFXCLK:
937d0e4e112SXiaojian Du 		case SMU_SCLK:
938d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.gfxclk;
939d0e4e112SXiaojian Du 			break;
940d0e4e112SXiaojian Du 		case SMU_SOCCLK:
941d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.socclk;
942d0e4e112SXiaojian Du 			break;
943d0e4e112SXiaojian Du 		case SMU_VCLK:
944d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.vclk;
945d0e4e112SXiaojian Du 			break;
946d0e4e112SXiaojian Du 		case SMU_DCLK:
947d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.dclk;
948d0e4e112SXiaojian Du 			break;
949d0e4e112SXiaojian Du 		default:
950d0e4e112SXiaojian Du 			clock_limit = 0;
951d0e4e112SXiaojian Du 			break;
952d0e4e112SXiaojian Du 		}
953d0e4e112SXiaojian Du 
954d0e4e112SXiaojian Du 		/* clock in Mhz unit */
955d0e4e112SXiaojian Du 		if (min)
956d0e4e112SXiaojian Du 			*min = clock_limit / 100;
957d0e4e112SXiaojian Du 		if (max)
958d0e4e112SXiaojian Du 			*max = clock_limit / 100;
959d0e4e112SXiaojian Du 
960d0e4e112SXiaojian Du 		return 0;
961d0e4e112SXiaojian Du 	}
962d0e4e112SXiaojian Du 	if (max) {
963d0e4e112SXiaojian Du 		ret = vangogh_get_profiling_clk_mask(smu,
964d0e4e112SXiaojian Du 							AMD_DPM_FORCED_LEVEL_PROFILE_PEAK,
965d0e4e112SXiaojian Du 							&vclk_mask,
966d0e4e112SXiaojian Du 							&dclk_mask,
967d0e4e112SXiaojian Du 							&mclk_mask,
968d0e4e112SXiaojian Du 							&fclk_mask,
969d0e4e112SXiaojian Du 							&soc_mask);
970d0e4e112SXiaojian Du 		if (ret)
971d0e4e112SXiaojian Du 			goto failed;
972d0e4e112SXiaojian Du 
973d0e4e112SXiaojian Du 		switch (clk_type) {
974d0e4e112SXiaojian Du 		case SMU_UCLK:
975d0e4e112SXiaojian Du 		case SMU_MCLK:
976d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, max);
977d0e4e112SXiaojian Du 			if (ret)
978d0e4e112SXiaojian Du 				goto failed;
979d0e4e112SXiaojian Du 			break;
980d0e4e112SXiaojian Du 		case SMU_SOCCLK:
981d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, max);
982d0e4e112SXiaojian Du 			if (ret)
983d0e4e112SXiaojian Du 				goto failed;
984d0e4e112SXiaojian Du 			break;
985d0e4e112SXiaojian Du 		case SMU_FCLK:
986d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, max);
987d0e4e112SXiaojian Du 			if (ret)
988d0e4e112SXiaojian Du 				goto failed;
989d0e4e112SXiaojian Du 			break;
990d0e4e112SXiaojian Du 		case SMU_VCLK:
991d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, max);
992d0e4e112SXiaojian Du 			if (ret)
993d0e4e112SXiaojian Du 				goto failed;
994d0e4e112SXiaojian Du 			break;
995d0e4e112SXiaojian Du 		case SMU_DCLK:
996d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, max);
997d0e4e112SXiaojian Du 			if (ret)
998d0e4e112SXiaojian Du 				goto failed;
999d0e4e112SXiaojian Du 			break;
1000d0e4e112SXiaojian Du 		default:
1001d0e4e112SXiaojian Du 			ret = -EINVAL;
1002d0e4e112SXiaojian Du 			goto failed;
1003d0e4e112SXiaojian Du 		}
1004d0e4e112SXiaojian Du 	}
1005d0e4e112SXiaojian Du 	if (min) {
1006d0e4e112SXiaojian Du 		switch (clk_type) {
1007d0e4e112SXiaojian Du 		case SMU_UCLK:
1008d0e4e112SXiaojian Du 		case SMU_MCLK:
1009d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, min);
1010d0e4e112SXiaojian Du 			if (ret)
1011d0e4e112SXiaojian Du 				goto failed;
1012d0e4e112SXiaojian Du 			break;
1013d0e4e112SXiaojian Du 		case SMU_SOCCLK:
1014d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, min);
1015d0e4e112SXiaojian Du 			if (ret)
1016d0e4e112SXiaojian Du 				goto failed;
1017d0e4e112SXiaojian Du 			break;
1018d0e4e112SXiaojian Du 		case SMU_FCLK:
1019d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, min);
1020d0e4e112SXiaojian Du 			if (ret)
1021d0e4e112SXiaojian Du 				goto failed;
1022d0e4e112SXiaojian Du 			break;
1023d0e4e112SXiaojian Du 		case SMU_VCLK:
1024d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, min);
1025d0e4e112SXiaojian Du 			if (ret)
1026d0e4e112SXiaojian Du 				goto failed;
1027d0e4e112SXiaojian Du 			break;
1028d0e4e112SXiaojian Du 		case SMU_DCLK:
1029d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, min);
1030d0e4e112SXiaojian Du 			if (ret)
1031d0e4e112SXiaojian Du 				goto failed;
1032d0e4e112SXiaojian Du 			break;
1033d0e4e112SXiaojian Du 		default:
1034d0e4e112SXiaojian Du 			ret = -EINVAL;
1035d0e4e112SXiaojian Du 			goto failed;
1036d0e4e112SXiaojian Du 		}
1037d0e4e112SXiaojian Du 	}
1038d0e4e112SXiaojian Du failed:
1039d0e4e112SXiaojian Du 	return ret;
1040d0e4e112SXiaojian Du }
1041d0e4e112SXiaojian Du 
1042307f049bSXiaojian Du static int vangogh_get_power_profile_mode(struct smu_context *smu,
1043307f049bSXiaojian Du 					   char *buf)
1044307f049bSXiaojian Du {
1045307f049bSXiaojian Du 	uint32_t i, size = 0;
1046307f049bSXiaojian Du 	int16_t workload_type = 0;
1047307f049bSXiaojian Du 
1048307f049bSXiaojian Du 	if (!buf)
1049307f049bSXiaojian Du 		return -EINVAL;
1050307f049bSXiaojian Du 
1051*dc622367SPerry Yuan 	for (i = 0; i < PP_SMC_POWER_PROFILE_COUNT; i++) {
1052307f049bSXiaojian Du 		/*
1053307f049bSXiaojian Du 		 * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
1054307f049bSXiaojian Du 		 * Not all profile modes are supported on vangogh.
1055307f049bSXiaojian Du 		 */
1056307f049bSXiaojian Du 		workload_type = smu_cmn_to_asic_specific_index(smu,
1057307f049bSXiaojian Du 							       CMN2ASIC_MAPPING_WORKLOAD,
1058307f049bSXiaojian Du 							       i);
1059307f049bSXiaojian Du 
1060307f049bSXiaojian Du 		if (workload_type < 0)
1061307f049bSXiaojian Du 			continue;
1062307f049bSXiaojian Du 
1063fe14c285SDarren Powell 		size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
106494a80b5bSDarren Powell 			i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1065307f049bSXiaojian Du 	}
1066307f049bSXiaojian Du 
1067307f049bSXiaojian Du 	return size;
1068307f049bSXiaojian Du }
1069307f049bSXiaojian Du 
1070d0e4e112SXiaojian Du static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1071d0e4e112SXiaojian Du {
1072d0e4e112SXiaojian Du 	int workload_type, ret;
1073d0e4e112SXiaojian Du 	uint32_t profile_mode = input[size];
1074d0e4e112SXiaojian Du 
1075*dc622367SPerry Yuan 	if (profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
1076d0e4e112SXiaojian Du 		dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
1077d0e4e112SXiaojian Du 		return -EINVAL;
1078d0e4e112SXiaojian Du 	}
1079d0e4e112SXiaojian Du 
1080f727ebebSXiaojian Du 	if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||
1081f727ebebSXiaojian Du 			profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)
1082f727ebebSXiaojian Du 		return 0;
1083f727ebebSXiaojian Du 
1084d0e4e112SXiaojian Du 	/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1085d0e4e112SXiaojian Du 	workload_type = smu_cmn_to_asic_specific_index(smu,
1086d0e4e112SXiaojian Du 						       CMN2ASIC_MAPPING_WORKLOAD,
1087d0e4e112SXiaojian Du 						       profile_mode);
1088d0e4e112SXiaojian Du 	if (workload_type < 0) {
10899d489afdSAlex Deucher 		dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on VANGOGH\n",
1090d0e4e112SXiaojian Du 					profile_mode);
1091d0e4e112SXiaojian Du 		return -EINVAL;
1092d0e4e112SXiaojian Du 	}
1093d0e4e112SXiaojian Du 
1094d0e4e112SXiaojian Du 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
1095d0e4e112SXiaojian Du 				    1 << workload_type,
1096d0e4e112SXiaojian Du 				    NULL);
1097d0e4e112SXiaojian Du 	if (ret) {
1098d0e4e112SXiaojian Du 		dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
1099d0e4e112SXiaojian Du 					workload_type);
1100d0e4e112SXiaojian Du 		return ret;
1101d0e4e112SXiaojian Du 	}
1102d0e4e112SXiaojian Du 
1103d0e4e112SXiaojian Du 	smu->power_profile_mode = profile_mode;
1104d0e4e112SXiaojian Du 
1105d0e4e112SXiaojian Du 	return 0;
1106d0e4e112SXiaojian Du }
1107d0e4e112SXiaojian Du 
1108dd9e0b21SXiaojian Du static int vangogh_set_soft_freq_limited_range(struct smu_context *smu,
1109dd9e0b21SXiaojian Du 					  enum smu_clk_type clk_type,
1110dd9e0b21SXiaojian Du 					  uint32_t min,
1111dd9e0b21SXiaojian Du 					  uint32_t max)
1112dd9e0b21SXiaojian Du {
1113dd9e0b21SXiaojian Du 	int ret = 0;
1114dd9e0b21SXiaojian Du 
1115dd9e0b21SXiaojian Du 	if (!vangogh_clk_dpm_is_enabled(smu, clk_type))
1116dd9e0b21SXiaojian Du 		return 0;
1117dd9e0b21SXiaojian Du 
1118dd9e0b21SXiaojian Du 	switch (clk_type) {
1119dd9e0b21SXiaojian Du 	case SMU_GFXCLK:
1120dd9e0b21SXiaojian Du 	case SMU_SCLK:
1121dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1122dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinGfxClk,
1123dd9e0b21SXiaojian Du 							min, NULL);
1124dd9e0b21SXiaojian Du 		if (ret)
1125dd9e0b21SXiaojian Du 			return ret;
1126dd9e0b21SXiaojian Du 
1127dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1128dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxGfxClk,
1129dd9e0b21SXiaojian Du 							max, NULL);
1130dd9e0b21SXiaojian Du 		if (ret)
1131dd9e0b21SXiaojian Du 			return ret;
1132dd9e0b21SXiaojian Du 		break;
1133dd9e0b21SXiaojian Du 	case SMU_FCLK:
1134dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1135dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinFclkByFreq,
1136dd9e0b21SXiaojian Du 							min, NULL);
1137dd9e0b21SXiaojian Du 		if (ret)
1138dd9e0b21SXiaojian Du 			return ret;
1139dd9e0b21SXiaojian Du 
1140dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1141dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxFclkByFreq,
1142dd9e0b21SXiaojian Du 							max, NULL);
1143dd9e0b21SXiaojian Du 		if (ret)
1144dd9e0b21SXiaojian Du 			return ret;
1145dd9e0b21SXiaojian Du 		break;
1146dd9e0b21SXiaojian Du 	case SMU_SOCCLK:
1147dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1148dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinSocclkByFreq,
1149dd9e0b21SXiaojian Du 							min, NULL);
1150dd9e0b21SXiaojian Du 		if (ret)
1151dd9e0b21SXiaojian Du 			return ret;
1152dd9e0b21SXiaojian Du 
1153dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1154dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxSocclkByFreq,
1155dd9e0b21SXiaojian Du 							max, NULL);
1156dd9e0b21SXiaojian Du 		if (ret)
1157dd9e0b21SXiaojian Du 			return ret;
1158dd9e0b21SXiaojian Du 		break;
1159dd9e0b21SXiaojian Du 	case SMU_VCLK:
1160dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1161dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinVcn,
1162dd9e0b21SXiaojian Du 							min << 16, NULL);
1163dd9e0b21SXiaojian Du 		if (ret)
1164dd9e0b21SXiaojian Du 			return ret;
1165dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1166dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxVcn,
1167dd9e0b21SXiaojian Du 							max << 16, NULL);
1168dd9e0b21SXiaojian Du 		if (ret)
1169dd9e0b21SXiaojian Du 			return ret;
1170dd9e0b21SXiaojian Du 		break;
1171dd9e0b21SXiaojian Du 	case SMU_DCLK:
1172dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1173dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinVcn,
1174dd9e0b21SXiaojian Du 							min, NULL);
1175dd9e0b21SXiaojian Du 		if (ret)
1176dd9e0b21SXiaojian Du 			return ret;
1177dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1178dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxVcn,
1179dd9e0b21SXiaojian Du 							max, NULL);
1180dd9e0b21SXiaojian Du 		if (ret)
1181dd9e0b21SXiaojian Du 			return ret;
1182dd9e0b21SXiaojian Du 		break;
1183dd9e0b21SXiaojian Du 	default:
1184dd9e0b21SXiaojian Du 		return -EINVAL;
1185dd9e0b21SXiaojian Du 	}
1186dd9e0b21SXiaojian Du 
1187dd9e0b21SXiaojian Du 	return ret;
1188dd9e0b21SXiaojian Du }
1189dd9e0b21SXiaojian Du 
1190dd9e0b21SXiaojian Du static int vangogh_force_clk_levels(struct smu_context *smu,
1191dd9e0b21SXiaojian Du 				   enum smu_clk_type clk_type, uint32_t mask)
1192dd9e0b21SXiaojian Du {
1193dd9e0b21SXiaojian Du 	uint32_t soft_min_level = 0, soft_max_level = 0;
1194dd9e0b21SXiaojian Du 	uint32_t min_freq = 0, max_freq = 0;
1195dd9e0b21SXiaojian Du 	int ret = 0 ;
1196dd9e0b21SXiaojian Du 
1197dd9e0b21SXiaojian Du 	soft_min_level = mask ? (ffs(mask) - 1) : 0;
1198dd9e0b21SXiaojian Du 	soft_max_level = mask ? (fls(mask) - 1) : 0;
1199dd9e0b21SXiaojian Du 
1200dd9e0b21SXiaojian Du 	switch (clk_type) {
1201dd9e0b21SXiaojian Du 	case SMU_SOCCLK:
1202dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu, clk_type,
1203dd9e0b21SXiaojian Du 						soft_min_level, &min_freq);
1204dd9e0b21SXiaojian Du 		if (ret)
1205dd9e0b21SXiaojian Du 			return ret;
1206dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu, clk_type,
1207dd9e0b21SXiaojian Du 						soft_max_level, &max_freq);
1208dd9e0b21SXiaojian Du 		if (ret)
1209dd9e0b21SXiaojian Du 			return ret;
1210dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1211dd9e0b21SXiaojian Du 								SMU_MSG_SetSoftMaxSocclkByFreq,
1212dd9e0b21SXiaojian Du 								max_freq, NULL);
1213dd9e0b21SXiaojian Du 		if (ret)
1214dd9e0b21SXiaojian Du 			return ret;
1215dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1216dd9e0b21SXiaojian Du 								SMU_MSG_SetHardMinSocclkByFreq,
1217dd9e0b21SXiaojian Du 								min_freq, NULL);
1218dd9e0b21SXiaojian Du 		if (ret)
1219dd9e0b21SXiaojian Du 			return ret;
1220dd9e0b21SXiaojian Du 		break;
1221dd9e0b21SXiaojian Du 	case SMU_FCLK:
1222dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
1223dd9e0b21SXiaojian Du 							clk_type, soft_min_level, &min_freq);
1224dd9e0b21SXiaojian Du 		if (ret)
1225dd9e0b21SXiaojian Du 			return ret;
1226dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
1227dd9e0b21SXiaojian Du 							clk_type, soft_max_level, &max_freq);
1228dd9e0b21SXiaojian Du 		if (ret)
1229dd9e0b21SXiaojian Du 			return ret;
1230dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1231dd9e0b21SXiaojian Du 								SMU_MSG_SetSoftMaxFclkByFreq,
1232dd9e0b21SXiaojian Du 								max_freq, NULL);
1233dd9e0b21SXiaojian Du 		if (ret)
1234dd9e0b21SXiaojian Du 			return ret;
1235dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1236dd9e0b21SXiaojian Du 								SMU_MSG_SetHardMinFclkByFreq,
1237dd9e0b21SXiaojian Du 								min_freq, NULL);
1238dd9e0b21SXiaojian Du 		if (ret)
1239dd9e0b21SXiaojian Du 			return ret;
1240dd9e0b21SXiaojian Du 		break;
1241dd9e0b21SXiaojian Du 	case SMU_VCLK:
1242dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
1243dd9e0b21SXiaojian Du 							clk_type, soft_min_level, &min_freq);
1244dd9e0b21SXiaojian Du 		if (ret)
1245dd9e0b21SXiaojian Du 			return ret;
1246307f049bSXiaojian Du 
1247dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
1248dd9e0b21SXiaojian Du 							clk_type, soft_max_level, &max_freq);
1249dd9e0b21SXiaojian Du 		if (ret)
1250dd9e0b21SXiaojian Du 			return ret;
1251307f049bSXiaojian Du 
1252307f049bSXiaojian Du 
1253dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1254dd9e0b21SXiaojian Du 								SMU_MSG_SetHardMinVcn,
1255dd9e0b21SXiaojian Du 								min_freq << 16, NULL);
1256dd9e0b21SXiaojian Du 		if (ret)
1257dd9e0b21SXiaojian Du 			return ret;
1258307f049bSXiaojian Du 
1259307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1260307f049bSXiaojian Du 								SMU_MSG_SetSoftMaxVcn,
1261307f049bSXiaojian Du 								max_freq << 16, NULL);
1262307f049bSXiaojian Du 		if (ret)
1263307f049bSXiaojian Du 			return ret;
1264307f049bSXiaojian Du 
1265dd9e0b21SXiaojian Du 		break;
1266dd9e0b21SXiaojian Du 	case SMU_DCLK:
1267dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
1268dd9e0b21SXiaojian Du 							clk_type, soft_min_level, &min_freq);
1269dd9e0b21SXiaojian Du 		if (ret)
1270dd9e0b21SXiaojian Du 			return ret;
1271307f049bSXiaojian Du 
1272dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
1273dd9e0b21SXiaojian Du 							clk_type, soft_max_level, &max_freq);
1274dd9e0b21SXiaojian Du 		if (ret)
1275dd9e0b21SXiaojian Du 			return ret;
1276307f049bSXiaojian Du 
1277dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1278dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinVcn,
1279dd9e0b21SXiaojian Du 							min_freq, NULL);
1280dd9e0b21SXiaojian Du 		if (ret)
1281dd9e0b21SXiaojian Du 			return ret;
1282307f049bSXiaojian Du 
1283307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1284307f049bSXiaojian Du 							SMU_MSG_SetSoftMaxVcn,
1285307f049bSXiaojian Du 							max_freq, NULL);
1286307f049bSXiaojian Du 		if (ret)
1287307f049bSXiaojian Du 			return ret;
1288307f049bSXiaojian Du 
1289dd9e0b21SXiaojian Du 		break;
1290dd9e0b21SXiaojian Du 	default:
1291dd9e0b21SXiaojian Du 		break;
1292dd9e0b21SXiaojian Du 	}
1293dd9e0b21SXiaojian Du 
1294dd9e0b21SXiaojian Du 	return ret;
1295dd9e0b21SXiaojian Du }
1296dd9e0b21SXiaojian Du 
1297dd9e0b21SXiaojian Du static int vangogh_force_dpm_limit_value(struct smu_context *smu, bool highest)
1298dd9e0b21SXiaojian Du {
1299dd9e0b21SXiaojian Du 	int ret = 0, i = 0;
1300dd9e0b21SXiaojian Du 	uint32_t min_freq, max_freq, force_freq;
1301dd9e0b21SXiaojian Du 	enum smu_clk_type clk_type;
1302dd9e0b21SXiaojian Du 
1303dd9e0b21SXiaojian Du 	enum smu_clk_type clks[] = {
1304dd9e0b21SXiaojian Du 		SMU_SOCCLK,
1305dd9e0b21SXiaojian Du 		SMU_VCLK,
1306dd9e0b21SXiaojian Du 		SMU_DCLK,
1307dd9e0b21SXiaojian Du 		SMU_FCLK,
1308dd9e0b21SXiaojian Du 	};
1309dd9e0b21SXiaojian Du 
1310dd9e0b21SXiaojian Du 	for (i = 0; i < ARRAY_SIZE(clks); i++) {
1311dd9e0b21SXiaojian Du 		clk_type = clks[i];
1312dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq);
1313dd9e0b21SXiaojian Du 		if (ret)
1314dd9e0b21SXiaojian Du 			return ret;
1315dd9e0b21SXiaojian Du 
1316dd9e0b21SXiaojian Du 		force_freq = highest ? max_freq : min_freq;
1317dd9e0b21SXiaojian Du 		ret = vangogh_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq);
1318dd9e0b21SXiaojian Du 		if (ret)
1319dd9e0b21SXiaojian Du 			return ret;
1320dd9e0b21SXiaojian Du 	}
1321dd9e0b21SXiaojian Du 
1322dd9e0b21SXiaojian Du 	return ret;
1323dd9e0b21SXiaojian Du }
1324dd9e0b21SXiaojian Du 
1325dd9e0b21SXiaojian Du static int vangogh_unforce_dpm_levels(struct smu_context *smu)
1326dd9e0b21SXiaojian Du {
1327dd9e0b21SXiaojian Du 	int ret = 0, i = 0;
1328dd9e0b21SXiaojian Du 	uint32_t min_freq, max_freq;
1329dd9e0b21SXiaojian Du 	enum smu_clk_type clk_type;
1330dd9e0b21SXiaojian Du 
1331dd9e0b21SXiaojian Du 	struct clk_feature_map {
1332dd9e0b21SXiaojian Du 		enum smu_clk_type clk_type;
1333dd9e0b21SXiaojian Du 		uint32_t	feature;
1334dd9e0b21SXiaojian Du 	} clk_feature_map[] = {
1335dd9e0b21SXiaojian Du 		{SMU_FCLK, SMU_FEATURE_DPM_FCLK_BIT},
1336dd9e0b21SXiaojian Du 		{SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT},
1337b0eec124SXiaojian Du 		{SMU_VCLK, SMU_FEATURE_VCN_DPM_BIT},
1338b0eec124SXiaojian Du 		{SMU_DCLK, SMU_FEATURE_VCN_DPM_BIT},
1339dd9e0b21SXiaojian Du 	};
1340dd9e0b21SXiaojian Du 
1341dd9e0b21SXiaojian Du 	for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) {
1342dd9e0b21SXiaojian Du 
1343dd9e0b21SXiaojian Du 		if (!smu_cmn_feature_is_enabled(smu, clk_feature_map[i].feature))
1344dd9e0b21SXiaojian Du 		    continue;
1345dd9e0b21SXiaojian Du 
1346dd9e0b21SXiaojian Du 		clk_type = clk_feature_map[i].clk_type;
1347dd9e0b21SXiaojian Du 
1348dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq);
1349dd9e0b21SXiaojian Du 
1350dd9e0b21SXiaojian Du 		if (ret)
1351dd9e0b21SXiaojian Du 			return ret;
1352dd9e0b21SXiaojian Du 
1353dd9e0b21SXiaojian Du 		ret = vangogh_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
1354dd9e0b21SXiaojian Du 
1355dd9e0b21SXiaojian Du 		if (ret)
1356dd9e0b21SXiaojian Du 			return ret;
1357dd9e0b21SXiaojian Du 	}
1358dd9e0b21SXiaojian Du 
1359dd9e0b21SXiaojian Du 	return ret;
1360dd9e0b21SXiaojian Du }
1361dd9e0b21SXiaojian Du 
1362dd9e0b21SXiaojian Du static int vangogh_set_peak_clock_by_device(struct smu_context *smu)
1363dd9e0b21SXiaojian Du {
1364dd9e0b21SXiaojian Du 	int ret = 0;
1365dd9e0b21SXiaojian Du 	uint32_t socclk_freq = 0, fclk_freq = 0;
1366307f049bSXiaojian Du 	uint32_t vclk_freq = 0, dclk_freq = 0;
1367dd9e0b21SXiaojian Du 
1368dd9e0b21SXiaojian Du 	ret = vangogh_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_freq);
1369dd9e0b21SXiaojian Du 	if (ret)
1370dd9e0b21SXiaojian Du 		return ret;
1371dd9e0b21SXiaojian Du 
1372dd9e0b21SXiaojian Du 	ret = vangogh_set_soft_freq_limited_range(smu, SMU_FCLK, fclk_freq, fclk_freq);
1373dd9e0b21SXiaojian Du 	if (ret)
1374dd9e0b21SXiaojian Du 		return ret;
1375dd9e0b21SXiaojian Du 
1376dd9e0b21SXiaojian Du 	ret = vangogh_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_freq);
1377dd9e0b21SXiaojian Du 	if (ret)
1378dd9e0b21SXiaojian Du 		return ret;
1379dd9e0b21SXiaojian Du 
1380dd9e0b21SXiaojian Du 	ret = vangogh_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk_freq, socclk_freq);
1381dd9e0b21SXiaojian Du 	if (ret)
1382dd9e0b21SXiaojian Du 		return ret;
1383dd9e0b21SXiaojian Du 
1384307f049bSXiaojian Du 	ret = vangogh_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_freq);
1385307f049bSXiaojian Du 	if (ret)
1386307f049bSXiaojian Du 		return ret;
1387307f049bSXiaojian Du 
1388307f049bSXiaojian Du 	ret = vangogh_set_soft_freq_limited_range(smu, SMU_VCLK, vclk_freq, vclk_freq);
1389307f049bSXiaojian Du 	if (ret)
1390307f049bSXiaojian Du 		return ret;
1391307f049bSXiaojian Du 
1392307f049bSXiaojian Du 	ret = vangogh_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_freq);
1393307f049bSXiaojian Du 	if (ret)
1394307f049bSXiaojian Du 		return ret;
1395307f049bSXiaojian Du 
1396307f049bSXiaojian Du 	ret = vangogh_set_soft_freq_limited_range(smu, SMU_DCLK, dclk_freq, dclk_freq);
1397307f049bSXiaojian Du 	if (ret)
1398307f049bSXiaojian Du 		return ret;
1399307f049bSXiaojian Du 
1400dd9e0b21SXiaojian Du 	return ret;
1401dd9e0b21SXiaojian Du }
1402dd9e0b21SXiaojian Du 
1403ea173d15SXiaojian Du static int vangogh_set_performance_level(struct smu_context *smu,
1404ea173d15SXiaojian Du 					enum amd_dpm_forced_level level)
1405ea173d15SXiaojian Du {
140691aa9c8fSAlex Deucher 	int ret = 0, i;
1407ea173d15SXiaojian Du 	uint32_t soc_mask, mclk_mask, fclk_mask;
1408307f049bSXiaojian Du 	uint32_t vclk_mask = 0, dclk_mask = 0;
1409ea173d15SXiaojian Du 
1410d7379efaSXiaojian Du 	smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1411d7379efaSXiaojian Du 	smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1412d7379efaSXiaojian Du 
141368e3871dSAlex Deucher 	switch (level) {
141468e3871dSAlex Deucher 	case AMD_DPM_FORCED_LEVEL_HIGH:
141568e3871dSAlex Deucher 		smu->gfx_actual_hard_min_freq = smu->gfx_default_soft_max_freq;
141668e3871dSAlex Deucher 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
141768e3871dSAlex Deucher 
141868e3871dSAlex Deucher 
1419ea173d15SXiaojian Du 		ret = vangogh_force_dpm_limit_value(smu, true);
142068e3871dSAlex Deucher 		if (ret)
142168e3871dSAlex Deucher 			return ret;
1422ea173d15SXiaojian Du 		break;
1423ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_LOW:
1424d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
142568e3871dSAlex Deucher 		smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq;
1426d7379efaSXiaojian Du 
1427ea173d15SXiaojian Du 		ret = vangogh_force_dpm_limit_value(smu, false);
142868e3871dSAlex Deucher 		if (ret)
142968e3871dSAlex Deucher 			return ret;
1430ea173d15SXiaojian Du 		break;
1431ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_AUTO:
1432d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1433d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1434d7379efaSXiaojian Du 
1435ea173d15SXiaojian Du 		ret = vangogh_unforce_dpm_levels(smu);
143668e3871dSAlex Deucher 		if (ret)
143768e3871dSAlex Deucher 			return ret;
1438ea173d15SXiaojian Du 		break;
1439ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
144068e3871dSAlex Deucher 		smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK;
144168e3871dSAlex Deucher 		smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK;
1442307f049bSXiaojian Du 
1443307f049bSXiaojian Du 		ret = vangogh_get_profiling_clk_mask(smu, level,
1444307f049bSXiaojian Du 							&vclk_mask,
1445307f049bSXiaojian Du 							&dclk_mask,
1446307f049bSXiaojian Du 							&mclk_mask,
1447307f049bSXiaojian Du 							&fclk_mask,
1448307f049bSXiaojian Du 							&soc_mask);
1449307f049bSXiaojian Du 		if (ret)
1450307f049bSXiaojian Du 			return ret;
1451307f049bSXiaojian Du 
1452307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask);
1453307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
1454307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_VCLK, 1 << vclk_mask);
1455307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_DCLK, 1 << dclk_mask);
1456ea173d15SXiaojian Du 		break;
1457ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1458d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
145968e3871dSAlex Deucher 		smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq;
1460ea173d15SXiaojian Du 		break;
1461ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1462d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1463d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1464d7379efaSXiaojian Du 
1465ea173d15SXiaojian Du 		ret = vangogh_get_profiling_clk_mask(smu, level,
1466ea173d15SXiaojian Du 							NULL,
1467ea173d15SXiaojian Du 							NULL,
1468ea173d15SXiaojian Du 							&mclk_mask,
1469ea173d15SXiaojian Du 							&fclk_mask,
1470307f049bSXiaojian Du 							NULL);
1471ea173d15SXiaojian Du 		if (ret)
1472ea173d15SXiaojian Du 			return ret;
1473307f049bSXiaojian Du 
1474ea173d15SXiaojian Du 		vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask);
1475ea173d15SXiaojian Du 		break;
1476ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
147768e3871dSAlex Deucher 		smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK;
147868e3871dSAlex Deucher 		smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK;
1479307f049bSXiaojian Du 
1480ea173d15SXiaojian Du 		ret = vangogh_set_peak_clock_by_device(smu);
148168e3871dSAlex Deucher 		if (ret)
148268e3871dSAlex Deucher 			return ret;
1483ea173d15SXiaojian Du 		break;
1484ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_MANUAL:
1485ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1486ea173d15SXiaojian Du 	default:
148768e3871dSAlex Deucher 		return 0;
1488ea173d15SXiaojian Du 	}
148968e3871dSAlex Deucher 
149068e3871dSAlex Deucher 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
149168e3871dSAlex Deucher 					      smu->gfx_actual_hard_min_freq, NULL);
149268e3871dSAlex Deucher 	if (ret)
149368e3871dSAlex Deucher 		return ret;
149468e3871dSAlex Deucher 
149568e3871dSAlex Deucher 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
149668e3871dSAlex Deucher 					      smu->gfx_actual_soft_max_freq, NULL);
149768e3871dSAlex Deucher 	if (ret)
149868e3871dSAlex Deucher 		return ret;
149968e3871dSAlex Deucher 
150091aa9c8fSAlex Deucher 	if (smu->adev->pm.fw_version >= 0x43f1b00) {
150191aa9c8fSAlex Deucher 		for (i = 0; i < smu->cpu_core_num; i++) {
150291aa9c8fSAlex Deucher 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinCclk,
150391aa9c8fSAlex Deucher 							      ((i << 20)
150491aa9c8fSAlex Deucher 							       | smu->cpu_actual_soft_min_freq),
150591aa9c8fSAlex Deucher 							      NULL);
150691aa9c8fSAlex Deucher 			if (ret)
150791aa9c8fSAlex Deucher 				return ret;
150891aa9c8fSAlex Deucher 
150991aa9c8fSAlex Deucher 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxCclk,
151091aa9c8fSAlex Deucher 							      ((i << 20)
151191aa9c8fSAlex Deucher 							       | smu->cpu_actual_soft_max_freq),
151291aa9c8fSAlex Deucher 							      NULL);
151391aa9c8fSAlex Deucher 			if (ret)
151491aa9c8fSAlex Deucher 				return ret;
151591aa9c8fSAlex Deucher 		}
151691aa9c8fSAlex Deucher 	}
151791aa9c8fSAlex Deucher 
1518ea173d15SXiaojian Du 	return ret;
1519ea173d15SXiaojian Du }
1520ea173d15SXiaojian Du 
1521271ab489SXiaojian Du static int vangogh_read_sensor(struct smu_context *smu,
1522271ab489SXiaojian Du 				 enum amd_pp_sensors sensor,
1523271ab489SXiaojian Du 				 void *data, uint32_t *size)
1524271ab489SXiaojian Du {
1525271ab489SXiaojian Du 	int ret = 0;
1526271ab489SXiaojian Du 
1527271ab489SXiaojian Du 	if (!data || !size)
1528271ab489SXiaojian Du 		return -EINVAL;
1529271ab489SXiaojian Du 
1530271ab489SXiaojian Du 	switch (sensor) {
1531271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_GPU_LOAD:
153286c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
15336cc24d8dSAlex Deucher 						   METRICS_AVERAGE_GFXACTIVITY,
15346cc24d8dSAlex Deucher 						   (uint32_t *)data);
1535271ab489SXiaojian Du 		*size = 4;
1536271ab489SXiaojian Du 		break;
1537271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_GPU_POWER:
153886c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
15396cc24d8dSAlex Deucher 						   METRICS_AVERAGE_SOCKETPOWER,
15406cc24d8dSAlex Deucher 						   (uint32_t *)data);
1541271ab489SXiaojian Du 		*size = 4;
1542271ab489SXiaojian Du 		break;
1543271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_EDGE_TEMP:
154486c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
15456cc24d8dSAlex Deucher 						   METRICS_TEMPERATURE_EDGE,
15466cc24d8dSAlex Deucher 						   (uint32_t *)data);
15476cc24d8dSAlex Deucher 		*size = 4;
15486cc24d8dSAlex Deucher 		break;
1549271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
155086c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
15516cc24d8dSAlex Deucher 						   METRICS_TEMPERATURE_HOTSPOT,
15526cc24d8dSAlex Deucher 						   (uint32_t *)data);
1553271ab489SXiaojian Du 		*size = 4;
1554271ab489SXiaojian Du 		break;
1555271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_GFX_MCLK:
155686c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
1557a99a5116SXiaojian Du 						   METRICS_CURR_UCLK,
15586cc24d8dSAlex Deucher 						   (uint32_t *)data);
1559271ab489SXiaojian Du 		*(uint32_t *)data *= 100;
1560271ab489SXiaojian Du 		*size = 4;
1561271ab489SXiaojian Du 		break;
1562271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_GFX_SCLK:
156386c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
1564a99a5116SXiaojian Du 						   METRICS_CURR_GFXCLK,
15656cc24d8dSAlex Deucher 						   (uint32_t *)data);
1566271ab489SXiaojian Du 		*(uint32_t *)data *= 100;
1567271ab489SXiaojian Du 		*size = 4;
1568271ab489SXiaojian Du 		break;
1569271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_VDDGFX:
157086c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
15712139d12bSAlex Deucher 						   METRICS_VOLTAGE_VDDGFX,
15722139d12bSAlex Deucher 						   (uint32_t *)data);
15732139d12bSAlex Deucher 		*size = 4;
15742139d12bSAlex Deucher 		break;
15752139d12bSAlex Deucher 	case AMDGPU_PP_SENSOR_VDDNB:
157686c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
15772139d12bSAlex Deucher 						   METRICS_VOLTAGE_VDDSOC,
15782139d12bSAlex Deucher 						   (uint32_t *)data);
1579271ab489SXiaojian Du 		*size = 4;
1580271ab489SXiaojian Du 		break;
1581517cb957SHuang Rui 	case AMDGPU_PP_SENSOR_CPU_CLK:
158286c8236eSXiaojian Du 		ret = vangogh_common_get_smu_metrics_data(smu,
1583517cb957SHuang Rui 						   METRICS_AVERAGE_CPUCLK,
1584517cb957SHuang Rui 						   (uint32_t *)data);
15854aef0ebcSHuang Rui 		*size = smu->cpu_core_num * sizeof(uint16_t);
1586517cb957SHuang Rui 		break;
1587271ab489SXiaojian Du 	default:
1588271ab489SXiaojian Du 		ret = -EOPNOTSUPP;
1589271ab489SXiaojian Du 		break;
1590271ab489SXiaojian Du 	}
1591271ab489SXiaojian Du 
1592271ab489SXiaojian Du 	return ret;
1593271ab489SXiaojian Du }
1594271ab489SXiaojian Du 
15950c3c9936SKun Liu static int vangogh_get_apu_thermal_limit(struct smu_context *smu, uint32_t *limit)
15960c3c9936SKun Liu {
15970c3c9936SKun Liu 	return smu_cmn_send_smc_msg_with_param(smu,
15980c3c9936SKun Liu 					      SMU_MSG_GetThermalLimit,
15990c3c9936SKun Liu 					      0, limit);
16000c3c9936SKun Liu }
16010c3c9936SKun Liu 
1602aea9040cSKun Liu static int vangogh_set_apu_thermal_limit(struct smu_context *smu, uint32_t limit)
16030c3c9936SKun Liu {
16040c3c9936SKun Liu 	return smu_cmn_send_smc_msg_with_param(smu,
16050c3c9936SKun Liu 					      SMU_MSG_SetReducedThermalLimit,
16060c3c9936SKun Liu 					      limit, NULL);
16070c3c9936SKun Liu }
16080c3c9936SKun Liu 
16090c3c9936SKun Liu 
1610271ab489SXiaojian Du static int vangogh_set_watermarks_table(struct smu_context *smu,
1611271ab489SXiaojian Du 				       struct pp_smu_wm_range_sets *clock_ranges)
1612271ab489SXiaojian Du {
1613271ab489SXiaojian Du 	int i;
1614271ab489SXiaojian Du 	int ret = 0;
1615271ab489SXiaojian Du 	Watermarks_t *table = smu->smu_table.watermarks_table;
1616271ab489SXiaojian Du 
1617271ab489SXiaojian Du 	if (!table || !clock_ranges)
1618271ab489SXiaojian Du 		return -EINVAL;
1619271ab489SXiaojian Du 
1620271ab489SXiaojian Du 	if (clock_ranges) {
1621271ab489SXiaojian Du 		if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
1622271ab489SXiaojian Du 			clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
1623271ab489SXiaojian Du 			return -EINVAL;
1624271ab489SXiaojian Du 
1625271ab489SXiaojian Du 		for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
1626271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].MinClock =
1627271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
1628271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].MaxClock =
1629271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
1630271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].MinMclk =
1631271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
1632271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
1633271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
1634271ab489SXiaojian Du 
1635271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].WmSetting =
1636271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].wm_inst;
1637271ab489SXiaojian Du 		}
1638271ab489SXiaojian Du 
1639271ab489SXiaojian Du 		for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
1640271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].MinClock =
1641271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
1642271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].MaxClock =
1643271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
1644271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].MinMclk =
1645271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
1646271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
1647271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
1648271ab489SXiaojian Du 
1649271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].WmSetting =
1650271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].wm_inst;
1651271ab489SXiaojian Du 		}
1652271ab489SXiaojian Du 
1653271ab489SXiaojian Du 		smu->watermarks_bitmap |= WATERMARKS_EXIST;
1654271ab489SXiaojian Du 	}
1655271ab489SXiaojian Du 
1656271ab489SXiaojian Du 	/* pass data to smu controller */
1657271ab489SXiaojian Du 	if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1658271ab489SXiaojian Du 	     !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1659271ab489SXiaojian Du 		ret = smu_cmn_write_watermarks_table(smu);
1660271ab489SXiaojian Du 		if (ret) {
1661271ab489SXiaojian Du 			dev_err(smu->adev->dev, "Failed to update WMTABLE!");
1662271ab489SXiaojian Du 			return ret;
1663271ab489SXiaojian Du 		}
1664271ab489SXiaojian Du 		smu->watermarks_bitmap |= WATERMARKS_LOADED;
1665271ab489SXiaojian Du 	}
1666271ab489SXiaojian Du 
1667271ab489SXiaojian Du 	return 0;
1668f46a221bSXiaojian Du }
1669f46a221bSXiaojian Du 
16700d6516efSLi Ma static ssize_t vangogh_get_legacy_gpu_metrics_v2_3(struct smu_context *smu,
16710d6516efSLi Ma 				      void **table)
16720d6516efSLi Ma {
16730d6516efSLi Ma 	struct smu_table_context *smu_table = &smu->smu_table;
16740d6516efSLi Ma 	struct gpu_metrics_v2_3 *gpu_metrics =
16750d6516efSLi Ma 		(struct gpu_metrics_v2_3 *)smu_table->gpu_metrics_table;
16760d6516efSLi Ma 	SmuMetrics_legacy_t metrics;
16770d6516efSLi Ma 	int ret = 0;
16780d6516efSLi Ma 
16790d6516efSLi Ma 	ret = smu_cmn_get_metrics_table(smu, &metrics, true);
16800d6516efSLi Ma 	if (ret)
16810d6516efSLi Ma 		return ret;
16820d6516efSLi Ma 
16830d6516efSLi Ma 	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 3);
16840d6516efSLi Ma 
16850d6516efSLi Ma 	gpu_metrics->temperature_gfx = metrics.GfxTemperature;
16860d6516efSLi Ma 	gpu_metrics->temperature_soc = metrics.SocTemperature;
16870d6516efSLi Ma 	memcpy(&gpu_metrics->temperature_core[0],
16880d6516efSLi Ma 		&metrics.CoreTemperature[0],
16890d6516efSLi Ma 		sizeof(uint16_t) * 4);
16900d6516efSLi Ma 	gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
16910d6516efSLi Ma 
16920d6516efSLi Ma 	gpu_metrics->average_gfx_activity = metrics.GfxActivity;
16930d6516efSLi Ma 	gpu_metrics->average_mm_activity = metrics.UvdActivity;
16940d6516efSLi Ma 
16950d6516efSLi Ma 	gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
16960d6516efSLi Ma 	gpu_metrics->average_cpu_power = metrics.Power[0];
16970d6516efSLi Ma 	gpu_metrics->average_soc_power = metrics.Power[1];
16980d6516efSLi Ma 	gpu_metrics->average_gfx_power = metrics.Power[2];
16990d6516efSLi Ma 	memcpy(&gpu_metrics->average_core_power[0],
17000d6516efSLi Ma 		&metrics.CorePower[0],
17010d6516efSLi Ma 		sizeof(uint16_t) * 4);
17020d6516efSLi Ma 
17030d6516efSLi Ma 	gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
17040d6516efSLi Ma 	gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
17050d6516efSLi Ma 	gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
17060d6516efSLi Ma 	gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
17070d6516efSLi Ma 	gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
17080d6516efSLi Ma 	gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
17090d6516efSLi Ma 
17100d6516efSLi Ma 	memcpy(&gpu_metrics->current_coreclk[0],
17110d6516efSLi Ma 		&metrics.CoreFrequency[0],
17120d6516efSLi Ma 		sizeof(uint16_t) * 4);
17130d6516efSLi Ma 	gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
17140d6516efSLi Ma 
17150d6516efSLi Ma 	gpu_metrics->throttle_status = metrics.ThrottlerStatus;
17160d6516efSLi Ma 	gpu_metrics->indep_throttle_status =
17170d6516efSLi Ma 			smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
17180d6516efSLi Ma 							   vangogh_throttler_map);
17190d6516efSLi Ma 
17200d6516efSLi Ma 	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
17210d6516efSLi Ma 
17220d6516efSLi Ma 	*table = (void *)gpu_metrics;
17230d6516efSLi Ma 
17240d6516efSLi Ma 	return sizeof(struct gpu_metrics_v2_3);
17250d6516efSLi Ma }
17260d6516efSLi Ma 
172786c8236eSXiaojian Du static ssize_t vangogh_get_legacy_gpu_metrics(struct smu_context *smu,
172886c8236eSXiaojian Du 				      void **table)
172986c8236eSXiaojian Du {
173086c8236eSXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
17317cab3cffSGraham Sider 	struct gpu_metrics_v2_2 *gpu_metrics =
17327cab3cffSGraham Sider 		(struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table;
173386c8236eSXiaojian Du 	SmuMetrics_legacy_t metrics;
173486c8236eSXiaojian Du 	int ret = 0;
173586c8236eSXiaojian Du 
173686c8236eSXiaojian Du 	ret = smu_cmn_get_metrics_table(smu, &metrics, true);
173786c8236eSXiaojian Du 	if (ret)
173886c8236eSXiaojian Du 		return ret;
173986c8236eSXiaojian Du 
17407cab3cffSGraham Sider 	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2);
174186c8236eSXiaojian Du 
174286c8236eSXiaojian Du 	gpu_metrics->temperature_gfx = metrics.GfxTemperature;
174386c8236eSXiaojian Du 	gpu_metrics->temperature_soc = metrics.SocTemperature;
174486c8236eSXiaojian Du 	memcpy(&gpu_metrics->temperature_core[0],
174586c8236eSXiaojian Du 		&metrics.CoreTemperature[0],
174686c8236eSXiaojian Du 		sizeof(uint16_t) * 4);
174786c8236eSXiaojian Du 	gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
174886c8236eSXiaojian Du 
174986c8236eSXiaojian Du 	gpu_metrics->average_gfx_activity = metrics.GfxActivity;
175086c8236eSXiaojian Du 	gpu_metrics->average_mm_activity = metrics.UvdActivity;
175186c8236eSXiaojian Du 
175286c8236eSXiaojian Du 	gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
175386c8236eSXiaojian Du 	gpu_metrics->average_cpu_power = metrics.Power[0];
175486c8236eSXiaojian Du 	gpu_metrics->average_soc_power = metrics.Power[1];
175586c8236eSXiaojian Du 	gpu_metrics->average_gfx_power = metrics.Power[2];
175686c8236eSXiaojian Du 	memcpy(&gpu_metrics->average_core_power[0],
175786c8236eSXiaojian Du 		&metrics.CorePower[0],
175886c8236eSXiaojian Du 		sizeof(uint16_t) * 4);
175986c8236eSXiaojian Du 
176086c8236eSXiaojian Du 	gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
176186c8236eSXiaojian Du 	gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
176286c8236eSXiaojian Du 	gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
176386c8236eSXiaojian Du 	gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
176486c8236eSXiaojian Du 	gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
176586c8236eSXiaojian Du 	gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
176686c8236eSXiaojian Du 
176786c8236eSXiaojian Du 	memcpy(&gpu_metrics->current_coreclk[0],
176886c8236eSXiaojian Du 		&metrics.CoreFrequency[0],
176986c8236eSXiaojian Du 		sizeof(uint16_t) * 4);
177086c8236eSXiaojian Du 	gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
177186c8236eSXiaojian Du 
177286c8236eSXiaojian Du 	gpu_metrics->throttle_status = metrics.ThrottlerStatus;
17737cab3cffSGraham Sider 	gpu_metrics->indep_throttle_status =
17747cab3cffSGraham Sider 			smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
17757cab3cffSGraham Sider 							   vangogh_throttler_map);
177686c8236eSXiaojian Du 
177786c8236eSXiaojian Du 	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
177886c8236eSXiaojian Du 
177986c8236eSXiaojian Du 	*table = (void *)gpu_metrics;
178086c8236eSXiaojian Du 
17817cab3cffSGraham Sider 	return sizeof(struct gpu_metrics_v2_2);
178286c8236eSXiaojian Du }
178386c8236eSXiaojian Du 
17840d6516efSLi Ma static ssize_t vangogh_get_gpu_metrics_v2_3(struct smu_context *smu,
17850d6516efSLi Ma 				      void **table)
17860d6516efSLi Ma {
17870d6516efSLi Ma 	struct smu_table_context *smu_table = &smu->smu_table;
17880d6516efSLi Ma 	struct gpu_metrics_v2_3 *gpu_metrics =
17890d6516efSLi Ma 		(struct gpu_metrics_v2_3 *)smu_table->gpu_metrics_table;
17900d6516efSLi Ma 	SmuMetrics_t metrics;
17910d6516efSLi Ma 	int ret = 0;
17920d6516efSLi Ma 
17930d6516efSLi Ma 	ret = smu_cmn_get_metrics_table(smu, &metrics, true);
17940d6516efSLi Ma 	if (ret)
17950d6516efSLi Ma 		return ret;
17960d6516efSLi Ma 
17970d6516efSLi Ma 	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 3);
17980d6516efSLi Ma 
17990d6516efSLi Ma 	gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
18000d6516efSLi Ma 	gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
18010d6516efSLi Ma 	memcpy(&gpu_metrics->temperature_core[0],
18020d6516efSLi Ma 		&metrics.Current.CoreTemperature[0],
18030d6516efSLi Ma 		sizeof(uint16_t) * 4);
18040d6516efSLi Ma 	gpu_metrics->temperature_l3[0] = metrics.Current.L3Temperature[0];
18050d6516efSLi Ma 
18060d6516efSLi Ma 	gpu_metrics->average_temperature_gfx = metrics.Average.GfxTemperature;
18070d6516efSLi Ma 	gpu_metrics->average_temperature_soc = metrics.Average.SocTemperature;
18080d6516efSLi Ma 	memcpy(&gpu_metrics->average_temperature_core[0],
18090d6516efSLi Ma 		&metrics.Average.CoreTemperature[0],
18100d6516efSLi Ma 		sizeof(uint16_t) * 4);
18110d6516efSLi Ma 	gpu_metrics->average_temperature_l3[0] = metrics.Average.L3Temperature[0];
18120d6516efSLi Ma 
18130d6516efSLi Ma 	gpu_metrics->average_gfx_activity = metrics.Current.GfxActivity;
18140d6516efSLi Ma 	gpu_metrics->average_mm_activity = metrics.Current.UvdActivity;
18150d6516efSLi Ma 
18160d6516efSLi Ma 	gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
18170d6516efSLi Ma 	gpu_metrics->average_cpu_power = metrics.Current.Power[0];
18180d6516efSLi Ma 	gpu_metrics->average_soc_power = metrics.Current.Power[1];
18190d6516efSLi Ma 	gpu_metrics->average_gfx_power = metrics.Current.Power[2];
18200d6516efSLi Ma 	memcpy(&gpu_metrics->average_core_power[0],
18210d6516efSLi Ma 		&metrics.Average.CorePower[0],
18220d6516efSLi Ma 		sizeof(uint16_t) * 4);
18230d6516efSLi Ma 
18240d6516efSLi Ma 	gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
18250d6516efSLi Ma 	gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
18260d6516efSLi Ma 	gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
18270d6516efSLi Ma 	gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
18280d6516efSLi Ma 	gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
18290d6516efSLi Ma 	gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
18300d6516efSLi Ma 
18310d6516efSLi Ma 	gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
18320d6516efSLi Ma 	gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
18330d6516efSLi Ma 	gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
18340d6516efSLi Ma 	gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
18350d6516efSLi Ma 	gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
18360d6516efSLi Ma 	gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
18370d6516efSLi Ma 
18380d6516efSLi Ma 	memcpy(&gpu_metrics->current_coreclk[0],
18390d6516efSLi Ma 		&metrics.Current.CoreFrequency[0],
18400d6516efSLi Ma 		sizeof(uint16_t) * 4);
18410d6516efSLi Ma 	gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0];
18420d6516efSLi Ma 
18430d6516efSLi Ma 	gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
18440d6516efSLi Ma 	gpu_metrics->indep_throttle_status =
18450d6516efSLi Ma 			smu_cmn_get_indep_throttler_status(metrics.Current.ThrottlerStatus,
18460d6516efSLi Ma 							   vangogh_throttler_map);
18470d6516efSLi Ma 
18480d6516efSLi Ma 	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
18490d6516efSLi Ma 
18500d6516efSLi Ma 	*table = (void *)gpu_metrics;
18510d6516efSLi Ma 
18520d6516efSLi Ma 	return sizeof(struct gpu_metrics_v2_3);
18530d6516efSLi Ma }
18540d6516efSLi Ma 
1855fd253334SXiaojian Du static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
1856fd253334SXiaojian Du 				      void **table)
1857fd253334SXiaojian Du {
1858fd253334SXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
18597cab3cffSGraham Sider 	struct gpu_metrics_v2_2 *gpu_metrics =
18607cab3cffSGraham Sider 		(struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table;
1861fd253334SXiaojian Du 	SmuMetrics_t metrics;
1862fd253334SXiaojian Du 	int ret = 0;
1863fd253334SXiaojian Du 
1864fd253334SXiaojian Du 	ret = smu_cmn_get_metrics_table(smu, &metrics, true);
1865fd253334SXiaojian Du 	if (ret)
1866fd253334SXiaojian Du 		return ret;
1867fd253334SXiaojian Du 
18687cab3cffSGraham Sider 	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2);
1869fd253334SXiaojian Du 
187086c8236eSXiaojian Du 	gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
187186c8236eSXiaojian Du 	gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
1872fd253334SXiaojian Du 	memcpy(&gpu_metrics->temperature_core[0],
187386c8236eSXiaojian Du 		&metrics.Current.CoreTemperature[0],
187486c8236eSXiaojian Du 		sizeof(uint16_t) * 4);
187586c8236eSXiaojian Du 	gpu_metrics->temperature_l3[0] = metrics.Current.L3Temperature[0];
1876fd253334SXiaojian Du 
187786c8236eSXiaojian Du 	gpu_metrics->average_gfx_activity = metrics.Current.GfxActivity;
187886c8236eSXiaojian Du 	gpu_metrics->average_mm_activity = metrics.Current.UvdActivity;
1879fd253334SXiaojian Du 
188086c8236eSXiaojian Du 	gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
188186c8236eSXiaojian Du 	gpu_metrics->average_cpu_power = metrics.Current.Power[0];
188286c8236eSXiaojian Du 	gpu_metrics->average_soc_power = metrics.Current.Power[1];
188386c8236eSXiaojian Du 	gpu_metrics->average_gfx_power = metrics.Current.Power[2];
1884fd253334SXiaojian Du 	memcpy(&gpu_metrics->average_core_power[0],
188586c8236eSXiaojian Du 		&metrics.Average.CorePower[0],
188686c8236eSXiaojian Du 		sizeof(uint16_t) * 4);
1887fd253334SXiaojian Du 
188886c8236eSXiaojian Du 	gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
188986c8236eSXiaojian Du 	gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
189086c8236eSXiaojian Du 	gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
189186c8236eSXiaojian Du 	gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
189286c8236eSXiaojian Du 	gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
189386c8236eSXiaojian Du 	gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
189486c8236eSXiaojian Du 
189586c8236eSXiaojian Du 	gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
189686c8236eSXiaojian Du 	gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
189786c8236eSXiaojian Du 	gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
189886c8236eSXiaojian Du 	gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
189986c8236eSXiaojian Du 	gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
190086c8236eSXiaojian Du 	gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
1901fd253334SXiaojian Du 
1902fd253334SXiaojian Du 	memcpy(&gpu_metrics->current_coreclk[0],
190386c8236eSXiaojian Du 		&metrics.Current.CoreFrequency[0],
190486c8236eSXiaojian Du 		sizeof(uint16_t) * 4);
190586c8236eSXiaojian Du 	gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0];
1906fd253334SXiaojian Du 
190786c8236eSXiaojian Du 	gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
19087cab3cffSGraham Sider 	gpu_metrics->indep_throttle_status =
19097cab3cffSGraham Sider 			smu_cmn_get_indep_throttler_status(metrics.Current.ThrottlerStatus,
19107cab3cffSGraham Sider 							   vangogh_throttler_map);
1911fd253334SXiaojian Du 
1912de4b7cd8SKevin Wang 	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
1913de4b7cd8SKevin Wang 
1914fd253334SXiaojian Du 	*table = (void *)gpu_metrics;
1915fd253334SXiaojian Du 
19167cab3cffSGraham Sider 	return sizeof(struct gpu_metrics_v2_2);
1917fd253334SXiaojian Du }
1918fd253334SXiaojian Du 
191986c8236eSXiaojian Du static ssize_t vangogh_common_get_gpu_metrics(struct smu_context *smu,
192086c8236eSXiaojian Du 				      void **table)
192186c8236eSXiaojian Du {
192286c8236eSXiaojian Du 	uint32_t if_version;
19230d6516efSLi Ma 	uint32_t smu_version;
192486c8236eSXiaojian Du 	int ret = 0;
192586c8236eSXiaojian Du 
19260d6516efSLi Ma 	ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
192786c8236eSXiaojian Du 	if (ret) {
192886c8236eSXiaojian Du 		return ret;
192986c8236eSXiaojian Du 	}
193086c8236eSXiaojian Du 
19310d6516efSLi Ma 	if (smu_version >= 0x043F3E00) {
19320d6516efSLi Ma 		if (if_version < 0x3)
19330d6516efSLi Ma 			ret = vangogh_get_legacy_gpu_metrics_v2_3(smu, table);
19340d6516efSLi Ma 		else
19350d6516efSLi Ma 			ret = vangogh_get_gpu_metrics_v2_3(smu, table);
19360d6516efSLi Ma 	} else {
193786c8236eSXiaojian Du 		if (if_version < 0x3)
193886c8236eSXiaojian Du 			ret = vangogh_get_legacy_gpu_metrics(smu, table);
193986c8236eSXiaojian Du 		else
194086c8236eSXiaojian Du 			ret = vangogh_get_gpu_metrics(smu, table);
19410d6516efSLi Ma 	}
194286c8236eSXiaojian Du 
194386c8236eSXiaojian Du 	return ret;
194486c8236eSXiaojian Du }
194586c8236eSXiaojian Du 
1946c98ee897SXiaojian Du static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
1947c98ee897SXiaojian Du 					long input[], uint32_t size)
1948c98ee897SXiaojian Du {
1949c98ee897SXiaojian Du 	int ret = 0;
1950d7379efaSXiaojian Du 	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1951c98ee897SXiaojian Du 
1952d7379efaSXiaojian Du 	if (!(smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)) {
1953d7ef887fSXiaojian Du 		dev_warn(smu->adev->dev,
1954ce7c670dSColin Ian King 			"pp_od_clk_voltage is not accessible if power_dpm_force_performance_level is not in manual mode!\n");
1955c98ee897SXiaojian Du 		return -EINVAL;
1956c98ee897SXiaojian Du 	}
1957c98ee897SXiaojian Du 
1958c98ee897SXiaojian Du 	switch (type) {
19590d90d0ddSHuang Rui 	case PP_OD_EDIT_CCLK_VDDC_TABLE:
19600d90d0ddSHuang Rui 		if (size != 3) {
19610d90d0ddSHuang Rui 			dev_err(smu->adev->dev, "Input parameter number not correct (should be 4 for processor)\n");
19620d90d0ddSHuang Rui 			return -EINVAL;
19630d90d0ddSHuang Rui 		}
19644aef0ebcSHuang Rui 		if (input[0] >= smu->cpu_core_num) {
19650d90d0ddSHuang Rui 			dev_err(smu->adev->dev, "core index is overflow, should be less than %d\n",
19664aef0ebcSHuang Rui 				smu->cpu_core_num);
19670d90d0ddSHuang Rui 		}
19680d90d0ddSHuang Rui 		smu->cpu_core_id_select = input[0];
19690d90d0ddSHuang Rui 		if (input[1] == 0) {
19700d90d0ddSHuang Rui 			if (input[2] < smu->cpu_default_soft_min_freq) {
19710d90d0ddSHuang Rui 				dev_warn(smu->adev->dev, "Fine grain setting minimum cclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
19720d90d0ddSHuang Rui 					input[2], smu->cpu_default_soft_min_freq);
19730d90d0ddSHuang Rui 				return -EINVAL;
19740d90d0ddSHuang Rui 			}
19750d90d0ddSHuang Rui 			smu->cpu_actual_soft_min_freq = input[2];
19760d90d0ddSHuang Rui 		} else if (input[1] == 1) {
19770d90d0ddSHuang Rui 			if (input[2] > smu->cpu_default_soft_max_freq) {
19780d90d0ddSHuang Rui 				dev_warn(smu->adev->dev, "Fine grain setting maximum cclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
19790d90d0ddSHuang Rui 					input[2], smu->cpu_default_soft_max_freq);
19800d90d0ddSHuang Rui 				return -EINVAL;
19810d90d0ddSHuang Rui 			}
19820d90d0ddSHuang Rui 			smu->cpu_actual_soft_max_freq = input[2];
19830d90d0ddSHuang Rui 		} else {
19840d90d0ddSHuang Rui 			return -EINVAL;
19850d90d0ddSHuang Rui 		}
19860d90d0ddSHuang Rui 		break;
1987c98ee897SXiaojian Du 	case PP_OD_EDIT_SCLK_VDDC_TABLE:
1988c98ee897SXiaojian Du 		if (size != 2) {
1989c98ee897SXiaojian Du 			dev_err(smu->adev->dev, "Input parameter number not correct\n");
1990c98ee897SXiaojian Du 			return -EINVAL;
1991c98ee897SXiaojian Du 		}
1992c98ee897SXiaojian Du 
1993c98ee897SXiaojian Du 		if (input[0] == 0) {
1994c98ee897SXiaojian Du 			if (input[1] < smu->gfx_default_hard_min_freq) {
1995307f049bSXiaojian Du 				dev_warn(smu->adev->dev,
1996307f049bSXiaojian Du 					"Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
1997c98ee897SXiaojian Du 					input[1], smu->gfx_default_hard_min_freq);
1998c98ee897SXiaojian Du 				return -EINVAL;
1999c98ee897SXiaojian Du 			}
2000c98ee897SXiaojian Du 			smu->gfx_actual_hard_min_freq = input[1];
2001c98ee897SXiaojian Du 		} else if (input[0] == 1) {
2002c98ee897SXiaojian Du 			if (input[1] > smu->gfx_default_soft_max_freq) {
2003307f049bSXiaojian Du 				dev_warn(smu->adev->dev,
2004307f049bSXiaojian Du 					"Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
2005c98ee897SXiaojian Du 					input[1], smu->gfx_default_soft_max_freq);
2006c98ee897SXiaojian Du 				return -EINVAL;
2007c98ee897SXiaojian Du 			}
2008c98ee897SXiaojian Du 			smu->gfx_actual_soft_max_freq = input[1];
2009c98ee897SXiaojian Du 		} else {
2010c98ee897SXiaojian Du 			return -EINVAL;
2011c98ee897SXiaojian Du 		}
2012c98ee897SXiaojian Du 		break;
2013c98ee897SXiaojian Du 	case PP_OD_RESTORE_DEFAULT_TABLE:
2014c98ee897SXiaojian Du 		if (size != 0) {
2015c98ee897SXiaojian Du 			dev_err(smu->adev->dev, "Input parameter number not correct\n");
2016c98ee897SXiaojian Du 			return -EINVAL;
2017c98ee897SXiaojian Du 		} else {
2018c98ee897SXiaojian Du 			smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
2019c98ee897SXiaojian Du 			smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
20200d90d0ddSHuang Rui 			smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
20210d90d0ddSHuang Rui 			smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
2022c98ee897SXiaojian Du 		}
2023c98ee897SXiaojian Du 		break;
2024c98ee897SXiaojian Du 	case PP_OD_COMMIT_DPM_TABLE:
2025c98ee897SXiaojian Du 		if (size != 0) {
2026c98ee897SXiaojian Du 			dev_err(smu->adev->dev, "Input parameter number not correct\n");
2027c98ee897SXiaojian Du 			return -EINVAL;
2028c98ee897SXiaojian Du 		} else {
2029c98ee897SXiaojian Du 			if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
2030307f049bSXiaojian Du 				dev_err(smu->adev->dev,
2031f5d8e164SColin Ian King 					"The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
2032307f049bSXiaojian Du 					smu->gfx_actual_hard_min_freq,
2033307f049bSXiaojian Du 					smu->gfx_actual_soft_max_freq);
2034c98ee897SXiaojian Du 				return -EINVAL;
2035c98ee897SXiaojian Du 			}
2036c98ee897SXiaojian Du 
2037c98ee897SXiaojian Du 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
2038c98ee897SXiaojian Du 									smu->gfx_actual_hard_min_freq, NULL);
2039c98ee897SXiaojian Du 			if (ret) {
2040c98ee897SXiaojian Du 				dev_err(smu->adev->dev, "Set hard min sclk failed!");
2041c98ee897SXiaojian Du 				return ret;
2042c98ee897SXiaojian Du 			}
2043c98ee897SXiaojian Du 
2044c98ee897SXiaojian Du 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
2045c98ee897SXiaojian Du 									smu->gfx_actual_soft_max_freq, NULL);
2046c98ee897SXiaojian Du 			if (ret) {
2047c98ee897SXiaojian Du 				dev_err(smu->adev->dev, "Set soft max sclk failed!");
2048c98ee897SXiaojian Du 				return ret;
2049c98ee897SXiaojian Du 			}
20500d90d0ddSHuang Rui 
20510d90d0ddSHuang Rui 			if (smu->adev->pm.fw_version < 0x43f1b00) {
20520d90d0ddSHuang Rui 				dev_warn(smu->adev->dev, "CPUSoftMax/CPUSoftMin are not supported, please update SBIOS!\n");
20530d90d0ddSHuang Rui 				break;
20540d90d0ddSHuang Rui 			}
20550d90d0ddSHuang Rui 
20560d90d0ddSHuang Rui 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinCclk,
20570d90d0ddSHuang Rui 							      ((smu->cpu_core_id_select << 20)
20580d90d0ddSHuang Rui 							       | smu->cpu_actual_soft_min_freq),
20590d90d0ddSHuang Rui 							      NULL);
20600d90d0ddSHuang Rui 			if (ret) {
20610d90d0ddSHuang Rui 				dev_err(smu->adev->dev, "Set hard min cclk failed!");
20620d90d0ddSHuang Rui 				return ret;
20630d90d0ddSHuang Rui 			}
20640d90d0ddSHuang Rui 
20650d90d0ddSHuang Rui 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxCclk,
20660d90d0ddSHuang Rui 							      ((smu->cpu_core_id_select << 20)
20670d90d0ddSHuang Rui 							       | smu->cpu_actual_soft_max_freq),
20680d90d0ddSHuang Rui 							      NULL);
20690d90d0ddSHuang Rui 			if (ret) {
20700d90d0ddSHuang Rui 				dev_err(smu->adev->dev, "Set soft max cclk failed!");
20710d90d0ddSHuang Rui 				return ret;
20720d90d0ddSHuang Rui 			}
2073c98ee897SXiaojian Du 		}
2074c98ee897SXiaojian Du 		break;
2075c98ee897SXiaojian Du 	default:
2076c98ee897SXiaojian Du 		return -ENOSYS;
2077c98ee897SXiaojian Du 	}
2078c98ee897SXiaojian Du 
2079c98ee897SXiaojian Du 	return ret;
2080c98ee897SXiaojian Du }
2081c98ee897SXiaojian Du 
2082fce8a4acSJinzhou Su static int vangogh_set_default_dpm_tables(struct smu_context *smu)
2083c98ee897SXiaojian Du {
2084c98ee897SXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
2085c98ee897SXiaojian Du 
2086c98ee897SXiaojian Du 	return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
2087c98ee897SXiaojian Du }
2088c98ee897SXiaojian Du 
2089c98ee897SXiaojian Du static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
2090c98ee897SXiaojian Du {
2091c98ee897SXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
2092c98ee897SXiaojian Du 
2093c98ee897SXiaojian Du 	smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
2094c98ee897SXiaojian Du 	smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
2095c98ee897SXiaojian Du 	smu->gfx_actual_hard_min_freq = 0;
2096c98ee897SXiaojian Du 	smu->gfx_actual_soft_max_freq = 0;
2097c98ee897SXiaojian Du 
20980d90d0ddSHuang Rui 	smu->cpu_default_soft_min_freq = 1400;
20990d90d0ddSHuang Rui 	smu->cpu_default_soft_max_freq = 3500;
21000d90d0ddSHuang Rui 	smu->cpu_actual_soft_min_freq = 0;
21010d90d0ddSHuang Rui 	smu->cpu_actual_soft_max_freq = 0;
21020d90d0ddSHuang Rui 
2103c98ee897SXiaojian Du 	return 0;
2104c98ee897SXiaojian Du }
2105c98ee897SXiaojian Du 
2106ae7b32e7SXiaojian Du static int vangogh_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table)
2107ae7b32e7SXiaojian Du {
2108ae7b32e7SXiaojian Du 	DpmClocks_t *table = smu->smu_table.clocks_table;
2109ae7b32e7SXiaojian Du 	int i;
2110ae7b32e7SXiaojian Du 
2111ae7b32e7SXiaojian Du 	if (!clock_table || !table)
2112ae7b32e7SXiaojian Du 		return -EINVAL;
2113ae7b32e7SXiaojian Du 
2114ae7b32e7SXiaojian Du 	for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
2115ae7b32e7SXiaojian Du 		clock_table->SocClocks[i].Freq = table->SocClocks[i];
2116ae7b32e7SXiaojian Du 		clock_table->SocClocks[i].Vol = table->SocVoltage[i];
2117ae7b32e7SXiaojian Du 	}
2118ae7b32e7SXiaojian Du 
2119ae7b32e7SXiaojian Du 	for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
2120ae7b32e7SXiaojian Du 		clock_table->FClocks[i].Freq = table->DfPstateTable[i].fclk;
2121ae7b32e7SXiaojian Du 		clock_table->FClocks[i].Vol = table->DfPstateTable[i].voltage;
2122ae7b32e7SXiaojian Du 	}
2123ae7b32e7SXiaojian Du 
2124ae7b32e7SXiaojian Du 	for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
2125ae7b32e7SXiaojian Du 		clock_table->MemClocks[i].Freq = table->DfPstateTable[i].memclk;
2126ae7b32e7SXiaojian Du 		clock_table->MemClocks[i].Vol = table->DfPstateTable[i].voltage;
2127ae7b32e7SXiaojian Du 	}
2128ae7b32e7SXiaojian Du 
2129ae7b32e7SXiaojian Du 	return 0;
2130ae7b32e7SXiaojian Du }
2131ae7b32e7SXiaojian Du 
2132ae7b32e7SXiaojian Du 
2133a0f55287SXiaomeng Hou static int vangogh_system_features_control(struct smu_context *smu, bool en)
2134a0f55287SXiaomeng Hou {
21359e3a6ab7SXiaomeng Hou 	struct amdgpu_device *adev = smu->adev;
2136aedebd40SHuang Rui 	int ret = 0;
21379e3a6ab7SXiaomeng Hou 
21385b2e2c09SAlex Deucher 	if (adev->pm.fw_version >= 0x43f1700 && !en)
2139aedebd40SHuang Rui 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RlcPowerNotify,
21405b2e2c09SAlex Deucher 						      RLC_STATUS_OFF, NULL);
2141aedebd40SHuang Rui 
2142aedebd40SHuang Rui 	return ret;
2143a0f55287SXiaomeng Hou }
2144a0f55287SXiaomeng Hou 
2145eefdf047SJinzhou Su static int vangogh_post_smu_init(struct smu_context *smu)
2146eefdf047SJinzhou Su {
2147eefdf047SJinzhou Su 	struct amdgpu_device *adev = smu->adev;
2148eefdf047SJinzhou Su 	uint32_t tmp;
21493313ef18SJinzhou Su 	int ret = 0;
2150eefdf047SJinzhou Su 	uint8_t aon_bits = 0;
2151eefdf047SJinzhou Su 	/* Two CUs in one WGP */
2152eefdf047SJinzhou Su 	uint32_t req_active_wgps = adev->gfx.cu_info.number/2;
2153eefdf047SJinzhou Su 	uint32_t total_cu = adev->gfx.config.max_cu_per_sh *
2154eefdf047SJinzhou Su 		adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines;
2155eefdf047SJinzhou Su 
21563313ef18SJinzhou Su 	/* allow message will be sent after enable message on Vangogh*/
21577ade3ca9SEvan Quan 	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
2158bb377febSJinzhou Su 			(adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
21593313ef18SJinzhou Su 		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL);
21603313ef18SJinzhou Su 		if (ret) {
21613313ef18SJinzhou Su 			dev_err(adev->dev, "Failed to Enable GfxOff!\n");
21623313ef18SJinzhou Su 			return ret;
21633313ef18SJinzhou Su 		}
2164bb377febSJinzhou Su 	} else {
2165bb377febSJinzhou Su 		adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
2166bb377febSJinzhou Su 		dev_info(adev->dev, "If GFX DPM or power gate disabled, disable GFXOFF\n");
2167bb377febSJinzhou Su 	}
21683313ef18SJinzhou Su 
2169eefdf047SJinzhou Su 	/* if all CUs are active, no need to power off any WGPs */
2170eefdf047SJinzhou Su 	if (total_cu == adev->gfx.cu_info.number)
2171eefdf047SJinzhou Su 		return 0;
2172eefdf047SJinzhou Su 
2173eefdf047SJinzhou Su 	/*
2174eefdf047SJinzhou Su 	 * Calculate the total bits number of always on WGPs for all SA/SEs in
2175eefdf047SJinzhou Su 	 * RLC_PG_ALWAYS_ON_WGP_MASK.
2176eefdf047SJinzhou Su 	 */
2177eefdf047SJinzhou Su 	tmp = RREG32_KIQ(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_ALWAYS_ON_WGP_MASK));
2178eefdf047SJinzhou Su 	tmp &= RLC_PG_ALWAYS_ON_WGP_MASK__AON_WGP_MASK_MASK;
2179eefdf047SJinzhou Su 
2180eefdf047SJinzhou Su 	aon_bits = hweight32(tmp) * adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines;
2181eefdf047SJinzhou Su 
2182eefdf047SJinzhou Su 	/* Do not request any WGPs less than set in the AON_WGP_MASK */
2183eefdf047SJinzhou Su 	if (aon_bits > req_active_wgps) {
2184eefdf047SJinzhou Su 		dev_info(adev->dev, "Number of always on WGPs greater than active WGPs: WGP power save not requested.\n");
2185eefdf047SJinzhou Su 		return 0;
2186eefdf047SJinzhou Su 	} else {
2187eefdf047SJinzhou Su 		return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestActiveWgp, req_active_wgps, NULL);
2188eefdf047SJinzhou Su 	}
2189eefdf047SJinzhou Su }
2190eefdf047SJinzhou Su 
219174353883SHuang Rui static int vangogh_mode_reset(struct smu_context *smu, int type)
219274353883SHuang Rui {
219374353883SHuang Rui 	int ret = 0, index = 0;
219474353883SHuang Rui 
219574353883SHuang Rui 	index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG,
219674353883SHuang Rui 					       SMU_MSG_GfxDeviceDriverReset);
219774353883SHuang Rui 	if (index < 0)
219874353883SHuang Rui 		return index == -EACCES ? 0 : index;
219974353883SHuang Rui 
220074353883SHuang Rui 	mutex_lock(&smu->message_lock);
220174353883SHuang Rui 
220274353883SHuang Rui 	ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index, type);
220374353883SHuang Rui 
220474353883SHuang Rui 	mutex_unlock(&smu->message_lock);
220574353883SHuang Rui 
220674353883SHuang Rui 	mdelay(10);
220774353883SHuang Rui 
220874353883SHuang Rui 	return ret;
220974353883SHuang Rui }
221074353883SHuang Rui 
221120e157c7SAlex Deucher static int vangogh_mode2_reset(struct smu_context *smu)
221220e157c7SAlex Deucher {
221374353883SHuang Rui 	return vangogh_mode_reset(smu, SMU_RESET_MODE_2);
221420e157c7SAlex Deucher }
221520e157c7SAlex Deucher 
221643195162SAndré Almeida /**
221743195162SAndré Almeida  * vangogh_get_gfxoff_status - Get gfxoff status
221843195162SAndré Almeida  *
221943195162SAndré Almeida  * @smu: amdgpu_device pointer
222043195162SAndré Almeida  *
222143195162SAndré Almeida  * Get current gfxoff status
222243195162SAndré Almeida  *
222343195162SAndré Almeida  * Return:
222443195162SAndré Almeida  * * 0	- GFXOFF (default if enabled).
222543195162SAndré Almeida  * * 1	- Transition out of GFX State.
222643195162SAndré Almeida  * * 2	- Not in GFXOFF.
222743195162SAndré Almeida  * * 3	- Transition into GFXOFF.
222843195162SAndré Almeida  */
222943195162SAndré Almeida static u32 vangogh_get_gfxoff_status(struct smu_context *smu)
223043195162SAndré Almeida {
223143195162SAndré Almeida 	struct amdgpu_device *adev = smu->adev;
223243195162SAndré Almeida 	u32 reg, gfxoff_status;
223343195162SAndré Almeida 
223443195162SAndré Almeida 	reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_GFX_MISC_CNTL);
223543195162SAndré Almeida 	gfxoff_status = (reg & SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK)
223643195162SAndré Almeida 		>> SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT;
223743195162SAndré Almeida 
223843195162SAndré Almeida 	return gfxoff_status;
223943195162SAndré Almeida }
224043195162SAndré Almeida 
2241488f211dSEvan Quan static int vangogh_get_power_limit(struct smu_context *smu,
2242488f211dSEvan Quan 				   uint32_t *current_power_limit,
2243488f211dSEvan Quan 				   uint32_t *default_power_limit,
2244488f211dSEvan Quan 				   uint32_t *max_power_limit)
2245ae07970aSXiaomeng Hou {
2246ae07970aSXiaomeng Hou 	struct smu_11_5_power_context *power_context =
2247ae07970aSXiaomeng Hou 								smu->smu_power.power_context;
2248ae07970aSXiaomeng Hou 	uint32_t ppt_limit;
2249ae07970aSXiaomeng Hou 	int ret = 0;
2250ae07970aSXiaomeng Hou 
2251ae07970aSXiaomeng Hou 	if (smu->adev->pm.fw_version < 0x43f1e00)
2252ae07970aSXiaomeng Hou 		return ret;
2253ae07970aSXiaomeng Hou 
2254ae07970aSXiaomeng Hou 	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSlowPPTLimit, &ppt_limit);
2255ae07970aSXiaomeng Hou 	if (ret) {
2256ae07970aSXiaomeng Hou 		dev_err(smu->adev->dev, "Get slow PPT limit failed!\n");
2257ae07970aSXiaomeng Hou 		return ret;
2258ae07970aSXiaomeng Hou 	}
2259ae07970aSXiaomeng Hou 	/* convert from milliwatt to watt */
2260488f211dSEvan Quan 	if (current_power_limit)
2261488f211dSEvan Quan 		*current_power_limit = ppt_limit / 1000;
2262488f211dSEvan Quan 	if (default_power_limit)
2263488f211dSEvan Quan 		*default_power_limit = ppt_limit / 1000;
2264488f211dSEvan Quan 	if (max_power_limit)
2265488f211dSEvan Quan 		*max_power_limit = 29;
2266ae07970aSXiaomeng Hou 
2267ae07970aSXiaomeng Hou 	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit);
2268ae07970aSXiaomeng Hou 	if (ret) {
2269ae07970aSXiaomeng Hou 		dev_err(smu->adev->dev, "Get fast PPT limit failed!\n");
2270ae07970aSXiaomeng Hou 		return ret;
2271ae07970aSXiaomeng Hou 	}
2272ae07970aSXiaomeng Hou 	/* convert from milliwatt to watt */
22736e58941cSEric Huang 	power_context->current_fast_ppt_limit =
22746e58941cSEric Huang 			power_context->default_fast_ppt_limit = ppt_limit / 1000;
2275ae07970aSXiaomeng Hou 	power_context->max_fast_ppt_limit = 30;
2276ae07970aSXiaomeng Hou 
2277ae07970aSXiaomeng Hou 	return ret;
2278ae07970aSXiaomeng Hou }
2279ae07970aSXiaomeng Hou 
2280ae07970aSXiaomeng Hou static int vangogh_get_ppt_limit(struct smu_context *smu,
2281ae07970aSXiaomeng Hou 								uint32_t *ppt_limit,
2282ae07970aSXiaomeng Hou 								enum smu_ppt_limit_type type,
2283ae07970aSXiaomeng Hou 								enum smu_ppt_limit_level level)
2284ae07970aSXiaomeng Hou {
2285ae07970aSXiaomeng Hou 	struct smu_11_5_power_context *power_context =
2286ae07970aSXiaomeng Hou 							smu->smu_power.power_context;
2287ae07970aSXiaomeng Hou 
2288ae07970aSXiaomeng Hou 	if (!power_context)
2289ae07970aSXiaomeng Hou 		return -EOPNOTSUPP;
2290ae07970aSXiaomeng Hou 
2291ae07970aSXiaomeng Hou 	if (type == SMU_FAST_PPT_LIMIT) {
2292ae07970aSXiaomeng Hou 		switch (level) {
2293ae07970aSXiaomeng Hou 		case SMU_PPT_LIMIT_MAX:
2294ae07970aSXiaomeng Hou 			*ppt_limit = power_context->max_fast_ppt_limit;
2295ae07970aSXiaomeng Hou 			break;
2296ae07970aSXiaomeng Hou 		case SMU_PPT_LIMIT_CURRENT:
2297ae07970aSXiaomeng Hou 			*ppt_limit = power_context->current_fast_ppt_limit;
2298ae07970aSXiaomeng Hou 			break;
22996e58941cSEric Huang 		case SMU_PPT_LIMIT_DEFAULT:
23006e58941cSEric Huang 			*ppt_limit = power_context->default_fast_ppt_limit;
23016e58941cSEric Huang 			break;
2302ae07970aSXiaomeng Hou 		default:
2303ae07970aSXiaomeng Hou 			break;
2304ae07970aSXiaomeng Hou 		}
2305ae07970aSXiaomeng Hou 	}
2306ae07970aSXiaomeng Hou 
2307ae07970aSXiaomeng Hou 	return 0;
2308ae07970aSXiaomeng Hou }
2309ae07970aSXiaomeng Hou 
23102d1ac1cbSDarren Powell static int vangogh_set_power_limit(struct smu_context *smu,
23112d1ac1cbSDarren Powell 				   enum smu_ppt_limit_type limit_type,
23122d1ac1cbSDarren Powell 				   uint32_t ppt_limit)
2313ae07970aSXiaomeng Hou {
2314ae07970aSXiaomeng Hou 	struct smu_11_5_power_context *power_context =
2315ae07970aSXiaomeng Hou 			smu->smu_power.power_context;
2316ae07970aSXiaomeng Hou 	int ret = 0;
2317ae07970aSXiaomeng Hou 
2318ae07970aSXiaomeng Hou 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
2319ae07970aSXiaomeng Hou 		dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
2320ae07970aSXiaomeng Hou 		return -EOPNOTSUPP;
2321ae07970aSXiaomeng Hou 	}
2322ae07970aSXiaomeng Hou 
2323ae07970aSXiaomeng Hou 	switch (limit_type) {
2324ae07970aSXiaomeng Hou 	case SMU_DEFAULT_PPT_LIMIT:
2325ae07970aSXiaomeng Hou 		ret = smu_cmn_send_smc_msg_with_param(smu,
2326ae07970aSXiaomeng Hou 				SMU_MSG_SetSlowPPTLimit,
2327ae07970aSXiaomeng Hou 				ppt_limit * 1000, /* convert from watt to milliwatt */
2328ae07970aSXiaomeng Hou 				NULL);
2329ae07970aSXiaomeng Hou 		if (ret)
2330ae07970aSXiaomeng Hou 			return ret;
2331ae07970aSXiaomeng Hou 
2332ae07970aSXiaomeng Hou 		smu->current_power_limit = ppt_limit;
2333ae07970aSXiaomeng Hou 		break;
2334ae07970aSXiaomeng Hou 	case SMU_FAST_PPT_LIMIT:
2335ae07970aSXiaomeng Hou 		ppt_limit &= ~(SMU_FAST_PPT_LIMIT << 24);
2336ae07970aSXiaomeng Hou 		if (ppt_limit > power_context->max_fast_ppt_limit) {
2337ae07970aSXiaomeng Hou 			dev_err(smu->adev->dev,
2338ae07970aSXiaomeng Hou 				"New power limit (%d) is over the max allowed %d\n",
2339ae07970aSXiaomeng Hou 				ppt_limit, power_context->max_fast_ppt_limit);
2340ae07970aSXiaomeng Hou 			return ret;
2341ae07970aSXiaomeng Hou 		}
2342ae07970aSXiaomeng Hou 
2343ae07970aSXiaomeng Hou 		ret = smu_cmn_send_smc_msg_with_param(smu,
2344ae07970aSXiaomeng Hou 				SMU_MSG_SetFastPPTLimit,
2345ae07970aSXiaomeng Hou 				ppt_limit * 1000, /* convert from watt to milliwatt */
2346ae07970aSXiaomeng Hou 				NULL);
2347ae07970aSXiaomeng Hou 		if (ret)
2348ae07970aSXiaomeng Hou 			return ret;
2349ae07970aSXiaomeng Hou 
2350ae07970aSXiaomeng Hou 		power_context->current_fast_ppt_limit = ppt_limit;
2351ae07970aSXiaomeng Hou 		break;
2352ae07970aSXiaomeng Hou 	default:
2353ae07970aSXiaomeng Hou 		return -EINVAL;
2354ae07970aSXiaomeng Hou 	}
2355ae07970aSXiaomeng Hou 
2356ae07970aSXiaomeng Hou 	return ret;
2357ae07970aSXiaomeng Hou }
2358ae07970aSXiaomeng Hou 
23591ed5a845SAndré Almeida /**
23601ed5a845SAndré Almeida  * vangogh_set_gfxoff_residency
23611ed5a845SAndré Almeida  *
23621ed5a845SAndré Almeida  * @smu: amdgpu_device pointer
23631ed5a845SAndré Almeida  * @start: start/stop residency log
23641ed5a845SAndré Almeida  *
23651ed5a845SAndré Almeida  * This function will be used to log gfxoff residency
23661ed5a845SAndré Almeida  *
23671ed5a845SAndré Almeida  *
23681ed5a845SAndré Almeida  * Returns standard response codes.
23691ed5a845SAndré Almeida  */
23701ed5a845SAndré Almeida static u32 vangogh_set_gfxoff_residency(struct smu_context *smu, bool start)
23711ed5a845SAndré Almeida {
23721ed5a845SAndré Almeida 	int ret = 0;
23731ed5a845SAndré Almeida 	u32 residency;
23741ed5a845SAndré Almeida 	struct amdgpu_device *adev = smu->adev;
23751ed5a845SAndré Almeida 
23761ed5a845SAndré Almeida 	if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
23771ed5a845SAndré Almeida 		return 0;
23781ed5a845SAndré Almeida 
23791ed5a845SAndré Almeida 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_LogGfxOffResidency,
23801ed5a845SAndré Almeida 					      start, &residency);
23811ed5a845SAndré Almeida 
23821ed5a845SAndré Almeida 	if (!start)
23831ed5a845SAndré Almeida 		adev->gfx.gfx_off_residency = residency;
23841ed5a845SAndré Almeida 
23851ed5a845SAndré Almeida 	return ret;
23861ed5a845SAndré Almeida }
23871ed5a845SAndré Almeida 
23881ed5a845SAndré Almeida /**
23891ed5a845SAndré Almeida  * vangogh_get_gfxoff_residency
23901ed5a845SAndré Almeida  *
23911ed5a845SAndré Almeida  * @smu: amdgpu_device pointer
23921ed5a845SAndré Almeida  *
23931ed5a845SAndré Almeida  * This function will be used to get gfxoff residency.
23941ed5a845SAndré Almeida  *
23951ed5a845SAndré Almeida  * Returns standard response codes.
23961ed5a845SAndré Almeida  */
23971ed5a845SAndré Almeida static u32 vangogh_get_gfxoff_residency(struct smu_context *smu, uint32_t *residency)
23981ed5a845SAndré Almeida {
23991ed5a845SAndré Almeida 	struct amdgpu_device *adev = smu->adev;
24001ed5a845SAndré Almeida 
24011ed5a845SAndré Almeida 	*residency = adev->gfx.gfx_off_residency;
24021ed5a845SAndré Almeida 
24031ed5a845SAndré Almeida 	return 0;
24041ed5a845SAndré Almeida }
24051ed5a845SAndré Almeida 
24061ed5a845SAndré Almeida /**
24071ed5a845SAndré Almeida  * vangogh_get_gfxoff_entrycount - get gfxoff entry count
24081ed5a845SAndré Almeida  *
24091ed5a845SAndré Almeida  * @smu: amdgpu_device pointer
24101ed5a845SAndré Almeida  *
24111ed5a845SAndré Almeida  * This function will be used to get gfxoff entry count
24121ed5a845SAndré Almeida  *
24131ed5a845SAndré Almeida  * Returns standard response codes.
24141ed5a845SAndré Almeida  */
24151ed5a845SAndré Almeida static u32 vangogh_get_gfxoff_entrycount(struct smu_context *smu, uint64_t *entrycount)
24161ed5a845SAndré Almeida {
24171ed5a845SAndré Almeida 	int ret = 0, value = 0;
24181ed5a845SAndré Almeida 	struct amdgpu_device *adev = smu->adev;
24191ed5a845SAndré Almeida 
24201ed5a845SAndré Almeida 	if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
24211ed5a845SAndré Almeida 		return 0;
24221ed5a845SAndré Almeida 
24231ed5a845SAndré Almeida 	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetGfxOffEntryCount, &value);
24241ed5a845SAndré Almeida 	*entrycount = value + adev->gfx.gfx_off_entrycount;
24251ed5a845SAndré Almeida 
24261ed5a845SAndré Almeida 	return ret;
24271ed5a845SAndré Almeida }
24281ed5a845SAndré Almeida 
2429f46a221bSXiaojian Du static const struct pptable_funcs vangogh_ppt_funcs = {
2430271ab489SXiaojian Du 
2431f46a221bSXiaojian Du 	.check_fw_status = smu_v11_0_check_fw_status,
2432f46a221bSXiaojian Du 	.check_fw_version = smu_v11_0_check_fw_version,
2433f46a221bSXiaojian Du 	.init_smc_tables = vangogh_init_smc_tables,
2434f46a221bSXiaojian Du 	.fini_smc_tables = smu_v11_0_fini_smc_tables,
2435f46a221bSXiaojian Du 	.init_power = smu_v11_0_init_power,
2436f46a221bSXiaojian Du 	.fini_power = smu_v11_0_fini_power,
2437f46a221bSXiaojian Du 	.register_irq_handler = smu_v11_0_register_irq_handler,
2438f46a221bSXiaojian Du 	.notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
2439f46a221bSXiaojian Du 	.send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
2440f46a221bSXiaojian Du 	.send_smc_msg = smu_cmn_send_smc_msg,
2441271ab489SXiaojian Du 	.dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable,
2442271ab489SXiaojian Du 	.dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable,
2443f46a221bSXiaojian Du 	.is_dpm_running = vangogh_is_dpm_running,
2444271ab489SXiaojian Du 	.read_sensor = vangogh_read_sensor,
24450c3c9936SKun Liu 	.get_apu_thermal_limit = vangogh_get_apu_thermal_limit,
24460c3c9936SKun Liu 	.set_apu_thermal_limit = vangogh_set_apu_thermal_limit,
24475af779adSEvan Quan 	.get_enabled_mask = smu_cmn_get_enabled_mask,
2448f46a221bSXiaojian Du 	.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
2449271ab489SXiaojian Du 	.set_watermarks_table = vangogh_set_watermarks_table,
2450271ab489SXiaojian Du 	.set_driver_table_location = smu_v11_0_set_driver_table_location,
2451f46a221bSXiaojian Du 	.interrupt_work = smu_v11_0_interrupt_work,
245286c8236eSXiaojian Du 	.get_gpu_metrics = vangogh_common_get_gpu_metrics,
2453c98ee897SXiaojian Du 	.od_edit_dpm_table = vangogh_od_edit_dpm_table,
245486c8236eSXiaojian Du 	.print_clk_levels = vangogh_common_print_clk_levels,
2455c98ee897SXiaojian Du 	.set_default_dpm_table = vangogh_set_default_dpm_tables,
2456c98ee897SXiaojian Du 	.set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters,
2457a0f55287SXiaomeng Hou 	.system_features_control = vangogh_system_features_control,
2458d0e4e112SXiaojian Du 	.feature_is_enabled = smu_cmn_feature_is_enabled,
2459d0e4e112SXiaojian Du 	.set_power_profile_mode = vangogh_set_power_profile_mode,
2460307f049bSXiaojian Du 	.get_power_profile_mode = vangogh_get_power_profile_mode,
2461ae7b32e7SXiaojian Du 	.get_dpm_clock_table = vangogh_get_dpm_clock_table,
2462dd9e0b21SXiaojian Du 	.force_clk_levels = vangogh_force_clk_levels,
2463ea173d15SXiaojian Du 	.set_performance_level = vangogh_set_performance_level,
2464eefdf047SJinzhou Su 	.post_init = vangogh_post_smu_init,
246520e157c7SAlex Deucher 	.mode2_reset = vangogh_mode2_reset,
2466b58ce1feSJinzhou Su 	.gfx_off_control = smu_v11_0_gfx_off_control,
246743195162SAndré Almeida 	.get_gfx_off_status = vangogh_get_gfxoff_status,
24681ed5a845SAndré Almeida 	.get_gfx_off_entrycount = vangogh_get_gfxoff_entrycount,
24691ed5a845SAndré Almeida 	.get_gfx_off_residency = vangogh_get_gfxoff_residency,
24701ed5a845SAndré Almeida 	.set_gfx_off_residency = vangogh_set_gfxoff_residency,
2471ae07970aSXiaomeng Hou 	.get_ppt_limit = vangogh_get_ppt_limit,
2472ae07970aSXiaomeng Hou 	.get_power_limit = vangogh_get_power_limit,
2473ae07970aSXiaomeng Hou 	.set_power_limit = vangogh_set_power_limit,
24743495d3c3SXiaojian Du 	.get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
2475f46a221bSXiaojian Du };
2476f46a221bSXiaojian Du 
2477f46a221bSXiaojian Du void vangogh_set_ppt_funcs(struct smu_context *smu)
2478f46a221bSXiaojian Du {
2479f46a221bSXiaojian Du 	smu->ppt_funcs = &vangogh_ppt_funcs;
2480f46a221bSXiaojian Du 	smu->message_map = vangogh_message_map;
2481f46a221bSXiaojian Du 	smu->feature_map = vangogh_feature_mask_map;
2482f46a221bSXiaojian Du 	smu->table_map = vangogh_table_map;
2483ec3b35c8SXiaojian Du 	smu->workload_map = vangogh_workload_map;
2484f46a221bSXiaojian Du 	smu->is_apu = true;
2485da1db031SAlex Deucher 	smu_v11_0_set_smu_mailbox_registers(smu);
2486f46a221bSXiaojian Du }
2487