vega10_smumgr.c 17.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
/*
 * Copyright 2016 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include "smumgr.h"
#include "vega10_inc.h"
#include "pp_soc15.h"
#include "vega10_smumgr.h"
#include "vega10_ppsmc.h"
#include "smu9_driver_if.h"

#include "ppatomctrl.h"
#include "pp_debug.h"
#include "smu_ucode_xfer_vi.h"
#include "smu7_smumgr.h"

#define AVFS_EN_MSB		1568
#define AVFS_EN_LSB		1568

#define VOLTAGE_SCALE	4

/* Microcode file is stored in this buffer */
#define BUFFER_SIZE                 80000
#define MAX_STRING_SIZE             15
#define BUFFER_SIZETWO              131072 /* 128 *1024 */

/* MP Apertures */
#define MP0_Public                  0x03800000
#define MP0_SRAM                    0x03900000
#define MP1_Public                  0x03b00000
#define MP1_SRAM                    0x03c00004

#define smnMP1_FIRMWARE_FLAGS                                                                           0x3010028
#define smnMP0_FW_INTF                                                                                  0x3010104
#define smnMP1_PUB_CTRL                                                                                 0x3010b14

56
static bool vega10_is_smc_ram_running(struct pp_hwmgr *hwmgr)
57 58 59 60 61 62
{
	uint32_t mp1_fw_flags, reg;

	reg = soc15_get_register_offset(NBIF_HWID, 0,
			mmPCIE_INDEX2_BASE_IDX, mmPCIE_INDEX2);

63
	cgs_write_register(hwmgr->device, reg,
64 65 66 67 68
			(MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff)));

	reg = soc15_get_register_offset(NBIF_HWID, 0,
			mmPCIE_DATA2_BASE_IDX, mmPCIE_DATA2);

69
	mp1_fw_flags = cgs_read_register(hwmgr->device, reg);
70 71 72 73 74 75 76

	if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK)
		return true;

	return false;
}

77 78 79 80 81 82
/*
 * Check if SMC has responded to previous message.
 *
 * @param    smumgr  the address of the powerplay hardware manager.
 * @return   TRUE    SMC has responded, FALSE otherwise.
 */
83
static uint32_t vega10_wait_for_response(struct pp_hwmgr *hwmgr)
84 85
{
	uint32_t reg;
86
	uint32_t ret;
87 88 89 90

	reg = soc15_get_register_offset(MP1_HWID, 0,
			mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);

91
	ret = phm_wait_for_register_unequal(hwmgr, reg,
92 93
			0, MP1_C2PMSG_90__CONTENT_MASK);

94 95 96
	if (ret)
		pr_err("No response from smu\n");

97
	return cgs_read_register(hwmgr->device, reg);
98 99
}

100 101 102 103 104 105
/*
 * Send a message to the SMC, and do not wait for its response.
 * @param    smumgr  the address of the powerplay hardware manager.
 * @param    msg the message to send.
 * @return   Always return 0.
 */
