Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
v4.6
   1/*
   2 * Copyright 2015 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 "smumgr.h"
 
  25#include "smu73.h"
  26#include "smu_ucode_xfer_vi.h"
  27#include "fiji_smumgr.h"
  28#include "fiji_ppsmc.h"
  29#include "smu73_discrete.h"
  30#include "ppatomctrl.h"
  31#include "smu/smu_7_1_3_d.h"
  32#include "smu/smu_7_1_3_sh_mask.h"
  33#include "gmc/gmc_8_1_d.h"
  34#include "gmc/gmc_8_1_sh_mask.h"
  35#include "oss/oss_3_0_d.h"
  36#include "gca/gfx_8_0_d.h"
  37#include "bif/bif_5_0_d.h"
  38#include "bif/bif_5_0_sh_mask.h"
  39#include "pp_debug.h"
  40#include "fiji_pwrvirus.h"
 
 
 
 
 
 
 
  41
  42#define AVFS_EN_MSB                                        1568
  43#define AVFS_EN_LSB                                        1568
  44
  45#define FIJI_SMC_SIZE 0x20000
  46
  47struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  48		/*  Min        Sclk       pcie     DeepSleep Activity  CgSpll      CgSpll    spllSpread  SpllSpread   CcPwr  CcPwr  Sclk   Display     Enabled     Enabled                       Voltage    Power */
  49		/* Voltage,  Frequency,  DpmLevel,  DivId,    Level,  FuncCntl3,  FuncCntl4,  Spectrum,   Spectrum2,  DynRm, DynRm1  Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */
  50		{ 0x3c0fd047, 0x30750000,   0x00,     0x03,   0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000,   0,      0,   0x16,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  51		{ 0xa00fd047, 0x409c0000,   0x01,     0x04,   0x1e00, 0x00800510, 0x87020000, 0x21680000, 0x11000000,   0,      0,   0x16,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  52		{ 0x0410d047, 0x50c30000,   0x01,     0x00,   0x1e00, 0x00600410, 0x87020000, 0x21680000, 0x0d000000,   0,      0,   0x0e,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  53		{ 0x6810d047, 0x60ea0000,   0x01,     0x00,   0x1e00, 0x00800410, 0x87020000, 0x21680000, 0x0e000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  54		{ 0xcc10d047, 0xe8fd0000,   0x01,     0x00,   0x1e00, 0x00e00410, 0x87020000, 0x21680000, 0x0f000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  55		{ 0x3011d047, 0x70110100,   0x01,     0x00,   0x1e00, 0x00400510, 0x87020000, 0x21680000, 0x10000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  56		{ 0x9411d047, 0xf8240100,   0x01,     0x00,   0x1e00, 0x00a00510, 0x87020000, 0x21680000, 0x11000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  57		{ 0xf811d047, 0x80380100,   0x01,     0x00,   0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000,   0,      0,   0x0c,   0x01,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 }
  58};
  59
  60static enum cgs_ucode_id fiji_convert_fw_type_to_cgs(uint32_t fw_type)
  61{
  62	enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
  63
  64	switch (fw_type) {
  65	case UCODE_ID_SMU:
  66		result = CGS_UCODE_ID_SMU;
  67		break;
  68	case UCODE_ID_SDMA0:
  69		result = CGS_UCODE_ID_SDMA0;
  70		break;
  71	case UCODE_ID_SDMA1:
  72		result = CGS_UCODE_ID_SDMA1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  73		break;
  74	case UCODE_ID_CP_CE:
  75		result = CGS_UCODE_ID_CP_CE;
 
  76		break;
  77	case UCODE_ID_CP_PFP:
  78		result = CGS_UCODE_ID_CP_PFP;
 
  79		break;
  80	case UCODE_ID_CP_ME:
  81		result = CGS_UCODE_ID_CP_ME;
 
  82		break;
  83	case UCODE_ID_CP_MEC:
  84		result = CGS_UCODE_ID_CP_MEC;
 
  85		break;
  86	case UCODE_ID_CP_MEC_JT1:
  87		result = CGS_UCODE_ID_CP_MEC_JT1;
 
  88		break;
  89	case UCODE_ID_CP_MEC_JT2:
  90		result = CGS_UCODE_ID_CP_MEC_JT2;
 
  91		break;
  92	case UCODE_ID_RLC_G:
  93		result = CGS_UCODE_ID_RLC_G;
 
  94		break;
  95	default:
 
 
  96		break;
  97	}
  98
  99	return result;
 100}
 101/**
 102* Set the address for reading/writing the SMC SRAM space.
 103* @param    smumgr  the address of the powerplay hardware manager.
 104* @param    smc_addr the address in the SMC RAM to access.
 105*/
 106static int fiji_set_smc_sram_address(struct pp_smumgr *smumgr,
 107		uint32_t smc_addr, uint32_t limit)
 108{
 109	PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)),
 110			"SMC address must be 4 byte aligned.", return -EINVAL;);
 111	PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)),
 112			"SMC address is beyond the SMC RAM area.", return -EINVAL;);
 113
 114	cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, smc_addr);
 115	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 116
 117	return 0;
 118}
 119
 120/**
 121* Copy bytes from an array into the SMC RAM space.
 122*
 123* @param    smumgr  the address of the powerplay SMU manager.
 124* @param    smcStartAddress the start address in the SMC RAM to copy bytes to.
 125* @param    src the byte array to copy the bytes from.
 126* @param    byteCount the number of bytes to copy.
 127*/
 128int fiji_copy_bytes_to_smc(struct pp_smumgr *smumgr,
 129		uint32_t smcStartAddress, const uint8_t *src,
 130		uint32_t byteCount, uint32_t limit)
 131{
 132	int result;
 133	uint32_t data, originalData;
 134	uint32_t addr, extraShift;
 135
 136	PP_ASSERT_WITH_CODE((0 == (3 & smcStartAddress)),
 137			"SMC address must be 4 byte aligned.", return -EINVAL;);
 138	PP_ASSERT_WITH_CODE((limit > (smcStartAddress + byteCount)),
 139			"SMC address is beyond the SMC RAM area.", return -EINVAL;);
 140
 141	addr = smcStartAddress;
 142
 143	while (byteCount >= 4) {
 144		/* Bytes are written into the SMC addres space with the MSB first. */
 145		data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3];
 
 
 
 146
 147		result = fiji_set_smc_sram_address(smumgr, addr, limit);
 148		if (result)
 149			return result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 150
 151		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data);
 
 152
 153		src += 4;
 154		byteCount -= 4;
 155		addr += 4;
 156	}
 157
 158	if (byteCount) {
 159		/* Now write the odd bytes left.
 160		 * Do a read modify write cycle.
 161		 */
 162		data = 0;
 163
 164		result = fiji_set_smc_sram_address(smumgr, addr, limit);
 165		if (result)
 166			return result;
 
 167
 168		originalData = cgs_read_register(smumgr->device, mmSMC_IND_DATA_0);
 169		extraShift = 8 * (4 - byteCount);
 170
 171		while (byteCount > 0) {
 172			/* Bytes are written into the SMC addres
 173			 * space with the MSB first.
 174			 */
 175			data = (0x100 * data) + *src++;
 176			byteCount--;
 177		}
 178		data <<= extraShift;
 179		data |= (originalData & ~((~0UL) << extraShift));
 180
 181		result = fiji_set_smc_sram_address(smumgr, addr, limit);
 182		if (!result)
 183			return result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 184
 185		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 186	}
 187	return 0;
 188}
 189
 190int fiji_program_jump_on_start(struct pp_smumgr *smumgr)
 191{
 192	static unsigned char data[] = { 0xE0, 0x00, 0x80, 0x40 };
 
 193
 194	fiji_copy_bytes_to_smc(smumgr, 0x0, data, 4, sizeof(data) + 1);
 
 
 195
 196	return 0;
 197}
 198
 199/**
 200* Return if the SMC is currently running.
 201*
 202* @param    smumgr  the address of the powerplay hardware manager.
 203*/
 204bool fiji_is_smc_ram_running(struct pp_smumgr *smumgr)
 205{
 206	return ((0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device,
 207			CGS_IND_REG__SMC,
 208			SMC_SYSCON_CLOCK_CNTL_0, ck_disable))
 209			&& (0x20100 <= cgs_read_ind_register(smumgr->device,
 210					CGS_IND_REG__SMC, ixSMC_PC_C)));
 
 
 
 
 211}
 212
 213/**
 214* Send a message to the SMC, and wait for its response.
 215*
 216* @param    smumgr  the address of the powerplay hardware manager.
 217* @param    msg the message to send.
 218* @return   The response that came from the SMC.
 219*/
 220int fiji_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
 221{
 222	if (!fiji_is_smc_ram_running(smumgr))
 223		return -1;
 224
 225	if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) {
 226		printk(KERN_ERR "Failed to send Previous Message.");
 227		SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
 228	}
 229
 230	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
 231	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
 
 232
 233	return 0;
 234}
 235
 236/**
 237 * Send a message to the SMC with parameter
 238 * @param    smumgr:  the address of the powerplay hardware manager.
 239 * @param    msg: the message to send.
 240 * @param    parameter: the parameter to send
 241 * @return   The response that came from the SMC.
 242 */
 243int fiji_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
 244		uint16_t msg, uint32_t parameter)
 245{
 246	if (!fiji_is_smc_ram_running(smumgr))
 247		return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 248
 249	if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) {
 250		printk(KERN_ERR "Failed to send Previous Message.");
 251		SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
 252	}
 253
 254	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter);
 255	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
 256	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
 
 257
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 258	return 0;
 259}
 260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 261
 262/**
 263* Send a message to the SMC with parameter, do not wait for response
 264*
 265* @param    smumgr:  the address of the powerplay hardware manager.
 266* @param    msg: the message to send.
 267* @param    parameter: the parameter to send
 268* @return   The response that came from the SMC.
 269*/
 270int fiji_send_msg_to_smc_with_parameter_without_waiting(
 271		struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter)
 272{
 273	if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) {
 274		printk(KERN_ERR "Failed to send Previous Message.");
 275		SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
 276	}
 277	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter);
 278	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
 279
 280	return 0;
 281}
 282
 283/**
 284* Uploads the SMU firmware from .hex file
 285*
 286* @param    smumgr  the address of the powerplay SMU manager.
 287* @return   0 or -1.
 288*/
 289
 290static int fiji_upload_smu_firmware_image(struct pp_smumgr *smumgr)
 291{
 292	const uint8_t *src;
 293	uint32_t byte_count;
 294	uint32_t *data;
 295	struct cgs_firmware_info info = {0};
 296
 297	cgs_get_firmware_info(smumgr->device,
 298			fiji_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
 
 
 299
 300	if (info.image_size & 3) {
 301		printk(KERN_ERR "SMC ucode is not 4 bytes aligned\n");
 302		return -EINVAL;
 303	}
 304
 305	if (info.image_size > FIJI_SMC_SIZE) {
 306		printk(KERN_ERR "SMC address is beyond the SMC RAM area\n");
 307		return -EINVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 308	}
 
 
 309
 310	cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, 0x20000);
 311	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1);
 
 
 
 312
 313	byte_count = info.image_size;
 314	src = (const uint8_t *)info.kptr;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 315
 316	data = (uint32_t *)src;
 317	for (; byte_count >= 4; data++, byte_count -= 4)
 318		cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data[0]);
 
 319
 320	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
 321	return 0;
 322}
 323
 324/**
 325* Read a 32bit value from the SMC SRAM space.
 326* ALL PARAMETERS ARE IN HOST BYTE ORDER.
 327* @param    smumgr  the address of the powerplay hardware manager.
 328* @param    smc_addr the address in the SMC RAM to access.
 329* @param    value and output parameter for the data read from the SMC SRAM.
 330*/
 331int fiji_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr,
 332		uint32_t *value, uint32_t limit)
 333{
 334	int	result = fiji_set_smc_sram_address(smumgr, smc_addr, limit);
 
 
 
 
 
 
 
 
 
 
 335
 336	if (result)
 337		return result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 338
 339	*value = cgs_read_register(smumgr->device, mmSMC_IND_DATA_0);
 340	return 0;
 341}
 342
 343/**
 344* Write a 32bit value to the SMC SRAM space.
 345* ALL PARAMETERS ARE IN HOST BYTE ORDER.
 346* @param    smumgr  the address of the powerplay hardware manager.
 347* @param    smc_addr the address in the SMC RAM to access.
 348* @param    value to write to the SMC SRAM.
 349*/
 350int fiji_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr,
 351		uint32_t value, uint32_t limit)
 352{
 353	int result;
 
 
 
 
 
 
 354
 355	result = fiji_set_smc_sram_address(smumgr, smc_addr, limit);
 356
 357	if (result)
 358		return result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 359
 360	cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, value);
 361	return 0;
 362}
 363
 364static uint32_t fiji_get_mask_for_firmware_type(uint32_t fw_type)
 365{
 366	uint32_t result = 0;
 
 367
 368	switch (fw_type) {
 369	case UCODE_ID_SDMA0:
 370		result = UCODE_ID_SDMA0_MASK;
 371		break;
 372	case UCODE_ID_SDMA1:
 373		result = UCODE_ID_SDMA1_MASK;
 374		break;
 375	case UCODE_ID_CP_CE:
 376		result = UCODE_ID_CP_CE_MASK;
 377		break;
 378	case UCODE_ID_CP_PFP:
 379		result = UCODE_ID_CP_PFP_MASK;
 380		break;
 381	case UCODE_ID_CP_ME:
 382		result = UCODE_ID_CP_ME_MASK;
 383		break;
 384	case UCODE_ID_CP_MEC_JT1:
 385		result = UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK;
 386		break;
 387	case UCODE_ID_CP_MEC_JT2:
 388		result = UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT2_MASK;
 389		break;
 390	case UCODE_ID_RLC_G:
 391		result = UCODE_ID_RLC_G_MASK;
 392		break;
 393	default:
 394		printk(KERN_ERR "UCode type is out of range!");
 395		result = 0;
 396	}
 397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 398	return result;
 399}
 400
 401/* Populate one firmware image to the data structure */
 402static int fiji_populate_single_firmware_entry(struct pp_smumgr *smumgr,
 403		uint32_t fw_type, struct SMU_Entry *entry)
 
 
 
 
 
 
 
 
 
 
 
 
 404{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 405	int result;
 406	struct cgs_firmware_info info = {0};
 407
 408	result = cgs_get_firmware_info(
 409			smumgr->device,
 410			fiji_convert_fw_type_to_cgs(fw_type),
 411			&info);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 412
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 413	if (!result) {
 414		entry->version = 0;
 415		entry->id = (uint16_t)fw_type;
 416		entry->image_addr_high = smu_upper_32_bits(info.mc_addr);
 417		entry->image_addr_low = smu_lower_32_bits(info.mc_addr);
 418		entry->meta_data_addr_high = 0;
 419		entry->meta_data_addr_low = 0;
 420		entry->data_size_byte = info.image_size;
 421		entry->num_register_entries = 0;
 422
 423		if (fw_type == UCODE_ID_RLC_G)
 424			entry->flags = 1;
 425		else
 426			entry->flags = 0;
 427	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 428
 429	return result;
 430}
 431
 432static int fiji_request_smu_load_fw(struct pp_smumgr *smumgr)
 433{
 434	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 435	uint32_t fw_to_load;
 436	struct SMU_DRAMData_TOC *toc;
 437
 438	if (priv->soft_regs_start)
 439		cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
 440				priv->soft_regs_start +
 441				offsetof(SMU73_SoftRegisters, UcodeLoadStatus),
 442				0x0);
 443
 444	toc = (struct SMU_DRAMData_TOC *)priv->header;
 445	toc->num_entries = 0;
 446	toc->structure_version = 1;
 447
 448	PP_ASSERT_WITH_CODE(
 449			0 == fiji_populate_single_firmware_entry(smumgr,
 450					UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]),
 451			"Failed to Get Firmware Entry.\n" , return -1 );
 452	PP_ASSERT_WITH_CODE(
 453			0 == fiji_populate_single_firmware_entry(smumgr,
 454					UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]),
 455			"Failed to Get Firmware Entry.\n" , return -1 );
 456	PP_ASSERT_WITH_CODE(
 457			0 == fiji_populate_single_firmware_entry(smumgr,
 458					UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]),
 459			"Failed to Get Firmware Entry.\n" , return -1 );
 460	PP_ASSERT_WITH_CODE(
 461			0 == fiji_populate_single_firmware_entry(smumgr,
 462					UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]),
 463			"Failed to Get Firmware Entry.\n" , return -1 );
 464	PP_ASSERT_WITH_CODE(
 465			0 == fiji_populate_single_firmware_entry(smumgr,
 466					UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]),
 467			"Failed to Get Firmware Entry.\n" , return -1 );
 468	PP_ASSERT_WITH_CODE(
 469			0 == fiji_populate_single_firmware_entry(smumgr,
 470					UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]),
 471					"Failed to Get Firmware Entry.\n" , return -1 );
 472	PP_ASSERT_WITH_CODE(
 473			0 == fiji_populate_single_firmware_entry(smumgr,
 474					UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]),
 475					"Failed to Get Firmware Entry.\n" , return -1 );
 476	PP_ASSERT_WITH_CODE(
 477			0 == fiji_populate_single_firmware_entry(smumgr,
 478					UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]),
 479					"Failed to Get Firmware Entry.\n" , return -1 );
 480	PP_ASSERT_WITH_CODE(
 481			0 == fiji_populate_single_firmware_entry(smumgr,
 482					UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]),
 483					"Failed to Get Firmware Entry.\n" , return -1 );
 484
 485	fiji_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_HI,
 486			priv->header_buffer.mc_addr_high);
 487	fiji_send_msg_to_smc_with_parameter(smumgr,PPSMC_MSG_DRV_DRAM_ADDR_LO,
 488			priv->header_buffer.mc_addr_low);
 489
 490	fw_to_load = UCODE_ID_RLC_G_MASK
 491			+ UCODE_ID_SDMA0_MASK
 492			+ UCODE_ID_SDMA1_MASK
 493			+ UCODE_ID_CP_CE_MASK
 494			+ UCODE_ID_CP_ME_MASK
 495			+ UCODE_ID_CP_PFP_MASK
 496			+ UCODE_ID_CP_MEC_MASK
 497			+ UCODE_ID_CP_MEC_JT1_MASK
 498			+ UCODE_ID_CP_MEC_JT2_MASK;
 499
 500	if (fiji_send_msg_to_smc_with_parameter(smumgr,
 501			PPSMC_MSG_LoadUcodes, fw_to_load))
 502		printk(KERN_ERR "Fail to Request SMU Load uCode");
 503
 504	return 0;
 505}
 506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 507
 508/* Check if the FW has been loaded, SMU will not return
 509 * if loading has not finished.
 510 */
 511static int fiji_check_fw_load_finish(struct pp_smumgr *smumgr,
 512		uint32_t fw_type)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 513{
 514	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 515	uint32_t mask = fiji_get_mask_for_firmware_type(fw_type);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 516
 517	/* Check SOFT_REGISTERS_TABLE_28.UcodeLoadStatus */
 518	if (smum_wait_on_indirect_register(smumgr, mmSMC_IND_INDEX,
 519			priv->soft_regs_start +
 520			offsetof(SMU73_SoftRegisters, UcodeLoadStatus),
 521			mask, mask)) {
 522		printk(KERN_ERR "check firmware loading failed\n");
 523		return -EINVAL;
 524	}
 525	return 0;
 526}
 527
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 528
 529static int fiji_reload_firmware(struct pp_smumgr *smumgr)
 
 530{
 531	return smumgr->smumgr_funcs->start_smu(smumgr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 532}
 533
 534static bool fiji_is_hw_virtualization_enabled(struct pp_smumgr *smumgr)
 535{
 536	uint32_t value;
 
 
 
 
 537
 538	value = cgs_read_register(smumgr->device, mmBIF_IOV_FUNC_IDENTIFIER);
 539	if (value & BIF_IOV_FUNC_IDENTIFIER__IOV_ENABLE_MASK) {
 540		/* driver reads on SR-IOV enabled PF: 0x80000000
 541		 * driver reads on SR-IOV enabled VF: 0x80000001
 542		 * driver reads on SR-IOV disabled:   0x00000000
 543		 */
 544		return true;
 
 
 545	}
 546	return false;
 
 
 
 
 
 
 
 
 547}
 548
 549static int fiji_request_smu_specific_fw_load(struct pp_smumgr *smumgr, uint32_t fw_type)
 
 550{
 551	if (fiji_is_hw_virtualization_enabled(smumgr)) {
 552		uint32_t masks = fiji_get_mask_for_firmware_type(fw_type);
 553		if (fiji_send_msg_to_smc_with_parameter_without_waiting(smumgr,
 554				PPSMC_MSG_LoadUcodes, masks))
 555			printk(KERN_ERR "Fail to Request SMU Load uCode");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 556	}
 557	/* For non-virtualization cases,
 558	 * SMU loads all FWs at once in fiji_request_smu_load_fw.
 559	 */
 560	return 0;
 561}
 562
 563static int fiji_start_smu_in_protection_mode(struct pp_smumgr *smumgr)
 
 564{
 565	int result = 0;
 
 566
 567	/* Wait for smc boot up */
 568	/* SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND,
 569		RCU_UC_EVENTS, boot_seq_done, 0); */
 570
 571	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 572			SMC_SYSCON_RESET_CNTL, rst_reg, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 573
 574	result = fiji_upload_smu_firmware_image(smumgr);
 575	if (result)
 576		return result;
 577
 578	/* Clear status */
 579	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
 580			ixSMU_STATUS, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 581
 582	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 583			SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
 
 
 
 
 
 
 584
 585	/* De-assert reset */
 586	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 587			SMC_SYSCON_RESET_CNTL, rst_reg, 0);
 588
 589	/* Wait for ROM firmware to initialize interrupt hendler */
 590	/*SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, SMC_IND,
 591			SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */
 
 
 
 
 
 
 
 
 
 592
 593	/* Set SMU Auto Start */
 594	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 595			SMU_INPUT_DATA, AUTO_START, 1);
 596
 597	/* Clear firmware interrupt enable flag */
 598	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
 599			ixFIRMWARE_FLAGS, 0);
 
 
 
 
 
 
 
 600
 601	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, RCU_UC_EVENTS,
 602			INTERRUPTS_ENABLED, 1);
 
 
 603
 604	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, 0x20000);
 605	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test);
 606	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
 
 607
 608	/* Wait for done bit to be set */
 609	SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND,
 610			SMU_STATUS, SMU_DONE, 0);
 611
 612	/* Check pass/failed indicator */
 613	if (1 != SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 614			SMU_STATUS, SMU_PASS)) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 615		PP_ASSERT_WITH_CODE(false,
 616				"SMU Firmware start failed!", return -1);
 
 617	}
 618
 619	/* Wait for firmware to initialize */
 620	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND,
 621			FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 622
 623	return result;
 
 
 
 
 624}
 625
 626static int fiji_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr)
 
 627{
 628	int result = 0;
 
 629
 630	/* wait for smc boot up */
 631	SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND,
 632			RCU_UC_EVENTS, boot_seq_done, 0);
 633
 634	/* Clear firmware interrupt enable flag */
 635	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
 636			ixFIRMWARE_FLAGS, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 637
 638	/* Assert reset */
 639	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 640			SMC_SYSCON_RESET_CNTL, rst_reg, 1);
 641
 642	result = fiji_upload_smu_firmware_image(smumgr);
 643	if (result)
 644		return result;
 
 
 645
 646	/* Set smc instruct start point at 0x0 */
 647	fiji_program_jump_on_start(smumgr);
 
 
 
 
 
 
 
 
 648
 649	/* Enable clock */
 650	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 651			SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
 652
 653	/* De-assert reset */
 654	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 655			SMC_SYSCON_RESET_CNTL, rst_reg, 0);
 656
 657	/* Wait for firmware to initialize */
 658	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND,
 659			FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
 660
 661	return result;
 662}
 663
 664int fiji_setup_pwr_virus(struct pp_smumgr *smumgr)
 665{
 666	int i, result = -1;
 667	uint32_t reg, data;
 668	PWR_Command_Table *virus = PwrVirusTable;
 669	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 670
 671	priv->avfs.AvfsBtcStatus = AVFS_LOAD_VIRUS;
 672	for (i = 0; (i < PWR_VIRUS_TABLE_SIZE); i++) {
 673		switch (virus->command) {
 674		case PwrCmdWrite:
 675			reg  = virus->reg;
 676			data = virus->data;
 677			cgs_write_register(smumgr->device, reg, data);
 678			break;
 679		case PwrCmdEnd:
 680			priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_LOADED;
 681			result = 0;
 682			break;
 683		default:
 684			printk(KERN_ERR "Table Exit with Invalid Command!");
 685			priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_FAIL;
 686			result = -1;
 687			break;
 688		}
 689		virus++;
 690	}
 691	return result;
 
 
 
 
 692}
 693
 694static int fiji_start_avfs_btc(struct pp_smumgr *smumgr)
 695{
 696	int result = 0;
 697	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 698
 699	priv->avfs.AvfsBtcStatus = AVFS_BTC_STARTED;
 700	if (priv->avfs.AvfsBtcParam) {
 701		if (!fiji_send_msg_to_smc_with_parameter(smumgr,
 702				PPSMC_MSG_PerformBtc, priv->avfs.AvfsBtcParam)) {
 703			if (!fiji_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs)) {
 704				priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_UNSAVED;
 705				result = 0;
 706			} else {
 707				printk(KERN_ERR "[AVFS][fiji_start_avfs_btc] Attempt"
 708						" to Enable AVFS Failed!");
 709				fiji_send_msg_to_smc(smumgr, PPSMC_MSG_DisableAvfs);
 710				result = -1;
 711			}
 712		} else {
 713			printk(KERN_ERR "[AVFS][fiji_start_avfs_btc] "
 714					"PerformBTC SMU msg failed");
 715			result = -1;
 716		}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 717	}
 718	/* Soft-Reset to reset the engine before loading uCode */
 719	 /* halt */
 720	cgs_write_register(smumgr->device, mmCP_MEC_CNTL, 0x50000000);
 721	/* reset everything */
 722	cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0xffffffff);
 723	/* clear reset */
 724	cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0);
 725
 726	return result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 727}
 728
 729int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr)
 730{
 731	int result = 0;
 732	uint32_t table_start;
 733	uint32_t charz_freq_addr, inversion_voltage_addr, charz_freq;
 734	uint16_t inversion_voltage;
 735
 736	charz_freq = 0x30750000; /* In 10KHz units 0x00007530 Actual value */
 737	inversion_voltage = 0x1A04; /* mV Q14.2 0x41A Actual value */
 
 
 
 
 
 
 
 
 
 
 
 738
 739	PP_ASSERT_WITH_CODE(0 == fiji_read_smc_sram_dword(smumgr,
 740			SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header,
 741					PmFuseTable), &table_start, 0x40000),
 742			"[AVFS][Fiji_SetupGfxLvlStruct] SMU could not communicate "
 743			"starting address of PmFuse structure",
 744			return -1;);
 745
 746	charz_freq_addr = table_start +
 747			offsetof(struct SMU73_Discrete_PmFuses, PsmCharzFreq);
 748	inversion_voltage_addr = table_start +
 749			offsetof(struct SMU73_Discrete_PmFuses, InversionVoltage);
 750
 751	result = fiji_copy_bytes_to_smc(smumgr, charz_freq_addr,
 752			(uint8_t *)(&charz_freq), sizeof(charz_freq), 0x40000);
 753	PP_ASSERT_WITH_CODE(0 == result,
 754			"[AVFS][fiji_setup_pm_fuse_for_avfs] charz_freq could not "
 755			"be populated.", return -1;);
 756
 757	result = fiji_copy_bytes_to_smc(smumgr, inversion_voltage_addr,
 758			(uint8_t *)(&inversion_voltage), sizeof(inversion_voltage), 0x40000);
 759	PP_ASSERT_WITH_CODE(0 == result, "[AVFS][fiji_setup_pm_fuse_for_avfs] "
 760			"charz_freq could not be populated.", return -1;);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 761
 762	return result;
 763}
 764
 765int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr)
 
 766{
 767	int32_t vr_config;
 768	uint32_t table_start;
 769	uint32_t level_addr, vr_config_addr;
 770	uint32_t level_size = sizeof(avfs_graphics_level);
 771
 772	PP_ASSERT_WITH_CODE(0 == fiji_read_smc_sram_dword(smumgr,
 773			SMU7_FIRMWARE_HEADER_LOCATION +
 774			offsetof(SMU73_Firmware_Header, DpmTable),
 775			&table_start, 0x40000),
 776			"[AVFS][Fiji_SetupGfxLvlStruct] SMU could not "
 777			"communicate starting address of DPM table",
 778			return -1;);
 779
 780	/* Default value for vr_config =
 781	 * VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */
 782	vr_config = 0x01000500;   /* Real value:0x50001 */
 783
 784	vr_config_addr = table_start +
 785			offsetof(SMU73_Discrete_DpmTable, VRConfig);
 
 786
 787	PP_ASSERT_WITH_CODE(0 == fiji_copy_bytes_to_smc(smumgr, vr_config_addr,
 788			(uint8_t *)&vr_config, sizeof(int32_t), 0x40000),
 789			"[AVFS][Fiji_SetupGfxLvlStruct] Problems copying "
 790			"vr_config value over to SMC",
 791			return -1;);
 792
 793	level_addr = table_start + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel);
 
 794
 795	PP_ASSERT_WITH_CODE(0 == fiji_copy_bytes_to_smc(smumgr, level_addr,
 796			(uint8_t *)(&avfs_graphics_level), level_size, 0x40000),
 797			"[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!",
 798			return -1;);
 799
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 800	return 0;
 801}
 802
 803/* Work in Progress */
 804int fiji_restore_vft_table(struct pp_smumgr *smumgr)
 805{
 806	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 807
 808	if (AVFS_BTC_COMPLETED_SAVED == priv->avfs.AvfsBtcStatus) {
 809		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED;
 810		return 0;
 811	} else
 812		return -EINVAL;
 813}
 814
 815/* Work in Progress */
 816int fiji_save_vft_table(struct pp_smumgr *smumgr)
 817{
 818	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 819
 820	if (AVFS_BTC_COMPLETED_SAVED == priv->avfs.AvfsBtcStatus) {
 821		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED;
 822		return 0;
 823	} else
 824		return -EINVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 825}
 826
 827int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started)
 828{
 829	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
 830
 831	switch (priv->avfs.AvfsBtcStatus) {
 832	case AVFS_BTC_COMPLETED_SAVED: /*S3 State - Pre SMU Start */
 833		priv->avfs.AvfsBtcStatus = AVFS_BTC_RESTOREVFT_FAILED;
 834		PP_ASSERT_WITH_CODE(0 == fiji_restore_vft_table(smumgr),
 835				"[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics "
 836				"Level table over to SMU",
 837				return -1;);
 838		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED;
 839		break;
 840	case AVFS_BTC_COMPLETED_RESTORED: /*S3 State - Post SMU Start*/
 841		priv->avfs.AvfsBtcStatus = AVFS_BTC_SMUMSG_ERROR;
 842		PP_ASSERT_WITH_CODE(0 == fiji_send_msg_to_smc(smumgr,
 843				PPSMC_MSG_VftTableIsValid),
 844				"[AVFS][fiji_avfs_event_mgr] SMU did not respond "
 845				"correctly to VftTableIsValid Msg",
 846				return -1;);
 847		priv->avfs.AvfsBtcStatus = AVFS_BTC_SMUMSG_ERROR;
 848		PP_ASSERT_WITH_CODE(0 == fiji_send_msg_to_smc(smumgr,
 849				PPSMC_MSG_EnableAvfs),
 850				"[AVFS][fiji_avfs_event_mgr] SMU did not respond "
 851				"correctly to EnableAvfs Message Msg",
 852				return -1;);
 853		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_SAVED;
 854		break;
 855	case AVFS_BTC_BOOT: /*Cold Boot State - Post SMU Start*/
 856		if (!smu_started)
 857			break;
 858		priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED;
 859		PP_ASSERT_WITH_CODE(0 == fiji_setup_pm_fuse_for_avfs(smumgr),
 860				"[AVFS][fiji_avfs_event_mgr] Failure at "
 861				"fiji_setup_pm_fuse_for_avfs",
 862				return -1;);
 863		priv->avfs.AvfsBtcStatus = AVFS_BTC_DPMTABLESETUP_FAILED;
 864		PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(smumgr),
 865				"[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level"
 866				" table over to SMU",
 867				return -1;);
 868		priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_FAIL;
 869		PP_ASSERT_WITH_CODE(0 == fiji_setup_pwr_virus(smumgr),
 870				"[AVFS][fiji_avfs_event_mgr] Could not setup "
 871				"Pwr Virus for AVFS ",
 872				return -1;);
 873		priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED;
 874		PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(smumgr),
 875				"[AVFS][fiji_avfs_event_mgr] Failure at "
 876				"fiji_start_avfs_btc. AVFS Disabled",
 877				return -1;);
 878		priv->avfs.AvfsBtcStatus = AVFS_BTC_SAVEVFT_FAILED;
 879		PP_ASSERT_WITH_CODE(0 == fiji_save_vft_table(smumgr),
 880				"[AVFS][fiji_avfs_event_mgr] Could not save VFT Table",
 881				return -1;);
 882		priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_SAVED;
 883		break;
 884	case AVFS_BTC_DISABLED: /* Do nothing */
 
 885		break;
 886	case AVFS_BTC_NOTSUPPORTED: /* Do nothing */
 
 887		break;
 888	default:
 889		printk(KERN_ERR "[AVFS] Something is broken. See log!");
 890		break;
 891	}
 892	return 0;
 893}
 894
 895static int fiji_start_smu(struct pp_smumgr *smumgr)
 896{
 897	int result = 0;
 898	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
 
 
 899
 900	/* Only start SMC if SMC RAM is not running */
 901	if (!fiji_is_smc_ram_running(smumgr)) {
 902		fiji_avfs_event_mgr(smumgr, false);
 
 903
 904		/* Check if SMU is running in protected mode */
 905		if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device,
 906				CGS_IND_REG__SMC,
 907				SMU_FIRMWARE, SMU_MODE)) {
 908			result = fiji_start_smu_in_non_protection_mode(smumgr);
 909			if (result)
 910				return result;
 911		} else {
 912			result = fiji_start_smu_in_protection_mode(smumgr);
 913			if (result)
 914				return result;
 915		}
 916		fiji_avfs_event_mgr(smumgr, true);
 917	}
 918
 919	/* To initialize all clock gating before RLC loaded and running.*/
 920	cgs_set_clockgating_state(smumgr->device,
 921			AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_GATE);
 922	cgs_set_clockgating_state(smumgr->device,
 923			AMD_IP_BLOCK_TYPE_GMC, AMD_CG_STATE_GATE);
 924	cgs_set_clockgating_state(smumgr->device,
 925			AMD_IP_BLOCK_TYPE_SDMA, AMD_CG_STATE_GATE);
 926	cgs_set_clockgating_state(smumgr->device,
 927			AMD_IP_BLOCK_TYPE_COMMON, AMD_CG_STATE_GATE);
 928
 929	/* Setup SoftRegsStart here for register lookup in case
 930	 * DummyBackEnd is used and ProcessFirmwareHeader is not executed
 931	 */
 932	fiji_read_smc_sram_dword(smumgr,
 933			SMU7_FIRMWARE_HEADER_LOCATION +
 934			offsetof(SMU73_Firmware_Header, SoftRegisters),
 935			&(priv->soft_regs_start), 0x40000);
 936
 937	result = fiji_request_smu_load_fw(smumgr);
 
 
 
 938
 939	return result;
 940}
 941
 942static bool fiji_is_hw_avfs_present(struct pp_smumgr *smumgr)
 943{
 
 
 944
 945	uint32_t efuse = 0;
 946	uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1;
 947
 948	if (!atomctrl_read_efuse(smumgr->device, AVFS_EN_LSB, AVFS_EN_MSB,
 949			mask, &efuse)) {
 950		if (efuse)
 951			return true;
 952	}
 953	return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 954}
 955
 956/**
 957* Write a 32bit value to the SMC SRAM space.
 958* ALL PARAMETERS ARE IN HOST BYTE ORDER.
 959* @param    smumgr  the address of the powerplay hardware manager.
 960* @param    smc_addr the address in the SMC RAM to access.
 961* @param    value to write to the SMC SRAM.
 962*/
 963static int fiji_smu_init(struct pp_smumgr *smumgr)
 964{
 965	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 966	uint64_t mc_addr;
 967
 968	priv->header_buffer.data_size =
 969			((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
 970	smu_allocate_memory(smumgr->device,
 971			priv->header_buffer.data_size,
 972			CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
 973			PAGE_SIZE,
 974			&mc_addr,
 975			&priv->header_buffer.kaddr,
 976			&priv->header_buffer.handle);
 977
 978	priv->header = priv->header_buffer.kaddr;
 979	priv->header_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
 980	priv->header_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
 981
 982	PP_ASSERT_WITH_CODE((NULL != priv->header),
 983			"Out of memory.",
 984			kfree(smumgr->backend);
 985			cgs_free_gpu_mem(smumgr->device,
 986			(cgs_handle_t)priv->header_buffer.handle);
 987			return -1);
 988
 989	priv->avfs.AvfsBtcStatus = AVFS_BTC_BOOT;
 990	if (fiji_is_hw_avfs_present(smumgr))
 991		/* AVFS Parameter
 992		 * 0 - BTC DC disabled, BTC AC disabled
 993		 * 1 - BTC DC enabled,  BTC AC disabled
 994		 * 2 - BTC DC disabled, BTC AC enabled
 995		 * 3 - BTC DC enabled,  BTC AC enabled
 996		 * Default is 0 - BTC DC disabled, BTC AC disabled
 997		 */
 998		priv->avfs.AvfsBtcParam = 0;
 999	else
1000		priv->avfs.AvfsBtcStatus = AVFS_BTC_NOTSUPPORTED;
1001
1002	priv->acpi_optimization = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1003
1004	return 0;
1005}
1006
1007static int fiji_smu_fini(struct pp_smumgr *smumgr)
1008{
1009	if (smumgr->backend) {
1010		kfree(smumgr->backend);
1011		smumgr->backend = NULL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1012	}
1013	return 0;
1014}
1015
1016static const struct pp_smumgr_func fiji_smu_funcs = {
1017	.smu_init = &fiji_smu_init,
1018	.smu_fini = &fiji_smu_fini,
1019	.start_smu = &fiji_start_smu,
1020	.check_fw_load_finish = &fiji_check_fw_load_finish,
1021	.request_smu_load_fw = &fiji_reload_firmware,
1022	.request_smu_load_specific_fw = &fiji_request_smu_specific_fw_load,
1023	.send_msg_to_smc = &fiji_send_msg_to_smc,
1024	.send_msg_to_smc_with_parameter = &fiji_send_msg_to_smc_with_parameter,
1025	.download_pptable_settings = NULL,
1026	.upload_pptable_settings = NULL,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1027};
1028
1029int fiji_smum_init(struct pp_smumgr *smumgr)
1030{
1031	struct fiji_smumgr *fiji_smu = NULL;
1032
1033	fiji_smu = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL);
1034
1035	if (fiji_smu == NULL)
1036		return -ENOMEM;
1037
1038	smumgr->backend = fiji_smu;
1039	smumgr->smumgr_funcs = &fiji_smu_funcs;
1040
1041	return 0;
1042}
v4.17
   1/*
   2 * Copyright 2015 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 "pp_debug.h"
  25#include "smumgr.h"
  26#include "smu7_dyn_defaults.h"
  27#include "smu73.h"
  28#include "smu_ucode_xfer_vi.h"
  29#include "fiji_smumgr.h"
  30#include "fiji_ppsmc.h"
  31#include "smu73_discrete.h"
  32#include "ppatomctrl.h"
  33#include "smu/smu_7_1_3_d.h"
  34#include "smu/smu_7_1_3_sh_mask.h"
  35#include "gmc/gmc_8_1_d.h"
  36#include "gmc/gmc_8_1_sh_mask.h"
  37#include "oss/oss_3_0_d.h"
  38#include "gca/gfx_8_0_d.h"
  39#include "bif/bif_5_0_d.h"
  40#include "bif/bif_5_0_sh_mask.h"
  41#include "dce/dce_10_0_d.h"
  42#include "dce/dce_10_0_sh_mask.h"
  43#include "hardwaremanager.h"
  44#include "cgs_common.h"
  45#include "atombios.h"
  46#include "pppcielanes.h"
  47#include "hwmgr.h"
  48#include "smu7_hwmgr.h"
  49
  50
  51#define AVFS_EN_MSB                                        1568
  52#define AVFS_EN_LSB                                        1568
  53
  54#define FIJI_SMC_SIZE 0x20000
  55
  56#define VOLTAGE_SCALE 4
  57#define POWERTUNE_DEFAULT_SET_MAX    1
  58#define VOLTAGE_VID_OFFSET_SCALE1   625
  59#define VOLTAGE_VID_OFFSET_SCALE2   100
  60#define VDDC_VDDCI_DELTA            300
  61#define MC_CG_ARB_FREQ_F1           0x0b
  62
  63/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs
  64 * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ]
  65 */
  66static const uint16_t fiji_clock_stretcher_lookup_table[2][4] = {
  67				{600, 1050, 3, 0}, {600, 1050, 6, 1} };
  68
  69/* [FF, SS] type, [] 4 voltage ranges, and
  70 * [Floor Freq, Boundary Freq, VID min , VID max]
  71 */
  72static const uint32_t fiji_clock_stretcher_ddt_table[2][4][4] = {
  73	{ {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
  74	{ {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
  75
  76/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%]
  77 * (coming from PWR_CKS_CNTL.stretch_amount reg spec)
  78 */
  79static const uint8_t fiji_clock_stretch_amount_conversion[2][6] = {
  80				{0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} };
  81
  82static const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
  83		/*sviLoadLIneEn,  SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */
  84		{1,               0xF,             0xFD,
  85		/* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */
  86		0x19,        5,               45}
  87};
  88
  89static const struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = {
  90		/*  Min        Sclk       pcie     DeepSleep Activity  CgSpll      CgSpll    spllSpread  SpllSpread   CcPwr  CcPwr  Sclk   Display     Enabled     Enabled                       Voltage    Power */
  91		/* Voltage,  Frequency,  DpmLevel,  DivId,    Level,  FuncCntl3,  FuncCntl4,  Spectrum,   Spectrum2,  DynRm, DynRm1  Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */
  92		{ 0x3c0fd047, 0x30750000,   0x00,     0x03,   0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000,   0,      0,   0x16,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  93		{ 0xa00fd047, 0x409c0000,   0x01,     0x04,   0x1e00, 0x00800510, 0x87020000, 0x21680000, 0x11000000,   0,      0,   0x16,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  94		{ 0x0410d047, 0x50c30000,   0x01,     0x00,   0x1e00, 0x00600410, 0x87020000, 0x21680000, 0x0d000000,   0,      0,   0x0e,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  95		{ 0x6810d047, 0x60ea0000,   0x01,     0x00,   0x1e00, 0x00800410, 0x87020000, 0x21680000, 0x0e000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  96		{ 0xcc10d047, 0xe8fd0000,   0x01,     0x00,   0x1e00, 0x00e00410, 0x87020000, 0x21680000, 0x0f000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  97		{ 0x3011d047, 0x70110100,   0x01,     0x00,   0x1e00, 0x00400510, 0x87020000, 0x21680000, 0x10000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  98		{ 0x9411d047, 0xf8240100,   0x01,     0x00,   0x1e00, 0x00a00510, 0x87020000, 0x21680000, 0x11000000,   0,      0,   0x0c,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
  99		{ 0xf811d047, 0x80380100,   0x01,     0x00,   0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000,   0,      0,   0x0c,   0x01,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 }
 100};
 101
 102static int fiji_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr)
 103{
 104	int result = 0;
 105
 106	/* Wait for smc boot up */
 107	/* PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
 108		RCU_UC_EVENTS, boot_seq_done, 0); */
 109
 110	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 111			SMC_SYSCON_RESET_CNTL, rst_reg, 1);
 112
 113	result = smu7_upload_smu_firmware_image(hwmgr);
 114	if (result)
 115		return result;
 116
 117	/* Clear status */
 118	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
 119			ixSMU_STATUS, 0);
 120
 121	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 122			SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
 123
 124	/* De-assert reset */
 125	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 126			SMC_SYSCON_RESET_CNTL, rst_reg, 0);
 127
 128	/* Wait for ROM firmware to initialize interrupt hendler */
 129	/*SMUM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, SMC_IND,
 130			SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */
 131
 132	/* Set SMU Auto Start */
 133	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 134			SMU_INPUT_DATA, AUTO_START, 1);
 135
 136	/* Clear firmware interrupt enable flag */
 137	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
 138			ixFIRMWARE_FLAGS, 0);
 139
 140	PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS,
 141			INTERRUPTS_ENABLED, 1);
 142
 143	cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, 0x20000);
 144	cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test);
 145	PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
 146
 147	/* Wait for done bit to be set */
 148	PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
 149			SMU_STATUS, SMU_DONE, 0);
 150
 151	/* Check pass/failed indicator */
 152	if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 153			SMU_STATUS, SMU_PASS) != 1) {
 154		PP_ASSERT_WITH_CODE(false,
 155				"SMU Firmware start failed!", return -1);
 156	}
 157
 158	/* Wait for firmware to initialize */
 159	PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND,
 160			FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
 161
 162	return result;
 163}
 164
 165static int fiji_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr)
 166{
 167	int result = 0;
 168
 169	/* wait for smc boot up */
 170	PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
 171			RCU_UC_EVENTS, boot_seq_done, 0);
 172
 173	/* Clear firmware interrupt enable flag */
 174	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
 175			ixFIRMWARE_FLAGS, 0);
 176
 177	/* Assert reset */
 178	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 179			SMC_SYSCON_RESET_CNTL, rst_reg, 1);
 180
 181	result = smu7_upload_smu_firmware_image(hwmgr);
 182	if (result)
 183		return result;
 184
 185	/* Set smc instruct start point at 0x0 */
 186	smu7_program_jump_on_start(hwmgr);
 187
 188	/* Enable clock */
 189	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 190			SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
 191
 192	/* De-assert reset */
 193	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 194			SMC_SYSCON_RESET_CNTL, rst_reg, 0);
 195
 196	/* Wait for firmware to initialize */
 197	PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND,
 198			FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
 199
 200	return result;
 201}
 202
 203static int fiji_start_avfs_btc(struct pp_hwmgr *hwmgr)
 204{
 205	int result = 0;
 206	struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 207
 208	if (0 != smu_data->avfs_btc_param) {
 209		if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr,
 210				PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param)) {
 211			pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed");
 212			result = -EINVAL;
 213		}
 214	}
 215	/* Soft-Reset to reset the engine before loading uCode */
 216	 /* halt */
 217	cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000);
 218	/* reset everything */
 219	cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0xffffffff);
 220	/* clear reset */
 221	cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0);
 222
 223	return result;
 224}
 225
 226static int fiji_setup_graphics_level_structure(struct pp_hwmgr *hwmgr)
 227{
 228	int32_t vr_config;
 229	uint32_t table_start;
 230	uint32_t level_addr, vr_config_addr;
 231	uint32_t level_size = sizeof(avfs_graphics_level);
 232
 233	PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr,
 234			SMU7_FIRMWARE_HEADER_LOCATION +
 235			offsetof(SMU73_Firmware_Header, DpmTable),
 236			&table_start, 0x40000),
 237			"[AVFS][Fiji_SetupGfxLvlStruct] SMU could not "
 238			"communicate starting address of DPM table",
 239			return -1;);
 240
 241	/* Default value for vr_config =
 242	 * VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */
 243	vr_config = 0x01000500;   /* Real value:0x50001 */
 244
 245	vr_config_addr = table_start +
 246			offsetof(SMU73_Discrete_DpmTable, VRConfig);
 247
 248	PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, vr_config_addr,
 249			(uint8_t *)&vr_config, sizeof(int32_t), 0x40000),
 250			"[AVFS][Fiji_SetupGfxLvlStruct] Problems copying "
 251			"vr_config value over to SMC",
 252			return -1;);
 253
 254	level_addr = table_start + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel);
 255
 256	PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, level_addr,
 257			(uint8_t *)(&avfs_graphics_level), level_size, 0x40000),
 258			"[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!",
 259			return -1;);
 260
 261	return 0;
 262}
 263
 264static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr)
 265{
 266	if (!hwmgr->avfs_supported)
 267		return 0;
 268
 269	PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr),
 270			"[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level"
 271			" table over to SMU",
 272			return -EINVAL);
 273	PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr),
 274			"[AVFS][fiji_avfs_event_mgr] Could not setup "
 275			"Pwr Virus for AVFS ",
 276			return -EINVAL);
 277	PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr),
 278			"[AVFS][fiji_avfs_event_mgr] Failure at "
 279			"fiji_start_avfs_btc. AVFS Disabled",
 280			return -EINVAL);
 281
 282	return 0;
 283}
 284
 285static int fiji_start_smu(struct pp_hwmgr *hwmgr)
 286{
 287	int result = 0;
 288	struct fiji_smumgr *priv = (struct fiji_smumgr *)(hwmgr->smu_backend);
 289
 290	/* Only start SMC if SMC RAM is not running */
 291	if (!(smu7_is_smc_ram_running(hwmgr)
 292		|| cgs_is_virtualization_enabled(hwmgr->device))) {
 293		/* Check if SMU is running in protected mode */
 294		if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
 295				CGS_IND_REG__SMC,
 296				SMU_FIRMWARE, SMU_MODE)) {
 297			result = fiji_start_smu_in_non_protection_mode(hwmgr);
 298			if (result)
 299				return result;
 300		} else {
 301			result = fiji_start_smu_in_protection_mode(hwmgr);
 302			if (result)
 303				return result;
 304		}
 305		if (fiji_avfs_event_mgr(hwmgr))
 306			hwmgr->avfs_supported = false;
 307	}
 308
 309	/* To initialize all clock gating before RLC loaded and running.*/
 310	cgs_set_clockgating_state(hwmgr->device,
 311			AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_GATE);
 312	cgs_set_clockgating_state(hwmgr->device,
 313			AMD_IP_BLOCK_TYPE_GMC, AMD_CG_STATE_GATE);
 314	cgs_set_clockgating_state(hwmgr->device,
 315			AMD_IP_BLOCK_TYPE_SDMA, AMD_CG_STATE_GATE);
 316	cgs_set_clockgating_state(hwmgr->device,
 317			AMD_IP_BLOCK_TYPE_COMMON, AMD_CG_STATE_GATE);
 318
 319	/* Setup SoftRegsStart here for register lookup in case
 320	 * DummyBackEnd is used and ProcessFirmwareHeader is not executed
 321	 */
 322	smu7_read_smc_sram_dword(hwmgr,
 323			SMU7_FIRMWARE_HEADER_LOCATION +
 324			offsetof(SMU73_Firmware_Header, SoftRegisters),
 325			&(priv->smu7_data.soft_regs_start), 0x40000);
 326
 327	result = smu7_request_smu_load_fw(hwmgr);
 328
 329	return result;
 330}
 331
 332static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr)
 333{
 334
 335	uint32_t efuse = 0;
 336	uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1;
 337
 338	if (cgs_is_virtualization_enabled(hwmgr->device))
 339		return 0;
 340
 341	if (!atomctrl_read_efuse(hwmgr->device, AVFS_EN_LSB, AVFS_EN_MSB,
 342			mask, &efuse)) {
 343		if (efuse)
 344			return true;
 345	}
 346	return false;
 347}
 348
 349static int fiji_smu_init(struct pp_hwmgr *hwmgr)
 350{
 351	struct fiji_smumgr *fiji_priv = NULL;
 352
 353	fiji_priv = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL);
 354
 355	if (fiji_priv == NULL)
 356		return -ENOMEM;
 357
 358	hwmgr->smu_backend = fiji_priv;
 359
 360	if (smu7_init(hwmgr)) {
 361		kfree(fiji_priv);
 362		return -EINVAL;
 363	}
 364
 365	return 0;
 366}
 367
 368static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
 369		struct phm_ppt_v1_clock_voltage_dependency_table *dep_table,
 370		uint32_t clock, uint32_t *voltage, uint32_t *mvdd)
 371{
 372	uint32_t i;
 373	uint16_t vddci;
 374	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 375	*voltage = *mvdd = 0;
 376
 377
 378	/* clock - voltage dependency table is empty table */
 379	if (dep_table->count == 0)
 380		return -EINVAL;
 381
 382	for (i = 0; i < dep_table->count; i++) {
 383		/* find first sclk bigger than request */
 384		if (dep_table->entries[i].clk >= clock) {
 385			*voltage |= (dep_table->entries[i].vddc *
 386					VOLTAGE_SCALE) << VDDC_SHIFT;
 387			if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
 388				*voltage |= (data->vbios_boot_state.vddci_bootup_value *
 389						VOLTAGE_SCALE) << VDDCI_SHIFT;
 390			else if (dep_table->entries[i].vddci)
 391				*voltage |= (dep_table->entries[i].vddci *
 392						VOLTAGE_SCALE) << VDDCI_SHIFT;
 393			else {
 394				vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
 395						(dep_table->entries[i].vddc -
 396								VDDC_VDDCI_DELTA));
 397				*voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
 398			}
 399
 400			if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control)
 401				*mvdd = data->vbios_boot_state.mvdd_bootup_value *
 402					VOLTAGE_SCALE;
 403			else if (dep_table->entries[i].mvdd)
 404				*mvdd = (uint32_t) dep_table->entries[i].mvdd *
 405					VOLTAGE_SCALE;
 406
 407			*voltage |= 1 << PHASES_SHIFT;
 408			return 0;
 409		}
 410	}
 411
 412	/* sclk is bigger than max sclk in the dependence table */
 413	*voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
 414
 415	if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
 416		*voltage |= (data->vbios_boot_state.vddci_bootup_value *
 417				VOLTAGE_SCALE) << VDDCI_SHIFT;
 418	else if (dep_table->entries[i-1].vddci) {
 419		vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
 420				(dep_table->entries[i].vddc -
 421						VDDC_VDDCI_DELTA));
 422		*voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
 423	}
 424
 425	if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control)
 426		*mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE;
 427	else if (dep_table->entries[i].mvdd)
 428		*mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE;
 429
 430	return 0;
 431}
 432
 433
 434static uint16_t scale_fan_gain_settings(uint16_t raw_setting)
 435{
 436	uint32_t tmp;
 437	tmp = raw_setting * 4096 / 100;
 438	return (uint16_t)tmp;
 439}
 440
 441static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t *sda)
 442{
 443	switch (line) {
 444	case SMU7_I2CLineID_DDC1:
 445		*scl = SMU7_I2C_DDC1CLK;
 446		*sda = SMU7_I2C_DDC1DATA;
 447		break;
 448	case SMU7_I2CLineID_DDC2:
 449		*scl = SMU7_I2C_DDC2CLK;
 450		*sda = SMU7_I2C_DDC2DATA;
 451		break;
 452	case SMU7_I2CLineID_DDC3:
 453		*scl = SMU7_I2C_DDC3CLK;
 454		*sda = SMU7_I2C_DDC3DATA;
 455		break;
 456	case SMU7_I2CLineID_DDC4:
 457		*scl = SMU7_I2C_DDC4CLK;
 458		*sda = SMU7_I2C_DDC4DATA;
 459		break;
 460	case SMU7_I2CLineID_DDC5:
 461		*scl = SMU7_I2C_DDC5CLK;
 462		*sda = SMU7_I2C_DDC5DATA;
 463		break;
 464	case SMU7_I2CLineID_DDC6:
 465		*scl = SMU7_I2C_DDC6CLK;
 466		*sda = SMU7_I2C_DDC6DATA;
 467		break;
 468	case SMU7_I2CLineID_SCLSDA:
 469		*scl = SMU7_I2C_SCL;
 470		*sda = SMU7_I2C_SDA;
 471		break;
 472	case SMU7_I2CLineID_DDCVGA:
 473		*scl = SMU7_I2C_DDCVGACLK;
 474		*sda = SMU7_I2C_DDCVGADATA;
 475		break;
 476	default:
 477		*scl = 0;
 478		*sda = 0;
 479		break;
 480	}
 
 
 481}
 
 
 
 
 
 
 
 
 
 
 
 
 482
 483static void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
 484{
 485	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 486	struct phm_ppt_v1_information *table_info =
 487			(struct  phm_ppt_v1_information *)(hwmgr->pptable);
 488
 489	if (table_info &&
 490			table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX &&
 491			table_info->cac_dtp_table->usPowerTuneDataSetID)
 492		smu_data->power_tune_defaults =
 493				&fiji_power_tune_data_set_array
 494				[table_info->cac_dtp_table->usPowerTuneDataSetID - 1];
 495	else
 496		smu_data->power_tune_defaults = &fiji_power_tune_data_set_array[0];
 497
 
 498}
 499
 500static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
 
 
 
 
 
 
 
 
 
 
 501{
 
 
 
 502
 503	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 504	const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults;
 
 
 505
 506	SMU73_Discrete_DpmTable  *dpm_table = &(smu_data->smc_state_table);
 507
 508	struct phm_ppt_v1_information *table_info =
 509			(struct phm_ppt_v1_information *)(hwmgr->pptable);
 510	struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table;
 511	struct pp_advance_fan_control_parameters *fan_table =
 512			&hwmgr->thermal_controller.advanceFanControlParameters;
 513	uint8_t uc_scl, uc_sda;
 514
 515	/* TDP number of fraction bits are changed from 8 to 7 for Fiji
 516	 * as requested by SMC team
 517	 */
 518	dpm_table->DefaultTdp = PP_HOST_TO_SMC_US(
 519			(uint16_t)(cac_dtp_table->usTDP * 128));
 520	dpm_table->TargetTdp = PP_HOST_TO_SMC_US(
 521			(uint16_t)(cac_dtp_table->usTDP * 128));
 522
 523	PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
 524			"Target Operating Temp is out of Range!",
 525			);
 526
 527	dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp);
 528	dpm_table->GpuTjHyst = 8;
 529
 530	dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase;
 531
 532	/* The following are for new Fiji Multi-input fan/thermal control */
 533	dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US(
 534			cac_dtp_table->usTargetOperatingTemp * 256);
 535	dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US(
 536			cac_dtp_table->usTemperatureLimitHotspot * 256);
 537	dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US(
 538			cac_dtp_table->usTemperatureLimitLiquid1 * 256);
 539	dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US(
 540			cac_dtp_table->usTemperatureLimitLiquid2 * 256);
 541	dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US(
 542			cac_dtp_table->usTemperatureLimitVrVddc * 256);
 543	dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US(
 544			cac_dtp_table->usTemperatureLimitVrMvdd * 256);
 545	dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US(
 546			cac_dtp_table->usTemperatureLimitPlx * 256);
 547
 548	dpm_table->FanGainEdge = PP_HOST_TO_SMC_US(
 549			scale_fan_gain_settings(fan_table->usFanGainEdge));
 550	dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US(
 551			scale_fan_gain_settings(fan_table->usFanGainHotspot));
 552	dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US(
 553			scale_fan_gain_settings(fan_table->usFanGainLiquid));
 554	dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US(
 555			scale_fan_gain_settings(fan_table->usFanGainVrVddc));
 556	dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US(
 557			scale_fan_gain_settings(fan_table->usFanGainVrMvdd));
 558	dpm_table->FanGainPlx = PP_HOST_TO_SMC_US(
 559			scale_fan_gain_settings(fan_table->usFanGainPlx));
 560	dpm_table->FanGainHbm = PP_HOST_TO_SMC_US(
 561			scale_fan_gain_settings(fan_table->usFanGainHbm));
 562
 563	dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address;
 564	dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address;
 565	dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address;
 566	dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address;
 567
 568	get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda);
 569	dpm_table->Liquid_I2C_LineSCL = uc_scl;
 570	dpm_table->Liquid_I2C_LineSDA = uc_sda;
 571
 572	get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda);
 573	dpm_table->Vr_I2C_LineSCL = uc_scl;
 574	dpm_table->Vr_I2C_LineSDA = uc_sda;
 575
 576	get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda);
 577	dpm_table->Plx_I2C_LineSCL = uc_scl;
 578	dpm_table->Plx_I2C_LineSDA = uc_sda;
 579
 580	return 0;
 581}
 582
 
 
 
 
 583
 584static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr)
 585{
 586	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 587	const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults;
 
 588
 589	smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn;
 590	smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC;
 591	smu_data->power_tune_table.SviLoadLineTrimVddC = 3;
 592	smu_data->power_tune_table.SviLoadLineOffsetVddC = 0;
 593
 594	return 0;
 595}
 596
 
 
 
 
 
 
 
 
 
 597
 598static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr)
 599{
 600	uint16_t tdc_limit;
 601	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 602	struct phm_ppt_v1_information *table_info =
 603			(struct phm_ppt_v1_information *)(hwmgr->pptable);
 604	const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults;
 605
 606	/* TDC number of fraction bits are changed from 8 to 7
 607	 * for Fiji as requested by SMC team
 608	 */
 609	tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128);
 610	smu_data->power_tune_table.TDC_VDDC_PkgLimit =
 611			CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
 612	smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
 613			defaults->TDC_VDDC_ThrottleReleaseLimitPerc;
 614	smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt;
 615
 616	return 0;
 617}
 618
 619static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
 620{
 621	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 622	const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults;
 623	uint32_t temp;
 624
 625	if (smu7_read_smc_sram_dword(hwmgr,
 626			fuse_table_offset +
 627			offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl),
 628			(uint32_t *)&temp, SMC_RAM_END))
 629		PP_ASSERT_WITH_CODE(false,
 630				"Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
 631				return -EINVAL);
 632	else {
 633		smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl;
 634		smu_data->power_tune_table.LPMLTemperatureMin =
 635				(uint8_t)((temp >> 16) & 0xff);
 636		smu_data->power_tune_table.LPMLTemperatureMax =
 637				(uint8_t)((temp >> 8) & 0xff);
 638		smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff);
 639	}
 640	return 0;
 641}
 642
 643static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
 644{
 645	int i;
 646	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 647
 648	/* Currently not used. Set all to zero. */
 649	for (i = 0; i < 16; i++)
 650		smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0;
 651
 652	return 0;
 653}
 654
 655static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
 656{
 657	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 658
 659	if ((hwmgr->thermal_controller.advanceFanControlParameters.
 660			usFanOutputSensitivity & (1 << 15)) ||
 661			0 == hwmgr->thermal_controller.advanceFanControlParameters.
 662			usFanOutputSensitivity)
 663		hwmgr->thermal_controller.advanceFanControlParameters.
 664		usFanOutputSensitivity = hwmgr->thermal_controller.
 665			advanceFanControlParameters.usDefaultFanOutputSensitivity;
 666
 667	smu_data->power_tune_table.FuzzyFan_PwmSetDelta =
 668			PP_HOST_TO_SMC_US(hwmgr->thermal_controller.
 669					advanceFanControlParameters.usFanOutputSensitivity);
 670	return 0;
 671}
 672
 673static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
 674{
 675	int i;
 676	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 
 
 
 
 
 
 
 
 
 
 
 
 677
 678	/* Currently not used. Set all to zero. */
 679	for (i = 0; i < 16; i++)
 680		smu_data->power_tune_table.GnbLPML[i] = 0;
 681
 682	return 0;
 683}
 684
 685static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
 
 
 
 
 
 
 
 
 686{
 687	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 688	struct phm_ppt_v1_information *table_info =
 689			(struct phm_ppt_v1_information *)(hwmgr->pptable);
 690	uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd;
 691	uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd;
 692	struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
 693
 694	HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
 695	LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
 696
 697	smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd =
 698			CONVERT_FROM_HOST_TO_SMC_US(HiSidd);
 699	smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd =
 700			CONVERT_FROM_HOST_TO_SMC_US(LoSidd);
 701
 702	return 0;
 703}
 
 
 704
 705static int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr)
 706{
 707	uint32_t pm_fuse_table_offset;
 708	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 709
 710	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 711			PHM_PlatformCaps_PowerContainment)) {
 712		if (smu7_read_smc_sram_dword(hwmgr,
 713				SMU7_FIRMWARE_HEADER_LOCATION +
 714				offsetof(SMU73_Firmware_Header, PmFuseTable),
 715				&pm_fuse_table_offset, SMC_RAM_END))
 716			PP_ASSERT_WITH_CODE(false,
 717					"Attempt to get pm_fuse_table_offset Failed!",
 718					return -EINVAL);
 719
 720		/* DW6 */
 721		if (fiji_populate_svi_load_line(hwmgr))
 722			PP_ASSERT_WITH_CODE(false,
 723					"Attempt to populate SviLoadLine Failed!",
 724					return -EINVAL);
 725		/* DW7 */
 726		if (fiji_populate_tdc_limit(hwmgr))
 727			PP_ASSERT_WITH_CODE(false,
 728					"Attempt to populate TDCLimit Failed!", return -EINVAL);
 729		/* DW8 */
 730		if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset))
 731			PP_ASSERT_WITH_CODE(false,
 732					"Attempt to populate TdcWaterfallCtl, "
 733					"LPMLTemperature Min and Max Failed!",
 734					return -EINVAL);
 735
 736		/* DW9-DW12 */
 737		if (0 != fiji_populate_temperature_scaler(hwmgr))
 738			PP_ASSERT_WITH_CODE(false,
 739					"Attempt to populate LPMLTemperatureScaler Failed!",
 740					return -EINVAL);
 741
 742		/* DW13-DW14 */
 743		if (fiji_populate_fuzzy_fan(hwmgr))
 744			PP_ASSERT_WITH_CODE(false,
 745					"Attempt to populate Fuzzy Fan Control parameters Failed!",
 746					return -EINVAL);
 747
 748		/* DW15-DW18 */
 749		if (fiji_populate_gnb_lpml(hwmgr))
 750			PP_ASSERT_WITH_CODE(false,
 751					"Attempt to populate GnbLPML Failed!",
 752					return -EINVAL);
 753
 754		/* DW20 */
 755		if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr))
 756			PP_ASSERT_WITH_CODE(false,
 757					"Attempt to populate BapmVddCBaseLeakage Hi and Lo "
 758					"Sidd Failed!", return -EINVAL);
 759
 760		if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset,
 761				(uint8_t *)&smu_data->power_tune_table,
 762				sizeof(struct SMU73_Discrete_PmFuses), SMC_RAM_END))
 763			PP_ASSERT_WITH_CODE(false,
 764					"Attempt to download PmFuseTable Failed!",
 765					return -EINVAL);
 766	}
 767	return 0;
 768}
 769
 770static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr,
 771		struct SMU73_Discrete_DpmTable *table)
 772{
 773	uint32_t count;
 774	uint8_t index;
 775	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 776	struct phm_ppt_v1_information *table_info =
 777			(struct phm_ppt_v1_information *)(hwmgr->pptable);
 778	struct phm_ppt_v1_voltage_lookup_table *lookup_table =
 779			table_info->vddc_lookup_table;
 780	/* tables is already swapped, so in order to use the value from it,
 781	 * we need to swap it back.
 782	 * We are populating vddc CAC data to BapmVddc table
 783	 * in split and merged mode
 784	 */
 785
 786	for (count = 0; count < lookup_table->count; count++) {
 787		index = phm_get_voltage_index(lookup_table,
 788				data->vddc_voltage_table.entries[count].value);
 789		table->BapmVddcVidLoSidd[count] =
 790			convert_to_vid(lookup_table->entries[index].us_cac_low);
 791		table->BapmVddcVidHiSidd[count] =
 792			convert_to_vid(lookup_table->entries[index].us_cac_high);
 
 
 
 
 
 
 
 793	}
 
 
 794
 795	return 0;
 796}
 797
 798static int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
 799		struct SMU73_Discrete_DpmTable *table)
 800{
 801	int result;
 
 
 
 
 
 
 
 
 
 802
 803	result = fiji_populate_cac_table(hwmgr, table);
 804	PP_ASSERT_WITH_CODE(0 == result,
 805			"can not populate CAC voltage tables to SMC",
 806			return -EINVAL);
 807
 808	return 0;
 809}
 
 
 810
 811static int fiji_populate_ulv_level(struct pp_hwmgr *hwmgr,
 812		struct SMU73_Discrete_Ulv *state)
 813{
 814	int result = 0;
 815
 816	struct phm_ppt_v1_information *table_info =
 817			(struct phm_ppt_v1_information *)(hwmgr->pptable);
 818
 819	state->CcPwrDynRm = 0;
 820	state->CcPwrDynRm1 = 0;
 821
 822	state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset;
 823	state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset *
 824			VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
 825
 826	state->VddcPhase = 1;
 827
 828	if (!result) {
 829		CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
 830		CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
 831		CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
 832	}
 833	return result;
 834}
 835
 836static int fiji_populate_ulv_state(struct pp_hwmgr *hwmgr,
 837		struct SMU73_Discrete_DpmTable *table)
 838{
 839	return fiji_populate_ulv_level(hwmgr, &table->Ulv);
 840}
 841
 842static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr,
 843		struct SMU73_Discrete_DpmTable *table)
 844{
 845	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 846	struct smu7_dpm_table *dpm_table = &data->dpm_table;
 847	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 848	int i;
 849
 850	/* Index (dpm_table->pcie_speed_table.count)
 851	 * is reserved for PCIE boot level. */
 852	for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
 853		table->LinkLevel[i].PcieGenSpeed  =
 854				(uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
 855		table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width(
 856				dpm_table->pcie_speed_table.dpm_levels[i].param1);
 857		table->LinkLevel[i].EnabledForActivity = 1;
 858		table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff);
 859		table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5);
 860		table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30);
 861	}
 862
 863	smu_data->smc_state_table.LinkLevelCount =
 864			(uint8_t)dpm_table->pcie_speed_table.count;
 865	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
 866			phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
 867
 
 868	return 0;
 869}
 870
 871static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr,
 872		uint32_t clock, struct SMU73_Discrete_GraphicsLevel *sclk)
 
 
 
 
 
 
 
 873{
 874	const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 875	struct pp_atomctrl_clock_dividers_vi dividers;
 876	uint32_t spll_func_cntl            = data->clock_registers.vCG_SPLL_FUNC_CNTL;
 877	uint32_t spll_func_cntl_3          = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
 878	uint32_t spll_func_cntl_4          = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
 879	uint32_t cg_spll_spread_spectrum   = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
 880	uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
 881	uint32_t ref_clock;
 882	uint32_t ref_divider;
 883	uint32_t fbdiv;
 884	int result;
 885
 886	/* get the engine clock dividers for this clock value */
 887	result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock,  &dividers);
 888
 889	PP_ASSERT_WITH_CODE(result == 0,
 890			"Error retrieving Engine Clock dividers from VBIOS.",
 891			return result);
 892
 893	/* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */
 894	ref_clock = atomctrl_get_reference_clock(hwmgr);
 895	ref_divider = 1 + dividers.uc_pll_ref_div;
 896
 897	/* low 14 bits is fraction and high 12 bits is divider */
 898	fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
 899
 900	/* SPLL_FUNC_CNTL setup */
 901	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
 902			SPLL_REF_DIV, dividers.uc_pll_ref_div);
 903	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
 904			SPLL_PDIV_A,  dividers.uc_pll_post_div);
 905
 906	/* SPLL_FUNC_CNTL_3 setup*/
 907	spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3,
 908			SPLL_FB_DIV, fbdiv);
 909
 910	/* set to use fractional accumulation*/
 911	spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3,
 912			SPLL_DITHEN, 1);
 913
 914	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 915				PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
 916		struct pp_atomctrl_internal_ss_info ssInfo;
 917
 918		uint32_t vco_freq = clock * dividers.uc_pll_post_div;
 919		if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr,
 920				vco_freq, &ssInfo)) {
 921			/*
 922			 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
 923			 * ss_info.speed_spectrum_rate -- in unit of khz
 924			 *
 925			 * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2
 926			 */
 927			uint32_t clk_s = ref_clock * 5 /
 928					(ref_divider * ssInfo.speed_spectrum_rate);
 929			/* clkv = 2 * D * fbdiv / NS */
 930			uint32_t clk_v = 4 * ssInfo.speed_spectrum_percentage *
 931					fbdiv / (clk_s * 10000);
 932
 933			cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum,
 934					CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s);
 935			cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum,
 936					CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
 937			cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2,
 938					CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v);
 939		}
 940	}
 941
 942	sclk->SclkFrequency        = clock;
 943	sclk->CgSpllFuncCntl3      = spll_func_cntl_3;
 944	sclk->CgSpllFuncCntl4      = spll_func_cntl_4;
 945	sclk->SpllSpreadSpectrum   = cg_spll_spread_spectrum;
 946	sclk->SpllSpreadSpectrum2  = cg_spll_spread_spectrum_2;
 947	sclk->SclkDid              = (uint8_t)dividers.pll_post_divider;
 948
 
 949	return 0;
 950}
 951
 952static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
 953		uint32_t clock, struct SMU73_Discrete_GraphicsLevel *level)
 
 
 
 
 
 
 
 954{
 955	int result;
 956	/* PP_Clocks minClocks; */
 957	uint32_t threshold, mvdd;
 958	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 959	struct phm_ppt_v1_information *table_info =
 960			(struct phm_ppt_v1_information *)(hwmgr->pptable);
 961	phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
 962
 963	result = fiji_calculate_sclk_params(hwmgr, clock, level);
 964
 965	if (hwmgr->od_enabled)
 966		vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk;
 967	else
 968		vdd_dep_table = table_info->vdd_dep_on_sclk;
 969
 970	/* populate graphics levels */
 971	result = fiji_get_dependency_volt_by_clk(hwmgr,
 972			vdd_dep_table, clock,
 973			(uint32_t *)(&level->MinVoltage), &mvdd);
 974	PP_ASSERT_WITH_CODE((0 == result),
 975			"can not find VDDC voltage value for "
 976			"VDDC engine clock dependency table",
 977			return result);
 978
 979	level->SclkFrequency = clock;
 980	level->ActivityLevel = data->current_profile_setting.sclk_activity;
 981	level->CcPwrDynRm = 0;
 982	level->CcPwrDynRm1 = 0;
 983	level->EnabledForActivity = 0;
 984	level->EnabledForThrottle = 1;
 985	level->UpHyst = data->current_profile_setting.sclk_up_hyst;
 986	level->DownHyst = data->current_profile_setting.sclk_down_hyst;
 987	level->VoltageDownHyst = 0;
 988	level->PowerThrottle = 0;
 989
 990	threshold = clock * data->fast_watermark_threshold / 100;
 991
 992	data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr;
 993
 994	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
 995		level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock,
 996								hwmgr->display_config.min_core_set_clock_in_sr);
 997
 998
 999	/* Default to slow, highest DPM level will be
1000	 * set to PPSMC_DISPLAY_WATERMARK_LOW later.
1001	 */
1002	level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1003
1004	CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage);
1005	CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency);
1006	CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel);
1007	CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3);
1008	CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4);
1009	CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum);
1010	CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2);
1011	CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm);
1012	CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1);
1013
 
