amdgpu_smu.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
/*
 * Copyright 2019 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 "pp_debug.h"
#include <linux/firmware.h>
#include <drm/drmP.h>
#include "amdgpu.h"
#include "amdgpu_smu.h"
#include "soc15_common.h"
29
#include "smu_v11_0.h"
30
#include "atom.h"
31

32 33 34 35 36 37 38 39 40 41 42 43 44
int smu_get_power_num_states(struct smu_context *smu,
			     struct pp_states_info *state_info)
{
	if (!state_info)
		return -EINVAL;

	/* not support power state */
	memset(state_info, 0, sizeof(struct pp_states_info));
	state_info->nums = 0;

	return 0;
}

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
			   void *data, uint32_t *size)
{
	int ret = 0;

	switch (sensor) {
	case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
		ret = smu_feature_get_enabled_mask(smu, (uint32_t *)data, 2);
		*size = 8;
		break;
	default:
		ret = -EINVAL;
		break;
	}

	if (ret)
		*size = 0;

	return ret;
}

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
int smu_update_table(struct smu_context *smu, uint32_t table_id,
		     void *table_data, bool drv2smu)
{
	struct smu_table_context *smu_table = &smu->smu_table;
	struct smu_table *table = NULL;
	int ret = 0;

	if (!table_data || table_id >= smu_table->table_count)
		return -EINVAL;

	table = &smu_table->tables[table_id];

	if (drv2smu)
		memcpy(table->cpu_addr, table_data, table->size);

	ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetDriverDramAddrHigh,
					  upper_32_bits(table->mc_address));
	if (ret)
		return ret;
	ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetDriverDramAddrLow,
					  lower_32_bits(table->mc_address));
	if (ret)
		return ret;
	ret = smu_send_smc_msg_with_param(smu, drv2smu ?
					  SMU_MSG_TransferTableDram2Smu :
					  SMU_MSG_TransferTableSmu2Dram,
					  table_id);
	if (ret)
		return ret;

	if (!drv2smu)
		memcpy(table_data, table->cpu_addr, table->size);

	return ret;
}

102 103 104 105 106 107 108 109 110 111 112
bool is_support_sw_smu(struct amdgpu_device *adev)
{
	if (amdgpu_dpm != 1)
		return false;

	if (adev->asic_type >= CHIP_VEGA20)
		return true;

	return false;
}

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
int smu_sys_get_pp_table(struct smu_context *smu, void **table)
{
	struct smu_table_context *smu_table = &smu->smu_table;

	if (!smu_table->power_play_table && !smu_table->hardcode_pptable)
		return -EINVAL;

	if (smu_table->hardcode_pptable)
		*table = smu_table->hardcode_pptable;
	else
		*table = smu_table->power_play_table;

	return smu_table->power_play_table_size;
}

int smu_sys_set_pp_table(struct smu_context *smu,  void *buf, size_t size)
{
	struct smu_table_context *smu_table = &smu->smu_table;
	ATOM_COMMON_TABLE_HEADER *header = (ATOM_COMMON_TABLE_HEADER *)buf;
	int ret = 0;

	if (header->usStructureSize != size) {
		pr_err("pp table size not matched !\n");
		return -EIO;
	}

	mutex_lock(&smu->mutex);
	if (!smu_table->hardcode_pptable)
		smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL);
	if (!smu_table->hardcode_pptable) {
		ret = -ENOMEM;
		goto failed;
	}

	memcpy(smu_table->hardcode_pptable, buf, size);
	smu_table->power_play_table = smu_table->hardcode_pptable;
	smu_table->power_play_table_size = size;
	mutex_unlock(&smu->mutex);

	ret = smu_reset(smu);
	if (ret)
		pr_info("smu reset failed, ret = %d\n", ret);

failed:
	mutex_unlock(&smu->mutex);
	return ret;
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
int smu_feature_init_dpm(struct smu_context *smu)
{
	struct smu_feature *feature = &smu->smu_feature;
	int ret = 0;
	uint32_t unallowed_feature_mask[SMU_FEATURE_MAX/32];

	bitmap_fill(feature->allowed, SMU_FEATURE_MAX);

	ret = smu_get_unallowed_feature_mask(smu, unallowed_feature_mask,
					     SMU_FEATURE_MAX/32);
	if (ret)
		return ret;

	bitmap_andnot(feature->allowed, feature->allowed,
		      (unsigned long *)unallowed_feature_mask,
		      feature->feature_num);

	return ret;
}

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
int smu_feature_is_enabled(struct smu_context *smu, int feature_id)
{
	struct smu_feature *feature = &smu->smu_feature;
	WARN_ON(feature_id > feature->feature_num);
	return test_bit(feature_id, feature->enabled);
}

