Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2021 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 
0024 #define SWSMU_CODE_LAYER_L2
0025 
0026 #include "amdgpu.h"
0027 #include "amdgpu_smu.h"
0028 #include "smu_v11_0.h"
0029 #include "smu11_driver_if_cyan_skillfish.h"
0030 #include "cyan_skillfish_ppt.h"
0031 #include "smu_v11_8_ppsmc.h"
0032 #include "smu_v11_8_pmfw.h"
0033 #include "smu_cmn.h"
0034 #include "soc15_common.h"
0035 
0036 /*
0037  * DO NOT use these for err/warn/info/debug messages.
0038  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
0039  * They are more MGPU friendly.
0040  */
0041 
0042 #undef pr_err
0043 #undef pr_warn
0044 #undef pr_info
0045 #undef pr_debug
0046 
0047 /* unit: MHz */
0048 #define CYAN_SKILLFISH_SCLK_MIN         1000
0049 #define CYAN_SKILLFISH_SCLK_MAX         2000
0050 
0051 /* unit: mV */
0052 #define CYAN_SKILLFISH_VDDC_MIN         700
0053 #define CYAN_SKILLFISH_VDDC_MAX         1129
0054 #define CYAN_SKILLFISH_VDDC_MAGIC           5118 // 0x13fe
0055 
0056 static struct gfx_user_settings {
0057     uint32_t sclk;
0058     uint32_t vddc;
0059 } cyan_skillfish_user_settings;
0060 
0061 static uint32_t cyan_skillfish_sclk_default;
0062 
0063 #define FEATURE_MASK(feature) (1ULL << feature)
0064 #define SMC_DPM_FEATURE ( \
0065     FEATURE_MASK(FEATURE_FCLK_DPM_BIT)  |   \
0066     FEATURE_MASK(FEATURE_SOC_DPM_BIT)   |   \
0067     FEATURE_MASK(FEATURE_GFX_DPM_BIT))
0068 
0069 static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = {
0070     MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,          0),
0071     MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,        0),
0072     MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,       0),
0073     MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverTableDramAddrHigh,   0),
0074     MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverTableDramAddrLow,    0),
0075     MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,    0),
0076     MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,    0),
0077     MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,    0),
0078     MSG_MAP(RequestGfxclk,                  PPSMC_MSG_RequestGfxclk,        0),
0079     MSG_MAP(ForceGfxVid,                    PPSMC_MSG_ForceGfxVid,          0),
0080     MSG_MAP(UnforceGfxVid,                  PPSMC_MSG_UnforceGfxVid,        0),
0081 };
0082 
0083 static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = {
0084     TAB_MAP_VALID(SMU_METRICS),
0085 };
0086 
0087 static int cyan_skillfish_tables_init(struct smu_context *smu)
0088 {
0089     struct smu_table_context *smu_table = &smu->smu_table;
0090     struct smu_table *tables = smu_table->tables;
0091 
0092     SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS,
0093                 sizeof(SmuMetrics_t),
0094                 PAGE_SIZE,
0095                 AMDGPU_GEM_DOMAIN_VRAM);
0096 
0097     smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
0098     if (!smu_table->metrics_table)
0099         goto err0_out;
0100 
0101     smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2);
0102     smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
0103     if (!smu_table->gpu_metrics_table)
0104         goto err1_out;
0105 
0106     smu_table->metrics_time = 0;
0107 
0108     return 0;
0109 
0110 err1_out:
0111     smu_table->gpu_metrics_table_size = 0;
0112     kfree(smu_table->metrics_table);
0113 err0_out:
0114     return -ENOMEM;
0115 }
0116 
0117 static int cyan_skillfish_init_smc_tables(struct smu_context *smu)
0118 {
0119     int ret = 0;
0120 
0121     ret = cyan_skillfish_tables_init(smu);
0122     if (ret)
0123         return ret;
0124 
0125     return smu_v11_0_init_smc_tables(smu);
0126 }
0127 
0128 static int
0129 cyan_skillfish_get_smu_metrics_data(struct smu_context *smu,
0130                     MetricsMember_t member,
0131                     uint32_t *value)
0132 {
0133     struct smu_table_context *smu_table = &smu->smu_table;
0134     SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
0135     int ret = 0;
0136 
0137     ret = smu_cmn_get_metrics_table(smu, NULL, false);
0138     if (ret)
0139         return ret;
0140 
0141     switch (member) {
0142     case METRICS_CURR_GFXCLK:
0143         *value = metrics->Current.GfxclkFrequency;
0144         break;
0145     case METRICS_CURR_SOCCLK:
0146         *value = metrics->Current.SocclkFrequency;
0147         break;
0148     case METRICS_CURR_VCLK:
0149         *value = metrics->Current.VclkFrequency;
0150         break;
0151     case METRICS_CURR_DCLK:
0152         *value = metrics->Current.DclkFrequency;
0153         break;
0154     case METRICS_CURR_UCLK:
0155         *value = metrics->Current.MemclkFrequency;
0156         break;
0157     case METRICS_AVERAGE_SOCKETPOWER:
0158         *value = (metrics->Current.CurrentSocketPower << 8) /
0159                 1000;
0160         break;
0161     case METRICS_TEMPERATURE_EDGE:
0162         *value = metrics->Current.GfxTemperature / 100 *
0163                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
0164         break;
0165     case METRICS_TEMPERATURE_HOTSPOT:
0166         *value = metrics->Current.SocTemperature / 100 *
0167                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
0168         break;
0169     case METRICS_VOLTAGE_VDDSOC:
0170         *value = metrics->Current.Voltage[0];
0171         break;
0172     case METRICS_VOLTAGE_VDDGFX:
0173         *value = metrics->Current.Voltage[1];
0174         break;
0175     case METRICS_THROTTLER_STATUS:
0176         *value = metrics->Current.ThrottlerStatus;
0177         break;
0178     default:
0179         *value = UINT_MAX;
0180         break;
0181     }
0182 
0183     return ret;
0184 }
0185 
0186 static int cyan_skillfish_read_sensor(struct smu_context *smu,
0187                     enum amd_pp_sensors sensor,
0188                     void *data,
0189                     uint32_t *size)
0190 {
0191     int ret = 0;
0192 
0193     if (!data || !size)
0194         return -EINVAL;
0195 
0196     switch (sensor) {
0197     case AMDGPU_PP_SENSOR_GFX_SCLK:
0198         ret = cyan_skillfish_get_smu_metrics_data(smu,
0199                            METRICS_CURR_GFXCLK,
0200                            (uint32_t *)data);
0201         *(uint32_t *)data *= 100;
0202         *size = 4;
0203         break;
0204     case AMDGPU_PP_SENSOR_GFX_MCLK:
0205         ret = cyan_skillfish_get_smu_metrics_data(smu,
0206                            METRICS_CURR_UCLK,
0207                            (uint32_t *)data);
0208         *(uint32_t *)data *= 100;
0209         *size = 4;
0210         break;
0211     case AMDGPU_PP_SENSOR_GPU_POWER:
0212         ret = cyan_skillfish_get_smu_metrics_data(smu,
0213                            METRICS_AVERAGE_SOCKETPOWER,
0214                            (uint32_t *)data);
0215         *size = 4;
0216         break;
0217     case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
0218         ret = cyan_skillfish_get_smu_metrics_data(smu,
0219                            METRICS_TEMPERATURE_HOTSPOT,
0220                            (uint32_t *)data);
0221         *size = 4;
0222         break;
0223     case AMDGPU_PP_SENSOR_EDGE_TEMP:
0224         ret = cyan_skillfish_get_smu_metrics_data(smu,
0225                            METRICS_TEMPERATURE_EDGE,
0226                            (uint32_t *)data);
0227         *size = 4;
0228         break;
0229     case AMDGPU_PP_SENSOR_VDDNB:
0230         ret = cyan_skillfish_get_smu_metrics_data(smu,
0231                            METRICS_VOLTAGE_VDDSOC,
0232                            (uint32_t *)data);
0233         *size = 4;
0234         break;
0235     case AMDGPU_PP_SENSOR_VDDGFX:
0236         ret = cyan_skillfish_get_smu_metrics_data(smu,
0237                            METRICS_VOLTAGE_VDDGFX,
0238                            (uint32_t *)data);
0239         *size = 4;
0240         break;
0241     default:
0242         ret = -EOPNOTSUPP;
0243         break;
0244     }
0245 
0246     return ret;
0247 }
0248 
0249 static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu,
0250                         enum smu_clk_type clk_type,
0251                         uint32_t *value)
0252 {
0253     MetricsMember_t member_type;
0254 
0255     switch (clk_type) {
0256     case SMU_GFXCLK:
0257     case SMU_SCLK:
0258         member_type = METRICS_CURR_GFXCLK;
0259         break;
0260     case SMU_FCLK:
0261     case SMU_MCLK:
0262         member_type = METRICS_CURR_UCLK;
0263         break;
0264     case SMU_SOCCLK:
0265         member_type = METRICS_CURR_SOCCLK;
0266         break;
0267     case SMU_VCLK:
0268         member_type = METRICS_CURR_VCLK;
0269         break;
0270     case SMU_DCLK:
0271         member_type = METRICS_CURR_DCLK;
0272         break;
0273     default:
0274         return -EINVAL;
0275     }
0276 
0277     return cyan_skillfish_get_smu_metrics_data(smu, member_type, value);
0278 }
0279 
0280 static int cyan_skillfish_print_clk_levels(struct smu_context *smu,
0281                     enum smu_clk_type clk_type,
0282                     char *buf)
0283 {
0284     int ret = 0, size = 0;
0285     uint32_t cur_value = 0;
0286     int i;
0287 
0288     smu_cmn_get_sysfs_buf(&buf, &size);
0289 
0290     switch (clk_type) {
0291     case SMU_OD_SCLK:
0292         ret  = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value);
0293         if (ret)
0294             return ret;
0295         size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK");
0296         size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value);
0297         break;
0298     case SMU_OD_VDDC_CURVE:
0299         ret  = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value);
0300         if (ret)
0301             return ret;
0302         size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC");
0303         size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value);
0304         break;
0305     case SMU_OD_RANGE:
0306         size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
0307         size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
0308                         CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
0309         size += sysfs_emit_at(buf, size, "VDDC: %7umV  %10umV\n",
0310                         CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
0311         break;
0312     case SMU_FCLK:
0313     case SMU_MCLK:
0314     case SMU_SOCCLK:
0315     case SMU_VCLK:
0316     case SMU_DCLK:
0317         ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value);
0318         if (ret)
0319             return ret;
0320         size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value);
0321         break;
0322     case SMU_SCLK:
0323     case SMU_GFXCLK:
0324         ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value);
0325         if (ret)
0326             return ret;
0327         if (cur_value  == CYAN_SKILLFISH_SCLK_MAX)
0328             i = 2;
0329         else if (cur_value == CYAN_SKILLFISH_SCLK_MIN)
0330             i = 0;
0331         else
0332             i = 1;
0333         size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MIN,
0334                 i == 0 ? "*" : "");
0335         size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
0336                 i == 1 ? cur_value : cyan_skillfish_sclk_default,
0337                 i == 1 ? "*" : "");
0338         size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MAX,
0339                 i == 2 ? "*" : "");
0340         break;
0341     default:
0342         dev_warn(smu->adev->dev, "Unsupported clock type\n");
0343         return ret;
0344     }
0345 
0346     return size;
0347 }
0348 
0349 static bool cyan_skillfish_is_dpm_running(struct smu_context *smu)
0350 {
0351     struct amdgpu_device *adev = smu->adev;
0352     int ret = 0;
0353     uint64_t feature_enabled;
0354 
0355     /* we need to re-init after suspend so return false */
0356     if (adev->in_suspend)
0357         return false;
0358 
0359     ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
0360     if (ret)
0361         return false;
0362 
0363     /*
0364      * cyan_skillfish specific, query default sclk inseted of hard code.
0365      */
0366     if (!cyan_skillfish_sclk_default)
0367         cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK,
0368             &cyan_skillfish_sclk_default);
0369 
0370     return !!(feature_enabled & SMC_DPM_FEATURE);
0371 }
0372 
0373 static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu,
0374                         void **table)
0375 {
0376     struct smu_table_context *smu_table = &smu->smu_table;
0377     struct gpu_metrics_v2_2 *gpu_metrics =
0378         (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table;
0379     SmuMetrics_t metrics;
0380     int i, ret = 0;
0381 
0382     ret = smu_cmn_get_metrics_table(smu, &metrics, true);
0383     if (ret)
0384         return ret;
0385 
0386     smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2);
0387 
0388     gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
0389     gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
0390 
0391     gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
0392     gpu_metrics->average_soc_power = metrics.Current.Power[0];
0393     gpu_metrics->average_gfx_power = metrics.Current.Power[1];
0394 
0395     gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
0396     gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
0397     gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
0398     gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
0399     gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
0400     gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
0401 
0402     gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
0403     gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
0404     gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
0405     gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
0406     gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
0407     gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
0408 
0409     for (i = 0; i < 6; i++) {
0410         gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i];
0411         gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i];
0412         gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i];
0413     }
0414 
0415     for (i = 0; i < 2; i++) {
0416         gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i];
0417         gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i];
0418     }
0419 
0420     gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
0421     gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
0422 
0423     *table = (void *)gpu_metrics;
0424 
0425     return sizeof(struct gpu_metrics_v2_2);
0426 }
0427 
0428 static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu,
0429                     enum PP_OD_DPM_TABLE_COMMAND type,
0430                     long input[], uint32_t size)
0431 {
0432     int ret = 0;
0433     uint32_t vid;
0434 
0435     switch (type) {
0436     case PP_OD_EDIT_VDDC_CURVE:
0437         if (size != 3 || input[0] != 0) {
0438             dev_err(smu->adev->dev, "Invalid parameter!\n");
0439             return -EINVAL;
0440         }
0441 
0442         if (input[1] < CYAN_SKILLFISH_SCLK_MIN ||
0443             input[1] > CYAN_SKILLFISH_SCLK_MAX) {
0444             dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n",
0445                     CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
0446             return -EINVAL;
0447         }
0448 
0449         if (input[2] < CYAN_SKILLFISH_VDDC_MIN ||
0450             input[2] > CYAN_SKILLFISH_VDDC_MAX) {
0451             dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n",
0452                     CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
0453             return -EINVAL;
0454         }
0455 
0456         cyan_skillfish_user_settings.sclk = input[1];
0457         cyan_skillfish_user_settings.vddc = input[2];
0458 
0459         break;
0460     case PP_OD_RESTORE_DEFAULT_TABLE:
0461         if (size != 0) {
0462             dev_err(smu->adev->dev, "Invalid parameter!\n");
0463             return -EINVAL;
0464         }
0465 
0466         cyan_skillfish_user_settings.sclk = cyan_skillfish_sclk_default;
0467         cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC;
0468 
0469         break;
0470     case PP_OD_COMMIT_DPM_TABLE:
0471         if (size != 0) {
0472             dev_err(smu->adev->dev, "Invalid parameter!\n");
0473             return -EINVAL;
0474         }
0475 
0476         if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN ||
0477             cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) {
0478             dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n",
0479                     CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
0480             return -EINVAL;
0481         }
0482 
0483         if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) &&
0484             (cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN ||
0485             cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) {
0486             dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n",
0487                     CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
0488             return -EINVAL;
0489         }
0490 
0491         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk,
0492                     cyan_skillfish_user_settings.sclk, NULL);
0493         if (ret) {
0494             dev_err(smu->adev->dev, "Set sclk failed!\n");
0495             return ret;
0496         }
0497 
0498         if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) {
0499             ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL);
0500             if (ret) {
0501                 dev_err(smu->adev->dev, "Unforce vddc failed!\n");
0502                 return ret;
0503             }
0504         } else {
0505             /*
0506              * PMFW accepts SVI2 VID code, convert voltage to VID:
0507              * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001)
0508              */
0509             vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000;
0510             ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL);
0511             if (ret) {
0512                 dev_err(smu->adev->dev, "Force vddc failed!\n");
0513                 return ret;
0514             }
0515         }
0516 
0517         break;
0518     default:
0519         return -EOPNOTSUPP;
0520     }
0521 
0522     return ret;
0523 }
0524 
0525 static int cyan_skillfish_get_dpm_ultimate_freq(struct smu_context *smu,
0526                         enum smu_clk_type clk_type,
0527                         uint32_t *min,
0528                         uint32_t *max)
0529 {
0530     int ret = 0;
0531     uint32_t low, high;
0532 
0533     switch (clk_type) {
0534     case SMU_GFXCLK:
0535     case SMU_SCLK:
0536         low = CYAN_SKILLFISH_SCLK_MIN;
0537         high = CYAN_SKILLFISH_SCLK_MAX;
0538         break;
0539     default:
0540         ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &low);
0541         if (ret)
0542             return ret;
0543         high = low;
0544         break;
0545     }
0546 
0547     if (min)
0548         *min = low;
0549     if (max)
0550         *max = high;
0551 
0552     return 0;
0553 }
0554 
0555 static int cyan_skillfish_get_enabled_mask(struct smu_context *smu,
0556                        uint64_t *feature_mask)
0557 {
0558     if (!feature_mask)
0559         return -EINVAL;
0560     memset(feature_mask, 0xff, sizeof(*feature_mask));
0561 
0562     return 0;
0563 }
0564 
0565 static const struct pptable_funcs cyan_skillfish_ppt_funcs = {
0566 
0567     .check_fw_status = smu_v11_0_check_fw_status,
0568     .check_fw_version = smu_v11_0_check_fw_version,
0569     .init_power = smu_v11_0_init_power,
0570     .fini_power = smu_v11_0_fini_power,
0571     .init_smc_tables = cyan_skillfish_init_smc_tables,
0572     .fini_smc_tables = smu_v11_0_fini_smc_tables,
0573     .read_sensor = cyan_skillfish_read_sensor,
0574     .print_clk_levels = cyan_skillfish_print_clk_levels,
0575     .get_enabled_mask = cyan_skillfish_get_enabled_mask,
0576     .is_dpm_running = cyan_skillfish_is_dpm_running,
0577     .get_gpu_metrics = cyan_skillfish_get_gpu_metrics,
0578     .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table,
0579     .get_dpm_ultimate_freq = cyan_skillfish_get_dpm_ultimate_freq,
0580     .register_irq_handler = smu_v11_0_register_irq_handler,
0581     .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
0582     .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
0583     .send_smc_msg = smu_cmn_send_smc_msg,
0584     .set_driver_table_location = smu_v11_0_set_driver_table_location,
0585     .interrupt_work = smu_v11_0_interrupt_work,
0586 };
0587 
0588 void cyan_skillfish_set_ppt_funcs(struct smu_context *smu)
0589 {
0590     smu->ppt_funcs = &cyan_skillfish_ppt_funcs;
0591     smu->message_map = cyan_skillfish_message_map;
0592     smu->table_map = cyan_skillfish_table_map;
0593     smu->is_apu = true;
0594     smu_v11_0_set_smu_mailbox_registers(smu);
0595 }