LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/pm/swsmu/smu11 - cyan_skillfish_ppt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 234 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 12 0.0 %

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

Generated by: LCOV version 1.14