File Index
Files and directories
Sign in
FILE

smu_v14_0_0_ppt.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_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#include "smu_types.h"
  25#define SWSMU_CODE_LAYER_L2
  26
  27#include "amdgpu.h"
  28#include "amdgpu_smu.h"
  29#include "smu_v14_0.h"
  30#include "smu14_driver_if_v14_0_0.h"
  31#include "smu_v14_0_0_ppt.h"
  32#include "smu_v14_0_0_ppsmc.h"
  33#include "smu_v14_0_0_pmfw.h"
  34#include "smu_cmn.h"
  35
  36/*
  37 * DO NOT use these for err/warn/info/debug messages.
  38 * Use dev_err, dev_warn, dev_info and dev_dbg instead.
  39 * They are more MGPU friendly.
  40 */
  41#undef pr_err
  42#undef pr_warn
  43#undef pr_info
  44#undef pr_debug
  45
  46#define mmMP1_SMN_C2PMSG_66			0x0282
  47#define mmMP1_SMN_C2PMSG_66_BASE_IDX            0
  48
  49#define mmMP1_SMN_C2PMSG_82			0x0292
  50#define mmMP1_SMN_C2PMSG_82_BASE_IDX            0
  51
  52#define mmMP1_SMN_C2PMSG_90			0x029a
  53#define mmMP1_SMN_C2PMSG_90_BASE_IDX		    0
  54
  55/* MALLPowerController message arguments (Defines for the Cache mode control) */
  56#define SMU_MALL_PMFW_CONTROL 0
  57#define SMU_MALL_DRIVER_CONTROL 1
  58
  59/*
  60 * MALLPowerState message arguments
  61 * (Defines for the Allocate/Release Cache mode if in driver mode)
  62 */
  63#define SMU_MALL_EXIT_PG 0
  64#define SMU_MALL_ENTER_PG 1
  65
  66#define SMU_MALL_PG_CONFIG_DEFAULT SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON
  67
  68#define SMU_14_0_0_UMD_PSTATE_GFXCLK			700
  69#define SMU_14_0_0_UMD_PSTATE_SOCCLK			678
  70#define SMU_14_0_0_UMD_PSTATE_FCLK			1800
  71
  72#define SMU_14_0_4_UMD_PSTATE_GFXCLK			938
  73#define SMU_14_0_4_UMD_PSTATE_SOCCLK			938
  74
  75#define FEATURE_MASK(feature) (1ULL << feature)
  76#define SMC_DPM_FEATURE ( \
  77	FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
  78	FEATURE_MASK(FEATURE_VCN_DPM_BIT)	 | \
  79	FEATURE_MASK(FEATURE_FCLK_DPM_BIT)	 | \
  80	FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT)	 | \
  81	FEATURE_MASK(FEATURE_LCLK_DPM_BIT)	 | \
  82	FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT)	 | \
  83	FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \
  84	FEATURE_MASK(FEATURE_ISP_DPM_BIT)| \
  85	FEATURE_MASK(FEATURE_IPU_DPM_BIT)	| \
  86	FEATURE_MASK(FEATURE_GFX_DPM_BIT)	| \
  87	FEATURE_MASK(FEATURE_VPE_DPM_BIT))
  88
  89enum smu_mall_pg_config {
  90	SMU_MALL_PG_CONFIG_PMFW_CONTROL = 0,
  91	SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON = 1,
  92	SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_OFF = 2,
  93};
  94
  95static struct cmn2asic_msg_mapping smu_v14_0_0_message_map[SMU_MSG_MAX_COUNT] = {
  96	MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,				1),
  97	MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetPmfwVersion,			1),
  98	MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,		1),
  99	MSG_MAP(PowerDownVcn0,                  PPSMC_MSG_PowerDownVcn0,			1),
 100	MSG_MAP(PowerUpVcn0,                    PPSMC_MSG_PowerUpVcn0,				1),
 101	MSG_MAP(SetHardMinVcn0,                 PPSMC_MSG_SetHardMinVcn0,			1),
 102	MSG_MAP(PowerDownVcn1,                  PPSMC_MSG_PowerDownVcn1,			1),
 103	MSG_MAP(PowerUpVcn1,                    PPSMC_MSG_PowerUpVcn1,				1),
 104	MSG_MAP(SetHardMinVcn1,                 PPSMC_MSG_SetHardMinVcn1,			1),
 105	MSG_MAP(SetSoftMinGfxclk,               PPSMC_MSG_SetSoftMinGfxclk,			1),
 106	MSG_MAP(PrepareMp1ForUnload,            PPSMC_MSG_PrepareMp1ForUnload,		1),
 107	MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh,	1),
 108	MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow,		1),
 109	MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,	1),
 110	MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,	1),
 111	MSG_MAP(GfxDeviceDriverReset,           PPSMC_MSG_GfxDeviceDriverReset,		1),
 112	MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,	1),
 113	MSG_MAP(SetHardMinSocclkByFreq,         PPSMC_MSG_SetHardMinSocclkByFreq,	1),
 114	MSG_MAP(SetSoftMinFclk,                 PPSMC_MSG_SetSoftMinFclk,			1),
 115	MSG_MAP(SetSoftMinVcn0,                 PPSMC_MSG_SetSoftMinVcn0,			1),
 116	MSG_MAP(SetSoftMinVcn1,                 PPSMC_MSG_SetSoftMinVcn1,			1),
 117	MSG_MAP(EnableGfxImu,                   PPSMC_MSG_EnableGfxImu,				1),
 118	MSG_MAP(AllowGfxOff,                    PPSMC_MSG_AllowGfxOff,				1),
 119	MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff,			1),
 120	MSG_MAP(SetSoftMaxGfxClk,               PPSMC_MSG_SetSoftMaxGfxClk,			1),
 121	MSG_MAP(SetHardMinGfxClk,               PPSMC_MSG_SetHardMinGfxClk,			1),
 122	MSG_MAP(SetSoftMaxSocclkByFreq,         PPSMC_MSG_SetSoftMaxSocclkByFreq,	1),
 123	MSG_MAP(SetSoftMaxFclkByFreq,           PPSMC_MSG_SetSoftMaxFclkByFreq,		1),
 124	MSG_MAP(SetSoftMaxVcn0,                 PPSMC_MSG_SetSoftMaxVcn0,			1),
 125	MSG_MAP(SetSoftMaxVcn1,                 PPSMC_MSG_SetSoftMaxVcn1,			1),
 126	MSG_MAP(PowerDownJpeg0,                 PPSMC_MSG_PowerDownJpeg0,			1),
 127	MSG_MAP(PowerUpJpeg0,                   PPSMC_MSG_PowerUpJpeg0,				1),
 128	MSG_MAP(PowerDownJpeg1,                 PPSMC_MSG_PowerDownJpeg1,			1),
 129	MSG_MAP(PowerUpJpeg1,                   PPSMC_MSG_PowerUpJpeg1,				1),
 130	MSG_MAP(SetHardMinFclkByFreq,           PPSMC_MSG_SetHardMinFclkByFreq,		1),
 131	MSG_MAP(SetSoftMinSocclkByFreq,         PPSMC_MSG_SetSoftMinSocclkByFreq,	1),
 132	MSG_MAP(PowerDownIspByTile,             PPSMC_MSG_PowerDownIspByTile,		1),
 133	MSG_MAP(PowerUpIspByTile,               PPSMC_MSG_PowerUpIspByTile,			1),
 134	MSG_MAP(SetHardMinIspiclkByFreq,        PPSMC_MSG_SetHardMinIspiclkByFreq,	1),
 135	MSG_MAP(SetHardMinIspxclkByFreq,        PPSMC_MSG_SetHardMinIspxclkByFreq,	1),
 136	MSG_MAP(PowerUpVpe,                     PPSMC_MSG_PowerUpVpe,				1),
 137	MSG_MAP(PowerDownVpe,                   PPSMC_MSG_PowerDownVpe,				1),
 138	MSG_MAP(PowerUpUmsch,                   PPSMC_MSG_PowerUpUmsch,				1),
 139	MSG_MAP(PowerDownUmsch,                 PPSMC_MSG_PowerDownUmsch,			1),
 140	MSG_MAP(SetSoftMaxVpe,                  PPSMC_MSG_SetSoftMaxVpe,			1),
 141	MSG_MAP(SetSoftMinVpe,                  PPSMC_MSG_SetSoftMinVpe,			1),
 142	MSG_MAP(MALLPowerController,            PPSMC_MSG_MALLPowerController,		1),
 143	MSG_MAP(MALLPowerState,                 PPSMC_MSG_MALLPowerState,			1),
 144};
 145
 146static struct cmn2asic_mapping smu_v14_0_0_feature_mask_map[SMU_FEATURE_COUNT] = {
 147	FEA_MAP(CCLK_DPM),
 148	FEA_MAP(FAN_CONTROLLER),
 149	FEA_MAP(PPT),
 150	FEA_MAP(TDC),
 151	FEA_MAP(THERMAL),
 152	FEA_MAP(VCN_DPM),
 153	FEA_MAP_REVERSE(FCLK),
 154	FEA_MAP_REVERSE(SOCCLK),
 155	FEA_MAP(LCLK_DPM),
 156	FEA_MAP(SHUBCLK_DPM),
 157	FEA_MAP(DCFCLK_DPM),
 158	FEA_MAP_HALF_REVERSE(GFX),
 159	FEA_MAP(DS_GFXCLK),
 160	FEA_MAP(DS_SOCCLK),
 161	FEA_MAP(DS_LCLK),
 162	FEA_MAP(LOW_POWER_DCNCLKS),
 163	FEA_MAP(DS_FCLK),
 164	FEA_MAP(DS_MP1CLK),
 165	FEA_MAP(PSI),
 166	FEA_MAP(PROCHOT),
 167	FEA_MAP(CPUOFF),
 168	FEA_MAP(STAPM),
 169	FEA_MAP(S0I3),
 170	FEA_MAP(PERF_LIMIT),
 171	FEA_MAP(CORE_DLDO),
 172	FEA_MAP(DS_VCN),
 173	FEA_MAP(CPPC),
 174	FEA_MAP(DF_CSTATES),
 175	FEA_MAP(ATHUB_PG),
 176};
 177
 178static struct cmn2asic_mapping smu_v14_0_0_table_map[SMU_TABLE_COUNT] = {
 179	TAB_MAP_VALID(WATERMARKS),
 180	TAB_MAP_VALID(SMU_METRICS),
 181	TAB_MAP_VALID(CUSTOM_DPM),
 182	TAB_MAP_VALID(DPMCLOCKS),
 183};
 184
 185static int smu_v14_0_0_init_smc_tables(struct smu_context *smu)
 186{
 187	struct smu_table_context *smu_table = &smu->smu_table;
 188	struct smu_table *tables = smu_table->tables;
 189
 190	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
 191		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 192	SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, max(sizeof(DpmClocks_t), sizeof(DpmClocks_t_v14_0_1)),
 193		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 194	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
 195		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 196
 197	smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
 198	if (!smu_table->metrics_table)
 199		goto err0_out;
 200	smu_table->metrics_time = 0;
 201
 202	smu_table->clocks_table = kzalloc(max(sizeof(DpmClocks_t), sizeof(DpmClocks_t_v14_0_1)), GFP_KERNEL);
 203	if (!smu_table->clocks_table)
 204		goto err1_out;
 205
 206	smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
 207	if (!smu_table->watermarks_table)
 208		goto err2_out;
 209
 210	smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v3_0);
 211	smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
 212	if (!smu_table->gpu_metrics_table)
 213		goto err3_out;
 214
 215	return 0;
 216
 217err3_out:
 218	kfree(smu_table->watermarks_table);
 219err2_out:
 220	kfree(smu_table->clocks_table);
 221err1_out:
 222	kfree(smu_table->metrics_table);
 223err0_out:
 224	return -ENOMEM;
 225}
 226
 227static int smu_v14_0_0_fini_smc_tables(struct smu_context *smu)
 228{
 229	struct smu_table_context *smu_table = &smu->smu_table;
 230
 231	kfree(smu_table->clocks_table);
 232	smu_table->clocks_table = NULL;
 233
 234	kfree(smu_table->metrics_table);
 235	smu_table->metrics_table = NULL;
 236
 237	kfree(smu_table->watermarks_table);
 238	smu_table->watermarks_table = NULL;
 239
 240	kfree(smu_table->gpu_metrics_table);
 241	smu_table->gpu_metrics_table = NULL;
 242
 243	return 0;
 244}
 245
 246static int smu_v14_0_0_system_features_control(struct smu_context *smu, bool en)
 247{
 248	struct amdgpu_device *adev = smu->adev;
 249	int ret = 0;
 250
 251	if (!en && !adev->in_s0ix)
 252		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
 253
 254	return ret;
 255}
 256
 257static int smu_v14_0_0_get_smu_metrics_data(struct smu_context *smu,
 258					    MetricsMember_t member,
 259					    uint32_t *value)
 260{
 261	struct smu_table_context *smu_table = &smu->smu_table;
 262
 263	SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
 264	int ret = 0;
 265
 266	ret = smu_cmn_get_metrics_table(smu, NULL, false);
 267	if (ret)
 268		return ret;
 269
 270	switch (member) {
 271	case METRICS_AVERAGE_GFXCLK:
 272		*value = metrics->GfxclkFrequency;
 273		break;
 274	case METRICS_AVERAGE_SOCCLK:
 275		*value = metrics->SocclkFrequency;
 276		break;
 277	case METRICS_AVERAGE_VCLK:
 278		*value = metrics->VclkFrequency;
 279		break;
 280	case METRICS_AVERAGE_DCLK:
 281		*value = 0;
 282		break;
 283	case METRICS_AVERAGE_UCLK:
 284		*value = metrics->MemclkFrequency;
 285		break;
 286	case METRICS_AVERAGE_FCLK:
 287		*value = metrics->FclkFrequency;
 288		break;
 289	case METRICS_AVERAGE_VPECLK:
 290		*value = metrics->VpeclkFrequency;
 291		break;
 292	case METRICS_AVERAGE_IPUCLK:
 293		*value = metrics->IpuclkFrequency;
 294		break;
 295	case METRICS_AVERAGE_MPIPUCLK:
 296		*value = metrics->MpipuclkFrequency;
 297		break;
 298	case METRICS_AVERAGE_GFXACTIVITY:
 299		if ((smu->smc_fw_version > 0x5d4600))
 300			*value = metrics->GfxActivity;
 301		else
 302			*value = metrics->GfxActivity / 100;
 303		break;
 304	case METRICS_AVERAGE_VCNACTIVITY:
 305		*value = metrics->VcnActivity / 100;
 306		break;
 307	case METRICS_AVERAGE_SOCKETPOWER:
 308	case METRICS_CURR_SOCKETPOWER:
 309		*value = (metrics->SocketPower / 1000 << 8) +
 310		(metrics->SocketPower % 1000 / 10);
 311		break;
 312	case METRICS_TEMPERATURE_EDGE:
 313		*value = metrics->GfxTemperature / 100 *
 314		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 315		break;
 316	case METRICS_TEMPERATURE_HOTSPOT:
 317		*value = metrics->SocTemperature / 100 *
 318		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 319		break;
 320	case METRICS_THROTTLER_RESIDENCY_PROCHOT:
 321		*value = metrics->ThrottleResidency_PROCHOT;
 322		break;
 323	case METRICS_THROTTLER_RESIDENCY_SPL:
 324		*value = metrics->ThrottleResidency_SPL;
 325		break;
 326	case METRICS_THROTTLER_RESIDENCY_FPPT:
 327		*value = metrics->ThrottleResidency_FPPT;
 328		break;
 329	case METRICS_THROTTLER_RESIDENCY_SPPT:
 330		*value = metrics->ThrottleResidency_SPPT;
 331		break;
 332	case METRICS_THROTTLER_RESIDENCY_THM_CORE:
 333		*value = metrics->ThrottleResidency_THM_CORE;
 334		break;
 335	case METRICS_THROTTLER_RESIDENCY_THM_GFX:
 336		*value = metrics->ThrottleResidency_THM_GFX;
 337		break;
 338	case METRICS_THROTTLER_RESIDENCY_THM_SOC:
 339		*value = metrics->ThrottleResidency_THM_SOC;
 340		break;
 341	case METRICS_VOLTAGE_VDDGFX:
 342		*value = 0;
 343		break;
 344	case METRICS_VOLTAGE_VDDSOC:
 345		*value = 0;
 346		break;
 347	case METRICS_SS_APU_SHARE:
 348		/* return the percentage of APU power with respect to APU's power limit.
 349		 * percentage is reported, this isn't boost value. Smartshift power
 350		 * boost/shift is only when the percentage is more than 100.
 351		 */
 352		if (metrics->StapmOpnLimit > 0)
 353			*value = (metrics->ApuPower * 100) / metrics->StapmOpnLimit;
 354		else
 355			*value = 0;
 356		break;
 357	case METRICS_SS_DGPU_SHARE:
 358		/* return the percentage of dGPU power with respect to dGPU's power limit.
 359		 * percentage is reported, this isn't boost value. Smartshift power
 360		 * boost/shift is only when the percentage is more than 100.
 361		 */
 362		if ((metrics->dGpuPower > 0) &&
 363		    (metrics->StapmCurrentLimit > metrics->StapmOpnLimit))
 364			*value = (metrics->dGpuPower * 100) /
 365				 (metrics->StapmCurrentLimit - metrics->StapmOpnLimit);
 366		else
 367			*value = 0;
 368		break;
 369	default:
 370		*value = UINT_MAX;
 371		break;
 372	}
 373
 374	return ret;
 375}
 376
 377static int smu_v14_0_0_read_sensor(struct smu_context *smu,
 378				   enum amd_pp_sensors sensor,
 379				   void *data, uint32_t *size)
 380{
 381	int ret = 0;
 382
 383	if (!data || !size)
 384		return -EINVAL;
 385
 386	switch (sensor) {
 387	case AMDGPU_PP_SENSOR_GPU_LOAD:
 388		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 389						       METRICS_AVERAGE_GFXACTIVITY,
 390						       (uint32_t *)data);
 391		*size = 4;
 392		break;
 393	case AMDGPU_PP_SENSOR_VCN_LOAD:
 394		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 395							METRICS_AVERAGE_VCNACTIVITY,
 396							(uint32_t *)data);
 397		*size = 4;
 398		break;
 399	case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
 400		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 401						       METRICS_AVERAGE_SOCKETPOWER,
 402						       (uint32_t *)data);
 403		*size = 4;
 404		break;
 405	case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
 406		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 407						       METRICS_CURR_SOCKETPOWER,
 408						       (uint32_t *)data);
 409		*size = 4;
 410		break;
 411	case AMDGPU_PP_SENSOR_EDGE_TEMP:
 412		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 413						       METRICS_TEMPERATURE_EDGE,
 414						       (uint32_t *)data);
 415		*size = 4;
 416		break;
 417	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
 418		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 419						       METRICS_TEMPERATURE_HOTSPOT,
 420						       (uint32_t *)data);
 421		*size = 4;
 422		break;
 423	case AMDGPU_PP_SENSOR_GFX_MCLK:
 424		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 425						       METRICS_AVERAGE_UCLK,
 426						       (uint32_t *)data);
 427		*(uint32_t *)data *= 100;
 428		*size = 4;
 429		break;
 430	case AMDGPU_PP_SENSOR_GFX_SCLK:
 431		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 432						       METRICS_AVERAGE_GFXCLK,
 433						       (uint32_t *)data);
 434		*(uint32_t *)data *= 100;
 435		*size = 4;
 436		break;
 437	case AMDGPU_PP_SENSOR_VDDGFX:
 438		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 439						       METRICS_VOLTAGE_VDDGFX,
 440						       (uint32_t *)data);
 441		*size = 4;
 442		break;
 443	case AMDGPU_PP_SENSOR_VDDNB:
 444		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 445						       METRICS_VOLTAGE_VDDSOC,
 446						       (uint32_t *)data);
 447		*size = 4;
 448		break;
 449	case AMDGPU_PP_SENSOR_SS_APU_SHARE:
 450		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 451						       METRICS_SS_APU_SHARE,
 452						       (uint32_t *)data);
 453		*size = 4;
 454		break;
 455	case AMDGPU_PP_SENSOR_SS_DGPU_SHARE:
 456		ret = smu_v14_0_0_get_smu_metrics_data(smu,
 457						       METRICS_SS_DGPU_SHARE,
 458						       (uint32_t *)data);
 459		*size = 4;
 460		break;
 461	default:
 462		ret = -EOPNOTSUPP;
 463		break;
 464	}
 465
 466	return ret;
 467}
 468
 469static bool smu_v14_0_0_is_dpm_running(struct smu_context *smu)
 470{
 471	int ret = 0;
 472	uint64_t feature_enabled;
 473
 474	ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
 475
 476	if (ret)
 477		return false;
 478
 479	return !!(feature_enabled & SMC_DPM_FEATURE);
 480}
 481
 482static int smu_v14_0_0_set_watermarks_table(struct smu_context *smu,
 483					    struct pp_smu_wm_range_sets *clock_ranges)
 484{
 485	int i;
 486	int ret = 0;
 487	Watermarks_t *table = smu->smu_table.watermarks_table;
 488
 489	if (!table || !clock_ranges)
 490		return -EINVAL;
 491
 492	if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
 493		clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
 494		return -EINVAL;
 495
 496	for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
 497		table->WatermarkRow[WM_DCFCLK][i].MinClock =
 498			clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
 499		table->WatermarkRow[WM_DCFCLK][i].MaxClock =
 500			clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
 501		table->WatermarkRow[WM_DCFCLK][i].MinMclk =
 502			clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
 503		table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
 504			clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
 505
 506		table->WatermarkRow[WM_DCFCLK][i].WmSetting =
 507			clock_ranges->reader_wm_sets[i].wm_inst;
 508	}
 509
 510	for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
 511		table->WatermarkRow[WM_SOCCLK][i].MinClock =
 512			clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
 513		table->WatermarkRow[WM_SOCCLK][i].MaxClock =
 514			clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
 515		table->WatermarkRow[WM_SOCCLK][i].MinMclk =
 516			clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
 517		table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
 518			clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
 519
 520		table->WatermarkRow[WM_SOCCLK][i].WmSetting =
 521			clock_ranges->writer_wm_sets[i].wm_inst;
 522	}
 523
 524	smu->watermarks_bitmap |= WATERMARKS_EXIST;
 525
 526	/* pass data to smu controller */
 527	if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
 528	     !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
 529		ret = smu_cmn_write_watermarks_table(smu);
 530		if (ret) {
 531			dev_err(smu->adev->dev, "Failed to update WMTABLE!");
 532			return ret;
 533		}
 534		smu->watermarks_bitmap |= WATERMARKS_LOADED;
 535	}
 536
 537	return 0;
 538}
 539
 540static ssize_t smu_v14_0_0_get_gpu_metrics(struct smu_context *smu,
 541						void **table)
 542{
 543	struct smu_table_context *smu_table = &smu->smu_table;
 544	struct gpu_metrics_v3_0 *gpu_metrics =
 545		(struct gpu_metrics_v3_0 *)smu_table->gpu_metrics_table;
 546	SmuMetrics_t metrics;
 547	int ret = 0;
 548
 549	ret = smu_cmn_get_metrics_table(smu, &metrics, true);
 550	if (ret)
 551		return ret;
 552
 553	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 3, 0);
 554
 555	gpu_metrics->temperature_gfx = metrics.GfxTemperature;
 556	gpu_metrics->temperature_soc = metrics.SocTemperature;
 557	memcpy(&gpu_metrics->temperature_core[0],
 558		&metrics.CoreTemperature[0],
 559		sizeof(uint16_t) * 16);
 560	gpu_metrics->temperature_skin = metrics.SkinTemp;
 561
 562	gpu_metrics->average_gfx_activity = metrics.GfxActivity;
 563	gpu_metrics->average_vcn_activity = metrics.VcnActivity;
 564	memcpy(&gpu_metrics->average_ipu_activity[0],
 565		&metrics.IpuBusy[0],
 566		sizeof(uint16_t) * 8);
 567	memcpy(&gpu_metrics->average_core_c0_activity[0],
 568		&metrics.CoreC0Residency[0],
 569		sizeof(uint16_t) * 16);
 570	gpu_metrics->average_dram_reads = metrics.DRAMReads;
 571	gpu_metrics->average_dram_writes = metrics.DRAMWrites;
 572	gpu_metrics->average_ipu_reads = metrics.IpuReads;
 573	gpu_metrics->average_ipu_writes = metrics.IpuWrites;
 574
 575	gpu_metrics->average_socket_power = metrics.SocketPower;
 576	gpu_metrics->average_ipu_power = metrics.IpuPower;
 577	gpu_metrics->average_apu_power = metrics.ApuPower;
 578	gpu_metrics->average_gfx_power = metrics.GfxPower;
 579	gpu_metrics->average_dgpu_power = metrics.dGpuPower;
 580	gpu_metrics->average_all_core_power = metrics.AllCorePower;
 581	gpu_metrics->average_sys_power = metrics.Psys;
 582	memcpy(&gpu_metrics->average_core_power[0],
 583		&metrics.CorePower[0],
 584		sizeof(uint16_t) * 16);
 585
 586	gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
 587	gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
 588	gpu_metrics->average_vpeclk_frequency = metrics.VpeclkFrequency;
 589	gpu_metrics->average_fclk_frequency = metrics.FclkFrequency;
 590	gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
 591	gpu_metrics->average_ipuclk_frequency = metrics.IpuclkFrequency;
 592	gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
 593	gpu_metrics->average_mpipu_frequency = metrics.MpipuclkFrequency;
 594
 595	memcpy(&gpu_metrics->current_coreclk[0],
 596		&metrics.CoreFrequency[0],
 597		sizeof(uint16_t) * 16);
 598	gpu_metrics->current_core_maxfreq = metrics.InfrastructureCpuMaxFreq;
 599	gpu_metrics->current_gfx_maxfreq = metrics.InfrastructureGfxMaxFreq;
 600
 601	gpu_metrics->throttle_residency_prochot = metrics.ThrottleResidency_PROCHOT;
 602	gpu_metrics->throttle_residency_spl = metrics.ThrottleResidency_SPL;
 603	gpu_metrics->throttle_residency_fppt = metrics.ThrottleResidency_FPPT;
 604	gpu_metrics->throttle_residency_sppt = metrics.ThrottleResidency_SPPT;
 605	gpu_metrics->throttle_residency_thm_core = metrics.ThrottleResidency_THM_CORE;
 606	gpu_metrics->throttle_residency_thm_gfx = metrics.ThrottleResidency_THM_GFX;
 607	gpu_metrics->throttle_residency_thm_soc = metrics.ThrottleResidency_THM_SOC;
 608
 609	gpu_metrics->time_filter_alphavalue = metrics.FilterAlphaValue;
 610	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
 611
 612	*table = (void *)gpu_metrics;
 613
 614	return sizeof(struct gpu_metrics_v3_0);
 615}
 616
 617static int smu_v14_0_0_mode2_reset(struct smu_context *smu)
 618{
 619	int ret;
 620
 621	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset,
 622					       SMU_RESET_MODE_2, NULL);
 623
 624	if (ret)
 625		dev_err(smu->adev->dev, "Failed to mode2 reset!\n");
 626
 627	return ret;
 628}
 629
 630static int smu_v14_0_1_get_dpm_freq_by_index(struct smu_context *smu,
 631						enum smu_clk_type clk_type,
 632						uint32_t dpm_level,
 633						uint32_t *freq)
 634{
 635	DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table;
 636
 637	if (!clk_table || clk_type >= SMU_CLK_COUNT)
 638		return -EINVAL;
 639
 640	switch (clk_type) {
 641	case SMU_SOCCLK:
 642		if (dpm_level >= clk_table->NumSocClkLevelsEnabled)
 643			return -EINVAL;
 644		*freq = clk_table->SocClocks[dpm_level];
 645		break;
 646	case SMU_VCLK:
 647		if (dpm_level >= clk_table->Vcn0ClkLevelsEnabled)
 648			return -EINVAL;
 649		*freq = clk_table->VClocks0[dpm_level];
 650		break;
 651	case SMU_DCLK:
 652		if (dpm_level >= clk_table->Vcn0ClkLevelsEnabled)
 653			return -EINVAL;
 654		*freq = clk_table->DClocks0[dpm_level];
 655		break;
 656	case SMU_VCLK1:
 657		if (dpm_level >= clk_table->Vcn1ClkLevelsEnabled)
 658			return -EINVAL;
 659		*freq = clk_table->VClocks1[dpm_level];
 660		break;
 661	case SMU_DCLK1:
 662		if (dpm_level >= clk_table->Vcn1ClkLevelsEnabled)
 663			return -EINVAL;
 664		*freq = clk_table->DClocks1[dpm_level];
 665		break;
 666	case SMU_UCLK:
 667	case SMU_MCLK:
 668		if (dpm_level >= clk_table->NumMemPstatesEnabled)
 669			return -EINVAL;
 670		*freq = clk_table->MemPstateTable[dpm_level].MemClk;
 671		break;
 672	case SMU_FCLK:
 673		if (dpm_level >= clk_table->NumFclkLevelsEnabled)
 674			return -EINVAL;
 675		*freq = clk_table->FclkClocks_Freq[dpm_level];
 676		break;
 677	default:
 678		return -EINVAL;
 679	}
 680
 681	return 0;
 682}
 683
 684static int smu_v14_0_0_get_dpm_freq_by_index(struct smu_context *smu,
 685						enum smu_clk_type clk_type,
 686						uint32_t dpm_level,
 687						uint32_t *freq)
 688{
 689	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
 690
 691	if (!clk_table || clk_type >= SMU_CLK_COUNT)
 692		return -EINVAL;
 693
 694	switch (clk_type) {
 695	case SMU_SOCCLK:
 696		if (dpm_level >= clk_table->NumSocClkLevelsEnabled)
 697			return -EINVAL;
 698		*freq = clk_table->SocClocks[dpm_level];
 699		break;
 700	case SMU_VCLK:
 701		if (dpm_level >= clk_table->VcnClkLevelsEnabled)
 702			return -EINVAL;
 703		*freq = clk_table->VClocks[dpm_level];
 704		break;
 705	case SMU_DCLK:
 706		if (dpm_level >= clk_table->VcnClkLevelsEnabled)
 707			return -EINVAL;
 708		*freq = clk_table->DClocks[dpm_level];
 709		break;
 710	case SMU_UCLK:
 711	case SMU_MCLK:
 712		if (dpm_level >= clk_table->NumMemPstatesEnabled)
 713			return -EINVAL;
 714		*freq = clk_table->MemPstateTable[dpm_level].MemClk;
 715		break;
 716	case SMU_FCLK:
 717		if (dpm_level >= clk_table->NumFclkLevelsEnabled)
 718			return -EINVAL;
 719		*freq = clk_table->FclkClocks_Freq[dpm_level];
 720		break;
 721	default:
 722		return -EINVAL;
 723	}
 724
 725	return 0;
 726}
 727
 728static int smu_v14_0_common_get_dpm_freq_by_index(struct smu_context *smu,
 729						enum smu_clk_type clk_type,
 730						uint32_t dpm_level,
 731						uint32_t *freq)
 732{
 733	if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
 734		smu_v14_0_1_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq);
 735	else if (clk_type != SMU_VCLK1 && clk_type != SMU_DCLK1)
 736		smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq);
 737
 738	return 0;
 739}
 740
 741static bool smu_v14_0_0_clk_dpm_is_enabled(struct smu_context *smu,
 742						enum smu_clk_type clk_type)
 743{
 744	enum smu_feature_mask feature_id = 0;
 745
 746	switch (clk_type) {
 747	case SMU_MCLK:
 748	case SMU_UCLK:
 749	case SMU_FCLK:
 750		feature_id = SMU_FEATURE_DPM_FCLK_BIT;
 751		break;
 752	case SMU_GFXCLK:
 753	case SMU_SCLK:
 754		feature_id = SMU_FEATURE_DPM_GFXCLK_BIT;
 755		break;
 756	case SMU_SOCCLK:
 757		feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
 758		break;
 759	case SMU_VCLK:
 760	case SMU_DCLK:
 761	case SMU_VCLK1:
 762	case SMU_DCLK1:
 763		feature_id = SMU_FEATURE_VCN_DPM_BIT;
 764		break;
 765	default:
 766		return true;
 767	}
 768
 769	return smu_cmn_feature_is_enabled(smu, feature_id);
 770}
 771
 772static int smu_v14_0_1_get_dpm_ultimate_freq(struct smu_context *smu,
 773							enum smu_clk_type clk_type,
 774							uint32_t *min,
 775							uint32_t *max)
 776{
 777	DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table;
 778	uint32_t clock_limit;
 779	uint32_t max_dpm_level, min_dpm_level;
 780	int ret = 0;
 781
 782	if (!smu_v14_0_0_clk_dpm_is_enabled(smu, clk_type)) {
 783		switch (clk_type) {
 784		case SMU_MCLK:
 785		case SMU_UCLK:
 786			clock_limit = smu->smu_table.boot_values.uclk;
 787			break;
 788		case SMU_FCLK:
 789			clock_limit = smu->smu_table.boot_values.fclk;
 790			break;
 791		case SMU_GFXCLK:
 792		case SMU_SCLK:
 793			clock_limit = smu->smu_table.boot_values.gfxclk;
 794			break;
 795		case SMU_SOCCLK:
 796			clock_limit = smu->smu_table.boot_values.socclk;
 797			break;
 798		case SMU_VCLK:
 799		case SMU_VCLK1:
 800			clock_limit = smu->smu_table.boot_values.vclk;
 801			break;
 802		case SMU_DCLK:
 803		case SMU_DCLK1:
 804			clock_limit = smu->smu_table.boot_values.dclk;
 805			break;
 806		default:
 807			clock_limit = 0;
 808			break;
 809		}
 810
 811		/* clock in Mhz unit */
 812		if (min)
 813			*min = clock_limit / 100;
 814		if (max)
 815			*max = clock_limit / 100;
 816
 817		return 0;
 818	}
 819
 820	if (max) {
 821		switch (clk_type) {
 822		case SMU_GFXCLK:
 823		case SMU_SCLK:
 824			*max = clk_table->MaxGfxClk;
 825			break;
 826		case SMU_MCLK:
 827		case SMU_UCLK:
 828			max_dpm_level = 0;
 829			break;
 830		case SMU_FCLK:
 831			max_dpm_level = clk_table->NumFclkLevelsEnabled - 1;
 832			break;
 833		case SMU_SOCCLK:
 834			max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1;
 835			break;
 836		case SMU_VCLK:
 837		case SMU_DCLK:
 838			max_dpm_level = clk_table->Vcn0ClkLevelsEnabled - 1;
 839			break;
 840		case SMU_VCLK1:
 841		case SMU_DCLK1:
 842			max_dpm_level = clk_table->Vcn1ClkLevelsEnabled - 1;
 843			break;
 844		default:
 845			ret = -EINVAL;
 846			goto failed;
 847		}
 848
 849		if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) {
 850			ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max);
 851			if (ret)
 852				goto failed;
 853		}
 854	}
 855
 856	if (min) {
 857		switch (clk_type) {
 858		case SMU_GFXCLK:
 859		case SMU_SCLK:
 860			*min = clk_table->MinGfxClk;
 861			break;
 862		case SMU_MCLK:
 863		case SMU_UCLK:
 864			min_dpm_level = clk_table->NumMemPstatesEnabled - 1;
 865			break;
 866		case SMU_FCLK:
 867			min_dpm_level = 0;
 868			break;
 869		case SMU_SOCCLK:
 870			min_dpm_level = 0;
 871			break;
 872		case SMU_VCLK:
 873		case SMU_DCLK:
 874		case SMU_VCLK1:
 875		case SMU_DCLK1:
 876			min_dpm_level = 0;
 877			break;
 878		default:
 879			ret = -EINVAL;
 880			goto failed;
 881		}
 882
 883		if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) {
 884			ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min);
 885			if (ret)
 886				goto failed;
 887		}
 888	}
 889
 890failed:
 891	return ret;
 892}
 893
 894static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu,
 895							enum smu_clk_type clk_type,
 896							uint32_t *min,
 897							uint32_t *max)
 898{
 899	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
 900	uint32_t clock_limit;
 901	uint32_t max_dpm_level, min_dpm_level;
 902	int ret = 0;
 903
 904	if (!smu_v14_0_0_clk_dpm_is_enabled(smu, clk_type)) {
 905		switch (clk_type) {
 906		case SMU_MCLK:
 907		case SMU_UCLK:
 908			clock_limit = smu->smu_table.boot_values.uclk;
 909			break;
 910		case SMU_FCLK:
 911			clock_limit = smu->smu_table.boot_values.fclk;
 912			break;
 913		case SMU_GFXCLK:
 914		case SMU_SCLK:
 915			clock_limit = smu->smu_table.boot_values.gfxclk;
 916			break;
 917		case SMU_SOCCLK:
 918			clock_limit = smu->smu_table.boot_values.socclk;
 919			break;
 920		case SMU_VCLK:
 921			clock_limit = smu->smu_table.boot_values.vclk;
 922			break;
 923		case SMU_DCLK:
 924			clock_limit = smu->smu_table.boot_values.dclk;
 925			break;
 926		default:
 927			clock_limit = 0;
 928			break;
 929		}
 930
 931		/* clock in Mhz unit */
 932		if (min)
 933			*min = clock_limit / 100;
 934		if (max)
 935			*max = clock_limit / 100;
 936
 937		return 0;
 938	}
 939
 940	if (max) {
 941		switch (clk_type) {
 942		case SMU_GFXCLK:
 943		case SMU_SCLK:
 944			*max = clk_table->MaxGfxClk;
 945			break;
 946		case SMU_MCLK:
 947		case SMU_UCLK:
 948			max_dpm_level = 0;
 949			break;
 950		case SMU_FCLK:
 951			max_dpm_level = clk_table->NumFclkLevelsEnabled - 1;
 952			break;
 953		case SMU_SOCCLK:
 954			max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1;
 955			break;
 956		case SMU_VCLK:
 957		case SMU_DCLK:
 958			max_dpm_level = clk_table->VcnClkLevelsEnabled - 1;
 959			break;
 960		default:
 961			ret = -EINVAL;
 962			goto failed;
 963		}
 964
 965		if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) {
 966			ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max);
 967			if (ret)
 968				goto failed;
 969		}
 970	}
 971
 972	if (min) {
 973		switch (clk_type) {
 974		case SMU_GFXCLK:
 975		case SMU_SCLK:
 976			*min = clk_table->MinGfxClk;
 977			break;
 978		case SMU_MCLK:
 979		case SMU_UCLK:
 980			min_dpm_level = clk_table->NumMemPstatesEnabled - 1;
 981			break;
 982		case SMU_FCLK:
 983			min_dpm_level = 0;
 984			break;
 985		case SMU_SOCCLK:
 986			min_dpm_level = 0;
 987			break;
 988		case SMU_VCLK:
 989		case SMU_DCLK:
 990			min_dpm_level = 0;
 991			break;
 992		default:
 993			ret = -EINVAL;
 994			goto failed;
 995		}
 996
 997		if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) {
 998			ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min);
 999			if (ret)