1014	return 0;
1015}
1016
1017static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
1018{
1019	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1020	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
1021
1022	struct smu7_dpm_table *dpm_table = &data->dpm_table;
1023	struct phm_ppt_v1_information *table_info =
1024			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1025	struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
1026	uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count;
1027	int result = 0;
1028	uint32_t array = smu_data->smu7_data.dpm_table_start +
1029			offsetof(SMU73_Discrete_DpmTable, GraphicsLevel);
1030	uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) *
1031			SMU73_MAX_LEVELS_GRAPHICS;
1032	struct SMU73_Discrete_GraphicsLevel *levels =
1033			smu_data->smc_state_table.GraphicsLevel;
1034	uint32_t i, max_entry;
1035	uint8_t hightest_pcie_level_enabled = 0,
1036			lowest_pcie_level_enabled = 0,
1037			mid_pcie_level_enabled = 0,
1038			count = 0;
1039
1040	for (i = 0; i < dpm_table->sclk_table.count; i++) {
1041		result = fiji_populate_single_graphic_level(hwmgr,
1042				dpm_table->sclk_table.dpm_levels[i].value,
1043				&levels[i]);
1044		if (result)
1045			return result;
1046
1047		/* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
1048		if (i > 1)
1049			levels[i].DeepSleepDivId = 0;
1050	}
1051
1052	/* Only enable level 0 for now.*/
1053	levels[0].EnabledForActivity = 1;
1054
1055	/* set highest level watermark to high */
1056	levels[dpm_table->sclk_table.count - 1].DisplayWatermark =
1057			PPSMC_DISPLAY_WATERMARK_HIGH;
1058
1059	smu_data->smc_state_table.GraphicsDpmLevelCount =
1060			(uint8_t)dpm_table->sclk_table.count;
1061	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
1062			phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
1063
1064	if (pcie_table != NULL) {
1065		PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt),
1066				"There must be 1 or more PCIE levels defined in PPTable.",
1067				return -EINVAL);
1068		max_entry = pcie_entry_cnt - 1;
1069		for (i = 0; i < dpm_table->sclk_table.count; i++)
1070			levels[i].pcieDpmLevel =
1071					(uint8_t) ((i < max_entry) ? i : max_entry);
1072	} else {
1073		while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
1074				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
1075						(1 << (hightest_pcie_level_enabled + 1))) != 0))
1076			hightest_pcie_level_enabled++;
1077
1078		while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
1079				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
1080						(1 << lowest_pcie_level_enabled)) == 0))
1081			lowest_pcie_level_enabled++;
1082
1083		while ((count < hightest_pcie_level_enabled) &&
1084				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
1085						(1 << (lowest_pcie_level_enabled + 1 + count))) == 0))
1086			count++;
1087
1088		mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) <
1089				hightest_pcie_level_enabled ?
1090						(lowest_pcie_level_enabled + 1 + count) :
1091						hightest_pcie_level_enabled;
1092
1093		/* set pcieDpmLevel to hightest_pcie_level_enabled */
1094		for (i = 2; i < dpm_table->sclk_table.count; i++)
1095			levels[i].pcieDpmLevel = hightest_pcie_level_enabled;
1096
1097		/* set pcieDpmLevel to lowest_pcie_level_enabled */
1098		levels[0].pcieDpmLevel = lowest_pcie_level_enabled;
1099
1100		/* set pcieDpmLevel to mid_pcie_level_enabled */
1101		levels[1].pcieDpmLevel = mid_pcie_level_enabled;
1102	}
1103	/* level count will send to smc once at init smc table and never change */
1104	result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
1105			(uint32_t)array_size, SMC_RAM_END);
1106
1107	return result;
1108}
1109
1110
1111/**
1112 * MCLK Frequency Ratio
1113 * SEQ_CG_RESP  Bit[31:24] - 0x0
1114 * Bit[27:24] \96 DDR3 Frequency ratio
1115 * 0x0 <= 100MHz,       450 < 0x8 <= 500MHz
1116 * 100 < 0x1 <= 150MHz,       500 < 0x9 <= 550MHz
1117 * 150 < 0x2 <= 200MHz,       550 < 0xA <= 600MHz
1118 * 200 < 0x3 <= 250MHz,       600 < 0xB <= 650MHz
1119 * 250 < 0x4 <= 300MHz,       650 < 0xC <= 700MHz
1120 * 300 < 0x5 <= 350MHz,       700 < 0xD <= 750MHz
1121 * 350 < 0x6 <= 400MHz,       750 < 0xE <= 800MHz
1122 * 400 < 0x7 <= 450MHz,       800 < 0xF
1123 */
1124static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock)
1125{
1126	if (mem_clock <= 10000)
1127		return 0x0;
1128	if (mem_clock <= 15000)
1129		return 0x1;
1130	if (mem_clock <= 20000)
1131		return 0x2;
1132	if (mem_clock <= 25000)
1133		return 0x3;
1134	if (mem_clock <= 30000)
1135		return 0x4;
1136	if (mem_clock <= 35000)
1137		return 0x5;
1138	if (mem_clock <= 40000)
1139		return 0x6;
1140	if (mem_clock <= 45000)
1141		return 0x7;
1142	if (mem_clock <= 50000)
1143		return 0x8;
1144	if (mem_clock <= 55000)
1145		return 0x9;
1146	if (mem_clock <= 60000)
1147		return 0xa;
1148	if (mem_clock <= 65000)
1149		return 0xb;
1150	if (mem_clock <= 70000)
1151		return 0xc;
1152	if (mem_clock <= 75000)
1153		return 0xd;
1154	if (mem_clock <= 80000)
1155		return 0xe;
1156	/* mem_clock > 800MHz */
1157	return 0xf;
1158}
1159
1160static int fiji_calculate_mclk_params(struct pp_hwmgr *hwmgr,
1161    uint32_t clock, struct SMU73_Discrete_MemoryLevel *mclk)
1162{
1163	struct pp_atomctrl_memory_clock_param mem_param;
1164	int result;
 
1165
1166	result = atomctrl_get_memory_pll_dividers_vi(hwmgr, clock, &mem_param);
1167	PP_ASSERT_WITH_CODE((0 == result),
1168			"Failed to get Memory PLL Dividers.",
1169			);
1170
1171	/* Save the result data to outpupt memory level structure */
1172	mclk->MclkFrequency   = clock;
1173	mclk->MclkDivider     = (uint8_t)mem_param.mpll_post_divider;
1174	mclk->FreqRange       = fiji_get_mclk_frequency_ratio(clock);
1175
1176	return result;
1177}
1178
1179static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr,
1180		uint32_t clock, struct SMU73_Discrete_MemoryLevel *mem_level)
1181{
1182	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1183	struct phm_ppt_v1_information *table_info =
1184			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1185	int result = 0;
1186	uint32_t mclk_stutter_mode_threshold = 60000;
1187	phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
1188
1189	if (hwmgr->od_enabled)
1190		vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk;
1191	else
1192		vdd_dep_table = table_info->vdd_dep_on_mclk;
1193
1194	if (vdd_dep_table) {
1195		result = fiji_get_dependency_volt_by_clk(hwmgr,
1196				vdd_dep_table, clock,
1197				(uint32_t *)(&mem_level->MinVoltage), &mem_level->MinMvdd);
1198		PP_ASSERT_WITH_CODE((0 == result),
1199				"can not find MinVddc voltage value from memory "
1200				"VDDC voltage dependency table", return result);
1201	}
1202
1203	mem_level->EnabledForThrottle = 1;
1204	mem_level->EnabledForActivity = 0;
1205	mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
1206	mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
1207	mem_level->VoltageDownHyst = 0;
1208	mem_level->ActivityLevel = data->current_profile_setting.mclk_activity;
1209	mem_level->StutterEnable = false;
1210
1211	mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1212
1213	/* enable stutter mode if all the follow condition applied
1214	 * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI,
1215	 * &(data->DisplayTiming.numExistingDisplays));
1216	 */
1217	data->display_timing.num_existing_displays = 1;
1218
1219	if (mclk_stutter_mode_threshold &&
1220		(clock <= mclk_stutter_mode_threshold) &&
1221		(!data->is_uvd_enabled) &&
1222		(PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL,
1223				STUTTER_ENABLE) & 0x1))
1224		mem_level->StutterEnable = true;
1225
1226	result = fiji_calculate_mclk_params(hwmgr, clock, mem_level);
1227	if (!result) {
1228		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd);
1229		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency);
1230		CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel);
1231		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage);
 
 
 
 
 
 
 
 
 
