2 * Copyright 2015 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include <linux/gfp.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"
38 #include "smu7_dyn_defaults.h"
40 #include "smu7_hwmgr.h"
41 #include "hardwaremanager.h"
42 #include "ppatomctrl.h"
46 #include "pppcielanes.h"
47 #include "pp_endian.h"
49 #include "gmc/gmc_8_1_d.h"
50 #include "gmc/gmc_8_1_sh_mask.h"
52 #include "bif/bif_5_0_d.h"
53 #include "bif/bif_5_0_sh_mask.h"
55 #include "dce/dce_10_0_d.h"
56 #include "dce/dce_10_0_sh_mask.h"
59 #define VOLTAGE_SCALE 4
60 #define POWERTUNE_DEFAULT_SET_MAX 1
61 #define VOLTAGE_VID_OFFSET_SCALE1 625
62 #define VOLTAGE_VID_OFFSET_SCALE2 100
63 #define MC_CG_ARB_FREQ_F1 0x0b
64 #define VDDC_VDDCI_DELTA 200
67 static const struct tonga_pt_defaults tonga_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
68 /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
69 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
73 {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8,
74 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
75 {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203,
76 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4}
80 /* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */
81 static const uint16_t tonga_clock_stretcher_lookup_table[2][4] = {
86 /* [FF, SS] type, [] 4 voltage ranges,
87 * and [Floor Freq, Boundary Freq, VID min , VID max]
89 static const uint32_t tonga_clock_stretcher_ddt_table[2][4][4] = {
90 { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
91 { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} }
94 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */
95 static const uint8_t tonga_clock_stretch_amount_conversion[2][6] = {
100 static int tonga_start_in_protection_mode(struct pp_hwmgr *hwmgr)
105 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
106 SMC_SYSCON_RESET_CNTL, rst_reg, 1);
108 result = smu7_upload_smu_firmware_image(hwmgr);
113 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
117 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
118 SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
120 /* De-assert reset */
121 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
122 SMC_SYSCON_RESET_CNTL, rst_reg, 0);
124 /* Set SMU Auto Start */
125 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
126 SMU_INPUT_DATA, AUTO_START, 1);
128 /* Clear firmware interrupt enable flag */
129 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
130 ixFIRMWARE_FLAGS, 0);
132 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND,
133 RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1);
136 * Call Test SMU message with 0x20000 offset to trigger SMU start
138 smu7_send_msg_to_smc_offset(hwmgr);
140 /* Wait for done bit to be set */
141 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
142 SMU_STATUS, SMU_DONE, 0);
144 /* Check pass/failed indicator */
145 if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
146 CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS)) {
147 pr_err("SMU Firmware start failed\n");
151 /* Wait for firmware to initialize */
152 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND,
153 FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
158 static int tonga_start_in_non_protection_mode(struct pp_hwmgr *hwmgr)
162 /* wait for smc boot up */
163 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
164 RCU_UC_EVENTS, boot_seq_done, 0);
166 /*Clear firmware interrupt enable flag*/
167 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
168 ixFIRMWARE_FLAGS, 0);
171 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
172 SMC_SYSCON_RESET_CNTL, rst_reg, 1);
174 result = smu7_upload_smu_firmware_image(hwmgr);
179 /* Set smc instruct start point at 0x0 */
180 smu7_program_jump_on_start(hwmgr);
183 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
184 SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
187 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
188 SMC_SYSCON_RESET_CNTL, rst_reg, 0);
190 /* Wait for firmware to initialize */
191 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND,
192 FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
197 static int tonga_start_smu(struct pp_hwmgr *hwmgr)
201 /* Only start SMC if SMC RAM is not running */
202 if (!(smu7_is_smc_ram_running(hwmgr) ||
203 cgs_is_virtualization_enabled(hwmgr->device))) {
204 /*Check if SMU is running in protected mode*/
205 if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
206 SMU_FIRMWARE, SMU_MODE)) {
207 result = tonga_start_in_non_protection_mode(hwmgr);
211 result = tonga_start_in_protection_mode(hwmgr);
217 result = smu7_request_smu_load_fw(hwmgr);
222 static int tonga_smu_init(struct pp_hwmgr *hwmgr)
224 struct tonga_smumgr *tonga_priv = NULL;
226 tonga_priv = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL);
227 if (tonga_priv == NULL)
230 hwmgr->smu_backend = tonga_priv;
232 if (smu7_init(hwmgr)) {
241 static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
242 phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table,
243 uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd)
246 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
247 struct phm_ppt_v1_information *pptable_info =
248 (struct phm_ppt_v1_information *)(hwmgr->pptable);
250 /* clock - voltage dependency table is empty table */
251 if (allowed_clock_voltage_table->count == 0)
254 for (i = 0; i < allowed_clock_voltage_table->count; i++) {
255 /* find first sclk bigger than request */
256 if (allowed_clock_voltage_table->entries[i].clk >= clock) {
257 voltage->VddGfx = phm_get_voltage_index(
258 pptable_info->vddgfx_lookup_table,
259 allowed_clock_voltage_table->entries[i].vddgfx);
260 voltage->Vddc = phm_get_voltage_index(
261 pptable_info->vddc_lookup_table,
262 allowed_clock_voltage_table->entries[i].vddc);
264 if (allowed_clock_voltage_table->entries[i].vddci)
266 phm_get_voltage_id(&data->vddci_voltage_table, allowed_clock_voltage_table->entries[i].vddci);
269 phm_get_voltage_id(&data->vddci_voltage_table,
270 allowed_clock_voltage_table->entries[i].vddc - VDDC_VDDCI_DELTA);
273 if (allowed_clock_voltage_table->entries[i].mvdd)
274 *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd;
281 /* sclk is bigger than max sclk in the dependence table */
282 voltage->VddGfx = phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
283 allowed_clock_voltage_table->entries[i-1].vddgfx);
284 voltage->Vddc = phm_get_voltage_index(pptable_info->vddc_lookup_table,
285 allowed_clock_voltage_table->entries[i-1].vddc);
287 if (allowed_clock_voltage_table->entries[i-1].vddci)
288 voltage->Vddci = phm_get_voltage_id(&data->vddci_voltage_table,
289 allowed_clock_voltage_table->entries[i-1].vddci);
291 if (allowed_clock_voltage_table->entries[i-1].mvdd)
292 *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd;
297 static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr,
298 SMU72_Discrete_DpmTable *table)
301 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
303 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
304 table->VddcLevelCount = data->vddc_voltage_table.count;
305 for (count = 0; count < table->VddcLevelCount; count++) {
306 table->VddcTable[count] =
307 PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE);
309 CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount);
314 static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr,
315 SMU72_Discrete_DpmTable *table)
318 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
320 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
321 table->VddGfxLevelCount = data->vddgfx_voltage_table.count;
322 for (count = 0; count < data->vddgfx_voltage_table.count; count++) {
323 table->VddGfxTable[count] =
324 PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE);
326 CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount);
331 static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr,
332 SMU72_Discrete_DpmTable *table)
334 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
337 table->VddciLevelCount = data->vddci_voltage_table.count;
338 for (count = 0; count < table->VddciLevelCount; count++) {
339 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
340 table->VddciTable[count] =
341 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
342 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
343 table->SmioTable1.Pattern[count].Voltage =
344 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
345 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */
346 table->SmioTable1.Pattern[count].Smio =
348 table->Smio[count] |=
349 data->vddci_voltage_table.entries[count].smio_low;
350 table->VddciTable[count] =
351 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
355 table->SmioMask1 = data->vddci_voltage_table.mask_low;
356 CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount);
361 static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
362 SMU72_Discrete_DpmTable *table)
364 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
367 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
368 table->MvddLevelCount = data->mvdd_voltage_table.count;
369 for (count = 0; count < table->MvddLevelCount; count++) {
370 table->SmioTable2.Pattern[count].Voltage =
371 PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE);
372 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
373 table->SmioTable2.Pattern[count].Smio =
375 table->Smio[count] |=
376 data->mvdd_voltage_table.entries[count].smio_low;
378 table->SmioMask2 = data->mvdd_voltage_table.mask_low;
380 CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
386 static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr,
387 SMU72_Discrete_DpmTable *table)
391 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
392 struct phm_ppt_v1_information *pptable_info =
393 (struct phm_ppt_v1_information *)(hwmgr->pptable);
394 struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table =
395 pptable_info->vddgfx_lookup_table;
396 struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table =
397 pptable_info->vddc_lookup_table;
399 /* table is already swapped, so in order to use the value from it
400 * we need to swap it back.
402 uint32_t vddc_level_count = PP_SMC_TO_HOST_UL(table->VddcLevelCount);
403 uint32_t vddgfx_level_count = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount);
405 for (count = 0; count < vddc_level_count; count++) {
406 /* We are populating vddc CAC data to BapmVddc table in split and merged mode */
407 index = phm_get_voltage_index(vddc_lookup_table,
408 data->vddc_voltage_table.entries[count].value);
409 table->BapmVddcVidLoSidd[count] =
410 convert_to_vid(vddc_lookup_table->entries[index].us_cac_low);
411 table->BapmVddcVidHiSidd[count] =
412 convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid);
413 table->BapmVddcVidHiSidd2[count] =
414 convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
417 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
418 /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */
419 for (count = 0; count < vddgfx_level_count; count++) {
420 index = phm_get_voltage_index(vddgfx_lookup_table,
421 convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid));
422 table->BapmVddGfxVidHiSidd2[count] =
423 convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high);
426 for (count = 0; count < vddc_level_count; count++) {
427 index = phm_get_voltage_index(vddc_lookup_table,
428 data->vddc_voltage_table.entries[count].value);
429 table->BapmVddGfxVidLoSidd[count] =
430 convert_to_vid(vddc_lookup_table->entries[index].us_cac_low);
431 table->BapmVddGfxVidHiSidd[count] =
432 convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid);
433 table->BapmVddGfxVidHiSidd2[count] =
434 convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
441 static int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
442 SMU72_Discrete_DpmTable *table)
446 result = tonga_populate_smc_vddc_table(hwmgr, table);
447 PP_ASSERT_WITH_CODE(!result,
448 "can not populate VDDC voltage table to SMC",
451 result = tonga_populate_smc_vdd_ci_table(hwmgr, table);
452 PP_ASSERT_WITH_CODE(!result,
453 "can not populate VDDCI voltage table to SMC",
456 result = tonga_populate_smc_vdd_gfx_table(hwmgr, table);
457 PP_ASSERT_WITH_CODE(!result,
458 "can not populate VDDGFX voltage table to SMC",
461 result = tonga_populate_smc_mvdd_table(hwmgr, table);
462 PP_ASSERT_WITH_CODE(!result,
463 "can not populate MVDD voltage table to SMC",
466 result = tonga_populate_cac_tables(hwmgr, table);
467 PP_ASSERT_WITH_CODE(!result,
468 "can not populate CAC voltage tables to SMC",
474 static int tonga_populate_ulv_level(struct pp_hwmgr *hwmgr,
475 struct SMU72_Discrete_Ulv *state)
477 struct phm_ppt_v1_information *table_info =
478 (struct phm_ppt_v1_information *)(hwmgr->pptable);
480 state->CcPwrDynRm = 0;
481 state->CcPwrDynRm1 = 0;
483 state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset;
484 state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset *
485 VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
487 state->VddcPhase = 1;
489 CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
490 CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
491 CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
496 static int tonga_populate_ulv_state(struct pp_hwmgr *hwmgr,
497 struct SMU72_Discrete_DpmTable *table)
499 return tonga_populate_ulv_level(hwmgr, &table->Ulv);
502 static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table)
504 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
505 struct smu7_dpm_table *dpm_table = &data->dpm_table;
506 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
509 /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
510 for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
511 table->LinkLevel[i].PcieGenSpeed =
512 (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
513 table->LinkLevel[i].PcieLaneCount =
514 (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1);
515 table->LinkLevel[i].EnabledForActivity =
517 table->LinkLevel[i].SPC =
518 (uint8_t)(data->pcie_spc_cap & 0xff);
519 table->LinkLevel[i].DownThreshold =
520 PP_HOST_TO_SMC_UL(5);
521 table->LinkLevel[i].UpThreshold =
522 PP_HOST_TO_SMC_UL(30);
525 smu_data->smc_state_table.LinkLevelCount =
526 (uint8_t)dpm_table->pcie_speed_table.count;
527 data->dpm_level_enable_mask.pcie_dpm_enable_mask =
528 phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
533 static int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr,
534 uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk)
536 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
537 pp_atomctrl_clock_dividers_vi dividers;
538 uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL;
539 uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
540 uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
541 uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
542 uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
543 uint32_t reference_clock;
544 uint32_t reference_divider;
548 /* get the engine clock dividers for this clock value*/
549 result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs);
551 PP_ASSERT_WITH_CODE(result == 0,
552 "Error retrieving Engine Clock dividers from VBIOS.", return result);
554 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
555 reference_clock = atomctrl_get_reference_clock(hwmgr);
557 reference_divider = 1 + dividers.uc_pll_ref_div;
559 /* low 14 bits is fraction and high 12 bits is divider*/
560 fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
562 /* SPLL_FUNC_CNTL setup*/
563 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
564 CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div);
565 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
566 CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div);
568 /* SPLL_FUNC_CNTL_3 setup*/
569 spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
570 CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv);
572 /* set to use fractional accumulation*/
573 spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
574 CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1);
576 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
577 PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
578 pp_atomctrl_internal_ss_info ss_info;
580 uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div;
581 if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) {
583 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
584 * ss_info.speed_spectrum_rate -- in unit of khz
586 /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
587 uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate);
589 /* clkv = 2 * D * fbdiv / NS */
590 uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000);
592 cg_spll_spread_spectrum =
593 PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS);
594 cg_spll_spread_spectrum =
595 PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
596 cg_spll_spread_spectrum_2 =
597 PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV);
601 sclk->SclkFrequency = engine_clock;
602 sclk->CgSpllFuncCntl3 = spll_func_cntl_3;
603 sclk->CgSpllFuncCntl4 = spll_func_cntl_4;
604 sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum;
605 sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2;
606 sclk->SclkDid = (uint8_t)dividers.pll_post_divider;
611 static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
612 uint32_t engine_clock,
613 SMU72_Discrete_GraphicsLevel *graphic_level)
617 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
618 struct phm_ppt_v1_information *pptable_info =
619 (struct phm_ppt_v1_information *)(hwmgr->pptable);
620 phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
622 result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level);
624 if (hwmgr->od_enabled)
625 vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk;
627 vdd_dep_table = pptable_info->vdd_dep_on_sclk;
629 /* populate graphics levels*/
630 result = tonga_get_dependency_volt_by_clk(hwmgr,
631 vdd_dep_table, engine_clock,
632 &graphic_level->MinVoltage, &mvdd);
633 PP_ASSERT_WITH_CODE((!result),
634 "can not find VDDC voltage value for VDDC "
635 "engine clock dependency table", return result);
637 /* SCLK frequency in units of 10KHz*/
638 graphic_level->SclkFrequency = engine_clock;
639 /* Indicates maximum activity level for this performance level. 50% for now*/
640 graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity;
642 graphic_level->CcPwrDynRm = 0;
643 graphic_level->CcPwrDynRm1 = 0;
644 /* this level can be used if activity is high enough.*/
645 graphic_level->EnabledForActivity = 0;
646 /* this level can be used for throttling.*/
647 graphic_level->EnabledForThrottle = 1;
648 graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst;
649 graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst;
650 graphic_level->VoltageDownHyst = 0;
651 graphic_level->PowerThrottle = 0;
653 data->display_timing.min_clock_in_sr =
654 hwmgr->display_config.min_core_set_clock_in_sr;
656 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
657 PHM_PlatformCaps_SclkDeepSleep))
658 graphic_level->DeepSleepDivId =
659 smu7_get_sleep_divider_id_from_clock(engine_clock,
660 data->display_timing.min_clock_in_sr);
662 /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
663 graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
666 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/
667 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/
668 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency);
669 CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel);
670 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3);
671 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4);
672 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum);
673 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2);
674 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm);
675 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1);
681 static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
683 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
684 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
685 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
686 struct smu7_dpm_table *dpm_table = &data->dpm_table;
687 struct phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table;
688 uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count;
689 uint32_t level_array_address = smu_data->smu7_data.dpm_table_start +
690 offsetof(SMU72_Discrete_DpmTable, GraphicsLevel);
692 uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) *
693 SMU72_MAX_LEVELS_GRAPHICS;
695 SMU72_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel;
697 uint32_t i, max_entry;
698 uint8_t highest_pcie_level_enabled = 0;
699 uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0;
703 memset(levels, 0x00, level_array_size);
705 for (i = 0; i < dpm_table->sclk_table.count; i++) {
706 result = tonga_populate_single_graphic_level(hwmgr,
707 dpm_table->sclk_table.dpm_levels[i].value,
708 &(smu_data->smc_state_table.GraphicsLevel[i]));
712 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
714 smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0;
717 /* Only enable level 0 for now. */
718 smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
720 /* set highest level watermark to high */
721 if (dpm_table->sclk_table.count > 1)
722 smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark =
723 PPSMC_DISPLAY_WATERMARK_HIGH;
725 smu_data->smc_state_table.GraphicsDpmLevelCount =
726 (uint8_t)dpm_table->sclk_table.count;
727 data->dpm_level_enable_mask.sclk_dpm_enable_mask =
728 phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
730 if (pcie_table != NULL) {
731 PP_ASSERT_WITH_CODE((pcie_entry_count >= 1),
732 "There must be 1 or more PCIE levels defined in PPTable.",
734 max_entry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/
735 for (i = 0; i < dpm_table->sclk_table.count; i++) {
736 smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel =
737 (uint8_t) ((i < max_entry) ? i : max_entry);
740 if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask)
741 pr_err("Pcie Dpm Enablemask is 0 !");
743 while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
744 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
745 (1<<(highest_pcie_level_enabled+1))) != 0)) {
746 highest_pcie_level_enabled++;
749 while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
750 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
751 (1<<lowest_pcie_level_enabled)) == 0)) {
752 lowest_pcie_level_enabled++;
755 while ((count < highest_pcie_level_enabled) &&
756 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
757 (1<<(lowest_pcie_level_enabled+1+count))) == 0)) {
760 mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ?
761 (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled;
764 /* set pcieDpmLevel to highest_pcie_level_enabled*/
765 for (i = 2; i < dpm_table->sclk_table.count; i++)
766 smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled;
768 /* set pcieDpmLevel to lowest_pcie_level_enabled*/
769 smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled;
771 /* set pcieDpmLevel to mid_pcie_level_enabled*/
772 smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled;
774 /* level count will send to smc once at init smc table and never change*/
775 result = smu7_copy_bytes_to_smc(hwmgr, level_array_address,
776 (uint8_t *)levels, (uint32_t)level_array_size,
782 static int tonga_calculate_mclk_params(
783 struct pp_hwmgr *hwmgr,
784 uint32_t memory_clock,
785 SMU72_Discrete_MemoryLevel *mclk,
790 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
792 uint32_t dll_cntl = data->clock_registers.vDLL_CNTL;
793 uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
794 uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL;
795 uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL;
796 uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL;
797 uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1;
798 uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2;
799 uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1;
800 uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2;
802 pp_atomctrl_memory_clock_param mpll_param;
805 result = atomctrl_get_memory_pll_dividers_si(hwmgr,
806 memory_clock, &mpll_param, strobe_mode);
809 "Error retrieving Memory Clock Parameters from VBIOS.",
812 /* MPLL_FUNC_CNTL setup*/
813 mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL,
816 /* MPLL_FUNC_CNTL_1 setup*/
817 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
818 MPLL_FUNC_CNTL_1, CLKF,
819 mpll_param.mpll_fb_divider.cl_kf);
820 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
821 MPLL_FUNC_CNTL_1, CLKFRAC,
822 mpll_param.mpll_fb_divider.clk_frac);
823 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
824 MPLL_FUNC_CNTL_1, VCO_MODE,
825 mpll_param.vco_mode);
827 /* MPLL_AD_FUNC_CNTL setup*/
828 mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl,
829 MPLL_AD_FUNC_CNTL, YCLK_POST_DIV,
830 mpll_param.mpll_post_divider);
832 if (data->is_memory_gddr5) {
833 /* MPLL_DQ_FUNC_CNTL setup*/
834 mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl,
835 MPLL_DQ_FUNC_CNTL, YCLK_SEL,
836 mpll_param.yclk_sel);
837 mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl,
838 MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV,
839 mpll_param.mpll_post_divider);
842 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
843 PHM_PlatformCaps_MemorySpreadSpectrumSupport)) {
845 ************************************
846 Fref = Reference Frequency
847 NF = Feedback divider ratio
848 NR = Reference divider ratio
849 Fnom = Nominal VCO output frequency = Fref * NF / NR
851 D = Percentage down-spread / 2
852 Fint = Reference input frequency to PFD = Fref / NR
853 NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
854 CLKS = NS - 1 = ISS_STEP_NUM[11:0]
855 NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
856 CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
857 *************************************
859 pp_atomctrl_internal_ss_info ss_info;
862 uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr);
864 /* for GDDR5 for all modes and DDR3 */
865 if (1 == mpll_param.qdr)
866 freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider);
868 freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider);
870 /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/
871 tmp = (freq_nom / reference_clock);
874 if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) {
875 /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
876 /* ss.Info.speed_spectrum_rate -- in unit of khz */
877 /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
878 /* = reference_clock * 5 / speed_spectrum_rate */
879 uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate;
881 /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
882 /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
884 (uint32_t)((((131 * ss_info.speed_spectrum_percentage *
885 ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom);
887 mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv);
888 mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks);
892 /* MCLK_PWRMGT_CNTL setup */
893 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
894 MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed);
895 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
896 MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn);
897 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
898 MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn);
900 /* Save the result data to outpupt memory level structure */
901 mclk->MclkFrequency = memory_clock;
902 mclk->MpllFuncCntl = mpll_func_cntl;
903 mclk->MpllFuncCntl_1 = mpll_func_cntl_1;
904 mclk->MpllFuncCntl_2 = mpll_func_cntl_2;
905 mclk->MpllAdFuncCntl = mpll_ad_func_cntl;
906 mclk->MpllDqFuncCntl = mpll_dq_func_cntl;
907 mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl;
908 mclk->DllCntl = dll_cntl;
909 mclk->MpllSs1 = mpll_ss1;
910 mclk->MpllSs2 = mpll_ss2;
915 static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock,
918 uint8_t mc_para_index;
921 if (memory_clock < 12500)
922 mc_para_index = 0x00;
923 else if (memory_clock > 47500)
924 mc_para_index = 0x0f;
926 mc_para_index = (uint8_t)((memory_clock - 10000) / 2500);
928 if (memory_clock < 65000)
929 mc_para_index = 0x00;
930 else if (memory_clock > 135000)
931 mc_para_index = 0x0f;
933 mc_para_index = (uint8_t)((memory_clock - 60000) / 5000);
936 return mc_para_index;
939 static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock)
941 uint8_t mc_para_index;
943 if (memory_clock < 10000)
945 else if (memory_clock >= 80000)
946 mc_para_index = 0x0f;
948 mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1);
950 return mc_para_index;
954 static int tonga_populate_single_memory_level(
955 struct pp_hwmgr *hwmgr,
956 uint32_t memory_clock,
957 SMU72_Discrete_MemoryLevel *memory_level
961 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
962 struct phm_ppt_v1_information *pptable_info =
963 (struct phm_ppt_v1_information *)(hwmgr->pptable);
966 struct cgs_display_info info = {0};
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;
973 if (hwmgr->od_enabled)
974 vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk;
976 vdd_dep_table = pptable_info->vdd_dep_on_mclk;
978 if (NULL != vdd_dep_table) {
979 result = tonga_get_dependency_volt_by_clk(hwmgr,
982 &memory_level->MinVoltage, &mvdd);
985 "can not find MinVddc voltage value from memory VDDC "
986 "voltage dependency table",
990 if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE)
991 memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value;
993 memory_level->MinMvdd = mvdd;
995 memory_level->EnabledForThrottle = 1;
996 memory_level->EnabledForActivity = 0;
997 memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
998 memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
999 memory_level->VoltageDownHyst = 0;
1001 /* Indicates maximum activity level for this performance level.*/
1002 memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
1003 memory_level->StutterEnable = 0;
1004 memory_level->StrobeEnable = 0;
1005 memory_level->EdcReadEnable = 0;
1006 memory_level->EdcWriteEnable = 0;
1007 memory_level->RttEnable = 0;
1009 /* default set to low watermark. Highest level will be set to high later.*/
1010 memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1012 cgs_get_active_displays_info(hwmgr->device, &info);
1013 data->display_timing.num_existing_displays = info.display_count;
1015 if ((mclk_stutter_mode_threshold != 0) &&
1016 (memory_clock <= mclk_stutter_mode_threshold) &&
1017 (!data->is_uvd_enabled)
1018 && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1)
1019 && (data->display_timing.num_existing_displays <= 2)
1020 && (data->display_timing.num_existing_displays != 0))
1021 memory_level->StutterEnable = 1;
1023 /* decide strobe mode*/
1024 memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) &&
1025 (memory_clock <= mclk_strobe_mode_threshold);
1027 /* decide EDC mode and memory clock ratio*/
1028 if (data->is_memory_gddr5) {
1029 memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock,
1030 memory_level->StrobeEnable);
1032 if ((mclk_edc_enable_threshold != 0) &&
1033 (memory_clock > mclk_edc_enable_threshold)) {
1034 memory_level->EdcReadEnable = 1;
1037 if ((mclk_edc_wr_enable_threshold != 0) &&
1038 (memory_clock > mclk_edc_wr_enable_threshold)) {
1039 memory_level->EdcWriteEnable = 1;
1042 if (memory_level->StrobeEnable) {
1043 if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >=
1044 ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) {
1045 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
1047 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0;
1051 dll_state_on = data->dll_default_on;
1054 memory_level->StrobeRatio =
1055 tonga_get_ddr3_mclk_frequency_ratio(memory_clock);
1056 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
1059 result = tonga_calculate_mclk_params(hwmgr,
1060 memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on);
1063 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd);
1064 /* MCLK frequency in units of 10KHz*/
1065 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency);
1066 /* Indicates maximum activity level for this performance level.*/
1067 CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel);
1068 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl);
1069 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1);
1070 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2);
1071 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl);
1072 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl);
1073 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl);
1074 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl);
1075 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1);
1076 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2);
1082 int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1084 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1085 struct tonga_smumgr *smu_data =
1086 (struct tonga_smumgr *)(hwmgr->smu_backend);
1087 struct smu7_dpm_table *dpm_table = &data->dpm_table;
1090 /* populate MCLK dpm table to SMU7 */
1091 uint32_t level_array_address =
1092 smu_data->smu7_data.dpm_table_start +
1093 offsetof(SMU72_Discrete_DpmTable, MemoryLevel);
1094 uint32_t level_array_size =
1095 sizeof(SMU72_Discrete_MemoryLevel) *
1096 SMU72_MAX_LEVELS_MEMORY;
1097 SMU72_Discrete_MemoryLevel *levels =
1098 smu_data->smc_state_table.MemoryLevel;
1101 memset(levels, 0x00, level_array_size);
1103 for (i = 0; i < dpm_table->mclk_table.count; i++) {
1104 PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
1105 "can not populate memory level as memory clock is zero",
1107 result = tonga_populate_single_memory_level(
1109 dpm_table->mclk_table.dpm_levels[i].value,
1110 &(smu_data->smc_state_table.MemoryLevel[i]));
1115 /* Only enable level 0 for now.*/
1116 smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
1119 * in order to prevent MC activity from stutter mode to push DPM up.
1120 * the UVD change complements this by putting the MCLK in a higher state
1121 * by default such that we are not effected by up threshold or and MCLK DPM latency.
1123 smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F;
1124 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel);
1126 smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count;
1127 data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
1128 /* set highest level watermark to high*/
1129 smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
1131 /* level count will send to smc once at init smc table and never change*/
1132 result = smu7_copy_bytes_to_smc(hwmgr,
1133 level_array_address, (uint8_t *)levels, (uint32_t)level_array_size,
1139 static int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr,
1140 uint32_t mclk, SMIO_Pattern *smio_pattern)
1142 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1143 struct phm_ppt_v1_information *table_info =
1144 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1147 if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
1148 /* find mvdd value which clock is more than request */
1149 for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) {
1150 if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) {
1151 /* Always round to higher voltage. */
1152 smio_pattern->Voltage =
1153 data->mvdd_voltage_table.entries[i].value;
1158 PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count,
1159 "MVDD Voltage is outside the supported range.",
1169 static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
1170 SMU72_Discrete_DpmTable *table)
1173 struct tonga_smumgr *smu_data =
1174 (struct tonga_smumgr *)(hwmgr->smu_backend);
1175 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1176 struct pp_atomctrl_clock_dividers_vi dividers;
1178 SMIO_Pattern voltage_level;
1179 uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL;
1180 uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
1181 uint32_t dll_cntl = data->clock_registers.vDLL_CNTL;
1182 uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
1184 /* The ACPI state should not do DPM on DC (or ever).*/
1185 table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
1187 table->ACPILevel.MinVoltage =
1188 smu_data->smc_state_table.GraphicsLevel[0].MinVoltage;
1190 /* assign zero for now*/
1191 table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr);
1193 /* get the engine clock dividers for this clock value*/
1194 result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
1195 table->ACPILevel.SclkFrequency, ÷rs);
1197 PP_ASSERT_WITH_CODE(result == 0,
1198 "Error retrieving Engine Clock dividers from VBIOS.",
1201 /* divider ID for required SCLK*/
1202 table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
1203 table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1204 table->ACPILevel.DeepSleepDivId = 0;
1206 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
1208 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL,
1210 spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2,
1213 table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
1214 table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
1215 table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
1216 table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
1217 table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
1218 table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
1219 table->ACPILevel.CcPwrDynRm = 0;
1220 table->ACPILevel.CcPwrDynRm1 = 0;
1223 /* For various features to be enabled/disabled while this level is active.*/
1224 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
1225 /* SCLK frequency in units of 10KHz*/
1226 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
1227 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
1228 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
1229 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
1230 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
1231 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
1232 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
1233 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
1234 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
1236 /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
1237 table->MemoryACPILevel.MinVoltage =
1238 smu_data->smc_state_table.MemoryLevel[0].MinVoltage;
1240 /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/
1242 if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level))
1243 table->MemoryACPILevel.MinMvdd =
1244 PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE);
1246 table->MemoryACPILevel.MinMvdd = 0;
1248 /* Force reset on DLL*/
1249 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1250 MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1);
1251 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1252 MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1);
1254 /* Disable DLL in ACPIState*/
1255 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1256 MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0);
1257 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1258 MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0);
1260 /* Enable DLL bypass signal*/
1261 dll_cntl = PHM_SET_FIELD(dll_cntl,
1262 DLL_CNTL, MRDCK0_BYPASS, 0);
1263 dll_cntl = PHM_SET_FIELD(dll_cntl,
1264 DLL_CNTL, MRDCK1_BYPASS, 0);
1266 table->MemoryACPILevel.DllCntl =
1267 PP_HOST_TO_SMC_UL(dll_cntl);
1268 table->MemoryACPILevel.MclkPwrmgtCntl =
1269 PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl);
1270 table->MemoryACPILevel.MpllAdFuncCntl =
1271 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL);
1272 table->MemoryACPILevel.MpllDqFuncCntl =
1273 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL);
1274 table->MemoryACPILevel.MpllFuncCntl =
1275 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL);
1276 table->MemoryACPILevel.MpllFuncCntl_1 =
1277 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1);
1278 table->MemoryACPILevel.MpllFuncCntl_2 =
1279 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2);
1280 table->MemoryACPILevel.MpllSs1 =
1281 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1);
1282 table->MemoryACPILevel.MpllSs2 =
1283 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2);
1285 table->MemoryACPILevel.EnabledForThrottle = 0;
1286 table->MemoryACPILevel.EnabledForActivity = 0;
1287 table->MemoryACPILevel.UpHyst = 0;
1288 table->MemoryACPILevel.DownHyst = 100;
1289 table->MemoryACPILevel.VoltageDownHyst = 0;
1290 /* Indicates maximum activity level for this performance level.*/
1291 table->MemoryACPILevel.ActivityLevel =
1292 PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
1294 table->MemoryACPILevel.StutterEnable = 0;
1295 table->MemoryACPILevel.StrobeEnable = 0;
1296 table->MemoryACPILevel.EdcReadEnable = 0;
1297 table->MemoryACPILevel.EdcWriteEnable = 0;
1298 table->MemoryACPILevel.RttEnable = 0;
1303 static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
1304 SMU72_Discrete_DpmTable *table)
1309 pp_atomctrl_clock_dividers_vi dividers;
1310 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1311 struct phm_ppt_v1_information *pptable_info =
1312 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1313 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1314 pptable_info->mm_dep_table;
1316 table->UvdLevelCount = (uint8_t) (mm_table->count);
1317 table->UvdBootLevel = 0;
1319 for (count = 0; count < table->UvdLevelCount; count++) {
1320 table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
1321 table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
1322 table->UvdLevel[count].MinVoltage.Vddc =
1323 phm_get_voltage_index(pptable_info->vddc_lookup_table,
1324 mm_table->entries[count].vddc);
1325 table->UvdLevel[count].MinVoltage.VddGfx =
1326 (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ?
1327 phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
1328 mm_table->entries[count].vddgfx) : 0;
1329 table->UvdLevel[count].MinVoltage.Vddci =
1330 phm_get_voltage_id(&data->vddci_voltage_table,
1331 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1332 table->UvdLevel[count].MinVoltage.Phases = 1;
1334 /* retrieve divider value for VBIOS */
1335 result = atomctrl_get_dfs_pll_dividers_vi(
1337 table->UvdLevel[count].VclkFrequency,
1340 PP_ASSERT_WITH_CODE((!result),
1341 "can not find divide id for Vclk clock",
1344 table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
1346 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1347 table->UvdLevel[count].DclkFrequency, ÷rs);
1348 PP_ASSERT_WITH_CODE((!result),
1349 "can not find divide id for Dclk clock",
1352 table->UvdLevel[count].DclkDivider =
1353 (uint8_t)dividers.pll_post_divider;
1355 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
1356 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
1363 static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
1364 SMU72_Discrete_DpmTable *table)
1369 pp_atomctrl_clock_dividers_vi dividers;
1370 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1371 struct phm_ppt_v1_information *pptable_info =
1372 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1373 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1374 pptable_info->mm_dep_table;
1376 table->VceLevelCount = (uint8_t) (mm_table->count);
1377 table->VceBootLevel = 0;
1379 for (count = 0; count < table->VceLevelCount; count++) {
1380 table->VceLevel[count].Frequency =
1381 mm_table->entries[count].eclk;
1382 table->VceLevel[count].MinVoltage.Vddc =
1383 phm_get_voltage_index(pptable_info->vddc_lookup_table,
1384 mm_table->entries[count].vddc);
1385 table->VceLevel[count].MinVoltage.VddGfx =
1386 (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ?
1387 phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
1388 mm_table->entries[count].vddgfx) : 0;
1389 table->VceLevel[count].MinVoltage.Vddci =
1390 phm_get_voltage_id(&data->vddci_voltage_table,
1391 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1392 table->VceLevel[count].MinVoltage.Phases = 1;
1394 /* retrieve divider value for VBIOS */
1395 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1396 table->VceLevel[count].Frequency, ÷rs);
1397 PP_ASSERT_WITH_CODE((!result),
1398 "can not find divide id for VCE engine clock",
1401 table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1403 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
1409 static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
1410 SMU72_Discrete_DpmTable *table)
1414 pp_atomctrl_clock_dividers_vi dividers;
1415 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1416 struct phm_ppt_v1_information *pptable_info =
1417 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1418 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1419 pptable_info->mm_dep_table;
1421 table->AcpLevelCount = (uint8_t) (mm_table->count);
1422 table->AcpBootLevel = 0;
1424 for (count = 0; count < table->AcpLevelCount; count++) {
1425 table->AcpLevel[count].Frequency =
1426 pptable_info->mm_dep_table->entries[count].aclk;
1427 table->AcpLevel[count].MinVoltage.Vddc =
1428 phm_get_voltage_index(pptable_info->vddc_lookup_table,
1429 mm_table->entries[count].vddc);
1430 table->AcpLevel[count].MinVoltage.VddGfx =
1431 (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ?
1432 phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
1433 mm_table->entries[count].vddgfx) : 0;
1434 table->AcpLevel[count].MinVoltage.Vddci =
1435 phm_get_voltage_id(&data->vddci_voltage_table,
1436 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1437 table->AcpLevel[count].MinVoltage.Phases = 1;
1439 /* retrieve divider value for VBIOS */
1440 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1441 table->AcpLevel[count].Frequency, ÷rs);
1442 PP_ASSERT_WITH_CODE((!result),
1443 "can not find divide id for engine clock", return result);
1445 table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1447 CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency);
1453 static int tonga_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
1454 SMU72_Discrete_DpmTable *table)
1458 pp_atomctrl_clock_dividers_vi dividers;
1459 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1460 struct phm_ppt_v1_information *pptable_info =
1461 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1462 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1463 pptable_info->mm_dep_table;
1465 table->SamuBootLevel = 0;
1466 table->SamuLevelCount = (uint8_t) (mm_table->count);
1468 for (count = 0; count < table->SamuLevelCount; count++) {
1469 /* not sure whether we need evclk or not */
1470 table->SamuLevel[count].Frequency =
1471 pptable_info->mm_dep_table->entries[count].samclock;
1472 table->SamuLevel[count].MinVoltage.Vddc =
1473 phm_get_voltage_index(pptable_info->vddc_lookup_table,
1474 mm_table->entries[count].vddc);
1475 table->SamuLevel[count].MinVoltage.VddGfx =
1476 (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ?
1477 phm_get_voltage_index(pptable_info->vddgfx_lookup_table,
1478 mm_table->entries[count].vddgfx) : 0;
1479 table->SamuLevel[count].MinVoltage.Vddci =
1480 phm_get_voltage_id(&data->vddci_voltage_table,
1481 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1482 table->SamuLevel[count].MinVoltage.Phases = 1;
1484 /* retrieve divider value for VBIOS */
1485 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1486 table->SamuLevel[count].Frequency, ÷rs);
1487 PP_ASSERT_WITH_CODE((!result),
1488 "can not find divide id for samu clock", return result);
1490 table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1492 CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
1498 static int tonga_populate_memory_timing_parameters(
1499 struct pp_hwmgr *hwmgr,
1500 uint32_t engine_clock,
1501 uint32_t memory_clock,
1502 struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs
1505 uint32_t dramTiming;
1506 uint32_t dramTiming2;
1510 result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
1511 engine_clock, memory_clock);
1513 PP_ASSERT_WITH_CODE(result == 0,
1514 "Error calling VBIOS to set DRAM_TIMING.", return result);
1516 dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
1517 dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
1518 burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
1520 arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming);
1521 arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2);
1522 arb_regs->McArbBurstTime = (uint8_t)burstTime;
1527 static int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
1529 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1530 struct tonga_smumgr *smu_data =
1531 (struct tonga_smumgr *)(hwmgr->smu_backend);
1533 SMU72_Discrete_MCArbDramTimingTable arb_regs;
1536 memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable));
1538 for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
1539 for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
1540 result = tonga_populate_memory_timing_parameters
1541 (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value,
1542 data->dpm_table.mclk_table.dpm_levels[j].value,
1543 &arb_regs.entries[i][j]);
1551 result = smu7_copy_bytes_to_smc(
1553 smu_data->smu7_data.arb_table_start,
1554 (uint8_t *)&arb_regs,
1555 sizeof(SMU72_Discrete_MCArbDramTimingTable),
1563 static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
1564 SMU72_Discrete_DpmTable *table)
1567 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1568 struct tonga_smumgr *smu_data =
1569 (struct tonga_smumgr *)(hwmgr->smu_backend);
1570 table->GraphicsBootLevel = 0;
1571 table->MemoryBootLevel = 0;
1573 /* find boot level from dpm table*/
1574 result = phm_find_boot_level(&(data->dpm_table.sclk_table),
1575 data->vbios_boot_state.sclk_bootup_value,
1576 (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel));
1579 smu_data->smc_state_table.GraphicsBootLevel = 0;
1580 pr_err("[powerplay] VBIOS did not find boot engine "
1581 "clock value in dependency table. "
1582 "Using Graphics DPM level 0 !");
1586 result = phm_find_boot_level(&(data->dpm_table.mclk_table),
1587 data->vbios_boot_state.mclk_bootup_value,
1588 (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel));
1591 smu_data->smc_state_table.MemoryBootLevel = 0;
1592 pr_err("[powerplay] VBIOS did not find boot "
1593 "engine clock value in dependency table."
1594 "Using Memory DPM level 0 !");
1598 table->BootVoltage.Vddc =
1599 phm_get_voltage_id(&(data->vddc_voltage_table),
1600 data->vbios_boot_state.vddc_bootup_value);
1601 table->BootVoltage.VddGfx =
1602 phm_get_voltage_id(&(data->vddgfx_voltage_table),
1603 data->vbios_boot_state.vddgfx_bootup_value);
1604 table->BootVoltage.Vddci =
1605 phm_get_voltage_id(&(data->vddci_voltage_table),
1606 data->vbios_boot_state.vddci_bootup_value);
1607 table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value;
1609 CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
1614 static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
1616 uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks,
1617 volt_with_cks, value;
1618 uint16_t clock_freq_u16;
1619 struct tonga_smumgr *smu_data =
1620 (struct tonga_smumgr *)(hwmgr->smu_backend);
1621 uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2,
1623 struct phm_ppt_v1_information *table_info =
1624 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1625 struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
1626 table_info->vdd_dep_on_sclk;
1627 uint32_t hw_revision, dev_id;
1628 struct amdgpu_device *adev = hwmgr->adev;
1630 stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount;
1632 hw_revision = adev->pdev->revision;
1633 dev_id = adev->pdev->device;
1635 /* Read SMU_Eefuse to read and calculate RO and determine
1636 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1638 efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1639 ixSMU_EFUSE_0 + (146 * 4));
1640 efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1641 ixSMU_EFUSE_0 + (148 * 4));
1642 efuse &= 0xFF000000;
1643 efuse = efuse >> 24;
1647 ro = (2300 - 1350) * efuse / 255 + 1350;
1649 ro = (2500 - 1000) * efuse / 255 + 1000;
1656 /* Populate Stretch amount */
1657 smu_data->smc_state_table.ClockStretcherAmount = stretch_amount;
1660 /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1661 for (i = 0; i < sclk_table->count; i++) {
1662 smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |=
1663 sclk_table->entries[i].cks_enable << i;
1664 if (ASICID_IS_TONGA_P(dev_id, hw_revision)) {
1665 volt_without_cks = (uint32_t)((7732 + 60 - ro - 20838 *
1666 (sclk_table->entries[i].clk/100) / 10000) * 1000 /
1667 (8730 - (5301 * (sclk_table->entries[i].clk/100) / 1000)));
1668 volt_with_cks = (uint32_t)((5250 + 51 - ro - 2404 *
1669 (sclk_table->entries[i].clk/100) / 100000) * 1000 /
1670 (6146 - (3193 * (sclk_table->entries[i].clk/100) / 1000)));
1672 volt_without_cks = (uint32_t)((14041 *
1673 (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 /
1674 (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000)));
1675 volt_with_cks = (uint32_t)((13946 *
1676 (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 /
1677 (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000)));
1679 if (volt_without_cks >= volt_with_cks)
1680 volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
1681 sclk_table->entries[i].cks_voffset) * 100 / 625) + 1);
1682 smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
1685 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1686 STRETCH_ENABLE, 0x0);
1687 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1689 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1691 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
1694 /* Populate CKS Lookup Table */
1695 if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
1696 stretch_amount2 = 0;
1697 else if (stretch_amount == 3 || stretch_amount == 4)
1698 stretch_amount2 = 1;
1700 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1701 PHM_PlatformCaps_ClockStretcher);
1702 PP_ASSERT_WITH_CODE(false,
1703 "Stretch Amount in PPTable not supported",
1707 value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1709 value &= 0xFFC2FF87;
1710 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq =
1711 tonga_clock_stretcher_lookup_table[stretch_amount2][0];
1712 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq =
1713 tonga_clock_stretcher_lookup_table[stretch_amount2][1];
1714 clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table.
1715 GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1].
1716 SclkFrequency) / 100);
1717 if (tonga_clock_stretcher_lookup_table[stretch_amount2][0] <
1719 tonga_clock_stretcher_lookup_table[stretch_amount2][1] >
1721 /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
1722 value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 16;
1723 /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
1724 value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][2]) << 18;
1725 /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
1726 value |= (tonga_clock_stretch_amount_conversion
1727 [tonga_clock_stretcher_lookup_table[stretch_amount2][3]]
1728 [stretch_amount]) << 3;
1730 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable.
1731 CKS_LOOKUPTableEntry[0].minFreq);
1732 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable.
1733 CKS_LOOKUPTableEntry[0].maxFreq);
1734 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting =
1735 tonga_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F;
1736 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |=
1737 (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 7;
1739 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1740 ixPWR_CKS_CNTL, value);
1742 /* Populate DDT Lookup Table */
1743 for (i = 0; i < 4; i++) {
1744 /* Assign the minimum and maximum VID stored
1745 * in the last row of Clock Stretcher Voltage Table.
1747 smu_data->smc_state_table.ClockStretcherDataTable.
1748 ClockStretcherDataTableEntry[i].minVID =
1749 (uint8_t) tonga_clock_stretcher_ddt_table[type][i][2];
1750 smu_data->smc_state_table.ClockStretcherDataTable.
1751 ClockStretcherDataTableEntry[i].maxVID =
1752 (uint8_t) tonga_clock_stretcher_ddt_table[type][i][3];
1753 /* Loop through each SCLK and check the frequency
1754 * to see if it lies within the frequency for clock stretcher.
1756 for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) {
1758 clock_freq = PP_SMC_TO_HOST_UL(
1759 smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency);
1760 /* Check the allowed frequency against the sclk level[j].
1761 * Sclk's endianness has already been converted,
1762 * and it's in 10Khz unit,
1763 * as opposed to Data table, which is in Mhz unit.
1765 if (clock_freq >= tonga_clock_stretcher_ddt_table[type][i][0] * 100) {
1767 if (clock_freq < tonga_clock_stretcher_ddt_table[type][i][1] * 100)
1770 smu_data->smc_state_table.ClockStretcherDataTable.
1771 ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2);
1773 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.
1774 ClockStretcherDataTable.
1775 ClockStretcherDataTableEntry[i].setting);
1778 value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1780 value &= 0xFFFFFFFE;
1781 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1782 ixPWR_CKS_CNTL, value);
1787 static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr,
1788 SMU72_Discrete_DpmTable *table)
1790 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1793 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
1795 config = VR_SVI2_PLANE_1;
1796 table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
1798 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1799 config = VR_SVI2_PLANE_2;
1800 table->VRConfig |= config;
1802 pr_err("VDDC and VDDGFX should "
1803 "be both on SVI2 control in splitted mode !\n");
1807 config = VR_MERGED_WITH_VDDC;
1808 table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
1810 /* Set Vddc Voltage Controller */
1811 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1812 config = VR_SVI2_PLANE_1;
1813 table->VRConfig |= config;
1815 pr_err("VDDC should be on "
1816 "SVI2 control in merged mode !\n");
1820 /* Set Vddci Voltage Controller */
1821 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
1822 config = VR_SVI2_PLANE_2; /* only in merged mode */
1823 table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
1824 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
1825 config = VR_SMIO_PATTERN_1;
1826 table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
1829 /* Set Mvdd Voltage Controller */
1830 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
1831 config = VR_SMIO_PATTERN_2;
1832 table->VRConfig |= (config<<VRCONF_MVDD_SHIFT);
1838 static int tonga_init_arb_table_index(struct pp_hwmgr *hwmgr)
1840 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
1845 * This is a read-modify-write on the first byte of the ARB table.
1846 * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure
1847 * is the field 'current'.
1848 * This solution is ugly, but we never write the whole table only
1849 * individual fields in it.
1850 * In reality this field should not be in that structure
1851 * but in a soft register.
1853 result = smu7_read_smc_sram_dword(hwmgr,
1854 smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END);
1860 tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
1862 return smu7_write_smc_sram_dword(hwmgr,
1863 smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END);
1867 static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
1869 struct tonga_smumgr *smu_data =
1870 (struct tonga_smumgr *)(hwmgr->smu_backend);
1871 const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults;
1872 SMU72_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table);
1873 struct phm_ppt_v1_information *table_info =
1874 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1875 struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table;
1877 const uint16_t *pdef1, *pdef2;
1879 dpm_table->DefaultTdp = PP_HOST_TO_SMC_US(
1880 (uint16_t)(cac_dtp_table->usTDP * 256));
1881 dpm_table->TargetTdp = PP_HOST_TO_SMC_US(
1882 (uint16_t)(cac_dtp_table->usConfigurableTDP * 256));
1884 PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
1885 "Target Operating Temp is out of Range !",
1888 dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp);
1889 dpm_table->GpuTjHyst = 8;
1891 dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base;
1893 dpm_table->BAPM_TEMP_GRADIENT =
1894 PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient);
1895 pdef1 = defaults->bapmti_r;
1896 pdef2 = defaults->bapmti_rc;
1898 for (i = 0; i < SMU72_DTE_ITERATIONS; i++) {
1899 for (j = 0; j < SMU72_DTE_SOURCES; j++) {
1900 for (k = 0; k < SMU72_DTE_SINKS; k++) {
1901 dpm_table->BAPMTI_R[i][j][k] =
1902 PP_HOST_TO_SMC_US(*pdef1);
1903 dpm_table->BAPMTI_RC[i][j][k] =
1904 PP_HOST_TO_SMC_US(*pdef2);
1914 static int tonga_populate_svi_load_line(struct pp_hwmgr *hwmgr)
1916 struct tonga_smumgr *smu_data =
1917 (struct tonga_smumgr *)(hwmgr->smu_backend);
1918 const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults;
1920 smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en;
1921 smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddC;
1922 smu_data->power_tune_table.SviLoadLineTrimVddC = 3;
1923 smu_data->power_tune_table.SviLoadLineOffsetVddC = 0;
1928 static int tonga_populate_tdc_limit(struct pp_hwmgr *hwmgr)
1931 struct tonga_smumgr *smu_data =
1932 (struct tonga_smumgr *)(hwmgr->smu_backend);
1933 const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults;
1934 struct phm_ppt_v1_information *table_info =
1935 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1937 /* TDC number of fraction bits are changed from 8 to 7
1938 * for Fiji as requested by SMC team
1940 tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 256);
1941 smu_data->power_tune_table.TDC_VDDC_PkgLimit =
1942 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
1943 smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
1944 defaults->tdc_vddc_throttle_release_limit_perc;
1945 smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt;
1950 static int tonga_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
1952 struct tonga_smumgr *smu_data =
1953 (struct tonga_smumgr *)(hwmgr->smu_backend);
1954 const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults;
1957 if (smu7_read_smc_sram_dword(hwmgr,
1959 offsetof(SMU72_Discrete_PmFuses, TdcWaterfallCtl),
1960 (uint32_t *)&temp, SMC_RAM_END))
1961 PP_ASSERT_WITH_CODE(false,
1962 "Attempt to read PmFuses.DW6 "
1963 "(SviLoadLineEn) from SMC Failed !",
1966 smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl;
1971 static int tonga_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
1974 struct tonga_smumgr *smu_data =
1975 (struct tonga_smumgr *)(hwmgr->smu_backend);
1977 /* Currently not used. Set all to zero. */
1978 for (i = 0; i < 16; i++)
1979 smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0;
1984 static int tonga_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
1986 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
1988 if ((hwmgr->thermal_controller.advanceFanControlParameters.
1989 usFanOutputSensitivity & (1 << 15)) ||
1990 (hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity == 0))
1991 hwmgr->thermal_controller.advanceFanControlParameters.
1992 usFanOutputSensitivity = hwmgr->thermal_controller.
1993 advanceFanControlParameters.usDefaultFanOutputSensitivity;
1995 smu_data->power_tune_table.FuzzyFan_PwmSetDelta =
1996 PP_HOST_TO_SMC_US(hwmgr->thermal_controller.
1997 advanceFanControlParameters.usFanOutputSensitivity);
2001 static int tonga_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
2004 struct tonga_smumgr *smu_data =
2005 (struct tonga_smumgr *)(hwmgr->smu_backend);
2007 /* Currently not used. Set all to zero. */
2008 for (i = 0; i < 16; i++)
2009 smu_data->power_tune_table.GnbLPML[i] = 0;
2014 static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
2016 struct tonga_smumgr *smu_data =
2017 (struct tonga_smumgr *)(hwmgr->smu_backend);
2018 struct phm_ppt_v1_information *table_info =
2019 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2020 uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd;
2021 uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd;
2022 struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
2024 hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
2025 lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
2027 smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd =
2028 CONVERT_FROM_HOST_TO_SMC_US(hi_sidd);
2029 smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd =
2030 CONVERT_FROM_HOST_TO_SMC_US(lo_sidd);
2035 static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr)
2037 struct tonga_smumgr *smu_data =
2038 (struct tonga_smumgr *)(hwmgr->smu_backend);
2039 uint32_t pm_fuse_table_offset;
2041 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2042 PHM_PlatformCaps_PowerContainment)) {
2043 if (smu7_read_smc_sram_dword(hwmgr,
2044 SMU72_FIRMWARE_HEADER_LOCATION +
2045 offsetof(SMU72_Firmware_Header, PmFuseTable),
2046 &pm_fuse_table_offset, SMC_RAM_END))
2047 PP_ASSERT_WITH_CODE(false,
2048 "Attempt to get pm_fuse_table_offset Failed !",
2052 if (tonga_populate_svi_load_line(hwmgr))
2053 PP_ASSERT_WITH_CODE(false,
2054 "Attempt to populate SviLoadLine Failed !",
2057 if (tonga_populate_tdc_limit(hwmgr))
2058 PP_ASSERT_WITH_CODE(false,
2059 "Attempt to populate TDCLimit Failed !",
2062 if (tonga_populate_dw8(hwmgr, pm_fuse_table_offset))
2063 PP_ASSERT_WITH_CODE(false,
2064 "Attempt to populate TdcWaterfallCtl Failed !",
2068 if (tonga_populate_temperature_scaler(hwmgr) != 0)
2069 PP_ASSERT_WITH_CODE(false,
2070 "Attempt to populate LPMLTemperatureScaler Failed !",
2074 if (tonga_populate_fuzzy_fan(hwmgr))
2075 PP_ASSERT_WITH_CODE(false,
2076 "Attempt to populate Fuzzy Fan "
2077 "Control parameters Failed !",
2081 if (tonga_populate_gnb_lpml(hwmgr))
2082 PP_ASSERT_WITH_CODE(false,
2083 "Attempt to populate GnbLPML Failed !",
2087 if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr))
2088 PP_ASSERT_WITH_CODE(
2090 "Attempt to populate BapmVddCBaseLeakage "
2091 "Hi and Lo Sidd Failed !",
2094 if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset,
2095 (uint8_t *)&smu_data->power_tune_table,
2096 sizeof(struct SMU72_Discrete_PmFuses), SMC_RAM_END))
2097 PP_ASSERT_WITH_CODE(false,
2098 "Attempt to download PmFuseTable Failed !",
2104 static int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr,
2105 SMU72_Discrete_MCRegisters *mc_reg_table)
2107 const struct tonga_smumgr *smu_data = (struct tonga_smumgr *)hwmgr->smu_backend;
2111 for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) {
2112 if (smu_data->mc_reg_table.validflag & 1<<j) {
2113 PP_ASSERT_WITH_CODE(
2114 i < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE,
2115 "Index of mc_reg_table->address[] array "
2118 mc_reg_table->address[i].s0 =
2119 PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0);
2120 mc_reg_table->address[i].s1 =
2121 PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1);
2126 mc_reg_table->last = (uint8_t)i;
2131 /*convert register values from driver to SMC format */
2132 static void tonga_convert_mc_registers(
2133 const struct tonga_mc_reg_entry *entry,
2134 SMU72_Discrete_MCRegisterSet *data,
2135 uint32_t num_entries, uint32_t valid_flag)
2139 for (i = 0, j = 0; j < num_entries; j++) {
2140 if (valid_flag & 1<<j) {
2141 data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]);
2147 static int tonga_convert_mc_reg_table_entry_to_smc(
2148 struct pp_hwmgr *hwmgr,
2149 const uint32_t memory_clock,
2150 SMU72_Discrete_MCRegisterSet *mc_reg_table_data
2153 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2156 for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) {
2158 smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) {
2163 if ((i == smu_data->mc_reg_table.num_entries) && (i > 0))
2166 tonga_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i],
2167 mc_reg_table_data, smu_data->mc_reg_table.last,
2168 smu_data->mc_reg_table.validflag);
2173 static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr,
2174 SMU72_Discrete_MCRegisters *mc_regs)
2177 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2181 for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
2182 res = tonga_convert_mc_reg_table_entry_to_smc(
2184 data->dpm_table.mclk_table.dpm_levels[i].value,
2195 static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr)
2197 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2198 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2202 if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK))
2206 memset(&smu_data->mc_regs, 0, sizeof(SMU72_Discrete_MCRegisters));
2208 result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs));
2214 address = smu_data->smu7_data.mc_reg_table_start +
2215 (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]);
2217 return smu7_copy_bytes_to_smc(
2219 (uint8_t *)&smu_data->mc_regs.data[0],
2220 sizeof(SMU72_Discrete_MCRegisterSet) *
2221 data->dpm_table.mclk_table.count,
2225 static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr)
2228 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2230 memset(&smu_data->mc_regs, 0x00, sizeof(SMU72_Discrete_MCRegisters));
2231 result = tonga_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs));
2232 PP_ASSERT_WITH_CODE(!result,
2233 "Failed to initialize MCRegTable for the MC register addresses !",
2236 result = tonga_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs);
2237 PP_ASSERT_WITH_CODE(!result,
2238 "Failed to initialize MCRegTable for driver state !",
2241 return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start,
2242 (uint8_t *)&smu_data->mc_regs, sizeof(SMU72_Discrete_MCRegisters), SMC_RAM_END);
2245 static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
2247 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2248 struct phm_ppt_v1_information *table_info =
2249 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2252 table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX &&
2253 table_info->cac_dtp_table->usPowerTuneDataSetID)
2254 smu_data->power_tune_defaults =
2255 &tonga_power_tune_data_set_array
2256 [table_info->cac_dtp_table->usPowerTuneDataSetID - 1];
2258 smu_data->power_tune_defaults = &tonga_power_tune_data_set_array[0];
2261 static int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
2264 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2265 struct tonga_smumgr *smu_data =
2266 (struct tonga_smumgr *)(hwmgr->smu_backend);
2267 SMU72_Discrete_DpmTable *table = &(smu_data->smc_state_table);
2268 struct phm_ppt_v1_information *table_info =
2269 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2272 pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
2275 memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table));
2277 tonga_initialize_power_tune_defaults(hwmgr);
2279 if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control)
2280 tonga_populate_smc_voltage_tables(hwmgr, table);
2282 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2283 PHM_PlatformCaps_AutomaticDCTransition))
2284 table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
2287 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2288 PHM_PlatformCaps_StepVddc))
2289 table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
2291 if (data->is_memory_gddr5)
2292 table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
2294 i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN);
2296 if (i == 1 || i == 0)
2297 table->SystemFlags |= 0x40;
2299 if (data->ulv_supported && table_info->us_ulv_voltage_offset) {
2300 result = tonga_populate_ulv_state(hwmgr, table);
2301 PP_ASSERT_WITH_CODE(!result,
2302 "Failed to initialize ULV state !",
2305 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
2306 ixCG_ULV_PARAMETER, 0x40035);
2309 result = tonga_populate_smc_link_level(hwmgr, table);
2310 PP_ASSERT_WITH_CODE(!result,
2311 "Failed to initialize Link Level !", return result);
2313 result = tonga_populate_all_graphic_levels(hwmgr);
2314 PP_ASSERT_WITH_CODE(!result,
2315 "Failed to initialize Graphics Level !", return result);
2317 result = tonga_populate_all_memory_levels(hwmgr);
2318 PP_ASSERT_WITH_CODE(!result,
2319 "Failed to initialize Memory Level !", return result);
2321 result = tonga_populate_smc_acpi_level(hwmgr, table);
2322 PP_ASSERT_WITH_CODE(!result,
2323 "Failed to initialize ACPI Level !", return result);
2325 result = tonga_populate_smc_vce_level(hwmgr, table);
2326 PP_ASSERT_WITH_CODE(!result,
2327 "Failed to initialize VCE Level !", return result);
2329 result = tonga_populate_smc_acp_level(hwmgr, table);
2330 PP_ASSERT_WITH_CODE(!result,
2331 "Failed to initialize ACP Level !", return result);
2333 result = tonga_populate_smc_samu_level(hwmgr, table);
2334 PP_ASSERT_WITH_CODE(!result,
2335 "Failed to initialize SAMU Level !", return result);
2337 /* Since only the initial state is completely set up at this
2338 * point (the other states are just copies of the boot state) we only
2339 * need to populate the ARB settings for the initial state.
2341 result = tonga_program_memory_timing_parameters(hwmgr);
2342 PP_ASSERT_WITH_CODE(!result,
2343 "Failed to Write ARB settings for the initial state.",
2346 result = tonga_populate_smc_uvd_level(hwmgr, table);
2347 PP_ASSERT_WITH_CODE(!result,
2348 "Failed to initialize UVD Level !", return result);
2350 result = tonga_populate_smc_boot_level(hwmgr, table);
2351 PP_ASSERT_WITH_CODE(!result,
2352 "Failed to initialize Boot Level !", return result);
2354 tonga_populate_bapm_parameters_in_dpm_table(hwmgr);
2355 PP_ASSERT_WITH_CODE(!result,
2356 "Failed to populate BAPM Parameters !", return result);
2358 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2359 PHM_PlatformCaps_ClockStretcher)) {
2360 result = tonga_populate_clock_stretcher_data_table(hwmgr);
2361 PP_ASSERT_WITH_CODE(!result,
2362 "Failed to populate Clock Stretcher Data Table !",
2365 table->GraphicsVoltageChangeEnable = 1;
2366 table->GraphicsThermThrottleEnable = 1;
2367 table->GraphicsInterval = 1;
2368 table->VoltageInterval = 1;
2369 table->ThermalInterval = 1;
2370 table->TemperatureLimitHigh =
2371 table_info->cac_dtp_table->usTargetOperatingTemp *
2372 SMU7_Q88_FORMAT_CONVERSION_UNIT;
2373 table->TemperatureLimitLow =
2374 (table_info->cac_dtp_table->usTargetOperatingTemp - 1) *
2375 SMU7_Q88_FORMAT_CONVERSION_UNIT;
2376 table->MemoryVoltageChangeEnable = 1;
2377 table->MemoryInterval = 1;
2378 table->VoltageResponseTime = 0;
2379 table->PhaseResponseTime = 0;
2380 table->MemoryThermThrottleEnable = 1;
2383 * Cail reads current link status and reports it as cap (we cannot
2384 * change this due to some previous issues we had)
2385 * SMC drops the link status to lowest level after enabling
2386 * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again
2387 * but this time Cail reads current link status which was set to low by
2388 * SMC and reports it as cap to powerplay
2389 * To avoid it, we set PCIeBootLinkLevel to highest dpm level
2391 PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count),
2392 "There must be 1 or more PCIE levels defined in PPTable.",
2395 table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count);
2397 table->PCIeGenInterval = 1;
2399 result = tonga_populate_vr_config(hwmgr, table);
2400 PP_ASSERT_WITH_CODE(!result,
2401 "Failed to populate VRConfig setting !", return result);
2402 data->vr_config = table->VRConfig;
2403 table->ThermGpio = 17;
2404 table->SclkStepSize = 0x4000;
2406 if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID,
2407 &gpio_pin_assignment)) {
2408 table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
2409 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2410 PHM_PlatformCaps_RegulatorHot);
2412 table->VRHotGpio = SMU7_UNUSED_GPIO_PIN;
2413 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2414 PHM_PlatformCaps_RegulatorHot);
2417 if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID,
2418 &gpio_pin_assignment)) {
2419 table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
2420 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2421 PHM_PlatformCaps_AutomaticDCTransition);
2423 table->AcDcGpio = SMU7_UNUSED_GPIO_PIN;
2424 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2425 PHM_PlatformCaps_AutomaticDCTransition);
2428 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2429 PHM_PlatformCaps_Falcon_QuickTransition);
2432 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2433 PHM_PlatformCaps_AutomaticDCTransition);
2434 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2435 PHM_PlatformCaps_Falcon_QuickTransition);
2438 if (atomctrl_get_pp_assign_pin(hwmgr,
2439 THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment)) {
2440 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2441 PHM_PlatformCaps_ThermalOutGPIO);
2443 table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
2445 table->ThermOutPolarity =
2446 (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) &
2447 (1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1 : 0;
2449 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
2451 /* if required, combine VRHot/PCC with thermal out GPIO*/
2452 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2453 PHM_PlatformCaps_RegulatorHot) &&
2454 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2455 PHM_PlatformCaps_CombinePCCWithThermalSignal)){
2456 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
2459 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2460 PHM_PlatformCaps_ThermalOutGPIO);
2462 table->ThermOutGpio = 17;
2463 table->ThermOutPolarity = 1;
2464 table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
2467 for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++)
2468 table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
2469 CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
2470 CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
2471 CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
2472 CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
2473 CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
2474 CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
2475 CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
2476 CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
2477 CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
2479 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2480 result = smu7_copy_bytes_to_smc(
2482 smu_data->smu7_data.dpm_table_start + offsetof(SMU72_Discrete_DpmTable, SystemFlags),
2483 (uint8_t *)&(table->SystemFlags),
2484 sizeof(SMU72_Discrete_DpmTable) - 3 * sizeof(SMU72_PIDController),
2487 PP_ASSERT_WITH_CODE(!result,
2488 "Failed to upload dpm data to SMC memory !", return result;);
2490 result = tonga_init_arb_table_index(hwmgr);
2491 PP_ASSERT_WITH_CODE(!result,
2492 "Failed to upload arb data to SMC memory !", return result);
2494 tonga_populate_pm_fuses(hwmgr);
2495 PP_ASSERT_WITH_CODE((!result),
2496 "Failed to populate initialize pm fuses !", return result);
2498 result = tonga_populate_initial_mc_reg_table(hwmgr);
2499 PP_ASSERT_WITH_CODE((!result),
2500 "Failed to populate initialize MC Reg table !", return result);
2505 static int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
2507 struct tonga_smumgr *smu_data =
2508 (struct tonga_smumgr *)(hwmgr->smu_backend);
2509 SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
2511 uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
2512 uint16_t fdo_min, slope1, slope2;
2513 uint32_t reference_clock;
2517 if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2518 PHM_PlatformCaps_MicrocodeFanControl))
2521 if (hwmgr->thermal_controller.fanInfo.bNoFan) {
2522 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2523 PHM_PlatformCaps_MicrocodeFanControl);
2527 if (0 == smu_data->smu7_data.fan_table_start) {
2528 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2529 PHM_PlatformCaps_MicrocodeFanControl);
2533 duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
2535 CG_FDO_CTRL1, FMAX_DUTY100);
2538 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
2539 PHM_PlatformCaps_MicrocodeFanControl);
2543 tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100;
2544 do_div(tmp64, 10000);
2545 fdo_min = (uint16_t)tmp64;
2547 t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed -
2548 hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
2549 t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh -
2550 hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
2552 pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed -
2553 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
2554 pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh -
2555 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
2557 slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
2558 slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
2560 fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100);
2561 fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100);
2562 fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100);
2564 fan_table.Slope1 = cpu_to_be16(slope1);
2565 fan_table.Slope2 = cpu_to_be16(slope2);
2567 fan_table.FdoMin = cpu_to_be16(fdo_min);
2569 fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst);
2571 fan_table.HystUp = cpu_to_be16(1);
2573 fan_table.HystSlope = cpu_to_be16(1);
2575 fan_table.TempRespLim = cpu_to_be16(5);
2577 reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
2579 fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
2581 fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
2583 fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL);
2585 fan_table.FanControl_GL_Flag = 1;
2587 res = smu7_copy_bytes_to_smc(hwmgr,
2588 smu_data->smu7_data.fan_table_start,
2589 (uint8_t *)&fan_table,
2590 (uint32_t)sizeof(fan_table),
2597 static int tonga_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
2599 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2601 if (data->need_update_smu7_dpm_table &
2602 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
2603 return tonga_program_memory_timing_parameters(hwmgr);
2608 static int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr)
2610 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2611 struct tonga_smumgr *smu_data =
2612 (struct tonga_smumgr *)(hwmgr->smu_backend);
2615 uint32_t low_sclk_interrupt_threshold = 0;
2617 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2618 PHM_PlatformCaps_SclkThrottleLowNotification)
2619 && (data->low_sclk_interrupt_threshold != 0)) {
2620 low_sclk_interrupt_threshold =
2621 data->low_sclk_interrupt_threshold;
2623 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
2625 result = smu7_copy_bytes_to_smc(
2627 smu_data->smu7_data.dpm_table_start +
2628 offsetof(SMU72_Discrete_DpmTable,
2629 LowSclkInterruptThreshold),
2630 (uint8_t *)&low_sclk_interrupt_threshold,
2635 result = tonga_update_and_upload_mc_reg_table(hwmgr);
2637 PP_ASSERT_WITH_CODE((!result),
2638 "Failed to upload MC reg table !",
2641 result = tonga_program_mem_timing_parameters(hwmgr);
2642 PP_ASSERT_WITH_CODE((result == 0),
2643 "Failed to program memory timing parameters !",
2649 static uint32_t tonga_get_offsetof(uint32_t type, uint32_t member)
2652 case SMU_SoftRegisters:
2654 case HandshakeDisables:
2655 return offsetof(SMU72_SoftRegisters, HandshakeDisables);
2656 case VoltageChangeTimeout:
2657 return offsetof(SMU72_SoftRegisters, VoltageChangeTimeout);
2658 case AverageGraphicsActivity:
2659 return offsetof(SMU72_SoftRegisters, AverageGraphicsActivity);
2661 return offsetof(SMU72_SoftRegisters, PreVBlankGap);
2663 return offsetof(SMU72_SoftRegisters, VBlankTimeout);
2664 case UcodeLoadStatus:
2665 return offsetof(SMU72_SoftRegisters, UcodeLoadStatus);
2666 case DRAM_LOG_ADDR_H:
2667 return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_H);
2668 case DRAM_LOG_ADDR_L:
2669 return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_L);
2670 case DRAM_LOG_PHY_ADDR_H:
2671 return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_H);
2672 case DRAM_LOG_PHY_ADDR_L:
2673 return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_L);
2674 case DRAM_LOG_BUFF_SIZE:
2675 return offsetof(SMU72_SoftRegisters, DRAM_LOG_BUFF_SIZE);
2677 case SMU_Discrete_DpmTable:
2680 return offsetof(SMU72_Discrete_DpmTable, UvdBootLevel);
2682 return offsetof(SMU72_Discrete_DpmTable, VceBootLevel);
2684 return offsetof(SMU72_Discrete_DpmTable, SamuBootLevel);
2685 case LowSclkInterruptThreshold:
2686 return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold);
2689 pr_warn("can't get the offset of type %x member %x\n", type, member);
2693 static uint32_t tonga_get_mac_definition(uint32_t value)
2696 case SMU_MAX_LEVELS_GRAPHICS:
2697 return SMU72_MAX_LEVELS_GRAPHICS;
2698 case SMU_MAX_LEVELS_MEMORY:
2699 return SMU72_MAX_LEVELS_MEMORY;
2700 case SMU_MAX_LEVELS_LINK:
2701 return SMU72_MAX_LEVELS_LINK;
2702 case SMU_MAX_ENTRIES_SMIO:
2703 return SMU72_MAX_ENTRIES_SMIO;
2704 case SMU_MAX_LEVELS_VDDC:
2705 return SMU72_MAX_LEVELS_VDDC;
2706 case SMU_MAX_LEVELS_VDDGFX:
2707 return SMU72_MAX_LEVELS_VDDGFX;
2708 case SMU_MAX_LEVELS_VDDCI:
2709 return SMU72_MAX_LEVELS_VDDCI;
2710 case SMU_MAX_LEVELS_MVDD:
2711 return SMU72_MAX_LEVELS_MVDD;
2713 pr_warn("can't get the mac value %x\n", value);
2718 static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr)
2720 struct tonga_smumgr *smu_data =
2721 (struct tonga_smumgr *)(hwmgr->smu_backend);
2722 uint32_t mm_boot_level_offset, mm_boot_level_value;
2723 struct phm_ppt_v1_information *table_info =
2724 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2726 smu_data->smc_state_table.UvdBootLevel = 0;
2727 if (table_info->mm_dep_table->count > 0)
2728 smu_data->smc_state_table.UvdBootLevel =
2729 (uint8_t) (table_info->mm_dep_table->count - 1);
2730 mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2731 offsetof(SMU72_Discrete_DpmTable, UvdBootLevel);
2732 mm_boot_level_offset /= 4;
2733 mm_boot_level_offset *= 4;
2734 mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2735 CGS_IND_REG__SMC, mm_boot_level_offset);
2736 mm_boot_level_value &= 0x00FFFFFF;
2737 mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24;
2738 cgs_write_ind_register(hwmgr->device,
2740 mm_boot_level_offset, mm_boot_level_value);
2742 if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2743 PHM_PlatformCaps_UVDDPM) ||
2744 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2745 PHM_PlatformCaps_StablePState))
2746 smum_send_msg_to_smc_with_parameter(hwmgr,
2747 PPSMC_MSG_UVDDPM_SetEnabledMask,
2748 (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel));
2752 static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr)
2754 struct tonga_smumgr *smu_data =
2755 (struct tonga_smumgr *)(hwmgr->smu_backend);
2756 uint32_t mm_boot_level_offset, mm_boot_level_value;
2757 struct phm_ppt_v1_information *table_info =
2758 (struct phm_ppt_v1_information *)(hwmgr->pptable);
2761 smu_data->smc_state_table.VceBootLevel =
2762 (uint8_t) (table_info->mm_dep_table->count - 1);
2764 mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2765 offsetof(SMU72_Discrete_DpmTable, VceBootLevel);
2766 mm_boot_level_offset /= 4;
2767 mm_boot_level_offset *= 4;
2768 mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2769 CGS_IND_REG__SMC, mm_boot_level_offset);
2770 mm_boot_level_value &= 0xFF00FFFF;
2771 mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16;
2772 cgs_write_ind_register(hwmgr->device,
2773 CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2775 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2776 PHM_PlatformCaps_StablePState))
2777 smum_send_msg_to_smc_with_parameter(hwmgr,
2778 PPSMC_MSG_VCEDPM_SetEnabledMask,
2779 (uint32_t)1 << smu_data->smc_state_table.VceBootLevel);
2783 static int tonga_update_samu_smc_table(struct pp_hwmgr *hwmgr)
2785 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2786 uint32_t mm_boot_level_offset, mm_boot_level_value;
2788 smu_data->smc_state_table.SamuBootLevel = 0;
2789 mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2790 offsetof(SMU72_Discrete_DpmTable, SamuBootLevel);
2792 mm_boot_level_offset /= 4;
2793 mm_boot_level_offset *= 4;
2794 mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2795 CGS_IND_REG__SMC, mm_boot_level_offset);
2796 mm_boot_level_value &= 0xFFFFFF00;
2797 mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0;
2798 cgs_write_ind_register(hwmgr->device,
2799 CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2801 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2802 PHM_PlatformCaps_StablePState))
2803 smum_send_msg_to_smc_with_parameter(hwmgr,
2804 PPSMC_MSG_SAMUDPM_SetEnabledMask,
2805 (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel));
2809 static int tonga_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
2813 tonga_update_uvd_smc_table(hwmgr);
2816 tonga_update_vce_smc_table(hwmgr);
2818 case SMU_SAMU_TABLE:
2819 tonga_update_samu_smc_table(hwmgr);
2827 static int tonga_process_firmware_header(struct pp_hwmgr *hwmgr)
2829 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2830 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
2836 result = smu7_read_smc_sram_dword(hwmgr,
2837 SMU72_FIRMWARE_HEADER_LOCATION +
2838 offsetof(SMU72_Firmware_Header, DpmTable),
2842 smu_data->smu7_data.dpm_table_start = tmp;
2844 error |= (result != 0);
2846 result = smu7_read_smc_sram_dword(hwmgr,
2847 SMU72_FIRMWARE_HEADER_LOCATION +
2848 offsetof(SMU72_Firmware_Header, SoftRegisters),
2852 data->soft_regs_start = tmp;
2853 smu_data->smu7_data.soft_regs_start = tmp;
2856 error |= (result != 0);
2859 result = smu7_read_smc_sram_dword(hwmgr,
2860 SMU72_FIRMWARE_HEADER_LOCATION +
2861 offsetof(SMU72_Firmware_Header, mcRegisterTable),
2865 smu_data->smu7_data.mc_reg_table_start = tmp;
2867 result = smu7_read_smc_sram_dword(hwmgr,
2868 SMU72_FIRMWARE_HEADER_LOCATION +
2869 offsetof(SMU72_Firmware_Header, FanTable),
2873 smu_data->smu7_data.fan_table_start = tmp;
2875 error |= (result != 0);
2877 result = smu7_read_smc_sram_dword(hwmgr,
2878 SMU72_FIRMWARE_HEADER_LOCATION +
2879 offsetof(SMU72_Firmware_Header, mcArbDramTimingTable),
2883 smu_data->smu7_data.arb_table_start = tmp;
2885 error |= (result != 0);
2887 result = smu7_read_smc_sram_dword(hwmgr,
2888 SMU72_FIRMWARE_HEADER_LOCATION +
2889 offsetof(SMU72_Firmware_Header, Version),
2893 hwmgr->microcode_version_info.SMC = tmp;
2895 error |= (result != 0);
2897 return error ? 1 : 0;
2900 /*---------------------------MC----------------------------*/
2902 static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr)
2904 return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16));
2907 static bool tonga_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg)
2912 case mmMC_SEQ_RAS_TIMING:
2913 *out_reg = mmMC_SEQ_RAS_TIMING_LP;
2916 case mmMC_SEQ_DLL_STBY:
2917 *out_reg = mmMC_SEQ_DLL_STBY_LP;
2920 case mmMC_SEQ_G5PDX_CMD0:
2921 *out_reg = mmMC_SEQ_G5PDX_CMD0_LP;
2924 case mmMC_SEQ_G5PDX_CMD1:
2925 *out_reg = mmMC_SEQ_G5PDX_CMD1_LP;
2928 case mmMC_SEQ_G5PDX_CTRL:
2929 *out_reg = mmMC_SEQ_G5PDX_CTRL_LP;
2932 case mmMC_SEQ_CAS_TIMING:
2933 *out_reg = mmMC_SEQ_CAS_TIMING_LP;
2936 case mmMC_SEQ_MISC_TIMING:
2937 *out_reg = mmMC_SEQ_MISC_TIMING_LP;
2940 case mmMC_SEQ_MISC_TIMING2:
2941 *out_reg = mmMC_SEQ_MISC_TIMING2_LP;
2944 case mmMC_SEQ_PMG_DVS_CMD:
2945 *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP;
2948 case mmMC_SEQ_PMG_DVS_CTL:
2949 *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP;
2952 case mmMC_SEQ_RD_CTL_D0:
2953 *out_reg = mmMC_SEQ_RD_CTL_D0_LP;
2956 case mmMC_SEQ_RD_CTL_D1:
2957 *out_reg = mmMC_SEQ_RD_CTL_D1_LP;
2960 case mmMC_SEQ_WR_CTL_D0:
2961 *out_reg = mmMC_SEQ_WR_CTL_D0_LP;
2964 case mmMC_SEQ_WR_CTL_D1:
2965 *out_reg = mmMC_SEQ_WR_CTL_D1_LP;
2968 case mmMC_PMG_CMD_EMRS:
2969 *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP;
2972 case mmMC_PMG_CMD_MRS:
2973 *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP;
2976 case mmMC_PMG_CMD_MRS1:
2977 *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP;
2980 case mmMC_SEQ_PMG_TIMING:
2981 *out_reg = mmMC_SEQ_PMG_TIMING_LP;
2984 case mmMC_PMG_CMD_MRS2:
2985 *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP;
2988 case mmMC_SEQ_WR_CTL_2:
2989 *out_reg = mmMC_SEQ_WR_CTL_2_LP;
3000 static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table *table)
3005 for (i = 0; i < table->last; i++) {
3006 table->mc_reg_address[i].s0 =
3007 tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1,
3010 table->mc_reg_address[i].s1;
3015 static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table,
3016 struct tonga_mc_reg_table *ni_table)
3020 PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3021 "Invalid VramInfo table.", return -EINVAL);
3022 PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES),
3023 "Invalid VramInfo table.", return -EINVAL);
3025 for (i = 0; i < table->last; i++)
3026 ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
3028 ni_table->last = table->last;
3030 for (i = 0; i < table->num_entries; i++) {
3031 ni_table->mc_reg_table_entry[i].mclk_max =
3032 table->mc_reg_table_entry[i].mclk_max;
3033 for (j = 0; j < table->last; j++) {
3034 ni_table->mc_reg_table_entry[i].mc_data[j] =
3035 table->mc_reg_table_entry[i].mc_data[j];
3039 ni_table->num_entries = table->num_entries;
3044 static int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr,
3045 struct tonga_mc_reg_table *table)
3049 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3051 for (i = 0, j = table->last; i < table->last; i++) {
3052 PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3053 "Invalid VramInfo table.", return -EINVAL);
3055 switch (table->mc_reg_address[i].s1) {
3057 case mmMC_SEQ_MISC1:
3058 temp_reg = cgs_read_register(hwmgr->device,
3060 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS;
3061 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP;
3062 for (k = 0; k < table->num_entries; k++) {
3063 table->mc_reg_table_entry[k].mc_data[j] =
3064 ((temp_reg & 0xffff0000)) |
3065 ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
3069 PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3070 "Invalid VramInfo table.", return -EINVAL);
3071 temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS);
3072 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS;
3073 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP;
3074 for (k = 0; k < table->num_entries; k++) {
3075 table->mc_reg_table_entry[k].mc_data[j] =
3076 (temp_reg & 0xffff0000) |
3077 (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
3079 if (!data->is_memory_gddr5)
3080 table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
3084 if (!data->is_memory_gddr5) {
3085 PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3086 "Invalid VramInfo table.", return -EINVAL);
3087 table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
3088 table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
3089 for (k = 0; k < table->num_entries; k++)
3090 table->mc_reg_table_entry[k].mc_data[j] =
3091 (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
3097 case mmMC_SEQ_RESERVE_M:
3098 temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1);
3099 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1;
3100 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP;
3101 for (k = 0; k < table->num_entries; k++) {
3102 table->mc_reg_table_entry[k].mc_data[j] =
3103 (temp_reg & 0xffff0000) |
3104 (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
3120 static int tonga_set_valid_flag(struct tonga_mc_reg_table *table)
3124 for (i = 0; i < table->last; i++) {
3125 for (j = 1; j < table->num_entries; j++) {
3126 if (table->mc_reg_table_entry[j-1].mc_data[i] !=
3127 table->mc_reg_table_entry[j].mc_data[i]) {
3128 table->validflag |= (1<<i);
3137 static int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
3140 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend);
3141 pp_atomctrl_mc_reg_table *table;
3142 struct tonga_mc_reg_table *ni_table = &smu_data->mc_reg_table;
3143 uint8_t module_index = tonga_get_memory_modile_index(hwmgr);
3145 table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL);
3150 /* Program additional LP registers that are no longer programmed by VBIOS */
3151 cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP,
3152 cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
3153 cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP,
3154 cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
3155 cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP,
3156 cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY));
3157 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP,
3158 cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0));
3159 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP,
3160 cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1));
3161 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP,
3162 cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL));
3163 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP,
3164 cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD));
3165 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP,
3166 cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL));
3167 cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP,
3168 cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING));
3169 cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP,
3170 cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
3171 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP,
3172 cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS));
3173 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP,
3174 cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS));
3175 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP,
3176 cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1));
3177 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP,
3178 cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0));
3179 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP,
3180 cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
3181 cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP,
3182 cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
3183 cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP,
3184 cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
3185 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP,
3186 cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
3187 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP,
3188 cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2));
3189 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP,
3190 cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2));
3192 memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table));
3194 result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table);
3197 result = tonga_copy_vbios_smc_reg_table(table, ni_table);
3200 tonga_set_s0_mc_reg_index(ni_table);
3201 result = tonga_set_mc_special_registers(hwmgr, ni_table);
3205 tonga_set_valid_flag(ni_table);
3212 static bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr)
3214 return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
3215 CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
3219 static int tonga_update_dpm_settings(struct pp_hwmgr *hwmgr,
3220 void *profile_setting)
3222 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3223 struct tonga_smumgr *smu_data = (struct tonga_smumgr *)
3224 (hwmgr->smu_backend);
3225 struct profile_mode_setting *setting;
3226 struct SMU72_Discrete_GraphicsLevel *levels =
3227 smu_data->smc_state_table.GraphicsLevel;
3228 uint32_t array = smu_data->smu7_data.dpm_table_start +
3229 offsetof(SMU72_Discrete_DpmTable, GraphicsLevel);
3231 uint32_t mclk_array = smu_data->smu7_data.dpm_table_start +
3232 offsetof(SMU72_Discrete_DpmTable, MemoryLevel);
3233 struct SMU72_Discrete_MemoryLevel *mclk_levels =
3234 smu_data->smc_state_table.MemoryLevel;
3236 uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
3238 if (profile_setting == NULL)
3241 setting = (struct profile_mode_setting *)profile_setting;
3243 if (setting->bupdate_sclk) {
3244 if (!data->sclk_dpm_key_disabled)
3245 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
3246 for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
3247 if (levels[i].ActivityLevel !=
3248 cpu_to_be16(setting->sclk_activity)) {
3249 levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
3251 clk_activity_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
3252 + offsetof(SMU72_Discrete_GraphicsLevel, ActivityLevel);
3253 offset = clk_activity_offset & ~0x3;
3254 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
3255 tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
3256 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
3259 if (levels[i].UpHyst != setting->sclk_up_hyst ||
3260 levels[i].DownHyst != setting->sclk_down_hyst) {
3261 levels[i].UpHyst = setting->sclk_up_hyst;
3262 levels[i].DownHyst = setting->sclk_down_hyst;
3263 up_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
3264 + offsetof(SMU72_Discrete_GraphicsLevel, UpHyst);
3265 down_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
3266 + offsetof(SMU72_Discrete_GraphicsLevel, DownHyst);
3267 offset = up_hyst_offset & ~0x3;
3268 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
3269 tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t));
3270 tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t));
3271 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
3274 if (!data->sclk_dpm_key_disabled)
3275 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
3278 if (setting->bupdate_mclk) {
3279 if (!data->mclk_dpm_key_disabled)
3280 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
3281 for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
3282 if (mclk_levels[i].ActivityLevel !=
3283 cpu_to_be16(setting->mclk_activity)) {
3284 mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
3286 clk_activity_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
3287 + offsetof(SMU72_Discrete_MemoryLevel, ActivityLevel);
3288 offset = clk_activity_offset & ~0x3;
3289 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
3290 tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
3291 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
3294 if (mclk_levels[i].UpHyst != setting->mclk_up_hyst ||
3295 mclk_levels[i].DownHyst != setting->mclk_down_hyst) {
3296 mclk_levels[i].UpHyst = setting->mclk_up_hyst;
3297 mclk_levels[i].DownHyst = setting->mclk_down_hyst;
3298 up_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
3299 + offsetof(SMU72_Discrete_MemoryLevel, UpHyst);
3300 down_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
3301 + offsetof(SMU72_Discrete_MemoryLevel, DownHyst);
3302 offset = up_hyst_offset & ~0x3;
3303 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
3304 tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t));
3305 tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t));
3306 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
3309 if (!data->mclk_dpm_key_disabled)
3310 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
3315 const struct pp_smumgr_func tonga_smu_funcs = {
3316 .smu_init = &tonga_smu_init,
3317 .smu_fini = &smu7_smu_fini,
3318 .start_smu = &tonga_start_smu,
3319 .check_fw_load_finish = &smu7_check_fw_load_finish,
3320 .request_smu_load_fw = &smu7_request_smu_load_fw,
3321 .request_smu_load_specific_fw = NULL,
3322 .send_msg_to_smc = &smu7_send_msg_to_smc,
3323 .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter,
3324 .download_pptable_settings = NULL,
3325 .upload_pptable_settings = NULL,
3326 .update_smc_table = tonga_update_smc_table,
3327 .get_offsetof = tonga_get_offsetof,
3328 .process_firmware_header = tonga_process_firmware_header,
3329 .init_smc_table = tonga_init_smc_table,
3330 .update_sclk_threshold = tonga_update_sclk_threshold,
3331 .thermal_setup_fan_table = tonga_thermal_setup_fan_table,
3332 .populate_all_graphic_levels = tonga_populate_all_graphic_levels,
3333 .populate_all_memory_levels = tonga_populate_all_memory_levels,
3334 .get_mac_definition = tonga_get_mac_definition,
3335 .initialize_mc_reg_table = tonga_initialize_mc_reg_table,
3336 .is_dpm_running = tonga_is_dpm_running,
3337 .update_dpm_settings = tonga_update_dpm_settings,