drm/amd/pm: fix spelling mistakes in dev_warn messages
[linux-2.6-microblaze.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
35 /*
36  * DO NOT use these for err/warn/info/debug messages.
37  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
38  * They are more MGPU friendly.
39  */
40 #undef pr_err
41 #undef pr_warn
42 #undef pr_info
43 #undef pr_debug
44
45 #define FEATURE_MASK(feature) (1ULL << feature)
46 #define SMC_DPM_FEATURE ( \
47         FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
48         FEATURE_MASK(FEATURE_VCN_DPM_BIT)        | \
49         FEATURE_MASK(FEATURE_FCLK_DPM_BIT)       | \
50         FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT)     | \
51         FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT)     | \
52         FEATURE_MASK(FEATURE_LCLK_DPM_BIT)       | \
53         FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT)    | \
54         FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \
55         FEATURE_MASK(FEATURE_GFX_DPM_BIT))
56
57 static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = {
58         MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,                  0),
59         MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,                0),
60         MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,   0),
61         MSG_MAP(EnableGfxOff,                   PPSMC_MSG_EnableGfxOff,                 0),
62         MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisableGfxOff,                0),
63         MSG_MAP(PowerDownIspByTile,             PPSMC_MSG_PowerDownIspByTile,   0),
64         MSG_MAP(PowerUpIspByTile,               PPSMC_MSG_PowerUpIspByTile,             0),
65         MSG_MAP(PowerDownVcn,                   PPSMC_MSG_PowerDownVcn,                 0),
66         MSG_MAP(PowerUpVcn,                     PPSMC_MSG_PowerUpVcn,                   0),
67         MSG_MAP(Spare,                          PPSMC_MSG_spare,                                0),
68         MSG_MAP(SetHardMinVcn,                  PPSMC_MSG_SetHardMinVcn,                0),
69         MSG_MAP(SetSoftMinGfxclk,               PPSMC_MSG_SetSoftMinGfxclk,             0),
70         MSG_MAP(ActiveProcessNotify,            PPSMC_MSG_ActiveProcessNotify,          0),
71         MSG_MAP(SetHardMinIspiclkByFreq,        PPSMC_MSG_SetHardMinIspiclkByFreq,      0),
72         MSG_MAP(SetHardMinIspxclkByFreq,        PPSMC_MSG_SetHardMinIspxclkByFreq,      0),
73         MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh,        0),
74         MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow,         0),
75         MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,        0),
76         MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,        0),
77         MSG_MAP(GfxDeviceDriverReset,           PPSMC_MSG_GfxDeviceDriverReset,         0),
78         MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,        0),
79         MSG_MAP(Spare1,                         PPSMC_MSG_spare1,                                       0),
80         MSG_MAP(SetHardMinSocclkByFreq,         PPSMC_MSG_SetHardMinSocclkByFreq,       0),
81         MSG_MAP(SetSoftMinFclk,                 PPSMC_MSG_SetSoftMinFclk,               0),
82         MSG_MAP(SetSoftMinVcn,                  PPSMC_MSG_SetSoftMinVcn,                0),
83         MSG_MAP(EnablePostCode,                 PPSMC_MSG_EnablePostCode,               0),
84         MSG_MAP(GetGfxclkFrequency,             PPSMC_MSG_GetGfxclkFrequency,   0),
85         MSG_MAP(GetFclkFrequency,               PPSMC_MSG_GetFclkFrequency,             0),
86         MSG_MAP(SetSoftMaxGfxClk,               PPSMC_MSG_SetSoftMaxGfxClk,             0),
87         MSG_MAP(SetHardMinGfxClk,               PPSMC_MSG_SetHardMinGfxClk,             0),
88         MSG_MAP(SetSoftMaxSocclkByFreq,         PPSMC_MSG_SetSoftMaxSocclkByFreq,       0),
89         MSG_MAP(SetSoftMaxFclkByFreq,           PPSMC_MSG_SetSoftMaxFclkByFreq,         0),
90         MSG_MAP(SetSoftMaxVcn,                  PPSMC_MSG_SetSoftMaxVcn,                        0),
91         MSG_MAP(Spare2,                         PPSMC_MSG_spare2,                                       0),
92         MSG_MAP(SetPowerLimitPercentage,        PPSMC_MSG_SetPowerLimitPercentage,      0),
93         MSG_MAP(PowerDownJpeg,                  PPSMC_MSG_PowerDownJpeg,                        0),
94         MSG_MAP(PowerUpJpeg,                    PPSMC_MSG_PowerUpJpeg,                          0),
95         MSG_MAP(SetHardMinFclkByFreq,           PPSMC_MSG_SetHardMinFclkByFreq,         0),
96         MSG_MAP(SetSoftMinSocclkByFreq,         PPSMC_MSG_SetSoftMinSocclkByFreq,       0),
97         MSG_MAP(PowerUpCvip,                    PPSMC_MSG_PowerUpCvip,                          0),
98         MSG_MAP(PowerDownCvip,                  PPSMC_MSG_PowerDownCvip,                        0),
99         MSG_MAP(GetPptLimit,                        PPSMC_MSG_GetPptLimit,                      0),
100         MSG_MAP(GetThermalLimit,                    PPSMC_MSG_GetThermalLimit,          0),
101         MSG_MAP(GetCurrentTemperature,              PPSMC_MSG_GetCurrentTemperature, 0),
102         MSG_MAP(GetCurrentPower,                    PPSMC_MSG_GetCurrentPower,           0),
103         MSG_MAP(GetCurrentVoltage,                  PPSMC_MSG_GetCurrentVoltage,         0),
104         MSG_MAP(GetCurrentCurrent,                  PPSMC_MSG_GetCurrentCurrent,         0),
105         MSG_MAP(GetAverageCpuActivity,              PPSMC_MSG_GetAverageCpuActivity, 0),
106         MSG_MAP(GetAverageGfxActivity,              PPSMC_MSG_GetAverageGfxActivity, 0),
107         MSG_MAP(GetAveragePower,                    PPSMC_MSG_GetAveragePower,           0),
108         MSG_MAP(GetAverageTemperature,              PPSMC_MSG_GetAverageTemperature, 0),
109         MSG_MAP(SetAveragePowerTimeConstant,        PPSMC_MSG_SetAveragePowerTimeConstant,                      0),
110         MSG_MAP(SetAverageActivityTimeConstant,     PPSMC_MSG_SetAverageActivityTimeConstant,           0),
111         MSG_MAP(SetAverageTemperatureTimeConstant,  PPSMC_MSG_SetAverageTemperatureTimeConstant,        0),
112         MSG_MAP(SetMitigationEndHysteresis,         PPSMC_MSG_SetMitigationEndHysteresis,                       0),
113         MSG_MAP(GetCurrentFreq,                     PPSMC_MSG_GetCurrentFreq,                                           0),
114         MSG_MAP(SetReducedPptLimit,                 PPSMC_MSG_SetReducedPptLimit,                                       0),
115         MSG_MAP(SetReducedThermalLimit,             PPSMC_MSG_SetReducedThermalLimit,                           0),
116         MSG_MAP(DramLogSetDramAddr,                 PPSMC_MSG_DramLogSetDramAddr,                                       0),
117         MSG_MAP(StartDramLogging,                   PPSMC_MSG_StartDramLogging,                                         0),
118         MSG_MAP(StopDramLogging,                    PPSMC_MSG_StopDramLogging,                                          0),
119         MSG_MAP(SetSoftMinCclk,                     PPSMC_MSG_SetSoftMinCclk,                                           0),
120         MSG_MAP(SetSoftMaxCclk,                     PPSMC_MSG_SetSoftMaxCclk,                                           0),
121 };
122
123 static struct cmn2asic_mapping vangogh_feature_mask_map[SMU_FEATURE_COUNT] = {
124         FEA_MAP(PPT),
125         FEA_MAP(TDC),
126         FEA_MAP(THERMAL),
127         FEA_MAP(DS_GFXCLK),
128         FEA_MAP(DS_SOCCLK),
129         FEA_MAP(DS_LCLK),
130         FEA_MAP(DS_FCLK),
131         FEA_MAP(DS_MP1CLK),
132         FEA_MAP(DS_MP0CLK),
133         FEA_MAP(ATHUB_PG),
134         FEA_MAP(CCLK_DPM),
135         FEA_MAP(FAN_CONTROLLER),
136         FEA_MAP(ULV),
137         FEA_MAP(VCN_DPM),
138         FEA_MAP(LCLK_DPM),
139         FEA_MAP(SHUBCLK_DPM),
140         FEA_MAP(DCFCLK_DPM),
141         FEA_MAP(DS_DCFCLK),
142         FEA_MAP(S0I2),
143         FEA_MAP(SMU_LOW_POWER),
144         FEA_MAP(GFX_DEM),
145         FEA_MAP(PSI),
146         FEA_MAP(PROCHOT),
147         FEA_MAP(CPUOFF),
148         FEA_MAP(STAPM),
149         FEA_MAP(S0I3),
150         FEA_MAP(DF_CSTATES),
151         FEA_MAP(PERF_LIMIT),
152         FEA_MAP(CORE_DLDO),
153         FEA_MAP(RSMU_LOW_POWER),
154         FEA_MAP(SMN_LOW_POWER),
155         FEA_MAP(THM_LOW_POWER),
156         FEA_MAP(SMUIO_LOW_POWER),
157         FEA_MAP(MP1_LOW_POWER),
158         FEA_MAP(DS_VCN),
159         FEA_MAP(CPPC),
160         FEA_MAP(OS_CSTATES),
161         FEA_MAP(ISP_DPM),
162         FEA_MAP(A55_DPM),
163         FEA_MAP(CVIP_DSP_DPM),
164         FEA_MAP(MSMU_LOW_POWER),
165 };
166
167 static struct cmn2asic_mapping vangogh_table_map[SMU_TABLE_COUNT] = {
168         TAB_MAP_VALID(WATERMARKS),
169         TAB_MAP_VALID(SMU_METRICS),
170         TAB_MAP_VALID(CUSTOM_DPM),
171         TAB_MAP_VALID(DPMCLOCKS),
172 };
173
174 static int vangogh_tables_init(struct smu_context *smu)
175 {
176         struct smu_table_context *smu_table = &smu->smu_table;
177         struct smu_table *tables = smu_table->tables;
178
179         SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
180                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
181         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
182                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
183         SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
184                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
185         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
186                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
187         SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t),
188                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
189         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
190         if (!smu_table->metrics_table)
191                 goto err0_out;
192         smu_table->metrics_time = 0;
193
194         smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0);
195         smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
196         if (!smu_table->gpu_metrics_table)
197                 goto err1_out;
198
199         smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
200         if (!smu_table->watermarks_table)
201                 goto err2_out;
202
203         smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
204         if (!smu_table->clocks_table)
205                 goto err3_out;
206
207         return 0;
208
209 err3_out:
210         kfree(smu_table->clocks_table);
211 err2_out:
212         kfree(smu_table->gpu_metrics_table);
213 err1_out:
214         kfree(smu_table->metrics_table);
215 err0_out:
216         return -ENOMEM;
217 }
218
219 static int vangogh_get_smu_metrics_data(struct smu_context *smu,
220                                        MetricsMember_t member,
221                                        uint32_t *value)
222 {
223         struct smu_table_context *smu_table = &smu->smu_table;
224
225         SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
226         int ret = 0;
227
228         mutex_lock(&smu->metrics_lock);
229
230         ret = smu_cmn_get_metrics_table_locked(smu,
231                                                NULL,
232                                                false);
233         if (ret) {
234                 mutex_unlock(&smu->metrics_lock);
235                 return ret;
236         }
237
238         switch (member) {
239         case METRICS_AVERAGE_GFXCLK:
240                 *value = metrics->GfxclkFrequency;
241                 break;
242         case METRICS_AVERAGE_SOCCLK:
243                 *value = metrics->SocclkFrequency;
244                 break;
245         case METRICS_AVERAGE_UCLK:
246                 *value = metrics->MemclkFrequency;
247                 break;
248         case METRICS_AVERAGE_GFXACTIVITY:
249                 *value = metrics->GfxActivity / 100;
250                 break;
251         case METRICS_AVERAGE_VCNACTIVITY:
252                 *value = metrics->UvdActivity;
253                 break;
254         case METRICS_AVERAGE_SOCKETPOWER:
255                 *value = metrics->CurrentSocketPower;
256                 break;
257         case METRICS_TEMPERATURE_EDGE:
258                 *value = metrics->GfxTemperature / 100 *
259                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
260                 break;
261         case METRICS_TEMPERATURE_HOTSPOT:
262                 *value = metrics->SocTemperature / 100 *
263                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
264                 break;
265         case METRICS_THROTTLER_STATUS:
266                 *value = metrics->ThrottlerStatus;
267                 break;
268         default:
269                 *value = UINT_MAX;
270                 break;
271         }
272
273         mutex_unlock(&smu->metrics_lock);
274
275         return ret;
276 }
277
278 static int vangogh_allocate_dpm_context(struct smu_context *smu)
279 {
280         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
281
282         smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
283                                        GFP_KERNEL);
284         if (!smu_dpm->dpm_context)
285                 return -ENOMEM;
286
287         smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
288
289         return 0;
290 }
291
292 static int vangogh_init_smc_tables(struct smu_context *smu)
293 {
294         int ret = 0;
295
296         ret = vangogh_tables_init(smu);
297         if (ret)
298                 return ret;
299
300         ret = vangogh_allocate_dpm_context(smu);
301         if (ret)
302                 return ret;
303
304         return smu_v11_0_init_smc_tables(smu);
305 }
306
307 static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
308 {
309         int ret = 0;
310
311         if (enable) {
312                 /* vcn dpm on is a prerequisite for vcn power gate messages */
313                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
314                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL);
315                         if (ret)
316                                 return ret;
317                 }
318         } else {
319                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
320                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL);
321                         if (ret)
322                                 return ret;
323                 }
324         }
325
326         return ret;
327 }
328
329 static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
330 {
331         int ret = 0;
332
333         if (enable) {
334                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
335                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL);
336                         if (ret)
337                                 return ret;
338                 }
339         } else {
340                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
341                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL);
342                         if (ret)
343                                 return ret;
344                 }
345         }
346
347         return ret;
348 }
349
350 static int vangogh_get_allowed_feature_mask(struct smu_context *smu,
351                                             uint32_t *feature_mask,
352                                             uint32_t num)
353 {
354         struct amdgpu_device *adev = smu->adev;
355
356         if (num > 2)
357                 return -EINVAL;
358
359         memset(feature_mask, 0, sizeof(uint32_t) * num);
360
361         *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_DPM_BIT)
362                                 | FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT)
363                                 | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT)
364                                 | FEATURE_MASK(FEATURE_PPT_BIT)
365                                 | FEATURE_MASK(FEATURE_TDC_BIT)
366                                 | FEATURE_MASK(FEATURE_FAN_CONTROLLER_BIT)
367                                 | FEATURE_MASK(FEATURE_DS_LCLK_BIT)
368                                 | FEATURE_MASK(FEATURE_DS_DCFCLK_BIT);
369
370         if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
371                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT);
372
373         if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
374                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT);
375
376         if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB)
377                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT);
378
379         return 0;
380 }
381
382 static bool vangogh_is_dpm_running(struct smu_context *smu)
383 {
384         int ret = 0;
385         uint32_t feature_mask[2];
386         uint64_t feature_enabled;
387
388         ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2);
389
390         if (ret)
391                 return false;
392
393         feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
394                                 ((uint64_t)feature_mask[1] << 32));
395
396         return !!(feature_enabled & SMC_DPM_FEATURE);
397 }
398
399 static int vangogh_get_current_activity_percent(struct smu_context *smu,
400                                                enum amd_pp_sensors sensor,
401                                                uint32_t *value)
402 {
403         int ret = 0;
404
405         if (!value)
406                 return -EINVAL;
407
408         switch (sensor) {
409         case AMDGPU_PP_SENSOR_GPU_LOAD:
410                 ret = vangogh_get_smu_metrics_data(smu,
411                                                   METRICS_AVERAGE_GFXACTIVITY,
412                                                   value);
413                 break;
414         default:
415                 dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
416                 return -EINVAL;
417         }
418
419         return 0;
420 }
421
422 static int vangogh_get_gpu_power(struct smu_context *smu, uint32_t *value)
423 {
424         if (!value)
425                 return -EINVAL;
426
427         return vangogh_get_smu_metrics_data(smu,
428                                            METRICS_AVERAGE_SOCKETPOWER,
429                                            value);
430 }
431
432 static int vangogh_thermal_get_temperature(struct smu_context *smu,
433                                              enum amd_pp_sensors sensor,
434                                              uint32_t *value)
435 {
436         int ret = 0;
437
438         if (!value)
439                 return -EINVAL;
440
441         switch (sensor) {
442         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
443                 ret = vangogh_get_smu_metrics_data(smu,
444                                                   METRICS_TEMPERATURE_HOTSPOT,
445                                                   value);
446                 break;
447         case AMDGPU_PP_SENSOR_EDGE_TEMP:
448                 ret = vangogh_get_smu_metrics_data(smu,
449                                                   METRICS_TEMPERATURE_EDGE,
450                                                   value);
451                 break;
452         default:
453                 dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
454                 return -EINVAL;
455         }
456
457         return ret;
458 }
459
460 static int vangogh_get_current_clk_freq_by_table(struct smu_context *smu,
461                                        enum smu_clk_type clk_type,
462                                        uint32_t *value)
463 {
464         MetricsMember_t member_type;
465
466         switch (clk_type) {
467         case SMU_GFXCLK:
468                 member_type = METRICS_AVERAGE_GFXCLK;
469                 break;
470         case SMU_MCLK:
471         case SMU_UCLK:
472                 member_type = METRICS_AVERAGE_UCLK;
473                 break;
474         case SMU_SOCCLK:
475                 member_type = METRICS_AVERAGE_SOCCLK;
476                 break;
477         default:
478                 return -EINVAL;
479         }
480
481         return vangogh_get_smu_metrics_data(smu,
482                                            member_type,
483                                            value);
484 }
485
486 static int vangogh_print_fine_grain_clk(struct smu_context *smu,
487                         enum smu_clk_type clk_type, char *buf)
488 {
489         int size = 0;
490
491         switch (clk_type) {
492         case SMU_OD_SCLK:
493                 if (smu->od_enabled) {
494                         size = sprintf(buf, "%s:\n", "OD_SCLK");
495                         size += sprintf(buf + size, "0: %10uMhz\n",
496                         (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
497                         size += sprintf(buf + size, "1: %10uMhz\n",
498                         (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
499                 }
500                 break;
501         case SMU_OD_RANGE:
502                 if (smu->od_enabled) {
503                         size = sprintf(buf, "%s:\n", "OD_RANGE");
504                         size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
505                                 smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
506                 }
507                 break;
508         default:
509                 break;
510         }
511
512         return size;
513 }
514
515 static int vangogh_read_sensor(struct smu_context *smu,
516                                  enum amd_pp_sensors sensor,
517                                  void *data, uint32_t *size)
518 {
519         int ret = 0;
520
521         if (!data || !size)
522                 return -EINVAL;
523
524         mutex_lock(&smu->sensor_lock);
525         switch (sensor) {
526         case AMDGPU_PP_SENSOR_GPU_LOAD:
527                 ret = vangogh_get_current_activity_percent(smu, sensor, (uint32_t *)data);
528                 *size = 4;
529                 break;
530         case AMDGPU_PP_SENSOR_GPU_POWER:
531                 ret = vangogh_get_gpu_power(smu, (uint32_t *)data);
532                 *size = 4;
533                 break;
534         case AMDGPU_PP_SENSOR_EDGE_TEMP:
535         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
536                 ret = vangogh_thermal_get_temperature(smu, sensor, (uint32_t *)data);
537                 *size = 4;
538                 break;
539         case AMDGPU_PP_SENSOR_GFX_MCLK:
540                 ret = vangogh_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
541                 *(uint32_t *)data *= 100;
542                 *size = 4;
543                 break;
544         case AMDGPU_PP_SENSOR_GFX_SCLK:
545                 ret = vangogh_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
546                 *(uint32_t *)data *= 100;
547                 *size = 4;
548                 break;
549         case AMDGPU_PP_SENSOR_VDDGFX:
550                 ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data);
551                 *size = 4;
552                 break;
553         default:
554                 ret = -EOPNOTSUPP;
555                 break;
556         }
557         mutex_unlock(&smu->sensor_lock);
558
559         return ret;
560 }
561
562 static int vangogh_set_watermarks_table(struct smu_context *smu,
563                                        struct pp_smu_wm_range_sets *clock_ranges)
564 {
565         int i;
566         int ret = 0;
567         Watermarks_t *table = smu->smu_table.watermarks_table;
568
569         if (!table || !clock_ranges)
570                 return -EINVAL;
571
572         if (clock_ranges) {
573                 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
574                     clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
575                         return -EINVAL;
576
577                 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
578                         table->WatermarkRow[WM_DCFCLK][i].MinClock =
579                                 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
580                         table->WatermarkRow[WM_DCFCLK][i].MaxClock =
581                                 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
582                         table->WatermarkRow[WM_DCFCLK][i].MinMclk =
583                                 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
584                         table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
585                                 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
586
587                         table->WatermarkRow[WM_DCFCLK][i].WmSetting =
588                                 clock_ranges->reader_wm_sets[i].wm_inst;
589                 }
590
591                 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
592                         table->WatermarkRow[WM_SOCCLK][i].MinClock =
593                                 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
594                         table->WatermarkRow[WM_SOCCLK][i].MaxClock =
595                                 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
596                         table->WatermarkRow[WM_SOCCLK][i].MinMclk =
597                                 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
598                         table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
599                                 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
600
601                         table->WatermarkRow[WM_SOCCLK][i].WmSetting =
602                                 clock_ranges->writer_wm_sets[i].wm_inst;
603                 }
604
605                 smu->watermarks_bitmap |= WATERMARKS_EXIST;
606         }
607
608         /* pass data to smu controller */
609         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
610              !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
611                 ret = smu_cmn_write_watermarks_table(smu);
612                 if (ret) {
613                         dev_err(smu->adev->dev, "Failed to update WMTABLE!");
614                         return ret;
615                 }
616                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
617         }
618
619         return 0;
620 }
621
622 static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
623                                       void **table)
624 {
625         struct smu_table_context *smu_table = &smu->smu_table;
626         struct gpu_metrics_v2_0 *gpu_metrics =
627                 (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table;
628         SmuMetrics_t metrics;
629         int ret = 0;
630
631         ret = smu_cmn_get_metrics_table(smu, &metrics, true);
632         if (ret)
633                 return ret;
634
635         smu_v11_0_init_gpu_metrics_v2_0(gpu_metrics);
636
637         gpu_metrics->temperature_gfx = metrics.GfxTemperature;
638         gpu_metrics->temperature_soc = metrics.SocTemperature;
639         memcpy(&gpu_metrics->temperature_core[0],
640                 &metrics.CoreTemperature[0],
641                 sizeof(uint16_t) * 8);
642         gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
643         gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1];
644
645         gpu_metrics->average_gfx_activity = metrics.GfxActivity;
646         gpu_metrics->average_mm_activity = metrics.UvdActivity;
647
648         gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
649         gpu_metrics->average_cpu_power = metrics.Power[0];
650         gpu_metrics->average_soc_power = metrics.Power[1];
651         memcpy(&gpu_metrics->average_core_power[0],
652                 &metrics.CorePower[0],
653                 sizeof(uint16_t) * 8);
654
655         gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
656         gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
657         gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
658         gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
659
660         memcpy(&gpu_metrics->current_coreclk[0],
661                 &metrics.CoreFrequency[0],
662                 sizeof(uint16_t) * 8);
663         gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
664         gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1];
665
666         gpu_metrics->throttle_status = metrics.ThrottlerStatus;
667
668         *table = (void *)gpu_metrics;
669
670         return sizeof(struct gpu_metrics_v2_0);
671 }
672
673 static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
674                                                         long input[], uint32_t size)
675 {
676         int ret = 0;
677
678         if (!smu->od_enabled) {
679                 dev_warn(smu->adev->dev, "Fine grain is not enabled!\n");
680                 return -EINVAL;
681         }
682
683         switch (type) {
684         case PP_OD_EDIT_SCLK_VDDC_TABLE:
685                 if (size != 2) {
686                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
687                         return -EINVAL;
688                 }
689
690                 if (input[0] == 0) {
691                         if (input[1] < smu->gfx_default_hard_min_freq) {
692                                 dev_warn(smu->adev->dev, "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
693                                         input[1], smu->gfx_default_hard_min_freq);
694                                 return -EINVAL;
695                         }
696                         smu->gfx_actual_hard_min_freq = input[1];
697                 } else if (input[0] == 1) {
698                         if (input[1] > smu->gfx_default_soft_max_freq) {
699                                 dev_warn(smu->adev->dev, "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
700                                         input[1], smu->gfx_default_soft_max_freq);
701                                 return -EINVAL;
702                         }
703                         smu->gfx_actual_soft_max_freq = input[1];
704                 } else {
705                         return -EINVAL;
706                 }
707                 break;
708         case PP_OD_RESTORE_DEFAULT_TABLE:
709                 if (size != 0) {
710                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
711                         return -EINVAL;
712                 } else {
713                         smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
714                         smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
715
716                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
717                                                                         smu->gfx_actual_hard_min_freq, NULL);
718                         if (ret) {
719                                 dev_err(smu->adev->dev, "Restore the default hard min sclk failed!");
720                                 return ret;
721                         }
722
723                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
724                                                                         smu->gfx_actual_soft_max_freq, NULL);
725                         if (ret) {
726                                 dev_err(smu->adev->dev, "Restore the default soft max sclk failed!");
727                                 return ret;
728                         }
729                 }
730                 break;
731         case PP_OD_COMMIT_DPM_TABLE:
732                 if (size != 0) {
733                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
734                         return -EINVAL;
735                 } else {
736                         if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
737                                 dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
738                                 smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq);
739                                 return -EINVAL;
740                         }
741
742                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
743                                                                         smu->gfx_actual_hard_min_freq, NULL);
744                         if (ret) {
745                                 dev_err(smu->adev->dev, "Set hard min sclk failed!");
746                                 return ret;
747                         }
748
749                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
750                                                                         smu->gfx_actual_soft_max_freq, NULL);
751                         if (ret) {
752                                 dev_err(smu->adev->dev, "Set soft max sclk failed!");
753                                 return ret;
754                         }
755                 }
756                 break;
757         default:
758                 return -ENOSYS;
759         }
760
761         return ret;
762 }
763
764 int vangogh_set_default_dpm_tables(struct smu_context *smu)
765 {
766         struct smu_table_context *smu_table = &smu->smu_table;
767
768         return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
769 }
770
771 static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
772 {
773         DpmClocks_t *clk_table = smu->smu_table.clocks_table;
774
775         smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
776         smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
777         smu->gfx_actual_hard_min_freq = 0;
778         smu->gfx_actual_soft_max_freq = 0;
779
780         return 0;
781 }
782
783 static const struct pptable_funcs vangogh_ppt_funcs = {
784
785         .check_fw_status = smu_v11_0_check_fw_status,
786         .check_fw_version = smu_v11_0_check_fw_version,
787         .init_smc_tables = vangogh_init_smc_tables,
788         .fini_smc_tables = smu_v11_0_fini_smc_tables,
789         .init_power = smu_v11_0_init_power,
790         .fini_power = smu_v11_0_fini_power,
791         .register_irq_handler = smu_v11_0_register_irq_handler,
792         .get_allowed_feature_mask = vangogh_get_allowed_feature_mask,
793         .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
794         .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
795         .send_smc_msg = smu_cmn_send_smc_msg,
796         .dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable,
797         .dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable,
798         .is_dpm_running = vangogh_is_dpm_running,
799         .read_sensor = vangogh_read_sensor,
800         .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask,
801         .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
802         .set_watermarks_table = vangogh_set_watermarks_table,
803         .set_driver_table_location = smu_v11_0_set_driver_table_location,
804         .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
805         .interrupt_work = smu_v11_0_interrupt_work,
806         .get_gpu_metrics = vangogh_get_gpu_metrics,
807         .od_edit_dpm_table = vangogh_od_edit_dpm_table,
808         .print_clk_levels = vangogh_print_fine_grain_clk,
809         .set_default_dpm_table = vangogh_set_default_dpm_tables,
810         .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters,
811 };
812
813 void vangogh_set_ppt_funcs(struct smu_context *smu)
814 {
815         smu->ppt_funcs = &vangogh_ppt_funcs;
816         smu->message_map = vangogh_message_map;
817         smu->feature_map = vangogh_feature_mask_map;
818         smu->table_map = vangogh_table_map;
819         smu->is_apu = true;
820 }