1232	}
1233	return result;
1234}
1235
1236static int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1237{
1238	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1239	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
1240	struct smu7_dpm_table *dpm_table = &data->dpm_table;
1241	int result;
1242	/* populate MCLK dpm table to SMU7 */
1243	uint32_t array = smu_data->smu7_data.dpm_table_start +
1244			offsetof(SMU73_Discrete_DpmTable, MemoryLevel);
1245	uint32_t array_size = sizeof(SMU73_Discrete_MemoryLevel) *
1246			SMU73_MAX_LEVELS_MEMORY;
1247	struct SMU73_Discrete_MemoryLevel *levels =
1248			smu_data->smc_state_table.MemoryLevel;
1249	uint32_t i;
1250
1251	for (i = 0; i < dpm_table->mclk_table.count; i++) {
1252		PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
1253				"can not populate memory level as memory clock is zero",
1254				return -EINVAL);
1255		result = fiji_populate_single_memory_level(hwmgr,
1256				dpm_table->mclk_table.dpm_levels[i].value,
1257				&levels[i]);
1258		if (result)
1259			return result;
1260	}
1261
1262	/* Only enable level 0 for now. */
1263	levels[0].EnabledForActivity = 1;
1264
1265	/* in order to prevent MC activity from stutter mode to push DPM up.
1266	 * the UVD change complements this by putting the MCLK in
1267	 * a higher state by default such that we are not effected by
1268	 * up threshold or and MCLK DPM latency.
1269	 */
1270	levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target;
1271	CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel);
1272
1273	smu_data->smc_state_table.MemoryDpmLevelCount =
1274			(uint8_t)dpm_table->mclk_table.count;
1275	data->dpm_level_enable_mask.mclk_dpm_enable_mask =
1276			phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
1277	/* set highest level watermark to high */
1278	levels[dpm_table->mclk_table.count - 1].DisplayWatermark =
1279			PPSMC_DISPLAY_WATERMARK_HIGH;
1280
1281	/* level count will send to smc once at init smc table and never change */
1282	result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
1283			(uint32_t)array_size, SMC_RAM_END);
1284
1285	return result;
1286}
1287
1288static int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr,
1289		uint32_t mclk, SMIO_Pattern *smio_pat)
1290{
1291	const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1292	struct phm_ppt_v1_information *table_info =
1293			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1294	uint32_t i = 0;
1295
1296	if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
1297		/* find mvdd value which clock is more than request */
1298		for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) {
1299			if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) {
1300				smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value;
1301				break;
1302			}
1303		}
1304		PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count,
1305				"MVDD Voltage is outside the supported range.",
1306				return -EINVAL);
1307	} else
1308		return -EINVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1309
1310	return 0;
1311}
1312
1313static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
1314		SMU73_Discrete_DpmTable *table)
1315{
1316	int result = 0;
1317	const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1318	struct phm_ppt_v1_information *table_info =
1319			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1320	struct pp_atomctrl_clock_dividers_vi dividers;
1321	SMIO_Pattern vol_level;
1322	uint32_t mvdd;
1323	uint16_t us_mvdd;
1324	uint32_t spll_func_cntl    = data->clock_registers.vCG_SPLL_FUNC_CNTL;
1325	uint32_t spll_func_cntl_2  = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
1326
1327	table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
1328
1329	if (!data->sclk_dpm_key_disabled) {
1330		/* Get MinVoltage and Frequency from DPM0,
1331		 * already converted to SMC_UL */
1332		table->ACPILevel.SclkFrequency =
1333				data->dpm_table.sclk_table.dpm_levels[0].value;
1334		result = fiji_get_dependency_volt_by_clk(hwmgr,
1335				table_info->vdd_dep_on_sclk,
1336				table->ACPILevel.SclkFrequency,
1337				(uint32_t *)(&table->ACPILevel.MinVoltage), &mvdd);
1338		PP_ASSERT_WITH_CODE((0 == result),
1339				"Cannot find ACPI VDDC voltage value " \
1340				"in Clock Dependency Table",
1341				);
1342	} else {
1343		table->ACPILevel.SclkFrequency =
1344				data->vbios_boot_state.sclk_bootup_value;
1345		table->ACPILevel.MinVoltage =
1346				data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE;
1347	}
1348
1349	/* get the engine clock dividers for this clock value */
1350	result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
1351			table->ACPILevel.SclkFrequency,  &dividers);
1352	PP_ASSERT_WITH_CODE(result == 0,
1353			"Error retrieving Engine Clock dividers from VBIOS.",
1354			return result);
1355
1356	table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
1357	table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1358	table->ACPILevel.DeepSleepDivId = 0;
1359
1360	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
1361			SPLL_PWRON, 0);
1362	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
1363			SPLL_RESET, 1);
1364	spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2,
1365			SCLK_MUX_SEL, 4);
1366
1367	table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
1368	table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
1369	table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
1370	table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
1371	table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
1372	table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
1373	table->ACPILevel.CcPwrDynRm = 0;
1374	table->ACPILevel.CcPwrDynRm1 = 0;
1375
1376	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
1377	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
1378	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage);
1379	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
1380	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
1381	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
1382	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
1383	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
1384	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
1385	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
1386	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
1387
1388	if (!data->mclk_dpm_key_disabled) {
1389		/* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */
1390		table->MemoryACPILevel.MclkFrequency =
1391				data->dpm_table.mclk_table.dpm_levels[0].value;
1392		result = fiji_get_dependency_volt_by_clk(hwmgr,
1393				table_info->vdd_dep_on_mclk,
1394				table->MemoryACPILevel.MclkFrequency,
1395			(uint32_t *)(&table->MemoryACPILevel.MinVoltage), &mvdd);
1396		PP_ASSERT_WITH_CODE((0 == result),
1397				"Cannot find ACPI VDDCI voltage value in Clock Dependency Table",
1398				);
1399	} else {
1400		table->MemoryACPILevel.MclkFrequency =
1401				data->vbios_boot_state.mclk_bootup_value;
1402		table->MemoryACPILevel.MinVoltage =
1403				data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE;
1404	}
1405
1406	us_mvdd = 0;
1407	if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) ||
1408			(data->mclk_dpm_key_disabled))
1409		us_mvdd = data->vbios_boot_state.mvdd_bootup_value;
1410	else {
1411		if (!fiji_populate_mvdd_value(hwmgr,
1412				data->dpm_table.mclk_table.dpm_levels[0].value,
1413				&vol_level))
1414			us_mvdd = vol_level.Voltage;
1415	}
1416
1417	table->MemoryACPILevel.MinMvdd =
1418			PP_HOST_TO_SMC_UL(us_mvdd * VOLTAGE_SCALE);
1419
1420	table->MemoryACPILevel.EnabledForThrottle = 0;
1421	table->MemoryACPILevel.EnabledForActivity = 0;
1422	table->MemoryACPILevel.UpHyst = 0;
1423	table->MemoryACPILevel.DownHyst = 100;
1424	table->MemoryACPILevel.VoltageDownHyst = 0;
1425	table->MemoryACPILevel.ActivityLevel =
1426			PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
1427
1428	table->MemoryACPILevel.StutterEnable = false;
1429	CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
1430	CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);
1431
1432	return result;
1433}
1434
1435static int fiji_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
1436		SMU73_Discrete_DpmTable *table)
1437{
1438	int result = -EINVAL;
1439	uint8_t count;
1440	struct pp_atomctrl_clock_dividers_vi dividers;
1441	struct phm_ppt_v1_information *table_info =
1442			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1443	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1444			table_info->mm_dep_table;
1445
1446	table->VceLevelCount = (uint8_t)(mm_table->count);
1447	table->VceBootLevel = 0;
1448
1449	for (count = 0; count < table->VceLevelCount; count++) {
1450		table->VceLevel[count].Frequency = mm_table->entries[count].eclk;
1451		table->VceLevel[count].MinVoltage = 0;
1452		table->VceLevel[count].MinVoltage |=
1453				(mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
1454		table->VceLevel[count].MinVoltage |=
1455				((mm_table->entries[count].vddc - VDDC_VDDCI_DELTA) *
1456						VOLTAGE_SCALE) << VDDCI_SHIFT;
1457		table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1458
1459		/*retrieve divider value for VBIOS */
1460		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1461				table->VceLevel[count].Frequency, &dividers);
1462		PP_ASSERT_WITH_CODE((0 == result),
1463				"can not find divide id for VCE engine clock",
1464				return result);
1465
1466		table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1467
1468		CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
1469		CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage);
 
 
 
1470	}
1471	return result;
1472}
1473
1474static int fiji_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
1475		SMU73_Discrete_DpmTable *table)
1476{
1477	int result = -EINVAL;
1478	uint8_t count;
1479	struct pp_atomctrl_clock_dividers_vi dividers;
1480	struct phm_ppt_v1_information *table_info =
1481			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1482	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1483			table_info->mm_dep_table;
1484
1485	table->AcpLevelCount = (uint8_t)(mm_table->count);
1486	table->AcpBootLevel = 0;
1487
1488	for (count = 0; count < table->AcpLevelCount; count++) {
1489		table->AcpLevel[count].Frequency = mm_table->entries[count].aclk;
1490		table->AcpLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
1491				VOLTAGE_SCALE) << VDDC_SHIFT;
1492		table->AcpLevel[count].MinVoltage |= ((mm_table->entries[count].vddc -
1493				VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT;
1494		table->AcpLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1495
1496		/* retrieve divider value for VBIOS */
1497		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1498				table->AcpLevel[count].Frequency, &dividers);
1499		PP_ASSERT_WITH_CODE((0 == result),
1500				"can not find divide id for engine clock", return result);
1501
1502		table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1503
1504		CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency);
1505		CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].MinVoltage);
1506	}
1507	return result;
1508}
1509
1510static int fiji_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
1511		SMU73_Discrete_DpmTable *table)
1512{
1513	int result = -EINVAL;
1514	uint8_t count;
1515	struct pp_atomctrl_clock_dividers_vi dividers;
1516	struct phm_ppt_v1_information *table_info =
1517			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1518	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1519			table_info->mm_dep_table;
1520
1521	table->SamuBootLevel = 0;
1522	table->SamuLevelCount = (uint8_t)(mm_table->count);
1523
1524	for (count = 0; count < table->SamuLevelCount; count++) {
1525		/* not sure whether we need evclk or not */
1526		table->SamuLevel[count].MinVoltage = 0;
1527		table->SamuLevel[count].Frequency = mm_table->entries[count].samclock;
1528		table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
1529				VOLTAGE_SCALE) << VDDC_SHIFT;
1530		table->SamuLevel[count].MinVoltage |= ((mm_table->entries[count].vddc -
1531				VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT;
1532		table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1533
1534		/* retrieve divider value for VBIOS */
1535		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1536				table->SamuLevel[count].Frequency, &dividers);
1537		PP_ASSERT_WITH_CODE((0 == result),
1538				"can not find divide id for samu clock", return result);
1539
1540		table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1541
1542		CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
1543		CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage);
1544	}
1545	return result;
1546}
1547
1548static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr,
1549		int32_t eng_clock, int32_t mem_clock,
1550		struct SMU73_Discrete_MCArbDramTimingTableEntry *arb_regs)
1551{
1552	uint32_t dram_timing;
1553	uint32_t dram_timing2;
1554	uint32_t burstTime;
1555	ULONG state, trrds, trrdl;
1556	int result;
1557
1558	result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
1559			eng_clock, mem_clock);
1560	PP_ASSERT_WITH_CODE(result == 0,
1561			"Error calling VBIOS to set DRAM_TIMING.", return result);
1562
1563	dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
1564	dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
1565	burstTime = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME);
1566
1567	state = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, STATE0);
1568	trrds = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDS0);
1569	trrdl = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDL0);
1570
1571	arb_regs->McArbDramTiming  = PP_HOST_TO_SMC_UL(dram_timing);
1572	arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2);
1573	arb_regs->McArbBurstTime   = (uint8_t)burstTime;
1574	arb_regs->TRRDS            = (uint8_t)trrds;
1575	arb_regs->TRRDL            = (uint8_t)trrdl;
1576
1577	return 0;
1578}
1579
1580static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
1581{
1582	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1583	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
1584	struct SMU73_Discrete_MCArbDramTimingTable arb_regs;
1585	uint32_t i, j;
1586	int result = 0;
1587
1588	for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
1589		for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
1590			result = fiji_populate_memory_timing_parameters(hwmgr,
1591					data->dpm_table.sclk_table.dpm_levels[i].value,
1592					data->dpm_table.mclk_table.dpm_levels[j].value,
1593					&arb_regs.entries[i][j]);
1594			if (result)
1595				break;
1596		}
1597	}
1598
1599	if (!result)
1600		result = smu7_copy_bytes_to_smc(
1601				hwmgr,
1602				smu_data->smu7_data.arb_table_start,
1603				(uint8_t *)&arb_regs,
1604				sizeof(SMU73_Discrete_MCArbDramTimingTable),
1605				SMC_RAM_END);
1606	return result;
1607}
1608
1609static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
1610		struct SMU73_Discrete_DpmTable *table)
1611{
1612	int result = -EINVAL;
1613	uint8_t count;
1614	struct pp_atomctrl_clock_dividers_vi dividers;
1615	struct phm_ppt_v1_information *table_info =
1616			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1617	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1618			table_info->mm_dep_table;
1619
1620	table->UvdLevelCount = (uint8_t)(mm_table->count);
1621	table->UvdBootLevel = 0;
1622
1623	for (count = 0; count < table->UvdLevelCount; count++) {
1624		table->UvdLevel[count].MinVoltage = 0;
1625		table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
1626		table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
1627		table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
1628				VOLTAGE_SCALE) << VDDC_SHIFT;
1629		table->UvdLevel[count].MinVoltage |= ((mm_table->entries[count].vddc -
1630				VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT;
1631		table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1632
1633		/* retrieve divider value for VBIOS */
1634		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1635				table->UvdLevel[count].VclkFrequency, &dividers);
1636		PP_ASSERT_WITH_CODE((0 == result),
1637				"can not find divide id for Vclk clock", return result);
1638
1639		table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
1640
1641		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1642				table->UvdLevel[count].DclkFrequency, &dividers);
1643		PP_ASSERT_WITH_CODE((0 == result),
1644				"can not find divide id for Dclk clock", return result);
1645
1646		table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider;
1647
1648		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
1649		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
1650		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage);
1651
1652	}
1653	return result;
 
 
 
