8a2c9c7abea6d4e21324b07607818f9688d3b7f0
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / amd / pm / swsmu / smu11 / vangogh_ppt.c
1 /*
2  * Copyright 2020 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23
24 #define SWSMU_CODE_LAYER_L2
25
26 #include "amdgpu.h"
27 #include "amdgpu_smu.h"
28 #include "smu_v11_0.h"
29 #include "smu11_driver_if_vangogh.h"
30 #include "vangogh_ppt.h"
31 #include "smu_v11_5_ppsmc.h"
32 #include "smu_v11_5_pmfw.h"
33 #include "smu_cmn.h"
34 #include "soc15_common.h"
35 #include "asic_reg/gc/gc_10_3_0_offset.h"
36 #include "asic_reg/gc/gc_10_3_0_sh_mask.h"
37 #include <asm/processor.h>
38
39 /*
40  * DO NOT use these for err/warn/info/debug messages.
41  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
42  * They are more MGPU friendly.
43  */
44 #undef pr_err
45 #undef pr_warn
46 #undef pr_info
47 #undef pr_debug
48
49 // Registers related to GFXOFF
50 // addressBlock: smuio_smuio_SmuSmuioDec
51 // base address: 0x5a000
52 #define mmSMUIO_GFX_MISC_CNTL                   0x00c5
53 #define mmSMUIO_GFX_MISC_CNTL_BASE_IDX          0
54
55 //SMUIO_GFX_MISC_CNTL
56 #define SMUIO_GFX_MISC_CNTL__SMU_GFX_cold_vs_gfxoff__SHIFT      0x0
57 #define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT           0x1
58 #define SMUIO_GFX_MISC_CNTL__SMU_GFX_cold_vs_gfxoff_MASK        0x00000001L
59 #define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK             0x00000006L
60
61 #define FEATURE_MASK(feature) (1ULL << feature)
62 #define SMC_DPM_FEATURE ( \
63         FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
64         FEATURE_MASK(FEATURE_VCN_DPM_BIT)        | \
65         FEATURE_MASK(FEATURE_FCLK_DPM_BIT)       | \
66         FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT)     | \
67         FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT)     | \
68         FEATURE_MASK(FEATURE_LCLK_DPM_BIT)       | \
69         FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT)    | \
70         FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \
71         FEATURE_MASK(FEATURE_GFX_DPM_BIT))
72
73 static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = {
74         MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,                  0),
75         MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,                0),
76         MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,   0),
77         MSG_MAP(EnableGfxOff,                   PPSMC_MSG_EnableGfxOff,                 0),
78         MSG_MAP(AllowGfxOff,                    PPSMC_MSG_AllowGfxOff,          0),
79         MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff,               0),
80         MSG_MAP(PowerDownIspByTile,             PPSMC_MSG_PowerDownIspByTile,   0),
81         MSG_MAP(PowerUpIspByTile,               PPSMC_MSG_PowerUpIspByTile,             0),
82         MSG_MAP(PowerDownVcn,                   PPSMC_MSG_PowerDownVcn,                 0),
83         MSG_MAP(PowerUpVcn,                     PPSMC_MSG_PowerUpVcn,                   0),
84         MSG_MAP(RlcPowerNotify,                 PPSMC_MSG_RlcPowerNotify,               0),
85         MSG_MAP(SetHardMinVcn,                  PPSMC_MSG_SetHardMinVcn,                0),
86         MSG_MAP(SetSoftMinGfxclk,               PPSMC_MSG_SetSoftMinGfxclk,             0),
87         MSG_MAP(ActiveProcessNotify,            PPSMC_MSG_ActiveProcessNotify,          0),
88         MSG_MAP(SetHardMinIspiclkByFreq,        PPSMC_MSG_SetHardMinIspiclkByFreq,      0),
89         MSG_MAP(SetHardMinIspxclkByFreq,        PPSMC_MSG_SetHardMinIspxclkByFreq,      0),
90         MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh,        0),
91         MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow,         0),
92         MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,        0),
93         MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,        0),
94         MSG_MAP(GfxDeviceDriverReset,           PPSMC_MSG_GfxDeviceDriverReset,         0),
95         MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,        0),
96         MSG_MAP(SetHardMinSocclkByFreq,         PPSMC_MSG_SetHardMinSocclkByFreq,       0),
97         MSG_MAP(SetSoftMinFclk,                 PPSMC_MSG_SetSoftMinFclk,               0),
98         MSG_MAP(SetSoftMinVcn,                  PPSMC_MSG_SetSoftMinVcn,                0),
99         MSG_MAP(EnablePostCode,                 PPSMC_MSG_EnablePostCode,               0),
100         MSG_MAP(GetGfxclkFrequency,             PPSMC_MSG_GetGfxclkFrequency,   0),
101         MSG_MAP(GetFclkFrequency,               PPSMC_MSG_GetFclkFrequency,             0),
102         MSG_MAP(SetSoftMaxGfxClk,               PPSMC_MSG_SetSoftMaxGfxClk,             0),
103         MSG_MAP(SetHardMinGfxClk,               PPSMC_MSG_SetHardMinGfxClk,             0),
104         MSG_MAP(SetSoftMaxSocclkByFreq,         PPSMC_MSG_SetSoftMaxSocclkByFreq,       0),
105         MSG_MAP(SetSoftMaxFclkByFreq,           PPSMC_MSG_SetSoftMaxFclkByFreq,         0),
106         MSG_MAP(SetSoftMaxVcn,                  PPSMC_MSG_SetSoftMaxVcn,                        0),
107         MSG_MAP(SetPowerLimitPercentage,        PPSMC_MSG_SetPowerLimitPercentage,      0),
108         MSG_MAP(PowerDownJpeg,                  PPSMC_MSG_PowerDownJpeg,                        0),
109         MSG_MAP(PowerUpJpeg,                    PPSMC_MSG_PowerUpJpeg,                          0),
110         MSG_MAP(SetHardMinFclkByFreq,           PPSMC_MSG_SetHardMinFclkByFreq,         0),
111         MSG_MAP(SetSoftMinSocclkByFreq,         PPSMC_MSG_SetSoftMinSocclkByFreq,       0),
112         MSG_MAP(PowerUpCvip,                    PPSMC_MSG_PowerUpCvip,                          0),
113         MSG_MAP(PowerDownCvip,                  PPSMC_MSG_PowerDownCvip,                        0),
114         MSG_MAP(GetPptLimit,                        PPSMC_MSG_GetPptLimit,                      0),
115         MSG_MAP(GetThermalLimit,                    PPSMC_MSG_GetThermalLimit,          0),
116         MSG_MAP(GetCurrentTemperature,              PPSMC_MSG_GetCurrentTemperature, 0),
117         MSG_MAP(GetCurrentPower,                    PPSMC_MSG_GetCurrentPower,           0),
118         MSG_MAP(GetCurrentVoltage,                  PPSMC_MSG_GetCurrentVoltage,         0),
119         MSG_MAP(GetCurrentCurrent,                  PPSMC_MSG_GetCurrentCurrent,         0),
120         MSG_MAP(GetAverageCpuActivity,              PPSMC_MSG_GetAverageCpuActivity, 0),
121         MSG_MAP(GetAverageGfxActivity,              PPSMC_MSG_GetAverageGfxActivity, 0),
122         MSG_MAP(GetAveragePower,                    PPSMC_MSG_GetAveragePower,           0),
123         MSG_MAP(GetAverageTemperature,              PPSMC_MSG_GetAverageTemperature, 0),
124         MSG_MAP(SetAveragePowerTimeConstant,        PPSMC_MSG_SetAveragePowerTimeConstant,                      0),
125         MSG_MAP(SetAverageActivityTimeConstant,     PPSMC_MSG_SetAverageActivityTimeConstant,           0),
126         MSG_MAP(SetAverageTemperatureTimeConstant,  PPSMC_MSG_SetAverageTemperatureTimeConstant,        0),
127         MSG_MAP(SetMitigationEndHysteresis,         PPSMC_MSG_SetMitigationEndHysteresis,                       0),
128         MSG_MAP(GetCurrentFreq,                     PPSMC_MSG_GetCurrentFreq,                                           0),
129         MSG_MAP(SetReducedPptLimit,                 PPSMC_MSG_SetReducedPptLimit,                                       0),
130         MSG_MAP(SetReducedThermalLimit,             PPSMC_MSG_SetReducedThermalLimit,                           0),
131         MSG_MAP(DramLogSetDramAddr,                 PPSMC_MSG_DramLogSetDramAddr,                                       0),
132         MSG_MAP(StartDramLogging,                   PPSMC_MSG_StartDramLogging,                                         0),
133         MSG_MAP(StopDramLogging,                    PPSMC_MSG_StopDramLogging,                                          0),
134         MSG_MAP(SetSoftMinCclk,                     PPSMC_MSG_SetSoftMinCclk,                                           0),
135         MSG_MAP(SetSoftMaxCclk,                     PPSMC_MSG_SetSoftMaxCclk,                                           0),
136         MSG_MAP(RequestActiveWgp,                   PPSMC_MSG_RequestActiveWgp,                     0),
137         MSG_MAP(SetFastPPTLimit,                    PPSMC_MSG_SetFastPPTLimit,                                          0),
138         MSG_MAP(SetSlowPPTLimit,                    PPSMC_MSG_SetSlowPPTLimit,                                          0),
139         MSG_MAP(GetFastPPTLimit,                    PPSMC_MSG_GetFastPPTLimit,                                          0),
140         MSG_MAP(GetSlowPPTLimit,                    PPSMC_MSG_GetSlowPPTLimit,                                          0),
141         MSG_MAP(GetGfxOffStatus,                    PPSMC_MSG_GetGfxOffStatus,                                          0),
142         MSG_MAP(GetGfxOffEntryCount,                PPSMC_MSG_GetGfxOffEntryCount,                                      0),
143         MSG_MAP(LogGfxOffResidency,                 PPSMC_MSG_LogGfxOffResidency,                                       0),
144 };
145
146 static struct cmn2asic_mapping vangogh_feature_mask_map[SMU_FEATURE_COUNT] = {
147         FEA_MAP(PPT),
148         FEA_MAP(TDC),
149         FEA_MAP(THERMAL),
150         FEA_MAP(DS_GFXCLK),
151         FEA_MAP(DS_SOCCLK),
152         FEA_MAP(DS_LCLK),
153         FEA_MAP(DS_FCLK),
154         FEA_MAP(DS_MP1CLK),
155         FEA_MAP(DS_MP0CLK),
156         FEA_MAP(ATHUB_PG),
157         FEA_MAP(CCLK_DPM),
158         FEA_MAP(FAN_CONTROLLER),
159         FEA_MAP(ULV),
160         FEA_MAP(VCN_DPM),
161         FEA_MAP(LCLK_DPM),
162         FEA_MAP(SHUBCLK_DPM),
163         FEA_MAP(DCFCLK_DPM),
164         FEA_MAP(DS_DCFCLK),
165         FEA_MAP(S0I2),
166         FEA_MAP(SMU_LOW_POWER),
167         FEA_MAP(GFX_DEM),
168         FEA_MAP(PSI),
169         FEA_MAP(PROCHOT),
170         FEA_MAP(CPUOFF),
171         FEA_MAP(STAPM),
172         FEA_MAP(S0I3),
173         FEA_MAP(DF_CSTATES),
174         FEA_MAP(PERF_LIMIT),
175         FEA_MAP(CORE_DLDO),
176         FEA_MAP(RSMU_LOW_POWER),
177         FEA_MAP(SMN_LOW_POWER),
178         FEA_MAP(THM_LOW_POWER),
179         FEA_MAP(SMUIO_LOW_POWER),
180         FEA_MAP(MP1_LOW_POWER),
181         FEA_MAP(DS_VCN),
182         FEA_MAP(CPPC),
183         FEA_MAP(OS_CSTATES),
184         FEA_MAP(ISP_DPM),
185         FEA_MAP(A55_DPM),
186         FEA_MAP(CVIP_DSP_DPM),
187         FEA_MAP(MSMU_LOW_POWER),
188         FEA_MAP_REVERSE(SOCCLK),
189         FEA_MAP_REVERSE(FCLK),
190         FEA_MAP_HALF_REVERSE(GFX),
191 };
192
193 static struct cmn2asic_mapping vangogh_table_map[SMU_TABLE_COUNT] = {
194         TAB_MAP_VALID(WATERMARKS),
195         TAB_MAP_VALID(SMU_METRICS),
196         TAB_MAP_VALID(CUSTOM_DPM),
197         TAB_MAP_VALID(DPMCLOCKS),
198 };
199
200 static struct cmn2asic_mapping vangogh_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
201         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,         WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
202         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
203         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
204         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_COMPUTE_BIT),
205         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
206         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CAPPED,               WORKLOAD_PPLIB_CAPPED_BIT),
207         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_UNCAPPED,             WORKLOAD_PPLIB_UNCAPPED_BIT),
208 };
209
210 static const uint8_t vangogh_throttler_map[] = {
211         [THROTTLER_STATUS_BIT_SPL]      = (SMU_THROTTLER_SPL_BIT),
212         [THROTTLER_STATUS_BIT_FPPT]     = (SMU_THROTTLER_FPPT_BIT),
213         [THROTTLER_STATUS_BIT_SPPT]     = (SMU_THROTTLER_SPPT_BIT),
214         [THROTTLER_STATUS_BIT_SPPT_APU] = (SMU_THROTTLER_SPPT_APU_BIT),
215         [THROTTLER_STATUS_BIT_THM_CORE] = (SMU_THROTTLER_TEMP_CORE_BIT),
216         [THROTTLER_STATUS_BIT_THM_GFX]  = (SMU_THROTTLER_TEMP_GPU_BIT),
217         [THROTTLER_STATUS_BIT_THM_SOC]  = (SMU_THROTTLER_TEMP_SOC_BIT),
218         [THROTTLER_STATUS_BIT_TDC_VDD]  = (SMU_THROTTLER_TDC_VDD_BIT),
219         [THROTTLER_STATUS_BIT_TDC_SOC]  = (SMU_THROTTLER_TDC_SOC_BIT),
220         [THROTTLER_STATUS_BIT_TDC_GFX]  = (SMU_THROTTLER_TDC_GFX_BIT),
221         [THROTTLER_STATUS_BIT_TDC_CVIP] = (SMU_THROTTLER_TDC_CVIP_BIT),
222 };
223
224 static int vangogh_tables_init(struct smu_context *smu)
225 {
226         struct smu_table_context *smu_table = &smu->smu_table;
227         struct smu_table *tables = smu_table->tables;
228         uint32_t if_version;
229         uint32_t smu_version;
230         uint32_t ret = 0;
231
232         ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
233         if (ret) {
234                 return ret;
235         }
236
237         SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
238                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
239         SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
240                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
241         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
242                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
243         SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t),
244                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
245
246         if (if_version < 0x3) {
247                 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_legacy_t),
248                                 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
249                 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_legacy_t), GFP_KERNEL);
250         } else {
251                 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
252                                 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
253                 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
254         }
255         if (!smu_table->metrics_table)
256                 goto err0_out;
257         smu_table->metrics_time = 0;
258
259         if (smu_version >= 0x043F3E00)
260                 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_3);
261         else
262                 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2);
263         smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
264         if (!smu_table->gpu_metrics_table)
265                 goto err1_out;
266
267         smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
268         if (!smu_table->watermarks_table)
269                 goto err2_out;
270
271         smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
272         if (!smu_table->clocks_table)
273                 goto err3_out;
274
275         return 0;
276
277 err3_out:
278         kfree(smu_table->watermarks_table);
279 err2_out:
280         kfree(smu_table->gpu_metrics_table);
281 err1_out:
282         kfree(smu_table->metrics_table);
283 err0_out:
284         return -ENOMEM;
285 }
286
287 static int vangogh_get_legacy_smu_metrics_data(struct smu_context *smu,
288                                        MetricsMember_t member,
289                                        uint32_t *value)
290 {
291         struct smu_table_context *smu_table = &smu->smu_table;
292         SmuMetrics_legacy_t *metrics = (SmuMetrics_legacy_t *)smu_table->metrics_table;
293         int ret = 0;
294
295         ret = smu_cmn_get_metrics_table(smu,
296                                         NULL,
297                                         false);
298         if (ret)
299                 return ret;
300
301         switch (member) {
302         case METRICS_CURR_GFXCLK:
303                 *value = metrics->GfxclkFrequency;
304                 break;
305         case METRICS_AVERAGE_SOCCLK:
306                 *value = metrics->SocclkFrequency;
307                 break;
308         case METRICS_AVERAGE_VCLK:
309                 *value = metrics->VclkFrequency;
310                 break;
311         case METRICS_AVERAGE_DCLK:
312                 *value = metrics->DclkFrequency;
313                 break;
314         case METRICS_CURR_UCLK:
315                 *value = metrics->MemclkFrequency;
316                 break;
317         case METRICS_AVERAGE_GFXACTIVITY:
318                 *value = metrics->GfxActivity / 100;
319                 break;
320         case METRICS_AVERAGE_VCNACTIVITY:
321                 *value = metrics->UvdActivity;
322                 break;
323         case METRICS_AVERAGE_SOCKETPOWER:
324                 *value = (metrics->CurrentSocketPower << 8) /
325                 1000 ;
326                 break;
327         case METRICS_TEMPERATURE_EDGE:
328                 *value = metrics->GfxTemperature / 100 *
329                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
330                 break;
331         case METRICS_TEMPERATURE_HOTSPOT:
332                 *value = metrics->SocTemperature / 100 *
333                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
334                 break;
335         case METRICS_THROTTLER_STATUS:
336                 *value = metrics->ThrottlerStatus;
337                 break;
338         case METRICS_VOLTAGE_VDDGFX:
339                 *value = metrics->Voltage[2];
340                 break;
341         case METRICS_VOLTAGE_VDDSOC:
342                 *value = metrics->Voltage[1];
343                 break;
344         case METRICS_AVERAGE_CPUCLK:
345                 memcpy(value, &metrics->CoreFrequency[0],
346                        smu->cpu_core_num * sizeof(uint16_t));
347                 break;
348         default:
349                 *value = UINT_MAX;
350                 break;
351         }
352
353         return ret;
354 }
355
356 static int vangogh_get_smu_metrics_data(struct smu_context *smu,
357                                        MetricsMember_t member,
358                                        uint32_t *value)
359 {
360         struct smu_table_context *smu_table = &smu->smu_table;
361         SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
362         int ret = 0;
363
364         ret = smu_cmn_get_metrics_table(smu,
365                                         NULL,
366                                         false);
367         if (ret)
368                 return ret;
369
370         switch (member) {
371         case METRICS_CURR_GFXCLK:
372                 *value = metrics->Current.GfxclkFrequency;
373                 break;
374         case METRICS_AVERAGE_SOCCLK:
375                 *value = metrics->Current.SocclkFrequency;
376                 break;
377         case METRICS_AVERAGE_VCLK:
378                 *value = metrics->Current.VclkFrequency;
379                 break;
380         case METRICS_AVERAGE_DCLK:
381                 *value = metrics->Current.DclkFrequency;
382                 break;
383         case METRICS_CURR_UCLK:
384                 *value = metrics->Current.MemclkFrequency;
385                 break;
386         case METRICS_AVERAGE_GFXACTIVITY:
387                 *value = metrics->Current.GfxActivity;
388                 break;
389         case METRICS_AVERAGE_VCNACTIVITY:
390                 *value = metrics->Current.UvdActivity;
391                 break;
392         case METRICS_AVERAGE_SOCKETPOWER:
393                 *value = (metrics->Average.CurrentSocketPower << 8) /
394                 1000;
395                 break;
396         case METRICS_CURR_SOCKETPOWER:
397                 *value = (metrics->Current.CurrentSocketPower << 8) /
398                 1000;
399                 break;
400         case METRICS_TEMPERATURE_EDGE:
401                 *value = metrics->Current.GfxTemperature / 100 *
402                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
403                 break;
404         case METRICS_TEMPERATURE_HOTSPOT:
405                 *value = metrics->Current.SocTemperature / 100 *
406                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
407                 break;
408         case METRICS_THROTTLER_STATUS:
409                 *value = metrics->Current.ThrottlerStatus;
410                 break;
411         case METRICS_VOLTAGE_VDDGFX:
412                 *value = metrics->Current.Voltage[2];
413                 break;
414         case METRICS_VOLTAGE_VDDSOC:
415                 *value = metrics->Current.Voltage[1];
416                 break;
417         case METRICS_AVERAGE_CPUCLK:
418                 memcpy(value, &metrics->Current.CoreFrequency[0],
419                        smu->cpu_core_num * sizeof(uint16_t));
420                 break;
421         default:
422                 *value = UINT_MAX;
423                 break;
424         }
425
426         return ret;
427 }
428
429 static int vangogh_common_get_smu_metrics_data(struct smu_context *smu,
430                                        MetricsMember_t member,
431                                        uint32_t *value)
432 {
433         struct amdgpu_device *adev = smu->adev;
434         uint32_t if_version;
435         int ret = 0;
436
437         ret = smu_cmn_get_smc_version(smu, &if_version, NULL);
438         if (ret) {
439                 dev_err(adev->dev, "Failed to get smu if version!\n");
440                 return ret;
441         }
442
443         if (if_version < 0x3)
444                 ret = vangogh_get_legacy_smu_metrics_data(smu, member, value);
445         else
446                 ret = vangogh_get_smu_metrics_data(smu, member, value);
447
448         return ret;
449 }
450
451 static int vangogh_allocate_dpm_context(struct smu_context *smu)
452 {
453         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
454
455         smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
456                                        GFP_KERNEL);
457         if (!smu_dpm->dpm_context)
458                 return -ENOMEM;
459
460         smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
461
462         return 0;
463 }
464
465 static int vangogh_init_smc_tables(struct smu_context *smu)
466 {
467         int ret = 0;
468
469         ret = vangogh_tables_init(smu);
470         if (ret)
471                 return ret;
472
473         ret = vangogh_allocate_dpm_context(smu);
474         if (ret)
475                 return ret;
476
477 #ifdef CONFIG_X86
478         /* AMD x86 APU only */
479         smu->cpu_core_num = boot_cpu_data.x86_max_cores;
480 #else
481         smu->cpu_core_num = 4;
482 #endif
483
484         return smu_v11_0_init_smc_tables(smu);
485 }
486
487 static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
488 {
489         int ret = 0;
490
491         if (enable) {
492                 /* vcn dpm on is a prerequisite for vcn power gate messages */
493                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL);
494                 if (ret)
495                         return ret;
496         } else {
497                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL);
498                 if (ret)
499                         return ret;
500         }
501
502         return ret;
503 }
504
505 static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
506 {
507         int ret = 0;
508
509         if (enable) {
510                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL);
511                 if (ret)
512                         return ret;
513         } else {
514                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL);
515                 if (ret)
516                         return ret;
517         }
518
519         return ret;
520 }
521
522 static bool vangogh_is_dpm_running(struct smu_context *smu)
523 {
524         struct amdgpu_device *adev = smu->adev;
525         int ret = 0;
526         uint64_t feature_enabled;
527
528         /* we need to re-init after suspend so return false */
529         if (adev->in_suspend)
530                 return false;
531
532         ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
533
534         if (ret)
535                 return false;
536
537         return !!(feature_enabled & SMC_DPM_FEATURE);
538 }
539
540 static int vangogh_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type,
541                                                 uint32_t dpm_level, uint32_t *freq)
542 {
543         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
544
545         if (!clk_table || clk_type >= SMU_CLK_COUNT)
546                 return -EINVAL;
547
548         switch (clk_type) {
549         case SMU_SOCCLK:
550                 if (dpm_level >= clk_table->NumSocClkLevelsEnabled)
551                         return -EINVAL;
552                 *freq = clk_table->SocClocks[dpm_level];
553                 break;
554         case SMU_VCLK:
555                 if (dpm_level >= clk_table->VcnClkLevelsEnabled)
556                         return -EINVAL;
557                 *freq = clk_table->VcnClocks[dpm_level].vclk;
558                 break;
559         case SMU_DCLK:
560                 if (dpm_level >= clk_table->VcnClkLevelsEnabled)
561                         return -EINVAL;
562                 *freq = clk_table->VcnClocks[dpm_level].dclk;
563                 break;
564         case SMU_UCLK:
565         case SMU_MCLK:
566                 if (dpm_level >= clk_table->NumDfPstatesEnabled)
567                         return -EINVAL;
568                 *freq = clk_table->DfPstateTable[dpm_level].memclk;
569
570                 break;
571         case SMU_FCLK:
572                 if (dpm_level >= clk_table->NumDfPstatesEnabled)
573                         return -EINVAL;
574                 *freq = clk_table->DfPstateTable[dpm_level].fclk;
575                 break;
576         default:
577                 return -EINVAL;
578         }
579
580         return 0;
581 }
582
583 static int vangogh_print_legacy_clk_levels(struct smu_context *smu,
584                         enum smu_clk_type clk_type, char *buf)
585 {
586         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
587         SmuMetrics_legacy_t metrics;
588         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
589         int i, idx, size = 0, ret = 0;
590         uint32_t cur_value = 0, value = 0, count = 0;
591         bool cur_value_match_level = false;
592
593         memset(&metrics, 0, sizeof(metrics));
594
595         ret = smu_cmn_get_metrics_table(smu, &metrics, false);
596         if (ret)
597                 return ret;
598
599         smu_cmn_get_sysfs_buf(&buf, &size);
600
601         switch (clk_type) {
602         case SMU_OD_SCLK:
603                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
604                         size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
605                         size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
606                         (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
607                         size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
608                         (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
609                 }
610                 break;
611         case SMU_OD_CCLK:
612                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
613                         size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select);
614                         size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
615                         (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);
616                         size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
617                         (smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq);
618                 }
619                 break;
620         case SMU_OD_RANGE:
621                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
622                         size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
623                         size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
624                                 smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
625                         size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n",
626                                 smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq);
627                 }
628                 break;
629         case SMU_SOCCLK:
630                 /* the level 3 ~ 6 of socclk use the same frequency for vangogh */
631                 count = clk_table->NumSocClkLevelsEnabled;
632                 cur_value = metrics.SocclkFrequency;
633                 break;
634         case SMU_VCLK:
635                 count = clk_table->VcnClkLevelsEnabled;
636                 cur_value = metrics.VclkFrequency;
637                 break;
638         case SMU_DCLK:
639                 count = clk_table->VcnClkLevelsEnabled;
640                 cur_value = metrics.DclkFrequency;
641                 break;
642         case SMU_MCLK:
643                 count = clk_table->NumDfPstatesEnabled;
644                 cur_value = metrics.MemclkFrequency;
645                 break;
646         case SMU_FCLK:
647                 count = clk_table->NumDfPstatesEnabled;
648                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetFclkFrequency, 0, &cur_value);
649                 if (ret)
650                         return ret;
651                 break;
652         default:
653                 break;
654         }
655
656         switch (clk_type) {
657         case SMU_SOCCLK:
658         case SMU_VCLK:
659         case SMU_DCLK:
660         case SMU_MCLK:
661         case SMU_FCLK:
662                 for (i = 0; i < count; i++) {
663                         idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i;
664                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, idx, &value);
665                         if (ret)
666                                 return ret;
667                         if (!value)
668                                 continue;
669                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
670                                         cur_value == value ? "*" : "");
671                         if (cur_value == value)
672                                 cur_value_match_level = true;
673                 }
674
675                 if (!cur_value_match_level)
676                         size += sysfs_emit_at(buf, size, "   %uMhz *\n", cur_value);
677                 break;
678         default:
679                 break;
680         }
681
682         return size;
683 }
684
685 static int vangogh_print_clk_levels(struct smu_context *smu,
686                         enum smu_clk_type clk_type, char *buf)
687 {
688         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
689         SmuMetrics_t metrics;
690         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
691         int i, idx, size = 0, ret = 0;
692         uint32_t cur_value = 0, value = 0, count = 0;
693         bool cur_value_match_level = false;
694         uint32_t min, max;
695
696         memset(&metrics, 0, sizeof(metrics));
697
698         ret = smu_cmn_get_metrics_table(smu, &metrics, false);
699         if (ret)
700                 return ret;
701
702         smu_cmn_get_sysfs_buf(&buf, &size);
703
704         switch (clk_type) {
705         case SMU_OD_SCLK:
706                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
707                         size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
708                         size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
709                         (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
710                         size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
711                         (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
712                 }
713                 break;
714         case SMU_OD_CCLK:
715                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
716                         size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select);
717                         size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
718                         (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);
719                         size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
720                         (smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq);
721                 }
722                 break;
723         case SMU_OD_RANGE:
724                 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
725                         size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
726                         size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
727                                 smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
728                         size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n",
729                                 smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq);
730                 }
731                 break;
732         case SMU_SOCCLK:
733                 /* the level 3 ~ 6 of socclk use the same frequency for vangogh */
734                 count = clk_table->NumSocClkLevelsEnabled;
735                 cur_value = metrics.Current.SocclkFrequency;
736                 break;
737         case SMU_VCLK:
738                 count = clk_table->VcnClkLevelsEnabled;
739                 cur_value = metrics.Current.VclkFrequency;
740                 break;
741         case SMU_DCLK:
742                 count = clk_table->VcnClkLevelsEnabled;
743                 cur_value = metrics.Current.DclkFrequency;
744                 break;
745         case SMU_MCLK:
746                 count = clk_table->NumDfPstatesEnabled;
747                 cur_value = metrics.Current.MemclkFrequency;
748                 break;
749         case SMU_FCLK:
750                 count = clk_table->NumDfPstatesEnabled;
751                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetFclkFrequency, 0, &cur_value);
752                 if (ret)
753                         return ret;
754                 break;
755         case SMU_GFXCLK:
756         case SMU_SCLK:
757                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetGfxclkFrequency, 0, &cur_value);
758                 if (ret) {
759                         return ret;
760                 }
761                 break;
762         default:
763                 break;
764         }
765
766         switch (clk_type) {
767         case SMU_SOCCLK:
768         case SMU_VCLK:
769         case SMU_DCLK:
770         case SMU_MCLK:
771         case SMU_FCLK:
772                 for (i = 0; i < count; i++) {
773                         idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i;
774                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, idx, &value);
775                         if (ret)
776                                 return ret;
777                         if (!value)
778                                 continue;
779                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
780                                         cur_value == value ? "*" : "");
781                         if (cur_value == value)
782                                 cur_value_match_level = true;
783                 }
784
785                 if (!cur_value_match_level)
786                         size += sysfs_emit_at(buf, size, "   %uMhz *\n", cur_value);
787                 break;
788         case SMU_GFXCLK:
789         case SMU_SCLK:
790                 min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
791                 max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
792                 if (cur_value  == max)
793                         i = 2;
794                 else if (cur_value == min)
795                         i = 0;
796                 else
797                         i = 1;
798                 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
799                                 i == 0 ? "*" : "");
800                 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
801                                 i == 1 ? cur_value : VANGOGH_UMD_PSTATE_STANDARD_GFXCLK,
802                                 i == 1 ? "*" : "");
803                 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
804                                 i == 2 ? "*" : "");
805                 break;
806         default:
807                 break;
808         }
809
810         return size;
811 }
812
813 static int vangogh_common_print_clk_levels(struct smu_context *smu,
814                         enum smu_clk_type clk_type, char *buf)
815 {
816         struct amdgpu_device *adev = smu->adev;
817         uint32_t if_version;
818         int ret = 0;
819
820         ret = smu_cmn_get_smc_version(smu, &if_version, NULL);
821         if (ret) {
822                 dev_err(adev->dev, "Failed to get smu if version!\n");
823                 return ret;
824         }
825
826         if (if_version < 0x3)
827                 ret = vangogh_print_legacy_clk_levels(smu, clk_type, buf);
828         else
829                 ret = vangogh_print_clk_levels(smu, clk_type, buf);
830
831         return ret;
832 }
833
834 static int vangogh_get_profiling_clk_mask(struct smu_context *smu,
835                                          enum amd_dpm_forced_level level,
836                                          uint32_t *vclk_mask,
837                                          uint32_t *dclk_mask,
838                                          uint32_t *mclk_mask,
839                                          uint32_t *fclk_mask,
840                                          uint32_t *soc_mask)
841 {
842         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
843
844         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
845                 if (mclk_mask)
846                         *mclk_mask = clk_table->NumDfPstatesEnabled - 1;
847
848                 if (fclk_mask)
849                         *fclk_mask = clk_table->NumDfPstatesEnabled - 1;
850
851                 if (soc_mask)
852                         *soc_mask = 0;
853         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
854                 if (mclk_mask)
855                         *mclk_mask = 0;
856
857                 if (fclk_mask)
858                         *fclk_mask = 0;
859
860                 if (soc_mask)
861                         *soc_mask = 1;
862
863                 if (vclk_mask)
864                         *vclk_mask = 1;
865
866                 if (dclk_mask)
867                         *dclk_mask = 1;
868         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) {
869                 if (mclk_mask)
870                         *mclk_mask = 0;
871
872                 if (fclk_mask)
873                         *fclk_mask = 0;
874
875                 if (soc_mask)
876                         *soc_mask = 1;
877
878                 if (vclk_mask)
879                         *vclk_mask = 1;
880
881                 if (dclk_mask)
882                         *dclk_mask = 1;
883         }
884
885         return 0;
886 }
887
888 static bool vangogh_clk_dpm_is_enabled(struct smu_context *smu,
889                                 enum smu_clk_type clk_type)
890 {
891         enum smu_feature_mask feature_id = 0;
892
893         switch (clk_type) {
894         case SMU_MCLK:
895         case SMU_UCLK:
896         case SMU_FCLK:
897                 feature_id = SMU_FEATURE_DPM_FCLK_BIT;
898                 break;
899         case SMU_GFXCLK:
900         case SMU_SCLK:
901                 feature_id = SMU_FEATURE_DPM_GFXCLK_BIT;
902                 break;
903         case SMU_SOCCLK:
904                 feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
905                 break;
906         case SMU_VCLK:
907         case SMU_DCLK:
908                 feature_id = SMU_FEATURE_VCN_DPM_BIT;
909                 break;
910         default:
911                 return true;
912         }
913
914         if (!smu_cmn_feature_is_enabled(smu, feature_id))
915                 return false;
916
917         return true;
918 }
919
920 static int vangogh_get_dpm_ultimate_freq(struct smu_context *smu,
921                                         enum smu_clk_type clk_type,
922                                         uint32_t *min,
923                                         uint32_t *max)
924 {
925         int ret = 0;
926         uint32_t soc_mask;
927         uint32_t vclk_mask;
928         uint32_t dclk_mask;
929         uint32_t mclk_mask;
930         uint32_t fclk_mask;
931         uint32_t clock_limit;
932
933         if (!vangogh_clk_dpm_is_enabled(smu, clk_type)) {
934                 switch (clk_type) {
935                 case SMU_MCLK:
936                 case SMU_UCLK:
937                         clock_limit = smu->smu_table.boot_values.uclk;
938                         break;
939                 case SMU_FCLK:
940                         clock_limit = smu->smu_table.boot_values.fclk;
941                         break;
942                 case SMU_GFXCLK:
943                 case SMU_SCLK:
944                         clock_limit = smu->smu_table.boot_values.gfxclk;
945                         break;
946                 case SMU_SOCCLK:
947                         clock_limit = smu->smu_table.boot_values.socclk;
948                         break;
949                 case SMU_VCLK:
950                         clock_limit = smu->smu_table.boot_values.vclk;
951                         break;
952                 case SMU_DCLK:
953                         clock_limit = smu->smu_table.boot_values.dclk;
954                         break;
955                 default:
956                         clock_limit = 0;
957                         break;
958                 }
959
960                 /* clock in Mhz unit */
961                 if (min)
962                         *min = clock_limit / 100;
963                 if (max)
964                         *max = clock_limit / 100;
965
966                 return 0;
967         }
968         if (max) {
969                 ret = vangogh_get_profiling_clk_mask(smu,
970                                                         AMD_DPM_FORCED_LEVEL_PROFILE_PEAK,
971                                                         &vclk_mask,
972                                                         &dclk_mask,
973                                                         &mclk_mask,
974                                                         &fclk_mask,
975                                                         &soc_mask);
976                 if (ret)
977                         goto failed;
978
979                 switch (clk_type) {
980                 case SMU_UCLK:
981                 case SMU_MCLK:
982                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, max);
983                         if (ret)
984                                 goto failed;
985                         break;
986                 case SMU_SOCCLK:
987                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, max);
988                         if (ret)
989                                 goto failed;
990                         break;
991                 case SMU_FCLK:
992                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, max);
993                         if (ret)
994                                 goto failed;
995                         break;
996                 case SMU_VCLK:
997                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, max);
998                         if (ret)
999                                 goto failed;
1000                         break;
1001                 case SMU_DCLK:
1002                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, max);
1003                         if (ret)
1004                                 goto failed;
1005                         break;
1006                 default:
1007                         ret = -EINVAL;
1008                         goto failed;
1009                 }
1010         }
1011         if (min) {
1012                 switch (clk_type) {
1013                 case SMU_UCLK:
1014                 case SMU_MCLK:
1015                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, min);
1016                         if (ret)
1017                                 goto failed;
1018                         break;
1019                 case SMU_SOCCLK:
1020                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, min);
1021                         if (ret)
1022                                 goto failed;
1023                         break;
1024                 case SMU_FCLK:
1025                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, min);
1026                         if (ret)
1027                                 goto failed;
1028                         break;
1029                 case SMU_VCLK:
1030                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, min);
1031                         if (ret)
1032                                 goto failed;
1033                         break;
1034                 case SMU_DCLK:
1035                         ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, min);
1036                         if (ret)
1037                                 goto failed;
1038                         break;
1039                 default:
1040                         ret = -EINVAL;
1041                         goto failed;
1042                 }
1043         }
1044 failed:
1045         return ret;
1046 }
1047
1048 static int vangogh_get_power_profile_mode(struct smu_context *smu,
1049                                            char *buf)
1050 {
1051         uint32_t i, size = 0;
1052         int16_t workload_type = 0;
1053
1054         if (!buf)
1055                 return -EINVAL;
1056
1057         for (i = 0; i < PP_SMC_POWER_PROFILE_COUNT; i++) {
1058                 /*
1059                  * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
1060                  * Not all profile modes are supported on vangogh.
1061                  */
1062                 workload_type = smu_cmn_to_asic_specific_index(smu,
1063                                                                CMN2ASIC_MAPPING_WORKLOAD,
1064                                                                i);
1065
1066                 if (workload_type < 0)
1067                         continue;
1068
1069                 size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
1070                         i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1071         }
1072
1073         return size;
1074 }
1075
1076 static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1077 {
1078         int workload_type, ret;
1079         uint32_t profile_mode = input[size];
1080
1081         if (profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
1082                 dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
1083                 return -EINVAL;
1084         }
1085
1086         if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||
1087                         profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)
1088                 return 0;
1089
1090         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1091         workload_type = smu_cmn_to_asic_specific_index(smu,
1092                                                        CMN2ASIC_MAPPING_WORKLOAD,
1093                                                        profile_mode);
1094         if (workload_type < 0) {
1095                 dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on VANGOGH\n",
1096                                         profile_mode);
1097                 return -EINVAL;
1098         }
1099
1100         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
1101                                     1 << workload_type,
1102                                     NULL);
1103         if (ret) {
1104                 dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
1105                                         workload_type);
1106                 return ret;
1107         }
1108
1109         smu->power_profile_mode = profile_mode;
1110
1111         return 0;
1112 }
1113
1114 static int vangogh_set_soft_freq_limited_range(struct smu_context *smu,
1115                                           enum smu_clk_type clk_type,
1116                                           uint32_t min,
1117                                           uint32_t max)
1118 {
1119         int ret = 0;
1120
1121         if (!vangogh_clk_dpm_is_enabled(smu, clk_type))
1122                 return 0;
1123
1124         switch (clk_type) {
1125         case SMU_GFXCLK:
1126         case SMU_SCLK:
1127                 ret = smu_cmn_send_smc_msg_with_param(smu,
1128                                                         SMU_MSG_SetHardMinGfxClk,
1129                                                         min, NULL);
1130                 if (ret)
1131                         return ret;
1132
1133                 ret = smu_cmn_send_smc_msg_with_param(smu,
1134                                                         SMU_MSG_SetSoftMaxGfxClk,
1135                                                         max, NULL);
1136                 if (ret)
1137                         return ret;
1138                 break;
1139         case SMU_FCLK:
1140                 ret = smu_cmn_send_smc_msg_with_param(smu,
1141                                                         SMU_MSG_SetHardMinFclkByFreq,
1142                                                         min, NULL);
1143                 if (ret)
1144                         return ret;
1145
1146                 ret = smu_cmn_send_smc_msg_with_param(smu,
1147                                                         SMU_MSG_SetSoftMaxFclkByFreq,
1148                                                         max, NULL);
1149                 if (ret)
1150                         return ret;
1151                 break;
1152         case SMU_SOCCLK:
1153                 ret = smu_cmn_send_smc_msg_with_param(smu,
1154                                                         SMU_MSG_SetHardMinSocclkByFreq,
1155                                                         min, NULL);
1156                 if (ret)
1157                         return ret;
1158
1159                 ret = smu_cmn_send_smc_msg_with_param(smu,
1160                                                         SMU_MSG_SetSoftMaxSocclkByFreq,
1161                                                         max, NULL);
1162                 if (ret)
1163                         return ret;
1164                 break;
1165         case SMU_VCLK:
1166                 ret = smu_cmn_send_smc_msg_with_param(smu,
1167                                                         SMU_MSG_SetHardMinVcn,
1168                                                         min << 16, NULL);
1169                 if (ret)
1170                         return ret;
1171                 ret = smu_cmn_send_smc_msg_with_param(smu,
1172                                                         SMU_MSG_SetSoftMaxVcn,
1173                                                         max << 16, NULL);
1174                 if (ret)
1175                         return ret;
1176                 break;
1177         case SMU_DCLK:
1178                 ret = smu_cmn_send_smc_msg_with_param(smu,
1179                                                         SMU_MSG_SetHardMinVcn,
1180                                                         min, NULL);
1181                 if (ret)
1182                         return ret;
1183                 ret = smu_cmn_send_smc_msg_with_param(smu,
1184                                                         SMU_MSG_SetSoftMaxVcn,
1185                                                         max, NULL);
1186                 if (ret)
1187                         return ret;
1188                 break;
1189         default:
1190                 return -EINVAL;
1191         }
1192
1193         return ret;
1194 }
1195
1196 static int vangogh_force_clk_levels(struct smu_context *smu,
1197                                    enum smu_clk_type clk_type, uint32_t mask)
1198 {
1199         uint32_t soft_min_level = 0, soft_max_level = 0;
1200         uint32_t min_freq = 0, max_freq = 0;
1201         int ret = 0 ;
1202
1203         soft_min_level = mask ? (ffs(mask) - 1) : 0;
1204         soft_max_level = mask ? (fls(mask) - 1) : 0;
1205
1206         switch (clk_type) {
1207         case SMU_SOCCLK:
1208                 ret = vangogh_get_dpm_clk_limited(smu, clk_type,
1209                                                 soft_min_level, &min_freq);
1210                 if (ret)
1211                         return ret;
1212                 ret = vangogh_get_dpm_clk_limited(smu, clk_type,
1213                                                 soft_max_level, &max_freq);
1214                 if (ret)
1215                         return ret;
1216                 ret = smu_cmn_send_smc_msg_with_param(smu,
1217                                                                 SMU_MSG_SetSoftMaxSocclkByFreq,
1218                                                                 max_freq, NULL);
1219                 if (ret)
1220                         return ret;
1221                 ret = smu_cmn_send_smc_msg_with_param(smu,
1222                                                                 SMU_MSG_SetHardMinSocclkByFreq,
1223                                                                 min_freq, NULL);
1224                 if (ret)
1225                         return ret;
1226                 break;
1227         case SMU_FCLK:
1228                 ret = vangogh_get_dpm_clk_limited(smu,
1229                                                         clk_type, soft_min_level, &min_freq);
1230                 if (ret)
1231                         return ret;
1232                 ret = vangogh_get_dpm_clk_limited(smu,
1233                                                         clk_type, soft_max_level, &max_freq);
1234                 if (ret)
1235                         return ret;
1236                 ret = smu_cmn_send_smc_msg_with_param(smu,
1237                                                                 SMU_MSG_SetSoftMaxFclkByFreq,
1238                                                                 max_freq, NULL);
1239                 if (ret)
1240                         return ret;
1241                 ret = smu_cmn_send_smc_msg_with_param(smu,
1242                                                                 SMU_MSG_SetHardMinFclkByFreq,
1243                                                                 min_freq, NULL);
1244                 if (ret)
1245                         return ret;
1246                 break;
1247         case SMU_VCLK:
1248                 ret = vangogh_get_dpm_clk_limited(smu,
1249                                                         clk_type, soft_min_level, &min_freq);
1250                 if (ret)
1251                         return ret;
1252
1253                 ret = vangogh_get_dpm_clk_limited(smu,
1254                                                         clk_type, soft_max_level, &max_freq);
1255                 if (ret)
1256                         return ret;
1257
1258
1259                 ret = smu_cmn_send_smc_msg_with_param(smu,
1260                                                                 SMU_MSG_SetHardMinVcn,
1261                                                                 min_freq << 16, NULL);
1262                 if (ret)
1263                         return ret;
1264
1265                 ret = smu_cmn_send_smc_msg_with_param(smu,
1266                                                                 SMU_MSG_SetSoftMaxVcn,
1267                                                                 max_freq << 16, NULL);
1268                 if (ret)
1269                         return ret;
1270
1271                 break;
1272         case SMU_DCLK:
1273                 ret = vangogh_get_dpm_clk_limited(smu,
1274                                                         clk_type, soft_min_level, &min_freq);
1275                 if (ret)
1276                         return ret;
1277
1278                 ret = vangogh_get_dpm_clk_limited(smu,
1279                                                         clk_type, soft_max_level, &max_freq);
1280                 if (ret)
1281                         return ret;
1282
1283                 ret = smu_cmn_send_smc_msg_with_param(smu,
1284                                                         SMU_MSG_SetHardMinVcn,
1285                                                         min_freq, NULL);
1286                 if (ret)
1287                         return ret;
1288
1289                 ret = smu_cmn_send_smc_msg_with_param(smu,
1290                                                         SMU_MSG_SetSoftMaxVcn,
1291                                                         max_freq, NULL);
1292                 if (ret)
1293                         return ret;
1294
1295                 break;
1296         default:
1297                 break;
1298         }
1299
1300         return ret;
1301 }
1302
1303 static int vangogh_force_dpm_limit_value(struct smu_context *smu, bool highest)
1304 {
1305         int ret = 0, i = 0;
1306         uint32_t min_freq, max_freq, force_freq;
1307         enum smu_clk_type clk_type;
1308
1309         enum smu_clk_type clks[] = {
1310                 SMU_SOCCLK,
1311                 SMU_VCLK,
1312                 SMU_DCLK,
1313                 SMU_FCLK,
1314         };
1315
1316         for (i = 0; i < ARRAY_SIZE(clks); i++) {
1317                 clk_type = clks[i];
1318                 ret = vangogh_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq);
1319                 if (ret)
1320                         return ret;
1321
1322                 force_freq = highest ? max_freq : min_freq;
1323                 ret = vangogh_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq);
1324                 if (ret)
1325                         return ret;
1326         }
1327
1328         return ret;
1329 }
1330
1331 static int vangogh_unforce_dpm_levels(struct smu_context *smu)
1332 {
1333         int ret = 0, i = 0;
1334         uint32_t min_freq, max_freq;
1335         enum smu_clk_type clk_type;
1336
1337         struct clk_feature_map {
1338                 enum smu_clk_type clk_type;
1339                 uint32_t        feature;
1340         } clk_feature_map[] = {
1341                 {SMU_FCLK, SMU_FEATURE_DPM_FCLK_BIT},
1342                 {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT},
1343                 {SMU_VCLK, SMU_FEATURE_VCN_DPM_BIT},
1344                 {SMU_DCLK, SMU_FEATURE_VCN_DPM_BIT},
1345         };
1346
1347         for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) {
1348
1349                 if (!smu_cmn_feature_is_enabled(smu, clk_feature_map[i].feature))
1350                     continue;
1351
1352                 clk_type = clk_feature_map[i].clk_type;
1353
1354                 ret = vangogh_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq);
1355
1356                 if (ret)
1357                         return ret;
1358
1359                 ret = vangogh_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
1360
1361                 if (ret)
1362                         return ret;
1363         }
1364
1365         return ret;
1366 }
1367
1368 static int vangogh_set_peak_clock_by_device(struct smu_context *smu)
1369 {
1370         int ret = 0;
1371         uint32_t socclk_freq = 0, fclk_freq = 0;
1372         uint32_t vclk_freq = 0, dclk_freq = 0;
1373
1374         ret = vangogh_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_freq);
1375         if (ret)
1376                 return ret;
1377
1378         ret = vangogh_set_soft_freq_limited_range(smu, SMU_FCLK, fclk_freq, fclk_freq);
1379         if (ret)
1380                 return ret;
1381
1382         ret = vangogh_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_freq);
1383         if (ret)
1384                 return ret;
1385
1386         ret = vangogh_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk_freq, socclk_freq);
1387         if (ret)
1388                 return ret;
1389
1390         ret = vangogh_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_freq);
1391         if (ret)
1392                 return ret;
1393
1394         ret = vangogh_set_soft_freq_limited_range(smu, SMU_VCLK, vclk_freq, vclk_freq);
1395         if (ret)
1396                 return ret;
1397
1398         ret = vangogh_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_freq);
1399         if (ret)
1400                 return ret;
1401
1402         ret = vangogh_set_soft_freq_limited_range(smu, SMU_DCLK, dclk_freq, dclk_freq);
1403         if (ret)
1404                 return ret;
1405
1406         return ret;
1407 }
1408
1409 static int vangogh_set_performance_level(struct smu_context *smu,
1410                                         enum amd_dpm_forced_level level)
1411 {
1412         int ret = 0, i;
1413         uint32_t soc_mask, mclk_mask, fclk_mask;
1414         uint32_t vclk_mask = 0, dclk_mask = 0;
1415
1416         smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1417         smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1418
1419         switch (level) {
1420         case AMD_DPM_FORCED_LEVEL_HIGH:
1421                 smu->gfx_actual_hard_min_freq = smu->gfx_default_soft_max_freq;
1422                 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1423
1424
1425                 ret = vangogh_force_dpm_limit_value(smu, true);
1426                 if (ret)
1427                         return ret;
1428                 break;
1429         case AMD_DPM_FORCED_LEVEL_LOW:
1430                 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1431                 smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq;
1432
1433                 ret = vangogh_force_dpm_limit_value(smu, false);
1434                 if (ret)
1435                         return ret;
1436                 break;
1437         case AMD_DPM_FORCED_LEVEL_AUTO:
1438                 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1439                 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1440
1441                 ret = vangogh_unforce_dpm_levels(smu);
1442                 if (ret)
1443                         return ret;
1444                 break;
1445         case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1446                 smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK;
1447                 smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK;
1448
1449                 ret = vangogh_get_profiling_clk_mask(smu, level,
1450                                                         &vclk_mask,
1451                                                         &dclk_mask,
1452                                                         &mclk_mask,
1453                                                         &fclk_mask,
1454                                                         &soc_mask);
1455                 if (ret)
1456                         return ret;
1457
1458                 vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask);
1459                 vangogh_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
1460                 vangogh_force_clk_levels(smu, SMU_VCLK, 1 << vclk_mask);
1461                 vangogh_force_clk_levels(smu, SMU_DCLK, 1 << dclk_mask);
1462                 break;
1463         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1464                 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1465                 smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq;
1466                 break;
1467         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1468                 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1469                 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1470
1471                 ret = vangogh_get_profiling_clk_mask(smu, level,
1472                                                         NULL,
1473                                                         NULL,
1474                                                         &mclk_mask,
1475                                                         &fclk_mask,
1476                                                         NULL);
1477                 if (ret)
1478                         return ret;
1479
1480                 vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask);
1481                 break;
1482         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1483                 smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK;
1484                 smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK;
1485
1486                 ret = vangogh_set_peak_clock_by_device(smu);
1487                 if (ret)
1488                         return ret;
1489                 break;
1490         case AMD_DPM_FORCED_LEVEL_MANUAL:
1491         case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1492         default:
1493                 return 0;
1494         }
1495
1496         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
1497                                               smu->gfx_actual_hard_min_freq, NULL);
1498         if (ret)
1499                 return ret;
1500
1501         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
1502                                               smu->gfx_actual_soft_max_freq, NULL);
1503         if (ret)
1504                 return ret;
1505
1506         if (smu->adev->pm.fw_version >= 0x43f1b00) {
1507                 for (i = 0; i < smu->cpu_core_num; i++) {
1508                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinCclk,
1509                                                               ((i << 20)
1510                                                                | smu->cpu_actual_soft_min_freq),
1511                                                               NULL);
1512                         if (ret)
1513                                 return ret;
1514
1515                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxCclk,
1516                                                               ((i << 20)
1517                                                                | smu->cpu_actual_soft_max_freq),
1518                                                               NULL);
1519                         if (ret)
1520                                 return ret;
1521                 }
1522         }
1523
1524         return ret;
1525 }
1526
1527 static int vangogh_read_sensor(struct smu_context *smu,
1528                                  enum amd_pp_sensors sensor,
1529                                  void *data, uint32_t *size)
1530 {
1531         int ret = 0;
1532
1533         if (!data || !size)
1534                 return -EINVAL;
1535
1536         switch (sensor) {
1537         case AMDGPU_PP_SENSOR_GPU_LOAD:
1538                 ret = vangogh_common_get_smu_metrics_data(smu,
1539                                                    METRICS_AVERAGE_GFXACTIVITY,
1540                                                    (uint32_t *)data);
1541                 *size = 4;
1542                 break;
1543         case AMDGPU_PP_SENSOR_GPU_POWER:
1544                 ret = vangogh_common_get_smu_metrics_data(smu,
1545                                                    METRICS_AVERAGE_SOCKETPOWER,
1546                                                    (uint32_t *)data);
1547                 *size = 4;
1548                 break;
1549         case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
1550                 ret = vangogh_common_get_smu_metrics_data(smu,
1551                                                    METRICS_CURR_SOCKETPOWER,
1552                                                    (uint32_t *)data);
1553                 *size = 4;
1554                 break;
1555         case AMDGPU_PP_SENSOR_EDGE_TEMP:
1556                 ret = vangogh_common_get_smu_metrics_data(smu,
1557                                                    METRICS_TEMPERATURE_EDGE,
1558                                                    (uint32_t *)data);
1559                 *size = 4;
1560                 break;
1561         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1562                 ret = vangogh_common_get_smu_metrics_data(smu,
1563                                                    METRICS_TEMPERATURE_HOTSPOT,
1564                                                    (uint32_t *)data);
1565                 *size = 4;
1566                 break;
1567         case AMDGPU_PP_SENSOR_GFX_MCLK:
1568                 ret = vangogh_common_get_smu_metrics_data(smu,
1569                                                    METRICS_CURR_UCLK,
1570                                                    (uint32_t *)data);
1571                 *(uint32_t *)data *= 100;
1572                 *size = 4;
1573                 break;
1574         case AMDGPU_PP_SENSOR_GFX_SCLK:
1575                 ret = vangogh_common_get_smu_metrics_data(smu,
1576                                                    METRICS_CURR_GFXCLK,
1577                                                    (uint32_t *)data);
1578                 *(uint32_t *)data *= 100;
1579                 *size = 4;
1580                 break;
1581         case AMDGPU_PP_SENSOR_VDDGFX:
1582                 ret = vangogh_common_get_smu_metrics_data(smu,
1583                                                    METRICS_VOLTAGE_VDDGFX,
1584                                                    (uint32_t *)data);
1585                 *size = 4;
1586                 break;
1587         case AMDGPU_PP_SENSOR_VDDNB:
1588                 ret = vangogh_common_get_smu_metrics_data(smu,
1589                                                    METRICS_VOLTAGE_VDDSOC,
1590                                                    (uint32_t *)data);
1591                 *size = 4;
1592                 break;
1593         case AMDGPU_PP_SENSOR_CPU_CLK:
1594                 ret = vangogh_common_get_smu_metrics_data(smu,
1595                                                    METRICS_AVERAGE_CPUCLK,
1596                                                    (uint32_t *)data);
1597                 *size = smu->cpu_core_num * sizeof(uint16_t);
1598                 break;
1599         default:
1600                 ret = -EOPNOTSUPP;
1601                 break;
1602         }
1603
1604         return ret;
1605 }
1606
1607 static int vangogh_get_apu_thermal_limit(struct smu_context *smu, uint32_t *limit)
1608 {
1609         return smu_cmn_send_smc_msg_with_param(smu,
1610                                               SMU_MSG_GetThermalLimit,
1611                                               0, limit);
1612 }
1613
1614 static int vangogh_set_apu_thermal_limit(struct smu_context *smu, uint32_t limit)
1615 {
1616         return smu_cmn_send_smc_msg_with_param(smu,
1617                                               SMU_MSG_SetReducedThermalLimit,
1618                                               limit, NULL);
1619 }
1620
1621
1622 static int vangogh_set_watermarks_table(struct smu_context *smu,
1623                                        struct pp_smu_wm_range_sets *clock_ranges)
1624 {
1625         int i;
1626         int ret = 0;
1627         Watermarks_t *table = smu->smu_table.watermarks_table;
1628
1629         if (!table || !clock_ranges)
1630                 return -EINVAL;
1631
1632         if (clock_ranges) {
1633                 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
1634                         clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
1635                         return -EINVAL;
1636
1637                 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
1638                         table->WatermarkRow[WM_DCFCLK][i].MinClock =
1639                                 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
1640                         table->WatermarkRow[WM_DCFCLK][i].MaxClock =
1641                                 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
1642                         table->WatermarkRow[WM_DCFCLK][i].MinMclk =
1643                                 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
1644                         table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
1645                                 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
1646
1647                         table->WatermarkRow[WM_DCFCLK][i].WmSetting =
1648                                 clock_ranges->reader_wm_sets[i].wm_inst;
1649                 }
1650
1651                 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
1652                         table->WatermarkRow[WM_SOCCLK][i].MinClock =
1653                                 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
1654                         table->WatermarkRow[WM_SOCCLK][i].MaxClock =
1655                                 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
1656                         table->WatermarkRow[WM_SOCCLK][i].MinMclk =
1657                                 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
1658                         table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
1659                                 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
1660
1661                         table->WatermarkRow[WM_SOCCLK][i].WmSetting =
1662                                 clock_ranges->writer_wm_sets[i].wm_inst;
1663                 }
1664
1665                 smu->watermarks_bitmap |= WATERMARKS_EXIST;
1666         }
1667
1668         /* pass data to smu controller */
1669         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1670              !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1671                 ret = smu_cmn_write_watermarks_table(smu);
1672                 if (ret) {
1673                         dev_err(smu->adev->dev, "Failed to update WMTABLE!");
1674                         return ret;
1675                 }
1676                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
1677         }
1678
1679         return 0;
1680 }
1681
1682 static ssize_t vangogh_get_legacy_gpu_metrics_v2_3(struct smu_context *smu,
1683                                       void **table)
1684 {
1685         struct smu_table_context *smu_table = &smu->smu_table;
1686         struct gpu_metrics_v2_3 *gpu_metrics =
1687                 (struct gpu_metrics_v2_3 *)smu_table->gpu_metrics_table;
1688         SmuMetrics_legacy_t metrics;
1689         int ret = 0;
1690
1691         ret = smu_cmn_get_metrics_table(smu, &metrics, true);
1692         if (ret)
1693                 return ret;
1694
1695         smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 3);
1696
1697         gpu_metrics->temperature_gfx = metrics.GfxTemperature;
1698         gpu_metrics->temperature_soc = metrics.SocTemperature;
1699         memcpy(&gpu_metrics->temperature_core[0],
1700                 &metrics.CoreTemperature[0],
1701                 sizeof(uint16_t) * 4);
1702         gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
1703
1704         gpu_metrics->average_gfx_activity = metrics.GfxActivity;
1705         gpu_metrics->average_mm_activity = metrics.UvdActivity;
1706
1707         gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
1708         gpu_metrics->average_cpu_power = metrics.Power[0];
1709         gpu_metrics->average_soc_power = metrics.Power[1];
1710         gpu_metrics->average_gfx_power = metrics.Power[2];
1711         memcpy(&gpu_metrics->average_core_power[0],
1712                 &metrics.CorePower[0],
1713                 sizeof(uint16_t) * 4);
1714
1715         gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
1716         gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
1717         gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
1718         gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
1719         gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
1720         gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
1721
1722         memcpy(&gpu_metrics->current_coreclk[0],
1723                 &metrics.CoreFrequency[0],
1724                 sizeof(uint16_t) * 4);
1725         gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
1726
1727         gpu_metrics->throttle_status = metrics.ThrottlerStatus;
1728         gpu_metrics->indep_throttle_status =
1729                         smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
1730                                                            vangogh_throttler_map);
1731
1732         gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
1733
1734         *table = (void *)gpu_metrics;
1735
1736         return sizeof(struct gpu_metrics_v2_3);
1737 }
1738
1739 static ssize_t vangogh_get_legacy_gpu_metrics(struct smu_context *smu,
1740                                       void **table)
1741 {
1742         struct smu_table_context *smu_table = &smu->smu_table;
1743         struct gpu_metrics_v2_2 *gpu_metrics =
1744                 (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table;
1745         SmuMetrics_legacy_t metrics;
1746         int ret = 0;
1747
1748         ret = smu_cmn_get_metrics_table(smu, &metrics, true);
1749         if (ret)
1750                 return ret;
1751
1752         smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2);
1753
1754         gpu_metrics->temperature_gfx = metrics.GfxTemperature;
1755         gpu_metrics->temperature_soc = metrics.SocTemperature;
1756         memcpy(&gpu_metrics->temperature_core[0],
1757                 &metrics.CoreTemperature[0],
1758                 sizeof(uint16_t) * 4);
1759         gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
1760
1761         gpu_metrics->average_gfx_activity = metrics.GfxActivity;
1762         gpu_metrics->average_mm_activity = metrics.UvdActivity;
1763
1764         gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
1765         gpu_metrics->average_cpu_power = metrics.Power[0];
1766         gpu_metrics->average_soc_power = metrics.Power[1];
1767         gpu_metrics->average_gfx_power = metrics.Power[2];
1768         memcpy(&gpu_metrics->average_core_power[0],
1769                 &metrics.CorePower[0],
1770                 sizeof(uint16_t) * 4);
1771
1772         gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
1773         gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
1774         gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
1775         gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
1776         gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
1777         gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
1778
1779         memcpy(&gpu_metrics->current_coreclk[0],
1780                 &metrics.CoreFrequency[0],
1781                 sizeof(uint16_t) * 4);
1782         gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
1783
1784         gpu_metrics->throttle_status = metrics.ThrottlerStatus;
1785         gpu_metrics->indep_throttle_status =
1786                         smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
1787                                                            vangogh_throttler_map);
1788
1789         gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
1790
1791         *table = (void *)gpu_metrics;
1792
1793         return sizeof(struct gpu_metrics_v2_2);
1794 }
1795
1796 static ssize_t vangogh_get_gpu_metrics_v2_3(struct smu_context *smu,
1797                                       void **table)
1798 {
1799         struct smu_table_context *smu_table = &smu->smu_table;
1800         struct gpu_metrics_v2_3 *gpu_metrics =
1801                 (struct gpu_metrics_v2_3 *)smu_table->gpu_metrics_table;
1802         SmuMetrics_t metrics;
1803         int ret = 0;
1804
1805         ret = smu_cmn_get_metrics_table(smu, &metrics, true);
1806         if (ret)
1807                 return ret;
1808
1809         smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 3);
1810
1811         gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
1812         gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
1813         memcpy(&gpu_metrics->temperature_core[0],
1814                 &metrics.Current.CoreTemperature[0],
1815                 sizeof(uint16_t) * 4);
1816         gpu_metrics->temperature_l3[0] = metrics.Current.L3Temperature[0];
1817
1818         gpu_metrics->average_temperature_gfx = metrics.Average.GfxTemperature;
1819         gpu_metrics->average_temperature_soc = metrics.Average.SocTemperature;
1820         memcpy(&gpu_metrics->average_temperature_core[0],
1821                 &metrics.Average.CoreTemperature[0],
1822                 sizeof(uint16_t) * 4);
1823         gpu_metrics->average_temperature_l3[0] = metrics.Average.L3Temperature[0];
1824
1825         gpu_metrics->average_gfx_activity = metrics.Current.GfxActivity;
1826         gpu_metrics->average_mm_activity = metrics.Current.UvdActivity;
1827
1828         gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
1829         gpu_metrics->average_cpu_power = metrics.Current.Power[0];
1830         gpu_metrics->average_soc_power = metrics.Current.Power[1];
1831         gpu_metrics->average_gfx_power = metrics.Current.Power[2];
1832         memcpy(&gpu_metrics->average_core_power[0],
1833                 &metrics.Average.CorePower[0],
1834                 sizeof(uint16_t) * 4);
1835
1836         gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
1837         gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
1838         gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
1839         gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
1840         gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
1841         gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
1842
1843         gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
1844         gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
1845         gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
1846         gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
1847         gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
1848         gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
1849
1850         memcpy(&gpu_metrics->current_coreclk[0],
1851                 &metrics.Current.CoreFrequency[0],
1852                 sizeof(uint16_t) * 4);
1853         gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0];
1854
1855         gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
1856         gpu_metrics->indep_throttle_status =
1857                         smu_cmn_get_indep_throttler_status(metrics.Current.ThrottlerStatus,
1858                                                            vangogh_throttler_map);
1859
1860         gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
1861
1862         *table = (void *)gpu_metrics;
1863
1864         return sizeof(struct gpu_metrics_v2_3);
1865 }
1866
1867 static ssize_t vangogh_get_gpu_metrics_v2_4(struct smu_context *smu,
1868                                             void **table)
1869 {
1870         SmuMetrics_t metrics;
1871         struct smu_table_context *smu_table = &smu->smu_table;
1872         struct gpu_metrics_v2_4 *gpu_metrics =
1873                                 (struct gpu_metrics_v2_4 *)smu_table->gpu_metrics_table;
1874         int ret = 0;
1875
1876         ret = smu_cmn_get_metrics_table(smu, &metrics, true);
1877         if (ret)
1878                 return ret;
1879
1880         smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 4);
1881
1882         gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
1883         gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
1884         memcpy(&gpu_metrics->temperature_core[0],
1885                &metrics.Current.CoreTemperature[0],
1886                sizeof(uint16_t) * 4);
1887         gpu_metrics->temperature_l3[0] = metrics.Current.L3Temperature[0];
1888
1889         gpu_metrics->average_temperature_gfx = metrics.Average.GfxTemperature;
1890         gpu_metrics->average_temperature_soc = metrics.Average.SocTemperature;
1891         memcpy(&gpu_metrics->average_temperature_core[0],
1892                &metrics.Average.CoreTemperature[0],
1893                sizeof(uint16_t) * 4);
1894         gpu_metrics->average_temperature_l3[0] = metrics.Average.L3Temperature[0];
1895
1896         gpu_metrics->average_gfx_activity = metrics.Current.GfxActivity;
1897         gpu_metrics->average_mm_activity = metrics.Current.UvdActivity;
1898
1899         gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
1900         gpu_metrics->average_cpu_power = metrics.Current.Power[0];
1901         gpu_metrics->average_soc_power = metrics.Current.Power[1];
1902         gpu_metrics->average_gfx_power = metrics.Current.Power[2];
1903
1904         gpu_metrics->average_cpu_voltage = metrics.Current.Voltage[0];
1905         gpu_metrics->average_soc_voltage = metrics.Current.Voltage[1];
1906         gpu_metrics->average_gfx_voltage = metrics.Current.Voltage[2];
1907
1908         gpu_metrics->average_cpu_current = metrics.Current.Current[0];
1909         gpu_metrics->average_soc_current = metrics.Current.Current[1];
1910         gpu_metrics->average_gfx_current = metrics.Current.Current[2];
1911
1912         memcpy(&gpu_metrics->average_core_power[0],
1913                &metrics.Average.CorePower[0],
1914                sizeof(uint16_t) * 4);
1915
1916         gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
1917         gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
1918         gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
1919         gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
1920         gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
1921         gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
1922
1923         gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
1924         gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
1925         gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
1926         gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
1927         gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
1928         gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
1929
1930         memcpy(&gpu_metrics->current_coreclk[0],
1931                &metrics.Current.CoreFrequency[0],
1932                sizeof(uint16_t) * 4);
1933         gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0];
1934
1935         gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
1936         gpu_metrics->indep_throttle_status =
1937                         smu_cmn_get_indep_throttler_status(metrics.Current.ThrottlerStatus,
1938                                                            vangogh_throttler_map);
1939
1940         gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
1941
1942         *table = (void *)gpu_metrics;
1943
1944         return sizeof(struct gpu_metrics_v2_4);
1945 }
1946
1947 static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
1948                                       void **table)
1949 {
1950         struct smu_table_context *smu_table = &smu->smu_table;
1951         struct gpu_metrics_v2_2 *gpu_metrics =
1952                 (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table;
1953         SmuMetrics_t metrics;
1954         int ret = 0;
1955
1956         ret = smu_cmn_get_metrics_table(smu, &metrics, true);
1957         if (ret)
1958                 return ret;
1959
1960         smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2);
1961
1962         gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
1963         gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
1964         memcpy(&gpu_metrics->temperature_core[0],
1965                 &metrics.Current.CoreTemperature[0],
1966                 sizeof(uint16_t) * 4);
1967         gpu_metrics->temperature_l3[0] = metrics.Current.L3Temperature[0];
1968
1969         gpu_metrics->average_gfx_activity = metrics.Current.GfxActivity;
1970         gpu_metrics->average_mm_activity = metrics.Current.UvdActivity;
1971
1972         gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
1973         gpu_metrics->average_cpu_power = metrics.Current.Power[0];
1974         gpu_metrics->average_soc_power = metrics.Current.Power[1];
1975         gpu_metrics->average_gfx_power = metrics.Current.Power[2];
1976         memcpy(&gpu_metrics->average_core_power[0],
1977                 &metrics.Average.CorePower[0],
1978                 sizeof(uint16_t) * 4);
1979
1980         gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
1981         gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
1982         gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
1983         gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
1984         gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
1985         gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
1986
1987         gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
1988         gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
1989         gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
1990         gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
1991         gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
1992         gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
1993
1994         memcpy(&gpu_metrics->current_coreclk[0],
1995                 &metrics.Current.CoreFrequency[0],
1996                 sizeof(uint16_t) * 4);
1997         gpu_metrics->current_l3clk[0] = metrics.Current.L3Frequency[0];
1998
1999         gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
2000         gpu_metrics->indep_throttle_status =
2001                         smu_cmn_get_indep_throttler_status(metrics.Current.ThrottlerStatus,
2002                                                            vangogh_throttler_map);
2003
2004         gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
2005
2006         *table = (void *)gpu_metrics;
2007
2008         return sizeof(struct gpu_metrics_v2_2);
2009 }
2010
2011 static ssize_t vangogh_common_get_gpu_metrics(struct smu_context *smu,
2012                                       void **table)
2013 {
2014         uint32_t if_version;
2015         uint32_t smu_version;
2016         uint32_t smu_program;
2017         uint32_t fw_version;
2018         int ret = 0;
2019
2020         ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
2021         if (ret)
2022                 return ret;
2023
2024         smu_program = (smu_version >> 24) & 0xff;
2025         fw_version = smu_version & 0xffffff;
2026         if (smu_program == 6) {
2027                 if (fw_version >= 0x3F0800)
2028                         ret = vangogh_get_gpu_metrics_v2_4(smu, table);
2029                 else
2030                         ret = vangogh_get_gpu_metrics_v2_3(smu, table);
2031
2032         } else {
2033                 if (smu_version >= 0x043F3E00) {
2034                         if (if_version < 0x3)
2035                                 ret = vangogh_get_legacy_gpu_metrics_v2_3(smu, table);
2036                         else
2037                                 ret = vangogh_get_gpu_metrics_v2_3(smu, table);
2038                 } else {
2039                         if (if_version < 0x3)
2040                                 ret = vangogh_get_legacy_gpu_metrics(smu, table);
2041                         else
2042                                 ret = vangogh_get_gpu_metrics(smu, table);
2043                 }
2044         }
2045
2046         return ret;
2047 }
2048
2049 static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
2050                                         long input[], uint32_t size)
2051 {
2052         int ret = 0;
2053         struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2054
2055         if (!(smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)) {
2056                 dev_warn(smu->adev->dev,
2057                         "pp_od_clk_voltage is not accessible if power_dpm_force_performance_level is not in manual mode!\n");
2058                 return -EINVAL;
2059         }
2060
2061         switch (type) {
2062         case PP_OD_EDIT_CCLK_VDDC_TABLE:
2063                 if (size != 3) {
2064                         dev_err(smu->adev->dev, "Input parameter number not correct (should be 4 for processor)\n");
2065                         return -EINVAL;
2066                 }
2067                 if (input[0] >= smu->cpu_core_num) {
2068                         dev_err(smu->adev->dev, "core index is overflow, should be less than %d\n",
2069                                 smu->cpu_core_num);
2070                 }
2071                 smu->cpu_core_id_select = input[0];
2072                 if (input[1] == 0) {
2073                         if (input[2] < smu->cpu_default_soft_min_freq) {
2074                                 dev_warn(smu->adev->dev, "Fine grain setting minimum cclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
2075                                         input[2], smu->cpu_default_soft_min_freq);
2076                                 return -EINVAL;
2077                         }
2078                         smu->cpu_actual_soft_min_freq = input[2];
2079                 } else if (input[1] == 1) {
2080                         if (input[2] > smu->cpu_default_soft_max_freq) {
2081                                 dev_warn(smu->adev->dev, "Fine grain setting maximum cclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
2082                                         input[2], smu->cpu_default_soft_max_freq);
2083                                 return -EINVAL;
2084                         }
2085                         smu->cpu_actual_soft_max_freq = input[2];
2086                 } else {
2087                         return -EINVAL;
2088                 }
2089                 break;
2090         case PP_OD_EDIT_SCLK_VDDC_TABLE:
2091                 if (size != 2) {
2092                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
2093                         return -EINVAL;
2094                 }
2095
2096                 if (input[0] == 0) {
2097                         if (input[1] < smu->gfx_default_hard_min_freq) {
2098                                 dev_warn(smu->adev->dev,
2099                                         "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
2100                                         input[1], smu->gfx_default_hard_min_freq);
2101                                 return -EINVAL;
2102                         }
2103                         smu->gfx_actual_hard_min_freq = input[1];
2104                 } else if (input[0] == 1) {
2105                         if (input[1] > smu->gfx_default_soft_max_freq) {
2106                                 dev_warn(smu->adev->dev,
2107                                         "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
2108                                         input[1], smu->gfx_default_soft_max_freq);
2109                                 return -EINVAL;
2110                         }
2111                         smu->gfx_actual_soft_max_freq = input[1];
2112                 } else {
2113                         return -EINVAL;
2114                 }
2115                 break;
2116         case PP_OD_RESTORE_DEFAULT_TABLE:
2117                 if (size != 0) {
2118                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
2119                         return -EINVAL;
2120                 } else {
2121                         smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
2122                         smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
2123                         smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
2124                         smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
2125                 }
2126                 break;
2127         case PP_OD_COMMIT_DPM_TABLE:
2128                 if (size != 0) {
2129                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
2130                         return -EINVAL;
2131                 } else {
2132                         if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
2133                                 dev_err(smu->adev->dev,
2134                                         "The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
2135                                         smu->gfx_actual_hard_min_freq,
2136                                         smu->gfx_actual_soft_max_freq);
2137                                 return -EINVAL;
2138                         }
2139
2140                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
2141                                                                         smu->gfx_actual_hard_min_freq, NULL);
2142                         if (ret) {
2143                                 dev_err(smu->adev->dev, "Set hard min sclk failed!");
2144                                 return ret;
2145                         }
2146
2147                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
2148                                                                         smu->gfx_actual_soft_max_freq, NULL);
2149                         if (ret) {
2150                                 dev_err(smu->adev->dev, "Set soft max sclk failed!");
2151                                 return ret;
2152                         }
2153
2154                         if (smu->adev->pm.fw_version < 0x43f1b00) {
2155                                 dev_warn(smu->adev->dev, "CPUSoftMax/CPUSoftMin are not supported, please update SBIOS!\n");
2156                                 break;
2157                         }
2158
2159                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinCclk,
2160                                                               ((smu->cpu_core_id_select << 20)
2161                                                                | smu->cpu_actual_soft_min_freq),
2162                                                               NULL);
2163                         if (ret) {
2164                                 dev_err(smu->adev->dev, "Set hard min cclk failed!");
2165                                 return ret;
2166                         }
2167
2168                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxCclk,
2169                                                               ((smu->cpu_core_id_select << 20)
2170                                                                | smu->cpu_actual_soft_max_freq),
2171                                                               NULL);
2172                         if (ret) {
2173                                 dev_err(smu->adev->dev, "Set soft max cclk failed!");
2174                                 return ret;
2175                         }
2176                 }
2177                 break;
2178         default:
2179                 return -ENOSYS;
2180         }
2181
2182         return ret;
2183 }
2184
2185 static int vangogh_set_default_dpm_tables(struct smu_context *smu)
2186 {
2187         struct smu_table_context *smu_table = &smu->smu_table;
2188
2189         return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
2190 }
2191
2192 static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
2193 {
2194         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
2195
2196         smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
2197         smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
2198         smu->gfx_actual_hard_min_freq = 0;
2199         smu->gfx_actual_soft_max_freq = 0;
2200
2201         smu->cpu_default_soft_min_freq = 1400;
2202         smu->cpu_default_soft_max_freq = 3500;
2203         smu->cpu_actual_soft_min_freq = 0;
2204         smu->cpu_actual_soft_max_freq = 0;
2205
2206         return 0;
2207 }
2208
2209 static int vangogh_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table)
2210 {
2211         DpmClocks_t *table = smu->smu_table.clocks_table;
2212         int i;
2213
2214         if (!clock_table || !table)
2215                 return -EINVAL;
2216
2217         for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
2218                 clock_table->SocClocks[i].Freq = table->SocClocks[i];
2219                 clock_table->SocClocks[i].Vol = table->SocVoltage[i];
2220         }
2221
2222         for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
2223                 clock_table->FClocks[i].Freq = table->DfPstateTable[i].fclk;
2224                 clock_table->FClocks[i].Vol = table->DfPstateTable[i].voltage;
2225         }
2226
2227         for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
2228                 clock_table->MemClocks[i].Freq = table->DfPstateTable[i].memclk;
2229                 clock_table->MemClocks[i].Vol = table->DfPstateTable[i].voltage;
2230         }
2231
2232         return 0;
2233 }
2234
2235
2236 static int vangogh_system_features_control(struct smu_context *smu, bool en)
2237 {
2238         struct amdgpu_device *adev = smu->adev;
2239         int ret = 0;
2240
2241         if (adev->pm.fw_version >= 0x43f1700 && !en)
2242                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RlcPowerNotify,
2243                                                       RLC_STATUS_OFF, NULL);
2244
2245         return ret;
2246 }
2247
2248 static int vangogh_post_smu_init(struct smu_context *smu)
2249 {
2250         struct amdgpu_device *adev = smu->adev;
2251         uint32_t tmp;
2252         int ret = 0;
2253         uint8_t aon_bits = 0;
2254         /* Two CUs in one WGP */
2255         uint32_t req_active_wgps = adev->gfx.cu_info.number/2;
2256         uint32_t total_cu = adev->gfx.config.max_cu_per_sh *
2257                 adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines;
2258
2259         /* allow message will be sent after enable message on Vangogh*/
2260         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
2261                         (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
2262                 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL);
2263                 if (ret) {
2264                         dev_err(adev->dev, "Failed to Enable GfxOff!\n");
2265                         return ret;
2266                 }
2267         } else {
2268                 adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
2269                 dev_info(adev->dev, "If GFX DPM or power gate disabled, disable GFXOFF\n");
2270         }
2271
2272         /* if all CUs are active, no need to power off any WGPs */
2273         if (total_cu == adev->gfx.cu_info.number)
2274                 return 0;
2275
2276         /*
2277          * Calculate the total bits number of always on WGPs for all SA/SEs in
2278          * RLC_PG_ALWAYS_ON_WGP_MASK.
2279          */
2280         tmp = RREG32_KIQ(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_ALWAYS_ON_WGP_MASK));
2281         tmp &= RLC_PG_ALWAYS_ON_WGP_MASK__AON_WGP_MASK_MASK;
2282
2283         aon_bits = hweight32(tmp) * adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines;
2284
2285         /* Do not request any WGPs less than set in the AON_WGP_MASK */
2286         if (aon_bits > req_active_wgps) {
2287                 dev_info(adev->dev, "Number of always on WGPs greater than active WGPs: WGP power save not requested.\n");
2288                 return 0;
2289         } else {
2290                 return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestActiveWgp, req_active_wgps, NULL);
2291         }
2292 }
2293
2294 static int vangogh_mode_reset(struct smu_context *smu, int type)
2295 {
2296         int ret = 0, index = 0;
2297
2298         index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG,
2299                                                SMU_MSG_GfxDeviceDriverReset);
2300         if (index < 0)
2301                 return index == -EACCES ? 0 : index;
2302
2303         mutex_lock(&smu->message_lock);
2304
2305         ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index, type);
2306
2307         mutex_unlock(&smu->message_lock);
2308
2309         mdelay(10);
2310
2311         return ret;
2312 }
2313
2314 static int vangogh_mode2_reset(struct smu_context *smu)
2315 {
2316         return vangogh_mode_reset(smu, SMU_RESET_MODE_2);
2317 }
2318
2319 /**
2320  * vangogh_get_gfxoff_status - Get gfxoff status
2321  *
2322  * @smu: amdgpu_device pointer
2323  *
2324  * Get current gfxoff status
2325  *
2326  * Return:
2327  * * 0  - GFXOFF (default if enabled).
2328  * * 1  - Transition out of GFX State.
2329  * * 2  - Not in GFXOFF.
2330  * * 3  - Transition into GFXOFF.
2331  */
2332 static u32 vangogh_get_gfxoff_status(struct smu_context *smu)
2333 {
2334         struct amdgpu_device *adev = smu->adev;
2335         u32 reg, gfxoff_status;
2336
2337         reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_GFX_MISC_CNTL);
2338         gfxoff_status = (reg & SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK)
2339                 >> SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT;
2340
2341         return gfxoff_status;
2342 }
2343
2344 static int vangogh_get_power_limit(struct smu_context *smu,
2345                                    uint32_t *current_power_limit,
2346                                    uint32_t *default_power_limit,
2347                                    uint32_t *max_power_limit)
2348 {
2349         struct smu_11_5_power_context *power_context =
2350                                                                 smu->smu_power.power_context;
2351         uint32_t ppt_limit;
2352         int ret = 0;
2353
2354         if (smu->adev->pm.fw_version < 0x43f1e00)
2355                 return ret;
2356
2357         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSlowPPTLimit, &ppt_limit);
2358         if (ret) {
2359                 dev_err(smu->adev->dev, "Get slow PPT limit failed!\n");
2360                 return ret;
2361         }
2362         /* convert from milliwatt to watt */
2363         if (current_power_limit)
2364                 *current_power_limit = ppt_limit / 1000;
2365         if (default_power_limit)
2366                 *default_power_limit = ppt_limit / 1000;
2367         if (max_power_limit)
2368                 *max_power_limit = 29;
2369
2370         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit);
2371         if (ret) {
2372                 dev_err(smu->adev->dev, "Get fast PPT limit failed!\n");
2373                 return ret;
2374         }
2375         /* convert from milliwatt to watt */
2376         power_context->current_fast_ppt_limit =
2377                         power_context->default_fast_ppt_limit = ppt_limit / 1000;
2378         power_context->max_fast_ppt_limit = 30;
2379
2380         return ret;
2381 }
2382
2383 static int vangogh_get_ppt_limit(struct smu_context *smu,
2384                                                                 uint32_t *ppt_limit,
2385                                                                 enum smu_ppt_limit_type type,
2386                                                                 enum smu_ppt_limit_level level)
2387 {
2388         struct smu_11_5_power_context *power_context =
2389                                                         smu->smu_power.power_context;
2390
2391         if (!power_context)
2392                 return -EOPNOTSUPP;
2393
2394         if (type == SMU_FAST_PPT_LIMIT) {
2395                 switch (level) {
2396                 case SMU_PPT_LIMIT_MAX:
2397                         *ppt_limit = power_context->max_fast_ppt_limit;
2398                         break;
2399                 case SMU_PPT_LIMIT_CURRENT:
2400                         *ppt_limit = power_context->current_fast_ppt_limit;
2401                         break;
2402                 case SMU_PPT_LIMIT_DEFAULT:
2403                         *ppt_limit = power_context->default_fast_ppt_limit;
2404                         break;
2405                 default:
2406                         break;
2407                 }
2408         }
2409
2410         return 0;
2411 }
2412
2413 static int vangogh_set_power_limit(struct smu_context *smu,
2414                                    enum smu_ppt_limit_type limit_type,
2415                                    uint32_t ppt_limit)
2416 {
2417         struct smu_11_5_power_context *power_context =
2418                         smu->smu_power.power_context;
2419         int ret = 0;
2420
2421         if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
2422                 dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
2423                 return -EOPNOTSUPP;
2424         }
2425
2426         switch (limit_type) {
2427         case SMU_DEFAULT_PPT_LIMIT:
2428                 ret = smu_cmn_send_smc_msg_with_param(smu,
2429                                 SMU_MSG_SetSlowPPTLimit,
2430                                 ppt_limit * 1000, /* convert from watt to milliwatt */
2431                                 NULL);
2432                 if (ret)
2433                         return ret;
2434
2435                 smu->current_power_limit = ppt_limit;
2436                 break;
2437         case SMU_FAST_PPT_LIMIT:
2438                 ppt_limit &= ~(SMU_FAST_PPT_LIMIT << 24);
2439                 if (ppt_limit > power_context->max_fast_ppt_limit) {
2440                         dev_err(smu->adev->dev,
2441                                 "New power limit (%d) is over the max allowed %d\n",
2442                                 ppt_limit, power_context->max_fast_ppt_limit);
2443                         return ret;
2444                 }
2445
2446                 ret = smu_cmn_send_smc_msg_with_param(smu,
2447                                 SMU_MSG_SetFastPPTLimit,
2448                                 ppt_limit * 1000, /* convert from watt to milliwatt */
2449                                 NULL);
2450                 if (ret)
2451                         return ret;
2452
2453                 power_context->current_fast_ppt_limit = ppt_limit;
2454                 break;
2455         default:
2456                 return -EINVAL;
2457         }
2458
2459         return ret;
2460 }
2461
2462 /**
2463  * vangogh_set_gfxoff_residency
2464  *
2465  * @smu: amdgpu_device pointer
2466  * @start: start/stop residency log
2467  *
2468  * This function will be used to log gfxoff residency
2469  *
2470  *
2471  * Returns standard response codes.
2472  */
2473 static u32 vangogh_set_gfxoff_residency(struct smu_context *smu, bool start)
2474 {
2475         int ret = 0;
2476         u32 residency;
2477         struct amdgpu_device *adev = smu->adev;
2478
2479         if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
2480                 return 0;
2481
2482         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_LogGfxOffResidency,
2483                                               start, &residency);
2484
2485         if (!start)
2486                 adev->gfx.gfx_off_residency = residency;
2487
2488         return ret;
2489 }
2490
2491 /**
2492  * vangogh_get_gfxoff_residency
2493  *
2494  * @smu: amdgpu_device pointer
2495  * @residency: placeholder for return value
2496  *
2497  * This function will be used to get gfxoff residency.
2498  *
2499  * Returns standard response codes.
2500  */
2501 static u32 vangogh_get_gfxoff_residency(struct smu_context *smu, uint32_t *residency)
2502 {
2503         struct amdgpu_device *adev = smu->adev;
2504
2505         *residency = adev->gfx.gfx_off_residency;
2506
2507         return 0;
2508 }
2509
2510 /**
2511  * vangogh_get_gfxoff_entrycount - get gfxoff entry count
2512  *
2513  * @smu: amdgpu_device pointer
2514  * @entrycount: placeholder for return value
2515  *
2516  * This function will be used to get gfxoff entry count
2517  *
2518  * Returns standard response codes.
2519  */
2520 static u32 vangogh_get_gfxoff_entrycount(struct smu_context *smu, uint64_t *entrycount)
2521 {
2522         int ret = 0, value = 0;
2523         struct amdgpu_device *adev = smu->adev;
2524
2525         if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
2526                 return 0;
2527
2528         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetGfxOffEntryCount, &value);
2529         *entrycount = value + adev->gfx.gfx_off_entrycount;
2530
2531         return ret;
2532 }
2533
2534 static const struct pptable_funcs vangogh_ppt_funcs = {
2535
2536         .check_fw_status = smu_v11_0_check_fw_status,
2537         .check_fw_version = smu_v11_0_check_fw_version,
2538         .init_smc_tables = vangogh_init_smc_tables,
2539         .fini_smc_tables = smu_v11_0_fini_smc_tables,
2540         .init_power = smu_v11_0_init_power,
2541         .fini_power = smu_v11_0_fini_power,
2542         .register_irq_handler = smu_v11_0_register_irq_handler,
2543         .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
2544         .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
2545         .send_smc_msg = smu_cmn_send_smc_msg,
2546         .dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable,
2547         .dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable,
2548         .is_dpm_running = vangogh_is_dpm_running,
2549         .read_sensor = vangogh_read_sensor,
2550         .get_apu_thermal_limit = vangogh_get_apu_thermal_limit,
2551         .set_apu_thermal_limit = vangogh_set_apu_thermal_limit,
2552         .get_enabled_mask = smu_cmn_get_enabled_mask,
2553         .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
2554         .set_watermarks_table = vangogh_set_watermarks_table,
2555         .set_driver_table_location = smu_v11_0_set_driver_table_location,
2556         .interrupt_work = smu_v11_0_interrupt_work,
2557         .get_gpu_metrics = vangogh_common_get_gpu_metrics,
2558         .od_edit_dpm_table = vangogh_od_edit_dpm_table,
2559         .print_clk_levels = vangogh_common_print_clk_levels,
2560         .set_default_dpm_table = vangogh_set_default_dpm_tables,
2561         .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters,
2562         .system_features_control = vangogh_system_features_control,
2563         .feature_is_enabled = smu_cmn_feature_is_enabled,
2564         .set_power_profile_mode = vangogh_set_power_profile_mode,
2565         .get_power_profile_mode = vangogh_get_power_profile_mode,
2566         .get_dpm_clock_table = vangogh_get_dpm_clock_table,
2567         .force_clk_levels = vangogh_force_clk_levels,
2568         .set_performance_level = vangogh_set_performance_level,
2569         .post_init = vangogh_post_smu_init,
2570         .mode2_reset = vangogh_mode2_reset,
2571         .gfx_off_control = smu_v11_0_gfx_off_control,
2572         .get_gfx_off_status = vangogh_get_gfxoff_status,
2573         .get_gfx_off_entrycount = vangogh_get_gfxoff_entrycount,
2574         .get_gfx_off_residency = vangogh_get_gfxoff_residency,
2575         .set_gfx_off_residency = vangogh_set_gfxoff_residency,
2576         .get_ppt_limit = vangogh_get_ppt_limit,
2577         .get_power_limit = vangogh_get_power_limit,
2578         .set_power_limit = vangogh_set_power_limit,
2579         .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
2580 };
2581
2582 void vangogh_set_ppt_funcs(struct smu_context *smu)
2583 {
2584         smu->ppt_funcs = &vangogh_ppt_funcs;
2585         smu->message_map = vangogh_message_map;
2586         smu->feature_map = vangogh_feature_mask_map;
2587         smu->table_map = vangogh_table_map;
2588         smu->workload_map = vangogh_workload_map;
2589         smu->is_apu = true;
2590         smu_v11_0_set_smu_mailbox_registers(smu);
2591 }