int smu_feature_set_enabled(struct smu_context *smu, int feature_id, bool enable)
{
	struct smu_feature *feature = &smu->smu_feature;
	WARN_ON(feature_id > feature->feature_num);
	if (enable)
		test_and_set_bit(feature_id, feature->enabled);
	else
		test_and_clear_bit(feature_id, feature->enabled);
	return 0;
}

int smu_feature_is_supported(struct smu_context *smu, int feature_id)
{
	struct smu_feature *feature = &smu->smu_feature;
	WARN_ON(feature_id > feature->feature_num);
	return test_bit(feature_id, feature->supported);
}

int smu_feature_set_supported(struct smu_context *smu, int feature_id,
			      bool enable)
{
	struct smu_feature *feature = &smu->smu_feature;
	WARN_ON(feature_id > feature->feature_num);
	if (enable)
		test_and_set_bit(feature_id, feature->supported);
	else
		test_and_clear_bit(feature_id, feature->supported);
	return 0;
}

218 219
static int smu_set_funcs(struct amdgpu_device *adev)
{
220 221 222 223 224 225 226 227 228 229
	struct smu_context *smu = &adev->smu;

	switch (adev->asic_type) {
	case CHIP_VEGA20:
		smu_v11_0_set_smu_funcs(smu);
		break;
	default:
		return -EINVAL;
	}

230 231 232 233 234 235 236 237 238 239 240
	return 0;
}

static int smu_early_init(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
	struct smu_context *smu = &adev->smu;

	smu->adev = adev;
	mutex_init(&smu->mutex);

241
	return smu_set_funcs(adev);
242 243
}

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
int smu_get_atom_data_table(struct smu_context *smu, uint32_t table,
			    uint16_t *size, uint8_t *frev, uint8_t *crev,
			    uint8_t **addr)
{
	struct amdgpu_device *adev = smu->adev;
	uint16_t data_start;

	if (!amdgpu_atom_parse_data_header(adev->mode_info.atom_context, table,
					   size, frev, crev, &data_start))
		return -EINVAL;

	*addr = (uint8_t *)adev->mode_info.atom_context->bios + data_start;

	return 0;
}

260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
static int smu_initialize_pptable(struct smu_context *smu)
{
	/* TODO */
	return 0;
}

static int smu_smc_table_sw_init(struct smu_context *smu)
{
	int ret;

	ret = smu_initialize_pptable(smu);
	if (ret) {
		pr_err("Failed to init smu_initialize_pptable!\n");
		return ret;
	}

276 277 278 279 280 281 282 283 284 285
	/**
	 * Create smu_table structure, and init smc tables such as
	 * TABLE_PPTABLE, TABLE_WATERMARKS, TABLE_SMU_METRICS, and etc.
	 */
	ret = smu_init_smc_tables(smu);
	if (ret) {
		pr_err("Failed to init smc tables!\n");
		return ret;
	}

286 287 288 289 290 291 292 293 294 295
	/**
	 * Create smu_power_context structure, and allocate smu_dpm_context and
	 * context size to fill the smu_power_context data.
	 */
	ret = smu_init_power(smu);
	if (ret) {
		pr_err("Failed to init smu_init_power!\n");
		return ret;
	}

296 297 298
	return 0;
}

299 300 301 302 303 304 305 306 307 308 309 310 311
static int smu_smc_table_sw_fini(struct smu_context *smu)
{
	int ret;

	ret = smu_fini_smc_tables(smu);
	if (ret) {
		pr_err("Failed to smu_fini_smc_tables!\n");
		return ret;
	}

	return 0;
}

312 313 314 315 316 317
static int smu_sw_init(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
	struct smu_context *smu = &adev->smu;
	int ret;

318
	if (!is_support_sw_smu(adev))
319 320
		return -EINVAL;

321
	smu->pool_size = adev->pm.smu_prv_buffer_size;
322 323 324 325
	smu->smu_feature.feature_num = SMU_FEATURE_MAX;
	bitmap_zero(smu->smu_feature.supported, SMU_FEATURE_MAX);
	bitmap_zero(smu->smu_feature.enabled, SMU_FEATURE_MAX);
	bitmap_zero(smu->smu_feature.allowed, SMU_FEATURE_MAX);
326

327 328 329 330 331 332
	ret = smu_init_microcode(smu);
	if (ret) {
		pr_err("Failed to load smu firmware!\n");
		return ret;
	}

333 334 335 336 337 338
	ret = smu_smc_table_sw_init(smu);
	if (ret) {
		pr_err("Failed to sw init smc table!\n");
		return ret;
	}

339 340 341 342 343 344
	return 0;
}