106
int vega10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
107 108 109 110 111 112
		uint16_t msg)
{
	uint32_t reg;

	reg = soc15_get_register_offset(MP1_HWID, 0,
			mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
113
	cgs_write_register(hwmgr->device, reg, msg);
114 115 116 117

	return 0;
}

118 119
/*
 * Send a message to the SMC, and wait for its response.
120
 * @param    hwmgr  the address of the powerplay hardware manager.
121 122 123
 * @param    msg the message to send.
 * @return   Always return 0.
 */
124
int vega10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
125 126
{
	uint32_t reg;
127
	uint32_t ret;
128

129
	vega10_wait_for_response(hwmgr);
130 131 132

	reg = soc15_get_register_offset(MP1_HWID, 0,
			mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
133
	cgs_write_register(hwmgr->device, reg, 0);
134

135
	vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
136

137 138 139
	ret = vega10_wait_for_response(hwmgr);
	if (ret != 1)
		pr_err("Failed to send message: 0x%x, ret value: 0x%x\n", msg, ret);
140 141 142 143

	return 0;
}

144
/*
145
 * Send a message to the SMC with parameter
146
 * @param    hwmgr:  the address of the powerplay hardware manager.
147 148
 * @param    msg: the message to send.
 * @param    parameter: the parameter to send
149
 * @return   Always return 0.
150
 */
151
int vega10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
152 153 154
		uint16_t msg, uint32_t parameter)
{
	uint32_t reg;
155
	uint32_t ret;
156

157
	vega10_wait_for_response(hwmgr);
158 159 160

	reg = soc15_get_register_offset(MP1_HWID, 0,
			mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
161
	cgs_write_register(hwmgr->device, reg, 0);
162 163 164

	reg = soc15_get_register_offset(MP1_HWID, 0,
			mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
165
	cgs_write_register(hwmgr->device, reg, parameter);
166

167
	vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
168

169 170 171
	ret = vega10_wait_for_response(hwmgr);
	if (ret != 1)
		pr_err("Failed to send message: 0x%x, ret value: 0x%x\n", msg, ret);
172 173 174 175 176

	return 0;
}


177 178
/*
 * Send a message to the SMC with parameter, do not wait for response
179
 * @param    hwmgr:  the address of the powerplay hardware manager.
180 181 182 183
 * @param    msg: the message to send.
 * @param    parameter: the parameter to send
 * @return   The response that came from the SMC.
 */
184
int vega10_send_msg_to_smc_with_parameter_without_waiting(
185
		struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter)
186 187 188 189 190
{
	uint32_t reg;

	reg = soc15_get_register_offset(MP1_HWID, 0,
			mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
191
	cgs_write_register(hwmgr->device, reg, parameter);
192

193
	return vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
194 195
}

196 197
/*
 * Retrieve an argument from SMC.
198
 * @param    hwmgr  the address of the powerplay hardware manager.
199 200 201
 * @param    arg     pointer to store the argument from SMC.
 * @return   Always return 0.
 */
202
int vega10_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg)
203 204 205 206 207 208
{
	uint32_t reg;

	reg = soc15_get_register_offset(MP1_HWID, 0,
			mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);

209
	*arg = cgs_read_register(hwmgr->device, reg);
210 211 212 213

	return 0;
}

214 215
/*
 * Copy table from SMC into driver FB
216
 * @param   hwmgr    the address of the HW manager
217 218
 * @param   table_id    the driver's table ID to copy from
 */
219
int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
220 221 222
		uint8_t *table, int16_t table_id)
{
	struct vega10_smumgr *priv =
223
			(struct vega10_smumgr *)(hwmgr->smu_backend);
224 225

	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
226
			"Invalid SMU Table ID!", return -EINVAL);
227
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
228
			"Invalid SMU Table version!", return -EINVAL);
229
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
230
			"Invalid SMU Table Length!", return -EINVAL);
231
	vega10_send_msg_to_smc_with_parameter(hwmgr,
232
			PPSMC_MSG_SetDriverDramAddrHigh,
233 234
			priv->smu_tables.entry[table_id].table_addr_high);
	vega10_send_msg_to_smc_with_parameter(hwmgr,
235
			PPSMC_MSG_SetDriverDramAddrLow,
236 237
			priv->smu_tables.entry[table_id].table_addr_low);
	vega10_send_msg_to_smc_with_parameter(hwmgr,
238
			PPSMC_MSG_TransferTableSmu2Dram,
239
			priv->smu_tables.entry[table_id].table_id);
240 241 242 243 244 245 246

	memcpy(table, priv->smu_tables.entry[table_id].table,
			priv->smu_tables.entry[table_id].size);

	return 0;
}

247 248
/*
 * Copy table from Driver FB into SMC
249
 * @param   hwmgr    the address of the HW manager
250 251
 * @param   table_id    the table to copy from
 */
252
int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
253 254 255
		uint8_t *table, int16_t table_id)
{
	struct vega10_smumgr *priv =
256
			(struct vega10_smumgr *)(hwmgr->smu_backend);
257 258

	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
259
			"Invalid SMU Table ID!", return -EINVAL);
260
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
261
			"Invalid SMU Table version!", return -EINVAL);
262
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
263
			"Invalid SMU Table Length!", return -EINVAL);
264 265 266 267

	memcpy(priv->smu_tables.entry[table_id].table, table,
			priv->smu_tables.entry[table_id].size);