1654}
1655
1656static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
1657		struct SMU73_Discrete_DpmTable *table)
1658{
1659	int result = 0;
1660	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1661
1662	table->GraphicsBootLevel = 0;
1663	table->MemoryBootLevel = 0;
 
1664
1665	/* find boot level from dpm table */
1666	result = phm_find_boot_level(&(data->dpm_table.sclk_table),
1667			data->vbios_boot_state.sclk_bootup_value,
1668			(uint32_t *)&(table->GraphicsBootLevel));
1669
1670	result = phm_find_boot_level(&(data->dpm_table.mclk_table),
1671			data->vbios_boot_state.mclk_bootup_value,
1672			(uint32_t *)&(table->MemoryBootLevel));
1673
1674	table->BootVddc  = data->vbios_boot_state.vddc_bootup_value *
1675			VOLTAGE_SCALE;
1676	table->BootVddci = data->vbios_boot_state.vddci_bootup_value *
1677			VOLTAGE_SCALE;
1678	table->BootMVdd  = data->vbios_boot_state.mvdd_bootup_value *
1679			VOLTAGE_SCALE;
1680
1681	CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc);
1682	CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci);
1683	CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
1684
1685	return 0;
1686}
 
1687
1688static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr)
1689{
1690	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1691	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
1692	struct phm_ppt_v1_information *table_info =
1693			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1694	uint8_t count, level;
1695
1696	count = (uint8_t)(table_info->vdd_dep_on_sclk->count);
1697	for (level = 0; level < count; level++) {
1698		if (table_info->vdd_dep_on_sclk->entries[level].clk >=
1699				data->vbios_boot_state.sclk_bootup_value) {
1700			smu_data->smc_state_table.GraphicsBootLevel = level;
1701			break;
1702		}
1703	}
1704
1705	count = (uint8_t)(table_info->vdd_dep_on_mclk->count);
1706	for (level = 0; level < count; level++) {
1707		if (table_info->vdd_dep_on_mclk->entries[level].clk >=
1708				data->vbios_boot_state.mclk_bootup_value) {
1709			smu_data->smc_state_table.MemoryBootLevel = level;
1710			break;
1711		}
1712	}
1713
1714	return 0;
1715}
 
