4840e4d69b106db554b68bd748bf5b1fe5795c92
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / amd / pm / swsmu / smu11 / cyan_skillfish_ppt.c
1 /*
2  * Copyright 2021 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_cyan_skillfish.h"
30 #include "cyan_skillfish_ppt.h"
31 #include "smu_v11_8_ppsmc.h"
32 #include "smu_v11_8_pmfw.h"
33 #include "smu_cmn.h"
34 #include "soc15_common.h"
35
36 /*
37  * DO NOT use these for err/warn/info/debug messages.
38  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
39  * They are more MGPU friendly.
40  */
41
42 #undef pr_err
43 #undef pr_warn
44 #undef pr_info
45 #undef pr_debug
46
47 /* unit: MHz */
48 #define CYAN_SKILLFISH_SCLK_MIN                 1000
49 #define CYAN_SKILLFISH_SCLK_MAX                 2000
50
51 /* unit: mV */
52 #define CYAN_SKILLFISH_VDDC_MIN                 700
53 #define CYAN_SKILLFISH_VDDC_MAX                 1129
54 #define CYAN_SKILLFISH_VDDC_MAGIC                       5118 // 0x13fe
55
56 static struct gfx_user_settings {
57         uint32_t sclk;
58         uint32_t vddc;
59 } cyan_skillfish_user_settings;
60
61 static uint32_t cyan_skillfish_sclk_default;
62
63 #define FEATURE_MASK(feature) (1ULL << feature)
64 #define SMC_DPM_FEATURE ( \
65         FEATURE_MASK(FEATURE_FCLK_DPM_BIT)      |       \
66         FEATURE_MASK(FEATURE_SOC_DPM_BIT)       |       \
67         FEATURE_MASK(FEATURE_GFX_DPM_BIT))
68
69 static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = {
70         MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,                  0),
71         MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,                0),
72         MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,           0),
73         MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverTableDramAddrHigh,   0),
74         MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverTableDramAddrLow,    0),
75         MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,        0),
76         MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,        0),
77         MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,        0),
78         MSG_MAP(RequestGfxclk,                  PPSMC_MSG_RequestGfxclk,                0),
79         MSG_MAP(ForceGfxVid,                    PPSMC_MSG_ForceGfxVid,                  0),
80         MSG_MAP(UnforceGfxVid,                  PPSMC_MSG_UnforceGfxVid,                0),
81 };
82
83 static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = {
84         TAB_MAP_VALID(SMU_METRICS),
85 };
86
87 static int cyan_skillfish_tables_init(struct smu_context *smu)
88 {
89         struct smu_table_context *smu_table = &smu->smu_table;
90         struct smu_table *tables = smu_table->tables;
91
92         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS,
93                                 sizeof(SmuMetrics_t),
94                                 PAGE_SIZE,
95                                 AMDGPU_GEM_DOMAIN_VRAM);
96
97         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
98         if (!smu_table->metrics_table)
99                 goto err0_out;
100
101         smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2);
102         smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
103         if (!smu_table->gpu_metrics_table)
104                 goto err1_out;
105
106         smu_table->metrics_time = 0;
107
108         return 0;
109
110 err1_out:
111         smu_table->gpu_metrics_table_size = 0;
112         kfree(smu_table->metrics_table);
113 err0_out:
114         return -ENOMEM;
115 }
116
117 static int cyan_skillfish_init_smc_tables(struct smu_context *smu)
118 {
119         int ret = 0;
120
121         ret = cyan_skillfish_tables_init(smu);
122         if (ret)
123                 return ret;
124
125         return smu_v11_0_init_smc_tables(smu);
126 }
127
128 static int
129 cyan_skillfish_get_smu_metrics_data(struct smu_context *smu,
130                                         MetricsMember_t member,
131                                         uint32_t *value)
132 {
133         struct smu_table_context *smu_table = &smu->smu_table;
134         SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
135         int ret = 0;
136
137         ret = smu_cmn_get_metrics_table(smu, NULL, false);
138         if (ret)
139                 return ret;
140
141         switch (member) {
142         case METRICS_CURR_GFXCLK:
143                 *value = metrics->Current.GfxclkFrequency;
144                 break;
145         case METRICS_CURR_SOCCLK:
146                 *value = metrics->Current.SocclkFrequency;
147                 break;
148         case METRICS_CURR_VCLK:
149                 *value = metrics->Current.VclkFrequency;
150                 break;
151         case METRICS_CURR_DCLK:
152                 *value = metrics->Current.DclkFrequency;
153                 break;
154         case METRICS_CURR_UCLK:
155                 *value = metrics->Current.MemclkFrequency;
156                 break;
157         case METRICS_CURR_SOCKETPOWER:
158                 *value = (metrics->Current.CurrentSocketPower << 8) /
159                                 1000;
160                 break;
161         case METRICS_AVERAGE_SOCKETPOWER:
162                 *value = (metrics->Average.CurrentSocketPower << 8) /
163                                 1000;
164                 break;
165         case METRICS_TEMPERATURE_EDGE:
166                 *value = metrics->Current.GfxTemperature / 100 *
167                                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
168                 break;
169         case METRICS_TEMPERATURE_HOTSPOT:
170                 *value = metrics->Current.SocTemperature / 100 *
171                                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
172                 break;
173         case METRICS_VOLTAGE_VDDSOC:
174                 *value = metrics->Current.Voltage[0];
175                 break;
176         case METRICS_VOLTAGE_VDDGFX:
177                 *value = metrics->Current.Voltage[1];
178                 break;
179         case METRICS_THROTTLER_STATUS:
180                 *value = metrics->Current.ThrottlerStatus;
181                 break;
182         default:
183                 *value = UINT_MAX;
184                 break;
185         }
186
187         return ret;
188 }
189
190 static int cyan_skillfish_read_sensor(struct smu_context *smu,
191                                         enum amd_pp_sensors sensor,
192                                         void *data,
193                                         uint32_t *size)
194 {
195         int ret = 0;
196
197         if (!data || !size)
198                 return -EINVAL;
199
200         switch (sensor) {
201         case AMDGPU_PP_SENSOR_GFX_SCLK:
202                 ret = cyan_skillfish_get_smu_metrics_data(smu,
203                                                    METRICS_CURR_GFXCLK,
204                                                    (uint32_t *)data);
205                 *(uint32_t *)data *= 100;
206                 *size = 4;
207                 break;
208         case AMDGPU_PP_SENSOR_GFX_MCLK:
209                 ret = cyan_skillfish_get_smu_metrics_data(smu,
210                                                    METRICS_CURR_UCLK,
211                                                    (uint32_t *)data);
212                 *(uint32_t *)data *= 100;
213                 *size = 4;
214                 break;
215         case AMDGPU_PP_SENSOR_GPU_POWER:
216                 ret = cyan_skillfish_get_smu_metrics_data(smu,
217                                                    METRICS_AVERAGE_SOCKETPOWER,
218                                                    (uint32_t *)data);
219                 *size = 4;
220                 break;
221         case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
222                 ret = cyan_skillfish_get_smu_metrics_data(smu,
223                                                    METRICS_CURR_SOCKETPOWER,
224                                                    (uint32_t *)data);
225                 *size = 4;
226                 break;
227         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
228                 ret = cyan_skillfish_get_smu_metrics_data(smu,
229                                                    METRICS_TEMPERATURE_HOTSPOT,
230                                                    (uint32_t *)data);
231                 *size = 4;
232                 break;
233         case AMDGPU_PP_SENSOR_EDGE_TEMP:
234                 ret = cyan_skillfish_get_smu_metrics_data(smu,
235                                                    METRICS_TEMPERATURE_EDGE,
236                                                    (uint32_t *)data);
237                 *size = 4;
238                 break;
239         case AMDGPU_PP_SENSOR_VDDNB:
240                 ret = cyan_skillfish_get_smu_metrics_data(smu,
241                                                    METRICS_VOLTAGE_VDDSOC,
242                                                    (uint32_t *)data);
243                 *size = 4;
244                 break;
245         case AMDGPU_PP_SENSOR_VDDGFX:
246                 ret = cyan_skillfish_get_smu_metrics_data(smu,
247                                                    METRICS_VOLTAGE_VDDGFX,
248                                                    (uint32_t *)data);
249                 *size = 4;
250                 break;
251         default:
252                 ret = -EOPNOTSUPP;
253                 break;
254         }
255
256         return ret;
257 }
258
259 static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu,
260                                                 enum smu_clk_type clk_type,
261                                                 uint32_t *value)
262 {
263         MetricsMember_t member_type;
264
265         switch (clk_type) {
266         case SMU_GFXCLK:
267         case SMU_SCLK:
268                 member_type = METRICS_CURR_GFXCLK;
269                 break;
270         case SMU_FCLK:
271         case SMU_MCLK:
272                 member_type = METRICS_CURR_UCLK;
273                 break;
274         case SMU_SOCCLK:
275                 member_type = METRICS_CURR_SOCCLK;
276                 break;
277         case SMU_VCLK:
278                 member_type = METRICS_CURR_VCLK;
279                 break;
280         case SMU_DCLK:
281                 member_type = METRICS_CURR_DCLK;
282                 break;
283         default:
284                 return -EINVAL;
285         }
286
287         return cyan_skillfish_get_smu_metrics_data(smu, member_type, value);
288 }
289
290 static int cyan_skillfish_print_clk_levels(struct smu_context *smu,
291                                         enum smu_clk_type clk_type,
292                                         char *buf)
293 {
294         int ret = 0, size = 0;
295         uint32_t cur_value = 0;
296         int i;
297
298         smu_cmn_get_sysfs_buf(&buf, &size);
299
300         switch (clk_type) {
301         case SMU_OD_SCLK:
302                 ret  = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value);
303                 if (ret)
304                         return ret;
305                 size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK");
306                 size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value);
307                 break;
308         case SMU_OD_VDDC_CURVE:
309                 ret  = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value);
310                 if (ret)
311                         return ret;
312                 size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC");
313                 size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value);
314                 break;
315         case SMU_OD_RANGE:
316                 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
317                 size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
318                                                 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
319                 size += sysfs_emit_at(buf, size, "VDDC: %7umV  %10umV\n",
320                                                 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
321                 break;
322         case SMU_FCLK:
323         case SMU_MCLK:
324         case SMU_SOCCLK:
325         case SMU_VCLK:
326         case SMU_DCLK:
327                 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value);
328                 if (ret)
329                         return ret;
330                 size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value);
331                 break;
332         case SMU_SCLK:
333         case SMU_GFXCLK:
334                 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value);
335                 if (ret)
336                         return ret;
337                 if (cur_value  == CYAN_SKILLFISH_SCLK_MAX)
338                         i = 2;
339                 else if (cur_value == CYAN_SKILLFISH_SCLK_MIN)
340                         i = 0;
341                 else
342                         i = 1;
343                 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MIN,
344                                 i == 0 ? "*" : "");
345                 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
346                                 i == 1 ? cur_value : cyan_skillfish_sclk_default,
347                                 i == 1 ? "*" : "");
348                 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MAX,
349                                 i == 2 ? "*" : "");
350                 break;
351         default:
352                 dev_warn(smu->adev->dev, "Unsupported clock type\n");
353                 return ret;
354         }
355
356         return size;
357 }
358
359 static bool cyan_skillfish_is_dpm_running(struct smu_context *smu)
360 {
361         struct amdgpu_device *adev = smu->adev;
362         int ret = 0;
363         uint64_t feature_enabled;
364
365         /* we need to re-init after suspend so return false */
366         if (adev->in_suspend)
367                 return false;
368
369         ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
370         if (ret)
371                 return false;
372
373         /*
374          * cyan_skillfish specific, query default sclk inseted of hard code.
375          */
376         if (!cyan_skillfish_sclk_default)
377                 cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK,
378                         &cyan_skillfish_sclk_default);
379
380         return !!(feature_enabled & SMC_DPM_FEATURE);
381 }
382
383 static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu,
384                                                 void **table)
385 {
386         struct smu_table_context *smu_table = &smu->smu_table;
387         struct gpu_metrics_v2_2 *gpu_metrics =
388                 (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table;
389         SmuMetrics_t metrics;
390         int i, ret = 0;
391
392         ret = smu_cmn_get_metrics_table(smu, &metrics, true);
393         if (ret)
394                 return ret;
395
396         smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2);
397
398         gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
399         gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
400
401         gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
402         gpu_metrics->average_soc_power = metrics.Current.Power[0];
403         gpu_metrics->average_gfx_power = metrics.Current.Power[1];
404
405         gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
406         gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
407         gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
408         gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
409         gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
410         gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
411
412         gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
413         gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
414         gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
415         gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
416         gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
417         gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
418
419         for (i = 0; i < 6; i++) {
420                 gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i];
421                 gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i];
422                 gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i];
423         }
424
425         for (i = 0; i < 2; i++) {
426                 gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i];
427                 gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i];
428         }
429
430         gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
431         gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
432
433         *table = (void *)gpu_metrics;
434
435         return sizeof(struct gpu_metrics_v2_2);
436 }
437
438 static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu,
439                                         enum PP_OD_DPM_TABLE_COMMAND type,
440                                         long input[], uint32_t size)
441 {
442         int ret = 0;
443         uint32_t vid;
444
445         switch (type) {
446         case PP_OD_EDIT_VDDC_CURVE:
447                 if (size != 3 || input[0] != 0) {
448                         dev_err(smu->adev->dev, "Invalid parameter!\n");
449                         return -EINVAL;
450                 }
451
452                 if (input[1] < CYAN_SKILLFISH_SCLK_MIN ||
453                         input[1] > CYAN_SKILLFISH_SCLK_MAX) {
454                         dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n",
455                                         CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
456                         return -EINVAL;
457                 }
458
459                 if (input[2] < CYAN_SKILLFISH_VDDC_MIN ||
460                         input[2] > CYAN_SKILLFISH_VDDC_MAX) {
461                         dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n",
462                                         CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
463                         return -EINVAL;
464                 }
465
466                 cyan_skillfish_user_settings.sclk = input[1];
467                 cyan_skillfish_user_settings.vddc = input[2];
468
469                 break;
470         case PP_OD_RESTORE_DEFAULT_TABLE:
471                 if (size != 0) {
472                         dev_err(smu->adev->dev, "Invalid parameter!\n");
473                         return -EINVAL;
474                 }
475
476                 cyan_skillfish_user_settings.sclk = cyan_skillfish_sclk_default;
477                 cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC;
478
479                 break;
480         case PP_OD_COMMIT_DPM_TABLE:
481                 if (size != 0) {
482                         dev_err(smu->adev->dev, "Invalid parameter!\n");
483                         return -EINVAL;
484                 }
485
486                 if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN ||
487                     cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) {
488                         dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n",
489                                         CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
490                         return -EINVAL;
491                 }
492
493                 if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) &&
494                         (cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN ||
495                         cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) {
496                         dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n",
497                                         CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
498                         return -EINVAL;
499                 }
500
501                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk,
502                                         cyan_skillfish_user_settings.sclk, NULL);
503                 if (ret) {
504                         dev_err(smu->adev->dev, "Set sclk failed!\n");
505                         return ret;
506                 }
507
508                 if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) {
509                         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL);
510                         if (ret) {
511                                 dev_err(smu->adev->dev, "Unforce vddc failed!\n");
512                                 return ret;
513                         }
514                 } else {
515                         /*
516                          * PMFW accepts SVI2 VID code, convert voltage to VID:
517                          * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001)
518                          */
519                         vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000;
520                         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL);
521                         if (ret) {
522                                 dev_err(smu->adev->dev, "Force vddc failed!\n");
523                                 return ret;
524                         }
525                 }
526
527                 break;
528         default:
529                 return -EOPNOTSUPP;
530         }
531
532         return ret;
533 }
534
535 static int cyan_skillfish_get_dpm_ultimate_freq(struct smu_context *smu,
536                                                 enum smu_clk_type clk_type,
537                                                 uint32_t *min,
538                                                 uint32_t *max)
539 {
540         int ret = 0;
541         uint32_t low, high;
542
543         switch (clk_type) {
544         case SMU_GFXCLK:
545         case SMU_SCLK:
546                 low = CYAN_SKILLFISH_SCLK_MIN;
547                 high = CYAN_SKILLFISH_SCLK_MAX;
548                 break;
549         default:
550                 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &low);
551                 if (ret)
552                         return ret;
553                 high = low;
554                 break;
555         }
556
557         if (min)
558                 *min = low;
559         if (max)
560                 *max = high;
561
562         return 0;
563 }
564
565 static int cyan_skillfish_get_enabled_mask(struct smu_context *smu,
566                                            uint64_t *feature_mask)
567 {
568         if (!feature_mask)
569                 return -EINVAL;
570         memset(feature_mask, 0xff, sizeof(*feature_mask));
571
572         return 0;
573 }
574
575 static const struct pptable_funcs cyan_skillfish_ppt_funcs = {
576
577         .check_fw_status = smu_v11_0_check_fw_status,
578         .check_fw_version = smu_v11_0_check_fw_version,
579         .init_power = smu_v11_0_init_power,
580         .fini_power = smu_v11_0_fini_power,
581         .init_smc_tables = cyan_skillfish_init_smc_tables,
582         .fini_smc_tables = smu_v11_0_fini_smc_tables,
583         .read_sensor = cyan_skillfish_read_sensor,
584         .print_clk_levels = cyan_skillfish_print_clk_levels,
585         .get_enabled_mask = cyan_skillfish_get_enabled_mask,
586         .is_dpm_running = cyan_skillfish_is_dpm_running,
587         .get_gpu_metrics = cyan_skillfish_get_gpu_metrics,
588         .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table,
589         .get_dpm_ultimate_freq = cyan_skillfish_get_dpm_ultimate_freq,
590         .register_irq_handler = smu_v11_0_register_irq_handler,
591         .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
592         .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
593         .send_smc_msg = smu_cmn_send_smc_msg,
594         .set_driver_table_location = smu_v11_0_set_driver_table_location,
595         .interrupt_work = smu_v11_0_interrupt_work,
596 };
597
598 void cyan_skillfish_set_ppt_funcs(struct smu_context *smu)
599 {
600         smu->ppt_funcs = &cyan_skillfish_ppt_funcs;
601         smu->message_map = cyan_skillfish_message_map;
602         smu->table_map = cyan_skillfish_table_map;
603         smu->is_apu = true;
604         smu_v11_0_set_smu_mailbox_registers(smu);
605 }