268
	vega10_send_msg_to_smc_with_parameter(hwmgr,
269
			PPSMC_MSG_SetDriverDramAddrHigh,
270 271
			priv->smu_tables.entry[table_id].table_addr_high);
	vega10_send_msg_to_smc_with_parameter(hwmgr,
272
			PPSMC_MSG_SetDriverDramAddrLow,
273 274
			priv->smu_tables.entry[table_id].table_addr_low);
	vega10_send_msg_to_smc_with_parameter(hwmgr,
275
			PPSMC_MSG_TransferTableDram2Smu,
276
			priv->smu_tables.entry[table_id].table_id);
277 278 279 280

	return 0;
}

281
int vega10_save_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table)
282 283 284
{
	PP_ASSERT_WITH_CODE(avfs_table,
			"No access to SMC AVFS Table",
285
			return -EINVAL);
286

287
	return vega10_copy_table_from_smc(hwmgr, avfs_table, AVFSTABLE);
288 289
}

290
int vega10_restore_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table)
291 292 293
{
	PP_ASSERT_WITH_CODE(avfs_table,
			"No access to SMC AVFS Table",
294
			return -EINVAL);
295

296
	return vega10_copy_table_to_smc(hwmgr, avfs_table, AVFSTABLE);
297 298
}

299
int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
300 301 302 303 304
		bool enable, uint32_t feature_mask)
{
	int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
			PPSMC_MSG_DisableSmuFeatures;

305
	return vega10_send_msg_to_smc_with_parameter(hwmgr,
306 307 308
			msg, feature_mask);
}

309
int vega10_get_smc_features(struct pp_hwmgr *hwmgr,
310 311
		uint32_t *features_enabled)
{
312 313 314
	if (features_enabled == NULL)
		return -EINVAL;

315 316 317
	vega10_send_msg_to_smc(hwmgr, PPSMC_MSG_GetEnabledSmuFeatures);
	vega10_read_arg_from_smc(hwmgr, features_enabled);
	return 0;
318 319
}

320
int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
321 322
{
	struct vega10_smumgr *priv =
323
			(struct vega10_smumgr *)(hwmgr->smu_backend);
324 325 326

	if (priv->smu_tables.entry[TOOLSTABLE].table_addr_high ||
			priv->smu_tables.entry[TOOLSTABLE].table_addr_low) {
327
		vega10_send_msg_to_smc_with_parameter(hwmgr,
328
				PPSMC_MSG_SetToolsDramAddrHigh,
329 330 331 332
				priv->smu_tables.entry[TOOLSTABLE].table_addr_high);
		vega10_send_msg_to_smc_with_parameter(hwmgr,
				PPSMC_MSG_SetToolsDramAddrLow,
				priv->smu_tables.entry[TOOLSTABLE].table_addr_low);
333 334 335 336
	}
	return 0;
}

337
static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
338 339
{
	uint32_t smc_driver_if_version;
340 341 342
	struct cgs_system_info sys_info = {0};
	uint32_t dev_id;
	uint32_t rev_id;
343

344
	PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(hwmgr,
345 346
			PPSMC_MSG_GetDriverIfVersion),
			"Attempt to get SMC IF Version Number Failed!",
347
			return -EINVAL);
348
	vega10_read_arg_from_smc(hwmgr, &smc_driver_if_version);
349

350 351
	sys_info.size = sizeof(struct cgs_system_info);
	sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV;
352
	cgs_query_system_info(hwmgr->device, &sys_info);
353 354 355 356
	dev_id = (uint32_t)sys_info.value;

	sys_info.size = sizeof(struct cgs_system_info);
	sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV;
357
	cgs_query_system_info(hwmgr->device, &sys_info);
358 359 360 361 362 363 364
	rev_id = (uint32_t)sys_info.value;

	if (!((dev_id == 0x687f) &&
		((rev_id == 0xc0) ||
		(rev_id == 0xc1) ||
		(rev_id == 0xc3)))) {
		if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
365 366
			pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n",
			       smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
367 368
			return -EINVAL;
		}
369
	}
370 371 372 373

	return 0;
}