static int smu_sw_fini(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
345 346
	struct smu_context *smu = &adev->smu;
	int ret;
347

348
	if (!is_support_sw_smu(adev))
349 350
		return -EINVAL;

351 352 353 354 355 356
	ret = smu_smc_table_sw_fini(smu);
	if (ret) {
		pr_err("Failed to sw fini smc table!\n");
		return ret;
	}

357 358 359 360 361 362
	ret = smu_fini_power(smu);
	if (ret) {
		pr_err("Failed to init smu_fini_power!\n");
		return ret;
	}

363 364 365
	return 0;
}

366 367
static int smu_init_fb_allocations(struct smu_context *smu)
{
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
	struct amdgpu_device *adev = smu->adev;
	struct smu_table_context *smu_table = &smu->smu_table;
	struct smu_table *tables = smu_table->tables;
	uint32_t table_count = smu_table->table_count;
	uint32_t i = 0;
	int32_t ret = 0;

	if (table_count <= 0)
		return -EINVAL;

	for (i = 0 ; i < table_count; i++) {
		if (tables[i].size == 0)
			continue;
		ret = amdgpu_bo_create_kernel(adev,
					      tables[i].size,
					      tables[i].align,
					      tables[i].domain,
					      &tables[i].bo,
					      &tables[i].mc_address,
					      &tables[i].cpu_addr);
		if (ret)
			goto failed;
	}

392
	return 0;
393 394 395 396 397 398 399 400 401 402
failed:
	for (; i > 0; i--) {
		if (tables[i].size == 0)
			continue;
		amdgpu_bo_free_kernel(&tables[i].bo,
				      &tables[i].mc_address,
				      &tables[i].cpu_addr);

	}
	return ret;
403 404
}

405 406 407 408 409 410 411 412
static int smu_fini_fb_allocations(struct smu_context *smu)
{
	struct smu_table_context *smu_table = &smu->smu_table;
	struct smu_table *tables = smu_table->tables;
	uint32_t table_count = smu_table->table_count;
	uint32_t i = 0;

	if (table_count == 0 || tables == NULL)
413
		return 0;
414 415 416 417 418 419 420 421 422 423 424

	for (i = 0 ; i < table_count; i++) {
		if (tables[i].size == 0)
			continue;
		amdgpu_bo_free_kernel(&tables[i].bo,
				      &tables[i].mc_address,
				      &tables[i].cpu_addr);
	}

	return 0;
}
425

426 427 428 429
static int smu_smc_table_hw_init(struct smu_context *smu)
{
	int ret;

430 431 432 433
	ret = smu_init_display(smu);
	if (ret)
		return ret;

434 435 436 437
	ret = smu_feature_set_allowed_mask(smu);
	if (ret)
		return ret;

438 439 440 441
	ret = smu_read_pptable_from_vbios(smu);
	if (ret)
		return ret;

442 443 444 445 446
	/* get boot_values from vbios to set revision, gfxclk, and etc. */
	ret = smu_get_vbios_bootup_values(smu);
	if (ret)
		return ret;

447 448 449 450
	ret = smu_get_clk_info_from_vbios(smu);
	if (ret)
		return ret;

451 452 453 454
	/*
	 * check if the format_revision in vbios is up to pptable header
	 * version, and the structure size is not 0.
	 */
455 456 457 458
	ret = smu_get_clk_info_from_vbios(smu);
	if (ret)
		return ret;

459 460 461 462
	ret = smu_check_pptable(smu);
	if (ret)
		return ret;

463 464 465 466 467 468 469
	/*
	 * allocate vram bos to store smc table contents.
	 */
	ret = smu_init_fb_allocations(smu);
	if (ret)
		return ret;

470 471 472 473 474 475 476 477 478
	/*
	 * Parse pptable format and fill PPTable_t smc_pptable to
	 * smu_table_context structure. And read the smc_dpm_table from vbios,
	 * then fill it into smc_pptable.
	 */
	ret = smu_parse_pptable(smu);
	if (ret)
		return ret;

479 480 481 482 483 484 485 486
	/*
	 * Send msg GetDriverIfVersion to check if the return value is equal
	 * with DRIVER_IF_VERSION of smc header.
	 */
	ret = smu_check_fw_version(smu);
	if (ret)
		return ret;

487 488 489 490 491 492 493 494
	/*
	 * Copy pptable bo in the vram to smc with SMU MSGs such as
	 * SetDriverDramAddr and TransferTableDram2Smu.
	 */
	ret = smu_write_pptable(smu);
	if (ret)
		return ret;

495 496 497 498 499
	/* issue RunAfllBtc msg */
	ret = smu_run_afll_btc(smu);
	if (ret)
		return ret;

500 501 502 503
	ret = smu_feature_enable_all(smu);
	if (ret)
		return ret;

504 505 506 507
	ret = smu_notify_display_change(smu);
	if (ret)
		return ret;

508 509 510 511 512 513 514 515
	/*
	 * Set min deep sleep dce fclk with bootup value from vbios via
	 * SetMinDeepSleepDcefclk MSG.
	 */
	ret = smu_set_min_dcef_deep_sleep(smu);
	if (ret)
		return ret;

516 517 518 519 520 521 522 523 524
	/*
	 * Set initialized values (get from vbios) to dpm tables context such as
	 * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each
	 * type of clks.
	 */
	ret = smu_populate_smc_pptable(smu);
	if (ret)
		return ret;

525 526 527 528
	ret = smu_init_max_sustainable_clocks(smu);
	if (ret)
		return ret;

529 530 531 532
	ret = smu_populate_umd_state_clk(smu);
	if (ret)
		return ret;

533 534 535 536
	ret = smu_get_power_limit(smu);
	if (ret)
		return ret;

537 538 539 540 541 542
	/*
	 * Set PMSTATUSLOG table bo address with SetToolsDramAddr MSG for tools.
	 */
	ret = smu_set_tool_table_location(smu);

	return ret;
543 544
}

