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"
58 #define POWERTUNE_DEFAULT_SET_MAX 1
59 #define MC_CG_ARB_FREQ_F1 0x0b
60 #define VDDC_VDDCI_DELTA 200
63 static const struct tonga_pt_defaults tonga_power_tune_data_set_array
[POWERTUNE_DEFAULT_SET_MAX
] = {
64 /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
65 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
69 {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8,
70 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
71 {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203,
72 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4}
76 /* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */
77 static const uint16_t tonga_clock_stretcher_lookup_table
[2][4] = {
82 /* [FF, SS] type, [] 4 voltage ranges,
83 * and [Floor Freq, Boundary Freq, VID min , VID max]
85 static const uint32_t tonga_clock_stretcher_ddt_table
[2][4][4] = {
86 { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
87 { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} }
90 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */
91 static const uint8_t tonga_clock_stretch_amount_conversion
[2][6] = {
96 static int tonga_start_in_protection_mode(struct pp_hwmgr
*hwmgr
)
101 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
102 SMC_SYSCON_RESET_CNTL
, rst_reg
, 1);
104 result
= smu7_upload_smu_firmware_image(hwmgr
);
109 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
113 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
114 SMC_SYSCON_CLOCK_CNTL_0
, ck_disable
, 0);
116 /* De-assert reset */
117 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
118 SMC_SYSCON_RESET_CNTL
, rst_reg
, 0);
120 /* Set SMU Auto Start */
121 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
122 SMU_INPUT_DATA
, AUTO_START
, 1);
124 /* Clear firmware interrupt enable flag */
125 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
126 ixFIRMWARE_FLAGS
, 0);
128 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
,
129 RCU_UC_EVENTS
, INTERRUPTS_ENABLED
, 1);
132 * Call Test SMU message with 0x20000 offset to trigger SMU start
134 smu7_send_msg_to_smc_offset(hwmgr
);
136 /* Wait for done bit to be set */
137 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr
, SMC_IND
,
138 SMU_STATUS
, SMU_DONE
, 0);
140 /* Check pass/failed indicator */
141 if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
,
142 CGS_IND_REG__SMC
, SMU_STATUS
, SMU_PASS
)) {
143 pr_err("SMU Firmware start failed\n");
147 /* Wait for firmware to initialize */
148 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
,
149 FIRMWARE_FLAGS
, INTERRUPTS_ENABLED
, 1);
154 static int tonga_start_in_non_protection_mode(struct pp_hwmgr
*hwmgr
)
158 /* wait for smc boot up */
159 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr
, SMC_IND
,
160 RCU_UC_EVENTS
, boot_seq_done
, 0);
162 /*Clear firmware interrupt enable flag*/
163 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
164 ixFIRMWARE_FLAGS
, 0);
167 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
168 SMC_SYSCON_RESET_CNTL
, rst_reg
, 1);
170 result
= smu7_upload_smu_firmware_image(hwmgr
);
175 /* Set smc instruct start point at 0x0 */
176 smu7_program_jump_on_start(hwmgr
);
179 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
180 SMC_SYSCON_CLOCK_CNTL_0
, ck_disable
, 0);
183 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
184 SMC_SYSCON_RESET_CNTL
, rst_reg
, 0);
186 /* Wait for firmware to initialize */
187 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
,
188 FIRMWARE_FLAGS
, INTERRUPTS_ENABLED
, 1);
193 static int tonga_start_smu(struct pp_hwmgr
*hwmgr
)
197 /* Only start SMC if SMC RAM is not running */
198 if (!smu7_is_smc_ram_running(hwmgr
) && hwmgr
->not_vf
) {
199 /*Check if SMU is running in protected mode*/
200 if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
201 SMU_FIRMWARE
, SMU_MODE
)) {
202 result
= tonga_start_in_non_protection_mode(hwmgr
);
206 result
= tonga_start_in_protection_mode(hwmgr
);
212 result
= smu7_request_smu_load_fw(hwmgr
);
217 static int tonga_smu_init(struct pp_hwmgr
*hwmgr
)
219 struct tonga_smumgr
*tonga_priv
= NULL
;
221 tonga_priv
= kzalloc(sizeof(struct tonga_smumgr
), GFP_KERNEL
);
222 if (tonga_priv
== NULL
)
225 hwmgr
->smu_backend
= tonga_priv
;
227 if (smu7_init(hwmgr
)) {
236 static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr
*hwmgr
,
237 phm_ppt_v1_clock_voltage_dependency_table
*allowed_clock_voltage_table
,
238 uint32_t clock
, SMU_VoltageLevel
*voltage
, uint32_t *mvdd
)
241 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
242 struct phm_ppt_v1_information
*pptable_info
=
243 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
245 /* clock - voltage dependency table is empty table */
246 if (allowed_clock_voltage_table
->count
== 0)
249 for (i
= 0; i
< allowed_clock_voltage_table
->count
; i
++) {
250 /* find first sclk bigger than request */
251 if (allowed_clock_voltage_table
->entries
[i
].clk
>= clock
) {
252 voltage
->VddGfx
= phm_get_voltage_index(
253 pptable_info
->vddgfx_lookup_table
,
254 allowed_clock_voltage_table
->entries
[i
].vddgfx
);
255 voltage
->Vddc
= phm_get_voltage_index(
256 pptable_info
->vddc_lookup_table
,
257 allowed_clock_voltage_table
->entries
[i
].vddc
);
259 if (allowed_clock_voltage_table
->entries
[i
].vddci
)
261 phm_get_voltage_id(&data
->vddci_voltage_table
, allowed_clock_voltage_table
->entries
[i
].vddci
);
264 phm_get_voltage_id(&data
->vddci_voltage_table
,
265 allowed_clock_voltage_table
->entries
[i
].vddc
- VDDC_VDDCI_DELTA
);
268 if (allowed_clock_voltage_table
->entries
[i
].mvdd
)
269 *mvdd
= (uint32_t) allowed_clock_voltage_table
->entries
[i
].mvdd
;
276 /* sclk is bigger than max sclk in the dependence table */
277 voltage
->VddGfx
= phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
278 allowed_clock_voltage_table
->entries
[i
-1].vddgfx
);
279 voltage
->Vddc
= phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
280 allowed_clock_voltage_table
->entries
[i
-1].vddc
);
282 if (allowed_clock_voltage_table
->entries
[i
-1].vddci
)
283 voltage
->Vddci
= phm_get_voltage_id(&data
->vddci_voltage_table
,
284 allowed_clock_voltage_table
->entries
[i
-1].vddci
);
286 if (allowed_clock_voltage_table
->entries
[i
-1].mvdd
)
287 *mvdd
= (uint32_t) allowed_clock_voltage_table
->entries
[i
-1].mvdd
;
292 static int tonga_populate_smc_vddc_table(struct pp_hwmgr
*hwmgr
,
293 SMU72_Discrete_DpmTable
*table
)
296 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
298 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
299 table
->VddcLevelCount
= data
->vddc_voltage_table
.count
;
300 for (count
= 0; count
< table
->VddcLevelCount
; count
++) {
301 table
->VddcTable
[count
] =
302 PP_HOST_TO_SMC_US(data
->vddc_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
304 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddcLevelCount
);
309 static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr
*hwmgr
,
310 SMU72_Discrete_DpmTable
*table
)
313 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
315 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vdd_gfx_control
) {
316 table
->VddGfxLevelCount
= data
->vddgfx_voltage_table
.count
;
317 for (count
= 0; count
< data
->vddgfx_voltage_table
.count
; count
++) {
318 table
->VddGfxTable
[count
] =
319 PP_HOST_TO_SMC_US(data
->vddgfx_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
321 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddGfxLevelCount
);
326 static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr
*hwmgr
,
327 SMU72_Discrete_DpmTable
*table
)
329 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
332 table
->VddciLevelCount
= data
->vddci_voltage_table
.count
;
333 for (count
= 0; count
< table
->VddciLevelCount
; count
++) {
334 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vddci_control
) {
335 table
->VddciTable
[count
] =
336 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
337 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->vddci_control
) {
338 table
->SmioTable1
.Pattern
[count
].Voltage
=
339 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
340 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */
341 table
->SmioTable1
.Pattern
[count
].Smio
=
343 table
->Smio
[count
] |=
344 data
->vddci_voltage_table
.entries
[count
].smio_low
;
345 table
->VddciTable
[count
] =
346 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
350 table
->SmioMask1
= data
->vddci_voltage_table
.mask_low
;
351 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddciLevelCount
);
356 static int tonga_populate_smc_mvdd_table(struct pp_hwmgr
*hwmgr
,
357 SMU72_Discrete_DpmTable
*table
)
359 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
362 if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->mvdd_control
) {
363 table
->MvddLevelCount
= data
->mvdd_voltage_table
.count
;
364 for (count
= 0; count
< table
->MvddLevelCount
; count
++) {
365 table
->SmioTable2
.Pattern
[count
].Voltage
=
366 PP_HOST_TO_SMC_US(data
->mvdd_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
367 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
368 table
->SmioTable2
.Pattern
[count
].Smio
=
370 table
->Smio
[count
] |=
371 data
->mvdd_voltage_table
.entries
[count
].smio_low
;
373 table
->SmioMask2
= data
->mvdd_voltage_table
.mask_low
;
375 CONVERT_FROM_HOST_TO_SMC_UL(table
->MvddLevelCount
);
381 static int tonga_populate_cac_tables(struct pp_hwmgr
*hwmgr
,
382 SMU72_Discrete_DpmTable
*table
)
386 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
387 struct phm_ppt_v1_information
*pptable_info
=
388 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
389 struct phm_ppt_v1_voltage_lookup_table
*vddgfx_lookup_table
=
390 pptable_info
->vddgfx_lookup_table
;
391 struct phm_ppt_v1_voltage_lookup_table
*vddc_lookup_table
=
392 pptable_info
->vddc_lookup_table
;
394 /* table is already swapped, so in order to use the value from it
395 * we need to swap it back.
397 uint32_t vddc_level_count
= PP_SMC_TO_HOST_UL(table
->VddcLevelCount
);
398 uint32_t vddgfx_level_count
= PP_SMC_TO_HOST_UL(table
->VddGfxLevelCount
);
400 for (count
= 0; count
< vddc_level_count
; count
++) {
401 /* We are populating vddc CAC data to BapmVddc table in split and merged mode */
402 index
= phm_get_voltage_index(vddc_lookup_table
,
403 data
->vddc_voltage_table
.entries
[count
].value
);
404 table
->BapmVddcVidLoSidd
[count
] =
405 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_low
);
406 table
->BapmVddcVidHiSidd
[count
] =
407 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_mid
);
408 table
->BapmVddcVidHiSidd2
[count
] =
409 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_high
);
412 if (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) {
413 /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */
414 for (count
= 0; count
< vddgfx_level_count
; count
++) {
415 index
= phm_get_voltage_index(vddgfx_lookup_table
,
416 convert_to_vid(vddgfx_lookup_table
->entries
[index
].us_cac_mid
));
417 table
->BapmVddGfxVidHiSidd2
[count
] =
418 convert_to_vid(vddgfx_lookup_table
->entries
[index
].us_cac_high
);
421 for (count
= 0; count
< vddc_level_count
; count
++) {
422 index
= phm_get_voltage_index(vddc_lookup_table
,
423 data
->vddc_voltage_table
.entries
[count
].value
);
424 table
->BapmVddGfxVidLoSidd
[count
] =
425 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_low
);
426 table
->BapmVddGfxVidHiSidd
[count
] =
427 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_mid
);
428 table
->BapmVddGfxVidHiSidd2
[count
] =
429 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_high
);
436 static int tonga_populate_smc_voltage_tables(struct pp_hwmgr
*hwmgr
,
437 SMU72_Discrete_DpmTable
*table
)
441 result
= tonga_populate_smc_vddc_table(hwmgr
, table
);
442 PP_ASSERT_WITH_CODE(!result
,
443 "can not populate VDDC voltage table to SMC",
446 result
= tonga_populate_smc_vdd_ci_table(hwmgr
, table
);
447 PP_ASSERT_WITH_CODE(!result
,
448 "can not populate VDDCI voltage table to SMC",
451 result
= tonga_populate_smc_vdd_gfx_table(hwmgr
, table
);
452 PP_ASSERT_WITH_CODE(!result
,
453 "can not populate VDDGFX voltage table to SMC",
456 result
= tonga_populate_smc_mvdd_table(hwmgr
, table
);
457 PP_ASSERT_WITH_CODE(!result
,
458 "can not populate MVDD voltage table to SMC",
461 result
= tonga_populate_cac_tables(hwmgr
, table
);
462 PP_ASSERT_WITH_CODE(!result
,
463 "can not populate CAC voltage tables to SMC",
469 static int tonga_populate_ulv_level(struct pp_hwmgr
*hwmgr
,
470 struct SMU72_Discrete_Ulv
*state
)
472 struct phm_ppt_v1_information
*table_info
=
473 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
475 state
->CcPwrDynRm
= 0;
476 state
->CcPwrDynRm1
= 0;
478 state
->VddcOffset
= (uint16_t) table_info
->us_ulv_voltage_offset
;
479 state
->VddcOffsetVid
= (uint8_t)(table_info
->us_ulv_voltage_offset
*
480 VOLTAGE_VID_OFFSET_SCALE2
/ VOLTAGE_VID_OFFSET_SCALE1
);
482 state
->VddcPhase
= 1;
484 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm
);
485 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm1
);
486 CONVERT_FROM_HOST_TO_SMC_US(state
->VddcOffset
);
491 static int tonga_populate_ulv_state(struct pp_hwmgr
*hwmgr
,
492 struct SMU72_Discrete_DpmTable
*table
)
494 return tonga_populate_ulv_level(hwmgr
, &table
->Ulv
);
497 static int tonga_populate_smc_link_level(struct pp_hwmgr
*hwmgr
, SMU72_Discrete_DpmTable
*table
)
499 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
500 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
501 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
504 /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
505 for (i
= 0; i
<= dpm_table
->pcie_speed_table
.count
; i
++) {
506 table
->LinkLevel
[i
].PcieGenSpeed
=
507 (uint8_t)dpm_table
->pcie_speed_table
.dpm_levels
[i
].value
;
508 table
->LinkLevel
[i
].PcieLaneCount
=
509 (uint8_t)encode_pcie_lane_width(dpm_table
->pcie_speed_table
.dpm_levels
[i
].param1
);
510 table
->LinkLevel
[i
].EnabledForActivity
=
512 table
->LinkLevel
[i
].SPC
=
513 (uint8_t)(data
->pcie_spc_cap
& 0xff);
514 table
->LinkLevel
[i
].DownThreshold
=
515 PP_HOST_TO_SMC_UL(5);
516 table
->LinkLevel
[i
].UpThreshold
=
517 PP_HOST_TO_SMC_UL(30);
520 smu_data
->smc_state_table
.LinkLevelCount
=
521 (uint8_t)dpm_table
->pcie_speed_table
.count
;
522 data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
=
523 phm_get_dpm_level_enable_mask_value(&dpm_table
->pcie_speed_table
);
528 static int tonga_calculate_sclk_params(struct pp_hwmgr
*hwmgr
,
529 uint32_t engine_clock
, SMU72_Discrete_GraphicsLevel
*sclk
)
531 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
532 pp_atomctrl_clock_dividers_vi dividers
;
533 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
534 uint32_t spll_func_cntl_3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
535 uint32_t spll_func_cntl_4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
536 uint32_t cg_spll_spread_spectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
537 uint32_t cg_spll_spread_spectrum_2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
538 uint32_t reference_clock
;
539 uint32_t reference_divider
;
543 /* get the engine clock dividers for this clock value*/
544 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
, engine_clock
, ÷rs
);
546 PP_ASSERT_WITH_CODE(result
== 0,
547 "Error retrieving Engine Clock dividers from VBIOS.", return result
);
549 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
550 reference_clock
= atomctrl_get_reference_clock(hwmgr
);
552 reference_divider
= 1 + dividers
.uc_pll_ref_div
;
554 /* low 14 bits is fraction and high 12 bits is divider*/
555 fbdiv
= dividers
.ul_fb_div
.ul_fb_divider
& 0x3FFFFFF;
557 /* SPLL_FUNC_CNTL setup*/
558 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
,
559 CG_SPLL_FUNC_CNTL
, SPLL_REF_DIV
, dividers
.uc_pll_ref_div
);
560 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
,
561 CG_SPLL_FUNC_CNTL
, SPLL_PDIV_A
, dividers
.uc_pll_post_div
);
563 /* SPLL_FUNC_CNTL_3 setup*/
564 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
,
565 CG_SPLL_FUNC_CNTL_3
, SPLL_FB_DIV
, fbdiv
);
567 /* set to use fractional accumulation*/
568 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
,
569 CG_SPLL_FUNC_CNTL_3
, SPLL_DITHEN
, 1);
571 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
572 PHM_PlatformCaps_EngineSpreadSpectrumSupport
)) {
573 pp_atomctrl_internal_ss_info ss_info
;
575 uint32_t vcoFreq
= engine_clock
* dividers
.uc_pll_post_div
;
576 if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr
, vcoFreq
, &ss_info
)) {
578 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
579 * ss_info.speed_spectrum_rate -- in unit of khz
581 /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
582 uint32_t clkS
= reference_clock
* 5 / (reference_divider
* ss_info
.speed_spectrum_rate
);
584 /* clkv = 2 * D * fbdiv / NS */
585 uint32_t clkV
= 4 * ss_info
.speed_spectrum_percentage
* fbdiv
/ (clkS
* 10000);
587 cg_spll_spread_spectrum
=
588 PHM_SET_FIELD(cg_spll_spread_spectrum
, CG_SPLL_SPREAD_SPECTRUM
, CLKS
, clkS
);
589 cg_spll_spread_spectrum
=
590 PHM_SET_FIELD(cg_spll_spread_spectrum
, CG_SPLL_SPREAD_SPECTRUM
, SSEN
, 1);
591 cg_spll_spread_spectrum_2
=
592 PHM_SET_FIELD(cg_spll_spread_spectrum_2
, CG_SPLL_SPREAD_SPECTRUM_2
, CLKV
, clkV
);
596 sclk
->SclkFrequency
= engine_clock
;
597 sclk
->CgSpllFuncCntl3
= spll_func_cntl_3
;
598 sclk
->CgSpllFuncCntl4
= spll_func_cntl_4
;
599 sclk
->SpllSpreadSpectrum
= cg_spll_spread_spectrum
;
600 sclk
->SpllSpreadSpectrum2
= cg_spll_spread_spectrum_2
;
601 sclk
->SclkDid
= (uint8_t)dividers
.pll_post_divider
;
606 static int tonga_populate_single_graphic_level(struct pp_hwmgr
*hwmgr
,
607 uint32_t engine_clock
,
608 SMU72_Discrete_GraphicsLevel
*graphic_level
)
612 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
613 struct phm_ppt_v1_information
*pptable_info
=
614 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
615 phm_ppt_v1_clock_voltage_dependency_table
*vdd_dep_table
= NULL
;
617 result
= tonga_calculate_sclk_params(hwmgr
, engine_clock
, graphic_level
);
619 if (hwmgr
->od_enabled
)
620 vdd_dep_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)&data
->odn_dpm_table
.vdd_dependency_on_sclk
;
622 vdd_dep_table
= pptable_info
->vdd_dep_on_sclk
;
624 /* populate graphics levels*/
625 result
= tonga_get_dependency_volt_by_clk(hwmgr
,
626 vdd_dep_table
, engine_clock
,
627 &graphic_level
->MinVoltage
, &mvdd
);
628 PP_ASSERT_WITH_CODE((!result
),
629 "can not find VDDC voltage value for VDDC "
630 "engine clock dependency table", return result
);
632 /* SCLK frequency in units of 10KHz*/
633 graphic_level
->SclkFrequency
= engine_clock
;
634 /* Indicates maximum activity level for this performance level. 50% for now*/
635 graphic_level
->ActivityLevel
= data
->current_profile_setting
.sclk_activity
;
637 graphic_level
->CcPwrDynRm
= 0;
638 graphic_level
->CcPwrDynRm1
= 0;
639 /* this level can be used if activity is high enough.*/
640 graphic_level
->EnabledForActivity
= 0;
641 /* this level can be used for throttling.*/
642 graphic_level
->EnabledForThrottle
= 1;
643 graphic_level
->UpHyst
= data
->current_profile_setting
.sclk_up_hyst
;
644 graphic_level
->DownHyst
= data
->current_profile_setting
.sclk_down_hyst
;
645 graphic_level
->VoltageDownHyst
= 0;
646 graphic_level
->PowerThrottle
= 0;
648 data
->display_timing
.min_clock_in_sr
=
649 hwmgr
->display_config
->min_core_set_clock_in_sr
;
651 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
652 PHM_PlatformCaps_SclkDeepSleep
))
653 graphic_level
->DeepSleepDivId
=
654 smu7_get_sleep_divider_id_from_clock(engine_clock
,
655 data
->display_timing
.min_clock_in_sr
);
657 /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
658 graphic_level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
661 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/
662 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/
663 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SclkFrequency
);
664 CONVERT_FROM_HOST_TO_SMC_US(graphic_level
->ActivityLevel
);
665 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CgSpllFuncCntl3
);
666 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CgSpllFuncCntl4
);
667 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SpllSpreadSpectrum
);
668 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SpllSpreadSpectrum2
);
669 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CcPwrDynRm
);
670 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CcPwrDynRm1
);
676 static int tonga_populate_all_graphic_levels(struct pp_hwmgr
*hwmgr
)
678 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
679 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
680 struct phm_ppt_v1_information
*pptable_info
= (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
681 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
682 struct phm_ppt_v1_pcie_table
*pcie_table
= pptable_info
->pcie_table
;
683 uint8_t pcie_entry_count
= (uint8_t) data
->dpm_table
.pcie_speed_table
.count
;
684 uint32_t level_array_address
= smu_data
->smu7_data
.dpm_table_start
+
685 offsetof(SMU72_Discrete_DpmTable
, GraphicsLevel
);
687 uint32_t level_array_size
= sizeof(SMU72_Discrete_GraphicsLevel
) *
688 SMU72_MAX_LEVELS_GRAPHICS
;
690 SMU72_Discrete_GraphicsLevel
*levels
= smu_data
->smc_state_table
.GraphicsLevel
;
692 uint32_t i
, max_entry
;
693 uint8_t highest_pcie_level_enabled
= 0;
694 uint8_t lowest_pcie_level_enabled
= 0, mid_pcie_level_enabled
= 0;
698 memset(levels
, 0x00, level_array_size
);
700 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++) {
701 result
= tonga_populate_single_graphic_level(hwmgr
,
702 dpm_table
->sclk_table
.dpm_levels
[i
].value
,
703 &(smu_data
->smc_state_table
.GraphicsLevel
[i
]));
707 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
709 smu_data
->smc_state_table
.GraphicsLevel
[i
].DeepSleepDivId
= 0;
712 /* Only enable level 0 for now. */
713 smu_data
->smc_state_table
.GraphicsLevel
[0].EnabledForActivity
= 1;
715 /* set highest level watermark to high */
716 if (dpm_table
->sclk_table
.count
> 1)
717 smu_data
->smc_state_table
.GraphicsLevel
[dpm_table
->sclk_table
.count
-1].DisplayWatermark
=
718 PPSMC_DISPLAY_WATERMARK_HIGH
;
720 smu_data
->smc_state_table
.GraphicsDpmLevelCount
=
721 (uint8_t)dpm_table
->sclk_table
.count
;
722 data
->dpm_level_enable_mask
.sclk_dpm_enable_mask
=
723 phm_get_dpm_level_enable_mask_value(&dpm_table
->sclk_table
);
725 if (pcie_table
!= NULL
) {
726 PP_ASSERT_WITH_CODE((pcie_entry_count
>= 1),
727 "There must be 1 or more PCIE levels defined in PPTable.",
729 max_entry
= pcie_entry_count
- 1; /* for indexing, we need to decrement by 1.*/
730 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++) {
731 smu_data
->smc_state_table
.GraphicsLevel
[i
].pcieDpmLevel
=
732 (uint8_t) ((i
< max_entry
) ? i
: max_entry
);
735 if (0 == data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
)
736 pr_err("Pcie Dpm Enablemask is 0 !");
738 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
739 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
740 (1<<(highest_pcie_level_enabled
+1))) != 0)) {
741 highest_pcie_level_enabled
++;
744 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
745 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
746 (1<<lowest_pcie_level_enabled
)) == 0)) {
747 lowest_pcie_level_enabled
++;
750 while ((count
< highest_pcie_level_enabled
) &&
751 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
752 (1<<(lowest_pcie_level_enabled
+1+count
))) == 0)) {
755 mid_pcie_level_enabled
= (lowest_pcie_level_enabled
+1+count
) < highest_pcie_level_enabled
?
756 (lowest_pcie_level_enabled
+1+count
) : highest_pcie_level_enabled
;
759 /* set pcieDpmLevel to highest_pcie_level_enabled*/
760 for (i
= 2; i
< dpm_table
->sclk_table
.count
; i
++)
761 smu_data
->smc_state_table
.GraphicsLevel
[i
].pcieDpmLevel
= highest_pcie_level_enabled
;
763 /* set pcieDpmLevel to lowest_pcie_level_enabled*/
764 smu_data
->smc_state_table
.GraphicsLevel
[0].pcieDpmLevel
= lowest_pcie_level_enabled
;
766 /* set pcieDpmLevel to mid_pcie_level_enabled*/
767 smu_data
->smc_state_table
.GraphicsLevel
[1].pcieDpmLevel
= mid_pcie_level_enabled
;
769 /* level count will send to smc once at init smc table and never change*/
770 result
= smu7_copy_bytes_to_smc(hwmgr
, level_array_address
,
771 (uint8_t *)levels
, (uint32_t)level_array_size
,
777 static int tonga_calculate_mclk_params(
778 struct pp_hwmgr
*hwmgr
,
779 uint32_t memory_clock
,
780 SMU72_Discrete_MemoryLevel
*mclk
,
785 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
787 uint32_t dll_cntl
= data
->clock_registers
.vDLL_CNTL
;
788 uint32_t mclk_pwrmgt_cntl
= data
->clock_registers
.vMCLK_PWRMGT_CNTL
;
789 uint32_t mpll_ad_func_cntl
= data
->clock_registers
.vMPLL_AD_FUNC_CNTL
;
790 uint32_t mpll_dq_func_cntl
= data
->clock_registers
.vMPLL_DQ_FUNC_CNTL
;
791 uint32_t mpll_func_cntl
= data
->clock_registers
.vMPLL_FUNC_CNTL
;
792 uint32_t mpll_func_cntl_1
= data
->clock_registers
.vMPLL_FUNC_CNTL_1
;
793 uint32_t mpll_func_cntl_2
= data
->clock_registers
.vMPLL_FUNC_CNTL_2
;
794 uint32_t mpll_ss1
= data
->clock_registers
.vMPLL_SS1
;
795 uint32_t mpll_ss2
= data
->clock_registers
.vMPLL_SS2
;
797 pp_atomctrl_memory_clock_param mpll_param
;
800 result
= atomctrl_get_memory_pll_dividers_si(hwmgr
,
801 memory_clock
, &mpll_param
, strobe_mode
);
804 "Error retrieving Memory Clock Parameters from VBIOS.",
807 /* MPLL_FUNC_CNTL setup*/
808 mpll_func_cntl
= PHM_SET_FIELD(mpll_func_cntl
, MPLL_FUNC_CNTL
, BWCTRL
,
811 /* MPLL_FUNC_CNTL_1 setup*/
812 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
813 MPLL_FUNC_CNTL_1
, CLKF
,
814 mpll_param
.mpll_fb_divider
.cl_kf
);
815 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
816 MPLL_FUNC_CNTL_1
, CLKFRAC
,
817 mpll_param
.mpll_fb_divider
.clk_frac
);
818 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
819 MPLL_FUNC_CNTL_1
, VCO_MODE
,
820 mpll_param
.vco_mode
);
822 /* MPLL_AD_FUNC_CNTL setup*/
823 mpll_ad_func_cntl
= PHM_SET_FIELD(mpll_ad_func_cntl
,
824 MPLL_AD_FUNC_CNTL
, YCLK_POST_DIV
,
825 mpll_param
.mpll_post_divider
);
827 if (data
->is_memory_gddr5
) {
828 /* MPLL_DQ_FUNC_CNTL setup*/
829 mpll_dq_func_cntl
= PHM_SET_FIELD(mpll_dq_func_cntl
,
830 MPLL_DQ_FUNC_CNTL
, YCLK_SEL
,
831 mpll_param
.yclk_sel
);
832 mpll_dq_func_cntl
= PHM_SET_FIELD(mpll_dq_func_cntl
,
833 MPLL_DQ_FUNC_CNTL
, YCLK_POST_DIV
,
834 mpll_param
.mpll_post_divider
);
837 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
838 PHM_PlatformCaps_MemorySpreadSpectrumSupport
)) {
840 ************************************
841 Fref = Reference Frequency
842 NF = Feedback divider ratio
843 NR = Reference divider ratio
844 Fnom = Nominal VCO output frequency = Fref * NF / NR
846 D = Percentage down-spread / 2
847 Fint = Reference input frequency to PFD = Fref / NR
848 NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
849 CLKS = NS - 1 = ISS_STEP_NUM[11:0]
850 NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
851 CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
852 *************************************
854 pp_atomctrl_internal_ss_info ss_info
;
857 uint32_t reference_clock
= atomctrl_get_mpll_reference_clock(hwmgr
);
859 /* for GDDR5 for all modes and DDR3 */
860 if (1 == mpll_param
.qdr
)
861 freq_nom
= memory_clock
* 4 * (1 << mpll_param
.mpll_post_divider
);
863 freq_nom
= memory_clock
* 2 * (1 << mpll_param
.mpll_post_divider
);
865 /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/
866 tmp
= (freq_nom
/ reference_clock
);
869 if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr
, freq_nom
, &ss_info
)) {
870 /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
871 /* ss.Info.speed_spectrum_rate -- in unit of khz */
872 /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
873 /* = reference_clock * 5 / speed_spectrum_rate */
874 uint32_t clks
= reference_clock
* 5 / ss_info
.speed_spectrum_rate
;
876 /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
877 /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
879 (uint32_t)((((131 * ss_info
.speed_spectrum_percentage
*
880 ss_info
.speed_spectrum_rate
) / 100) * tmp
) / freq_nom
);
882 mpll_ss1
= PHM_SET_FIELD(mpll_ss1
, MPLL_SS1
, CLKV
, clkv
);
883 mpll_ss2
= PHM_SET_FIELD(mpll_ss2
, MPLL_SS2
, CLKS
, clks
);
887 /* MCLK_PWRMGT_CNTL setup */
888 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
889 MCLK_PWRMGT_CNTL
, DLL_SPEED
, mpll_param
.dll_speed
);
890 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
891 MCLK_PWRMGT_CNTL
, MRDCK0_PDNB
, dllStateOn
);
892 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
893 MCLK_PWRMGT_CNTL
, MRDCK1_PDNB
, dllStateOn
);
895 /* Save the result data to outpupt memory level structure */
896 mclk
->MclkFrequency
= memory_clock
;
897 mclk
->MpllFuncCntl
= mpll_func_cntl
;
898 mclk
->MpllFuncCntl_1
= mpll_func_cntl_1
;
899 mclk
->MpllFuncCntl_2
= mpll_func_cntl_2
;
900 mclk
->MpllAdFuncCntl
= mpll_ad_func_cntl
;
901 mclk
->MpllDqFuncCntl
= mpll_dq_func_cntl
;
902 mclk
->MclkPwrmgtCntl
= mclk_pwrmgt_cntl
;
903 mclk
->DllCntl
= dll_cntl
;
904 mclk
->MpllSs1
= mpll_ss1
;
905 mclk
->MpllSs2
= mpll_ss2
;
910 static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock
,
913 uint8_t mc_para_index
;
916 if (memory_clock
< 12500)
917 mc_para_index
= 0x00;
918 else if (memory_clock
> 47500)
919 mc_para_index
= 0x0f;
921 mc_para_index
= (uint8_t)((memory_clock
- 10000) / 2500);
923 if (memory_clock
< 65000)
924 mc_para_index
= 0x00;
925 else if (memory_clock
> 135000)
926 mc_para_index
= 0x0f;
928 mc_para_index
= (uint8_t)((memory_clock
- 60000) / 5000);
931 return mc_para_index
;
934 static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock
)
936 uint8_t mc_para_index
;
938 if (memory_clock
< 10000)
940 else if (memory_clock
>= 80000)
941 mc_para_index
= 0x0f;
943 mc_para_index
= (uint8_t)((memory_clock
- 10000) / 5000 + 1);
945 return mc_para_index
;
949 static int tonga_populate_single_memory_level(
950 struct pp_hwmgr
*hwmgr
,
951 uint32_t memory_clock
,
952 SMU72_Discrete_MemoryLevel
*memory_level
955 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
956 struct phm_ppt_v1_information
*pptable_info
=
957 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
958 uint32_t mclk_edc_wr_enable_threshold
= 40000;
959 uint32_t mclk_stutter_mode_threshold
= 30000;
960 uint32_t mclk_edc_enable_threshold
= 40000;
961 uint32_t mclk_strobe_mode_threshold
= 40000;
962 phm_ppt_v1_clock_voltage_dependency_table
*vdd_dep_table
= NULL
;
967 if (hwmgr
->od_enabled
)
968 vdd_dep_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)&data
->odn_dpm_table
.vdd_dependency_on_mclk
;
970 vdd_dep_table
= pptable_info
->vdd_dep_on_mclk
;
972 if (NULL
!= vdd_dep_table
) {
973 result
= tonga_get_dependency_volt_by_clk(hwmgr
,
976 &memory_level
->MinVoltage
, &mvdd
);
979 "can not find MinVddc voltage value from memory VDDC "
980 "voltage dependency table",
984 if (data
->mvdd_control
== SMU7_VOLTAGE_CONTROL_NONE
)
985 memory_level
->MinMvdd
= data
->vbios_boot_state
.mvdd_bootup_value
;
987 memory_level
->MinMvdd
= mvdd
;
989 memory_level
->EnabledForThrottle
= 1;
990 memory_level
->EnabledForActivity
= 0;
991 memory_level
->UpHyst
= data
->current_profile_setting
.mclk_up_hyst
;
992 memory_level
->DownHyst
= data
->current_profile_setting
.mclk_down_hyst
;
993 memory_level
->VoltageDownHyst
= 0;
995 /* Indicates maximum activity level for this performance level.*/
996 memory_level
->ActivityLevel
= data
->current_profile_setting
.mclk_activity
;
997 memory_level
->StutterEnable
= 0;
998 memory_level
->StrobeEnable
= 0;
999 memory_level
->EdcReadEnable
= 0;
1000 memory_level
->EdcWriteEnable
= 0;
1001 memory_level
->RttEnable
= 0;
1003 /* default set to low watermark. Highest level will be set to high later.*/
1004 memory_level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1006 data
->display_timing
.num_existing_displays
= hwmgr
->display_config
->num_display
;
1008 if ((mclk_stutter_mode_threshold
!= 0) &&
1009 (memory_clock
<= mclk_stutter_mode_threshold
) &&
1010 (!data
->is_uvd_enabled
)
1011 && (PHM_READ_FIELD(hwmgr
->device
, DPG_PIPE_STUTTER_CONTROL
, STUTTER_ENABLE
) & 0x1)
1012 && (data
->display_timing
.num_existing_displays
<= 2)
1013 && (data
->display_timing
.num_existing_displays
!= 0))
1014 memory_level
->StutterEnable
= 1;
1016 /* decide strobe mode*/
1017 memory_level
->StrobeEnable
= (mclk_strobe_mode_threshold
!= 0) &&
1018 (memory_clock
<= mclk_strobe_mode_threshold
);
1020 /* decide EDC mode and memory clock ratio*/
1021 if (data
->is_memory_gddr5
) {
1022 memory_level
->StrobeRatio
= tonga_get_mclk_frequency_ratio(memory_clock
,
1023 memory_level
->StrobeEnable
);
1025 if ((mclk_edc_enable_threshold
!= 0) &&
1026 (memory_clock
> mclk_edc_enable_threshold
)) {
1027 memory_level
->EdcReadEnable
= 1;
1030 if ((mclk_edc_wr_enable_threshold
!= 0) &&
1031 (memory_clock
> mclk_edc_wr_enable_threshold
)) {
1032 memory_level
->EdcWriteEnable
= 1;
1035 if (memory_level
->StrobeEnable
) {
1036 if (tonga_get_mclk_frequency_ratio(memory_clock
, 1) >=
1037 ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC7
) >> 16) & 0xf)) {
1038 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC5
) >> 1) & 0x1) ? 1 : 0;
1040 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC6
) >> 1) & 0x1) ? 1 : 0;
1044 dll_state_on
= data
->dll_default_on
;
1047 memory_level
->StrobeRatio
=
1048 tonga_get_ddr3_mclk_frequency_ratio(memory_clock
);
1049 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC5
) >> 1) & 0x1) ? 1 : 0;
1052 result
= tonga_calculate_mclk_params(hwmgr
,
1053 memory_clock
, memory_level
, memory_level
->StrobeEnable
, dll_state_on
);
1056 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MinMvdd
);
1057 /* MCLK frequency in units of 10KHz*/
1058 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MclkFrequency
);
1059 /* Indicates maximum activity level for this performance level.*/
1060 CONVERT_FROM_HOST_TO_SMC_US(memory_level
->ActivityLevel
);
1061 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl
);
1062 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl_1
);
1063 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl_2
);
1064 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllAdFuncCntl
);
1065 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllDqFuncCntl
);
1066 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MclkPwrmgtCntl
);
1067 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->DllCntl
);
1068 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllSs1
);
1069 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllSs2
);
1075 int tonga_populate_all_memory_levels(struct pp_hwmgr
*hwmgr
)
1077 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1078 struct tonga_smumgr
*smu_data
=
1079 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1080 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
1083 /* populate MCLK dpm table to SMU7 */
1084 uint32_t level_array_address
=
1085 smu_data
->smu7_data
.dpm_table_start
+
1086 offsetof(SMU72_Discrete_DpmTable
, MemoryLevel
);
1087 uint32_t level_array_size
=
1088 sizeof(SMU72_Discrete_MemoryLevel
) *
1089 SMU72_MAX_LEVELS_MEMORY
;
1090 SMU72_Discrete_MemoryLevel
*levels
=
1091 smu_data
->smc_state_table
.MemoryLevel
;
1094 memset(levels
, 0x00, level_array_size
);
1096 for (i
= 0; i
< dpm_table
->mclk_table
.count
; i
++) {
1097 PP_ASSERT_WITH_CODE((0 != dpm_table
->mclk_table
.dpm_levels
[i
].value
),
1098 "can not populate memory level as memory clock is zero",
1100 result
= tonga_populate_single_memory_level(
1102 dpm_table
->mclk_table
.dpm_levels
[i
].value
,
1103 &(smu_data
->smc_state_table
.MemoryLevel
[i
]));
1108 /* Only enable level 0 for now.*/
1109 smu_data
->smc_state_table
.MemoryLevel
[0].EnabledForActivity
= 1;
1112 * in order to prevent MC activity from stutter mode to push DPM up.
1113 * the UVD change complements this by putting the MCLK in a higher state
1114 * by default such that we are not effected by up threshold or and MCLK DPM latency.
1116 smu_data
->smc_state_table
.MemoryLevel
[0].ActivityLevel
= 0x1F;
1117 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.MemoryLevel
[0].ActivityLevel
);
1119 smu_data
->smc_state_table
.MemoryDpmLevelCount
= (uint8_t)dpm_table
->mclk_table
.count
;
1120 data
->dpm_level_enable_mask
.mclk_dpm_enable_mask
= phm_get_dpm_level_enable_mask_value(&dpm_table
->mclk_table
);
1121 /* set highest level watermark to high*/
1122 smu_data
->smc_state_table
.MemoryLevel
[dpm_table
->mclk_table
.count
-1].DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_HIGH
;
1124 /* level count will send to smc once at init smc table and never change*/
1125 result
= smu7_copy_bytes_to_smc(hwmgr
,
1126 level_array_address
, (uint8_t *)levels
, (uint32_t)level_array_size
,
1132 static int tonga_populate_mvdd_value(struct pp_hwmgr
*hwmgr
,
1133 uint32_t mclk
, SMIO_Pattern
*smio_pattern
)
1135 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1136 struct phm_ppt_v1_information
*table_info
=
1137 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1140 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->mvdd_control
) {
1141 /* find mvdd value which clock is more than request */
1142 for (i
= 0; i
< table_info
->vdd_dep_on_mclk
->count
; i
++) {
1143 if (mclk
<= table_info
->vdd_dep_on_mclk
->entries
[i
].clk
) {
1144 /* Always round to higher voltage. */
1145 smio_pattern
->Voltage
=
1146 data
->mvdd_voltage_table
.entries
[i
].value
;
1151 PP_ASSERT_WITH_CODE(i
< table_info
->vdd_dep_on_mclk
->count
,
1152 "MVDD Voltage is outside the supported range.",
1162 static int tonga_populate_smc_acpi_level(struct pp_hwmgr
*hwmgr
,
1163 SMU72_Discrete_DpmTable
*table
)
1166 struct tonga_smumgr
*smu_data
=
1167 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1168 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1169 struct pp_atomctrl_clock_dividers_vi dividers
;
1171 SMIO_Pattern voltage_level
;
1172 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
1173 uint32_t spll_func_cntl_2
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_2
;
1174 uint32_t dll_cntl
= data
->clock_registers
.vDLL_CNTL
;
1175 uint32_t mclk_pwrmgt_cntl
= data
->clock_registers
.vMCLK_PWRMGT_CNTL
;
1177 /* The ACPI state should not do DPM on DC (or ever).*/
1178 table
->ACPILevel
.Flags
&= ~PPSMC_SWSTATE_FLAG_DC
;
1180 table
->ACPILevel
.MinVoltage
=
1181 smu_data
->smc_state_table
.GraphicsLevel
[0].MinVoltage
;
1183 /* assign zero for now*/
1184 table
->ACPILevel
.SclkFrequency
= atomctrl_get_reference_clock(hwmgr
);
1186 /* get the engine clock dividers for this clock value*/
1187 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
,
1188 table
->ACPILevel
.SclkFrequency
, ÷rs
);
1190 PP_ASSERT_WITH_CODE(result
== 0,
1191 "Error retrieving Engine Clock dividers from VBIOS.",
1194 /* divider ID for required SCLK*/
1195 table
->ACPILevel
.SclkDid
= (uint8_t)dividers
.pll_post_divider
;
1196 table
->ACPILevel
.DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1197 table
->ACPILevel
.DeepSleepDivId
= 0;
1199 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1201 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1203 spll_func_cntl_2
= PHM_SET_FIELD(spll_func_cntl_2
, CG_SPLL_FUNC_CNTL_2
,
1206 table
->ACPILevel
.CgSpllFuncCntl
= spll_func_cntl
;
1207 table
->ACPILevel
.CgSpllFuncCntl2
= spll_func_cntl_2
;
1208 table
->ACPILevel
.CgSpllFuncCntl3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
1209 table
->ACPILevel
.CgSpllFuncCntl4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
1210 table
->ACPILevel
.SpllSpreadSpectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
1211 table
->ACPILevel
.SpllSpreadSpectrum2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
1212 table
->ACPILevel
.CcPwrDynRm
= 0;
1213 table
->ACPILevel
.CcPwrDynRm1
= 0;
1216 /* For various features to be enabled/disabled while this level is active.*/
1217 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.Flags
);
1218 /* SCLK frequency in units of 10KHz*/
1219 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SclkFrequency
);
1220 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl
);
1221 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl2
);
1222 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl3
);
1223 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl4
);
1224 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum
);
1225 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum2
);
1226 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm
);
1227 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm1
);
1229 /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
1230 table
->MemoryACPILevel
.MinVoltage
=
1231 smu_data
->smc_state_table
.MemoryLevel
[0].MinVoltage
;
1233 /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/
1235 if (0 == tonga_populate_mvdd_value(hwmgr
, 0, &voltage_level
))
1236 table
->MemoryACPILevel
.MinMvdd
=
1237 PP_HOST_TO_SMC_UL(voltage_level
.Voltage
* VOLTAGE_SCALE
);
1239 table
->MemoryACPILevel
.MinMvdd
= 0;
1241 /* Force reset on DLL*/
1242 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1243 MCLK_PWRMGT_CNTL
, MRDCK0_RESET
, 0x1);
1244 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1245 MCLK_PWRMGT_CNTL
, MRDCK1_RESET
, 0x1);
1247 /* Disable DLL in ACPIState*/
1248 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1249 MCLK_PWRMGT_CNTL
, MRDCK0_PDNB
, 0);
1250 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1251 MCLK_PWRMGT_CNTL
, MRDCK1_PDNB
, 0);
1253 /* Enable DLL bypass signal*/
1254 dll_cntl
= PHM_SET_FIELD(dll_cntl
,
1255 DLL_CNTL
, MRDCK0_BYPASS
, 0);
1256 dll_cntl
= PHM_SET_FIELD(dll_cntl
,
1257 DLL_CNTL
, MRDCK1_BYPASS
, 0);
1259 table
->MemoryACPILevel
.DllCntl
=
1260 PP_HOST_TO_SMC_UL(dll_cntl
);
1261 table
->MemoryACPILevel
.MclkPwrmgtCntl
=
1262 PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl
);
1263 table
->MemoryACPILevel
.MpllAdFuncCntl
=
1264 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_AD_FUNC_CNTL
);
1265 table
->MemoryACPILevel
.MpllDqFuncCntl
=
1266 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_DQ_FUNC_CNTL
);
1267 table
->MemoryACPILevel
.MpllFuncCntl
=
1268 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL
);
1269 table
->MemoryACPILevel
.MpllFuncCntl_1
=
1270 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL_1
);
1271 table
->MemoryACPILevel
.MpllFuncCntl_2
=
1272 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL_2
);
1273 table
->MemoryACPILevel
.MpllSs1
=
1274 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_SS1
);
1275 table
->MemoryACPILevel
.MpllSs2
=
1276 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_SS2
);
1278 table
->MemoryACPILevel
.EnabledForThrottle
= 0;
1279 table
->MemoryACPILevel
.EnabledForActivity
= 0;
1280 table
->MemoryACPILevel
.UpHyst
= 0;
1281 table
->MemoryACPILevel
.DownHyst
= 100;
1282 table
->MemoryACPILevel
.VoltageDownHyst
= 0;
1283 /* Indicates maximum activity level for this performance level.*/
1284 table
->MemoryACPILevel
.ActivityLevel
=
1285 PP_HOST_TO_SMC_US(data
->current_profile_setting
.mclk_activity
);
1287 table
->MemoryACPILevel
.StutterEnable
= 0;
1288 table
->MemoryACPILevel
.StrobeEnable
= 0;
1289 table
->MemoryACPILevel
.EdcReadEnable
= 0;
1290 table
->MemoryACPILevel
.EdcWriteEnable
= 0;
1291 table
->MemoryACPILevel
.RttEnable
= 0;
1296 static int tonga_populate_smc_uvd_level(struct pp_hwmgr
*hwmgr
,
1297 SMU72_Discrete_DpmTable
*table
)
1302 pp_atomctrl_clock_dividers_vi dividers
;
1303 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1304 struct phm_ppt_v1_information
*pptable_info
=
1305 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1306 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1307 pptable_info
->mm_dep_table
;
1309 table
->UvdLevelCount
= (uint8_t) (mm_table
->count
);
1310 table
->UvdBootLevel
= 0;
1312 for (count
= 0; count
< table
->UvdLevelCount
; count
++) {
1313 table
->UvdLevel
[count
].VclkFrequency
= mm_table
->entries
[count
].vclk
;
1314 table
->UvdLevel
[count
].DclkFrequency
= mm_table
->entries
[count
].dclk
;
1315 table
->UvdLevel
[count
].MinVoltage
.Vddc
=
1316 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1317 mm_table
->entries
[count
].vddc
);
1318 table
->UvdLevel
[count
].MinVoltage
.VddGfx
=
1319 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1320 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1321 mm_table
->entries
[count
].vddgfx
) : 0;
1322 table
->UvdLevel
[count
].MinVoltage
.Vddci
=
1323 phm_get_voltage_id(&data
->vddci_voltage_table
,
1324 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1325 table
->UvdLevel
[count
].MinVoltage
.Phases
= 1;
1327 /* retrieve divider value for VBIOS */
1328 result
= atomctrl_get_dfs_pll_dividers_vi(
1330 table
->UvdLevel
[count
].VclkFrequency
,
1333 PP_ASSERT_WITH_CODE((!result
),
1334 "can not find divide id for Vclk clock",
1337 table
->UvdLevel
[count
].VclkDivider
= (uint8_t)dividers
.pll_post_divider
;
1339 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1340 table
->UvdLevel
[count
].DclkFrequency
, ÷rs
);
1341 PP_ASSERT_WITH_CODE((!result
),
1342 "can not find divide id for Dclk clock",
1345 table
->UvdLevel
[count
].DclkDivider
=
1346 (uint8_t)dividers
.pll_post_divider
;
1348 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].VclkFrequency
);
1349 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].DclkFrequency
);
1356 static int tonga_populate_smc_vce_level(struct pp_hwmgr
*hwmgr
,
1357 SMU72_Discrete_DpmTable
*table
)
1362 pp_atomctrl_clock_dividers_vi dividers
;
1363 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1364 struct phm_ppt_v1_information
*pptable_info
=
1365 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1366 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1367 pptable_info
->mm_dep_table
;
1369 table
->VceLevelCount
= (uint8_t) (mm_table
->count
);
1370 table
->VceBootLevel
= 0;
1372 for (count
= 0; count
< table
->VceLevelCount
; count
++) {
1373 table
->VceLevel
[count
].Frequency
=
1374 mm_table
->entries
[count
].eclk
;
1375 table
->VceLevel
[count
].MinVoltage
.Vddc
=
1376 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1377 mm_table
->entries
[count
].vddc
);
1378 table
->VceLevel
[count
].MinVoltage
.VddGfx
=
1379 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1380 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1381 mm_table
->entries
[count
].vddgfx
) : 0;
1382 table
->VceLevel
[count
].MinVoltage
.Vddci
=
1383 phm_get_voltage_id(&data
->vddci_voltage_table
,
1384 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1385 table
->VceLevel
[count
].MinVoltage
.Phases
= 1;
1387 /* retrieve divider value for VBIOS */
1388 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1389 table
->VceLevel
[count
].Frequency
, ÷rs
);
1390 PP_ASSERT_WITH_CODE((!result
),
1391 "can not find divide id for VCE engine clock",
1394 table
->VceLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1396 CONVERT_FROM_HOST_TO_SMC_UL(table
->VceLevel
[count
].Frequency
);
1402 static int tonga_populate_smc_acp_level(struct pp_hwmgr
*hwmgr
,
1403 SMU72_Discrete_DpmTable
*table
)
1407 pp_atomctrl_clock_dividers_vi dividers
;
1408 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1409 struct phm_ppt_v1_information
*pptable_info
=
1410 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1411 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1412 pptable_info
->mm_dep_table
;
1414 table
->AcpLevelCount
= (uint8_t) (mm_table
->count
);
1415 table
->AcpBootLevel
= 0;
1417 for (count
= 0; count
< table
->AcpLevelCount
; count
++) {
1418 table
->AcpLevel
[count
].Frequency
=
1419 pptable_info
->mm_dep_table
->entries
[count
].aclk
;
1420 table
->AcpLevel
[count
].MinVoltage
.Vddc
=
1421 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1422 mm_table
->entries
[count
].vddc
);
1423 table
->AcpLevel
[count
].MinVoltage
.VddGfx
=
1424 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1425 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1426 mm_table
->entries
[count
].vddgfx
) : 0;
1427 table
->AcpLevel
[count
].MinVoltage
.Vddci
=
1428 phm_get_voltage_id(&data
->vddci_voltage_table
,
1429 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1430 table
->AcpLevel
[count
].MinVoltage
.Phases
= 1;
1432 /* retrieve divider value for VBIOS */
1433 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1434 table
->AcpLevel
[count
].Frequency
, ÷rs
);
1435 PP_ASSERT_WITH_CODE((!result
),
1436 "can not find divide id for engine clock", return result
);
1438 table
->AcpLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1440 CONVERT_FROM_HOST_TO_SMC_UL(table
->AcpLevel
[count
].Frequency
);
1446 static int tonga_populate_memory_timing_parameters(
1447 struct pp_hwmgr
*hwmgr
,
1448 uint32_t engine_clock
,
1449 uint32_t memory_clock
,
1450 struct SMU72_Discrete_MCArbDramTimingTableEntry
*arb_regs
1453 uint32_t dramTiming
;
1454 uint32_t dramTiming2
;
1458 result
= atomctrl_set_engine_dram_timings_rv770(hwmgr
,
1459 engine_clock
, memory_clock
);
1461 PP_ASSERT_WITH_CODE(result
== 0,
1462 "Error calling VBIOS to set DRAM_TIMING.", return result
);
1464 dramTiming
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING
);
1465 dramTiming2
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING2
);
1466 burstTime
= PHM_READ_FIELD(hwmgr
->device
, MC_ARB_BURST_TIME
, STATE0
);
1468 arb_regs
->McArbDramTiming
= PP_HOST_TO_SMC_UL(dramTiming
);
1469 arb_regs
->McArbDramTiming2
= PP_HOST_TO_SMC_UL(dramTiming2
);
1470 arb_regs
->McArbBurstTime
= (uint8_t)burstTime
;
1475 static int tonga_program_memory_timing_parameters(struct pp_hwmgr
*hwmgr
)
1477 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1478 struct tonga_smumgr
*smu_data
=
1479 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1481 SMU72_Discrete_MCArbDramTimingTable arb_regs
;
1484 memset(&arb_regs
, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable
));
1486 for (i
= 0; i
< data
->dpm_table
.sclk_table
.count
; i
++) {
1487 for (j
= 0; j
< data
->dpm_table
.mclk_table
.count
; j
++) {
1488 result
= tonga_populate_memory_timing_parameters
1489 (hwmgr
, data
->dpm_table
.sclk_table
.dpm_levels
[i
].value
,
1490 data
->dpm_table
.mclk_table
.dpm_levels
[j
].value
,
1491 &arb_regs
.entries
[i
][j
]);
1499 result
= smu7_copy_bytes_to_smc(
1501 smu_data
->smu7_data
.arb_table_start
,
1502 (uint8_t *)&arb_regs
,
1503 sizeof(SMU72_Discrete_MCArbDramTimingTable
),
1511 static int tonga_populate_smc_boot_level(struct pp_hwmgr
*hwmgr
,
1512 SMU72_Discrete_DpmTable
*table
)
1515 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1516 struct tonga_smumgr
*smu_data
=
1517 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1518 table
->GraphicsBootLevel
= 0;
1519 table
->MemoryBootLevel
= 0;
1521 /* find boot level from dpm table*/
1522 result
= phm_find_boot_level(&(data
->dpm_table
.sclk_table
),
1523 data
->vbios_boot_state
.sclk_bootup_value
,
1524 (uint32_t *)&(smu_data
->smc_state_table
.GraphicsBootLevel
));
1527 smu_data
->smc_state_table
.GraphicsBootLevel
= 0;
1528 pr_err("[powerplay] VBIOS did not find boot engine "
1529 "clock value in dependency table. "
1530 "Using Graphics DPM level 0 !");
1534 result
= phm_find_boot_level(&(data
->dpm_table
.mclk_table
),
1535 data
->vbios_boot_state
.mclk_bootup_value
,
1536 (uint32_t *)&(smu_data
->smc_state_table
.MemoryBootLevel
));
1539 smu_data
->smc_state_table
.MemoryBootLevel
= 0;
1540 pr_err("[powerplay] VBIOS did not find boot "
1541 "engine clock value in dependency table."
1542 "Using Memory DPM level 0 !");
1546 table
->BootVoltage
.Vddc
=
1547 phm_get_voltage_id(&(data
->vddc_voltage_table
),
1548 data
->vbios_boot_state
.vddc_bootup_value
);
1549 table
->BootVoltage
.VddGfx
=
1550 phm_get_voltage_id(&(data
->vddgfx_voltage_table
),
1551 data
->vbios_boot_state
.vddgfx_bootup_value
);
1552 table
->BootVoltage
.Vddci
=
1553 phm_get_voltage_id(&(data
->vddci_voltage_table
),
1554 data
->vbios_boot_state
.vddci_bootup_value
);
1555 table
->BootMVdd
= data
->vbios_boot_state
.mvdd_bootup_value
;
1557 CONVERT_FROM_HOST_TO_SMC_US(table
->BootMVdd
);
1562 static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr
*hwmgr
)
1564 uint32_t ro
, efuse
, efuse2
, clock_freq
, volt_without_cks
,
1565 volt_with_cks
, value
;
1566 uint16_t clock_freq_u16
;
1567 struct tonga_smumgr
*smu_data
=
1568 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1569 uint8_t type
, i
, j
, cks_setting
, stretch_amount
, stretch_amount2
,
1571 struct phm_ppt_v1_information
*table_info
=
1572 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1573 struct phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
=
1574 table_info
->vdd_dep_on_sclk
;
1575 uint32_t hw_revision
, dev_id
;
1576 struct amdgpu_device
*adev
= hwmgr
->adev
;
1578 stretch_amount
= (uint8_t)table_info
->cac_dtp_table
->usClockStretchAmount
;
1580 hw_revision
= adev
->pdev
->revision
;
1581 dev_id
= adev
->pdev
->device
;
1583 /* Read SMU_Eefuse to read and calculate RO and determine
1584 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1586 efuse
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1587 ixSMU_EFUSE_0
+ (146 * 4));
1588 efuse2
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1589 ixSMU_EFUSE_0
+ (148 * 4));
1590 efuse
&= 0xFF000000;
1591 efuse
= efuse
>> 24;
1595 ro
= (2300 - 1350) * efuse
/ 255 + 1350;
1597 ro
= (2500 - 1000) * efuse
/ 255 + 1000;
1604 /* Populate Stretch amount */
1605 smu_data
->smc_state_table
.ClockStretcherAmount
= stretch_amount
;
1608 /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1609 for (i
= 0; i
< sclk_table
->count
; i
++) {
1610 smu_data
->smc_state_table
.Sclk_CKS_masterEn0_7
|=
1611 sclk_table
->entries
[i
].cks_enable
<< i
;
1612 if (ASICID_IS_TONGA_P(dev_id
, hw_revision
)) {
1613 volt_without_cks
= (uint32_t)((7732 + 60 - ro
- 20838 *
1614 (sclk_table
->entries
[i
].clk
/100) / 10000) * 1000 /
1615 (8730 - (5301 * (sclk_table
->entries
[i
].clk
/100) / 1000)));
1616 volt_with_cks
= (uint32_t)((5250 + 51 - ro
- 2404 *
1617 (sclk_table
->entries
[i
].clk
/100) / 100000) * 1000 /
1618 (6146 - (3193 * (sclk_table
->entries
[i
].clk
/100) / 1000)));
1620 volt_without_cks
= (uint32_t)((14041 *
1621 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3571 + 75 - ro
) * 1000 /
1622 (4026 - (13924 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1623 volt_with_cks
= (uint32_t)((13946 *
1624 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3320 + 45 - ro
) * 1000 /
1625 (3664 - (11454 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1627 if (volt_without_cks
>= volt_with_cks
)
1628 volt_offset
= (uint8_t)(((volt_without_cks
- volt_with_cks
+
1629 sclk_table
->entries
[i
].cks_voffset
) * 100 / 625) + 1);
1630 smu_data
->smc_state_table
.Sclk_voltageOffset
[i
] = volt_offset
;
1633 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1634 STRETCH_ENABLE
, 0x0);
1635 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1637 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1639 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1642 /* Populate CKS Lookup Table */
1643 if (stretch_amount
== 1 || stretch_amount
== 2 || stretch_amount
== 5)
1644 stretch_amount2
= 0;
1645 else if (stretch_amount
== 3 || stretch_amount
== 4)
1646 stretch_amount2
= 1;
1648 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
1649 PHM_PlatformCaps_ClockStretcher
);
1650 PP_ASSERT_WITH_CODE(false,
1651 "Stretch Amount in PPTable not supported",
1655 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1657 value
&= 0xFFC2FF87;
1658 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].minFreq
=
1659 tonga_clock_stretcher_lookup_table
[stretch_amount2
][0];
1660 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].maxFreq
=
1661 tonga_clock_stretcher_lookup_table
[stretch_amount2
][1];
1662 clock_freq_u16
= (uint16_t)(PP_SMC_TO_HOST_UL(smu_data
->smc_state_table
.
1663 GraphicsLevel
[smu_data
->smc_state_table
.GraphicsDpmLevelCount
- 1].
1664 SclkFrequency
) / 100);
1665 if (tonga_clock_stretcher_lookup_table
[stretch_amount2
][0] <
1667 tonga_clock_stretcher_lookup_table
[stretch_amount2
][1] >
1669 /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
1670 value
|= (tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 16;
1671 /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
1672 value
|= (tonga_clock_stretcher_lookup_table
[stretch_amount2
][2]) << 18;
1673 /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
1674 value
|= (tonga_clock_stretch_amount_conversion
1675 [tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]]
1676 [stretch_amount
]) << 3;
1678 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1679 CKS_LOOKUPTableEntry
[0].minFreq
);
1680 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1681 CKS_LOOKUPTableEntry
[0].maxFreq
);
1682 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
=
1683 tonga_clock_stretcher_lookup_table
[stretch_amount2
][2] & 0x7F;
1684 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
|=
1685 (tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 7;
1687 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1688 ixPWR_CKS_CNTL
, value
);
1690 /* Populate DDT Lookup Table */
1691 for (i
= 0; i
< 4; i
++) {
1692 /* Assign the minimum and maximum VID stored
1693 * in the last row of Clock Stretcher Voltage Table.
1695 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1696 ClockStretcherDataTableEntry
[i
].minVID
=
1697 (uint8_t) tonga_clock_stretcher_ddt_table
[type
][i
][2];
1698 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1699 ClockStretcherDataTableEntry
[i
].maxVID
=
1700 (uint8_t) tonga_clock_stretcher_ddt_table
[type
][i
][3];
1701 /* Loop through each SCLK and check the frequency
1702 * to see if it lies within the frequency for clock stretcher.
1704 for (j
= 0; j
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; j
++) {
1706 clock_freq
= PP_SMC_TO_HOST_UL(
1707 smu_data
->smc_state_table
.GraphicsLevel
[j
].SclkFrequency
);
1708 /* Check the allowed frequency against the sclk level[j].
1709 * Sclk's endianness has already been converted,
1710 * and it's in 10Khz unit,
1711 * as opposed to Data table, which is in Mhz unit.
1713 if (clock_freq
>= tonga_clock_stretcher_ddt_table
[type
][i
][0] * 100) {
1715 if (clock_freq
< tonga_clock_stretcher_ddt_table
[type
][i
][1] * 100)
1718 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1719 ClockStretcherDataTableEntry
[i
].setting
|= cks_setting
<< (j
* 2);
1721 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.
1722 ClockStretcherDataTable
.
1723 ClockStretcherDataTableEntry
[i
].setting
);
1726 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1728 value
&= 0xFFFFFFFE;
1729 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1730 ixPWR_CKS_CNTL
, value
);
1735 static int tonga_populate_vr_config(struct pp_hwmgr
*hwmgr
,
1736 SMU72_Discrete_DpmTable
*table
)
1738 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1741 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vdd_gfx_control
) {
1743 config
= VR_SVI2_PLANE_1
;
1744 table
->VRConfig
|= (config
<<VRCONF_VDDGFX_SHIFT
);
1746 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
1747 config
= VR_SVI2_PLANE_2
;
1748 table
->VRConfig
|= config
;
1750 pr_err("VDDC and VDDGFX should "
1751 "be both on SVI2 control in splitted mode !\n");
1755 config
= VR_MERGED_WITH_VDDC
;
1756 table
->VRConfig
|= (config
<<VRCONF_VDDGFX_SHIFT
);
1758 /* Set Vddc Voltage Controller */
1759 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
1760 config
= VR_SVI2_PLANE_1
;
1761 table
->VRConfig
|= config
;
1763 pr_err("VDDC should be on "
1764 "SVI2 control in merged mode !\n");
1768 /* Set Vddci Voltage Controller */
1769 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vddci_control
) {
1770 config
= VR_SVI2_PLANE_2
; /* only in merged mode */
1771 table
->VRConfig
|= (config
<<VRCONF_VDDCI_SHIFT
);
1772 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->vddci_control
) {
1773 config
= VR_SMIO_PATTERN_1
;
1774 table
->VRConfig
|= (config
<<VRCONF_VDDCI_SHIFT
);
1777 /* Set Mvdd Voltage Controller */
1778 if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->mvdd_control
) {
1779 config
= VR_SMIO_PATTERN_2
;
1780 table
->VRConfig
|= (config
<<VRCONF_MVDD_SHIFT
);
1786 static int tonga_init_arb_table_index(struct pp_hwmgr
*hwmgr
)
1788 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1793 * This is a read-modify-write on the first byte of the ARB table.
1794 * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure
1795 * is the field 'current'.
1796 * This solution is ugly, but we never write the whole table only
1797 * individual fields in it.
1798 * In reality this field should not be in that structure
1799 * but in a soft register.
1801 result
= smu7_read_smc_sram_dword(hwmgr
,
1802 smu_data
->smu7_data
.arb_table_start
, &tmp
, SMC_RAM_END
);
1808 tmp
|= ((uint32_t)MC_CG_ARB_FREQ_F1
) << 24;
1810 return smu7_write_smc_sram_dword(hwmgr
,
1811 smu_data
->smu7_data
.arb_table_start
, tmp
, SMC_RAM_END
);
1815 static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr
*hwmgr
)
1817 struct tonga_smumgr
*smu_data
=
1818 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1819 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1820 SMU72_Discrete_DpmTable
*dpm_table
= &(smu_data
->smc_state_table
);
1821 struct phm_ppt_v1_information
*table_info
=
1822 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1823 struct phm_cac_tdp_table
*cac_dtp_table
= table_info
->cac_dtp_table
;
1825 const uint16_t *pdef1
, *pdef2
;
1827 dpm_table
->DefaultTdp
= PP_HOST_TO_SMC_US(
1828 (uint16_t)(cac_dtp_table
->usTDP
* 256));
1829 dpm_table
->TargetTdp
= PP_HOST_TO_SMC_US(
1830 (uint16_t)(cac_dtp_table
->usConfigurableTDP
* 256));
1832 PP_ASSERT_WITH_CODE(cac_dtp_table
->usTargetOperatingTemp
<= 255,
1833 "Target Operating Temp is out of Range !",
1836 dpm_table
->GpuTjMax
= (uint8_t)(cac_dtp_table
->usTargetOperatingTemp
);
1837 dpm_table
->GpuTjHyst
= 8;
1839 dpm_table
->DTEAmbientTempBase
= defaults
->dte_ambient_temp_base
;
1841 dpm_table
->BAPM_TEMP_GRADIENT
=
1842 PP_HOST_TO_SMC_UL(defaults
->bapm_temp_gradient
);
1843 pdef1
= defaults
->bapmti_r
;
1844 pdef2
= defaults
->bapmti_rc
;
1846 for (i
= 0; i
< SMU72_DTE_ITERATIONS
; i
++) {
1847 for (j
= 0; j
< SMU72_DTE_SOURCES
; j
++) {
1848 for (k
= 0; k
< SMU72_DTE_SINKS
; k
++) {
1849 dpm_table
->BAPMTI_R
[i
][j
][k
] =
1850 PP_HOST_TO_SMC_US(*pdef1
);
1851 dpm_table
->BAPMTI_RC
[i
][j
][k
] =
1852 PP_HOST_TO_SMC_US(*pdef2
);
1862 static int tonga_populate_svi_load_line(struct pp_hwmgr
*hwmgr
)
1864 struct tonga_smumgr
*smu_data
=
1865 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1866 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1868 smu_data
->power_tune_table
.SviLoadLineEn
= defaults
->svi_load_line_en
;
1869 smu_data
->power_tune_table
.SviLoadLineVddC
= defaults
->svi_load_line_vddC
;
1870 smu_data
->power_tune_table
.SviLoadLineTrimVddC
= 3;
1871 smu_data
->power_tune_table
.SviLoadLineOffsetVddC
= 0;
1876 static int tonga_populate_tdc_limit(struct pp_hwmgr
*hwmgr
)
1879 struct tonga_smumgr
*smu_data
=
1880 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1881 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1882 struct phm_ppt_v1_information
*table_info
=
1883 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1885 /* TDC number of fraction bits are changed from 8 to 7
1886 * for Fiji as requested by SMC team
1888 tdc_limit
= (uint16_t)(table_info
->cac_dtp_table
->usTDC
* 256);
1889 smu_data
->power_tune_table
.TDC_VDDC_PkgLimit
=
1890 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit
);
1891 smu_data
->power_tune_table
.TDC_VDDC_ThrottleReleaseLimitPerc
=
1892 defaults
->tdc_vddc_throttle_release_limit_perc
;
1893 smu_data
->power_tune_table
.TDC_MAWt
= defaults
->tdc_mawt
;
1898 static int tonga_populate_dw8(struct pp_hwmgr
*hwmgr
, uint32_t fuse_table_offset
)
1900 struct tonga_smumgr
*smu_data
=
1901 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1902 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1905 if (smu7_read_smc_sram_dword(hwmgr
,
1907 offsetof(SMU72_Discrete_PmFuses
, TdcWaterfallCtl
),
1908 (uint32_t *)&temp
, SMC_RAM_END
))
1909 PP_ASSERT_WITH_CODE(false,
1910 "Attempt to read PmFuses.DW6 "
1911 "(SviLoadLineEn) from SMC Failed !",
1914 smu_data
->power_tune_table
.TdcWaterfallCtl
= defaults
->tdc_waterfall_ctl
;
1919 static int tonga_populate_temperature_scaler(struct pp_hwmgr
*hwmgr
)
1922 struct tonga_smumgr
*smu_data
=
1923 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1925 /* Currently not used. Set all to zero. */
1926 for (i
= 0; i
< 16; i
++)
1927 smu_data
->power_tune_table
.LPMLTemperatureScaler
[i
] = 0;
1932 static int tonga_populate_fuzzy_fan(struct pp_hwmgr
*hwmgr
)
1934 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1936 if ((hwmgr
->thermal_controller
.advanceFanControlParameters
.
1937 usFanOutputSensitivity
& (1 << 15)) ||
1938 (hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
== 0))
1939 hwmgr
->thermal_controller
.advanceFanControlParameters
.
1940 usFanOutputSensitivity
= hwmgr
->thermal_controller
.
1941 advanceFanControlParameters
.usDefaultFanOutputSensitivity
;
1943 smu_data
->power_tune_table
.FuzzyFan_PwmSetDelta
=
1944 PP_HOST_TO_SMC_US(hwmgr
->thermal_controller
.
1945 advanceFanControlParameters
.usFanOutputSensitivity
);
1949 static int tonga_populate_gnb_lpml(struct pp_hwmgr
*hwmgr
)
1952 struct tonga_smumgr
*smu_data
=
1953 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1955 /* Currently not used. Set all to zero. */
1956 for (i
= 0; i
< 16; i
++)
1957 smu_data
->power_tune_table
.GnbLPML
[i
] = 0;
1962 static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr
*hwmgr
)
1964 struct tonga_smumgr
*smu_data
=
1965 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1966 struct phm_ppt_v1_information
*table_info
=
1967 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1968 uint16_t hi_sidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
;
1969 uint16_t lo_sidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
;
1970 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
1972 hi_sidd
= (uint16_t)(cac_table
->usHighCACLeakage
/ 100 * 256);
1973 lo_sidd
= (uint16_t)(cac_table
->usLowCACLeakage
/ 100 * 256);
1975 smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
=
1976 CONVERT_FROM_HOST_TO_SMC_US(hi_sidd
);
1977 smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
=
1978 CONVERT_FROM_HOST_TO_SMC_US(lo_sidd
);
1983 static int tonga_populate_pm_fuses(struct pp_hwmgr
*hwmgr
)
1985 struct tonga_smumgr
*smu_data
=
1986 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1987 uint32_t pm_fuse_table_offset
;
1989 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
1990 PHM_PlatformCaps_PowerContainment
)) {
1991 if (smu7_read_smc_sram_dword(hwmgr
,
1992 SMU72_FIRMWARE_HEADER_LOCATION
+
1993 offsetof(SMU72_Firmware_Header
, PmFuseTable
),
1994 &pm_fuse_table_offset
, SMC_RAM_END
))
1995 PP_ASSERT_WITH_CODE(false,
1996 "Attempt to get pm_fuse_table_offset Failed !",
2000 if (tonga_populate_svi_load_line(hwmgr
))
2001 PP_ASSERT_WITH_CODE(false,
2002 "Attempt to populate SviLoadLine Failed !",
2005 if (tonga_populate_tdc_limit(hwmgr
))
2006 PP_ASSERT_WITH_CODE(false,
2007 "Attempt to populate TDCLimit Failed !",
2010 if (tonga_populate_dw8(hwmgr
, pm_fuse_table_offset
))
2011 PP_ASSERT_WITH_CODE(false,
2012 "Attempt to populate TdcWaterfallCtl Failed !",
2016 if (tonga_populate_temperature_scaler(hwmgr
) != 0)
2017 PP_ASSERT_WITH_CODE(false,
2018 "Attempt to populate LPMLTemperatureScaler Failed !",
2022 if (tonga_populate_fuzzy_fan(hwmgr
))
2023 PP_ASSERT_WITH_CODE(false,
2024 "Attempt to populate Fuzzy Fan "
2025 "Control parameters Failed !",
2029 if (tonga_populate_gnb_lpml(hwmgr
))
2030 PP_ASSERT_WITH_CODE(false,
2031 "Attempt to populate GnbLPML Failed !",
2035 if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr
))
2036 PP_ASSERT_WITH_CODE(
2038 "Attempt to populate BapmVddCBaseLeakage "
2039 "Hi and Lo Sidd Failed !",
2042 if (smu7_copy_bytes_to_smc(hwmgr
, pm_fuse_table_offset
,
2043 (uint8_t *)&smu_data
->power_tune_table
,
2044 sizeof(struct SMU72_Discrete_PmFuses
), SMC_RAM_END
))
2045 PP_ASSERT_WITH_CODE(false,
2046 "Attempt to download PmFuseTable Failed !",
2052 static int tonga_populate_mc_reg_address(struct pp_hwmgr
*hwmgr
,
2053 SMU72_Discrete_MCRegisters
*mc_reg_table
)
2055 const struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)hwmgr
->smu_backend
;
2059 for (i
= 0, j
= 0; j
< smu_data
->mc_reg_table
.last
; j
++) {
2060 if (smu_data
->mc_reg_table
.validflag
& 1<<j
) {
2061 PP_ASSERT_WITH_CODE(
2062 i
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
,
2063 "Index of mc_reg_table->address[] array "
2066 mc_reg_table
->address
[i
].s0
=
2067 PP_HOST_TO_SMC_US(smu_data
->mc_reg_table
.mc_reg_address
[j
].s0
);
2068 mc_reg_table
->address
[i
].s1
=
2069 PP_HOST_TO_SMC_US(smu_data
->mc_reg_table
.mc_reg_address
[j
].s1
);
2074 mc_reg_table
->last
= (uint8_t)i
;
2079 /*convert register values from driver to SMC format */
2080 static void tonga_convert_mc_registers(
2081 const struct tonga_mc_reg_entry
*entry
,
2082 SMU72_Discrete_MCRegisterSet
*data
,
2083 uint32_t num_entries
, uint32_t valid_flag
)
2087 for (i
= 0, j
= 0; j
< num_entries
; j
++) {
2088 if (valid_flag
& 1<<j
) {
2089 data
->value
[i
] = PP_HOST_TO_SMC_UL(entry
->mc_data
[j
]);
2095 static int tonga_convert_mc_reg_table_entry_to_smc(
2096 struct pp_hwmgr
*hwmgr
,
2097 const uint32_t memory_clock
,
2098 SMU72_Discrete_MCRegisterSet
*mc_reg_table_data
2101 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2104 for (i
= 0; i
< smu_data
->mc_reg_table
.num_entries
; i
++) {
2106 smu_data
->mc_reg_table
.mc_reg_table_entry
[i
].mclk_max
) {
2111 if ((i
== smu_data
->mc_reg_table
.num_entries
) && (i
> 0))
2114 tonga_convert_mc_registers(&smu_data
->mc_reg_table
.mc_reg_table_entry
[i
],
2115 mc_reg_table_data
, smu_data
->mc_reg_table
.last
,
2116 smu_data
->mc_reg_table
.validflag
);
2121 static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr
*hwmgr
,
2122 SMU72_Discrete_MCRegisters
*mc_regs
)
2125 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2129 for (i
= 0; i
< data
->dpm_table
.mclk_table
.count
; i
++) {
2130 res
= tonga_convert_mc_reg_table_entry_to_smc(
2132 data
->dpm_table
.mclk_table
.dpm_levels
[i
].value
,
2143 static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr
*hwmgr
)
2145 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2146 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2150 if (0 == (data
->need_update_smu7_dpm_table
& DPMTABLE_OD_UPDATE_MCLK
))
2154 memset(&smu_data
->mc_regs
, 0, sizeof(SMU72_Discrete_MCRegisters
));
2156 result
= tonga_convert_mc_reg_table_to_smc(hwmgr
, &(smu_data
->mc_regs
));
2162 address
= smu_data
->smu7_data
.mc_reg_table_start
+
2163 (uint32_t)offsetof(SMU72_Discrete_MCRegisters
, data
[0]);
2165 return smu7_copy_bytes_to_smc(
2167 (uint8_t *)&smu_data
->mc_regs
.data
[0],
2168 sizeof(SMU72_Discrete_MCRegisterSet
) *
2169 data
->dpm_table
.mclk_table
.count
,
2173 static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr
*hwmgr
)
2176 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2178 memset(&smu_data
->mc_regs
, 0x00, sizeof(SMU72_Discrete_MCRegisters
));
2179 result
= tonga_populate_mc_reg_address(hwmgr
, &(smu_data
->mc_regs
));
2180 PP_ASSERT_WITH_CODE(!result
,
2181 "Failed to initialize MCRegTable for the MC register addresses !",
2184 result
= tonga_convert_mc_reg_table_to_smc(hwmgr
, &smu_data
->mc_regs
);
2185 PP_ASSERT_WITH_CODE(!result
,
2186 "Failed to initialize MCRegTable for driver state !",
2189 return smu7_copy_bytes_to_smc(hwmgr
, smu_data
->smu7_data
.mc_reg_table_start
,
2190 (uint8_t *)&smu_data
->mc_regs
, sizeof(SMU72_Discrete_MCRegisters
), SMC_RAM_END
);
2193 static void tonga_initialize_power_tune_defaults(struct pp_hwmgr
*hwmgr
)
2195 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2196 struct phm_ppt_v1_information
*table_info
=
2197 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2200 table_info
->cac_dtp_table
->usPowerTuneDataSetID
<= POWERTUNE_DEFAULT_SET_MAX
&&
2201 table_info
->cac_dtp_table
->usPowerTuneDataSetID
)
2202 smu_data
->power_tune_defaults
=
2203 &tonga_power_tune_data_set_array
2204 [table_info
->cac_dtp_table
->usPowerTuneDataSetID
- 1];
2206 smu_data
->power_tune_defaults
= &tonga_power_tune_data_set_array
[0];
2209 static int tonga_init_smc_table(struct pp_hwmgr
*hwmgr
)
2212 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2213 struct tonga_smumgr
*smu_data
=
2214 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2215 SMU72_Discrete_DpmTable
*table
= &(smu_data
->smc_state_table
);
2216 struct phm_ppt_v1_information
*table_info
=
2217 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2220 pp_atomctrl_gpio_pin_assignment gpio_pin_assignment
;
2223 memset(&(smu_data
->smc_state_table
), 0x00, sizeof(smu_data
->smc_state_table
));
2225 tonga_initialize_power_tune_defaults(hwmgr
);
2227 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->voltage_control
)
2228 tonga_populate_smc_voltage_tables(hwmgr
, table
);
2230 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2231 PHM_PlatformCaps_AutomaticDCTransition
))
2232 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GPIO_DC
;
2235 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2236 PHM_PlatformCaps_StepVddc
))
2237 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_STEPVDDC
;
2239 if (data
->is_memory_gddr5
)
2240 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GDDR5
;
2242 i
= PHM_READ_FIELD(hwmgr
->device
, CC_MC_MAX_CHANNEL
, NOOFCHAN
);
2244 if (i
== 1 || i
== 0)
2245 table
->SystemFlags
|= 0x40;
2247 if (data
->ulv_supported
&& table_info
->us_ulv_voltage_offset
) {
2248 result
= tonga_populate_ulv_state(hwmgr
, table
);
2249 PP_ASSERT_WITH_CODE(!result
,
2250 "Failed to initialize ULV state !",
2253 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
2254 ixCG_ULV_PARAMETER
, 0x40035);
2257 result
= tonga_populate_smc_link_level(hwmgr
, table
);
2258 PP_ASSERT_WITH_CODE(!result
,
2259 "Failed to initialize Link Level !", return result
);
2261 result
= tonga_populate_all_graphic_levels(hwmgr
);
2262 PP_ASSERT_WITH_CODE(!result
,
2263 "Failed to initialize Graphics Level !", return result
);
2265 result
= tonga_populate_all_memory_levels(hwmgr
);
2266 PP_ASSERT_WITH_CODE(!result
,
2267 "Failed to initialize Memory Level !", return result
);
2269 result
= tonga_populate_smc_acpi_level(hwmgr
, table
);
2270 PP_ASSERT_WITH_CODE(!result
,
2271 "Failed to initialize ACPI Level !", return result
);
2273 result
= tonga_populate_smc_vce_level(hwmgr
, table
);
2274 PP_ASSERT_WITH_CODE(!result
,
2275 "Failed to initialize VCE Level !", return result
);
2277 result
= tonga_populate_smc_acp_level(hwmgr
, table
);
2278 PP_ASSERT_WITH_CODE(!result
,
2279 "Failed to initialize ACP Level !", return result
);
2281 /* Since only the initial state is completely set up at this
2282 * point (the other states are just copies of the boot state) we only
2283 * need to populate the ARB settings for the initial state.
2285 result
= tonga_program_memory_timing_parameters(hwmgr
);
2286 PP_ASSERT_WITH_CODE(!result
,
2287 "Failed to Write ARB settings for the initial state.",
2290 result
= tonga_populate_smc_uvd_level(hwmgr
, table
);
2291 PP_ASSERT_WITH_CODE(!result
,
2292 "Failed to initialize UVD Level !", return result
);
2294 result
= tonga_populate_smc_boot_level(hwmgr
, table
);
2295 PP_ASSERT_WITH_CODE(!result
,
2296 "Failed to initialize Boot Level !", return result
);
2298 tonga_populate_bapm_parameters_in_dpm_table(hwmgr
);
2299 PP_ASSERT_WITH_CODE(!result
,
2300 "Failed to populate BAPM Parameters !", return result
);
2302 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2303 PHM_PlatformCaps_ClockStretcher
)) {
2304 result
= tonga_populate_clock_stretcher_data_table(hwmgr
);
2305 PP_ASSERT_WITH_CODE(!result
,
2306 "Failed to populate Clock Stretcher Data Table !",
2309 table
->GraphicsVoltageChangeEnable
= 1;
2310 table
->GraphicsThermThrottleEnable
= 1;
2311 table
->GraphicsInterval
= 1;
2312 table
->VoltageInterval
= 1;
2313 table
->ThermalInterval
= 1;
2314 table
->TemperatureLimitHigh
=
2315 table_info
->cac_dtp_table
->usTargetOperatingTemp
*
2316 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2317 table
->TemperatureLimitLow
=
2318 (table_info
->cac_dtp_table
->usTargetOperatingTemp
- 1) *
2319 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2320 table
->MemoryVoltageChangeEnable
= 1;
2321 table
->MemoryInterval
= 1;
2322 table
->VoltageResponseTime
= 0;
2323 table
->PhaseResponseTime
= 0;
2324 table
->MemoryThermThrottleEnable
= 1;
2327 * Cail reads current link status and reports it as cap (we cannot
2328 * change this due to some previous issues we had)
2329 * SMC drops the link status to lowest level after enabling
2330 * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again
2331 * but this time Cail reads current link status which was set to low by
2332 * SMC and reports it as cap to powerplay
2333 * To avoid it, we set PCIeBootLinkLevel to highest dpm level
2335 PP_ASSERT_WITH_CODE((1 <= data
->dpm_table
.pcie_speed_table
.count
),
2336 "There must be 1 or more PCIE levels defined in PPTable.",
2339 table
->PCIeBootLinkLevel
= (uint8_t) (data
->dpm_table
.pcie_speed_table
.count
);
2341 table
->PCIeGenInterval
= 1;
2343 result
= tonga_populate_vr_config(hwmgr
, table
);
2344 PP_ASSERT_WITH_CODE(!result
,
2345 "Failed to populate VRConfig setting !", return result
);
2346 data
->vr_config
= table
->VRConfig
;
2347 table
->ThermGpio
= 17;
2348 table
->SclkStepSize
= 0x4000;
2350 if (atomctrl_get_pp_assign_pin(hwmgr
, VDDC_VRHOT_GPIO_PINID
,
2351 &gpio_pin_assignment
)) {
2352 table
->VRHotGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2353 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2354 PHM_PlatformCaps_RegulatorHot
);
2356 table
->VRHotGpio
= SMU7_UNUSED_GPIO_PIN
;
2357 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2358 PHM_PlatformCaps_RegulatorHot
);
2361 if (atomctrl_get_pp_assign_pin(hwmgr
, PP_AC_DC_SWITCH_GPIO_PINID
,
2362 &gpio_pin_assignment
)) {
2363 table
->AcDcGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2364 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2365 PHM_PlatformCaps_AutomaticDCTransition
);
2367 table
->AcDcGpio
= SMU7_UNUSED_GPIO_PIN
;
2368 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2369 PHM_PlatformCaps_AutomaticDCTransition
);
2372 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2373 PHM_PlatformCaps_Falcon_QuickTransition
);
2376 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2377 PHM_PlatformCaps_AutomaticDCTransition
);
2378 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2379 PHM_PlatformCaps_Falcon_QuickTransition
);
2382 if (atomctrl_get_pp_assign_pin(hwmgr
,
2383 THERMAL_INT_OUTPUT_GPIO_PINID
, &gpio_pin_assignment
)) {
2384 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2385 PHM_PlatformCaps_ThermalOutGPIO
);
2387 table
->ThermOutGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2389 table
->ThermOutPolarity
=
2390 (0 == (cgs_read_register(hwmgr
->device
, mmGPIOPAD_A
) &
2391 (1 << gpio_pin_assignment
.uc_gpio_pin_bit_shift
))) ? 1 : 0;
2393 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_ONLY
;
2395 /* if required, combine VRHot/PCC with thermal out GPIO*/
2396 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2397 PHM_PlatformCaps_RegulatorHot
) &&
2398 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2399 PHM_PlatformCaps_CombinePCCWithThermalSignal
)){
2400 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_VRHOT
;
2403 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2404 PHM_PlatformCaps_ThermalOutGPIO
);
2406 table
->ThermOutGpio
= 17;
2407 table
->ThermOutPolarity
= 1;
2408 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_DISABLE
;
2411 for (i
= 0; i
< SMU72_MAX_ENTRIES_SMIO
; i
++)
2412 table
->Smio
[i
] = PP_HOST_TO_SMC_UL(table
->Smio
[i
]);
2413 CONVERT_FROM_HOST_TO_SMC_UL(table
->SystemFlags
);
2414 CONVERT_FROM_HOST_TO_SMC_UL(table
->VRConfig
);
2415 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask1
);
2416 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask2
);
2417 CONVERT_FROM_HOST_TO_SMC_UL(table
->SclkStepSize
);
2418 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitHigh
);
2419 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitLow
);
2420 CONVERT_FROM_HOST_TO_SMC_US(table
->VoltageResponseTime
);
2421 CONVERT_FROM_HOST_TO_SMC_US(table
->PhaseResponseTime
);
2423 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2424 result
= smu7_copy_bytes_to_smc(
2426 smu_data
->smu7_data
.dpm_table_start
+ offsetof(SMU72_Discrete_DpmTable
, SystemFlags
),
2427 (uint8_t *)&(table
->SystemFlags
),
2428 sizeof(SMU72_Discrete_DpmTable
) - 3 * sizeof(SMU72_PIDController
),
2431 PP_ASSERT_WITH_CODE(!result
,
2432 "Failed to upload dpm data to SMC memory !", return result
;);
2434 result
= tonga_init_arb_table_index(hwmgr
);
2435 PP_ASSERT_WITH_CODE(!result
,
2436 "Failed to upload arb data to SMC memory !", return result
);
2438 tonga_populate_pm_fuses(hwmgr
);
2439 PP_ASSERT_WITH_CODE((!result
),
2440 "Failed to populate initialize pm fuses !", return result
);
2442 result
= tonga_populate_initial_mc_reg_table(hwmgr
);
2443 PP_ASSERT_WITH_CODE((!result
),
2444 "Failed to populate initialize MC Reg table !", return result
);
2449 static int tonga_thermal_setup_fan_table(struct pp_hwmgr
*hwmgr
)
2451 struct tonga_smumgr
*smu_data
=
2452 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2453 SMU72_Discrete_FanTable fan_table
= { FDO_MODE_HARDWARE
};
2455 uint32_t t_diff1
, t_diff2
, pwm_diff1
, pwm_diff2
;
2456 uint16_t fdo_min
, slope1
, slope2
;
2457 uint32_t reference_clock
;
2461 if (!phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2462 PHM_PlatformCaps_MicrocodeFanControl
))
2465 if (hwmgr
->thermal_controller
.fanInfo
.bNoFan
) {
2466 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2467 PHM_PlatformCaps_MicrocodeFanControl
);
2471 if (0 == smu_data
->smu7_data
.fan_table_start
) {
2472 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2473 PHM_PlatformCaps_MicrocodeFanControl
);
2477 duty100
= PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
,
2479 CG_FDO_CTRL1
, FMAX_DUTY100
);
2482 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2483 PHM_PlatformCaps_MicrocodeFanControl
);
2487 tmp64
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
* duty100
;
2488 do_div(tmp64
, 10000);
2489 fdo_min
= (uint16_t)tmp64
;
2491 t_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
-
2492 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
;
2493 t_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
-
2494 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
;
2496 pwm_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
-
2497 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
;
2498 pwm_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
-
2499 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
;
2501 slope1
= (uint16_t)((50 + ((16 * duty100
* pwm_diff1
) / t_diff1
)) / 100);
2502 slope2
= (uint16_t)((50 + ((16 * duty100
* pwm_diff2
) / t_diff2
)) / 100);
2504 fan_table
.TempMin
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
) / 100);
2505 fan_table
.TempMed
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
) / 100);
2506 fan_table
.TempMax
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
) / 100);
2508 fan_table
.Slope1
= cpu_to_be16(slope1
);
2509 fan_table
.Slope2
= cpu_to_be16(slope2
);
2511 fan_table
.FdoMin
= cpu_to_be16(fdo_min
);
2513 fan_table
.HystDown
= cpu_to_be16(hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
);
2515 fan_table
.HystUp
= cpu_to_be16(1);
2517 fan_table
.HystSlope
= cpu_to_be16(1);
2519 fan_table
.TempRespLim
= cpu_to_be16(5);
2521 reference_clock
= amdgpu_asic_get_xclk((struct amdgpu_device
*)hwmgr
->adev
);
2523 fan_table
.RefreshPeriod
= cpu_to_be32((hwmgr
->thermal_controller
.advanceFanControlParameters
.ulCycleDelay
* reference_clock
) / 1600);
2525 fan_table
.FdoMax
= cpu_to_be16((uint16_t)duty100
);
2527 fan_table
.TempSrc
= (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, CG_MULT_THERMAL_CTRL
, TEMP_SEL
);
2529 fan_table
.FanControl_GL_Flag
= 1;
2531 res
= smu7_copy_bytes_to_smc(hwmgr
,
2532 smu_data
->smu7_data
.fan_table_start
,
2533 (uint8_t *)&fan_table
,
2534 (uint32_t)sizeof(fan_table
),
2541 static int tonga_program_mem_timing_parameters(struct pp_hwmgr
*hwmgr
)
2543 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2545 if (data
->need_update_smu7_dpm_table
&
2546 (DPMTABLE_OD_UPDATE_SCLK
+ DPMTABLE_OD_UPDATE_MCLK
))
2547 return tonga_program_memory_timing_parameters(hwmgr
);
2552 static int tonga_update_sclk_threshold(struct pp_hwmgr
*hwmgr
)
2554 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2555 struct tonga_smumgr
*smu_data
=
2556 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2559 uint32_t low_sclk_interrupt_threshold
= 0;
2561 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2562 PHM_PlatformCaps_SclkThrottleLowNotification
)
2563 && (data
->low_sclk_interrupt_threshold
!= 0)) {
2564 low_sclk_interrupt_threshold
=
2565 data
->low_sclk_interrupt_threshold
;
2567 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold
);
2569 result
= smu7_copy_bytes_to_smc(
2571 smu_data
->smu7_data
.dpm_table_start
+
2572 offsetof(SMU72_Discrete_DpmTable
,
2573 LowSclkInterruptThreshold
),
2574 (uint8_t *)&low_sclk_interrupt_threshold
,
2579 result
= tonga_update_and_upload_mc_reg_table(hwmgr
);
2581 PP_ASSERT_WITH_CODE((!result
),
2582 "Failed to upload MC reg table !",
2585 result
= tonga_program_mem_timing_parameters(hwmgr
);
2586 PP_ASSERT_WITH_CODE((result
== 0),
2587 "Failed to program memory timing parameters !",
2593 static uint32_t tonga_get_offsetof(uint32_t type
, uint32_t member
)
2596 case SMU_SoftRegisters
:
2598 case HandshakeDisables
:
2599 return offsetof(SMU72_SoftRegisters
, HandshakeDisables
);
2600 case VoltageChangeTimeout
:
2601 return offsetof(SMU72_SoftRegisters
, VoltageChangeTimeout
);
2602 case AverageGraphicsActivity
:
2603 return offsetof(SMU72_SoftRegisters
, AverageGraphicsActivity
);
2605 return offsetof(SMU72_SoftRegisters
, PreVBlankGap
);
2607 return offsetof(SMU72_SoftRegisters
, VBlankTimeout
);
2608 case UcodeLoadStatus
:
2609 return offsetof(SMU72_SoftRegisters
, UcodeLoadStatus
);
2610 case DRAM_LOG_ADDR_H
:
2611 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_ADDR_H
);
2612 case DRAM_LOG_ADDR_L
:
2613 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_ADDR_L
);
2614 case DRAM_LOG_PHY_ADDR_H
:
2615 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_PHY_ADDR_H
);
2616 case DRAM_LOG_PHY_ADDR_L
:
2617 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_PHY_ADDR_L
);
2618 case DRAM_LOG_BUFF_SIZE
:
2619 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_BUFF_SIZE
);
2622 case SMU_Discrete_DpmTable
:
2625 return offsetof(SMU72_Discrete_DpmTable
, UvdBootLevel
);
2627 return offsetof(SMU72_Discrete_DpmTable
, VceBootLevel
);
2628 case LowSclkInterruptThreshold
:
2629 return offsetof(SMU72_Discrete_DpmTable
, LowSclkInterruptThreshold
);
2633 pr_warn("can't get the offset of type %x member %x\n", type
, member
);
2637 static uint32_t tonga_get_mac_definition(uint32_t value
)
2640 case SMU_MAX_LEVELS_GRAPHICS
:
2641 return SMU72_MAX_LEVELS_GRAPHICS
;
2642 case SMU_MAX_LEVELS_MEMORY
:
2643 return SMU72_MAX_LEVELS_MEMORY
;
2644 case SMU_MAX_LEVELS_LINK
:
2645 return SMU72_MAX_LEVELS_LINK
;
2646 case SMU_MAX_ENTRIES_SMIO
:
2647 return SMU72_MAX_ENTRIES_SMIO
;
2648 case SMU_MAX_LEVELS_VDDC
:
2649 return SMU72_MAX_LEVELS_VDDC
;
2650 case SMU_MAX_LEVELS_VDDGFX
:
2651 return SMU72_MAX_LEVELS_VDDGFX
;
2652 case SMU_MAX_LEVELS_VDDCI
:
2653 return SMU72_MAX_LEVELS_VDDCI
;
2654 case SMU_MAX_LEVELS_MVDD
:
2655 return SMU72_MAX_LEVELS_MVDD
;
2657 pr_warn("can't get the mac value %x\n", value
);
2662 static int tonga_update_uvd_smc_table(struct pp_hwmgr
*hwmgr
)
2664 struct tonga_smumgr
*smu_data
=
2665 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2666 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2667 struct phm_ppt_v1_information
*table_info
=
2668 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2670 smu_data
->smc_state_table
.UvdBootLevel
= 0;
2671 if (table_info
->mm_dep_table
->count
> 0)
2672 smu_data
->smc_state_table
.UvdBootLevel
=
2673 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2674 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2675 offsetof(SMU72_Discrete_DpmTable
, UvdBootLevel
);
2676 mm_boot_level_offset
/= 4;
2677 mm_boot_level_offset
*= 4;
2678 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2679 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2680 mm_boot_level_value
&= 0x00FFFFFF;
2681 mm_boot_level_value
|= smu_data
->smc_state_table
.UvdBootLevel
<< 24;
2682 cgs_write_ind_register(hwmgr
->device
,
2684 mm_boot_level_offset
, mm_boot_level_value
);
2686 if (!phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2687 PHM_PlatformCaps_UVDDPM
) ||
2688 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2689 PHM_PlatformCaps_StablePState
))
2690 smum_send_msg_to_smc_with_parameter(hwmgr
,
2691 PPSMC_MSG_UVDDPM_SetEnabledMask
,
2692 (uint32_t)(1 << smu_data
->smc_state_table
.UvdBootLevel
));
2696 static int tonga_update_vce_smc_table(struct pp_hwmgr
*hwmgr
)
2698 struct tonga_smumgr
*smu_data
=
2699 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2700 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2701 struct phm_ppt_v1_information
*table_info
=
2702 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2705 smu_data
->smc_state_table
.VceBootLevel
=
2706 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2708 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2709 offsetof(SMU72_Discrete_DpmTable
, VceBootLevel
);
2710 mm_boot_level_offset
/= 4;
2711 mm_boot_level_offset
*= 4;
2712 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2713 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2714 mm_boot_level_value
&= 0xFF00FFFF;
2715 mm_boot_level_value
|= smu_data
->smc_state_table
.VceBootLevel
<< 16;
2716 cgs_write_ind_register(hwmgr
->device
,
2717 CGS_IND_REG__SMC
, mm_boot_level_offset
, mm_boot_level_value
);
2719 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2720 PHM_PlatformCaps_StablePState
))
2721 smum_send_msg_to_smc_with_parameter(hwmgr
,
2722 PPSMC_MSG_VCEDPM_SetEnabledMask
,
2723 (uint32_t)1 << smu_data
->smc_state_table
.VceBootLevel
);
2727 static int tonga_update_smc_table(struct pp_hwmgr
*hwmgr
, uint32_t type
)
2731 tonga_update_uvd_smc_table(hwmgr
);
2734 tonga_update_vce_smc_table(hwmgr
);
2742 static int tonga_process_firmware_header(struct pp_hwmgr
*hwmgr
)
2744 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2745 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2751 result
= smu7_read_smc_sram_dword(hwmgr
,
2752 SMU72_FIRMWARE_HEADER_LOCATION
+
2753 offsetof(SMU72_Firmware_Header
, DpmTable
),
2757 smu_data
->smu7_data
.dpm_table_start
= tmp
;
2759 error
|= (result
!= 0);
2761 result
= smu7_read_smc_sram_dword(hwmgr
,
2762 SMU72_FIRMWARE_HEADER_LOCATION
+
2763 offsetof(SMU72_Firmware_Header
, SoftRegisters
),
2767 data
->soft_regs_start
= tmp
;
2768 smu_data
->smu7_data
.soft_regs_start
= tmp
;
2771 error
|= (result
!= 0);
2774 result
= smu7_read_smc_sram_dword(hwmgr
,
2775 SMU72_FIRMWARE_HEADER_LOCATION
+
2776 offsetof(SMU72_Firmware_Header
, mcRegisterTable
),
2780 smu_data
->smu7_data
.mc_reg_table_start
= tmp
;
2782 result
= smu7_read_smc_sram_dword(hwmgr
,
2783 SMU72_FIRMWARE_HEADER_LOCATION
+
2784 offsetof(SMU72_Firmware_Header
, FanTable
),
2788 smu_data
->smu7_data
.fan_table_start
= tmp
;
2790 error
|= (result
!= 0);
2792 result
= smu7_read_smc_sram_dword(hwmgr
,
2793 SMU72_FIRMWARE_HEADER_LOCATION
+
2794 offsetof(SMU72_Firmware_Header
, mcArbDramTimingTable
),
2798 smu_data
->smu7_data
.arb_table_start
= tmp
;
2800 error
|= (result
!= 0);
2802 result
= smu7_read_smc_sram_dword(hwmgr
,
2803 SMU72_FIRMWARE_HEADER_LOCATION
+
2804 offsetof(SMU72_Firmware_Header
, Version
),
2808 hwmgr
->microcode_version_info
.SMC
= tmp
;
2810 error
|= (result
!= 0);
2812 return error
? 1 : 0;
2815 /*---------------------------MC----------------------------*/
2817 static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr
*hwmgr
)
2819 return (uint8_t) (0xFF & (cgs_read_register(hwmgr
->device
, mmBIOS_SCRATCH_4
) >> 16));
2822 static bool tonga_check_s0_mc_reg_index(uint16_t in_reg
, uint16_t *out_reg
)
2827 case mmMC_SEQ_RAS_TIMING
:
2828 *out_reg
= mmMC_SEQ_RAS_TIMING_LP
;
2831 case mmMC_SEQ_DLL_STBY
:
2832 *out_reg
= mmMC_SEQ_DLL_STBY_LP
;
2835 case mmMC_SEQ_G5PDX_CMD0
:
2836 *out_reg
= mmMC_SEQ_G5PDX_CMD0_LP
;
2839 case mmMC_SEQ_G5PDX_CMD1
:
2840 *out_reg
= mmMC_SEQ_G5PDX_CMD1_LP
;
2843 case mmMC_SEQ_G5PDX_CTRL
:
2844 *out_reg
= mmMC_SEQ_G5PDX_CTRL_LP
;
2847 case mmMC_SEQ_CAS_TIMING
:
2848 *out_reg
= mmMC_SEQ_CAS_TIMING_LP
;
2851 case mmMC_SEQ_MISC_TIMING
:
2852 *out_reg
= mmMC_SEQ_MISC_TIMING_LP
;
2855 case mmMC_SEQ_MISC_TIMING2
:
2856 *out_reg
= mmMC_SEQ_MISC_TIMING2_LP
;
2859 case mmMC_SEQ_PMG_DVS_CMD
:
2860 *out_reg
= mmMC_SEQ_PMG_DVS_CMD_LP
;
2863 case mmMC_SEQ_PMG_DVS_CTL
:
2864 *out_reg
= mmMC_SEQ_PMG_DVS_CTL_LP
;
2867 case mmMC_SEQ_RD_CTL_D0
:
2868 *out_reg
= mmMC_SEQ_RD_CTL_D0_LP
;
2871 case mmMC_SEQ_RD_CTL_D1
:
2872 *out_reg
= mmMC_SEQ_RD_CTL_D1_LP
;
2875 case mmMC_SEQ_WR_CTL_D0
:
2876 *out_reg
= mmMC_SEQ_WR_CTL_D0_LP
;
2879 case mmMC_SEQ_WR_CTL_D1
:
2880 *out_reg
= mmMC_SEQ_WR_CTL_D1_LP
;
2883 case mmMC_PMG_CMD_EMRS
:
2884 *out_reg
= mmMC_SEQ_PMG_CMD_EMRS_LP
;
2887 case mmMC_PMG_CMD_MRS
:
2888 *out_reg
= mmMC_SEQ_PMG_CMD_MRS_LP
;
2891 case mmMC_PMG_CMD_MRS1
:
2892 *out_reg
= mmMC_SEQ_PMG_CMD_MRS1_LP
;
2895 case mmMC_SEQ_PMG_TIMING
:
2896 *out_reg
= mmMC_SEQ_PMG_TIMING_LP
;
2899 case mmMC_PMG_CMD_MRS2
:
2900 *out_reg
= mmMC_SEQ_PMG_CMD_MRS2_LP
;
2903 case mmMC_SEQ_WR_CTL_2
:
2904 *out_reg
= mmMC_SEQ_WR_CTL_2_LP
;
2915 static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table
*table
)
2920 for (i
= 0; i
< table
->last
; i
++) {
2921 table
->mc_reg_address
[i
].s0
=
2922 tonga_check_s0_mc_reg_index(table
->mc_reg_address
[i
].s1
,
2925 table
->mc_reg_address
[i
].s1
;
2930 static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table
*table
,
2931 struct tonga_mc_reg_table
*ni_table
)
2935 PP_ASSERT_WITH_CODE((table
->last
<= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
2936 "Invalid VramInfo table.", return -EINVAL
);
2937 PP_ASSERT_WITH_CODE((table
->num_entries
<= MAX_AC_TIMING_ENTRIES
),
2938 "Invalid VramInfo table.", return -EINVAL
);
2940 for (i
= 0; i
< table
->last
; i
++)
2941 ni_table
->mc_reg_address
[i
].s1
= table
->mc_reg_address
[i
].s1
;
2943 ni_table
->last
= table
->last
;
2945 for (i
= 0; i
< table
->num_entries
; i
++) {
2946 ni_table
->mc_reg_table_entry
[i
].mclk_max
=
2947 table
->mc_reg_table_entry
[i
].mclk_max
;
2948 for (j
= 0; j
< table
->last
; j
++) {
2949 ni_table
->mc_reg_table_entry
[i
].mc_data
[j
] =
2950 table
->mc_reg_table_entry
[i
].mc_data
[j
];
2954 ni_table
->num_entries
= table
->num_entries
;
2959 static int tonga_set_mc_special_registers(struct pp_hwmgr
*hwmgr
,
2960 struct tonga_mc_reg_table
*table
)
2964 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2966 for (i
= 0, j
= table
->last
; i
< table
->last
; i
++) {
2967 PP_ASSERT_WITH_CODE((j
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
2968 "Invalid VramInfo table.", return -EINVAL
);
2970 switch (table
->mc_reg_address
[i
].s1
) {
2972 case mmMC_SEQ_MISC1
:
2973 temp_reg
= cgs_read_register(hwmgr
->device
,
2975 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_EMRS
;
2976 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_EMRS_LP
;
2977 for (k
= 0; k
< table
->num_entries
; k
++) {
2978 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
2979 ((temp_reg
& 0xffff0000)) |
2980 ((table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0xffff0000) >> 16);
2984 PP_ASSERT_WITH_CODE((j
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
2985 "Invalid VramInfo table.", return -EINVAL
);
2986 temp_reg
= cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS
);
2987 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_MRS
;
2988 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_MRS_LP
;
2989 for (k
= 0; k
< table
->num_entries
; k
++) {
2990 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
2991 (temp_reg
& 0xffff0000) |
2992 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0x0000ffff);
2994 if (!data
->is_memory_gddr5
)
2995 table
->mc_reg_table_entry
[k
].mc_data
[j
] |= 0x100;
2999 if (!data
->is_memory_gddr5
) {
3000 PP_ASSERT_WITH_CODE((j
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
3001 "Invalid VramInfo table.", return -EINVAL
);
3002 table
->mc_reg_address
[j
].s1
= mmMC_PMG_AUTO_CMD
;
3003 table
->mc_reg_address
[j
].s0
= mmMC_PMG_AUTO_CMD
;
3004 for (k
= 0; k
< table
->num_entries
; k
++)
3005 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3006 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0xffff0000) >> 16;
3012 case mmMC_SEQ_RESERVE_M
:
3013 temp_reg
= cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS1
);
3014 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_MRS1
;
3015 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_MRS1_LP
;
3016 for (k
= 0; k
< table
->num_entries
; k
++) {
3017 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3018 (temp_reg
& 0xffff0000) |
3019 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0x0000ffff);
3035 static int tonga_set_valid_flag(struct tonga_mc_reg_table
*table
)
3039 for (i
= 0; i
< table
->last
; i
++) {
3040 for (j
= 1; j
< table
->num_entries
; j
++) {
3041 if (table
->mc_reg_table_entry
[j
-1].mc_data
[i
] !=
3042 table
->mc_reg_table_entry
[j
].mc_data
[i
]) {
3043 table
->validflag
|= (1<<i
);
3052 static int tonga_initialize_mc_reg_table(struct pp_hwmgr
*hwmgr
)
3055 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
3056 pp_atomctrl_mc_reg_table
*table
;
3057 struct tonga_mc_reg_table
*ni_table
= &smu_data
->mc_reg_table
;
3058 uint8_t module_index
= tonga_get_memory_modile_index(hwmgr
);
3060 table
= kzalloc(sizeof(pp_atomctrl_mc_reg_table
), GFP_KERNEL
);
3065 /* Program additional LP registers that are no longer programmed by VBIOS */
3066 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING_LP
,
3067 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING
));
3068 cgs_write_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING_LP
,
3069 cgs_read_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING
));
3070 cgs_write_register(hwmgr
->device
, mmMC_SEQ_DLL_STBY_LP
,
3071 cgs_read_register(hwmgr
->device
, mmMC_SEQ_DLL_STBY
));
3072 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD0_LP
,
3073 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD0
));
3074 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD1_LP
,
3075 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD1
));
3076 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CTRL_LP
,
3077 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CTRL
));
3078 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CMD_LP
,
3079 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CMD
));
3080 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CTL_LP
,
3081 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CTL
));
3082 cgs_write_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING_LP
,
3083 cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING
));
3084 cgs_write_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2_LP
,
3085 cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2
));
3086 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_EMRS_LP
,
3087 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_EMRS
));
3088 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS_LP
,
3089 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS
));
3090 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS1_LP
,
3091 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS1
));
3092 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D0_LP
,
3093 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D0
));
3094 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1_LP
,
3095 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1
));
3096 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0_LP
,
3097 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0
));
3098 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1_LP
,
3099 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1
));
3100 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING_LP
,
3101 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING
));
3102 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS2_LP
,
3103 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS2
));
3104 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_2_LP
,
3105 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_2
));
3107 memset(table
, 0x00, sizeof(pp_atomctrl_mc_reg_table
));
3109 result
= atomctrl_initialize_mc_reg_table(hwmgr
, module_index
, table
);
3112 result
= tonga_copy_vbios_smc_reg_table(table
, ni_table
);
3115 tonga_set_s0_mc_reg_index(ni_table
);
3116 result
= tonga_set_mc_special_registers(hwmgr
, ni_table
);
3120 tonga_set_valid_flag(ni_table
);
3127 static bool tonga_is_dpm_running(struct pp_hwmgr
*hwmgr
)
3129 return (1 == PHM_READ_INDIRECT_FIELD(hwmgr
->device
,
3130 CGS_IND_REG__SMC
, FEATURE_STATUS
, VOLTAGE_CONTROLLER_ON
))
3134 static int tonga_update_dpm_settings(struct pp_hwmgr
*hwmgr
,
3135 void *profile_setting
)
3137 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
3138 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)
3139 (hwmgr
->smu_backend
);
3140 struct profile_mode_setting
*setting
;
3141 struct SMU72_Discrete_GraphicsLevel
*levels
=
3142 smu_data
->smc_state_table
.GraphicsLevel
;
3143 uint32_t array
= smu_data
->smu7_data
.dpm_table_start
+
3144 offsetof(SMU72_Discrete_DpmTable
, GraphicsLevel
);
3146 uint32_t mclk_array
= smu_data
->smu7_data
.dpm_table_start
+
3147 offsetof(SMU72_Discrete_DpmTable
, MemoryLevel
);
3148 struct SMU72_Discrete_MemoryLevel
*mclk_levels
=
3149 smu_data
->smc_state_table
.MemoryLevel
;
3151 uint32_t offset
, up_hyst_offset
, down_hyst_offset
, clk_activity_offset
, tmp
;
3153 if (profile_setting
== NULL
)
3156 setting
= (struct profile_mode_setting
*)profile_setting
;
3158 if (setting
->bupdate_sclk
) {
3159 if (!data
->sclk_dpm_key_disabled
)
3160 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_SCLKDPM_FreezeLevel
);
3161 for (i
= 0; i
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; i
++) {
3162 if (levels
[i
].ActivityLevel
!=
3163 cpu_to_be16(setting
->sclk_activity
)) {
3164 levels
[i
].ActivityLevel
= cpu_to_be16(setting
->sclk_activity
);
3166 clk_activity_offset
= array
+ (sizeof(SMU72_Discrete_GraphicsLevel
) * i
)
3167 + offsetof(SMU72_Discrete_GraphicsLevel
, ActivityLevel
);
3168 offset
= clk_activity_offset
& ~0x3;
3169 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
3170 tmp
= phm_set_field_to_u32(clk_activity_offset
, tmp
, levels
[i
].ActivityLevel
, sizeof(uint16_t));
3171 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
3174 if (levels
[i
].UpHyst
!= setting
->sclk_up_hyst
||
3175 levels
[i
].DownHyst
!= setting
->sclk_down_hyst
) {
3176 levels
[i
].UpHyst
= setting
->sclk_up_hyst
;
3177 levels
[i
].DownHyst
= setting
->sclk_down_hyst
;
3178 up_hyst_offset
= array
+ (sizeof(SMU72_Discrete_GraphicsLevel
) * i
)
3179 + offsetof(SMU72_Discrete_GraphicsLevel
, UpHyst
);
3180 down_hyst_offset
= array
+ (sizeof(SMU72_Discrete_GraphicsLevel
) * i
)
3181 + offsetof(SMU72_Discrete_GraphicsLevel
, DownHyst
);
3182 offset
= up_hyst_offset
& ~0x3;
3183 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
3184 tmp
= phm_set_field_to_u32(up_hyst_offset
, tmp
, levels
[i
].UpHyst
, sizeof(uint8_t));
3185 tmp
= phm_set_field_to_u32(down_hyst_offset
, tmp
, levels
[i
].DownHyst
, sizeof(uint8_t));
3186 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
3189 if (!data
->sclk_dpm_key_disabled
)
3190 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_SCLKDPM_UnfreezeLevel
);
3193 if (setting
->bupdate_mclk
) {
3194 if (!data
->mclk_dpm_key_disabled
)
3195 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_MCLKDPM_FreezeLevel
);
3196 for (i
= 0; i
< smu_data
->smc_state_table
.MemoryDpmLevelCount
; i
++) {
3197 if (mclk_levels
[i
].ActivityLevel
!=
3198 cpu_to_be16(setting
->mclk_activity
)) {
3199 mclk_levels
[i
].ActivityLevel
= cpu_to_be16(setting
->mclk_activity
);
3201 clk_activity_offset
= mclk_array
+ (sizeof(SMU72_Discrete_MemoryLevel
) * i
)
3202 + offsetof(SMU72_Discrete_MemoryLevel
, ActivityLevel
);
3203 offset
= clk_activity_offset
& ~0x3;
3204 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
3205 tmp
= phm_set_field_to_u32(clk_activity_offset
, tmp
, mclk_levels
[i
].ActivityLevel
, sizeof(uint16_t));
3206 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
3209 if (mclk_levels
[i
].UpHyst
!= setting
->mclk_up_hyst
||
3210 mclk_levels
[i
].DownHyst
!= setting
->mclk_down_hyst
) {
3211 mclk_levels
[i
].UpHyst
= setting
->mclk_up_hyst
;
3212 mclk_levels
[i
].DownHyst
= setting
->mclk_down_hyst
;
3213 up_hyst_offset
= mclk_array
+ (sizeof(SMU72_Discrete_MemoryLevel
) * i
)
3214 + offsetof(SMU72_Discrete_MemoryLevel
, UpHyst
);
3215 down_hyst_offset
= mclk_array
+ (sizeof(SMU72_Discrete_MemoryLevel
) * i
)
3216 + offsetof(SMU72_Discrete_MemoryLevel
, DownHyst
);
3217 offset
= up_hyst_offset
& ~0x3;
3218 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
3219 tmp
= phm_set_field_to_u32(up_hyst_offset
, tmp
, mclk_levels
[i
].UpHyst
, sizeof(uint8_t));
3220 tmp
= phm_set_field_to_u32(down_hyst_offset
, tmp
, mclk_levels
[i
].DownHyst
, sizeof(uint8_t));
3221 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
3224 if (!data
->mclk_dpm_key_disabled
)
3225 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_MCLKDPM_UnfreezeLevel
);
3230 const struct pp_smumgr_func tonga_smu_funcs
= {
3231 .smu_init
= &tonga_smu_init
,
3232 .smu_fini
= &smu7_smu_fini
,
3233 .start_smu
= &tonga_start_smu
,
3234 .check_fw_load_finish
= &smu7_check_fw_load_finish
,
3235 .request_smu_load_fw
= &smu7_request_smu_load_fw
,
3236 .request_smu_load_specific_fw
= NULL
,
3237 .send_msg_to_smc
= &smu7_send_msg_to_smc
,
3238 .send_msg_to_smc_with_parameter
= &smu7_send_msg_to_smc_with_parameter
,
3239 .download_pptable_settings
= NULL
,
3240 .upload_pptable_settings
= NULL
,
3241 .update_smc_table
= tonga_update_smc_table
,
3242 .get_offsetof
= tonga_get_offsetof
,
3243 .process_firmware_header
= tonga_process_firmware_header
,
3244 .init_smc_table
= tonga_init_smc_table
,
3245 .update_sclk_threshold
= tonga_update_sclk_threshold
,
3246 .thermal_setup_fan_table
= tonga_thermal_setup_fan_table
,
3247 .populate_all_graphic_levels
= tonga_populate_all_graphic_levels
,
3248 .populate_all_memory_levels
= tonga_populate_all_memory_levels
,
3249 .get_mac_definition
= tonga_get_mac_definition
,
3250 .initialize_mc_reg_table
= tonga_initialize_mc_reg_table
,
3251 .is_dpm_running
= tonga_is_dpm_running
,
3252 .update_dpm_settings
= tonga_update_dpm_settings
,