374
static int vega10_smu_init(struct pp_hwmgr *hwmgr)
375 376 377 378 379 380 381 382
{
	struct vega10_smumgr *priv;
	uint64_t mc_addr;
	void *kaddr = NULL;
	unsigned long handle, tools_size;
	int ret;
	struct cgs_firmware_info info = {0};

383
	ret = cgs_get_firmware_info(hwmgr->device,
384 385 386 387 388 389 390 391 392 393
				    smu7_convert_fw_type_to_cgs(UCODE_ID_SMU),
				    &info);
	if (ret || !info.kptr)
		return -EINVAL;

	priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL);

	if (!priv)
		return -ENOMEM;

394
	hwmgr->smu_backend = priv;
395 396

	/* allocate space for pptable */
397
	smu_allocate_memory(hwmgr->device,
398 399 400 401 402 403 404 405 406
			sizeof(PPTable_t),
			CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
			PAGE_SIZE,
			&mc_addr,
			&kaddr,
			&handle);

	PP_ASSERT_WITH_CODE(kaddr,
			"[vega10_smu_init] Out of memory for pptable.",
407
			kfree(hwmgr->smu_backend);
408
			cgs_free_gpu_mem(hwmgr->device,
409
			(cgs_handle_t)handle);
410
			return -EINVAL);
411 412 413 414 415 416 417 418 419 420 421 422

	priv->smu_tables.entry[PPTABLE].version = 0x01;
	priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
	priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
	priv->smu_tables.entry[PPTABLE].table_addr_high =
			smu_upper_32_bits(mc_addr);
	priv->smu_tables.entry[PPTABLE].table_addr_low =
			smu_lower_32_bits(mc_addr);
	priv->smu_tables.entry[PPTABLE].table = kaddr;
	priv->smu_tables.entry[PPTABLE].handle = handle;

	/* allocate space for watermarks table */
