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