vega10_smumgr.c 14.9 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
/*
 * 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"
28
#include "vega10_hwmgr.h"
29 30 31 32
#include "vega10_ppsmc.h"
#include "smu9_driver_if.h"
#include "ppatomctrl.h"
#include "pp_debug.h"
33

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

#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

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

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

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

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

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

	if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK)
		return true;

	return false;
}

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

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

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

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

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
static int vega10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
106 107 108 109 110 111
		uint16_t msg)
{
	uint32_t reg;

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

	return 0;
}

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

128
	vega10_wait_for_response(hwmgr);
129 130 131

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

134
	vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
135

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

	return 0;
}

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

156
	vega10_wait_for_response(hwmgr);
157 158 159

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

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

166
	vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
167

168 169
	ret = vega10_wait_for_response(hwmgr);
	if (ret != 1)
170
		pr_err("Failed message: 0x%x, input parameter: 0x%x, error code: 0x%x\n", msg, parameter, ret);
171 172 173 174

	return 0;
}

175
static int vega10_get_argument(struct pp_hwmgr *hwmgr)
176 177 178 179 180 181
{
	uint32_t reg;

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

182
	return cgs_read_register(hwmgr->device, reg);
183 184
}

185
static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
186 187
		uint8_t *table, int16_t table_id)
{
188
	struct vega10_smumgr *priv = hwmgr->smu_backend;
189 190

	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
191
			"Invalid SMU Table ID!", return -EINVAL);
192
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
193
			"Invalid SMU Table version!", return -EINVAL);
194
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
195
			"Invalid SMU Table Length!", return -EINVAL);
196
	vega10_send_msg_to_smc_with_parameter(hwmgr,
197
			PPSMC_MSG_SetDriverDramAddrHigh,
198
			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
199
	vega10_send_msg_to_smc_with_parameter(hwmgr,
200
			PPSMC_MSG_SetDriverDramAddrLow,
201
			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
202
	vega10_send_msg_to_smc_with_parameter(hwmgr,
203
			PPSMC_MSG_TransferTableSmu2Dram,
204
			priv->smu_tables.entry[table_id].table_id);
205 206 207 208 209 210 211

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

	return 0;
}

212
static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
213 214
		uint8_t *table, int16_t table_id)
{
215
	struct vega10_smumgr *priv = hwmgr->smu_backend;
216 217

	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
218
			"Invalid SMU Table ID!", return -EINVAL);
219
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
220
			"Invalid SMU Table version!", return -EINVAL);
221
	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
222
			"Invalid SMU Table Length!", return -EINVAL);
223 224 225 226

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

227
	vega10_send_msg_to_smc_with_parameter(hwmgr,
228
			PPSMC_MSG_SetDriverDramAddrHigh,
229
			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
230
	vega10_send_msg_to_smc_with_parameter(hwmgr,
231
			PPSMC_MSG_SetDriverDramAddrLow,
232
			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
233
	vega10_send_msg_to_smc_with_parameter(hwmgr,
234
			PPSMC_MSG_TransferTableDram2Smu,
235
			priv->smu_tables.entry[table_id].table_id);
236 237 238 239

	return 0;
}

240
static int vega10_get_smc_features(struct pp_hwmgr *hwmgr,
241 242
		uint32_t *features_enabled)
{
243 244 245
	if (features_enabled == NULL)
		return -EINVAL;

246
	vega10_send_msg_to_smc(hwmgr, PPSMC_MSG_GetEnabledSmuFeatures);
247 248
	*features_enabled = vega10_get_argument(hwmgr);

249
	return 0;
250 251
}

252 253 254 255 256 257 258 259 260 261 262 263
static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
{
	uint32_t features_enabled = 0;

	vega10_get_smc_features(hwmgr, &features_enabled);

	if (features_enabled & SMC_DPM_FEATURES)
		return true;
	else
		return false;
}

264
static int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
265
{
266
	struct vega10_smumgr *priv = hwmgr->smu_backend;
267

268
	if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) {
269
		vega10_send_msg_to_smc_with_parameter(hwmgr,
270
				PPSMC_MSG_SetToolsDramAddrHigh,
271
				upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr));
272 273
		vega10_send_msg_to_smc_with_parameter(hwmgr,
				PPSMC_MSG_SetToolsDramAddrLow,
274
				lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr));
275 276 277 278
	}
	return 0;
}

279
static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
280 281
{
	uint32_t smc_driver_if_version;
282
	struct amdgpu_device *adev = hwmgr->adev;
283 284
	uint32_t dev_id;
	uint32_t rev_id;
285

286
	PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(hwmgr,
287 288
			PPSMC_MSG_GetDriverIfVersion),
			"Attempt to get SMC IF Version Number Failed!",
289
			return -EINVAL);
290
	smc_driver_if_version = vega10_get_argument(hwmgr);
291

292 293
	dev_id = adev->pdev->device;
	rev_id = adev->pdev->revision;
294 295 296 297 298 299

	if (!((dev_id == 0x687f) &&
		((rev_id == 0xc0) ||
		(rev_id == 0xc1) ||
		(rev_id == 0xc3)))) {
		if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
300 301
			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);
302 303
			return -EINVAL;
		}
304
	}
305 306 307 308

	return 0;
}

309
static int vega10_smu_init(struct pp_hwmgr *hwmgr)
310 311
{
	struct vega10_smumgr *priv;
312
	unsigned long tools_size;
313 314 315
	int ret;
	struct cgs_firmware_info info = {0};

316
	ret = cgs_get_firmware_info(hwmgr->device,
317
				    CGS_UCODE_ID_SMU,
318 319 320 321 322 323 324 325 326
				    &info);
	if (ret || !info.kptr)
		return -EINVAL;

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

	if (!priv)
		return -ENOMEM;

327
	hwmgr->smu_backend = priv;
328 329

	/* allocate space for pptable */
