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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2019 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 <linux/firmware.h>
      27             : #include "amdgpu.h"
      28             : #include "amdgpu_dpm.h"
      29             : #include "amdgpu_smu.h"
      30             : #include "atomfirmware.h"
      31             : #include "amdgpu_atomfirmware.h"
      32             : #include "amdgpu_atombios.h"
      33             : #include "smu_v11_0.h"
      34             : #include "smu11_driver_if_arcturus.h"
      35             : #include "soc15_common.h"
      36             : #include "atom.h"
      37             : #include "arcturus_ppt.h"
      38             : #include "smu_v11_0_pptable.h"
      39             : #include "arcturus_ppsmc.h"
      40             : #include "nbio/nbio_7_4_offset.h"
      41             : #include "nbio/nbio_7_4_sh_mask.h"
      42             : #include "thm/thm_11_0_2_offset.h"
      43             : #include "thm/thm_11_0_2_sh_mask.h"
      44             : #include "amdgpu_xgmi.h"
      45             : #include <linux/i2c.h>
      46             : #include <linux/pci.h>
      47             : #include "amdgpu_ras.h"
      48             : #include "smu_cmn.h"
      49             : 
      50             : /*
      51             :  * DO NOT use these for err/warn/info/debug messages.
      52             :  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
      53             :  * They are more MGPU friendly.
      54             :  */
      55             : #undef pr_err
      56             : #undef pr_warn
      57             : #undef pr_info
      58             : #undef pr_debug
      59             : 
      60             : #define ARCTURUS_FEA_MAP(smu_feature, arcturus_feature) \
      61             :         [smu_feature] = {1, (arcturus_feature)}
      62             : 
      63             : #define SMU_FEATURES_LOW_MASK        0x00000000FFFFFFFF
      64             : #define SMU_FEATURES_LOW_SHIFT       0
      65             : #define SMU_FEATURES_HIGH_MASK       0xFFFFFFFF00000000
      66             : #define SMU_FEATURES_HIGH_SHIFT      32
      67             : 
      68             : #define SMC_DPM_FEATURE ( \
      69             :         FEATURE_DPM_PREFETCHER_MASK | \
      70             :         FEATURE_DPM_GFXCLK_MASK | \
      71             :         FEATURE_DPM_UCLK_MASK | \
      72             :         FEATURE_DPM_SOCCLK_MASK | \
      73             :         FEATURE_DPM_MP0CLK_MASK | \
      74             :         FEATURE_DPM_FCLK_MASK | \
      75             :         FEATURE_DPM_XGMI_MASK)
      76             : 
      77             : /* possible frequency drift (1Mhz) */
      78             : #define EPSILON                         1
      79             : 
      80             : #define smnPCIE_ESM_CTRL                        0x111003D0
      81             : 
      82             : #define mmCG_FDO_CTRL0_ARCT                     0x8B
      83             : #define mmCG_FDO_CTRL0_ARCT_BASE_IDX            0
      84             : 
      85             : #define mmCG_FDO_CTRL1_ARCT                     0x8C
      86             : #define mmCG_FDO_CTRL1_ARCT_BASE_IDX            0
      87             : 
      88             : #define mmCG_FDO_CTRL2_ARCT                     0x8D
      89             : #define mmCG_FDO_CTRL2_ARCT_BASE_IDX            0
      90             : 
      91             : #define mmCG_TACH_CTRL_ARCT                     0x8E
      92             : #define mmCG_TACH_CTRL_ARCT_BASE_IDX            0
      93             : 
      94             : #define mmCG_TACH_STATUS_ARCT                   0x8F
      95             : #define mmCG_TACH_STATUS_ARCT_BASE_IDX          0
      96             : 
      97             : #define mmCG_THERMAL_STATUS_ARCT                0x90
      98             : #define mmCG_THERMAL_STATUS_ARCT_BASE_IDX       0
      99             : 
     100             : static const struct cmn2asic_msg_mapping arcturus_message_map[SMU_MSG_MAX_COUNT] = {
     101             :         MSG_MAP(TestMessage,                         PPSMC_MSG_TestMessage,                     0),
     102             :         MSG_MAP(GetSmuVersion,                       PPSMC_MSG_GetSmuVersion,                   1),
     103             :         MSG_MAP(GetDriverIfVersion,                  PPSMC_MSG_GetDriverIfVersion,              1),
     104             :         MSG_MAP(SetAllowedFeaturesMaskLow,           PPSMC_MSG_SetAllowedFeaturesMaskLow,       0),
     105             :         MSG_MAP(SetAllowedFeaturesMaskHigh,          PPSMC_MSG_SetAllowedFeaturesMaskHigh,      0),
     106             :         MSG_MAP(EnableAllSmuFeatures,                PPSMC_MSG_EnableAllSmuFeatures,            0),
     107             :         MSG_MAP(DisableAllSmuFeatures,               PPSMC_MSG_DisableAllSmuFeatures,           0),
     108             :         MSG_MAP(EnableSmuFeaturesLow,                PPSMC_MSG_EnableSmuFeaturesLow,            1),
     109             :         MSG_MAP(EnableSmuFeaturesHigh,               PPSMC_MSG_EnableSmuFeaturesHigh,           1),
     110             :         MSG_MAP(DisableSmuFeaturesLow,               PPSMC_MSG_DisableSmuFeaturesLow,           0),
     111             :         MSG_MAP(DisableSmuFeaturesHigh,              PPSMC_MSG_DisableSmuFeaturesHigh,          0),
     112             :         MSG_MAP(GetEnabledSmuFeaturesLow,            PPSMC_MSG_GetEnabledSmuFeaturesLow,        0),
     113             :         MSG_MAP(GetEnabledSmuFeaturesHigh,           PPSMC_MSG_GetEnabledSmuFeaturesHigh,       0),
     114             :         MSG_MAP(SetDriverDramAddrHigh,               PPSMC_MSG_SetDriverDramAddrHigh,           1),
     115             :         MSG_MAP(SetDriverDramAddrLow,                PPSMC_MSG_SetDriverDramAddrLow,            1),
     116             :         MSG_MAP(SetToolsDramAddrHigh,                PPSMC_MSG_SetToolsDramAddrHigh,            0),
     117             :         MSG_MAP(SetToolsDramAddrLow,                 PPSMC_MSG_SetToolsDramAddrLow,             0),
     118             :         MSG_MAP(TransferTableSmu2Dram,               PPSMC_MSG_TransferTableSmu2Dram,           1),
     119             :         MSG_MAP(TransferTableDram2Smu,               PPSMC_MSG_TransferTableDram2Smu,           0),
     120             :         MSG_MAP(UseDefaultPPTable,                   PPSMC_MSG_UseDefaultPPTable,               0),
     121             :         MSG_MAP(UseBackupPPTable,                    PPSMC_MSG_UseBackupPPTable,                0),
     122             :         MSG_MAP(SetSystemVirtualDramAddrHigh,        PPSMC_MSG_SetSystemVirtualDramAddrHigh,    0),
     123             :         MSG_MAP(SetSystemVirtualDramAddrLow,         PPSMC_MSG_SetSystemVirtualDramAddrLow,     0),
     124             :         MSG_MAP(EnterBaco,                           PPSMC_MSG_EnterBaco,                       0),
     125             :         MSG_MAP(ExitBaco,                            PPSMC_MSG_ExitBaco,                        0),
     126             :         MSG_MAP(ArmD3,                               PPSMC_MSG_ArmD3,                           0),
     127             :         MSG_MAP(SetSoftMinByFreq,                    PPSMC_MSG_SetSoftMinByFreq,                0),
     128             :         MSG_MAP(SetSoftMaxByFreq,                    PPSMC_MSG_SetSoftMaxByFreq,                0),
     129             :         MSG_MAP(SetHardMinByFreq,                    PPSMC_MSG_SetHardMinByFreq,                0),
     130             :         MSG_MAP(SetHardMaxByFreq,                    PPSMC_MSG_SetHardMaxByFreq,                0),
     131             :         MSG_MAP(GetMinDpmFreq,                       PPSMC_MSG_GetMinDpmFreq,                   0),
     132             :         MSG_MAP(GetMaxDpmFreq,                       PPSMC_MSG_GetMaxDpmFreq,                   0),
     133             :         MSG_MAP(GetDpmFreqByIndex,                   PPSMC_MSG_GetDpmFreqByIndex,               1),
     134             :         MSG_MAP(SetWorkloadMask,                     PPSMC_MSG_SetWorkloadMask,                 1),
     135             :         MSG_MAP(SetDfSwitchType,                     PPSMC_MSG_SetDfSwitchType,                 0),
     136             :         MSG_MAP(GetVoltageByDpm,                     PPSMC_MSG_GetVoltageByDpm,                 0),
     137             :         MSG_MAP(GetVoltageByDpmOverdrive,            PPSMC_MSG_GetVoltageByDpmOverdrive,        0),
     138             :         MSG_MAP(SetPptLimit,                         PPSMC_MSG_SetPptLimit,                     0),
     139             :         MSG_MAP(GetPptLimit,                         PPSMC_MSG_GetPptLimit,                     1),
     140             :         MSG_MAP(PowerUpVcn0,                         PPSMC_MSG_PowerUpVcn0,                     0),
     141             :         MSG_MAP(PowerDownVcn0,                       PPSMC_MSG_PowerDownVcn0,                   0),
     142             :         MSG_MAP(PowerUpVcn1,                         PPSMC_MSG_PowerUpVcn1,                     0),
     143             :         MSG_MAP(PowerDownVcn1,                       PPSMC_MSG_PowerDownVcn1,                   0),
     144             :         MSG_MAP(PrepareMp1ForUnload,                 PPSMC_MSG_PrepareMp1ForUnload,             0),
     145             :         MSG_MAP(PrepareMp1ForReset,                  PPSMC_MSG_PrepareMp1ForReset,              0),
     146             :         MSG_MAP(PrepareMp1ForShutdown,               PPSMC_MSG_PrepareMp1ForShutdown,           0),
     147             :         MSG_MAP(SoftReset,                           PPSMC_MSG_SoftReset,                       0),
     148             :         MSG_MAP(RunAfllBtc,                          PPSMC_MSG_RunAfllBtc,                      0),
     149             :         MSG_MAP(RunDcBtc,                            PPSMC_MSG_RunDcBtc,                        0),
     150             :         MSG_MAP(DramLogSetDramAddrHigh,              PPSMC_MSG_DramLogSetDramAddrHigh,          0),
     151             :         MSG_MAP(DramLogSetDramAddrLow,               PPSMC_MSG_DramLogSetDramAddrLow,           0),
     152             :         MSG_MAP(DramLogSetDramSize,                  PPSMC_MSG_DramLogSetDramSize,              0),
     153             :         MSG_MAP(GetDebugData,                        PPSMC_MSG_GetDebugData,                    0),
     154             :         MSG_MAP(WaflTest,                            PPSMC_MSG_WaflTest,                        0),
     155             :         MSG_MAP(SetXgmiMode,                         PPSMC_MSG_SetXgmiMode,                     0),
     156             :         MSG_MAP(SetMemoryChannelEnable,              PPSMC_MSG_SetMemoryChannelEnable,          0),
     157             :         MSG_MAP(DFCstateControl,                     PPSMC_MSG_DFCstateControl,                 0),
     158             :         MSG_MAP(GmiPwrDnControl,                     PPSMC_MSG_GmiPwrDnControl,                 0),
     159             :         MSG_MAP(ReadSerialNumTop32,                  PPSMC_MSG_ReadSerialNumTop32,              1),
     160             :         MSG_MAP(ReadSerialNumBottom32,               PPSMC_MSG_ReadSerialNumBottom32,           1),
     161             :         MSG_MAP(LightSBR,                            PPSMC_MSG_LightSBR,                        0),
     162             : };
     163             : 
     164             : static const struct cmn2asic_mapping arcturus_clk_map[SMU_CLK_COUNT] = {
     165             :         CLK_MAP(GFXCLK, PPCLK_GFXCLK),
     166             :         CLK_MAP(SCLK,   PPCLK_GFXCLK),
     167             :         CLK_MAP(SOCCLK, PPCLK_SOCCLK),
     168             :         CLK_MAP(FCLK, PPCLK_FCLK),
     169             :         CLK_MAP(UCLK, PPCLK_UCLK),
     170             :         CLK_MAP(MCLK, PPCLK_UCLK),
     171             :         CLK_MAP(DCLK, PPCLK_DCLK),
     172             :         CLK_MAP(VCLK, PPCLK_VCLK),
     173             : };
     174             : 
     175             : static const struct cmn2asic_mapping arcturus_feature_mask_map[SMU_FEATURE_COUNT] = {
     176             :         FEA_MAP(DPM_PREFETCHER),
     177             :         FEA_MAP(DPM_GFXCLK),
     178             :         FEA_MAP(DPM_UCLK),
     179             :         FEA_MAP(DPM_SOCCLK),
     180             :         FEA_MAP(DPM_FCLK),
     181             :         FEA_MAP(DPM_MP0CLK),
     182             :         FEA_MAP(DPM_XGMI),
     183             :         FEA_MAP(DS_GFXCLK),
     184             :         FEA_MAP(DS_SOCCLK),
     185             :         FEA_MAP(DS_LCLK),
     186             :         FEA_MAP(DS_FCLK),
     187             :         FEA_MAP(DS_UCLK),
     188             :         FEA_MAP(GFX_ULV),
     189             :         ARCTURUS_FEA_MAP(SMU_FEATURE_VCN_DPM_BIT, FEATURE_DPM_VCN_BIT),
     190             :         FEA_MAP(RSMU_SMN_CG),
     191             :         FEA_MAP(WAFL_CG),
     192             :         FEA_MAP(PPT),
     193             :         FEA_MAP(TDC),
     194             :         FEA_MAP(APCC_PLUS),
     195             :         FEA_MAP(VR0HOT),
     196             :         FEA_MAP(VR1HOT),
     197             :         FEA_MAP(FW_CTF),
     198             :         FEA_MAP(FAN_CONTROL),
     199             :         FEA_MAP(THERMAL),
     200             :         FEA_MAP(OUT_OF_BAND_MONITOR),
     201             :         FEA_MAP(TEMP_DEPENDENT_VMIN),
     202             : };
     203             : 
     204             : static const struct cmn2asic_mapping arcturus_table_map[SMU_TABLE_COUNT] = {
     205             :         TAB_MAP(PPTABLE),
     206             :         TAB_MAP(AVFS),
     207             :         TAB_MAP(AVFS_PSM_DEBUG),
     208             :         TAB_MAP(AVFS_FUSE_OVERRIDE),
     209             :         TAB_MAP(PMSTATUSLOG),
     210             :         TAB_MAP(SMU_METRICS),
     211             :         TAB_MAP(DRIVER_SMU_CONFIG),
     212             :         TAB_MAP(OVERDRIVE),
     213             :         TAB_MAP(I2C_COMMANDS),
     214             :         TAB_MAP(ACTIVITY_MONITOR_COEFF),
     215             : };
     216             : 
     217             : static const struct cmn2asic_mapping arcturus_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
     218             :         PWR_MAP(AC),
     219             :         PWR_MAP(DC),
     220             : };
     221             : 
     222             : static const struct cmn2asic_mapping arcturus_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
     223             :         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,       WORKLOAD_PPLIB_DEFAULT_BIT),
     224             :         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,          WORKLOAD_PPLIB_POWER_SAVING_BIT),
     225             :         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
     226             :         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_COMPUTE_BIT),
     227             :         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
     228             : };
     229             : 
     230             : static const uint8_t arcturus_throttler_map[] = {
     231             :         [THROTTLER_TEMP_EDGE_BIT]       = (SMU_THROTTLER_TEMP_EDGE_BIT),
     232             :         [THROTTLER_TEMP_HOTSPOT_BIT]    = (SMU_THROTTLER_TEMP_HOTSPOT_BIT),
     233             :         [THROTTLER_TEMP_MEM_BIT]        = (SMU_THROTTLER_TEMP_MEM_BIT),
     234             :         [THROTTLER_TEMP_VR_GFX_BIT]     = (SMU_THROTTLER_TEMP_VR_GFX_BIT),
     235             :         [THROTTLER_TEMP_VR_MEM_BIT]     = (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
     236             :         [THROTTLER_TEMP_VR_SOC_BIT]     = (SMU_THROTTLER_TEMP_VR_SOC_BIT),
     237             :         [THROTTLER_TDC_GFX_BIT]         = (SMU_THROTTLER_TDC_GFX_BIT),
     238             :         [THROTTLER_TDC_SOC_BIT]         = (SMU_THROTTLER_TDC_SOC_BIT),
     239             :         [THROTTLER_PPT0_BIT]            = (SMU_THROTTLER_PPT0_BIT),
     240             :         [THROTTLER_PPT1_BIT]            = (SMU_THROTTLER_PPT1_BIT),
     241             :         [THROTTLER_PPT2_BIT]            = (SMU_THROTTLER_PPT2_BIT),
     242             :         [THROTTLER_PPT3_BIT]            = (SMU_THROTTLER_PPT3_BIT),
     243             :         [THROTTLER_PPM_BIT]             = (SMU_THROTTLER_PPM_BIT),
     244             :         [THROTTLER_FIT_BIT]             = (SMU_THROTTLER_FIT_BIT),
     245             :         [THROTTLER_APCC_BIT]            = (SMU_THROTTLER_APCC_BIT),
     246             :         [THROTTLER_VRHOT0_BIT]          = (SMU_THROTTLER_VRHOT0_BIT),
     247             :         [THROTTLER_VRHOT1_BIT]          = (SMU_THROTTLER_VRHOT1_BIT),
     248             : };
     249             : 
     250           0 : static int arcturus_tables_init(struct smu_context *smu)
     251             : {
     252           0 :         struct smu_table_context *smu_table = &smu->smu_table;
     253           0 :         struct smu_table *tables = smu_table->tables;
     254             : 
     255           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
     256             :                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     257             : 
     258           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
     259             :                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     260             : 
     261           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
     262             :                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     263             : 
     264           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
     265             :                                PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     266             : 
     267           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
     268             :                        sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
     269             :                        AMDGPU_GEM_DOMAIN_VRAM);
     270             : 
     271           0 :         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
     272           0 :         if (!smu_table->metrics_table)
     273             :                 return -ENOMEM;
     274           0 :         smu_table->metrics_time = 0;
     275             : 
     276           0 :         smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
     277           0 :         smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
     278           0 :         if (!smu_table->gpu_metrics_table) {
     279           0 :                 kfree(smu_table->metrics_table);
     280           0 :                 return -ENOMEM;
     281             :         }
     282             : 
     283             :         return 0;
     284             : }
     285             : 
     286             : static int arcturus_allocate_dpm_context(struct smu_context *smu)
     287             : {
     288           0 :         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
     289             : 
     290           0 :         smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
     291             :                                        GFP_KERNEL);
     292           0 :         if (!smu_dpm->dpm_context)
     293             :                 return -ENOMEM;
     294           0 :         smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
     295             : 
     296             :         return 0;
     297             : }
     298             : 
     299           0 : static int arcturus_init_smc_tables(struct smu_context *smu)
     300             : {
     301           0 :         int ret = 0;
     302             : 
     303           0 :         ret = arcturus_tables_init(smu);
     304           0 :         if (ret)
     305             :                 return ret;
     306             : 
     307           0 :         ret = arcturus_allocate_dpm_context(smu);
     308           0 :         if (ret)
     309             :                 return ret;
     310             : 
     311           0 :         return smu_v11_0_init_smc_tables(smu);
     312             : }
     313             : 
     314             : static int
     315           0 : arcturus_get_allowed_feature_mask(struct smu_context *smu,
     316             :                                   uint32_t *feature_mask, uint32_t num)
     317             : {
     318           0 :         if (num > 2)
     319             :                 return -EINVAL;
     320             : 
     321             :         /* pptable will handle the features to enable */
     322           0 :         memset(feature_mask, 0xFF, sizeof(uint32_t) * num);
     323             : 
     324           0 :         return 0;
     325             : }
     326             : 
     327           0 : static int arcturus_set_default_dpm_table(struct smu_context *smu)
     328             : {
     329           0 :         struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
     330           0 :         PPTable_t *driver_ppt = smu->smu_table.driver_pptable;
     331           0 :         struct smu_11_0_dpm_table *dpm_table = NULL;
     332           0 :         int ret = 0;
     333             : 
     334             :         /* socclk dpm table setup */
     335           0 :         dpm_table = &dpm_context->dpm_tables.soc_table;
     336           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
     337           0 :                 ret = smu_v11_0_set_single_dpm_table(smu,
     338             :                                                      SMU_SOCCLK,
     339             :                                                      dpm_table);
     340           0 :                 if (ret)
     341             :                         return ret;
     342           0 :                 dpm_table->is_fine_grained =
     343           0 :                         !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete;
     344             :         } else {
     345           0 :                 dpm_table->count = 1;
     346           0 :                 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
     347           0 :                 dpm_table->dpm_levels[0].enabled = true;
     348           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     349           0 :                 dpm_table->max = dpm_table->dpm_levels[0].value;
     350             :         }
     351             : 
     352             :         /* gfxclk dpm table setup */
     353           0 :         dpm_table = &dpm_context->dpm_tables.gfx_table;
     354           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
     355           0 :                 ret = smu_v11_0_set_single_dpm_table(smu,
     356             :                                                      SMU_GFXCLK,
     357             :                                                      dpm_table);
     358           0 :                 if (ret)
     359             :                         return ret;
     360           0 :                 dpm_table->is_fine_grained =
     361           0 :                         !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete;
     362             :         } else {
     363           0 :                 dpm_table->count = 1;
     364           0 :                 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
     365           0 :                 dpm_table->dpm_levels[0].enabled = true;
     366           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     367           0 :                 dpm_table->max = dpm_table->dpm_levels[0].value;
     368             :         }
     369             : 
     370             :         /* memclk dpm table setup */
     371           0 :         dpm_table = &dpm_context->dpm_tables.uclk_table;
     372           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
     373           0 :                 ret = smu_v11_0_set_single_dpm_table(smu,
     374             :                                                      SMU_UCLK,
     375             :                                                      dpm_table);
     376           0 :                 if (ret)
     377             :                         return ret;
     378           0 :                 dpm_table->is_fine_grained =
     379           0 :                         !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete;
     380             :         } else {
     381           0 :                 dpm_table->count = 1;
     382           0 :                 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
     383           0 :                 dpm_table->dpm_levels[0].enabled = true;
     384           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     385           0 :                 dpm_table->max = dpm_table->dpm_levels[0].value;
     386             :         }
     387             : 
     388             :         /* fclk dpm table setup */
     389           0 :         dpm_table = &dpm_context->dpm_tables.fclk_table;
     390           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
     391           0 :                 ret = smu_v11_0_set_single_dpm_table(smu,
     392             :                                                      SMU_FCLK,
     393             :                                                      dpm_table);
     394           0 :                 if (ret)
     395             :                         return ret;
     396           0 :                 dpm_table->is_fine_grained =
     397           0 :                         !driver_ppt->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete;
     398             :         } else {
     399           0 :                 dpm_table->count = 1;
     400           0 :                 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100;
     401           0 :                 dpm_table->dpm_levels[0].enabled = true;
     402           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     403           0 :                 dpm_table->max = dpm_table->dpm_levels[0].value;
     404             :         }
     405             : 
     406             :         return 0;
     407             : }
     408             : 
     409           0 : static void arcturus_check_bxco_support(struct smu_context *smu)
     410             : {
     411           0 :         struct smu_table_context *table_context = &smu->smu_table;
     412           0 :         struct smu_11_0_powerplay_table *powerplay_table =
     413             :                 table_context->power_play_table;
     414           0 :         struct smu_baco_context *smu_baco = &smu->smu_baco;
     415           0 :         struct amdgpu_device *adev = smu->adev;
     416             :         uint32_t val;
     417             : 
     418           0 :         if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO ||
     419           0 :             powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) {
     420           0 :                 val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
     421           0 :                 smu_baco->platform_support =
     422           0 :                         (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true :
     423             :                                                                         false;
     424             :         }
     425           0 : }
     426             : 
     427           0 : static void arcturus_check_fan_support(struct smu_context *smu)
     428             : {
     429           0 :         struct smu_table_context *table_context = &smu->smu_table;
     430           0 :         PPTable_t *pptable = table_context->driver_pptable;
     431             : 
     432             :         /* No sort of fan control possible if PPTable has it disabled */
     433           0 :         smu->adev->pm.no_fan =
     434           0 :                 !(pptable->FeaturesToRun[0] & FEATURE_FAN_CONTROL_MASK);
     435           0 :         if (smu->adev->pm.no_fan)
     436           0 :                 dev_info_once(smu->adev->dev,
     437             :                               "PMFW based fan control disabled");
     438           0 : }
     439             : 
     440             : static int arcturus_check_powerplay_table(struct smu_context *smu)
     441             : {
     442           0 :         struct smu_table_context *table_context = &smu->smu_table;
     443           0 :         struct smu_11_0_powerplay_table *powerplay_table =
     444             :                 table_context->power_play_table;
     445             : 
     446           0 :         arcturus_check_bxco_support(smu);
     447           0 :         arcturus_check_fan_support(smu);
     448             : 
     449           0 :         table_context->thermal_controller_type =
     450           0 :                 powerplay_table->thermal_controller_type;
     451             : 
     452             :         return 0;
     453             : }
     454             : 
     455             : static int arcturus_store_powerplay_table(struct smu_context *smu)
     456             : {
     457           0 :         struct smu_table_context *table_context = &smu->smu_table;
     458           0 :         struct smu_11_0_powerplay_table *powerplay_table =
     459             :                 table_context->power_play_table;
     460             : 
     461           0 :         memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
     462             :                sizeof(PPTable_t));
     463             : 
     464             :         return 0;
     465             : }
     466             : 
     467           0 : static int arcturus_append_powerplay_table(struct smu_context *smu)
     468             : {
     469           0 :         struct smu_table_context *table_context = &smu->smu_table;
     470           0 :         PPTable_t *smc_pptable = table_context->driver_pptable;
     471             :         struct atom_smc_dpm_info_v4_6 *smc_dpm_table;
     472             :         int index, ret;
     473             : 
     474           0 :         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
     475             :                                            smc_dpm_info);
     476             : 
     477           0 :         ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
     478             :                                       (uint8_t **)&smc_dpm_table);
     479           0 :         if (ret)
     480             :                 return ret;
     481             : 
     482           0 :         dev_info(smu->adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n",
     483             :                         smc_dpm_table->table_header.format_revision,
     484             :                         smc_dpm_table->table_header.content_revision);
     485             : 
     486           0 :         if ((smc_dpm_table->table_header.format_revision == 4) &&
     487           0 :             (smc_dpm_table->table_header.content_revision == 6))
     488           0 :                 smu_memcpy_trailing(smc_pptable, MaxVoltageStepGfx, BoardReserved,
     489             :                                     smc_dpm_table, maxvoltagestepgfx);
     490             :         return 0;
     491             : }
     492             : 
     493           0 : static int arcturus_setup_pptable(struct smu_context *smu)
     494             : {
     495           0 :         int ret = 0;
     496             : 
     497           0 :         ret = smu_v11_0_setup_pptable(smu);
     498           0 :         if (ret)
     499             :                 return ret;
     500             : 
     501           0 :         ret = arcturus_store_powerplay_table(smu);
     502             :         if (ret)
     503             :                 return ret;
     504             : 
     505           0 :         ret = arcturus_append_powerplay_table(smu);
     506           0 :         if (ret)
     507             :                 return ret;
     508             : 
     509           0 :         ret = arcturus_check_powerplay_table(smu);
     510             :         if (ret)
     511             :                 return ret;
     512             : 
     513           0 :         return ret;
     514             : }
     515             : 
     516           0 : static int arcturus_run_btc(struct smu_context *smu)
     517             : {
     518           0 :         int ret = 0;
     519             : 
     520           0 :         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunAfllBtc, NULL);
     521           0 :         if (ret) {
     522           0 :                 dev_err(smu->adev->dev, "RunAfllBtc failed!\n");
     523           0 :                 return ret;
     524             :         }
     525             : 
     526           0 :         return smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL);
     527             : }
     528             : 
     529           0 : static int arcturus_populate_umd_state_clk(struct smu_context *smu)
     530             : {
     531           0 :         struct smu_11_0_dpm_context *dpm_context =
     532             :                                 smu->smu_dpm.dpm_context;
     533           0 :         struct smu_11_0_dpm_table *gfx_table =
     534             :                                 &dpm_context->dpm_tables.gfx_table;
     535           0 :         struct smu_11_0_dpm_table *mem_table =
     536             :                                 &dpm_context->dpm_tables.uclk_table;
     537           0 :         struct smu_11_0_dpm_table *soc_table =
     538             :                                 &dpm_context->dpm_tables.soc_table;
     539           0 :         struct smu_umd_pstate_table *pstate_table =
     540             :                                 &smu->pstate_table;
     541             : 
     542           0 :         pstate_table->gfxclk_pstate.min = gfx_table->min;
     543           0 :         pstate_table->gfxclk_pstate.peak = gfx_table->max;
     544             : 
     545           0 :         pstate_table->uclk_pstate.min = mem_table->min;
     546           0 :         pstate_table->uclk_pstate.peak = mem_table->max;
     547             : 
     548           0 :         pstate_table->socclk_pstate.min = soc_table->min;
     549           0 :         pstate_table->socclk_pstate.peak = soc_table->max;
     550             : 
     551           0 :         if (gfx_table->count > ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL &&
     552           0 :             mem_table->count > ARCTURUS_UMD_PSTATE_MCLK_LEVEL &&
     553           0 :             soc_table->count > ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL) {
     554           0 :                 pstate_table->gfxclk_pstate.standard =
     555           0 :                         gfx_table->dpm_levels[ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL].value;
     556           0 :                 pstate_table->uclk_pstate.standard =
     557           0 :                         mem_table->dpm_levels[ARCTURUS_UMD_PSTATE_MCLK_LEVEL].value;
     558           0 :                 pstate_table->socclk_pstate.standard =
     559           0 :                         soc_table->dpm_levels[ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL].value;
     560             :         } else {
     561           0 :                 pstate_table->gfxclk_pstate.standard =
     562             :                         pstate_table->gfxclk_pstate.min;
     563           0 :                 pstate_table->uclk_pstate.standard =
     564             :                         pstate_table->uclk_pstate.min;
     565           0 :                 pstate_table->socclk_pstate.standard =
     566             :                         pstate_table->socclk_pstate.min;
     567             :         }
     568             : 
     569           0 :         return 0;
     570             : }
     571             : 
     572             : static int arcturus_get_clk_table(struct smu_context *smu,
     573             :                         struct pp_clock_levels_with_latency *clocks,
     574             :                         struct smu_11_0_dpm_table *dpm_table)
     575             : {
     576             :         uint32_t i;
     577             : 
     578           0 :         clocks->num_levels = min_t(uint32_t,
     579             :                                    dpm_table->count,
     580             :                                    (uint32_t)PP_MAX_CLOCK_LEVELS);
     581             : 
     582           0 :         for (i = 0; i < clocks->num_levels; i++) {
     583           0 :                 clocks->data[i].clocks_in_khz =
     584           0 :                         dpm_table->dpm_levels[i].value * 1000;
     585             :                 clocks->data[i].latency_in_us = 0;
     586             :         }
     587             : 
     588             :         return 0;
     589             : }
     590             : 
     591             : static int arcturus_freqs_in_same_level(int32_t frequency1,
     592             :                                         int32_t frequency2)
     593             : {
     594           0 :         return (abs(frequency1 - frequency2) <= EPSILON);
     595             : }
     596             : 
     597           0 : static int arcturus_get_smu_metrics_data(struct smu_context *smu,
     598             :                                          MetricsMember_t member,
     599             :                                          uint32_t *value)
     600             : {
     601           0 :         struct smu_table_context *smu_table= &smu->smu_table;
     602           0 :         SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
     603           0 :         int ret = 0;
     604             : 
     605           0 :         ret = smu_cmn_get_metrics_table(smu,
     606             :                                         NULL,
     607             :                                         false);
     608           0 :         if (ret)
     609             :                 return ret;
     610             : 
     611           0 :         switch (member) {
     612             :         case METRICS_CURR_GFXCLK:
     613           0 :                 *value = metrics->CurrClock[PPCLK_GFXCLK];
     614           0 :                 break;
     615             :         case METRICS_CURR_SOCCLK:
     616           0 :                 *value = metrics->CurrClock[PPCLK_SOCCLK];
     617           0 :                 break;
     618             :         case METRICS_CURR_UCLK:
     619           0 :                 *value = metrics->CurrClock[PPCLK_UCLK];
     620           0 :                 break;
     621             :         case METRICS_CURR_VCLK:
     622           0 :                 *value = metrics->CurrClock[PPCLK_VCLK];
     623           0 :                 break;
     624             :         case METRICS_CURR_DCLK:
     625           0 :                 *value = metrics->CurrClock[PPCLK_DCLK];
     626           0 :                 break;
     627             :         case METRICS_CURR_FCLK:
     628           0 :                 *value = metrics->CurrClock[PPCLK_FCLK];
     629           0 :                 break;
     630             :         case METRICS_AVERAGE_GFXCLK:
     631           0 :                 *value = metrics->AverageGfxclkFrequency;
     632           0 :                 break;
     633             :         case METRICS_AVERAGE_SOCCLK:
     634           0 :                 *value = metrics->AverageSocclkFrequency;
     635           0 :                 break;
     636             :         case METRICS_AVERAGE_UCLK:
     637           0 :                 *value = metrics->AverageUclkFrequency;
     638           0 :                 break;
     639             :         case METRICS_AVERAGE_VCLK:
     640           0 :                 *value = metrics->AverageVclkFrequency;
     641           0 :                 break;
     642             :         case METRICS_AVERAGE_DCLK:
     643           0 :                 *value = metrics->AverageDclkFrequency;
     644           0 :                 break;
     645             :         case METRICS_AVERAGE_GFXACTIVITY:
     646           0 :                 *value = metrics->AverageGfxActivity;
     647           0 :                 break;
     648             :         case METRICS_AVERAGE_MEMACTIVITY:
     649           0 :                 *value = metrics->AverageUclkActivity;
     650           0 :                 break;
     651             :         case METRICS_AVERAGE_VCNACTIVITY:
     652           0 :                 *value = metrics->VcnActivityPercentage;
     653           0 :                 break;
     654             :         case METRICS_AVERAGE_SOCKETPOWER:
     655           0 :                 *value = metrics->AverageSocketPower << 8;
     656           0 :                 break;
     657             :         case METRICS_TEMPERATURE_EDGE:
     658           0 :                 *value = metrics->TemperatureEdge *
     659             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     660           0 :                 break;
     661             :         case METRICS_TEMPERATURE_HOTSPOT:
     662           0 :                 *value = metrics->TemperatureHotspot *
     663             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     664           0 :                 break;
     665             :         case METRICS_TEMPERATURE_MEM:
     666           0 :                 *value = metrics->TemperatureHBM *
     667             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     668           0 :                 break;
     669             :         case METRICS_TEMPERATURE_VRGFX:
     670           0 :                 *value = metrics->TemperatureVrGfx *
     671             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     672           0 :                 break;
     673             :         case METRICS_TEMPERATURE_VRSOC:
     674           0 :                 *value = metrics->TemperatureVrSoc *
     675             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     676           0 :                 break;
     677             :         case METRICS_TEMPERATURE_VRMEM:
     678           0 :                 *value = metrics->TemperatureVrMem *
     679             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     680           0 :                 break;
     681             :         case METRICS_THROTTLER_STATUS:
     682           0 :                 *value = metrics->ThrottlerStatus;
     683           0 :                 break;
     684             :         case METRICS_CURR_FANSPEED:
     685           0 :                 *value = metrics->CurrFanSpeed;
     686           0 :                 break;
     687             :         default:
     688           0 :                 *value = UINT_MAX;
     689           0 :                 break;
     690             :         }
     691             : 
     692             :         return ret;
     693             : }
     694             : 
     695           0 : static int arcturus_get_current_clk_freq_by_table(struct smu_context *smu,
     696             :                                        enum smu_clk_type clk_type,
     697             :                                        uint32_t *value)
     698             : {
     699             :         MetricsMember_t member_type;
     700           0 :         int clk_id = 0;
     701             : 
     702           0 :         if (!value)
     703             :                 return -EINVAL;
     704             : 
     705           0 :         clk_id = smu_cmn_to_asic_specific_index(smu,
     706             :                                                 CMN2ASIC_MAPPING_CLK,
     707             :                                                 clk_type);
     708           0 :         if (clk_id < 0)
     709             :                 return -EINVAL;
     710             : 
     711           0 :         switch (clk_id) {
     712             :         case PPCLK_GFXCLK:
     713             :                 /*
     714             :                  * CurrClock[clk_id] can provide accurate
     715             :                  *   output only when the dpm feature is enabled.
     716             :                  * We can use Average_* for dpm disabled case.
     717             :                  *   But this is available for gfxclk/uclk/socclk/vclk/dclk.
     718             :                  */
     719           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT))
     720             :                         member_type = METRICS_CURR_GFXCLK;
     721             :                 else
     722           0 :                         member_type = METRICS_AVERAGE_GFXCLK;
     723             :                 break;
     724             :         case PPCLK_UCLK:
     725           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT))
     726             :                         member_type = METRICS_CURR_UCLK;
     727             :                 else
     728           0 :                         member_type = METRICS_AVERAGE_UCLK;
     729             :                 break;
     730             :         case PPCLK_SOCCLK:
     731           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT))
     732             :                         member_type = METRICS_CURR_SOCCLK;
     733             :                 else
     734           0 :                         member_type = METRICS_AVERAGE_SOCCLK;
     735             :                 break;
     736             :         case PPCLK_VCLK:
     737           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_DPM_BIT))
     738             :                         member_type = METRICS_CURR_VCLK;
     739             :                 else
     740           0 :                         member_type = METRICS_AVERAGE_VCLK;
     741             :                 break;
     742             :         case PPCLK_DCLK:
     743           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_DPM_BIT))
     744             :                         member_type = METRICS_CURR_DCLK;
     745             :                 else
     746           0 :                         member_type = METRICS_AVERAGE_DCLK;
     747             :                 break;
     748             :         case PPCLK_FCLK:
     749             :                 member_type = METRICS_CURR_FCLK;
     750             :                 break;
     751             :         default:
     752             :                 return -EINVAL;
     753             :         }
     754             : 
     755           0 :         return arcturus_get_smu_metrics_data(smu,
     756             :                                              member_type,
     757             :                                              value);
     758             : }
     759             : 
     760           0 : static int arcturus_print_clk_levels(struct smu_context *smu,
     761             :                         enum smu_clk_type type, char *buf)
     762             : {
     763           0 :         int i, now, size = 0;
     764           0 :         int ret = 0;
     765             :         struct pp_clock_levels_with_latency clocks;
     766             :         struct smu_11_0_dpm_table *single_dpm_table;
     767           0 :         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
     768           0 :         struct smu_11_0_dpm_context *dpm_context = NULL;
     769             :         uint32_t gen_speed, lane_width;
     770             : 
     771           0 :         smu_cmn_get_sysfs_buf(&buf, &size);
     772             : 
     773           0 :         if (amdgpu_ras_intr_triggered()) {
     774           0 :                 size += sysfs_emit_at(buf, size, "unavailable\n");
     775           0 :                 return size;
     776             :         }
     777             : 
     778           0 :         dpm_context = smu_dpm->dpm_context;
     779             : 
     780           0 :         switch (type) {
     781             :         case SMU_SCLK:
     782           0 :                 ret = arcturus_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now);
     783           0 :                 if (ret) {
     784           0 :                         dev_err(smu->adev->dev, "Attempt to get current gfx clk Failed!");
     785           0 :                         return ret;
     786             :                 }
     787             : 
     788           0 :                 single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
     789           0 :                 ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table);
     790             :                 if (ret) {
     791             :                         dev_err(smu->adev->dev, "Attempt to get gfx clk levels Failed!");
     792             :                         return ret;
     793             :                 }
     794             : 
     795             :                 /*
     796             :                  * For DPM disabled case, there will be only one clock level.
     797             :                  * And it's safe to assume that is always the current clock.
     798             :                  */
     799           0 :                 for (i = 0; i < clocks.num_levels; i++)
     800           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i,
     801           0 :                                         clocks.data[i].clocks_in_khz / 1000,
     802             :                                         (clocks.num_levels == 1) ? "*" :
     803           0 :                                         (arcturus_freqs_in_same_level(
     804           0 :                                         clocks.data[i].clocks_in_khz / 1000,
     805           0 :                                         now) ? "*" : ""));
     806             :                 break;
     807             : 
     808             :         case SMU_MCLK:
     809           0 :                 ret = arcturus_get_current_clk_freq_by_table(smu, SMU_UCLK, &now);
     810           0 :                 if (ret) {
     811           0 :                         dev_err(smu->adev->dev, "Attempt to get current mclk Failed!");
     812           0 :                         return ret;
     813             :                 }
     814             : 
     815           0 :                 single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
     816           0 :                 ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table);
     817             :                 if (ret) {
     818             :                         dev_err(smu->adev->dev, "Attempt to get memory clk levels Failed!");
     819             :                         return ret;
     820             :                 }
     821             : 
     822           0 :                 for (i = 0; i < clocks.num_levels; i++)
     823           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     824           0 :                                 i, clocks.data[i].clocks_in_khz / 1000,
     825             :                                 (clocks.num_levels == 1) ? "*" :
     826           0 :                                 (arcturus_freqs_in_same_level(
     827           0 :                                 clocks.data[i].clocks_in_khz / 1000,
     828           0 :                                 now) ? "*" : ""));
     829             :                 break;
     830             : 
     831             :         case SMU_SOCCLK:
     832           0 :                 ret = arcturus_get_current_clk_freq_by_table(smu, SMU_SOCCLK, &now);
     833           0 :                 if (ret) {
     834           0 :                         dev_err(smu->adev->dev, "Attempt to get current socclk Failed!");
     835           0 :                         return ret;
     836             :                 }
     837             : 
     838           0 :                 single_dpm_table = &(dpm_context->dpm_tables.soc_table);
     839           0 :                 ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table);
     840             :                 if (ret) {
     841             :                         dev_err(smu->adev->dev, "Attempt to get socclk levels Failed!");
     842             :                         return ret;
     843             :                 }
     844             : 
     845           0 :                 for (i = 0; i < clocks.num_levels; i++)
     846           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     847           0 :                                 i, clocks.data[i].clocks_in_khz / 1000,
     848             :                                 (clocks.num_levels == 1) ? "*" :
     849           0 :                                 (arcturus_freqs_in_same_level(
     850           0 :                                 clocks.data[i].clocks_in_khz / 1000,
     851           0 :                                 now) ? "*" : ""));
     852             :                 break;
     853             : 
     854             :         case SMU_FCLK:
     855           0 :                 ret = arcturus_get_current_clk_freq_by_table(smu, SMU_FCLK, &now);
     856           0 :                 if (ret) {
     857           0 :                         dev_err(smu->adev->dev, "Attempt to get current fclk Failed!");
     858           0 :                         return ret;
     859             :                 }
     860             : 
     861           0 :                 single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
     862           0 :                 ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table);
     863             :                 if (ret) {
     864             :                         dev_err(smu->adev->dev, "Attempt to get fclk levels Failed!");
     865             :                         return ret;
     866             :                 }
     867             : 
     868           0 :                 for (i = 0; i < single_dpm_table->count; i++)
     869           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     870             :                                 i, single_dpm_table->dpm_levels[i].value,
     871             :                                 (clocks.num_levels == 1) ? "*" :
     872           0 :                                 (arcturus_freqs_in_same_level(
     873           0 :                                 clocks.data[i].clocks_in_khz / 1000,
     874           0 :                                 now) ? "*" : ""));
     875             :                 break;
     876             : 
     877             :         case SMU_VCLK:
     878           0 :                 ret = arcturus_get_current_clk_freq_by_table(smu, SMU_VCLK, &now);
     879           0 :                 if (ret) {
     880           0 :                         dev_err(smu->adev->dev, "Attempt to get current vclk Failed!");
     881           0 :                         return ret;
     882             :                 }
     883             : 
     884           0 :                 single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
     885           0 :                 ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table);
     886             :                 if (ret) {
     887             :                         dev_err(smu->adev->dev, "Attempt to get vclk levels Failed!");
     888             :                         return ret;
     889             :                 }
     890             : 
     891           0 :                 for (i = 0; i < single_dpm_table->count; i++)
     892           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     893             :                                 i, single_dpm_table->dpm_levels[i].value,
     894             :                                 (clocks.num_levels == 1) ? "*" :
     895           0 :                                 (arcturus_freqs_in_same_level(
     896           0 :                                 clocks.data[i].clocks_in_khz / 1000,
     897           0 :                                 now) ? "*" : ""));
     898             :                 break;
     899             : 
     900             :         case SMU_DCLK:
     901           0 :                 ret = arcturus_get_current_clk_freq_by_table(smu, SMU_DCLK, &now);
     902           0 :                 if (ret) {
     903           0 :                         dev_err(smu->adev->dev, "Attempt to get current dclk Failed!");
     904           0 :                         return ret;
     905             :                 }
     906             : 
     907           0 :                 single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
     908           0 :                 ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table);
     909             :                 if (ret) {
     910             :                         dev_err(smu->adev->dev, "Attempt to get dclk levels Failed!");
     911             :                         return ret;
     912             :                 }
     913             : 
     914           0 :                 for (i = 0; i < single_dpm_table->count; i++)
     915           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     916             :                                 i, single_dpm_table->dpm_levels[i].value,
     917             :                                 (clocks.num_levels == 1) ? "*" :
     918           0 :                                 (arcturus_freqs_in_same_level(
     919           0 :                                 clocks.data[i].clocks_in_khz / 1000,
     920           0 :                                 now) ? "*" : ""));
     921             :                 break;
     922             : 
     923             :         case SMU_PCIE:
     924           0 :                 gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu);
     925           0 :                 lane_width = smu_v11_0_get_current_pcie_link_width_level(smu);
     926           0 :                 size += sysfs_emit_at(buf, size, "0: %s %s %dMhz *\n",
     927             :                                 (gen_speed == 0) ? "2.5GT/s," :
     928           0 :                                 (gen_speed == 1) ? "5.0GT/s," :
     929           0 :                                 (gen_speed == 2) ? "8.0GT/s," :
     930           0 :                                 (gen_speed == 3) ? "16.0GT/s," : "",
     931             :                                 (lane_width == 1) ? "x1" :
     932           0 :                                 (lane_width == 2) ? "x2" :
     933           0 :                                 (lane_width == 3) ? "x4" :
     934           0 :                                 (lane_width == 4) ? "x8" :
     935           0 :                                 (lane_width == 5) ? "x12" :
     936           0 :                                 (lane_width == 6) ? "x16" : "",
     937           0 :                                 smu->smu_table.boot_values.lclk / 100);
     938           0 :                 break;
     939             : 
     940             :         default:
     941             :                 break;
     942             :         }
     943             : 
     944             :         return size;
     945             : }
     946             : 
     947           0 : static int arcturus_upload_dpm_level(struct smu_context *smu,
     948             :                                      bool max,
     949             :                                      uint32_t feature_mask,
     950             :                                      uint32_t level)
     951             : {
     952           0 :         struct smu_11_0_dpm_context *dpm_context =
     953             :                         smu->smu_dpm.dpm_context;
     954             :         uint32_t freq;
     955           0 :         int ret = 0;
     956             : 
     957           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
     958           0 :             (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
     959           0 :                 freq = dpm_context->dpm_tables.gfx_table.dpm_levels[level].value;
     960           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu,
     961             :                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
     962             :                         (PPCLK_GFXCLK << 16) | (freq & 0xffff),
     963             :                         NULL);
     964           0 :                 if (ret) {
     965           0 :                         dev_err(smu->adev->dev, "Failed to set soft %s gfxclk !\n",
     966             :                                                 max ? "max" : "min");
     967           0 :                         return ret;
     968             :                 }
     969             :         }
     970             : 
     971           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
     972           0 :             (feature_mask & FEATURE_DPM_UCLK_MASK)) {
     973           0 :                 freq = dpm_context->dpm_tables.uclk_table.dpm_levels[level].value;
     974           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu,
     975             :                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
     976           0 :                         (PPCLK_UCLK << 16) | (freq & 0xffff),
     977             :                         NULL);
     978           0 :                 if (ret) {
     979           0 :                         dev_err(smu->adev->dev, "Failed to set soft %s memclk !\n",
     980             :                                                 max ? "max" : "min");
     981           0 :                         return ret;
     982             :                 }
     983             :         }
     984             : 
     985           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) &&
     986           0 :             (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
     987           0 :                 freq = dpm_context->dpm_tables.soc_table.dpm_levels[level].value;
     988           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu,
     989             :                         (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
     990           0 :                         (PPCLK_SOCCLK << 16) | (freq & 0xffff),
     991             :                         NULL);
     992           0 :                 if (ret) {
     993           0 :                         dev_err(smu->adev->dev, "Failed to set soft %s socclk !\n",
     994             :                                                 max ? "max" : "min");
     995           0 :                         return ret;
     996             :                 }
     997             :         }
     998             : 
     999             :         return ret;
    1000             : }
    1001             : 
    1002           0 : static int arcturus_force_clk_levels(struct smu_context *smu,
    1003             :                         enum smu_clk_type type, uint32_t mask)
    1004             : {
    1005           0 :         struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
    1006           0 :         struct smu_11_0_dpm_table *single_dpm_table = NULL;
    1007             :         uint32_t soft_min_level, soft_max_level;
    1008             :         uint32_t smu_version;
    1009           0 :         int ret = 0;
    1010             : 
    1011           0 :         ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
    1012           0 :         if (ret) {
    1013           0 :                 dev_err(smu->adev->dev, "Failed to get smu version!\n");
    1014           0 :                 return ret;
    1015             :         }
    1016             : 
    1017           0 :         if ((smu_version >= 0x361200) &&
    1018             :             (smu_version <= 0x361a00)) {
    1019           0 :                 dev_err(smu->adev->dev, "Forcing clock level is not supported with "
    1020             :                        "54.18 - 54.26(included) SMU firmwares\n");
    1021           0 :                 return -EOPNOTSUPP;
    1022             :         }
    1023             : 
    1024           0 :         soft_min_level = mask ? (ffs(mask) - 1) : 0;
    1025           0 :         soft_max_level = mask ? (fls(mask) - 1) : 0;
    1026             : 
    1027           0 :         switch (type) {
    1028             :         case SMU_SCLK:
    1029           0 :                 single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
    1030           0 :                 if (soft_max_level >= single_dpm_table->count) {
    1031           0 :                         dev_err(smu->adev->dev, "Clock level specified %d is over max allowed %d\n",
    1032             :                                         soft_max_level, single_dpm_table->count - 1);
    1033           0 :                         ret = -EINVAL;
    1034           0 :                         break;
    1035             :                 }
    1036             : 
    1037           0 :                 ret = arcturus_upload_dpm_level(smu,
    1038             :                                                 false,
    1039             :                                                 FEATURE_DPM_GFXCLK_MASK,
    1040             :                                                 soft_min_level);
    1041           0 :                 if (ret) {
    1042           0 :                         dev_err(smu->adev->dev, "Failed to upload boot level to lowest!\n");
    1043           0 :                         break;
    1044             :                 }
    1045             : 
    1046           0 :                 ret = arcturus_upload_dpm_level(smu,
    1047             :                                                 true,
    1048             :                                                 FEATURE_DPM_GFXCLK_MASK,
    1049             :                                                 soft_max_level);
    1050           0 :                 if (ret)
    1051           0 :                         dev_err(smu->adev->dev, "Failed to upload dpm max level to highest!\n");
    1052             : 
    1053             :                 break;
    1054             : 
    1055             :         case SMU_MCLK:
    1056             :         case SMU_SOCCLK:
    1057             :         case SMU_FCLK:
    1058             :                 /*
    1059             :                  * Should not arrive here since Arcturus does not
    1060             :                  * support mclk/socclk/fclk softmin/softmax settings
    1061             :                  */
    1062           0 :                 ret = -EINVAL;
    1063           0 :                 break;
    1064             : 
    1065             :         default:
    1066             :                 break;
    1067             :         }
    1068             : 
    1069             :         return ret;
    1070             : }
    1071             : 
    1072           0 : static int arcturus_get_thermal_temperature_range(struct smu_context *smu,
    1073             :                                                 struct smu_temperature_range *range)
    1074             : {
    1075           0 :         struct smu_table_context *table_context = &smu->smu_table;
    1076           0 :         struct smu_11_0_powerplay_table *powerplay_table =
    1077             :                                 table_context->power_play_table;
    1078           0 :         PPTable_t *pptable = smu->smu_table.driver_pptable;
    1079             : 
    1080           0 :         if (!range)
    1081             :                 return -EINVAL;
    1082             : 
    1083           0 :         memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range));
    1084             : 
    1085           0 :         range->max = pptable->TedgeLimit *
    1086             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1087           0 :         range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) *
    1088             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1089           0 :         range->hotspot_crit_max = pptable->ThotspotLimit *
    1090             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1091           0 :         range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
    1092             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1093           0 :         range->mem_crit_max = pptable->TmemLimit *
    1094             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1095           0 :         range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)*
    1096             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1097           0 :         range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
    1098             : 
    1099           0 :         return 0;
    1100             : }
    1101             : 
    1102           0 : static int arcturus_read_sensor(struct smu_context *smu,
    1103             :                                 enum amd_pp_sensors sensor,
    1104             :                                 void *data, uint32_t *size)
    1105             : {
    1106           0 :         struct smu_table_context *table_context = &smu->smu_table;
    1107           0 :         PPTable_t *pptable = table_context->driver_pptable;
    1108           0 :         int ret = 0;
    1109             : 
    1110           0 :         if (amdgpu_ras_intr_triggered())
    1111             :                 return 0;
    1112             : 
    1113           0 :         if (!data || !size)
    1114             :                 return -EINVAL;
    1115             : 
    1116           0 :         switch (sensor) {
    1117             :         case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
    1118           0 :                 *(uint32_t *)data = pptable->FanMaximumRpm;
    1119           0 :                 *size = 4;
    1120           0 :                 break;
    1121             :         case AMDGPU_PP_SENSOR_MEM_LOAD:
    1122           0 :                 ret = arcturus_get_smu_metrics_data(smu,
    1123             :                                                     METRICS_AVERAGE_MEMACTIVITY,
    1124             :                                                     (uint32_t *)data);
    1125           0 :                 *size = 4;
    1126           0 :                 break;
    1127             :         case AMDGPU_PP_SENSOR_GPU_LOAD:
    1128           0 :                 ret = arcturus_get_smu_metrics_data(smu,
    1129             :                                                     METRICS_AVERAGE_GFXACTIVITY,
    1130             :                                                     (uint32_t *)data);
    1131           0 :                 *size = 4;
    1132           0 :                 break;
    1133             :         case AMDGPU_PP_SENSOR_GPU_POWER:
    1134           0 :                 ret = arcturus_get_smu_metrics_data(smu,
    1135             :                                                     METRICS_AVERAGE_SOCKETPOWER,
    1136             :                                                     (uint32_t *)data);
    1137           0 :                 *size = 4;
    1138           0 :                 break;
    1139             :         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
    1140           0 :                 ret = arcturus_get_smu_metrics_data(smu,
    1141             :                                                     METRICS_TEMPERATURE_HOTSPOT,
    1142             :                                                     (uint32_t *)data);
    1143           0 :                 *size = 4;
    1144           0 :                 break;
    1145             :         case AMDGPU_PP_SENSOR_EDGE_TEMP:
    1146           0 :                 ret = arcturus_get_smu_metrics_data(smu,
    1147             :                                                     METRICS_TEMPERATURE_EDGE,
    1148             :                                                     (uint32_t *)data);
    1149           0 :                 *size = 4;
    1150           0 :                 break;
    1151             :         case AMDGPU_PP_SENSOR_MEM_TEMP:
    1152           0 :                 ret = arcturus_get_smu_metrics_data(smu,
    1153             :                                                     METRICS_TEMPERATURE_MEM,
    1154             :                                                     (uint32_t *)data);
    1155           0 :                 *size = 4;
    1156           0 :                 break;
    1157             :         case AMDGPU_PP_SENSOR_GFX_MCLK:
    1158           0 :                 ret = arcturus_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
    1159             :                 /* the output clock frequency in 10K unit */
    1160           0 :                 *(uint32_t *)data *= 100;
    1161           0 :                 *size = 4;
    1162           0 :                 break;
    1163             :         case AMDGPU_PP_SENSOR_GFX_SCLK:
    1164           0 :                 ret = arcturus_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
    1165           0 :                 *(uint32_t *)data *= 100;
    1166           0 :                 *size = 4;
    1167           0 :                 break;
    1168             :         case AMDGPU_PP_SENSOR_VDDGFX:
    1169           0 :                 ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data);
    1170           0 :                 *size = 4;
    1171           0 :                 break;
    1172             :         default:
    1173             :                 ret = -EOPNOTSUPP;
    1174             :                 break;
    1175             :         }
    1176             : 
    1177             :         return ret;
    1178             : }
    1179             : 
    1180           0 : static int arcturus_set_fan_static_mode(struct smu_context *smu,
    1181             :                                         uint32_t mode)
    1182             : {
    1183           0 :         struct amdgpu_device *adev = smu->adev;
    1184             : 
    1185           0 :         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2_ARCT,
    1186             :                      REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2_ARCT),
    1187             :                                    CG_FDO_CTRL2, TMIN, 0));
    1188           0 :         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2_ARCT,
    1189             :                      REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2_ARCT),
    1190             :                                    CG_FDO_CTRL2, FDO_PWM_MODE, mode));
    1191             : 
    1192           0 :         return 0;
    1193             : }
    1194             : 
    1195           0 : static int arcturus_get_fan_speed_rpm(struct smu_context *smu,
    1196             :                                       uint32_t *speed)
    1197             : {
    1198           0 :         struct amdgpu_device *adev = smu->adev;
    1199           0 :         uint32_t crystal_clock_freq = 2500;
    1200             :         uint32_t tach_status;
    1201             :         uint64_t tmp64;
    1202           0 :         int ret = 0;
    1203             : 
    1204           0 :         if (!speed)
    1205             :                 return -EINVAL;
    1206             : 
    1207           0 :         switch (smu_v11_0_get_fan_control_mode(smu)) {
    1208             :         case AMD_FAN_CTRL_AUTO:
    1209             :                 ret = arcturus_get_smu_metrics_data(smu,
    1210             :                                                     METRICS_CURR_FANSPEED,
    1211             :                                                     speed);
    1212             :                 break;
    1213             :         default:
    1214             :                 /*
    1215             :                  * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
    1216             :                  * detected via register retrieving. To workaround this, we will
    1217             :                  * report the fan speed as 0 RPM if user just requested such.
    1218             :                  */
    1219           0 :                 if ((smu->user_dpm_profile.flags & SMU_CUSTOM_FAN_SPEED_RPM)
    1220           0 :                      && !smu->user_dpm_profile.fan_speed_rpm) {
    1221           0 :                         *speed = 0;
    1222           0 :                         return 0;
    1223             :                 }
    1224             : 
    1225           0 :                 tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
    1226           0 :                 tach_status = RREG32_SOC15(THM, 0, mmCG_TACH_STATUS_ARCT);
    1227           0 :                 if (tach_status) {
    1228           0 :                         do_div(tmp64, tach_status);
    1229           0 :                         *speed = (uint32_t)tmp64;
    1230             :                 } else {
    1231           0 :                         *speed = 0;
    1232             :                 }
    1233             : 
    1234             :                 break;
    1235             :         }
    1236             : 
    1237             :         return ret;
    1238             : }
    1239             : 
    1240           0 : static int arcturus_set_fan_speed_pwm(struct smu_context *smu,
    1241             :                                       uint32_t speed)
    1242             : {
    1243           0 :         struct amdgpu_device *adev = smu->adev;
    1244             :         uint32_t duty100, duty;
    1245             :         uint64_t tmp64;
    1246             : 
    1247           0 :         speed = MIN(speed, 255);
    1248             : 
    1249           0 :         duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1_ARCT),
    1250             :                                 CG_FDO_CTRL1, FMAX_DUTY100);
    1251           0 :         if (!duty100)
    1252             :                 return -EINVAL;
    1253             : 
    1254           0 :         tmp64 = (uint64_t)speed * duty100;
    1255           0 :         do_div(tmp64, 255);
    1256           0 :         duty = (uint32_t)tmp64;
    1257             : 
    1258           0 :         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0_ARCT,
    1259             :                      REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0_ARCT),
    1260             :                                    CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
    1261             : 
    1262           0 :         return arcturus_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC);
    1263             : }
    1264             : 
    1265           0 : static int arcturus_set_fan_speed_rpm(struct smu_context *smu,
    1266             :                                       uint32_t speed)
    1267             : {
    1268           0 :         struct amdgpu_device *adev = smu->adev;
    1269             :         /*
    1270             :          * crystal_clock_freq used for fan speed rpm calculation is
    1271             :          * always 25Mhz. So, hardcode it as 2500(in 10K unit).
    1272             :          */
    1273           0 :         uint32_t crystal_clock_freq = 2500;
    1274             :         uint32_t tach_period;
    1275             : 
    1276           0 :         tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
    1277           0 :         WREG32_SOC15(THM, 0, mmCG_TACH_CTRL_ARCT,
    1278             :                      REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL_ARCT),
    1279             :                                    CG_TACH_CTRL, TARGET_PERIOD,
    1280             :                                    tach_period));
    1281             : 
    1282           0 :         return arcturus_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
    1283             : }
    1284             : 
    1285           0 : static int arcturus_get_fan_speed_pwm(struct smu_context *smu,
    1286             :                                       uint32_t *speed)
    1287             : {
    1288           0 :         struct amdgpu_device *adev = smu->adev;
    1289             :         uint32_t duty100, duty;
    1290             :         uint64_t tmp64;
    1291             : 
    1292             :         /*
    1293             :          * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
    1294             :          * detected via register retrieving. To workaround this, we will
    1295             :          * report the fan speed as 0 PWM if user just requested such.
    1296             :          */
    1297           0 :         if ((smu->user_dpm_profile.flags & SMU_CUSTOM_FAN_SPEED_PWM)
    1298           0 :              && !smu->user_dpm_profile.fan_speed_pwm) {
    1299           0 :                 *speed = 0;
    1300           0 :                 return 0;
    1301             :         }
    1302             : 
    1303           0 :         duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1_ARCT),
    1304             :                                 CG_FDO_CTRL1, FMAX_DUTY100);
    1305           0 :         duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS_ARCT),
    1306             :                                 CG_THERMAL_STATUS, FDO_PWM_DUTY);
    1307             : 
    1308           0 :         if (duty100) {
    1309           0 :                 tmp64 = (uint64_t)duty * 255;
    1310           0 :                 do_div(tmp64, duty100);
    1311           0 :                 *speed = MIN((uint32_t)tmp64, 255);
    1312             :         } else {
    1313           0 :                 *speed = 0;
    1314             :         }
    1315             : 
    1316             :         return 0;
    1317             : }
    1318             : 
    1319           0 : static int arcturus_get_fan_parameters(struct smu_context *smu)
    1320             : {
    1321           0 :         PPTable_t *pptable = smu->smu_table.driver_pptable;
    1322             : 
    1323           0 :         smu->fan_max_rpm = pptable->FanMaximumRpm;
    1324             : 
    1325           0 :         return 0;
    1326             : }
    1327             : 
    1328           0 : static int arcturus_get_power_limit(struct smu_context *smu,
    1329             :                                     uint32_t *current_power_limit,
    1330             :                                     uint32_t *default_power_limit,
    1331             :                                     uint32_t *max_power_limit)
    1332             : {
    1333           0 :         struct smu_11_0_powerplay_table *powerplay_table =
    1334             :                 (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
    1335           0 :         PPTable_t *pptable = smu->smu_table.driver_pptable;
    1336             :         uint32_t power_limit, od_percent;
    1337             : 
    1338           0 :         if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
    1339             :                 /* the last hope to figure out the ppt limit */
    1340           0 :                 if (!pptable) {
    1341           0 :                         dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
    1342           0 :                         return -EINVAL;
    1343             :                 }
    1344           0 :                 power_limit =
    1345           0 :                         pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
    1346             :         }
    1347             : 
    1348           0 :         if (current_power_limit)
    1349           0 :                 *current_power_limit = power_limit;
    1350           0 :         if (default_power_limit)
    1351           0 :                 *default_power_limit = power_limit;
    1352             : 
    1353           0 :         if (max_power_limit) {
    1354           0 :                 if (smu->od_enabled) {
    1355           0 :                         od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
    1356             : 
    1357             :                         dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
    1358             : 
    1359           0 :                         power_limit *= (100 + od_percent);
    1360           0 :                         power_limit /= 100;
    1361             :                 }
    1362             : 
    1363           0 :                 *max_power_limit = power_limit;
    1364             :         }
    1365             : 
    1366             :         return 0;
    1367             : }
    1368             : 
    1369           0 : static int arcturus_get_power_profile_mode(struct smu_context *smu,
    1370             :                                            char *buf)
    1371             : {
    1372             :         DpmActivityMonitorCoeffInt_t activity_monitor;
    1373             :         static const char *title[] = {
    1374             :                         "PROFILE_INDEX(NAME)",
    1375             :                         "CLOCK_TYPE(NAME)",
    1376             :                         "FPS",
    1377             :                         "UseRlcBusy",
    1378             :                         "MinActiveFreqType",
    1379             :                         "MinActiveFreq",
    1380             :                         "BoosterFreqType",
    1381             :                         "BoosterFreq",
    1382             :                         "PD_Data_limit_c",
    1383             :                         "PD_Data_error_coeff",
    1384             :                         "PD_Data_error_rate_coeff"};
    1385           0 :         uint32_t i, size = 0;
    1386           0 :         int16_t workload_type = 0;
    1387           0 :         int result = 0;
    1388             :         uint32_t smu_version;
    1389             : 
    1390           0 :         if (!buf)
    1391             :                 return -EINVAL;
    1392             : 
    1393           0 :         result = smu_cmn_get_smc_version(smu, NULL, &smu_version);
    1394           0 :         if (result)
    1395             :                 return result;
    1396             : 
    1397           0 :         if (smu_version >= 0x360d00)
    1398           0 :                 size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
    1399             :                         title[0], title[1], title[2], title[3], title[4], title[5],
    1400             :                         title[6], title[7], title[8], title[9], title[10]);
    1401             :         else
    1402           0 :                 size += sysfs_emit_at(buf, size, "%16s\n",
    1403             :                         title[0]);
    1404             : 
    1405           0 :         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
    1406             :                 /*
    1407             :                  * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
    1408             :                  * Not all profile modes are supported on arcturus.
    1409             :                  */
    1410           0 :                 workload_type = smu_cmn_to_asic_specific_index(smu,
    1411             :                                                                CMN2ASIC_MAPPING_WORKLOAD,
    1412             :                                                                i);
    1413           0 :                 if (workload_type < 0)
    1414           0 :                         continue;
    1415             : 
    1416           0 :                 if (smu_version >= 0x360d00) {
    1417           0 :                         result = smu_cmn_update_table(smu,
    1418             :                                                   SMU_TABLE_ACTIVITY_MONITOR_COEFF,
    1419             :                                                   workload_type,
    1420             :                                                   (void *)(&activity_monitor),
    1421             :                                                   false);
    1422           0 :                         if (result) {
    1423           0 :                                 dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
    1424           0 :                                 return result;
    1425             :                         }
    1426             :                 }
    1427             : 
    1428           0 :                 size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
    1429           0 :                         i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
    1430             : 
    1431           0 :                 if (smu_version >= 0x360d00) {
    1432           0 :                         size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
    1433             :                                 " ",
    1434             :                                 0,
    1435             :                                 "GFXCLK",
    1436           0 :                                 activity_monitor.Gfx_FPS,
    1437           0 :                                 activity_monitor.Gfx_UseRlcBusy,
    1438           0 :                                 activity_monitor.Gfx_MinActiveFreqType,
    1439           0 :                                 activity_monitor.Gfx_MinActiveFreq,
    1440           0 :                                 activity_monitor.Gfx_BoosterFreqType,
    1441           0 :                                 activity_monitor.Gfx_BoosterFreq,
    1442             :                                 activity_monitor.Gfx_PD_Data_limit_c,
    1443             :                                 activity_monitor.Gfx_PD_Data_error_coeff,
    1444             :                                 activity_monitor.Gfx_PD_Data_error_rate_coeff);
    1445             : 
    1446           0 :                         size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
    1447             :                                 " ",
    1448             :                                 1,
    1449             :                                 "UCLK",
    1450           0 :                                 activity_monitor.Mem_FPS,
    1451           0 :                                 activity_monitor.Mem_UseRlcBusy,
    1452           0 :                                 activity_monitor.Mem_MinActiveFreqType,
    1453           0 :                                 activity_monitor.Mem_MinActiveFreq,
    1454           0 :                                 activity_monitor.Mem_BoosterFreqType,
    1455           0 :                                 activity_monitor.Mem_BoosterFreq,
    1456             :                                 activity_monitor.Mem_PD_Data_limit_c,
    1457             :                                 activity_monitor.Mem_PD_Data_error_coeff,
    1458             :                                 activity_monitor.Mem_PD_Data_error_rate_coeff);
    1459             :                 }
    1460             :         }
    1461             : 
    1462           0 :         return size;
    1463             : }
    1464             : 
    1465           0 : static int arcturus_set_power_profile_mode(struct smu_context *smu,
    1466             :                                            long *input,
    1467             :                                            uint32_t size)
    1468             : {
    1469             :         DpmActivityMonitorCoeffInt_t activity_monitor;
    1470           0 :         int workload_type = 0;
    1471           0 :         uint32_t profile_mode = input[size];
    1472           0 :         int ret = 0;
    1473             :         uint32_t smu_version;
    1474             : 
    1475           0 :         if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
    1476           0 :                 dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
    1477           0 :                 return -EINVAL;
    1478             :         }
    1479             : 
    1480           0 :         ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
    1481           0 :         if (ret)
    1482             :                 return ret;
    1483             : 
    1484           0 :         if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
    1485           0 :              (smu_version >=0x360d00)) {
    1486           0 :                 ret = smu_cmn_update_table(smu,
    1487             :                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF,
    1488             :                                        WORKLOAD_PPLIB_CUSTOM_BIT,
    1489             :                                        (void *)(&activity_monitor),
    1490             :                                        false);
    1491           0 :                 if (ret) {
    1492           0 :                         dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
    1493           0 :                         return ret;
    1494             :                 }
    1495             : 
    1496           0 :                 switch (input[0]) {
    1497             :                 case 0: /* Gfxclk */
    1498           0 :                         activity_monitor.Gfx_FPS = input[1];
    1499           0 :                         activity_monitor.Gfx_UseRlcBusy = input[2];
    1500           0 :                         activity_monitor.Gfx_MinActiveFreqType = input[3];
    1501           0 :                         activity_monitor.Gfx_MinActiveFreq = input[4];
    1502           0 :                         activity_monitor.Gfx_BoosterFreqType = input[5];
    1503           0 :                         activity_monitor.Gfx_BoosterFreq = input[6];
    1504           0 :                         activity_monitor.Gfx_PD_Data_limit_c = input[7];
    1505           0 :                         activity_monitor.Gfx_PD_Data_error_coeff = input[8];
    1506           0 :                         activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
    1507           0 :                         break;
    1508             :                 case 1: /* Uclk */
    1509           0 :                         activity_monitor.Mem_FPS = input[1];
    1510           0 :                         activity_monitor.Mem_UseRlcBusy = input[2];
    1511           0 :                         activity_monitor.Mem_MinActiveFreqType = input[3];
    1512           0 :                         activity_monitor.Mem_MinActiveFreq = input[4];
    1513           0 :                         activity_monitor.Mem_BoosterFreqType = input[5];
    1514           0 :                         activity_monitor.Mem_BoosterFreq = input[6];
    1515           0 :                         activity_monitor.Mem_PD_Data_limit_c = input[7];
    1516           0 :                         activity_monitor.Mem_PD_Data_error_coeff = input[8];
    1517           0 :                         activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
    1518           0 :                         break;
    1519             :                 }
    1520             : 
    1521           0 :                 ret = smu_cmn_update_table(smu,
    1522             :                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF,
    1523             :                                        WORKLOAD_PPLIB_CUSTOM_BIT,
    1524             :                                        (void *)(&activity_monitor),
    1525             :                                        true);
    1526           0 :                 if (ret) {
    1527           0 :                         dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
    1528           0 :                         return ret;
    1529             :                 }
    1530             :         }
    1531             : 
    1532             :         /*
    1533             :          * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
    1534             :          * Not all profile modes are supported on arcturus.
    1535             :          */
    1536           0 :         workload_type = smu_cmn_to_asic_specific_index(smu,
    1537             :                                                        CMN2ASIC_MAPPING_WORKLOAD,
    1538             :                                                        profile_mode);
    1539           0 :         if (workload_type < 0) {
    1540             :                 dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on arcturus\n", profile_mode);
    1541             :                 return -EINVAL;
    1542             :         }
    1543             : 
    1544           0 :         ret = smu_cmn_send_smc_msg_with_param(smu,
    1545             :                                           SMU_MSG_SetWorkloadMask,
    1546           0 :                                           1 << workload_type,
    1547             :                                           NULL);
    1548           0 :         if (ret) {
    1549           0 :                 dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
    1550           0 :                 return ret;
    1551             :         }
    1552             : 
    1553           0 :         smu->power_profile_mode = profile_mode;
    1554             : 
    1555           0 :         return 0;
    1556             : }
    1557             : 
    1558           0 : static int arcturus_set_performance_level(struct smu_context *smu,
    1559             :                                           enum amd_dpm_forced_level level)
    1560             : {
    1561             :         uint32_t smu_version;
    1562             :         int ret;
    1563             : 
    1564           0 :         ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
    1565           0 :         if (ret) {
    1566           0 :                 dev_err(smu->adev->dev, "Failed to get smu version!\n");
    1567           0 :                 return ret;
    1568             :         }
    1569             : 
    1570           0 :         switch (level) {
    1571             :         case AMD_DPM_FORCED_LEVEL_HIGH:
    1572             :         case AMD_DPM_FORCED_LEVEL_LOW:
    1573             :         case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
    1574             :         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
    1575             :         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
    1576             :         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
    1577           0 :                 if ((smu_version >= 0x361200) &&
    1578             :                     (smu_version <= 0x361a00)) {
    1579           0 :                         dev_err(smu->adev->dev, "Forcing clock level is not supported with "
    1580             :                                "54.18 - 54.26(included) SMU firmwares\n");
    1581           0 :                         return -EOPNOTSUPP;
    1582             :                 }
    1583             :                 break;
    1584             :         default:
    1585             :                 break;
    1586             :         }
    1587             : 
    1588           0 :         return smu_v11_0_set_performance_level(smu, level);
    1589             : }
    1590             : 
    1591           0 : static void arcturus_dump_pptable(struct smu_context *smu)
    1592             : {
    1593           0 :         struct smu_table_context *table_context = &smu->smu_table;
    1594           0 :         PPTable_t *pptable = table_context->driver_pptable;
    1595             :         int i;
    1596             : 
    1597           0 :         dev_info(smu->adev->dev, "Dumped PPTable:\n");
    1598             : 
    1599           0 :         dev_info(smu->adev->dev, "Version = 0x%08x\n", pptable->Version);
    1600             : 
    1601           0 :         dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", pptable->FeaturesToRun[0]);
    1602           0 :         dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", pptable->FeaturesToRun[1]);
    1603             : 
    1604           0 :         for (i = 0; i < PPT_THROTTLER_COUNT; i++) {
    1605           0 :                 dev_info(smu->adev->dev, "SocketPowerLimitAc[%d] = %d\n", i, pptable->SocketPowerLimitAc[i]);
    1606           0 :                 dev_info(smu->adev->dev, "SocketPowerLimitAcTau[%d] = %d\n", i, pptable->SocketPowerLimitAcTau[i]);
    1607             :         }
    1608             : 
    1609           0 :         dev_info(smu->adev->dev, "TdcLimitSoc = %d\n", pptable->TdcLimitSoc);
    1610           0 :         dev_info(smu->adev->dev, "TdcLimitSocTau = %d\n", pptable->TdcLimitSocTau);
    1611           0 :         dev_info(smu->adev->dev, "TdcLimitGfx = %d\n", pptable->TdcLimitGfx);
    1612           0 :         dev_info(smu->adev->dev, "TdcLimitGfxTau = %d\n", pptable->TdcLimitGfxTau);
    1613             : 
    1614           0 :         dev_info(smu->adev->dev, "TedgeLimit = %d\n", pptable->TedgeLimit);
    1615           0 :         dev_info(smu->adev->dev, "ThotspotLimit = %d\n", pptable->ThotspotLimit);
    1616           0 :         dev_info(smu->adev->dev, "TmemLimit = %d\n", pptable->TmemLimit);
    1617           0 :         dev_info(smu->adev->dev, "Tvr_gfxLimit = %d\n", pptable->Tvr_gfxLimit);
    1618           0 :         dev_info(smu->adev->dev, "Tvr_memLimit = %d\n", pptable->Tvr_memLimit);
    1619           0 :         dev_info(smu->adev->dev, "Tvr_socLimit = %d\n", pptable->Tvr_socLimit);
    1620           0 :         dev_info(smu->adev->dev, "FitLimit = %d\n", pptable->FitLimit);
    1621             : 
    1622           0 :         dev_info(smu->adev->dev, "PpmPowerLimit = %d\n", pptable->PpmPowerLimit);
    1623           0 :         dev_info(smu->adev->dev, "PpmTemperatureThreshold = %d\n", pptable->PpmTemperatureThreshold);
    1624             : 
    1625           0 :         dev_info(smu->adev->dev, "ThrottlerControlMask = %d\n", pptable->ThrottlerControlMask);
    1626             : 
    1627           0 :         dev_info(smu->adev->dev, "UlvVoltageOffsetGfx = %d\n", pptable->UlvVoltageOffsetGfx);
    1628           0 :         dev_info(smu->adev->dev, "UlvPadding = 0x%08x\n", pptable->UlvPadding);
    1629             : 
    1630           0 :         dev_info(smu->adev->dev, "UlvGfxclkBypass = %d\n", pptable->UlvGfxclkBypass);
    1631           0 :         dev_info(smu->adev->dev, "Padding234[0] = 0x%02x\n", pptable->Padding234[0]);
    1632           0 :         dev_info(smu->adev->dev, "Padding234[1] = 0x%02x\n", pptable->Padding234[1]);
    1633           0 :         dev_info(smu->adev->dev, "Padding234[2] = 0x%02x\n", pptable->Padding234[2]);
    1634             : 
    1635           0 :         dev_info(smu->adev->dev, "MinVoltageGfx = %d\n", pptable->MinVoltageGfx);
    1636           0 :         dev_info(smu->adev->dev, "MinVoltageSoc = %d\n", pptable->MinVoltageSoc);
    1637           0 :         dev_info(smu->adev->dev, "MaxVoltageGfx = %d\n", pptable->MaxVoltageGfx);
    1638           0 :         dev_info(smu->adev->dev, "MaxVoltageSoc = %d\n", pptable->MaxVoltageSoc);
    1639             : 
    1640           0 :         dev_info(smu->adev->dev, "LoadLineResistanceGfx = %d\n", pptable->LoadLineResistanceGfx);
    1641           0 :         dev_info(smu->adev->dev, "LoadLineResistanceSoc = %d\n", pptable->LoadLineResistanceSoc);
    1642             : 
    1643           0 :         dev_info(smu->adev->dev, "[PPCLK_GFXCLK]\n"
    1644             :                         "  .VoltageMode          = 0x%02x\n"
    1645             :                         "  .SnapToDiscrete       = 0x%02x\n"
    1646             :                         "  .NumDiscreteLevels    = 0x%02x\n"
    1647             :                         "  .padding              = 0x%02x\n"
    1648             :                         "  .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
    1649             :                         "  .SsCurve            {a = 0x%08x b = 0x%08x c = 0x%08x}\n"
    1650             :                         "  .SsFmin               = 0x%04x\n"
    1651             :                         "  .Padding_16           = 0x%04x\n",
    1652             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].VoltageMode,
    1653             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete,
    1654             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].NumDiscreteLevels,
    1655             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].padding,
    1656             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.m,
    1657             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.b,
    1658             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.a,
    1659             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.b,
    1660             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.c,
    1661             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].SsFmin,
    1662             :                         pptable->DpmDescriptor[PPCLK_GFXCLK].Padding16);
    1663             : 
    1664           0 :         dev_info(smu->adev->dev, "[PPCLK_VCLK]\n"
    1665             :                         "  .VoltageMode          = 0x%02x\n"
    1666             :                         "  .SnapToDiscrete       = 0x%02x\n"
    1667             :                         "  .NumDiscreteLevels    = 0x%02x\n"
    1668             :                         "  .padding              = 0x%02x\n"
    1669             :                         "  .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
    1670             :                         "  .SsCurve            {a = 0x%08x b = 0x%08x c = 0x%08x}\n"
    1671             :                         "  .SsFmin               = 0x%04x\n"
    1672             :                         "  .Padding_16           = 0x%04x\n",
    1673             :                         pptable->DpmDescriptor[PPCLK_VCLK].VoltageMode,
    1674             :                         pptable->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete,
    1675             :                         pptable->DpmDescriptor[PPCLK_VCLK].NumDiscreteLevels,
    1676             :                         pptable->DpmDescriptor[PPCLK_VCLK].padding,
    1677             :                         pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.m,
    1678             :                         pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.b,
    1679             :                         pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.a,
    1680             :                         pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.b,
    1681             :                         pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.c,
    1682             :                         pptable->DpmDescriptor[PPCLK_VCLK].SsFmin,
    1683             :                         pptable->DpmDescriptor[PPCLK_VCLK].Padding16);
    1684             : 
    1685           0 :         dev_info(smu->adev->dev, "[PPCLK_DCLK]\n"
    1686             :                         "  .VoltageMode          = 0x%02x\n"
    1687             :                         "  .SnapToDiscrete       = 0x%02x\n"
    1688             :                         "  .NumDiscreteLevels    = 0x%02x\n"
    1689             :                         "  .padding              = 0x%02x\n"
    1690             :                         "  .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
    1691             :                         "  .SsCurve            {a = 0x%08x b = 0x%08x c = 0x%08x}\n"
    1692             :                         "  .SsFmin               = 0x%04x\n"
    1693             :                         "  .Padding_16           = 0x%04x\n",
    1694             :                         pptable->DpmDescriptor[PPCLK_DCLK].VoltageMode,
    1695             :                         pptable->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete,
    1696             :                         pptable->DpmDescriptor[PPCLK_DCLK].NumDiscreteLevels,
    1697             :                         pptable->DpmDescriptor[PPCLK_DCLK].padding,
    1698             :                         pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.m,
    1699             :                         pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.b,
    1700             :                         pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.a,
    1701             :                         pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.b,
    1702             :                         pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.c,
    1703             :                         pptable->DpmDescriptor[PPCLK_DCLK].SsFmin,
    1704             :                         pptable->DpmDescriptor[PPCLK_DCLK].Padding16);
    1705             : 
    1706           0 :         dev_info(smu->adev->dev, "[PPCLK_SOCCLK]\n"
    1707             :                         "  .VoltageMode          = 0x%02x\n"
    1708             :                         "  .SnapToDiscrete       = 0x%02x\n"
    1709             :                         "  .NumDiscreteLevels    = 0x%02x\n"
    1710             :                         "  .padding              = 0x%02x\n"
    1711             :                         "  .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
    1712             :                         "  .SsCurve            {a = 0x%08x b = 0x%08x c = 0x%08x}\n"
    1713             :                         "  .SsFmin               = 0x%04x\n"
    1714             :                         "  .Padding_16           = 0x%04x\n",
    1715             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].VoltageMode,
    1716             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete,
    1717             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].NumDiscreteLevels,
    1718             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].padding,
    1719             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.m,
    1720             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.b,
    1721             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.a,
    1722             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.b,
    1723             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.c,
    1724             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].SsFmin,
    1725             :                         pptable->DpmDescriptor[PPCLK_SOCCLK].Padding16);
    1726             : 
    1727           0 :         dev_info(smu->adev->dev, "[PPCLK_UCLK]\n"
    1728             :                         "  .VoltageMode          = 0x%02x\n"
    1729             :                         "  .SnapToDiscrete       = 0x%02x\n"
    1730             :                         "  .NumDiscreteLevels    = 0x%02x\n"
    1731             :                         "  .padding              = 0x%02x\n"
    1732             :                         "  .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
    1733             :                         "  .SsCurve            {a = 0x%08x b = 0x%08x c = 0x%08x}\n"
    1734             :                         "  .SsFmin               = 0x%04x\n"
    1735             :                         "  .Padding_16           = 0x%04x\n",
    1736             :                         pptable->DpmDescriptor[PPCLK_UCLK].VoltageMode,
    1737             :                         pptable->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete,
    1738             :                         pptable->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels,
    1739             :                         pptable->DpmDescriptor[PPCLK_UCLK].padding,
    1740             :                         pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.m,
    1741             :                         pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.b,
    1742             :                         pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.a,
    1743             :                         pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.b,
    1744             :                         pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.c,
    1745             :                         pptable->DpmDescriptor[PPCLK_UCLK].SsFmin,
    1746             :                         pptable->DpmDescriptor[PPCLK_UCLK].Padding16);
    1747             : 
    1748           0 :         dev_info(smu->adev->dev, "[PPCLK_FCLK]\n"
    1749             :                         "  .VoltageMode          = 0x%02x\n"
    1750             :                         "  .SnapToDiscrete       = 0x%02x\n"
    1751             :                         "  .NumDiscreteLevels    = 0x%02x\n"
    1752             :                         "  .padding              = 0x%02x\n"
    1753             :                         "  .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
    1754             :                         "  .SsCurve            {a = 0x%08x b = 0x%08x c = 0x%08x}\n"
    1755             :                         "  .SsFmin               = 0x%04x\n"
    1756             :                         "  .Padding_16           = 0x%04x\n",
    1757             :                         pptable->DpmDescriptor[PPCLK_FCLK].VoltageMode,
    1758             :                         pptable->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete,
    1759             :                         pptable->DpmDescriptor[PPCLK_FCLK].NumDiscreteLevels,
    1760             :                         pptable->DpmDescriptor[PPCLK_FCLK].padding,
    1761             :                         pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.m,
    1762             :                         pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.b,
    1763             :                         pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.a,
    1764             :                         pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.b,
    1765             :                         pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.c,
    1766             :                         pptable->DpmDescriptor[PPCLK_FCLK].SsFmin,
    1767             :                         pptable->DpmDescriptor[PPCLK_FCLK].Padding16);
    1768             : 
    1769             : 
    1770           0 :         dev_info(smu->adev->dev, "FreqTableGfx\n");
    1771           0 :         for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++)
    1772           0 :                 dev_info(smu->adev->dev, "  .[%02d] = %d\n", i, pptable->FreqTableGfx[i]);
    1773             : 
    1774           0 :         dev_info(smu->adev->dev, "FreqTableVclk\n");
    1775           0 :         for (i = 0; i < NUM_VCLK_DPM_LEVELS; i++)
    1776           0 :                 dev_info(smu->adev->dev, "  .[%02d] = %d\n", i, pptable->FreqTableVclk[i]);
    1777             : 
    1778           0 :         dev_info(smu->adev->dev, "FreqTableDclk\n");
    1779           0 :         for (i = 0; i < NUM_DCLK_DPM_LEVELS; i++)
    1780           0 :                 dev_info(smu->adev->dev, "  .[%02d] = %d\n", i, pptable->FreqTableDclk[i]);
    1781             : 
    1782           0 :         dev_info(smu->adev->dev, "FreqTableSocclk\n");
    1783           0 :         for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++)
    1784           0 :                 dev_info(smu->adev->dev, "  .[%02d] = %d\n", i, pptable->FreqTableSocclk[i]);
    1785             : 
    1786           0 :         dev_info(smu->adev->dev, "FreqTableUclk\n");
    1787           0 :         for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++)
    1788           0 :                 dev_info(smu->adev->dev, "  .[%02d] = %d\n", i, pptable->FreqTableUclk[i]);
    1789             : 
    1790           0 :         dev_info(smu->adev->dev, "FreqTableFclk\n");
    1791           0 :         for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++)
    1792           0 :                 dev_info(smu->adev->dev, "  .[%02d] = %d\n", i, pptable->FreqTableFclk[i]);
    1793             : 
    1794           0 :         dev_info(smu->adev->dev, "Mp0clkFreq\n");
    1795           0 :         for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++)
    1796           0 :                 dev_info(smu->adev->dev, "  .[%d] = %d\n", i, pptable->Mp0clkFreq[i]);
    1797             : 
    1798           0 :         dev_info(smu->adev->dev, "Mp0DpmVoltage\n");
    1799           0 :         for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++)
    1800           0 :                 dev_info(smu->adev->dev, "  .[%d] = %d\n", i, pptable->Mp0DpmVoltage[i]);
    1801             : 
    1802           0 :         dev_info(smu->adev->dev, "GfxclkFidle = 0x%x\n", pptable->GfxclkFidle);
    1803           0 :         dev_info(smu->adev->dev, "GfxclkSlewRate = 0x%x\n", pptable->GfxclkSlewRate);
    1804           0 :         dev_info(smu->adev->dev, "Padding567[0] = 0x%x\n", pptable->Padding567[0]);
    1805           0 :         dev_info(smu->adev->dev, "Padding567[1] = 0x%x\n", pptable->Padding567[1]);
    1806           0 :         dev_info(smu->adev->dev, "Padding567[2] = 0x%x\n", pptable->Padding567[2]);
    1807           0 :         dev_info(smu->adev->dev, "Padding567[3] = 0x%x\n", pptable->Padding567[3]);
    1808           0 :         dev_info(smu->adev->dev, "GfxclkDsMaxFreq = %d\n", pptable->GfxclkDsMaxFreq);
    1809           0 :         dev_info(smu->adev->dev, "GfxclkSource = 0x%x\n", pptable->GfxclkSource);
    1810           0 :         dev_info(smu->adev->dev, "Padding456 = 0x%x\n", pptable->Padding456);
    1811             : 
    1812           0 :         dev_info(smu->adev->dev, "EnableTdpm = %d\n", pptable->EnableTdpm);
    1813           0 :         dev_info(smu->adev->dev, "TdpmHighHystTemperature = %d\n", pptable->TdpmHighHystTemperature);
    1814           0 :         dev_info(smu->adev->dev, "TdpmLowHystTemperature = %d\n", pptable->TdpmLowHystTemperature);
    1815           0 :         dev_info(smu->adev->dev, "GfxclkFreqHighTempLimit = %d\n", pptable->GfxclkFreqHighTempLimit);
    1816             : 
    1817           0 :         dev_info(smu->adev->dev, "FanStopTemp = %d\n", pptable->FanStopTemp);
    1818           0 :         dev_info(smu->adev->dev, "FanStartTemp = %d\n", pptable->FanStartTemp);
    1819             : 
    1820           0 :         dev_info(smu->adev->dev, "FanGainEdge = %d\n", pptable->FanGainEdge);
    1821           0 :         dev_info(smu->adev->dev, "FanGainHotspot = %d\n", pptable->FanGainHotspot);
    1822           0 :         dev_info(smu->adev->dev, "FanGainVrGfx = %d\n", pptable->FanGainVrGfx);
    1823           0 :         dev_info(smu->adev->dev, "FanGainVrSoc = %d\n", pptable->FanGainVrSoc);
    1824           0 :         dev_info(smu->adev->dev, "FanGainVrMem = %d\n", pptable->FanGainVrMem);
    1825           0 :         dev_info(smu->adev->dev, "FanGainHbm = %d\n", pptable->FanGainHbm);
    1826             : 
    1827           0 :         dev_info(smu->adev->dev, "FanPwmMin = %d\n", pptable->FanPwmMin);
    1828           0 :         dev_info(smu->adev->dev, "FanAcousticLimitRpm = %d\n", pptable->FanAcousticLimitRpm);
    1829           0 :         dev_info(smu->adev->dev, "FanThrottlingRpm = %d\n", pptable->FanThrottlingRpm);
    1830           0 :         dev_info(smu->adev->dev, "FanMaximumRpm = %d\n", pptable->FanMaximumRpm);
    1831           0 :         dev_info(smu->adev->dev, "FanTargetTemperature = %d\n", pptable->FanTargetTemperature);
    1832           0 :         dev_info(smu->adev->dev, "FanTargetGfxclk = %d\n", pptable->FanTargetGfxclk);
    1833           0 :         dev_info(smu->adev->dev, "FanZeroRpmEnable = %d\n", pptable->FanZeroRpmEnable);
    1834           0 :         dev_info(smu->adev->dev, "FanTachEdgePerRev = %d\n", pptable->FanTachEdgePerRev);
    1835           0 :         dev_info(smu->adev->dev, "FanTempInputSelect = %d\n", pptable->FanTempInputSelect);
    1836             : 
    1837           0 :         dev_info(smu->adev->dev, "FuzzyFan_ErrorSetDelta = %d\n", pptable->FuzzyFan_ErrorSetDelta);
    1838           0 :         dev_info(smu->adev->dev, "FuzzyFan_ErrorRateSetDelta = %d\n", pptable->FuzzyFan_ErrorRateSetDelta);
    1839           0 :         dev_info(smu->adev->dev, "FuzzyFan_PwmSetDelta = %d\n", pptable->FuzzyFan_PwmSetDelta);
    1840           0 :         dev_info(smu->adev->dev, "FuzzyFan_Reserved = %d\n", pptable->FuzzyFan_Reserved);
    1841             : 
    1842           0 :         dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_GFX]);
    1843           0 :         dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_SOC]);
    1844           0 :         dev_info(smu->adev->dev, "Padding8_Avfs[0] = %d\n", pptable->Padding8_Avfs[0]);
    1845           0 :         dev_info(smu->adev->dev, "Padding8_Avfs[1] = %d\n", pptable->Padding8_Avfs[1]);
    1846             : 
    1847           0 :         dev_info(smu->adev->dev, "dBtcGbGfxPll{a = 0x%x b = 0x%x c = 0x%x}\n",
    1848             :                         pptable->dBtcGbGfxPll.a,
    1849             :                         pptable->dBtcGbGfxPll.b,
    1850             :                         pptable->dBtcGbGfxPll.c);
    1851           0 :         dev_info(smu->adev->dev, "dBtcGbGfxAfll{a = 0x%x b = 0x%x c = 0x%x}\n",
    1852             :                         pptable->dBtcGbGfxAfll.a,
    1853             :                         pptable->dBtcGbGfxAfll.b,
    1854             :                         pptable->dBtcGbGfxAfll.c);
    1855           0 :         dev_info(smu->adev->dev, "dBtcGbSoc{a = 0x%x b = 0x%x c = 0x%x}\n",
    1856             :                         pptable->dBtcGbSoc.a,
    1857             :                         pptable->dBtcGbSoc.b,
    1858             :                         pptable->dBtcGbSoc.c);
    1859             : 
    1860           0 :         dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_GFX]{m = 0x%x b = 0x%x}\n",
    1861             :                         pptable->qAgingGb[AVFS_VOLTAGE_GFX].m,
    1862             :                         pptable->qAgingGb[AVFS_VOLTAGE_GFX].b);
    1863           0 :         dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_SOC]{m = 0x%x b = 0x%x}\n",
    1864             :                         pptable->qAgingGb[AVFS_VOLTAGE_SOC].m,
    1865             :                         pptable->qAgingGb[AVFS_VOLTAGE_SOC].b);
    1866             : 
    1867           0 :         dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n",
    1868             :                         pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].a,
    1869             :                         pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].b,
    1870             :                         pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].c);
    1871           0 :         dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n",
    1872             :                         pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].a,
    1873             :                         pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].b,
    1874             :                         pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].c);
    1875             : 
    1876           0 :         dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_GFX]);
    1877           0 :         dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_SOC]);
    1878             : 
    1879           0 :         dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_GFX]);
    1880           0 :         dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_SOC]);
    1881           0 :         dev_info(smu->adev->dev, "Padding8_GfxBtc[0] = 0x%x\n", pptable->Padding8_GfxBtc[0]);
    1882           0 :         dev_info(smu->adev->dev, "Padding8_GfxBtc[1] = 0x%x\n", pptable->Padding8_GfxBtc[1]);
    1883             : 
    1884           0 :         dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_GFX]);
    1885           0 :         dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_SOC]);
    1886           0 :         dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_GFX]);
    1887           0 :         dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_SOC]);
    1888             : 
    1889           0 :         dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_GFX]);
    1890           0 :         dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_SOC]);
    1891             : 
    1892           0 :         dev_info(smu->adev->dev, "XgmiDpmPstates\n");
    1893           0 :         for (i = 0; i < NUM_XGMI_LEVELS; i++)
    1894           0 :                 dev_info(smu->adev->dev, "  .[%d] = %d\n", i, pptable->XgmiDpmPstates[i]);
    1895           0 :         dev_info(smu->adev->dev, "XgmiDpmSpare[0] = 0x%02x\n", pptable->XgmiDpmSpare[0]);
    1896           0 :         dev_info(smu->adev->dev, "XgmiDpmSpare[1] = 0x%02x\n", pptable->XgmiDpmSpare[1]);
    1897             : 
    1898           0 :         dev_info(smu->adev->dev, "VDDGFX_TVmin = %d\n", pptable->VDDGFX_TVmin);
    1899           0 :         dev_info(smu->adev->dev, "VDDSOC_TVmin = %d\n", pptable->VDDSOC_TVmin);
    1900           0 :         dev_info(smu->adev->dev, "VDDGFX_Vmin_HiTemp = %d\n", pptable->VDDGFX_Vmin_HiTemp);
    1901           0 :         dev_info(smu->adev->dev, "VDDGFX_Vmin_LoTemp = %d\n", pptable->VDDGFX_Vmin_LoTemp);
    1902           0 :         dev_info(smu->adev->dev, "VDDSOC_Vmin_HiTemp = %d\n", pptable->VDDSOC_Vmin_HiTemp);
    1903           0 :         dev_info(smu->adev->dev, "VDDSOC_Vmin_LoTemp = %d\n", pptable->VDDSOC_Vmin_LoTemp);
    1904           0 :         dev_info(smu->adev->dev, "VDDGFX_TVminHystersis = %d\n", pptable->VDDGFX_TVminHystersis);
    1905           0 :         dev_info(smu->adev->dev, "VDDSOC_TVminHystersis = %d\n", pptable->VDDSOC_TVminHystersis);
    1906             : 
    1907           0 :         dev_info(smu->adev->dev, "DebugOverrides = 0x%x\n", pptable->DebugOverrides);
    1908           0 :         dev_info(smu->adev->dev, "ReservedEquation0{a = 0x%x b = 0x%x c = 0x%x}\n",
    1909             :                         pptable->ReservedEquation0.a,
    1910             :                         pptable->ReservedEquation0.b,
    1911             :                         pptable->ReservedEquation0.c);
    1912           0 :         dev_info(smu->adev->dev, "ReservedEquation1{a = 0x%x b = 0x%x c = 0x%x}\n",
    1913             :                         pptable->ReservedEquation1.a,
    1914             :                         pptable->ReservedEquation1.b,
    1915             :                         pptable->ReservedEquation1.c);
    1916           0 :         dev_info(smu->adev->dev, "ReservedEquation2{a = 0x%x b = 0x%x c = 0x%x}\n",
    1917             :                         pptable->ReservedEquation2.a,
    1918             :                         pptable->ReservedEquation2.b,
    1919             :                         pptable->ReservedEquation2.c);
    1920           0 :         dev_info(smu->adev->dev, "ReservedEquation3{a = 0x%x b = 0x%x c = 0x%x}\n",
    1921             :                         pptable->ReservedEquation3.a,
    1922             :                         pptable->ReservedEquation3.b,
    1923             :                         pptable->ReservedEquation3.c);
    1924             : 
    1925           0 :         dev_info(smu->adev->dev, "MinVoltageUlvGfx = %d\n", pptable->MinVoltageUlvGfx);
    1926           0 :         dev_info(smu->adev->dev, "PaddingUlv = %d\n", pptable->PaddingUlv);
    1927             : 
    1928           0 :         dev_info(smu->adev->dev, "TotalPowerConfig = %d\n", pptable->TotalPowerConfig);
    1929           0 :         dev_info(smu->adev->dev, "TotalPowerSpare1 = %d\n", pptable->TotalPowerSpare1);
    1930           0 :         dev_info(smu->adev->dev, "TotalPowerSpare2 = %d\n", pptable->TotalPowerSpare2);
    1931             : 
    1932           0 :         dev_info(smu->adev->dev, "PccThresholdLow = %d\n", pptable->PccThresholdLow);
    1933           0 :         dev_info(smu->adev->dev, "PccThresholdHigh = %d\n", pptable->PccThresholdHigh);
    1934             : 
    1935           0 :         dev_info(smu->adev->dev, "Board Parameters:\n");
    1936           0 :         dev_info(smu->adev->dev, "MaxVoltageStepGfx = 0x%x\n", pptable->MaxVoltageStepGfx);
    1937           0 :         dev_info(smu->adev->dev, "MaxVoltageStepSoc = 0x%x\n", pptable->MaxVoltageStepSoc);
    1938             : 
    1939           0 :         dev_info(smu->adev->dev, "VddGfxVrMapping = 0x%x\n", pptable->VddGfxVrMapping);
    1940           0 :         dev_info(smu->adev->dev, "VddSocVrMapping = 0x%x\n", pptable->VddSocVrMapping);
    1941           0 :         dev_info(smu->adev->dev, "VddMemVrMapping = 0x%x\n", pptable->VddMemVrMapping);
    1942           0 :         dev_info(smu->adev->dev, "BoardVrMapping = 0x%x\n", pptable->BoardVrMapping);
    1943             : 
    1944           0 :         dev_info(smu->adev->dev, "GfxUlvPhaseSheddingMask = 0x%x\n", pptable->GfxUlvPhaseSheddingMask);
    1945           0 :         dev_info(smu->adev->dev, "ExternalSensorPresent = 0x%x\n", pptable->ExternalSensorPresent);
    1946             : 
    1947           0 :         dev_info(smu->adev->dev, "GfxMaxCurrent = 0x%x\n", pptable->GfxMaxCurrent);
    1948           0 :         dev_info(smu->adev->dev, "GfxOffset = 0x%x\n", pptable->GfxOffset);
    1949           0 :         dev_info(smu->adev->dev, "Padding_TelemetryGfx = 0x%x\n", pptable->Padding_TelemetryGfx);
    1950             : 
    1951           0 :         dev_info(smu->adev->dev, "SocMaxCurrent = 0x%x\n", pptable->SocMaxCurrent);
    1952           0 :         dev_info(smu->adev->dev, "SocOffset = 0x%x\n", pptable->SocOffset);
    1953           0 :         dev_info(smu->adev->dev, "Padding_TelemetrySoc = 0x%x\n", pptable->Padding_TelemetrySoc);
    1954             : 
    1955           0 :         dev_info(smu->adev->dev, "MemMaxCurrent = 0x%x\n", pptable->MemMaxCurrent);
    1956           0 :         dev_info(smu->adev->dev, "MemOffset = 0x%x\n", pptable->MemOffset);
    1957           0 :         dev_info(smu->adev->dev, "Padding_TelemetryMem = 0x%x\n", pptable->Padding_TelemetryMem);
    1958             : 
    1959           0 :         dev_info(smu->adev->dev, "BoardMaxCurrent = 0x%x\n", pptable->BoardMaxCurrent);
    1960           0 :         dev_info(smu->adev->dev, "BoardOffset = 0x%x\n", pptable->BoardOffset);
    1961           0 :         dev_info(smu->adev->dev, "Padding_TelemetryBoardInput = 0x%x\n", pptable->Padding_TelemetryBoardInput);
    1962             : 
    1963           0 :         dev_info(smu->adev->dev, "VR0HotGpio = %d\n", pptable->VR0HotGpio);
    1964           0 :         dev_info(smu->adev->dev, "VR0HotPolarity = %d\n", pptable->VR0HotPolarity);
    1965           0 :         dev_info(smu->adev->dev, "VR1HotGpio = %d\n", pptable->VR1HotGpio);
    1966           0 :         dev_info(smu->adev->dev, "VR1HotPolarity = %d\n", pptable->VR1HotPolarity);
    1967             : 
    1968           0 :         dev_info(smu->adev->dev, "PllGfxclkSpreadEnabled = %d\n", pptable->PllGfxclkSpreadEnabled);
    1969           0 :         dev_info(smu->adev->dev, "PllGfxclkSpreadPercent = %d\n", pptable->PllGfxclkSpreadPercent);
    1970           0 :         dev_info(smu->adev->dev, "PllGfxclkSpreadFreq = %d\n", pptable->PllGfxclkSpreadFreq);
    1971             : 
    1972           0 :         dev_info(smu->adev->dev, "UclkSpreadEnabled = %d\n", pptable->UclkSpreadEnabled);
    1973           0 :         dev_info(smu->adev->dev, "UclkSpreadPercent = %d\n", pptable->UclkSpreadPercent);
    1974           0 :         dev_info(smu->adev->dev, "UclkSpreadFreq = %d\n", pptable->UclkSpreadFreq);
    1975             : 
    1976           0 :         dev_info(smu->adev->dev, "FclkSpreadEnabled = %d\n", pptable->FclkSpreadEnabled);
    1977           0 :         dev_info(smu->adev->dev, "FclkSpreadPercent = %d\n", pptable->FclkSpreadPercent);
    1978           0 :         dev_info(smu->adev->dev, "FclkSpreadFreq = %d\n", pptable->FclkSpreadFreq);
    1979             : 
    1980           0 :         dev_info(smu->adev->dev, "FllGfxclkSpreadEnabled = %d\n", pptable->FllGfxclkSpreadEnabled);
    1981           0 :         dev_info(smu->adev->dev, "FllGfxclkSpreadPercent = %d\n", pptable->FllGfxclkSpreadPercent);
    1982           0 :         dev_info(smu->adev->dev, "FllGfxclkSpreadFreq = %d\n", pptable->FllGfxclkSpreadFreq);
    1983             : 
    1984           0 :         for (i = 0; i < NUM_I2C_CONTROLLERS; i++) {
    1985           0 :                 dev_info(smu->adev->dev, "I2cControllers[%d]:\n", i);
    1986           0 :                 dev_info(smu->adev->dev, "                   .Enabled = %d\n",
    1987             :                                 pptable->I2cControllers[i].Enabled);
    1988           0 :                 dev_info(smu->adev->dev, "                   .SlaveAddress = 0x%x\n",
    1989             :                                 pptable->I2cControllers[i].SlaveAddress);
    1990           0 :                 dev_info(smu->adev->dev, "                   .ControllerPort = %d\n",
    1991             :                                 pptable->I2cControllers[i].ControllerPort);
    1992           0 :                 dev_info(smu->adev->dev, "                   .ControllerName = %d\n",
    1993             :                                 pptable->I2cControllers[i].ControllerName);
    1994           0 :                 dev_info(smu->adev->dev, "                   .ThermalThrottler = %d\n",
    1995             :                                 pptable->I2cControllers[i].ThermalThrotter);
    1996           0 :                 dev_info(smu->adev->dev, "                   .I2cProtocol = %d\n",
    1997             :                                 pptable->I2cControllers[i].I2cProtocol);
    1998           0 :                 dev_info(smu->adev->dev, "                   .Speed = %d\n",
    1999             :                                 pptable->I2cControllers[i].Speed);
    2000             :         }
    2001             : 
    2002           0 :         dev_info(smu->adev->dev, "MemoryChannelEnabled = %d\n", pptable->MemoryChannelEnabled);
    2003           0 :         dev_info(smu->adev->dev, "DramBitWidth = %d\n", pptable->DramBitWidth);
    2004             : 
    2005           0 :         dev_info(smu->adev->dev, "TotalBoardPower = %d\n", pptable->TotalBoardPower);
    2006             : 
    2007           0 :         dev_info(smu->adev->dev, "XgmiLinkSpeed\n");
    2008           0 :         for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++)
    2009           0 :                 dev_info(smu->adev->dev, "  .[%d] = %d\n", i, pptable->XgmiLinkSpeed[i]);
    2010           0 :         dev_info(smu->adev->dev, "XgmiLinkWidth\n");
    2011           0 :         for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++)
    2012           0 :                 dev_info(smu->adev->dev, "  .[%d] = %d\n", i, pptable->XgmiLinkWidth[i]);
    2013           0 :         dev_info(smu->adev->dev, "XgmiFclkFreq\n");
    2014           0 :         for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++)
    2015           0 :                 dev_info(smu->adev->dev, "  .[%d] = %d\n", i, pptable->XgmiFclkFreq[i]);
    2016           0 :         dev_info(smu->adev->dev, "XgmiSocVoltage\n");
    2017           0 :         for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++)
    2018           0 :                 dev_info(smu->adev->dev, "  .[%d] = %d\n", i, pptable->XgmiSocVoltage[i]);
    2019             : 
    2020           0 : }
    2021             : 
    2022           0 : static bool arcturus_is_dpm_running(struct smu_context *smu)
    2023             : {
    2024           0 :         int ret = 0;
    2025             :         uint64_t feature_enabled;
    2026             : 
    2027           0 :         ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
    2028           0 :         if (ret)
    2029             :                 return false;
    2030             : 
    2031           0 :         return !!(feature_enabled & SMC_DPM_FEATURE);
    2032             : }
    2033             : 
    2034           0 : static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
    2035             : {
    2036           0 :         int ret = 0;
    2037             : 
    2038           0 :         if (enable) {
    2039           0 :                 if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_DPM_BIT)) {
    2040           0 :                         ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_DPM_BIT, 1);
    2041           0 :                         if (ret) {
    2042           0 :                                 dev_err(smu->adev->dev, "[EnableVCNDPM] failed!\n");
    2043           0 :                                 return ret;
    2044             :                         }
    2045             :                 }
    2046             :         } else {
    2047           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_DPM_BIT)) {
    2048           0 :                         ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_DPM_BIT, 0);
    2049           0 :                         if (ret) {
    2050           0 :                                 dev_err(smu->adev->dev, "[DisableVCNDPM] failed!\n");
    2051           0 :                                 return ret;
    2052             :                         }
    2053             :                 }
    2054             :         }
    2055             : 
    2056             :         return ret;
    2057             : }
    2058             : 
    2059           0 : static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
    2060             :                              struct i2c_msg *msg, int num_msgs)
    2061             : {
    2062           0 :         struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
    2063           0 :         struct amdgpu_device *adev = smu_i2c->adev;
    2064           0 :         struct smu_context *smu = adev->powerplay.pp_handle;
    2065           0 :         struct smu_table_context *smu_table = &smu->smu_table;
    2066           0 :         struct smu_table *table = &smu_table->driver_table;
    2067           0 :         SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
    2068             :         int i, j, r, c;
    2069             :         u16 dir;
    2070             : 
    2071           0 :         if (!adev->pm.dpm_enabled)
    2072             :                 return -EBUSY;
    2073             : 
    2074           0 :         req = kzalloc(sizeof(*req), GFP_KERNEL);
    2075           0 :         if (!req)
    2076             :                 return -ENOMEM;
    2077             : 
    2078           0 :         req->I2CcontrollerPort = smu_i2c->port;
    2079           0 :         req->I2CSpeed = I2C_SPEED_FAST_400K;
    2080           0 :         req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
    2081           0 :         dir = msg[0].flags & I2C_M_RD;
    2082             : 
    2083           0 :         for (c = i = 0; i < num_msgs; i++) {
    2084           0 :                 for (j = 0; j < msg[i].len; j++, c++) {
    2085           0 :                         SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
    2086             : 
    2087           0 :                         if (!(msg[i].flags & I2C_M_RD)) {
    2088             :                                 /* write */
    2089           0 :                                 cmd->Cmd = I2C_CMD_WRITE;
    2090           0 :                                 cmd->RegisterAddr = msg[i].buf[j];
    2091             :                         }
    2092             : 
    2093           0 :                         if ((dir ^ msg[i].flags) & I2C_M_RD) {
    2094             :                                 /* The direction changes.
    2095             :                                  */
    2096           0 :                                 dir = msg[i].flags & I2C_M_RD;
    2097           0 :                                 cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
    2098             :                         }
    2099             : 
    2100           0 :                         req->NumCmds++;
    2101             : 
    2102             :                         /*
    2103             :                          * Insert STOP if we are at the last byte of either last
    2104             :                          * message for the transaction or the client explicitly
    2105             :                          * requires a STOP at this particular message.
    2106             :                          */
    2107           0 :                         if ((j == msg[i].len - 1) &&
    2108           0 :                             ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
    2109           0 :                                 cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
    2110           0 :                                 cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
    2111             :                         }
    2112             :                 }
    2113             :         }
    2114           0 :         mutex_lock(&adev->pm.mutex);
    2115           0 :         r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
    2116           0 :         mutex_unlock(&adev->pm.mutex);
    2117           0 :         if (r)
    2118             :                 goto fail;
    2119             : 
    2120           0 :         for (c = i = 0; i < num_msgs; i++) {
    2121           0 :                 if (!(msg[i].flags & I2C_M_RD)) {
    2122           0 :                         c += msg[i].len;
    2123           0 :                         continue;
    2124             :                 }
    2125           0 :                 for (j = 0; j < msg[i].len; j++, c++) {
    2126           0 :                         SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
    2127             : 
    2128           0 :                         msg[i].buf[j] = cmd->Data;
    2129             :                 }
    2130             :         }
    2131             :         r = num_msgs;
    2132             : fail:
    2133           0 :         kfree(req);
    2134           0 :         return r;
    2135             : }
    2136             : 
    2137           0 : static u32 arcturus_i2c_func(struct i2c_adapter *adap)
    2138             : {
    2139           0 :         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
    2140             : }
    2141             : 
    2142             : 
    2143             : static const struct i2c_algorithm arcturus_i2c_algo = {
    2144             :         .master_xfer = arcturus_i2c_xfer,
    2145             :         .functionality = arcturus_i2c_func,
    2146             : };
    2147             : 
    2148             : 
    2149             : static const struct i2c_adapter_quirks arcturus_i2c_control_quirks = {
    2150             :         .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
    2151             :         .max_read_len  = MAX_SW_I2C_COMMANDS,
    2152             :         .max_write_len = MAX_SW_I2C_COMMANDS,
    2153             :         .max_comb_1st_msg_len = 2,
    2154             :         .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
    2155             : };
    2156             : 
    2157           0 : static int arcturus_i2c_control_init(struct smu_context *smu)
    2158             : {
    2159           0 :         struct amdgpu_device *adev = smu->adev;
    2160             :         int res, i;
    2161             : 
    2162           0 :         for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
    2163           0 :                 struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
    2164           0 :                 struct i2c_adapter *control = &smu_i2c->adapter;
    2165             : 
    2166           0 :                 smu_i2c->adev = adev;
    2167           0 :                 smu_i2c->port = i;
    2168           0 :                 mutex_init(&smu_i2c->mutex);
    2169           0 :                 control->owner = THIS_MODULE;
    2170           0 :                 control->class = I2C_CLASS_HWMON;
    2171           0 :                 control->dev.parent = &adev->pdev->dev;
    2172           0 :                 control->algo = &arcturus_i2c_algo;
    2173           0 :                 control->quirks = &arcturus_i2c_control_quirks;
    2174           0 :                 snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i);
    2175           0 :                 i2c_set_adapdata(control, smu_i2c);
    2176             : 
    2177           0 :                 res = i2c_add_adapter(control);
    2178           0 :                 if (res) {
    2179           0 :                         DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
    2180             :                         goto Out_err;
    2181             :                 }
    2182             :         }
    2183             : 
    2184           0 :         adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
    2185           0 :         adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter;
    2186             : 
    2187           0 :         return 0;
    2188             : Out_err:
    2189           0 :         for ( ; i >= 0; i--) {
    2190           0 :                 struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
    2191           0 :                 struct i2c_adapter *control = &smu_i2c->adapter;
    2192             : 
    2193           0 :                 i2c_del_adapter(control);
    2194             :         }
    2195             :         return res;
    2196             : }
    2197             : 
    2198           0 : static void arcturus_i2c_control_fini(struct smu_context *smu)
    2199             : {
    2200           0 :         struct amdgpu_device *adev = smu->adev;
    2201             :         int i;
    2202             : 
    2203           0 :         for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
    2204           0 :                 struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
    2205           0 :                 struct i2c_adapter *control = &smu_i2c->adapter;
    2206             : 
    2207           0 :                 i2c_del_adapter(control);
    2208             :         }
    2209           0 :         adev->pm.ras_eeprom_i2c_bus = NULL;
    2210           0 :         adev->pm.fru_eeprom_i2c_bus = NULL;
    2211           0 : }
    2212             : 
    2213           0 : static void arcturus_get_unique_id(struct smu_context *smu)
    2214             : {
    2215           0 :         struct amdgpu_device *adev = smu->adev;
    2216           0 :         uint32_t top32 = 0, bottom32 = 0, smu_version;
    2217             :         uint64_t id;
    2218             : 
    2219           0 :         if (smu_cmn_get_smc_version(smu, NULL, &smu_version)) {
    2220           0 :                 dev_warn(adev->dev, "Failed to get smu version, cannot get unique_id or serial_number\n");
    2221           0 :                 return;
    2222             :         }
    2223             : 
    2224             :         /* PPSMC_MSG_ReadSerial* is supported by 54.23.0 and onwards */
    2225           0 :         if (smu_version < 0x361700) {
    2226           0 :                 dev_warn(adev->dev, "ReadSerial is only supported by PMFW 54.23.0 and onwards\n");
    2227           0 :                 return;
    2228             :         }
    2229             : 
    2230             :         /* Get the SN to turn into a Unique ID */
    2231           0 :         smu_cmn_send_smc_msg(smu, SMU_MSG_ReadSerialNumTop32, &top32);
    2232           0 :         smu_cmn_send_smc_msg(smu, SMU_MSG_ReadSerialNumBottom32, &bottom32);
    2233             : 
    2234           0 :         id = ((uint64_t)bottom32 << 32) | top32;
    2235           0 :         adev->unique_id = id;
    2236             :         /* For Arcturus-and-later, unique_id == serial_number, so convert it to a
    2237             :          * 16-digit HEX string for convenience and backwards-compatibility
    2238             :          */
    2239           0 :         sprintf(adev->serial, "%llx", id);
    2240             : }
    2241             : 
    2242           0 : static int arcturus_set_df_cstate(struct smu_context *smu,
    2243             :                                   enum pp_df_cstate state)
    2244             : {
    2245             :         uint32_t smu_version;
    2246             :         int ret;
    2247             : 
    2248           0 :         ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
    2249           0 :         if (ret) {
    2250           0 :                 dev_err(smu->adev->dev, "Failed to get smu version!\n");
    2251           0 :                 return ret;
    2252             :         }
    2253             : 
    2254             :         /* PPSMC_MSG_DFCstateControl is supported by 54.15.0 and onwards */
    2255           0 :         if (smu_version < 0x360F00) {
    2256           0 :                 dev_err(smu->adev->dev, "DFCstateControl is only supported by PMFW 54.15.0 and onwards\n");
    2257           0 :                 return -EINVAL;
    2258             :         }
    2259             : 
    2260           0 :         return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state, NULL);
    2261             : }
    2262             : 
    2263           0 : static int arcturus_allow_xgmi_power_down(struct smu_context *smu, bool en)
    2264             : {
    2265             :         uint32_t smu_version;
    2266             :         int ret;
    2267             : 
    2268           0 :         ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
    2269           0 :         if (ret) {
    2270           0 :                 dev_err(smu->adev->dev, "Failed to get smu version!\n");
    2271           0 :                 return ret;
    2272             :         }
    2273             : 
    2274             :         /* PPSMC_MSG_GmiPwrDnControl is supported by 54.23.0 and onwards */
    2275           0 :         if (smu_version < 0x00361700) {
    2276           0 :                 dev_err(smu->adev->dev, "XGMI power down control is only supported by PMFW 54.23.0 and onwards\n");
    2277           0 :                 return -EINVAL;
    2278             :         }
    2279             : 
    2280           0 :         if (en)
    2281           0 :                 return smu_cmn_send_smc_msg_with_param(smu,
    2282             :                                                    SMU_MSG_GmiPwrDnControl,
    2283             :                                                    1,
    2284             :                                                    NULL);
    2285             : 
    2286           0 :         return smu_cmn_send_smc_msg_with_param(smu,
    2287             :                                            SMU_MSG_GmiPwrDnControl,
    2288             :                                            0,
    2289             :                                            NULL);
    2290             : }
    2291             : 
    2292             : static const struct throttling_logging_label {
    2293             :         uint32_t feature_mask;
    2294             :         const char *label;
    2295             : } logging_label[] = {
    2296             :         {(1U << THROTTLER_TEMP_HOTSPOT_BIT), "GPU"},
    2297             :         {(1U << THROTTLER_TEMP_MEM_BIT), "HBM"},
    2298             :         {(1U << THROTTLER_TEMP_VR_GFX_BIT), "VR of GFX rail"},
    2299             :         {(1U << THROTTLER_TEMP_VR_MEM_BIT), "VR of HBM rail"},
    2300             :         {(1U << THROTTLER_TEMP_VR_SOC_BIT), "VR of SOC rail"},
    2301             :         {(1U << THROTTLER_VRHOT0_BIT), "VR0 HOT"},
    2302             :         {(1U << THROTTLER_VRHOT1_BIT), "VR1 HOT"},
    2303             : };
    2304           0 : static void arcturus_log_thermal_throttling_event(struct smu_context *smu)
    2305             : {
    2306             :         int ret;
    2307           0 :         int throttler_idx, throtting_events = 0, buf_idx = 0;
    2308           0 :         struct amdgpu_device *adev = smu->adev;
    2309             :         uint32_t throttler_status;
    2310             :         char log_buf[256];
    2311             : 
    2312           0 :         ret = arcturus_get_smu_metrics_data(smu,
    2313             :                                             METRICS_THROTTLER_STATUS,
    2314             :                                             &throttler_status);
    2315           0 :         if (ret)
    2316           0 :                 return;
    2317             : 
    2318           0 :         memset(log_buf, 0, sizeof(log_buf));
    2319           0 :         for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label);
    2320           0 :              throttler_idx++) {
    2321           0 :                 if (throttler_status & logging_label[throttler_idx].feature_mask) {
    2322           0 :                         throtting_events++;
    2323           0 :                         buf_idx += snprintf(log_buf + buf_idx,
    2324             :                                             sizeof(log_buf) - buf_idx,
    2325             :                                             "%s%s",
    2326             :                                             throtting_events > 1 ? " and " : "",
    2327             :                                             logging_label[throttler_idx].label);
    2328           0 :                         if (buf_idx >= sizeof(log_buf)) {
    2329           0 :                                 dev_err(adev->dev, "buffer overflow!\n");
    2330           0 :                                 log_buf[sizeof(log_buf) - 1] = '\0';
    2331           0 :                                 break;
    2332             :                         }
    2333             :                 }
    2334             :         }
    2335             : 
    2336           0 :         dev_warn(adev->dev, "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n",
    2337             :                         log_buf);
    2338           0 :         kgd2kfd_smi_event_throttle(smu->adev->kfd.dev,
    2339             :                 smu_cmn_get_indep_throttler_status(throttler_status,
    2340             :                                                    arcturus_throttler_map));
    2341             : }
    2342             : 
    2343           0 : static uint16_t arcturus_get_current_pcie_link_speed(struct smu_context *smu)
    2344             : {
    2345           0 :         struct amdgpu_device *adev = smu->adev;
    2346             :         uint32_t esm_ctrl;
    2347             : 
    2348             :         /* TODO: confirm this on real target */
    2349           0 :         esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL);
    2350           0 :         if ((esm_ctrl >> 15) & 0x1FFFF)
    2351           0 :                 return (uint16_t)(((esm_ctrl >> 8) & 0x3F) + 128);
    2352             : 
    2353           0 :         return smu_v11_0_get_current_pcie_link_speed(smu);
    2354             : }
    2355             : 
    2356           0 : static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu,
    2357             :                                         void **table)
    2358             : {
    2359           0 :         struct smu_table_context *smu_table = &smu->smu_table;
    2360           0 :         struct gpu_metrics_v1_3 *gpu_metrics =
    2361             :                 (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
    2362             :         SmuMetrics_t metrics;
    2363           0 :         int ret = 0;
    2364             : 
    2365           0 :         ret = smu_cmn_get_metrics_table(smu,
    2366             :                                         &metrics,
    2367             :                                         true);
    2368           0 :         if (ret)
    2369           0 :                 return ret;
    2370             : 
    2371           0 :         smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
    2372             : 
    2373           0 :         gpu_metrics->temperature_edge = metrics.TemperatureEdge;
    2374           0 :         gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
    2375           0 :         gpu_metrics->temperature_mem = metrics.TemperatureHBM;
    2376           0 :         gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
    2377           0 :         gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
    2378           0 :         gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem;
    2379             : 
    2380           0 :         gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
    2381           0 :         gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
    2382           0 :         gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage;
    2383             : 
    2384           0 :         gpu_metrics->average_socket_power = metrics.AverageSocketPower;
    2385           0 :         gpu_metrics->energy_accumulator = metrics.EnergyAccumulator;
    2386             : 
    2387           0 :         gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
    2388           0 :         gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
    2389           0 :         gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
    2390           0 :         gpu_metrics->average_vclk0_frequency = metrics.AverageVclkFrequency;
    2391           0 :         gpu_metrics->average_dclk0_frequency = metrics.AverageDclkFrequency;
    2392             : 
    2393           0 :         gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
    2394           0 :         gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
    2395           0 :         gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
    2396           0 :         gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
    2397           0 :         gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
    2398             : 
    2399           0 :         gpu_metrics->throttle_status = metrics.ThrottlerStatus;
    2400           0 :         gpu_metrics->indep_throttle_status =
    2401           0 :                         smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
    2402             :                                                            arcturus_throttler_map);
    2403             : 
    2404           0 :         gpu_metrics->current_fan_speed = metrics.CurrFanSpeed;
    2405             : 
    2406           0 :         gpu_metrics->pcie_link_width =
    2407           0 :                         smu_v11_0_get_current_pcie_link_width(smu);
    2408           0 :         gpu_metrics->pcie_link_speed =
    2409           0 :                         arcturus_get_current_pcie_link_speed(smu);
    2410             : 
    2411           0 :         gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
    2412             : 
    2413           0 :         *table = (void *)gpu_metrics;
    2414             : 
    2415           0 :         return sizeof(struct gpu_metrics_v1_3);
    2416             : }
    2417             : 
    2418             : static const struct pptable_funcs arcturus_ppt_funcs = {
    2419             :         /* init dpm */
    2420             :         .get_allowed_feature_mask = arcturus_get_allowed_feature_mask,
    2421             :         /* btc */
    2422             :         .run_btc = arcturus_run_btc,
    2423             :         /* dpm/clk tables */
    2424             :         .set_default_dpm_table = arcturus_set_default_dpm_table,
    2425             :         .populate_umd_state_clk = arcturus_populate_umd_state_clk,
    2426             :         .get_thermal_temperature_range = arcturus_get_thermal_temperature_range,
    2427             :         .print_clk_levels = arcturus_print_clk_levels,
    2428             :         .force_clk_levels = arcturus_force_clk_levels,
    2429             :         .read_sensor = arcturus_read_sensor,
    2430             :         .get_fan_speed_pwm = arcturus_get_fan_speed_pwm,
    2431             :         .get_fan_speed_rpm = arcturus_get_fan_speed_rpm,
    2432             :         .get_power_profile_mode = arcturus_get_power_profile_mode,
    2433             :         .set_power_profile_mode = arcturus_set_power_profile_mode,
    2434             :         .set_performance_level = arcturus_set_performance_level,
    2435             :         /* debug (internal used) */
    2436             :         .dump_pptable = arcturus_dump_pptable,
    2437             :         .get_power_limit = arcturus_get_power_limit,
    2438             :         .is_dpm_running = arcturus_is_dpm_running,
    2439             :         .dpm_set_vcn_enable = arcturus_dpm_set_vcn_enable,
    2440             :         .i2c_init = arcturus_i2c_control_init,
    2441             :         .i2c_fini = arcturus_i2c_control_fini,
    2442             :         .get_unique_id = arcturus_get_unique_id,
    2443             :         .init_microcode = smu_v11_0_init_microcode,
    2444             :         .load_microcode = smu_v11_0_load_microcode,
    2445             :         .fini_microcode = smu_v11_0_fini_microcode,
    2446             :         .init_smc_tables = arcturus_init_smc_tables,
    2447             :         .fini_smc_tables = smu_v11_0_fini_smc_tables,
    2448             :         .init_power = smu_v11_0_init_power,
    2449             :         .fini_power = smu_v11_0_fini_power,
    2450             :         .check_fw_status = smu_v11_0_check_fw_status,
    2451             :         /* pptable related */
    2452             :         .setup_pptable = arcturus_setup_pptable,
    2453             :         .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values,
    2454             :         .check_fw_version = smu_v11_0_check_fw_version,
    2455             :         .write_pptable = smu_cmn_write_pptable,
    2456             :         .set_driver_table_location = smu_v11_0_set_driver_table_location,
    2457             :         .set_tool_table_location = smu_v11_0_set_tool_table_location,
    2458             :         .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
    2459             :         .system_features_control = smu_v11_0_system_features_control,
    2460             :         .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
    2461             :         .send_smc_msg = smu_cmn_send_smc_msg,
    2462             :         .init_display_count = NULL,
    2463             :         .set_allowed_mask = smu_v11_0_set_allowed_mask,
    2464             :         .get_enabled_mask = smu_cmn_get_enabled_mask,
    2465             :         .feature_is_enabled = smu_cmn_feature_is_enabled,
    2466             :         .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
    2467             :         .notify_display_change = NULL,
    2468             :         .set_power_limit = smu_v11_0_set_power_limit,
    2469             :         .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
    2470             :         .enable_thermal_alert = smu_v11_0_enable_thermal_alert,
    2471             :         .disable_thermal_alert = smu_v11_0_disable_thermal_alert,
    2472             :         .set_min_dcef_deep_sleep = NULL,
    2473             :         .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request,
    2474             :         .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
    2475             :         .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
    2476             :         .set_fan_speed_pwm = arcturus_set_fan_speed_pwm,
    2477             :         .set_fan_speed_rpm = arcturus_set_fan_speed_rpm,
    2478             :         .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
    2479             :         .gfx_off_control = smu_v11_0_gfx_off_control,
    2480             :         .register_irq_handler = smu_v11_0_register_irq_handler,
    2481             :         .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
    2482             :         .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
    2483             :         .baco_is_support = smu_v11_0_baco_is_support,
    2484             :         .baco_get_state = smu_v11_0_baco_get_state,
    2485             :         .baco_set_state = smu_v11_0_baco_set_state,
    2486             :         .baco_enter = smu_v11_0_baco_enter,
    2487             :         .baco_exit = smu_v11_0_baco_exit,
    2488             :         .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
    2489             :         .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
    2490             :         .set_df_cstate = arcturus_set_df_cstate,
    2491             :         .allow_xgmi_power_down = arcturus_allow_xgmi_power_down,
    2492             :         .log_thermal_throttling_event = arcturus_log_thermal_throttling_event,
    2493             :         .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
    2494             :         .set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
    2495             :         .get_gpu_metrics = arcturus_get_gpu_metrics,
    2496             :         .gfx_ulv_control = smu_v11_0_gfx_ulv_control,
    2497             :         .deep_sleep_control = smu_v11_0_deep_sleep_control,
    2498             :         .get_fan_parameters = arcturus_get_fan_parameters,
    2499             :         .interrupt_work = smu_v11_0_interrupt_work,
    2500             :         .smu_handle_passthrough_sbr = smu_v11_0_handle_passthrough_sbr,
    2501             :         .set_mp1_state = smu_cmn_set_mp1_state,
    2502             : };
    2503             : 
    2504           0 : void arcturus_set_ppt_funcs(struct smu_context *smu)
    2505             : {
    2506           0 :         smu->ppt_funcs = &arcturus_ppt_funcs;
    2507           0 :         smu->message_map = arcturus_message_map;
    2508           0 :         smu->clock_map = arcturus_clk_map;
    2509           0 :         smu->feature_map = arcturus_feature_mask_map;
    2510           0 :         smu->table_map = arcturus_table_map;
    2511           0 :         smu->pwr_src_map = arcturus_pwr_src_map;
    2512           0 :         smu->workload_map = arcturus_workload_map;
    2513           0 :         smu_v11_0_set_smu_mailbox_registers(smu);
    2514           0 : }

Generated by: LCOV version 1.14