1/*	$NetBSD: amdgpu_iceland_smumgr.c,v 1.3 2021/12/19 12:02:40 riastradh Exp $	*/
2
3/*
4 * Copyright 2016 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Author: Huang Rui <ray.huang@amd.com>
25 *
26 */
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: amdgpu_iceland_smumgr.c,v 1.3 2021/12/19 12:02:40 riastradh Exp $");
29
30#include "pp_debug.h"
31#include <linux/types.h>
32#include <linux/kernel.h>
33#include <linux/pci.h>
34#include <linux/slab.h>
35#include <linux/gfp.h>
36
37#include "smumgr.h"
38#include "iceland_smumgr.h"
39
40#include "ppsmc.h"
41
42#include "cgs_common.h"
43
44#include "smu7_dyn_defaults.h"
45#include "smu7_hwmgr.h"
46#include "hardwaremanager.h"
47#include "ppatomctrl.h"
48#include "atombios.h"
49#include "pppcielanes.h"
50#include "pp_endian.h"
51#include "processpptables.h"
52
53
54#include "smu/smu_7_1_1_d.h"
55#include "smu/smu_7_1_1_sh_mask.h"
56#include "smu71_discrete.h"
57
58#include "smu_ucode_xfer_vi.h"
59#include "gmc/gmc_8_1_d.h"
60#include "gmc/gmc_8_1_sh_mask.h"
61#include "bif/bif_5_0_d.h"
62#include "bif/bif_5_0_sh_mask.h"
63#include "dce/dce_10_0_d.h"
64#include "dce/dce_10_0_sh_mask.h"
65
66
67#define ICELAND_SMC_SIZE               0x20000
68
69#define POWERTUNE_DEFAULT_SET_MAX    1
70#define MC_CG_ARB_FREQ_F1           0x0b
71#define VDDC_VDDCI_DELTA            200
72
73#define DEVICE_ID_VI_ICELAND_M_6900	0x6900
74#define DEVICE_ID_VI_ICELAND_M_6901	0x6901
75#define DEVICE_ID_VI_ICELAND_M_6902	0x6902
76#define DEVICE_ID_VI_ICELAND_M_6903	0x6903
77
78static const struct iceland_pt_defaults defaults_iceland = {
79	/*
80	 * sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc,
81	 * TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
82	 */
83	1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
84	{ 0x79,  0x253, 0x25D, 0xAE,  0x72,  0x80,  0x83,  0x86,  0x6F,  0xC8,  0xC9,  0xC9,  0x2F,  0x4D,  0x61  },
85	{ 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 }
86};
87
88/* 35W - XT, XTL */
89static const struct iceland_pt_defaults defaults_icelandxt = {
90	/*
91	 * sviLoadLIneEn, SviLoadLineVddC,
92	 * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
93	 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac,
94	 * BAPM_TEMP_GRADIENT
95	 */
96	1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0,
97	{ 0xA7,  0x0, 0x0, 0xB5,  0x0, 0x0, 0x9F,  0x0, 0x0, 0xD6,  0x0, 0x0, 0xD7,  0x0, 0x0},
98	{ 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0}
99};
100
101/* 25W - PRO, LE */
102static const struct iceland_pt_defaults defaults_icelandpro = {
103	/*
104	 * sviLoadLIneEn, SviLoadLineVddC,
105	 * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
106	 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac,
107	 * BAPM_TEMP_GRADIENT
108	 */
109	1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0,
110	{ 0xB7,  0x0, 0x0, 0xC3,  0x0, 0x0, 0xB5,  0x0, 0x0, 0xEA,  0x0, 0x0, 0xE6,  0x0, 0x0},
111	{ 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0}
112};
113
114static int iceland_start_smc(struct pp_hwmgr *hwmgr)
115{
116	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
117				  SMC_SYSCON_RESET_CNTL, rst_reg, 0);
118
119	return 0;
120}
121
122static void iceland_reset_smc(struct pp_hwmgr *hwmgr)
123{
124	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
125				  SMC_SYSCON_RESET_CNTL,
126				  rst_reg, 1);
127}
128
129
130static void iceland_stop_smc_clock(struct pp_hwmgr *hwmgr)
131{
132	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
133				  SMC_SYSCON_CLOCK_CNTL_0,
134				  ck_disable, 1);
135}
136
137static void iceland_start_smc_clock(struct pp_hwmgr *hwmgr)
138{
139	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
140				  SMC_SYSCON_CLOCK_CNTL_0,
141				  ck_disable, 0);
142}
143
144static int iceland_smu_start_smc(struct pp_hwmgr *hwmgr)
145{
146	/* set smc instruct start point at 0x0 */
147	smu7_program_jump_on_start(hwmgr);
148
149	/* enable smc clock */
150	iceland_start_smc_clock(hwmgr);
151
152	/* de-assert reset */
153	iceland_start_smc(hwmgr);
154
155	PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS,
156				 INTERRUPTS_ENABLED, 1);
157
158	return 0;
159}
160
161
162static int iceland_upload_smc_firmware_data(struct pp_hwmgr *hwmgr,
163					uint32_t length, const uint8_t *src,
164					uint32_t limit, uint32_t start_addr)
165{
166	uint32_t byte_count = length;
167	uint32_t data;
168
169	PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL);
170
171	cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr);
172	PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1);
173
174	while (byte_count >= 4) {
175		data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3];
176		cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data);
177		src += 4;
178		byte_count -= 4;
179	}
180
181	PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
182
183	PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL);
184
185	return 0;
186}
187
188
189static int iceland_smu_upload_firmware_image(struct pp_hwmgr *hwmgr)
190{
191	uint32_t val;
192	struct cgs_firmware_info info = {0};
193
194	if (hwmgr == NULL || hwmgr->device == NULL)
195		return -EINVAL;
196
197	/* load SMC firmware */
198	cgs_get_firmware_info(hwmgr->device,
199		smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
200
201	if (info.image_size & 3) {
202		pr_err("[ powerplay ] SMC ucode is not 4 bytes aligned\n");
203		return -EINVAL;
204	}
205
206	if (info.image_size > ICELAND_SMC_SIZE) {
207		pr_err("[ powerplay ] SMC address is beyond the SMC RAM area\n");
208		return -EINVAL;
209	}
210	hwmgr->smu_version = info.version;
211	/* wait for smc boot up */
212	PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
213					 RCU_UC_EVENTS, boot_seq_done, 0);
214
215	/* clear firmware interrupt enable flag */
216	val = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
217				    ixSMC_SYSCON_MISC_CNTL);
218	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
219			       ixSMC_SYSCON_MISC_CNTL, val | 1);
220
221	/* stop smc clock */
222	iceland_stop_smc_clock(hwmgr);
223
224	/* reset smc */
225	iceland_reset_smc(hwmgr);
226	iceland_upload_smc_firmware_data(hwmgr, info.image_size,
227				(uint8_t *)info.kptr, ICELAND_SMC_SIZE,
228				info.ucode_start_address);
229
230	return 0;
231}
232
233static int iceland_request_smu_load_specific_fw(struct pp_hwmgr *hwmgr,
234						uint32_t firmwareType)
235{
236	return 0;
237}
238
239static int iceland_start_smu(struct pp_hwmgr *hwmgr)
240{
241	struct iceland_smumgr *priv = hwmgr->smu_backend;
242	int result;
243
244	if (!smu7_is_smc_ram_running(hwmgr)) {
245		result = iceland_smu_upload_firmware_image(hwmgr);
246		if (result)
247			return result;
248
249		iceland_smu_start_smc(hwmgr);
250	}
251
252	/* Setup SoftRegsStart here to visit the register UcodeLoadStatus
253	 * to check fw loading state
254	 */
255	smu7_read_smc_sram_dword(hwmgr,
256			SMU71_FIRMWARE_HEADER_LOCATION +
257			offsetof(SMU71_Firmware_Header, SoftRegisters),
258			&(priv->smu7_data.soft_regs_start), 0x40000);
259
260	result = smu7_request_smu_load_fw(hwmgr);
261
262	return result;
263}
264
265static int iceland_smu_init(struct pp_hwmgr *hwmgr)
266{
267	struct iceland_smumgr *iceland_priv = NULL;
268
269	iceland_priv = kzalloc(sizeof(struct iceland_smumgr), GFP_KERNEL);
270
271	if (iceland_priv == NULL)
272		return -ENOMEM;
273
274	hwmgr->smu_backend = iceland_priv;
275
276	if (smu7_init(hwmgr)) {
277		kfree(iceland_priv);
278		return -EINVAL;
279	}
280
281	return 0;
282}
283
284
285static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
286{
287	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
288	struct amdgpu_device *adev = hwmgr->adev;
289	uint32_t dev_id;
290
291	dev_id = adev->pdev->device;
292
293	switch (dev_id) {
294	case DEVICE_ID_VI_ICELAND_M_6900:
295	case DEVICE_ID_VI_ICELAND_M_6903:
296		smu_data->power_tune_defaults = &defaults_icelandxt;
297		break;
298
299	case DEVICE_ID_VI_ICELAND_M_6901:
300	case DEVICE_ID_VI_ICELAND_M_6902:
301		smu_data->power_tune_defaults = &defaults_icelandpro;
302		break;
303	default:
304		smu_data->power_tune_defaults = &defaults_iceland;
305		pr_warn("Unknown V.I. Device ID.\n");
306		break;
307	}
308	return;
309}
310
311static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr)
312{
313	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
314	const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults;
315
316	smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en;
317	smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc;
318	smu_data->power_tune_table.SviLoadLineTrimVddC = 3;
319	smu_data->power_tune_table.SviLoadLineOffsetVddC = 0;
320
321	return 0;
322}
323
324static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr)
325{
326	uint16_t tdc_limit;
327	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
328	const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults;
329
330	tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256);
331	smu_data->power_tune_table.TDC_VDDC_PkgLimit =
332			CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
333	smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
334			defaults->tdc_vddc_throttle_release_limit_perc;
335	smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt;
336
337	return 0;
338}
339
340static int iceland_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
341{
342	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
343	const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults;
344	uint32_t temp;
345
346	if (smu7_read_smc_sram_dword(hwmgr,
347			fuse_table_offset +
348			offsetof(SMU71_Discrete_PmFuses, TdcWaterfallCtl),
349			(uint32_t *)&temp, SMC_RAM_END))
350		PP_ASSERT_WITH_CODE(false,
351				"Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
352				return -EINVAL);
353	else
354		smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl;
355
356	return 0;
357}
358
359static int iceland_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
360{
361	return 0;
362}
363
364static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
365{
366	int i;
367	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
368
369	/* Currently not used. Set all to zero. */
370	for (i = 0; i < 8; i++)
371		smu_data->power_tune_table.GnbLPML[i] = 0;
372
373	return 0;
374}
375
376static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
377{
378	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
379	uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd;
380	uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd;
381	struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table;
382
383	HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
384	LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
385
386	smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd =
387			CONVERT_FROM_HOST_TO_SMC_US(HiSidd);
388	smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd =
389			CONVERT_FROM_HOST_TO_SMC_US(LoSidd);
390
391	return 0;
392}
393
394static int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr)
395{
396	int i;
397	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
398	uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd;
399	uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd;
400
401	PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table,
402			    "The CAC Leakage table does not exist!", return -EINVAL);
403	PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8,
404			    "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL);
405	PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count,
406			    "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL);
407
408	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) {
409		for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) {
410			lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1);
411			hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2);
412		}
413	} else {
414		PP_ASSERT_WITH_CODE(false, "Iceland should always support EVV", return -EINVAL);
415	}
416
417	return 0;
418}
419
420static int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr)
421{
422	int i;
423	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
424	uint8_t *vid = smu_data->power_tune_table.VddCVid;
425	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
426
427	PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8,
428		"There should never be more than 8 entries for VddcVid!!!",
429		return -EINVAL);
430
431	for (i = 0; i < (int)data->vddc_voltage_table.count; i++) {
432		vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value);
433	}
434
435	return 0;
436}
437
438
439
440static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr)
441{
442	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
443	uint32_t pm_fuse_table_offset;
444
445	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
446			PHM_PlatformCaps_PowerContainment)) {
447		if (smu7_read_smc_sram_dword(hwmgr,
448				SMU71_FIRMWARE_HEADER_LOCATION +
449				offsetof(SMU71_Firmware_Header, PmFuseTable),
450				&pm_fuse_table_offset, SMC_RAM_END))
451			PP_ASSERT_WITH_CODE(false,
452					"Attempt to get pm_fuse_table_offset Failed!",
453					return -EINVAL);
454
455		/* DW0 - DW3 */
456		if (iceland_populate_bapm_vddc_vid_sidd(hwmgr))
457			PP_ASSERT_WITH_CODE(false,
458					"Attempt to populate bapm vddc vid Failed!",
459					return -EINVAL);
460
461		/* DW4 - DW5 */
462		if (iceland_populate_vddc_vid(hwmgr))
463			PP_ASSERT_WITH_CODE(false,
464					"Attempt to populate vddc vid Failed!",
465					return -EINVAL);
466
467		/* DW6 */
468		if (iceland_populate_svi_load_line(hwmgr))
469			PP_ASSERT_WITH_CODE(false,
470					"Attempt to populate SviLoadLine Failed!",
471					return -EINVAL);
472		/* DW7 */
473		if (iceland_populate_tdc_limit(hwmgr))
474			PP_ASSERT_WITH_CODE(false,
475					"Attempt to populate TDCLimit Failed!", return -EINVAL);
476		/* DW8 */
477		if (iceland_populate_dw8(hwmgr, pm_fuse_table_offset))
478			PP_ASSERT_WITH_CODE(false,
479					"Attempt to populate TdcWaterfallCtl, "
480					"LPMLTemperature Min and Max Failed!",
481					return -EINVAL);
482
483		/* DW9-DW12 */
484		if (0 != iceland_populate_temperature_scaler(hwmgr))
485			PP_ASSERT_WITH_CODE(false,
486					"Attempt to populate LPMLTemperatureScaler Failed!",
487					return -EINVAL);
488
489		/* DW13-DW16 */
490		if (iceland_populate_gnb_lpml(hwmgr))
491			PP_ASSERT_WITH_CODE(false,
492					"Attempt to populate GnbLPML Failed!",
493					return -EINVAL);
494
495		/* DW18 */
496		if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr))
497			PP_ASSERT_WITH_CODE(false,
498					"Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!",
499					return -EINVAL);
500
501		if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset,
502				(uint8_t *)&smu_data->power_tune_table,
503				sizeof(struct SMU71_Discrete_PmFuses), SMC_RAM_END))
504			PP_ASSERT_WITH_CODE(false,
505					"Attempt to download PmFuseTable Failed!",
506					return -EINVAL);
507	}
508	return 0;
509}
510
511static int iceland_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
512	struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table,
513	uint32_t clock, uint32_t *vol)
514{
515	uint32_t i = 0;
516
517	/* clock - voltage dependency table is empty table */
518	if (allowed_clock_voltage_table->count == 0)
519		return -EINVAL;
520
521	for (i = 0; i < allowed_clock_voltage_table->count; i++) {
522		/* find first sclk bigger than request */
523		if (allowed_clock_voltage_table->entries[i].clk >= clock) {
524			*vol = allowed_clock_voltage_table->entries[i].v;
525			return 0;
526		}
527	}
528
529	/* sclk is bigger than max sclk in the dependence table */
530	*vol = allowed_clock_voltage_table->entries[i - 1].v;
531
532	return 0;
533}
534
535static int iceland_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr,
536		pp_atomctrl_voltage_table_entry *tab, uint16_t *hi,
537		uint16_t *lo)
538{
539	uint16_t v_index;
540	bool vol_found = false;
541	*hi = tab->value * VOLTAGE_SCALE;
542	*lo = tab->value * VOLTAGE_SCALE;
543
544	/* SCLK/VDDC Dependency Table has to exist. */
545	PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk,
546			"The SCLK/VDDC Dependency Table does not exist.",
547			return -EINVAL);
548
549	if (NULL == hwmgr->dyn_state.cac_leakage_table) {
550		pr_warn("CAC Leakage Table does not exist, using vddc.\n");
551		return 0;
552	}
553
554	/*
555	 * Since voltage in the sclk/vddc dependency table is not
556	 * necessarily in ascending order because of ELB voltage
557	 * patching, loop through entire list to find exact voltage.
558	 */
559	for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) {
560		if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) {
561			vol_found = true;
562			if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) {
563				*lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE;
564				*hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE);
565			} else {
566				pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n");
567				*lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE;
568				*hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE);
569			}
570			break;
571		}
572	}
573
574	/*
575	 * If voltage is not found in the first pass, loop again to
576	 * find the best match, equal or higher value.
577	 */
578	if (!vol_found) {
579		for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) {
580			if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) {
581				vol_found = true;
582				if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) {
583					*lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE;
584					*hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE;
585				} else {
586					pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table.");
587					*lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE;
588					*hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE);
589				}
590				break;
591			}
592		}
593
594		if (!vol_found)
595			pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n");
596	}
597
598	return 0;
599}
600
601static int iceland_populate_smc_voltage_table(struct pp_hwmgr *hwmgr,
602		pp_atomctrl_voltage_table_entry *tab,
603		SMU71_Discrete_VoltageLevel *smc_voltage_tab)
604{
605	int result;
606
607	result = iceland_get_std_voltage_value_sidd(hwmgr, tab,
608			&smc_voltage_tab->StdVoltageHiSidd,
609			&smc_voltage_tab->StdVoltageLoSidd);
610	if (0 != result) {
611		smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE;
612		smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE;
613	}
614
615	smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE);
616	CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd);
617	CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd);
618
619	return 0;
620}
621
622static int iceland_populate_smc_vddc_table(struct pp_hwmgr *hwmgr,
623			SMU71_Discrete_DpmTable *table)
624{
625	unsigned int count;
626	int result;
627	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
628
629	table->VddcLevelCount = data->vddc_voltage_table.count;
630	for (count = 0; count < table->VddcLevelCount; count++) {
631		result = iceland_populate_smc_voltage_table(hwmgr,
632				&(data->vddc_voltage_table.entries[count]),
633				&(table->VddcLevel[count]));
634		PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL);
635
636		/* GPIO voltage control */
637		if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control)
638			table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low;
639		else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control)
640			table->VddcLevel[count].Smio = 0;
641	}
642
643	CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount);
644
645	return 0;
646}
647
648static int iceland_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr,
649			SMU71_Discrete_DpmTable *table)
650{
651	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
652	uint32_t count;
653	int result;
654
655	table->VddciLevelCount = data->vddci_voltage_table.count;
656
657	for (count = 0; count < table->VddciLevelCount; count++) {
658		result = iceland_populate_smc_voltage_table(hwmgr,
659				&(data->vddci_voltage_table.entries[count]),
660				&(table->VddciLevel[count]));
661		PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL);
662		if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
663			table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low;
664		else
665			table->VddciLevel[count].Smio |= 0;
666	}
667
668	CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount);
669
670	return 0;
671}
672
673static int iceland_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
674			SMU71_Discrete_DpmTable *table)
675{
676	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
677	uint32_t count;
678	int result;
679
680	table->MvddLevelCount = data->mvdd_voltage_table.count;
681
682	for (count = 0; count < table->VddciLevelCount; count++) {
683		result = iceland_populate_smc_voltage_table(hwmgr,
684				&(data->mvdd_voltage_table.entries[count]),
685				&table->MvddLevel[count]);
686		PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL);
687		if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control)
688			table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low;
689		else
690			table->MvddLevel[count].Smio |= 0;
691	}
692
693	CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
694
695	return 0;
696}
697
698
699static int iceland_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
700	SMU71_Discrete_DpmTable *table)
701{
702	int result;
703
704	result = iceland_populate_smc_vddc_table(hwmgr, table);
705	PP_ASSERT_WITH_CODE(0 == result,
706			"can not populate VDDC voltage table to SMC", return -EINVAL);
707
708	result = iceland_populate_smc_vdd_ci_table(hwmgr, table);
709	PP_ASSERT_WITH_CODE(0 == result,
710			"can not populate VDDCI voltage table to SMC", return -EINVAL);
711
712	result = iceland_populate_smc_mvdd_table(hwmgr, table);
713	PP_ASSERT_WITH_CODE(0 == result,
714			"can not populate MVDD voltage table to SMC", return -EINVAL);
715
716	return 0;
717}
718
719static int iceland_populate_ulv_level(struct pp_hwmgr *hwmgr,
720		struct SMU71_Discrete_Ulv *state)
721{
722	uint32_t voltage_response_time, ulv_voltage;
723	int result;
724	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
725
726	state->CcPwrDynRm = 0;
727	state->CcPwrDynRm1 = 0;
728
729	result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage);
730	PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;);
731
732	if (ulv_voltage == 0) {
733		data->ulv_supported = false;
734		return 0;
735	}
736
737	if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) {
738		/* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */
739		if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v)
740			state->VddcOffset = 0;
741		else
742			/* used in SMIO Mode. not implemented for now. this is backup only for CI. */
743			state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage);
744	} else {
745		/* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */
746		if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v)
747			state->VddcOffsetVid = 0;
748		else  /* used in SVI2 Mode */
749			state->VddcOffsetVid = (uint8_t)(
750					(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage)
751						* VOLTAGE_VID_OFFSET_SCALE2
752						/ VOLTAGE_VID_OFFSET_SCALE1);
753	}
754	state->VddcPhase = 1;
755
756	CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
757	CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
758	CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
759
760	return 0;
761}
762
763static int iceland_populate_ulv_state(struct pp_hwmgr *hwmgr,
764		 SMU71_Discrete_Ulv *ulv_level)
765{
766	return iceland_populate_ulv_level(hwmgr, ulv_level);
767}
768
769static int iceland_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU71_Discrete_DpmTable *table)
770{
771	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
772	struct smu7_dpm_table *dpm_table = &data->dpm_table;
773	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
774	uint32_t i;
775
776	/* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
777	for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
778		table->LinkLevel[i].PcieGenSpeed  =
779			(uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
780		table->LinkLevel[i].PcieLaneCount =
781			(uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1);
782		table->LinkLevel[i].EnabledForActivity =
783			1;
784		table->LinkLevel[i].SPC =
785			(uint8_t)(data->pcie_spc_cap & 0xff);
786		table->LinkLevel[i].DownThreshold =
787			PP_HOST_TO_SMC_UL(5);
788		table->LinkLevel[i].UpThreshold =
789			PP_HOST_TO_SMC_UL(30);
790	}
791
792	smu_data->smc_state_table.LinkLevelCount =
793		(uint8_t)dpm_table->pcie_speed_table.count;
794	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
795		phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
796
797	return 0;
798}
799
800static int iceland_calculate_sclk_params(struct pp_hwmgr *hwmgr,
801		uint32_t engine_clock, SMU71_Discrete_GraphicsLevel *sclk)
802{
803	const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
804	pp_atomctrl_clock_dividers_vi dividers;
805	uint32_t spll_func_cntl            = data->clock_registers.vCG_SPLL_FUNC_CNTL;
806	uint32_t spll_func_cntl_3          = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
807	uint32_t spll_func_cntl_4          = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
808	uint32_t cg_spll_spread_spectrum   = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
809	uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
810	uint32_t    reference_clock;
811	uint32_t reference_divider;
812	uint32_t fbdiv;
813	int result;
814
815	/* get the engine clock dividers for this clock value*/
816	result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock,  &dividers);
817
818	PP_ASSERT_WITH_CODE(result == 0,
819		"Error retrieving Engine Clock dividers from VBIOS.", return result);
820
821	/* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
822	reference_clock = atomctrl_get_reference_clock(hwmgr);
823
824	reference_divider = 1 + dividers.uc_pll_ref_div;
825
826	/* low 14 bits is fraction and high 12 bits is divider*/
827	fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
828
829	/* SPLL_FUNC_CNTL setup*/
830	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
831		CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div);
832	spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
833		CG_SPLL_FUNC_CNTL, SPLL_PDIV_A,  dividers.uc_pll_post_div);
834
835	/* SPLL_FUNC_CNTL_3 setup*/
836	spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
837		CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv);
838
839	/* set to use fractional accumulation*/
840	spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
841		CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1);
842
843	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
844			PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
845		pp_atomctrl_internal_ss_info ss_info;
846
847		uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div;
848		if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) {
849			/*
850			* ss_info.speed_spectrum_percentage -- in unit of 0.01%
851			* ss_info.speed_spectrum_rate -- in unit of khz
852			*/
853			/* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
854			uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate);
855
856			/* clkv = 2 * D * fbdiv / NS */
857			uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000);
858
859			cg_spll_spread_spectrum =
860				PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS);
861			cg_spll_spread_spectrum =
862				PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
863			cg_spll_spread_spectrum_2 =
864				PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV);
865		}
866	}
867
868	sclk->SclkFrequency        = engine_clock;
869	sclk->CgSpllFuncCntl3      = spll_func_cntl_3;
870	sclk->CgSpllFuncCntl4      = spll_func_cntl_4;
871	sclk->SpllSpreadSpectrum   = cg_spll_spread_spectrum;
872	sclk->SpllSpreadSpectrum2  = cg_spll_spread_spectrum_2;
873	sclk->SclkDid              = (uint8_t)dividers.pll_post_divider;
874
875	return 0;
876}
877
878static int iceland_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr,
879				const struct phm_phase_shedding_limits_table *pl,
880					uint32_t sclk, uint32_t *p_shed)
881{
882	unsigned int i;
883
884	/* use the minimum phase shedding */
885	*p_shed = 1;
886
887	for (i = 0; i < pl->count; i++) {
888		if (sclk < pl->entries[i].Sclk) {
889			*p_shed = i;
890			break;
891		}
892	}
893	return 0;
894}
895
896static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
897						uint32_t engine_clock,
898				SMU71_Discrete_GraphicsLevel *graphic_level)
899{
900	int result;
901	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
902
903	result = iceland_calculate_sclk_params(hwmgr, engine_clock, graphic_level);
904
905	/* populate graphics levels*/
906	result = iceland_get_dependency_volt_by_clk(hwmgr,
907		hwmgr->dyn_state.vddc_dependency_on_sclk, engine_clock,
908		&graphic_level->MinVddc);
909	PP_ASSERT_WITH_CODE((0 == result),
910		"can not find VDDC voltage value for VDDC engine clock dependency table", return result);
911
912	/* SCLK frequency in units of 10KHz*/
913	graphic_level->SclkFrequency = engine_clock;
914	graphic_level->MinVddcPhases = 1;
915
916	if (data->vddc_phase_shed_control)
917		iceland_populate_phase_value_based_on_sclk(hwmgr,
918				hwmgr->dyn_state.vddc_phase_shed_limits_table,
919				engine_clock,
920				&graphic_level->MinVddcPhases);
921
922	/* Indicates maximum activity level for this performance level. 50% for now*/
923	graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity;
924
925	graphic_level->CcPwrDynRm = 0;
926	graphic_level->CcPwrDynRm1 = 0;
927	/* this level can be used if activity is high enough.*/
928	graphic_level->EnabledForActivity = 0;
929	/* this level can be used for throttling.*/
930	graphic_level->EnabledForThrottle = 1;
931	graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst;
932	graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst;
933	graphic_level->VoltageDownHyst = 0;
934	graphic_level->PowerThrottle = 0;
935
936	data->display_timing.min_clock_in_sr =
937			hwmgr->display_config->min_core_set_clock_in_sr;
938
939	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
940			PHM_PlatformCaps_SclkDeepSleep))
941		graphic_level->DeepSleepDivId =
942				smu7_get_sleep_divider_id_from_clock(engine_clock,
943						data->display_timing.min_clock_in_sr);
944
945	/* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
946	graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
947
948	if (0 == result) {
949		graphic_level->MinVddc = PP_HOST_TO_SMC_UL(graphic_level->MinVddc * VOLTAGE_SCALE);
950		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);
951		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency);
952		CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel);
953		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3);
954		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4);
955		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum);
956		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2);
957		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm);
958		CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1);
959	}
960
961	return result;
962}
963
964static int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
965{
966	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
967	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
968	struct smu7_dpm_table *dpm_table = &data->dpm_table;
969	uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start +
970				offsetof(SMU71_Discrete_DpmTable, GraphicsLevel);
971
972	uint32_t level_array_size = sizeof(SMU71_Discrete_GraphicsLevel) *
973						SMU71_MAX_LEVELS_GRAPHICS;
974
975	SMU71_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel;
976
977	uint32_t i;
978	uint8_t highest_pcie_level_enabled = 0;
979	uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0;
980	uint8_t count = 0;
981	int result = 0;
982
983	memset(levels, 0x00, level_array_size);
984
985	for (i = 0; i < dpm_table->sclk_table.count; i++) {
986		result = iceland_populate_single_graphic_level(hwmgr,
987					dpm_table->sclk_table.dpm_levels[i].value,
988					&(smu_data->smc_state_table.GraphicsLevel[i]));
989		if (result != 0)
990			return result;
991
992		/* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
993		if (i > 1)
994			smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0;
995	}
996
997	/* Only enable level 0 for now. */
998	smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
999
1000	/* set highest level watermark to high */
1001	if (dpm_table->sclk_table.count > 1)
1002		smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark =
1003			PPSMC_DISPLAY_WATERMARK_HIGH;
1004
1005	smu_data->smc_state_table.GraphicsDpmLevelCount =
1006		(uint8_t)dpm_table->sclk_table.count;
1007	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
1008		phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
1009
1010	while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
1011				(1 << (highest_pcie_level_enabled + 1))) != 0) {
1012		highest_pcie_level_enabled++;
1013	}
1014
1015	while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
1016		(1 << lowest_pcie_level_enabled)) == 0) {
1017		lowest_pcie_level_enabled++;
1018	}
1019
1020	while ((count < highest_pcie_level_enabled) &&
1021			((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
1022				(1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) {
1023		count++;
1024	}
1025
1026	mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ?
1027		(lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled;
1028
1029
1030	/* set pcieDpmLevel to highest_pcie_level_enabled*/
1031	for (i = 2; i < dpm_table->sclk_table.count; i++) {
1032		smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled;
1033	}
1034
1035	/* set pcieDpmLevel to lowest_pcie_level_enabled*/
1036	smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled;
1037
1038	/* set pcieDpmLevel to mid_pcie_level_enabled*/
1039	smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled;
1040
1041	/* level count will send to smc once at init smc table and never change*/
1042	result = smu7_copy_bytes_to_smc(hwmgr, level_array_adress,
1043				(uint8_t *)levels, (uint32_t)level_array_size,
1044								SMC_RAM_END);
1045
1046	return result;
1047}
1048
1049static int iceland_calculate_mclk_params(
1050		struct pp_hwmgr *hwmgr,
1051		uint32_t memory_clock,
1052		SMU71_Discrete_MemoryLevel *mclk,
1053		bool strobe_mode,
1054		bool dllStateOn
1055		)
1056{
1057	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1058
1059	uint32_t  dll_cntl = data->clock_registers.vDLL_CNTL;
1060	uint32_t  mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
1061	uint32_t  mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL;
1062	uint32_t  mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL;
1063	uint32_t  mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL;
1064	uint32_t  mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1;
1065	uint32_t  mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2;
1066	uint32_t  mpll_ss1 = data->clock_registers.vMPLL_SS1;
1067	uint32_t  mpll_ss2 = data->clock_registers.vMPLL_SS2;
1068
1069	pp_atomctrl_memory_clock_param mpll_param;
1070	int result;
1071
1072	result = atomctrl_get_memory_pll_dividers_si(hwmgr,
1073				memory_clock, &mpll_param, strobe_mode);
1074	PP_ASSERT_WITH_CODE(0 == result,
1075		"Error retrieving Memory Clock Parameters from VBIOS.", return result);
1076
1077	/* MPLL_FUNC_CNTL setup*/
1078	mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl);
1079
1080	/* MPLL_FUNC_CNTL_1 setup*/
1081	mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
1082							MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf);
1083	mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
1084							MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac);
1085	mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
1086							MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode);
1087
1088	/* MPLL_AD_FUNC_CNTL setup*/
1089	mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl,
1090							MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
1091
1092	if (data->is_memory_gddr5) {
1093		/* MPLL_DQ_FUNC_CNTL setup*/
1094		mpll_dq_func_cntl  = PHM_SET_FIELD(mpll_dq_func_cntl,
1095								MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel);
1096		mpll_dq_func_cntl  = PHM_SET_FIELD(mpll_dq_func_cntl,
1097								MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
1098	}
1099
1100	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1101			PHM_PlatformCaps_MemorySpreadSpectrumSupport)) {
1102		/*
1103		 ************************************
1104		 Fref = Reference Frequency
1105		 NF = Feedback divider ratio
1106		 NR = Reference divider ratio
1107		 Fnom = Nominal VCO output frequency = Fref * NF / NR
1108		 Fs = Spreading Rate
1109		 D = Percentage down-spread / 2
1110		 Fint = Reference input frequency to PFD = Fref / NR
1111		 NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
1112		 CLKS = NS - 1 = ISS_STEP_NUM[11:0]
1113		 NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
1114		 CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
1115		 *************************************
1116		 */
1117		pp_atomctrl_internal_ss_info ss_info;
1118		uint32_t freq_nom;
1119		uint32_t tmp;
1120		uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr);
1121
1122		/* for GDDR5 for all modes and DDR3 */
1123		if (1 == mpll_param.qdr)
1124			freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider);
1125		else
1126			freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider);
1127
1128		/* tmp = (freq_nom / reference_clock * reference_divider) ^ 2  Note: S.I. reference_divider = 1*/
1129		tmp = (freq_nom / reference_clock);
1130		tmp = tmp * tmp;
1131
1132		if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) {
1133			/* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
1134			/* ss.Info.speed_spectrum_rate -- in unit of khz */
1135			/* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
1136			/*     = reference_clock * 5 / speed_spectrum_rate */
1137			uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate;
1138
1139			/* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
1140			/*     = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
1141			uint32_t clkv =
1142				(uint32_t)((((131 * ss_info.speed_spectrum_percentage *
1143							ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom);
1144
1145			mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv);
1146			mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks);
1147		}
1148	}
1149
1150	/* MCLK_PWRMGT_CNTL setup */
1151	mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1152		MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed);
1153	mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1154		MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn);
1155	mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1156		MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn);
1157
1158
1159	/* Save the result data to outpupt memory level structure */
1160	mclk->MclkFrequency   = memory_clock;
1161	mclk->MpllFuncCntl    = mpll_func_cntl;
1162	mclk->MpllFuncCntl_1  = mpll_func_cntl_1;
1163	mclk->MpllFuncCntl_2  = mpll_func_cntl_2;
1164	mclk->MpllAdFuncCntl  = mpll_ad_func_cntl;
1165	mclk->MpllDqFuncCntl  = mpll_dq_func_cntl;
1166	mclk->MclkPwrmgtCntl  = mclk_pwrmgt_cntl;
1167	mclk->DllCntl         = dll_cntl;
1168	mclk->MpllSs1         = mpll_ss1;
1169	mclk->MpllSs2         = mpll_ss2;
1170
1171	return 0;
1172}
1173
1174static uint8_t iceland_get_mclk_frequency_ratio(uint32_t memory_clock,
1175		bool strobe_mode)
1176{
1177	uint8_t mc_para_index;
1178
1179	if (strobe_mode) {
1180		if (memory_clock < 12500) {
1181			mc_para_index = 0x00;
1182		} else if (memory_clock > 47500) {
1183			mc_para_index = 0x0f;
1184		} else {
1185			mc_para_index = (uint8_t)((memory_clock - 10000) / 2500);
1186		}
1187	} else {
1188		if (memory_clock < 65000) {
1189			mc_para_index = 0x00;
1190		} else if (memory_clock > 135000) {
1191			mc_para_index = 0x0f;
1192		} else {
1193			mc_para_index = (uint8_t)((memory_clock - 60000) / 5000);
1194		}
1195	}
1196
1197	return mc_para_index;
1198}
1199
1200static uint8_t iceland_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock)
1201{
1202	uint8_t mc_para_index;
1203
1204	if (memory_clock < 10000) {
1205		mc_para_index = 0;
1206	} else if (memory_clock >= 80000) {
1207		mc_para_index = 0x0f;
1208	} else {
1209		mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1);
1210	}
1211
1212	return mc_para_index;
1213}
1214
1215static int iceland_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl,
1216					uint32_t memory_clock, uint32_t *p_shed)
1217{
1218	unsigned int i;
1219
1220	*p_shed = 1;
1221
1222	for (i = 0; i < pl->count; i++) {
1223		if (memory_clock < pl->entries[i].Mclk) {
1224			*p_shed = i;
1225			break;
1226		}
1227	}
1228
1229	return 0;
1230}
1231
1232static int iceland_populate_single_memory_level(
1233		struct pp_hwmgr *hwmgr,
1234		uint32_t memory_clock,
1235		SMU71_Discrete_MemoryLevel *memory_level
1236		)
1237{
1238	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1239	int result = 0;
1240	bool dll_state_on;
1241	uint32_t mclk_edc_wr_enable_threshold = 40000;
1242	uint32_t mclk_edc_enable_threshold = 40000;
1243	uint32_t mclk_strobe_mode_threshold = 40000;
1244
1245	if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) {
1246		result = iceland_get_dependency_volt_by_clk(hwmgr,
1247			hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc);
1248		PP_ASSERT_WITH_CODE((0 == result),
1249			"can not find MinVddc voltage value from memory VDDC voltage dependency table", return result);
1250	}
1251
1252	if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) {
1253		memory_level->MinVddci = memory_level->MinVddc;
1254	} else if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) {
1255		result = iceland_get_dependency_volt_by_clk(hwmgr,
1256				hwmgr->dyn_state.vddci_dependency_on_mclk,
1257				memory_clock,
1258				&memory_level->MinVddci);
1259		PP_ASSERT_WITH_CODE((0 == result),
1260			"can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result);
1261	}
1262
1263	memory_level->MinVddcPhases = 1;
1264
1265	if (data->vddc_phase_shed_control) {
1266		iceland_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table,
1267				memory_clock, &memory_level->MinVddcPhases);
1268	}
1269
1270	memory_level->EnabledForThrottle = 1;
1271	memory_level->EnabledForActivity = 0;
1272	memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
1273	memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
1274	memory_level->VoltageDownHyst = 0;
1275
1276	/* Indicates maximum activity level for this performance level.*/
1277	memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
1278	memory_level->StutterEnable = 0;
1279	memory_level->StrobeEnable = 0;
1280	memory_level->EdcReadEnable = 0;
1281	memory_level->EdcWriteEnable = 0;
1282	memory_level->RttEnable = 0;
1283
1284	/* default set to low watermark. Highest level will be set to high later.*/
1285	memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1286
1287	data->display_timing.num_existing_displays = hwmgr->display_config->num_display;
1288	data->display_timing.vrefresh = hwmgr->display_config->vrefresh;
1289
1290	/* stutter mode not support on iceland */
1291
1292	/* decide strobe mode*/
1293	memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) &&
1294		(memory_clock <= mclk_strobe_mode_threshold);
1295
1296	/* decide EDC mode and memory clock ratio*/
1297	if (data->is_memory_gddr5) {
1298		memory_level->StrobeRatio = iceland_get_mclk_frequency_ratio(memory_clock,
1299					memory_level->StrobeEnable);
1300
1301		if ((mclk_edc_enable_threshold != 0) &&
1302				(memory_clock > mclk_edc_enable_threshold)) {
1303			memory_level->EdcReadEnable = 1;
1304		}
1305
1306		if ((mclk_edc_wr_enable_threshold != 0) &&
1307				(memory_clock > mclk_edc_wr_enable_threshold)) {
1308			memory_level->EdcWriteEnable = 1;
1309		}
1310
1311		if (memory_level->StrobeEnable) {
1312			if (iceland_get_mclk_frequency_ratio(memory_clock, 1) >=
1313					((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf))
1314				dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
1315			else
1316				dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0;
1317		} else
1318			dll_state_on = data->dll_default_on;
1319	} else {
1320		memory_level->StrobeRatio =
1321			iceland_get_ddr3_mclk_frequency_ratio(memory_clock);
1322		dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
1323	}
1324
1325	result = iceland_calculate_mclk_params(hwmgr,
1326		memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on);
1327
1328	if (0 == result) {
1329		memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE);
1330		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases);
1331		memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE);
1332		memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE);
1333		/* MCLK frequency in units of 10KHz*/
1334		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency);
1335		/* Indicates maximum activity level for this performance level.*/
1336		CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel);
1337		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl);
1338		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1);
1339		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2);
1340		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl);
1341		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl);
1342		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl);
1343		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl);
1344		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1);
1345		CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2);
1346	}
1347
1348	return result;
1349}
1350
1351static int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1352{
1353	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1354	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1355	struct smu7_dpm_table *dpm_table = &data->dpm_table;
1356	int result;
1357
1358	/* populate MCLK dpm table to SMU7 */
1359	uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, MemoryLevel);
1360	uint32_t level_array_size = sizeof(SMU71_Discrete_MemoryLevel) * SMU71_MAX_LEVELS_MEMORY;
1361	SMU71_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel;
1362	uint32_t i;
1363
1364	memset(levels, 0x00, level_array_size);
1365
1366	for (i = 0; i < dpm_table->mclk_table.count; i++) {
1367		PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
1368			"can not populate memory level as memory clock is zero", return -EINVAL);
1369		result = iceland_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value,
1370			&(smu_data->smc_state_table.MemoryLevel[i]));
1371		if (0 != result) {
1372			return result;
1373		}
1374	}
1375
1376	/* Only enable level 0 for now.*/
1377	smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
1378
1379	/*
1380	* in order to prevent MC activity from stutter mode to push DPM up.
1381	* the UVD change complements this by putting the MCLK in a higher state
1382	* by default such that we are not effected by up threshold or and MCLK DPM latency.
1383	*/
1384	smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F;
1385	CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel);
1386
1387	smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count;
1388	data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
1389	/* set highest level watermark to high*/
1390	smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
1391
1392	/* level count will send to smc once at init smc table and never change*/
1393	result = smu7_copy_bytes_to_smc(hwmgr,
1394		level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size,
1395		SMC_RAM_END);
1396
1397	return result;
1398}
1399
1400static int iceland_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk,
1401					SMU71_Discrete_VoltageLevel *voltage)
1402{
1403	const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1404
1405	uint32_t i = 0;
1406
1407	if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
1408		/* find mvdd value which clock is more than request */
1409		for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) {
1410			if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) {
1411				/* Always round to higher voltage. */
1412				voltage->Voltage = data->mvdd_voltage_table.entries[i].value;
1413				break;
1414			}
1415		}
1416
1417		PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count,
1418			"MVDD Voltage is outside the supported range.", return -EINVAL);
1419
1420	} else {
1421		return -EINVAL;
1422	}
1423
1424	return 0;
1425}
1426
1427static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
1428	SMU71_Discrete_DpmTable *table)
1429{
1430	int result = 0;
1431	const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1432	struct pp_atomctrl_clock_dividers_vi dividers;
1433	uint32_t vddc_phase_shed_control = 0;
1434
1435	SMU71_Discrete_VoltageLevel voltage_level;
1436	uint32_t spll_func_cntl    = data->clock_registers.vCG_SPLL_FUNC_CNTL;
1437	uint32_t spll_func_cntl_2  = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
1438	uint32_t dll_cntl          = data->clock_registers.vDLL_CNTL;
1439	uint32_t mclk_pwrmgt_cntl  = data->clock_registers.vMCLK_PWRMGT_CNTL;
1440
1441
1442	/* The ACPI state should not do DPM on DC (or ever).*/
1443	table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
1444
1445	if (data->acpi_vddc)
1446		table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE);
1447	else
1448		table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE);
1449
1450	table->ACPILevel.MinVddcPhases = vddc_phase_shed_control ? 0 : 1;
1451	/* assign zero for now*/
1452	table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr);
1453
1454	/* get the engine clock dividers for this clock value*/
1455	result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
1456		table->ACPILevel.SclkFrequency,  &dividers);
1457
1458	PP_ASSERT_WITH_CODE(result == 0,
1459		"Error retrieving Engine Clock dividers from VBIOS.", return result);
1460
1461	/* divider ID for required SCLK*/
1462	table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
1463	table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1464	table->ACPILevel.DeepSleepDivId = 0;
1465
1466	spll_func_cntl      = PHM_SET_FIELD(spll_func_cntl,
1467							CG_SPLL_FUNC_CNTL,   SPLL_PWRON,     0);
1468	spll_func_cntl      = PHM_SET_FIELD(spll_func_cntl,
1469							CG_SPLL_FUNC_CNTL,   SPLL_RESET,     1);
1470	spll_func_cntl_2    = PHM_SET_FIELD(spll_func_cntl_2,
1471							CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL,   4);
1472
1473	table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
1474	table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
1475	table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
1476	table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
1477	table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
1478	table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
1479	table->ACPILevel.CcPwrDynRm = 0;
1480	table->ACPILevel.CcPwrDynRm1 = 0;
1481
1482
1483	/* For various features to be enabled/disabled while this level is active.*/
1484	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
1485	/* SCLK frequency in units of 10KHz*/
1486	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
1487	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
1488	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
1489	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
1490	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
1491	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
1492	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
1493	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
1494	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
1495
1496	/* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
1497	table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc;
1498	table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;
1499
1500	if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
1501		table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc;
1502	else {
1503		if (data->acpi_vddci != 0)
1504			table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE);
1505		else
1506			table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE);
1507	}
1508
1509	if (0 == iceland_populate_mvdd_value(hwmgr, 0, &voltage_level))
1510		table->MemoryACPILevel.MinMvdd =
1511			PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE);
1512	else
1513		table->MemoryACPILevel.MinMvdd = 0;
1514
1515	/* Force reset on DLL*/
1516	mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1517		MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1);
1518	mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1519		MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1);
1520
1521	/* Disable DLL in ACPIState*/
1522	mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1523		MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0);
1524	mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1525		MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0);
1526
1527	/* Enable DLL bypass signal*/
1528	dll_cntl            = PHM_SET_FIELD(dll_cntl,
1529		DLL_CNTL, MRDCK0_BYPASS, 0);
1530	dll_cntl            = PHM_SET_FIELD(dll_cntl,
1531		DLL_CNTL, MRDCK1_BYPASS, 0);
1532
1533	table->MemoryACPILevel.DllCntl            =
1534		PP_HOST_TO_SMC_UL(dll_cntl);
1535	table->MemoryACPILevel.MclkPwrmgtCntl     =
1536		PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl);
1537	table->MemoryACPILevel.MpllAdFuncCntl     =
1538		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL);
1539	table->MemoryACPILevel.MpllDqFuncCntl     =
1540		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL);
1541	table->MemoryACPILevel.MpllFuncCntl       =
1542		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL);
1543	table->MemoryACPILevel.MpllFuncCntl_1     =
1544		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1);
1545	table->MemoryACPILevel.MpllFuncCntl_2     =
1546		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2);
1547	table->MemoryACPILevel.MpllSs1            =
1548		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1);
1549	table->MemoryACPILevel.MpllSs2            =
1550		PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2);
1551
1552	table->MemoryACPILevel.EnabledForThrottle = 0;
1553	table->MemoryACPILevel.EnabledForActivity = 0;
1554	table->MemoryACPILevel.UpHyst = 0;
1555	table->MemoryACPILevel.DownHyst = 100;
1556	table->MemoryACPILevel.VoltageDownHyst = 0;
1557	/* Indicates maximum activity level for this performance level.*/
1558	table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
1559
1560	table->MemoryACPILevel.StutterEnable = 0;
1561	table->MemoryACPILevel.StrobeEnable = 0;
1562	table->MemoryACPILevel.EdcReadEnable = 0;
1563	table->MemoryACPILevel.EdcWriteEnable = 0;
1564	table->MemoryACPILevel.RttEnable = 0;
1565
1566	return result;
1567}
1568
1569static int iceland_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
1570					SMU71_Discrete_DpmTable *table)
1571{
1572	return 0;
1573}
1574
1575static int iceland_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
1576		SMU71_Discrete_DpmTable *table)
1577{
1578	return 0;
1579}
1580
1581static int iceland_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
1582		SMU71_Discrete_DpmTable *table)
1583{
1584	return 0;
1585}
1586
1587static int iceland_populate_memory_timing_parameters(
1588		struct pp_hwmgr *hwmgr,
1589		uint32_t engine_clock,
1590		uint32_t memory_clock,
1591		struct SMU71_Discrete_MCArbDramTimingTableEntry *arb_regs
1592		)
1593{
1594	uint32_t dramTiming;
1595	uint32_t dramTiming2;
1596	uint32_t burstTime;
1597	int result;
1598
1599	result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
1600				engine_clock, memory_clock);
1601
1602	PP_ASSERT_WITH_CODE(result == 0,
1603		"Error calling VBIOS to set DRAM_TIMING.", return result);
1604
1605	dramTiming  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
1606	dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
1607	burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
1608
1609	arb_regs->McArbDramTiming  = PP_HOST_TO_SMC_UL(dramTiming);
1610	arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2);
1611	arb_regs->McArbBurstTime = (uint8_t)burstTime;
1612
1613	return 0;
1614}
1615
1616static int iceland_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
1617{
1618	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1619	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1620	int result = 0;
1621	SMU71_Discrete_MCArbDramTimingTable  arb_regs;
1622	uint32_t i, j;
1623
1624	memset(&arb_regs, 0x00, sizeof(SMU71_Discrete_MCArbDramTimingTable));
1625
1626	for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
1627		for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
1628			result = iceland_populate_memory_timing_parameters
1629				(hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value,
1630				 data->dpm_table.mclk_table.dpm_levels[j].value,
1631				 &arb_regs.entries[i][j]);
1632
1633			if (0 != result) {
1634				break;
1635			}
1636		}
1637	}
1638
1639	if (0 == result) {
1640		result = smu7_copy_bytes_to_smc(
1641				hwmgr,
1642				smu_data->smu7_data.arb_table_start,
1643				(uint8_t *)&arb_regs,
1644				sizeof(SMU71_Discrete_MCArbDramTimingTable),
1645				SMC_RAM_END
1646				);
1647	}
1648
1649	return result;
1650}
1651
1652static int iceland_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
1653			SMU71_Discrete_DpmTable *table)
1654{
1655	int result = 0;
1656	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1657	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1658	table->GraphicsBootLevel = 0;
1659	table->MemoryBootLevel = 0;
1660
1661	/* find boot level from dpm table*/
1662	result = phm_find_boot_level(&(data->dpm_table.sclk_table),
1663			data->vbios_boot_state.sclk_bootup_value,
1664			(uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel));
1665
1666	if (0 != result) {
1667		smu_data->smc_state_table.GraphicsBootLevel = 0;
1668		pr_err("VBIOS did not find boot engine clock value in dependency table. Using Graphics DPM level 0!\n");
1669		result = 0;
1670	}
1671
1672	result = phm_find_boot_level(&(data->dpm_table.mclk_table),
1673		data->vbios_boot_state.mclk_bootup_value,
1674		(uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel));
1675
1676	if (0 != result) {
1677		smu_data->smc_state_table.MemoryBootLevel = 0;
1678		pr_err("VBIOS did not find boot engine clock value in dependency table. Using Memory DPM level 0!\n");
1679		result = 0;
1680	}
1681
1682	table->BootVddc = data->vbios_boot_state.vddc_bootup_value;
1683	if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
1684		table->BootVddci = table->BootVddc;
1685	else
1686		table->BootVddci = data->vbios_boot_state.vddci_bootup_value;
1687
1688	table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value;
1689
1690	return result;
1691}
1692
1693static int iceland_populate_mc_reg_address(struct pp_hwmgr *hwmgr,
1694				 SMU71_Discrete_MCRegisters *mc_reg_table)
1695{
1696	const struct iceland_smumgr *smu_data = (struct iceland_smumgr *)hwmgr->smu_backend;
1697
1698	uint32_t i, j;
1699
1700	for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) {
1701		if (smu_data->mc_reg_table.validflag & 1<<j) {
1702			PP_ASSERT_WITH_CODE(i < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE,
1703				"Index of mc_reg_table->address[] array out of boundary", return -EINVAL);
1704			mc_reg_table->address[i].s0 =
1705				PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0);
1706			mc_reg_table->address[i].s1 =
1707				PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1);
1708			i++;
1709		}
1710	}
1711
1712	mc_reg_table->last = (uint8_t)i;
1713
1714	return 0;
1715}
1716
1717/*convert register values from driver to SMC format */
1718static void iceland_convert_mc_registers(
1719	const struct iceland_mc_reg_entry *entry,
1720	SMU71_Discrete_MCRegisterSet *data,
1721	uint32_t num_entries, uint32_t valid_flag)
1722{
1723	uint32_t i, j;
1724
1725	for (i = 0, j = 0; j < num_entries; j++) {
1726		if (valid_flag & 1<<j) {
1727			data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]);
1728			i++;
1729		}
1730	}
1731}
1732
1733static int iceland_convert_mc_reg_table_entry_to_smc(struct pp_hwmgr *hwmgr,
1734		const uint32_t memory_clock,
1735		SMU71_Discrete_MCRegisterSet *mc_reg_table_data
1736		)
1737{
1738	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1739	uint32_t i = 0;
1740
1741	for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) {
1742		if (memory_clock <=
1743			smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) {
1744			break;
1745		}
1746	}
1747
1748	if ((i == smu_data->mc_reg_table.num_entries) && (i > 0))
1749		--i;
1750
1751	iceland_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i],
1752				mc_reg_table_data, smu_data->mc_reg_table.last,
1753				smu_data->mc_reg_table.validflag);
1754
1755	return 0;
1756}
1757
1758static int iceland_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr,
1759		SMU71_Discrete_MCRegisters *mc_regs)
1760{
1761	int result = 0;
1762	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1763	int res;
1764	uint32_t i;
1765
1766	for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
1767		res = iceland_convert_mc_reg_table_entry_to_smc(
1768				hwmgr,
1769				data->dpm_table.mclk_table.dpm_levels[i].value,
1770				&mc_regs->data[i]
1771				);
1772
1773		if (0 != res)
1774			result = res;
1775	}
1776
1777	return result;
1778}
1779
1780static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr)
1781{
1782	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1783	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1784	uint32_t address;
1785	int32_t result;
1786
1787	if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK))
1788		return 0;
1789
1790
1791	memset(&smu_data->mc_regs, 0, sizeof(SMU71_Discrete_MCRegisters));
1792
1793	result = iceland_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs));
1794
1795	if (result != 0)
1796		return result;
1797
1798
1799	address = smu_data->smu7_data.mc_reg_table_start + (uint32_t)offsetof(SMU71_Discrete_MCRegisters, data[0]);
1800
1801	return  smu7_copy_bytes_to_smc(hwmgr, address,
1802				 (uint8_t *)&smu_data->mc_regs.data[0],
1803				sizeof(SMU71_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count,
1804				SMC_RAM_END);
1805}
1806
1807static int iceland_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr)
1808{
1809	int result;
1810	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1811
1812	memset(&smu_data->mc_regs, 0x00, sizeof(SMU71_Discrete_MCRegisters));
1813	result = iceland_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs));
1814	PP_ASSERT_WITH_CODE(0 == result,
1815		"Failed to initialize MCRegTable for the MC register addresses!", return result;);
1816
1817	result = iceland_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs);
1818	PP_ASSERT_WITH_CODE(0 == result,
1819		"Failed to initialize MCRegTable for driver state!", return result;);
1820
1821	return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start,
1822			(uint8_t *)&smu_data->mc_regs, sizeof(SMU71_Discrete_MCRegisters), SMC_RAM_END);
1823}
1824
1825static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr)
1826{
1827	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1828	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1829	uint8_t count, level;
1830
1831	count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count);
1832
1833	for (level = 0; level < count; level++) {
1834		if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk
1835			 >= data->vbios_boot_state.sclk_bootup_value) {
1836			smu_data->smc_state_table.GraphicsBootLevel = level;
1837			break;
1838		}
1839	}
1840
1841	count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count);
1842
1843	for (level = 0; level < count; level++) {
1844		if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk
1845			>= data->vbios_boot_state.mclk_bootup_value) {
1846			smu_data->smc_state_table.MemoryBootLevel = level;
1847			break;
1848		}
1849	}
1850
1851	return 0;
1852}
1853
1854static int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
1855{
1856	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1857	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1858	const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults;
1859	SMU71_Discrete_DpmTable  *dpm_table = &(smu_data->smc_state_table);
1860	struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table;
1861	struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table;
1862	const uint16_t *def1, *def2;
1863	int i, j, k;
1864
1865
1866	/*
1867	 * TDP number of fraction bits are changed from 8 to 7 for Iceland
1868	 * as requested by SMC team
1869	 */
1870
1871	dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256));
1872	dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256));
1873
1874
1875	dpm_table->DTETjOffset = 0;
1876
1877	dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES);
1878	dpm_table->GpuTjHyst = 8;
1879
1880	dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base;
1881
1882	/* The following are for new Iceland Multi-input fan/thermal control */
1883	if (NULL != ppm) {
1884		dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000;
1885		dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256;
1886	} else {
1887		dpm_table->PPM_PkgPwrLimit = 0;
1888		dpm_table->PPM_TemperatureLimit = 0;
1889	}
1890
1891	CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit);
1892	CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit);
1893
1894	dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient);
1895	def1 = defaults->bapmti_r;
1896	def2 = defaults->bapmti_rc;
1897
1898	for (i = 0; i < SMU71_DTE_ITERATIONS; i++) {
1899		for (j = 0; j < SMU71_DTE_SOURCES; j++) {
1900			for (k = 0; k < SMU71_DTE_SINKS; k++) {
1901				dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1);
1902				dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2);
1903				def1++;
1904				def2++;
1905			}
1906		}
1907	}
1908
1909	return 0;
1910}
1911
1912static int iceland_populate_smc_svi2_config(struct pp_hwmgr *hwmgr,
1913					    SMU71_Discrete_DpmTable *tab)
1914{
1915	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1916
1917	if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control)
1918		tab->SVI2Enable |= VDDC_ON_SVI2;
1919
1920	if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
1921		tab->SVI2Enable |= VDDCI_ON_SVI2;
1922	else
1923		tab->MergedVddci = 1;
1924
1925	if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control)
1926		tab->SVI2Enable |= MVDD_ON_SVI2;
1927
1928	PP_ASSERT_WITH_CODE(tab->SVI2Enable != (VDDC_ON_SVI2 | VDDCI_ON_SVI2 | MVDD_ON_SVI2) &&
1929		(tab->SVI2Enable & VDDC_ON_SVI2), "SVI2 domain configuration is incorrect!", return -EINVAL);
1930
1931	return 0;
1932}
1933
1934static int iceland_init_smc_table(struct pp_hwmgr *hwmgr)
1935{
1936	int result;
1937	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1938	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
1939	SMU71_Discrete_DpmTable  *table = &(smu_data->smc_state_table);
1940
1941
1942	iceland_initialize_power_tune_defaults(hwmgr);
1943	memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table));
1944
1945	if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) {
1946		iceland_populate_smc_voltage_tables(hwmgr, table);
1947	}
1948
1949	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1950			PHM_PlatformCaps_AutomaticDCTransition))
1951		table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
1952
1953
1954	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1955			PHM_PlatformCaps_StepVddc))
1956		table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
1957
1958	if (data->is_memory_gddr5)
1959		table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
1960
1961
1962	if (data->ulv_supported) {
1963		result = iceland_populate_ulv_state(hwmgr, &(smu_data->ulv_setting));
1964		PP_ASSERT_WITH_CODE(0 == result,
1965			"Failed to initialize ULV state!", return result;);
1966
1967		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1968			ixCG_ULV_PARAMETER, 0x40035);
1969	}
1970
1971	result = iceland_populate_smc_link_level(hwmgr, table);
1972	PP_ASSERT_WITH_CODE(0 == result,
1973		"Failed to initialize Link Level!", return result;);
1974
1975	result = iceland_populate_all_graphic_levels(hwmgr);
1976	PP_ASSERT_WITH_CODE(0 == result,
1977		"Failed to initialize Graphics Level!", return result;);
1978
1979	result = iceland_populate_all_memory_levels(hwmgr);
1980	PP_ASSERT_WITH_CODE(0 == result,
1981		"Failed to initialize Memory Level!", return result;);
1982
1983	result = iceland_populate_smc_acpi_level(hwmgr, table);
1984	PP_ASSERT_WITH_CODE(0 == result,
1985		"Failed to initialize ACPI Level!", return result;);
1986
1987	result = iceland_populate_smc_vce_level(hwmgr, table);
1988	PP_ASSERT_WITH_CODE(0 == result,
1989		"Failed to initialize VCE Level!", return result;);
1990
1991	result = iceland_populate_smc_acp_level(hwmgr, table);
1992	PP_ASSERT_WITH_CODE(0 == result,
1993		"Failed to initialize ACP Level!", return result;);
1994
1995	/* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */
1996	/* need to populate the  ARB settings for the initial state. */
1997	result = iceland_program_memory_timing_parameters(hwmgr);
1998	PP_ASSERT_WITH_CODE(0 == result,
1999		"Failed to Write ARB settings for the initial state.", return result;);
2000
2001	result = iceland_populate_smc_uvd_level(hwmgr, table);
2002	PP_ASSERT_WITH_CODE(0 == result,
2003		"Failed to initialize UVD Level!", return result;);
2004
2005	table->GraphicsBootLevel = 0;
2006	table->MemoryBootLevel = 0;
2007
2008	result = iceland_populate_smc_boot_level(hwmgr, table);
2009	PP_ASSERT_WITH_CODE(0 == result,
2010		"Failed to initialize Boot Level!", return result;);
2011
2012	result = iceland_populate_smc_initial_state(hwmgr);
2013	PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result);
2014
2015	result = iceland_populate_bapm_parameters_in_dpm_table(hwmgr);
2016	PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result);
2017
2018	table->GraphicsVoltageChangeEnable  = 1;
2019	table->GraphicsThermThrottleEnable  = 1;
2020	table->GraphicsInterval = 1;
2021	table->VoltageInterval  = 1;
2022	table->ThermalInterval  = 1;
2023
2024	table->TemperatureLimitHigh =
2025		(data->thermal_temp_setting.temperature_high *
2026		 SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2027	table->TemperatureLimitLow =
2028		(data->thermal_temp_setting.temperature_low *
2029		SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2030
2031	table->MemoryVoltageChangeEnable  = 1;
2032	table->MemoryInterval  = 1;
2033	table->VoltageResponseTime  = 0;
2034	table->PhaseResponseTime  = 0;
2035	table->MemoryThermThrottleEnable  = 1;
2036	table->PCIeBootLinkLevel = 0;
2037	table->PCIeGenInterval = 1;
2038
2039	result = iceland_populate_smc_svi2_config(hwmgr, table);
2040	PP_ASSERT_WITH_CODE(0 == result,
2041		"Failed to populate SVI2 setting!", return result);
2042
2043	table->ThermGpio  = 17;
2044	table->SclkStepSize = 0x4000;
2045
2046	CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
2047	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid);
2048	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase);
2049	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid);
2050	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid);
2051	CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
2052	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
2053	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
2054	CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
2055	CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
2056
2057	table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE);
2058	table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE);
2059	table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE);
2060
2061	/* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2062	result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.dpm_table_start +
2063										offsetof(SMU71_Discrete_DpmTable, SystemFlags),
2064										(uint8_t *)&(table->SystemFlags),
2065										sizeof(SMU71_Discrete_DpmTable)-3 * sizeof(SMU71_PIDController),
2066										SMC_RAM_END);
2067
2068	PP_ASSERT_WITH_CODE(0 == result,
2069		"Failed to upload dpm data to SMC memory!", return result;);
2070
2071	/* Upload all ulv setting to SMC memory.(dpm level, dpm level count etc) */
2072	result = smu7_copy_bytes_to_smc(hwmgr,
2073			smu_data->smu7_data.ulv_setting_starts,
2074			(uint8_t *)&(smu_data->ulv_setting),
2075			sizeof(SMU71_Discrete_Ulv),
2076			SMC_RAM_END);
2077
2078
2079	result = iceland_populate_initial_mc_reg_table(hwmgr);
2080	PP_ASSERT_WITH_CODE((0 == result),
2081		"Failed to populate initialize MC Reg table!", return result);
2082
2083	result = iceland_populate_pm_fuses(hwmgr);
2084	PP_ASSERT_WITH_CODE(0 == result,
2085			"Failed to  populate PM fuses to SMC memory!", return result);
2086
2087	return 0;
2088}
2089
2090int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
2091{
2092	struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
2093	SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
2094	uint32_t duty100;
2095	uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
2096	uint16_t fdo_min, slope1, slope2;
2097	uint32_t reference_clock;
2098	int res __unused;
2099	uint64_t tmp64;
2100
2101	if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
2102		return 0;
2103
2104	if (hwmgr->thermal_controller.fanInfo.bNoFan) {
2105		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2106			PHM_PlatformCaps_MicrocodeFanControl);
2107		return 0;
2108	}
2109
2110	if (0 == smu7_data->fan_table_start) {
2111		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
2112		return 0;
2113	}
2114
2115	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100);
2116
2117	if (0 == duty100) {
2118		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
2119		return 0;
2120	}
2121
2122	tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100;
2123	do_div(tmp64, 10000);
2124	fdo_min = (uint16_t)tmp64;
2125
2126	t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
2127	t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
2128
2129	pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
2130	pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
2131
2132	slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
2133	slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
2134
2135	fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100);
2136	fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100);
2137	fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100);
2138
2139	fan_table.Slope1 = cpu_to_be16(slope1);
2140	fan_table.Slope2 = cpu_to_be16(slope2);
2141
2142	fan_table.FdoMin = cpu_to_be16(fdo_min);
2143
2144	fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst);
2145
2146	fan_table.HystUp = cpu_to_be16(1);
2147
2148	fan_table.HystSlope = cpu_to_be16(1);
2149
2150	fan_table.TempRespLim = cpu_to_be16(5);
2151
2152	reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
2153
2154	fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
2155
2156	fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
2157
2158	fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL);
2159
2160	/* fan_table.FanControl_GL_Flag = 1; */
2161
2162	res = smu7_copy_bytes_to_smc(hwmgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END);
2163
2164	return 0;
2165}
2166
2167
2168static int iceland_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
2169{
2170	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2171
2172	if (data->need_update_smu7_dpm_table &
2173		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
2174		return iceland_program_memory_timing_parameters(hwmgr);
2175
2176	return 0;
2177}
2178
2179static int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr)
2180{
2181	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2182	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
2183
2184	int result = 0;
2185	uint32_t low_sclk_interrupt_threshold = 0;
2186
2187	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2188			PHM_PlatformCaps_SclkThrottleLowNotification)
2189		&& (data->low_sclk_interrupt_threshold != 0)) {
2190		low_sclk_interrupt_threshold =
2191				data->low_sclk_interrupt_threshold;
2192
2193		CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
2194
2195		result = smu7_copy_bytes_to_smc(
2196				hwmgr,
2197				smu_data->smu7_data.dpm_table_start +
2198				offsetof(SMU71_Discrete_DpmTable,
2199					LowSclkInterruptThreshold),
2200				(uint8_t *)&low_sclk_interrupt_threshold,
2201				sizeof(uint32_t),
2202				SMC_RAM_END);
2203	}
2204
2205	result = iceland_update_and_upload_mc_reg_table(hwmgr);
2206
2207	PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result);
2208
2209	result = iceland_program_mem_timing_parameters(hwmgr);
2210	PP_ASSERT_WITH_CODE((result == 0),
2211			"Failed to program memory timing parameters!",
2212			);
2213
2214	return result;
2215}
2216
2217static uint32_t iceland_get_offsetof(uint32_t type, uint32_t member)
2218{
2219	switch (type) {
2220	case SMU_SoftRegisters:
2221		switch (member) {
2222		case HandshakeDisables:
2223			return offsetof(SMU71_SoftRegisters, HandshakeDisables);
2224		case VoltageChangeTimeout:
2225			return offsetof(SMU71_SoftRegisters, VoltageChangeTimeout);
2226		case AverageGraphicsActivity:
2227			return offsetof(SMU71_SoftRegisters, AverageGraphicsActivity);
2228		case AverageMemoryActivity:
2229			return offsetof(SMU71_SoftRegisters, AverageMemoryActivity);
2230		case PreVBlankGap:
2231			return offsetof(SMU71_SoftRegisters, PreVBlankGap);
2232		case VBlankTimeout:
2233			return offsetof(SMU71_SoftRegisters, VBlankTimeout);
2234		case UcodeLoadStatus:
2235			return offsetof(SMU71_SoftRegisters, UcodeLoadStatus);
2236		case DRAM_LOG_ADDR_H:
2237			return offsetof(SMU71_SoftRegisters, DRAM_LOG_ADDR_H);
2238		case DRAM_LOG_ADDR_L:
2239			return offsetof(SMU71_SoftRegisters, DRAM_LOG_ADDR_L);
2240		case DRAM_LOG_PHY_ADDR_H:
2241			return offsetof(SMU71_SoftRegisters, DRAM_LOG_PHY_ADDR_H);
2242		case DRAM_LOG_PHY_ADDR_L:
2243			return offsetof(SMU71_SoftRegisters, DRAM_LOG_PHY_ADDR_L);
2244		case DRAM_LOG_BUFF_SIZE:
2245			return offsetof(SMU71_SoftRegisters, DRAM_LOG_BUFF_SIZE);
2246		}
2247		break;
2248	case SMU_Discrete_DpmTable:
2249		switch (member) {
2250		case LowSclkInterruptThreshold:
2251			return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold);
2252		}
2253		break;
2254	}
2255	pr_warn("can't get the offset of type %x member %x\n", type, member);
2256	return 0;
2257}
2258
2259static uint32_t iceland_get_mac_definition(uint32_t value)
2260{
2261	switch (value) {
2262	case SMU_MAX_LEVELS_GRAPHICS:
2263		return SMU71_MAX_LEVELS_GRAPHICS;
2264	case SMU_MAX_LEVELS_MEMORY:
2265		return SMU71_MAX_LEVELS_MEMORY;
2266	case SMU_MAX_LEVELS_LINK:
2267		return SMU71_MAX_LEVELS_LINK;
2268	case SMU_MAX_ENTRIES_SMIO:
2269		return SMU71_MAX_ENTRIES_SMIO;
2270	case SMU_MAX_LEVELS_VDDC:
2271		return SMU71_MAX_LEVELS_VDDC;
2272	case SMU_MAX_LEVELS_VDDCI:
2273		return SMU71_MAX_LEVELS_VDDCI;
2274	case SMU_MAX_LEVELS_MVDD:
2275		return SMU71_MAX_LEVELS_MVDD;
2276	}
2277
2278	pr_warn("can't get the mac of %x\n", value);
2279	return 0;
2280}
2281
2282static int iceland_process_firmware_header(struct pp_hwmgr *hwmgr)
2283{
2284	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2285	struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
2286
2287	uint32_t tmp;
2288	int result;
2289	bool error = false;
2290
2291	result = smu7_read_smc_sram_dword(hwmgr,
2292				SMU71_FIRMWARE_HEADER_LOCATION +
2293				offsetof(SMU71_Firmware_Header, DpmTable),
2294				&tmp, SMC_RAM_END);
2295
2296	if (0 == result) {
2297		smu7_data->dpm_table_start = tmp;
2298	}
2299
2300	error |= (0 != result);
2301
2302	result = smu7_read_smc_sram_dword(hwmgr,
2303				SMU71_FIRMWARE_HEADER_LOCATION +
2304				offsetof(SMU71_Firmware_Header, SoftRegisters),
2305				&tmp, SMC_RAM_END);
2306
2307	if (0 == result) {
2308		data->soft_regs_start = tmp;
2309		smu7_data->soft_regs_start = tmp;
2310	}
2311
2312	error |= (0 != result);
2313
2314
2315	result = smu7_read_smc_sram_dword(hwmgr,
2316				SMU71_FIRMWARE_HEADER_LOCATION +
2317				offsetof(SMU71_Firmware_Header, mcRegisterTable),
2318				&tmp, SMC_RAM_END);
2319
2320	if (0 == result) {
2321		smu7_data->mc_reg_table_start = tmp;
2322	}
2323
2324	result = smu7_read_smc_sram_dword(hwmgr,
2325				SMU71_FIRMWARE_HEADER_LOCATION +
2326				offsetof(SMU71_Firmware_Header, FanTable),
2327				&tmp, SMC_RAM_END);
2328
2329	if (0 == result) {
2330		smu7_data->fan_table_start = tmp;
2331	}
2332
2333	error |= (0 != result);
2334
2335	result = smu7_read_smc_sram_dword(hwmgr,
2336				SMU71_FIRMWARE_HEADER_LOCATION +
2337				offsetof(SMU71_Firmware_Header, mcArbDramTimingTable),
2338				&tmp, SMC_RAM_END);
2339
2340	if (0 == result) {
2341		smu7_data->arb_table_start = tmp;
2342	}
2343
2344	error |= (0 != result);
2345
2346
2347	result = smu7_read_smc_sram_dword(hwmgr,
2348				SMU71_FIRMWARE_HEADER_LOCATION +
2349				offsetof(SMU71_Firmware_Header, Version),
2350				&tmp, SMC_RAM_END);
2351
2352	if (0 == result) {
2353		hwmgr->microcode_version_info.SMC = tmp;
2354	}
2355
2356	error |= (0 != result);
2357
2358	result = smu7_read_smc_sram_dword(hwmgr,
2359				SMU71_FIRMWARE_HEADER_LOCATION +
2360				offsetof(SMU71_Firmware_Header, UlvSettings),
2361				&tmp, SMC_RAM_END);
2362
2363	if (0 == result) {
2364		smu7_data->ulv_setting_starts = tmp;
2365	}
2366
2367	error |= (0 != result);
2368
2369	return error ? 1 : 0;
2370}
2371
2372/*---------------------------MC----------------------------*/
2373
2374static uint8_t iceland_get_memory_modile_index(struct pp_hwmgr *hwmgr)
2375{
2376	return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16));
2377}
2378
2379static bool iceland_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg)
2380{
2381	bool result = true;
2382
2383	switch (in_reg) {
2384	case  mmMC_SEQ_RAS_TIMING:
2385		*out_reg = mmMC_SEQ_RAS_TIMING_LP;
2386		break;
2387
2388	case  mmMC_SEQ_DLL_STBY:
2389		*out_reg = mmMC_SEQ_DLL_STBY_LP;
2390		break;
2391
2392	case  mmMC_SEQ_G5PDX_CMD0:
2393		*out_reg = mmMC_SEQ_G5PDX_CMD0_LP;
2394		break;
2395
2396	case  mmMC_SEQ_G5PDX_CMD1:
2397		*out_reg = mmMC_SEQ_G5PDX_CMD1_LP;
2398		break;
2399
2400	case  mmMC_SEQ_G5PDX_CTRL:
2401		*out_reg = mmMC_SEQ_G5PDX_CTRL_LP;
2402		break;
2403
2404	case mmMC_SEQ_CAS_TIMING:
2405		*out_reg = mmMC_SEQ_CAS_TIMING_LP;
2406		break;
2407
2408	case mmMC_SEQ_MISC_TIMING:
2409		*out_reg = mmMC_SEQ_MISC_TIMING_LP;
2410		break;
2411
2412	case mmMC_SEQ_MISC_TIMING2:
2413		*out_reg = mmMC_SEQ_MISC_TIMING2_LP;
2414		break;
2415
2416	case mmMC_SEQ_PMG_DVS_CMD:
2417		*out_reg = mmMC_SEQ_PMG_DVS_CMD_LP;
2418		break;
2419
2420	case mmMC_SEQ_PMG_DVS_CTL:
2421		*out_reg = mmMC_SEQ_PMG_DVS_CTL_LP;
2422		break;
2423
2424	case mmMC_SEQ_RD_CTL_D0:
2425		*out_reg = mmMC_SEQ_RD_CTL_D0_LP;
2426		break;
2427
2428	case mmMC_SEQ_RD_CTL_D1:
2429		*out_reg = mmMC_SEQ_RD_CTL_D1_LP;
2430		break;
2431
2432	case mmMC_SEQ_WR_CTL_D0:
2433		*out_reg = mmMC_SEQ_WR_CTL_D0_LP;
2434		break;
2435
2436	case mmMC_SEQ_WR_CTL_D1:
2437		*out_reg = mmMC_SEQ_WR_CTL_D1_LP;
2438		break;
2439
2440	case mmMC_PMG_CMD_EMRS:
2441		*out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP;
2442		break;
2443
2444	case mmMC_PMG_CMD_MRS:
2445		*out_reg = mmMC_SEQ_PMG_CMD_MRS_LP;
2446		break;
2447
2448	case mmMC_PMG_CMD_MRS1:
2449		*out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP;
2450		break;
2451
2452	case mmMC_SEQ_PMG_TIMING:
2453		*out_reg = mmMC_SEQ_PMG_TIMING_LP;
2454		break;
2455
2456	case mmMC_PMG_CMD_MRS2:
2457		*out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP;
2458		break;
2459
2460	case mmMC_SEQ_WR_CTL_2:
2461		*out_reg = mmMC_SEQ_WR_CTL_2_LP;
2462		break;
2463
2464	default:
2465		result = false;
2466		break;
2467	}
2468
2469	return result;
2470}
2471
2472static int iceland_set_s0_mc_reg_index(struct iceland_mc_reg_table *table)
2473{
2474	uint32_t i;
2475	uint16_t address;
2476
2477	for (i = 0; i < table->last; i++) {
2478		table->mc_reg_address[i].s0 =
2479			iceland_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address)
2480			? address : table->mc_reg_address[i].s1;
2481	}
2482	return 0;
2483}
2484
2485static int iceland_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table,
2486					struct iceland_mc_reg_table *ni_table)
2487{
2488	uint8_t i, j;
2489
2490	PP_ASSERT_WITH_CODE((table->last <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2491		"Invalid VramInfo table.", return -EINVAL);
2492	PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES),
2493		"Invalid VramInfo table.", return -EINVAL);
2494
2495	for (i = 0; i < table->last; i++) {
2496		ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
2497	}
2498	ni_table->last = table->last;
2499
2500	for (i = 0; i < table->num_entries; i++) {
2501		ni_table->mc_reg_table_entry[i].mclk_max =
2502			table->mc_reg_table_entry[i].mclk_max;
2503		for (j = 0; j < table->last; j++) {
2504			ni_table->mc_reg_table_entry[i].mc_data[j] =
2505				table->mc_reg_table_entry[i].mc_data[j];
2506		}
2507	}
2508
2509	ni_table->num_entries = table->num_entries;
2510
2511	return 0;
2512}
2513
2514static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr,
2515					struct iceland_mc_reg_table *table)
2516{
2517	uint8_t i, j, k;
2518	uint32_t temp_reg;
2519	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2520
2521	for (i = 0, j = table->last; i < table->last; i++) {
2522		PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2523			"Invalid VramInfo table.", return -EINVAL);
2524
2525		switch (table->mc_reg_address[i].s1) {
2526
2527		case mmMC_SEQ_MISC1:
2528			temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS);
2529			table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS;
2530			table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP;
2531			for (k = 0; k < table->num_entries; k++) {
2532				table->mc_reg_table_entry[k].mc_data[j] =
2533					((temp_reg & 0xffff0000)) |
2534					((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
2535			}
2536			j++;
2537
2538			PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2539				"Invalid VramInfo table.", return -EINVAL);
2540			temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS);
2541			table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS;
2542			table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP;
2543			for (k = 0; k < table->num_entries; k++) {
2544				table->mc_reg_table_entry[k].mc_data[j] =
2545					(temp_reg & 0xffff0000) |
2546					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
2547
2548				if (!data->is_memory_gddr5) {
2549					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
2550				}
2551			}
2552			j++;
2553
2554			if (!data->is_memory_gddr5) {
2555				PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2556					"Invalid VramInfo table.", return -EINVAL);
2557				table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
2558				table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
2559				for (k = 0; k < table->num_entries; k++) {
2560					table->mc_reg_table_entry[k].mc_data[j] =
2561						(table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
2562				}
2563				j++;
2564			}
2565
2566			break;
2567
2568		case mmMC_SEQ_RESERVE_M:
2569			temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1);
2570			table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1;
2571			table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP;
2572			for (k = 0; k < table->num_entries; k++) {
2573				table->mc_reg_table_entry[k].mc_data[j] =
2574					(temp_reg & 0xffff0000) |
2575					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
2576			}
2577			j++;
2578			break;
2579
2580		default:
2581			break;
2582		}
2583
2584	}
2585
2586	table->last = j;
2587
2588	return 0;
2589}
2590
2591static int iceland_set_valid_flag(struct iceland_mc_reg_table *table)
2592{
2593	uint8_t i, j;
2594	for (i = 0; i < table->last; i++) {
2595		for (j = 1; j < table->num_entries; j++) {
2596			if (table->mc_reg_table_entry[j-1].mc_data[i] !=
2597				table->mc_reg_table_entry[j].mc_data[i]) {
2598				table->validflag |= (1<<i);
2599				break;
2600			}
2601		}
2602	}
2603
2604	return 0;
2605}
2606
2607static int iceland_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
2608{
2609	int result;
2610	struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
2611	pp_atomctrl_mc_reg_table *table;
2612	struct iceland_mc_reg_table *ni_table = &smu_data->mc_reg_table;
2613	uint8_t module_index = iceland_get_memory_modile_index(hwmgr);
2614
2615	table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL);
2616
2617	if (NULL == table)
2618		return -ENOMEM;
2619
2620	/* Program additional LP registers that are no longer programmed by VBIOS */
2621	cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
2622	cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
2623	cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY));
2624	cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0));
2625	cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1));
2626	cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL));
2627	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD));
2628	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL));
2629	cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING));
2630	cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
2631	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS));
2632	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS));
2633	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1));
2634	cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0));
2635	cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
2636	cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
2637	cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
2638	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
2639	cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2));
2640	cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2));
2641
2642	result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table);
2643
2644	if (0 == result)
2645		result = iceland_copy_vbios_smc_reg_table(table, ni_table);
2646
2647	if (0 == result) {
2648		iceland_set_s0_mc_reg_index(ni_table);
2649		result = iceland_set_mc_special_registers(hwmgr, ni_table);
2650	}
2651
2652	if (0 == result)
2653		iceland_set_valid_flag(ni_table);
2654
2655	kfree(table);
2656
2657	return result;
2658}
2659
2660static bool iceland_is_dpm_running(struct pp_hwmgr *hwmgr)
2661{
2662	return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
2663			CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
2664			? true : false;
2665}
2666
2667const struct pp_smumgr_func iceland_smu_funcs = {
2668	.name = "iceland_smu",
2669	.smu_init = &iceland_smu_init,
2670	.smu_fini = &smu7_smu_fini,
2671	.start_smu = &iceland_start_smu,
2672	.check_fw_load_finish = &smu7_check_fw_load_finish,
2673	.request_smu_load_fw = &smu7_request_smu_load_fw,
2674	.request_smu_load_specific_fw = &iceland_request_smu_load_specific_fw,
2675	.send_msg_to_smc = &smu7_send_msg_to_smc,
2676	.send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter,
2677	.download_pptable_settings = NULL,
2678	.upload_pptable_settings = NULL,
2679	.get_offsetof = iceland_get_offsetof,
2680	.process_firmware_header = iceland_process_firmware_header,
2681	.init_smc_table = iceland_init_smc_table,
2682	.update_sclk_threshold = iceland_update_sclk_threshold,
2683	.thermal_setup_fan_table = iceland_thermal_setup_fan_table,
2684	.populate_all_graphic_levels = iceland_populate_all_graphic_levels,
2685	.populate_all_memory_levels = iceland_populate_all_memory_levels,
2686	.get_mac_definition = iceland_get_mac_definition,
2687	.initialize_mc_reg_table = iceland_initialize_mc_reg_table,
2688	.is_dpm_running = iceland_is_dpm_running,
2689};
2690
2691