330
	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
331 332
			sizeof(PPTable_t),
			PAGE_SIZE,
333
			AMDGPU_GEM_DOMAIN_VRAM,
334 335 336
			&priv->smu_tables.entry[PPTABLE].handle,
			&priv->smu_tables.entry[PPTABLE].mc_addr,
			&priv->smu_tables.entry[PPTABLE].table);
337
	if (ret)
338
		goto free_backend;
339 340 341 342 343 344

	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;

	/* allocate space for watermarks table */
345
	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
346 347
			sizeof(Watermarks_t),
			PAGE_SIZE,
348
			AMDGPU_GEM_DOMAIN_VRAM,
349 350 351
			&priv->smu_tables.entry[WMTABLE].handle,
			&priv->smu_tables.entry[WMTABLE].mc_addr,
			&priv->smu_tables.entry[WMTABLE].table);
352 353 354

	if (ret)
		goto err0;
355 356 357 358 359 360

	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;

	/* allocate space for AVFS table */
361
	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
362 363
			sizeof(AvfsTable_t),
			PAGE_SIZE,
364
			AMDGPU_GEM_DOMAIN_VRAM,
365 366 367
			&priv->smu_tables.entry[AVFSTABLE].handle,
			&priv->smu_tables.entry[AVFSTABLE].mc_addr,
			&priv->smu_tables.entry[AVFSTABLE].table);
368 369 370

	if (ret)
		goto err1;
371 372 373 374 375

	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;

376
	tools_size = 0x19000;
377
	if (tools_size) {
378
		ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
379 380
				tools_size,
				PAGE_SIZE,
381
				AMDGPU_GEM_DOMAIN_VRAM,
382 383 384
				&priv->smu_tables.entry[TOOLSTABLE].handle,
				&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
				&priv->smu_tables.entry[TOOLSTABLE].table);
385 386 387 388 389
		if (ret)
			goto err2;
		priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
		priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
		priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
390 391
	}

392
	/* allocate space for AVFS Fuse table */
393
	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
394 395
			sizeof(AvfsFuseOverride_t),
			PAGE_SIZE,
396
			AMDGPU_GEM_DOMAIN_VRAM,
397 398 399
			&priv->smu_tables.entry[AVFSFUSETABLE].handle,
			&priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
			&priv->smu_tables.entry[AVFSFUSETABLE].table);
400 401
	if (ret)
		goto err3;
402 403 404 405

	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;
406

407

408
	return 0;
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426

err3:
	if (priv->smu_tables.entry[TOOLSTABLE].table)
		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
				&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
				&priv->smu_tables.entry[TOOLSTABLE].table);
err2:
	amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
				&priv->smu_tables.entry[AVFSTABLE].mc_addr,
				&priv->smu_tables.entry[AVFSTABLE].table);
err1:
	amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
				&priv->smu_tables.entry[WMTABLE].mc_addr,
				&priv->smu_tables.entry[WMTABLE].table);
err0:
	amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
			&priv->smu_tables.entry[PPTABLE].mc_addr,
			&priv->smu_tables.entry[PPTABLE].table);
427 428 429
free_backend:
	kfree(hwmgr->smu_backend);

430
	return -EINVAL;
431 432
}

433
static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
434
{
435
	struct vega10_smumgr *priv = hwmgr->smu_backend;
436 437

	if (priv) {
438 439 440 441 442 443 444 445 446
		amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
				&priv->smu_tables.entry[PPTABLE].mc_addr,
				&priv->smu_tables.entry[PPTABLE].table);
		amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
					&priv->smu_tables.entry[WMTABLE].mc_addr,
					&priv->smu_tables.entry[WMTABLE].table);
		amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
					&priv->smu_tables.entry[AVFSTABLE].mc_addr,
					&priv->smu_tables.entry[AVFSTABLE].table);
447
		if (priv->smu_tables.entry[TOOLSTABLE].table)
448 449 450 451 452 453
			amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
					&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
					&priv->smu_tables.entry[TOOLSTABLE].table);
		amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle,
					&priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
					&priv->smu_tables.entry[AVFSFUSETABLE].table);
454 455
		kfree(hwmgr->smu_backend);
		hwmgr->smu_backend = NULL;
456 457 458 459
	}
	return 0;
}

460
static int vega10_start_smu(struct pp_hwmgr *hwmgr)
461
{
462 463 464
	if (!vega10_is_smc_ram_running(hwmgr))
		return -EINVAL;

465
	PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
466
			"Failed to verify SMC interface!",
467
			return -EINVAL);
468

469
	vega10_set_tools_address(hwmgr);
470

471 472 473
	return 0;
}

474 475 476 477 478 479 480 481 482 483 484 485
static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
{
	int ret;

	if (rw)
		ret = vega10_copy_table_from_smc(hwmgr, table, table_id);
	else
		ret = vega10_copy_table_to_smc(hwmgr, table, table_id);

	return ret;
}

486 487 488 489 490 491 492 493 494
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,
495
	.is_dpm_running = vega10_is_dpm_running,
496 497
	.get_argument = vega10_get_argument,
	.smc_table_manager = vega10_smc_table_manager,
498
};