1716
1717static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
1718{
1719	uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks,
1720			volt_with_cks, value;
1721	uint16_t clock_freq_u16;
1722	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
1723	uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2,
1724			volt_offset = 0;
1725	struct phm_ppt_v1_information *table_info =
1726			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1727	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
1728			table_info->vdd_dep_on_sclk;
1729
1730	stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount;
 
 
1731
1732	/* Read SMU_Eefuse to read and calculate RO and determine
1733	 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1734	 */
1735	efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1736			ixSMU_EFUSE_0 + (146 * 4));
1737	efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1738			ixSMU_EFUSE_0 + (148 * 4));
1739	efuse &= 0xFF000000;
1740	efuse = efuse >> 24;
1741	efuse2 &= 0xF;
1742
1743	if (efuse2 == 1)
1744		ro = (2300 - 1350) * efuse / 255 + 1350;
1745	else
1746		ro = (2500 - 1000) * efuse / 255 + 1000;
1747
1748	if (ro >= 1660)
1749		type = 0;
1750	else
1751		type = 1;
1752
1753	/* Populate Stretch amount */
1754	smu_data->smc_state_table.ClockStretcherAmount = stretch_amount;
 
1755
1756	/* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1757	for (i = 0; i < sclk_table->count; i++) {
1758		smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |=
1759				sclk_table->entries[i].cks_enable << i;
1760		volt_without_cks = (uint32_t)((14041 *
1761			(sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 /
1762			(4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000)));
1763		volt_with_cks = (uint32_t)((13946 *
1764			(sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 /
1765			(3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000)));
1766		if (volt_without_cks >= volt_with_cks)
1767			volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
1768					sclk_table->entries[i].cks_voffset) * 100 / 625) + 1);
1769		smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
1770	}
1771
1772	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1773			STRETCH_ENABLE, 0x0);
1774	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1775			masterReset, 0x1);
1776	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1777			staticEnable, 0x1);
1778	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1779			masterReset, 0x0);
1780
1781	/* Populate CKS Lookup Table */
1782	if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
1783		stretch_amount2 = 0;
1784	else if (stretch_amount == 3 || stretch_amount == 4)
1785		stretch_amount2 = 1;
1786	else {
1787		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1788				PHM_PlatformCaps_ClockStretcher);
1789		PP_ASSERT_WITH_CODE(false,
1790				"Stretch Amount in PPTable not supported",
1791				return -EINVAL);
1792	}
1793
1794	value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1795			ixPWR_CKS_CNTL);
1796	value &= 0xFFC2FF87;
1797	smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq =
1798			fiji_clock_stretcher_lookup_table[stretch_amount2][0];
1799	smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq =
1800			fiji_clock_stretcher_lookup_table[stretch_amount2][1];
1801	clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table.
1802			GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1].
1803			SclkFrequency) / 100);
1804	if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] <
1805			clock_freq_u16 &&
1806	    fiji_clock_stretcher_lookup_table[stretch_amount2][1] >
1807			clock_freq_u16) {
1808		/* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
1809		value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16;
1810		/* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
1811		value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][2]) << 18;
1812		/* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
1813		value |= (fiji_clock_stretch_amount_conversion
1814				[fiji_clock_stretcher_lookup_table[stretch_amount2][3]]
1815				 [stretch_amount]) << 3;
1816	}
1817	CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable.
1818			CKS_LOOKUPTableEntry[0].minFreq);
1819	CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable.
1820			CKS_LOOKUPTableEntry[0].maxFreq);
1821	smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting =
1822			fiji_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F;
1823	smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |=
1824			(fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 7;
1825
1826	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1827			ixPWR_CKS_CNTL, value);
1828
1829	/* Populate DDT Lookup Table */
1830	for (i = 0; i < 4; i++) {
1831		/* Assign the minimum and maximum VID stored
1832		 * in the last row of Clock Stretcher Voltage Table.
1833		 */
1834		smu_data->smc_state_table.ClockStretcherDataTable.
1835		ClockStretcherDataTableEntry[i].minVID =
1836				(uint8_t) fiji_clock_stretcher_ddt_table[type][i][2];
1837		smu_data->smc_state_table.ClockStretcherDataTable.
1838		ClockStretcherDataTableEntry[i].maxVID =
1839				(uint8_t) fiji_clock_stretcher_ddt_table[type][i][3];
1840		/* Loop through each SCLK and check the frequency
1841		 * to see if it lies within the frequency for clock stretcher.
1842		 */
1843		for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) {
1844			cks_setting = 0;
1845			clock_freq = PP_SMC_TO_HOST_UL(
1846					smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency);
1847			/* Check the allowed frequency against the sclk level[j].
1848			 *  Sclk's endianness has already been converted,
1849			 *  and it's in 10Khz unit,
1850			 *  as opposed to Data table, which is in Mhz unit.
1851			 */
1852			if (clock_freq >=
1853					(fiji_clock_stretcher_ddt_table[type][i][0]) * 100) {
1854				cks_setting |= 0x2;
1855				if (clock_freq <
1856						(fiji_clock_stretcher_ddt_table[type][i][1]) * 100)
1857					cks_setting |= 0x1;
1858			}
1859			smu_data->smc_state_table.ClockStretcherDataTable.
1860			ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2);
1861		}
1862		CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.
1863				ClockStretcherDataTable.
1864				ClockStretcherDataTableEntry[i].setting);
1865	}
1866
1867	value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL);
1868	value &= 0xFFFFFFFE;
1869	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value);
1870
1871	return 0;
1872}
1873
1874static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr,
1875		struct SMU73_Discrete_DpmTable *table)
1876{
1877	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1878	uint16_t config;
1879
1880	config = VR_MERGED_WITH_VDDC;
1881	table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT);
 