1000				goto failed;
1001		}
1002	}
1003
1004failed:
1005	return ret;
1006}
1007
1008static int smu_v14_0_common_get_dpm_ultimate_freq(struct smu_context *smu,
1009							enum smu_clk_type clk_type,
1010							uint32_t *min,
1011							uint32_t *max)
1012{
1013	if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
1014		smu_v14_0_1_get_dpm_ultimate_freq(smu, clk_type, min, max);
1015	else if (clk_type != SMU_VCLK1 && clk_type != SMU_DCLK1)
1016		smu_v14_0_0_get_dpm_ultimate_freq(smu, clk_type, min, max);
1017
1018	return 0;
1019}
1020
1021static int smu_v14_0_0_get_current_clk_freq(struct smu_context *smu,
1022					    enum smu_clk_type clk_type,
1023					    uint32_t *value)
1024{
1025	MetricsMember_t member_type;
1026
1027	switch (clk_type) {
1028	case SMU_SOCCLK:
1029		member_type = METRICS_AVERAGE_SOCCLK;
1030		break;
1031	case SMU_VCLK:
1032		member_type = METRICS_AVERAGE_VCLK;
1033		break;
1034	case SMU_VCLK1:
1035		member_type = METRICS_AVERAGE_VCLK1;
1036		break;
1037	case SMU_DCLK:
1038		member_type = METRICS_AVERAGE_DCLK;
1039		break;
1040	case SMU_DCLK1:
1041		member_type = METRICS_AVERAGE_DCLK1;
1042		break;
1043	case SMU_MCLK:
1044		member_type = METRICS_AVERAGE_UCLK;
1045		break;
1046	case SMU_FCLK:
1047		member_type = METRICS_AVERAGE_FCLK;
1048		break;
1049	case SMU_GFXCLK:
1050	case SMU_SCLK:
1051		member_type = METRICS_AVERAGE_GFXCLK;
1052		break;
1053	default:
1054		return -EINVAL;
1055	}
1056
1057	return smu_v14_0_0_get_smu_metrics_data(smu, member_type, value);
1058}
1059
1060static int smu_v14_0_1_get_dpm_level_count(struct smu_context *smu,
1061					   enum smu_clk_type clk_type,
1062					   uint32_t *count)
1063{
1064	DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table;
1065
1066	switch (clk_type) {
1067	case SMU_SOCCLK:
1068		*count = clk_table->NumSocClkLevelsEnabled;
1069		break;
1070	case SMU_VCLK:
1071	case SMU_DCLK:
1072		*count = clk_table->Vcn0ClkLevelsEnabled;
1073		break;
1074	case SMU_VCLK1:
1075	case SMU_DCLK1:
1076		*count = clk_table->Vcn1ClkLevelsEnabled;
1077		break;
1078	case SMU_MCLK:
1079		*count = clk_table->NumMemPstatesEnabled;
1080		break;
1081	case SMU_FCLK:
1082		*count = clk_table->NumFclkLevelsEnabled;
1083		break;
1084	default:
1085		break;
1086	}
1087
1088	return 0;
1089}
1090
1091static int smu_v14_0_0_get_dpm_level_count(struct smu_context *smu,
1092					   enum smu_clk_type clk_type,
1093					   uint32_t *count)
1094{
1095	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
1096
1097	switch (clk_type) {
1098	case SMU_SOCCLK:
1099		*count = clk_table->NumSocClkLevelsEnabled;
1100		break;
1101	case SMU_VCLK:
1102		*count = clk_table->VcnClkLevelsEnabled;
1103		break;
1104	case SMU_DCLK:
1105		*count = clk_table->VcnClkLevelsEnabled;
1106		break;
1107	case SMU_MCLK:
1108		*count = clk_table->NumMemPstatesEnabled;
1109		break;
1110	case SMU_FCLK:
1111		*count = clk_table->NumFclkLevelsEnabled;
1112		break;
1113	default:
1114		break;
1115	}
1116
1117	return 0;
1118}
1119
1120static int smu_v14_0_common_get_dpm_level_count(struct smu_context *smu,
1121					   enum smu_clk_type clk_type,
1122					   uint32_t *count)
1123{
1124	if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
1125		smu_v14_0_1_get_dpm_level_count(smu, clk_type, count);
1126	else if (clk_type != SMU_VCLK1 && clk_type != SMU_DCLK1)
1127		smu_v14_0_0_get_dpm_level_count(smu, clk_type, count);
1128
1129	return 0;
1130}
1131
1132static int smu_v14_0_0_print_clk_levels(struct smu_context *smu,
1133					enum smu_clk_type clk_type, char *buf)
1134{
1135	int i, idx, ret = 0, size = 0, start_offset = 0;
1136	uint32_t cur_value = 0, value = 0, count = 0;
1137	uint32_t min, max;
1138
1139	smu_cmn_get_sysfs_buf(&buf, &size);
1140	start_offset = size;
1141
1142	switch (clk_type) {
1143	case SMU_OD_SCLK:
1144		size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
1145		size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
1146		(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
1147		size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
1148		(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
1149		break;
1150	case SMU_OD_RANGE:
1151		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1152		size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
1153				      smu->gfx_default_hard_min_freq,
1154				      smu->gfx_default_soft_max_freq);
1155		break;
1156	case SMU_SOCCLK:
1157	case SMU_VCLK:
1158	case SMU_DCLK:
1159	case SMU_VCLK1:
1160	case SMU_DCLK1:
1161	case SMU_MCLK:
1162	case SMU_FCLK:
1163		ret = smu_v14_0_0_get_current_clk_freq(smu, clk_type, &cur_value);
1164		if (ret)
1165			break;
1166
1167		ret = smu_v14_0_common_get_dpm_level_count(smu, clk_type, &count);
1168		if (ret)
1169			break;
1170
1171		for (i = 0; i < count; i++) {
1172			idx = (clk_type == SMU_MCLK) ? (count - i - 1) : i;
1173			ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, idx, &value);
1174			if (ret)
1175				break;
1176
1177			size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
1178					      cur_value == value ? "*" : "");
1179		}
1180		break;
1181	case SMU_GFXCLK:
1182	case SMU_SCLK:
1183		ret = smu_v14_0_0_get_current_clk_freq(smu, clk_type, &cur_value);
1184		if (ret)
1185			break;
1186		min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
1187		max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
1188		if (cur_value  == max)
1189			i = 2;
1190		else if (cur_value == min)
1191			i = 0;
1192		else
1193			i = 1;
1194		size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
1195				      i == 0 ? "*" : "");
1196		size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
1197				      i == 1 ? cur_value : 1100, /* UMD PSTATE GFXCLK 1100 */
1198				      i == 1 ? "*" : "");
1199		size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
1200				      i == 2 ? "*" : "");
1201		break;
1202	default:
1203		break;
1204	}
1205
1206	return size - start_offset;
1207}
1208
1209static int smu_v14_0_0_set_soft_freq_limited_range(struct smu_context *smu,
1210						   enum smu_clk_type clk_type,
1211						   u32 min,
1212						   u32 max,
1213						   bool __always_unused automatic)
1214{
1215	enum smu_message_type msg_set_min = SMU_MSG_MAX_COUNT;
1216	enum smu_message_type msg_set_max = SMU_MSG_MAX_COUNT;
1217	int ret = -EINVAL;
1218
1219	if (!smu_v14_0_0_clk_dpm_is_enabled(smu, clk_type))
1220		return -EINVAL;
1221
1222	switch (clk_type) {
1223	case SMU_GFXCLK:
1224	case SMU_SCLK:
1225		msg_set_min = SMU_MSG_SetHardMinGfxClk;
1226		msg_set_max = SMU_MSG_SetSoftMaxGfxClk;
1227		break;
1228	case SMU_FCLK:
1229		msg_set_min = SMU_MSG_SetHardMinFclkByFreq;
1230		msg_set_max = SMU_MSG_SetSoftMaxFclkByFreq;
1231		break;
1232	case SMU_SOCCLK:
1233		msg_set_min = SMU_MSG_SetHardMinSocclkByFreq;
1234		msg_set_max = SMU_MSG_SetSoftMaxSocclkByFreq;
1235		break;
1236	case SMU_VCLK:
1237	case SMU_DCLK:
1238		msg_set_min = SMU_MSG_SetHardMinVcn0;
1239		msg_set_max = SMU_MSG_SetSoftMaxVcn0;
1240		break;
1241	case SMU_VCLK1:
1242	case SMU_DCLK1:
1243		msg_set_min = SMU_MSG_SetHardMinVcn1;
1244		msg_set_max = SMU_MSG_SetSoftMaxVcn1;
1245		break;
1246	case SMU_ISPICLK:
1247		msg_set_min = SMU_MSG_SetHardMinIspiclkByFreq;
1248		break;
1249	case SMU_ISPXCLK:
1250		msg_set_min = SMU_MSG_SetHardMinIspxclkByFreq;
1251		break;
1252	default:
1253		return -EINVAL;
1254	}
1255
1256	if (min && msg_set_min != SMU_MSG_MAX_COUNT)
1257		ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min, NULL);
1258
1259	if (max && msg_set_max != SMU_MSG_MAX_COUNT)
1260		ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max, NULL);
1261
1262	return ret;
1263}
1264
1265static int smu_v14_0_0_force_clk_levels(struct smu_context *smu,
1266					enum smu_clk_type clk_type,
1267					uint32_t mask)
1268{
1269	uint32_t soft_min_level = 0, soft_max_level = 0;
1270	uint32_t min_freq = 0, max_freq = 0;
1271	int ret = 0;
1272
1273	soft_min_level = mask ? (ffs(mask) - 1) : 0;
1274	soft_max_level = mask ? (fls(mask) - 1) : 0;
1275
1276	switch (clk_type) {
1277	case SMU_SOCCLK:
1278	case SMU_FCLK:
1279	case SMU_VCLK:
1280	case SMU_DCLK:
1281	case SMU_VCLK1:
1282	case SMU_DCLK1:
1283		ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
1284		if (ret)
1285			break;
1286
1287		ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
1288		if (ret)
1289			break;
1290
1291		ret = smu_v14_0_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
1292		break;
1293	default:
1294		ret = -EINVAL;
1295		break;
1296	}
1297
1298	return ret;
1299}
1300
1301static int smu_v14_0_common_get_dpm_profile_freq(struct smu_context *smu,
1302					enum amd_dpm_forced_level level,
1303					enum smu_clk_type clk_type,
1304					uint32_t *min_clk,
1305					uint32_t *max_clk)
1306{
1307	uint32_t clk_limit = 0;
1308	int ret = 0;
1309
1310	switch (clk_type) {
1311	case SMU_GFXCLK:
1312	case SMU_SCLK:
1313		if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 4))
1314			clk_limit = SMU_14_0_4_UMD_PSTATE_GFXCLK;
1315		else
1316			clk_limit = SMU_14_0_0_UMD_PSTATE_GFXCLK;
1317		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
1318			smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &clk_limit);
1319		else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
1320			smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &clk_limit, NULL);
1321		break;
1322	case SMU_SOCCLK:
1323		if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 4))
1324			clk_limit = SMU_14_0_4_UMD_PSTATE_SOCCLK;
1325		else
1326			clk_limit = SMU_14_0_0_UMD_PSTATE_SOCCLK;
1327		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
1328			smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &clk_limit);
1329		break;
1330	case SMU_FCLK:
1331		if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 4))
1332			smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit);
1333		else
1334			clk_limit = SMU_14_0_0_UMD_PSTATE_FCLK;
1335		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
1336			smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit);
1337		else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
1338			smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &clk_limit, NULL);
1339		break;
1340	case SMU_VCLK:
1341		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &clk_limit);
1342		break;
1343	case SMU_VCLK1:
1344		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK1, NULL, &clk_limit);
1345		break;
1346	case SMU_DCLK:
1347		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &clk_limit);
1348		break;
1349	case SMU_DCLK1:
1350		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK1, NULL, &clk_limit);
1351		break;
1352	default:
1353		ret = -EINVAL;
1354		break;
1355	}
1356	*min_clk = *max_clk = clk_limit;
1357	return ret;
1358}
1359
1360static int smu_v14_0_common_set_performance_level(struct smu_context *smu,
1361					     enum amd_dpm_forced_level level)
1362{
1363	struct amdgpu_device *adev = smu->adev;
1364	uint32_t sclk_min = 0, sclk_max = 0;
1365	uint32_t fclk_min = 0, fclk_max = 0;
1366	uint32_t socclk_min = 0, socclk_max = 0;
1367	uint32_t vclk_min = 0, vclk_max = 0;
1368	uint32_t dclk_min = 0, dclk_max = 0;
1369	uint32_t vclk1_min = 0, vclk1_max = 0;
1370	uint32_t dclk1_min = 0, dclk1_max = 0;
1371	int ret = 0;
1372
1373	switch (level) {
1374	case AMD_DPM_FORCED_LEVEL_HIGH:
1375		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
1376		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max);
1377		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max);
1378		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_max);
1379		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_max);
1380		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK1, NULL, &vclk1_max);
1381		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK1, NULL, &dclk1_max);
1382		sclk_min = sclk_max;
1383		fclk_min = fclk_max;
1384		socclk_min = socclk_max;
1385		vclk_min = vclk_max;
1386		dclk_min = dclk_max;
1387		vclk1_min = vclk1_max;
1388		dclk1_min = dclk1_max;
1389		break;
1390	case AMD_DPM_FORCED_LEVEL_LOW:
1391		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
1392		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL);
1393		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL);
1394		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, NULL);
1395		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, NULL);
1396		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK1, &vclk1_min, NULL);
1397		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK1, &dclk1_min, NULL);
1398		sclk_max = sclk_min;
1399		fclk_max = fclk_min;
1400		socclk_max = socclk_min;
1401		vclk_max = vclk_min;
1402		dclk_max = dclk_min;
1403		vclk1_max = vclk1_min;
1404		dclk1_max = dclk1_min;
1405		break;
1406	case AMD_DPM_FORCED_LEVEL_AUTO:
1407		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
1408		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max);
1409		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max);
1410		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, &vclk_max);
1411		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, &dclk_max);
1412		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_VCLK1, &vclk1_min, &vclk1_max);
1413		smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_DCLK1, &dclk1_min, &dclk1_max);
1414		break;
1415	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1416	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1417	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1418	case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1419		smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_SCLK, &sclk_min, &sclk_max);
1420		smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_FCLK, &fclk_min, &fclk_max);
1421		smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_SOCCLK, &socclk_min, &socclk_max);
1422		smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_VCLK, &vclk_min, &vclk_max);
1423		smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_DCLK, &dclk_min, &dclk_max);
1424		smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_VCLK1, &vclk1_min, &vclk1_max);
1425		smu_v14_0_common_get_dpm_profile_freq(smu, level, SMU_DCLK1, &dclk1_min, &dclk1_max);
1426		break;
1427	case AMD_DPM_FORCED_LEVEL_MANUAL:
1428	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1429		return 0;
1430	default:
1431		dev_err(adev->dev, "Invalid performance level %d\n", level);
1432		return -EINVAL;
1433	}
1434
1435	if (sclk_min && sclk_max) {
1436		ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
1437							      SMU_SCLK,
1438							      sclk_min,
1439							      sclk_max,
1440							      false);
1441		if (ret)
1442			return ret;
1443
1444		smu->gfx_actual_hard_min_freq = sclk_min;
1445		smu->gfx_actual_soft_max_freq = sclk_max;
1446	}
1447
1448	if (fclk_min && fclk_max) {
1449		ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
1450							      SMU_FCLK,
1451							      fclk_min,
1452							      fclk_max,
1453							      false);
1454		if (ret)
1455			return ret;
1456	}
1457
1458	if (socclk_min && socclk_max) {
1459		ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
1460							      SMU_SOCCLK,
1461							      socclk_min,
1462							      socclk_max,
1463							      false);
1464		if (ret)
1465			return ret;
1466	}
1467
1468	if (vclk_min && vclk_max) {
1469		ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
1470							      SMU_VCLK,
1471							      vclk_min,
1472							      vclk_max,
1473							      false);
1474		if (ret)
1475			return ret;
1476	}
1477
1478	if (vclk1_min && vclk1_max) {
1479		ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
1480							      SMU_VCLK1,
1481							      vclk1_min,
1482							      vclk1_max,
1483							      false);
1484		if (ret)
1485			return ret;
1486	}
1487
1488	if (dclk_min && dclk_max) {
1489		ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
1490							      SMU_DCLK,
1491							      dclk_min,
1492							      dclk_max,
1493							      false);
1494		if (ret)
1495			return ret;
1496	}
1497
1498	if (dclk1_min && dclk1_max) {
1499		ret = smu_v14_0_0_set_soft_freq_limited_range(smu,
1500							      SMU_DCLK1,
1501							      dclk1_min,
1502							      dclk1_max,
1503							      false);
1504		if (ret)
1505			return ret;
1506	}
1507
1508	return ret;
1509}
1510
1511static int smu_v14_0_1_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
1512{
1513	DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table;
1514
1515	smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
1516	smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
1517	if (smu->gfx_actual_hard_min_freq == 0)
1518		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1519	if (smu->gfx_actual_soft_max_freq == 0)
1520		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1521	return 0;
1522}
1523
1524static int smu_v14_0_0_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
1525{
1526	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
1527
1528	smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
1529	smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
1530	if (smu->gfx_actual_hard_min_freq == 0)
1531		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1532	if (smu->gfx_actual_soft_max_freq == 0)
1533		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1534
1535	return 0;
1536}
1537
1538static int smu_v14_0_common_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
1539{
1540	if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
1541		smu_v14_0_1_set_fine_grain_gfx_freq_parameters(smu);
1542	else
1543		smu_v14_0_0_set_fine_grain_gfx_freq_parameters(smu);
1544
1545	return 0;
1546}
1547
1548static int smu_v14_0_0_set_vpe_enable(struct smu_context *smu,
1549				      bool enable)
1550{
1551	return smu_cmn_send_smc_msg_with_param(smu, enable ?
1552					       SMU_MSG_PowerUpVpe : SMU_MSG_PowerDownVpe,
1553					       0, NULL);
1554}
1555
1556static int smu_v14_0_0_set_isp_enable(struct smu_context *smu,
1557				      bool enable)
1558{
1559	return smu_cmn_send_smc_msg_with_param(smu, enable ?
1560				      SMU_MSG_PowerUpIspByTile : SMU_MSG_PowerDownIspByTile,
1561				      ISP_ALL_TILES_MASK, NULL);
1562}
1563
1564static int smu_v14_0_0_set_umsch_mm_enable(struct smu_context *smu,
1565			      bool enable)
1566{
1567	return smu_cmn_send_smc_msg_with_param(smu, enable ?
1568					       SMU_MSG_PowerUpUmsch : SMU_MSG_PowerDownUmsch,
1569					       0, NULL);
1570}
1571
1572static int smu_14_0_1_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table)
1573{
1574	DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table;
1575	uint8_t idx;
1576
1577	/* Only the Clock information of SOC and VPE is copied to provide VPE DPM settings for use. */
1578	for (idx = 0; idx < NUM_SOCCLK_DPM_LEVELS; idx++) {
1579		clock_table->SocClocks[idx].Freq = (idx < clk_table->NumSocClkLevelsEnabled) ? clk_table->SocClocks[idx]:0;
1580		clock_table->SocClocks[idx].Vol = 0;
1581	}
1582
1583	for (idx = 0; idx < NUM_VPE_DPM_LEVELS; idx++) {
1584		clock_table->VPEClocks[idx].Freq = (idx < clk_table->VpeClkLevelsEnabled) ? clk_table->VPEClocks[idx]:0;
1585		clock_table->VPEClocks[idx].Vol = 0;
1586	}
1587
1588	return 0;
1589}
1590
1591static int smu_14_0_0_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table)
1592{
1593	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
1594	uint8_t idx;
1595
1596	/* Only the Clock information of SOC and VPE is copied to provide VPE DPM settings for use. */
1597	for (idx = 0; idx < NUM_SOCCLK_DPM_LEVELS; idx++) {
1598		clock_table->SocClocks[idx].Freq = (idx < clk_table->NumSocClkLevelsEnabled) ? clk_table->SocClocks[idx]:0;
1599		clock_table->SocClocks[idx].Vol = 0;
1600	}
1601
1602	for (idx = 0; idx < NUM_VPE_DPM_LEVELS; idx++) {
1603		clock_table->VPEClocks[idx].Freq = (idx < clk_table->VpeClkLevelsEnabled) ? clk_table->VPEClocks[idx]:0;
1604		clock_table->VPEClocks[idx].Vol = 0;
1605	}
1606
1607	return 0;
1608}
1609
1610static int smu_v14_0_common_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table)
1611{
1612	if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
1613		smu_14_0_1_get_dpm_table(smu, clock_table);
1614	else
1615		smu_14_0_0_get_dpm_table(smu, clock_table);
1616
1617	return 0;
1618}
1619
1620static int smu_v14_0_1_init_mall_power_gating(struct smu_context *smu, enum smu_mall_pg_config pg_config)
1621{
1622	struct amdgpu_device *adev = smu->adev;
1623	int ret = 0;
1624
1625	if (pg_config == SMU_MALL_PG_CONFIG_PMFW_CONTROL) {
1626		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerController,
1627								SMU_MALL_PMFW_CONTROL, NULL);
1628		if (ret) {
1629			dev_err(adev->dev, "Init MALL PMFW CONTROL Failure\n");
1630			return ret;
1631		}
1632	} else {
1633		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerController,
1634								SMU_MALL_DRIVER_CONTROL, NULL);
1635		if (ret) {
1636			dev_err(adev->dev, "Init MALL Driver CONTROL Failure\n");
1637			return ret;
1638		}
1639
1640		if (pg_config == SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_ON) {
1641			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerState,
1642									SMU_MALL_EXIT_PG, NULL);
1643			if (ret) {
1644				dev_err(adev->dev, "EXIT MALL PG Failure\n");
1645				return ret;
1646			}
1647		} else if (pg_config == SMU_MALL_PG_CONFIG_DRIVER_CONTROL_ALWAYS_OFF) {
1648			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_MALLPowerState,
1649									SMU_MALL_ENTER_PG, NULL);
1650			if (ret) {
1651				dev_err(adev->dev, "Enter MALL PG Failure\n");
1652				return ret;
1653			}
1654		}
1655	}
1656
1657	return ret;
1658}
1659
1660static int smu_v14_0_common_set_mall_enable(struct smu_context *smu)
1661{
1662	enum smu_mall_pg_config pg_config = SMU_MALL_PG_CONFIG_DEFAULT;
1663	int ret = 0;
1664
1665	if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1))
1666		ret = smu_v14_0_1_init_mall_power_gating(smu, pg_config);
1667
1668	return ret;
1669}
1670
1671static int smu_v14_0_0_restore_user_od_settings(struct smu_context *smu)
1672{
1673	int ret;
1674
1675	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
1676					      smu->gfx_actual_hard_min_freq,
1677					      NULL);
1678	if (ret) {
1679		dev_err(smu->adev->dev, "Failed to restore hard min sclk!\n");
1680		return ret;
1681	}
1682
1683	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
1684					      smu->gfx_actual_soft_max_freq,
1685					      NULL);
1686	if (ret) {
1687		dev_err(smu->adev->dev, "Failed to restore soft max sclk!\n");
1688		return ret;
1689	}
1690
1691	return 0;
1692}
1693
1694static const struct pptable_funcs smu_v14_0_0_ppt_funcs = {
1695	.check_fw_status = smu_v14_0_check_fw_status,
1696	.check_fw_version = smu_v14_0_check_fw_version,
1697	.init_smc_tables = smu_v14_0_0_init_smc_tables,
1698	.fini_smc_tables = smu_v14_0_0_fini_smc_tables,
1699	.get_vbios_bootup_values = smu_v14_0_get_vbios_bootup_values,
1700	.system_features_control = smu_v14_0_0_system_features_control,
1701	.send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
1702	.send_smc_msg = smu_cmn_send_smc_msg,
1703	.dpm_set_vcn_enable = smu_v14_0_set_vcn_enable,
1704	.dpm_set_jpeg_enable = smu_v14_0_set_jpeg_enable,
1705	.set_default_dpm_table = smu_v14_0_set_default_dpm_tables,
1706	.read_sensor = smu_v14_0_0_read_sensor,
1707	.is_dpm_running = smu_v14_0_0_is_dpm_running,
1708	.set_watermarks_table = smu_v14_0_0_set_watermarks_table,
1709	.get_gpu_metrics = smu_v14_0_0_get_gpu_metrics,
1710	.get_enabled_mask = smu_cmn_get_enabled_mask,
1711	.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
1712	.set_driver_table_location = smu_v14_0_set_driver_table_location,
1713	.gfx_off_control = smu_v14_0_gfx_off_control,
1714	.mode2_reset = smu_v14_0_0_mode2_reset,
1715	.get_dpm_ultimate_freq = smu_v14_0_common_get_dpm_ultimate_freq,
1716	.set_soft_freq_limited_range = smu_v14_0_0_set_soft_freq_limited_range,
1717	.restore_user_od_settings = smu_v14_0_0_restore_user_od_settings,
1718	.od_edit_dpm_table = smu_v14_0_od_edit_dpm_table,
1719	.print_clk_levels = smu_v14_0_0_print_clk_levels,
1720	.force_clk_levels = smu_v14_0_0_force_clk_levels,
1721	.set_performance_level = smu_v14_0_common_set_performance_level,
1722	.set_fine_grain_gfx_freq_parameters = smu_v14_0_common_set_fine_grain_gfx_freq_parameters,
1723	.set_gfx_power_up_by_imu = smu_v14_0_set_gfx_power_up_by_imu,
1724	.dpm_set_vpe_enable = smu_v14_0_0_set_vpe_enable,
1725	.dpm_set_isp_enable = smu_v14_0_0_set_isp_enable,
1726	.dpm_set_umsch_mm_enable = smu_v14_0_0_set_umsch_mm_enable,
1727	.get_dpm_clock_table = smu_v14_0_common_get_dpm_table,
1728	.set_mall_enable = smu_v14_0_common_set_mall_enable,
1729};
1730
1731static void smu_v14_0_0_set_smu_mailbox_registers(struct smu_context *smu)
1732{
1733	struct amdgpu_device *adev = smu->adev;
1734
1735	smu->param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_82);
1736	smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_66);
1737	smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
1738}
1739
1740void smu_v14_0_0_set_ppt_funcs(struct smu_context *smu)
1741{
1742
1743	smu->ppt_funcs = &smu_v14_0_0_ppt_funcs;
1744	smu->message_map = smu_v14_0_0_message_map;
1745	smu->feature_map = smu_v14_0_0_feature_mask_map;
1746	smu->table_map = smu_v14_0_0_table_map;
1747	smu->is_apu = true;
1748
1749	smu_v14_0_0_set_smu_mailbox_registers(smu);
1750}
~/ Read-only file preview.