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