423
	smu_allocate_memory(hwmgr->device,
424 425 426 427 428 429 430 431 432
			sizeof(Watermarks_t),
			CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
			PAGE_SIZE,
			&mc_addr,
			&kaddr,
			&handle);

	PP_ASSERT_WITH_CODE(kaddr,
			"[vega10_smu_init] Out of memory for wmtable.",
433
			kfree(hwmgr->smu_backend);
434
			cgs_free_gpu_mem(hwmgr->device,
435
			(cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
436
			cgs_free_gpu_mem(hwmgr->device,
437
			(cgs_handle_t)handle);
438
			return -EINVAL);
439 440 441 442 443 444 445 446 447 448 449 450

	priv->smu_tables.entry[WMTABLE].version = 0x01;
	priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
	priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
	priv->smu_tables.entry[WMTABLE].table_addr_high =
			smu_upper_32_bits(mc_addr);
	priv->smu_tables.entry[WMTABLE].table_addr_low =
			smu_lower_32_bits(mc_addr);
	priv->smu_tables.entry[WMTABLE].table = kaddr;
	priv->smu_tables.entry[WMTABLE].handle = handle;

	/* allocate space for AVFS table */
451
	smu_allocate_memory(hwmgr->device,
452 453 454 455 456 457 458 459 460
			sizeof(AvfsTable_t),
			CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
			PAGE_SIZE,
			&mc_addr,
			&kaddr,
			&handle);

	PP_ASSERT_WITH_CODE(kaddr,
			"[vega10_smu_init] Out of memory for avfs table.",
461
			kfree(hwmgr->smu_backend);
462
			cgs_free_gpu_mem(hwmgr->device,
463
			(cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
464
			cgs_free_gpu_mem(hwmgr->device,
465
			(cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
466
			cgs_free_gpu_mem(hwmgr->device,
467
			(cgs_handle_t)handle);
468
			return -EINVAL);
469 470 471 472 473 474 475 476 477 478 479

	priv->smu_tables.entry[AVFSTABLE].version = 0x01;
	priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
	priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
	priv->smu_tables.entry[AVFSTABLE].table_addr_high =
			smu_upper_32_bits(mc_addr);
	priv->smu_tables.entry[AVFSTABLE].table_addr_low =
			smu_lower_32_bits(mc_addr);
	priv->smu_tables.entry[AVFSTABLE].table = kaddr;
	priv->smu_tables.entry[AVFSTABLE].handle = handle;

480
	tools_size = 0x19000;
481
	if (tools_size) {
482
		smu_allocate_memory(hwmgr->device,
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
				tools_size,
				CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
				PAGE_SIZE,
				&mc_addr,
				&kaddr,
				&handle);

		if (kaddr) {
			priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
			priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
			priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
			priv->smu_tables.entry[TOOLSTABLE].table_addr_high =
					smu_upper_32_bits(mc_addr);
			priv->smu_tables.entry[TOOLSTABLE].table_addr_low =
					smu_lower_32_bits(mc_addr);
			priv->smu_tables.entry[TOOLSTABLE].table = kaddr;
			priv->smu_tables.entry[TOOLSTABLE].handle = handle;
		}
	}

503
	/* allocate space for AVFS Fuse table */
504
	smu_allocate_memory(hwmgr->device,
505 506 507 508 509 510 511 512 513
			sizeof(AvfsFuseOverride_t),
			CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
			PAGE_SIZE,
			&mc_addr,
			&kaddr,
			&handle);

	PP_ASSERT_WITH_CODE(kaddr,
			"[vega10_smu_init] Out of memory for avfs fuse table.",
514
			kfree(hwmgr->smu_backend);
515
			cgs_free_gpu_mem(hwmgr->device,
516
			(cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
517
			cgs_free_gpu_mem(hwmgr->device,
518
			(cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
519
			cgs_free_gpu_mem(hwmgr->device,
520
			(cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
521
			cgs_free_gpu_mem(hwmgr->device,
522
			(cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
523
			cgs_free_gpu_mem(hwmgr->device,
524
			(cgs_handle_t)handle);
525
			return -EINVAL);
526 527 528 529 530 531 532 533 534 535 536

	priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
	priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
	priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
	priv->smu_tables.entry[AVFSFUSETABLE].table_addr_high =
			smu_upper_32_bits(mc_addr);
	priv->smu_tables.entry[AVFSFUSETABLE].table_addr_low =
			smu_lower_32_bits(mc_addr);
	priv->smu_tables.entry[AVFSFUSETABLE].table = kaddr;
	priv->smu_tables.entry[AVFSFUSETABLE].handle = handle;

537 538 539
	return 0;
}

540
static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
541 542
{
	struct vega10_smumgr *priv =
543
			(struct vega10_smumgr *)(hwmgr->smu_backend);
544 545

	if (priv) {
546
		cgs_free_gpu_mem(hwmgr->device,
547
				(cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
548
		cgs_free_gpu_mem(hwmgr->device,
549
				(cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
550
		cgs_free_gpu_mem(hwmgr->device,
551 552
				(cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
		if (priv->smu_tables.entry[TOOLSTABLE].table)
553
			cgs_free_gpu_mem(hwmgr->device,
554
					(cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
555
		cgs_free_gpu_mem(hwmgr->device,
556
				(cgs_handle_t)priv->smu_tables.entry[AVFSFUSETABLE].handle);
557 558
		kfree(hwmgr->smu_backend);
		hwmgr->smu_backend = NULL;
559 560 561 562
	}
	return 0;
}

563
static int vega10_start_smu(struct pp_hwmgr *hwmgr)
564
{
565 566 567
	if (!vega10_is_smc_ram_running(hwmgr))
		return -EINVAL;

568
	PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
569
			"Failed to verify SMC interface!",
570
			return -EINVAL);
571

572
	vega10_set_tools_address(hwmgr);
573

574 575 576 577 578 579 580 581 582 583 584 585 586
	return 0;
}

const struct pp_smumgr_func vega10_smu_funcs = {
	.smu_init = &vega10_smu_init,
	.smu_fini = &vega10_smu_fini,
	.start_smu = &vega10_start_smu,
	.request_smu_load_specific_fw = NULL,
	.send_msg_to_smc = &vega10_send_msg_to_smc,
	.send_msg_to_smc_with_parameter = &vega10_send_msg_to_smc_with_parameter,
	.download_pptable_settings = NULL,
	.upload_pptable_settings = NULL,
};