LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/pm/swsmu/smu13 - aldebaran_ppt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 846 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 48 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_v13_0.h"
      34             : #include "smu13_driver_if_aldebaran.h"
      35             : #include "soc15_common.h"
      36             : #include "atom.h"
      37             : #include "aldebaran_ppt.h"
      38             : #include "smu_v13_0_pptable.h"
      39             : #include "aldebaran_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/pci.h>
      46             : #include "amdgpu_ras.h"
      47             : #include "smu_cmn.h"
      48             : #include "mp/mp_13_0_2_offset.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 ALDEBARAN_FEA_MAP(smu_feature, aldebaran_feature) \
      61             :         [smu_feature] = {1, (aldebaran_feature)}
      62             : 
      63             : #define FEATURE_MASK(feature) (1ULL << feature)
      64             : #define SMC_DPM_FEATURE ( \
      65             :                           FEATURE_MASK(FEATURE_DATA_CALCULATIONS) | \
      66             :                           FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)  | \
      67             :                           FEATURE_MASK(FEATURE_DPM_UCLK_BIT)    | \
      68             :                           FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)  | \
      69             :                           FEATURE_MASK(FEATURE_DPM_FCLK_BIT)    | \
      70             :                           FEATURE_MASK(FEATURE_DPM_LCLK_BIT)    | \
      71             :                           FEATURE_MASK(FEATURE_DPM_XGMI_BIT)    | \
      72             :                           FEATURE_MASK(FEATURE_DPM_VCN_BIT))
      73             : 
      74             : /* possible frequency drift (1Mhz) */
      75             : #define EPSILON                         1
      76             : 
      77             : #define smnPCIE_ESM_CTRL                        0x111003D0
      78             : 
      79             : /*
      80             :  * SMU support ECCTABLE since version 68.42.0,
      81             :  * use this to check ECCTALE feature whether support
      82             :  */
      83             : #define SUPPORT_ECCTABLE_SMU_VERSION 0x00442a00
      84             : 
      85             : /*
      86             :  * SMU support mca_ceumc_addr in ECCTABLE since version 68.55.0,
      87             :  * use this to check mca_ceumc_addr record whether support
      88             :  */
      89             : #define SUPPORT_ECCTABLE_V2_SMU_VERSION 0x00443700
      90             : 
      91             : /*
      92             :  * SMU support BAD CHENNEL info MSG since version 68.51.00,
      93             :  * use this to check ECCTALE feature whether support
      94             :  */
      95             : #define SUPPORT_BAD_CHANNEL_INFO_MSG_VERSION 0x00443300
      96             : 
      97             : static const struct smu_temperature_range smu13_thermal_policy[] =
      98             : {
      99             :         {-273150,  99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
     100             :         { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
     101             : };
     102             : 
     103             : static const struct cmn2asic_msg_mapping aldebaran_message_map[SMU_MSG_MAX_COUNT] = {
     104             :         MSG_MAP(TestMessage,                         PPSMC_MSG_TestMessage,                     0),
     105             :         MSG_MAP(GetSmuVersion,                       PPSMC_MSG_GetSmuVersion,                   1),
     106             :         MSG_MAP(GetDriverIfVersion,                  PPSMC_MSG_GetDriverIfVersion,              1),
     107             :         MSG_MAP(EnableAllSmuFeatures,                PPSMC_MSG_EnableAllSmuFeatures,            0),
     108             :         MSG_MAP(DisableAllSmuFeatures,               PPSMC_MSG_DisableAllSmuFeatures,           0),
     109             :         MSG_MAP(GetEnabledSmuFeaturesLow,            PPSMC_MSG_GetEnabledSmuFeaturesLow,        1),
     110             :         MSG_MAP(GetEnabledSmuFeaturesHigh,           PPSMC_MSG_GetEnabledSmuFeaturesHigh,       1),
     111             :         MSG_MAP(SetDriverDramAddrHigh,               PPSMC_MSG_SetDriverDramAddrHigh,           1),
     112             :         MSG_MAP(SetDriverDramAddrLow,                PPSMC_MSG_SetDriverDramAddrLow,            1),
     113             :         MSG_MAP(SetToolsDramAddrHigh,                PPSMC_MSG_SetToolsDramAddrHigh,            0),
     114             :         MSG_MAP(SetToolsDramAddrLow,                 PPSMC_MSG_SetToolsDramAddrLow,             0),
     115             :         MSG_MAP(TransferTableSmu2Dram,               PPSMC_MSG_TransferTableSmu2Dram,           1),
     116             :         MSG_MAP(TransferTableDram2Smu,               PPSMC_MSG_TransferTableDram2Smu,           0),
     117             :         MSG_MAP(UseDefaultPPTable,                   PPSMC_MSG_UseDefaultPPTable,               0),
     118             :         MSG_MAP(SetSystemVirtualDramAddrHigh,        PPSMC_MSG_SetSystemVirtualDramAddrHigh,    0),
     119             :         MSG_MAP(SetSystemVirtualDramAddrLow,         PPSMC_MSG_SetSystemVirtualDramAddrLow,     0),
     120             :         MSG_MAP(SetSoftMinByFreq,                    PPSMC_MSG_SetSoftMinByFreq,                0),
     121             :         MSG_MAP(SetSoftMaxByFreq,                    PPSMC_MSG_SetSoftMaxByFreq,                0),
     122             :         MSG_MAP(SetHardMinByFreq,                    PPSMC_MSG_SetHardMinByFreq,                0),
     123             :         MSG_MAP(SetHardMaxByFreq,                    PPSMC_MSG_SetHardMaxByFreq,                0),
     124             :         MSG_MAP(GetMinDpmFreq,                       PPSMC_MSG_GetMinDpmFreq,                   0),
     125             :         MSG_MAP(GetMaxDpmFreq,                       PPSMC_MSG_GetMaxDpmFreq,                   0),
     126             :         MSG_MAP(GetDpmFreqByIndex,                   PPSMC_MSG_GetDpmFreqByIndex,               1),
     127             :         MSG_MAP(SetWorkloadMask,                     PPSMC_MSG_SetWorkloadMask,                 1),
     128             :         MSG_MAP(GetVoltageByDpm,                     PPSMC_MSG_GetVoltageByDpm,                 0),
     129             :         MSG_MAP(GetVoltageByDpmOverdrive,            PPSMC_MSG_GetVoltageByDpmOverdrive,        0),
     130             :         MSG_MAP(SetPptLimit,                         PPSMC_MSG_SetPptLimit,                     0),
     131             :         MSG_MAP(GetPptLimit,                         PPSMC_MSG_GetPptLimit,                     1),
     132             :         MSG_MAP(PrepareMp1ForUnload,                 PPSMC_MSG_PrepareMp1ForUnload,             0),
     133             :         MSG_MAP(GfxDeviceDriverReset,                PPSMC_MSG_GfxDriverReset,                  0),
     134             :         MSG_MAP(RunDcBtc,                            PPSMC_MSG_RunDcBtc,                        0),
     135             :         MSG_MAP(DramLogSetDramAddrHigh,              PPSMC_MSG_DramLogSetDramAddrHigh,          0),
     136             :         MSG_MAP(DramLogSetDramAddrLow,               PPSMC_MSG_DramLogSetDramAddrLow,           0),
     137             :         MSG_MAP(DramLogSetDramSize,                  PPSMC_MSG_DramLogSetDramSize,              0),
     138             :         MSG_MAP(GetDebugData,                        PPSMC_MSG_GetDebugData,                    0),
     139             :         MSG_MAP(WaflTest,                            PPSMC_MSG_WaflTest,                        0),
     140             :         MSG_MAP(SetMemoryChannelEnable,              PPSMC_MSG_SetMemoryChannelEnable,          0),
     141             :         MSG_MAP(SetNumBadHbmPagesRetired,            PPSMC_MSG_SetNumBadHbmPagesRetired,        0),
     142             :         MSG_MAP(DFCstateControl,                     PPSMC_MSG_DFCstateControl,                 0),
     143             :         MSG_MAP(GetGmiPwrDnHyst,                     PPSMC_MSG_GetGmiPwrDnHyst,                 0),
     144             :         MSG_MAP(SetGmiPwrDnHyst,                     PPSMC_MSG_SetGmiPwrDnHyst,                 0),
     145             :         MSG_MAP(GmiPwrDnControl,                     PPSMC_MSG_GmiPwrDnControl,                 0),
     146             :         MSG_MAP(EnterGfxoff,                         PPSMC_MSG_EnterGfxoff,                     0),
     147             :         MSG_MAP(ExitGfxoff,                          PPSMC_MSG_ExitGfxoff,                      0),
     148             :         MSG_MAP(SetExecuteDMATest,                   PPSMC_MSG_SetExecuteDMATest,               0),
     149             :         MSG_MAP(EnableDeterminism,                   PPSMC_MSG_EnableDeterminism,               0),
     150             :         MSG_MAP(DisableDeterminism,                  PPSMC_MSG_DisableDeterminism,              0),
     151             :         MSG_MAP(SetUclkDpmMode,                      PPSMC_MSG_SetUclkDpmMode,                  0),
     152             :         MSG_MAP(GfxDriverResetRecovery,              PPSMC_MSG_GfxDriverResetRecovery,          0),
     153             :         MSG_MAP(BoardPowerCalibration,               PPSMC_MSG_BoardPowerCalibration,           0),
     154             :         MSG_MAP(HeavySBR,                            PPSMC_MSG_HeavySBR,                        0),
     155             :         MSG_MAP(SetBadHBMPagesRetiredFlagsPerChannel,   PPSMC_MSG_SetBadHBMPagesRetiredFlagsPerChannel, 0),
     156             : };
     157             : 
     158             : static const struct cmn2asic_mapping aldebaran_clk_map[SMU_CLK_COUNT] = {
     159             :         CLK_MAP(GFXCLK, PPCLK_GFXCLK),
     160             :         CLK_MAP(SCLK,   PPCLK_GFXCLK),
     161             :         CLK_MAP(SOCCLK, PPCLK_SOCCLK),
     162             :         CLK_MAP(FCLK, PPCLK_FCLK),
     163             :         CLK_MAP(UCLK, PPCLK_UCLK),
     164             :         CLK_MAP(MCLK, PPCLK_UCLK),
     165             :         CLK_MAP(DCLK, PPCLK_DCLK),
     166             :         CLK_MAP(VCLK, PPCLK_VCLK),
     167             :         CLK_MAP(LCLK,   PPCLK_LCLK),
     168             : };
     169             : 
     170             : static const struct cmn2asic_mapping aldebaran_feature_mask_map[SMU_FEATURE_COUNT] = {
     171             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DATA_CALCULATIONS_BIT,            FEATURE_DATA_CALCULATIONS),
     172             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_GFXCLK_BIT,                   FEATURE_DPM_GFXCLK_BIT),
     173             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_UCLK_BIT,                     FEATURE_DPM_UCLK_BIT),
     174             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_SOCCLK_BIT,                   FEATURE_DPM_SOCCLK_BIT),
     175             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_FCLK_BIT,                     FEATURE_DPM_FCLK_BIT),
     176             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_LCLK_BIT,                     FEATURE_DPM_LCLK_BIT),
     177             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_XGMI_BIT,                             FEATURE_DPM_XGMI_BIT),
     178             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_GFXCLK_BIT,                    FEATURE_DS_GFXCLK_BIT),
     179             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_SOCCLK_BIT,                    FEATURE_DS_SOCCLK_BIT),
     180             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_LCLK_BIT,                              FEATURE_DS_LCLK_BIT),
     181             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_FCLK_BIT,                              FEATURE_DS_FCLK_BIT),
     182             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DS_UCLK_BIT,                              FEATURE_DS_UCLK_BIT),
     183             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_GFX_SS_BIT,                               FEATURE_GFX_SS_BIT),
     184             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_VCN_DPM_BIT,                              FEATURE_DPM_VCN_BIT),
     185             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_RSMU_SMN_CG_BIT,                  FEATURE_RSMU_SMN_CG_BIT),
     186             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_WAFL_CG_BIT,                              FEATURE_WAFL_CG_BIT),
     187             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_PPT_BIT,                                  FEATURE_PPT_BIT),
     188             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_TDC_BIT,                                  FEATURE_TDC_BIT),
     189             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_APCC_PLUS_BIT,                    FEATURE_APCC_PLUS_BIT),
     190             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_APCC_DFLL_BIT,                    FEATURE_APCC_DFLL_BIT),
     191             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_FUSE_CG_BIT,                              FEATURE_FUSE_CG_BIT),
     192             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_MP1_CG_BIT,                               FEATURE_MP1_CG_BIT),
     193             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_SMUIO_CG_BIT,                     FEATURE_SMUIO_CG_BIT),
     194             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_THM_CG_BIT,                               FEATURE_THM_CG_BIT),
     195             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_CLK_CG_BIT,                               FEATURE_CLK_CG_BIT),
     196             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_FW_CTF_BIT,                               FEATURE_FW_CTF_BIT),
     197             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_THERMAL_BIT,                              FEATURE_THERMAL_BIT),
     198             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_OUT_OF_BAND_MONITOR_BIT,  FEATURE_OUT_OF_BAND_MONITOR_BIT),
     199             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_XGMI_PER_LINK_PWR_DWN_BIT,FEATURE_XGMI_PER_LINK_PWR_DWN),
     200             :         ALDEBARAN_FEA_MAP(SMU_FEATURE_DF_CSTATE_BIT,                    FEATURE_DF_CSTATE),
     201             : };
     202             : 
     203             : static const struct cmn2asic_mapping aldebaran_table_map[SMU_TABLE_COUNT] = {
     204             :         TAB_MAP(PPTABLE),
     205             :         TAB_MAP(AVFS_PSM_DEBUG),
     206             :         TAB_MAP(AVFS_FUSE_OVERRIDE),
     207             :         TAB_MAP(PMSTATUSLOG),
     208             :         TAB_MAP(SMU_METRICS),
     209             :         TAB_MAP(DRIVER_SMU_CONFIG),
     210             :         TAB_MAP(I2C_COMMANDS),
     211             :         TAB_MAP(ECCINFO),
     212             : };
     213             : 
     214             : static const uint8_t aldebaran_throttler_map[] = {
     215             :         [THROTTLER_PPT0_BIT]            = (SMU_THROTTLER_PPT0_BIT),
     216             :         [THROTTLER_PPT1_BIT]            = (SMU_THROTTLER_PPT1_BIT),
     217             :         [THROTTLER_TDC_GFX_BIT]         = (SMU_THROTTLER_TDC_GFX_BIT),
     218             :         [THROTTLER_TDC_SOC_BIT]         = (SMU_THROTTLER_TDC_SOC_BIT),
     219             :         [THROTTLER_TDC_HBM_BIT]         = (SMU_THROTTLER_TDC_MEM_BIT),
     220             :         [THROTTLER_TEMP_GPU_BIT]        = (SMU_THROTTLER_TEMP_GPU_BIT),
     221             :         [THROTTLER_TEMP_MEM_BIT]        = (SMU_THROTTLER_TEMP_MEM_BIT),
     222             :         [THROTTLER_TEMP_VR_GFX_BIT]     = (SMU_THROTTLER_TEMP_VR_GFX_BIT),
     223             :         [THROTTLER_TEMP_VR_SOC_BIT]     = (SMU_THROTTLER_TEMP_VR_SOC_BIT),
     224             :         [THROTTLER_TEMP_VR_MEM_BIT]     = (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
     225             :         [THROTTLER_APCC_BIT]            = (SMU_THROTTLER_APCC_BIT),
     226             : };
     227             : 
     228           0 : static int aldebaran_tables_init(struct smu_context *smu)
     229             : {
     230           0 :         struct smu_table_context *smu_table = &smu->smu_table;
     231           0 :         struct smu_table *tables = smu_table->tables;
     232             : 
     233           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
     234             :                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     235             : 
     236           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
     237             :                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     238             : 
     239           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
     240             :                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     241             : 
     242           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
     243             :                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     244             : 
     245           0 :         SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t),
     246             :                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
     247             : 
     248           0 :         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
     249           0 :         if (!smu_table->metrics_table)
     250             :                 return -ENOMEM;
     251           0 :         smu_table->metrics_time = 0;
     252             : 
     253           0 :         smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
     254           0 :         smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
     255           0 :         if (!smu_table->gpu_metrics_table) {
     256           0 :                 kfree(smu_table->metrics_table);
     257           0 :                 return -ENOMEM;
     258             :         }
     259             : 
     260           0 :         smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL);
     261           0 :         if (!smu_table->ecc_table)
     262             :                 return -ENOMEM;
     263             : 
     264           0 :         return 0;
     265             : }
     266             : 
     267             : static int aldebaran_allocate_dpm_context(struct smu_context *smu)
     268             : {
     269           0 :         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
     270             : 
     271           0 :         smu_dpm->dpm_context = kzalloc(sizeof(struct smu_13_0_dpm_context),
     272             :                                        GFP_KERNEL);
     273           0 :         if (!smu_dpm->dpm_context)
     274             :                 return -ENOMEM;
     275           0 :         smu_dpm->dpm_context_size = sizeof(struct smu_13_0_dpm_context);
     276             : 
     277             :         return 0;
     278             : }
     279             : 
     280           0 : static int aldebaran_init_smc_tables(struct smu_context *smu)
     281             : {
     282           0 :         int ret = 0;
     283             : 
     284           0 :         ret = aldebaran_tables_init(smu);
     285           0 :         if (ret)
     286             :                 return ret;
     287             : 
     288           0 :         ret = aldebaran_allocate_dpm_context(smu);
     289           0 :         if (ret)
     290             :                 return ret;
     291             : 
     292           0 :         return smu_v13_0_init_smc_tables(smu);
     293             : }
     294             : 
     295           0 : static int aldebaran_get_allowed_feature_mask(struct smu_context *smu,
     296             :                                               uint32_t *feature_mask, uint32_t num)
     297             : {
     298           0 :         if (num > 2)
     299             :                 return -EINVAL;
     300             : 
     301             :         /* pptable will handle the features to enable */
     302           0 :         memset(feature_mask, 0xFF, sizeof(uint32_t) * num);
     303             : 
     304           0 :         return 0;
     305             : }
     306             : 
     307           0 : static int aldebaran_set_default_dpm_table(struct smu_context *smu)
     308             : {
     309           0 :         struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
     310           0 :         struct smu_13_0_dpm_table *dpm_table = NULL;
     311           0 :         PPTable_t *pptable = smu->smu_table.driver_pptable;
     312           0 :         int ret = 0;
     313             : 
     314             :         /* socclk dpm table setup */
     315           0 :         dpm_table = &dpm_context->dpm_tables.soc_table;
     316           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
     317           0 :                 ret = smu_v13_0_set_single_dpm_table(smu,
     318             :                                                      SMU_SOCCLK,
     319             :                                                      dpm_table);
     320           0 :                 if (ret)
     321             :                         return ret;
     322             :         } else {
     323           0 :                 dpm_table->count = 1;
     324           0 :                 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
     325           0 :                 dpm_table->dpm_levels[0].enabled = true;
     326           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     327           0 :                 dpm_table->max = dpm_table->dpm_levels[0].value;
     328             :         }
     329             : 
     330             :         /* gfxclk dpm table setup */
     331           0 :         dpm_table = &dpm_context->dpm_tables.gfx_table;
     332           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
     333             :                 /* in the case of gfxclk, only fine-grained dpm is honored */
     334           0 :                 dpm_table->count = 2;
     335           0 :                 dpm_table->dpm_levels[0].value = pptable->GfxclkFmin;
     336           0 :                 dpm_table->dpm_levels[0].enabled = true;
     337           0 :                 dpm_table->dpm_levels[1].value = pptable->GfxclkFmax;
     338           0 :                 dpm_table->dpm_levels[1].enabled = true;
     339           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     340           0 :                 dpm_table->max = dpm_table->dpm_levels[1].value;
     341             :         } else {
     342           0 :                 dpm_table->count = 1;
     343           0 :                 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
     344           0 :                 dpm_table->dpm_levels[0].enabled = true;
     345           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     346           0 :                 dpm_table->max = dpm_table->dpm_levels[0].value;
     347             :         }
     348             : 
     349             :         /* memclk dpm table setup */
     350           0 :         dpm_table = &dpm_context->dpm_tables.uclk_table;
     351           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
     352           0 :                 ret = smu_v13_0_set_single_dpm_table(smu,
     353             :                                                      SMU_UCLK,
     354             :                                                      dpm_table);
     355           0 :                 if (ret)
     356             :                         return ret;
     357             :         } else {
     358           0 :                 dpm_table->count = 1;
     359           0 :                 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
     360           0 :                 dpm_table->dpm_levels[0].enabled = true;
     361           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     362           0 :                 dpm_table->max = dpm_table->dpm_levels[0].value;
     363             :         }
     364             : 
     365             :         /* fclk dpm table setup */
     366           0 :         dpm_table = &dpm_context->dpm_tables.fclk_table;
     367           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
     368           0 :                 ret = smu_v13_0_set_single_dpm_table(smu,
     369             :                                                      SMU_FCLK,
     370             :                                                      dpm_table);
     371           0 :                 if (ret)
     372             :                         return ret;
     373             :         } else {
     374           0 :                 dpm_table->count = 1;
     375           0 :                 dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100;
     376           0 :                 dpm_table->dpm_levels[0].enabled = true;
     377           0 :                 dpm_table->min = dpm_table->dpm_levels[0].value;
     378           0 :                 dpm_table->max = dpm_table->dpm_levels[0].value;
     379             :         }
     380             : 
     381             :         return 0;
     382             : }
     383             : 
     384             : static int aldebaran_check_powerplay_table(struct smu_context *smu)
     385             : {
     386           0 :         struct smu_table_context *table_context = &smu->smu_table;
     387           0 :         struct smu_13_0_powerplay_table *powerplay_table =
     388             :                 table_context->power_play_table;
     389             : 
     390           0 :         table_context->thermal_controller_type =
     391           0 :                 powerplay_table->thermal_controller_type;
     392             : 
     393             :         return 0;
     394             : }
     395             : 
     396             : static int aldebaran_store_powerplay_table(struct smu_context *smu)
     397             : {
     398           0 :         struct smu_table_context *table_context = &smu->smu_table;
     399           0 :         struct smu_13_0_powerplay_table *powerplay_table =
     400             :                 table_context->power_play_table;
     401           0 :         memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
     402             :                sizeof(PPTable_t));
     403             : 
     404             :         return 0;
     405             : }
     406             : 
     407           0 : static int aldebaran_append_powerplay_table(struct smu_context *smu)
     408             : {
     409           0 :         struct smu_table_context *table_context = &smu->smu_table;
     410           0 :         PPTable_t *smc_pptable = table_context->driver_pptable;
     411             :         struct atom_smc_dpm_info_v4_10 *smc_dpm_table;
     412             :         int index, ret;
     413             : 
     414           0 :         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
     415             :                                            smc_dpm_info);
     416             : 
     417           0 :         ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
     418             :                                       (uint8_t **)&smc_dpm_table);
     419           0 :         if (ret)
     420             :                 return ret;
     421             : 
     422           0 :         dev_info(smu->adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n",
     423             :                         smc_dpm_table->table_header.format_revision,
     424             :                         smc_dpm_table->table_header.content_revision);
     425             : 
     426           0 :         if ((smc_dpm_table->table_header.format_revision == 4) &&
     427           0 :             (smc_dpm_table->table_header.content_revision == 10))
     428           0 :                 smu_memcpy_trailing(smc_pptable, GfxMaxCurrent, reserved,
     429             :                                     smc_dpm_table, GfxMaxCurrent);
     430             :         return 0;
     431             : }
     432             : 
     433           0 : static int aldebaran_setup_pptable(struct smu_context *smu)
     434             : {
     435           0 :         int ret = 0;
     436             : 
     437             :         /* VBIOS pptable is the first choice */
     438           0 :         smu->smu_table.boot_values.pp_table_id = 0;
     439             : 
     440           0 :         ret = smu_v13_0_setup_pptable(smu);
     441           0 :         if (ret)
     442             :                 return ret;
     443             : 
     444           0 :         ret = aldebaran_store_powerplay_table(smu);
     445             :         if (ret)
     446             :                 return ret;
     447             : 
     448           0 :         ret = aldebaran_append_powerplay_table(smu);
     449           0 :         if (ret)
     450             :                 return ret;
     451             : 
     452           0 :         ret = aldebaran_check_powerplay_table(smu);
     453             :         if (ret)
     454             :                 return ret;
     455             : 
     456           0 :         return ret;
     457             : }
     458             : 
     459             : static bool aldebaran_is_primary(struct smu_context *smu)
     460             : {
     461           0 :         struct amdgpu_device *adev = smu->adev;
     462             : 
     463           0 :         if (adev->smuio.funcs && adev->smuio.funcs->get_die_id)
     464           0 :                 return adev->smuio.funcs->get_die_id(adev) == 0;
     465             : 
     466             :         return true;
     467             : }
     468             : 
     469           0 : static int aldebaran_run_board_btc(struct smu_context *smu)
     470             : {
     471             :         u32 smu_version;
     472             :         int ret;
     473             : 
     474           0 :         if (!aldebaran_is_primary(smu))
     475             :                 return 0;
     476             : 
     477           0 :         ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
     478           0 :         if (ret) {
     479           0 :                 dev_err(smu->adev->dev, "Failed to get smu version!\n");
     480           0 :                 return ret;
     481             :         }
     482           0 :         if (smu_version <= 0x00441d00)
     483             :                 return 0;
     484             : 
     485           0 :         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_BoardPowerCalibration, NULL);
     486           0 :         if (ret)
     487           0 :                 dev_err(smu->adev->dev, "Board power calibration failed!\n");
     488             : 
     489             :         return ret;
     490             : }
     491             : 
     492           0 : static int aldebaran_run_btc(struct smu_context *smu)
     493             : {
     494             :         int ret;
     495             : 
     496           0 :         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL);
     497           0 :         if (ret)
     498           0 :                 dev_err(smu->adev->dev, "RunDcBtc failed!\n");
     499             :         else
     500           0 :                 ret = aldebaran_run_board_btc(smu);
     501             : 
     502           0 :         return ret;
     503             : }
     504             : 
     505           0 : static int aldebaran_populate_umd_state_clk(struct smu_context *smu)
     506             : {
     507           0 :         struct smu_13_0_dpm_context *dpm_context =
     508             :                 smu->smu_dpm.dpm_context;
     509           0 :         struct smu_13_0_dpm_table *gfx_table =
     510             :                 &dpm_context->dpm_tables.gfx_table;
     511           0 :         struct smu_13_0_dpm_table *mem_table =
     512             :                 &dpm_context->dpm_tables.uclk_table;
     513           0 :         struct smu_13_0_dpm_table *soc_table =
     514             :                 &dpm_context->dpm_tables.soc_table;
     515           0 :         struct smu_umd_pstate_table *pstate_table =
     516             :                 &smu->pstate_table;
     517             : 
     518           0 :         pstate_table->gfxclk_pstate.min = gfx_table->min;
     519           0 :         pstate_table->gfxclk_pstate.peak = gfx_table->max;
     520           0 :         pstate_table->gfxclk_pstate.curr.min = gfx_table->min;
     521           0 :         pstate_table->gfxclk_pstate.curr.max = gfx_table->max;
     522             : 
     523           0 :         pstate_table->uclk_pstate.min = mem_table->min;
     524           0 :         pstate_table->uclk_pstate.peak = mem_table->max;
     525           0 :         pstate_table->uclk_pstate.curr.min = mem_table->min;
     526           0 :         pstate_table->uclk_pstate.curr.max = mem_table->max;
     527             : 
     528           0 :         pstate_table->socclk_pstate.min = soc_table->min;
     529           0 :         pstate_table->socclk_pstate.peak = soc_table->max;
     530           0 :         pstate_table->socclk_pstate.curr.min = soc_table->min;
     531           0 :         pstate_table->socclk_pstate.curr.max = soc_table->max;
     532             : 
     533           0 :         if (gfx_table->count > ALDEBARAN_UMD_PSTATE_GFXCLK_LEVEL &&
     534           0 :             mem_table->count > ALDEBARAN_UMD_PSTATE_MCLK_LEVEL &&
     535           0 :             soc_table->count > ALDEBARAN_UMD_PSTATE_SOCCLK_LEVEL) {
     536           0 :                 pstate_table->gfxclk_pstate.standard =
     537           0 :                         gfx_table->dpm_levels[ALDEBARAN_UMD_PSTATE_GFXCLK_LEVEL].value;
     538           0 :                 pstate_table->uclk_pstate.standard =
     539           0 :                         mem_table->dpm_levels[ALDEBARAN_UMD_PSTATE_MCLK_LEVEL].value;
     540           0 :                 pstate_table->socclk_pstate.standard =
     541           0 :                         soc_table->dpm_levels[ALDEBARAN_UMD_PSTATE_SOCCLK_LEVEL].value;
     542             :         } else {
     543           0 :                 pstate_table->gfxclk_pstate.standard =
     544             :                         pstate_table->gfxclk_pstate.min;
     545           0 :                 pstate_table->uclk_pstate.standard =
     546             :                         pstate_table->uclk_pstate.min;
     547           0 :                 pstate_table->socclk_pstate.standard =
     548             :                         pstate_table->socclk_pstate.min;
     549             :         }
     550             : 
     551           0 :         return 0;
     552             : }
     553             : 
     554             : static int aldebaran_get_clk_table(struct smu_context *smu,
     555             :                                    struct pp_clock_levels_with_latency *clocks,
     556             :                                    struct smu_13_0_dpm_table *dpm_table)
     557             : {
     558             :         uint32_t i;
     559             : 
     560           0 :         clocks->num_levels = min_t(uint32_t,
     561             :                                    dpm_table->count,
     562             :                                    (uint32_t)PP_MAX_CLOCK_LEVELS);
     563             : 
     564           0 :         for (i = 0; i < clocks->num_levels; i++) {
     565           0 :                 clocks->data[i].clocks_in_khz =
     566           0 :                         dpm_table->dpm_levels[i].value * 1000;
     567             :                 clocks->data[i].latency_in_us = 0;
     568             :         }
     569             : 
     570             :         return 0;
     571             : }
     572             : 
     573             : static int aldebaran_freqs_in_same_level(int32_t frequency1,
     574             :                                          int32_t frequency2)
     575             : {
     576           0 :         return (abs(frequency1 - frequency2) <= EPSILON);
     577             : }
     578             : 
     579           0 : static int aldebaran_get_smu_metrics_data(struct smu_context *smu,
     580             :                                           MetricsMember_t member,
     581             :                                           uint32_t *value)
     582             : {
     583           0 :         struct smu_table_context *smu_table= &smu->smu_table;
     584           0 :         SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
     585           0 :         int ret = 0;
     586             : 
     587           0 :         ret = smu_cmn_get_metrics_table(smu,
     588             :                                         NULL,
     589             :                                         false);
     590           0 :         if (ret)
     591             :                 return ret;
     592             : 
     593           0 :         switch (member) {
     594             :         case METRICS_CURR_GFXCLK:
     595           0 :                 *value = metrics->CurrClock[PPCLK_GFXCLK];
     596           0 :                 break;
     597             :         case METRICS_CURR_SOCCLK:
     598           0 :                 *value = metrics->CurrClock[PPCLK_SOCCLK];
     599           0 :                 break;
     600             :         case METRICS_CURR_UCLK:
     601           0 :                 *value = metrics->CurrClock[PPCLK_UCLK];
     602           0 :                 break;
     603             :         case METRICS_CURR_VCLK:
     604           0 :                 *value = metrics->CurrClock[PPCLK_VCLK];
     605           0 :                 break;
     606             :         case METRICS_CURR_DCLK:
     607           0 :                 *value = metrics->CurrClock[PPCLK_DCLK];
     608           0 :                 break;
     609             :         case METRICS_CURR_FCLK:
     610           0 :                 *value = metrics->CurrClock[PPCLK_FCLK];
     611           0 :                 break;
     612             :         case METRICS_AVERAGE_GFXCLK:
     613           0 :                 *value = metrics->AverageGfxclkFrequency;
     614           0 :                 break;
     615             :         case METRICS_AVERAGE_SOCCLK:
     616           0 :                 *value = metrics->AverageSocclkFrequency;
     617           0 :                 break;
     618             :         case METRICS_AVERAGE_UCLK:
     619           0 :                 *value = metrics->AverageUclkFrequency;
     620           0 :                 break;
     621             :         case METRICS_AVERAGE_GFXACTIVITY:
     622           0 :                 *value = metrics->AverageGfxActivity;
     623           0 :                 break;
     624             :         case METRICS_AVERAGE_MEMACTIVITY:
     625           0 :                 *value = metrics->AverageUclkActivity;
     626           0 :                 break;
     627             :         case METRICS_AVERAGE_SOCKETPOWER:
     628             :                 /* Valid power data is available only from primary die */
     629           0 :                 *value = aldebaran_is_primary(smu) ?
     630           0 :                                  metrics->AverageSocketPower << 8 :
     631             :                                  0;
     632           0 :                 break;
     633             :         case METRICS_TEMPERATURE_EDGE:
     634           0 :                 *value = metrics->TemperatureEdge *
     635             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     636           0 :                 break;
     637             :         case METRICS_TEMPERATURE_HOTSPOT:
     638           0 :                 *value = metrics->TemperatureHotspot *
     639             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     640           0 :                 break;
     641             :         case METRICS_TEMPERATURE_MEM:
     642           0 :                 *value = metrics->TemperatureHBM *
     643             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     644           0 :                 break;
     645             :         case METRICS_TEMPERATURE_VRGFX:
     646           0 :                 *value = metrics->TemperatureVrGfx *
     647             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     648           0 :                 break;
     649             :         case METRICS_TEMPERATURE_VRSOC:
     650           0 :                 *value = metrics->TemperatureVrSoc *
     651             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     652           0 :                 break;
     653             :         case METRICS_TEMPERATURE_VRMEM:
     654           0 :                 *value = metrics->TemperatureVrMem *
     655             :                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
     656           0 :                 break;
     657             :         case METRICS_THROTTLER_STATUS:
     658           0 :                 *value = metrics->ThrottlerStatus;
     659           0 :                 break;
     660             :         case METRICS_UNIQUE_ID_UPPER32:
     661           0 :                 *value = metrics->PublicSerialNumUpper32;
     662           0 :                 break;
     663             :         case METRICS_UNIQUE_ID_LOWER32:
     664           0 :                 *value = metrics->PublicSerialNumLower32;
     665           0 :                 break;
     666             :         default:
     667           0 :                 *value = UINT_MAX;
     668           0 :                 break;
     669             :         }
     670             : 
     671             :         return ret;
     672             : }
     673             : 
     674           0 : static int aldebaran_get_current_clk_freq_by_table(struct smu_context *smu,
     675             :                                                    enum smu_clk_type clk_type,
     676             :                                                    uint32_t *value)
     677             : {
     678             :         MetricsMember_t member_type;
     679           0 :         int clk_id = 0;
     680             : 
     681           0 :         if (!value)
     682             :                 return -EINVAL;
     683             : 
     684           0 :         clk_id = smu_cmn_to_asic_specific_index(smu,
     685             :                                                 CMN2ASIC_MAPPING_CLK,
     686             :                                                 clk_type);
     687           0 :         if (clk_id < 0)
     688             :                 return -EINVAL;
     689             : 
     690           0 :         switch (clk_id) {
     691             :         case PPCLK_GFXCLK:
     692             :                 /*
     693             :                  * CurrClock[clk_id] can provide accurate
     694             :                  *   output only when the dpm feature is enabled.
     695             :                  * We can use Average_* for dpm disabled case.
     696             :                  *   But this is available for gfxclk/uclk/socclk/vclk/dclk.
     697             :                  */
     698           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT))
     699             :                         member_type = METRICS_CURR_GFXCLK;
     700             :                 else
     701           0 :                         member_type = METRICS_AVERAGE_GFXCLK;
     702             :                 break;
     703             :         case PPCLK_UCLK:
     704           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT))
     705             :                         member_type = METRICS_CURR_UCLK;
     706             :                 else
     707           0 :                         member_type = METRICS_AVERAGE_UCLK;
     708             :                 break;
     709             :         case PPCLK_SOCCLK:
     710           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT))
     711             :                         member_type = METRICS_CURR_SOCCLK;
     712             :                 else
     713           0 :                         member_type = METRICS_AVERAGE_SOCCLK;
     714             :                 break;
     715             :         case PPCLK_VCLK:
     716           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT))
     717             :                         member_type = METRICS_CURR_VCLK;
     718             :                 else
     719           0 :                         member_type = METRICS_AVERAGE_VCLK;
     720             :                 break;
     721             :         case PPCLK_DCLK:
     722           0 :                 if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT))
     723             :                         member_type = METRICS_CURR_DCLK;
     724             :                 else
     725           0 :                         member_type = METRICS_AVERAGE_DCLK;
     726             :                 break;
     727             :         case PPCLK_FCLK:
     728             :                 member_type = METRICS_CURR_FCLK;
     729             :                 break;
     730             :         default:
     731             :                 return -EINVAL;
     732             :         }
     733             : 
     734           0 :         return aldebaran_get_smu_metrics_data(smu,
     735             :                                               member_type,
     736             :                                               value);
     737             : }
     738             : 
     739           0 : static int aldebaran_print_clk_levels(struct smu_context *smu,
     740             :                                       enum smu_clk_type type, char *buf)
     741             : {
     742           0 :         int i, now, size = 0;
     743           0 :         int ret = 0;
     744           0 :         struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
     745             :         struct pp_clock_levels_with_latency clocks;
     746             :         struct smu_13_0_dpm_table *single_dpm_table;
     747           0 :         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
     748           0 :         struct smu_13_0_dpm_context *dpm_context = NULL;
     749             :         int display_levels;
     750           0 :         uint32_t freq_values[3] = {0};
     751             :         uint32_t min_clk, max_clk;
     752             : 
     753           0 :         smu_cmn_get_sysfs_buf(&buf, &size);
     754             : 
     755           0 :         if (amdgpu_ras_intr_triggered()) {
     756           0 :                 size += sysfs_emit_at(buf, size, "unavailable\n");
     757           0 :                 return size;
     758             :         }
     759             : 
     760           0 :         dpm_context = smu_dpm->dpm_context;
     761             : 
     762           0 :         switch (type) {
     763             : 
     764             :         case SMU_OD_SCLK:
     765           0 :                 size += sysfs_emit_at(buf, size, "%s:\n", "GFXCLK");
     766             :                 fallthrough;
     767             :         case SMU_SCLK:
     768           0 :                 ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now);
     769           0 :                 if (ret) {
     770           0 :                         dev_err(smu->adev->dev, "Attempt to get current gfx clk Failed!");
     771           0 :                         return ret;
     772             :                 }
     773             : 
     774           0 :                 single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
     775           0 :                 ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
     776             :                 if (ret) {
     777             :                         dev_err(smu->adev->dev, "Attempt to get gfx clk levels Failed!");
     778             :                         return ret;
     779             :                 }
     780             : 
     781           0 :                 display_levels = (clocks.num_levels == 1) ? 1 : 2;
     782             : 
     783           0 :                 min_clk = pstate_table->gfxclk_pstate.curr.min;
     784           0 :                 max_clk = pstate_table->gfxclk_pstate.curr.max;
     785             : 
     786           0 :                 freq_values[0] = min_clk;
     787           0 :                 freq_values[1] = max_clk;
     788             : 
     789             :                 /* fine-grained dpm has only 2 levels */
     790           0 :                 if (now > min_clk && now < max_clk) {
     791           0 :                         display_levels++;
     792           0 :                         freq_values[2] = max_clk;
     793           0 :                         freq_values[1] = now;
     794             :                 }
     795             : 
     796           0 :                 for (i = 0; i < display_levels; i++)
     797           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i,
     798             :                                 freq_values[i],
     799             :                                 (display_levels == 1) ?
     800             :                                         "*" :
     801           0 :                                         (aldebaran_freqs_in_same_level(
     802           0 :                                                  freq_values[i], now) ?
     803           0 :                                                  "*" :
     804             :                                                  ""));
     805             : 
     806             :                 break;
     807             : 
     808             :         case SMU_OD_MCLK:
     809           0 :                 size += sysfs_emit_at(buf, size, "%s:\n", "MCLK");
     810             :                 fallthrough;
     811             :         case SMU_MCLK:
     812           0 :                 ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, &now);
     813           0 :                 if (ret) {
     814           0 :                         dev_err(smu->adev->dev, "Attempt to get current mclk Failed!");
     815           0 :                         return ret;
     816             :                 }
     817             : 
     818           0 :                 single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
     819           0 :                 ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
     820             :                 if (ret) {
     821             :                         dev_err(smu->adev->dev, "Attempt to get memory clk levels Failed!");
     822             :                         return ret;
     823             :                 }
     824             : 
     825           0 :                 for (i = 0; i < clocks.num_levels; i++)
     826           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     827           0 :                                         i, clocks.data[i].clocks_in_khz / 1000,
     828             :                                         (clocks.num_levels == 1) ? "*" :
     829           0 :                                         (aldebaran_freqs_in_same_level(
     830           0 :                                                                        clocks.data[i].clocks_in_khz / 1000,
     831           0 :                                                                        now) ? "*" : ""));
     832             :                 break;
     833             : 
     834             :         case SMU_SOCCLK:
     835           0 :                 ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_SOCCLK, &now);
     836           0 :                 if (ret) {
     837           0 :                         dev_err(smu->adev->dev, "Attempt to get current socclk Failed!");
     838           0 :                         return ret;
     839             :                 }
     840             : 
     841           0 :                 single_dpm_table = &(dpm_context->dpm_tables.soc_table);
     842           0 :                 ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
     843             :                 if (ret) {
     844             :                         dev_err(smu->adev->dev, "Attempt to get socclk levels Failed!");
     845             :                         return ret;
     846             :                 }
     847             : 
     848           0 :                 for (i = 0; i < clocks.num_levels; i++)
     849           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     850           0 :                                         i, clocks.data[i].clocks_in_khz / 1000,
     851             :                                         (clocks.num_levels == 1) ? "*" :
     852           0 :                                         (aldebaran_freqs_in_same_level(
     853           0 :                                                                        clocks.data[i].clocks_in_khz / 1000,
     854           0 :                                                                        now) ? "*" : ""));
     855             :                 break;
     856             : 
     857             :         case SMU_FCLK:
     858           0 :                 ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_FCLK, &now);
     859           0 :                 if (ret) {
     860           0 :                         dev_err(smu->adev->dev, "Attempt to get current fclk Failed!");
     861           0 :                         return ret;
     862             :                 }
     863             : 
     864           0 :                 single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
     865           0 :                 ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
     866             :                 if (ret) {
     867             :                         dev_err(smu->adev->dev, "Attempt to get fclk levels Failed!");
     868             :                         return ret;
     869             :                 }
     870             : 
     871           0 :                 for (i = 0; i < single_dpm_table->count; i++)
     872           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     873             :                                         i, single_dpm_table->dpm_levels[i].value,
     874             :                                         (clocks.num_levels == 1) ? "*" :
     875           0 :                                         (aldebaran_freqs_in_same_level(
     876           0 :                                                                        clocks.data[i].clocks_in_khz / 1000,
     877           0 :                                                                        now) ? "*" : ""));
     878             :                 break;
     879             : 
     880             :         case SMU_VCLK:
     881           0 :                 ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_VCLK, &now);
     882           0 :                 if (ret) {
     883           0 :                         dev_err(smu->adev->dev, "Attempt to get current vclk Failed!");
     884           0 :                         return ret;
     885             :                 }
     886             : 
     887           0 :                 single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
     888           0 :                 ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
     889             :                 if (ret) {
     890             :                         dev_err(smu->adev->dev, "Attempt to get vclk levels Failed!");
     891             :                         return ret;
     892             :                 }
     893             : 
     894           0 :                 for (i = 0; i < single_dpm_table->count; i++)
     895           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     896             :                                         i, single_dpm_table->dpm_levels[i].value,
     897             :                                         (clocks.num_levels == 1) ? "*" :
     898           0 :                                         (aldebaran_freqs_in_same_level(
     899           0 :                                                                        clocks.data[i].clocks_in_khz / 1000,
     900           0 :                                                                        now) ? "*" : ""));
     901             :                 break;
     902             : 
     903             :         case SMU_DCLK:
     904           0 :                 ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_DCLK, &now);
     905           0 :                 if (ret) {
     906           0 :                         dev_err(smu->adev->dev, "Attempt to get current dclk Failed!");
     907           0 :                         return ret;
     908             :                 }
     909             : 
     910           0 :                 single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
     911           0 :                 ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);
     912             :                 if (ret) {
     913             :                         dev_err(smu->adev->dev, "Attempt to get dclk levels Failed!");
     914             :                         return ret;
     915             :                 }
     916             : 
     917           0 :                 for (i = 0; i < single_dpm_table->count; i++)
     918           0 :                         size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
     919             :                                         i, single_dpm_table->dpm_levels[i].value,
     920             :                                         (clocks.num_levels == 1) ? "*" :
     921           0 :                                         (aldebaran_freqs_in_same_level(
     922           0 :                                                                        clocks.data[i].clocks_in_khz / 1000,
     923           0 :                                                                        now) ? "*" : ""));
     924             :                 break;
     925             : 
     926             :         default:
     927             :                 break;
     928             :         }
     929             : 
     930             :         return size;
     931             : }
     932             : 
     933           0 : static int aldebaran_upload_dpm_level(struct smu_context *smu,
     934             :                                       bool max,
     935             :                                       uint32_t feature_mask,
     936             :                                       uint32_t level)
     937             : {
     938           0 :         struct smu_13_0_dpm_context *dpm_context =
     939             :                 smu->smu_dpm.dpm_context;
     940             :         uint32_t freq;
     941           0 :         int ret = 0;
     942             : 
     943           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
     944             :             (feature_mask & FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT))) {
     945           0 :                 freq = dpm_context->dpm_tables.gfx_table.dpm_levels[level].value;
     946           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu,
     947             :                                                       (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq),
     948             :                                                       (PPCLK_GFXCLK << 16) | (freq & 0xffff),
     949             :                                                       NULL);
     950           0 :                 if (ret) {
     951           0 :                         dev_err(smu->adev->dev, "Failed to set soft %s gfxclk !\n",
     952             :                                 max ? "max" : "min");
     953           0 :                         return ret;
     954             :                 }
     955             :         }
     956             : 
     957           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
     958             :             (feature_mask & FEATURE_MASK(FEATURE_DPM_UCLK_BIT))) {
     959           0 :                 freq = dpm_context->dpm_tables.uclk_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           0 :                                                       (PPCLK_UCLK << 16) | (freq & 0xffff),
     963             :                                                       NULL);
     964           0 :                 if (ret) {
     965           0 :                         dev_err(smu->adev->dev, "Failed to set soft %s memclk !\n",
     966             :                                 max ? "max" : "min");
     967           0 :                         return ret;
     968             :                 }
     969             :         }
     970             : 
     971           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) &&
     972             :             (feature_mask & FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT))) {
     973           0 :                 freq = dpm_context->dpm_tables.soc_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_SOCCLK << 16) | (freq & 0xffff),
     977             :                                                       NULL);
     978           0 :                 if (ret) {
     979           0 :                         dev_err(smu->adev->dev, "Failed to set soft %s socclk !\n",
     980             :                                 max ? "max" : "min");
     981           0 :                         return ret;
     982             :                 }
     983             :         }
     984             : 
     985             :         return ret;
     986             : }
     987             : 
     988           0 : static int aldebaran_force_clk_levels(struct smu_context *smu,
     989             :                                       enum smu_clk_type type, uint32_t mask)
     990             : {
     991           0 :         struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
     992           0 :         struct smu_13_0_dpm_table *single_dpm_table = NULL;
     993             :         uint32_t soft_min_level, soft_max_level;
     994           0 :         int ret = 0;
     995             : 
     996           0 :         soft_min_level = mask ? (ffs(mask) - 1) : 0;
     997           0 :         soft_max_level = mask ? (fls(mask) - 1) : 0;
     998             : 
     999           0 :         switch (type) {
    1000             :         case SMU_SCLK:
    1001           0 :                 single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
    1002           0 :                 if (soft_max_level >= single_dpm_table->count) {
    1003           0 :                         dev_err(smu->adev->dev, "Clock level specified %d is over max allowed %d\n",
    1004             :                                 soft_max_level, single_dpm_table->count - 1);
    1005           0 :                         ret = -EINVAL;
    1006           0 :                         break;
    1007             :                 }
    1008             : 
    1009           0 :                 ret = aldebaran_upload_dpm_level(smu,
    1010             :                                                  false,
    1011             :                                                  FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT),
    1012             :                                                  soft_min_level);
    1013           0 :                 if (ret) {
    1014           0 :                         dev_err(smu->adev->dev, "Failed to upload boot level to lowest!\n");
    1015           0 :                         break;
    1016             :                 }
    1017             : 
    1018           0 :                 ret = aldebaran_upload_dpm_level(smu,
    1019             :                                                  true,
    1020             :                                                  FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT),
    1021             :                                                  soft_max_level);
    1022           0 :                 if (ret)
    1023           0 :                         dev_err(smu->adev->dev, "Failed to upload dpm max level to highest!\n");
    1024             : 
    1025             :                 break;
    1026             : 
    1027             :         case SMU_MCLK:
    1028             :         case SMU_SOCCLK:
    1029             :         case SMU_FCLK:
    1030             :                 /*
    1031             :                  * Should not arrive here since aldebaran does not
    1032             :                  * support mclk/socclk/fclk softmin/softmax settings
    1033             :                  */
    1034           0 :                 ret = -EINVAL;
    1035           0 :                 break;
    1036             : 
    1037             :         default:
    1038             :                 break;
    1039             :         }
    1040             : 
    1041           0 :         return ret;
    1042             : }
    1043             : 
    1044           0 : static int aldebaran_get_thermal_temperature_range(struct smu_context *smu,
    1045             :                                                    struct smu_temperature_range *range)
    1046             : {
    1047           0 :         struct smu_table_context *table_context = &smu->smu_table;
    1048           0 :         struct smu_13_0_powerplay_table *powerplay_table =
    1049             :                 table_context->power_play_table;
    1050           0 :         PPTable_t *pptable = smu->smu_table.driver_pptable;
    1051             : 
    1052           0 :         if (!range)
    1053             :                 return -EINVAL;
    1054             : 
    1055           0 :         memcpy(range, &smu13_thermal_policy[0], sizeof(struct smu_temperature_range));
    1056             : 
    1057           0 :         range->hotspot_crit_max = pptable->ThotspotLimit *
    1058             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1059           0 :         range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
    1060             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1061           0 :         range->mem_crit_max = pptable->TmemLimit *
    1062             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1063           0 :         range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)*
    1064             :                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
    1065           0 :         range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
    1066             : 
    1067           0 :         return 0;
    1068             : }
    1069             : 
    1070           0 : static int aldebaran_get_current_activity_percent(struct smu_context *smu,
    1071             :                                                   enum amd_pp_sensors sensor,
    1072             :                                                   uint32_t *value)
    1073             : {
    1074           0 :         int ret = 0;
    1075             : 
    1076           0 :         if (!value)
    1077             :                 return -EINVAL;
    1078             : 
    1079           0 :         switch (sensor) {
    1080             :         case AMDGPU_PP_SENSOR_GPU_LOAD:
    1081             :                 ret = aldebaran_get_smu_metrics_data(smu,
    1082             :                                                      METRICS_AVERAGE_GFXACTIVITY,
    1083             :                                                      value);
    1084             :                 break;
    1085             :         case AMDGPU_PP_SENSOR_MEM_LOAD:
    1086             :                 ret = aldebaran_get_smu_metrics_data(smu,
    1087             :                                                      METRICS_AVERAGE_MEMACTIVITY,
    1088             :                                                      value);
    1089             :                 break;
    1090             :         default:
    1091           0 :                 dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
    1092           0 :                 return -EINVAL;
    1093             :         }
    1094             : 
    1095             :         return ret;
    1096             : }
    1097             : 
    1098             : static int aldebaran_get_gpu_power(struct smu_context *smu, uint32_t *value)
    1099             : {
    1100           0 :         if (!value)
    1101             :                 return -EINVAL;
    1102             : 
    1103           0 :         return aldebaran_get_smu_metrics_data(smu,
    1104             :                                               METRICS_AVERAGE_SOCKETPOWER,
    1105             :                                               value);
    1106             : }
    1107             : 
    1108           0 : static int aldebaran_thermal_get_temperature(struct smu_context *smu,
    1109             :                                              enum amd_pp_sensors sensor,
    1110             :                                              uint32_t *value)
    1111             : {
    1112           0 :         int ret = 0;
    1113             : 
    1114           0 :         if (!value)
    1115             :                 return -EINVAL;
    1116             : 
    1117           0 :         switch (sensor) {
    1118             :         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
    1119             :                 ret = aldebaran_get_smu_metrics_data(smu,
    1120             :                                                      METRICS_TEMPERATURE_HOTSPOT,
    1121             :                                                      value);
    1122             :                 break;
    1123             :         case AMDGPU_PP_SENSOR_EDGE_TEMP:
    1124             :                 ret = aldebaran_get_smu_metrics_data(smu,
    1125             :                                                      METRICS_TEMPERATURE_EDGE,
    1126             :                                                      value);
    1127             :                 break;
    1128             :         case AMDGPU_PP_SENSOR_MEM_TEMP:
    1129             :                 ret = aldebaran_get_smu_metrics_data(smu,
    1130             :                                                      METRICS_TEMPERATURE_MEM,
    1131             :                                                      value);
    1132             :                 break;
    1133             :         default:
    1134           0 :                 dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
    1135           0 :                 return -EINVAL;
    1136             :         }
    1137             : 
    1138             :         return ret;
    1139             : }
    1140             : 
    1141           0 : static int aldebaran_read_sensor(struct smu_context *smu,
    1142             :                                  enum amd_pp_sensors sensor,
    1143             :                                  void *data, uint32_t *size)
    1144             : {
    1145           0 :         int ret = 0;
    1146             : 
    1147           0 :         if (amdgpu_ras_intr_triggered())
    1148             :                 return 0;
    1149             : 
    1150           0 :         if (!data || !size)
    1151             :                 return -EINVAL;
    1152             : 
    1153           0 :         switch (sensor) {
    1154             :         case AMDGPU_PP_SENSOR_MEM_LOAD:
    1155             :         case AMDGPU_PP_SENSOR_GPU_LOAD:
    1156           0 :                 ret = aldebaran_get_current_activity_percent(smu,
    1157             :                                                              sensor,
    1158             :                                                              (uint32_t *)data);
    1159           0 :                 *size = 4;
    1160           0 :                 break;
    1161             :         case AMDGPU_PP_SENSOR_GPU_POWER:
    1162           0 :                 ret = aldebaran_get_gpu_power(smu, (uint32_t *)data);
    1163           0 :                 *size = 4;
    1164           0 :                 break;
    1165             :         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
    1166             :         case AMDGPU_PP_SENSOR_EDGE_TEMP:
    1167             :         case AMDGPU_PP_SENSOR_MEM_TEMP:
    1168           0 :                 ret = aldebaran_thermal_get_temperature(smu, sensor,
    1169             :                                                         (uint32_t *)data);
    1170           0 :                 *size = 4;
    1171           0 :                 break;
    1172             :         case AMDGPU_PP_SENSOR_GFX_MCLK:
    1173           0 :                 ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
    1174             :                 /* the output clock frequency in 10K unit */
    1175           0 :                 *(uint32_t *)data *= 100;
    1176           0 :                 *size = 4;
    1177           0 :                 break;
    1178             :         case AMDGPU_PP_SENSOR_GFX_SCLK:
    1179           0 :                 ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
    1180           0 :                 *(uint32_t *)data *= 100;
    1181           0 :                 *size = 4;
    1182           0 :                 break;
    1183             :         case AMDGPU_PP_SENSOR_VDDGFX:
    1184           0 :                 ret = smu_v13_0_get_gfx_vdd(smu, (uint32_t *)data);
    1185           0 :                 *size = 4;
    1186           0 :                 break;
    1187             :         default:
    1188             :                 ret = -EOPNOTSUPP;
    1189             :                 break;
    1190             :         }
    1191             : 
    1192             :         return ret;
    1193             : }
    1194             : 
    1195           0 : static int aldebaran_get_power_limit(struct smu_context *smu,
    1196             :                                      uint32_t *current_power_limit,
    1197             :                                      uint32_t *default_power_limit,
    1198             :                                      uint32_t *max_power_limit)
    1199             : {
    1200           0 :         PPTable_t *pptable = smu->smu_table.driver_pptable;
    1201           0 :         uint32_t power_limit = 0;
    1202             :         int ret;
    1203             : 
    1204           0 :         if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
    1205           0 :                 if (current_power_limit)
    1206           0 :                         *current_power_limit = 0;
    1207           0 :                 if (default_power_limit)
    1208           0 :                         *default_power_limit = 0;
    1209           0 :                 if (max_power_limit)
    1210           0 :                         *max_power_limit = 0;
    1211             : 
    1212           0 :                 dev_warn(smu->adev->dev,
    1213             :                         "PPT feature is not enabled, power values can't be fetched.");
    1214             : 
    1215           0 :                 return 0;
    1216             :         }
    1217             : 
    1218             :         /* Valid power data is available only from primary die.
    1219             :          * For secondary die show the value as 0.
    1220             :          */
    1221           0 :         if (aldebaran_is_primary(smu)) {
    1222           0 :                 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit,
    1223             :                                            &power_limit);
    1224             : 
    1225           0 :                 if (ret) {
    1226             :                         /* the last hope to figure out the ppt limit */
    1227           0 :                         if (!pptable) {
    1228           0 :                                 dev_err(smu->adev->dev,
    1229             :                                         "Cannot get PPT limit due to pptable missing!");
    1230           0 :                                 return -EINVAL;
    1231             :                         }
    1232           0 :                         power_limit = pptable->PptLimit;
    1233             :                 }
    1234             :         }
    1235             : 
    1236           0 :         if (current_power_limit)
    1237           0 :                 *current_power_limit = power_limit;
    1238           0 :         if (default_power_limit)
    1239           0 :                 *default_power_limit = power_limit;
    1240             : 
    1241           0 :         if (max_power_limit) {
    1242           0 :                 if (pptable)
    1243           0 :                         *max_power_limit = pptable->PptLimit;
    1244             :         }
    1245             : 
    1246             :         return 0;
    1247             : }
    1248             : 
    1249           0 : static int aldebaran_set_power_limit(struct smu_context *smu,
    1250             :                                      enum smu_ppt_limit_type limit_type,
    1251             :                                      uint32_t limit)
    1252             : {
    1253             :         /* Power limit can be set only through primary die */
    1254           0 :         if (aldebaran_is_primary(smu))
    1255           0 :                 return smu_v13_0_set_power_limit(smu, limit_type, limit);
    1256             : 
    1257             :         return -EINVAL;
    1258             : }
    1259             : 
    1260           0 : static int aldebaran_system_features_control(struct  smu_context *smu, bool enable)
    1261             : {
    1262             :         int ret;
    1263             : 
    1264           0 :         ret = smu_v13_0_system_features_control(smu, enable);
    1265           0 :         if (!ret && enable)
    1266           0 :                 ret = aldebaran_run_btc(smu);
    1267             : 
    1268           0 :         return ret;
    1269             : }
    1270             : 
    1271           0 : static int aldebaran_set_performance_level(struct smu_context *smu,
    1272             :                                            enum amd_dpm_forced_level level)
    1273             : {
    1274           0 :         struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
    1275           0 :         struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
    1276           0 :         struct smu_13_0_dpm_table *gfx_table =
    1277             :                 &dpm_context->dpm_tables.gfx_table;
    1278           0 :         struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
    1279             : 
    1280             :         /* Disable determinism if switching to another mode */
    1281           0 :         if ((smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) &&
    1282             :             (level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)) {
    1283           0 :                 smu_cmn_send_smc_msg(smu, SMU_MSG_DisableDeterminism, NULL);
    1284           0 :                 pstate_table->gfxclk_pstate.curr.max = gfx_table->max;
    1285             :         }
    1286             : 
    1287           0 :         switch (level) {
    1288             : 
    1289             :         case AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM:
    1290             :                 return 0;
    1291             : 
    1292             :         case AMD_DPM_FORCED_LEVEL_HIGH:
    1293             :         case AMD_DPM_FORCED_LEVEL_LOW:
    1294             :         case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
    1295             :         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
    1296             :         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
    1297             :         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
    1298             :         default:
    1299             :                 break;
    1300             :         }
    1301             : 
    1302           0 :         return smu_v13_0_set_performance_level(smu, level);
    1303             : }
    1304             : 
    1305           0 : static int aldebaran_set_soft_freq_limited_range(struct smu_context *smu,
    1306             :                                           enum smu_clk_type clk_type,
    1307             :                                           uint32_t min,
    1308             :                                           uint32_t max)
    1309             : {
    1310           0 :         struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
    1311           0 :         struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
    1312           0 :         struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
    1313           0 :         struct amdgpu_device *adev = smu->adev;
    1314             :         uint32_t min_clk;
    1315             :         uint32_t max_clk;
    1316           0 :         int ret = 0;
    1317             : 
    1318           0 :         if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK)
    1319             :                 return -EINVAL;
    1320             : 
    1321           0 :         if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
    1322           0 :                         && (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM))
    1323             :                 return -EINVAL;
    1324             : 
    1325           0 :         if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
    1326           0 :                 if (min >= max) {
    1327           0 :                         dev_err(smu->adev->dev,
    1328             :                                 "Minimum GFX clk should be less than the maximum allowed clock\n");
    1329           0 :                         return -EINVAL;
    1330             :                 }
    1331             : 
    1332           0 :                 if ((min == pstate_table->gfxclk_pstate.curr.min) &&
    1333           0 :                     (max == pstate_table->gfxclk_pstate.curr.max))
    1334             :                         return 0;
    1335             : 
    1336           0 :                 ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_GFXCLK,
    1337             :                                                             min, max);
    1338           0 :                 if (!ret) {
    1339           0 :                         pstate_table->gfxclk_pstate.curr.min = min;
    1340           0 :                         pstate_table->gfxclk_pstate.curr.max = max;
    1341             :                 }
    1342             : 
    1343             :                 return ret;
    1344             :         }
    1345             : 
    1346           0 :         if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
    1347           0 :                 if (!max || (max < dpm_context->dpm_tables.gfx_table.min) ||
    1348           0 :                         (max > dpm_context->dpm_tables.gfx_table.max)) {
    1349           0 :                         dev_warn(adev->dev,
    1350             :                                         "Invalid max frequency %d MHz specified for determinism\n", max);
    1351           0 :                         return -EINVAL;
    1352             :                 }
    1353             : 
    1354             :                 /* Restore default min/max clocks and enable determinism */
    1355           0 :                 min_clk = dpm_context->dpm_tables.gfx_table.min;
    1356           0 :                 max_clk = dpm_context->dpm_tables.gfx_table.max;
    1357           0 :                 ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
    1358           0 :                 if (!ret) {
    1359           0 :                         usleep_range(500, 1000);
    1360           0 :                         ret = smu_cmn_send_smc_msg_with_param(smu,
    1361             :                                         SMU_MSG_EnableDeterminism,
    1362             :                                         max, NULL);
    1363           0 :                         if (ret) {
    1364           0 :                                 dev_err(adev->dev,
    1365             :                                                 "Failed to enable determinism at GFX clock %d MHz\n", max);
    1366             :                         } else {
    1367           0 :                                 pstate_table->gfxclk_pstate.curr.min = min_clk;
    1368           0 :                                 pstate_table->gfxclk_pstate.curr.max = max;
    1369             :                         }
    1370             :                 }
    1371             :         }
    1372             : 
    1373             :         return ret;
    1374             : }
    1375             : 
    1376           0 : static int aldebaran_usr_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
    1377             :                                                         long input[], uint32_t size)
    1378             : {
    1379           0 :         struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
    1380           0 :         struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
    1381           0 :         struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
    1382             :         uint32_t min_clk;
    1383             :         uint32_t max_clk;
    1384           0 :         int ret = 0;
    1385             : 
    1386             :         /* Only allowed in manual or determinism mode */
    1387           0 :         if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
    1388           0 :                         && (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM))
    1389             :                 return -EINVAL;
    1390             : 
    1391           0 :         switch (type) {
    1392             :         case PP_OD_EDIT_SCLK_VDDC_TABLE:
    1393           0 :                 if (size != 2) {
    1394           0 :                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
    1395           0 :                         return -EINVAL;
    1396             :                 }
    1397             : 
    1398           0 :                 if (input[0] == 0) {
    1399           0 :                         if (input[1] < dpm_context->dpm_tables.gfx_table.min) {
    1400           0 :                                 dev_warn(smu->adev->dev, "Minimum GFX clk (%ld) MHz specified is less than the minimum allowed (%d) MHz\n",
    1401             :                                         input[1], dpm_context->dpm_tables.gfx_table.min);
    1402           0 :                                 pstate_table->gfxclk_pstate.custom.min =
    1403           0 :                                         pstate_table->gfxclk_pstate.curr.min;
    1404           0 :                                 return -EINVAL;
    1405             :                         }
    1406             : 
    1407           0 :                         pstate_table->gfxclk_pstate.custom.min = input[1];
    1408           0 :                 } else if (input[0] == 1) {
    1409           0 :                         if (input[1] > dpm_context->dpm_tables.gfx_table.max) {
    1410           0 :                                 dev_warn(smu->adev->dev, "Maximum GFX clk (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
    1411             :                                         input[1], dpm_context->dpm_tables.gfx_table.max);
    1412           0 :                                 pstate_table->gfxclk_pstate.custom.max =
    1413           0 :                                         pstate_table->gfxclk_pstate.curr.max;
    1414           0 :                                 return -EINVAL;
    1415             :                         }
    1416             : 
    1417           0 :                         pstate_table->gfxclk_pstate.custom.max = input[1];
    1418             :                 } else {
    1419             :                         return -EINVAL;
    1420             :                 }
    1421             :                 break;
    1422             :         case PP_OD_RESTORE_DEFAULT_TABLE:
    1423           0 :                 if (size != 0) {
    1424           0 :                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
    1425           0 :                         return -EINVAL;
    1426             :                 } else {
    1427             :                         /* Use the default frequencies for manual and determinism mode */
    1428           0 :                         min_clk = dpm_context->dpm_tables.gfx_table.min;
    1429           0 :                         max_clk = dpm_context->dpm_tables.gfx_table.max;
    1430             : 
    1431           0 :                         return aldebaran_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
    1432             :                 }
    1433             :                 break;
    1434             :         case PP_OD_COMMIT_DPM_TABLE:
    1435           0 :                 if (size != 0) {
    1436           0 :                         dev_err(smu->adev->dev, "Input parameter number not correct\n");
    1437           0 :                         return -EINVAL;
    1438             :                 } else {
    1439           0 :                         if (!pstate_table->gfxclk_pstate.custom.min)
    1440           0 :                                 pstate_table->gfxclk_pstate.custom.min =
    1441           0 :                                         pstate_table->gfxclk_pstate.curr.min;
    1442             : 
    1443           0 :                         if (!pstate_table->gfxclk_pstate.custom.max)
    1444           0 :                                 pstate_table->gfxclk_pstate.custom.max =
    1445           0 :                                         pstate_table->gfxclk_pstate.curr.max;
    1446             : 
    1447           0 :                         min_clk = pstate_table->gfxclk_pstate.custom.min;
    1448           0 :                         max_clk = pstate_table->gfxclk_pstate.custom.max;
    1449             : 
    1450           0 :                         return aldebaran_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
    1451             :                 }
    1452             :                 break;
    1453             :         default:
    1454             :                 return -ENOSYS;
    1455             :         }
    1456             : 
    1457             :         return ret;
    1458             : }
    1459             : 
    1460           0 : static bool aldebaran_is_dpm_running(struct smu_context *smu)
    1461             : {
    1462             :         int ret;
    1463             :         uint64_t feature_enabled;
    1464             : 
    1465           0 :         ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
    1466           0 :         if (ret)
    1467             :                 return false;
    1468           0 :         return !!(feature_enabled & SMC_DPM_FEATURE);
    1469             : }
    1470             : 
    1471           0 : static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
    1472             :                               struct i2c_msg *msg, int num_msgs)
    1473             : {
    1474           0 :         struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
    1475           0 :         struct amdgpu_device *adev = smu_i2c->adev;
    1476           0 :         struct smu_context *smu = adev->powerplay.pp_handle;
    1477           0 :         struct smu_table_context *smu_table = &smu->smu_table;
    1478           0 :         struct smu_table *table = &smu_table->driver_table;
    1479           0 :         SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
    1480             :         int i, j, r, c;
    1481             :         u16 dir;
    1482             : 
    1483           0 :         if (!adev->pm.dpm_enabled)
    1484             :                 return -EBUSY;
    1485             : 
    1486           0 :         req = kzalloc(sizeof(*req), GFP_KERNEL);
    1487           0 :         if (!req)
    1488             :                 return -ENOMEM;
    1489             : 
    1490           0 :         req->I2CcontrollerPort = smu_i2c->port;
    1491           0 :         req->I2CSpeed = I2C_SPEED_FAST_400K;
    1492           0 :         req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
    1493           0 :         dir = msg[0].flags & I2C_M_RD;
    1494             : 
    1495           0 :         for (c = i = 0; i < num_msgs; i++) {
    1496           0 :                 for (j = 0; j < msg[i].len; j++, c++) {
    1497           0 :                         SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
    1498             : 
    1499           0 :                         if (!(msg[i].flags & I2C_M_RD)) {
    1500             :                                 /* write */
    1501           0 :                                 cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
    1502           0 :                                 cmd->ReadWriteData = msg[i].buf[j];
    1503             :                         }
    1504             : 
    1505           0 :                         if ((dir ^ msg[i].flags) & I2C_M_RD) {
    1506             :                                 /* The direction changes.
    1507             :                                  */
    1508           0 :                                 dir = msg[i].flags & I2C_M_RD;
    1509           0 :                                 cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
    1510             :                         }
    1511             : 
    1512           0 :                         req->NumCmds++;
    1513             : 
    1514             :                         /*
    1515             :                          * Insert STOP if we are at the last byte of either last
    1516             :                          * message for the transaction or the client explicitly
    1517             :                          * requires a STOP at this particular message.
    1518             :                          */
    1519           0 :                         if ((j == msg[i].len - 1) &&
    1520           0 :                             ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
    1521           0 :                                 cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
    1522           0 :                                 cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
    1523             :                         }
    1524             :                 }
    1525             :         }
    1526           0 :         mutex_lock(&adev->pm.mutex);
    1527           0 :         r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
    1528           0 :         mutex_unlock(&adev->pm.mutex);
    1529           0 :         if (r)
    1530             :                 goto fail;
    1531             : 
    1532           0 :         for (c = i = 0; i < num_msgs; i++) {
    1533           0 :                 if (!(msg[i].flags & I2C_M_RD)) {
    1534           0 :                         c += msg[i].len;
    1535           0 :                         continue;
    1536             :                 }
    1537           0 :                 for (j = 0; j < msg[i].len; j++, c++) {
    1538           0 :                         SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
    1539             : 
    1540           0 :                         msg[i].buf[j] = cmd->ReadWriteData;
    1541             :                 }
    1542             :         }
    1543             :         r = num_msgs;
    1544             : fail:
    1545           0 :         kfree(req);
    1546           0 :         return r;
    1547             : }
    1548             : 
    1549           0 : static u32 aldebaran_i2c_func(struct i2c_adapter *adap)
    1550             : {
    1551           0 :         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
    1552             : }
    1553             : 
    1554             : 
    1555             : static const struct i2c_algorithm aldebaran_i2c_algo = {
    1556             :         .master_xfer = aldebaran_i2c_xfer,
    1557             :         .functionality = aldebaran_i2c_func,
    1558             : };
    1559             : 
    1560             : static const struct i2c_adapter_quirks aldebaran_i2c_control_quirks = {
    1561             :         .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
    1562             :         .max_read_len  = MAX_SW_I2C_COMMANDS,
    1563             :         .max_write_len = MAX_SW_I2C_COMMANDS,
    1564             :         .max_comb_1st_msg_len = 2,
    1565             :         .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
    1566             : };
    1567             : 
    1568           0 : static int aldebaran_i2c_control_init(struct smu_context *smu)
    1569             : {
    1570           0 :         struct amdgpu_device *adev = smu->adev;
    1571           0 :         struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[0];
    1572           0 :         struct i2c_adapter *control = &smu_i2c->adapter;
    1573             :         int res;
    1574             : 
    1575           0 :         smu_i2c->adev = adev;
    1576           0 :         smu_i2c->port = 0;
    1577           0 :         mutex_init(&smu_i2c->mutex);
    1578           0 :         control->owner = THIS_MODULE;
    1579           0 :         control->class = I2C_CLASS_SPD;
    1580           0 :         control->dev.parent = &adev->pdev->dev;
    1581           0 :         control->algo = &aldebaran_i2c_algo;
    1582           0 :         snprintf(control->name, sizeof(control->name), "AMDGPU SMU 0");
    1583           0 :         control->quirks = &aldebaran_i2c_control_quirks;
    1584           0 :         i2c_set_adapdata(control, smu_i2c);
    1585             : 
    1586           0 :         res = i2c_add_adapter(control);
    1587           0 :         if (res) {
    1588           0 :                 DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
    1589             :                 goto Out_err;
    1590             :         }
    1591             : 
    1592           0 :         adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
    1593           0 :         adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
    1594             : 
    1595           0 :         return 0;
    1596             : Out_err:
    1597           0 :         i2c_del_adapter(control);
    1598             : 
    1599           0 :         return res;
    1600             : }
    1601             : 
    1602           0 : static void aldebaran_i2c_control_fini(struct smu_context *smu)
    1603             : {
    1604           0 :         struct amdgpu_device *adev = smu->adev;
    1605             :         int i;
    1606             : 
    1607           0 :         for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
    1608           0 :                 struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
    1609           0 :                 struct i2c_adapter *control = &smu_i2c->adapter;
    1610             : 
    1611           0 :                 i2c_del_adapter(control);
    1612             :         }
    1613           0 :         adev->pm.ras_eeprom_i2c_bus = NULL;
    1614           0 :         adev->pm.fru_eeprom_i2c_bus = NULL;
    1615           0 : }
    1616             : 
    1617           0 : static void aldebaran_get_unique_id(struct smu_context *smu)
    1618             : {
    1619           0 :         struct amdgpu_device *adev = smu->adev;
    1620           0 :         uint32_t upper32 = 0, lower32 = 0;
    1621             : 
    1622           0 :         if (aldebaran_get_smu_metrics_data(smu, METRICS_UNIQUE_ID_UPPER32, &upper32))
    1623             :                 goto out;
    1624             :         if (aldebaran_get_smu_metrics_data(smu, METRICS_UNIQUE_ID_LOWER32, &lower32))
    1625             :                 goto out;
    1626             : 
    1627             : out:
    1628           0 :         adev->unique_id = ((uint64_t)upper32 << 32) | lower32;
    1629           0 :         if (adev->serial[0] == '\0')
    1630           0 :                 sprintf(adev->serial, "%016llx", adev->unique_id);
    1631           0 : }
    1632             : 
    1633           0 : static bool aldebaran_is_baco_supported(struct smu_context *smu)
    1634             : {
    1635             :         /* aldebaran is not support baco */
    1636             : 
    1637           0 :         return false;
    1638             : }
    1639             : 
    1640           0 : static int aldebaran_set_df_cstate(struct smu_context *smu,
    1641             :                                    enum pp_df_cstate state)
    1642             : {
    1643           0 :         return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state, NULL);
    1644             : }
    1645             : 
    1646           0 : static int aldebaran_allow_xgmi_power_down(struct smu_context *smu, bool en)
    1647             : {
    1648           0 :         struct amdgpu_device *adev = smu->adev;
    1649             : 
    1650             :         /* The message only works on master die and NACK will be sent
    1651             :            back for other dies, only send it on master die */
    1652           0 :         if (!adev->smuio.funcs->get_socket_id(adev) &&
    1653           0 :             !adev->smuio.funcs->get_die_id(adev))
    1654           0 :                 return smu_cmn_send_smc_msg_with_param(smu,
    1655             :                                    SMU_MSG_GmiPwrDnControl,
    1656           0 :                                    en ? 0 : 1,
    1657             :                                    NULL);
    1658             :         else
    1659             :                 return 0;
    1660             : }
    1661             : 
    1662             : static const struct throttling_logging_label {
    1663             :         uint32_t feature_mask;
    1664             :         const char *label;
    1665             : } logging_label[] = {
    1666             :         {(1U << THROTTLER_TEMP_GPU_BIT), "GPU"},
    1667             :         {(1U << THROTTLER_TEMP_MEM_BIT), "HBM"},
    1668             :         {(1U << THROTTLER_TEMP_VR_GFX_BIT), "VR of GFX rail"},
    1669             :         {(1U << THROTTLER_TEMP_VR_MEM_BIT), "VR of HBM rail"},
    1670             :         {(1U << THROTTLER_TEMP_VR_SOC_BIT), "VR of SOC rail"},
    1671             : };
    1672           0 : static void aldebaran_log_thermal_throttling_event(struct smu_context *smu)
    1673             : {
    1674             :         int ret;
    1675           0 :         int throttler_idx, throtting_events = 0, buf_idx = 0;
    1676           0 :         struct amdgpu_device *adev = smu->adev;
    1677             :         uint32_t throttler_status;
    1678             :         char log_buf[256];
    1679             : 
    1680           0 :         ret = aldebaran_get_smu_metrics_data(smu,
    1681             :                                              METRICS_THROTTLER_STATUS,
    1682             :                                              &throttler_status);
    1683           0 :         if (ret)
    1684           0 :                 return;
    1685             : 
    1686           0 :         memset(log_buf, 0, sizeof(log_buf));
    1687           0 :         for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label);
    1688           0 :              throttler_idx++) {
    1689           0 :                 if (throttler_status & logging_label[throttler_idx].feature_mask) {
    1690           0 :                         throtting_events++;
    1691           0 :                         buf_idx += snprintf(log_buf + buf_idx,
    1692             :                                             sizeof(log_buf) - buf_idx,
    1693             :                                             "%s%s",
    1694             :                                             throtting_events > 1 ? " and " : "",
    1695             :                                             logging_label[throttler_idx].label);
    1696           0 :                         if (buf_idx >= sizeof(log_buf)) {
    1697           0 :                                 dev_err(adev->dev, "buffer overflow!\n");
    1698           0 :                                 log_buf[sizeof(log_buf) - 1] = '\0';
    1699           0 :                                 break;
    1700             :                         }
    1701             :                 }
    1702             :         }
    1703             : 
    1704           0 :         dev_warn(adev->dev, "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n",
    1705             :                  log_buf);
    1706           0 :         kgd2kfd_smi_event_throttle(smu->adev->kfd.dev,
    1707             :                 smu_cmn_get_indep_throttler_status(throttler_status,
    1708             :                                                    aldebaran_throttler_map));
    1709             : }
    1710             : 
    1711           0 : static int aldebaran_get_current_pcie_link_speed(struct smu_context *smu)
    1712             : {
    1713           0 :         struct amdgpu_device *adev = smu->adev;
    1714             :         uint32_t esm_ctrl;
    1715             : 
    1716             :         /* TODO: confirm this on real target */
    1717           0 :         esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL);
    1718           0 :         if ((esm_ctrl >> 15) & 0x1FFFF)
    1719           0 :                 return (((esm_ctrl >> 8) & 0x3F) + 128);
    1720             : 
    1721           0 :         return smu_v13_0_get_current_pcie_link_speed(smu);
    1722             : }
    1723             : 
    1724           0 : static ssize_t aldebaran_get_gpu_metrics(struct smu_context *smu,
    1725             :                                          void **table)
    1726             : {
    1727           0 :         struct smu_table_context *smu_table = &smu->smu_table;
    1728           0 :         struct gpu_metrics_v1_3 *gpu_metrics =
    1729             :                 (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
    1730             :         SmuMetrics_t metrics;
    1731           0 :         int i, ret = 0;
    1732             : 
    1733           0 :         ret = smu_cmn_get_metrics_table(smu,
    1734             :                                         &metrics,
    1735             :                                         true);
    1736           0 :         if (ret)
    1737           0 :                 return ret;
    1738             : 
    1739           0 :         smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
    1740             : 
    1741           0 :         gpu_metrics->temperature_edge = metrics.TemperatureEdge;
    1742           0 :         gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
    1743           0 :         gpu_metrics->temperature_mem = metrics.TemperatureHBM;
    1744           0 :         gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
    1745           0 :         gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
    1746           0 :         gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem;
    1747             : 
    1748           0 :         gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
    1749           0 :         gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
    1750           0 :         gpu_metrics->average_mm_activity = 0;
    1751             : 
    1752             :         /* Valid power data is available only from primary die */
    1753           0 :         if (aldebaran_is_primary(smu)) {
    1754           0 :                 gpu_metrics->average_socket_power = metrics.AverageSocketPower;
    1755           0 :                 gpu_metrics->energy_accumulator =
    1756           0 :                         (uint64_t)metrics.EnergyAcc64bitHigh << 32 |
    1757           0 :                         metrics.EnergyAcc64bitLow;
    1758             :         } else {
    1759           0 :                 gpu_metrics->average_socket_power = 0;
    1760           0 :                 gpu_metrics->energy_accumulator = 0;
    1761             :         }
    1762             : 
    1763           0 :         gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
    1764           0 :         gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
    1765           0 :         gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
    1766           0 :         gpu_metrics->average_vclk0_frequency = 0;
    1767           0 :         gpu_metrics->average_dclk0_frequency = 0;
    1768             : 
    1769           0 :         gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
    1770           0 :         gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
    1771           0 :         gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
    1772           0 :         gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
    1773           0 :         gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
    1774             : 
    1775           0 :         gpu_metrics->throttle_status = metrics.ThrottlerStatus;
    1776           0 :         gpu_metrics->indep_throttle_status =
    1777           0 :                         smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
    1778             :                                                            aldebaran_throttler_map);
    1779             : 
    1780           0 :         gpu_metrics->current_fan_speed = 0;
    1781             : 
    1782           0 :         gpu_metrics->pcie_link_width =
    1783           0 :                 smu_v13_0_get_current_pcie_link_width(smu);
    1784           0 :         gpu_metrics->pcie_link_speed =
    1785           0 :                 aldebaran_get_current_pcie_link_speed(smu);
    1786             : 
    1787           0 :         gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
    1788             : 
    1789           0 :         gpu_metrics->gfx_activity_acc = metrics.GfxBusyAcc;
    1790           0 :         gpu_metrics->mem_activity_acc = metrics.DramBusyAcc;
    1791             : 
    1792           0 :         for (i = 0; i < NUM_HBM_INSTANCES; i++)
    1793           0 :                 gpu_metrics->temperature_hbm[i] = metrics.TemperatureAllHBM[i];
    1794             : 
    1795           0 :         gpu_metrics->firmware_timestamp = ((uint64_t)metrics.TimeStampHigh << 32) |
    1796           0 :                                         metrics.TimeStampLow;
    1797             : 
    1798           0 :         *table = (void *)gpu_metrics;
    1799             : 
    1800           0 :         return sizeof(struct gpu_metrics_v1_3);
    1801             : }
    1802             : 
    1803           0 : static int aldebaran_check_ecc_table_support(struct smu_context *smu,
    1804             :                 int *ecctable_version)
    1805             : {
    1806           0 :         uint32_t if_version = 0xff, smu_version = 0xff;
    1807           0 :         int ret = 0;
    1808             : 
    1809           0 :         ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
    1810           0 :         if (ret) {
    1811             :                 /* return not support if failed get smu_version */
    1812           0 :                 ret = -EOPNOTSUPP;
    1813             :         }
    1814             : 
    1815           0 :         if (smu_version < SUPPORT_ECCTABLE_SMU_VERSION)
    1816             :                 ret = -EOPNOTSUPP;
    1817           0 :         else if (smu_version >= SUPPORT_ECCTABLE_SMU_VERSION &&
    1818             :                         smu_version < SUPPORT_ECCTABLE_V2_SMU_VERSION)
    1819           0 :                 *ecctable_version = 1;
    1820             :         else
    1821           0 :                 *ecctable_version = 2;
    1822             : 
    1823           0 :         return ret;
    1824             : }
    1825             : 
    1826           0 : static ssize_t aldebaran_get_ecc_info(struct smu_context *smu,
    1827             :                                          void *table)
    1828             : {
    1829           0 :         struct smu_table_context *smu_table = &smu->smu_table;
    1830           0 :         EccInfoTable_t *ecc_table = NULL;
    1831           0 :         struct ecc_info_per_ch *ecc_info_per_channel = NULL;
    1832           0 :         int i, ret = 0;
    1833           0 :         int table_version = 0;
    1834           0 :         struct umc_ecc_info *eccinfo = (struct umc_ecc_info *)table;
    1835             : 
    1836           0 :         ret = aldebaran_check_ecc_table_support(smu, &table_version);
    1837           0 :         if (ret)
    1838           0 :                 return ret;
    1839             : 
    1840           0 :         ret = smu_cmn_update_table(smu,
    1841             :                                SMU_TABLE_ECCINFO,
    1842             :                                0,
    1843             :                                smu_table->ecc_table,
    1844             :                                false);
    1845           0 :         if (ret) {
    1846           0 :                 dev_info(smu->adev->dev, "Failed to export SMU ecc table!\n");
    1847           0 :                 return ret;
    1848             :         }
    1849             : 
    1850           0 :         ecc_table = (EccInfoTable_t *)smu_table->ecc_table;
    1851             : 
    1852           0 :         if (table_version == 1) {
    1853           0 :                 for (i = 0; i < ALDEBARAN_UMC_CHANNEL_NUM; i++) {
    1854           0 :                         ecc_info_per_channel = &(eccinfo->ecc[i]);
    1855           0 :                         ecc_info_per_channel->ce_count_lo_chip =
    1856           0 :                                 ecc_table->EccInfo[i].ce_count_lo_chip;
    1857           0 :                         ecc_info_per_channel->ce_count_hi_chip =
    1858           0 :                                 ecc_table->EccInfo[i].ce_count_hi_chip;
    1859           0 :                         ecc_info_per_channel->mca_umc_status =
    1860           0 :                                 ecc_table->EccInfo[i].mca_umc_status;
    1861           0 :                         ecc_info_per_channel->mca_umc_addr =
    1862           0 :                                 ecc_table->EccInfo[i].mca_umc_addr;
    1863             :                 }
    1864           0 :         } else if (table_version == 2) {
    1865           0 :                 for (i = 0; i < ALDEBARAN_UMC_CHANNEL_NUM; i++) {
    1866           0 :                         ecc_info_per_channel = &(eccinfo->ecc[i]);
    1867           0 :                         ecc_info_per_channel->ce_count_lo_chip =
    1868           0 :                                 ecc_table->EccInfo_V2[i].ce_count_lo_chip;
    1869           0 :                         ecc_info_per_channel->ce_count_hi_chip =
    1870           0 :                                 ecc_table->EccInfo_V2[i].ce_count_hi_chip;
    1871           0 :                         ecc_info_per_channel->mca_umc_status =
    1872           0 :                                 ecc_table->EccInfo_V2[i].mca_umc_status;
    1873           0 :                         ecc_info_per_channel->mca_umc_addr =
    1874           0 :                                 ecc_table->EccInfo_V2[i].mca_umc_addr;
    1875           0 :                         ecc_info_per_channel->mca_ceumc_addr =
    1876           0 :                                 ecc_table->EccInfo_V2[i].mca_ceumc_addr;
    1877             :                 }
    1878           0 :                 eccinfo->record_ce_addr_supported = 1;
    1879             :         }
    1880             : 
    1881           0 :         return ret;
    1882             : }
    1883             : 
    1884           0 : static int aldebaran_mode1_reset(struct smu_context *smu)
    1885             : {
    1886             :         u32 smu_version, fatal_err, param;
    1887           0 :         int ret = 0;
    1888           0 :         struct amdgpu_device *adev = smu->adev;
    1889           0 :         struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
    1890             : 
    1891           0 :         fatal_err = 0;
    1892           0 :         param = SMU_RESET_MODE_1;
    1893             : 
    1894             :         /*
    1895             :         * PM FW support SMU_MSG_GfxDeviceDriverReset from 68.07
    1896             :         */
    1897           0 :         smu_cmn_get_smc_version(smu, NULL, &smu_version);
    1898           0 :         if (smu_version < 0x00440700) {
    1899           0 :                 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_Mode1Reset, NULL);
    1900             :         }
    1901             :         else {
    1902             :                 /* fatal error triggered by ras, PMFW supports the flag
    1903             :                    from 68.44.0 */
    1904           0 :                 if ((smu_version >= 0x00442c00) && ras &&
    1905           0 :                     atomic_read(&ras->in_recovery))
    1906           0 :                         fatal_err = 1;
    1907             : 
    1908           0 :                 param |= (fatal_err << 16);
    1909           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu,
    1910             :                                         SMU_MSG_GfxDeviceDriverReset, param, NULL);
    1911             :         }
    1912             : 
    1913           0 :         if (!ret)
    1914           0 :                 msleep(SMU13_MODE1_RESET_WAIT_TIME_IN_MS);
    1915             : 
    1916           0 :         return ret;
    1917             : }
    1918             : 
    1919           0 : static int aldebaran_mode2_reset(struct smu_context *smu)
    1920             : {
    1921             :         u32 smu_version;
    1922           0 :         int ret = 0, index;
    1923           0 :         struct amdgpu_device *adev = smu->adev;
    1924           0 :         int timeout = 10;
    1925             : 
    1926           0 :         smu_cmn_get_smc_version(smu, NULL, &smu_version);
    1927             : 
    1928           0 :         index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG,
    1929             :                                                 SMU_MSG_GfxDeviceDriverReset);
    1930             : 
    1931           0 :         mutex_lock(&smu->message_lock);
    1932           0 :         if (smu_version >= 0x00441400) {
    1933           0 :                 ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index, SMU_RESET_MODE_2);
    1934             :                 /* This is similar to FLR, wait till max FLR timeout */
    1935           0 :                 msleep(100);
    1936             :                 dev_dbg(smu->adev->dev, "restore config space...\n");
    1937             :                 /* Restore the config space saved during init */
    1938           0 :                 amdgpu_device_load_pci_state(adev->pdev);
    1939             : 
    1940             :                 dev_dbg(smu->adev->dev, "wait for reset ack\n");
    1941           0 :                 while (ret == -ETIME && timeout)  {
    1942           0 :                         ret = smu_cmn_wait_for_response(smu);
    1943             :                         /* Wait a bit more time for getting ACK */
    1944           0 :                         if (ret == -ETIME) {
    1945           0 :                                 --timeout;
    1946           0 :                                 usleep_range(500, 1000);
    1947           0 :                                 continue;
    1948             :                         }
    1949             : 
    1950           0 :                         if (ret != 1) {
    1951           0 :                                 dev_err(adev->dev, "failed to send mode2 message \tparam: 0x%08x response %#x\n",
    1952             :                                                 SMU_RESET_MODE_2, ret);
    1953           0 :                                 goto out;
    1954             :                         }
    1955             :                 }
    1956             : 
    1957             :         } else {
    1958           0 :                 dev_err(adev->dev, "smu fw 0x%x does not support MSG_GfxDeviceDriverReset MSG\n",
    1959             :                                 smu_version);
    1960             :         }
    1961             : 
    1962           0 :         if (ret == 1)
    1963           0 :                 ret = 0;
    1964             : out:
    1965           0 :         mutex_unlock(&smu->message_lock);
    1966             : 
    1967           0 :         return ret;
    1968             : }
    1969             : 
    1970           0 : static int aldebaran_smu_handle_passthrough_sbr(struct smu_context *smu, bool enable)
    1971             : {
    1972           0 :         int ret = 0;
    1973           0 :         ret =  smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_HeavySBR, enable ? 1 : 0, NULL);
    1974             : 
    1975           0 :         return ret;
    1976             : }
    1977             : 
    1978           0 : static bool aldebaran_is_mode1_reset_supported(struct smu_context *smu)
    1979             : {
    1980             : #if 0
    1981             :         struct amdgpu_device *adev = smu->adev;
    1982             :         u32 smu_version;
    1983             :         uint32_t val;
    1984             :         /**
    1985             :          * PM FW version support mode1 reset from 68.07
    1986             :          */
    1987             :         smu_cmn_get_smc_version(smu, NULL, &smu_version);
    1988             :         if ((smu_version < 0x00440700))
    1989             :                 return false;
    1990             :         /**
    1991             :          * mode1 reset relies on PSP, so we should check if
    1992             :          * PSP is alive.
    1993             :          */
    1994             :         val = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81);
    1995             : 
    1996             :         return val != 0x0;
    1997             : #endif
    1998           0 :         return true;
    1999             : }
    2000             : 
    2001           0 : static bool aldebaran_is_mode2_reset_supported(struct smu_context *smu)
    2002             : {
    2003           0 :         return true;
    2004             : }
    2005             : 
    2006           0 : static int aldebaran_set_mp1_state(struct smu_context *smu,
    2007             :                                    enum pp_mp1_state mp1_state)
    2008             : {
    2009           0 :         switch (mp1_state) {
    2010             :         case PP_MP1_STATE_UNLOAD:
    2011           0 :                 return smu_cmn_set_mp1_state(smu, mp1_state);
    2012             :         default:
    2013             :                 return 0;
    2014             :         }
    2015             : }
    2016             : 
    2017           0 : static int aldebaran_smu_send_hbm_bad_page_num(struct smu_context *smu,
    2018             :                 uint32_t size)
    2019             : {
    2020           0 :         int ret = 0;
    2021             : 
    2022             :         /* message SMU to update the bad page number on SMUBUS */
    2023           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetNumBadHbmPagesRetired, size, NULL);
    2024           0 :         if (ret)
    2025           0 :                 dev_err(smu->adev->dev, "[%s] failed to message SMU to update HBM bad pages number\n",
    2026             :                                 __func__);
    2027             : 
    2028           0 :         return ret;
    2029             : }
    2030             : 
    2031           0 : static int aldebaran_check_bad_channel_info_support(struct smu_context *smu)
    2032             : {
    2033           0 :         uint32_t if_version = 0xff, smu_version = 0xff;
    2034           0 :         int ret = 0;
    2035             : 
    2036           0 :         ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
    2037           0 :         if (ret) {
    2038             :                 /* return not support if failed get smu_version */
    2039           0 :                 ret = -EOPNOTSUPP;
    2040             :         }
    2041             : 
    2042           0 :         if (smu_version < SUPPORT_BAD_CHANNEL_INFO_MSG_VERSION)
    2043           0 :                 ret = -EOPNOTSUPP;
    2044             : 
    2045           0 :         return ret;
    2046             : }
    2047             : 
    2048           0 : static int aldebaran_send_hbm_bad_channel_flag(struct smu_context *smu,
    2049             :                 uint32_t size)
    2050             : {
    2051           0 :         int ret = 0;
    2052             : 
    2053           0 :         ret = aldebaran_check_bad_channel_info_support(smu);
    2054           0 :         if (ret)
    2055             :                 return ret;
    2056             : 
    2057             :         /* message SMU to update the bad channel info on SMUBUS */
    2058           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetBadHBMPagesRetiredFlagsPerChannel, size, NULL);
    2059           0 :         if (ret)
    2060           0 :                 dev_err(smu->adev->dev, "[%s] failed to message SMU to update HBM bad channel info\n",
    2061             :                                 __func__);
    2062             : 
    2063             :         return ret;
    2064             : }
    2065             : 
    2066             : static const struct pptable_funcs aldebaran_ppt_funcs = {
    2067             :         /* init dpm */
    2068             :         .get_allowed_feature_mask = aldebaran_get_allowed_feature_mask,
    2069             :         /* dpm/clk tables */
    2070             :         .set_default_dpm_table = aldebaran_set_default_dpm_table,
    2071             :         .populate_umd_state_clk = aldebaran_populate_umd_state_clk,
    2072             :         .get_thermal_temperature_range = aldebaran_get_thermal_temperature_range,
    2073             :         .print_clk_levels = aldebaran_print_clk_levels,
    2074             :         .force_clk_levels = aldebaran_force_clk_levels,
    2075             :         .read_sensor = aldebaran_read_sensor,
    2076             :         .set_performance_level = aldebaran_set_performance_level,
    2077             :         .get_power_limit = aldebaran_get_power_limit,
    2078             :         .is_dpm_running = aldebaran_is_dpm_running,
    2079             :         .get_unique_id = aldebaran_get_unique_id,
    2080             :         .init_microcode = smu_v13_0_init_microcode,
    2081             :         .load_microcode = smu_v13_0_load_microcode,
    2082             :         .fini_microcode = smu_v13_0_fini_microcode,
    2083             :         .init_smc_tables = aldebaran_init_smc_tables,
    2084             :         .fini_smc_tables = smu_v13_0_fini_smc_tables,
    2085             :         .init_power = smu_v13_0_init_power,
    2086             :         .fini_power = smu_v13_0_fini_power,
    2087             :         .check_fw_status = smu_v13_0_check_fw_status,
    2088             :         /* pptable related */
    2089             :         .setup_pptable = aldebaran_setup_pptable,
    2090             :         .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
    2091             :         .check_fw_version = smu_v13_0_check_fw_version,
    2092             :         .write_pptable = smu_cmn_write_pptable,
    2093             :         .set_driver_table_location = smu_v13_0_set_driver_table_location,
    2094             :         .set_tool_table_location = smu_v13_0_set_tool_table_location,
    2095             :         .notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
    2096             :         .system_features_control = aldebaran_system_features_control,
    2097             :         .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
    2098             :         .send_smc_msg = smu_cmn_send_smc_msg,
    2099             :         .get_enabled_mask = smu_cmn_get_enabled_mask,
    2100             :         .feature_is_enabled = smu_cmn_feature_is_enabled,
    2101             :         .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
    2102             :         .set_power_limit = aldebaran_set_power_limit,
    2103             :         .init_max_sustainable_clocks = smu_v13_0_init_max_sustainable_clocks,
    2104             :         .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
    2105             :         .disable_thermal_alert = smu_v13_0_disable_thermal_alert,
    2106             :         .set_xgmi_pstate = smu_v13_0_set_xgmi_pstate,
    2107             :         .register_irq_handler = smu_v13_0_register_irq_handler,
    2108             :         .set_azalia_d3_pme = smu_v13_0_set_azalia_d3_pme,
    2109             :         .get_max_sustainable_clocks_by_dc = smu_v13_0_get_max_sustainable_clocks_by_dc,
    2110             :         .baco_is_support= aldebaran_is_baco_supported,
    2111             :         .get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq,
    2112             :         .set_soft_freq_limited_range = aldebaran_set_soft_freq_limited_range,
    2113             :         .od_edit_dpm_table = aldebaran_usr_edit_dpm_table,
    2114             :         .set_df_cstate = aldebaran_set_df_cstate,
    2115             :         .allow_xgmi_power_down = aldebaran_allow_xgmi_power_down,
    2116             :         .log_thermal_throttling_event = aldebaran_log_thermal_throttling_event,
    2117             :         .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
    2118             :         .set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
    2119             :         .get_gpu_metrics = aldebaran_get_gpu_metrics,
    2120             :         .mode1_reset_is_support = aldebaran_is_mode1_reset_supported,
    2121             :         .mode2_reset_is_support = aldebaran_is_mode2_reset_supported,
    2122             :         .smu_handle_passthrough_sbr = aldebaran_smu_handle_passthrough_sbr,
    2123             :         .mode1_reset = aldebaran_mode1_reset,
    2124             :         .set_mp1_state = aldebaran_set_mp1_state,
    2125             :         .mode2_reset = aldebaran_mode2_reset,
    2126             :         .wait_for_event = smu_v13_0_wait_for_event,
    2127             :         .i2c_init = aldebaran_i2c_control_init,
    2128             :         .i2c_fini = aldebaran_i2c_control_fini,
    2129             :         .send_hbm_bad_pages_num = aldebaran_smu_send_hbm_bad_page_num,
    2130             :         .get_ecc_info = aldebaran_get_ecc_info,
    2131             :         .send_hbm_bad_channel_flag = aldebaran_send_hbm_bad_channel_flag,
    2132             : };
    2133             : 
    2134           0 : void aldebaran_set_ppt_funcs(struct smu_context *smu)
    2135             : {
    2136           0 :         smu->ppt_funcs = &aldebaran_ppt_funcs;
    2137           0 :         smu->message_map = aldebaran_message_map;
    2138           0 :         smu->clock_map = aldebaran_clk_map;
    2139           0 :         smu->feature_map = aldebaran_feature_mask_map;
    2140           0 :         smu->table_map = aldebaran_table_map;
    2141           0 :         smu_v13_0_set_smu_mailbox_registers(smu);
    2142           0 : }

Generated by: LCOV version 1.14