1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 #include "pp_debug.h"
24 #include <linux/delay.h>
25 #include <linux/fb.h>
26 #include <linux/module.h>
27 #include <linux/pci.h>
28 #include <linux/slab.h>
29 #include <asm/div64.h>
30 #include <drm/amdgpu_drm.h>
31 #include "ppatomctrl.h"
32 #include "atombios.h"
33 #include "pptable_v1_0.h"
34 #include "pppcielanes.h"
35 #include "amd_pcie_helpers.h"
36 #include "hardwaremanager.h"
37 #include "process_pptables_v1_0.h"
38 #include "cgs_common.h"
39 
40 #include "smu7_common.h"
41 
42 #include "hwmgr.h"
43 #include "smu7_hwmgr.h"
44 #include "smu_ucode_xfer_vi.h"
45 #include "smu7_powertune.h"
46 #include "smu7_dyn_defaults.h"
47 #include "smu7_thermal.h"
48 #include "smu7_clockpowergating.h"
49 #include "processpptables.h"
50 #include "pp_thermal.h"
51 #include "smu7_baco.h"
52 #include "smu7_smumgr.h"
53 #include "polaris10_smumgr.h"
54 
55 #include "ivsrcid/ivsrcid_vislands30.h"
56 
57 #define MC_CG_ARB_FREQ_F0           0x0a
58 #define MC_CG_ARB_FREQ_F1           0x0b
59 #define MC_CG_ARB_FREQ_F2           0x0c
60 #define MC_CG_ARB_FREQ_F3           0x0d
61 
62 #define MC_CG_SEQ_DRAMCONF_S0       0x05
63 #define MC_CG_SEQ_DRAMCONF_S1       0x06
64 #define MC_CG_SEQ_YCLK_SUSPEND      0x04
65 #define MC_CG_SEQ_YCLK_RESUME       0x0a
66 
67 #define SMC_CG_IND_START            0xc0030000
68 #define SMC_CG_IND_END              0xc0040000
69 
70 #define MEM_FREQ_LOW_LATENCY        25000
71 #define MEM_FREQ_HIGH_LATENCY       80000
72 
73 #define MEM_LATENCY_HIGH            45
74 #define MEM_LATENCY_LOW             35
75 #define MEM_LATENCY_ERR             0xFFFF
76 
77 #define MC_SEQ_MISC0_GDDR5_SHIFT 28
78 #define MC_SEQ_MISC0_GDDR5_MASK  0xf0000000
79 #define MC_SEQ_MISC0_GDDR5_VALUE 5
80 
81 #define PCIE_BUS_CLK                10000
82 #define TCLK                        (PCIE_BUS_CLK / 10)
83 
84 static struct profile_mode_setting smu7_profiling[7] =
85 					{{0, 0, 0, 0, 0, 0, 0, 0},
86 					 {1, 0, 100, 30, 1, 0, 100, 10},
87 					 {1, 10, 0, 30, 0, 0, 0, 0},
88 					 {0, 0, 0, 0, 1, 10, 16, 31},
89 					 {1, 0, 11, 50, 1, 0, 100, 10},
90 					 {1, 0, 5, 30, 0, 0, 0, 0},
91 					 {0, 0, 0, 0, 0, 0, 0, 0},
92 					};
93 
94 #define PPSMC_MSG_SetVBITimeout_VEGAM    ((uint16_t) 0x310)
95 
96 #define ixPWR_SVI2_PLANE1_LOAD                     0xC0200280
97 #define PWR_SVI2_PLANE1_LOAD__PSI1_MASK                    0x00000020L
98 #define PWR_SVI2_PLANE1_LOAD__PSI0_EN_MASK                 0x00000040L
99 #define PWR_SVI2_PLANE1_LOAD__PSI1__SHIFT                  0x00000005
100 #define PWR_SVI2_PLANE1_LOAD__PSI0_EN__SHIFT               0x00000006
101 
102 #define STRAP_EVV_REVISION_MSB		2211
103 #define STRAP_EVV_REVISION_LSB		2208
104 
105 /** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
106 enum DPM_EVENT_SRC {
107 	DPM_EVENT_SRC_ANALOG = 0,
108 	DPM_EVENT_SRC_EXTERNAL = 1,
109 	DPM_EVENT_SRC_DIGITAL = 2,
110 	DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
111 	DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4
112 };
113 
114 #define ixDIDT_SQ_EDC_CTRL                         0x0013
115 #define ixDIDT_SQ_EDC_THRESHOLD                    0x0014
116 #define ixDIDT_SQ_EDC_STALL_PATTERN_1_2            0x0015
117 #define ixDIDT_SQ_EDC_STALL_PATTERN_3_4            0x0016
118 #define ixDIDT_SQ_EDC_STALL_PATTERN_5_6            0x0017
119 #define ixDIDT_SQ_EDC_STALL_PATTERN_7              0x0018
120 
121 #define ixDIDT_TD_EDC_CTRL                         0x0053
122 #define ixDIDT_TD_EDC_THRESHOLD                    0x0054
123 #define ixDIDT_TD_EDC_STALL_PATTERN_1_2            0x0055
124 #define ixDIDT_TD_EDC_STALL_PATTERN_3_4            0x0056
125 #define ixDIDT_TD_EDC_STALL_PATTERN_5_6            0x0057
126 #define ixDIDT_TD_EDC_STALL_PATTERN_7              0x0058
127 
128 #define ixDIDT_TCP_EDC_CTRL                        0x0073
129 #define ixDIDT_TCP_EDC_THRESHOLD                   0x0074
130 #define ixDIDT_TCP_EDC_STALL_PATTERN_1_2           0x0075
131 #define ixDIDT_TCP_EDC_STALL_PATTERN_3_4           0x0076
132 #define ixDIDT_TCP_EDC_STALL_PATTERN_5_6           0x0077
133 #define ixDIDT_TCP_EDC_STALL_PATTERN_7             0x0078
134 
135 #define ixDIDT_DB_EDC_CTRL                         0x0033
136 #define ixDIDT_DB_EDC_THRESHOLD                    0x0034
137 #define ixDIDT_DB_EDC_STALL_PATTERN_1_2            0x0035
138 #define ixDIDT_DB_EDC_STALL_PATTERN_3_4            0x0036
139 #define ixDIDT_DB_EDC_STALL_PATTERN_5_6            0x0037
140 #define ixDIDT_DB_EDC_STALL_PATTERN_7              0x0038
141 
142 uint32_t DIDTEDCConfig_P12[] = {
143     ixDIDT_SQ_EDC_STALL_PATTERN_1_2,
144     ixDIDT_SQ_EDC_STALL_PATTERN_3_4,
145     ixDIDT_SQ_EDC_STALL_PATTERN_5_6,
146     ixDIDT_SQ_EDC_STALL_PATTERN_7,
147     ixDIDT_SQ_EDC_THRESHOLD,
148     ixDIDT_SQ_EDC_CTRL,
149     ixDIDT_TD_EDC_STALL_PATTERN_1_2,
150     ixDIDT_TD_EDC_STALL_PATTERN_3_4,
151     ixDIDT_TD_EDC_STALL_PATTERN_5_6,
152     ixDIDT_TD_EDC_STALL_PATTERN_7,
153     ixDIDT_TD_EDC_THRESHOLD,
154     ixDIDT_TD_EDC_CTRL,
155     ixDIDT_TCP_EDC_STALL_PATTERN_1_2,
156     ixDIDT_TCP_EDC_STALL_PATTERN_3_4,
157     ixDIDT_TCP_EDC_STALL_PATTERN_5_6,
158     ixDIDT_TCP_EDC_STALL_PATTERN_7,
159     ixDIDT_TCP_EDC_THRESHOLD,
160     ixDIDT_TCP_EDC_CTRL,
161     ixDIDT_DB_EDC_STALL_PATTERN_1_2,
162     ixDIDT_DB_EDC_STALL_PATTERN_3_4,
163     ixDIDT_DB_EDC_STALL_PATTERN_5_6,
164     ixDIDT_DB_EDC_STALL_PATTERN_7,
165     ixDIDT_DB_EDC_THRESHOLD,
166     ixDIDT_DB_EDC_CTRL,
167     0xFFFFFFFF // End of list
168 };
169 
170 static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic);
171 static int smu7_force_clock_level(struct pp_hwmgr *hwmgr,
172 		enum pp_clock_type type, uint32_t mask);
173 static int smu7_notify_has_display(struct pp_hwmgr *hwmgr);
174 
175 static struct smu7_power_state *cast_phw_smu7_power_state(
176 				  struct pp_hw_power_state *hw_ps)
177 {
178 	PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),
179 				"Invalid Powerstate Type!",
180 				 return NULL);
181 
182 	return (struct smu7_power_state *)hw_ps;
183 }
184 
185 static const struct smu7_power_state *cast_const_phw_smu7_power_state(
186 				 const struct pp_hw_power_state *hw_ps)
187 {
188 	PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),
189 				"Invalid Powerstate Type!",
190 				 return NULL);
191 
192 	return (const struct smu7_power_state *)hw_ps;
193 }
194 
195 /**
196  * smu7_get_mc_microcode_version - Find the MC microcode version and store it in the HwMgr struct
197  *
198  * @hwmgr:  the address of the powerplay hardware manager.
199  * Return:   always 0
200  */
201 static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr)
202 {
203 	cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
204 
205 	hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA);
206 
207 	return 0;
208 }
209 
210 static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
211 {
212 	uint32_t speedCntl = 0;
213 
214 	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
215 	speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE,
216 			ixPCIE_LC_SPEED_CNTL);
217 	return((uint16_t)PHM_GET_FIELD(speedCntl,
218 			PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
219 }
220 
221 static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
222 {
223 	uint32_t link_width;
224 
225 	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
226 	link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
227 			PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD);
228 
229 	PP_ASSERT_WITH_CODE((7 >= link_width),
230 			"Invalid PCIe lane width!", return 0);
231 
232 	return decode_pcie_lane_width(link_width);
233 }
234 
235 /**
236  * smu7_enable_smc_voltage_controller - Enable voltage control
237  *
238  * @hwmgr:  the address of the powerplay hardware manager.
239  * Return:   always PP_Result_OK
240  */
241 static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
242 {
243 	if (hwmgr->chip_id >= CHIP_POLARIS10 &&
244 	    hwmgr->chip_id <= CHIP_VEGAM) {
245 		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
246 				CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI1, 0);
247 		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
248 				CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI0_EN, 0);
249 	}
250 
251 	if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK)
252 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Enable, NULL);
253 
254 	return 0;
255 }
256 
257 /**
258  * smu7_voltage_control - Checks if we want to support voltage control
259  *
260  * @hwmgr:  the address of the powerplay hardware manager.
261  */
262 static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr)
263 {
264 	const struct smu7_hwmgr *data =
265 			(const struct smu7_hwmgr *)(hwmgr->backend);
266 
267 	return (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control);
268 }
269 
270 /**
271  * smu7_enable_voltage_control - Enable voltage control
272  *
273  * @hwmgr:  the address of the powerplay hardware manager.
274  * Return:   always 0
275  */
276 static int smu7_enable_voltage_control(struct pp_hwmgr *hwmgr)
277 {
278 	/* enable voltage control */
279 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
280 			GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1);
281 
282 	return 0;
283 }
284 
285 static int phm_get_svi2_voltage_table_v0(pp_atomctrl_voltage_table *voltage_table,
286 		struct phm_clock_voltage_dependency_table *voltage_dependency_table
287 		)
288 {
289 	uint32_t i;
290 
291 	PP_ASSERT_WITH_CODE((NULL != voltage_table),
292 			"Voltage Dependency Table empty.", return -EINVAL;);
293 
294 	voltage_table->mask_low = 0;
295 	voltage_table->phase_delay = 0;
296 	voltage_table->count = voltage_dependency_table->count;
297 
298 	for (i = 0; i < voltage_dependency_table->count; i++) {
299 		voltage_table->entries[i].value =
300 			voltage_dependency_table->entries[i].v;
301 		voltage_table->entries[i].smio_low = 0;
302 	}
303 
304 	return 0;
305 }
306 
307 
308 /**
309  * smu7_construct_voltage_tables - Create Voltage Tables.
310  *
311  * @hwmgr:  the address of the powerplay hardware manager.
312  * Return:   always 0
313  */
314 static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr)
315 {
316 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
317 	struct phm_ppt_v1_information *table_info =
318 			(struct phm_ppt_v1_information *)hwmgr->pptable;
319 	int result = 0;
320 	uint32_t tmp;
321 
322 	if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
323 		result = atomctrl_get_voltage_table_v3(hwmgr,
324 				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT,
325 				&(data->mvdd_voltage_table));
326 		PP_ASSERT_WITH_CODE((0 == result),
327 				"Failed to retrieve MVDD table.",
328 				return result);
329 	} else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
330 		if (hwmgr->pp_table_version == PP_TABLE_V1)
331 			result = phm_get_svi2_mvdd_voltage_table(&(data->mvdd_voltage_table),
332 					table_info->vdd_dep_on_mclk);
333 		else if (hwmgr->pp_table_version == PP_TABLE_V0)
334 			result = phm_get_svi2_voltage_table_v0(&(data->mvdd_voltage_table),
335 					hwmgr->dyn_state.mvdd_dependency_on_mclk);
336 
337 		PP_ASSERT_WITH_CODE((0 == result),
338 				"Failed to retrieve SVI2 MVDD table from dependency table.",
339 				return result;);
340 	}
341 
342 	if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
343 		result = atomctrl_get_voltage_table_v3(hwmgr,
344 				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT,
345 				&(data->vddci_voltage_table));
346 		PP_ASSERT_WITH_CODE((0 == result),
347 				"Failed to retrieve VDDCI table.",
348 				return result);
349 	} else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
350 		if (hwmgr->pp_table_version == PP_TABLE_V1)
351 			result = phm_get_svi2_vddci_voltage_table(&(data->vddci_voltage_table),
352 					table_info->vdd_dep_on_mclk);
353 		else if (hwmgr->pp_table_version == PP_TABLE_V0)
354 			result = phm_get_svi2_voltage_table_v0(&(data->vddci_voltage_table),
355 					hwmgr->dyn_state.vddci_dependency_on_mclk);
356 		PP_ASSERT_WITH_CODE((0 == result),
357 				"Failed to retrieve SVI2 VDDCI table from dependency table.",
358 				return result);
359 	}
360 
361 	if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
362 		/* VDDGFX has only SVI2 voltage control */
363 		result = phm_get_svi2_vdd_voltage_table(&(data->vddgfx_voltage_table),
364 					table_info->vddgfx_lookup_table);
365 		PP_ASSERT_WITH_CODE((0 == result),
366 			"Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;);
367 	}
368 
369 
370 	if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) {
371 		result = atomctrl_get_voltage_table_v3(hwmgr,
372 					VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT,
373 					&data->vddc_voltage_table);
374 		PP_ASSERT_WITH_CODE((0 == result),
375 			"Failed to retrieve VDDC table.", return result;);
376 	} else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
377 
378 		if (hwmgr->pp_table_version == PP_TABLE_V0)
379 			result = phm_get_svi2_voltage_table_v0(&data->vddc_voltage_table,
380 					hwmgr->dyn_state.vddc_dependency_on_mclk);
381 		else if (hwmgr->pp_table_version == PP_TABLE_V1)
382 			result = phm_get_svi2_vdd_voltage_table(&(data->vddc_voltage_table),
383 				table_info->vddc_lookup_table);
384 
385 		PP_ASSERT_WITH_CODE((0 == result),
386 			"Failed to retrieve SVI2 VDDC table from dependency table.", return result;);
387 	}
388 
389 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC);
390 	PP_ASSERT_WITH_CODE(
391 			(data->vddc_voltage_table.count <= tmp),
392 		"Too many voltage values for VDDC. Trimming to fit state table.",
393 			phm_trim_voltage_table_to_fit_state_table(tmp,
394 						&(data->vddc_voltage_table)));
395 
396 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX);
397 	PP_ASSERT_WITH_CODE(
398 			(data->vddgfx_voltage_table.count <= tmp),
399 		"Too many voltage values for VDDC. Trimming to fit state table.",
400 			phm_trim_voltage_table_to_fit_state_table(tmp,
401 						&(data->vddgfx_voltage_table)));
402 
403 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDCI);
404 	PP_ASSERT_WITH_CODE(
405 			(data->vddci_voltage_table.count <= tmp),
406 		"Too many voltage values for VDDCI. Trimming to fit state table.",
407 			phm_trim_voltage_table_to_fit_state_table(tmp,
408 					&(data->vddci_voltage_table)));
409 
410 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MVDD);
411 	PP_ASSERT_WITH_CODE(
412 			(data->mvdd_voltage_table.count <= tmp),
413 		"Too many voltage values for MVDD. Trimming to fit state table.",
414 			phm_trim_voltage_table_to_fit_state_table(tmp,
415 						&(data->mvdd_voltage_table)));
416 
417 	return 0;
418 }
419 
420 /**
421  * smu7_program_static_screen_threshold_parameters - Programs static screed detection parameters
422  *
423  * @hwmgr:  the address of the powerplay hardware manager.
424  * Return:   always 0
425  */
426 static int smu7_program_static_screen_threshold_parameters(
427 							struct pp_hwmgr *hwmgr)
428 {
429 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
430 
431 	/* Set static screen threshold unit */
432 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
433 			CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT,
434 			data->static_screen_threshold_unit);
435 	/* Set static screen threshold */
436 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
437 			CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD,
438 			data->static_screen_threshold);
439 
440 	return 0;
441 }
442 
443 /**
444  * smu7_enable_display_gap - Setup display gap for glitch free memory clock switching.
445  *
446  * @hwmgr:  the address of the powerplay hardware manager.
447  * Return:   always  0
448  */
449 static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr)
450 {
451 	uint32_t display_gap =
452 			cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
453 					ixCG_DISPLAY_GAP_CNTL);
454 
455 	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,
456 			DISP_GAP, DISPLAY_GAP_IGNORE);
457 
458 	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,
459 			DISP_GAP_MCHG, DISPLAY_GAP_VBLANK);
460 
461 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
462 			ixCG_DISPLAY_GAP_CNTL, display_gap);
463 
464 	return 0;
465 }
466 
467 /**
468  * smu7_program_voting_clients - Programs activity state transition voting clients
469  *
470  * @hwmgr:  the address of the powerplay hardware manager.
471  * Return:   always  0
472  */
473 static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr)
474 {
475 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
476 	int i;
477 
478 	/* Clear reset for voting clients before enabling DPM */
479 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
480 			SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0);
481 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
482 			SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0);
483 
484 	for (i = 0; i < 8; i++)
485 		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
486 					ixCG_FREQ_TRAN_VOTING_0 + i * 4,
487 					data->voting_rights_clients[i]);
488 	return 0;
489 }
490 
491 static int smu7_clear_voting_clients(struct pp_hwmgr *hwmgr)
492 {
493 	int i;
494 
495 	/* Reset voting clients before disabling DPM */
496 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
497 			SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1);
498 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
499 			SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1);
500 
501 	for (i = 0; i < 8; i++)
502 		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
503 				ixCG_FREQ_TRAN_VOTING_0 + i * 4, 0);
504 
505 	return 0;
506 }
507 
508 /* Copy one arb setting to another and then switch the active set.
509  * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants.
510  */
511 static int smu7_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr,
512 		uint32_t arb_src, uint32_t arb_dest)
513 {
514 	uint32_t mc_arb_dram_timing;
515 	uint32_t mc_arb_dram_timing2;
516 	uint32_t burst_time;
517 	uint32_t mc_cg_config;
518 
519 	switch (arb_src) {
520 	case MC_CG_ARB_FREQ_F0:
521 		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
522 		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
523 		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
524 		break;
525 	case MC_CG_ARB_FREQ_F1:
526 		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1);
527 		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1);
528 		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1);
529 		break;
530 	default:
531 		return -EINVAL;
532 	}
533 
534 	switch (arb_dest) {
535 	case MC_CG_ARB_FREQ_F0:
536 		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing);
537 		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
538 		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time);
539 		break;
540 	case MC_CG_ARB_FREQ_F1:
541 		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
542 		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
543 		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time);
544 		break;
545 	default:
546 		return -EINVAL;
547 	}
548 
549 	mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG);
550 	mc_cg_config |= 0x0000000F;
551 	cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config);
552 	PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest);
553 
554 	return 0;
555 }
556 
557 static int smu7_reset_to_default(struct pp_hwmgr *hwmgr)
558 {
559 	return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ResetToDefaults, NULL);
560 }
561 
562 /**
563  * smu7_initial_switch_from_arbf0_to_f1 - Initial switch from ARB F0->F1
564  *
565  * @hwmgr:  the address of the powerplay hardware manager.
566  * Return:   always 0
567  * This function is to be called from the SetPowerState table.
568  */
569 static int smu7_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr)
570 {
571 	return smu7_copy_and_switch_arb_sets(hwmgr,
572 			MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
573 }
574 
575 static int smu7_force_switch_to_arbf0(struct pp_hwmgr *hwmgr)
576 {
577 	uint32_t tmp;
578 
579 	tmp = (cgs_read_ind_register(hwmgr->device,
580 			CGS_IND_REG__SMC, ixSMC_SCRATCH9) &
581 			0x0000ff00) >> 8;
582 
583 	if (tmp == MC_CG_ARB_FREQ_F0)
584 		return 0;
585 
586 	return smu7_copy_and_switch_arb_sets(hwmgr,
587 			tmp, MC_CG_ARB_FREQ_F0);
588 }
589 
590 static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
591 {
592 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
593 
594 	struct phm_ppt_v1_information *table_info =
595 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
596 	struct phm_ppt_v1_pcie_table *pcie_table = NULL;
597 
598 	uint32_t i, max_entry;
599 	uint32_t tmp;
600 
601 	PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels ||
602 			data->use_pcie_power_saving_levels), "No pcie performance levels!",
603 			return -EINVAL);
604 
605 	if (table_info != NULL)
606 		pcie_table = table_info->pcie_table;
607 
608 	if (data->use_pcie_performance_levels &&
609 			!data->use_pcie_power_saving_levels) {
610 		data->pcie_gen_power_saving = data->pcie_gen_performance;
611 		data->pcie_lane_power_saving = data->pcie_lane_performance;
612 	} else if (!data->use_pcie_performance_levels &&
613 			data->use_pcie_power_saving_levels) {
614 		data->pcie_gen_performance = data->pcie_gen_power_saving;
615 		data->pcie_lane_performance = data->pcie_lane_power_saving;
616 	}
617 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_LINK);
618 	phm_reset_single_dpm_table(&data->dpm_table.pcie_speed_table,
619 					tmp,
620 					MAX_REGULAR_DPM_NUMBER);
621 
622 	if (pcie_table != NULL) {
623 		/* max_entry is used to make sure we reserve one PCIE level
624 		 * for boot level (fix for A+A PSPP issue).
625 		 * If PCIE table from PPTable have ULV entry + 8 entries,
626 		 * then ignore the last entry.*/
627 		max_entry = (tmp < pcie_table->count) ? tmp : pcie_table->count;
628 		for (i = 1; i < max_entry; i++) {
629 			phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1,
630 					get_pcie_gen_support(data->pcie_gen_cap,
631 							pcie_table->entries[i].gen_speed),
632 					get_pcie_lane_support(data->pcie_lane_cap,
633 							pcie_table->entries[i].lane_width));
634 		}
635 		data->dpm_table.pcie_speed_table.count = max_entry - 1;
636 		smum_update_smc_table(hwmgr, SMU_BIF_TABLE);
637 	} else {
638 		/* Hardcode Pcie Table */
639 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0,
640 				get_pcie_gen_support(data->pcie_gen_cap,
641 						PP_Min_PCIEGen),
642 				get_pcie_lane_support(data->pcie_lane_cap,
643 						PP_Max_PCIELane));
644 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1,
645 				get_pcie_gen_support(data->pcie_gen_cap,
646 						PP_Min_PCIEGen),
647 				get_pcie_lane_support(data->pcie_lane_cap,
648 						PP_Max_PCIELane));
649 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2,
650 				get_pcie_gen_support(data->pcie_gen_cap,
651 						PP_Max_PCIEGen),
652 				get_pcie_lane_support(data->pcie_lane_cap,
653 						PP_Max_PCIELane));
654 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3,
655 				get_pcie_gen_support(data->pcie_gen_cap,
656 						PP_Max_PCIEGen),
657 				get_pcie_lane_support(data->pcie_lane_cap,
658 						PP_Max_PCIELane));
659 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4,
660 				get_pcie_gen_support(data->pcie_gen_cap,
661 						PP_Max_PCIEGen),
662 				get_pcie_lane_support(data->pcie_lane_cap,
663 						PP_Max_PCIELane));
664 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5,
665 				get_pcie_gen_support(data->pcie_gen_cap,
666 						PP_Max_PCIEGen),
667 				get_pcie_lane_support(data->pcie_lane_cap,
668 						PP_Max_PCIELane));
669 
670 		data->dpm_table.pcie_speed_table.count = 6;
671 	}
672 	/* Populate last level for boot PCIE level, but do not increment count. */
673 	if (hwmgr->chip_family == AMDGPU_FAMILY_CI) {
674 		for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++)
675 			phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i,
676 				get_pcie_gen_support(data->pcie_gen_cap,
677 						PP_Max_PCIEGen),
678 				data->vbios_boot_state.pcie_lane_bootup_value);
679 	} else {
680 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
681 			data->dpm_table.pcie_speed_table.count,
682 			get_pcie_gen_support(data->pcie_gen_cap,
683 					PP_Min_PCIEGen),
684 			get_pcie_lane_support(data->pcie_lane_cap,
685 					PP_Max_PCIELane));
686 	}
687 	return 0;
688 }
689 
690 static int smu7_reset_dpm_tables(struct pp_hwmgr *hwmgr)
691 {
692 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
693 
694 	memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table));
695 
696 	phm_reset_single_dpm_table(
697 			&data->dpm_table.sclk_table,
698 				smum_get_mac_definition(hwmgr,
699 					SMU_MAX_LEVELS_GRAPHICS),
700 					MAX_REGULAR_DPM_NUMBER);
701 	phm_reset_single_dpm_table(
702 			&data->dpm_table.mclk_table,
703 			smum_get_mac_definition(hwmgr,
704 				SMU_MAX_LEVELS_MEMORY), MAX_REGULAR_DPM_NUMBER);
705 
706 	phm_reset_single_dpm_table(
707 			&data->dpm_table.vddc_table,
708 				smum_get_mac_definition(hwmgr,
709 					SMU_MAX_LEVELS_VDDC),
710 					MAX_REGULAR_DPM_NUMBER);
711 	phm_reset_single_dpm_table(
712 			&data->dpm_table.vddci_table,
713 			smum_get_mac_definition(hwmgr,
714 				SMU_MAX_LEVELS_VDDCI), MAX_REGULAR_DPM_NUMBER);
715 
716 	phm_reset_single_dpm_table(
717 			&data->dpm_table.mvdd_table,
718 				smum_get_mac_definition(hwmgr,
719 					SMU_MAX_LEVELS_MVDD),
720 					MAX_REGULAR_DPM_NUMBER);
721 	return 0;
722 }
723 /*
724  * This function is to initialize all DPM state tables
725  * for SMU7 based on the dependency table.
726  * Dynamic state patching function will then trim these
727  * state tables to the allowed range based
728  * on the power policy or external client requests,
729  * such as UVD request, etc.
730  */
731 
732 static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr)
733 {
734 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
735 	struct phm_clock_voltage_dependency_table *allowed_vdd_sclk_table =
736 		hwmgr->dyn_state.vddc_dependency_on_sclk;
737 	struct phm_clock_voltage_dependency_table *allowed_vdd_mclk_table =
738 		hwmgr->dyn_state.vddc_dependency_on_mclk;
739 	struct phm_cac_leakage_table *std_voltage_table =
740 		hwmgr->dyn_state.cac_leakage_table;
741 	uint32_t i;
742 
743 	PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,
744 		"SCLK dependency table is missing. This table is mandatory", return -EINVAL);
745 	PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1,
746 		"SCLK dependency table has to have is missing. This table is mandatory", return -EINVAL);
747 
748 	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,
749 		"MCLK dependency table is missing. This table is mandatory", return -EINVAL);
750 	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1,
751 		"VMCLK dependency table has to have is missing. This table is mandatory", return -EINVAL);
752 
753 
754 	/* Initialize Sclk DPM table based on allow Sclk values*/
755 	data->dpm_table.sclk_table.count = 0;
756 
757 	for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
758 		if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value !=
759 				allowed_vdd_sclk_table->entries[i].clk) {
760 			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
761 				allowed_vdd_sclk_table->entries[i].clk;
762 			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0;
763 			data->dpm_table.sclk_table.count++;
764 		}
765 	}
766 
767 	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,
768 		"MCLK dependency table is missing. This table is mandatory", return -EINVAL);
769 	/* Initialize Mclk DPM table based on allow Mclk values */
770 	data->dpm_table.mclk_table.count = 0;
771 	for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
772 		if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value !=
773 			allowed_vdd_mclk_table->entries[i].clk) {
774 			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
775 				allowed_vdd_mclk_table->entries[i].clk;
776 			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = (i == 0) ? 1 : 0;
777 			data->dpm_table.mclk_table.count++;
778 		}
779 	}
780 
781 	/* Initialize Vddc DPM table based on allow Vddc values.  And populate corresponding std values. */
782 	for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
783 		data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
784 		data->dpm_table.vddc_table.dpm_levels[i].param1 = std_voltage_table->entries[i].Leakage;
785 		/* param1 is for corresponding std voltage */
786 		data->dpm_table.vddc_table.dpm_levels[i].enabled = true;
787 	}
788 
789 	data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count;
790 	allowed_vdd_mclk_table = hwmgr->dyn_state.vddci_dependency_on_mclk;
791 
792 	if (NULL != allowed_vdd_mclk_table) {
793 		/* Initialize Vddci DPM table based on allow Mclk values */
794 		for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
795 			data->dpm_table.vddci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
796 			data->dpm_table.vddci_table.dpm_levels[i].enabled = true;
797 		}
798 		data->dpm_table.vddci_table.count = allowed_vdd_mclk_table->count;
799 	}
800 
801 	allowed_vdd_mclk_table = hwmgr->dyn_state.mvdd_dependency_on_mclk;
802 
803 	if (NULL != allowed_vdd_mclk_table) {
804 		/*
805 		 * Initialize MVDD DPM table based on allow Mclk
806 		 * values
807 		 */
808 		for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
809 			data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
810 			data->dpm_table.mvdd_table.dpm_levels[i].enabled = true;
811 		}
812 		data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count;
813 	}
814 
815 	return 0;
816 }
817 
818 static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr)
819 {
820 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
821 	struct phm_ppt_v1_information *table_info =
822 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
823 	uint32_t i;
824 
825 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
826 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
827 
828 	if (table_info == NULL)
829 		return -EINVAL;
830 
831 	dep_sclk_table = table_info->vdd_dep_on_sclk;
832 	dep_mclk_table = table_info->vdd_dep_on_mclk;
833 
834 	PP_ASSERT_WITH_CODE(dep_sclk_table != NULL,
835 			"SCLK dependency table is missing.",
836 			return -EINVAL);
837 	PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1,
838 			"SCLK dependency table count is 0.",
839 			return -EINVAL);
840 
841 	PP_ASSERT_WITH_CODE(dep_mclk_table != NULL,
842 			"MCLK dependency table is missing.",
843 			return -EINVAL);
844 	PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,
845 			"MCLK dependency table count is 0",
846 			return -EINVAL);
847 
848 	/* Initialize Sclk DPM table based on allow Sclk values */
849 	data->dpm_table.sclk_table.count = 0;
850 	for (i = 0; i < dep_sclk_table->count; i++) {
851 		if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count - 1].value !=
852 						dep_sclk_table->entries[i].clk) {
853 
854 			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
855 					dep_sclk_table->entries[i].clk;
856 
857 			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled =
858 					(i == 0) ? true : false;
859 			data->dpm_table.sclk_table.count++;
860 		}
861 	}
862 	if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0)
863 		hwmgr->platform_descriptor.overdriveLimit.engineClock = dep_sclk_table->entries[i-1].clk;
864 	/* Initialize Mclk DPM table based on allow Mclk values */
865 	data->dpm_table.mclk_table.count = 0;
866 	for (i = 0; i < dep_mclk_table->count; i++) {
867 		if (i == 0 || data->dpm_table.mclk_table.dpm_levels
868 				[data->dpm_table.mclk_table.count - 1].value !=
869 						dep_mclk_table->entries[i].clk) {
870 			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
871 							dep_mclk_table->entries[i].clk;
872 			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled =
873 							(i == 0) ? true : false;
874 			data->dpm_table.mclk_table.count++;
875 		}
876 	}
877 
878 	if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0)
879 		hwmgr->platform_descriptor.overdriveLimit.memoryClock = dep_mclk_table->entries[i-1].clk;
880 	return 0;
881 }
882 
883 static int smu7_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
884 {
885 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
886 	struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
887 	struct phm_ppt_v1_information *table_info =
888 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
889 	uint32_t i;
890 
891 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
892 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
893 	struct phm_odn_performance_level *entries;
894 
895 	if (table_info == NULL)
896 		return -EINVAL;
897 
898 	dep_sclk_table = table_info->vdd_dep_on_sclk;
899 	dep_mclk_table = table_info->vdd_dep_on_mclk;
900 
901 	odn_table->odn_core_clock_dpm_levels.num_of_pl =
902 						data->golden_dpm_table.sclk_table.count;
903 	entries = odn_table->odn_core_clock_dpm_levels.entries;
904 	for (i=0; i<data->golden_dpm_table.sclk_table.count; i++) {
905 		entries[i].clock = data->golden_dpm_table.sclk_table.dpm_levels[i].value;
906 		entries[i].enabled = true;
907 		entries[i].vddc = dep_sclk_table->entries[i].vddc;
908 	}
909 
910 	smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table,
911 		(struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk));
912 
913 	odn_table->odn_memory_clock_dpm_levels.num_of_pl =
914 						data->golden_dpm_table.mclk_table.count;
915 	entries = odn_table->odn_memory_clock_dpm_levels.entries;
916 	for (i=0; i<data->golden_dpm_table.mclk_table.count; i++) {
917 		entries[i].clock = data->golden_dpm_table.mclk_table.dpm_levels[i].value;
918 		entries[i].enabled = true;
919 		entries[i].vddc = dep_mclk_table->entries[i].vddc;
920 	}
921 
922 	smu_get_voltage_dependency_table_ppt_v1(dep_mclk_table,
923 		(struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk));
924 
925 	return 0;
926 }
927 
928 static void smu7_setup_voltage_range_from_vbios(struct pp_hwmgr *hwmgr)
929 {
930 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
931 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
932 	struct phm_ppt_v1_information *table_info =
933 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
934 	uint32_t min_vddc = 0;
935 	uint32_t max_vddc = 0;
936 
937 	if (!table_info)
938 		return;
939 
940 	dep_sclk_table = table_info->vdd_dep_on_sclk;
941 
942 	atomctrl_get_voltage_range(hwmgr, &max_vddc, &min_vddc);
943 
944 	if (min_vddc == 0 || min_vddc > 2000
945 		|| min_vddc > dep_sclk_table->entries[0].vddc)
946 		min_vddc = dep_sclk_table->entries[0].vddc;
947 
948 	if (max_vddc == 0 || max_vddc > 2000
949 		|| max_vddc < dep_sclk_table->entries[dep_sclk_table->count-1].vddc)
950 		max_vddc = dep_sclk_table->entries[dep_sclk_table->count-1].vddc;
951 
952 	data->odn_dpm_table.min_vddc = min_vddc;
953 	data->odn_dpm_table.max_vddc = max_vddc;
954 }
955 
956 static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
957 {
958 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
959 	struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
960 	struct phm_ppt_v1_information *table_info =
961 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
962 	uint32_t i;
963 
964 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
965 	struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table;
966 
967 	if (table_info == NULL)
968 		return;
969 
970 	for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
971 		if (odn_table->odn_core_clock_dpm_levels.entries[i].clock !=
972 					data->dpm_table.sclk_table.dpm_levels[i].value) {
973 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
974 			break;
975 		}
976 	}
977 
978 	for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
979 		if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock !=
980 					data->dpm_table.mclk_table.dpm_levels[i].value) {
981 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
982 			break;
983 		}
984 	}
985 
986 	dep_table = table_info->vdd_dep_on_mclk;
987 	odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk);
988 
989 	for (i = 0; i < dep_table->count; i++) {
990 		if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
991 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK;
992 			return;
993 		}
994 	}
995 
996 	dep_table = table_info->vdd_dep_on_sclk;
997 	odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk);
998 	for (i = 0; i < dep_table->count; i++) {
999 		if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
1000 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK;
1001 			return;
1002 		}
1003 	}
1004 	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
1005 		data->need_update_smu7_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC;
1006 		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK;
1007 	}
1008 }
1009 
1010 static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
1011 {
1012 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1013 
1014 	smu7_reset_dpm_tables(hwmgr);
1015 
1016 	if (hwmgr->pp_table_version == PP_TABLE_V1)
1017 		smu7_setup_dpm_tables_v1(hwmgr);
1018 	else if (hwmgr->pp_table_version == PP_TABLE_V0)
1019 		smu7_setup_dpm_tables_v0(hwmgr);
1020 
1021 	smu7_setup_default_pcie_table(hwmgr);
1022 
1023 	/* save a copy of the default DPM table */
1024 	memcpy(&(data->golden_dpm_table), &(data->dpm_table),
1025 			sizeof(struct smu7_dpm_table));
1026 
1027 	/* initialize ODN table */
1028 	if (hwmgr->od_enabled) {
1029 		if (data->odn_dpm_table.max_vddc) {
1030 			smu7_check_dpm_table_updated(hwmgr);
1031 		} else {
1032 			smu7_setup_voltage_range_from_vbios(hwmgr);
1033 			smu7_odn_initial_default_setting(hwmgr);
1034 		}
1035 	}
1036 	return 0;
1037 }
1038 
1039 static int smu7_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr)
1040 {
1041 
1042 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1043 			PHM_PlatformCaps_RegulatorHot))
1044 		return smum_send_msg_to_smc(hwmgr,
1045 				PPSMC_MSG_EnableVRHotGPIOInterrupt,
1046 				NULL);
1047 
1048 	return 0;
1049 }
1050 
1051 static int smu7_enable_sclk_control(struct pp_hwmgr *hwmgr)
1052 {
1053 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
1054 			SCLK_PWRMGT_OFF, 0);
1055 	return 0;
1056 }
1057 
1058 static int smu7_enable_ulv(struct pp_hwmgr *hwmgr)
1059 {
1060 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1061 
1062 	if (data->ulv_supported)
1063 		return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableULV, NULL);
1064 
1065 	return 0;
1066 }
1067 
1068 static int smu7_disable_ulv(struct pp_hwmgr *hwmgr)
1069 {
1070 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1071 
1072 	if (data->ulv_supported)
1073 		return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableULV, NULL);
1074 
1075 	return 0;
1076 }
1077 
1078 static int smu7_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
1079 {
1080 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1081 			PHM_PlatformCaps_SclkDeepSleep)) {
1082 		if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_ON, NULL))
1083 			PP_ASSERT_WITH_CODE(false,
1084 					"Attempt to enable Master Deep Sleep switch failed!",
1085 					return -EINVAL);
1086 	} else {
1087 		if (smum_send_msg_to_smc(hwmgr,
1088 				PPSMC_MSG_MASTER_DeepSleep_OFF,
1089 				NULL)) {
1090 			PP_ASSERT_WITH_CODE(false,
1091 					"Attempt to disable Master Deep Sleep switch failed!",
1092 					return -EINVAL);
1093 		}
1094 	}
1095 
1096 	return 0;
1097 }
1098 
1099 static int smu7_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
1100 {
1101 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1102 			PHM_PlatformCaps_SclkDeepSleep)) {
1103 		if (smum_send_msg_to_smc(hwmgr,
1104 				PPSMC_MSG_MASTER_DeepSleep_OFF,
1105 				NULL)) {
1106 			PP_ASSERT_WITH_CODE(false,
1107 					"Attempt to disable Master Deep Sleep switch failed!",
1108 					return -EINVAL);
1109 		}
1110 	}
1111 
1112 	return 0;
1113 }
1114 
1115 static int smu7_disable_sclk_vce_handshake(struct pp_hwmgr *hwmgr)
1116 {
1117 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1118 	uint32_t soft_register_value = 0;
1119 	uint32_t handshake_disables_offset = data->soft_regs_start
1120 				+ smum_get_offsetof(hwmgr,
1121 					SMU_SoftRegisters, HandshakeDisables);
1122 
1123 	soft_register_value = cgs_read_ind_register(hwmgr->device,
1124 				CGS_IND_REG__SMC, handshake_disables_offset);
1125 	soft_register_value |= SMU7_VCE_SCLK_HANDSHAKE_DISABLE;
1126 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1127 			handshake_disables_offset, soft_register_value);
1128 	return 0;
1129 }
1130 
1131 static int smu7_disable_handshake_uvd(struct pp_hwmgr *hwmgr)
1132 {
1133 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1134 	uint32_t soft_register_value = 0;
1135 	uint32_t handshake_disables_offset = data->soft_regs_start
1136 				+ smum_get_offsetof(hwmgr,
1137 					SMU_SoftRegisters, HandshakeDisables);
1138 
1139 	soft_register_value = cgs_read_ind_register(hwmgr->device,
1140 				CGS_IND_REG__SMC, handshake_disables_offset);
1141 	soft_register_value |= smum_get_mac_definition(hwmgr,
1142 					SMU_UVD_MCLK_HANDSHAKE_DISABLE);
1143 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1144 			handshake_disables_offset, soft_register_value);
1145 	return 0;
1146 }
1147 
1148 static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
1149 {
1150 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1151 
1152 	/* enable SCLK dpm */
1153 	if (!data->sclk_dpm_key_disabled) {
1154 		if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1155 		    hwmgr->chip_id <= CHIP_VEGAM)
1156 			smu7_disable_sclk_vce_handshake(hwmgr);
1157 
1158 		PP_ASSERT_WITH_CODE(
1159 		(0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Enable, NULL)),
1160 		"Failed to enable SCLK DPM during DPM Start Function!",
1161 		return -EINVAL);
1162 	}
1163 
1164 	/* enable MCLK dpm */
1165 	if (0 == data->mclk_dpm_key_disabled) {
1166 		if (!(hwmgr->feature_mask & PP_UVD_HANDSHAKE_MASK))
1167 			smu7_disable_handshake_uvd(hwmgr);
1168 
1169 		PP_ASSERT_WITH_CODE(
1170 				(0 == smum_send_msg_to_smc(hwmgr,
1171 						PPSMC_MSG_MCLKDPM_Enable,
1172 						NULL)),
1173 				"Failed to enable MCLK DPM during DPM Start Function!",
1174 				return -EINVAL);
1175 
1176 		if ((hwmgr->chip_family == AMDGPU_FAMILY_CI) ||
1177 		    (hwmgr->chip_id == CHIP_POLARIS10) ||
1178 		    (hwmgr->chip_id == CHIP_POLARIS11) ||
1179 		    (hwmgr->chip_id == CHIP_POLARIS12) ||
1180 		    (hwmgr->chip_id == CHIP_TONGA))
1181 			PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1);
1182 
1183 
1184 		if (hwmgr->chip_family == AMDGPU_FAMILY_CI) {
1185 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x5);
1186 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x5);
1187 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x100005);
1188 			udelay(10);
1189 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x400005);
1190 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x400005);
1191 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x500005);
1192 		} else {
1193 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5);
1194 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5);
1195 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005);
1196 			udelay(10);
1197 			if (hwmgr->chip_id == CHIP_VEGAM) {
1198 				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400009);
1199 				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400009);
1200 			} else {
1201 				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005);
1202 				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005);
1203 			}
1204 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005);
1205 		}
1206 	}
1207 
1208 	return 0;
1209 }
1210 
1211 static int smu7_start_dpm(struct pp_hwmgr *hwmgr)
1212 {
1213 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1214 
1215 	/*enable general power management */
1216 
1217 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
1218 			GLOBAL_PWRMGT_EN, 1);
1219 
1220 	/* enable sclk deep sleep */
1221 
1222 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
1223 			DYNAMIC_PM_EN, 1);
1224 
1225 	/* prepare for PCIE DPM */
1226 
1227 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1228 			data->soft_regs_start +
1229 			smum_get_offsetof(hwmgr, SMU_SoftRegisters,
1230 						VoltageChangeTimeout), 0x1000);
1231 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
1232 			SWRST_COMMAND_1, RESETLC, 0x0);
1233 
1234 	if (hwmgr->chip_family == AMDGPU_FAMILY_CI)
1235 		cgs_write_register(hwmgr->device, 0x1488,
1236 			(cgs_read_register(hwmgr->device, 0x1488) & ~0x1));
1237 
1238 	if (smu7_enable_sclk_mclk_dpm(hwmgr)) {
1239 		pr_err("Failed to enable Sclk DPM and Mclk DPM!");
1240 		return -EINVAL;
1241 	}
1242 
1243 	/* enable PCIE dpm */
1244 	if (0 == data->pcie_dpm_key_disabled) {
1245 		PP_ASSERT_WITH_CODE(
1246 				(0 == smum_send_msg_to_smc(hwmgr,
1247 						PPSMC_MSG_PCIeDPM_Enable,
1248 						NULL)),
1249 				"Failed to enable pcie DPM during DPM Start Function!",
1250 				return -EINVAL);
1251 	}
1252 
1253 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1254 				PHM_PlatformCaps_Falcon_QuickTransition)) {
1255 		PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr,
1256 				PPSMC_MSG_EnableACDCGPIOInterrupt,
1257 				NULL)),
1258 				"Failed to enable AC DC GPIO Interrupt!",
1259 				);
1260 	}
1261 
1262 	return 0;
1263 }
1264 
1265 static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
1266 {
1267 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1268 
1269 	/* disable SCLK dpm */
1270 	if (!data->sclk_dpm_key_disabled) {
1271 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
1272 				"Trying to disable SCLK DPM when DPM is disabled",
1273 				return 0);
1274 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Disable, NULL);
1275 	}
1276 
1277 	/* disable MCLK dpm */
1278 	if (!data->mclk_dpm_key_disabled) {
1279 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
1280 				"Trying to disable MCLK DPM when DPM is disabled",
1281 				return 0);
1282 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_Disable, NULL);
1283 	}
1284 
1285 	return 0;
1286 }
1287 
1288 static int smu7_stop_dpm(struct pp_hwmgr *hwmgr)
1289 {
1290 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1291 
1292 	/* disable general power management */
1293 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
1294 			GLOBAL_PWRMGT_EN, 0);
1295 	/* disable sclk deep sleep */
1296 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
1297 			DYNAMIC_PM_EN, 0);
1298 
1299 	/* disable PCIE dpm */
1300 	if (!data->pcie_dpm_key_disabled) {
1301 		PP_ASSERT_WITH_CODE(
1302 				(smum_send_msg_to_smc(hwmgr,
1303 						PPSMC_MSG_PCIeDPM_Disable,
1304 						NULL) == 0),
1305 				"Failed to disable pcie DPM during DPM Stop Function!",
1306 				return -EINVAL);
1307 	}
1308 
1309 	smu7_disable_sclk_mclk_dpm(hwmgr);
1310 
1311 	PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
1312 			"Trying to disable voltage DPM when DPM is disabled",
1313 			return 0);
1314 
1315 	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Disable, NULL);
1316 
1317 	return 0;
1318 }
1319 
1320 static void smu7_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources)
1321 {
1322 	bool protection;
1323 	enum DPM_EVENT_SRC src;
1324 
1325 	switch (sources) {
1326 	default:
1327 		pr_err("Unknown throttling event sources.");
1328 		fallthrough;
1329 	case 0:
1330 		protection = false;
1331 		/* src is unused */
1332 		break;
1333 	case (1 << PHM_AutoThrottleSource_Thermal):
1334 		protection = true;
1335 		src = DPM_EVENT_SRC_DIGITAL;
1336 		break;
1337 	case (1 << PHM_AutoThrottleSource_External):
1338 		protection = true;
1339 		src = DPM_EVENT_SRC_EXTERNAL;
1340 		break;
1341 	case (1 << PHM_AutoThrottleSource_External) |
1342 			(1 << PHM_AutoThrottleSource_Thermal):
1343 		protection = true;
1344 		src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL;
1345 		break;
1346 	}
1347 	/* Order matters - don't enable thermal protection for the wrong source. */
1348 	if (protection) {
1349 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL,
1350 				DPM_EVENT_SRC, src);
1351 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
1352 				THERMAL_PROTECTION_DIS,
1353 				!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1354 						PHM_PlatformCaps_ThermalController));
1355 	} else
1356 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
1357 				THERMAL_PROTECTION_DIS, 1);
1358 }
1359 
1360 static int smu7_enable_auto_throttle_source(struct pp_hwmgr *hwmgr,
1361 		PHM_AutoThrottleSource source)
1362 {
1363 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1364 
1365 	if (!(data->active_auto_throttle_sources & (1 << source))) {
1366 		data->active_auto_throttle_sources |= 1 << source;
1367 		smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
1368 	}
1369 	return 0;
1370 }
1371 
1372 static int smu7_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
1373 {
1374 	return smu7_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
1375 }
1376 
1377 static int smu7_disable_auto_throttle_source(struct pp_hwmgr *hwmgr,
1378 		PHM_AutoThrottleSource source)
1379 {
1380 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1381 
1382 	if (data->active_auto_throttle_sources & (1 << source)) {
1383 		data->active_auto_throttle_sources &= ~(1 << source);
1384 		smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
1385 	}
1386 	return 0;
1387 }
1388 
1389 static int smu7_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
1390 {
1391 	return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
1392 }
1393 
1394 static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
1395 {
1396 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1397 	data->pcie_performance_request = true;
1398 
1399 	return 0;
1400 }
1401 
1402 static int smu7_program_edc_didt_registers(struct pp_hwmgr *hwmgr,
1403 					   uint32_t *cac_config_regs,
1404 					   AtomCtrl_EDCLeakgeTable *edc_leakage_table)
1405 {
1406 	uint32_t data, i = 0;
1407 
1408 	while (cac_config_regs[i] != 0xFFFFFFFF) {
1409 		data = edc_leakage_table->DIDT_REG[i];
1410 		cgs_write_ind_register(hwmgr->device,
1411 				       CGS_IND_REG__DIDT,
1412 				       cac_config_regs[i],
1413 				       data);
1414 		i++;
1415 	}
1416 
1417 	return 0;
1418 }
1419 
1420 static int smu7_populate_edc_leakage_registers(struct pp_hwmgr *hwmgr)
1421 {
1422 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1423 	int ret = 0;
1424 
1425 	if (!data->disable_edc_leakage_controller &&
1426 	    data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset &&
1427 	    data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) {
1428 		ret = smu7_program_edc_didt_registers(hwmgr,
1429 						      DIDTEDCConfig_P12,
1430 						      &data->edc_leakage_table);
1431 		if (ret)
1432 			return ret;
1433 
1434 		ret = smum_send_msg_to_smc(hwmgr,
1435 					   (PPSMC_Msg)PPSMC_MSG_EnableEDCController,
1436 					   NULL);
1437 	} else {
1438 		ret = smum_send_msg_to_smc(hwmgr,
1439 					   (PPSMC_Msg)PPSMC_MSG_DisableEDCController,
1440 					   NULL);
1441 	}
1442 
1443 	return ret;
1444 }
1445 
1446 static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
1447 {
1448 	int tmp_result = 0;
1449 	int result = 0;
1450 
1451 	if (smu7_voltage_control(hwmgr)) {
1452 		tmp_result = smu7_enable_voltage_control(hwmgr);
1453 		PP_ASSERT_WITH_CODE(tmp_result == 0,
1454 				"Failed to enable voltage control!",
1455 				result = tmp_result);
1456 
1457 		tmp_result = smu7_construct_voltage_tables(hwmgr);
1458 		PP_ASSERT_WITH_CODE((0 == tmp_result),
1459 				"Failed to construct voltage tables!",
1460 				result = tmp_result);
1461 	}
1462 	smum_initialize_mc_reg_table(hwmgr);
1463 
1464 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1465 			PHM_PlatformCaps_EngineSpreadSpectrumSupport))
1466 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1467 				GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1);
1468 
1469 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1470 			PHM_PlatformCaps_ThermalController))
1471 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1472 				GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0);
1473 
1474 	tmp_result = smu7_program_static_screen_threshold_parameters(hwmgr);
1475 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1476 			"Failed to program static screen threshold parameters!",
1477 			result = tmp_result);
1478 
1479 	tmp_result = smu7_enable_display_gap(hwmgr);
1480 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1481 			"Failed to enable display gap!", result = tmp_result);
1482 
1483 	tmp_result = smu7_program_voting_clients(hwmgr);
1484 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1485 			"Failed to program voting clients!", result = tmp_result);
1486 
1487 	tmp_result = smum_process_firmware_header(hwmgr);
1488 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1489 			"Failed to process firmware header!", result = tmp_result);
1490 
1491 	if (hwmgr->chip_id != CHIP_VEGAM) {
1492 		tmp_result = smu7_initial_switch_from_arbf0_to_f1(hwmgr);
1493 		PP_ASSERT_WITH_CODE((0 == tmp_result),
1494 				"Failed to initialize switch from ArbF0 to F1!",
1495 				result = tmp_result);
1496 	}
1497 
1498 	result = smu7_setup_default_dpm_tables(hwmgr);
1499 	PP_ASSERT_WITH_CODE(0 == result,
1500 			"Failed to setup default DPM tables!", return result);
1501 
1502 	tmp_result = smum_init_smc_table(hwmgr);
1503 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1504 			"Failed to initialize SMC table!", result = tmp_result);
1505 
1506 	tmp_result = smu7_enable_vrhot_gpio_interrupt(hwmgr);
1507 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1508 			"Failed to enable VR hot GPIO interrupt!", result = tmp_result);
1509 
1510 	if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1511 	    hwmgr->chip_id <= CHIP_VEGAM) {
1512 		tmp_result = smu7_notify_has_display(hwmgr);
1513 		PP_ASSERT_WITH_CODE((0 == tmp_result),
1514 				"Failed to enable display setting!", result = tmp_result);
1515 	} else {
1516 		smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL);
1517 	}
1518 
1519 	if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1520 	    hwmgr->chip_id <= CHIP_VEGAM) {
1521 		tmp_result = smu7_populate_edc_leakage_registers(hwmgr);
1522 		PP_ASSERT_WITH_CODE((0 == tmp_result),
1523 				"Failed to populate edc leakage registers!", result = tmp_result);
1524 	}
1525 
1526 	tmp_result = smu7_enable_sclk_control(hwmgr);
1527 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1528 			"Failed to enable SCLK control!", result = tmp_result);
1529 
1530 	tmp_result = smu7_enable_smc_voltage_controller(hwmgr);
1531 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1532 			"Failed to enable voltage control!", result = tmp_result);
1533 
1534 	tmp_result = smu7_enable_ulv(hwmgr);
1535 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1536 			"Failed to enable ULV!", result = tmp_result);
1537 
1538 	tmp_result = smu7_enable_deep_sleep_master_switch(hwmgr);
1539 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1540 			"Failed to enable deep sleep master switch!", result = tmp_result);
1541 
1542 	tmp_result = smu7_enable_didt_config(hwmgr);
1543 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1544 			"Failed to enable deep sleep master switch!", result = tmp_result);
1545 
1546 	tmp_result = smu7_start_dpm(hwmgr);
1547 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1548 			"Failed to start DPM!", result = tmp_result);
1549 
1550 	tmp_result = smu7_enable_smc_cac(hwmgr);
1551 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1552 			"Failed to enable SMC CAC!", result = tmp_result);
1553 
1554 	tmp_result = smu7_enable_power_containment(hwmgr);
1555 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1556 			"Failed to enable power containment!", result = tmp_result);
1557 
1558 	tmp_result = smu7_power_control_set_level(hwmgr);
1559 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1560 			"Failed to power control set level!", result = tmp_result);
1561 
1562 	tmp_result = smu7_enable_thermal_auto_throttle(hwmgr);
1563 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1564 			"Failed to enable thermal auto throttle!", result = tmp_result);
1565 
1566 	tmp_result = smu7_pcie_performance_request(hwmgr);
1567 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1568 			"pcie performance request failed!", result = tmp_result);
1569 
1570 	return 0;
1571 }
1572 
1573 static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable)
1574 {
1575 	if (!hwmgr->avfs_supported)
1576 		return 0;
1577 
1578 	if (enable) {
1579 		if (!PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
1580 				CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) {
1581 			PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(
1582 					hwmgr, PPSMC_MSG_EnableAvfs, NULL),
1583 					"Failed to enable AVFS!",
1584 					return -EINVAL);
1585 		}
1586 	} else if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
1587 			CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) {
1588 		PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(
1589 				hwmgr, PPSMC_MSG_DisableAvfs, NULL),
1590 				"Failed to disable AVFS!",
1591 				return -EINVAL);
1592 	}
1593 
1594 	return 0;
1595 }
1596 
1597 static int smu7_update_avfs(struct pp_hwmgr *hwmgr)
1598 {
1599 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1600 
1601 	if (!hwmgr->avfs_supported)
1602 		return 0;
1603 
1604 	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
1605 		smu7_avfs_control(hwmgr, false);
1606 	} else if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
1607 		smu7_avfs_control(hwmgr, false);
1608 		smu7_avfs_control(hwmgr, true);
1609 	} else {
1610 		smu7_avfs_control(hwmgr, true);
1611 	}
1612 
1613 	return 0;
1614 }
1615 
1616 static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
1617 {
1618 	int tmp_result, result = 0;
1619 
1620 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1621 			PHM_PlatformCaps_ThermalController))
1622 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1623 				GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 1);
1624 
1625 	tmp_result = smu7_disable_power_containment(hwmgr);
1626 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1627 			"Failed to disable power containment!", result = tmp_result);
1628 
1629 	tmp_result = smu7_disable_smc_cac(hwmgr);
1630 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1631 			"Failed to disable SMC CAC!", result = tmp_result);
1632 
1633 	tmp_result = smu7_disable_didt_config(hwmgr);
1634 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1635 			"Failed to disable DIDT!", result = tmp_result);
1636 
1637 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1638 			CG_SPLL_SPREAD_SPECTRUM, SSEN, 0);
1639 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1640 			GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 0);
1641 
1642 	tmp_result = smu7_disable_thermal_auto_throttle(hwmgr);
1643 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1644 			"Failed to disable thermal auto throttle!", result = tmp_result);
1645 
1646 	tmp_result = smu7_avfs_control(hwmgr, false);
1647 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1648 			"Failed to disable AVFS!", result = tmp_result);
1649 
1650 	tmp_result = smu7_stop_dpm(hwmgr);
1651 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1652 			"Failed to stop DPM!", result = tmp_result);
1653 
1654 	tmp_result = smu7_disable_deep_sleep_master_switch(hwmgr);
1655 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1656 			"Failed to disable deep sleep master switch!", result = tmp_result);
1657 
1658 	tmp_result = smu7_disable_ulv(hwmgr);
1659 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1660 			"Failed to disable ULV!", result = tmp_result);
1661 
1662 	tmp_result = smu7_clear_voting_clients(hwmgr);
1663 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1664 			"Failed to clear voting clients!", result = tmp_result);
1665 
1666 	tmp_result = smu7_reset_to_default(hwmgr);
1667 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1668 			"Failed to reset to default!", result = tmp_result);
1669 
1670 	tmp_result = smum_stop_smc(hwmgr);
1671 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1672 			"Failed to stop smc!", result = tmp_result);
1673 
1674 	tmp_result = smu7_force_switch_to_arbf0(hwmgr);
1675 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1676 			"Failed to force to switch arbf0!", result = tmp_result);
1677 
1678 	return result;
1679 }
1680 
1681 static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
1682 {
1683 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1684 	struct phm_ppt_v1_information *table_info =
1685 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1686 	struct amdgpu_device *adev = hwmgr->adev;
1687 	uint8_t tmp1, tmp2;
1688 	uint16_t tmp3 = 0;
1689 
1690 	data->dll_default_on = false;
1691 	data->mclk_dpm0_activity_target = 0xa;
1692 	data->vddc_vddgfx_delta = 300;
1693 	data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT;
1694 	data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT;
1695 	data->voting_rights_clients[0] = SMU7_VOTINGRIGHTSCLIENTS_DFLT0;
1696 	data->voting_rights_clients[1]= SMU7_VOTINGRIGHTSCLIENTS_DFLT1;
1697 	data->voting_rights_clients[2] = SMU7_VOTINGRIGHTSCLIENTS_DFLT2;
1698 	data->voting_rights_clients[3]= SMU7_VOTINGRIGHTSCLIENTS_DFLT3;
1699 	data->voting_rights_clients[4]= SMU7_VOTINGRIGHTSCLIENTS_DFLT4;
1700 	data->voting_rights_clients[5]= SMU7_VOTINGRIGHTSCLIENTS_DFLT5;
1701 	data->voting_rights_clients[6]= SMU7_VOTINGRIGHTSCLIENTS_DFLT6;
1702 	data->voting_rights_clients[7]= SMU7_VOTINGRIGHTSCLIENTS_DFLT7;
1703 
1704 	data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
1705 	data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
1706 	data->pcie_dpm_key_disabled = hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true;
1707 	/* need to set voltage control types before EVV patching */
1708 	data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE;
1709 	data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE;
1710 	data->mvdd_control = SMU7_VOLTAGE_CONTROL_NONE;
1711 	data->enable_tdc_limit_feature = true;
1712 	data->enable_pkg_pwr_tracking_feature = true;
1713 	data->force_pcie_gen = PP_PCIEGenInvalid;
1714 	data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false;
1715 	data->current_profile_setting.bupdate_sclk = 1;
1716 	data->current_profile_setting.sclk_up_hyst = 0;
1717 	data->current_profile_setting.sclk_down_hyst = 100;
1718 	data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT;
1719 	data->current_profile_setting.bupdate_mclk = 1;
1720 	if (hwmgr->chip_id >= CHIP_POLARIS10) {
1721 		if (adev->gmc.vram_width == 256) {
1722 			data->current_profile_setting.mclk_up_hyst = 10;
1723 			data->current_profile_setting.mclk_down_hyst = 60;
1724 			data->current_profile_setting.mclk_activity = 25;
1725 		} else if (adev->gmc.vram_width == 128) {
1726 			data->current_profile_setting.mclk_up_hyst = 5;
1727 			data->current_profile_setting.mclk_down_hyst = 16;
1728 			data->current_profile_setting.mclk_activity = 20;
1729 		} else if (adev->gmc.vram_width == 64) {
1730 			data->current_profile_setting.mclk_up_hyst = 3;
1731 			data->current_profile_setting.mclk_down_hyst = 16;
1732 			data->current_profile_setting.mclk_activity = 20;
1733 		}
1734 	} else {
1735 		data->current_profile_setting.mclk_up_hyst = 0;
1736 		data->current_profile_setting.mclk_down_hyst = 100;
1737 		data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT;
1738 	}
1739 	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
1740 	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1741 	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1742 
1743 	if (hwmgr->chip_id  == CHIP_HAWAII) {
1744 		data->thermal_temp_setting.temperature_low = 94500;
1745 		data->thermal_temp_setting.temperature_high = 95000;
1746 		data->thermal_temp_setting.temperature_shutdown = 104000;
1747 	} else {
1748 		data->thermal_temp_setting.temperature_low = 99500;
1749 		data->thermal_temp_setting.temperature_high = 100000;
1750 		data->thermal_temp_setting.temperature_shutdown = 104000;
1751 	}
1752 
1753 	data->fast_watermark_threshold = 100;
1754 	if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1755 			VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
1756 		data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_SVID2;
1757 	else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1758 			VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT))
1759 		data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_GPIO;
1760 
1761 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1762 			PHM_PlatformCaps_ControlVDDGFX)) {
1763 		if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1764 			VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) {
1765 			data->vdd_gfx_control = SMU7_VOLTAGE_CONTROL_BY_SVID2;
1766 		}
1767 	}
1768 
1769 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1770 			PHM_PlatformCaps_EnableMVDDControl)) {
1771 		if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1772 				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT))
1773 			data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_GPIO;
1774 		else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1775 				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2))
1776 			data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_SVID2;
1777 	}
1778 
1779 	if (SMU7_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control)
1780 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1781 			PHM_PlatformCaps_ControlVDDGFX);
1782 
1783 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1784 			PHM_PlatformCaps_ControlVDDCI)) {
1785 		if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1786 				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
1787 			data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_GPIO;
1788 		else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1789 				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2))
1790 			data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_SVID2;
1791 	}
1792 
1793 	if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE)
1794 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1795 				PHM_PlatformCaps_EnableMVDDControl);
1796 
1797 	if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE)
1798 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1799 				PHM_PlatformCaps_ControlVDDCI);
1800 
1801 	data->vddc_phase_shed_control = 1;
1802 	if ((hwmgr->chip_id == CHIP_POLARIS12) ||
1803 	    ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) ||
1804 	    ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) ||
1805 	    ASICID_IS_P30(adev->pdev->device, adev->pdev->revision) ||
1806 	    ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
1807 		if (data->voltage_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
1808 			atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2,
1809 							&tmp3);
1810 			tmp3 = (tmp3 >> 5) & 0x3;
1811 			data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3;
1812 		}
1813 	} else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) {
1814 		data->vddc_phase_shed_control = 1;
1815 	}
1816 
1817 	if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK)
1818 		&& (table_info->cac_dtp_table->usClockStretchAmount != 0))
1819 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1820 					PHM_PlatformCaps_ClockStretcher);
1821 
1822 	data->pcie_gen_performance.max = PP_PCIEGen1;
1823 	data->pcie_gen_performance.min = PP_PCIEGen3;
1824 	data->pcie_gen_power_saving.max = PP_PCIEGen1;
1825 	data->pcie_gen_power_saving.min = PP_PCIEGen3;
1826 	data->pcie_lane_performance.max = 0;
1827 	data->pcie_lane_performance.min = 16;
1828 	data->pcie_lane_power_saving.max = 0;
1829 	data->pcie_lane_power_saving.min = 16;
1830 
1831 
1832 	if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
1833 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1834 			      PHM_PlatformCaps_UVDPowerGating);
1835 	if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
1836 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1837 			      PHM_PlatformCaps_VCEPowerGating);
1838 
1839 	data->disable_edc_leakage_controller = true;
1840 	if (((adev->asic_type == CHIP_POLARIS10) && hwmgr->is_kicker) ||
1841 	    ((adev->asic_type == CHIP_POLARIS11) && hwmgr->is_kicker) ||
1842 	    (adev->asic_type == CHIP_POLARIS12) ||
1843 	    (adev->asic_type == CHIP_VEGAM))
1844 		data->disable_edc_leakage_controller = false;
1845 
1846 	if (!atomctrl_is_asic_internal_ss_supported(hwmgr)) {
1847 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1848 			PHM_PlatformCaps_MemorySpreadSpectrumSupport);
1849 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1850 			PHM_PlatformCaps_EngineSpreadSpectrumSupport);
1851 	}
1852 
1853 	if ((adev->pdev->device == 0x699F) &&
1854 	    (adev->pdev->revision == 0xCF)) {
1855 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1856 				PHM_PlatformCaps_PowerContainment);
1857 		data->enable_tdc_limit_feature = false;
1858 		data->enable_pkg_pwr_tracking_feature = false;
1859 		data->disable_edc_leakage_controller = true;
1860 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1861 					PHM_PlatformCaps_ClockStretcher);
1862 	}
1863 }
1864 
1865 static int smu7_calculate_ro_range(struct pp_hwmgr *hwmgr)
1866 {
1867 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1868 	struct amdgpu_device *adev = hwmgr->adev;
1869 	uint32_t asicrev1, evv_revision, max = 0, min = 0;
1870 
1871 	atomctrl_read_efuse(hwmgr, STRAP_EVV_REVISION_LSB, STRAP_EVV_REVISION_MSB,
1872 			&evv_revision);
1873 
1874 	atomctrl_read_efuse(hwmgr, 568, 579, &asicrev1);
1875 
1876 	if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) ||
1877 	    ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
1878 		min = 1200;
1879 		max = 2500;
1880 	} else if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) ||
1881 		   ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
1882 		min = 900;
1883 		max= 2100;
1884 	} else if (hwmgr->chip_id == CHIP_POLARIS10) {
1885 		if (adev->pdev->subsystem_vendor == 0x106B) {
1886 			min = 1000;
1887 			max = 2300;
1888 		} else {
1889 			if (evv_revision == 0) {
1890 				min = 1000;
1891 				max = 2300;
1892 			} else if (evv_revision == 1) {
1893 				if (asicrev1 == 326) {
1894 					min = 1200;
1895 					max = 2500;
1896 					/* TODO: PATCH RO in VBIOS */
1897 				} else {
1898 					min = 1200;
1899 					max = 2000;
1900 				}
1901 			} else if (evv_revision == 2) {
1902 				min = 1200;
1903 				max = 2500;
1904 			}
1905 		}
1906 	} else {
1907 		min = 1100;
1908 		max = 2100;
1909 	}
1910 
1911 	data->ro_range_minimum = min;
1912 	data->ro_range_maximum = max;
1913 
1914 	/* TODO: PATCH RO in VBIOS here */
1915 
1916 	return 0;
1917 }
1918 
1919 /**
1920  * smu7_get_evv_voltages - Get Leakage VDDC based on leakage ID.
1921  *
1922  * @hwmgr:  the address of the powerplay hardware manager.
1923  * Return:   always 0
1924  */
1925 static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
1926 {
1927 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1928 	uint16_t vv_id;
1929 	uint16_t vddc = 0;
1930 	uint16_t vddgfx = 0;
1931 	uint16_t i, j;
1932 	uint32_t sclk = 0;
1933 	struct phm_ppt_v1_information *table_info =
1934 			(struct phm_ppt_v1_information *)hwmgr->pptable;
1935 	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL;
1936 
1937 	if (hwmgr->chip_id == CHIP_POLARIS10 ||
1938 	    hwmgr->chip_id == CHIP_POLARIS11 ||
1939 	    hwmgr->chip_id == CHIP_POLARIS12)
1940 		smu7_calculate_ro_range(hwmgr);
1941 
1942 	for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) {
1943 		vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
1944 
1945 		if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
1946 			if ((hwmgr->pp_table_version == PP_TABLE_V1)
1947 			    && !phm_get_sclk_for_voltage_evv(hwmgr,
1948 						table_info->vddgfx_lookup_table, vv_id, &sclk)) {
1949 				if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1950 							PHM_PlatformCaps_ClockStretcher)) {
1951 					sclk_table = table_info->vdd_dep_on_sclk;
1952 
1953 					for (j = 1; j < sclk_table->count; j++) {
1954 						if (sclk_table->entries[j].clk == sclk &&
1955 								sclk_table->entries[j].cks_enable == 0) {
1956 							sclk += 5000;
1957 							break;
1958 						}
1959 					}
1960 				}
1961 				if (0 == atomctrl_get_voltage_evv_on_sclk
1962 				    (hwmgr, VOLTAGE_TYPE_VDDGFX, sclk,
1963 				     vv_id, &vddgfx)) {
1964 					/* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */
1965 					PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -EINVAL);
1966 
1967 					/* the voltage should not be zero nor equal to leakage ID */
1968 					if (vddgfx != 0 && vddgfx != vv_id) {
1969 						data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx;
1970 						data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = vv_id;
1971 						data->vddcgfx_leakage.count++;
1972 					}
1973 				} else {
1974 					pr_info("Error retrieving EVV voltage value!\n");
1975 				}
1976 			}
1977 		} else {
1978 			if ((hwmgr->pp_table_version == PP_TABLE_V0)
1979 				|| !phm_get_sclk_for_voltage_evv(hwmgr,
1980 					table_info->vddc_lookup_table, vv_id, &sclk)) {
1981 				if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1982 						PHM_PlatformCaps_ClockStretcher)) {
1983 					if (table_info == NULL)
1984 						return -EINVAL;
1985 					sclk_table = table_info->vdd_dep_on_sclk;
1986 
1987 					for (j = 1; j < sclk_table->count; j++) {
1988 						if (sclk_table->entries[j].clk == sclk &&
1989 								sclk_table->entries[j].cks_enable == 0) {
1990 							sclk += 5000;
1991 							break;
1992 						}
1993 					}
1994 				}
1995 
1996 				if (phm_get_voltage_evv_on_sclk(hwmgr,
1997 							VOLTAGE_TYPE_VDDC,
1998 							sclk, vv_id, &vddc) == 0) {
1999 					if (vddc >= 2000 || vddc == 0)
2000 						return -EINVAL;
2001 				} else {
2002 					pr_debug("failed to retrieving EVV voltage!\n");
2003 					continue;
2004 				}
2005 
2006 				/* the voltage should not be zero nor equal to leakage ID */
2007 				if (vddc != 0 && vddc != vv_id) {
2008 					data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc);
2009 					data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id;
2010 					data->vddc_leakage.count++;
2011 				}
2012 			}
2013 		}
2014 	}
2015 
2016 	return 0;
2017 }
2018 
2019 /**
2020  * smu7_patch_ppt_v1_with_vdd_leakage - Change virtual leakage voltage to actual value.
2021  *
2022  * @hwmgr:  the address of the powerplay hardware manager.
2023  * @voltage: pointer to changing voltage
2024  * @leakage_table: pointer to leakage table
2025  */
2026 static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr,
2027 		uint16_t *voltage, struct smu7_leakage_voltage *leakage_table)
2028 {
2029 	uint32_t index;
2030 
2031 	/* search for leakage voltage ID 0xff01 ~ 0xff08 */
2032 	for (index = 0; index < leakage_table->count; index++) {
2033 		/* if this voltage matches a leakage voltage ID */
2034 		/* patch with actual leakage voltage */
2035 		if (leakage_table->leakage_id[index] == *voltage) {
2036 			*voltage = leakage_table->actual_voltage[index];
2037 			break;
2038 		}
2039 	}
2040 
2041 	if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
2042 		pr_err("Voltage value looks like a Leakage ID but it's not patched \n");
2043 }
2044 
2045 /**
2046  * smu7_patch_lookup_table_with_leakage - Patch voltage lookup table by EVV leakages.
2047  *
2048  * @hwmgr:  the address of the powerplay hardware manager.
2049  * @lookup_table: pointer to voltage lookup table
2050  * @leakage_table: pointer to leakage table
2051  * Return:     always 0
2052  */
2053 static int smu7_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
2054 		phm_ppt_v1_voltage_lookup_table *lookup_table,
2055 		struct smu7_leakage_voltage *leakage_table)
2056 {
2057 	uint32_t i;
2058 
2059 	for (i = 0; i < lookup_table->count; i++)
2060 		smu7_patch_ppt_v1_with_vdd_leakage(hwmgr,
2061 				&lookup_table->entries[i].us_vdd, leakage_table);
2062 
2063 	return 0;
2064 }
2065 
2066 static int smu7_patch_clock_voltage_limits_with_vddc_leakage(
2067 		struct pp_hwmgr *hwmgr, struct smu7_leakage_voltage *leakage_table,
2068 		uint16_t *vddc)
2069 {
2070 	struct phm_ppt_v1_information *table_info =
2071 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2072 	smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table);
2073 	hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
2074 			table_info->max_clock_voltage_on_dc.vddc;
2075 	return 0;
2076 }
2077 
2078 static int smu7_patch_voltage_dependency_tables_with_lookup_table(
2079 		struct pp_hwmgr *hwmgr)
2080 {
2081 	uint8_t entry_id;
2082 	uint8_t voltage_id;
2083 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2084 	struct phm_ppt_v1_information *table_info =
2085 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2086 
2087 	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
2088 			table_info->vdd_dep_on_sclk;
2089 	struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
2090 			table_info->vdd_dep_on_mclk;
2091 	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
2092 			table_info->mm_dep_table;
2093 
2094 	if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2095 		for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2096 			voltage_id = sclk_table->entries[entry_id].vddInd;
2097 			sclk_table->entries[entry_id].vddgfx =
2098 				table_info->vddgfx_lookup_table->entries[voltage_id].us_vdd;
2099 		}
2100 	} else {
2101 		for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2102 			voltage_id = sclk_table->entries[entry_id].vddInd;
2103 			sclk_table->entries[entry_id].vddc =
2104 				table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2105 		}
2106 	}
2107 
2108 	for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
2109 		voltage_id = mclk_table->entries[entry_id].vddInd;
2110 		mclk_table->entries[entry_id].vddc =
2111 			table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2112 	}
2113 
2114 	for (entry_id = 0; entry_id < mm_table->count; ++entry_id) {
2115 		voltage_id = mm_table->entries[entry_id].vddcInd;
2116 		mm_table->entries[entry_id].vddc =
2117 			table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2118 	}
2119 
2120 	return 0;
2121 
2122 }
2123 
2124 static int phm_add_voltage(struct pp_hwmgr *hwmgr,
2125 			phm_ppt_v1_voltage_lookup_table *look_up_table,
2126 			phm_ppt_v1_voltage_lookup_record *record)
2127 {
2128 	uint32_t i;
2129 
2130 	PP_ASSERT_WITH_CODE((NULL != look_up_table),
2131 		"Lookup Table empty.", return -EINVAL);
2132 	PP_ASSERT_WITH_CODE((0 != look_up_table->count),
2133 		"Lookup Table empty.", return -EINVAL);
2134 
2135 	i = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX);
2136 	PP_ASSERT_WITH_CODE((i >= look_up_table->count),
2137 		"Lookup Table is full.", return -EINVAL);
2138 
2139 	/* This is to avoid entering duplicate calculated records. */
2140 	for (i = 0; i < look_up_table->count; i++) {
2141 		if (look_up_table->entries[i].us_vdd == record->us_vdd) {
2142 			if (look_up_table->entries[i].us_calculated == 1)
2143 				return 0;
2144 			break;
2145 		}
2146 	}
2147 
2148 	look_up_table->entries[i].us_calculated = 1;
2149 	look_up_table->entries[i].us_vdd = record->us_vdd;
2150 	look_up_table->entries[i].us_cac_low = record->us_cac_low;
2151 	look_up_table->entries[i].us_cac_mid = record->us_cac_mid;
2152 	look_up_table->entries[i].us_cac_high = record->us_cac_high;
2153 	/* Only increment the count when we're appending, not replacing duplicate entry. */
2154 	if (i == look_up_table->count)
2155 		look_up_table->count++;
2156 
2157 	return 0;
2158 }
2159 
2160 
2161 static int smu7_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr)
2162 {
2163 	uint8_t entry_id;
2164 	struct phm_ppt_v1_voltage_lookup_record v_record;
2165 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2166 	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2167 
2168 	phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
2169 	phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk;
2170 
2171 	if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2172 		for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2173 			if (sclk_table->entries[entry_id].vdd_offset & (1 << 15))
2174 				v_record.us_vdd = sclk_table->entries[entry_id].vddgfx +
2175 					sclk_table->entries[entry_id].vdd_offset - 0xFFFF;
2176 			else
2177 				v_record.us_vdd = sclk_table->entries[entry_id].vddgfx +
2178 					sclk_table->entries[entry_id].vdd_offset;
2179 
2180 			sclk_table->entries[entry_id].vddc =
2181 				v_record.us_cac_low = v_record.us_cac_mid =
2182 				v_record.us_cac_high = v_record.us_vdd;
2183 
2184 			phm_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record);
2185 		}
2186 
2187 		for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
2188 			if (mclk_table->entries[entry_id].vdd_offset & (1 << 15))
2189 				v_record.us_vdd = mclk_table->entries[entry_id].vddc +
2190 					mclk_table->entries[entry_id].vdd_offset - 0xFFFF;
2191 			else
2192 				v_record.us_vdd = mclk_table->entries[entry_id].vddc +
2193 					mclk_table->entries[entry_id].vdd_offset;
2194 
2195 			mclk_table->entries[entry_id].vddgfx = v_record.us_cac_low =
2196 				v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
2197 			phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
2198 		}
2199 	}
2200 	return 0;
2201 }
2202 
2203 static int smu7_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr)
2204 {
2205 	uint8_t entry_id;
2206 	struct phm_ppt_v1_voltage_lookup_record v_record;
2207 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2208 	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2209 	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
2210 
2211 	if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2212 		for (entry_id = 0; entry_id < mm_table->count; entry_id++) {
2213 			if (mm_table->entries[entry_id].vddgfx_offset & (1 << 15))
2214 				v_record.us_vdd = mm_table->entries[entry_id].vddc +
2215 					mm_table->entries[entry_id].vddgfx_offset - 0xFFFF;
2216 			else
2217 				v_record.us_vdd = mm_table->entries[entry_id].vddc +
2218 					mm_table->entries[entry_id].vddgfx_offset;
2219 
2220 			/* Add the calculated VDDGFX to the VDDGFX lookup table */
2221 			mm_table->entries[entry_id].vddgfx = v_record.us_cac_low =
2222 				v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
2223 			phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
2224 		}
2225 	}
2226 	return 0;
2227 }
2228 
2229 static int smu7_sort_lookup_table(struct pp_hwmgr *hwmgr,
2230 		struct phm_ppt_v1_voltage_lookup_table *lookup_table)
2231 {
2232 	uint32_t table_size, i, j;
2233 	table_size = lookup_table->count;
2234 
2235 	PP_ASSERT_WITH_CODE(0 != lookup_table->count,
2236 		"Lookup table is empty", return -EINVAL);
2237 
2238 	/* Sorting voltages */
2239 	for (i = 0; i < table_size - 1; i++) {
2240 		for (j = i + 1; j > 0; j--) {
2241 			if (lookup_table->entries[j].us_vdd <
2242 					lookup_table->entries[j - 1].us_vdd) {
2243 				swap(lookup_table->entries[j - 1],
2244 				     lookup_table->entries[j]);
2245 			}
2246 		}
2247 	}
2248 
2249 	return 0;
2250 }
2251 
2252 static int smu7_complete_dependency_tables(struct pp_hwmgr *hwmgr)
2253 {
2254 	int result = 0;
2255 	int tmp_result;
2256 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2257 	struct phm_ppt_v1_information *table_info =
2258 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2259 
2260 	if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2261 		tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr,
2262 			table_info->vddgfx_lookup_table, &(data->vddcgfx_leakage));
2263 		if (tmp_result != 0)
2264 			result = tmp_result;
2265 
2266 		smu7_patch_ppt_v1_with_vdd_leakage(hwmgr,
2267 			&table_info->max_clock_voltage_on_dc.vddgfx, &(data->vddcgfx_leakage));
2268 	} else {
2269 
2270 		tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr,
2271 				table_info->vddc_lookup_table, &(data->vddc_leakage));
2272 		if (tmp_result)
2273 			result = tmp_result;
2274 
2275 		tmp_result = smu7_patch_clock_voltage_limits_with_vddc_leakage(hwmgr,
2276 				&(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc);
2277 		if (tmp_result)
2278 			result = tmp_result;
2279 	}
2280 
2281 	tmp_result = smu7_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
2282 	if (tmp_result)
2283 		result = tmp_result;
2284 
2285 	tmp_result = smu7_calc_voltage_dependency_tables(hwmgr);
2286 	if (tmp_result)
2287 		result = tmp_result;
2288 
2289 	tmp_result = smu7_calc_mm_voltage_dependency_table(hwmgr);
2290 	if (tmp_result)
2291 		result = tmp_result;
2292 
2293 	tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddgfx_lookup_table);
2294 	if (tmp_result)
2295 		result = tmp_result;
2296 
2297 	tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
2298 	if (tmp_result)
2299 		result = tmp_result;
2300 
2301 	return result;
2302 }
2303 
2304 static int smu7_find_highest_vddc(struct pp_hwmgr *hwmgr)
2305 {
2306 	struct phm_ppt_v1_information *table_info =
2307 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2308 	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
2309 						table_info->vdd_dep_on_sclk;
2310 	struct phm_ppt_v1_voltage_lookup_table *lookup_table =
2311 						table_info->vddc_lookup_table;
2312 	uint16_t highest_voltage;
2313 	uint32_t i;
2314 
2315 	highest_voltage = allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
2316 
2317 	for (i = 0; i < lookup_table->count; i++) {
2318 		if (lookup_table->entries[i].us_vdd < ATOM_VIRTUAL_VOLTAGE_ID0 &&
2319 		    lookup_table->entries[i].us_vdd > highest_voltage)
2320 			highest_voltage = lookup_table->entries[i].us_vdd;
2321 	}
2322 
2323 	return highest_voltage;
2324 }
2325 
2326 static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr)
2327 {
2328 	struct phm_ppt_v1_information *table_info =
2329 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2330 
2331 	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
2332 						table_info->vdd_dep_on_sclk;
2333 	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
2334 						table_info->vdd_dep_on_mclk;
2335 
2336 	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
2337 		"VDD dependency on SCLK table is missing.",
2338 		return -EINVAL);
2339 	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
2340 		"VDD dependency on SCLK table has to have is missing.",
2341 		return -EINVAL);
2342 
2343 	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
2344 		"VDD dependency on MCLK table is missing",
2345 		return -EINVAL);
2346 	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
2347 		"VDD dependency on MCLK table has to have is missing.",
2348 		return -EINVAL);
2349 
2350 	table_info->max_clock_voltage_on_ac.sclk =
2351 		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
2352 	table_info->max_clock_voltage_on_ac.mclk =
2353 		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
2354 	if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM)
2355 		table_info->max_clock_voltage_on_ac.vddc =
2356 			smu7_find_highest_vddc(hwmgr);
2357 	else
2358 		table_info->max_clock_voltage_on_ac.vddc =
2359 			allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
2360 	table_info->max_clock_voltage_on_ac.vddci =
2361 		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
2362 
2363 	hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = table_info->max_clock_voltage_on_ac.sclk;
2364 	hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = table_info->max_clock_voltage_on_ac.mclk;
2365 	hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = table_info->max_clock_voltage_on_ac.vddc;
2366 	hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = table_info->max_clock_voltage_on_ac.vddci;
2367 
2368 	return 0;
2369 }
2370 
2371 static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
2372 {
2373 	struct phm_ppt_v1_information *table_info =
2374 		       (struct phm_ppt_v1_information *)(hwmgr->pptable);
2375 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
2376 	struct phm_ppt_v1_voltage_lookup_table *lookup_table;
2377 	uint32_t i;
2378 	uint32_t hw_revision, sub_vendor_id, sub_sys_id;
2379 	struct amdgpu_device *adev = hwmgr->adev;
2380 
2381 	if (table_info != NULL) {
2382 		dep_mclk_table = table_info->vdd_dep_on_mclk;
2383 		lookup_table = table_info->vddc_lookup_table;
2384 	} else
2385 		return 0;
2386 
2387 	hw_revision = adev->pdev->revision;
2388 	sub_sys_id = adev->pdev->subsystem_device;
2389 	sub_vendor_id = adev->pdev->subsystem_vendor;
2390 
2391 	if (adev->pdev->device == 0x67DF && hw_revision == 0xC7 &&
2392 	    ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) ||
2393 	     (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) ||
2394 	     (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) {
2395 
2396 		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
2397 					      CGS_IND_REG__SMC,
2398 					      PWR_CKS_CNTL,
2399 					      CKS_STRETCH_AMOUNT,
2400 					      0x3);
2401 
2402 		if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000)
2403 			return 0;
2404 
2405 		for (i = 0; i < lookup_table->count; i++) {
2406 			if (lookup_table->entries[i].us_vdd < 0xff01 && lookup_table->entries[i].us_vdd >= 1000) {
2407 				dep_mclk_table->entries[dep_mclk_table->count-1].vddInd = (uint8_t) i;
2408 				return 0;
2409 			}
2410 		}
2411 	}
2412 	return 0;
2413 }
2414 
2415 static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr)
2416 {
2417 	struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
2418 	uint32_t temp_reg;
2419 	struct phm_ppt_v1_information *table_info =
2420 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2421 
2422 
2423 	if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) {
2424 		temp_reg = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL);
2425 		switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) {
2426 		case 0:
2427 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1);
2428 			break;
2429 		case 1:
2430 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2);
2431 			break;
2432 		case 2:
2433 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW, 0x1);
2434 			break;
2435 		case 3:
2436 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1);
2437 			break;
2438 		case 4:
2439 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1);
2440 			break;
2441 		default:
2442 			break;
2443 		}
2444 		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL, temp_reg);
2445 	}
2446 
2447 	if (table_info == NULL)
2448 		return 0;
2449 
2450 	if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp != 0 &&
2451 		hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode) {
2452 		hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit =
2453 			(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit;
2454 
2455 		hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMaxLimit =
2456 			(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
2457 
2458 		hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMStep = 1;
2459 
2460 		hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 100;
2461 
2462 		hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMinLimit =
2463 			(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit;
2464 
2465 		hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMStep = 1;
2466 
2467 		table_info->cac_dtp_table->usDefaultTargetOperatingTemp = (table_info->cac_dtp_table->usDefaultTargetOperatingTemp >= 50) ?
2468 								(table_info->cac_dtp_table->usDefaultTargetOperatingTemp - 50) : 0;
2469 
2470 		table_info->cac_dtp_table->usOperatingTempMaxLimit = table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
2471 		table_info->cac_dtp_table->usOperatingTempStep = 1;
2472 		table_info->cac_dtp_table->usOperatingTempHyst = 1;
2473 
2474 		hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM =
2475 			       hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
2476 
2477 		hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
2478 			       hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM;
2479 
2480 		hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit =
2481 			       table_info->cac_dtp_table->usOperatingTempMinLimit;
2482 
2483 		hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit =
2484 			       table_info->cac_dtp_table->usOperatingTempMaxLimit;
2485 
2486 		hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
2487 			       table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
2488 
2489 		hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep =
2490 			       table_info->cac_dtp_table->usOperatingTempStep;
2491 
2492 		hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp =
2493 			       table_info->cac_dtp_table->usTargetOperatingTemp;
2494 		if (hwmgr->feature_mask & PP_OD_FUZZY_FAN_CONTROL_MASK)
2495 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2496 					PHM_PlatformCaps_ODFuzzyFanControlSupport);
2497 	}
2498 
2499 	return 0;
2500 }
2501 
2502 /**
2503  * smu7_patch_ppt_v0_with_vdd_leakage - Change virtual leakage voltage to actual value.
2504  *
2505  * @hwmgr:  the address of the powerplay hardware manager.
2506  * @voltage: pointer to changing voltage
2507  * @leakage_table: pointer to leakage table
2508  */
2509 static void smu7_patch_ppt_v0_with_vdd_leakage(struct pp_hwmgr *hwmgr,
2510 		uint32_t *voltage, struct smu7_leakage_voltage *leakage_table)
2511 {
2512 	uint32_t index;
2513 
2514 	/* search for leakage voltage ID 0xff01 ~ 0xff08 */
2515 	for (index = 0; index < leakage_table->count; index++) {
2516 		/* if this voltage matches a leakage voltage ID */
2517 		/* patch with actual leakage voltage */
2518 		if (leakage_table->leakage_id[index] == *voltage) {
2519 			*voltage = leakage_table->actual_voltage[index];
2520 			break;
2521 		}
2522 	}
2523 
2524 	if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
2525 		pr_err("Voltage value looks like a Leakage ID but it's not patched \n");
2526 }
2527 
2528 
2529 static int smu7_patch_vddc(struct pp_hwmgr *hwmgr,
2530 			      struct phm_clock_voltage_dependency_table *tab)
2531 {
2532 	uint16_t i;
2533 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2534 
2535 	if (tab)
2536 		for (i = 0; i < tab->count; i++)
2537 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2538 						&data->vddc_leakage);
2539 
2540 	return 0;
2541 }
2542 
2543 static int smu7_patch_vddci(struct pp_hwmgr *hwmgr,
2544 			       struct phm_clock_voltage_dependency_table *tab)
2545 {
2546 	uint16_t i;
2547 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2548 
2549 	if (tab)
2550 		for (i = 0; i < tab->count; i++)
2551 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2552 							&data->vddci_leakage);
2553 
2554 	return 0;
2555 }
2556 
2557 static int smu7_patch_vce_vddc(struct pp_hwmgr *hwmgr,
2558 				  struct phm_vce_clock_voltage_dependency_table *tab)
2559 {
2560 	uint16_t i;
2561 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2562 
2563 	if (tab)
2564 		for (i = 0; i < tab->count; i++)
2565 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2566 							&data->vddc_leakage);
2567 
2568 	return 0;
2569 }
2570 
2571 
2572 static int smu7_patch_uvd_vddc(struct pp_hwmgr *hwmgr,
2573 				  struct phm_uvd_clock_voltage_dependency_table *tab)
2574 {
2575 	uint16_t i;
2576 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2577 
2578 	if (tab)
2579 		for (i = 0; i < tab->count; i++)
2580 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2581 							&data->vddc_leakage);
2582 
2583 	return 0;
2584 }
2585 
2586 static int smu7_patch_vddc_shed_limit(struct pp_hwmgr *hwmgr,
2587 					 struct phm_phase_shedding_limits_table *tab)
2588 {
2589 	uint16_t i;
2590 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2591 
2592 	if (tab)
2593 		for (i = 0; i < tab->count; i++)
2594 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].Voltage,
2595 							&data->vddc_leakage);
2596 
2597 	return 0;
2598 }
2599 
2600 static int smu7_patch_samu_vddc(struct pp_hwmgr *hwmgr,
2601 				   struct phm_samu_clock_voltage_dependency_table *tab)
2602 {
2603 	uint16_t i;
2604 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2605 
2606 	if (tab)
2607 		for (i = 0; i < tab->count; i++)
2608 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2609 							&data->vddc_leakage);
2610 
2611 	return 0;
2612 }
2613 
2614 static int smu7_patch_acp_vddc(struct pp_hwmgr *hwmgr,
2615 				  struct phm_acp_clock_voltage_dependency_table *tab)
2616 {
2617 	uint16_t i;
2618 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2619 
2620 	if (tab)
2621 		for (i = 0; i < tab->count; i++)
2622 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2623 					&data->vddc_leakage);
2624 
2625 	return 0;
2626 }
2627 
2628 static int smu7_patch_limits_vddc(struct pp_hwmgr *hwmgr,
2629 				  struct phm_clock_and_voltage_limits *tab)
2630 {
2631 	uint32_t vddc, vddci;
2632 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2633 
2634 	if (tab) {
2635 		vddc = tab->vddc;
2636 		smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc,
2637 						   &data->vddc_leakage);
2638 		tab->vddc = vddc;
2639 		vddci = tab->vddci;
2640 		smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddci,
2641 						   &data->vddci_leakage);
2642 		tab->vddci = vddci;
2643 	}
2644 
2645 	return 0;
2646 }
2647 
2648 static int smu7_patch_cac_vddc(struct pp_hwmgr *hwmgr, struct phm_cac_leakage_table *tab)
2649 {
2650 	uint32_t i;
2651 	uint32_t vddc;
2652 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2653 
2654 	if (tab) {
2655 		for (i = 0; i < tab->count; i++) {
2656 			vddc = (uint32_t)(tab->entries[i].Vddc);
2657 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, &data->vddc_leakage);
2658 			tab->entries[i].Vddc = (uint16_t)vddc;
2659 		}
2660 	}
2661 
2662 	return 0;
2663 }
2664 
2665 static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr)
2666 {
2667 	int tmp;
2668 
2669 	tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_sclk);
2670 	if (tmp)
2671 		return -EINVAL;
2672 
2673 	tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_mclk);
2674 	if (tmp)
2675 		return -EINVAL;
2676 
2677 	tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
2678 	if (tmp)
2679 		return -EINVAL;
2680 
2681 	tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk);
2682 	if (tmp)
2683 		return -EINVAL;
2684 
2685 	tmp = smu7_patch_vce_vddc(hwmgr, hwmgr->dyn_state.vce_clock_voltage_dependency_table);
2686 	if (tmp)
2687 		return -EINVAL;
2688 
2689 	tmp = smu7_patch_uvd_vddc(hwmgr, hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
2690 	if (tmp)
2691 		return -EINVAL;
2692 
2693 	tmp = smu7_patch_samu_vddc(hwmgr, hwmgr->dyn_state.samu_clock_voltage_dependency_table);
2694 	if (tmp)
2695 		return -EINVAL;
2696 
2697 	tmp = smu7_patch_acp_vddc(hwmgr, hwmgr->dyn_state.acp_clock_voltage_dependency_table);
2698 	if (tmp)
2699 		return -EINVAL;
2700 
2701 	tmp = smu7_patch_vddc_shed_limit(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table);
2702 	if (tmp)
2703 		return -EINVAL;
2704 
2705 	tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_ac);
2706 	if (tmp)
2707 		return -EINVAL;
2708 
2709 	tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_dc);
2710 	if (tmp)
2711 		return -EINVAL;
2712 
2713 	tmp = smu7_patch_cac_vddc(hwmgr, hwmgr->dyn_state.cac_leakage_table);
2714 	if (tmp)
2715 		return -EINVAL;
2716 
2717 	return 0;
2718 }
2719 
2720 
2721 static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr)
2722 {
2723 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2724 
2725 	struct phm_clock_voltage_dependency_table *allowed_sclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_sclk;
2726 	struct phm_clock_voltage_dependency_table *allowed_mclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_mclk;
2727 	struct phm_clock_voltage_dependency_table *allowed_mclk_vddci_table = hwmgr->dyn_state.vddci_dependency_on_mclk;
2728 
2729 	PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table != NULL,
2730 		"VDDC dependency on SCLK table is missing. This table is mandatory",
2731 		return -EINVAL);
2732 	PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table->count >= 1,
2733 		"VDDC dependency on SCLK table has to have is missing. This table is mandatory",
2734 		return -EINVAL);
2735 
2736 	PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table != NULL,
2737 		"VDDC dependency on MCLK table is missing. This table is mandatory",
2738 		return -EINVAL);
2739 	PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table->count >= 1,
2740 		"VDD dependency on MCLK table has to have is missing. This table is mandatory",
2741 		return -EINVAL);
2742 
2743 	data->min_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[0].v;
2744 	data->max_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v;
2745 
2746 	hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
2747 		allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].clk;
2748 	hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
2749 		allowed_mclk_vddc_table->entries[allowed_mclk_vddc_table->count - 1].clk;
2750 	hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
2751 		allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v;
2752 
2753 	if (allowed_mclk_vddci_table != NULL && allowed_mclk_vddci_table->count >= 1) {
2754 		data->min_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[0].v;
2755 		data->max_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v;
2756 	}
2757 
2758 	if (hwmgr->dyn_state.vddci_dependency_on_mclk != NULL && hwmgr->dyn_state.vddci_dependency_on_mclk->count >= 1)
2759 		hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = hwmgr->dyn_state.vddci_dependency_on_mclk->entries[hwmgr->dyn_state.vddci_dependency_on_mclk->count - 1].v;
2760 
2761 	return 0;
2762 }
2763 
2764 static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
2765 {
2766 	kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
2767 	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
2768 	kfree(hwmgr->backend);
2769 	hwmgr->backend = NULL;
2770 
2771 	return 0;
2772 }
2773 
2774 static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr)
2775 {
2776 	uint16_t virtual_voltage_id, vddc, vddci, efuse_voltage_id;
2777 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2778 	int i;
2779 
2780 	if (atomctrl_get_leakage_id_from_efuse(hwmgr, &efuse_voltage_id) == 0) {
2781 		for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) {
2782 			virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
2783 			if (atomctrl_get_leakage_vddc_base_on_leakage(hwmgr, &vddc, &vddci,
2784 								virtual_voltage_id,
2785 								efuse_voltage_id) == 0) {
2786 				if (vddc != 0 && vddc != virtual_voltage_id) {
2787 					data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc;
2788 					data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id;
2789 					data->vddc_leakage.count++;
2790 				}
2791 				if (vddci != 0 && vddci != virtual_voltage_id) {
2792 					data->vddci_leakage.actual_voltage[data->vddci_leakage.count] = vddci;
2793 					data->vddci_leakage.leakage_id[data->vddci_leakage.count] = virtual_voltage_id;
2794 					data->vddci_leakage.count++;
2795 				}
2796 			}
2797 		}
2798 	}
2799 	return 0;
2800 }
2801 
2802 #define LEAKAGE_ID_MSB			463
2803 #define LEAKAGE_ID_LSB			454
2804 
2805 static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr)
2806 {
2807 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2808 	uint32_t efuse;
2809 	uint16_t offset;
2810 	int ret = 0;
2811 
2812 	if (data->disable_edc_leakage_controller)
2813 		return 0;
2814 
2815 	ret = atomctrl_get_edc_hilo_leakage_offset_table(hwmgr,
2816 							 &data->edc_hilo_leakage_offset_from_vbios);
2817 	if (ret)
2818 		return ret;
2819 
2820 	if (data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset &&
2821 	    data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) {
2822 		atomctrl_read_efuse(hwmgr, LEAKAGE_ID_LSB, LEAKAGE_ID_MSB, &efuse);
2823 		if (efuse < data->edc_hilo_leakage_offset_from_vbios.usHiLoLeakageThreshold)
2824 			offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset;
2825 		else
2826 			offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset;
2827 
2828 		ret = atomctrl_get_edc_leakage_table(hwmgr,
2829 						     &data->edc_leakage_table,
2830 						     offset);
2831 		if (ret)
2832 			return ret;
2833 	}
2834 
2835 	return ret;
2836 }
2837 
2838 static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
2839 {
2840 	struct smu7_hwmgr *data;
2841 	int result = 0;
2842 
2843 	data = kzalloc(sizeof(struct smu7_hwmgr), GFP_KERNEL);
2844 	if (data == NULL)
2845 		return -ENOMEM;
2846 
2847 	hwmgr->backend = data;
2848 	smu7_patch_voltage_workaround(hwmgr);
2849 	smu7_init_dpm_defaults(hwmgr);
2850 
2851 	/* Get leakage voltage based on leakage ID. */
2852 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2853 			PHM_PlatformCaps_EVV)) {
2854 		result = smu7_get_evv_voltages(hwmgr);
2855 		if (result) {
2856 			pr_info("Get EVV Voltage Failed.  Abort Driver loading!\n");
2857 			return -EINVAL;
2858 		}
2859 	} else {
2860 		smu7_get_elb_voltages(hwmgr);
2861 	}
2862 
2863 	if (hwmgr->pp_table_version == PP_TABLE_V1) {
2864 		smu7_complete_dependency_tables(hwmgr);
2865 		smu7_set_private_data_based_on_pptable_v1(hwmgr);
2866 	} else if (hwmgr->pp_table_version == PP_TABLE_V0) {
2867 		smu7_patch_dependency_tables_with_leakage(hwmgr);
2868 		smu7_set_private_data_based_on_pptable_v0(hwmgr);
2869 	}
2870 
2871 	/* Initalize Dynamic State Adjustment Rule Settings */
2872 	result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
2873 
2874 	if (0 == result) {
2875 		struct amdgpu_device *adev = hwmgr->adev;
2876 
2877 		data->is_tlu_enabled = false;
2878 
2879 		hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
2880 							SMU7_MAX_HARDWARE_POWERLEVELS;
2881 		hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
2882 		hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
2883 
2884 		data->pcie_gen_cap = adev->pm.pcie_gen_mask;
2885 		if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
2886 			data->pcie_spc_cap = 20;
2887 		else
2888 			data->pcie_spc_cap = 16;
2889 		data->pcie_lane_cap = adev->pm.pcie_mlw_mask;
2890 
2891 		hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
2892 /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
2893 		hwmgr->platform_descriptor.clockStep.engineClock = 500;
2894 		hwmgr->platform_descriptor.clockStep.memoryClock = 500;
2895 		smu7_thermal_parameter_init(hwmgr);
2896 	} else {
2897 		/* Ignore return value in here, we are cleaning up a mess. */
2898 		smu7_hwmgr_backend_fini(hwmgr);
2899 	}
2900 
2901 	result = smu7_update_edc_leakage_table(hwmgr);
2902 	if (result)
2903 		return result;
2904 
2905 	return 0;
2906 }
2907 
2908 static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr)
2909 {
2910 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2911 	uint32_t level, tmp;
2912 
2913 	if (!data->pcie_dpm_key_disabled) {
2914 		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
2915 			level = 0;
2916 			tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask;
2917 			while (tmp >>= 1)
2918 				level++;
2919 
2920 			if (level)
2921 				smum_send_msg_to_smc_with_parameter(hwmgr,
2922 						PPSMC_MSG_PCIeDPM_ForceLevel, level,
2923 						NULL);
2924 		}
2925 	}
2926 
2927 	if (!data->sclk_dpm_key_disabled) {
2928 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
2929 			level = 0;
2930 			tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
2931 			while (tmp >>= 1)
2932 				level++;
2933 
2934 			if (level)
2935 				smum_send_msg_to_smc_with_parameter(hwmgr,
2936 						PPSMC_MSG_SCLKDPM_SetEnabledMask,
2937 						(1 << level),
2938 						NULL);
2939 		}
2940 	}
2941 
2942 	if (!data->mclk_dpm_key_disabled) {
2943 		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
2944 			level = 0;
2945 			tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
2946 			while (tmp >>= 1)
2947 				level++;
2948 
2949 			if (level)
2950 				smum_send_msg_to_smc_with_parameter(hwmgr,
2951 						PPSMC_MSG_MCLKDPM_SetEnabledMask,
2952 						(1 << level),
2953 						NULL);
2954 		}
2955 	}
2956 
2957 	return 0;
2958 }
2959 
2960 static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
2961 {
2962 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2963 
2964 	if (hwmgr->pp_table_version == PP_TABLE_V1)
2965 		phm_apply_dal_min_voltage_request(hwmgr);
2966 /* TO DO  for v0 iceland and Ci*/
2967 
2968 	if (!data->sclk_dpm_key_disabled) {
2969 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask)
2970 			smum_send_msg_to_smc_with_parameter(hwmgr,
2971 					PPSMC_MSG_SCLKDPM_SetEnabledMask,
2972 					data->dpm_level_enable_mask.sclk_dpm_enable_mask,
2973 					NULL);
2974 	}
2975 
2976 	if (!data->mclk_dpm_key_disabled) {
2977 		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask)
2978 			smum_send_msg_to_smc_with_parameter(hwmgr,
2979 					PPSMC_MSG_MCLKDPM_SetEnabledMask,
2980 					data->dpm_level_enable_mask.mclk_dpm_enable_mask,
2981 					NULL);
2982 	}
2983 
2984 	return 0;
2985 }
2986 
2987 static int smu7_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
2988 {
2989 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2990 
2991 	if (!smum_is_dpm_running(hwmgr))
2992 		return -EINVAL;
2993 
2994 	if (!data->pcie_dpm_key_disabled) {
2995 		smum_send_msg_to_smc(hwmgr,
2996 				PPSMC_MSG_PCIeDPM_UnForceLevel,
2997 				NULL);
2998 	}
2999 
3000 	return smu7_upload_dpm_level_enable_mask(hwmgr);
3001 }
3002 
3003 static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr)
3004 {
3005 	struct smu7_hwmgr *data =
3006 			(struct smu7_hwmgr *)(hwmgr->backend);
3007 	uint32_t level;
3008 
3009 	if (!data->sclk_dpm_key_disabled)
3010 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3011 			level = phm_get_lowest_enabled_level(hwmgr,
3012 							      data->dpm_level_enable_mask.sclk_dpm_enable_mask);
3013 			smum_send_msg_to_smc_with_parameter(hwmgr,
3014 							    PPSMC_MSG_SCLKDPM_SetEnabledMask,
3015 							    (1 << level),
3016 							    NULL);
3017 
3018 	}
3019 
3020 	if (!data->mclk_dpm_key_disabled) {
3021 		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
3022 			level = phm_get_lowest_enabled_level(hwmgr,
3023 							      data->dpm_level_enable_mask.mclk_dpm_enable_mask);
3024 			smum_send_msg_to_smc_with_parameter(hwmgr,
3025 							    PPSMC_MSG_MCLKDPM_SetEnabledMask,
3026 							    (1 << level),
3027 							    NULL);
3028 		}
3029 	}
3030 
3031 	if (!data->pcie_dpm_key_disabled) {
3032 		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
3033 			level = phm_get_lowest_enabled_level(hwmgr,
3034 							      data->dpm_level_enable_mask.pcie_dpm_enable_mask);
3035 			smum_send_msg_to_smc_with_parameter(hwmgr,
3036 							    PPSMC_MSG_PCIeDPM_ForceLevel,
3037 							    (level),
3038 							    NULL);
3039 		}
3040 	}
3041 
3042 	return 0;
3043 }
3044 
3045 static int smu7_get_profiling_clk(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
3046 				uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *pcie_mask)
3047 {
3048 	uint32_t percentage;
3049 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3050 	struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table;
3051 	int32_t tmp_mclk;
3052 	int32_t tmp_sclk;
3053 	int32_t count;
3054 
3055 	if (golden_dpm_table->mclk_table.count < 1)
3056 		return -EINVAL;
3057 
3058 	percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value /
3059 			golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
3060 
3061 	if (golden_dpm_table->mclk_table.count == 1) {
3062 		percentage = 70;
3063 		tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
3064 		*mclk_mask = golden_dpm_table->mclk_table.count - 1;
3065 	} else {
3066 		tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value;
3067 		*mclk_mask = golden_dpm_table->mclk_table.count - 2;
3068 	}
3069 
3070 	tmp_sclk = tmp_mclk * percentage / 100;
3071 
3072 	if (hwmgr->pp_table_version == PP_TABLE_V0) {
3073 		for (count = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1;
3074 			count >= 0; count--) {
3075 			if (tmp_sclk >= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk) {
3076 				tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk;
3077 				*sclk_mask = count;
3078 				break;
3079 			}
3080 		}
3081 		if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
3082 			*sclk_mask = 0;
3083 			tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].clk;
3084 		}
3085 
3086 		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3087 			*sclk_mask = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1;
3088 	} else if (hwmgr->pp_table_version == PP_TABLE_V1) {
3089 		struct phm_ppt_v1_information *table_info =
3090 				(struct phm_ppt_v1_information *)(hwmgr->pptable);
3091 
3092 		for (count = table_info->vdd_dep_on_sclk->count-1; count >= 0; count--) {
3093 			if (tmp_sclk >= table_info->vdd_dep_on_sclk->entries[count].clk) {
3094 				tmp_sclk = table_info->vdd_dep_on_sclk->entries[count].clk;
3095 				*sclk_mask = count;
3096 				break;
3097 			}
3098 		}
3099 		if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
3100 			*sclk_mask = 0;
3101 			tmp_sclk =  table_info->vdd_dep_on_sclk->entries[0].clk;
3102 		}
3103 
3104 		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3105 			*sclk_mask = table_info->vdd_dep_on_sclk->count - 1;
3106 	}
3107 
3108 	if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
3109 		*mclk_mask = 0;
3110 	else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3111 		*mclk_mask = golden_dpm_table->mclk_table.count - 1;
3112 
3113 	*pcie_mask = data->dpm_table.pcie_speed_table.count - 1;
3114 	hwmgr->pstate_sclk = tmp_sclk;
3115 	hwmgr->pstate_mclk = tmp_mclk;
3116 
3117 	return 0;
3118 }
3119 
3120 static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr,
3121 				enum amd_dpm_forced_level level)
3122 {
3123 	int ret = 0;
3124 	uint32_t sclk_mask = 0;
3125 	uint32_t mclk_mask = 0;
3126 	uint32_t pcie_mask = 0;
3127 
3128 	if (hwmgr->pstate_sclk == 0)
3129 		smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask);
3130 
3131 	switch (level) {
3132 	case AMD_DPM_FORCED_LEVEL_HIGH:
3133 		ret = smu7_force_dpm_highest(hwmgr);
3134 		break;
3135 	case AMD_DPM_FORCED_LEVEL_LOW:
3136 		ret = smu7_force_dpm_lowest(hwmgr);
3137 		break;
3138 	case AMD_DPM_FORCED_LEVEL_AUTO:
3139 		ret = smu7_unforce_dpm_levels(hwmgr);
3140 		break;
3141 	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
3142 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
3143 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
3144 	case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
3145 		ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask);
3146 		if (ret)
3147 			return ret;
3148 		smu7_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask);
3149 		smu7_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask);
3150 		smu7_force_clock_level(hwmgr, PP_PCIE, 1<<pcie_mask);
3151 		break;
3152 	case AMD_DPM_FORCED_LEVEL_MANUAL:
3153 	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
3154 	default:
3155 		break;
3156 	}
3157 
3158 	if (!ret) {
3159 		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3160 			smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
3161 		else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3162 			smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr);
3163 	}
3164 	return ret;
3165 }
3166 
3167 static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr)
3168 {
3169 	return sizeof(struct smu7_power_state);
3170 }
3171 
3172 static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr,
3173 				 uint32_t vblank_time_us)
3174 {
3175 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3176 	uint32_t switch_limit_us;
3177 
3178 	switch (hwmgr->chip_id) {
3179 	case CHIP_POLARIS10:
3180 	case CHIP_POLARIS11:
3181 	case CHIP_POLARIS12:
3182 		if (hwmgr->is_kicker || (hwmgr->chip_id == CHIP_POLARIS12))
3183 			switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
3184 		else
3185 			switch_limit_us = data->is_memory_gddr5 ? 200 : 150;
3186 		break;
3187 	case CHIP_VEGAM:
3188 		switch_limit_us = 30;
3189 		break;
3190 	default:
3191 		switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
3192 		break;
3193 	}
3194 
3195 	if (vblank_time_us < switch_limit_us)
3196 		return true;
3197 	else
3198 		return false;
3199 }
3200 
3201 static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
3202 				struct pp_power_state *request_ps,
3203 			const struct pp_power_state *current_ps)
3204 {
3205 	struct amdgpu_device *adev = hwmgr->adev;
3206 	struct smu7_power_state *smu7_ps =
3207 				cast_phw_smu7_power_state(&request_ps->hardware);
3208 	uint32_t sclk;
3209 	uint32_t mclk;
3210 	struct PP_Clocks minimum_clocks = {0};
3211 	bool disable_mclk_switching;
3212 	bool disable_mclk_switching_for_frame_lock;
3213 	bool disable_mclk_switching_for_display;
3214 	const struct phm_clock_and_voltage_limits *max_limits;
3215 	uint32_t i;
3216 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3217 	struct phm_ppt_v1_information *table_info =
3218 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
3219 	int32_t count;
3220 	int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
3221 	uint32_t latency;
3222 	bool latency_allowed = false;
3223 
3224 	data->battery_state = (PP_StateUILabel_Battery ==
3225 			request_ps->classification.ui_label);
3226 	data->mclk_ignore_signal = false;
3227 
3228 	PP_ASSERT_WITH_CODE(smu7_ps->performance_level_count == 2,
3229 				 "VI should always have 2 performance levels",
3230 				);
3231 
3232 	max_limits = adev->pm.ac_power ?
3233 			&(hwmgr->dyn_state.max_clock_voltage_on_ac) :
3234 			&(hwmgr->dyn_state.max_clock_voltage_on_dc);
3235 
3236 	/* Cap clock DPM tables at DC MAX if it is in DC. */
3237 	if (!adev->pm.ac_power) {
3238 		for (i = 0; i < smu7_ps->performance_level_count; i++) {
3239 			if (smu7_ps->performance_levels[i].memory_clock > max_limits->mclk)
3240 				smu7_ps->performance_levels[i].memory_clock = max_limits->mclk;
3241 			if (smu7_ps->performance_levels[i].engine_clock > max_limits->sclk)
3242 				smu7_ps->performance_levels[i].engine_clock = max_limits->sclk;
3243 		}
3244 	}
3245 
3246 	minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock;
3247 	minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
3248 
3249 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3250 			PHM_PlatformCaps_StablePState)) {
3251 		max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
3252 		stable_pstate_sclk = (max_limits->sclk * 75) / 100;
3253 
3254 		for (count = table_info->vdd_dep_on_sclk->count - 1;
3255 				count >= 0; count--) {
3256 			if (stable_pstate_sclk >=
3257 					table_info->vdd_dep_on_sclk->entries[count].clk) {
3258 				stable_pstate_sclk =
3259 						table_info->vdd_dep_on_sclk->entries[count].clk;
3260 				break;
3261 			}
3262 		}
3263 
3264 		if (count < 0)
3265 			stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
3266 
3267 		stable_pstate_mclk = max_limits->mclk;
3268 
3269 		minimum_clocks.engineClock = stable_pstate_sclk;
3270 		minimum_clocks.memoryClock = stable_pstate_mclk;
3271 	}
3272 
3273 	disable_mclk_switching_for_frame_lock = phm_cap_enabled(
3274 				    hwmgr->platform_descriptor.platformCaps,
3275 				    PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
3276 
3277 	disable_mclk_switching_for_display = ((1 < hwmgr->display_config->num_display) &&
3278 						!hwmgr->display_config->multi_monitor_in_sync) ||
3279 						smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time);
3280 
3281 	disable_mclk_switching = disable_mclk_switching_for_frame_lock ||
3282 					 disable_mclk_switching_for_display;
3283 
3284 	if (hwmgr->display_config->num_display == 0) {
3285 		if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM)
3286 			data->mclk_ignore_signal = true;
3287 		else
3288 			disable_mclk_switching = false;
3289 	}
3290 
3291 	sclk = smu7_ps->performance_levels[0].engine_clock;
3292 	mclk = smu7_ps->performance_levels[0].memory_clock;
3293 
3294 	if (disable_mclk_switching &&
3295 	    (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
3296 	    hwmgr->chip_id <= CHIP_VEGAM)))
3297 		mclk = smu7_ps->performance_levels
3298 		[smu7_ps->performance_level_count - 1].memory_clock;
3299 
3300 	if (sclk < minimum_clocks.engineClock)
3301 		sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
3302 				max_limits->sclk : minimum_clocks.engineClock;
3303 
3304 	if (mclk < minimum_clocks.memoryClock)
3305 		mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
3306 				max_limits->mclk : minimum_clocks.memoryClock;
3307 
3308 	smu7_ps->performance_levels[0].engine_clock = sclk;
3309 	smu7_ps->performance_levels[0].memory_clock = mclk;
3310 
3311 	smu7_ps->performance_levels[1].engine_clock =
3312 		(smu7_ps->performance_levels[1].engine_clock >=
3313 				smu7_ps->performance_levels[0].engine_clock) ?
3314 						smu7_ps->performance_levels[1].engine_clock :
3315 						smu7_ps->performance_levels[0].engine_clock;
3316 
3317 	if (disable_mclk_switching) {
3318 		if (mclk < smu7_ps->performance_levels[1].memory_clock)
3319 			mclk = smu7_ps->performance_levels[1].memory_clock;
3320 
3321 		if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM) {
3322 			if (disable_mclk_switching_for_display) {
3323 				/* Find the lowest MCLK frequency that is within
3324 				 * the tolerable latency defined in DAL
3325 				 */
3326 				latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3327 				for (i = 0; i < data->mclk_latency_table.count; i++) {
3328 					if (data->mclk_latency_table.entries[i].latency <= latency) {
3329 						latency_allowed = true;
3330 
3331 						if ((data->mclk_latency_table.entries[i].frequency >=
3332 								smu7_ps->performance_levels[0].memory_clock) &&
3333 						    (data->mclk_latency_table.entries[i].frequency <=
3334 								smu7_ps->performance_levels[1].memory_clock)) {
3335 							mclk = data->mclk_latency_table.entries[i].frequency;
3336 							break;
3337 						}
3338 					}
3339 				}
3340 				if ((i >= data->mclk_latency_table.count - 1) && !latency_allowed) {
3341 					data->mclk_ignore_signal = true;
3342 				} else {
3343 					data->mclk_ignore_signal = false;
3344 				}
3345 			}
3346 
3347 			if (disable_mclk_switching_for_frame_lock)
3348 				mclk = smu7_ps->performance_levels[1].memory_clock;
3349 		}
3350 
3351 		smu7_ps->performance_levels[0].memory_clock = mclk;
3352 
3353 		if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
3354 		      hwmgr->chip_id <= CHIP_VEGAM))
3355 			smu7_ps->performance_levels[1].memory_clock = mclk;
3356 	} else {
3357 		if (smu7_ps->performance_levels[1].memory_clock <
3358 				smu7_ps->performance_levels[0].memory_clock)
3359 			smu7_ps->performance_levels[1].memory_clock =
3360 					smu7_ps->performance_levels[0].memory_clock;
3361 	}
3362 
3363 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3364 			PHM_PlatformCaps_StablePState)) {
3365 		for (i = 0; i < smu7_ps->performance_level_count; i++) {
3366 			smu7_ps->performance_levels[i].engine_clock = stable_pstate_sclk;
3367 			smu7_ps->performance_levels[i].memory_clock = stable_pstate_mclk;
3368 			smu7_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max;
3369 			smu7_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max;
3370 		}
3371 	}
3372 	return 0;
3373 }
3374 
3375 
3376 static uint32_t smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
3377 {
3378 	struct pp_power_state  *ps;
3379 	struct smu7_power_state  *smu7_ps;
3380 
3381 	if (hwmgr == NULL)
3382 		return -EINVAL;
3383 
3384 	ps = hwmgr->request_ps;
3385 
3386 	if (ps == NULL)
3387 		return -EINVAL;
3388 
3389 	smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
3390 
3391 	if (low)
3392 		return smu7_ps->performance_levels[0].memory_clock;
3393 	else
3394 		return smu7_ps->performance_levels
3395 				[smu7_ps->performance_level_count-1].memory_clock;
3396 }
3397 
3398 static uint32_t smu7_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
3399 {
3400 	struct pp_power_state  *ps;
3401 	struct smu7_power_state  *smu7_ps;
3402 
3403 	if (hwmgr == NULL)
3404 		return -EINVAL;
3405 
3406 	ps = hwmgr->request_ps;
3407 
3408 	if (ps == NULL)
3409 		return -EINVAL;
3410 
3411 	smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
3412 
3413 	if (low)
3414 		return smu7_ps->performance_levels[0].engine_clock;
3415 	else
3416 		return smu7_ps->performance_levels
3417 				[smu7_ps->performance_level_count-1].engine_clock;
3418 }
3419 
3420 static int smu7_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
3421 					struct pp_hw_power_state *hw_ps)
3422 {
3423 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3424 	struct smu7_power_state *ps = (struct smu7_power_state *)hw_ps;
3425 	ATOM_FIRMWARE_INFO_V2_2 *fw_info;
3426 	uint16_t size;
3427 	uint8_t frev, crev;
3428 	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
3429 
3430 	/* First retrieve the Boot clocks and VDDC from the firmware info table.
3431 	 * We assume here that fw_info is unchanged if this call fails.
3432 	 */
3433 	fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)smu_atom_get_data_table(hwmgr->adev, index,
3434 			&size, &frev, &crev);
3435 	if (!fw_info)
3436 		/* During a test, there is no firmware info table. */
3437 		return 0;
3438 
3439 	/* Patch the state. */
3440 	data->vbios_boot_state.sclk_bootup_value =
3441 			le32_to_cpu(fw_info->ulDefaultEngineClock);
3442 	data->vbios_boot_state.mclk_bootup_value =
3443 			le32_to_cpu(fw_info->ulDefaultMemoryClock);
3444 	data->vbios_boot_state.mvdd_bootup_value =
3445 			le16_to_cpu(fw_info->usBootUpMVDDCVoltage);
3446 	data->vbios_boot_state.vddc_bootup_value =
3447 			le16_to_cpu(fw_info->usBootUpVDDCVoltage);
3448 	data->vbios_boot_state.vddci_bootup_value =
3449 			le16_to_cpu(fw_info->usBootUpVDDCIVoltage);
3450 	data->vbios_boot_state.pcie_gen_bootup_value =
3451 			smu7_get_current_pcie_speed(hwmgr);
3452 
3453 	data->vbios_boot_state.pcie_lane_bootup_value =
3454 			(uint16_t)smu7_get_current_pcie_lane_number(hwmgr);
3455 
3456 	/* set boot power state */
3457 	ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value;
3458 	ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value;
3459 	ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value;
3460 	ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value;
3461 
3462 	return 0;
3463 }
3464 
3465 static int smu7_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr)
3466 {
3467 	int result;
3468 	unsigned long ret = 0;
3469 
3470 	if (hwmgr->pp_table_version == PP_TABLE_V0) {
3471 		result = pp_tables_get_num_of_entries(hwmgr, &ret);
3472 		return result ? 0 : ret;
3473 	} else if (hwmgr->pp_table_version == PP_TABLE_V1) {
3474 		result = get_number_of_powerplay_table_entries_v1_0(hwmgr);
3475 		return result;
3476 	}
3477 	return 0;
3478 }
3479 
3480 static int smu7_get_pp_table_entry_callback_func_v1(struct pp_hwmgr *hwmgr,
3481 		void *state, struct pp_power_state *power_state,
3482 		void *pp_table, uint32_t classification_flag)
3483 {
3484 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3485 	struct smu7_power_state  *smu7_power_state =
3486 			(struct smu7_power_state *)(&(power_state->hardware));
3487 	struct smu7_performance_level *performance_level;
3488 	ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state;
3489 	ATOM_Tonga_POWERPLAYTABLE *powerplay_table =
3490 			(ATOM_Tonga_POWERPLAYTABLE *)pp_table;
3491 	PPTable_Generic_SubTable_Header *sclk_dep_table =
3492 			(PPTable_Generic_SubTable_Header *)
3493 			(((unsigned long)powerplay_table) +
3494 				le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
3495 
3496 	ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
3497 			(ATOM_Tonga_MCLK_Dependency_Table *)
3498 			(((unsigned long)powerplay_table) +
3499 				le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
3500 
3501 	/* The following fields are not initialized here: id orderedList allStatesList */
3502 	power_state->classification.ui_label =
3503 			(le16_to_cpu(state_entry->usClassification) &
3504 			ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
3505 			ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
3506 	power_state->classification.flags = classification_flag;
3507 	/* NOTE: There is a classification2 flag in BIOS that is not being used right now */
3508 
3509 	power_state->classification.temporary_state = false;
3510 	power_state->classification.to_be_deleted = false;
3511 
3512 	power_state->validation.disallowOnDC =
3513 			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) &
3514 					ATOM_Tonga_DISALLOW_ON_DC));
3515 
3516 	power_state->pcie.lanes = 0;
3517 
3518 	power_state->display.disableFrameModulation = false;
3519 	power_state->display.limitRefreshrate = false;
3520 	power_state->display.enableVariBright =
3521 			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) &
3522 					ATOM_Tonga_ENABLE_VARIBRIGHT));
3523 
3524 	power_state->validation.supportedPowerLevels = 0;
3525 	power_state->uvd_clocks.VCLK = 0;
3526 	power_state->uvd_clocks.DCLK = 0;
3527 	power_state->temperatures.min = 0;
3528 	power_state->temperatures.max = 0;
3529 
3530 	performance_level = &(smu7_power_state->performance_levels
3531 			[smu7_power_state->performance_level_count++]);
3532 
3533 	PP_ASSERT_WITH_CODE(
3534 			(smu7_power_state->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)),
3535 			"Performance levels exceeds SMC limit!",
3536 			return -EINVAL);
3537 
3538 	PP_ASSERT_WITH_CODE(
3539 			(smu7_power_state->performance_level_count <=
3540 					hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
3541 			"Performance levels exceeds Driver limit!",
3542 			return -EINVAL);
3543 
3544 	/* Performance levels are arranged from low to high. */
3545 	performance_level->memory_clock = mclk_dep_table->entries
3546 			[state_entry->ucMemoryClockIndexLow].ulMclk;
3547 	if (sclk_dep_table->ucRevId == 0)
3548 		performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
3549 			[state_entry->ucEngineClockIndexLow].ulSclk;
3550 	else if (sclk_dep_table->ucRevId == 1)
3551 		performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
3552 			[state_entry->ucEngineClockIndexLow].ulSclk;
3553 	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
3554 			state_entry->ucPCIEGenLow);
3555 	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
3556 			state_entry->ucPCIELaneLow);
3557 
3558 	performance_level = &(smu7_power_state->performance_levels
3559 			[smu7_power_state->performance_level_count++]);
3560 	performance_level->memory_clock = mclk_dep_table->entries
3561 			[state_entry->ucMemoryClockIndexHigh].ulMclk;
3562 
3563 	if (sclk_dep_table->ucRevId == 0)
3564 		performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
3565 			[state_entry->ucEngineClockIndexHigh].ulSclk;
3566 	else if (sclk_dep_table->ucRevId == 1)
3567 		performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
3568 			[state_entry->ucEngineClockIndexHigh].ulSclk;
3569 
3570 	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
3571 			state_entry->ucPCIEGenHigh);
3572 	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
3573 			state_entry->ucPCIELaneHigh);
3574 
3575 	return 0;
3576 }
3577 
3578 static int smu7_get_pp_table_entry_v1(struct pp_hwmgr *hwmgr,
3579 		unsigned long entry_index, struct pp_power_state *state)
3580 {
3581 	int result;
3582 	struct smu7_power_state *ps;
3583 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3584 	struct phm_ppt_v1_information *table_info =
3585 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
3586 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
3587 			table_info->vdd_dep_on_mclk;
3588 
3589 	state->hardware.magic = PHM_VIslands_Magic;
3590 
3591 	ps = (struct smu7_power_state *)(&state->hardware);
3592 
3593 	result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, state,
3594 			smu7_get_pp_table_entry_callback_func_v1);
3595 
3596 	/* This is the earliest time we have all the dependency table and the VBIOS boot state
3597 	 * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state
3598 	 * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state
3599 	 */
3600 	if (dep_mclk_table != NULL && dep_mclk_table->count == 1) {
3601 		if (dep_mclk_table->entries[0].clk !=
3602 				data->vbios_boot_state.mclk_bootup_value)
3603 			pr_debug("Single MCLK entry VDDCI/MCLK dependency table "
3604 					"does not match VBIOS boot MCLK level");
3605 		if (dep_mclk_table->entries[0].vddci !=
3606 				data->vbios_boot_state.vddci_bootup_value)
3607 			pr_debug("Single VDDCI entry VDDCI/MCLK dependency table "
3608 					"does not match VBIOS boot VDDCI level");
3609 	}
3610 
3611 	/* set DC compatible flag if this state supports DC */
3612 	if (!state->validation.disallowOnDC)
3613 		ps->dc_compatible = true;
3614 
3615 	if (state->classification.flags & PP_StateClassificationFlag_ACPI)
3616 		data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen;
3617 
3618 	ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
3619 	ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
3620 
3621 	if (!result) {
3622 		uint32_t i;
3623 
3624 		switch (state->classification.ui_label) {
3625 		case PP_StateUILabel_Performance:
3626 			data->use_pcie_performance_levels = true;
3627 			for (i = 0; i < ps->performance_level_count; i++) {
3628 				if (data->pcie_gen_performance.max <
3629 						ps->performance_levels[i].pcie_gen)
3630 					data->pcie_gen_performance.max =
3631 							ps->performance_levels[i].pcie_gen;
3632 
3633 				if (data->pcie_gen_performance.min >
3634 						ps->performance_levels[i].pcie_gen)
3635 					data->pcie_gen_performance.min =
3636 							ps->performance_levels[i].pcie_gen;
3637 
3638 				if (data->pcie_lane_performance.max <
3639 						ps->performance_levels[i].pcie_lane)
3640 					data->pcie_lane_performance.max =
3641 							ps->performance_levels[i].pcie_lane;
3642 				if (data->pcie_lane_performance.min >
3643 						ps->performance_levels[i].pcie_lane)
3644 					data->pcie_lane_performance.min =
3645 							ps->performance_levels[i].pcie_lane;
3646 			}
3647 			break;
3648 		case PP_StateUILabel_Battery:
3649 			data->use_pcie_power_saving_levels = true;
3650 
3651 			for (i = 0; i < ps->performance_level_count; i++) {
3652 				if (data->pcie_gen_power_saving.max <
3653 						ps->performance_levels[i].pcie_gen)
3654 					data->pcie_gen_power_saving.max =
3655 							ps->performance_levels[i].pcie_gen;
3656 
3657 				if (data->pcie_gen_power_saving.min >
3658 						ps->performance_levels[i].pcie_gen)
3659 					data->pcie_gen_power_saving.min =
3660 							ps->performance_levels[i].pcie_gen;
3661 
3662 				if (data->pcie_lane_power_saving.max <
3663 						ps->performance_levels[i].pcie_lane)
3664 					data->pcie_lane_power_saving.max =
3665 							ps->performance_levels[i].pcie_lane;
3666 
3667 				if (data->pcie_lane_power_saving.min >
3668 						ps->performance_levels[i].pcie_lane)
3669 					data->pcie_lane_power_saving.min =
3670 							ps->performance_levels[i].pcie_lane;
3671 			}
3672 			break;
3673 		default:
3674 			break;
3675 		}
3676 	}
3677 	return 0;
3678 }
3679 
3680 static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr,
3681 					struct pp_hw_power_state *power_state,
3682 					unsigned int index, const void *clock_info)
3683 {
3684 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3685 	struct smu7_power_state  *ps = cast_phw_smu7_power_state(power_state);
3686 	const ATOM_PPLIB_CI_CLOCK_INFO *visland_clk_info = clock_info;
3687 	struct smu7_performance_level *performance_level;
3688 	uint32_t engine_clock, memory_clock;
3689 	uint16_t pcie_gen_from_bios;
3690 
3691 	engine_clock = visland_clk_info->ucEngineClockHigh << 16 | visland_clk_info->usEngineClockLow;
3692 	memory_clock = visland_clk_info->ucMemoryClockHigh << 16 | visland_clk_info->usMemoryClockLow;
3693 
3694 	if (!(data->mc_micro_code_feature & DISABLE_MC_LOADMICROCODE) && memory_clock > data->highest_mclk)
3695 		data->highest_mclk = memory_clock;
3696 
3697 	PP_ASSERT_WITH_CODE(
3698 			(ps->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)),
3699 			"Performance levels exceeds SMC limit!",
3700 			return -EINVAL);
3701 
3702 	PP_ASSERT_WITH_CODE(
3703 			(ps->performance_level_count <
3704 					hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
3705 			"Performance levels exceeds Driver limit, Skip!",
3706 			return 0);
3707 
3708 	performance_level = &(ps->performance_levels
3709 			[ps->performance_level_count++]);
3710 
3711 	/* Performance levels are arranged from low to high. */
3712 	performance_level->memory_clock = memory_clock;
3713 	performance_level->engine_clock = engine_clock;
3714 
3715 	pcie_gen_from_bios = visland_clk_info->ucPCIEGen;
3716 
3717 	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, pcie_gen_from_bios);
3718 	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, visland_clk_info->usPCIELane);
3719 
3720 	return 0;
3721 }
3722 
3723 static int smu7_get_pp_table_entry_v0(struct pp_hwmgr *hwmgr,
3724 		unsigned long entry_index, struct pp_power_state *state)
3725 {
3726 	int result;
3727 	struct smu7_power_state *ps;
3728 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3729 	struct phm_clock_voltage_dependency_table *dep_mclk_table =
3730 			hwmgr->dyn_state.vddci_dependency_on_mclk;
3731 
3732 	memset(&state->hardware, 0x00, sizeof(struct pp_hw_power_state));
3733 
3734 	state->hardware.magic = PHM_VIslands_Magic;
3735 
3736 	ps = (struct smu7_power_state *)(&state->hardware);
3737 
3738 	result = pp_tables_get_entry(hwmgr, entry_index, state,
3739 			smu7_get_pp_table_entry_callback_func_v0);
3740 
3741 	/*
3742 	 * This is the earliest time we have all the dependency table
3743 	 * and the VBIOS boot state as
3744 	 * PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot
3745 	 * state if there is only one VDDCI/MCLK level, check if it's
3746 	 * the same as VBIOS boot state
3747 	 */
3748 	if (dep_mclk_table != NULL && dep_mclk_table->count == 1) {
3749 		if (dep_mclk_table->entries[0].clk !=
3750 				data->vbios_boot_state.mclk_bootup_value)
3751 			pr_debug("Single MCLK entry VDDCI/MCLK dependency table "
3752 					"does not match VBIOS boot MCLK level");
3753 		if (dep_mclk_table->entries[0].v !=
3754 				data->vbios_boot_state.vddci_bootup_value)
3755 			pr_debug("Single VDDCI entry VDDCI/MCLK dependency table "
3756 					"does not match VBIOS boot VDDCI level");
3757 	}
3758 
3759 	/* set DC compatible flag if this state supports DC */
3760 	if (!state->validation.disallowOnDC)
3761 		ps->dc_compatible = true;
3762 
3763 	if (state->classification.flags & PP_StateClassificationFlag_ACPI)
3764 		data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen;
3765 
3766 	ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
3767 	ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
3768 
3769 	if (!result) {
3770 		uint32_t i;
3771 
3772 		switch (state->classification.ui_label) {
3773 		case PP_StateUILabel_Performance:
3774 			data->use_pcie_performance_levels = true;
3775 
3776 			for (i = 0; i < ps->performance_level_count; i++) {
3777 				if (data->pcie_gen_performance.max <
3778 						ps->performance_levels[i].pcie_gen)
3779 					data->pcie_gen_performance.max =
3780 							ps->performance_levels[i].pcie_gen;
3781 
3782 				if (data->pcie_gen_performance.min >
3783 						ps->performance_levels[i].pcie_gen)
3784 					data->pcie_gen_performance.min =
3785 							ps->performance_levels[i].pcie_gen;
3786 
3787 				if (data->pcie_lane_performance.max <
3788 						ps->performance_levels[i].pcie_lane)
3789 					data->pcie_lane_performance.max =
3790 							ps->performance_levels[i].pcie_lane;
3791 
3792 				if (data->pcie_lane_performance.min >
3793 						ps->performance_levels[i].pcie_lane)
3794 					data->pcie_lane_performance.min =
3795 							ps->performance_levels[i].pcie_lane;
3796 			}
3797 			break;
3798 		case PP_StateUILabel_Battery:
3799 			data->use_pcie_power_saving_levels = true;
3800 
3801 			for (i = 0; i < ps->performance_level_count; i++) {
3802 				if (data->pcie_gen_power_saving.max <
3803 						ps->performance_levels[i].pcie_gen)
3804 					data->pcie_gen_power_saving.max =
3805 							ps->performance_levels[i].pcie_gen;
3806 
3807 				if (data->pcie_gen_power_saving.min >
3808 						ps->performance_levels[i].pcie_gen)
3809 					data->pcie_gen_power_saving.min =
3810 							ps->performance_levels[i].pcie_gen;
3811 
3812 				if (data->pcie_lane_power_saving.max <
3813 						ps->performance_levels[i].pcie_lane)
3814 					data->pcie_lane_power_saving.max =
3815 							ps->performance_levels[i].pcie_lane;
3816 
3817 				if (data->pcie_lane_power_saving.min >
3818 						ps->performance_levels[i].pcie_lane)
3819 					data->pcie_lane_power_saving.min =
3820 							ps->performance_levels[i].pcie_lane;
3821 			}
3822 			break;
3823 		default:
3824 			break;
3825 		}
3826 	}
3827 	return 0;
3828 }
3829 
3830 static int smu7_get_pp_table_entry(struct pp_hwmgr *hwmgr,
3831 		unsigned long entry_index, struct pp_power_state *state)
3832 {
3833 	if (hwmgr->pp_table_version == PP_TABLE_V0)
3834 		return smu7_get_pp_table_entry_v0(hwmgr, entry_index, state);
3835 	else if (hwmgr->pp_table_version == PP_TABLE_V1)
3836 		return smu7_get_pp_table_entry_v1(hwmgr, entry_index, state);
3837 
3838 	return 0;
3839 }
3840 
3841 static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, u32 *query)
3842 {
3843 	struct amdgpu_device *adev = hwmgr->adev;
3844 	int i;
3845 	u32 tmp = 0;
3846 
3847 	if (!query)
3848 		return -EINVAL;
3849 
3850 	/*
3851 	 * PPSMC_MSG_GetCurrPkgPwr is not supported on:
3852 	 *  - Hawaii
3853 	 *  - Bonaire
3854 	 *  - Fiji
3855 	 *  - Tonga
3856 	 */
3857 	if ((adev->asic_type != CHIP_HAWAII) &&
3858 	    (adev->asic_type != CHIP_BONAIRE) &&
3859 	    (adev->asic_type != CHIP_FIJI) &&
3860 	    (adev->asic_type != CHIP_TONGA)) {
3861 		smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetCurrPkgPwr, 0, &tmp);
3862 		*query = tmp;
3863 
3864 		if (tmp != 0)
3865 			return 0;
3866 	}
3867 
3868 	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogStart, NULL);
3869 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
3870 							ixSMU_PM_STATUS_95, 0);
3871 
3872 	for (i = 0; i < 10; i++) {
3873 		msleep(500);
3874 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogSample, NULL);
3875 		tmp = cgs_read_ind_register(hwmgr->device,
3876 						CGS_IND_REG__SMC,
3877 						ixSMU_PM_STATUS_95);
3878 		if (tmp != 0)
3879 			break;
3880 	}
3881 	*query = tmp;
3882 
3883 	return 0;
3884 }
3885 
3886 static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx,
3887 			    void *value, int *size)
3888 {
3889 	uint32_t sclk, mclk, activity_percent;
3890 	uint32_t offset, val_vid;
3891 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3892 
3893 	/* size must be at least 4 bytes for all sensors */
3894 	if (*size < 4)
3895 		return -EINVAL;
3896 
3897 	switch (idx) {
3898 	case AMDGPU_PP_SENSOR_GFX_SCLK:
3899 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &sclk);
3900 		*((uint32_t *)value) = sclk;
3901 		*size = 4;
3902 		return 0;
3903 	case AMDGPU_PP_SENSOR_GFX_MCLK:
3904 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &mclk);
3905 		*((uint32_t *)value) = mclk;
3906 		*size = 4;
3907 		return 0;
3908 	case AMDGPU_PP_SENSOR_GPU_LOAD:
3909 	case AMDGPU_PP_SENSOR_MEM_LOAD:
3910 		offset = data->soft_regs_start + smum_get_offsetof(hwmgr,
3911 								SMU_SoftRegisters,
3912 								(idx == AMDGPU_PP_SENSOR_GPU_LOAD) ?
3913 								AverageGraphicsActivity:
3914 								AverageMemoryActivity);
3915 
3916 		activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
3917 		activity_percent += 0x80;
3918 		activity_percent >>= 8;
3919 		*((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
3920 		*size = 4;
3921 		return 0;
3922 	case AMDGPU_PP_SENSOR_GPU_TEMP:
3923 		*((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr);
3924 		*size = 4;
3925 		return 0;
3926 	case AMDGPU_PP_SENSOR_UVD_POWER:
3927 		*((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
3928 		*size = 4;
3929 		return 0;
3930 	case AMDGPU_PP_SENSOR_VCE_POWER:
3931 		*((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
3932 		*size = 4;
3933 		return 0;
3934 	case AMDGPU_PP_SENSOR_GPU_POWER:
3935 		return smu7_get_gpu_power(hwmgr, (uint32_t *)value);
3936 	case AMDGPU_PP_SENSOR_VDDGFX:
3937 		if ((data->vr_config & VRCONF_VDDGFX_MASK) ==
3938 		    (VR_SVI2_PLANE_2 << VRCONF_VDDGFX_SHIFT))
3939 			val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device,
3940 					CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID);
3941 		else
3942 			val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device,
3943 					CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE1_VID);
3944 
3945 		*((uint32_t *)value) = (uint32_t)convert_to_vddc(val_vid);
3946 		return 0;
3947 	default:
3948 		return -EINVAL;
3949 	}
3950 }
3951 
3952 static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
3953 {
3954 	const struct phm_set_power_state_input *states =
3955 			(const struct phm_set_power_state_input *)input;
3956 	const struct smu7_power_state *smu7_ps =
3957 			cast_const_phw_smu7_power_state(states->pnew_state);
3958 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3959 	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
3960 	uint32_t sclk = smu7_ps->performance_levels
3961 			[smu7_ps->performance_level_count - 1].engine_clock;
3962 	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
3963 	uint32_t mclk = smu7_ps->performance_levels
3964 			[smu7_ps->performance_level_count - 1].memory_clock;
3965 	struct PP_Clocks min_clocks = {0};
3966 	uint32_t i;
3967 
3968 	for (i = 0; i < sclk_table->count; i++) {
3969 		if (sclk == sclk_table->dpm_levels[i].value)
3970 			break;
3971 	}
3972 
3973 	if (i >= sclk_table->count) {
3974 		if (sclk > sclk_table->dpm_levels[i-1].value) {
3975 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
3976 			sclk_table->dpm_levels[i-1].value = sclk;
3977 		}
3978 	} else {
3979 	/* TODO: Check SCLK in DAL's minimum clocks
3980 	 * in case DeepSleep divider update is required.
3981 	 */
3982 		if (data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR &&
3983 			(min_clocks.engineClockInSR >= SMU7_MINIMUM_ENGINE_CLOCK ||
3984 				data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK))
3985 			data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
3986 	}
3987 
3988 	for (i = 0; i < mclk_table->count; i++) {
3989 		if (mclk == mclk_table->dpm_levels[i].value)
3990 			break;
3991 	}
3992 
3993 	if (i >= mclk_table->count) {
3994 		if (mclk > mclk_table->dpm_levels[i-1].value) {
3995 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
3996 			mclk_table->dpm_levels[i-1].value = mclk;
3997 		}
3998 	}
3999 
4000 	if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
4001 		data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK;
4002 
4003 	return 0;
4004 }
4005 
4006 static uint16_t smu7_get_maximum_link_speed(struct pp_hwmgr *hwmgr,
4007 		const struct smu7_power_state *smu7_ps)
4008 {
4009 	uint32_t i;
4010 	uint32_t sclk, max_sclk = 0;
4011 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4012 	struct smu7_dpm_table *dpm_table = &data->dpm_table;
4013 
4014 	for (i = 0; i < smu7_ps->performance_level_count; i++) {
4015 		sclk = smu7_ps->performance_levels[i].engine_clock;
4016 		if (max_sclk < sclk)
4017 			max_sclk = sclk;
4018 	}
4019 
4020 	for (i = 0; i < dpm_table->sclk_table.count; i++) {
4021 		if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk)
4022 			return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ?
4023 					dpm_table->pcie_speed_table.dpm_levels
4024 					[dpm_table->pcie_speed_table.count - 1].value :
4025 					dpm_table->pcie_speed_table.dpm_levels[i].value);
4026 	}
4027 
4028 	return 0;
4029 }
4030 
4031 static int smu7_request_link_speed_change_before_state_change(
4032 		struct pp_hwmgr *hwmgr, const void *input)
4033 {
4034 	const struct phm_set_power_state_input *states =
4035 			(const struct phm_set_power_state_input *)input;
4036 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4037 	const struct smu7_power_state *smu7_nps =
4038 			cast_const_phw_smu7_power_state(states->pnew_state);
4039 	const struct smu7_power_state *polaris10_cps =
4040 			cast_const_phw_smu7_power_state(states->pcurrent_state);
4041 
4042 	uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_nps);
4043 	uint16_t current_link_speed;
4044 
4045 	if (data->force_pcie_gen == PP_PCIEGenInvalid)
4046 		current_link_speed = smu7_get_maximum_link_speed(hwmgr, polaris10_cps);
4047 	else
4048 		current_link_speed = data->force_pcie_gen;
4049 
4050 	data->force_pcie_gen = PP_PCIEGenInvalid;
4051 	data->pspp_notify_required = false;
4052 
4053 	if (target_link_speed > current_link_speed) {
4054 		switch (target_link_speed) {
4055 #ifdef CONFIG_ACPI
4056 		case PP_PCIEGen3:
4057 			if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN3, false))
4058 				break;
4059 			data->force_pcie_gen = PP_PCIEGen2;
4060 			if (current_link_speed == PP_PCIEGen2)
4061 				break;
4062 			fallthrough;
4063 		case PP_PCIEGen2:
4064 			if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN2, false))
4065 				break;
4066 			fallthrough;
4067 #endif
4068 		default:
4069 			data->force_pcie_gen = smu7_get_current_pcie_speed(hwmgr);
4070 			break;
4071 		}
4072 	} else {
4073 		if (target_link_speed < current_link_speed)
4074 			data->pspp_notify_required = true;
4075 	}
4076 
4077 	return 0;
4078 }
4079 
4080 static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
4081 {
4082 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4083 
4084 	if (0 == data->need_update_smu7_dpm_table)
4085 		return 0;
4086 
4087 	if ((0 == data->sclk_dpm_key_disabled) &&
4088 		(data->need_update_smu7_dpm_table &
4089 			(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
4090 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
4091 				"Trying to freeze SCLK DPM when DPM is disabled",
4092 				);
4093 		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
4094 				PPSMC_MSG_SCLKDPM_FreezeLevel,
4095 				NULL),
4096 				"Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!",
4097 				return -EINVAL);
4098 	}
4099 
4100 	if ((0 == data->mclk_dpm_key_disabled) &&
4101 		!data->mclk_ignore_signal &&
4102 		(data->need_update_smu7_dpm_table &
4103 		 DPMTABLE_OD_UPDATE_MCLK)) {
4104 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
4105 				"Trying to freeze MCLK DPM when DPM is disabled",
4106 				);
4107 		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
4108 				PPSMC_MSG_MCLKDPM_FreezeLevel,
4109 				NULL),
4110 				"Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!",
4111 				return -EINVAL);
4112 	}
4113 
4114 	return 0;
4115 }
4116 
4117 static int smu7_populate_and_upload_sclk_mclk_dpm_levels(
4118 		struct pp_hwmgr *hwmgr, const void *input)
4119 {
4120 	int result = 0;
4121 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4122 	struct smu7_dpm_table *dpm_table = &data->dpm_table;
4123 	uint32_t count;
4124 	struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
4125 	struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels);
4126 	struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels);
4127 
4128 	if (0 == data->need_update_smu7_dpm_table)
4129 		return 0;
4130 
4131 	if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
4132 		for (count = 0; count < dpm_table->sclk_table.count; count++) {
4133 			dpm_table->sclk_table.dpm_levels[count].enabled = odn_sclk_table->entries[count].enabled;
4134 			dpm_table->sclk_table.dpm_levels[count].value = odn_sclk_table->entries[count].clock;
4135 		}
4136 	}
4137 
4138 	if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
4139 		for (count = 0; count < dpm_table->mclk_table.count; count++) {
4140 			dpm_table->mclk_table.dpm_levels[count].enabled = odn_mclk_table->entries[count].enabled;
4141 			dpm_table->mclk_table.dpm_levels[count].value = odn_mclk_table->entries[count].clock;
4142 		}
4143 	}
4144 
4145 	if (data->need_update_smu7_dpm_table &
4146 			(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) {
4147 		result = smum_populate_all_graphic_levels(hwmgr);
4148 		PP_ASSERT_WITH_CODE((0 == result),
4149 				"Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
4150 				return result);
4151 	}
4152 
4153 	if (data->need_update_smu7_dpm_table &
4154 			(DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
4155 		/*populate MCLK dpm table to SMU7 */
4156 		result = smum_populate_all_memory_levels(hwmgr);
4157 		PP_ASSERT_WITH_CODE((0 == result),
4158 				"Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
4159 				return result);
4160 	}
4161 
4162 	return result;
4163 }
4164 
4165 static int smu7_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
4166 			  struct smu7_single_dpm_table *dpm_table,
4167 			uint32_t low_limit, uint32_t high_limit)
4168 {
4169 	uint32_t i;
4170 
4171 	/* force the trim if mclk_switching is disabled to prevent flicker */
4172 	bool force_trim = (low_limit == high_limit);
4173 	for (i = 0; i < dpm_table->count; i++) {
4174 	/*skip the trim if od is enabled*/
4175 		if ((!hwmgr->od_enabled || force_trim)
4176 			&& (dpm_table->dpm_levels[i].value < low_limit
4177 			|| dpm_table->dpm_levels[i].value > high_limit))
4178 			dpm_table->dpm_levels[i].enabled = false;
4179 		else
4180 			dpm_table->dpm_levels[i].enabled = true;
4181 	}
4182 
4183 	return 0;
4184 }
4185 
4186 static int smu7_trim_dpm_states(struct pp_hwmgr *hwmgr,
4187 		const struct smu7_power_state *smu7_ps)
4188 {
4189 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4190 	uint32_t high_limit_count;
4191 
4192 	PP_ASSERT_WITH_CODE((smu7_ps->performance_level_count >= 1),
4193 			"power state did not have any performance level",
4194 			return -EINVAL);
4195 
4196 	high_limit_count = (1 == smu7_ps->performance_level_count) ? 0 : 1;
4197 
4198 	smu7_trim_single_dpm_states(hwmgr,
4199 			&(data->dpm_table.sclk_table),
4200 			smu7_ps->performance_levels[0].engine_clock,
4201 			smu7_ps->performance_levels[high_limit_count].engine_clock);
4202 
4203 	smu7_trim_single_dpm_states(hwmgr,
4204 			&(data->dpm_table.mclk_table),
4205 			smu7_ps->performance_levels[0].memory_clock,
4206 			smu7_ps->performance_levels[high_limit_count].memory_clock);
4207 
4208 	return 0;
4209 }
4210 
4211 static int smu7_generate_dpm_level_enable_mask(
4212 		struct pp_hwmgr *hwmgr, const void *input)
4213 {
4214 	int result = 0;
4215 	const struct phm_set_power_state_input *states =
4216 			(const struct phm_set_power_state_input *)input;
4217 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4218 	const struct smu7_power_state *smu7_ps =
4219 			cast_const_phw_smu7_power_state(states->pnew_state);
4220 
4221 
4222 	result = smu7_trim_dpm_states(hwmgr, smu7_ps);
4223 	if (result)
4224 		return result;
4225 
4226 	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
4227 			phm_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table);
4228 	data->dpm_level_enable_mask.mclk_dpm_enable_mask =
4229 			phm_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table);
4230 	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
4231 			phm_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table);
4232 
4233 	return 0;
4234 }
4235 
4236 static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
4237 {
4238 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4239 
4240 	if (0 == data->need_update_smu7_dpm_table)
4241 		return 0;
4242 
4243 	if ((0 == data->sclk_dpm_key_disabled) &&
4244 		(data->need_update_smu7_dpm_table &
4245 		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
4246 
4247 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
4248 				"Trying to Unfreeze SCLK DPM when DPM is disabled",
4249 				);
4250 		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
4251 				PPSMC_MSG_SCLKDPM_UnfreezeLevel,
4252 				NULL),
4253 			"Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!",
4254 			return -EINVAL);
4255 	}
4256 
4257 	if ((0 == data->mclk_dpm_key_disabled) &&
4258 		!data->mclk_ignore_signal &&
4259 		(data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
4260 
4261 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
4262 				"Trying to Unfreeze MCLK DPM when DPM is disabled",
4263 				);
4264 		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
4265 				PPSMC_MSG_MCLKDPM_UnfreezeLevel,
4266 				NULL),
4267 		    "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!",
4268 		    return -EINVAL);
4269 	}
4270 
4271 	data->need_update_smu7_dpm_table &= DPMTABLE_OD_UPDATE_VDDC;
4272 
4273 	return 0;
4274 }
4275 
4276 static int smu7_notify_link_speed_change_after_state_change(
4277 		struct pp_hwmgr *hwmgr, const void *input)
4278 {
4279 	const struct phm_set_power_state_input *states =
4280 			(const struct phm_set_power_state_input *)input;
4281 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4282 	const struct smu7_power_state *smu7_ps =
4283 			cast_const_phw_smu7_power_state(states->pnew_state);
4284 	uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_ps);
4285 	uint8_t  request;
4286 
4287 	if (data->pspp_notify_required) {
4288 		if (target_link_speed == PP_PCIEGen3)
4289 			request = PCIE_PERF_REQ_GEN3;
4290 		else if (target_link_speed == PP_PCIEGen2)
4291 			request = PCIE_PERF_REQ_GEN2;
4292 		else
4293 			request = PCIE_PERF_REQ_GEN1;
4294 
4295 		if (request == PCIE_PERF_REQ_GEN1 &&
4296 				smu7_get_current_pcie_speed(hwmgr) > 0)
4297 			return 0;
4298 
4299 #ifdef CONFIG_ACPI
4300 		if (amdgpu_acpi_pcie_performance_request(hwmgr->adev, request, false)) {
4301 			if (PP_PCIEGen2 == target_link_speed)
4302 				pr_info("PSPP request to switch to Gen2 from Gen3 Failed!");
4303 			else
4304 				pr_info("PSPP request to switch to Gen1 from Gen2 Failed!");
4305 		}
4306 #endif
4307 	}
4308 
4309 	return 0;
4310 }
4311 
4312 static int smu7_notify_no_display(struct pp_hwmgr *hwmgr)
4313 {
4314 	return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL) == 0) ?  0 : -EINVAL;
4315 }
4316 
4317 static int smu7_notify_has_display(struct pp_hwmgr *hwmgr)
4318 {
4319 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4320 
4321 	if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) {
4322 		if (hwmgr->chip_id == CHIP_VEGAM)
4323 			smum_send_msg_to_smc_with_parameter(hwmgr,
4324 					(PPSMC_Msg)PPSMC_MSG_SetVBITimeout_VEGAM, data->frame_time_x2,
4325 					NULL);
4326 		else
4327 			smum_send_msg_to_smc_with_parameter(hwmgr,
4328 					(PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2,
4329 					NULL);
4330 		data->last_sent_vbi_timeout = data->frame_time_x2;
4331 	}
4332 
4333 	return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay, NULL) == 0) ?  0 : -EINVAL;
4334 }
4335 
4336 static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr)
4337 {
4338 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4339 	int result = 0;
4340 
4341 	if (data->mclk_ignore_signal)
4342 		result = smu7_notify_no_display(hwmgr);
4343 	else
4344 		result = smu7_notify_has_display(hwmgr);
4345 
4346 	return result;
4347 }
4348 
4349 static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
4350 {
4351 	int tmp_result, result = 0;
4352 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4353 
4354 	tmp_result = smu7_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
4355 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4356 			"Failed to find DPM states clocks in DPM table!",
4357 			result = tmp_result);
4358 
4359 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4360 			PHM_PlatformCaps_PCIEPerformanceRequest)) {
4361 		tmp_result =
4362 			smu7_request_link_speed_change_before_state_change(hwmgr, input);
4363 		PP_ASSERT_WITH_CODE((0 == tmp_result),
4364 				"Failed to request link speed change before state change!",
4365 				result = tmp_result);
4366 	}
4367 
4368 	tmp_result = smu7_freeze_sclk_mclk_dpm(hwmgr);
4369 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4370 			"Failed to freeze SCLK MCLK DPM!", result = tmp_result);
4371 
4372 	tmp_result = smu7_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
4373 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4374 			"Failed to populate and upload SCLK MCLK DPM levels!",
4375 			result = tmp_result);
4376 
4377 	/*
4378 	 * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag.
4379 	 * That effectively disables AVFS feature.
4380 	 */
4381 	if (hwmgr->hardcode_pp_table != NULL)
4382 		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
4383 
4384 	tmp_result = smu7_update_avfs(hwmgr);
4385 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4386 			"Failed to update avfs voltages!",
4387 			result = tmp_result);
4388 
4389 	tmp_result = smu7_generate_dpm_level_enable_mask(hwmgr, input);
4390 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4391 			"Failed to generate DPM level enabled mask!",
4392 			result = tmp_result);
4393 
4394 	tmp_result = smum_update_sclk_threshold(hwmgr);
4395 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4396 			"Failed to update SCLK threshold!",
4397 			result = tmp_result);
4398 
4399 	tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr);
4400 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4401 			"Failed to unfreeze SCLK MCLK DPM!",
4402 			result = tmp_result);
4403 
4404 	tmp_result = smu7_upload_dpm_level_enable_mask(hwmgr);
4405 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4406 			"Failed to upload DPM level enabled mask!",
4407 			result = tmp_result);
4408 
4409 	tmp_result = smu7_notify_smc_display(hwmgr);
4410 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4411 			"Failed to notify smc display settings!",
4412 			result = tmp_result);
4413 
4414 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4415 			PHM_PlatformCaps_PCIEPerformanceRequest)) {
4416 		tmp_result =
4417 			smu7_notify_link_speed_change_after_state_change(hwmgr, input);
4418 		PP_ASSERT_WITH_CODE((0 == tmp_result),
4419 				"Failed to notify link speed change after state change!",
4420 				result = tmp_result);
4421 	}
4422 	data->apply_optimized_settings = false;
4423 	return result;
4424 }
4425 
4426 static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm)
4427 {
4428 	hwmgr->thermal_controller.
4429 	advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm;
4430 
4431 	return smum_send_msg_to_smc_with_parameter(hwmgr,
4432 			PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm,
4433 			NULL);
4434 }
4435 
4436 static int
4437 smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
4438 {
4439 	return 0;
4440 }
4441 
4442 /**
4443  * smu7_program_display_gap - Programs the display gap
4444  *
4445  * @hwmgr:  the address of the powerplay hardware manager.
4446  * Return:   always OK
4447  */
4448 static int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
4449 {
4450 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4451 	uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL);
4452 	uint32_t display_gap2;
4453 	uint32_t pre_vbi_time_in_us;
4454 	uint32_t frame_time_in_us;
4455 	uint32_t ref_clock, refresh_rate;
4456 
4457 	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (hwmgr->display_config->num_display > 0) ? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE);
4458 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap);
4459 
4460 	ref_clock =  amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
4461 	refresh_rate = hwmgr->display_config->vrefresh;
4462 
4463 	if (0 == refresh_rate)
4464 		refresh_rate = 60;
4465 
4466 	frame_time_in_us = 1000000 / refresh_rate;
4467 
4468 	pre_vbi_time_in_us = frame_time_in_us - 200 - hwmgr->display_config->min_vblank_time;
4469 
4470 	data->frame_time_x2 = frame_time_in_us * 2 / 100;
4471 
4472 	if (data->frame_time_x2 < 280) {
4473 		pr_debug("%s: enforce minimal VBITimeout: %d -> 280\n", __func__, data->frame_time_x2);
4474 		data->frame_time_x2 = 280;
4475 	}
4476 
4477 	display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
4478 
4479 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2);
4480 
4481 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4482 			data->soft_regs_start + smum_get_offsetof(hwmgr,
4483 							SMU_SoftRegisters,
4484 							PreVBlankGap), 0x64);
4485 
4486 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4487 			data->soft_regs_start + smum_get_offsetof(hwmgr,
4488 							SMU_SoftRegisters,
4489 							VBlankTimeout),
4490 					(frame_time_in_us - pre_vbi_time_in_us));
4491 
4492 	return 0;
4493 }
4494 
4495 static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
4496 {
4497 	return smu7_program_display_gap(hwmgr);
4498 }
4499 
4500 /**
4501  * smu7_set_max_fan_rpm_output - Set maximum target operating fan output RPM
4502  *
4503  * @hwmgr:  the address of the powerplay hardware manager.
4504  * @us_max_fan_rpm:  max operating fan RPM value.
4505  * Return:   The response that came from the SMC.
4506  */
4507 static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm)
4508 {
4509 	hwmgr->thermal_controller.
4510 	advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm;
4511 
4512 	return smum_send_msg_to_smc_with_parameter(hwmgr,
4513 			PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm,
4514 			NULL);
4515 }
4516 
4517 static const struct amdgpu_irq_src_funcs smu7_irq_funcs = {
4518 	.process = phm_irq_process,
4519 };
4520 
4521 static int smu7_register_irq_handlers(struct pp_hwmgr *hwmgr)
4522 {
4523 	struct amdgpu_irq_src *source =
4524 		kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL);
4525 
4526 	if (!source)
4527 		return -ENOMEM;
4528 
4529 	source->funcs = &smu7_irq_funcs;
4530 
4531 	amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4532 			AMDGPU_IRQ_CLIENTID_LEGACY,
4533 			VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH,
4534 			source);
4535 	amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4536 			AMDGPU_IRQ_CLIENTID_LEGACY,
4537 			VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW,
4538 			source);
4539 
4540 	/* Register CTF(GPIO_19) interrupt */
4541 	amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4542 			AMDGPU_IRQ_CLIENTID_LEGACY,
4543 			VISLANDS30_IV_SRCID_GPIO_19,
4544 			source);
4545 
4546 	return 0;
4547 }
4548 
4549 static bool
4550 smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
4551 {
4552 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4553 	bool is_update_required = false;
4554 
4555 	if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
4556 		is_update_required = true;
4557 
4558 	if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh)
4559 		is_update_required = true;
4560 
4561 	if (hwmgr->chip_id >= CHIP_POLARIS10 &&
4562 	    hwmgr->chip_id <= CHIP_VEGAM &&
4563 	    data->last_sent_vbi_timeout != data->frame_time_x2)
4564 		is_update_required = true;
4565 
4566 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
4567 		if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr &&
4568 			(data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK ||
4569 			hwmgr->display_config->min_core_set_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK))
4570 			is_update_required = true;
4571 	}
4572 	return is_update_required;
4573 }
4574 
4575 static inline bool smu7_are_power_levels_equal(const struct smu7_performance_level *pl1,
4576 							   const struct smu7_performance_level *pl2)
4577 {
4578 	return ((pl1->memory_clock == pl2->memory_clock) &&
4579 		  (pl1->engine_clock == pl2->engine_clock) &&
4580 		  (pl1->pcie_gen == pl2->pcie_gen) &&
4581 		  (pl1->pcie_lane == pl2->pcie_lane));
4582 }
4583 
4584 static int smu7_check_states_equal(struct pp_hwmgr *hwmgr,
4585 		const struct pp_hw_power_state *pstate1,
4586 		const struct pp_hw_power_state *pstate2, bool *equal)
4587 {
4588 	const struct smu7_power_state *psa;
4589 	const struct smu7_power_state *psb;
4590 	int i;
4591 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4592 
4593 	if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
4594 		return -EINVAL;
4595 
4596 	psa = cast_const_phw_smu7_power_state(pstate1);
4597 	psb = cast_const_phw_smu7_power_state(pstate2);
4598 	/* If the two states don't even have the same number of performance levels they cannot be the same state. */
4599 	if (psa->performance_level_count != psb->performance_level_count) {
4600 		*equal = false;
4601 		return 0;
4602 	}
4603 
4604 	for (i = 0; i < psa->performance_level_count; i++) {
4605 		if (!smu7_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
4606 			/* If we have found even one performance level pair that is different the states are different. */
4607 			*equal = false;
4608 			return 0;
4609 		}
4610 	}
4611 
4612 	/* If all performance levels are the same try to use the UVD clocks to break the tie.*/
4613 	*equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk));
4614 	*equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk));
4615 	*equal &= (psa->sclk_threshold == psb->sclk_threshold);
4616 	/* For OD call, set value based on flag */
4617 	*equal &= !(data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK |
4618 							DPMTABLE_OD_UPDATE_MCLK |
4619 							DPMTABLE_OD_UPDATE_VDDC));
4620 
4621 	return 0;
4622 }
4623 
4624 static int smu7_check_mc_firmware(struct pp_hwmgr *hwmgr)
4625 {
4626 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4627 
4628 	uint32_t tmp;
4629 
4630 	/* Read MC indirect register offset 0x9F bits [3:0] to see
4631 	 * if VBIOS has already loaded a full version of MC ucode
4632 	 * or not.
4633 	 */
4634 
4635 	smu7_get_mc_microcode_version(hwmgr);
4636 
4637 	data->need_long_memory_training = false;
4638 
4639 	cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX,
4640 							ixMC_IO_DEBUG_UP_13);
4641 	tmp = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA);
4642 
4643 	if (tmp & (1 << 23)) {
4644 		data->mem_latency_high = MEM_LATENCY_HIGH;
4645 		data->mem_latency_low = MEM_LATENCY_LOW;
4646 		if ((hwmgr->chip_id == CHIP_POLARIS10) ||
4647 		    (hwmgr->chip_id == CHIP_POLARIS11) ||
4648 		    (hwmgr->chip_id == CHIP_POLARIS12))
4649 			smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableFFC, NULL);
4650 	} else {
4651 		data->mem_latency_high = 330;
4652 		data->mem_latency_low = 330;
4653 		if ((hwmgr->chip_id == CHIP_POLARIS10) ||
4654 		    (hwmgr->chip_id == CHIP_POLARIS11) ||
4655 		    (hwmgr->chip_id == CHIP_POLARIS12))
4656 			smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableFFC, NULL);
4657 	}
4658 
4659 	return 0;
4660 }
4661 
4662 static int smu7_read_clock_registers(struct pp_hwmgr *hwmgr)
4663 {
4664 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4665 
4666 	data->clock_registers.vCG_SPLL_FUNC_CNTL         =
4667 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL);
4668 	data->clock_registers.vCG_SPLL_FUNC_CNTL_2       =
4669 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2);
4670 	data->clock_registers.vCG_SPLL_FUNC_CNTL_3       =
4671 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3);
4672 	data->clock_registers.vCG_SPLL_FUNC_CNTL_4       =
4673 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4);
4674 	data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM   =
4675 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM);
4676 	data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 =
4677 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2);
4678 	data->clock_registers.vDLL_CNTL                  =
4679 		cgs_read_register(hwmgr->device, mmDLL_CNTL);
4680 	data->clock_registers.vMCLK_PWRMGT_CNTL          =
4681 		cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL);
4682 	data->clock_registers.vMPLL_AD_FUNC_CNTL         =
4683 		cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL);
4684 	data->clock_registers.vMPLL_DQ_FUNC_CNTL         =
4685 		cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL);
4686 	data->clock_registers.vMPLL_FUNC_CNTL            =
4687 		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL);
4688 	data->clock_registers.vMPLL_FUNC_CNTL_1          =
4689 		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1);
4690 	data->clock_registers.vMPLL_FUNC_CNTL_2          =
4691 		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2);
4692 	data->clock_registers.vMPLL_SS1                  =
4693 		cgs_read_register(hwmgr->device, mmMPLL_SS1);
4694 	data->clock_registers.vMPLL_SS2                  =
4695 		cgs_read_register(hwmgr->device, mmMPLL_SS2);
4696 	return 0;
4697 
4698 }
4699 
4700 /**
4701  * smu7_get_memory_type - Find out if memory is GDDR5.
4702  *
4703  * @hwmgr:  the address of the powerplay hardware manager.
4704  * Return:   always 0
4705  */
4706 static int smu7_get_memory_type(struct pp_hwmgr *hwmgr)
4707 {
4708 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4709 	struct amdgpu_device *adev = hwmgr->adev;
4710 
4711 	data->is_memory_gddr5 = (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5);
4712 
4713 	return 0;
4714 }
4715 
4716 /**
4717  * smu7_enable_acpi_power_management - Enables Dynamic Power Management by SMC
4718  *
4719  * @hwmgr:  the address of the powerplay hardware manager.
4720  * Return:   always 0
4721  */
4722 static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
4723 {
4724 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
4725 			GENERAL_PWRMGT, STATIC_PM_EN, 1);
4726 
4727 	return 0;
4728 }
4729 
4730 /**
4731  * smu7_init_power_gate_state - Initialize PowerGating States for different engines
4732  *
4733  * @hwmgr:  the address of the powerplay hardware manager.
4734  * Return:   always 0
4735  */
4736 static int smu7_init_power_gate_state(struct pp_hwmgr *hwmgr)
4737 {
4738 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4739 
4740 	data->uvd_power_gated = false;
4741 	data->vce_power_gated = false;
4742 
4743 	return 0;
4744 }
4745 
4746 static int smu7_init_sclk_threshold(struct pp_hwmgr *hwmgr)
4747 {
4748 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4749 
4750 	data->low_sclk_interrupt_threshold = 0;
4751 	return 0;
4752 }
4753 
4754 static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr)
4755 {
4756 	int tmp_result, result = 0;
4757 
4758 	smu7_check_mc_firmware(hwmgr);
4759 
4760 	tmp_result = smu7_read_clock_registers(hwmgr);
4761 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4762 			"Failed to read clock registers!", result = tmp_result);
4763 
4764 	tmp_result = smu7_get_memory_type(hwmgr);
4765 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4766 			"Failed to get memory type!", result = tmp_result);
4767 
4768 	tmp_result = smu7_enable_acpi_power_management(hwmgr);
4769 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4770 			"Failed to enable ACPI power management!", result = tmp_result);
4771 
4772 	tmp_result = smu7_init_power_gate_state(hwmgr);
4773 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4774 			"Failed to init power gate state!", result = tmp_result);
4775 
4776 	tmp_result = smu7_get_mc_microcode_version(hwmgr);
4777 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4778 			"Failed to get MC microcode version!", result = tmp_result);
4779 
4780 	tmp_result = smu7_init_sclk_threshold(hwmgr);
4781 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4782 			"Failed to init sclk threshold!", result = tmp_result);
4783 
4784 	return result;
4785 }
4786 
4787 static int smu7_force_clock_level(struct pp_hwmgr *hwmgr,
4788 		enum pp_clock_type type, uint32_t mask)
4789 {
4790 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4791 
4792 	if (mask == 0)
4793 		return -EINVAL;
4794 
4795 	switch (type) {
4796 	case PP_SCLK:
4797 		if (!data->sclk_dpm_key_disabled)
4798 			smum_send_msg_to_smc_with_parameter(hwmgr,
4799 					PPSMC_MSG_SCLKDPM_SetEnabledMask,
4800 					data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask,
4801 					NULL);
4802 		break;
4803 	case PP_MCLK:
4804 		if (!data->mclk_dpm_key_disabled)
4805 			smum_send_msg_to_smc_with_parameter(hwmgr,
4806 					PPSMC_MSG_MCLKDPM_SetEnabledMask,
4807 					data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask,
4808 					NULL);
4809 		break;
4810 	case PP_PCIE:
4811 	{
4812 		uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask;
4813 
4814 		if (!data->pcie_dpm_key_disabled) {
4815 			if (fls(tmp) != ffs(tmp))
4816 				smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_UnForceLevel,
4817 						NULL);
4818 			else
4819 				smum_send_msg_to_smc_with_parameter(hwmgr,
4820 					PPSMC_MSG_PCIeDPM_ForceLevel,
4821 					fls(tmp) - 1,
4822 					NULL);
4823 		}
4824 		break;
4825 	}
4826 	default:
4827 		break;
4828 	}
4829 
4830 	return 0;
4831 }
4832 
4833 static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
4834 		enum pp_clock_type type, char *buf)
4835 {
4836 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4837 	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
4838 	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
4839 	struct smu7_single_dpm_table *pcie_table = &(data->dpm_table.pcie_speed_table);
4840 	struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
4841 	struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels);
4842 	struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels);
4843 	int i, now, size = 0;
4844 	uint32_t clock, pcie_speed;
4845 
4846 	switch (type) {
4847 	case PP_SCLK:
4848 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &clock);
4849 
4850 		for (i = 0; i < sclk_table->count; i++) {
4851 			if (clock > sclk_table->dpm_levels[i].value)
4852 				continue;
4853 			break;
4854 		}
4855 		now = i;
4856 
4857 		for (i = 0; i < sclk_table->count; i++)
4858 			size += sprintf(buf + size, "%d: %uMhz %s\n",
4859 					i, sclk_table->dpm_levels[i].value / 100,
4860 					(i == now) ? "*" : "");
4861 		break;
4862 	case PP_MCLK:
4863 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &clock);
4864 
4865 		for (i = 0; i < mclk_table->count; i++) {
4866 			if (clock > mclk_table->dpm_levels[i].value)
4867 				continue;
4868 			break;
4869 		}
4870 		now = i;
4871 
4872 		for (i = 0; i < mclk_table->count; i++)
4873 			size += sprintf(buf + size, "%d: %uMhz %s\n",
4874 					i, mclk_table->dpm_levels[i].value / 100,
4875 					(i == now) ? "*" : "");
4876 		break;
4877 	case PP_PCIE:
4878 		pcie_speed = smu7_get_current_pcie_speed(hwmgr);
4879 		for (i = 0; i < pcie_table->count; i++) {
4880 			if (pcie_speed != pcie_table->dpm_levels[i].value)
4881 				continue;
4882 			break;
4883 		}
4884 		now = i;
4885 
4886 		for (i = 0; i < pcie_table->count; i++)
4887 			size += sprintf(buf + size, "%d: %s %s\n", i,
4888 					(pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" :
4889 					(pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" :
4890 					(pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "",
4891 					(i == now) ? "*" : "");
4892 		break;
4893 	case OD_SCLK:
4894 		if (hwmgr->od_enabled) {
4895 			size = sprintf(buf, "%s:\n", "OD_SCLK");
4896 			for (i = 0; i < odn_sclk_table->num_of_pl; i++)
4897 				size += sprintf(buf + size, "%d: %10uMHz %10umV\n",
4898 					i, odn_sclk_table->entries[i].clock/100,
4899 					odn_sclk_table->entries[i].vddc);
4900 		}
4901 		break;
4902 	case OD_MCLK:
4903 		if (hwmgr->od_enabled) {
4904 			size = sprintf(buf, "%s:\n", "OD_MCLK");
4905 			for (i = 0; i < odn_mclk_table->num_of_pl; i++)
4906 				size += sprintf(buf + size, "%d: %10uMHz %10umV\n",
4907 					i, odn_mclk_table->entries[i].clock/100,
4908 					odn_mclk_table->entries[i].vddc);
4909 		}
4910 		break;
4911 	case OD_RANGE:
4912 		if (hwmgr->od_enabled) {
4913 			size = sprintf(buf, "%s:\n", "OD_RANGE");
4914 			size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
4915 				data->golden_dpm_table.sclk_table.dpm_levels[0].value/100,
4916 				hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
4917 			size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n",
4918 				data->golden_dpm_table.mclk_table.dpm_levels[0].value/100,
4919 				hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
4920 			size += sprintf(buf + size, "VDDC: %7umV %11umV\n",
4921 				data->odn_dpm_table.min_vddc,
4922 				data->odn_dpm_table.max_vddc);
4923 		}
4924 		break;
4925 	default:
4926 		break;
4927 	}
4928 	return size;
4929 }
4930 
4931 static void smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
4932 {
4933 	switch (mode) {
4934 	case AMD_FAN_CTRL_NONE:
4935 		smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
4936 		break;
4937 	case AMD_FAN_CTRL_MANUAL:
4938 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4939 			PHM_PlatformCaps_MicrocodeFanControl))
4940 			smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
4941 		break;
4942 	case AMD_FAN_CTRL_AUTO:
4943 		if (!smu7_fan_ctrl_set_static_mode(hwmgr, mode))
4944 			smu7_fan_ctrl_start_smc_fan_control(hwmgr);
4945 		break;
4946 	default:
4947 		break;
4948 	}
4949 }
4950 
4951 static uint32_t smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr)
4952 {
4953 	return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL;
4954 }
4955 
4956 static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr)
4957 {
4958 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4959 	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
4960 	struct smu7_single_dpm_table *golden_sclk_table =
4961 			&(data->golden_dpm_table.sclk_table);
4962 	int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
4963 	int golden_value = golden_sclk_table->dpm_levels
4964 			[golden_sclk_table->count - 1].value;
4965 
4966 	value -= golden_value;
4967 	value = DIV_ROUND_UP(value * 100, golden_value);
4968 
4969 	return value;
4970 }
4971 
4972 static int smu7_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
4973 {
4974 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4975 	struct smu7_single_dpm_table *golden_sclk_table =
4976 			&(data->golden_dpm_table.sclk_table);
4977 	struct pp_power_state  *ps;
4978 	struct smu7_power_state  *smu7_ps;
4979 
4980 	if (value > 20)
4981 		value = 20;
4982 
4983 	ps = hwmgr->request_ps;
4984 
4985 	if (ps == NULL)
4986 		return -EINVAL;
4987 
4988 	smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
4989 
4990 	smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].engine_clock =
4991 			golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value *
4992 			value / 100 +
4993 			golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
4994 
4995 	return 0;
4996 }
4997 
4998 static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr)
4999 {
5000 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5001 	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
5002 	struct smu7_single_dpm_table *golden_mclk_table =
5003 			&(data->golden_dpm_table.mclk_table);
5004         int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
5005 	int golden_value = golden_mclk_table->dpm_levels
5006 			[golden_mclk_table->count - 1].value;
5007 
5008 	value -= golden_value;
5009 	value = DIV_ROUND_UP(value * 100, golden_value);
5010 
5011 	return value;
5012 }
5013 
5014 static int smu7_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
5015 {
5016 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5017 	struct smu7_single_dpm_table *golden_mclk_table =
5018 			&(data->golden_dpm_table.mclk_table);
5019 	struct pp_power_state  *ps;
5020 	struct smu7_power_state  *smu7_ps;
5021 
5022 	if (value > 20)
5023 		value = 20;
5024 
5025 	ps = hwmgr->request_ps;
5026 
5027 	if (ps == NULL)
5028 		return -EINVAL;
5029 
5030 	smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
5031 
5032 	smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].memory_clock =
5033 			golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value *
5034 			value / 100 +
5035 			golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
5036 
5037 	return 0;
5038 }
5039 
5040 
5041 static int smu7_get_sclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks)
5042 {
5043 	struct phm_ppt_v1_information *table_info =
5044 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5045 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = NULL;
5046 	struct phm_clock_voltage_dependency_table *sclk_table;
5047 	int i;
5048 
5049 	if (hwmgr->pp_table_version == PP_TABLE_V1) {
5050 		if (table_info == NULL || table_info->vdd_dep_on_sclk == NULL)
5051 			return -EINVAL;
5052 		dep_sclk_table = table_info->vdd_dep_on_sclk;
5053 		for (i = 0; i < dep_sclk_table->count; i++)
5054 			clocks->clock[i] = dep_sclk_table->entries[i].clk * 10;
5055 		clocks->count = dep_sclk_table->count;
5056 	} else if (hwmgr->pp_table_version == PP_TABLE_V0) {
5057 		sclk_table = hwmgr->dyn_state.vddc_dependency_on_sclk;
5058 		for (i = 0; i < sclk_table->count; i++)
5059 			clocks->clock[i] = sclk_table->entries[i].clk * 10;
5060 		clocks->count = sclk_table->count;
5061 	}
5062 
5063 	return 0;
5064 }
5065 
5066 static uint32_t smu7_get_mem_latency(struct pp_hwmgr *hwmgr, uint32_t clk)
5067 {
5068 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5069 
5070 	if (clk >= MEM_FREQ_LOW_LATENCY && clk < MEM_FREQ_HIGH_LATENCY)
5071 		return data->mem_latency_high;
5072 	else if (clk >= MEM_FREQ_HIGH_LATENCY)
5073 		return data->mem_latency_low;
5074 	else
5075 		return MEM_LATENCY_ERR;
5076 }
5077 
5078 static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks)
5079 {
5080 	struct phm_ppt_v1_information *table_info =
5081 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5082 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
5083 	int i;
5084 	struct phm_clock_voltage_dependency_table *mclk_table;
5085 
5086 	if (hwmgr->pp_table_version == PP_TABLE_V1) {
5087 		if (table_info == NULL)
5088 			return -EINVAL;
5089 		dep_mclk_table = table_info->vdd_dep_on_mclk;
5090 		for (i = 0; i < dep_mclk_table->count; i++) {
5091 			clocks->clock[i] = dep_mclk_table->entries[i].clk * 10;
5092 			clocks->latency[i] = smu7_get_mem_latency(hwmgr,
5093 						dep_mclk_table->entries[i].clk);
5094 		}
5095 		clocks->count = dep_mclk_table->count;
5096 	} else if (hwmgr->pp_table_version == PP_TABLE_V0) {
5097 		mclk_table = hwmgr->dyn_state.vddc_dependency_on_mclk;
5098 		for (i = 0; i < mclk_table->count; i++)
5099 			clocks->clock[i] = mclk_table->entries[i].clk * 10;
5100 		clocks->count = mclk_table->count;
5101 	}
5102 	return 0;
5103 }
5104 
5105 static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type,
5106 						struct amd_pp_clocks *clocks)
5107 {
5108 	switch (type) {
5109 	case amd_pp_sys_clock:
5110 		smu7_get_sclks(hwmgr, clocks);
5111 		break;
5112 	case amd_pp_mem_clock:
5113 		smu7_get_mclks(hwmgr, clocks);
5114 		break;
5115 	default:
5116 		return -EINVAL;
5117 	}
5118 
5119 	return 0;
5120 }
5121 
5122 static int smu7_get_sclks_with_latency(struct pp_hwmgr *hwmgr,
5123 				       struct pp_clock_levels_with_latency *clocks)
5124 {
5125 	struct phm_ppt_v1_information *table_info =
5126 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5127 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
5128 			table_info->vdd_dep_on_sclk;
5129 	int i;
5130 
5131 	clocks->num_levels = 0;
5132 	for (i = 0; i < dep_sclk_table->count; i++) {
5133 		if (dep_sclk_table->entries[i].clk) {
5134 			clocks->data[clocks->num_levels].clocks_in_khz =
5135 				dep_sclk_table->entries[i].clk * 10;
5136 			clocks->num_levels++;
5137 		}
5138 	}
5139 
5140 	return 0;
5141 }
5142 
5143 static int smu7_get_mclks_with_latency(struct pp_hwmgr *hwmgr,
5144 				       struct pp_clock_levels_with_latency *clocks)
5145 {
5146 	struct phm_ppt_v1_information *table_info =
5147 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5148 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
5149 			table_info->vdd_dep_on_mclk;
5150 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5151 	int i;
5152 
5153 	clocks->num_levels = 0;
5154 	data->mclk_latency_table.count = 0;
5155 	for (i = 0; i < dep_mclk_table->count; i++) {
5156 		if (dep_mclk_table->entries[i].clk) {
5157 			clocks->data[clocks->num_levels].clocks_in_khz =
5158 					dep_mclk_table->entries[i].clk * 10;
5159 			data->mclk_latency_table.entries[data->mclk_latency_table.count].frequency =
5160 					dep_mclk_table->entries[i].clk;
5161 			clocks->data[clocks->num_levels].latency_in_us =
5162 				data->mclk_latency_table.entries[data->mclk_latency_table.count].latency =
5163 					smu7_get_mem_latency(hwmgr, dep_mclk_table->entries[i].clk);
5164 			clocks->num_levels++;
5165 			data->mclk_latency_table.count++;
5166 		}
5167 	}
5168 
5169 	return 0;
5170 }
5171 
5172 static int smu7_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
5173 					       enum amd_pp_clock_type type,
5174 					       struct pp_clock_levels_with_latency *clocks)
5175 {
5176 	if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
5177 	      hwmgr->chip_id <= CHIP_VEGAM))
5178 		return -EINVAL;
5179 
5180 	switch (type) {
5181 	case amd_pp_sys_clock:
5182 		smu7_get_sclks_with_latency(hwmgr, clocks);
5183 		break;
5184 	case amd_pp_mem_clock:
5185 		smu7_get_mclks_with_latency(hwmgr, clocks);
5186 		break;
5187 	default:
5188 		return -EINVAL;
5189 	}
5190 
5191 	return 0;
5192 }
5193 
5194 static int smu7_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
5195 						 void *clock_range)
5196 {
5197 	struct phm_ppt_v1_information *table_info =
5198 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5199 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
5200 			table_info->vdd_dep_on_mclk;
5201 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
5202 			table_info->vdd_dep_on_sclk;
5203 	struct polaris10_smumgr *smu_data =
5204 			(struct polaris10_smumgr *)(hwmgr->smu_backend);
5205 	SMU74_Discrete_DpmTable  *table = &(smu_data->smc_state_table);
5206 	struct dm_pp_wm_sets_with_clock_ranges *watermarks =
5207 			(struct dm_pp_wm_sets_with_clock_ranges *)clock_range;
5208 	uint32_t i, j, k;
5209 	bool valid_entry;
5210 
5211 	if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
5212 	      hwmgr->chip_id <= CHIP_VEGAM))
5213 		return -EINVAL;
5214 
5215 	for (i = 0; i < dep_mclk_table->count; i++) {
5216 		for (j = 0; j < dep_sclk_table->count; j++) {
5217 			valid_entry = false;
5218 			for (k = 0; k < watermarks->num_wm_sets; k++) {
5219 				if (dep_sclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz &&
5220 				    dep_sclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz &&
5221 				    dep_mclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz &&
5222 				    dep_mclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz) {
5223 					valid_entry = true;
5224 					table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k].wm_set_id;
5225 					break;
5226 				}
5227 			}
5228 			PP_ASSERT_WITH_CODE(valid_entry,
5229 					"Clock is not in range of specified clock range for watermark from DAL!  Using highest water mark set.",
5230 					table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k - 1].wm_set_id);
5231 		}
5232 	}
5233 
5234 	return smu7_copy_bytes_to_smc(hwmgr,
5235 				      smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, DisplayWatermark),
5236 				      (uint8_t *)table->DisplayWatermark,
5237 				      sizeof(uint8_t) * SMU74_MAX_LEVELS_MEMORY * SMU74_MAX_LEVELS_GRAPHICS,
5238 				      SMC_RAM_END);
5239 }
5240 
5241 static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
5242 					uint32_t virtual_addr_low,
5243 					uint32_t virtual_addr_hi,
5244 					uint32_t mc_addr_low,
5245 					uint32_t mc_addr_hi,
5246 					uint32_t size)
5247 {
5248 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5249 
5250 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5251 					data->soft_regs_start +
5252 					smum_get_offsetof(hwmgr,
5253 					SMU_SoftRegisters, DRAM_LOG_ADDR_H),
5254 					mc_addr_hi);
5255 
5256 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5257 					data->soft_regs_start +
5258 					smum_get_offsetof(hwmgr,
5259 					SMU_SoftRegisters, DRAM_LOG_ADDR_L),
5260 					mc_addr_low);
5261 
5262 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5263 					data->soft_regs_start +
5264 					smum_get_offsetof(hwmgr,
5265 					SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H),
5266 					virtual_addr_hi);
5267 
5268 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5269 					data->soft_regs_start +
5270 					smum_get_offsetof(hwmgr,
5271 					SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L),
5272 					virtual_addr_low);
5273 
5274 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5275 					data->soft_regs_start +
5276 					smum_get_offsetof(hwmgr,
5277 					SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE),
5278 					size);
5279 	return 0;
5280 }
5281 
5282 static int smu7_get_max_high_clocks(struct pp_hwmgr *hwmgr,
5283 					struct amd_pp_simple_clock_info *clocks)
5284 {
5285 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5286 	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
5287 	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
5288 
5289 	if (clocks == NULL)
5290 		return -EINVAL;
5291 
5292 	clocks->memory_max_clock = mclk_table->count > 1 ?
5293 				mclk_table->dpm_levels[mclk_table->count-1].value :
5294 				mclk_table->dpm_levels[0].value;
5295 	clocks->engine_max_clock = sclk_table->count > 1 ?
5296 				sclk_table->dpm_levels[sclk_table->count-1].value :
5297 				sclk_table->dpm_levels[0].value;
5298 	return 0;
5299 }
5300 
5301 static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
5302 		struct PP_TemperatureRange *thermal_data)
5303 {
5304 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5305 	struct phm_ppt_v1_information *table_info =
5306 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5307 
5308 	memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange));
5309 
5310 	if (hwmgr->pp_table_version == PP_TABLE_V1)
5311 		thermal_data->max = table_info->cac_dtp_table->usSoftwareShutdownTemp *
5312 			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
5313 	else if (hwmgr->pp_table_version == PP_TABLE_V0)
5314 		thermal_data->max = data->thermal_temp_setting.temperature_shutdown *
5315 			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
5316 
5317 	return 0;
5318 }
5319 
5320 static bool smu7_check_clk_voltage_valid(struct pp_hwmgr *hwmgr,
5321 					enum PP_OD_DPM_TABLE_COMMAND type,
5322 					uint32_t clk,
5323 					uint32_t voltage)
5324 {
5325 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5326 
5327 	if (voltage < data->odn_dpm_table.min_vddc || voltage > data->odn_dpm_table.max_vddc) {
5328 		pr_info("OD voltage is out of range [%d - %d] mV\n",
5329 						data->odn_dpm_table.min_vddc,
5330 						data->odn_dpm_table.max_vddc);
5331 		return false;
5332 	}
5333 
5334 	if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
5335 		if (data->golden_dpm_table.sclk_table.dpm_levels[0].value > clk ||
5336 			hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) {
5337 			pr_info("OD engine clock is out of range [%d - %d] MHz\n",
5338 				data->golden_dpm_table.sclk_table.dpm_levels[0].value/100,
5339 				hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
5340 			return false;
5341 		}
5342 	} else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
5343 		if (data->golden_dpm_table.mclk_table.dpm_levels[0].value > clk ||
5344 			hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) {
5345 			pr_info("OD memory clock is out of range [%d - %d] MHz\n",
5346 				data->golden_dpm_table.mclk_table.dpm_levels[0].value/100,
5347 				hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
5348 			return false;
5349 		}
5350 	} else {
5351 		return false;
5352 	}
5353 
5354 	return true;
5355 }
5356 
5357 static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
5358 					enum PP_OD_DPM_TABLE_COMMAND type,
5359 					long *input, uint32_t size)
5360 {
5361 	uint32_t i;
5362 	struct phm_odn_clock_levels *podn_dpm_table_in_backend = NULL;
5363 	struct smu7_odn_clock_voltage_dependency_table *podn_vdd_dep_in_backend = NULL;
5364 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5365 
5366 	uint32_t input_clk;
5367 	uint32_t input_vol;
5368 	uint32_t input_level;
5369 
5370 	PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
5371 				return -EINVAL);
5372 
5373 	if (!hwmgr->od_enabled) {
5374 		pr_info("OverDrive feature not enabled\n");
5375 		return -EINVAL;
5376 	}
5377 
5378 	if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
5379 		podn_dpm_table_in_backend = &data->odn_dpm_table.odn_core_clock_dpm_levels;
5380 		podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_sclk;
5381 		PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend),
5382 				"Failed to get ODN SCLK and Voltage tables",
5383 				return -EINVAL);
5384 	} else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
5385 		podn_dpm_table_in_backend = &data->odn_dpm_table.odn_memory_clock_dpm_levels;
5386 		podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_mclk;
5387 
5388 		PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend),
5389 			"Failed to get ODN MCLK and Voltage tables",
5390 			return -EINVAL);
5391 	} else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
5392 		smu7_odn_initial_default_setting(hwmgr);
5393 		return 0;
5394 	} else if (PP_OD_COMMIT_DPM_TABLE == type) {
5395 		smu7_check_dpm_table_updated(hwmgr);
5396 		return 0;
5397 	} else {
5398 		return -EINVAL;
5399 	}
5400 
5401 	for (i = 0; i < size; i += 3) {
5402 		if (i + 3 > size || input[i] >= podn_dpm_table_in_backend->num_of_pl) {
5403 			pr_info("invalid clock voltage input \n");
5404 			return 0;
5405 		}
5406 		input_level = input[i];
5407 		input_clk = input[i+1] * 100;
5408 		input_vol = input[i+2];
5409 
5410 		if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) {
5411 			podn_dpm_table_in_backend->entries[input_level].clock = input_clk;
5412 			podn_vdd_dep_in_backend->entries[input_level].clk = input_clk;
5413 			podn_dpm_table_in_backend->entries[input_level].vddc = input_vol;
5414 			podn_vdd_dep_in_backend->entries[input_level].vddc = input_vol;
5415 			podn_vdd_dep_in_backend->entries[input_level].vddgfx = input_vol;
5416 		} else {
5417 			return -EINVAL;
5418 		}
5419 	}
5420 
5421 	return 0;
5422 }
5423 
5424 static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
5425 {
5426 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5427 	uint32_t i, size = 0;
5428 	uint32_t len;
5429 
5430 	static const char *profile_name[7] = {"BOOTUP_DEFAULT",
5431 					"3D_FULL_SCREEN",
5432 					"POWER_SAVING",
5433 					"VIDEO",
5434 					"VR",
5435 					"COMPUTE",
5436 					"CUSTOM"};
5437 
5438 	static const char *title[8] = {"NUM",
5439 			"MODE_NAME",
5440 			"SCLK_UP_HYST",
5441 			"SCLK_DOWN_HYST",
5442 			"SCLK_ACTIVE_LEVEL",
5443 			"MCLK_UP_HYST",
5444 			"MCLK_DOWN_HYST",
5445 			"MCLK_ACTIVE_LEVEL"};
5446 
5447 	if (!buf)
5448 		return -EINVAL;
5449 
5450 	size += sprintf(buf + size, "%s %16s %16s %16s %16s %16s %16s %16s\n",
5451 			title[0], title[1], title[2], title[3],
5452 			title[4], title[5], title[6], title[7]);
5453 
5454 	len = ARRAY_SIZE(smu7_profiling);
5455 
5456 	for (i = 0; i < len; i++) {
5457 		if (i == hwmgr->power_profile_mode) {
5458 			size += sprintf(buf + size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n",
5459 			i, profile_name[i], "*",
5460 			data->current_profile_setting.sclk_up_hyst,
5461 			data->current_profile_setting.sclk_down_hyst,
5462 			data->current_profile_setting.sclk_activity,
5463 			data->current_profile_setting.mclk_up_hyst,
5464 			data->current_profile_setting.mclk_down_hyst,
5465 			data->current_profile_setting.mclk_activity);
5466 			continue;
5467 		}
5468 		if (smu7_profiling[i].bupdate_sclk)
5469 			size += sprintf(buf + size, "%3d %16s: %8d %16d %16d ",
5470 			i, profile_name[i], smu7_profiling[i].sclk_up_hyst,
5471 			smu7_profiling[i].sclk_down_hyst,
5472 			smu7_profiling[i].sclk_activity);
5473 		else
5474 			size += sprintf(buf + size, "%3d %16s: %8s %16s %16s ",
5475 			i, profile_name[i], "-", "-", "-");
5476 
5477 		if (smu7_profiling[i].bupdate_mclk)
5478 			size += sprintf(buf + size, "%16d %16d %16d\n",
5479 			smu7_profiling[i].mclk_up_hyst,
5480 			smu7_profiling[i].mclk_down_hyst,
5481 			smu7_profiling[i].mclk_activity);
5482 		else
5483 			size += sprintf(buf + size, "%16s %16s %16s\n",
5484 			"-", "-", "-");
5485 	}
5486 
5487 	return size;
5488 }
5489 
5490 static void smu7_patch_compute_profile_mode(struct pp_hwmgr *hwmgr,
5491 					enum PP_SMC_POWER_PROFILE requst)
5492 {
5493 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5494 	uint32_t tmp, level;
5495 
5496 	if (requst == PP_SMC_POWER_PROFILE_COMPUTE) {
5497 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
5498 			level = 0;
5499 			tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
5500 			while (tmp >>= 1)
5501 				level++;
5502 			if (level > 0)
5503 				smu7_force_clock_level(hwmgr, PP_SCLK, 3 << (level-1));
5504 		}
5505 	} else if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) {
5506 		smu7_force_clock_level(hwmgr, PP_SCLK, data->dpm_level_enable_mask.sclk_dpm_enable_mask);
5507 	}
5508 }
5509 
5510 static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
5511 {
5512 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5513 	struct profile_mode_setting tmp;
5514 	enum PP_SMC_POWER_PROFILE mode;
5515 
5516 	if (input == NULL)
5517 		return -EINVAL;
5518 
5519 	mode = input[size];
5520 	switch (mode) {
5521 	case PP_SMC_POWER_PROFILE_CUSTOM:
5522 		if (size < 8 && size != 0)
5523 			return -EINVAL;
5524 		/* If only CUSTOM is passed in, use the saved values. Check
5525 		 * that we actually have a CUSTOM profile by ensuring that
5526 		 * the "use sclk" or the "use mclk" bits are set
5527 		 */
5528 		tmp = smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM];
5529 		if (size == 0) {
5530 			if (tmp.bupdate_sclk == 0 && tmp.bupdate_mclk == 0)
5531 				return -EINVAL;
5532 		} else {
5533 			tmp.bupdate_sclk = input[0];
5534 			tmp.sclk_up_hyst = input[1];
5535 			tmp.sclk_down_hyst = input[2];
5536 			tmp.sclk_activity = input[3];
5537 			tmp.bupdate_mclk = input[4];
5538 			tmp.mclk_up_hyst = input[5];
5539 			tmp.mclk_down_hyst = input[6];
5540 			tmp.mclk_activity = input[7];
5541 			smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM] = tmp;
5542 		}
5543 		if (!smum_update_dpm_settings(hwmgr, &tmp)) {
5544 			memcpy(&data->current_profile_setting, &tmp, sizeof(struct profile_mode_setting));
5545 			hwmgr->power_profile_mode = mode;
5546 		}
5547 		break;
5548 	case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
5549 	case PP_SMC_POWER_PROFILE_POWERSAVING:
5550 	case PP_SMC_POWER_PROFILE_VIDEO:
5551 	case PP_SMC_POWER_PROFILE_VR:
5552 	case PP_SMC_POWER_PROFILE_COMPUTE:
5553 		if (mode == hwmgr->power_profile_mode)
5554 			return 0;
5555 
5556 		memcpy(&tmp, &smu7_profiling[mode], sizeof(struct profile_mode_setting));
5557 		if (!smum_update_dpm_settings(hwmgr, &tmp)) {
5558 			if (tmp.bupdate_sclk) {
5559 				data->current_profile_setting.bupdate_sclk = tmp.bupdate_sclk;
5560 				data->current_profile_setting.sclk_up_hyst = tmp.sclk_up_hyst;
5561 				data->current_profile_setting.sclk_down_hyst = tmp.sclk_down_hyst;
5562 				data->current_profile_setting.sclk_activity = tmp.sclk_activity;
5563 			}
5564 			if (tmp.bupdate_mclk) {
5565 				data->current_profile_setting.bupdate_mclk = tmp.bupdate_mclk;
5566 				data->current_profile_setting.mclk_up_hyst = tmp.mclk_up_hyst;
5567 				data->current_profile_setting.mclk_down_hyst = tmp.mclk_down_hyst;
5568 				data->current_profile_setting.mclk_activity = tmp.mclk_activity;
5569 			}
5570 			smu7_patch_compute_profile_mode(hwmgr, mode);
5571 			hwmgr->power_profile_mode = mode;
5572 		}
5573 		break;
5574 	default:
5575 		return -EINVAL;
5576 	}
5577 
5578 	return 0;
5579 }
5580 
5581 static int smu7_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
5582 				PHM_PerformanceLevelDesignation designation, uint32_t index,
5583 				PHM_PerformanceLevel *level)
5584 {
5585 	const struct smu7_power_state *ps;
5586 	uint32_t i;
5587 
5588 	if (level == NULL || hwmgr == NULL || state == NULL)
5589 		return -EINVAL;
5590 
5591 	ps = cast_const_phw_smu7_power_state(state);
5592 
5593 	i = index > ps->performance_level_count - 1 ?
5594 			ps->performance_level_count - 1 : index;
5595 
5596 	level->coreClock = ps->performance_levels[i].engine_clock;
5597 	level->memory_clock = ps->performance_levels[i].memory_clock;
5598 
5599 	return 0;
5600 }
5601 
5602 static int smu7_power_off_asic(struct pp_hwmgr *hwmgr)
5603 {
5604 	int result;
5605 
5606 	result = smu7_disable_dpm_tasks(hwmgr);
5607 	PP_ASSERT_WITH_CODE((0 == result),
5608 			"[disable_dpm_tasks] Failed to disable DPM!",
5609 			);
5610 
5611 	return result;
5612 }
5613 
5614 static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
5615 	.backend_init = &smu7_hwmgr_backend_init,
5616 	.backend_fini = &smu7_hwmgr_backend_fini,
5617 	.asic_setup = &smu7_setup_asic_task,
5618 	.dynamic_state_management_enable = &smu7_enable_dpm_tasks,
5619 	.apply_state_adjust_rules = smu7_apply_state_adjust_rules,
5620 	.force_dpm_level = &smu7_force_dpm_level,
5621 	.power_state_set = smu7_set_power_state_tasks,
5622 	.get_power_state_size = smu7_get_power_state_size,
5623 	.get_mclk = smu7_dpm_get_mclk,
5624 	.get_sclk = smu7_dpm_get_sclk,
5625 	.patch_boot_state = smu7_dpm_patch_boot_state,
5626 	.get_pp_table_entry = smu7_get_pp_table_entry,
5627 	.get_num_of_pp_table_entries = smu7_get_number_of_powerplay_table_entries,
5628 	.powerdown_uvd = smu7_powerdown_uvd,
5629 	.powergate_uvd = smu7_powergate_uvd,
5630 	.powergate_vce = smu7_powergate_vce,
5631 	.disable_clock_power_gating = smu7_disable_clock_power_gating,
5632 	.update_clock_gatings = smu7_update_clock_gatings,
5633 	.notify_smc_display_config_after_ps_adjustment = smu7_notify_smc_display_config_after_ps_adjustment,
5634 	.display_config_changed = smu7_display_configuration_changed_task,
5635 	.set_max_fan_pwm_output = smu7_set_max_fan_pwm_output,
5636 	.set_max_fan_rpm_output = smu7_set_max_fan_rpm_output,
5637 	.stop_thermal_controller = smu7_thermal_stop_thermal_controller,
5638 	.get_fan_speed_info = smu7_fan_ctrl_get_fan_speed_info,
5639 	.get_fan_speed_percent = smu7_fan_ctrl_get_fan_speed_percent,
5640 	.set_fan_speed_percent = smu7_fan_ctrl_set_fan_speed_percent,
5641 	.reset_fan_speed_to_default = smu7_fan_ctrl_reset_fan_speed_to_default,
5642 	.get_fan_speed_rpm = smu7_fan_ctrl_get_fan_speed_rpm,
5643 	.set_fan_speed_rpm = smu7_fan_ctrl_set_fan_speed_rpm,
5644 	.uninitialize_thermal_controller = smu7_thermal_ctrl_uninitialize_thermal_controller,
5645 	.register_irq_handlers = smu7_register_irq_handlers,
5646 	.check_smc_update_required_for_display_configuration = smu7_check_smc_update_required_for_display_configuration,
5647 	.check_states_equal = smu7_check_states_equal,
5648 	.set_fan_control_mode = smu7_set_fan_control_mode,
5649 	.get_fan_control_mode = smu7_get_fan_control_mode,
5650 	.force_clock_level = smu7_force_clock_level,
5651 	.print_clock_levels = smu7_print_clock_levels,
5652 	.powergate_gfx = smu7_powergate_gfx,
5653 	.get_sclk_od = smu7_get_sclk_od,
5654 	.set_sclk_od = smu7_set_sclk_od,
5655 	.get_mclk_od = smu7_get_mclk_od,
5656 	.set_mclk_od = smu7_set_mclk_od,
5657 	.get_clock_by_type = smu7_get_clock_by_type,
5658 	.get_clock_by_type_with_latency = smu7_get_clock_by_type_with_latency,
5659 	.set_watermarks_for_clocks_ranges = smu7_set_watermarks_for_clocks_ranges,
5660 	.read_sensor = smu7_read_sensor,
5661 	.dynamic_state_management_disable = smu7_disable_dpm_tasks,
5662 	.avfs_control = smu7_avfs_control,
5663 	.disable_smc_firmware_ctf = smu7_thermal_disable_alert,
5664 	.start_thermal_controller = smu7_start_thermal_controller,
5665 	.notify_cac_buffer_info = smu7_notify_cac_buffer_info,
5666 	.get_max_high_clocks = smu7_get_max_high_clocks,
5667 	.get_thermal_temperature_range = smu7_get_thermal_temperature_range,
5668 	.odn_edit_dpm_table = smu7_odn_edit_dpm_table,
5669 	.set_power_limit = smu7_set_power_limit,
5670 	.get_power_profile_mode = smu7_get_power_profile_mode,
5671 	.set_power_profile_mode = smu7_set_power_profile_mode,
5672 	.get_performance_level = smu7_get_performance_level,
5673 	.get_asic_baco_capability = smu7_baco_get_capability,
5674 	.get_asic_baco_state = smu7_baco_get_state,
5675 	.set_asic_baco_state = smu7_baco_set_state,
5676 	.power_off_asic = smu7_power_off_asic,
5677 };
5678 
5679 uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
5680 		uint32_t clock_insr)
5681 {
5682 	uint8_t i;
5683 	uint32_t temp;
5684 	uint32_t min = max(clock_insr, (uint32_t)SMU7_MINIMUM_ENGINE_CLOCK);
5685 
5686 	PP_ASSERT_WITH_CODE((clock >= min), "Engine clock can't satisfy stutter requirement!", return 0);
5687 	for (i = SMU7_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
5688 		temp = clock >> i;
5689 
5690 		if (temp >= min || i == 0)
5691 			break;
5692 	}
5693 	return i;
5694 }
5695 
5696 int smu7_init_function_pointers(struct pp_hwmgr *hwmgr)
5697 {
5698 	hwmgr->hwmgr_func = &smu7_hwmgr_funcs;
5699 	if (hwmgr->pp_table_version == PP_TABLE_V0)
5700 		hwmgr->pptable_func = &pptable_funcs;
5701 	else if (hwmgr->pp_table_version == PP_TABLE_V1)
5702 		hwmgr->pptable_func = &pptable_v1_0_funcs;
5703 
5704 	return 0;
5705 }
5706