vega10_smumgr.c 18.2 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 86
{
	uint32_t reg;

87
	if (!vega10_is_smc_ram_running(hwmgr))
88
		return -EINVAL;
89 90 91 92

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

93
	phm_wait_for_register_unequal(hwmgr, reg,
94 95
			0, MP1_C2PMSG_90__CONTENT_MASK);

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

99 100 101 102 103 104
/*
 * 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.
 */
105
int vega10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
106 107 108 109
		uint16_t msg)
{
	uint32_t reg;

110
	if (!vega10_is_smc_ram_running(hwmgr))
111
		return -EINVAL;
112 113 114

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

	return 0;
}

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

130
	if (!vega10_is_smc_ram_running(hwmgr))
131
		return -EINVAL;
132

133
	vega10_wait_for_response(hwmgr);
134 135 136

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

139
	vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
140

141
	if (vega10_wait_for_response(hwmgr) != 1)
142
		pr_err("Failed to send message: 0x%x\n", msg);
143 144 145 146

	return 0;
}

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

159
	if (!vega10_is_smc_ram_running(hwmgr))
160
		return -EINVAL;
161

162
	vega10_wait_for_response(hwmgr);
163 164 165

	reg = soc15_get_register_offset(MP1_HWID, 0,
			mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
166
	cgs_write_register(hwmgr->device, reg, 0);
167 168 169

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

172
	vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
173

174
	if (vega10_wait_for_response(hwmgr) != 1)
175
		pr_err("Failed to send message: 0x%x\n", msg);
176 177 178 179 180

	return 0;
}


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

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

197
	return vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
198 199
}

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

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

213
	*arg = cgs_read_register(hwmgr->device, reg);
214 215 216 217

	return 0;
}

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

	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
230
			"Invalid SMU Table ID!", return -EINVAL);
231
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
232
			"Invalid SMU Table version!", return -EINVAL);
233
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
234
			"Invalid SMU Table Length!", return -EINVAL);
235
	PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
236 237
			PPSMC_MSG_SetDriverDramAddrHigh,
			priv->smu_tables.entry[table_id].table_addr_high) == 0,
238
			"[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
239
	PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
240 241 242
			PPSMC_MSG_SetDriverDramAddrLow,
			priv->smu_tables.entry[table_id].table_addr_low) == 0,
			"[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
243
			return -EINVAL);
244
	PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
245 246 247
			PPSMC_MSG_TransferTableSmu2Dram,
			priv->smu_tables.entry[table_id].table_id) == 0,
			"[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
248
			return -EINVAL);
249 250 251 252 253 254 255

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

	return 0;
}

256 257
/*
 * Copy table from Driver FB into SMC
258
 * @param   hwmgr    the address of the HW manager
259 260
 * @param   table_id    the table to copy from
 */
261
int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
262 263 264
		uint8_t *table, int16_t table_id)
{
	struct vega10_smumgr *priv =
265
			(struct vega10_smumgr *)(hwmgr->smu_backend);
266 267

	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
268
			"Invalid SMU Table ID!", return -EINVAL);
269
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
270
			"Invalid SMU Table version!", return -EINVAL);
271
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
272
			"Invalid SMU Table Length!", return -EINVAL);
273 274 275 276

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

277
	PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
278 279 280
			PPSMC_MSG_SetDriverDramAddrHigh,
			priv->smu_tables.entry[table_id].table_addr_high) == 0,
			"[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
281
			return -EINVAL;);
282
	PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
283 284 285
			PPSMC_MSG_SetDriverDramAddrLow,
			priv->smu_tables.entry[table_id].table_addr_low) == 0,
			"[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
286
			return -EINVAL);
287
	PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
288 289 290
			PPSMC_MSG_TransferTableDram2Smu,
			priv->smu_tables.entry[table_id].table_id) == 0,
			"[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
291
			return -EINVAL);
292 293 294 295

	return 0;
}

296
int vega10_save_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table)
297 298 299
{
	PP_ASSERT_WITH_CODE(avfs_table,
			"No access to SMC AVFS Table",
300
			return -EINVAL);
301

302
	return vega10_copy_table_from_smc(hwmgr, avfs_table, AVFSTABLE);
303 304
}

305
int vega10_restore_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table)
306 307 308
{
	PP_ASSERT_WITH_CODE(avfs_table,
			"No access to SMC AVFS Table",
309
			return -EINVAL);
310

311
	return vega10_copy_table_to_smc(hwmgr, avfs_table, AVFSTABLE);
312 313
}

314
int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
315 316 317 318 319
		bool enable, uint32_t feature_mask)
{
	int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
			PPSMC_MSG_DisableSmuFeatures;

320
	return vega10_send_msg_to_smc_with_parameter(hwmgr,
321 322 323
			msg, feature_mask);
}

324
int vega10_get_smc_features(struct pp_hwmgr *hwmgr,
325 326
		uint32_t *features_enabled)
{
327 328 329
	if (features_enabled == NULL)
		return -EINVAL;

330
	if (!vega10_send_msg_to_smc(hwmgr,
331
			PPSMC_MSG_GetEnabledSmuFeatures)) {
332
		vega10_read_arg_from_smc(hwmgr, features_enabled);
333
		return 0;
334 335
	}

336
	return -EINVAL;
337 338
}