545 546 547 548 549 550 551 552 553 554 555 556
/**
 * smu_alloc_memory_pool - allocate memory pool in the system memory
 *
 * @smu: amdgpu_device pointer
 *
 * This memory pool will be used for SMC use and msg SetSystemVirtualDramAddr
 * and DramLogSetDramAddr can notify it changed.
 *
 * Returns 0 on success, error on failure.
 */
static int smu_alloc_memory_pool(struct smu_context *smu)
{
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
	struct amdgpu_device *adev = smu->adev;
	struct smu_table_context *smu_table = &smu->smu_table;
	struct smu_table *memory_pool = &smu_table->memory_pool;
	uint64_t pool_size = smu->pool_size;
	int ret = 0;

	if (pool_size == SMU_MEMORY_POOL_SIZE_ZERO)
		return ret;

	memory_pool->size = pool_size;
	memory_pool->align = PAGE_SIZE;
	memory_pool->domain = AMDGPU_GEM_DOMAIN_GTT;

	switch (pool_size) {
	case SMU_MEMORY_POOL_SIZE_256_MB:
	case SMU_MEMORY_POOL_SIZE_512_MB:
	case SMU_MEMORY_POOL_SIZE_1_GB:
	case SMU_MEMORY_POOL_SIZE_2_GB:
		ret = amdgpu_bo_create_kernel(adev,
					      memory_pool->size,
					      memory_pool->align,
					      memory_pool->domain,
					      &memory_pool->bo,
					      &memory_pool->mc_address,
					      &memory_pool->cpu_addr);
		break;
	default:
		break;
	}

	return ret;
588 589
}

590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
static int smu_free_memory_pool(struct smu_context *smu)
{
	struct smu_table_context *smu_table = &smu->smu_table;
	struct smu_table *memory_pool = &smu_table->memory_pool;
	int ret = 0;

	if (memory_pool->size == SMU_MEMORY_POOL_SIZE_ZERO)
		return ret;

	amdgpu_bo_free_kernel(&memory_pool->bo,
			      &memory_pool->mc_address,
			      &memory_pool->cpu_addr);

	memset(memory_pool, 0, sizeof(struct smu_table));

	return ret;
}
607 608 609 610 611 612
static int smu_hw_init(void *handle)
{
	int ret;
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
	struct smu_context *smu = &adev->smu;

613
	if (!is_support_sw_smu(adev))
614 615
		return -EINVAL;

616 617 618 619 620 621
	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
		ret = smu_load_microcode(smu);
		if (ret)
			return ret;
	}

622 623 624 625 626 627
	ret = smu_check_fw_status(smu);
	if (ret) {
		pr_err("SMC firmware status is not correct\n");
		return ret;
	}

628 629
	mutex_lock(&smu->mutex);

630 631 632 633
	ret = smu_feature_init_dpm(smu);
	if (ret)
		goto failed;

634 635 636
	ret = smu_smc_table_hw_init(smu);
	if (ret)
		goto failed;
