File Index
Files and directories
Sign in
FILE

smu_v14_0_2_ppt.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c C
   1/*
   2 * Copyright 2023 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 */
  23
  24#define SWSMU_CODE_LAYER_L2
  25
  26#include <linux/firmware.h>
  27#include <linux/pci.h>
  28#include <linux/i2c.h>
  29#include "amdgpu.h"
  30#include "amdgpu_smu.h"
  31#include "atomfirmware.h"
  32#include "amdgpu_atomfirmware.h"
  33#include "amdgpu_atombios.h"
  34#include "smu_v14_0.h"
  35#include "smu14_driver_if_v14_0.h"
  36#include "soc15_common.h"
  37#include "atom.h"
  38#include "smu_v14_0_2_ppt.h"
  39#include "smu_v14_0_2_pptable.h"
  40#include "smu_v14_0_2_ppsmc.h"
  41#include "mp/mp_14_0_2_offset.h"
  42#include "mp/mp_14_0_2_sh_mask.h"
  43
  44#include "smu_cmn.h"
  45#include "amdgpu_ras.h"
  46
  47/*
  48 * DO NOT use these for err/warn/info/debug messages.
  49 * Use dev_err, dev_warn, dev_info and dev_dbg instead.
  50 * They are more MGPU friendly.
  51 */
  52#undef pr_err
  53#undef pr_warn
  54#undef pr_info
  55#undef pr_debug
  56
  57#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
  58
  59#define FEATURE_MASK(feature) (1ULL << feature)
  60#define SMC_DPM_FEATURE ( \
  61	FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)     | \
  62	FEATURE_MASK(FEATURE_DPM_UCLK_BIT)	 | \
  63	FEATURE_MASK(FEATURE_DPM_LINK_BIT)       | \
  64	FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)     | \
  65	FEATURE_MASK(FEATURE_DPM_FCLK_BIT))
  66
  67#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE	0x4000
  68#define DEBUGSMC_MSG_Mode1Reset        2
  69#define LINK_SPEED_MAX					3
  70
  71#define PP_OD_FEATURE_GFXCLK_FMIN			0
  72#define PP_OD_FEATURE_GFXCLK_FMAX			1
  73#define PP_OD_FEATURE_UCLK_FMIN				2
  74#define PP_OD_FEATURE_UCLK_FMAX				3
  75#define PP_OD_FEATURE_GFX_VF_CURVE			4
  76#define PP_OD_FEATURE_FAN_CURVE_TEMP			5
  77#define PP_OD_FEATURE_FAN_CURVE_PWM			6
  78#define PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT		7
  79#define PP_OD_FEATURE_FAN_ACOUSTIC_TARGET		8
  80#define PP_OD_FEATURE_FAN_TARGET_TEMPERATURE		9
  81#define PP_OD_FEATURE_FAN_MINIMUM_PWM			10
  82#define PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE		11
  83
  84static struct cmn2asic_msg_mapping smu_v14_0_2_message_map[SMU_MSG_MAX_COUNT] = {
  85	MSG_MAP(TestMessage,			PPSMC_MSG_TestMessage,                 1),
  86	MSG_MAP(GetSmuVersion,			PPSMC_MSG_GetSmuVersion,               1),
  87	MSG_MAP(GetDriverIfVersion,		PPSMC_MSG_GetDriverIfVersion,          1),
  88	MSG_MAP(SetAllowedFeaturesMaskLow,	PPSMC_MSG_SetAllowedFeaturesMaskLow,   0),
  89	MSG_MAP(SetAllowedFeaturesMaskHigh,	PPSMC_MSG_SetAllowedFeaturesMaskHigh,  0),
  90	MSG_MAP(EnableAllSmuFeatures,		PPSMC_MSG_EnableAllSmuFeatures,        0),
  91	MSG_MAP(DisableAllSmuFeatures,		PPSMC_MSG_DisableAllSmuFeatures,       0),
  92	MSG_MAP(EnableSmuFeaturesLow,		PPSMC_MSG_EnableSmuFeaturesLow,        1),
  93	MSG_MAP(EnableSmuFeaturesHigh,		PPSMC_MSG_EnableSmuFeaturesHigh,       1),
  94	MSG_MAP(DisableSmuFeaturesLow,		PPSMC_MSG_DisableSmuFeaturesLow,       1),
  95	MSG_MAP(DisableSmuFeaturesHigh,		PPSMC_MSG_DisableSmuFeaturesHigh,      1),
  96	MSG_MAP(GetEnabledSmuFeaturesLow,       PPSMC_MSG_GetRunningSmuFeaturesLow,    1),
  97	MSG_MAP(GetEnabledSmuFeaturesHigh,	PPSMC_MSG_GetRunningSmuFeaturesHigh,   1),
  98	MSG_MAP(SetWorkloadMask,		PPSMC_MSG_SetWorkloadMask,             1),
  99	MSG_MAP(SetPptLimit,			PPSMC_MSG_SetPptLimit,                 0),
 100	MSG_MAP(SetDriverDramAddrHigh,		PPSMC_MSG_SetDriverDramAddrHigh,       1),
 101	MSG_MAP(SetDriverDramAddrLow,		PPSMC_MSG_SetDriverDramAddrLow,        1),
 102	MSG_MAP(SetToolsDramAddrHigh,		PPSMC_MSG_SetToolsDramAddrHigh,        0),
 103	MSG_MAP(SetToolsDramAddrLow,		PPSMC_MSG_SetToolsDramAddrLow,         0),
 104	MSG_MAP(TransferTableSmu2Dram,		PPSMC_MSG_TransferTableSmu2Dram,       1),
 105	MSG_MAP(TransferTableDram2Smu,		PPSMC_MSG_TransferTableDram2Smu,       0),
 106	MSG_MAP(UseDefaultPPTable,		PPSMC_MSG_UseDefaultPPTable,           0),
 107	MSG_MAP(RunDcBtc,			PPSMC_MSG_RunDcBtc,                    0),
 108	MSG_MAP(EnterBaco,			PPSMC_MSG_EnterBaco,                   0),
 109	MSG_MAP(ExitBaco,			PPSMC_MSG_ExitBaco,                    0),
 110	MSG_MAP(SetSoftMinByFreq,		PPSMC_MSG_SetSoftMinByFreq,            1),
 111	MSG_MAP(SetSoftMaxByFreq,		PPSMC_MSG_SetSoftMaxByFreq,            1),
 112	MSG_MAP(SetHardMinByFreq,		PPSMC_MSG_SetHardMinByFreq,            1),
 113	MSG_MAP(SetHardMaxByFreq,		PPSMC_MSG_SetHardMaxByFreq,            0),
 114	MSG_MAP(GetMinDpmFreq,			PPSMC_MSG_GetMinDpmFreq,               1),
 115	MSG_MAP(GetMaxDpmFreq,			PPSMC_MSG_GetMaxDpmFreq,               1),
 116	MSG_MAP(GetDpmFreqByIndex,		PPSMC_MSG_GetDpmFreqByIndex,           1),
 117	MSG_MAP(PowerUpVcn,			PPSMC_MSG_PowerUpVcn,                  0),
 118	MSG_MAP(PowerDownVcn,			PPSMC_MSG_PowerDownVcn,                0),
 119	MSG_MAP(PowerUpJpeg,			PPSMC_MSG_PowerUpJpeg,                 0),
 120	MSG_MAP(PowerDownJpeg,			PPSMC_MSG_PowerDownJpeg,               0),
 121	MSG_MAP(GetDcModeMaxDpmFreq,		PPSMC_MSG_GetDcModeMaxDpmFreq,         1),
 122	MSG_MAP(OverridePcieParameters,		PPSMC_MSG_OverridePcieParameters,      0),
 123	MSG_MAP(DramLogSetDramAddrHigh,		PPSMC_MSG_DramLogSetDramAddrHigh,      0),
 124	MSG_MAP(DramLogSetDramAddrLow,		PPSMC_MSG_DramLogSetDramAddrLow,       0),
 125	MSG_MAP(DramLogSetDramSize,		PPSMC_MSG_DramLogSetDramSize,          0),
 126	MSG_MAP(AllowGfxOff,			PPSMC_MSG_AllowGfxOff,                 0),
 127	MSG_MAP(DisallowGfxOff,			PPSMC_MSG_DisallowGfxOff,              0),
 128	MSG_MAP(SetMGpuFanBoostLimitRpm,	PPSMC_MSG_SetMGpuFanBoostLimitRpm,     0),
 129	MSG_MAP(GetPptLimit,			PPSMC_MSG_GetPptLimit,                 0),
 130	MSG_MAP(NotifyPowerSource,		PPSMC_MSG_NotifyPowerSource,           0),
 131	MSG_MAP(PrepareMp1ForUnload,		PPSMC_MSG_PrepareMp1ForUnload,         0),
 132	MSG_MAP(DFCstateControl,		PPSMC_MSG_SetExternalClientDfCstateAllow, 0),
 133	MSG_MAP(ArmD3,				PPSMC_MSG_ArmD3,                       0),
 134	MSG_MAP(SetNumBadMemoryPagesRetired,	PPSMC_MSG_SetNumBadMemoryPagesRetired,   0),
 135	MSG_MAP(SetBadMemoryPagesRetiredFlagsPerChannel,
 136			    PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel,   0),
 137	MSG_MAP(AllowIHHostInterrupt,		PPSMC_MSG_AllowIHHostInterrupt,       0),
 138	MSG_MAP(ReenableAcDcInterrupt,		PPSMC_MSG_ReenableAcDcInterrupt,       0),
 139};
 140
 141static struct cmn2asic_mapping smu_v14_0_2_clk_map[SMU_CLK_COUNT] = {
 142	CLK_MAP(GFXCLK,		PPCLK_GFXCLK),
 143	CLK_MAP(SCLK,		PPCLK_GFXCLK),
 144	CLK_MAP(SOCCLK,		PPCLK_SOCCLK),
 145	CLK_MAP(FCLK,		PPCLK_FCLK),
 146	CLK_MAP(UCLK,		PPCLK_UCLK),
 147	CLK_MAP(MCLK,		PPCLK_UCLK),
 148	CLK_MAP(VCLK,		PPCLK_VCLK_0),
 149	CLK_MAP(DCLK,		PPCLK_DCLK_0),
 150	CLK_MAP(DCEFCLK,	PPCLK_DCFCLK),
 151};
 152
 153static struct cmn2asic_mapping smu_v14_0_2_feature_mask_map[SMU_FEATURE_COUNT] = {
 154	FEA_MAP(FW_DATA_READ),
 155	FEA_MAP(DPM_GFXCLK),
 156	FEA_MAP(DPM_GFX_POWER_OPTIMIZER),
 157	FEA_MAP(DPM_UCLK),
 158	FEA_MAP(DPM_FCLK),
 159	FEA_MAP(DPM_SOCCLK),
 160	FEA_MAP(DPM_LINK),
 161	FEA_MAP(DPM_DCN),
 162	FEA_MAP(VMEMP_SCALING),
 163	FEA_MAP(VDDIO_MEM_SCALING),
 164	FEA_MAP(DS_GFXCLK),
 165	FEA_MAP(DS_SOCCLK),
 166	FEA_MAP(DS_FCLK),
 167	FEA_MAP(DS_LCLK),
 168	FEA_MAP(DS_DCFCLK),
 169	FEA_MAP(DS_UCLK),
 170	FEA_MAP(GFX_ULV),
 171	FEA_MAP(FW_DSTATE),
 172	FEA_MAP(GFXOFF),
 173	FEA_MAP(BACO),
 174	FEA_MAP(MM_DPM),
 175	FEA_MAP(SOC_MPCLK_DS),
 176	FEA_MAP(BACO_MPCLK_DS),
 177	FEA_MAP(THROTTLERS),
 178	FEA_MAP(SMARTSHIFT),
 179	FEA_MAP(GTHR),
 180	FEA_MAP(ACDC),
 181	FEA_MAP(VR0HOT),
 182	FEA_MAP(FW_CTF),
 183	FEA_MAP(FAN_CONTROL),
 184	FEA_MAP(GFX_DCS),
 185	FEA_MAP(GFX_READ_MARGIN),
 186	FEA_MAP(LED_DISPLAY),
 187	FEA_MAP(GFXCLK_SPREAD_SPECTRUM),
 188	FEA_MAP(OUT_OF_BAND_MONITOR),
 189	FEA_MAP(OPTIMIZED_VMIN),
 190	FEA_MAP(GFX_IMU),
 191	FEA_MAP(BOOT_TIME_CAL),
 192	FEA_MAP(GFX_PCC_DFLL),
 193	FEA_MAP(SOC_CG),
 194	FEA_MAP(DF_CSTATE),
 195	FEA_MAP(GFX_EDC),
 196	FEA_MAP(BOOT_POWER_OPT),
 197	FEA_MAP(CLOCK_POWER_DOWN_BYPASS),
 198	FEA_MAP(DS_VCN),
 199	FEA_MAP(BACO_CG),
 200	FEA_MAP(MEM_TEMP_READ),
 201	FEA_MAP(ATHUB_MMHUB_PG),
 202	FEA_MAP(SOC_PCC),
 203	FEA_MAP(EDC_PWRBRK),
 204	FEA_MAP(SOC_EDC_XVMIN),
 205	FEA_MAP(GFX_PSM_DIDT),
 206	FEA_MAP(APT_ALL_ENABLE),
 207	FEA_MAP(APT_SQ_THROTTLE),
 208	FEA_MAP(APT_PF_DCS),
 209	FEA_MAP(GFX_EDC_XVMIN),
 210	FEA_MAP(GFX_DIDT_XVMIN),
 211	FEA_MAP(FAN_ABNORMAL),
 212	[SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
 213	[SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
 214	[SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT},
 215};
 216
 217static struct cmn2asic_mapping smu_v14_0_2_table_map[SMU_TABLE_COUNT] = {
 218	TAB_MAP(PPTABLE),
 219	TAB_MAP(WATERMARKS),
 220	TAB_MAP(AVFS_PSM_DEBUG),
 221	TAB_MAP(PMSTATUSLOG),
 222	TAB_MAP(SMU_METRICS),
 223	TAB_MAP(DRIVER_SMU_CONFIG),
 224	TAB_MAP(ACTIVITY_MONITOR_COEFF),
 225	[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
 226	TAB_MAP(I2C_COMMANDS),
 227	TAB_MAP(ECCINFO),
 228	TAB_MAP(OVERDRIVE),
 229};
 230
 231static struct cmn2asic_mapping smu_v14_0_2_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
 232	PWR_MAP(AC),
 233	PWR_MAP(DC),
 234};
 235
 236static struct cmn2asic_mapping smu_v14_0_2_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
 237	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,	WORKLOAD_PPLIB_DEFAULT_BIT),
 238	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,		WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
 239	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,		WORKLOAD_PPLIB_POWER_SAVING_BIT),
 240	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,		WORKLOAD_PPLIB_VIDEO_BIT),
 241	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,			WORKLOAD_PPLIB_VR_BIT),
 242	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,		WORKLOAD_PPLIB_COMPUTE_BIT),
 243	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,		WORKLOAD_PPLIB_CUSTOM_BIT),
 244	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_WINDOW3D,		WORKLOAD_PPLIB_WINDOW_3D_BIT),
 245};
 246
 247static const uint8_t smu_v14_0_2_throttler_map[] = {
 248	[THROTTLER_PPT0_BIT]		= (SMU_THROTTLER_PPT0_BIT),
 249	[THROTTLER_PPT1_BIT]		= (SMU_THROTTLER_PPT1_BIT),
 250	[THROTTLER_PPT2_BIT]		= (SMU_THROTTLER_PPT2_BIT),
 251	[THROTTLER_PPT3_BIT]		= (SMU_THROTTLER_PPT3_BIT),
 252	[THROTTLER_TDC_GFX_BIT]		= (SMU_THROTTLER_TDC_GFX_BIT),
 253	[THROTTLER_TDC_SOC_BIT]		= (SMU_THROTTLER_TDC_SOC_BIT),
 254	[THROTTLER_TEMP_EDGE_BIT]	= (SMU_THROTTLER_TEMP_EDGE_BIT),
 255	[THROTTLER_TEMP_HOTSPOT_BIT]	= (SMU_THROTTLER_TEMP_HOTSPOT_BIT),
 256	[THROTTLER_TEMP_MEM_BIT]	= (SMU_THROTTLER_TEMP_MEM_BIT),
 257	[THROTTLER_TEMP_VR_GFX_BIT]	= (SMU_THROTTLER_TEMP_VR_GFX_BIT),
 258	[THROTTLER_TEMP_VR_SOC_BIT]	= (SMU_THROTTLER_TEMP_VR_SOC_BIT),
 259	[THROTTLER_TEMP_VR_MEM0_BIT]	= (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
 260	[THROTTLER_TEMP_VR_MEM1_BIT]	= (SMU_THROTTLER_TEMP_VR_MEM1_BIT),
 261	[THROTTLER_TEMP_LIQUID0_BIT]	= (SMU_THROTTLER_TEMP_LIQUID0_BIT),
 262	[THROTTLER_TEMP_LIQUID1_BIT]	= (SMU_THROTTLER_TEMP_LIQUID1_BIT),
 263	[THROTTLER_GFX_APCC_PLUS_BIT]	= (SMU_THROTTLER_APCC_BIT),
 264	[THROTTLER_FIT_BIT]		= (SMU_THROTTLER_FIT_BIT),
 265};
 266
 267static int
 268smu_v14_0_2_get_allowed_feature_mask(struct smu_context *smu,
 269				  uint32_t *feature_mask, uint32_t num)
 270{
 271	struct amdgpu_device *adev = smu->adev;
 272	/*u32 smu_version;*/
 273
 274	if (num > 2)
 275		return -EINVAL;
 276
 277	memset(feature_mask, 0xff, sizeof(uint32_t) * num);
 278
 279	if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) {
 280		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
 281		*(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT);
 282	}
 283#if 0
 284	if (!(adev->pg_flags & AMD_PG_SUPPORT_ATHUB) ||
 285	    !(adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
 286		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
 287
 288	if (!(adev->pm.pp_feature & PP_SOCCLK_DPM_MASK))
 289		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
 290
 291	/* PMFW 78.58 contains a critical fix for gfxoff feature */
 292	smu_cmn_get_smc_version(smu, NULL, &smu_version);
 293	if ((smu_version < 0x004e3a00) ||
 294	     !(adev->pm.pp_feature & PP_GFXOFF_MASK))
 295		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFXOFF_BIT);
 296
 297	if (!(adev->pm.pp_feature & PP_MCLK_DPM_MASK)) {
 298		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
 299		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
 300		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
 301	}
 302
 303	if (!(adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK))
 304		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
 305
 306	if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK)) {
 307		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_LINK_BIT);
 308		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_LCLK_BIT);
 309	}
 310
 311	if (!(adev->pm.pp_feature & PP_ULV_MASK))
 312		*(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFX_ULV_BIT);
 313#endif
 314
 315	return 0;
 316}
 317
 318static int smu_v14_0_2_check_powerplay_table(struct smu_context *smu)
 319{
 320	struct smu_table_context *table_context = &smu->smu_table;
 321	struct smu_14_0_2_powerplay_table *powerplay_table =
 322		table_context->power_play_table;
 323	struct smu_baco_context *smu_baco = &smu->smu_baco;
 324	PPTable_t *pptable = smu->smu_table.driver_pptable;
 325	const OverDriveLimits_t * const overdrive_upperlimits =
 326				&pptable->SkuTable.OverDriveLimitsBasicMax;
 327	const OverDriveLimits_t * const overdrive_lowerlimits =
 328				&pptable->SkuTable.OverDriveLimitsBasicMin;
 329
 330	if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_HARDWAREDC)
 331		smu->dc_controlled_by_gpio = true;
 332
 333	if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_BACO) {
 334		smu_baco->platform_support = true;
 335
 336		if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_MACO)
 337			smu_baco->maco_support = true;
 338	}
 339
 340	if (!overdrive_lowerlimits->FeatureCtrlMask ||
 341	    !overdrive_upperlimits->FeatureCtrlMask)
 342		smu->od_enabled = false;
 343
 344	table_context->thermal_controller_type =
 345		powerplay_table->thermal_controller_type;
 346
 347	/*
 348	 * Instead of having its own buffer space and get overdrive_table copied,
 349	 * smu->od_settings just points to the actual overdrive_table
 350	 */
 351	smu->od_settings = &powerplay_table->overdrive_table;
 352
 353	smu->adev->pm.no_fan =
 354		!(pptable->PFE_Settings.FeaturesToRun[0] & (1 << FEATURE_FAN_CONTROL_BIT));
 355
 356	return 0;
 357}
 358
 359static int smu_v14_0_2_store_powerplay_table(struct smu_context *smu)
 360{
 361	struct smu_table_context *table_context = &smu->smu_table;
 362	struct smu_14_0_2_powerplay_table *powerplay_table =
 363		table_context->power_play_table;
 364
 365	memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
 366	       sizeof(PPTable_t));
 367
 368	return 0;
 369}
 370
 371static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
 372					     void **table,
 373					     uint32_t *size)
 374{
 375	struct smu_table_context *smu_table = &smu->smu_table;
 376	void *combo_pptable = smu_table->combo_pptable;
 377	int ret = 0;
 378
 379	ret = smu_cmn_get_combo_pptable(smu);
 380	if (ret)
 381		return ret;
 382
 383	*table = combo_pptable;
 384	*size = sizeof(struct smu_14_0_2_powerplay_table);
 385
 386	return 0;
 387}
 388
 389static int smu_v14_0_2_setup_pptable(struct smu_context *smu)
 390{
 391	struct smu_table_context *smu_table = &smu->smu_table;
 392	int ret = 0;
 393
 394	if (amdgpu_sriov_vf(smu->adev))
 395		return 0;
 396
 397	ret = smu_v14_0_2_get_pptable_from_pmfw(smu,
 398							&smu_table->power_play_table,
 399							&smu_table->power_play_table_size);
 400	if (ret)
 401		return ret;
 402
 403	ret = smu_v14_0_2_store_powerplay_table(smu);
 404	if (ret)
 405		return ret;
 406
 407	ret = smu_v14_0_2_check_powerplay_table(smu);
 408	if (ret)
 409		return ret;
 410
 411	return ret;
 412}
 413
 414static int smu_v14_0_2_tables_init(struct smu_context *smu)
 415{
 416	struct smu_table_context *smu_table = &smu->smu_table;
 417	struct smu_table *tables = smu_table->tables;
 418
 419	SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
 420		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 421	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
 422		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 423	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t),
 424		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 425	SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
 426		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 427	SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
 428		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 429	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU14_TOOL_SIZE,
 430		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 431	SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
 432		       sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE,
 433		       AMDGPU_GEM_DOMAIN_VRAM);
 434	SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE,
 435			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 436	SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t),
 437			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 438
 439	smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);
 440	if (!smu_table->metrics_table)
 441		goto err0_out;
 442	smu_table->metrics_time = 0;
 443
 444	smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
 445	smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
 446	if (!smu_table->gpu_metrics_table)
 447		goto err1_out;
 448
 449	smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
 450	if (!smu_table->watermarks_table)
 451		goto err2_out;
 452
 453	smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL);
 454	if (!smu_table->ecc_table)
 455		goto err3_out;
 456
 457	return 0;
 458
 459err3_out:
 460	kfree(smu_table->watermarks_table);
 461err2_out:
 462	kfree(smu_table->gpu_metrics_table);
 463err1_out:
 464	kfree(smu_table->metrics_table);
 465err0_out:
 466	return -ENOMEM;
 467}
 468
 469static int smu_v14_0_2_allocate_dpm_context(struct smu_context *smu)
 470{
 471	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
 472
 473	smu_dpm->dpm_context = kzalloc(sizeof(struct smu_14_0_dpm_context),
 474				       GFP_KERNEL);
 475	if (!smu_dpm->dpm_context)
 476		return -ENOMEM;
 477
 478	smu_dpm->dpm_context_size = sizeof(struct smu_14_0_dpm_context);
 479
 480	return 0;
 481}
 482
 483static int smu_v14_0_2_init_smc_tables(struct smu_context *smu)
 484{
 485	int ret = 0;
 486
 487	ret = smu_v14_0_2_tables_init(smu);
 488	if (ret)
 489		return ret;
 490
 491	ret = smu_v14_0_2_allocate_dpm_context(smu);
 492	if (ret)
 493		return ret;
 494
 495	return smu_v14_0_init_smc_tables(smu);
 496}
 497
 498static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu)
 499{
 500	struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
 501	struct smu_table_context *table_context = &smu->smu_table;
 502	PPTable_t *pptable = table_context->driver_pptable;
 503	SkuTable_t *skutable = &pptable->SkuTable;
 504	struct smu_14_0_dpm_table *dpm_table;
 505	int ret = 0;
 506
 507	/* socclk dpm table setup */
 508	dpm_table = &dpm_context->dpm_tables.soc_table;
 509	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
 510		ret = smu_v14_0_set_single_dpm_table(smu,
 511						     SMU_SOCCLK,
 512						     dpm_table);
 513		if (ret)
 514			return ret;
 515	} else {
 516		dpm_table->count = 1;
 517		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
 518		dpm_table->dpm_levels[0].enabled = true;
 519		dpm_table->min = dpm_table->dpm_levels[0].value;
 520		dpm_table->max = dpm_table->dpm_levels[0].value;
 521	}
 522
 523	/* gfxclk dpm table setup */
 524	dpm_table = &dpm_context->dpm_tables.gfx_table;
 525	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
 526		ret = smu_v14_0_set_single_dpm_table(smu,
 527						     SMU_GFXCLK,
 528						     dpm_table);
 529		if (ret)
 530			return ret;
 531
 532		/*
 533		 * Update the reported maximum shader clock to the value
 534		 * which can be guarded to be achieved on all cards. This
 535		 * is aligned with Window setting. And considering that value
 536		 * might be not the peak frequency the card can achieve, it
 537		 * is normal some real-time clock frequency can overtake this
 538		 * labelled maximum clock frequency(for example in pp_dpm_sclk
 539		 * sysfs output).
 540		 */
 541		if (skutable->DriverReportedClocks.GameClockAc &&
 542		    (dpm_table->dpm_levels[dpm_table->count - 1].value >
 543		    skutable->DriverReportedClocks.GameClockAc)) {
 544			dpm_table->dpm_levels[dpm_table->count - 1].value =
 545				skutable->DriverReportedClocks.GameClockAc;
 546			dpm_table->max = skutable->DriverReportedClocks.GameClockAc;
 547		}
 548	} else {
 549		dpm_table->count = 1;
 550		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
 551		dpm_table->dpm_levels[0].enabled = true;
 552		dpm_table->min = dpm_table->dpm_levels[0].value;
 553		dpm_table->max = dpm_table->dpm_levels[0].value;
 554	}
 555
 556	/* uclk dpm table setup */
 557	dpm_table = &dpm_context->dpm_tables.uclk_table;
 558	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
 559		ret = smu_v14_0_set_single_dpm_table(smu,
 560						     SMU_UCLK,
 561						     dpm_table);
 562		if (ret)
 563			return ret;
 564	} else {
 565		dpm_table->count = 1;
 566		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
 567		dpm_table->dpm_levels[0].enabled = true;
 568		dpm_table->min = dpm_table->dpm_levels[0].value;
 569		dpm_table->max = dpm_table->dpm_levels[0].value;
 570	}
 571
 572	/* fclk dpm table setup */
 573	dpm_table = &dpm_context->dpm_tables.fclk_table;
 574	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
 575		ret = smu_v14_0_set_single_dpm_table(smu,
 576						     SMU_FCLK,
 577						     dpm_table);
 578		if (ret)
 579			return ret;
 580	} else {
 581		dpm_table->count = 1;
 582		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100;
 583		dpm_table->dpm_levels[0].enabled = true;
 584		dpm_table->min = dpm_table->dpm_levels[0].value;
 585		dpm_table->max = dpm_table->dpm_levels[0].value;
 586	}
 587
 588	/* vclk dpm table setup */
 589	dpm_table = &dpm_context->dpm_tables.vclk_table;
 590	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) {
 591		ret = smu_v14_0_set_single_dpm_table(smu,
 592						     SMU_VCLK,
 593						     dpm_table);
 594		if (ret)
 595			return ret;
 596	} else {
 597		dpm_table->count = 1;
 598		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
 599		dpm_table->dpm_levels[0].enabled = true;
 600		dpm_table->min = dpm_table->dpm_levels[0].value;
 601		dpm_table->max = dpm_table->dpm_levels[0].value;
 602	}
 603
 604	/* dclk dpm table setup */
 605	dpm_table = &dpm_context->dpm_tables.dclk_table;
 606	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) {
 607		ret = smu_v14_0_set_single_dpm_table(smu,
 608						     SMU_DCLK,
 609						     dpm_table);
 610		if (ret)
 611			return ret;
 612	} else {
 613		dpm_table->count = 1;
 614		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
 615		dpm_table->dpm_levels[0].enabled = true;
 616		dpm_table->min = dpm_table->dpm_levels[0].value;
 617		dpm_table->max = dpm_table->dpm_levels[0].value;
 618	}
 619
 620	/* dcefclk dpm table setup */
 621	dpm_table = &dpm_context->dpm_tables.dcef_table;
 622	if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCN_BIT)) {
 623		ret = smu_v14_0_set_single_dpm_table(smu,
 624						     SMU_DCEFCLK,
 625						     dpm_table);
 626		if (ret)
 627			return ret;
 628	} else {
 629		dpm_table->count = 1;
 630		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100;
 631		dpm_table->dpm_levels[0].enabled = true;
 632		dpm_table->min = dpm_table->dpm_levels[0].value;
 633		dpm_table->max = dpm_table->dpm_levels[0].value;
 634	}
 635
 636	return 0;
 637}
 638
 639static bool smu_v14_0_2_is_dpm_running(struct smu_context *smu)
 640{
 641	int ret = 0;
 642	uint64_t feature_enabled;
 643
 644	ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
 645	if (ret)
 646		return false;
 647
 648	return !!(feature_enabled & SMC_DPM_FEATURE);
 649}
 650
 651static uint32_t smu_v14_0_2_get_throttler_status(SmuMetrics_t *metrics)
 652{
 653	uint32_t throttler_status = 0;
 654	int i;
 655
 656	for (i = 0; i < THROTTLER_COUNT; i++)
 657		throttler_status |=
 658			(metrics->ThrottlingPercentage[i] ? 1U << i : 0);
 659
 660	return throttler_status;
 661}
 662
 663#define SMU_14_0_2_BUSY_THRESHOLD	5
 664static int smu_v14_0_2_get_smu_metrics_data(struct smu_context *smu,
 665					    MetricsMember_t member,
 666					    uint32_t *value)
 667{
 668	struct smu_table_context *smu_table = &smu->smu_table;
 669	SmuMetrics_t *metrics =
 670		&(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
 671	int ret = 0;
 672
 673	ret = smu_cmn_get_metrics_table(smu,
 674					NULL,
 675					false);
 676	if (ret)
 677		return ret;
 678
 679	switch (member) {
 680	case METRICS_CURR_GFXCLK:
 681		*value = metrics->CurrClock[PPCLK_GFXCLK];
 682		break;
 683	case METRICS_CURR_SOCCLK:
 684		*value = metrics->CurrClock[PPCLK_SOCCLK];
 685		break;
 686	case METRICS_CURR_UCLK:
 687		*value = metrics->CurrClock[PPCLK_UCLK];
 688		break;
 689	case METRICS_CURR_VCLK:
 690		*value = metrics->CurrClock[PPCLK_VCLK_0];
 691		break;
 692	case METRICS_CURR_DCLK:
 693		*value = metrics->CurrClock[PPCLK_DCLK_0];
 694		break;
 695	case METRICS_CURR_FCLK:
 696		*value = metrics->CurrClock[PPCLK_FCLK];
 697		break;
 698	case METRICS_CURR_DCEFCLK:
 699		*value = metrics->CurrClock[PPCLK_DCFCLK];
 700		break;
 701	case METRICS_AVERAGE_GFXCLK:
 702		if (metrics->AverageGfxActivity <= SMU_14_0_2_BUSY_THRESHOLD)
 703			*value = metrics->AverageGfxclkFrequencyPostDs;
 704		else
 705			*value = metrics->AverageGfxclkFrequencyPreDs;
 706		break;
 707	case METRICS_AVERAGE_FCLK:
 708		if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD)
 709			*value = metrics->AverageFclkFrequencyPostDs;
 710		else
 711			*value = metrics->AverageFclkFrequencyPreDs;
 712		break;
 713	case METRICS_AVERAGE_UCLK:
 714		if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD)
 715			*value = metrics->AverageMemclkFrequencyPostDs;
 716		else
 717			*value = metrics->AverageMemclkFrequencyPreDs;
 718		break;
 719	case METRICS_AVERAGE_VCLK:
 720		*value = metrics->AverageVclk0Frequency;
 721		break;
 722	case METRICS_AVERAGE_DCLK:
 723		*value = metrics->AverageDclk0Frequency;
 724		break;
 725	case METRICS_AVERAGE_VCLK1:
 726		*value = metrics->AverageVclk1Frequency;
 727		break;
 728	case METRICS_AVERAGE_DCLK1:
 729		*value = metrics->AverageDclk1Frequency;
 730		break;
 731	case METRICS_AVERAGE_GFXACTIVITY:
 732		*value = metrics->AverageGfxActivity;
 733		break;
 734	case METRICS_AVERAGE_MEMACTIVITY:
 735		*value = metrics->AverageUclkActivity;
 736		break;
 737	case METRICS_AVERAGE_VCNACTIVITY:
 738		*value = max(metrics->AverageVcn0ActivityPercentage,
 739			     metrics->Vcn1ActivityPercentage);
 740		break;
 741	case METRICS_AVERAGE_SOCKETPOWER:
 742		*value = metrics->AverageSocketPower << 8;
 743		break;
 744	case METRICS_TEMPERATURE_EDGE:
 745		*value = metrics->AvgTemperature[TEMP_EDGE] *
 746			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 747		break;
 748	case METRICS_TEMPERATURE_HOTSPOT:
 749		*value = metrics->AvgTemperature[TEMP_HOTSPOT] *
 750			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 751		break;
 752	case METRICS_TEMPERATURE_MEM:
 753		*value = metrics->AvgTemperature[TEMP_MEM] *
 754			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 755		break;
 756	case METRICS_TEMPERATURE_VRGFX:
 757		*value = metrics->AvgTemperature[TEMP_VR_GFX] *
 758			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 759		break;
 760	case METRICS_TEMPERATURE_VRSOC:
 761		*value = metrics->AvgTemperature[TEMP_VR_SOC] *
 762			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 763		break;
 764	case METRICS_THROTTLER_STATUS:
 765		*value = smu_v14_0_2_get_throttler_status(metrics);
 766		break;
 767	case METRICS_CURR_FANSPEED:
 768		*value = metrics->AvgFanRpm;
 769		break;
 770	case METRICS_CURR_FANPWM:
 771		*value = metrics->AvgFanPwm;
 772		break;
 773	case METRICS_VOLTAGE_VDDGFX:
 774		*value = metrics->AvgVoltage[SVI_PLANE_VDD_GFX];
 775		break;
 776	case METRICS_PCIE_RATE:
 777		*value = metrics->PcieRate;
 778		break;
 779	case METRICS_PCIE_WIDTH:
 780		*value = metrics->PcieWidth;
 781		break;
 782	default:
 783		*value = UINT_MAX;
 784		break;
 785	}
 786
 787	return ret;
 788}
 789
 790static int smu_v14_0_2_get_dpm_ultimate_freq(struct smu_context *smu,
 791					     enum smu_clk_type clk_type,
 792					     uint32_t *min,
 793					     uint32_t *max)
 794{
 795	struct smu_14_0_dpm_context *dpm_context =
 796		smu->smu_dpm.dpm_context;
 797	struct smu_14_0_dpm_table *dpm_table;
 798
 799	switch (clk_type) {
 800	case SMU_MCLK:
 801	case SMU_UCLK:
 802		/* uclk dpm table */
 803		dpm_table = &dpm_context->dpm_tables.uclk_table;
 804		break;
 805	case SMU_GFXCLK:
 806	case SMU_SCLK:
 807		/* gfxclk dpm table */
 808		dpm_table = &dpm_context->dpm_tables.gfx_table;
 809		break;
 810	case SMU_SOCCLK:
 811		/* socclk dpm table */
 812		dpm_table = &dpm_context->dpm_tables.soc_table;
 813		break;
 814	case SMU_FCLK:
 815		/* fclk dpm table */
 816		dpm_table = &dpm_context->dpm_tables.fclk_table;
 817		break;
 818	case SMU_VCLK:
 819	case SMU_VCLK1:
 820		/* vclk dpm table */
 821		dpm_table = &dpm_context->dpm_tables.vclk_table;
 822		break;
 823	case SMU_DCLK:
 824	case SMU_DCLK1:
 825		/* dclk dpm table */
 826		dpm_table = &dpm_context->dpm_tables.dclk_table;
 827		break;
 828	default:
 829		dev_err(smu->adev->dev, "Unsupported clock type!\n");
 830		return -EINVAL;
 831	}
 832
 833	if (min)
 834		*min = dpm_table->min;
 835	if (max)
 836		*max = dpm_table->max;
 837
 838	return 0;
 839}
 840
 841static int smu_v14_0_2_read_sensor(struct smu_context *smu,
 842				   enum amd_pp_sensors sensor,
 843				   void *data,
 844				   uint32_t *size)
 845{
 846	struct smu_table_context *table_context = &smu->smu_table;
 847	PPTable_t *smc_pptable = table_context->driver_pptable;
 848	int ret = 0;
 849
 850	switch (sensor) {
 851	case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
 852		*(uint16_t *)data = smc_pptable->CustomSkuTable.FanMaximumRpm;
 853		*size = 4;
 854		break;
 855	case AMDGPU_PP_SENSOR_MEM_LOAD:
 856		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 857						       METRICS_AVERAGE_MEMACTIVITY,
 858						       (uint32_t *)data);
 859		*size = 4;
 860		break;
 861	case AMDGPU_PP_SENSOR_GPU_LOAD:
 862		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 863						       METRICS_AVERAGE_GFXACTIVITY,
 864						       (uint32_t *)data);
 865		*size = 4;
 866		break;
 867	case AMDGPU_PP_SENSOR_VCN_LOAD:
 868		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 869						       METRICS_AVERAGE_VCNACTIVITY,
 870						       (uint32_t *)data);
 871		*size = 4;
 872		break;
 873	case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
 874		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 875						       METRICS_AVERAGE_SOCKETPOWER,
 876						       (uint32_t *)data);
 877		*size = 4;
 878		break;
 879	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
 880		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 881						       METRICS_TEMPERATURE_HOTSPOT,
 882						       (uint32_t *)data);
 883		*size = 4;
 884		break;
 885	case AMDGPU_PP_SENSOR_EDGE_TEMP:
 886		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 887						       METRICS_TEMPERATURE_EDGE,
 888						       (uint32_t *)data);
 889		*size = 4;
 890		break;
 891	case AMDGPU_PP_SENSOR_MEM_TEMP:
 892		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 893						       METRICS_TEMPERATURE_MEM,
 894						       (uint32_t *)data);
 895		*size = 4;
 896		break;
 897	case AMDGPU_PP_SENSOR_GFX_MCLK:
 898		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 899						       METRICS_CURR_UCLK,
 900						       (uint32_t *)data);
 901		*(uint32_t *)data *= 100;
 902		*size = 4;
 903		break;
 904	case AMDGPU_PP_SENSOR_GFX_SCLK:
 905		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 906						       METRICS_AVERAGE_GFXCLK,
 907						       (uint32_t *)data);
 908		*(uint32_t *)data *= 100;
 909		*size = 4;
 910		break;
 911	case AMDGPU_PP_SENSOR_VDDGFX:
 912		ret = smu_v14_0_2_get_smu_metrics_data(smu,
 913						       METRICS_VOLTAGE_VDDGFX,
 914						       (uint32_t *)data);
 915		*size = 4;
 916		break;
 917	default:
 918		ret = -EOPNOTSUPP;
 919		break;
 920	}
 921
 922	return ret;
 923}
 924
 925static int smu_v14_0_2_get_current_clk_freq_by_table(struct smu_context *smu,
 926						     enum smu_clk_type clk_type,
 927						     uint32_t *value)
 928{
 929	MetricsMember_t member_type;
 930	int clk_id = 0;
 931
 932	clk_id = smu_cmn_to_asic_specific_index(smu,
 933						CMN2ASIC_MAPPING_CLK,
 934						clk_type);
 935	if (clk_id < 0)
 936		return -EINVAL;
 937
 938	switch (clk_id) {
 939	case PPCLK_GFXCLK:
 940		member_type = METRICS_AVERAGE_GFXCLK;
 941		break;
 942	case PPCLK_UCLK:
 943		member_type = METRICS_CURR_UCLK;
 944		break;
 945	case PPCLK_FCLK:
 946		member_type = METRICS_CURR_FCLK;
 947		break;
 948	case PPCLK_SOCCLK:
 949		member_type = METRICS_CURR_SOCCLK;
 950		break;
 951	case PPCLK_VCLK_0:
 952		member_type = METRICS_AVERAGE_VCLK;
 953		break;
 954	case PPCLK_DCLK_0:
 955		member_type = METRICS_AVERAGE_DCLK;
 956		break;
 957	case PPCLK_DCFCLK:
 958		member_type = METRICS_CURR_DCEFCLK;
 959		break;
 960	default:
 961		return -EINVAL;
 962	}
 963
 964	return smu_v14_0_2_get_smu_metrics_data(smu,
 965						member_type,
 966						value);
 967}
 968
 969static bool smu_v14_0_2_is_od_feature_supported(struct smu_context *smu,
 970						int od_feature_bit)
 971{
 972	PPTable_t *pptable = smu->smu_table.driver_pptable;
 973	const OverDriveLimits_t * const overdrive_upperlimits =
 974				&pptable->SkuTable.OverDriveLimitsBasicMax;
 975
 976	return overdrive_upperlimits->FeatureCtrlMask & (1U << od_feature_bit);
 977}
 978
 979static void smu_v14_0_2_get_od_setting_limits(struct smu_context *smu,
 980					      int od_feature_bit,
 981					      int32_t *min,
 982					      int32_t *max)
 983{
 984	PPTable_t *pptable = smu->smu_table.driver_pptable;
 985	const OverDriveLimits_t * const overdrive_upperlimits =
 986				&pptable->SkuTable.OverDriveLimitsBasicMax;
 987	const OverDriveLimits_t * const overdrive_lowerlimits =
 988				&pptable->SkuTable.OverDriveLimitsBasicMin;
 989	int32_t od_min_setting, od_max_setting;
 990
 991	switch (od_feature_bit) {
 992	case PP_OD_FEATURE_GFXCLK_FMIN:
 993	case PP_OD_FEATURE_GFXCLK_FMAX:
 994		od_min_setting = overdrive_lowerlimits->GfxclkFoffset;
 995		od_max_setting = overdrive_upperlimits->GfxclkFoffset;
 996		break;
 997	case PP_OD_FEATURE_UCLK_FMIN:
 998		od_min_setting = overdrive_lowerlimits->UclkFmin;
 999		od_max_setting = overdrive_upperlimits->UclkFmin;
1000		break;
1001	case PP_OD_FEATURE_UCLK_FMAX:
1002		od_min_setting = overdrive_lowerlimits->UclkFmax;
1003		od_max_setting = overdrive_upperlimits->UclkFmax;
1004		break;
1005	case PP_OD_FEATURE_GFX_VF_CURVE:
1006		od_min_setting = overdrive_lowerlimits->VoltageOffsetPerZoneBoundary[0];
1007		od_max_setting = overdrive_upperlimits->VoltageOffsetPerZoneBoundary[0];
1008		break;
1009	case PP_OD_FEATURE_FAN_CURVE_TEMP:
1010		od_min_setting = overdrive_lowerlimits->FanLinearTempPoints[0];
1011		od_max_setting = overdrive_upperlimits->FanLinearTempPoints[0];
1012		break;
1013	case PP_OD_FEATURE_FAN_CURVE_PWM:
1014		od_min_setting = overdrive_lowerlimits->FanLinearPwmPoints[0];
1015		od_max_setting = overdrive_upperlimits->FanLinearPwmPoints[0];
1016		break;
1017	case PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT:
1018		od_min_setting = overdrive_lowerlimits->AcousticLimitRpmThreshold;
1019		od_max_setting = overdrive_upperlimits->AcousticLimitRpmThreshold;
1020		break;
1021	case PP_OD_FEATURE_FAN_ACOUSTIC_TARGET:
1022		od_min_setting = overdrive_lowerlimits->AcousticTargetRpmThreshold;
1023		od_max_setting = overdrive_upperlimits->AcousticTargetRpmThreshold;
1024		break;
1025	case PP_OD_FEATURE_FAN_TARGET_TEMPERATURE:
1026		od_min_setting = overdrive_lowerlimits->FanTargetTemperature;
1027		od_max_setting = overdrive_upperlimits->FanTargetTemperature;
1028		break;
1029	case PP_OD_FEATURE_FAN_MINIMUM_PWM:
1030		od_min_setting = overdrive_lowerlimits->FanMinimumPwm;
1031		od_max_setting = overdrive_upperlimits->FanMinimumPwm;
1032		break;
1033	case PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE:
1034		od_min_setting = overdrive_lowerlimits->FanZeroRpmEnable;
1035		od_max_setting = overdrive_upperlimits->FanZeroRpmEnable;
1036		break;
1037	default:
1038		od_min_setting = od_max_setting = INT_MAX;
1039		break;
1040	}
1041
1042	if (min)
1043		*min = od_min_setting;
1044	if (max)
1045		*max = od_max_setting;
1046}
1047
1048static int smu_v14_0_2_print_clk_levels(struct smu_context *smu,
1049					enum smu_clk_type clk_type,
1050					char *buf)
1051{
1052	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1053	struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1054	OverDriveTableExternal_t *od_table =
1055		(OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
1056	struct smu_14_0_dpm_table *single_dpm_table;
1057	struct smu_14_0_pcie_table *pcie_table;
1058	uint32_t gen_speed, lane_width;
1059	int i, curr_freq, size = 0, start_offset = 0;
1060	int32_t min_value, max_value;
1061	int ret = 0;
1062
1063	smu_cmn_get_sysfs_buf(&buf, &size);
1064	start_offset = size;
1065
1066	if (amdgpu_ras_intr_triggered()) {
1067		size += sysfs_emit_at(buf, size, "unavailable\n");
1068		return size - start_offset;
1069	}
1070
1071	switch (clk_type) {
1072	case SMU_SCLK:
1073		single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
1074		break;
1075	case SMU_MCLK:
1076		single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
1077		break;
1078	case SMU_SOCCLK:
1079		single_dpm_table = &(dpm_context->dpm_tables.soc_table);
1080		break;
1081	case SMU_FCLK:
1082		single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
1083		break;
1084	case SMU_VCLK:
1085	case SMU_VCLK1:
1086		single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
1087		break;
1088	case SMU_DCLK:
1089	case SMU_DCLK1:
1090		single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
1091		break;
1092	case SMU_DCEFCLK:
1093		single_dpm_table = &(dpm_context->dpm_tables.dcef_table);
1094		break;
1095	default:
1096		break;
1097	}
1098
1099	switch (clk_type) {
1100	case SMU_SCLK:
1101	case SMU_MCLK:
1102	case SMU_SOCCLK:
1103	case SMU_FCLK:
1104	case SMU_VCLK:
1105	case SMU_VCLK1:
1106	case SMU_DCLK:
1107	case SMU_DCLK1:
1108	case SMU_DCEFCLK:
1109		ret = smu_v14_0_2_get_current_clk_freq_by_table(smu, clk_type, &curr_freq);
1110		if (ret) {
1111			dev_err(smu->adev->dev, "Failed to get current clock freq!");
1112			return ret;
1113		}
1114
1115		if (single_dpm_table->is_fine_grained) {
1116			/*
1117			 * For fine grained dpms, there are only two dpm levels:
1118			 *   - level 0 -> min clock freq
1119			 *   - level 1 -> max clock freq
1120			 * And the current clock frequency can be any value between them.
1121			 * So, if the current clock frequency is not at level 0 or level 1,
1122			 * we will fake it as three dpm levels:
1123			 *   - level 0 -> min clock freq
1124			 *   - level 1 -> current actual clock freq
1125			 *   - level 2 -> max clock freq
1126			 */
1127			if ((single_dpm_table->dpm_levels[0].value != curr_freq) &&
1128			     (single_dpm_table->dpm_levels[1].value != curr_freq)) {
1129				size += sysfs_emit_at(buf, size, "0: %uMhz\n",
1130						single_dpm_table->dpm_levels[0].value);
1131				size += sysfs_emit_at(buf, size, "1: %uMhz *\n",
1132						curr_freq);
1133				size += sysfs_emit_at(buf, size, "2: %uMhz\n",
1134						single_dpm_table->dpm_levels[1].value);
1135			} else {
1136				size += sysfs_emit_at(buf, size, "0: %uMhz %s\n",
1137						single_dpm_table->dpm_levels[0].value,
1138						single_dpm_table->dpm_levels[0].value == curr_freq ? "*" : "");
1139				size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
1140						single_dpm_table->dpm_levels[1].value,
1141						single_dpm_table->dpm_levels[1].value == curr_freq ? "*" : "");
1142			}
1143		} else {
1144			for (i = 0; i < single_dpm_table->count; i++)
1145				size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
1146						i, single_dpm_table->dpm_levels[i].value,
1147						single_dpm_table->dpm_levels[i].value == curr_freq ? "*" : "");
1148		}
1149		break;
1150	case SMU_PCIE:
1151		ret = smu_v14_0_2_get_smu_metrics_data(smu,
1152						       METRICS_PCIE_RATE,
1153						       &gen_speed);
1154		if (ret)
1155			return ret;
1156
1157		ret = smu_v14_0_2_get_smu_metrics_data(smu,
1158						       METRICS_PCIE_WIDTH,
1159						       &lane_width);
1160		if (ret)
1161			return ret;
1162
1163		pcie_table = &(dpm_context->dpm_tables.pcie_table);
1164		for (i = 0; i < pcie_table->num_of_link_levels; i++)
1165			size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
1166					(pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," :
1167					(pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," :
1168					(pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," :
1169					(pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," :
1170					(pcie_table->pcie_gen[i] == 4) ? "32.0GT/s," : "",
1171					(pcie_table->pcie_lane[i] == 1) ? "x1" :
1172					(pcie_table->pcie_lane[i] == 2) ? "x2" :
1173					(pcie_table->pcie_lane[i] == 3) ? "x4" :
1174					(pcie_table->pcie_lane[i] == 4) ? "x8" :
1175					(pcie_table->pcie_lane[i] == 5) ? "x12" :
1176					(pcie_table->pcie_lane[i] == 6) ? "x16" :
1177					(pcie_table->pcie_lane[i] == 7) ? "x32" : "",
1178					pcie_table->clk_freq[i],
1179					(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
1180					(lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
1181					"*" : "");
1182		break;
1183
1184	case SMU_OD_SCLK:
1185		if (!smu_v14_0_2_is_od_feature_supported(smu,
1186							 PP_OD_FEATURE_GFXCLK_BIT))
1187			break;
1188
1189		size += sysfs_emit_at(buf, size, "OD_SCLK_OFFSET:\n");
1190		size += sysfs_emit_at(buf, size, "%dMhz\n",
1191					od_table->OverDriveTable.GfxclkFoffset);
1192		break;
1193
1194	case SMU_OD_MCLK:
1195		if (!smu_v14_0_2_is_od_feature_supported(smu,
1196							 PP_OD_FEATURE_UCLK_BIT))
1197			break;
1198
1199		size += sysfs_emit_at(buf, size, "OD_MCLK:\n");
1200		size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMHz\n",
1201					od_table->OverDriveTable.UclkFmin,
1202					od_table->OverDriveTable.UclkFmax);
1203		break;
1204
1205	case SMU_OD_VDDGFX_OFFSET:
1206		if (!smu_v14_0_2_is_od_feature_supported(smu,
1207							 PP_OD_FEATURE_GFX_VF_CURVE_BIT))
1208			break;
1209
1210		size += sysfs_emit_at(buf, size, "OD_VDDGFX_OFFSET:\n");
1211		size += sysfs_emit_at(buf, size, "%dmV\n",
1212				      od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[0]);
1213		break;
1214
1215	case SMU_OD_FAN_CURVE:
1216		if (!smu_v14_0_2_is_od_feature_supported(smu,
1217							 PP_OD_FEATURE_FAN_CURVE_BIT))
1218			break;
1219
1220		size += sysfs_emit_at(buf, size, "OD_FAN_CURVE:\n");
1221		for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++)
1222			size += sysfs_emit_at(buf, size, "%d: %dC %d%%\n",
1223						i,
1224						(int)od_table->OverDriveTable.FanLinearTempPoints[i],
1225						(int)od_table->OverDriveTable.FanLinearPwmPoints[i]);
1226
1227		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1228		smu_v14_0_2_get_od_setting_limits(smu,
1229						  PP_OD_FEATURE_FAN_CURVE_TEMP,
1230						  &min_value,
1231						  &max_value);
1232		size += sysfs_emit_at(buf, size, "FAN_CURVE(hotspot temp): %uC %uC\n",
1233				      min_value, max_value);
1234
1235		smu_v14_0_2_get_od_setting_limits(smu,
1236						  PP_OD_FEATURE_FAN_CURVE_PWM,
1237						  &min_value,
1238						  &max_value);
1239		size += sysfs_emit_at(buf, size, "FAN_CURVE(fan speed): %u%% %u%%\n",
1240				      min_value, max_value);
1241
1242		break;
1243
1244	case SMU_OD_ACOUSTIC_LIMIT:
1245		if (!smu_v14_0_2_is_od_feature_supported(smu,
1246							 PP_OD_FEATURE_FAN_CURVE_BIT))
1247			break;
1248
1249		size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_LIMIT:\n");
1250		size += sysfs_emit_at(buf, size, "%d\n",
1251					(int)od_table->OverDriveTable.AcousticLimitRpmThreshold);
1252
1253		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1254		smu_v14_0_2_get_od_setting_limits(smu,
1255						  PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT,
1256						  &min_value,
1257						  &max_value);
1258		size += sysfs_emit_at(buf, size, "ACOUSTIC_LIMIT: %u %u\n",
1259				      min_value, max_value);
1260		break;
1261
1262	case SMU_OD_ACOUSTIC_TARGET:
1263		if (!smu_v14_0_2_is_od_feature_supported(smu,
1264							 PP_OD_FEATURE_FAN_CURVE_BIT))
1265			break;
1266
1267		size += sysfs_emit_at(buf, size, "OD_ACOUSTIC_TARGET:\n");
1268		size += sysfs_emit_at(buf, size, "%d\n",
1269					(int)od_table->OverDriveTable.AcousticTargetRpmThreshold);
1270
1271		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1272		smu_v14_0_2_get_od_setting_limits(smu,
1273						  PP_OD_FEATURE_FAN_ACOUSTIC_TARGET,
1274						  &min_value,
1275						  &max_value);
1276		size += sysfs_emit_at(buf, size, "ACOUSTIC_TARGET: %u %u\n",
1277				      min_value, max_value);
1278		break;
1279
1280	case SMU_OD_FAN_TARGET_TEMPERATURE:
1281		if (!smu_v14_0_2_is_od_feature_supported(smu,
1282							 PP_OD_FEATURE_FAN_CURVE_BIT))
1283			break;
1284
1285		size += sysfs_emit_at(buf, size, "FAN_TARGET_TEMPERATURE:\n");
1286		size += sysfs_emit_at(buf, size, "%d\n",
1287					(int)od_table->OverDriveTable.FanTargetTemperature);
1288
1289		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1290		smu_v14_0_2_get_od_setting_limits(smu,
1291						  PP_OD_FEATURE_FAN_TARGET_TEMPERATURE,
1292						  &min_value,
1293						  &max_value);
1294		size += sysfs_emit_at(buf, size, "TARGET_TEMPERATURE: %u %u\n",
1295				      min_value, max_value);
1296		break;
1297
1298	case SMU_OD_FAN_MINIMUM_PWM:
1299		if (!smu_v14_0_2_is_od_feature_supported(smu,
1300							 PP_OD_FEATURE_FAN_CURVE_BIT))
1301			break;
1302
1303		size += sysfs_emit_at(buf, size, "FAN_MINIMUM_PWM:\n");
1304		size += sysfs_emit_at(buf, size, "%d\n",
1305					(int)od_table->OverDriveTable.FanMinimumPwm);
1306
1307		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1308		smu_v14_0_2_get_od_setting_limits(smu,
1309						  PP_OD_FEATURE_FAN_MINIMUM_PWM,
1310						  &min_value,
1311						  &max_value);
1312		size += sysfs_emit_at(buf, size, "MINIMUM_PWM: %u %u\n",
1313				      min_value, max_value);
1314		break;
1315
1316	case SMU_OD_FAN_ZERO_RPM_ENABLE:
1317		if (!smu_v14_0_2_is_od_feature_supported(smu,
1318							 PP_OD_FEATURE_ZERO_FAN_BIT))
1319			break;
1320
1321		size += sysfs_emit_at(buf, size, "FAN_ZERO_RPM_ENABLE:\n");
1322		size += sysfs_emit_at(buf, size, "%d\n",
1323				(int)od_table->OverDriveTable.FanZeroRpmEnable);
1324
1325		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1326		smu_v14_0_2_get_od_setting_limits(smu,
1327						  PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
1328						  &min_value,
1329						  &max_value);
1330		size += sysfs_emit_at(buf, size, "ZERO_RPM_ENABLE: %u %u\n",
1331				      min_value, max_value);
1332		break;
1333
1334	case SMU_OD_RANGE:
1335		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT) &&
1336		    !smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT) &&
1337		    !smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT))
1338			break;
1339
1340		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1341
1342		if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
1343			smu_v14_0_2_get_od_setting_limits(smu,
1344							  PP_OD_FEATURE_GFXCLK_FMAX,
1345							  &min_value,
1346							  &max_value);
1347			size += sysfs_emit_at(buf, size, "SCLK_OFFSET: %7dMhz %10uMhz\n",
1348					      min_value, max_value);
1349		}
1350
1351		if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
1352			smu_v14_0_2_get_od_setting_limits(smu,
1353							  PP_OD_FEATURE_UCLK_FMIN,
1354							  &min_value,
1355							  NULL);
1356			smu_v14_0_2_get_od_setting_limits(smu,
1357							  PP_OD_FEATURE_UCLK_FMAX,
1358							  NULL,
1359							  &max_value);
1360			size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n",
1361					      min_value, max_value);
1362		}
1363
1364		if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
1365			smu_v14_0_2_get_od_setting_limits(smu,
1366							  PP_OD_FEATURE_GFX_VF_CURVE,
1367							  &min_value,
1368							  &max_value);
1369			size += sysfs_emit_at(buf, size, "VDDGFX_OFFSET: %7dmv %10dmv\n",
1370					      min_value, max_value);
1371		}
1372		break;
1373
1374	default:
1375		break;
1376	}
1377
1378	return size - start_offset;
1379}
1380
1381static int smu_v14_0_2_force_clk_levels(struct smu_context *smu,
1382					enum smu_clk_type clk_type,
1383					uint32_t mask)
1384{
1385	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
1386	struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context;
1387	struct smu_14_0_dpm_table *single_dpm_table;
1388	uint32_t soft_min_level, soft_max_level;
1389	uint32_t min_freq, max_freq;
1390	int ret = 0;
1391
1392	soft_min_level = mask ? (ffs(mask) - 1) : 0;
1393	soft_max_level = mask ? (fls(mask) - 1) : 0;
1394
1395	switch (clk_type) {
1396	case SMU_GFXCLK:
1397	case SMU_SCLK:
1398		single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
1399		break;
1400	case SMU_MCLK:
1401	case SMU_UCLK:
1402		single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
1403		break;
1404	case SMU_SOCCLK:
1405		single_dpm_table = &(dpm_context->dpm_tables.soc_table);
1406		break;
1407	case SMU_FCLK:
1408		single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
1409		break;
1410	case SMU_VCLK:
1411	case SMU_VCLK1:
1412		single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
1413		break;
1414	case SMU_DCLK:
1415	case SMU_DCLK1:
1416		single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
1417		break;
1418	default:
1419		break;
1420	}
1421
1422	switch (clk_type) {
1423	case SMU_GFXCLK:
1424	case SMU_SCLK:
1425	case SMU_MCLK:
1426	case SMU_UCLK:
1427	case SMU_SOCCLK:
1428	case SMU_FCLK:
1429	case SMU_VCLK:
1430	case SMU_VCLK1:
1431	case SMU_DCLK:
1432	case SMU_DCLK1:
1433		if (single_dpm_table->is_fine_grained) {
1434			/* There is only 2 levels for fine grained DPM */
1435			soft_max_level = (soft_max_level >= 1 ? 1 : 0);
1436			soft_min_level = (soft_min_level >= 1 ? 1 : 0);
1437		} else {
1438			if ((soft_max_level >= single_dpm_table->count) ||
1439			    (soft_min_level >= single_dpm_table->count))
1440				return -EINVAL;
1441		}
1442
1443		min_freq = single_dpm_table->dpm_levels[soft_min_level].value;
1444		max_freq = single_dpm_table->dpm_levels[soft_max_level].value;
1445
1446		ret = smu_v14_0_set_soft_freq_limited_range(smu,
1447							    clk_type,
1448							    min_freq,
1449							    max_freq,
1450							    false);
1451		break;
1452	case SMU_DCEFCLK:
1453	case SMU_PCIE:
1454	default:
1455		break;
1456	}
1457
1458	return ret;
1459}
1460
1461static int smu_v14_0_2_update_pcie_parameters(struct smu_context *smu,
1462					      uint8_t pcie_gen_cap,
1463					      uint8_t pcie_width_cap)
1464{
1465	struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
1466	struct smu_14_0_pcie_table *pcie_table =
1467				&dpm_context->dpm_tables.pcie_table;
1468	int num_of_levels;
1469	uint32_t smu_pcie_arg;
1470	uint32_t link_level;
1471	struct smu_table_context *table_context = &smu->smu_table;
1472	PPTable_t *pptable = table_context->driver_pptable;
1473	SkuTable_t *skutable = &pptable->SkuTable;
1474	int ret = 0;
1475	int i;
1476
1477	pcie_table->num_of_link_levels = 0;
1478	for (link_level = 0; link_level < NUM_LINK_LEVELS; link_level++) {
1479		if (!skutable->PcieGenSpeed[link_level] &&
1480		    !skutable->PcieLaneCount[link_level] &&
1481		    !skutable->LclkFreq[link_level])
1482			continue;
1483
1484		pcie_table->pcie_gen[pcie_table->num_of_link_levels] =
1485					skutable->PcieGenSpeed[link_level];
1486		pcie_table->pcie_lane[pcie_table->num_of_link_levels] =
1487					skutable->PcieLaneCount[link_level];
1488		pcie_table->clk_freq[pcie_table->num_of_link_levels] =
1489					skutable->LclkFreq[link_level];
1490		pcie_table->num_of_link_levels++;
1491	}
1492	num_of_levels = pcie_table->num_of_link_levels;
1493	if (!num_of_levels)
1494		return 0;
1495
1496	if (!(smu->adev->pm.pp_feature & PP_PCIE_DPM_MASK)) {
1497		if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap)
1498			pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1];
1499
1500		if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap)
1501			pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1];
1502
1503		/* Force all levels to use the same settings */
1504		for (i = 0; i < num_of_levels; i++) {
1505			pcie_table->pcie_gen[i] = pcie_gen_cap;
1506			pcie_table->pcie_lane[i] = pcie_width_cap;
1507			smu_pcie_arg = i << 16;
1508			smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
1509			smu_pcie_arg |= pcie_table->pcie_lane[i];
1510
1511			ret = smu_cmn_send_smc_msg_with_param(smu,
1512						      SMU_MSG_OverridePcieParameters,
1513						      smu_pcie_arg,
1514						      NULL);
1515			if (ret)
1516				break;
1517		}
1518	} else {
1519		for (i = 0; i < num_of_levels; i++) {
1520			if (pcie_table->pcie_gen[i] > pcie_gen_cap ||
1521				pcie_table->pcie_lane[i] > pcie_width_cap) {
1522				pcie_table->pcie_gen[i] = pcie_table->pcie_gen[i] > pcie_gen_cap ?
1523										  pcie_gen_cap : pcie_table->pcie_gen[i];
1524				pcie_table->pcie_lane[i] = pcie_table->pcie_lane[i] > pcie_width_cap ?
1525										   pcie_width_cap : pcie_table->pcie_lane[i];
1526				smu_pcie_arg = i << 16;
1527				smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
1528				smu_pcie_arg |= pcie_table->pcie_lane[i];
1529
1530				ret = smu_cmn_send_smc_msg_with_param(smu,
1531						      SMU_MSG_OverridePcieParameters,
1532						      smu_pcie_arg,
1533						      NULL);
1534				if (ret)
1535					break;
1536			}
1537		}
1538	}
1539
1540	return ret;
1541}
1542
1543static const struct smu_temperature_range smu14_thermal_policy[] = {
1544	{-273150,  99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
1545	{ 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
1546};
1547
1548static int smu_v14_0_2_get_thermal_temperature_range(struct smu_context *smu,
1549						     struct smu_temperature_range *range)
1550{
1551	struct smu_table_context *table_context = &smu->smu_table;
1552	struct smu_14_0_2_powerplay_table *powerplay_table =
1553		table_context->power_play_table;
1554	PPTable_t *pptable = smu->smu_table.driver_pptable;
1555
1556	if (amdgpu_sriov_vf(smu->adev))
1557		return 0;
1558
1559	if (!range)
1560		return -EINVAL;
1561
1562	memcpy(range, &smu14_thermal_policy[0], sizeof(struct smu_temperature_range));
1563
1564	range->max = pptable->CustomSkuTable.TemperatureLimit[TEMP_EDGE] *
1565		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1566	range->edge_emergency_max = (pptable->CustomSkuTable.TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) *
1567		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1568	range->hotspot_crit_max = pptable->CustomSkuTable.TemperatureLimit[TEMP_HOTSPOT] *
1569		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1570	range->hotspot_emergency_max = (pptable->CustomSkuTable.TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) *
1571		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1572	range->mem_crit_max = pptable->CustomSkuTable.TemperatureLimit[TEMP_MEM] *
1573		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1574	range->mem_emergency_max = (pptable->CustomSkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)*
1575		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1576	range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
1577	range->software_shutdown_temp_offset = pptable->CustomSkuTable.FanAbnormalTempLimitOffset;
1578
1579	return 0;
1580}
1581
1582static int smu_v14_0_2_populate_umd_state_clk(struct smu_context *smu)
1583{
1584	struct smu_14_0_dpm_context *dpm_context =
1585		smu->smu_dpm.dpm_context;
1586	struct smu_14_0_dpm_table *gfx_table =
1587		&dpm_context->dpm_tables.gfx_table;
1588	struct smu_14_0_dpm_table *mem_table =
1589		&dpm_context->dpm_tables.uclk_table;
1590	struct smu_14_0_dpm_table *soc_table =
1591		&dpm_context->dpm_tables.soc_table;
1592	struct smu_14_0_dpm_table *vclk_table =
1593		&dpm_context->dpm_tables.vclk_table;
1594	struct smu_14_0_dpm_table *dclk_table =
1595		&dpm_context->dpm_tables.dclk_table;
1596	struct smu_14_0_dpm_table *fclk_table =
1597		&dpm_context->dpm_tables.fclk_table;
1598	struct smu_umd_pstate_table *pstate_table =
1599		&smu->pstate_table;
1600	struct smu_table_context *table_context = &smu->smu_table;
1601	PPTable_t *pptable = table_context->driver_pptable;
1602	DriverReportedClocks_t driver_clocks =
1603			pptable->SkuTable.DriverReportedClocks;
1604
1605	pstate_table->gfxclk_pstate.min = gfx_table->min;
1606	if (driver_clocks.GameClockAc &&
1607	    (driver_clocks.GameClockAc < gfx_table->max))
1608		pstate_table->gfxclk_pstate.peak = driver_clocks.GameClockAc;
1609	else
1610		pstate_table->gfxclk_pstate.peak = gfx_table->max;
1611
1612	pstate_table->uclk_pstate.min = mem_table->min;
1613	pstate_table->uclk_pstate.peak = mem_table->max;
1614
1615	pstate_table->socclk_pstate.min = soc_table->min;
1616	pstate_table->socclk_pstate.peak = soc_table->max;
1617
1618	pstate_table->vclk_pstate.min = vclk_table->min;
1619	pstate_table->vclk_pstate.peak = vclk_table->max;
1620
1621	pstate_table->dclk_pstate.min = dclk_table->min;
1622	pstate_table->dclk_pstate.peak = dclk_table->max;
1623
1624	pstate_table->fclk_pstate.min = fclk_table->min;
1625	pstate_table->fclk_pstate.peak = fclk_table->max;
1626
1627	if (driver_clocks.BaseClockAc &&
1628	    driver_clocks.BaseClockAc < gfx_table->max)
1629		pstate_table->gfxclk_pstate.standard = driver_clocks.BaseClockAc;
1630	else
1631		pstate_table->gfxclk_pstate.standard = gfx_table->max;
1632	pstate_table->uclk_pstate.standard = mem_table->max;
1633	pstate_table->socclk_pstate.standard = soc_table->min;
1634	pstate_table->vclk_pstate.standard = vclk_table->min;
1635	pstate_table->dclk_pstate.standard = dclk_table->min;
1636	pstate_table->fclk_pstate.standard = fclk_table->min;
1637
1638	return 0;
1639}
1640
1641static void smu_v14_0_2_get_unique_id(struct smu_context *smu)
1642{
1643	struct smu_table_context *smu_table = &smu->smu_table;
1644	SmuMetrics_t *metrics =
1645		&(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
1646	struct amdgpu_device *adev = smu->adev;
1647	uint32_t upper32 = 0, lower32 = 0;
1648	int ret;
1649
1650	ret = smu_cmn_get_metrics_table(smu, NULL, false);
1651	if (ret)
1652		goto out;
1653
1654	upper32 = metrics->PublicSerialNumberUpper;
1655	lower32 = metrics->PublicSerialNumberLower;
1656
1657out:
1658	adev->unique_id = ((uint64_t)upper32 << 32) | lower32;
1659}
1660
1661static int smu_v14_0_2_get_fan_speed_pwm(struct smu_context *smu,
1662					 uint32_t *speed)
1663{
1664	int ret;
1665
1666	if (!speed)
1667		return -EINVAL;
1668
1669	ret = smu_v14_0_2_get_smu_metrics_data(smu,
1670					       METRICS_CURR_FANPWM,
1671					       speed);
1672	if (ret) {
1673		dev_err(smu->adev->dev, "Failed to get fan speed(PWM)!");
1674		return ret;
1675	}
1676
1677	/* Convert the PMFW output which is in percent to pwm(255) based */
1678	*speed = min(*speed * 255 / 100, (uint32_t)255);
1679
1680	return 0;
1681}
1682
1683static int smu_v14_0_2_get_fan_speed_rpm(struct smu_context *smu,
1684					 uint32_t *speed)
1685{
1686	if (!speed)
1687		return -EINVAL;
1688
1689	return smu_v14_0_2_get_smu_metrics_data(smu,
1690						METRICS_CURR_FANSPEED,
1691						speed);
1692}
1693
1694static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
1695				       uint32_t *current_power_limit,
1696				       uint32_t *default_power_limit,
1697				       uint32_t *max_power_limit,
1698				       uint32_t *min_power_limit)
1699{
1700	struct smu_table_context *table_context = &smu->smu_table;
1701	struct smu_14_0_2_powerplay_table *powerplay_table =
1702		table_context->power_play_table;
1703	PPTable_t *pptable = table_context->driver_pptable;
1704	CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
1705	int16_t od_percent_upper = 0, od_percent_lower = 0;
1706	uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
1707	uint32_t power_limit;
1708
1709	if (smu_v14_0_get_current_power_limit(smu, &power_limit))
1710		power_limit = smu->adev->pm.ac_power ?
1711			      skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
1712			      skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
1713
1714	if (current_power_limit)
1715		*current_power_limit = power_limit;
1716	if (default_power_limit)
1717		*default_power_limit = power_limit;
1718
1719	if (powerplay_table) {
1720		if (smu->od_enabled &&
1721		    smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
1722			od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt;
1723			od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
1724		} else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
1725			od_percent_upper = 0;
1726			od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt;
1727		}
1728	}
1729
1730	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
1731					od_percent_upper, od_percent_lower, power_limit);
1732
1733	if (max_power_limit) {
1734		*max_power_limit = msg_limit * (100 + od_percent_upper);
1735		*max_power_limit /= 100;
1736	}
1737
1738	if (min_power_limit) {
1739		*min_power_limit = power_limit * (100 + od_percent_lower);
1740		*min_power_limit /= 100;
1741	}
1742
1743	return 0;
1744}
1745
1746static int smu_v14_0_2_get_power_profile_mode(struct smu_context *smu,
1747					      char *buf)
1748{
1749	DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
1750	DpmActivityMonitorCoeffInt_t *activity_monitor =
1751		&(activity_monitor_external.DpmActivityMonitorCoeffInt);
1752	static const char *title[] = {
1753			"PROFILE_INDEX(NAME)",
1754			"CLOCK_TYPE(NAME)",
1755			"FPS",
1756			"MinActiveFreqType",
1757			"MinActiveFreq",
1758			"BoosterFreqType",
1759			"BoosterFreq",
1760			"PD_Data_limit_c",
1761			"PD_Data_error_coeff",
1762			"PD_Data_error_rate_coeff"};
1763	int16_t workload_type = 0;
1764	uint32_t i, size = 0;
1765	int result = 0;
1766
1767	if (!buf)
1768		return -EINVAL;
1769
1770	size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s\n",
1771			title[0], title[1], title[2], title[3], title[4], title[5],
1772			title[6], title[7], title[8], title[9]);
1773
1774	for (i = 0; i < PP_SMC_POWER_PROFILE_COUNT; i++) {
1775		/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1776		workload_type = smu_cmn_to_asic_specific_index(smu,
1777							       CMN2ASIC_MAPPING_WORKLOAD,
1778							       i);
1779		if (workload_type == -ENOTSUPP)
1780			continue;
1781		else if (workload_type < 0)
1782			return -EINVAL;
1783
1784		result = smu_cmn_update_table(smu,
1785					      SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1786					      workload_type,
1787					      (void *)(&activity_monitor_external),
1788					      false);
1789		if (result) {
1790			dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1791			return result;
1792		}
1793
1794		size += sysfs_emit_at(buf, size, "%2d %14s%s:\n",
1795			i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1796
1797		size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n",
1798			" ",
1799			0,
1800			"GFXCLK",
1801			activity_monitor->Gfx_FPS,
1802			activity_monitor->Gfx_MinActiveFreqType,
1803			activity_monitor->Gfx_MinActiveFreq,
1804			activity_monitor->Gfx_BoosterFreqType,
1805			activity_monitor->Gfx_BoosterFreq,
1806			activity_monitor->Gfx_PD_Data_limit_c,
1807			activity_monitor->Gfx_PD_Data_error_coeff,
1808			activity_monitor->Gfx_PD_Data_error_rate_coeff);
1809
1810		size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n",
1811			" ",
1812			1,
1813			"FCLK",
1814			activity_monitor->Fclk_FPS,
1815			activity_monitor->Fclk_MinActiveFreqType,
1816			activity_monitor->Fclk_MinActiveFreq,
1817			activity_monitor->Fclk_BoosterFreqType,
1818			activity_monitor->Fclk_BoosterFreq,
1819			activity_monitor->Fclk_PD_Data_limit_c,
1820			activity_monitor->Fclk_PD_Data_error_coeff,
1821			activity_monitor->Fclk_PD_Data_error_rate_coeff);
1822	}
1823
1824	return size;
1825}
1826
1827#define SMU_14_0_2_CUSTOM_PARAMS_COUNT 9
1828#define SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT 2
1829#define SMU_14_0_2_CUSTOM_PARAMS_SIZE (SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT * SMU_14_0_2_CUSTOM_PARAMS_COUNT * sizeof(long))
1830
1831static int smu_v14_0_2_set_power_profile_mode_coeff(struct smu_context *smu,
1832						    long *input)
1833{
1834	DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
1835	DpmActivityMonitorCoeffInt_t *activity_monitor =
1836		&(activity_monitor_external.DpmActivityMonitorCoeffInt);
1837	int ret, idx;
1838
1839	ret = smu_cmn_update_table(smu,
1840				   SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1841				   WORKLOAD_PPLIB_CUSTOM_BIT,
1842				   (void *)(&activity_monitor_external),
1843				   false);
1844	if (ret) {
1845		dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1846		return ret;
1847	}
1848
1849	idx = 0 * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
1850	if (input[idx]) {
1851		/* Gfxclk */
1852		activity_monitor->Gfx_FPS = input[idx + 1];
1853		activity_monitor->Gfx_MinActiveFreqType = input[idx + 2];
1854		activity_monitor->Gfx_MinActiveFreq = input[idx + 3];
1855		activity_monitor->Gfx_BoosterFreqType = input[idx + 4];
1856		activity_monitor->Gfx_BoosterFreq = input[idx + 5];
1857		activity_monitor->Gfx_PD_Data_limit_c = input[idx + 6];
1858		activity_monitor->Gfx_PD_Data_error_coeff = input[idx + 7];
1859		activity_monitor->Gfx_PD_Data_error_rate_coeff = input[idx + 8];
1860	}
1861	idx = 1 * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
1862	if (input[idx]) {
1863		/* Fclk */
1864		activity_monitor->Fclk_FPS = input[idx + 1];
1865		activity_monitor->Fclk_MinActiveFreqType = input[idx + 2];
1866		activity_monitor->Fclk_MinActiveFreq = input[idx + 3];
1867		activity_monitor->Fclk_BoosterFreqType = input[idx + 4];
1868		activity_monitor->Fclk_BoosterFreq = input[idx + 5];
1869		activity_monitor->Fclk_PD_Data_limit_c = input[idx + 6];
1870		activity_monitor->Fclk_PD_Data_error_coeff = input[idx + 7];
1871		activity_monitor->Fclk_PD_Data_error_rate_coeff = input[idx + 8];
1872	}
1873
1874	ret = smu_cmn_update_table(smu,
1875				   SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1876				   WORKLOAD_PPLIB_CUSTOM_BIT,
1877				   (void *)(&activity_monitor_external),
1878				   true);
1879	if (ret) {
1880		dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
1881		return ret;
1882	}
1883
1884	return ret;
1885}
1886
1887static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
1888					      u32 workload_mask,
1889					      long *custom_params,
1890					      u32 custom_params_max_idx)
1891{
1892	u32 backend_workload_mask = 0;
1893	int ret, idx = -1, i;
1894
1895	smu_cmn_get_backend_workload_mask(smu, workload_mask,
1896					  &backend_workload_mask);
1897
1898	/* disable deep sleep if compute is enabled */
1899	if (workload_mask & (1 << PP_SMC_POWER_PROFILE_COMPUTE))
1900		smu_v14_0_deep_sleep_control(smu, false);
1901	else
1902		smu_v14_0_deep_sleep_control(smu, true);
1903
1904	if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
1905		if (!smu->custom_profile_params) {
1906			smu->custom_profile_params =
1907				kzalloc(SMU_14_0_2_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
1908			if (!smu->custom_profile_params)
1909				return -ENOMEM;
1910		}
1911		if (custom_params && custom_params_max_idx) {
1912			if (custom_params_max_idx != SMU_14_0_2_CUSTOM_PARAMS_COUNT)
1913				return -EINVAL;
1914			if (custom_params[0] >= SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT)
1915				return -EINVAL;
1916			idx = custom_params[0] * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
1917			smu->custom_profile_params[idx] = 1;
1918			for (i = 1; i < custom_params_max_idx; i++)
1919				smu->custom_profile_params[idx + i] = custom_params[i];
1920		}
1921		ret = smu_v14_0_2_set_power_profile_mode_coeff(smu,
1922							       smu->custom_profile_params);
1923		if (ret) {
1924			if (idx != -1)
1925				smu->custom_profile_params[idx] = 0;
1926			return ret;
1927		}
1928	} else if (smu->custom_profile_params) {
1929		memset(smu->custom_profile_params, 0, SMU_14_0_2_CUSTOM_PARAMS_SIZE);
1930	}
1931
1932	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1933					      backend_workload_mask, NULL);
1934	if (ret) {
1935		dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
1936			workload_mask);
1937		if (idx != -1)
1938			smu->custom_profile_params[idx] = 0;
1939		return ret;
1940	}
1941
1942	return ret;
1943}
1944
1945static int smu_v14_0_2_baco_enter(struct smu_context *smu)
1946{
1947	struct smu_baco_context *smu_baco = &smu->smu_baco;
1948	struct amdgpu_device *adev = smu->adev;
1949
1950	if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev))
1951		return smu_v14_0_baco_set_armd3_sequence(smu,
1952				smu_baco->maco_support ? BACO_SEQ_BAMACO : BACO_SEQ_BACO);
1953	else
1954		return smu_v14_0_baco_enter(smu);
1955}
1956
1957static int smu_v14_0_2_baco_exit(struct smu_context *smu)
1958{
1959	struct amdgpu_device *adev = smu->adev;
1960
1961	if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) {
1962		/* Wait for PMFW handling for the Dstate change */
1963		usleep_range(10000, 11000);
1964		return smu_v14_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS);
1965	} else {
1966		return smu_v14_0_baco_exit(smu);
1967	}
1968}
1969
1970static bool smu_v14_0_2_is_mode1_reset_supported(struct smu_context *smu)
1971{
1972	// TODO
1973
1974	return true;
1975}
1976
1977static int smu_v14_0_2_i2c_xfer(struct i2c_adapter *i2c_adap,
1978				   struct i2c_msg *msg, int num_msgs)
1979{
1980	struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
1981	struct amdgpu_device *adev = smu_i2c->adev;
1982	struct smu_context *smu = adev->powerplay.pp_handle;
1983	struct smu_table_context *smu_table = &smu->smu_table;
1984	struct smu_table *table = &smu_table->driver_table;
1985	SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
1986	int i, j, r, c;
1987	u16 dir;
1988
1989	if (!adev->pm.dpm_enabled)
1990		return -EBUSY;
1991
1992	req = kzalloc(sizeof(*req), GFP_KERNEL);
1993	if (!req)
1994		return -ENOMEM;
1995
1996	req->I2CcontrollerPort = smu_i2c->port;
1997	req->I2CSpeed = I2C_SPEED_FAST_400K;
1998	req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
1999	dir = msg[0].flags & I2C_M_RD;
2000
2001	for (c = i = 0; i < num_msgs; i++) {
2002		for (j = 0; j < msg[i].len; j++, c++) {
2003			SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
2004
2005			if (!(msg[i].flags & I2C_M_RD)) {
2006				/* write */
2007				cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
2008				cmd->ReadWriteData = msg[i].buf[j];
2009			}
2010
2011			if ((dir ^ msg[i].flags) & I2C_M_RD) {
2012				/* The direction changes.
2013				 */
2014				dir = msg[i].flags & I2C_M_RD;
2015				cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
2016			}
2017
2018			req->NumCmds++;
2019
2020			/*
2021			 * Insert STOP if we are at the last byte of either last
2022			 * message for the transaction or the client explicitly
2023			 * requires a STOP at this particular message.
2024			 */
2025			if ((j == msg[i].len - 1) &&
2026			    ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) {
2027				cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
2028				cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
2029			}
2030		}
2031	}
2032	mutex_lock(&adev->pm.mutex);
2033	r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
2034	mutex_unlock(&adev->pm.mutex);
2035	if (r)
2036		goto fail;
2037
2038	for (c = i = 0; i < num_msgs; i++) {
2039		if (!(msg[i].flags & I2C_M_RD)) {
2040			c += msg[i].len;
2041			continue;
2042		}
2043		for (j = 0; j < msg[i].len; j++, c++) {
2044			SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
2045
2046			msg[i].buf[j] = cmd->ReadWriteData;
2047		}
2048	}
2049	r = num_msgs;
2050fail:
2051	kfree(req);
2052	return r;
2053}
2054
2055static u32 smu_v14_0_2_i2c_func(struct i2c_adapter *adap)
2056{
2057	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
2058}
2059
2060static const struct i2c_algorithm smu_v14_0_2_i2c_algo = {
2061	.master_xfer = smu_v14_0_2_i2c_xfer,
2062	.functionality = smu_v14_0_2_i2c_func,
2063};
2064
2065static const struct i2c_adapter_quirks smu_v14_0_2_i2c_control_quirks = {
2066	.flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
2067	.max_read_len  = MAX_SW_I2C_COMMANDS,
2068	.max_write_len = MAX_SW_I2C_COMMANDS,
2069	.max_comb_1st_msg_len = 2,
2070	.max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
2071};
2072
2073static int smu_v14_0_2_i2c_control_init(struct smu_context *smu)
2074{
2075	struct amdgpu_device *adev = smu->adev;
2076	int res, i;
2077
2078	for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
2079		struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
2080		struct i2c_adapter *control = &smu_i2c->adapter;
2081
2082		smu_i2c->adev = adev;
2083		smu_i2c->port = i;
2084		mutex_init(&smu_i2c->mutex);
2085		control->owner = THIS_MODULE;
2086		control->dev.parent = &adev->pdev->dev;
2087		control->algo = &smu_v14_0_2_i2c_algo;
2088		snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i);
2089		control->quirks = &smu_v14_0_2_i2c_control_quirks;
2090		i2c_set_adapdata(control, smu_i2c);
2091
2092		res = devm_i2c_add_adapter(adev->dev, control);
2093		if (res) {
2094			DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
2095			return res;
2096		}
2097	}
2098
2099	/* assign the buses used for the FRU EEPROM and RAS EEPROM */
2100	/* XXX ideally this would be something in a vbios data table */
2101	adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter;
2102	adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
2103
2104	return 0;
2105}
2106
2107static void smu_v14_0_2_i2c_control_fini(struct smu_context *smu)
2108{
2109	struct amdgpu_device *adev = smu->adev;
2110
2111	adev->pm.ras_eeprom_i2c_bus = NULL;
2112	adev->pm.fru_eeprom_i2c_bus = NULL;
2113}
2114
2115static int smu_v14_0_2_set_mp1_state(struct smu_context *smu,
2116				     enum pp_mp1_state mp1_state)
2117{
2118	int ret;
2119
2120	switch (mp1_state) {
2121	case PP_MP1_STATE_UNLOAD:
2122		ret = smu_cmn_set_mp1_state(smu, mp1_state);
2123		break;
2124	default:
2125		/* Ignore others */
2126		ret = 0;
2127	}
2128
2129	return ret;
2130}
2131
2132static int smu_v14_0_2_set_df_cstate(struct smu_context *smu,
2133				     enum pp_df_cstate state)
2134{
2135	return smu_cmn_send_smc_msg_with_param(smu,
2136					       SMU_MSG_DFCstateControl,
2137					       state,
2138					       NULL);
2139}
2140
2141static int smu_v14_0_2_mode1_reset(struct smu_context *smu)
2142{
2143	int ret = 0;
2144
2145	ret = smu_cmn_send_debug_smc_msg(smu, DEBUGSMC_MSG_Mode1Reset);
2146	if (!ret) {
2147		if (amdgpu_emu_mode == 1) {
2148			msleep(50000);
2149		} else {
2150			/* disable mmio access while doing mode 1 reset*/
2151			smu->adev->no_hw_access = true;
2152			/* ensure no_hw_access is globally visible before any MMIO */
2153			smp_mb();
2154			msleep(1000);
2155		}
2156	}
2157
2158	return ret;
2159}
2160
2161static int smu_v14_0_2_mode2_reset(struct smu_context *smu)
2162{
2163	int ret = 0;
2164
2165	// TODO
2166
2167	return ret;
2168}
2169
2170static int smu_v14_0_2_enable_gfx_features(struct smu_context *smu)
2171{
2172	struct amdgpu_device *adev = smu->adev;
2173
2174	if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 2))
2175		return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnableAllSmuFeatures,
2176										   FEATURE_PWR_GFX, NULL);
2177	else
2178		return -EOPNOTSUPP;
2179}
2180
2181static void smu_v14_0_2_set_smu_mailbox_registers(struct smu_context *smu)
2182{
2183	struct amdgpu_device *adev = smu->adev;
2184
2185	smu->param_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_82);
2186	smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_66);
2187	smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_90);
2188
2189	smu->debug_param_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_53);
2190	smu->debug_msg_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_75);
2191	smu->debug_resp_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_54);
2192}
2193
2194static ssize_t smu_v14_0_2_get_gpu_metrics(struct smu_context *smu,
2195					   void **table)
2196{
2197	struct smu_table_context *smu_table = &smu->smu_table;
2198	struct gpu_metrics_v1_3 *gpu_metrics =
2199		(struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
2200	SmuMetricsExternal_t metrics_ext;
2201	SmuMetrics_t *metrics = &metrics_ext.SmuMetrics;
2202	int ret = 0;
2203
2204	ret = smu_cmn_get_metrics_table(smu,
2205					&metrics_ext,
2206					true);
2207	if (ret)
2208		return ret;
2209
2210	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
2211
2212	gpu_metrics->temperature_edge = metrics->AvgTemperature[TEMP_EDGE];
2213	gpu_metrics->temperature_hotspot = metrics->AvgTemperature[TEMP_HOTSPOT];
2214	gpu_metrics->temperature_mem = metrics->AvgTemperature[TEMP_MEM];
2215	gpu_metrics->temperature_vrgfx = metrics->AvgTemperature[TEMP_VR_GFX];
2216	gpu_metrics->temperature_vrsoc = metrics->AvgTemperature[TEMP_VR_SOC];
2217	gpu_metrics->temperature_vrmem = max(metrics->AvgTemperature[TEMP_VR_MEM0],
2218					     metrics->AvgTemperature[TEMP_VR_MEM1]);
2219
2220	gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
2221	gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
2222	gpu_metrics->average_mm_activity = max(metrics->AverageVcn0ActivityPercentage,
2223					       metrics->Vcn1ActivityPercentage);
2224
2225	gpu_metrics->average_socket_power = metrics->AverageSocketPower;
2226	gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
2227
2228	if (metrics->AverageGfxActivity <= SMU_14_0_2_BUSY_THRESHOLD)
2229		gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
2230	else
2231		gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
2232
2233	if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD)
2234		gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs;
2235	else
2236		gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs;
2237
2238	gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency;
2239	gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency;
2240	gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
2241	gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
2242
2243	gpu_metrics->current_gfxclk = gpu_metrics->average_gfxclk_frequency;
2244	gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
2245	gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
2246	gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
2247	gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
2248	gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_0];
2249	gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_0];
2250
2251	gpu_metrics->throttle_status =
2252			smu_v14_0_2_get_throttler_status(metrics);
2253	gpu_metrics->indep_throttle_status =
2254			smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
2255							   smu_v14_0_2_throttler_map);
2256
2257	gpu_metrics->current_fan_speed = metrics->AvgFanRpm;
2258
2259	gpu_metrics->pcie_link_width = metrics->PcieWidth;
2260	if ((metrics->PcieRate - 1) > LINK_SPEED_MAX)
2261		gpu_metrics->pcie_link_speed = pcie_gen_to_speed(1);
2262	else
2263		gpu_metrics->pcie_link_speed = pcie_gen_to_speed(metrics->PcieRate);
2264
2265	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
2266
2267	gpu_metrics->voltage_gfx = metrics->AvgVoltage[SVI_PLANE_VDD_GFX];
2268	gpu_metrics->voltage_soc = metrics->AvgVoltage[SVI_PLANE_VDD_SOC];
2269	gpu_metrics->voltage_mem = metrics->AvgVoltage[SVI_PLANE_VDDIO_MEM];
2270
2271	*table = (void *)gpu_metrics;
2272
2273	return sizeof(struct gpu_metrics_v1_3);
2274}
2275
2276static void smu_v14_0_2_dump_od_table(struct smu_context *smu,
2277				      OverDriveTableExternal_t *od_table)
2278{
2279	struct amdgpu_device *adev = smu->adev;
2280
2281	dev_dbg(adev->dev, "OD: Gfxclk offset: (%d)\n", od_table->OverDriveTable.GfxclkFoffset);
2282	dev_dbg(adev->dev, "OD: Uclk: (%d, %d)\n", od_table->OverDriveTable.UclkFmin,
2283						   od_table->OverDriveTable.UclkFmax);
2284}
2285
2286static int smu_v14_0_2_upload_overdrive_table(struct smu_context *smu,
2287					      OverDriveTableExternal_t *od_table)
2288{
2289	int ret;
2290	ret = smu_cmn_update_table(smu,
2291				   SMU_TABLE_OVERDRIVE,
2292				   0,
2293				   (void *)od_table,
2294				   true);
2295	if (ret)
2296		dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
2297
2298	return ret;
2299}
2300
2301static void smu_v14_0_2_set_supported_od_feature_mask(struct smu_context *smu)
2302{
2303	struct amdgpu_device *adev = smu->adev;
2304
2305	if (smu_v14_0_2_is_od_feature_supported(smu,
2306						PP_OD_FEATURE_FAN_CURVE_BIT))
2307		adev->pm.od_feature_mask |= OD_OPS_SUPPORT_FAN_CURVE_RETRIEVE |
2308					    OD_OPS_SUPPORT_FAN_CURVE_SET |
2309					    OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_RETRIEVE |
2310					    OD_OPS_SUPPORT_ACOUSTIC_LIMIT_THRESHOLD_SET |
2311					    OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_RETRIEVE |
2312					    OD_OPS_SUPPORT_ACOUSTIC_TARGET_THRESHOLD_SET |
2313					    OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_RETRIEVE |
2314					    OD_OPS_SUPPORT_FAN_TARGET_TEMPERATURE_SET |
2315					    OD_OPS_SUPPORT_FAN_MINIMUM_PWM_RETRIEVE |
2316					    OD_OPS_SUPPORT_FAN_MINIMUM_PWM_SET |
2317					    OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_RETRIEVE |
2318					    OD_OPS_SUPPORT_FAN_ZERO_RPM_ENABLE_SET;
2319}
2320
2321static int smu_v14_0_2_get_overdrive_table(struct smu_context *smu,
2322					   OverDriveTableExternal_t *od_table)
2323{
2324	int ret;
2325	ret = smu_cmn_update_table(smu,
2326				   SMU_TABLE_OVERDRIVE,
2327				   0,
2328				   (void *)od_table,
2329				   false);
2330	if (ret)
2331		dev_err(smu->adev->dev, "Failed to get overdrive table!\n");
2332
2333	return ret;
2334}
2335
2336static int smu_v14_0_2_set_default_od_settings(struct smu_context *smu)
2337{
2338	OverDriveTableExternal_t *od_table =
2339		(OverDriveTableExternal_t *)smu->smu_table.overdrive_table;
2340	OverDriveTableExternal_t *boot_od_table =
2341		(OverDriveTableExternal_t *)smu->smu_table.boot_overdrive_table;
2342	OverDriveTableExternal_t *user_od_table =
2343		(OverDriveTableExternal_t *)smu->smu_table.user_overdrive_table;
2344	OverDriveTableExternal_t user_od_table_bak;
2345	int ret;
2346	int i;
2347
2348	ret = smu_v14_0_2_get_overdrive_table(smu, boot_od_table);
2349	if (ret)
2350		return ret;
2351
2352	smu_v14_0_2_dump_od_table(smu, boot_od_table);
2353
2354	memcpy(od_table,
2355	       boot_od_table,
2356	       sizeof(OverDriveTableExternal_t));
2357
2358	/*
2359	 * For S3/S4/Runpm resume, we need to setup those overdrive tables again,
2360	 * but we have to preserve user defined values in "user_od_table".
2361	 */
2362	if (!smu->adev->in_suspend) {
2363		memcpy(user_od_table,
2364		       boot_od_table,
2365		       sizeof(OverDriveTableExternal_t));
2366		smu->user_dpm_profile.user_od = false;
2367	} else if (smu->user_dpm_profile.user_od) {
2368		memcpy(&user_od_table_bak,
2369		       user_od_table,
2370		       sizeof(OverDriveTableExternal_t));
2371		memcpy(user_od_table,
2372		       boot_od_table,
2373		       sizeof(OverDriveTableExternal_t));
2374		user_od_table->OverDriveTable.GfxclkFoffset =
2375				user_od_table_bak.OverDriveTable.GfxclkFoffset;
2376		user_od_table->OverDriveTable.UclkFmin =
2377				user_od_table_bak.OverDriveTable.UclkFmin;
2378		user_od_table->OverDriveTable.UclkFmax =
2379				user_od_table_bak.OverDriveTable.UclkFmax;
2380		for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
2381			user_od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] =
2382				user_od_table_bak.OverDriveTable.VoltageOffsetPerZoneBoundary[i];
2383		for (i = 0; i < NUM_OD_FAN_MAX_POINTS - 1; i++) {
2384			user_od_table->OverDriveTable.FanLinearTempPoints[i] =
2385				user_od_table_bak.OverDriveTable.FanLinearTempPoints[i];
2386			user_od_table->OverDriveTable.FanLinearPwmPoints[i] =
2387				user_od_table_bak.OverDriveTable.FanLinearPwmPoints[i];
2388		}
2389		user_od_table->OverDriveTable.AcousticLimitRpmThreshold =
2390			user_od_table_bak.OverDriveTable.AcousticLimitRpmThreshold;
2391		user_od_table->OverDriveTable.AcousticTargetRpmThreshold =
2392			user_od_table_bak.OverDriveTable.AcousticTargetRpmThreshold;
2393		user_od_table->OverDriveTable.FanTargetTemperature =
2394			user_od_table_bak.OverDriveTable.FanTargetTemperature;
2395		user_od_table->OverDriveTable.FanMinimumPwm =
2396			user_od_table_bak.OverDriveTable.FanMinimumPwm;
2397		user_od_table->OverDriveTable.FanZeroRpmEnable =
2398			user_od_table_bak.OverDriveTable.FanZeroRpmEnable;
2399	}
2400
2401	smu_v14_0_2_set_supported_od_feature_mask(smu);
2402
2403	return 0;
2404}
2405
2406static int smu_v14_0_2_restore_user_od_settings(struct smu_context *smu)
2407{
2408	struct smu_table_context *table_context = &smu->smu_table;
2409	OverDriveTableExternal_t *od_table = table_context->overdrive_table;
2410	OverDriveTableExternal_t *user_od_table = table_context->user_overdrive_table;
2411	int res;
2412
2413	user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) |
2414							BIT(PP_OD_FEATURE_UCLK_BIT) |
2415							BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) |
2416							BIT(PP_OD_FEATURE_FAN_CURVE_BIT) |
2417							BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
2418	res = smu_v14_0_2_upload_overdrive_table(smu, user_od_table);
2419	user_od_table->OverDriveTable.FeatureCtrlMask = 0;
2420	if (res == 0)
2421		memcpy(od_table, user_od_table, sizeof(OverDriveTableExternal_t));
2422
2423	return res;
2424}
2425
2426static int smu_v14_0_2_od_restore_table_single(struct smu_context *smu, long input)
2427{
2428	struct smu_table_context *table_context = &smu->smu_table;
2429	OverDriveTableExternal_t *boot_overdrive_table =
2430		(OverDriveTableExternal_t *)table_context->boot_overdrive_table;
2431	OverDriveTableExternal_t *od_table =
2432		(OverDriveTableExternal_t *)table_context->overdrive_table;
2433	struct amdgpu_device *adev = smu->adev;
2434	int i;
2435
2436	switch (input) {
2437	case PP_OD_EDIT_FAN_CURVE:
2438		for (i = 0; i < NUM_OD_FAN_MAX_POINTS; i++) {
2439			od_table->OverDriveTable.FanLinearTempPoints[i] =
2440					boot_overdrive_table->OverDriveTable.FanLinearTempPoints[i];
2441			od_table->OverDriveTable.FanLinearPwmPoints[i] =
2442					boot_overdrive_table->OverDriveTable.FanLinearPwmPoints[i];
2443		}
2444		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2445		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2446		break;
2447	case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
2448		od_table->OverDriveTable.FanZeroRpmEnable =
2449					boot_overdrive_table->OverDriveTable.FanZeroRpmEnable;
2450		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
2451		break;
2452	case PP_OD_EDIT_ACOUSTIC_LIMIT:
2453		od_table->OverDriveTable.AcousticLimitRpmThreshold =
2454					boot_overdrive_table->OverDriveTable.AcousticLimitRpmThreshold;
2455		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2456		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2457		break;
2458	case PP_OD_EDIT_ACOUSTIC_TARGET:
2459		od_table->OverDriveTable.AcousticTargetRpmThreshold =
2460					boot_overdrive_table->OverDriveTable.AcousticTargetRpmThreshold;
2461		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2462		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2463		break;
2464	case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
2465		od_table->OverDriveTable.FanTargetTemperature =
2466					boot_overdrive_table->OverDriveTable.FanTargetTemperature;
2467		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2468		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2469		break;
2470	case PP_OD_EDIT_FAN_MINIMUM_PWM:
2471		od_table->OverDriveTable.FanMinimumPwm =
2472					boot_overdrive_table->OverDriveTable.FanMinimumPwm;
2473		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2474		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2475		break;
2476	default:
2477		dev_info(adev->dev, "Invalid table index: %ld\n", input);
2478		return -EINVAL;
2479	}
2480
2481	return 0;
2482}
2483
2484static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu,
2485					 enum PP_OD_DPM_TABLE_COMMAND type,
2486					 long input[],
2487					 uint32_t size)
2488{
2489	struct smu_table_context *table_context = &smu->smu_table;
2490	OverDriveTableExternal_t *od_table =
2491		(OverDriveTableExternal_t *)table_context->overdrive_table;
2492	struct amdgpu_device *adev = smu->adev;
2493	uint32_t offset_of_voltageoffset;
2494	int32_t minimum, maximum;
2495	uint32_t feature_ctrlmask;
2496	int i, ret = 0;
2497
2498	switch (type) {
2499	case PP_OD_EDIT_SCLK_VDDC_TABLE:
2500		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFXCLK_BIT)) {
2501			dev_warn(adev->dev, "GFXCLK_LIMITS setting not supported!\n");
2502			return -ENOTSUPP;
2503		}
2504
2505		if (size != 1) {
2506			dev_info(adev->dev, "invalid number of input parameters %d\n", size);
2507			return -EINVAL;
2508		}
2509
2510		smu_v14_0_2_get_od_setting_limits(smu,
2511						  PP_OD_FEATURE_GFXCLK_FMAX,
2512						  &minimum,
2513						  &maximum);
2514		if (input[0] < minimum ||
2515		    input[0] > maximum) {
2516			dev_info(adev->dev, "GfxclkFoffset must be within [%d, %u]!\n",
2517				 minimum, maximum);
2518			return -EINVAL;
2519		}
2520
2521		od_table->OverDriveTable.GfxclkFoffset = input[0];
2522		od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_GFXCLK_BIT;
2523		break;
2524
2525	case PP_OD_EDIT_MCLK_VDDC_TABLE:
2526		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_UCLK_BIT)) {
2527			dev_warn(adev->dev, "UCLK_LIMITS setting not supported!\n");
2528			return -ENOTSUPP;
2529		}
2530
2531		for (i = 0; i < size; i += 2) {
2532			if (i + 2 > size) {
2533				dev_info(adev->dev, "invalid number of input parameters %d\n", size);
2534				return -EINVAL;
2535			}
2536
2537			switch (input[i]) {
2538			case 0:
2539				smu_v14_0_2_get_od_setting_limits(smu,
2540								  PP_OD_FEATURE_UCLK_FMIN,
2541								  &minimum,
2542								  &maximum);
2543				if (input[i + 1] < minimum ||
2544				    input[i + 1] > maximum) {
2545					dev_info(adev->dev, "UclkFmin (%ld) must be within [%u, %u]!\n",
2546						input[i + 1], minimum, maximum);
2547					return -EINVAL;
2548				}
2549
2550				od_table->OverDriveTable.UclkFmin = input[i + 1];
2551				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
2552				break;
2553
2554			case 1:
2555				smu_v14_0_2_get_od_setting_limits(smu,
2556								  PP_OD_FEATURE_UCLK_FMAX,
2557								  &minimum,
2558								  &maximum);
2559				if (input[i + 1] < minimum ||
2560				    input[i + 1] > maximum) {
2561					dev_info(adev->dev, "UclkFmax (%ld) must be within [%u, %u]!\n",
2562						input[i + 1], minimum, maximum);
2563					return -EINVAL;
2564				}
2565
2566				od_table->OverDriveTable.UclkFmax = input[i + 1];
2567				od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_UCLK_BIT;
2568				break;
2569
2570			default:
2571				dev_info(adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[i]);
2572				dev_info(adev->dev, "Supported indices: [0:min,1:max]\n");
2573				return -EINVAL;
2574			}
2575		}
2576
2577		if (od_table->OverDriveTable.UclkFmin > od_table->OverDriveTable.UclkFmax) {
2578			dev_err(adev->dev,
2579				"Invalid setting: UclkFmin(%u) is bigger than UclkFmax(%u)\n",
2580				(uint32_t)od_table->OverDriveTable.UclkFmin,
2581				(uint32_t)od_table->OverDriveTable.UclkFmax);
2582			return -EINVAL;
2583		}
2584		break;
2585
2586	case PP_OD_EDIT_VDDGFX_OFFSET:
2587		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_GFX_VF_CURVE_BIT)) {
2588			dev_warn(adev->dev, "Gfx offset setting not supported!\n");
2589			return -ENOTSUPP;
2590		}
2591
2592		smu_v14_0_2_get_od_setting_limits(smu,
2593						  PP_OD_FEATURE_GFX_VF_CURVE,
2594						  &minimum,
2595						  &maximum);
2596		if (input[0] < minimum ||
2597		    input[0] > maximum) {
2598			dev_info(adev->dev, "Voltage offset (%ld) must be within [%d, %d]!\n",
2599				 input[0], minimum, maximum);
2600			return -EINVAL;
2601		}
2602
2603		for (i = 0; i < PP_NUM_OD_VF_CURVE_POINTS; i++)
2604			od_table->OverDriveTable.VoltageOffsetPerZoneBoundary[i] = input[0];
2605		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT);
2606		break;
2607
2608	case PP_OD_EDIT_FAN_CURVE:
2609		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
2610			dev_warn(adev->dev, "Fan curve setting not supported!\n");
2611			return -ENOTSUPP;
2612		}
2613
2614		if (input[0] >= NUM_OD_FAN_MAX_POINTS - 1 ||
2615		    input[0] < 0)
2616			return -EINVAL;
2617
2618		smu_v14_0_2_get_od_setting_limits(smu,
2619						  PP_OD_FEATURE_FAN_CURVE_TEMP,
2620						  &minimum,
2621						  &maximum);
2622		if (input[1] < minimum ||
2623		    input[1] > maximum) {
2624			dev_info(adev->dev, "Fan curve temp setting(%ld) must be within [%d, %d]!\n",
2625				 input[1], minimum, maximum);
2626			return -EINVAL;
2627		}
2628
2629		smu_v14_0_2_get_od_setting_limits(smu,
2630						  PP_OD_FEATURE_FAN_CURVE_PWM,
2631						  &minimum,
2632						  &maximum);
2633		if (input[2] < minimum ||
2634		    input[2] > maximum) {
2635			dev_info(adev->dev, "Fan curve pwm setting(%ld) must be within [%d, %d]!\n",
2636				 input[2], minimum, maximum);
2637			return -EINVAL;
2638		}
2639
2640		od_table->OverDriveTable.FanLinearTempPoints[input[0]] = input[1];
2641		od_table->OverDriveTable.FanLinearPwmPoints[input[0]] = input[2];
2642		od_table->OverDriveTable.FanMode = FAN_MODE_MANUAL_LINEAR;
2643		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2644		break;
2645
2646	case PP_OD_EDIT_ACOUSTIC_LIMIT:
2647		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
2648			dev_warn(adev->dev, "Fan curve setting not supported!\n");
2649			return -ENOTSUPP;
2650		}
2651
2652		smu_v14_0_2_get_od_setting_limits(smu,
2653						  PP_OD_FEATURE_FAN_ACOUSTIC_LIMIT,
2654						  &minimum,
2655						  &maximum);
2656		if (input[0] < minimum ||
2657		    input[0] > maximum) {
2658			dev_info(adev->dev, "acoustic limit threshold setting(%ld) must be within [%d, %d]!\n",
2659				 input[0], minimum, maximum);
2660			return -EINVAL;
2661		}
2662
2663		od_table->OverDriveTable.AcousticLimitRpmThreshold = input[0];
2664		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2665		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2666		break;
2667
2668	case PP_OD_EDIT_ACOUSTIC_TARGET:
2669		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
2670			dev_warn(adev->dev, "Fan curve setting not supported!\n");
2671			return -ENOTSUPP;
2672		}
2673
2674		smu_v14_0_2_get_od_setting_limits(smu,
2675						  PP_OD_FEATURE_FAN_ACOUSTIC_TARGET,
2676						  &minimum,
2677						  &maximum);
2678		if (input[0] < minimum ||
2679		    input[0] > maximum) {
2680			dev_info(adev->dev, "acoustic target threshold setting(%ld) must be within [%d, %d]!\n",
2681				 input[0], minimum, maximum);
2682			return -EINVAL;
2683		}
2684
2685		od_table->OverDriveTable.AcousticTargetRpmThreshold = input[0];
2686		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2687		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2688		break;
2689
2690	case PP_OD_EDIT_FAN_TARGET_TEMPERATURE:
2691		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
2692			dev_warn(adev->dev, "Fan curve setting not supported!\n");
2693			return -ENOTSUPP;
2694		}
2695
2696		smu_v14_0_2_get_od_setting_limits(smu,
2697						  PP_OD_FEATURE_FAN_TARGET_TEMPERATURE,
2698						  &minimum,
2699						  &maximum);
2700		if (input[0] < minimum ||
2701		    input[0] > maximum) {
2702			dev_info(adev->dev, "fan target temperature setting(%ld) must be within [%d, %d]!\n",
2703				 input[0], minimum, maximum);
2704			return -EINVAL;
2705		}
2706
2707		od_table->OverDriveTable.FanTargetTemperature = input[0];
2708		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2709		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2710		break;
2711
2712	case PP_OD_EDIT_FAN_MINIMUM_PWM:
2713		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) {
2714			dev_warn(adev->dev, "Fan curve setting not supported!\n");
2715			return -ENOTSUPP;
2716		}
2717
2718		smu_v14_0_2_get_od_setting_limits(smu,
2719						  PP_OD_FEATURE_FAN_MINIMUM_PWM,
2720						  &minimum,
2721						  &maximum);
2722		if (input[0] < minimum ||
2723		    input[0] > maximum) {
2724			dev_info(adev->dev, "fan minimum pwm setting(%ld) must be within [%d, %d]!\n",
2725				 input[0], minimum, maximum);
2726			return -EINVAL;
2727		}
2728
2729		od_table->OverDriveTable.FanMinimumPwm = input[0];
2730		od_table->OverDriveTable.FanMode = FAN_MODE_AUTO;
2731		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT);
2732		break;
2733
2734	case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE:
2735		if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_ZERO_FAN_BIT)) {
2736			dev_warn(adev->dev, "Zero RPM setting not supported!\n");
2737			return -ENOTSUPP;
2738		}
2739
2740		smu_v14_0_2_get_od_setting_limits(smu,
2741						  PP_OD_FEATURE_FAN_ZERO_RPM_ENABLE,
2742						  &minimum,
2743						  &maximum);
2744		if (input[0] < minimum ||
2745		    input[0] > maximum) {
2746			dev_info(adev->dev, "zero RPM enable setting(%ld) must be within [%d, %d]!\n",
2747				 input[0], minimum, maximum);
2748			return -EINVAL;
2749		}
2750
2751		od_table->OverDriveTable.FanZeroRpmEnable = input[0];
2752		od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_ZERO_FAN_BIT);
2753		break;
2754
2755	case PP_OD_RESTORE_DEFAULT_TABLE:
2756		if (size == 1) {
2757			ret = smu_v14_0_2_od_restore_table_single(smu, input[0]);
2758			if (ret)
2759				return ret;
2760		} else {
2761			feature_ctrlmask = od_table->OverDriveTable.FeatureCtrlMask;
2762			memcpy(od_table,
2763		       table_context->boot_overdrive_table,
2764		       sizeof(OverDriveTableExternal_t));
2765			od_table->OverDriveTable.FeatureCtrlMask = feature_ctrlmask;
2766		}
2767		fallthrough;
2768	case PP_OD_COMMIT_DPM_TABLE:
2769		/*
2770		 * The member below instructs PMFW the settings focused in
2771		 * this single operation.
2772		 * `uint32_t FeatureCtrlMask;`
2773		 * It does not contain actual informations about user's custom
2774		 * settings. Thus we do not cache it.
2775		 */
2776		offset_of_voltageoffset = offsetof(OverDriveTable_t, VoltageOffsetPerZoneBoundary);
2777		if (memcmp((u8 *)od_table + offset_of_voltageoffset,
2778			   table_context->user_overdrive_table + offset_of_voltageoffset,
2779			   sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset)) {
2780			smu_v14_0_2_dump_od_table(smu, od_table);
2781
2782			ret = smu_v14_0_2_upload_overdrive_table(smu, od_table);
2783			if (ret) {
2784				dev_err(adev->dev, "Failed to upload overdrive table!\n");
2785				return ret;
2786			}
2787
2788			od_table->OverDriveTable.FeatureCtrlMask = 0;
2789			memcpy(table_context->user_overdrive_table + offset_of_voltageoffset,
2790			       (u8 *)od_table + offset_of_voltageoffset,
2791			       sizeof(OverDriveTableExternal_t) - offset_of_voltageoffset);
2792
2793			if (!memcmp(table_context->user_overdrive_table,
2794				    table_context->boot_overdrive_table,
2795				    sizeof(OverDriveTableExternal_t)))
2796				smu->user_dpm_profile.user_od = false;
2797			else
2798				smu->user_dpm_profile.user_od = true;
2799		}
2800		break;
2801
2802	default:
2803		return -ENOSYS;
2804	}
2805
2806	return ret;
2807}
2808
2809static int smu_v14_0_2_set_power_limit(struct smu_context *smu,
2810				       enum smu_ppt_limit_type limit_type,
2811				       uint32_t limit)
2812{
2813	PPTable_t *pptable = smu->smu_table.driver_pptable;
2814	uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
2815	struct smu_table_context *table_context = &smu->smu_table;
2816	OverDriveTableExternal_t *od_table =
2817		(OverDriveTableExternal_t *)table_context->overdrive_table;
2818	int ret = 0;
2819
2820	if (limit_type != SMU_DEFAULT_PPT_LIMIT)
2821		return -EINVAL;
2822
2823	if (limit <= msg_limit) {
2824		if (smu->current_power_limit > msg_limit) {
2825			od_table->OverDriveTable.Ppt = 0;
2826			od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
2827
2828			ret = smu_v14_0_2_upload_overdrive_table(smu, od_table);
2829			if (ret) {
2830				dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
2831				return ret;
2832			}
2833		}
2834		return smu_v14_0_set_power_limit(smu, limit_type, limit);
2835	} else if (smu->od_enabled) {
2836		ret = smu_v14_0_set_power_limit(smu, limit_type, msg_limit);
2837		if (ret)
2838			return ret;
2839
2840		od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100;
2841		od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT;
2842
2843		ret = smu_v14_0_2_upload_overdrive_table(smu, od_table);
2844		if (ret) {
2845		  dev_err(smu->adev->dev, "Failed to upload overdrive table!\n");
2846		  return ret;
2847		}
2848
2849		smu->current_power_limit = limit;
2850	} else {
2851		return -EINVAL;
2852	}
2853
2854	return 0;
2855}
2856
2857static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
2858	.get_allowed_feature_mask = smu_v14_0_2_get_allowed_feature_mask,
2859	.set_default_dpm_table = smu_v14_0_2_set_default_dpm_table,
2860	.i2c_init = smu_v14_0_2_i2c_control_init,
2861	.i2c_fini = smu_v14_0_2_i2c_control_fini,
2862	.is_dpm_running = smu_v14_0_2_is_dpm_running,
2863	.init_microcode = smu_v14_0_init_microcode,
2864	.load_microcode = smu_v14_0_load_microcode,
2865	.fini_microcode = smu_v14_0_fini_microcode,
2866	.init_smc_tables = smu_v14_0_2_init_smc_tables,
2867	.fini_smc_tables = smu_v14_0_fini_smc_tables,
2868	.init_power = smu_v14_0_init_power,
2869	.fini_power = smu_v14_0_fini_power,
2870	.check_fw_status = smu_v14_0_check_fw_status,
2871	.setup_pptable = smu_v14_0_2_setup_pptable,
2872	.check_fw_version = smu_v14_0_check_fw_version,
2873	.set_driver_table_location = smu_v14_0_set_driver_table_location,
2874	.system_features_control = smu_v14_0_system_features_control,
2875	.set_allowed_mask = smu_v14_0_set_allowed_mask,
2876	.get_enabled_mask = smu_cmn_get_enabled_mask,
2877	.dpm_set_vcn_enable = smu_v14_0_set_vcn_enable,
2878	.dpm_set_jpeg_enable = smu_v14_0_set_jpeg_enable,
2879	.get_dpm_ultimate_freq = smu_v14_0_2_get_dpm_ultimate_freq,
2880	.get_vbios_bootup_values = smu_v14_0_get_vbios_bootup_values,
2881	.read_sensor = smu_v14_0_2_read_sensor,
2882	.feature_is_enabled = smu_cmn_feature_is_enabled,
2883	.print_clk_levels = smu_v14_0_2_print_clk_levels,
2884	.force_clk_levels = smu_v14_0_2_force_clk_levels,
2885	.update_pcie_parameters = smu_v14_0_2_update_pcie_parameters,
2886	.get_thermal_temperature_range = smu_v14_0_2_get_thermal_temperature_range,
2887	.register_irq_handler = smu_v14_0_register_irq_handler,
2888	.enable_thermal_alert = smu_v14_0_enable_thermal_alert,
2889	.disable_thermal_alert = smu_v14_0_disable_thermal_alert,
2890	.notify_memory_pool_location = smu_v14_0_notify_memory_pool_location,
2891	.get_gpu_metrics = smu_v14_0_2_get_gpu_metrics,
2892	.set_soft_freq_limited_range = smu_v14_0_set_soft_freq_limited_range,
2893	.set_default_od_settings = smu_v14_0_2_set_default_od_settings,
2894	.restore_user_od_settings = smu_v14_0_2_restore_user_od_settings,
2895	.od_edit_dpm_table = smu_v14_0_2_od_edit_dpm_table,
2896	.init_pptable_microcode = smu_v14_0_init_pptable_microcode,
2897	.populate_umd_state_clk = smu_v14_0_2_populate_umd_state_clk,
2898	.set_performance_level = smu_v14_0_set_performance_level,
2899	.gfx_off_control = smu_v14_0_gfx_off_control,
2900	.get_unique_id = smu_v14_0_2_get_unique_id,
2901	.get_fan_speed_pwm = smu_v14_0_2_get_fan_speed_pwm,
2902	.get_fan_speed_rpm = smu_v14_0_2_get_fan_speed_rpm,
2903	.get_power_limit = smu_v14_0_2_get_power_limit,
2904	.set_power_limit = smu_v14_0_2_set_power_limit,
2905	.get_power_profile_mode = smu_v14_0_2_get_power_profile_mode,
2906	.set_power_profile_mode = smu_v14_0_2_set_power_profile_mode,
2907	.run_btc = smu_v14_0_run_btc,
2908	.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
2909	.set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
2910	.set_tool_table_location = smu_v14_0_set_tool_table_location,
2911	.deep_sleep_control = smu_v14_0_deep_sleep_control,
2912	.gfx_ulv_control = smu_v14_0_gfx_ulv_control,
2913	.get_bamaco_support = smu_v14_0_get_bamaco_support,
2914	.baco_get_state = smu_v14_0_baco_get_state,
2915	.baco_set_state = smu_v14_0_baco_set_state,
2916	.baco_enter = smu_v14_0_2_baco_enter,
2917	.baco_exit = smu_v14_0_2_baco_exit,
2918	.mode1_reset_is_support = smu_v14_0_2_is_mode1_reset_supported,
2919	.mode1_reset = smu_v14_0_2_mode1_reset,
2920	.mode2_reset = smu_v14_0_2_mode2_reset,
2921	.enable_gfx_features = smu_v14_0_2_enable_gfx_features,
2922	.set_mp1_state = smu_v14_0_2_set_mp1_state,
2923	.set_df_cstate = smu_v14_0_2_set_df_cstate,
2924#if 0
2925	.gpo_control = smu_v14_0_gpo_control,
2926#endif
2927};
2928
2929void smu_v14_0_2_set_ppt_funcs(struct smu_context *smu)
2930{
2931	smu->ppt_funcs = &smu_v14_0_2_ppt_funcs;
2932	smu->message_map = smu_v14_0_2_message_map;
2933	smu->clock_map = smu_v14_0_2_clk_map;
2934	smu->feature_map = smu_v14_0_2_feature_mask_map;
2935	smu->table_map = smu_v14_0_2_table_map;
2936	smu->pwr_src_map = smu_v14_0_2_pwr_src_map;
2937	smu->workload_map = smu_v14_0_2_workload_map;
2938	smu_v14_0_2_set_smu_mailbox_registers(smu);
2939}
~/ Read-only file preview.