1882
1883	/* Set Vddc Voltage Controller */
1884	if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1885		config = VR_SVI2_PLANE_1;
1886		table->VRConfig |= config;
1887	} else {
1888		PP_ASSERT_WITH_CODE(false,
1889				"VDDC should be on SVI2 control in merged mode!",
1890				);
1891	}
1892	/* Set Vddci Voltage Controller */
1893	if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
1894		config = VR_SVI2_PLANE_2;  /* only in merged mode */
1895		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1896	} else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
1897		config = VR_SMIO_PATTERN_1;
1898		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1899	} else {
1900		config = VR_STATIC_VOLTAGE;
1901		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1902	}
1903	/* Set Mvdd Voltage Controller */
1904	if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
1905		config = VR_SVI2_PLANE_2;
1906		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
1907	} else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
1908		config = VR_SMIO_PATTERN_2;
1909		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
1910	} else {
1911		config = VR_STATIC_VOLTAGE;
1912		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
1913	}
1914
1915	return 0;
1916}
 
1917
1918static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr)
1919{
1920	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
1921	uint32_t tmp;
1922	int result;
1923
1924	/* This is a read-modify-write on the first byte of the ARB table.
1925	 * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure
1926	 * is the field 'current'.
1927	 * This solution is ugly, but we never write the whole table only
1928	 * individual fields in it.
1929	 * In reality this field should not be in that structure
1930	 * but in a soft register.
1931	 */
1932	result = smu7_read_smc_sram_dword(hwmgr,
1933			smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END);
1934
1935	if (result)
1936		return result;
 
1937
1938	tmp &= 0x00FFFFFF;
1939	tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
 
1940
1941	return smu7_write_smc_sram_dword(hwmgr,
1942			smu_data->smu7_data.arb_table_start,  tmp, SMC_RAM_END);
 
 
 
1943}
1944
1945static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr)
1946{
1947	pp_atomctrl_voltage_table param_led_dpm;
1948	int result = 0;
1949	u32 mask = 0;
1950
1951	result = atomctrl_get_voltage_table_v3(hwmgr,
1952					       VOLTAGE_TYPE_LEDDPM, VOLTAGE_OBJ_GPIO_LUT,
1953					       &param_led_dpm);
1954	if (result == 0) {
1955		int i, j;
1956		u32 tmp = param_led_dpm.mask_low;
1957
1958		for (i = 0, j = 0; i < 32; i++) {
1959			if (tmp & 1) {
1960				mask |= (i << (8 * j));
1961				if (++j >= 3)
1962					break;
1963			}
1964			tmp >>= 1;
 
 
 
 
1965		}
 
1966	}
1967	if (mask)
1968		smum_send_msg_to_smc_with_parameter(hwmgr,
1969						    PPSMC_MSG_LedConfig,
1970						    mask);
1971	return 0;
1972}
1973
1974static int fiji_init_smc_table(struct pp_hwmgr *hwmgr)
1975{
1976	int result;
1977	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1978	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
1979	struct phm_ppt_v1_information *table_info =
1980			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1981	struct SMU73_Discrete_DpmTable *table = &(smu_data->smc_state_table);
1982	uint8_t i;
1983	struct pp_atomctrl_gpio_pin_assignment gpio_pin;
1984
1985	fiji_initialize_power_tune_defaults(hwmgr);
1986
1987	if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control)
1988		fiji_populate_smc_voltage_tables(hwmgr, table);
1989
1990	table->SystemFlags = 0;
1991
1992	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1993			PHM_PlatformCaps_AutomaticDCTransition))
1994		table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
1995
1996	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1997			PHM_PlatformCaps_StepVddc))
1998		table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
1999
2000	if (data->is_memory_gddr5)
2001		table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
2002
2003	if (data->ulv_supported && table_info->us_ulv_voltage_offset) {
2004		result = fiji_populate_ulv_state(hwmgr, table);
2005		PP_ASSERT_WITH_CODE(0 == result,
2006				"Failed to initialize ULV state!", return result);
2007		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
2008				ixCG_ULV_PARAMETER, 0x40035);
2009	}
2010
2011	result = fiji_populate_smc_link_level(hwmgr, table);
2012	PP_ASSERT_WITH_CODE(0 == result,
2013			"Failed to initialize Link Level!", return result);
2014
2015	result = fiji_populate_all_graphic_levels(hwmgr);
2016	PP_ASSERT_WITH_CODE(0 == result,
2017			"Failed to initialize Graphics Level!", return result);
2018
2019	result = fiji_populate_all_memory_levels(hwmgr);
2020	PP_ASSERT_WITH_CODE(0 == result,
2021			"Failed to initialize Memory Level!", return result);
2022
2023	result = fiji_populate_smc_acpi_level(hwmgr, table);
2024	PP_ASSERT_WITH_CODE(0 == result,
2025			"Failed to initialize ACPI Level!", return result);
2026
2027	result = fiji_populate_smc_vce_level(hwmgr, table);
2028	PP_ASSERT_WITH_CODE(0 == result,
2029			"Failed to initialize VCE Level!", return result);
2030
2031	result = fiji_populate_smc_acp_level(hwmgr, table);
2032	PP_ASSERT_WITH_CODE(0 == result,
2033			"Failed to initialize ACP Level!", return result);
2034
2035	result = fiji_populate_smc_samu_level(hwmgr, table);
2036	PP_ASSERT_WITH_CODE(0 == result,
2037			"Failed to initialize SAMU Level!", return result);
2038
2039	/* Since only the initial state is completely set up at this point
2040	 * (the other states are just copies of the boot state) we only
2041	 * need to populate the  ARB settings for the initial state.
2042	 */
2043	result = fiji_program_memory_timing_parameters(hwmgr);
2044	PP_ASSERT_WITH_CODE(0 == result,
2045			"Failed to Write ARB settings for the initial state.", return result);
2046
2047	result = fiji_populate_smc_uvd_level(hwmgr, table);
2048	PP_ASSERT_WITH_CODE(0 == result,
2049			"Failed to initialize UVD Level!", return result);
2050
2051	result = fiji_populate_smc_boot_level(hwmgr, table);
2052	PP_ASSERT_WITH_CODE(0 == result,
2053			"Failed to initialize Boot Level!", return result);
2054
2055	result = fiji_populate_smc_initailial_state(hwmgr);
2056	PP_ASSERT_WITH_CODE(0 == result,
2057			"Failed to initialize Boot State!", return result);
2058
2059	result = fiji_populate_bapm_parameters_in_dpm_table(hwmgr);
2060	PP_ASSERT_WITH_CODE(0 == result,
2061			"Failed to populate BAPM Parameters!", return result);
2062
2063	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2064			PHM_PlatformCaps_ClockStretcher)) {
2065		result = fiji_populate_clock_stretcher_data_table(hwmgr);
2066		PP_ASSERT_WITH_CODE(0 == result,
2067				"Failed to populate Clock Stretcher Data Table!",
2068				return result);
2069	}
 
 
 
 
 
 
 