637

638 639 640 641
	ret = smu_alloc_memory_pool(smu);
	if (ret)
		goto failed;

642 643 644 645 646 647 648 649
	/*
	 * Use msg SetSystemVirtualDramAddr and DramLogSetDramAddr can notify
	 * pool location.
	 */
	ret = smu_notify_memory_pool_location(smu);
	if (ret)
		goto failed;

650 651 652 653
	ret = smu_start_thermal_control(smu);
	if (ret)
		goto failed;

654 655 656 657 658
	mutex_unlock(&smu->mutex);

	pr_info("SMU is initialized successfully!\n");

	return 0;
659 660 661 662

failed:
	mutex_unlock(&smu->mutex);
	return ret;
663 664 665 666 667 668
}

static int smu_hw_fini(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
	struct smu_context *smu = &adev->smu;
669
	struct smu_table_context *table_context = &smu->smu_table;
670
	int ret = 0;
671

672
	if (!is_support_sw_smu(adev))
673 674
		return -EINVAL;

675 676 677 678
	if (table_context->driver_pptable) {
		kfree(table_context->driver_pptable);
		table_context->driver_pptable = NULL;
	}
679

680 681 682 683 684
	if (table_context->max_sustainable_clocks) {
		kfree(table_context->max_sustainable_clocks);
		table_context->max_sustainable_clocks = NULL;
	}

685 686 687 688
	ret = smu_fini_fb_allocations(smu);
	if (ret)
		return ret;

689 690 691 692
	ret = smu_free_memory_pool(smu);
	if (ret)
		return ret;

693 694 695
	return 0;
}

696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
int smu_reset(struct smu_context *smu)
{
	struct amdgpu_device *adev = smu->adev;
	int ret = 0;

	ret = smu_hw_fini(adev);
	if (ret)
		return ret;

	ret = smu_hw_init(adev);
	if (ret)
		return ret;

	return ret;
}

712 713 714 715
static int smu_suspend(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

716
	if (!is_support_sw_smu(adev))
717 718 719 720 721 722 723 724 725 726 727
		return -EINVAL;

	return 0;
}

static int smu_resume(void *handle)
{
	int ret;
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
	struct smu_context *smu = &adev->smu;

728
	if (!is_support_sw_smu(adev))
729 730
		return -EINVAL;

731 732 733 734 735 736 737 738 739 740 741 742 743 744
	pr_info("SMU is resuming...\n");

	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
		ret = smu_load_microcode(smu);
		if (ret)
			return ret;
	}

	ret = smu_check_fw_status(smu);
	if (ret) {
		pr_err("SMC firmware status is not correct\n");
		return ret;
	}

745 746
	mutex_lock(&smu->mutex);

747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
	ret = smu_set_tool_table_location(smu);
	if (ret)
		goto failed;

	ret = smu_write_pptable(smu);
	if (ret)
		goto failed;

	ret = smu_write_watermarks_table(smu);
	if (ret)
		goto failed;

	ret = smu_set_last_dcef_min_deep_sleep_clk(smu);
	if (ret)
		goto failed;

	ret = smu_system_features_control(smu, true);
	if (ret)
		goto failed;
766 767 768

	mutex_unlock(&smu->mutex);

769 770
	pr_info("SMU is resumed successfully!\n");

771
	return 0;
772 773 774
failed:
	mutex_unlock(&smu->mutex);
	return ret;
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805
}

static int smu_set_clockgating_state(void *handle,
				     enum amd_clockgating_state state)
{
	return 0;
}

static int smu_set_powergating_state(void *handle,
				     enum amd_powergating_state state)
{
	return 0;
}

const struct amd_ip_funcs smu_ip_funcs = {
	.name = "smu",
	.early_init = smu_early_init,
	.late_init = NULL,
	.sw_init = smu_sw_init,
	.sw_fini = smu_sw_fini,
	.hw_init = smu_hw_init,
	.hw_fini = smu_hw_fini,
	.suspend = smu_suspend,
	.resume = smu_resume,
	.is_idle = NULL,
	.check_soft_reset = NULL,
	.wait_for_idle = NULL,
	.soft_reset = NULL,
	.set_clockgating_state = smu_set_clockgating_state,
	.set_powergating_state = smu_set_powergating_state,
};
806 807 808 809 810 811 812 813 814

const struct amdgpu_ip_block_version smu_v11_0_ip_block =
{
	.type = AMD_IP_BLOCK_TYPE_SMC,
	.major = 11,
	.minor = 0,
	.rev = 0,
	.funcs = &smu_ip_funcs,
};