1 /* $NetBSD: amdgpu_tonga_smumgr.c,v 1.3 2021/12/19 12:21:30 riastradh Exp $ */
2
3 /*
4 * Copyright 2015 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25 #include <sys/cdefs.h>
26 __KERNEL_RCSID(0, "$NetBSD: amdgpu_tonga_smumgr.c,v 1.3 2021/12/19 12:21:30 riastradh Exp $");
27
28 #include "pp_debug.h"
29 #include <linux/types.h>
30 #include <linux/kernel.h>
31 #include <linux/pci.h>
32 #include <linux/slab.h>
33 #include <linux/gfp.h>
34
35 #include "smumgr.h"
36 #include "tonga_smumgr.h"
37 #include "smu_ucode_xfer_vi.h"
38 #include "tonga_ppsmc.h"
39 #include "smu/smu_7_1_2_d.h"
40 #include "smu/smu_7_1_2_sh_mask.h"
41 #include "cgs_common.h"
42 #include "smu7_smumgr.h"
43
44 #include "smu7_dyn_defaults.h"
45
46 #include "smu7_hwmgr.h"
47 #include "hardwaremanager.h"
48 #include "ppatomctrl.h"
49
50 #include "atombios.h"
51
52 #include "pppcielanes.h"
53 #include "pp_endian.h"
54
55 #include "gmc/gmc_8_1_d.h"
56 #include "gmc/gmc_8_1_sh_mask.h"
57
58 #include "bif/bif_5_0_d.h"
59 #include "bif/bif_5_0_sh_mask.h"
60
61 #include "dce/dce_10_0_d.h"
62 #include "dce/dce_10_0_sh_mask.h"
63
64 #define POWERTUNE_DEFAULT_SET_MAX 1
65 #define MC_CG_ARB_FREQ_F1 0x0b
66 #define VDDC_VDDCI_DELTA 200
67
68
69 static const struct tonga_pt_defaults tonga_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
70 /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
71 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
72 */
73 {1, 0xF, 0xFD, 0x19,
74 5, 45, 0, 0xB0000,
75 {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8,
76 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
77 {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203,
78 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4}
79 },
80 };
81
82 /* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */
83 static const uint16_t tonga_clock_stretcher_lookup_table[2][4] = {
84 {600, 1050, 3, 0},
85 {600, 1050, 6, 1}
86 };
87
88 /* [FF, SS] type, [] 4 voltage ranges,
89 * and [Floor Freq, Boundary Freq, VID min , VID max]
90 */
91 static const uint32_t tonga_clock_stretcher_ddt_table[2][4][4] = {
92 { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
93 { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} }
94 };
95
96 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */
97 static const uint8_t tonga_clock_stretch_amount_conversion[2][6] = {
98 {0, 1, 3, 2, 4, 5},
99 {0, 2, 4, 5, 6, 5}
100 };
101
tonga_start_in_protection_mode(struct pp_hwmgr * hwmgr)102 static int tonga_start_in_protection_mode(struct pp_hwmgr *hwmgr)
103 {
104 int result;
105
106 /* Assert reset */
107 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
108 SMC_SYSCON_RESET_CNTL, rst_reg, 1);
109
110 result = smu7_upload_smu_firmware_image(hwmgr);
111 if (result)
112 return result;
113
114 /* Clear status */
115 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
116 ixSMU_STATUS, 0);
117
118 /* Enable clock */
119 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
120 SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
121
122 /* De-assert reset */
123 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
124 SMC_SYSCON_RESET_CNTL, rst_reg, 0);
125
126 /* Set SMU Auto Start */
127 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
128 SMU_INPUT_DATA, AUTO_START, 1);
129
130 /* Clear firmware interrupt enable flag */
131 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
132 ixFIRMWARE_FLAGS, 0);
133
134 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND,
135 RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1);
136
137 /**
138 * Call Test SMU message with 0x20000 offset to trigger SMU start
139 */
140 smu7_send_msg_to_smc_offset(hwmgr);
141
142 /* Wait for done bit to be set */
143 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
144 SMU_STATUS, SMU_DONE, 0);
145
146 /* Check pass/failed indicator */
147 if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
148 CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS)) {
149 pr_err("SMU Firmware start failed\n");
150 return -EINVAL;
151 }
152
153 /* Wait for firmware to initialize */
154 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND,
155 FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
156
157 return 0;
158 }
159
tonga_start_in_non_protection_mode(struct pp_hwmgr * hwmgr)160 static int tonga_start_in_non_protection_mode(struct pp_hwmgr *hwmgr)
161 {
162 int result = 0;
163
164 /* wait for smc boot up */
165 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
166 RCU_UC_EVENTS, boot_seq_done, 0);
167
168 /*Clear firmware interrupt enable flag*/
169 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
170 ixFIRMWARE_FLAGS, 0);
171
172
173 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
174 SMC_SYSCON_RESET_CNTL, rst_reg, 1);
175
176 result = smu7_upload_smu_firmware_image(hwmgr);
177
178 if (result != 0)
179 return result;
180
181 /* Set smc instruct start point at 0x0 */
182 smu7_program_jump_on_start(hwmgr);
183
184
185 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
186 SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
187
188 /*De-assert reset*/
189 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
190 SMC_SYSCON_RESET_CNTL, rst_reg, 0);
191
192 /* Wait for firmware to initialize */
193 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND,
194 FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
195
196 return result;
197 }
198
tonga_start_smu(struct pp_hwmgr * hwmgr)199 static int tonga_start_smu(struct pp_hwmgr *hwmgr)
200 {
201 struct tonga_smumgr *priv = hwmgr->smu_backend;
202 int result;
203
204 /* Only start SMC if SMC RAM is not running */
205 if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) {
206 /*Check if SMU is running in protected mode*/
207 if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
208 SMU_FIRMWARE, SMU_MODE)) {
209 result = tonga_start_in_non_protection_mode(hwmgr);
210 if (result)
211 return result;
212 } else {
213 result = tonga_start_in_protection_mode(hwmgr);
214 if (result)
215 return result;
216 }
217 }
218
219 /* Setup SoftRegsStart here to visit the register UcodeLoadStatus
220 * to check fw loading state
221 */
222 smu7_read_smc_sram_dword(hwmgr,
223 SMU72_FIRMWARE_HEADER_LOCATION +
224 offsetof(SMU72_Firmware_Header, SoftRegisters),
225 &(priv->smu7_data.soft_regs_start), 0x40000);
226
227 result = smu7_request_smu_load_fw(hwmgr);
228
229 return result;
230 }
231
tonga_smu_init(struct pp_hwmgr * hwmgr)232 static int tonga_smu_init(struct pp_hwmgr *hwmgr)
233 {
234 struct tonga_smumgr *tonga_priv = NULL;
235
236 tonga_priv = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL);
237 if (tonga_priv == NULL)
238 return -ENOMEM;
239
240 hwmgr->smu_backend = tonga_priv;
241
242 if (smu7_init(hwmgr)) {
243 kfree(tonga_priv);
244 return -EINVAL;
245 }
246
247 return 0;
248 }
249
250
tonga_get_dependency_volt_by_clk(struct pp_hwmgr * hwmgr,phm_ppt_v1_clock_voltage_dependency_table * allowed_clock_voltage_table,uint32_t clock,SMU_VoltageLevel * voltage,uint32_t * mvdd)251 static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
252 phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table,
253 uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd)
254 {
255 uint32_t i = 0;
256 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
257 struct phm_ppt_v1_information *pptable_info =
258 (struct phm_ppt_v1_information *)(hwmgr->pptable);
259
260 /* clock - voltage dependency table is empty table */
261 if (allowed_clock_voltage_table->count == 0)
262 return -EINVAL;
263
264 for (i = 0; i < allowed_clock_voltage_table->count; i++) {
265 /* find first sclk bigger than request */
266 if (allowed_clock_voltage_table->entries[i].clk >= clock) {
267 voltage->VddGfx = phm_get_voltage_index(
268 pptable_info->vddgfx_lookup_table,
269 allowed_clock_voltage_table->entries[i].vddgfx);
270 voltage->Vddc = phm_get_voltage_index(
271 pptable_info->vddc_lookup_table,
272 allowed_clock_voltage_table->entries[i].vddc);
273
274 if (allowed_clock_voltage_table->entries[i].vddci)
275 voltage->Vddci =
276 phm_get_voltage_id(&data->vddci_voltage_table, allowed_clock_voltage_table->entries[i].vddci);
277 else
278 voltage->Vddci =
279 phm_get_voltage_id(&data->vddci_voltage_table,
280 allowed_clock_voltage_table->entries[i].vddc - VDDC_VDDCI_DELTA);
281
282
283 if (allowed_clock_voltage_table->entries[i].mvdd)
284 *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd;
285
286 voltage->Phases = 1;
287 return 0;
288 }
289 }
290
291 /* sclk is bigger than max sclk in the dependence table */
292 voltage->VddGfx = phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
293 allowed_clock_voltage_table->entries[i-1].vddgfx);
294 voltage->Vddc = phm_get_voltage_index(pptable_info->vddc_lookup_table,
295 allowed_clock_voltage_table->entries[i-1].vddc);
296
297 if (allowed_clock_voltage_table->entries[i-1].vddci)
298 voltage->Vddci = phm_get_voltage_id(&data->vddci_voltage_table,
299 allowed_clock_voltage_table->entries[i-1].vddci);
300
301 if (allowed_clock_voltage_table->entries[i-1].mvdd)
302 *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd;
303
304 return 0;
305 }
306
tonga_populate_smc_vddc_table(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)307 static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr,
308 SMU72_Discrete_DpmTable *table)
309 {
310 unsigned int count;
311 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
312
313 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
314 table->VddcLevelCount = data->vddc_voltage_table.count;
315 for (count = 0; count < table->VddcLevelCount; count++) {
316 table->VddcTable[count] =
317 PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE);
318 }
319 CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount);
320 }
321 return 0;
322 }
323
tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)324 static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr,
325 SMU72_Discrete_DpmTable *table)
326 {
327 unsigned int count;
328 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
329
330 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
331 table->VddGfxLevelCount = data->vddgfx_voltage_table.count;
332 for (count = 0; count < data->vddgfx_voltage_table.count; count++) {
333 table->VddGfxTable[count] =
334 PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE);
335 }
336 CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount);
337 }
338 return 0;
339 }
340
tonga_populate_smc_vdd_ci_table(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)341 static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr,
342 SMU72_Discrete_DpmTable *table)
343 {
344 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
345 uint32_t count;
346
347 table->VddciLevelCount = data->vddci_voltage_table.count;
348 for (count = 0; count < table->VddciLevelCount; count++) {
349 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
350 table->VddciTable[count] =
351 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
352 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
353 table->SmioTable1.Pattern[count].Voltage =
354 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
355 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */
356 table->SmioTable1.Pattern[count].Smio =
357 (uint8_t) count;
358 table->Smio[count] |=
359 data->vddci_voltage_table.entries[count].smio_low;
360 table->VddciTable[count] =
361 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
362 }
363 }
364
365 table->SmioMask1 = data->vddci_voltage_table.mask_low;
366 CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount);
367
368 return 0;
369 }
370
tonga_populate_smc_mvdd_table(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)371 static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
372 SMU72_Discrete_DpmTable *table)
373 {
374 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
375 uint32_t count;
376
377 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
378 table->MvddLevelCount = data->mvdd_voltage_table.count;
379 for (count = 0; count < table->MvddLevelCount; count++) {
380 table->SmioTable2.Pattern[count].Voltage =
381 PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE);
382 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
383 table->SmioTable2.Pattern[count].Smio =
384 (uint8_t) count;
385 table->Smio[count] |=
386 data->mvdd_voltage_table.entries[count].smio_low;
387 }
388 table->SmioMask2 = data->mvdd_voltage_table.mask_low;
389
390 CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
391 }
392
393 return 0;
394 }
395
tonga_populate_cac_tables(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)396 static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr,
397 SMU72_Discrete_DpmTable *table)
398 {
399 uint32_t count;
400 uint8_t index = 0;
401 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
402 struct phm_ppt_v1_information *pptable_info =
403 (struct phm_ppt_v1_information *)(hwmgr->pptable);
404 struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table =
405 pptable_info->vddgfx_lookup_table;
406 struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table =
407 pptable_info->vddc_lookup_table;
408
409 /* table is already swapped, so in order to use the value from it
410 * we need to swap it back.
411 */
412 uint32_t vddc_level_count = PP_SMC_TO_HOST_UL(table->VddcLevelCount);
413 uint32_t vddgfx_level_count = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount);
414
415 for (count = 0; count < vddc_level_count; count++) {
416 /* We are populating vddc CAC data to BapmVddc table in split and merged mode */
417 index = phm_get_voltage_index(vddc_lookup_table,
418 data->vddc_voltage_table.entries[count].value);
419 table->BapmVddcVidLoSidd[count] =
420 convert_to_vid(vddc_lookup_table->entries[index].us_cac_low);
421 table->BapmVddcVidHiSidd[count] =
422 convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid);
423 table->BapmVddcVidHiSidd2[count] =
424 convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
425 }
426
427 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
428 /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */
429 for (count = 0; count < vddgfx_level_count; count++) {
430 index = phm_get_voltage_index(vddgfx_lookup_table,
431 convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid));
432 table->BapmVddGfxVidHiSidd2[count] =
433 convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high);
434 }
435 } else {
436 for (count = 0; count < vddc_level_count; count++) {
437 index = phm_get_voltage_index(vddc_lookup_table,
438 data->vddc_voltage_table.entries[count].value);
439 table->BapmVddGfxVidLoSidd[count] =
440 convert_to_vid(vddc_lookup_table->entries[index].us_cac_low);
441 table->BapmVddGfxVidHiSidd[count] =
442 convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid);
443 table->BapmVddGfxVidHiSidd2[count] =
444 convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
445 }
446 }
447
448 return 0;
449 }
450
tonga_populate_smc_voltage_tables(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)451 static int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
452 SMU72_Discrete_DpmTable *table)
453 {
454 int result;
455
456 result = tonga_populate_smc_vddc_table(hwmgr, table);
457 PP_ASSERT_WITH_CODE(!result,
458 "can not populate VDDC voltage table to SMC",
459 return -EINVAL);
460
461 result = tonga_populate_smc_vdd_ci_table(hwmgr, table);
462 PP_ASSERT_WITH_CODE(!result,
463 "can not populate VDDCI voltage table to SMC",
464 return -EINVAL);
465
466 result = tonga_populate_smc_vdd_gfx_table(hwmgr, table);
467 PP_ASSERT_WITH_CODE(!result,
468 "can not populate VDDGFX voltage table to SMC",
469 return -EINVAL);
470
471 result = tonga_populate_smc_mvdd_table(hwmgr, table);
472 PP_ASSERT_WITH_CODE(!result,
473 "can not populate MVDD voltage table to SMC",
474 return -EINVAL);
475
476 result = tonga_populate_cac_tables(hwmgr, table);
477 PP_ASSERT_WITH_CODE(!result,
478 "can not populate CAC voltage tables to SMC",
479 return -EINVAL);
480
481 return 0;
482 }
483
tonga_populate_ulv_level(struct pp_hwmgr * hwmgr,struct SMU72_Discrete_Ulv * state)484 static int tonga_populate_ulv_level(struct pp_hwmgr *hwmgr,
485 struct SMU72_Discrete_Ulv *state)
486 {
487 struct phm_ppt_v1_information *table_info =
488 (struct phm_ppt_v1_information *)(hwmgr->pptable);
489
490 state->CcPwrDynRm = 0;
491 state->CcPwrDynRm1 = 0;
492
493 state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset;
494 state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset *
495 VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
496
497 state->VddcPhase = 1;
498
499 CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
500 CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
501 CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
502
503 return 0;
504 }
505
tonga_populate_ulv_state(struct pp_hwmgr * hwmgr,struct SMU72_Discrete_DpmTable * table)506 static int tonga_populate_ulv_state(struct pp_hwmgr *hwmgr,
507 struct SMU72_Discrete_DpmTable *table)
508 {
509 return tonga_populate_ulv_level(hwmgr, &table->Ulv);
510 }
511
tonga_populate_smc_link_level(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)512 static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table)
513 {
514 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
515 struct smu7_dpm_table *dpm_table = &data->dpm_table;
516 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
517 uint32_t i;
518
519 /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
520 for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
521 table->LinkLevel[i].PcieGenSpeed =
522 (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
523 table->LinkLevel[i].PcieLaneCount =
524 (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1);
525 table->LinkLevel[i].EnabledForActivity =
526 1;
527 table->LinkLevel[i].SPC =
528 (uint8_t)(data->pcie_spc_cap & 0xff);
529 table->LinkLevel[i].DownThreshold =
530 PP_HOST_TO_SMC_UL(5);
531 table->LinkLevel[i].UpThreshold =
532 PP_HOST_TO_SMC_UL(30);
533 }
534
535 smu_data->smc_state_table.LinkLevelCount =
536 (uint8_t)dpm_table->pcie_speed_table.count;
537 data->dpm_level_enable_mask.pcie_dpm_enable_mask =
538 phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
539
540 return 0;
541 }
542
tonga_calculate_sclk_params(struct pp_hwmgr * hwmgr,uint32_t engine_clock,SMU72_Discrete_GraphicsLevel * sclk)543 static int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr,
544 uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk)
545 {
546 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
547 pp_atomctrl_clock_dividers_vi dividers;
548 uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL;
549 uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
550 uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
551 uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
552 uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
553 uint32_t reference_clock;
554 uint32_t reference_divider;
555 uint32_t fbdiv;
556 int result;
557
558 /* get the engine clock dividers for this clock value*/
559 result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs);
560
561 PP_ASSERT_WITH_CODE(result == 0,
562 "Error retrieving Engine Clock dividers from VBIOS.", return result);
563
564 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
565 reference_clock = atomctrl_get_reference_clock(hwmgr);
566
567 reference_divider = 1 + dividers.uc_pll_ref_div;
568
569 /* low 14 bits is fraction and high 12 bits is divider*/
570 fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
571
572 /* SPLL_FUNC_CNTL setup*/
573 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
574 CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div);
575 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
576 CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div);
577
578 /* SPLL_FUNC_CNTL_3 setup*/
579 spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
580 CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv);
581
582 /* set to use fractional accumulation*/
583 spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
584 CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1);
585
586 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
587 PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
588 pp_atomctrl_internal_ss_info ss_info;
589
590 uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div;
591 if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) {
592 /*
593 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
594 * ss_info.speed_spectrum_rate -- in unit of khz
595 */
596 /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
597 uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate);
598
599 /* clkv = 2 * D * fbdiv / NS */
600 uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000);
601
602 cg_spll_spread_spectrum =
603 PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS);
604 cg_spll_spread_spectrum =
605 PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
606 cg_spll_spread_spectrum_2 =
607 PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV);
608 }
609 }
610
611 sclk->SclkFrequency = engine_clock;
612 sclk->CgSpllFuncCntl3 = spll_func_cntl_3;
613 sclk->CgSpllFuncCntl4 = spll_func_cntl_4;
614 sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum;
615 sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2;
616 sclk->SclkDid = (uint8_t)dividers.pll_post_divider;
617
618 return 0;
619 }
620
tonga_populate_single_graphic_level(struct pp_hwmgr * hwmgr,uint32_t engine_clock,SMU72_Discrete_GraphicsLevel * graphic_level)621 static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
622 uint32_t engine_clock,
623 SMU72_Discrete_GraphicsLevel *graphic_level)
624 {
625 int result;
626 uint32_t mvdd;
627 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
628 struct phm_ppt_v1_information *pptable_info =
629 (struct phm_ppt_v1_information *)(hwmgr->pptable);
630 phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
631
632 result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level);
633
634 if (hwmgr->od_enabled)
635 vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk;
636 else
637 vdd_dep_table = pptable_info->vdd_dep_on_sclk;
638
639 /* populate graphics levels*/
640 result = tonga_get_dependency_volt_by_clk(hwmgr,
641 vdd_dep_table, engine_clock,
642 &graphic_level->MinVoltage, &mvdd);
643 PP_ASSERT_WITH_CODE((!result),
644 "can not find VDDC voltage value for VDDC "
645 "engine clock dependency table", return result);
646
647 /* SCLK frequency in units of 10KHz*/
648 graphic_level->SclkFrequency = engine_clock;
649 /* Indicates maximum activity level for this performance level. 50% for now*/
650 graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity;
651
652 graphic_level->CcPwrDynRm = 0;
653 graphic_level->CcPwrDynRm1 = 0;
654 /* this level can be used if activity is high enough.*/
655 graphic_level->EnabledForActivity = 0;
656 /* this level can be used for throttling.*/
657 graphic_level->EnabledForThrottle = 1;
658 graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst;
659 graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst;
660 graphic_level->VoltageDownHyst = 0;
661 graphic_level->PowerThrottle = 0;
662
663 data->display_timing.min_clock_in_sr =
664 hwmgr->display_config->min_core_set_clock_in_sr;
665
666 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
667 PHM_PlatformCaps_SclkDeepSleep))
668 graphic_level->DeepSleepDivId =
669 smu7_get_sleep_divider_id_from_clock(engine_clock,
670 data->display_timing.min_clock_in_sr);
671
672 /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
673 graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
674
675 if (!result) {
676 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/
677 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/
678 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency);
679 CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel);
680 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3);
681 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4);
682 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum);
683 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2);
684 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm);
685 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1);
686 }
687
688 return result;
689 }
690
tonga_populate_all_graphic_levels(struct pp_hwmgr * hwmgr)691 static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
692 {
693 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
694 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
695 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
696 struct smu7_dpm_table *dpm_table = &data->dpm_table;
697 struct phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table;
698 uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count;
699 uint32_t level_array_address = smu_data->smu7_data.dpm_table_start +
700 offsetof(SMU72_Discrete_DpmTable, GraphicsLevel);
701
702 uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) *
703 SMU72_MAX_LEVELS_GRAPHICS;
704
705 SMU72_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel;
706
707 uint32_t i, max_entry;
708 uint8_t highest_pcie_level_enabled = 0;
709 uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0;
710 uint8_t count = 0;
711 int result = 0;
712
713 memset(levels, 0x00, level_array_size);
714
715 for (i = 0; i < dpm_table->sclk_table.count; i++) {
716 result = tonga_populate_single_graphic_level(hwmgr,
717 dpm_table->sclk_table.dpm_levels[i].value,
718 &(smu_data->smc_state_table.GraphicsLevel[i]));
719 if (result != 0)
720 return result;
721
722 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
723 if (i > 1)
724 smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0;
725 }
726
727 /* Only enable level 0 for now. */
728 smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
729
730 /* set highest level watermark to high */
731 if (dpm_table->sclk_table.count > 1)
732 smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark =
733 PPSMC_DISPLAY_WATERMARK_HIGH;
734
735 smu_data->smc_state_table.GraphicsDpmLevelCount =
736 (uint8_t)dpm_table->sclk_table.count;
737 data->dpm_level_enable_mask.sclk_dpm_enable_mask =
738 phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
739
740 if (pcie_table != NULL) {
741 PP_ASSERT_WITH_CODE((pcie_entry_count >= 1),
742 "There must be 1 or more PCIE levels defined in PPTable.",
743 return -EINVAL);
744 max_entry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/
745 for (i = 0; i < dpm_table->sclk_table.count; i++) {
746 smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel =
747 (uint8_t) ((i < max_entry) ? i : max_entry);
748 }
749 } else {
750 if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask)
751 pr_err("Pcie Dpm Enablemask is 0 !");
752
753 while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
754 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
755 (1<<(highest_pcie_level_enabled+1))) != 0)) {
756 highest_pcie_level_enabled++;
757 }
758
759 while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
760 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
761 (1<<lowest_pcie_level_enabled)) == 0)) {
762 lowest_pcie_level_enabled++;
763 }
764
765 while ((count < highest_pcie_level_enabled) &&
766 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
767 (1<<(lowest_pcie_level_enabled+1+count))) == 0)) {
768 count++;
769 }
770 mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ?
771 (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled;
772
773
774 /* set pcieDpmLevel to highest_pcie_level_enabled*/
775 for (i = 2; i < dpm_table->sclk_table.count; i++)
776 smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled;
777
778 /* set pcieDpmLevel to lowest_pcie_level_enabled*/
779 smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled;
780
781 /* set pcieDpmLevel to mid_pcie_level_enabled*/
782 smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled;
783 }
784 /* level count will send to smc once at init smc table and never change*/
785 result = smu7_copy_bytes_to_smc(hwmgr, level_array_address,
786 (uint8_t *)levels, (uint32_t)level_array_size,
787 SMC_RAM_END);
788
789 return result;
790 }
791
tonga_calculate_mclk_params(struct pp_hwmgr * hwmgr,uint32_t memory_clock,SMU72_Discrete_MemoryLevel * mclk,bool strobe_mode,bool dllStateOn)792 static int tonga_calculate_mclk_params(
793 struct pp_hwmgr *hwmgr,
794 uint32_t memory_clock,
795 SMU72_Discrete_MemoryLevel *mclk,
796 bool strobe_mode,
797 bool dllStateOn
798 )
799 {
800 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
801
802 uint32_t dll_cntl = data->clock_registers.vDLL_CNTL;
803 uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
804 uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL;
805 uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL;
806 uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL;
807 uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1;
808 uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2;
809 uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1;
810 uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2;
811
812 pp_atomctrl_memory_clock_param mpll_param;
813 int result;
814
815 result = atomctrl_get_memory_pll_dividers_si(hwmgr,
816 memory_clock, &mpll_param, strobe_mode);
817 PP_ASSERT_WITH_CODE(
818 !result,
819 "Error retrieving Memory Clock Parameters from VBIOS.",
820 return result);
821
822 /* MPLL_FUNC_CNTL setup*/
823 mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL,
824 mpll_param.bw_ctrl);
825
826 /* MPLL_FUNC_CNTL_1 setup*/
827 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
828 MPLL_FUNC_CNTL_1, CLKF,
829 mpll_param.mpll_fb_divider.cl_kf);
830 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
831 MPLL_FUNC_CNTL_1, CLKFRAC,
832 mpll_param.mpll_fb_divider.clk_frac);
833 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
834 MPLL_FUNC_CNTL_1, VCO_MODE,
835 mpll_param.vco_mode);
836
837 /* MPLL_AD_FUNC_CNTL setup*/
838 mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl,
839 MPLL_AD_FUNC_CNTL, YCLK_POST_DIV,
840 mpll_param.mpll_post_divider);
841
842 if (data->is_memory_gddr5) {
843 /* MPLL_DQ_FUNC_CNTL setup*/
844 mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl,
845 MPLL_DQ_FUNC_CNTL, YCLK_SEL,
846 mpll_param.yclk_sel);
847 mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl,
848 MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV,
849 mpll_param.mpll_post_divider);
850 }
851
852 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
853 PHM_PlatformCaps_MemorySpreadSpectrumSupport)) {
854 /*
855 ************************************
856 Fref = Reference Frequency
857 NF = Feedback divider ratio
858 NR = Reference divider ratio
859 Fnom = Nominal VCO output frequency = Fref * NF / NR
860 Fs = Spreading Rate
861 D = Percentage down-spread / 2
862 Fint = Reference input frequency to PFD = Fref / NR
863 NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
864 CLKS = NS - 1 = ISS_STEP_NUM[11:0]
865 NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
866 CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
867 *************************************
868 */
869 pp_atomctrl_internal_ss_info ss_info;
870 uint32_t freq_nom;
871 uint32_t tmp;
872 uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr);
873
874 /* for GDDR5 for all modes and DDR3 */
875 if (1 == mpll_param.qdr)
876 freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider);
877 else
878 freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider);
879
880 /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/
881 tmp = (freq_nom / reference_clock);
882 tmp = tmp * tmp;
883
884 if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) {
885 /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
886 /* ss.Info.speed_spectrum_rate -- in unit of khz */
887 /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
888 /* = reference_clock * 5 / speed_spectrum_rate */
889 uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate;
890
891 /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
892 /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
893 uint32_t clkv =
894 (uint32_t)((((131 * ss_info.speed_spectrum_percentage *
895 ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom);
896
897 mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv);
898 mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks);
899 }
900 }
901
902 /* MCLK_PWRMGT_CNTL setup */
903 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
904 MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed);
905 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
906 MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn);
907 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
908 MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn);
909
910 /* Save the result data to outpupt memory level structure */
911 mclk->MclkFrequency = memory_clock;
912 mclk->MpllFuncCntl = mpll_func_cntl;
913 mclk->MpllFuncCntl_1 = mpll_func_cntl_1;
914 mclk->MpllFuncCntl_2 = mpll_func_cntl_2;
915 mclk->MpllAdFuncCntl = mpll_ad_func_cntl;
916 mclk->MpllDqFuncCntl = mpll_dq_func_cntl;
917 mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl;
918 mclk->DllCntl = dll_cntl;
919 mclk->MpllSs1 = mpll_ss1;
920 mclk->MpllSs2 = mpll_ss2;
921
922 return 0;
923 }
924
tonga_get_mclk_frequency_ratio(uint32_t memory_clock,bool strobe_mode)925 static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock,
926 bool strobe_mode)
927 {
928 uint8_t mc_para_index;
929
930 if (strobe_mode) {
931 if (memory_clock < 12500)
932 mc_para_index = 0x00;
933 else if (memory_clock > 47500)
934 mc_para_index = 0x0f;
935 else
936 mc_para_index = (uint8_t)((memory_clock - 10000) / 2500);
937 } else {
938 if (memory_clock < 65000)
939 mc_para_index = 0x00;
940 else if (memory_clock > 135000)
941 mc_para_index = 0x0f;
942 else
943 mc_para_index = (uint8_t)((memory_clock - 60000) / 5000);
944 }
945
946 return mc_para_index;
947 }
948
tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock)949 static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock)
950 {
951 uint8_t mc_para_index;
952
953 if (memory_clock < 10000)
954 mc_para_index = 0;
955 else if (memory_clock >= 80000)
956 mc_para_index = 0x0f;
957 else
958 mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1);
959
960 return mc_para_index;
961 }
962
963
tonga_populate_single_memory_level(struct pp_hwmgr * hwmgr,uint32_t memory_clock,SMU72_Discrete_MemoryLevel * memory_level)964 static int tonga_populate_single_memory_level(
965 struct pp_hwmgr *hwmgr,
966 uint32_t memory_clock,
967 SMU72_Discrete_MemoryLevel *memory_level
968 )
969 {
970 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
971 struct phm_ppt_v1_information *pptable_info =
972 (struct phm_ppt_v1_information *)(hwmgr->pptable);
973 uint32_t mclk_edc_wr_enable_threshold = 40000;
974 uint32_t mclk_stutter_mode_threshold = 30000;
975 uint32_t mclk_edc_enable_threshold = 40000;
976 uint32_t mclk_strobe_mode_threshold = 40000;
977 phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
978 int result = 0;
979 bool dll_state_on;
980 uint32_t mvdd = 0;
981
982 if (hwmgr->od_enabled)
983 vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk;
984 else
985 vdd_dep_table = pptable_info->vdd_dep_on_mclk;
986
987 if (NULL != vdd_dep_table) {
988 result = tonga_get_dependency_volt_by_clk(hwmgr,
989 vdd_dep_table,
990 memory_clock,
991 &memory_level->MinVoltage, &mvdd);
992 PP_ASSERT_WITH_CODE(
993 !result,
994 "can not find MinVddc voltage value from memory VDDC "
995 "voltage dependency table",
996 return result);
997 }
998
999 if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE)
1000 memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value;
1001 else
1002 memory_level->MinMvdd = mvdd;
1003
1004 memory_level->EnabledForThrottle = 1;
1005 memory_level->EnabledForActivity = 0;
1006 memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
1007 memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
1008 memory_level->VoltageDownHyst = 0;
1009
1010 /* Indicates maximum activity level for this performance level.*/
1011 memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
1012 memory_level->StutterEnable = 0;
1013 memory_level->StrobeEnable = 0;
1014 memory_level->EdcReadEnable = 0;
1015 memory_level->EdcWriteEnable = 0;
1016 memory_level->RttEnable = 0;
1017
1018 /* default set to low watermark. Highest level will be set to high later.*/
1019 memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1020
1021 data->display_timing.num_existing_displays = hwmgr->display_config->num_display;
1022 data->display_timing.vrefresh = hwmgr->display_config->vrefresh;
1023
1024 if ((mclk_stutter_mode_threshold != 0) &&
1025 (memory_clock <= mclk_stutter_mode_threshold) &&
1026 (!data->is_uvd_enabled)
1027 && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1)
1028 && (data->display_timing.num_existing_displays <= 2)
1029 && (data->display_timing.num_existing_displays != 0))
1030 memory_level->StutterEnable = 1;
1031
1032 /* decide strobe mode*/
1033 memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) &&
1034 (memory_clock <= mclk_strobe_mode_threshold);
1035
1036 /* decide EDC mode and memory clock ratio*/
1037 if (data->is_memory_gddr5) {
1038 memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock,
1039 memory_level->StrobeEnable);
1040
1041 if ((mclk_edc_enable_threshold != 0) &&
1042 (memory_clock > mclk_edc_enable_threshold)) {
1043 memory_level->EdcReadEnable = 1;
1044 }
1045
1046 if ((mclk_edc_wr_enable_threshold != 0) &&
1047 (memory_clock > mclk_edc_wr_enable_threshold)) {
1048 memory_level->EdcWriteEnable = 1;
1049 }
1050
1051 if (memory_level->StrobeEnable) {
1052 if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >=
1053 ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) {
1054 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
1055 } else {
1056 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0;
1057 }
1058
1059 } else {
1060 dll_state_on = data->dll_default_on;
1061 }
1062 } else {
1063 memory_level->StrobeRatio =
1064 tonga_get_ddr3_mclk_frequency_ratio(memory_clock);
1065 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
1066 }
1067
1068 result = tonga_calculate_mclk_params(hwmgr,
1069 memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on);
1070
1071 if (!result) {
1072 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd);
1073 /* MCLK frequency in units of 10KHz*/
1074 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency);
1075 /* Indicates maximum activity level for this performance level.*/
1076 CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel);
1077 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl);
1078 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1);
1079 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2);
1080 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl);
1081 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl);
1082 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl);
1083 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl);
1084 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1);
1085 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2);
1086 }
1087
1088 return result;
1089 }
1090
tonga_populate_all_memory_levels(struct pp_hwmgr * hwmgr)1091 int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1092 {
1093 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1094 struct tonga_smumgr *smu_data =
1095 (struct tonga_smumgr *)(hwmgr->smu_backend);
1096 struct smu7_dpm_table *dpm_table = &data->dpm_table;
1097 int result;
1098
1099 /* populate MCLK dpm table to SMU7 */
1100 uint32_t level_array_address =
1101 smu_data->smu7_data.dpm_table_start +
1102 offsetof(SMU72_Discrete_DpmTable, MemoryLevel);
1103 uint32_t level_array_size =
1104 sizeof(SMU72_Discrete_MemoryLevel) *
1105 SMU72_MAX_LEVELS_MEMORY;
1106 SMU72_Discrete_MemoryLevel *levels =
1107 smu_data->smc_state_table.MemoryLevel;
1108 uint32_t i;
1109
1110 memset(levels, 0x00, level_array_size);
1111
1112 for (i = 0; i < dpm_table->mclk_table.count; i++) {
1113 PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
1114 "can not populate memory level as memory clock is zero",
1115 return -EINVAL);
1116 result = tonga_populate_single_memory_level(
1117 hwmgr,
1118 dpm_table->mclk_table.dpm_levels[i].value,
1119 &(smu_data->smc_state_table.MemoryLevel[i]));
1120 if (result)
1121 return result;
1122 }
1123
1124 /* Only enable level 0 for now.*/
1125 smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
1126
1127 /*
1128 * in order to prevent MC activity from stutter mode to push DPM up.
1129 * the UVD change complements this by putting the MCLK in a higher state
1130 * by default such that we are not effected by up threshold or and MCLK DPM latency.
1131 */
1132 smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F;
1133 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel);
1134
1135 smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count;
1136 data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
1137 /* set highest level watermark to high*/
1138 smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
1139
1140 /* level count will send to smc once at init smc table and never change*/
1141 result = smu7_copy_bytes_to_smc(hwmgr,
1142 level_array_address, (uint8_t *)levels, (uint32_t)level_array_size,
1143 SMC_RAM_END);
1144
1145 return result;
1146 }
1147
tonga_populate_mvdd_value(struct pp_hwmgr * hwmgr,uint32_t mclk,SMIO_Pattern * smio_pattern)1148 static int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr,
1149 uint32_t mclk, SMIO_Pattern *smio_pattern)
1150 {
1151 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1152 struct phm_ppt_v1_information *table_info =
1153 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1154 uint32_t i = 0;
1155
1156 if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
1157 /* find mvdd value which clock is more than request */
1158 for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) {
1159 if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) {
1160 /* Always round to higher voltage. */
1161 smio_pattern->Voltage =
1162 data->mvdd_voltage_table.entries[i].value;
1163 break;
1164 }
1165 }
1166
1167 PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count,
1168 "MVDD Voltage is outside the supported range.",
1169 return -EINVAL);
1170 } else {
1171 return -EINVAL;
1172 }
1173
1174 return 0;
1175 }
1176
1177
tonga_populate_smc_acpi_level(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)1178 static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
1179 SMU72_Discrete_DpmTable *table)
1180 {
1181 int result = 0;
1182 struct tonga_smumgr *smu_data =
1183 (struct tonga_smumgr *)(hwmgr->smu_backend);
1184 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1185 struct pp_atomctrl_clock_dividers_vi dividers;
1186
1187 SMIO_Pattern voltage_level;
1188 uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL;
1189 uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
1190 uint32_t dll_cntl = data->clock_registers.vDLL_CNTL;
1191 uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
1192
1193 /* The ACPI state should not do DPM on DC (or ever).*/
1194 table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
1195
1196 table->ACPILevel.MinVoltage =
1197 smu_data->smc_state_table.GraphicsLevel[0].MinVoltage;
1198
1199 /* assign zero for now*/
1200 table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr);
1201
1202 /* get the engine clock dividers for this clock value*/
1203 result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
1204 table->ACPILevel.SclkFrequency, ÷rs);
1205
1206 PP_ASSERT_WITH_CODE(result == 0,
1207 "Error retrieving Engine Clock dividers from VBIOS.",
1208 return result);
1209
1210 /* divider ID for required SCLK*/
1211 table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
1212 table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1213 table->ACPILevel.DeepSleepDivId = 0;
1214
1215 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
1216 SPLL_PWRON, 0);
1217 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
1218 SPLL_RESET, 1);
1219 spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2,
1220 SCLK_MUX_SEL, 4);
1221
1222 table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
1223 table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
1224 table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
1225 table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
1226 table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
1227 table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
1228 table->ACPILevel.CcPwrDynRm = 0;
1229 table->ACPILevel.CcPwrDynRm1 = 0;
1230
1231
1232 /* For various features to be enabled/disabled while this level is active.*/
1233 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
1234 /* SCLK frequency in units of 10KHz*/
1235 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
1236 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
1237 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
1238 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
1239 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
1240 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
1241 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
1242 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
1243 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
1244
1245 /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
1246 table->MemoryACPILevel.MinVoltage =
1247 smu_data->smc_state_table.MemoryLevel[0].MinVoltage;
1248
1249 /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/
1250
1251 if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level))
1252 table->MemoryACPILevel.MinMvdd =
1253 PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE);
1254 else
1255 table->MemoryACPILevel.MinMvdd = 0;
1256
1257 /* Force reset on DLL*/
1258 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1259 MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1);
1260 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1261 MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1);
1262
1263 /* Disable DLL in ACPIState*/
1264 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1265 MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0);
1266 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1267 MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0);
1268
1269 /* Enable DLL bypass signal*/
1270 dll_cntl = PHM_SET_FIELD(dll_cntl,
1271 DLL_CNTL, MRDCK0_BYPASS, 0);
1272 dll_cntl = PHM_SET_FIELD(dll_cntl,
1273 DLL_CNTL, MRDCK1_BYPASS, 0);
1274
1275 table->MemoryACPILevel.DllCntl =
1276 PP_HOST_TO_SMC_UL(dll_cntl);
1277 table->MemoryACPILevel.MclkPwrmgtCntl =
1278 PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl);
1279 table->MemoryACPILevel.MpllAdFuncCntl =
1280 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL);
1281 table->MemoryACPILevel.MpllDqFuncCntl =
1282 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL);
1283 table->MemoryACPILevel.MpllFuncCntl =
1284 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL);
1285 table->MemoryACPILevel.MpllFuncCntl_1 =
1286 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1);
1287 table->MemoryACPILevel.MpllFuncCntl_2 =
1288 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2);
1289 table->MemoryACPILevel.MpllSs1 =
1290 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1);
1291 table->MemoryACPILevel.MpllSs2 =
1292 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2);
1293
1294 table->MemoryACPILevel.EnabledForThrottle = 0;
1295 table->MemoryACPILevel.EnabledForActivity = 0;
1296 table->MemoryACPILevel.UpHyst = 0;
1297 table->MemoryACPILevel.DownHyst = 100;
1298 table->MemoryACPILevel.VoltageDownHyst = 0;
1299 /* Indicates maximum activity level for this performance level.*/
1300 table->MemoryACPILevel.ActivityLevel =
1301 PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
1302
1303 table->MemoryACPILevel.StutterEnable = 0;
1304 table->MemoryACPILevel.StrobeEnable = 0;
1305 table->MemoryACPILevel.EdcReadEnable = 0;
1306 table->MemoryACPILevel.EdcWriteEnable = 0;
1307 table->MemoryACPILevel.RttEnable = 0;
1308
1309 return result;
1310 }
1311
tonga_populate_smc_uvd_level(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)1312 static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
1313 SMU72_Discrete_DpmTable *table)
1314 {
1315 int result = 0;
1316
1317 uint8_t count;
1318 pp_atomctrl_clock_dividers_vi dividers;
1319 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1320 struct phm_ppt_v1_information *pptable_info =
1321 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1322 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1323 pptable_info->mm_dep_table;
1324
1325 table->UvdLevelCount = (uint8_t) (mm_table->count);
1326 table->UvdBootLevel = 0;
1327
1328 for (count = 0; count < table->UvdLevelCount; count++) {
1329 table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
1330 table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
1331 table->UvdLevel[count].MinVoltage.Vddc =
1332 phm_get_voltage_index(pptable_info->vddc_lookup_table,
1333 mm_table->entries[count].vddc);
1334 table->UvdLevel[count].MinVoltage.VddGfx =
1335 (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ?
1336 phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
1337 mm_table->entries[count].vddgfx) : 0;
1338 table->UvdLevel[count].MinVoltage.Vddci =
1339 phm_get_voltage_id(&data->vddci_voltage_table,
1340 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1341 table->UvdLevel[count].MinVoltage.Phases = 1;
1342
1343 /* retrieve divider value for VBIOS */
1344 result = atomctrl_get_dfs_pll_dividers_vi(
1345 hwmgr,
1346 table->UvdLevel[count].VclkFrequency,
1347 ÷rs);
1348
1349 PP_ASSERT_WITH_CODE((!result),
1350 "can not find divide id for Vclk clock",
1351 return result);
1352
1353 table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
1354
1355 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1356 table->UvdLevel[count].DclkFrequency, ÷rs);
1357 PP_ASSERT_WITH_CODE((!result),
1358 "can not find divide id for Dclk clock",
1359 return result);
1360
1361 table->UvdLevel[count].DclkDivider =
1362 (uint8_t)dividers.pll_post_divider;
1363
1364 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
1365 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
1366 }
1367
1368 return result;
1369
1370 }
1371
tonga_populate_smc_vce_level(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)1372 static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
1373 SMU72_Discrete_DpmTable *table)
1374 {
1375 int result = 0;
1376
1377 uint8_t count;
1378 pp_atomctrl_clock_dividers_vi dividers;
1379 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1380 struct phm_ppt_v1_information *pptable_info =
1381 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1382 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1383 pptable_info->mm_dep_table;
1384
1385 table->VceLevelCount = (uint8_t) (mm_table->count);
1386 table->VceBootLevel = 0;
1387
1388 for (count = 0; count < table->VceLevelCount; count++) {
1389 table->VceLevel[count].Frequency =
1390 mm_table->entries[count].eclk;
1391 table->VceLevel[count].MinVoltage.Vddc =
1392 phm_get_voltage_index(pptable_info->vddc_lookup_table,
1393 mm_table->entries[count].vddc);
1394 table->VceLevel[count].MinVoltage.VddGfx =
1395 (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ?
1396 phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
1397 mm_table->entries[count].vddgfx) : 0;
1398 table->VceLevel[count].MinVoltage.Vddci =
1399 phm_get_voltage_id(&data->vddci_voltage_table,
1400 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1401 table->VceLevel[count].MinVoltage.Phases = 1;
1402
1403 /* retrieve divider value for VBIOS */
1404 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1405 table->VceLevel[count].Frequency, ÷rs);
1406 PP_ASSERT_WITH_CODE((!result),
1407 "can not find divide id for VCE engine clock",
1408 return result);
1409
1410 table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1411
1412 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
1413 }
1414
1415 return result;
1416 }
1417
tonga_populate_smc_acp_level(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)1418 static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
1419 SMU72_Discrete_DpmTable *table)
1420 {
1421 int result = 0;
1422 uint8_t count;
1423 pp_atomctrl_clock_dividers_vi dividers;
1424 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1425 struct phm_ppt_v1_information *pptable_info =
1426 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1427 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1428 pptable_info->mm_dep_table;
1429
1430 table->AcpLevelCount = (uint8_t) (mm_table->count);
1431 table->AcpBootLevel = 0;
1432
1433 for (count = 0; count < table->AcpLevelCount; count++) {
1434 table->AcpLevel[count].Frequency =
1435 pptable_info->mm_dep_table->entries[count].aclk;
1436 table->AcpLevel[count].MinVoltage.Vddc =
1437 phm_get_voltage_index(pptable_info->vddc_lookup_table,
1438 mm_table->entries[count].vddc);
1439 table->AcpLevel[count].MinVoltage.VddGfx =
1440 (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ?
1441 phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
1442 mm_table->entries[count].vddgfx) : 0;
1443 table->AcpLevel[count].MinVoltage.Vddci =
1444 phm_get_voltage_id(&data->vddci_voltage_table,
1445 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1446 table->AcpLevel[count].MinVoltage.Phases = 1;
1447
1448 /* retrieve divider value for VBIOS */
1449 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1450 table->AcpLevel[count].Frequency, ÷rs);
1451 PP_ASSERT_WITH_CODE((!result),
1452 "can not find divide id for engine clock", return result);
1453
1454 table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1455
1456 CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency);
1457 }
1458
1459 return result;
1460 }
1461
tonga_populate_memory_timing_parameters(struct pp_hwmgr * hwmgr,uint32_t engine_clock,uint32_t memory_clock,struct SMU72_Discrete_MCArbDramTimingTableEntry * arb_regs)1462 static int tonga_populate_memory_timing_parameters(
1463 struct pp_hwmgr *hwmgr,
1464 uint32_t engine_clock,
1465 uint32_t memory_clock,
1466 struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs
1467 )
1468 {
1469 uint32_t dramTiming;
1470 uint32_t dramTiming2;
1471 uint32_t burstTime;
1472 int result;
1473
1474 result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
1475 engine_clock, memory_clock);
1476
1477 PP_ASSERT_WITH_CODE(result == 0,
1478 "Error calling VBIOS to set DRAM_TIMING.", return result);
1479
1480 dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
1481 dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
1482 burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
1483
1484 arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming);
1485 arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2);
1486 arb_regs->McArbBurstTime = (uint8_t)burstTime;
1487
1488 return 0;
1489 }
1490
tonga_program_memory_timing_parameters(struct pp_hwmgr * hwmgr)1491 static int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
1492 {
1493 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1494 struct tonga_smumgr *smu_data =
1495 (struct tonga_smumgr *)(hwmgr->smu_backend);
1496 int result = 0;
1497 SMU72_Discrete_MCArbDramTimingTable arb_regs;
1498 uint32_t i, j;
1499
1500 memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable));
1501
1502 for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
1503 for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
1504 result = tonga_populate_memory_timing_parameters
1505 (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value,
1506 data->dpm_table.mclk_table.dpm_levels[j].value,
1507 &arb_regs.entries[i][j]);
1508
1509 if (result)
1510 break;
1511 }
1512 }
1513
1514 if (!result) {
1515 result = smu7_copy_bytes_to_smc(
1516 hwmgr,
1517 smu_data->smu7_data.arb_table_start,
1518 (uint8_t *)&arb_regs,
1519 sizeof(SMU72_Discrete_MCArbDramTimingTable),
1520 SMC_RAM_END
1521 );
1522 }
1523
1524 return result;
1525 }
1526
tonga_populate_smc_boot_level(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)1527 static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
1528 SMU72_Discrete_DpmTable *table)
1529 {
1530 int result = 0;
1531 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1532 struct tonga_smumgr *smu_data =
1533 (struct tonga_smumgr *)(hwmgr->smu_backend);
1534 table->GraphicsBootLevel = 0;
1535 table->MemoryBootLevel = 0;
1536
1537 /* find boot level from dpm table*/
1538 result = phm_find_boot_level(&(data->dpm_table.sclk_table),
1539 data->vbios_boot_state.sclk_bootup_value,
1540 (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel));
1541
1542 if (result != 0) {
1543 smu_data->smc_state_table.GraphicsBootLevel = 0;
1544 pr_err("[powerplay] VBIOS did not find boot engine "
1545 "clock value in dependency table. "
1546 "Using Graphics DPM level 0 !");
1547 result = 0;
1548 }
1549
1550 result = phm_find_boot_level(&(data->dpm_table.mclk_table),
1551 data->vbios_boot_state.mclk_bootup_value,
1552 (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel));
1553
1554 if (result != 0) {
1555 smu_data->smc_state_table.MemoryBootLevel = 0;
1556 pr_err("[powerplay] VBIOS did not find boot "
1557 "engine clock value in dependency table."
1558 "Using Memory DPM level 0 !");
1559 result = 0;
1560 }
1561
1562 table->BootVoltage.Vddc =
1563 phm_get_voltage_id(&(data->vddc_voltage_table),
1564 data->vbios_boot_state.vddc_bootup_value);
1565 table->BootVoltage.VddGfx =
1566 phm_get_voltage_id(&(data->vddgfx_voltage_table),
1567 data->vbios_boot_state.vddgfx_bootup_value);
1568 table->BootVoltage.Vddci =
1569 phm_get_voltage_id(&(data->vddci_voltage_table),
1570 data->vbios_boot_state.vddci_bootup_value);
1571 table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value;
1572
1573 CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
1574
1575 return result;
1576 }
1577
tonga_populate_clock_stretcher_data_table(struct pp_hwmgr * hwmgr)1578 static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
1579 {
1580 uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks,
1581 volt_with_cks, value;
1582 uint16_t clock_freq_u16;
1583 struct tonga_smumgr *smu_data =
1584 (struct tonga_smumgr *)(hwmgr->smu_backend);
1585 uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2,
1586 volt_offset = 0;
1587 struct phm_ppt_v1_information *table_info =
1588 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1589 struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
1590 table_info->vdd_dep_on_sclk;
1591 uint32_t hw_revision, dev_id;
1592 struct amdgpu_device *adev = hwmgr->adev;
1593
1594 stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount;
1595
1596 hw_revision = adev->pdev->revision;
1597 dev_id = adev->pdev->device;
1598
1599 /* Read SMU_Eefuse to read and calculate RO and determine
1600 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1601 */
1602 efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1603 ixSMU_EFUSE_0 + (146 * 4));
1604 efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1605 ixSMU_EFUSE_0 + (148 * 4));
1606 efuse &= 0xFF000000;
1607 efuse = efuse >> 24;
1608 efuse2 &= 0xF;
1609
1610 if (efuse2 == 1)
1611 ro = (2300 - 1350) * efuse / 255 + 1350;
1612 else
1613 ro = (2500 - 1000) * efuse / 255 + 1000;
1614
1615 if (ro >= 1660)
1616 type = 0;
1617 else
1618 type = 1;
1619
1620 /* Populate Stretch amount */
1621 smu_data->smc_state_table.ClockStretcherAmount = stretch_amount;
1622
1623
1624 /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1625 for (i = 0; i < sclk_table->count; i++) {
1626 smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |=
1627 sclk_table->entries[i].cks_enable << i;
1628 if (ASICID_IS_TONGA_P(dev_id, hw_revision)) {
1629 volt_without_cks = (uint32_t)((7732 + 60 - ro - 20838 *
1630 (sclk_table->entries[i].clk/100) / 10000) * 1000 /
1631 (8730 - (5301 * (sclk_table->entries[i].clk/100) / 1000)));
1632 volt_with_cks = (uint32_t)((5250 + 51 - ro - 2404 *
1633 (sclk_table->entries[i].clk/100) / 100000) * 1000 /
1634 (6146 - (3193 * (sclk_table->entries[i].clk/100) / 1000)));
1635 } else {
1636 volt_without_cks = (uint32_t)((14041 *
1637 (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 /
1638 (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000)));
1639 volt_with_cks = (uint32_t)((13946 *
1640 (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 /
1641 (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000)));
1642 }
1643 if (volt_without_cks >= volt_with_cks)
1644 volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
1645 sclk_table->entries[i].cks_voffset) * 100 / 625) + 1);
1646 smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
1647 }
1648
1649 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1650 STRETCH_ENABLE, 0x0);
1651 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1652 masterReset, 0x1);
1653 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1654 staticEnable, 0x1);
1655 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1656 masterReset, 0x0);
1657
1658 /* Populate CKS Lookup Table */
1659 if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
1660 stretch_amount2 = 0;
1661 else if (stretch_amount == 3 || stretch_amount == 4)
1662 stretch_amount2 = 1;
1663 else {
1664 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1665 PHM_PlatformCaps_ClockStretcher);
1666 PP_ASSERT_WITH_CODE(false,
1667 "Stretch Amount in PPTable not supported",
1668 return -EINVAL);
1669 }
1670
1671 value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1672 ixPWR_CKS_CNTL);
1673 value &= 0xFFC2FF87;
1674 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq =
1675 tonga_clock_stretcher_lookup_table[stretch_amount2][0];
1676 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq =
1677 tonga_clock_stretcher_lookup_table[stretch_amount2][1];
1678 clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table.
1679 GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1].
1680 SclkFrequency) / 100);
1681 if (tonga_clock_stretcher_lookup_table[stretch_amount2][0] <
1682 clock_freq_u16 &&
1683 tonga_clock_stretcher_lookup_table[stretch_amount2][1] >
1684 clock_freq_u16) {
1685 /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
1686 value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 16;
1687 /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
1688 value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][2]) << 18;
1689 /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
1690 value |= (tonga_clock_stretch_amount_conversion
1691 [tonga_clock_stretcher_lookup_table[stretch_amount2][3]]
1692 [stretch_amount]) << 3;
1693 }
1694 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable.
1695 CKS_LOOKUPTableEntry[0].minFreq);
1696 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable.
1697 CKS_LOOKUPTableEntry[0].maxFreq);
1698 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting =
1699 tonga_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F;
1700 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |=
1701 (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 7;
1702
1703 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1704 ixPWR_CKS_CNTL, value);
1705
1706 /* Populate DDT Lookup Table */
1707 for (i = 0; i < 4; i++) {
1708 /* Assign the minimum and maximum VID stored
1709 * in the last row of Clock Stretcher Voltage Table.
1710 */
1711 smu_data->smc_state_table.ClockStretcherDataTable.
1712 ClockStretcherDataTableEntry[i].minVID =
1713 (uint8_t) tonga_clock_stretcher_ddt_table[type][i][2];
1714 smu_data->smc_state_table.ClockStretcherDataTable.
1715 ClockStretcherDataTableEntry[i].maxVID =
1716 (uint8_t) tonga_clock_stretcher_ddt_table[type][i][3];
1717 /* Loop through each SCLK and check the frequency
1718 * to see if it lies within the frequency for clock stretcher.
1719 */
1720 for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) {
1721 cks_setting = 0;
1722 clock_freq = PP_SMC_TO_HOST_UL(
1723 smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency);
1724 /* Check the allowed frequency against the sclk level[j].
1725 * Sclk's endianness has already been converted,
1726 * and it's in 10Khz unit,
1727 * as opposed to Data table, which is in Mhz unit.
1728 */
1729 if (clock_freq >= tonga_clock_stretcher_ddt_table[type][i][0] * 100) {
1730 cks_setting |= 0x2;
1731 if (clock_freq < tonga_clock_stretcher_ddt_table[type][i][1] * 100)
1732 cks_setting |= 0x1;
1733 }
1734 smu_data->smc_state_table.ClockStretcherDataTable.
1735 ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2);
1736 }
1737 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.
1738 ClockStretcherDataTable.
1739 ClockStretcherDataTableEntry[i].setting);
1740 }
1741
1742 value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1743 ixPWR_CKS_CNTL);
1744 value &= 0xFFFFFFFE;
1745 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1746 ixPWR_CKS_CNTL, value);
1747
1748 return 0;
1749 }
1750
tonga_populate_vr_config(struct pp_hwmgr * hwmgr,SMU72_Discrete_DpmTable * table)1751 static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr,
1752 SMU72_Discrete_DpmTable *table)
1753 {
1754 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1755 uint16_t config;
1756
1757 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
1758 /* Splitted mode */
1759 config = VR_SVI2_PLANE_1;
1760 table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
1761
1762 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1763 config = VR_SVI2_PLANE_2;
1764 table->VRConfig |= config;
1765 } else {
1766 pr_err("VDDC and VDDGFX should "
1767 "be both on SVI2 control in splitted mode !\n");
1768 }
1769 } else {
1770 /* Merged mode */
1771 config = VR_MERGED_WITH_VDDC;
1772 table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
1773
1774 /* Set Vddc Voltage Controller */
1775 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1776 config = VR_SVI2_PLANE_1;
1777 table->VRConfig |= config;
1778 } else {
1779 pr_err("VDDC should be on "
1780 "SVI2 control in merged mode !\n");
1781 }
1782 }
1783
1784 /* Set Vddci Voltage Controller */
1785 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
1786 config = VR_SVI2_PLANE_2; /* only in merged mode */
1787 table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
1788 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
1789 config = VR_SMIO_PATTERN_1;
1790 table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
1791 }
1792
1793 /* Set Mvdd Voltage Controller */
1794 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
1795 config = VR_SMIO_PATTERN_2;
1796 table->VRConfig |= (config<<VRCONF_MVDD_SHIFT);
1797 }
1798
1799 return 0;
1800 }
1801
tonga_init_arb_table_index(struct pp_hwmgr * hwmgr)1802 static int tonga_init_arb_table_index(struct pp_hwmgr *hwmgr)
1803 {
1804 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
1805 uint32_t tmp;
1806 int result;
1807
1808 /*
1809 * This is a read-modify-write on the first byte of the ARB table.
1810 * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure
1811 * is the field 'current'.
1812 * This solution is ugly, but we never write the whole table only
1813 * individual fields in it.
1814 * In reality this field should not be in that structure
1815 * but in a soft register.
1816 */
1817 result = smu7_read_smc_sram_dword(hwmgr,
1818 smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END);
1819
1820 if (result != 0)
1821 return result;
1822
1823 tmp &= 0x00FFFFFF;
1824 tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
1825
1826 return smu7_write_smc_sram_dword(hwmgr,
1827 smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END);
1828 }
1829
1830
tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr * hwmgr)1831 static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
1832 {
1833 struct tonga_smumgr *smu_data =
1834 (struct tonga_smumgr *)(hwmgr->smu_backend);
1835 const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults;
1836 SMU72_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table);
1837 struct phm_ppt_v1_information *table_info =
1838 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1839 struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table;
1840 int i, j, k;
1841 const uint16_t *pdef1, *pdef2;
1842
1843 dpm_table->DefaultTdp = PP_HOST_TO_SMC_US(
1844 (uint16_t)(cac_dtp_table->usTDP * 256));
1845 dpm_table->TargetTdp = PP_HOST_TO_SMC_US(
1846 (uint16_t)(cac_dtp_table->usConfigurableTDP * 256));
1847
1848 PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
1849 "Target Operating Temp is out of Range !",
1850 );
1851
1852 dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp);
1853 dpm_table->GpuTjHyst = 8;
1854
1855 dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base;
1856
1857 dpm_table->BAPM_TEMP_GRADIENT =
1858 PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient);
1859 pdef1 = defaults->bapmti_r;
1860 pdef2 = defaults->bapmti_rc;
1861
1862 for (i = 0; i < SMU72_DTE_ITERATIONS; i++) {
1863 for (j = 0; j < SMU72_DTE_SOURCES; j++) {
1864 for (k = 0; k < SMU72_DTE_SINKS; k++) {
1865 dpm_table->BAPMTI_R[i][j][k] =
1866 PP_HOST_TO_SMC_US(*pdef1);
1867 dpm_table->BAPMTI_RC[i][j][k] =
1868 PP_HOST_TO_SMC_US(*pdef2);
1869 pdef1++;
1870 pdef2++;
1871 }
1872 }
1873 }
1874
1875 return 0;
1876 }
1877
tonga_populate_svi_load_line(struct pp_hwmgr * hwmgr)1878 static int tonga_populate_svi_load_line(struct pp_hwmgr *hwmgr)
1879 {
1880 struct tonga_smumgr *smu_data =
1881 (struct tonga_smumgr *)(hwmgr->smu_backend);
1882 const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults;
1883
1884 smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en;
1885 smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddC;
1886 smu_data->power_tune_table.SviLoadLineTrimVddC = 3;
1887 smu_data->power_tune_table.SviLoadLineOffsetVddC = 0;
1888
1889 return 0;
1890 }
1891
tonga_populate_tdc_limit(struct pp_hwmgr * hwmgr)1892 static int tonga_populate_tdc_limit(struct pp_hwmgr *hwmgr)
1893 {
1894 uint16_t tdc_limit;
1895 struct tonga_smumgr *smu_data =
1896 (struct tonga_smumgr *)(hwmgr->smu_backend);
1897 const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults;
1898 struct phm_ppt_v1_information *table_info =
1899 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1900
1901 /* TDC number of fraction bits are changed from 8 to 7
1902 * for Fiji as requested by SMC team
1903 */
1904 tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 256);
1905 smu_data->power_tune_table.TDC_VDDC_PkgLimit =
1906 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
1907 smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
1908 defaults->tdc_vddc_throttle_release_limit_perc;
1909 smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt;
1910
1911 return 0;
1912 }
1913
tonga_populate_dw8(struct pp_hwmgr * hwmgr,uint32_t fuse_table_offset)1914 static int tonga_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
1915 {
1916 struct tonga_smumgr *smu_data =
1917 (struct tonga_smumgr *)(hwmgr->smu_backend);
1918 const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults;
1919 uint32_t temp;
1920
1921 if (smu7_read_smc_sram_dword(hwmgr,
1922 fuse_table_offset +
1923 offsetof(SMU72_Discrete_PmFuses, TdcWaterfallCtl),
1924 (uint32_t *)&temp, SMC_RAM_END))
1925 PP_ASSERT_WITH_CODE(false,
1926 "Attempt to read PmFuses.DW6 "
1927 "(SviLoadLineEn) from SMC Failed !",
1928 return -EINVAL);
1929 else
1930 smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl;
1931
1932 return 0;
1933 }
1934
tonga_populate_temperature_scaler(struct pp_hwmgr * hwmgr)1935 static int tonga_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
1936 {
1937 int i;
1938 struct tonga_smumgr *smu_data =
1939 (struct tonga_smumgr *)(hwmgr->smu_backend);
1940
1941 /* Currently not used. Set all to zero. */
1942 for (i = 0; i < 16; i++)
1943 smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0;
1944
1945 return 0;
1946 }
1947
tonga_populate_fuzzy_fan(struct pp_hwmgr * hwmgr)1948 static int tonga_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
1949 {
1950 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
1951
1952 if ((hwmgr->thermal_controller.advanceFanControlParameters.
1953 usFanOutputSensitivity & (1 << 15)) ||
1954 (hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity == 0))
1955 hwmgr->thermal_controller.advanceFanControlParameters.
1956 usFanOutputSensitivity = hwmgr->thermal_controller.
1957 advanceFanControlParameters.usDefaultFanOutputSensitivity;
1958
1959 smu_data->power_tune_table.FuzzyFan_PwmSetDelta =
1960 PP_HOST_TO_SMC_US(hwmgr->thermal_controller.
1961 advanceFanControlParameters.usFanOutputSensitivity);
1962 return 0;
1963 }
1964
tonga_populate_gnb_lpml(struct pp_hwmgr * hwmgr)1965 static int tonga_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
1966 {
1967 int i;
1968 struct tonga_smumgr *smu_data =
1969 (struct tonga_smumgr *)(hwmgr->smu_backend);
1970
1971 /* Currently not used. Set all to zero. */
1972 for (i = 0; i < 16; i++)
1973 smu_data->power_tune_table.GnbLPML[i] = 0;
1974
1975 return 0;
1976 }
1977
tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr * hwmgr)1978 static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
1979 {
1980 struct tonga_smumgr *smu_data =
1981 (struct tonga_smumgr *)(hwmgr->smu_backend);
1982 struct phm_ppt_v1_information *table_info =
1983 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1984 uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd;
1985 uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd;
1986 struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
1987
1988 hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
1989 lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
1990
1991 smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd =
1992 CONVERT_FROM_HOST_TO_SMC_US(hi_sidd);
1993 smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd =
1994 CONVERT_FROM_HOST_TO_SMC_US(lo_sidd);
1995
1996 return 0;
1997 }
1998
tonga_populate_pm_fuses(struct pp_hwmgr * hwmgr)1999 static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr)
2000 {
2001 struct tonga_smumgr *smu_data =
2002 (struct tonga_smumgr *)(hwmgr->smu_backend);
2003 uint32_t pm_fuse_table_offset;
2004
2005 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2006 PHM_PlatformCaps_PowerContainment)) {
2007 if (smu7_read_smc_sram_dword(hwmgr,
2008 SMU72_FIRMWARE_HEADER_LOCATION +
2009 offsetof(SMU72_Firmware_Header, PmFuseTable),
2010 &pm_fuse_table_offset, SMC_RAM_END))
2011 PP_ASSERT_WITH_CODE(false,
2012 "Attempt to get pm_fuse_table_offset Failed !",
2013 return -EINVAL);
2014
2015 /* DW6 */
2016 if (tonga_populate_svi_load_line(hwmgr))
2017 PP_ASSERT_WITH_CODE(false,
2018 "Attempt to populate SviLoadLine Failed !",
2019 return -EINVAL);
2020 /* DW7 */
2021 if (tonga_populate_tdc_limit(hwmgr))
2022 PP_ASSERT_WITH_CODE(false,
2023 "Attempt to populate TDCLimit Failed !",
2024 return -EINVAL);
2025 /* DW8 */
2026 if (tonga_populate_dw8(hwmgr, pm_fuse_table_offset))
2027 PP_ASSERT_WITH_CODE(false,
2028 "Attempt to populate TdcWaterfallCtl Failed !",
2029 return -EINVAL);
2030
2031 /* DW9-DW12 */
2032 if (tonga_populate_temperature_scaler(hwmgr) != 0)
2033 PP_ASSERT_WITH_CODE(false,
2034 "Attempt to populate LPMLTemperatureScaler Failed !",
2035 return -EINVAL);
2036
2037 /* DW13-DW14 */
2038 if (tonga_populate_fuzzy_fan(hwmgr))
2039 PP_ASSERT_WITH_CODE(false,
2040 "Attempt to populate Fuzzy Fan "
2041 "Control parameters Failed !",
2042 return -EINVAL);
2043
2044 /* DW15-DW18 */
2045 if (tonga_populate_gnb_lpml(hwmgr))
2046 PP_ASSERT_WITH_CODE(false,
2047 "Attempt to populate GnbLPML Failed !",
2048 return -EINVAL);
2049
2050 /* DW20 */
2051 if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr))
2052 PP_ASSERT_WITH_CODE(
2053 false,
2054 "Attempt to populate BapmVddCBaseLeakage "
2055 "Hi and Lo Sidd Failed !",
2056 return -EINVAL);
2057
2058 if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset,
2059 (uint8_t *)&smu_data->power_tune_table,
2060 sizeof(struct SMU72_Discrete_PmFuses), SMC_RAM_END))
2061 PP_ASSERT_WITH_CODE(false,
2062 "Attempt to download PmFuseTable Failed !",
2063 return -EINVAL);
2064 }
2065 return 0;
2066 }
2067
tonga_populate_mc_reg_address(struct pp_hwmgr * hwmgr,SMU72_Discrete_MCRegisters * mc_reg_table)2068 static int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr,
2069 SMU72_Discrete_MCRegisters *mc_reg_table)
2070 {
2071 const struct tonga_smumgr *smu_data = (struct tonga_smumgr *)hwmgr->smu_backend;
2072
2073 uint32_t i, j;
2074
2075 for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) {
2076 if (smu_data->mc_reg_table.validflag & 1<<j) {
2077 PP_ASSERT_WITH_CODE(
2078 i < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE,
2079 "Index of mc_reg_table->address[] array "
2080 "out of boundary",
2081 return -EINVAL);
2082 mc_reg_table->address[i].s0 =
2083 PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0);
2084 mc_reg_table->address[i].s1 =
2085 PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1);
2086 i++;
2087 }
2088 }
2089
2090 mc_reg_table->last = (uint8_t)i;
2091
2092 return 0;
2093 }
2094
2095 /*convert register values from driver to SMC format */
tonga_convert_mc_registers(const struct tonga_mc_reg_entry * entry,SMU72_Discrete_MCRegisterSet * data,uint32_t num_entries,uint32_t valid_flag)2096 static void tonga_convert_mc_registers(
2097 const struct tonga_mc_reg_entry *entry,
2098 SMU72_Discrete_MCRegisterSet *data,
2099 uint32_t num_entries, uint32_t valid_flag)
2100 {
2101 uint32_t i, j;
2102
2103 for (i = 0, j = 0; j < num_entries; j++) {
2104 if (valid_flag & 1<<j) {
2105 data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]);
2106 i++;
2107 }
2108 }
2109 }
2110
tonga_convert_mc_reg_table_entry_to_smc(struct pp_hwmgr * hwmgr,const uint32_t memory_clock,SMU72_Discrete_MCRegisterSet * mc_reg_table_data)2111 static int tonga_convert_mc_reg_table_entry_to_smc(
2112 struct pp_hwmgr *hwmgr,
2113 const uint32_t memory_clock,
2114 SMU72_Discrete_MCRegisterSet *mc_reg_table_data
2115 )
2116 {
2117 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2118 uint32_t i = 0;
2119
2120 for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) {
2121 if (memory_clock <=
2122 smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) {
2123 break;
2124 }
2125 }
2126
2127 if ((i == smu_data->mc_reg_table.num_entries) && (i > 0))
2128 --i;
2129
2130 tonga_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i],
2131 mc_reg_table_data, smu_data->mc_reg_table.last,
2132 smu_data->mc_reg_table.validflag);
2133
2134 return 0;
2135 }
2136
tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr * hwmgr,SMU72_Discrete_MCRegisters * mc_regs)2137 static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr,
2138 SMU72_Discrete_MCRegisters *mc_regs)
2139 {
2140 int result = 0;
2141 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2142 int res;
2143 uint32_t i;
2144
2145 for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
2146 res = tonga_convert_mc_reg_table_entry_to_smc(
2147 hwmgr,
2148 data->dpm_table.mclk_table.dpm_levels[i].value,
2149 &mc_regs->data[i]
2150 );
2151
2152 if (0 != res)
2153 result = res;
2154 }
2155
2156 return result;
2157 }
2158
tonga_update_and_upload_mc_reg_table(struct pp_hwmgr * hwmgr)2159 static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr)
2160 {
2161 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2162 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2163 uint32_t address;
2164 int32_t result;
2165
2166 if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK))
2167 return 0;
2168
2169
2170 memset(&smu_data->mc_regs, 0, sizeof(SMU72_Discrete_MCRegisters));
2171
2172 result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs));
2173
2174 if (result != 0)
2175 return result;
2176
2177
2178 address = smu_data->smu7_data.mc_reg_table_start +
2179 (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]);
2180
2181 return smu7_copy_bytes_to_smc(
2182 hwmgr, address,
2183 (uint8_t *)&smu_data->mc_regs.data[0],
2184 sizeof(SMU72_Discrete_MCRegisterSet) *
2185 data->dpm_table.mclk_table.count,
2186 SMC_RAM_END);
2187 }
2188
tonga_populate_initial_mc_reg_table(struct pp_hwmgr * hwmgr)2189 static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr)
2190 {
2191 int result;
2192 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2193
2194 memset(&smu_data->mc_regs, 0x00, sizeof(SMU72_Discrete_MCRegisters));
2195 result = tonga_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs));
2196 PP_ASSERT_WITH_CODE(!result,
2197 "Failed to initialize MCRegTable for the MC register addresses !",
2198 return result;);
2199
2200 result = tonga_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs);
2201 PP_ASSERT_WITH_CODE(!result,
2202 "Failed to initialize MCRegTable for driver state !",
2203 return result;);
2204
2205 return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start,
2206 (uint8_t *)&smu_data->mc_regs, sizeof(SMU72_Discrete_MCRegisters), SMC_RAM_END);
2207 }
2208
tonga_initialize_power_tune_defaults(struct pp_hwmgr * hwmgr)2209 static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
2210 {
2211 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2212 struct phm_ppt_v1_information *table_info =
2213 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2214
2215 if (table_info &&
2216 table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX &&
2217 table_info->cac_dtp_table->usPowerTuneDataSetID)
2218 smu_data->power_tune_defaults =
2219 &tonga_power_tune_data_set_array
2220 [table_info->cac_dtp_table->usPowerTuneDataSetID - 1];
2221 else
2222 smu_data->power_tune_defaults = &tonga_power_tune_data_set_array[0];
2223 }
2224
tonga_init_smc_table(struct pp_hwmgr * hwmgr)2225 static int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
2226 {
2227 int result;
2228 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2229 struct tonga_smumgr *smu_data =
2230 (struct tonga_smumgr *)(hwmgr->smu_backend);
2231 SMU72_Discrete_DpmTable *table = &(smu_data->smc_state_table);
2232 struct phm_ppt_v1_information *table_info =
2233 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2234
2235 uint8_t i;
2236 pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
2237
2238
2239 memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table));
2240
2241 tonga_initialize_power_tune_defaults(hwmgr);
2242
2243 if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control)
2244 tonga_populate_smc_voltage_tables(hwmgr, table);
2245
2246 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2247 PHM_PlatformCaps_AutomaticDCTransition))
2248 table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
2249
2250
2251 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2252 PHM_PlatformCaps_StepVddc))
2253 table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
2254
2255 if (data->is_memory_gddr5)
2256 table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
2257
2258 i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN);
2259
2260 if (i == 1 || i == 0)
2261 table->SystemFlags |= 0x40;
2262
2263 if (data->ulv_supported && table_info->us_ulv_voltage_offset) {
2264 result = tonga_populate_ulv_state(hwmgr, table);
2265 PP_ASSERT_WITH_CODE(!result,
2266 "Failed to initialize ULV state !",
2267 return result;);
2268
2269 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
2270 ixCG_ULV_PARAMETER, 0x40035);
2271 }
2272
2273 result = tonga_populate_smc_link_level(hwmgr, table);
2274 PP_ASSERT_WITH_CODE(!result,
2275 "Failed to initialize Link Level !", return result);
2276
2277 result = tonga_populate_all_graphic_levels(hwmgr);
2278 PP_ASSERT_WITH_CODE(!result,
2279 "Failed to initialize Graphics Level !", return result);
2280
2281 result = tonga_populate_all_memory_levels(hwmgr);
2282 PP_ASSERT_WITH_CODE(!result,
2283 "Failed to initialize Memory Level !", return result);
2284
2285 result = tonga_populate_smc_acpi_level(hwmgr, table);
2286 PP_ASSERT_WITH_CODE(!result,
2287 "Failed to initialize ACPI Level !", return result);
2288
2289 result = tonga_populate_smc_vce_level(hwmgr, table);
2290 PP_ASSERT_WITH_CODE(!result,
2291 "Failed to initialize VCE Level !", return result);
2292
2293 result = tonga_populate_smc_acp_level(hwmgr, table);
2294 PP_ASSERT_WITH_CODE(!result,
2295 "Failed to initialize ACP Level !", return result);
2296
2297 /* Since only the initial state is completely set up at this
2298 * point (the other states are just copies of the boot state) we only
2299 * need to populate the ARB settings for the initial state.
2300 */
2301 result = tonga_program_memory_timing_parameters(hwmgr);
2302 PP_ASSERT_WITH_CODE(!result,
2303 "Failed to Write ARB settings for the initial state.",
2304 return result;);
2305
2306 result = tonga_populate_smc_uvd_level(hwmgr, table);
2307 PP_ASSERT_WITH_CODE(!result,
2308 "Failed to initialize UVD Level !", return result);
2309
2310 result = tonga_populate_smc_boot_level(hwmgr, table);
2311 PP_ASSERT_WITH_CODE(!result,
2312 "Failed to initialize Boot Level !", return result);
2313
2314 tonga_populate_bapm_parameters_in_dpm_table(hwmgr);
2315 PP_ASSERT_WITH_CODE(!result,
2316 "Failed to populate BAPM Parameters !", return result);
2317
2318 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2319 PHM_PlatformCaps_ClockStretcher)) {
2320 result = tonga_populate_clock_stretcher_data_table(hwmgr);
2321 PP_ASSERT_WITH_CODE(!result,
2322 "Failed to populate Clock Stretcher Data Table !",
2323 return result;);
2324 }
2325 table->GraphicsVoltageChangeEnable = 1;
2326 table->GraphicsThermThrottleEnable = 1;
2327 table->GraphicsInterval = 1;
2328 table->VoltageInterval = 1;
2329 table->ThermalInterval = 1;
2330 table->TemperatureLimitHigh =
2331 table_info->cac_dtp_table->usTargetOperatingTemp *
2332 SMU7_Q88_FORMAT_CONVERSION_UNIT;
2333 table->TemperatureLimitLow =
2334 (table_info->cac_dtp_table->usTargetOperatingTemp - 1) *
2335 SMU7_Q88_FORMAT_CONVERSION_UNIT;
2336 table->MemoryVoltageChangeEnable = 1;
2337 table->MemoryInterval = 1;
2338 table->VoltageResponseTime = 0;
2339 table->PhaseResponseTime = 0;
2340 table->MemoryThermThrottleEnable = 1;
2341
2342 /*
2343 * Cail reads current link status and reports it as cap (we cannot
2344 * change this due to some previous issues we had)
2345 * SMC drops the link status to lowest level after enabling
2346 * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again
2347 * but this time Cail reads current link status which was set to low by
2348 * SMC and reports it as cap to powerplay
2349 * To avoid it, we set PCIeBootLinkLevel to highest dpm level
2350 */
2351 PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count),
2352 "There must be 1 or more PCIE levels defined in PPTable.",
2353 return -EINVAL);
2354
2355 table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count);
2356
2357 table->PCIeGenInterval = 1;
2358
2359 result = tonga_populate_vr_config(hwmgr, table);
2360 PP_ASSERT_WITH_CODE(!result,
2361 "Failed to populate VRConfig setting !", return result);
2362 data->vr_config = table->VRConfig;
2363 table->ThermGpio = 17;
2364 table->SclkStepSize = 0x4000;
2365
2366 if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID,
2367 &gpio_pin_assignment)) {
2368 table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
2369 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2370 PHM_PlatformCaps_RegulatorHot);
2371 } else {
2372 table->VRHotGpio = SMU7_UNUSED_GPIO_PIN;
2373 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2374 PHM_PlatformCaps_RegulatorHot);
2375 }
2376
2377 if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID,
2378 &gpio_pin_assignment)) {
2379 table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
2380 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2381 PHM_PlatformCaps_AutomaticDCTransition);
2382 } else {
2383 table->AcDcGpio = SMU7_UNUSED_GPIO_PIN;
2384 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2385 PHM_PlatformCaps_AutomaticDCTransition);
2386 }
2387
2388 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2389 PHM_PlatformCaps_Falcon_QuickTransition);
2390
2391 if (0) {
2392 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2393 PHM_PlatformCaps_AutomaticDCTransition);
2394 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2395 PHM_PlatformCaps_Falcon_QuickTransition);
2396 }
2397
2398 if (atomctrl_get_pp_assign_pin(hwmgr,
2399 THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment)) {
2400 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2401 PHM_PlatformCaps_ThermalOutGPIO);
2402
2403 table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
2404
2405 table->ThermOutPolarity =
2406 (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) &
2407 (1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1 : 0;
2408
2409 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
2410
2411 /* if required, combine VRHot/PCC with thermal out GPIO*/
2412 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2413 PHM_PlatformCaps_RegulatorHot) &&
2414 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2415 PHM_PlatformCaps_CombinePCCWithThermalSignal)){
2416 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
2417 }
2418 } else {
2419 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2420 PHM_PlatformCaps_ThermalOutGPIO);
2421
2422 table->ThermOutGpio = 17;
2423 table->ThermOutPolarity = 1;
2424 table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
2425 }
2426
2427 for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++)
2428 table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
2429 CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
2430 CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
2431 CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
2432 CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
2433 CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
2434 CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
2435 CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
2436 CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
2437 CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
2438
2439 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2440 result = smu7_copy_bytes_to_smc(
2441 hwmgr,
2442 smu_data->smu7_data.dpm_table_start + offsetof(SMU72_Discrete_DpmTable, SystemFlags),
2443 (uint8_t *)&(table->SystemFlags),
2444 sizeof(SMU72_Discrete_DpmTable) - 3 * sizeof(SMU72_PIDController),
2445 SMC_RAM_END);
2446
2447 PP_ASSERT_WITH_CODE(!result,
2448 "Failed to upload dpm data to SMC memory !", return result;);
2449
2450 result = tonga_init_arb_table_index(hwmgr);
2451 PP_ASSERT_WITH_CODE(!result,
2452 "Failed to upload arb data to SMC memory !", return result);
2453
2454 tonga_populate_pm_fuses(hwmgr);
2455 PP_ASSERT_WITH_CODE((!result),
2456 "Failed to populate initialize pm fuses !", return result);
2457
2458 result = tonga_populate_initial_mc_reg_table(hwmgr);
2459 PP_ASSERT_WITH_CODE((!result),
2460 "Failed to populate initialize MC Reg table !", return result);
2461
2462 return 0;
2463 }
2464
tonga_thermal_setup_fan_table(struct pp_hwmgr * hwmgr)2465 static int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
2466 {
2467 struct tonga_smumgr *smu_data =
2468 (struct tonga_smumgr *)(hwmgr->smu_backend);
2469 SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
2470 uint32_t duty100;
2471 uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
2472 uint16_t fdo_min, slope1, slope2;
2473 uint32_t reference_clock;
2474 int res __unused;
2475 uint64_t tmp64;
2476
2477 if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2478 PHM_PlatformCaps_MicrocodeFanControl))
2479 return 0;
2480
2481 if (hwmgr->thermal_controller.fanInfo.bNoFan) {
2482 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2483 PHM_PlatformCaps_MicrocodeFanControl);
2484 return 0;
2485 }
2486
2487 if (0 == smu_data->smu7_data.fan_table_start) {
2488 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2489 PHM_PlatformCaps_MicrocodeFanControl);
2490 return 0;
2491 }
2492
2493 duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
2494 CGS_IND_REG__SMC,
2495 CG_FDO_CTRL1, FMAX_DUTY100);
2496
2497 if (0 == duty100) {
2498 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2499 PHM_PlatformCaps_MicrocodeFanControl);
2500 return 0;
2501 }
2502
2503 tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100;
2504 do_div(tmp64, 10000);
2505 fdo_min = (uint16_t)tmp64;
2506
2507 t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed -
2508 hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
2509 t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh -
2510 hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
2511
2512 pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed -
2513 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
2514 pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh -
2515 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
2516
2517 slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
2518 slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
2519
2520 fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100);
2521 fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100);
2522 fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100);
2523
2524 fan_table.Slope1 = cpu_to_be16(slope1);
2525 fan_table.Slope2 = cpu_to_be16(slope2);
2526
2527 fan_table.FdoMin = cpu_to_be16(fdo_min);
2528
2529 fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst);
2530
2531 fan_table.HystUp = cpu_to_be16(1);
2532
2533 fan_table.HystSlope = cpu_to_be16(1);
2534
2535 fan_table.TempRespLim = cpu_to_be16(5);
2536
2537 reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
2538
2539 fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
2540
2541 fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
2542
2543 fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL);
2544
2545 fan_table.FanControl_GL_Flag = 1;
2546
2547 res = smu7_copy_bytes_to_smc(hwmgr,
2548 smu_data->smu7_data.fan_table_start,
2549 (uint8_t *)&fan_table,
2550 (uint32_t)sizeof(fan_table),
2551 SMC_RAM_END);
2552
2553 return 0;
2554 }
2555
2556
tonga_program_mem_timing_parameters(struct pp_hwmgr * hwmgr)2557 static int tonga_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
2558 {
2559 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2560
2561 if (data->need_update_smu7_dpm_table &
2562 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
2563 return tonga_program_memory_timing_parameters(hwmgr);
2564
2565 return 0;
2566 }
2567
tonga_update_sclk_threshold(struct pp_hwmgr * hwmgr)2568 static int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr)
2569 {
2570 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2571 struct tonga_smumgr *smu_data =
2572 (struct tonga_smumgr *)(hwmgr->smu_backend);
2573
2574 int result = 0;
2575 uint32_t low_sclk_interrupt_threshold = 0;
2576
2577 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2578 PHM_PlatformCaps_SclkThrottleLowNotification)
2579 && (data->low_sclk_interrupt_threshold != 0)) {
2580 low_sclk_interrupt_threshold =
2581 data->low_sclk_interrupt_threshold;
2582
2583 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
2584
2585 result = smu7_copy_bytes_to_smc(
2586 hwmgr,
2587 smu_data->smu7_data.dpm_table_start +
2588 offsetof(SMU72_Discrete_DpmTable,
2589 LowSclkInterruptThreshold),
2590 (uint8_t *)&low_sclk_interrupt_threshold,
2591 sizeof(uint32_t),
2592 SMC_RAM_END);
2593 }
2594
2595 result = tonga_update_and_upload_mc_reg_table(hwmgr);
2596
2597 PP_ASSERT_WITH_CODE((!result),
2598 "Failed to upload MC reg table !",
2599 return result);
2600
2601 result = tonga_program_mem_timing_parameters(hwmgr);
2602 PP_ASSERT_WITH_CODE((result == 0),
2603 "Failed to program memory timing parameters !",
2604 );
2605
2606 return result;
2607 }
2608
tonga_get_offsetof(uint32_t type,uint32_t member)2609 static uint32_t tonga_get_offsetof(uint32_t type, uint32_t member)
2610 {
2611 switch (type) {
2612 case SMU_SoftRegisters:
2613 switch (member) {
2614 case HandshakeDisables:
2615 return offsetof(SMU72_SoftRegisters, HandshakeDisables);
2616 case VoltageChangeTimeout:
2617 return offsetof(SMU72_SoftRegisters, VoltageChangeTimeout);
2618 case AverageGraphicsActivity:
2619 return offsetof(SMU72_SoftRegisters, AverageGraphicsActivity);
2620 case AverageMemoryActivity:
2621 return offsetof(SMU72_SoftRegisters, AverageMemoryActivity);
2622 case PreVBlankGap:
2623 return offsetof(SMU72_SoftRegisters, PreVBlankGap);
2624 case VBlankTimeout:
2625 return offsetof(SMU72_SoftRegisters, VBlankTimeout);
2626 case UcodeLoadStatus:
2627 return offsetof(SMU72_SoftRegisters, UcodeLoadStatus);
2628 case DRAM_LOG_ADDR_H:
2629 return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_H);
2630 case DRAM_LOG_ADDR_L:
2631 return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_L);
2632 case DRAM_LOG_PHY_ADDR_H:
2633 return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_H);
2634 case DRAM_LOG_PHY_ADDR_L:
2635 return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_L);
2636 case DRAM_LOG_BUFF_SIZE:
2637 return offsetof(SMU72_SoftRegisters, DRAM_LOG_BUFF_SIZE);
2638 }
2639 break;
2640 case SMU_Discrete_DpmTable:
2641 switch (member) {
2642 case UvdBootLevel:
2643 return offsetof(SMU72_Discrete_DpmTable, UvdBootLevel);
2644 case VceBootLevel:
2645 return offsetof(SMU72_Discrete_DpmTable, VceBootLevel);
2646 case LowSclkInterruptThreshold:
2647 return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold);
2648 }
2649 break;
2650 }
2651 pr_warn("can't get the offset of type %x member %x\n", type, member);
2652 return 0;
2653 }
2654
tonga_get_mac_definition(uint32_t value)2655 static uint32_t tonga_get_mac_definition(uint32_t value)
2656 {
2657 switch (value) {
2658 case SMU_MAX_LEVELS_GRAPHICS:
2659 return SMU72_MAX_LEVELS_GRAPHICS;
2660 case SMU_MAX_LEVELS_MEMORY:
2661 return SMU72_MAX_LEVELS_MEMORY;
2662 case SMU_MAX_LEVELS_LINK:
2663 return SMU72_MAX_LEVELS_LINK;
2664 case SMU_MAX_ENTRIES_SMIO:
2665 return SMU72_MAX_ENTRIES_SMIO;
2666 case SMU_MAX_LEVELS_VDDC:
2667 return SMU72_MAX_LEVELS_VDDC;
2668 case SMU_MAX_LEVELS_VDDGFX:
2669 return SMU72_MAX_LEVELS_VDDGFX;
2670 case SMU_MAX_LEVELS_VDDCI:
2671 return SMU72_MAX_LEVELS_VDDCI;
2672 case SMU_MAX_LEVELS_MVDD:
2673 return SMU72_MAX_LEVELS_MVDD;
2674 }
2675 pr_warn("can't get the mac value %x\n", value);
2676
2677 return 0;
2678 }
2679
tonga_update_uvd_smc_table(struct pp_hwmgr * hwmgr)2680 static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr)
2681 {
2682 struct tonga_smumgr *smu_data =
2683 (struct tonga_smumgr *)(hwmgr->smu_backend);
2684 uint32_t mm_boot_level_offset, mm_boot_level_value;
2685 struct phm_ppt_v1_information *table_info =
2686 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2687
2688 smu_data->smc_state_table.UvdBootLevel = 0;
2689 if (table_info->mm_dep_table->count > 0)
2690 smu_data->smc_state_table.UvdBootLevel =
2691 (uint8_t) (table_info->mm_dep_table->count - 1);
2692 mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2693 offsetof(SMU72_Discrete_DpmTable, UvdBootLevel);
2694 mm_boot_level_offset /= 4;
2695 mm_boot_level_offset *= 4;
2696 mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2697 CGS_IND_REG__SMC, mm_boot_level_offset);
2698 mm_boot_level_value &= 0x00FFFFFF;
2699 mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24;
2700 cgs_write_ind_register(hwmgr->device,
2701 CGS_IND_REG__SMC,
2702 mm_boot_level_offset, mm_boot_level_value);
2703
2704 if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2705 PHM_PlatformCaps_UVDDPM) ||
2706 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2707 PHM_PlatformCaps_StablePState))
2708 smum_send_msg_to_smc_with_parameter(hwmgr,
2709 PPSMC_MSG_UVDDPM_SetEnabledMask,
2710 (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel));
2711 return 0;
2712 }
2713
tonga_update_vce_smc_table(struct pp_hwmgr * hwmgr)2714 static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr)
2715 {
2716 struct tonga_smumgr *smu_data =
2717 (struct tonga_smumgr *)(hwmgr->smu_backend);
2718 uint32_t mm_boot_level_offset, mm_boot_level_value;
2719 struct phm_ppt_v1_information *table_info =
2720 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2721
2722
2723 smu_data->smc_state_table.VceBootLevel =
2724 (uint8_t) (table_info->mm_dep_table->count - 1);
2725
2726 mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2727 offsetof(SMU72_Discrete_DpmTable, VceBootLevel);
2728 mm_boot_level_offset /= 4;
2729 mm_boot_level_offset *= 4;
2730 mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2731 CGS_IND_REG__SMC, mm_boot_level_offset);
2732 mm_boot_level_value &= 0xFF00FFFF;
2733 mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16;
2734 cgs_write_ind_register(hwmgr->device,
2735 CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2736
2737 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2738 PHM_PlatformCaps_StablePState))
2739 smum_send_msg_to_smc_with_parameter(hwmgr,
2740 PPSMC_MSG_VCEDPM_SetEnabledMask,
2741 (uint32_t)1 << smu_data->smc_state_table.VceBootLevel);
2742 return 0;
2743 }
2744
tonga_update_smc_table(struct pp_hwmgr * hwmgr,uint32_t type)2745 static int tonga_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
2746 {
2747 switch (type) {
2748 case SMU_UVD_TABLE:
2749 tonga_update_uvd_smc_table(hwmgr);
2750 break;
2751 case SMU_VCE_TABLE:
2752 tonga_update_vce_smc_table(hwmgr);
2753 break;
2754 default:
2755 break;
2756 }
2757 return 0;
2758 }
2759
tonga_process_firmware_header(struct pp_hwmgr * hwmgr)2760 static int tonga_process_firmware_header(struct pp_hwmgr *hwmgr)
2761 {
2762 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2763 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2764
2765 uint32_t tmp;
2766 int result;
2767 bool error = false;
2768
2769 result = smu7_read_smc_sram_dword(hwmgr,
2770 SMU72_FIRMWARE_HEADER_LOCATION +
2771 offsetof(SMU72_Firmware_Header, DpmTable),
2772 &tmp, SMC_RAM_END);
2773
2774 if (!result)
2775 smu_data->smu7_data.dpm_table_start = tmp;
2776
2777 error |= (result != 0);
2778
2779 result = smu7_read_smc_sram_dword(hwmgr,
2780 SMU72_FIRMWARE_HEADER_LOCATION +
2781 offsetof(SMU72_Firmware_Header, SoftRegisters),
2782 &tmp, SMC_RAM_END);
2783
2784 if (!result) {
2785 data->soft_regs_start = tmp;
2786 smu_data->smu7_data.soft_regs_start = tmp;
2787 }
2788
2789 error |= (result != 0);
2790
2791
2792 result = smu7_read_smc_sram_dword(hwmgr,
2793 SMU72_FIRMWARE_HEADER_LOCATION +
2794 offsetof(SMU72_Firmware_Header, mcRegisterTable),
2795 &tmp, SMC_RAM_END);
2796
2797 if (!result)
2798 smu_data->smu7_data.mc_reg_table_start = tmp;
2799
2800 result = smu7_read_smc_sram_dword(hwmgr,
2801 SMU72_FIRMWARE_HEADER_LOCATION +
2802 offsetof(SMU72_Firmware_Header, FanTable),
2803 &tmp, SMC_RAM_END);
2804
2805 if (!result)
2806 smu_data->smu7_data.fan_table_start = tmp;
2807
2808 error |= (result != 0);
2809
2810 result = smu7_read_smc_sram_dword(hwmgr,
2811 SMU72_FIRMWARE_HEADER_LOCATION +
2812 offsetof(SMU72_Firmware_Header, mcArbDramTimingTable),
2813 &tmp, SMC_RAM_END);
2814
2815 if (!result)
2816 smu_data->smu7_data.arb_table_start = tmp;
2817
2818 error |= (result != 0);
2819
2820 result = smu7_read_smc_sram_dword(hwmgr,
2821 SMU72_FIRMWARE_HEADER_LOCATION +
2822 offsetof(SMU72_Firmware_Header, Version),
2823 &tmp, SMC_RAM_END);
2824
2825 if (!result)
2826 hwmgr->microcode_version_info.SMC = tmp;
2827
2828 error |= (result != 0);
2829
2830 return error ? 1 : 0;
2831 }
2832
2833 /*---------------------------MC----------------------------*/
2834
tonga_get_memory_modile_index(struct pp_hwmgr * hwmgr)2835 static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr)
2836 {
2837 return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16));
2838 }
2839
tonga_check_s0_mc_reg_index(uint16_t in_reg,uint16_t * out_reg)2840 static bool tonga_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg)
2841 {
2842 bool result = true;
2843
2844 switch (in_reg) {
2845 case mmMC_SEQ_RAS_TIMING:
2846 *out_reg = mmMC_SEQ_RAS_TIMING_LP;
2847 break;
2848
2849 case mmMC_SEQ_DLL_STBY:
2850 *out_reg = mmMC_SEQ_DLL_STBY_LP;
2851 break;
2852
2853 case mmMC_SEQ_G5PDX_CMD0:
2854 *out_reg = mmMC_SEQ_G5PDX_CMD0_LP;
2855 break;
2856
2857 case mmMC_SEQ_G5PDX_CMD1:
2858 *out_reg = mmMC_SEQ_G5PDX_CMD1_LP;
2859 break;
2860
2861 case mmMC_SEQ_G5PDX_CTRL:
2862 *out_reg = mmMC_SEQ_G5PDX_CTRL_LP;
2863 break;
2864
2865 case mmMC_SEQ_CAS_TIMING:
2866 *out_reg = mmMC_SEQ_CAS_TIMING_LP;
2867 break;
2868
2869 case mmMC_SEQ_MISC_TIMING:
2870 *out_reg = mmMC_SEQ_MISC_TIMING_LP;
2871 break;
2872
2873 case mmMC_SEQ_MISC_TIMING2:
2874 *out_reg = mmMC_SEQ_MISC_TIMING2_LP;
2875 break;
2876
2877 case mmMC_SEQ_PMG_DVS_CMD:
2878 *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP;
2879 break;
2880
2881 case mmMC_SEQ_PMG_DVS_CTL:
2882 *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP;
2883 break;
2884
2885 case mmMC_SEQ_RD_CTL_D0:
2886 *out_reg = mmMC_SEQ_RD_CTL_D0_LP;
2887 break;
2888
2889 case mmMC_SEQ_RD_CTL_D1:
2890 *out_reg = mmMC_SEQ_RD_CTL_D1_LP;
2891 break;
2892
2893 case mmMC_SEQ_WR_CTL_D0:
2894 *out_reg = mmMC_SEQ_WR_CTL_D0_LP;
2895 break;
2896
2897 case mmMC_SEQ_WR_CTL_D1:
2898 *out_reg = mmMC_SEQ_WR_CTL_D1_LP;
2899 break;
2900
2901 case mmMC_PMG_CMD_EMRS:
2902 *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP;
2903 break;
2904
2905 case mmMC_PMG_CMD_MRS:
2906 *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP;
2907 break;
2908
2909 case mmMC_PMG_CMD_MRS1:
2910 *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP;
2911 break;
2912
2913 case mmMC_SEQ_PMG_TIMING:
2914 *out_reg = mmMC_SEQ_PMG_TIMING_LP;
2915 break;
2916
2917 case mmMC_PMG_CMD_MRS2:
2918 *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP;
2919 break;
2920
2921 case mmMC_SEQ_WR_CTL_2:
2922 *out_reg = mmMC_SEQ_WR_CTL_2_LP;
2923 break;
2924
2925 default:
2926 result = false;
2927 break;
2928 }
2929
2930 return result;
2931 }
2932
tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table * table)2933 static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table *table)
2934 {
2935 uint32_t i;
2936 uint16_t address;
2937
2938 for (i = 0; i < table->last; i++) {
2939 table->mc_reg_address[i].s0 =
2940 tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1,
2941 &address) ?
2942 address :
2943 table->mc_reg_address[i].s1;
2944 }
2945 return 0;
2946 }
2947
tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table * table,struct tonga_mc_reg_table * ni_table)2948 static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table,
2949 struct tonga_mc_reg_table *ni_table)
2950 {
2951 uint8_t i, j;
2952
2953 PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2954 "Invalid VramInfo table.", return -EINVAL);
2955 PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES),
2956 "Invalid VramInfo table.", return -EINVAL);
2957
2958 for (i = 0; i < table->last; i++)
2959 ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
2960
2961 ni_table->last = table->last;
2962
2963 for (i = 0; i < table->num_entries; i++) {
2964 ni_table->mc_reg_table_entry[i].mclk_max =
2965 table->mc_reg_table_entry[i].mclk_max;
2966 for (j = 0; j < table->last; j++) {
2967 ni_table->mc_reg_table_entry[i].mc_data[j] =
2968 table->mc_reg_table_entry[i].mc_data[j];
2969 }
2970 }
2971
2972 ni_table->num_entries = table->num_entries;
2973
2974 return 0;
2975 }
2976
tonga_set_mc_special_registers(struct pp_hwmgr * hwmgr,struct tonga_mc_reg_table * table)2977 static int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr,
2978 struct tonga_mc_reg_table *table)
2979 {
2980 uint8_t i, j, k;
2981 uint32_t temp_reg;
2982 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2983
2984 for (i = 0, j = table->last; i < table->last; i++) {
2985 PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2986 "Invalid VramInfo table.", return -EINVAL);
2987
2988 switch (table->mc_reg_address[i].s1) {
2989
2990 case mmMC_SEQ_MISC1:
2991 temp_reg = cgs_read_register(hwmgr->device,
2992 mmMC_PMG_CMD_EMRS);
2993 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS;
2994 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP;
2995 for (k = 0; k < table->num_entries; k++) {
2996 table->mc_reg_table_entry[k].mc_data[j] =
2997 ((temp_reg & 0xffff0000)) |
2998 ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
2999 }
3000 j++;
3001
3002 PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3003 "Invalid VramInfo table.", return -EINVAL);
3004 temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS);
3005 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS;
3006 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP;
3007 for (k = 0; k < table->num_entries; k++) {
3008 table->mc_reg_table_entry[k].mc_data[j] =
3009 (temp_reg & 0xffff0000) |
3010 (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
3011
3012 if (!data->is_memory_gddr5)
3013 table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
3014 }
3015 j++;
3016
3017 if (!data->is_memory_gddr5) {
3018 PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3019 "Invalid VramInfo table.", return -EINVAL);
3020 table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
3021 table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
3022 for (k = 0; k < table->num_entries; k++)
3023 table->mc_reg_table_entry[k].mc_data[j] =
3024 (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
3025 j++;
3026 }
3027
3028 break;
3029
3030 case mmMC_SEQ_RESERVE_M:
3031 temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1);
3032 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1;
3033 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP;
3034 for (k = 0; k < table->num_entries; k++) {
3035 table->mc_reg_table_entry[k].mc_data[j] =
3036 (temp_reg & 0xffff0000) |
3037 (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
3038 }
3039 j++;
3040 break;
3041
3042 default:
3043 break;
3044 }
3045
3046 }
3047
3048 table->last = j;
3049
3050 return 0;
3051 }
3052
tonga_set_valid_flag(struct tonga_mc_reg_table * table)3053 static int tonga_set_valid_flag(struct tonga_mc_reg_table *table)
3054 {
3055 uint8_t i, j;
3056
3057 for (i = 0; i < table->last; i++) {
3058 for (j = 1; j < table->num_entries; j++) {
3059 if (table->mc_reg_table_entry[j-1].mc_data[i] !=
3060 table->mc_reg_table_entry[j].mc_data[i]) {
3061 table->validflag |= (1<<i);
3062 break;
3063 }
3064 }
3065 }
3066
3067 return 0;
3068 }
3069
tonga_initialize_mc_reg_table(struct pp_hwmgr * hwmgr)3070 static int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
3071 {
3072 int result;
3073 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
3074 pp_atomctrl_mc_reg_table *table;
3075 struct tonga_mc_reg_table *ni_table = &smu_data->mc_reg_table;
3076 uint8_t module_index = tonga_get_memory_modile_index(hwmgr);
3077
3078 table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL);
3079
3080 if (table == NULL)
3081 return -ENOMEM;
3082
3083 /* Program additional LP registers that are no longer programmed by VBIOS */
3084 cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP,
3085 cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
3086 cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP,
3087 cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
3088 cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP,
3089 cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY));
3090 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP,
3091 cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0));
3092 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP,
3093 cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1));
3094 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP,
3095 cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL));
3096 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP,
3097 cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD));
3098 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP,
3099 cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL));
3100 cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP,
3101 cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING));
3102 cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP,
3103 cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
3104 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP,
3105 cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS));
3106 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP,
3107 cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS));
3108 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP,
3109 cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1));
3110 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP,
3111 cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0));
3112 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP,
3113 cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
3114 cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP,
3115 cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
3116 cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP,
3117 cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
3118 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP,
3119 cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
3120 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP,
3121 cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2));
3122 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP,
3123 cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2));
3124
3125 result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table);
3126
3127 if (!result)
3128 result = tonga_copy_vbios_smc_reg_table(table, ni_table);
3129
3130 if (!result) {
3131 tonga_set_s0_mc_reg_index(ni_table);
3132 result = tonga_set_mc_special_registers(hwmgr, ni_table);
3133 }
3134
3135 if (!result)
3136 tonga_set_valid_flag(ni_table);
3137
3138 kfree(table);
3139
3140 return result;
3141 }
3142
tonga_is_dpm_running(struct pp_hwmgr * hwmgr)3143 static bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr)
3144 {
3145 return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
3146 CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
3147 ? true : false;
3148 }
3149
tonga_update_dpm_settings(struct pp_hwmgr * hwmgr,void * profile_setting)3150 static int tonga_update_dpm_settings(struct pp_hwmgr *hwmgr,
3151 void *profile_setting)
3152 {
3153 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3154 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)
3155 (hwmgr->smu_backend);
3156 struct profile_mode_setting *setting;
3157 struct SMU72_Discrete_GraphicsLevel *levels =
3158 smu_data->smc_state_table.GraphicsLevel;
3159 uint32_t array = smu_data->smu7_data.dpm_table_start +
3160 offsetof(SMU72_Discrete_DpmTable, GraphicsLevel);
3161
3162 uint32_t mclk_array = smu_data->smu7_data.dpm_table_start +
3163 offsetof(SMU72_Discrete_DpmTable, MemoryLevel);
3164 struct SMU72_Discrete_MemoryLevel *mclk_levels =
3165 smu_data->smc_state_table.MemoryLevel;
3166 uint32_t i;
3167 uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
3168
3169 if (profile_setting == NULL)
3170 return -EINVAL;
3171
3172 setting = (struct profile_mode_setting *)profile_setting;
3173
3174 if (setting->bupdate_sclk) {
3175 if (!data->sclk_dpm_key_disabled)
3176 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
3177 for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
3178 if (levels[i].ActivityLevel !=
3179 cpu_to_be16(setting->sclk_activity)) {
3180 levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
3181
3182 clk_activity_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
3183 + offsetof(SMU72_Discrete_GraphicsLevel, ActivityLevel);
3184 offset = clk_activity_offset & ~0x3;
3185 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
3186 tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
3187 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
3188
3189 }
3190 if (levels[i].UpHyst != setting->sclk_up_hyst ||
3191 levels[i].DownHyst != setting->sclk_down_hyst) {
3192 levels[i].UpHyst = setting->sclk_up_hyst;
3193 levels[i].DownHyst = setting->sclk_down_hyst;
3194 up_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
3195 + offsetof(SMU72_Discrete_GraphicsLevel, UpHyst);
3196 down_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
3197 + offsetof(SMU72_Discrete_GraphicsLevel, DownHyst);
3198 offset = up_hyst_offset & ~0x3;
3199 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
3200 tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t));
3201 tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t));
3202 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
3203 }
3204 }
3205 if (!data->sclk_dpm_key_disabled)
3206 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
3207 }
3208
3209 if (setting->bupdate_mclk) {
3210 if (!data->mclk_dpm_key_disabled)
3211 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
3212 for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
3213 if (mclk_levels[i].ActivityLevel !=
3214 cpu_to_be16(setting->mclk_activity)) {
3215 mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
3216
3217 clk_activity_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
3218 + offsetof(SMU72_Discrete_MemoryLevel, ActivityLevel);
3219 offset = clk_activity_offset & ~0x3;
3220 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
3221 tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
3222 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
3223
3224 }
3225 if (mclk_levels[i].UpHyst != setting->mclk_up_hyst ||
3226 mclk_levels[i].DownHyst != setting->mclk_down_hyst) {
3227 mclk_levels[i].UpHyst = setting->mclk_up_hyst;
3228 mclk_levels[i].DownHyst = setting->mclk_down_hyst;
3229 up_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
3230 + offsetof(SMU72_Discrete_MemoryLevel, UpHyst);
3231 down_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
3232 + offsetof(SMU72_Discrete_MemoryLevel, DownHyst);
3233 offset = up_hyst_offset & ~0x3;
3234 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
3235 tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t));
3236 tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t));
3237 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
3238 }
3239 }
3240 if (!data->mclk_dpm_key_disabled)
3241 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
3242 }
3243 return 0;
3244 }
3245
3246 const struct pp_smumgr_func tonga_smu_funcs = {
3247 .name = "tonga_smu",
3248 .smu_init = &tonga_smu_init,
3249 .smu_fini = &smu7_smu_fini,
3250 .start_smu = &tonga_start_smu,
3251 .check_fw_load_finish = &smu7_check_fw_load_finish,
3252 .request_smu_load_fw = &smu7_request_smu_load_fw,
3253 .request_smu_load_specific_fw = NULL,
3254 .send_msg_to_smc = &smu7_send_msg_to_smc,
3255 .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter,
3256 .download_pptable_settings = NULL,
3257 .upload_pptable_settings = NULL,
3258 .update_smc_table = tonga_update_smc_table,
3259 .get_offsetof = tonga_get_offsetof,
3260 .process_firmware_header = tonga_process_firmware_header,
3261 .init_smc_table = tonga_init_smc_table,
3262 .update_sclk_threshold = tonga_update_sclk_threshold,
3263 .thermal_setup_fan_table = tonga_thermal_setup_fan_table,
3264 .populate_all_graphic_levels = tonga_populate_all_graphic_levels,
3265 .populate_all_memory_levels = tonga_populate_all_memory_levels,
3266 .get_mac_definition = tonga_get_mac_definition,
3267 .initialize_mc_reg_table = tonga_initialize_mc_reg_table,
3268 .is_dpm_running = tonga_is_dpm_running,
3269 .update_dpm_settings = tonga_update_dpm_settings,
3270 };
3271