2070
2071	table->GraphicsVoltageChangeEnable  = 1;
2072	table->GraphicsThermThrottleEnable  = 1;
2073	table->GraphicsInterval = 1;
2074	table->VoltageInterval  = 1;
2075	table->ThermalInterval  = 1;
2076	table->TemperatureLimitHigh =
2077			table_info->cac_dtp_table->usTargetOperatingTemp *
2078			SMU7_Q88_FORMAT_CONVERSION_UNIT;
2079	table->TemperatureLimitLow  =
2080			(table_info->cac_dtp_table->usTargetOperatingTemp - 1) *
2081			SMU7_Q88_FORMAT_CONVERSION_UNIT;
2082	table->MemoryVoltageChangeEnable = 1;
2083	table->MemoryInterval = 1;
2084	table->VoltageResponseTime = 0;
2085	table->PhaseResponseTime = 0;
2086	table->MemoryThermThrottleEnable = 1;
2087	table->PCIeBootLinkLevel = 0;      /* 0:Gen1 1:Gen2 2:Gen3*/
2088	table->PCIeGenInterval = 1;
2089	table->VRConfig = 0;
2090
2091	result = fiji_populate_vr_config(hwmgr, table);
2092	PP_ASSERT_WITH_CODE(0 == result,
2093			"Failed to populate VRConfig setting!", return result);
2094	data->vr_config = table->VRConfig;
2095	table->ThermGpio = 17;
2096	table->SclkStepSize = 0x4000;
2097
2098	if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) {
2099		table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift;
2100		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2101				PHM_PlatformCaps_RegulatorHot);
2102	} else {
2103		table->VRHotGpio = SMU7_UNUSED_GPIO_PIN;
2104		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2105				PHM_PlatformCaps_RegulatorHot);
2106	}
2107
2108	if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID,
2109			&gpio_pin)) {
2110		table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift;
2111		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2112				PHM_PlatformCaps_AutomaticDCTransition);
2113	} else {
2114		table->AcDcGpio = SMU7_UNUSED_GPIO_PIN;
2115		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2116				PHM_PlatformCaps_AutomaticDCTransition);
2117	}
2118
2119	/* Thermal Output GPIO */
2120	if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID,
2121			&gpio_pin)) {
2122		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2123				PHM_PlatformCaps_ThermalOutGPIO);
2124
2125		table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift;
2126
2127		/* For porlarity read GPIOPAD_A with assigned Gpio pin
2128		 * since VBIOS will program this register to set 'inactive state',
2129		 * driver can then determine 'active state' from this and
2130		 * program SMU with correct polarity
2131		 */
2132		table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) &
2133				(1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0;
2134		table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
2135
2136		/* if required, combine VRHot/PCC with thermal out GPIO */
2137		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2138				PHM_PlatformCaps_RegulatorHot) &&
2139			phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2140					PHM_PlatformCaps_CombinePCCWithThermalSignal))
2141			table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
2142	} else {
2143		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2144				PHM_PlatformCaps_ThermalOutGPIO);
2145		table->ThermOutGpio = 17;
2146		table->ThermOutPolarity = 1;
2147		table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
2148	}
2149
2150	for (i = 0; i < SMU73_MAX_ENTRIES_SMIO; i++)
2151		table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
2152
2153	CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
2154	CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
2155	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
2156	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
2157	CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
2158	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
2159	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
2160	CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
2161	CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
2162
2163	/* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2164	result = smu7_copy_bytes_to_smc(hwmgr,
2165			smu_data->smu7_data.dpm_table_start +
2166			offsetof(SMU73_Discrete_DpmTable, SystemFlags),
2167			(uint8_t *)&(table->SystemFlags),
2168			sizeof(SMU73_Discrete_DpmTable) - 3 * sizeof(SMU73_PIDController),
2169			SMC_RAM_END);
2170	PP_ASSERT_WITH_CODE(0 == result,
2171			"Failed to upload dpm data to SMC memory!", return result);
2172
2173	result = fiji_init_arb_table_index(hwmgr);
2174	PP_ASSERT_WITH_CODE(0 == result,
2175			"Failed to upload arb data to SMC memory!", return result);
2176
2177	result = fiji_populate_pm_fuses(hwmgr);
2178	PP_ASSERT_WITH_CODE(0 == result,
2179			"Failed to  populate PM fuses to SMC memory!", return result);
2180
2181	result = fiji_setup_dpm_led_config(hwmgr);
2182	PP_ASSERT_WITH_CODE(0 == result,
2183			    "Failed to setup dpm led config", return result);
2184
2185	return 0;
2186}
2187
2188static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
2189{
2190	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
 
 
 
2191
2192	SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
2193	uint32_t duty100;
2194	uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
2195	uint16_t fdo_min, slope1, slope2;
2196	uint32_t reference_clock;
2197	int res;
2198	uint64_t tmp64;
2199
2200	if (hwmgr->thermal_controller.fanInfo.bNoFan) {
2201		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2202			PHM_PlatformCaps_MicrocodeFanControl);
2203		return 0;
2204	}
2205
2206	if (smu_data->smu7_data.fan_table_start == 0) {
2207		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2208				PHM_PlatformCaps_MicrocodeFanControl);
2209		return 0;
2210	}
 
2211
2212	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
2213			CG_FDO_CTRL1, FMAX_DUTY100);
 
 
2214
2215	if (duty100 == 0) {
2216		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2217				PHM_PlatformCaps_MicrocodeFanControl);
2218		return 0;
2219	}
2220
2221	tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.
2222			usPWMMin * duty100;
2223	do_div(tmp64, 10000);
2224	fdo_min = (uint16_t)tmp64;
2225
2226	t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed -
2227			hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
2228	t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh -
2229			hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
2230
2231	pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed -
2232			hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
2233	pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh -
2234			hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
2235
2236	slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
2237	slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
2238
2239	fan_table.TempMin = cpu_to_be16((50 + hwmgr->
2240			thermal_controller.advanceFanControlParameters.usTMin) / 100);
2241	fan_table.TempMed = cpu_to_be16((50 + hwmgr->
2242			thermal_controller.advanceFanControlParameters.usTMed) / 100);
2243	fan_table.TempMax = cpu_to_be16((50 + hwmgr->
2244			thermal_controller.advanceFanControlParameters.usTMax) / 100);
2245
2246	fan_table.Slope1 = cpu_to_be16(slope1);
2247	fan_table.Slope2 = cpu_to_be16(slope2);
2248
2249	fan_table.FdoMin = cpu_to_be16(fdo_min);
2250
2251	fan_table.HystDown = cpu_to_be16(hwmgr->
2252			thermal_controller.advanceFanControlParameters.ucTHyst);
2253
2254	fan_table.HystUp = cpu_to_be16(1);
2255
2256	fan_table.HystSlope = cpu_to_be16(1);
2257
2258	fan_table.TempRespLim = cpu_to_be16(5);
2259
2260	reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
2261
2262	fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
2263			thermal_controller.advanceFanControlParameters.ulCycleDelay *
2264			reference_clock) / 1600);
2265
2266	fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
2267
2268	fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(
2269			hwmgr->device, CGS_IND_REG__SMC,
2270			CG_MULT_THERMAL_CTRL, TEMP_SEL);
2271
2272	res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start,
2273			(uint8_t *)&fan_table, (uint32_t)sizeof(fan_table),
2274			SMC_RAM_END);
2275
2276	if (!res && hwmgr->thermal_controller.
2277			advanceFanControlParameters.ucMinimumPWMLimit)
2278		res = smum_send_msg_to_smc_with_parameter(hwmgr,
2279				PPSMC_MSG_SetFanMinPwm,
2280				hwmgr->thermal_controller.
2281				advanceFanControlParameters.ucMinimumPWMLimit);
2282
2283	if (!res && hwmgr->thermal_controller.
2284			advanceFanControlParameters.ulMinFanSCLKAcousticLimit)
2285		res = smum_send_msg_to_smc_with_parameter(hwmgr,
2286				PPSMC_MSG_SetFanSclkTarget,
2287				hwmgr->thermal_controller.
2288				advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
2289
2290	if (res)
2291		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2292				PHM_PlatformCaps_MicrocodeFanControl);
2293
2294	return 0;
2295}
2296
2297
2298static int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr)
2299{
2300	if (!hwmgr->avfs_supported)
2301		return 0;
 
 
2302
2303	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs);
 
 
 
 
 
 
2304
2305	return 0;
2306}
 
2307
2308static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
2309{
2310	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2311
2312	if (data->need_update_smu7_dpm_table &
2313		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
2314		return fiji_program_memory_timing_parameters(hwmgr);
 
 
2315
2316	return 0;
2317}
2318
2319static int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr)
2320{
2321	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2322	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
2323
2324	int result = 0;
2325	uint32_t low_sclk_interrupt_threshold = 0;
2326
2327	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2328			PHM_PlatformCaps_SclkThrottleLowNotification)
2329		&& (data->low_sclk_interrupt_threshold != 0)) {
2330		low_sclk_interrupt_threshold =
2331				data->low_sclk_interrupt_threshold;
2332
2333		CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
2334
2335		result = smu7_copy_bytes_to_smc(
2336				hwmgr,
2337				smu_data->smu7_data.dpm_table_start +
2338				offsetof(SMU73_Discrete_DpmTable,
2339					LowSclkInterruptThreshold),
2340				(uint8_t *)&low_sclk_interrupt_threshold,
2341				sizeof(uint32_t),
2342				SMC_RAM_END);
2343	}
2344	result = fiji_program_mem_timing_parameters(hwmgr);
2345	PP_ASSERT_WITH_CODE((result == 0),
2346			"Failed to program memory timing parameters!",
2347			);
2348	return result;
2349}
2350
2351static uint32_t fiji_get_offsetof(uint32_t type, uint32_t member)
2352{
2353	switch (type) {
2354	case SMU_SoftRegisters:
2355		switch (member) {
2356		case HandshakeDisables:
2357			return offsetof(SMU73_SoftRegisters, HandshakeDisables);
2358		case VoltageChangeTimeout:
2359			return offsetof(SMU73_SoftRegisters, VoltageChangeTimeout);
2360		case AverageGraphicsActivity:
2361			return offsetof(SMU73_SoftRegisters, AverageGraphicsActivity);
2362		case PreVBlankGap:
2363			return offsetof(SMU73_SoftRegisters, PreVBlankGap);
2364		case VBlankTimeout:
2365			return offsetof(SMU73_SoftRegisters, VBlankTimeout);
2366		case UcodeLoadStatus:
2367			return offsetof(SMU73_SoftRegisters, UcodeLoadStatus);
2368		case DRAM_LOG_ADDR_H:
2369			return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_H);
2370		case DRAM_LOG_ADDR_L:
2371			return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_L);
2372		case DRAM_LOG_PHY_ADDR_H:
2373			return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_H);
2374		case DRAM_LOG_PHY_ADDR_L:
2375			return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_L);
2376		case DRAM_LOG_BUFF_SIZE:
2377			return offsetof(SMU73_SoftRegisters, DRAM_LOG_BUFF_SIZE);
2378		}
2379	case SMU_Discrete_DpmTable:
2380		switch (member) {
2381		case UvdBootLevel:
2382			return offsetof(SMU73_Discrete_DpmTable, UvdBootLevel);
2383		case VceBootLevel:
2384			return offsetof(SMU73_Discrete_DpmTable, VceBootLevel);
2385		case SamuBootLevel:
2386			return offsetof(SMU73_Discrete_DpmTable, SamuBootLevel);
2387		case LowSclkInterruptThreshold:
2388			return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold);
2389		}
2390	}
2391	pr_warn("can't get the offset of type %x member %x\n", type, member);
2392	return 0;
2393}
2394
2395static uint32_t fiji_get_mac_definition(uint32_t value)
 
2396{
2397	switch (value) {
2398	case SMU_MAX_LEVELS_GRAPHICS:
2399		return SMU73_MAX_LEVELS_GRAPHICS;
2400	case SMU_MAX_LEVELS_MEMORY:
2401		return SMU73_MAX_LEVELS_MEMORY;
2402	case SMU_MAX_LEVELS_LINK:
2403		return SMU73_MAX_LEVELS_LINK;
2404	case SMU_MAX_ENTRIES_SMIO:
2405		return SMU73_MAX_ENTRIES_SMIO;
2406	case SMU_MAX_LEVELS_VDDC:
2407		return SMU73_MAX_LEVELS_VDDC;
2408	case SMU_MAX_LEVELS_VDDGFX:
2409		return SMU73_MAX_LEVELS_VDDGFX;
2410	case SMU_MAX_LEVELS_VDDCI:
2411		return SMU73_MAX_LEVELS_VDDCI;
2412	case SMU_MAX_LEVELS_MVDD:
2413		return SMU73_MAX_LEVELS_MVDD;
2414	}
2415
2416	pr_warn("can't get the mac of %x\n", value);
2417	return 0;
 
 
 
2418}
2419
2420
2421static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr)
2422{
2423	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
2424	uint32_t mm_boot_level_offset, mm_boot_level_value;
2425	struct phm_ppt_v1_information *table_info =
2426			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2427
2428	smu_data->smc_state_table.UvdBootLevel = 0;
2429	if (table_info->mm_dep_table->count > 0)
2430		smu_data->smc_state_table.UvdBootLevel =
2431				(uint8_t) (table_info->mm_dep_table->count - 1);
2432	mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU73_Discrete_DpmTable,
2433						UvdBootLevel);
2434	mm_boot_level_offset /= 4;
2435	mm_boot_level_offset *= 4;
2436	mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2437			CGS_IND_REG__SMC, mm_boot_level_offset);
2438	mm_boot_level_value &= 0x00FFFFFF;
2439	mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24;
2440	cgs_write_ind_register(hwmgr->device,
2441			CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2442
2443	if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2444			PHM_PlatformCaps_UVDDPM) ||
2445		phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2446			PHM_PlatformCaps_StablePState))
2447		smum_send_msg_to_smc_with_parameter(hwmgr,
2448				PPSMC_MSG_UVDDPM_SetEnabledMask,
2449				(uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel));
2450	return 0;
2451}
2452
2453static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr)
2454{
2455	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
2456	uint32_t mm_boot_level_offset, mm_boot_level_value;
2457	struct phm_ppt_v1_information *table_info =
2458			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2459
2460	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2461					PHM_PlatformCaps_StablePState))
2462		smu_data->smc_state_table.VceBootLevel =
2463			(uint8_t) (table_info->mm_dep_table->count - 1);
2464	else
2465		smu_data->smc_state_table.VceBootLevel = 0;
2466
2467	mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2468					offsetof(SMU73_Discrete_DpmTable, VceBootLevel);
2469	mm_boot_level_offset /= 4;
2470	mm_boot_level_offset *= 4;
2471	mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2472			CGS_IND_REG__SMC, mm_boot_level_offset);
2473	mm_boot_level_value &= 0xFF00FFFF;
2474	mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16;
2475	cgs_write_ind_register(hwmgr->device,
2476			CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2477
2478	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
2479		smum_send_msg_to_smc_with_parameter(hwmgr,
2480				PPSMC_MSG_VCEDPM_SetEnabledMask,
2481				(uint32_t)1 << smu_data->smc_state_table.VceBootLevel);
2482	return 0;
2483}
2484
2485static int fiji_update_samu_smc_table(struct pp_hwmgr *hwmgr)
2486{
2487	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
2488	uint32_t mm_boot_level_offset, mm_boot_level_value;
2489
2490
2491	smu_data->smc_state_table.SamuBootLevel = 0;
2492	mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2493				offsetof(SMU73_Discrete_DpmTable, SamuBootLevel);
2494
2495	mm_boot_level_offset /= 4;
2496	mm_boot_level_offset *= 4;
2497	mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2498			CGS_IND_REG__SMC, mm_boot_level_offset);
2499	mm_boot_level_value &= 0xFFFFFF00;
2500	mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0;
2501	cgs_write_ind_register(hwmgr->device,
2502			CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2503
2504	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2505			PHM_PlatformCaps_StablePState))
2506		smum_send_msg_to_smc_with_parameter(hwmgr,
2507				PPSMC_MSG_SAMUDPM_SetEnabledMask,
2508				(uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel));
2509	return 0;
2510}
2511
2512static int fiji_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
2513{
2514	switch (type) {
2515	case SMU_UVD_TABLE:
2516		fiji_update_uvd_smc_table(hwmgr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2517		break;
2518	case SMU_VCE_TABLE:
2519		fiji_update_vce_smc_table(hwmgr);
2520		break;
2521	case SMU_SAMU_TABLE:
2522		fiji_update_samu_smc_table(hwmgr);
2523		break;
2524	default:
 
2525		break;
2526	}
2527	return 0;
2528}
2529
2530static int fiji_process_firmware_header(struct pp_hwmgr *hwmgr)
2531{
2532	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2533	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend);
2534	uint32_t tmp;
2535	int result;
2536	bool error = false;
2537
2538	result = smu7_read_smc_sram_dword(hwmgr,
2539			SMU7_FIRMWARE_HEADER_LOCATION +
2540			offsetof(SMU73_Firmware_Header, DpmTable),
2541			&tmp, SMC_RAM_END);
2542
2543	if (0 == result)
2544		smu_data->smu7_data.dpm_table_start = tmp;
 
 
 
 
 
 
 
 
 
 
 
 
2545
2546	error |= (0 != result);
 
 
 
 
 
 
 
 
2547
2548	result = smu7_read_smc_sram_dword(hwmgr,
 
 
 
2549			SMU7_FIRMWARE_HEADER_LOCATION +
2550			offsetof(SMU73_Firmware_Header, SoftRegisters),
2551			&tmp, SMC_RAM_END);
2552
2553	if (!result) {
2554		data->soft_regs_start = tmp;
2555		smu_data->smu7_data.soft_regs_start = tmp;
2556	}
2557
2558	error |= (0 != result);
 
2559
2560	result = smu7_read_smc_sram_dword(hwmgr,
2561			SMU7_FIRMWARE_HEADER_LOCATION +
2562			offsetof(SMU73_Firmware_Header, mcRegisterTable),
2563			&tmp, SMC_RAM_END);
2564
2565	if (!result)
2566		smu_data->smu7_data.mc_reg_table_start = tmp;
2567
2568	result = smu7_read_smc_sram_dword(hwmgr,
2569			SMU7_FIRMWARE_HEADER_LOCATION +
2570			offsetof(SMU73_Firmware_Header, FanTable),
2571			&tmp, SMC_RAM_END);
2572
2573	if (!result)
2574		smu_data->smu7_data.fan_table_start = tmp;
2575
2576	error |= (0 != result);
2577
2578	result = smu7_read_smc_sram_dword(hwmgr,
2579			SMU7_FIRMWARE_HEADER_LOCATION +
2580			offsetof(SMU73_Firmware_Header, mcArbDramTimingTable),
2581			&tmp, SMC_RAM_END);
2582
2583	if (!result)
2584		smu_data->smu7_data.arb_table_start = tmp;
2585
2586	error |= (0 != result);
2587
2588	result = smu7_read_smc_sram_dword(hwmgr,
2589			SMU7_FIRMWARE_HEADER_LOCATION +
2590			offsetof(SMU73_Firmware_Header, Version),
2591			&tmp, SMC_RAM_END);
2592
2593	if (!result)
2594		hwmgr->microcode_version_info.SMC = tmp;
2595
2596	error |= (0 != result);
2597
2598	return error ? -1 : 0;
2599}
2600
2601static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
2602{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2603
2604	/* Program additional LP registers
2605	 * that are no longer programmed by VBIOS
2606	 */
2607	cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP,
2608			cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
2609	cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP,
2610			cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
2611	cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP,
2612			cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
2613	cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP,
2614			cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
2615	cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP,
2616			cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
2617	cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP,
2618			cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
2619	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP,
2620			cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
2621
2622	return 0;
2623}
2624
2625static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr)
2626{
2627	return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
2628			CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
2629			? true : false;
2630}
2631
2632static int fiji_update_dpm_settings(struct pp_hwmgr *hwmgr,
2633				void *profile_setting)
2634{
2635	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2636	struct fiji_smumgr *smu_data = (struct fiji_smumgr *)
2637			(hwmgr->smu_backend);
2638	struct profile_mode_setting *setting;
2639	struct SMU73_Discrete_GraphicsLevel *levels =
2640			smu_data->smc_state_table.GraphicsLevel;
2641	uint32_t array = smu_data->smu7_data.dpm_table_start +
2642			offsetof(SMU73_Discrete_DpmTable, GraphicsLevel);
2643
2644	uint32_t mclk_array = smu_data->smu7_data.dpm_table_start +
2645			offsetof(SMU73_Discrete_DpmTable, MemoryLevel);
2646	struct SMU73_Discrete_MemoryLevel *mclk_levels =
2647			smu_data->smc_state_table.MemoryLevel;
2648	uint32_t i;
2649	uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
2650
2651	if (profile_setting == NULL)
2652		return -EINVAL;
2653
2654	setting = (struct profile_mode_setting *)profile_setting;
2655
2656	if (setting->bupdate_sclk) {
2657		if (!data->sclk_dpm_key_disabled)
2658			smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
2659		for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
2660			if (levels[i].ActivityLevel !=
2661				cpu_to_be16(setting->sclk_activity)) {
2662				levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
2663
2664				clk_activity_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
2665						+ offsetof(SMU73_Discrete_GraphicsLevel, ActivityLevel);
2666				offset = clk_activity_offset & ~0x3;
2667				tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
2668				tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
2669				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
2670
2671			}
2672			if (levels[i].UpHyst != setting->sclk_up_hyst ||
2673				levels[i].DownHyst != setting->sclk_down_hyst) {
2674				levels[i].UpHyst = setting->sclk_up_hyst;
2675				levels[i].DownHyst = setting->sclk_down_hyst;
2676				up_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
2677						+ offsetof(SMU73_Discrete_GraphicsLevel, UpHyst);
2678				down_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
2679						+ offsetof(SMU73_Discrete_GraphicsLevel, DownHyst);
2680				offset = up_hyst_offset & ~0x3;
2681				tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
2682				tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t));
2683				tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t));
2684				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
2685			}
2686		}
2687		if (!data->sclk_dpm_key_disabled)
2688			smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
2689	}
2690
2691	if (setting->bupdate_mclk) {
2692		if (!data->mclk_dpm_key_disabled)
2693			smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
2694		for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
2695			if (mclk_levels[i].ActivityLevel !=
2696				cpu_to_be16(setting->mclk_activity)) {
2697				mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
2698
2699				clk_activity_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
2700						+ offsetof(SMU73_Discrete_MemoryLevel, ActivityLevel);
2701				offset = clk_activity_offset & ~0x3;
2702				tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
2703				tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
2704				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
2705
2706			}
2707			if (mclk_levels[i].UpHyst != setting->mclk_up_hyst ||
2708				mclk_levels[i].DownHyst != setting->mclk_down_hyst) {
2709				mclk_levels[i].UpHyst = setting->mclk_up_hyst;
2710				mclk_levels[i].DownHyst = setting->mclk_down_hyst;
2711				up_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
2712						+ offsetof(SMU73_Discrete_MemoryLevel, UpHyst);
2713				down_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
2714						+ offsetof(SMU73_Discrete_MemoryLevel, DownHyst);
2715				offset = up_hyst_offset & ~0x3;
2716				tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
2717				tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t));
2718				tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t));
2719				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
2720			}
2721		}
2722		if (!data->mclk_dpm_key_disabled)
2723			smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
2724	}
2725	return 0;
2726}
2727
2728const struct pp_smumgr_func fiji_smu_funcs = {
2729	.smu_init = &fiji_smu_init,
2730	.smu_fini = &smu7_smu_fini,
2731	.start_smu = &fiji_start_smu,
2732	.check_fw_load_finish = &smu7_check_fw_load_finish,
2733	.request_smu_load_fw = &smu7_reload_firmware,
2734	.request_smu_load_specific_fw = NULL,
2735	.send_msg_to_smc = &smu7_send_msg_to_smc,
2736	.send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter,
2737	.download_pptable_settings = NULL,
2738	.upload_pptable_settings = NULL,
2739	.update_smc_table = fiji_update_smc_table,
2740	.get_offsetof = fiji_get_offsetof,
2741	.process_firmware_header = fiji_process_firmware_header,
2742	.init_smc_table = fiji_init_smc_table,
2743	.update_sclk_threshold = fiji_update_sclk_threshold,
2744	.thermal_setup_fan_table = fiji_thermal_setup_fan_table,
2745	.thermal_avfs_enable = fiji_thermal_avfs_enable,
2746	.populate_all_graphic_levels = fiji_populate_all_graphic_levels,
2747	.populate_all_memory_levels = fiji_populate_all_memory_levels,
2748	.get_mac_definition = fiji_get_mac_definition,
2749	.initialize_mc_reg_table = fiji_initialize_mc_reg_table,
2750	.is_dpm_running = fiji_is_dpm_running,
2751	.is_hw_avfs_present = fiji_is_hw_avfs_present,
2752	.update_dpm_settings = fiji_update_dpm_settings,
2753};