339
int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
340 341
{
	struct vega10_smumgr *priv =
342
			(struct vega10_smumgr *)(hwmgr->smu_backend);
343 344 345

	if (priv->smu_tables.entry[TOOLSTABLE].table_addr_high ||
			priv->smu_tables.entry[TOOLSTABLE].table_addr_low) {
346
		if (!vega10_send_msg_to_smc_with_parameter(hwmgr,
347 348
				PPSMC_MSG_SetToolsDramAddrHigh,
				priv->smu_tables.entry[TOOLSTABLE].table_addr_high))
349
			vega10_send_msg_to_smc_with_parameter(hwmgr,
350 351 352 353 354 355
					PPSMC_MSG_SetToolsDramAddrLow,
					priv->smu_tables.entry[TOOLSTABLE].table_addr_low);
	}
	return 0;
}

356
static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
357 358
{
	uint32_t smc_driver_if_version;
359 360 361
	struct cgs_system_info sys_info = {0};
	uint32_t dev_id;
	uint32_t rev_id;
362

363
	PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(hwmgr,
364 365
			PPSMC_MSG_GetDriverIfVersion),
			"Attempt to get SMC IF Version Number Failed!",
366
			return -EINVAL);
367
	vega10_read_arg_from_smc(hwmgr, &smc_driver_if_version);
368

369 370
	sys_info.size = sizeof(struct cgs_system_info);
	sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV;
371
	cgs_query_system_info(hwmgr->device, &sys_info);
372 373 374 375
	dev_id = (uint32_t)sys_info.value;

	sys_info.size = sizeof(struct cgs_system_info);
	sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV;
376
	cgs_query_system_info(hwmgr->device, &sys_info);
377 378 379 380 381 382 383
	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) {
384 385
			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);
386 387
			return -EINVAL;
		}
388
	}
389 390 391 392

	return 0;
}

393
static int vega10_smu_init(struct pp_hwmgr *hwmgr)
394 395 396 397 398 399 400 401
{
	struct vega10_smumgr *priv;
	uint64_t mc_addr;
	void *kaddr = NULL;
	unsigned long handle, tools_size;
	int ret;
	struct cgs_firmware_info info = {0};

402
	ret = cgs_get_firmware_info(hwmgr->device,
403 404 405 406 407 408 409 410 411 412
				    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;

413
	hwmgr->smu_backend = priv;
414 415

	/* allocate space for pptable */
416
	smu_allocate_memory(hwmgr->device,
417 418 419 420 421 422 423 424 425
			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.",
426
			kfree(hwmgr->smu_backend);
427
			cgs_free_gpu_mem(hwmgr->device,
428
			(cgs_handle_t)handle);
429
			return -EINVAL);
430 431 432 433 434 435 436 437 438 439 440 441

	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 */
442
	smu_allocate_memory(hwmgr->device,
443 444 445 446 447 448 449 450 451
			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.",
452
			kfree(hwmgr->smu_backend);
453
			cgs_free_gpu_mem(hwmgr->device,
454
			(cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
455
			cgs_free_gpu_mem(hwmgr->device,
456
			(cgs_handle_t)handle);
457
			return -EINVAL);
458 459 460 461 462 463 464 465 466 467 468 469

	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 */
470
	smu_allocate_memory(hwmgr->device,
471 472 473 474 475 476 477 478 479
			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.",
480
			kfree(hwmgr->smu_backend);
481
			cgs_free_gpu_mem(hwmgr->device,
482
			(cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
483
			cgs_free_gpu_mem(hwmgr->device,
484
			(cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
485
			cgs_free_gpu_mem(hwmgr->device,
486
			(cgs_handle_t)handle);
487
			return -EINVAL);
488 489 490 491 492 493 494 495 496 497 498

	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;

499
	tools_size = 0x19000;
500
	if (tools_size) {
501
		smu_allocate_memory(hwmgr->device,
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
				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;
		}
	}

522
	/* allocate space for AVFS Fuse table */
523
	smu_allocate_memory(hwmgr->device,
524 525 526 527 528 529 530 531 532
			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.",
533
			kfree(hwmgr->smu_backend);
534
			cgs_free_gpu_mem(hwmgr->device,
535
			(cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
536
			cgs_free_gpu_mem(hwmgr->device,
537
			(cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
538
			cgs_free_gpu_mem(hwmgr->device,
539
			(cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
540
			cgs_free_gpu_mem(hwmgr->device,
541
			(cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
542
			cgs_free_gpu_mem(hwmgr->device,
543
			(cgs_handle_t)handle);
544
			return -EINVAL);
545 546 547 548 549 550 551 552 553 554 555

	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;

556 557 558
	return 0;
}

559
static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
560 561
{
	struct vega10_smumgr *priv =
562
			(struct vega10_smumgr *)(hwmgr->smu_backend);
563 564

	if (priv) {
565
		cgs_free_gpu_mem(hwmgr->device,
566
				(cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
567
		cgs_free_gpu_mem(hwmgr->device,
568
				(cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
569
		cgs_free_gpu_mem(hwmgr->device,
570 571
				(cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
		if (priv->smu_tables.entry[TOOLSTABLE].table)
572
			cgs_free_gpu_mem(hwmgr->device,
573
					(cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
574
		cgs_free_gpu_mem(hwmgr->device,
575
				(cgs_handle_t)priv->smu_tables.entry[AVFSFUSETABLE].handle);
576 577
		kfree(hwmgr->smu_backend);
		hwmgr->smu_backend = NULL;
578 579 580 581
	}
	return 0;
}

582
static int vega10_start_smu(struct pp_hwmgr *hwmgr)
583
{
584
	PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
585
			"Failed to verify SMC interface!",
586
			return -EINVAL);
587

588
	vega10_set_tools_address(hwmgr);
589

590 591 592 593 594 595 596 597 598 599 600 601 602
	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,
};