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/pci.h>
27 #include <linux/slab.h>
28 #include <linux/gfp.h>
31 #include "tonga_smumgr.h"
32 #include "smu_ucode_xfer_vi.h"
33 #include "tonga_ppsmc.h"
34 #include "smu/smu_7_1_2_d.h"
35 #include "smu/smu_7_1_2_sh_mask.h"
36 #include "cgs_common.h"
37 #include "smu7_smumgr.h"
39 #include "smu7_dyn_defaults.h"
41 #include "smu7_hwmgr.h"
42 #include "hardwaremanager.h"
43 #include "ppatomctrl.h"
47 #include "pppcielanes.h"
48 #include "pp_endian.h"
50 #include "gmc/gmc_8_1_d.h"
51 #include "gmc/gmc_8_1_sh_mask.h"
53 #include "bif/bif_5_0_d.h"
54 #include "bif/bif_5_0_sh_mask.h"
56 #include "dce/dce_10_0_d.h"
57 #include "dce/dce_10_0_sh_mask.h"
59 #define POWERTUNE_DEFAULT_SET_MAX 1
60 #define MC_CG_ARB_FREQ_F1 0x0b
61 #define VDDC_VDDCI_DELTA 200
64 static const struct tonga_pt_defaults tonga_power_tune_data_set_array
[POWERTUNE_DEFAULT_SET_MAX
] = {
65 /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
66 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
70 {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8,
71 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
72 {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203,
73 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4}
77 /* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */
78 static const uint16_t tonga_clock_stretcher_lookup_table
[2][4] = {
83 /* [FF, SS] type, [] 4 voltage ranges,
84 * and [Floor Freq, Boundary Freq, VID min , VID max]
86 static const uint32_t tonga_clock_stretcher_ddt_table
[2][4][4] = {
87 { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
88 { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} }
91 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */
92 static const uint8_t tonga_clock_stretch_amount_conversion
[2][6] = {
97 static int tonga_start_in_protection_mode(struct pp_hwmgr
*hwmgr
)
102 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
103 SMC_SYSCON_RESET_CNTL
, rst_reg
, 1);
105 result
= smu7_upload_smu_firmware_image(hwmgr
);
110 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
114 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
115 SMC_SYSCON_CLOCK_CNTL_0
, ck_disable
, 0);
117 /* De-assert reset */
118 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
119 SMC_SYSCON_RESET_CNTL
, rst_reg
, 0);
121 /* Set SMU Auto Start */
122 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
123 SMU_INPUT_DATA
, AUTO_START
, 1);
125 /* Clear firmware interrupt enable flag */
126 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
127 ixFIRMWARE_FLAGS
, 0);
129 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
,
130 RCU_UC_EVENTS
, INTERRUPTS_ENABLED
, 1);
133 * Call Test SMU message with 0x20000 offset to trigger SMU start
135 smu7_send_msg_to_smc_offset(hwmgr
);
137 /* Wait for done bit to be set */
138 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr
, SMC_IND
,
139 SMU_STATUS
, SMU_DONE
, 0);
141 /* Check pass/failed indicator */
142 if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
,
143 CGS_IND_REG__SMC
, SMU_STATUS
, SMU_PASS
)) {
144 pr_err("SMU Firmware start failed\n");
148 /* Wait for firmware to initialize */
149 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
,
150 FIRMWARE_FLAGS
, INTERRUPTS_ENABLED
, 1);
155 static int tonga_start_in_non_protection_mode(struct pp_hwmgr
*hwmgr
)
159 /* wait for smc boot up */
160 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr
, SMC_IND
,
161 RCU_UC_EVENTS
, boot_seq_done
, 0);
163 /*Clear firmware interrupt enable flag*/
164 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
165 ixFIRMWARE_FLAGS
, 0);
168 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
169 SMC_SYSCON_RESET_CNTL
, rst_reg
, 1);
171 result
= smu7_upload_smu_firmware_image(hwmgr
);
176 /* Set smc instruct start point at 0x0 */
177 smu7_program_jump_on_start(hwmgr
);
180 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
181 SMC_SYSCON_CLOCK_CNTL_0
, ck_disable
, 0);
184 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
185 SMC_SYSCON_RESET_CNTL
, rst_reg
, 0);
187 /* Wait for firmware to initialize */
188 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
,
189 FIRMWARE_FLAGS
, INTERRUPTS_ENABLED
, 1);
194 static int tonga_start_smu(struct pp_hwmgr
*hwmgr
)
196 struct tonga_smumgr
*priv
= hwmgr
->smu_backend
;
199 /* Only start SMC if SMC RAM is not running */
200 if (!smu7_is_smc_ram_running(hwmgr
) && hwmgr
->not_vf
) {
201 /*Check if SMU is running in protected mode*/
202 if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
203 SMU_FIRMWARE
, SMU_MODE
)) {
204 result
= tonga_start_in_non_protection_mode(hwmgr
);
208 result
= tonga_start_in_protection_mode(hwmgr
);
214 /* Setup SoftRegsStart here to visit the register UcodeLoadStatus
215 * to check fw loading state
217 smu7_read_smc_sram_dword(hwmgr
,
218 SMU72_FIRMWARE_HEADER_LOCATION
+
219 offsetof(SMU72_Firmware_Header
, SoftRegisters
),
220 &(priv
->smu7_data
.soft_regs_start
), 0x40000);
222 result
= smu7_request_smu_load_fw(hwmgr
);
227 static int tonga_smu_init(struct pp_hwmgr
*hwmgr
)
229 struct tonga_smumgr
*tonga_priv
= NULL
;
231 tonga_priv
= kzalloc(sizeof(struct tonga_smumgr
), GFP_KERNEL
);
232 if (tonga_priv
== NULL
)
235 hwmgr
->smu_backend
= tonga_priv
;
237 if (smu7_init(hwmgr
)) {
246 static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr
*hwmgr
,
247 phm_ppt_v1_clock_voltage_dependency_table
*allowed_clock_voltage_table
,
248 uint32_t clock
, SMU_VoltageLevel
*voltage
, uint32_t *mvdd
)
251 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
252 struct phm_ppt_v1_information
*pptable_info
=
253 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
255 /* clock - voltage dependency table is empty table */
256 if (allowed_clock_voltage_table
->count
== 0)
259 for (i
= 0; i
< allowed_clock_voltage_table
->count
; i
++) {
260 /* find first sclk bigger than request */
261 if (allowed_clock_voltage_table
->entries
[i
].clk
>= clock
) {
262 voltage
->VddGfx
= phm_get_voltage_index(
263 pptable_info
->vddgfx_lookup_table
,
264 allowed_clock_voltage_table
->entries
[i
].vddgfx
);
265 voltage
->Vddc
= phm_get_voltage_index(
266 pptable_info
->vddc_lookup_table
,
267 allowed_clock_voltage_table
->entries
[i
].vddc
);
269 if (allowed_clock_voltage_table
->entries
[i
].vddci
)
271 phm_get_voltage_id(&data
->vddci_voltage_table
, allowed_clock_voltage_table
->entries
[i
].vddci
);
274 phm_get_voltage_id(&data
->vddci_voltage_table
,
275 allowed_clock_voltage_table
->entries
[i
].vddc
- VDDC_VDDCI_DELTA
);
278 if (allowed_clock_voltage_table
->entries
[i
].mvdd
)
279 *mvdd
= (uint32_t) allowed_clock_voltage_table
->entries
[i
].mvdd
;
286 /* sclk is bigger than max sclk in the dependence table */
287 voltage
->VddGfx
= phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
288 allowed_clock_voltage_table
->entries
[i
-1].vddgfx
);
289 voltage
->Vddc
= phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
290 allowed_clock_voltage_table
->entries
[i
-1].vddc
);
292 if (allowed_clock_voltage_table
->entries
[i
-1].vddci
)
293 voltage
->Vddci
= phm_get_voltage_id(&data
->vddci_voltage_table
,
294 allowed_clock_voltage_table
->entries
[i
-1].vddci
);
296 if (allowed_clock_voltage_table
->entries
[i
-1].mvdd
)
297 *mvdd
= (uint32_t) allowed_clock_voltage_table
->entries
[i
-1].mvdd
;
302 static int tonga_populate_smc_vddc_table(struct pp_hwmgr
*hwmgr
,
303 SMU72_Discrete_DpmTable
*table
)
306 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
308 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
309 table
->VddcLevelCount
= data
->vddc_voltage_table
.count
;
310 for (count
= 0; count
< table
->VddcLevelCount
; count
++) {
311 table
->VddcTable
[count
] =
312 PP_HOST_TO_SMC_US(data
->vddc_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
314 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddcLevelCount
);
319 static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr
*hwmgr
,
320 SMU72_Discrete_DpmTable
*table
)
323 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
325 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vdd_gfx_control
) {
326 table
->VddGfxLevelCount
= data
->vddgfx_voltage_table
.count
;
327 for (count
= 0; count
< data
->vddgfx_voltage_table
.count
; count
++) {
328 table
->VddGfxTable
[count
] =
329 PP_HOST_TO_SMC_US(data
->vddgfx_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
331 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddGfxLevelCount
);
336 static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr
*hwmgr
,
337 SMU72_Discrete_DpmTable
*table
)
339 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
342 table
->VddciLevelCount
= data
->vddci_voltage_table
.count
;
343 for (count
= 0; count
< table
->VddciLevelCount
; count
++) {
344 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vddci_control
) {
345 table
->VddciTable
[count
] =
346 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
347 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->vddci_control
) {
348 table
->SmioTable1
.Pattern
[count
].Voltage
=
349 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
350 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */
351 table
->SmioTable1
.Pattern
[count
].Smio
=
353 table
->Smio
[count
] |=
354 data
->vddci_voltage_table
.entries
[count
].smio_low
;
355 table
->VddciTable
[count
] =
356 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
360 table
->SmioMask1
= data
->vddci_voltage_table
.mask_low
;
361 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddciLevelCount
);
366 static int tonga_populate_smc_mvdd_table(struct pp_hwmgr
*hwmgr
,
367 SMU72_Discrete_DpmTable
*table
)
369 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
372 if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->mvdd_control
) {
373 table
->MvddLevelCount
= data
->mvdd_voltage_table
.count
;
374 for (count
= 0; count
< table
->MvddLevelCount
; count
++) {
375 table
->SmioTable2
.Pattern
[count
].Voltage
=
376 PP_HOST_TO_SMC_US(data
->mvdd_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
377 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
378 table
->SmioTable2
.Pattern
[count
].Smio
=
380 table
->Smio
[count
] |=
381 data
->mvdd_voltage_table
.entries
[count
].smio_low
;
383 table
->SmioMask2
= data
->mvdd_voltage_table
.mask_low
;
385 CONVERT_FROM_HOST_TO_SMC_UL(table
->MvddLevelCount
);
391 static int tonga_populate_cac_tables(struct pp_hwmgr
*hwmgr
,
392 SMU72_Discrete_DpmTable
*table
)
396 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
397 struct phm_ppt_v1_information
*pptable_info
=
398 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
399 struct phm_ppt_v1_voltage_lookup_table
*vddgfx_lookup_table
=
400 pptable_info
->vddgfx_lookup_table
;
401 struct phm_ppt_v1_voltage_lookup_table
*vddc_lookup_table
=
402 pptable_info
->vddc_lookup_table
;
404 /* table is already swapped, so in order to use the value from it
405 * we need to swap it back.
407 uint32_t vddc_level_count
= PP_SMC_TO_HOST_UL(table
->VddcLevelCount
);
408 uint32_t vddgfx_level_count
= PP_SMC_TO_HOST_UL(table
->VddGfxLevelCount
);
410 for (count
= 0; count
< vddc_level_count
; count
++) {
411 /* We are populating vddc CAC data to BapmVddc table in split and merged mode */
412 index
= phm_get_voltage_index(vddc_lookup_table
,
413 data
->vddc_voltage_table
.entries
[count
].value
);
414 table
->BapmVddcVidLoSidd
[count
] =
415 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_low
);
416 table
->BapmVddcVidHiSidd
[count
] =
417 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_mid
);
418 table
->BapmVddcVidHiSidd2
[count
] =
419 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_high
);
422 if (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) {
423 /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */
424 for (count
= 0; count
< vddgfx_level_count
; count
++) {
425 index
= phm_get_voltage_index(vddgfx_lookup_table
,
426 convert_to_vid(vddgfx_lookup_table
->entries
[index
].us_cac_mid
));
427 table
->BapmVddGfxVidHiSidd2
[count
] =
428 convert_to_vid(vddgfx_lookup_table
->entries
[index
].us_cac_high
);
431 for (count
= 0; count
< vddc_level_count
; count
++) {
432 index
= phm_get_voltage_index(vddc_lookup_table
,
433 data
->vddc_voltage_table
.entries
[count
].value
);
434 table
->BapmVddGfxVidLoSidd
[count
] =
435 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_low
);
436 table
->BapmVddGfxVidHiSidd
[count
] =
437 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_mid
);
438 table
->BapmVddGfxVidHiSidd2
[count
] =
439 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_high
);
446 static int tonga_populate_smc_voltage_tables(struct pp_hwmgr
*hwmgr
,
447 SMU72_Discrete_DpmTable
*table
)
451 result
= tonga_populate_smc_vddc_table(hwmgr
, table
);
452 PP_ASSERT_WITH_CODE(!result
,
453 "can not populate VDDC voltage table to SMC",
456 result
= tonga_populate_smc_vdd_ci_table(hwmgr
, table
);
457 PP_ASSERT_WITH_CODE(!result
,
458 "can not populate VDDCI voltage table to SMC",
461 result
= tonga_populate_smc_vdd_gfx_table(hwmgr
, table
);
462 PP_ASSERT_WITH_CODE(!result
,
463 "can not populate VDDGFX voltage table to SMC",
466 result
= tonga_populate_smc_mvdd_table(hwmgr
, table
);
467 PP_ASSERT_WITH_CODE(!result
,
468 "can not populate MVDD voltage table to SMC",
471 result
= tonga_populate_cac_tables(hwmgr
, table
);
472 PP_ASSERT_WITH_CODE(!result
,
473 "can not populate CAC voltage tables to SMC",
479 static int tonga_populate_ulv_level(struct pp_hwmgr
*hwmgr
,
480 struct SMU72_Discrete_Ulv
*state
)
482 struct phm_ppt_v1_information
*table_info
=
483 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
485 state
->CcPwrDynRm
= 0;
486 state
->CcPwrDynRm1
= 0;
488 state
->VddcOffset
= (uint16_t) table_info
->us_ulv_voltage_offset
;
489 state
->VddcOffsetVid
= (uint8_t)(table_info
->us_ulv_voltage_offset
*
490 VOLTAGE_VID_OFFSET_SCALE2
/ VOLTAGE_VID_OFFSET_SCALE1
);
492 state
->VddcPhase
= 1;
494 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm
);
495 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm1
);
496 CONVERT_FROM_HOST_TO_SMC_US(state
->VddcOffset
);
501 static int tonga_populate_ulv_state(struct pp_hwmgr
*hwmgr
,
502 struct SMU72_Discrete_DpmTable
*table
)
504 return tonga_populate_ulv_level(hwmgr
, &table
->Ulv
);
507 static int tonga_populate_smc_link_level(struct pp_hwmgr
*hwmgr
, SMU72_Discrete_DpmTable
*table
)
509 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
510 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
511 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
514 /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
515 for (i
= 0; i
<= dpm_table
->pcie_speed_table
.count
; i
++) {
516 table
->LinkLevel
[i
].PcieGenSpeed
=
517 (uint8_t)dpm_table
->pcie_speed_table
.dpm_levels
[i
].value
;
518 table
->LinkLevel
[i
].PcieLaneCount
=
519 (uint8_t)encode_pcie_lane_width(dpm_table
->pcie_speed_table
.dpm_levels
[i
].param1
);
520 table
->LinkLevel
[i
].EnabledForActivity
=
522 table
->LinkLevel
[i
].SPC
=
523 (uint8_t)(data
->pcie_spc_cap
& 0xff);
524 table
->LinkLevel
[i
].DownThreshold
=
525 PP_HOST_TO_SMC_UL(5);
526 table
->LinkLevel
[i
].UpThreshold
=
527 PP_HOST_TO_SMC_UL(30);
530 smu_data
->smc_state_table
.LinkLevelCount
=
531 (uint8_t)dpm_table
->pcie_speed_table
.count
;
532 data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
=
533 phm_get_dpm_level_enable_mask_value(&dpm_table
->pcie_speed_table
);
538 static int tonga_calculate_sclk_params(struct pp_hwmgr
*hwmgr
,
539 uint32_t engine_clock
, SMU72_Discrete_GraphicsLevel
*sclk
)
541 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
542 pp_atomctrl_clock_dividers_vi dividers
;
543 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
544 uint32_t spll_func_cntl_3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
545 uint32_t spll_func_cntl_4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
546 uint32_t cg_spll_spread_spectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
547 uint32_t cg_spll_spread_spectrum_2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
548 uint32_t reference_clock
;
549 uint32_t reference_divider
;
553 /* get the engine clock dividers for this clock value*/
554 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
, engine_clock
, ÷rs
);
556 PP_ASSERT_WITH_CODE(result
== 0,
557 "Error retrieving Engine Clock dividers from VBIOS.", return result
);
559 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
560 reference_clock
= atomctrl_get_reference_clock(hwmgr
);
562 reference_divider
= 1 + dividers
.uc_pll_ref_div
;
564 /* low 14 bits is fraction and high 12 bits is divider*/
565 fbdiv
= dividers
.ul_fb_div
.ul_fb_divider
& 0x3FFFFFF;
567 /* SPLL_FUNC_CNTL setup*/
568 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
,
569 CG_SPLL_FUNC_CNTL
, SPLL_REF_DIV
, dividers
.uc_pll_ref_div
);
570 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
,
571 CG_SPLL_FUNC_CNTL
, SPLL_PDIV_A
, dividers
.uc_pll_post_div
);
573 /* SPLL_FUNC_CNTL_3 setup*/
574 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
,
575 CG_SPLL_FUNC_CNTL_3
, SPLL_FB_DIV
, fbdiv
);
577 /* set to use fractional accumulation*/
578 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
,
579 CG_SPLL_FUNC_CNTL_3
, SPLL_DITHEN
, 1);
581 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
582 PHM_PlatformCaps_EngineSpreadSpectrumSupport
)) {
583 pp_atomctrl_internal_ss_info ss_info
;
585 uint32_t vcoFreq
= engine_clock
* dividers
.uc_pll_post_div
;
586 if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr
, vcoFreq
, &ss_info
)) {
588 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
589 * ss_info.speed_spectrum_rate -- in unit of khz
591 /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
592 uint32_t clkS
= reference_clock
* 5 / (reference_divider
* ss_info
.speed_spectrum_rate
);
594 /* clkv = 2 * D * fbdiv / NS */
595 uint32_t clkV
= 4 * ss_info
.speed_spectrum_percentage
* fbdiv
/ (clkS
* 10000);
597 cg_spll_spread_spectrum
=
598 PHM_SET_FIELD(cg_spll_spread_spectrum
, CG_SPLL_SPREAD_SPECTRUM
, CLKS
, clkS
);
599 cg_spll_spread_spectrum
=
600 PHM_SET_FIELD(cg_spll_spread_spectrum
, CG_SPLL_SPREAD_SPECTRUM
, SSEN
, 1);
601 cg_spll_spread_spectrum_2
=
602 PHM_SET_FIELD(cg_spll_spread_spectrum_2
, CG_SPLL_SPREAD_SPECTRUM_2
, CLKV
, clkV
);
606 sclk
->SclkFrequency
= engine_clock
;
607 sclk
->CgSpllFuncCntl3
= spll_func_cntl_3
;
608 sclk
->CgSpllFuncCntl4
= spll_func_cntl_4
;
609 sclk
->SpllSpreadSpectrum
= cg_spll_spread_spectrum
;
610 sclk
->SpllSpreadSpectrum2
= cg_spll_spread_spectrum_2
;
611 sclk
->SclkDid
= (uint8_t)dividers
.pll_post_divider
;
616 static int tonga_populate_single_graphic_level(struct pp_hwmgr
*hwmgr
,
617 uint32_t engine_clock
,
618 SMU72_Discrete_GraphicsLevel
*graphic_level
)
622 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
623 struct phm_ppt_v1_information
*pptable_info
=
624 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
625 phm_ppt_v1_clock_voltage_dependency_table
*vdd_dep_table
= NULL
;
627 result
= tonga_calculate_sclk_params(hwmgr
, engine_clock
, graphic_level
);
629 if (hwmgr
->od_enabled
)
630 vdd_dep_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)&data
->odn_dpm_table
.vdd_dependency_on_sclk
;
632 vdd_dep_table
= pptable_info
->vdd_dep_on_sclk
;
634 /* populate graphics levels*/
635 result
= tonga_get_dependency_volt_by_clk(hwmgr
,
636 vdd_dep_table
, engine_clock
,
637 &graphic_level
->MinVoltage
, &mvdd
);
638 PP_ASSERT_WITH_CODE((!result
),
639 "can not find VDDC voltage value for VDDC "
640 "engine clock dependency table", return result
);
642 /* SCLK frequency in units of 10KHz*/
643 graphic_level
->SclkFrequency
= engine_clock
;
644 /* Indicates maximum activity level for this performance level. 50% for now*/
645 graphic_level
->ActivityLevel
= data
->current_profile_setting
.sclk_activity
;
647 graphic_level
->CcPwrDynRm
= 0;
648 graphic_level
->CcPwrDynRm1
= 0;
649 /* this level can be used if activity is high enough.*/
650 graphic_level
->EnabledForActivity
= 0;
651 /* this level can be used for throttling.*/
652 graphic_level
->EnabledForThrottle
= 1;
653 graphic_level
->UpHyst
= data
->current_profile_setting
.sclk_up_hyst
;
654 graphic_level
->DownHyst
= data
->current_profile_setting
.sclk_down_hyst
;
655 graphic_level
->VoltageDownHyst
= 0;
656 graphic_level
->PowerThrottle
= 0;
658 data
->display_timing
.min_clock_in_sr
=
659 hwmgr
->display_config
->min_core_set_clock_in_sr
;
661 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
662 PHM_PlatformCaps_SclkDeepSleep
))
663 graphic_level
->DeepSleepDivId
=
664 smu7_get_sleep_divider_id_from_clock(engine_clock
,
665 data
->display_timing
.min_clock_in_sr
);
667 /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
668 graphic_level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
671 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/
672 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/
673 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SclkFrequency
);
674 CONVERT_FROM_HOST_TO_SMC_US(graphic_level
->ActivityLevel
);
675 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CgSpllFuncCntl3
);
676 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CgSpllFuncCntl4
);
677 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SpllSpreadSpectrum
);
678 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SpllSpreadSpectrum2
);
679 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CcPwrDynRm
);
680 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CcPwrDynRm1
);
686 static int tonga_populate_all_graphic_levels(struct pp_hwmgr
*hwmgr
)
688 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
689 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
690 struct phm_ppt_v1_information
*pptable_info
= (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
691 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
692 struct phm_ppt_v1_pcie_table
*pcie_table
= pptable_info
->pcie_table
;
693 uint8_t pcie_entry_count
= (uint8_t) data
->dpm_table
.pcie_speed_table
.count
;
694 uint32_t level_array_address
= smu_data
->smu7_data
.dpm_table_start
+
695 offsetof(SMU72_Discrete_DpmTable
, GraphicsLevel
);
697 uint32_t level_array_size
= sizeof(SMU72_Discrete_GraphicsLevel
) *
698 SMU72_MAX_LEVELS_GRAPHICS
;
700 SMU72_Discrete_GraphicsLevel
*levels
= smu_data
->smc_state_table
.GraphicsLevel
;
702 uint32_t i
, max_entry
;
703 uint8_t highest_pcie_level_enabled
= 0;
704 uint8_t lowest_pcie_level_enabled
= 0, mid_pcie_level_enabled
= 0;
708 memset(levels
, 0x00, level_array_size
);
710 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++) {
711 result
= tonga_populate_single_graphic_level(hwmgr
,
712 dpm_table
->sclk_table
.dpm_levels
[i
].value
,
713 &(smu_data
->smc_state_table
.GraphicsLevel
[i
]));
717 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
719 smu_data
->smc_state_table
.GraphicsLevel
[i
].DeepSleepDivId
= 0;
722 /* Only enable level 0 for now. */
723 smu_data
->smc_state_table
.GraphicsLevel
[0].EnabledForActivity
= 1;
725 /* set highest level watermark to high */
726 if (dpm_table
->sclk_table
.count
> 1)
727 smu_data
->smc_state_table
.GraphicsLevel
[dpm_table
->sclk_table
.count
-1].DisplayWatermark
=
728 PPSMC_DISPLAY_WATERMARK_HIGH
;
730 smu_data
->smc_state_table
.GraphicsDpmLevelCount
=
731 (uint8_t)dpm_table
->sclk_table
.count
;
732 data
->dpm_level_enable_mask
.sclk_dpm_enable_mask
=
733 phm_get_dpm_level_enable_mask_value(&dpm_table
->sclk_table
);
735 if (pcie_table
!= NULL
) {
736 PP_ASSERT_WITH_CODE((pcie_entry_count
>= 1),
737 "There must be 1 or more PCIE levels defined in PPTable.",
739 max_entry
= pcie_entry_count
- 1; /* for indexing, we need to decrement by 1.*/
740 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++) {
741 smu_data
->smc_state_table
.GraphicsLevel
[i
].pcieDpmLevel
=
742 (uint8_t) ((i
< max_entry
) ? i
: max_entry
);
745 if (0 == data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
)
746 pr_err("Pcie Dpm Enablemask is 0 !");
748 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
749 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
750 (1<<(highest_pcie_level_enabled
+1))) != 0)) {
751 highest_pcie_level_enabled
++;
754 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
755 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
756 (1<<lowest_pcie_level_enabled
)) == 0)) {
757 lowest_pcie_level_enabled
++;
760 while ((count
< highest_pcie_level_enabled
) &&
761 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
762 (1<<(lowest_pcie_level_enabled
+1+count
))) == 0)) {
765 mid_pcie_level_enabled
= (lowest_pcie_level_enabled
+1+count
) < highest_pcie_level_enabled
?
766 (lowest_pcie_level_enabled
+1+count
) : highest_pcie_level_enabled
;
769 /* set pcieDpmLevel to highest_pcie_level_enabled*/
770 for (i
= 2; i
< dpm_table
->sclk_table
.count
; i
++)
771 smu_data
->smc_state_table
.GraphicsLevel
[i
].pcieDpmLevel
= highest_pcie_level_enabled
;
773 /* set pcieDpmLevel to lowest_pcie_level_enabled*/
774 smu_data
->smc_state_table
.GraphicsLevel
[0].pcieDpmLevel
= lowest_pcie_level_enabled
;
776 /* set pcieDpmLevel to mid_pcie_level_enabled*/
777 smu_data
->smc_state_table
.GraphicsLevel
[1].pcieDpmLevel
= mid_pcie_level_enabled
;
779 /* level count will send to smc once at init smc table and never change*/
780 result
= smu7_copy_bytes_to_smc(hwmgr
, level_array_address
,
781 (uint8_t *)levels
, (uint32_t)level_array_size
,
787 static int tonga_calculate_mclk_params(
788 struct pp_hwmgr
*hwmgr
,
789 uint32_t memory_clock
,
790 SMU72_Discrete_MemoryLevel
*mclk
,
795 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
797 uint32_t dll_cntl
= data
->clock_registers
.vDLL_CNTL
;
798 uint32_t mclk_pwrmgt_cntl
= data
->clock_registers
.vMCLK_PWRMGT_CNTL
;
799 uint32_t mpll_ad_func_cntl
= data
->clock_registers
.vMPLL_AD_FUNC_CNTL
;
800 uint32_t mpll_dq_func_cntl
= data
->clock_registers
.vMPLL_DQ_FUNC_CNTL
;
801 uint32_t mpll_func_cntl
= data
->clock_registers
.vMPLL_FUNC_CNTL
;
802 uint32_t mpll_func_cntl_1
= data
->clock_registers
.vMPLL_FUNC_CNTL_1
;
803 uint32_t mpll_func_cntl_2
= data
->clock_registers
.vMPLL_FUNC_CNTL_2
;
804 uint32_t mpll_ss1
= data
->clock_registers
.vMPLL_SS1
;
805 uint32_t mpll_ss2
= data
->clock_registers
.vMPLL_SS2
;
807 pp_atomctrl_memory_clock_param mpll_param
;
810 result
= atomctrl_get_memory_pll_dividers_si(hwmgr
,
811 memory_clock
, &mpll_param
, strobe_mode
);
814 "Error retrieving Memory Clock Parameters from VBIOS.",
817 /* MPLL_FUNC_CNTL setup*/
818 mpll_func_cntl
= PHM_SET_FIELD(mpll_func_cntl
, MPLL_FUNC_CNTL
, BWCTRL
,
821 /* MPLL_FUNC_CNTL_1 setup*/
822 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
823 MPLL_FUNC_CNTL_1
, CLKF
,
824 mpll_param
.mpll_fb_divider
.cl_kf
);
825 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
826 MPLL_FUNC_CNTL_1
, CLKFRAC
,
827 mpll_param
.mpll_fb_divider
.clk_frac
);
828 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
829 MPLL_FUNC_CNTL_1
, VCO_MODE
,
830 mpll_param
.vco_mode
);
832 /* MPLL_AD_FUNC_CNTL setup*/
833 mpll_ad_func_cntl
= PHM_SET_FIELD(mpll_ad_func_cntl
,
834 MPLL_AD_FUNC_CNTL
, YCLK_POST_DIV
,
835 mpll_param
.mpll_post_divider
);
837 if (data
->is_memory_gddr5
) {
838 /* MPLL_DQ_FUNC_CNTL setup*/
839 mpll_dq_func_cntl
= PHM_SET_FIELD(mpll_dq_func_cntl
,
840 MPLL_DQ_FUNC_CNTL
, YCLK_SEL
,
841 mpll_param
.yclk_sel
);
842 mpll_dq_func_cntl
= PHM_SET_FIELD(mpll_dq_func_cntl
,
843 MPLL_DQ_FUNC_CNTL
, YCLK_POST_DIV
,
844 mpll_param
.mpll_post_divider
);
847 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
848 PHM_PlatformCaps_MemorySpreadSpectrumSupport
)) {
850 ************************************
851 Fref = Reference Frequency
852 NF = Feedback divider ratio
853 NR = Reference divider ratio
854 Fnom = Nominal VCO output frequency = Fref * NF / NR
856 D = Percentage down-spread / 2
857 Fint = Reference input frequency to PFD = Fref / NR
858 NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
859 CLKS = NS - 1 = ISS_STEP_NUM[11:0]
860 NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
861 CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
862 *************************************
864 pp_atomctrl_internal_ss_info ss_info
;
867 uint32_t reference_clock
= atomctrl_get_mpll_reference_clock(hwmgr
);
869 /* for GDDR5 for all modes and DDR3 */
870 if (1 == mpll_param
.qdr
)
871 freq_nom
= memory_clock
* 4 * (1 << mpll_param
.mpll_post_divider
);
873 freq_nom
= memory_clock
* 2 * (1 << mpll_param
.mpll_post_divider
);
875 /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/
876 tmp
= (freq_nom
/ reference_clock
);
879 if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr
, freq_nom
, &ss_info
)) {
880 /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
881 /* ss.Info.speed_spectrum_rate -- in unit of khz */
882 /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
883 /* = reference_clock * 5 / speed_spectrum_rate */
884 uint32_t clks
= reference_clock
* 5 / ss_info
.speed_spectrum_rate
;
886 /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
887 /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
889 (uint32_t)((((131 * ss_info
.speed_spectrum_percentage
*
890 ss_info
.speed_spectrum_rate
) / 100) * tmp
) / freq_nom
);
892 mpll_ss1
= PHM_SET_FIELD(mpll_ss1
, MPLL_SS1
, CLKV
, clkv
);
893 mpll_ss2
= PHM_SET_FIELD(mpll_ss2
, MPLL_SS2
, CLKS
, clks
);
897 /* MCLK_PWRMGT_CNTL setup */
898 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
899 MCLK_PWRMGT_CNTL
, DLL_SPEED
, mpll_param
.dll_speed
);
900 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
901 MCLK_PWRMGT_CNTL
, MRDCK0_PDNB
, dllStateOn
);
902 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
903 MCLK_PWRMGT_CNTL
, MRDCK1_PDNB
, dllStateOn
);
905 /* Save the result data to outpupt memory level structure */
906 mclk
->MclkFrequency
= memory_clock
;
907 mclk
->MpllFuncCntl
= mpll_func_cntl
;
908 mclk
->MpllFuncCntl_1
= mpll_func_cntl_1
;
909 mclk
->MpllFuncCntl_2
= mpll_func_cntl_2
;
910 mclk
->MpllAdFuncCntl
= mpll_ad_func_cntl
;
911 mclk
->MpllDqFuncCntl
= mpll_dq_func_cntl
;
912 mclk
->MclkPwrmgtCntl
= mclk_pwrmgt_cntl
;
913 mclk
->DllCntl
= dll_cntl
;
914 mclk
->MpllSs1
= mpll_ss1
;
915 mclk
->MpllSs2
= mpll_ss2
;
920 static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock
,
923 uint8_t mc_para_index
;
926 if (memory_clock
< 12500)
927 mc_para_index
= 0x00;
928 else if (memory_clock
> 47500)
929 mc_para_index
= 0x0f;
931 mc_para_index
= (uint8_t)((memory_clock
- 10000) / 2500);
933 if (memory_clock
< 65000)
934 mc_para_index
= 0x00;
935 else if (memory_clock
> 135000)
936 mc_para_index
= 0x0f;
938 mc_para_index
= (uint8_t)((memory_clock
- 60000) / 5000);
941 return mc_para_index
;
944 static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock
)
946 uint8_t mc_para_index
;
948 if (memory_clock
< 10000)
950 else if (memory_clock
>= 80000)
951 mc_para_index
= 0x0f;
953 mc_para_index
= (uint8_t)((memory_clock
- 10000) / 5000 + 1);
955 return mc_para_index
;
959 static int tonga_populate_single_memory_level(
960 struct pp_hwmgr
*hwmgr
,
961 uint32_t memory_clock
,
962 SMU72_Discrete_MemoryLevel
*memory_level
965 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
966 struct phm_ppt_v1_information
*pptable_info
=
967 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
968 uint32_t mclk_edc_wr_enable_threshold
= 40000;
969 uint32_t mclk_stutter_mode_threshold
= 30000;
970 uint32_t mclk_edc_enable_threshold
= 40000;
971 uint32_t mclk_strobe_mode_threshold
= 40000;
972 phm_ppt_v1_clock_voltage_dependency_table
*vdd_dep_table
= NULL
;
977 if (hwmgr
->od_enabled
)
978 vdd_dep_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)&data
->odn_dpm_table
.vdd_dependency_on_mclk
;
980 vdd_dep_table
= pptable_info
->vdd_dep_on_mclk
;
982 if (NULL
!= vdd_dep_table
) {
983 result
= tonga_get_dependency_volt_by_clk(hwmgr
,
986 &memory_level
->MinVoltage
, &mvdd
);
989 "can not find MinVddc voltage value from memory VDDC "
990 "voltage dependency table",
994 if (data
->mvdd_control
== SMU7_VOLTAGE_CONTROL_NONE
)
995 memory_level
->MinMvdd
= data
->vbios_boot_state
.mvdd_bootup_value
;
997 memory_level
->MinMvdd
= mvdd
;
999 memory_level
->EnabledForThrottle
= 1;
1000 memory_level
->EnabledForActivity
= 0;
1001 memory_level
->UpHyst
= data
->current_profile_setting
.mclk_up_hyst
;
1002 memory_level
->DownHyst
= data
->current_profile_setting
.mclk_down_hyst
;
1003 memory_level
->VoltageDownHyst
= 0;
1005 /* Indicates maximum activity level for this performance level.*/
1006 memory_level
->ActivityLevel
= data
->current_profile_setting
.mclk_activity
;
1007 memory_level
->StutterEnable
= 0;
1008 memory_level
->StrobeEnable
= 0;
1009 memory_level
->EdcReadEnable
= 0;
1010 memory_level
->EdcWriteEnable
= 0;
1011 memory_level
->RttEnable
= 0;
1013 /* default set to low watermark. Highest level will be set to high later.*/
1014 memory_level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1016 data
->display_timing
.num_existing_displays
= hwmgr
->display_config
->num_display
;
1017 data
->display_timing
.vrefresh
= hwmgr
->display_config
->vrefresh
;
1019 if ((mclk_stutter_mode_threshold
!= 0) &&
1020 (memory_clock
<= mclk_stutter_mode_threshold
) &&
1021 (!data
->is_uvd_enabled
)
1022 && (PHM_READ_FIELD(hwmgr
->device
, DPG_PIPE_STUTTER_CONTROL
, STUTTER_ENABLE
) & 0x1)
1023 && (data
->display_timing
.num_existing_displays
<= 2)
1024 && (data
->display_timing
.num_existing_displays
!= 0))
1025 memory_level
->StutterEnable
= 1;
1027 /* decide strobe mode*/
1028 memory_level
->StrobeEnable
= (mclk_strobe_mode_threshold
!= 0) &&
1029 (memory_clock
<= mclk_strobe_mode_threshold
);
1031 /* decide EDC mode and memory clock ratio*/
1032 if (data
->is_memory_gddr5
) {
1033 memory_level
->StrobeRatio
= tonga_get_mclk_frequency_ratio(memory_clock
,
1034 memory_level
->StrobeEnable
);
1036 if ((mclk_edc_enable_threshold
!= 0) &&
1037 (memory_clock
> mclk_edc_enable_threshold
)) {
1038 memory_level
->EdcReadEnable
= 1;
1041 if ((mclk_edc_wr_enable_threshold
!= 0) &&
1042 (memory_clock
> mclk_edc_wr_enable_threshold
)) {
1043 memory_level
->EdcWriteEnable
= 1;
1046 if (memory_level
->StrobeEnable
) {
1047 if (tonga_get_mclk_frequency_ratio(memory_clock
, 1) >=
1048 ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC7
) >> 16) & 0xf)) {
1049 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC5
) >> 1) & 0x1) ? 1 : 0;
1051 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC6
) >> 1) & 0x1) ? 1 : 0;
1055 dll_state_on
= data
->dll_default_on
;
1058 memory_level
->StrobeRatio
=
1059 tonga_get_ddr3_mclk_frequency_ratio(memory_clock
);
1060 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC5
) >> 1) & 0x1) ? 1 : 0;
1063 result
= tonga_calculate_mclk_params(hwmgr
,
1064 memory_clock
, memory_level
, memory_level
->StrobeEnable
, dll_state_on
);
1067 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MinMvdd
);
1068 /* MCLK frequency in units of 10KHz*/
1069 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MclkFrequency
);
1070 /* Indicates maximum activity level for this performance level.*/
1071 CONVERT_FROM_HOST_TO_SMC_US(memory_level
->ActivityLevel
);
1072 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl
);
1073 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl_1
);
1074 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl_2
);
1075 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllAdFuncCntl
);
1076 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllDqFuncCntl
);
1077 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MclkPwrmgtCntl
);
1078 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->DllCntl
);
1079 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllSs1
);
1080 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllSs2
);
1086 int tonga_populate_all_memory_levels(struct pp_hwmgr
*hwmgr
)
1088 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1089 struct tonga_smumgr
*smu_data
=
1090 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1091 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
1094 /* populate MCLK dpm table to SMU7 */
1095 uint32_t level_array_address
=
1096 smu_data
->smu7_data
.dpm_table_start
+
1097 offsetof(SMU72_Discrete_DpmTable
, MemoryLevel
);
1098 uint32_t level_array_size
=
1099 sizeof(SMU72_Discrete_MemoryLevel
) *
1100 SMU72_MAX_LEVELS_MEMORY
;
1101 SMU72_Discrete_MemoryLevel
*levels
=
1102 smu_data
->smc_state_table
.MemoryLevel
;
1105 memset(levels
, 0x00, level_array_size
);
1107 for (i
= 0; i
< dpm_table
->mclk_table
.count
; i
++) {
1108 PP_ASSERT_WITH_CODE((0 != dpm_table
->mclk_table
.dpm_levels
[i
].value
),
1109 "can not populate memory level as memory clock is zero",
1111 result
= tonga_populate_single_memory_level(
1113 dpm_table
->mclk_table
.dpm_levels
[i
].value
,
1114 &(smu_data
->smc_state_table
.MemoryLevel
[i
]));
1119 /* Only enable level 0 for now.*/
1120 smu_data
->smc_state_table
.MemoryLevel
[0].EnabledForActivity
= 1;
1123 * in order to prevent MC activity from stutter mode to push DPM up.
1124 * the UVD change complements this by putting the MCLK in a higher state
1125 * by default such that we are not effected by up threshold or and MCLK DPM latency.
1127 smu_data
->smc_state_table
.MemoryLevel
[0].ActivityLevel
= 0x1F;
1128 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.MemoryLevel
[0].ActivityLevel
);
1130 smu_data
->smc_state_table
.MemoryDpmLevelCount
= (uint8_t)dpm_table
->mclk_table
.count
;
1131 data
->dpm_level_enable_mask
.mclk_dpm_enable_mask
= phm_get_dpm_level_enable_mask_value(&dpm_table
->mclk_table
);
1132 /* set highest level watermark to high*/
1133 smu_data
->smc_state_table
.MemoryLevel
[dpm_table
->mclk_table
.count
-1].DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_HIGH
;
1135 /* level count will send to smc once at init smc table and never change*/
1136 result
= smu7_copy_bytes_to_smc(hwmgr
,
1137 level_array_address
, (uint8_t *)levels
, (uint32_t)level_array_size
,
1143 static int tonga_populate_mvdd_value(struct pp_hwmgr
*hwmgr
,
1144 uint32_t mclk
, SMIO_Pattern
*smio_pattern
)
1146 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1147 struct phm_ppt_v1_information
*table_info
=
1148 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1151 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->mvdd_control
) {
1152 /* find mvdd value which clock is more than request */
1153 for (i
= 0; i
< table_info
->vdd_dep_on_mclk
->count
; i
++) {
1154 if (mclk
<= table_info
->vdd_dep_on_mclk
->entries
[i
].clk
) {
1155 /* Always round to higher voltage. */
1156 smio_pattern
->Voltage
=
1157 data
->mvdd_voltage_table
.entries
[i
].value
;
1162 PP_ASSERT_WITH_CODE(i
< table_info
->vdd_dep_on_mclk
->count
,
1163 "MVDD Voltage is outside the supported range.",
1173 static int tonga_populate_smc_acpi_level(struct pp_hwmgr
*hwmgr
,
1174 SMU72_Discrete_DpmTable
*table
)
1177 struct tonga_smumgr
*smu_data
=
1178 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1179 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1180 struct pp_atomctrl_clock_dividers_vi dividers
;
1182 SMIO_Pattern voltage_level
;
1183 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
1184 uint32_t spll_func_cntl_2
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_2
;
1185 uint32_t dll_cntl
= data
->clock_registers
.vDLL_CNTL
;
1186 uint32_t mclk_pwrmgt_cntl
= data
->clock_registers
.vMCLK_PWRMGT_CNTL
;
1188 /* The ACPI state should not do DPM on DC (or ever).*/
1189 table
->ACPILevel
.Flags
&= ~PPSMC_SWSTATE_FLAG_DC
;
1191 table
->ACPILevel
.MinVoltage
=
1192 smu_data
->smc_state_table
.GraphicsLevel
[0].MinVoltage
;
1194 /* assign zero for now*/
1195 table
->ACPILevel
.SclkFrequency
= atomctrl_get_reference_clock(hwmgr
);
1197 /* get the engine clock dividers for this clock value*/
1198 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
,
1199 table
->ACPILevel
.SclkFrequency
, ÷rs
);
1201 PP_ASSERT_WITH_CODE(result
== 0,
1202 "Error retrieving Engine Clock dividers from VBIOS.",
1205 /* divider ID for required SCLK*/
1206 table
->ACPILevel
.SclkDid
= (uint8_t)dividers
.pll_post_divider
;
1207 table
->ACPILevel
.DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1208 table
->ACPILevel
.DeepSleepDivId
= 0;
1210 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1212 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1214 spll_func_cntl_2
= PHM_SET_FIELD(spll_func_cntl_2
, CG_SPLL_FUNC_CNTL_2
,
1217 table
->ACPILevel
.CgSpllFuncCntl
= spll_func_cntl
;
1218 table
->ACPILevel
.CgSpllFuncCntl2
= spll_func_cntl_2
;
1219 table
->ACPILevel
.CgSpllFuncCntl3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
1220 table
->ACPILevel
.CgSpllFuncCntl4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
1221 table
->ACPILevel
.SpllSpreadSpectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
1222 table
->ACPILevel
.SpllSpreadSpectrum2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
1223 table
->ACPILevel
.CcPwrDynRm
= 0;
1224 table
->ACPILevel
.CcPwrDynRm1
= 0;
1227 /* For various features to be enabled/disabled while this level is active.*/
1228 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.Flags
);
1229 /* SCLK frequency in units of 10KHz*/
1230 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SclkFrequency
);
1231 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl
);
1232 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl2
);
1233 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl3
);
1234 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl4
);
1235 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum
);
1236 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum2
);
1237 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm
);
1238 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm1
);
1240 /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
1241 table
->MemoryACPILevel
.MinVoltage
=
1242 smu_data
->smc_state_table
.MemoryLevel
[0].MinVoltage
;
1244 /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/
1246 if (0 == tonga_populate_mvdd_value(hwmgr
, 0, &voltage_level
))
1247 table
->MemoryACPILevel
.MinMvdd
=
1248 PP_HOST_TO_SMC_UL(voltage_level
.Voltage
* VOLTAGE_SCALE
);
1250 table
->MemoryACPILevel
.MinMvdd
= 0;
1252 /* Force reset on DLL*/
1253 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1254 MCLK_PWRMGT_CNTL
, MRDCK0_RESET
, 0x1);
1255 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1256 MCLK_PWRMGT_CNTL
, MRDCK1_RESET
, 0x1);
1258 /* Disable DLL in ACPIState*/
1259 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1260 MCLK_PWRMGT_CNTL
, MRDCK0_PDNB
, 0);
1261 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1262 MCLK_PWRMGT_CNTL
, MRDCK1_PDNB
, 0);
1264 /* Enable DLL bypass signal*/
1265 dll_cntl
= PHM_SET_FIELD(dll_cntl
,
1266 DLL_CNTL
, MRDCK0_BYPASS
, 0);
1267 dll_cntl
= PHM_SET_FIELD(dll_cntl
,
1268 DLL_CNTL
, MRDCK1_BYPASS
, 0);
1270 table
->MemoryACPILevel
.DllCntl
=
1271 PP_HOST_TO_SMC_UL(dll_cntl
);
1272 table
->MemoryACPILevel
.MclkPwrmgtCntl
=
1273 PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl
);
1274 table
->MemoryACPILevel
.MpllAdFuncCntl
=
1275 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_AD_FUNC_CNTL
);
1276 table
->MemoryACPILevel
.MpllDqFuncCntl
=
1277 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_DQ_FUNC_CNTL
);
1278 table
->MemoryACPILevel
.MpllFuncCntl
=
1279 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL
);
1280 table
->MemoryACPILevel
.MpllFuncCntl_1
=
1281 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL_1
);
1282 table
->MemoryACPILevel
.MpllFuncCntl_2
=
1283 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL_2
);
1284 table
->MemoryACPILevel
.MpllSs1
=
1285 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_SS1
);
1286 table
->MemoryACPILevel
.MpllSs2
=
1287 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_SS2
);
1289 table
->MemoryACPILevel
.EnabledForThrottle
= 0;
1290 table
->MemoryACPILevel
.EnabledForActivity
= 0;
1291 table
->MemoryACPILevel
.UpHyst
= 0;
1292 table
->MemoryACPILevel
.DownHyst
= 100;
1293 table
->MemoryACPILevel
.VoltageDownHyst
= 0;
1294 /* Indicates maximum activity level for this performance level.*/
1295 table
->MemoryACPILevel
.ActivityLevel
=
1296 PP_HOST_TO_SMC_US(data
->current_profile_setting
.mclk_activity
);
1298 table
->MemoryACPILevel
.StutterEnable
= 0;
1299 table
->MemoryACPILevel
.StrobeEnable
= 0;
1300 table
->MemoryACPILevel
.EdcReadEnable
= 0;
1301 table
->MemoryACPILevel
.EdcWriteEnable
= 0;
1302 table
->MemoryACPILevel
.RttEnable
= 0;
1307 static int tonga_populate_smc_uvd_level(struct pp_hwmgr
*hwmgr
,
1308 SMU72_Discrete_DpmTable
*table
)
1313 pp_atomctrl_clock_dividers_vi dividers
;
1314 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1315 struct phm_ppt_v1_information
*pptable_info
=
1316 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1317 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1318 pptable_info
->mm_dep_table
;
1320 table
->UvdLevelCount
= (uint8_t) (mm_table
->count
);
1321 table
->UvdBootLevel
= 0;
1323 for (count
= 0; count
< table
->UvdLevelCount
; count
++) {
1324 table
->UvdLevel
[count
].VclkFrequency
= mm_table
->entries
[count
].vclk
;
1325 table
->UvdLevel
[count
].DclkFrequency
= mm_table
->entries
[count
].dclk
;
1326 table
->UvdLevel
[count
].MinVoltage
.Vddc
=
1327 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1328 mm_table
->entries
[count
].vddc
);
1329 table
->UvdLevel
[count
].MinVoltage
.VddGfx
=
1330 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1331 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1332 mm_table
->entries
[count
].vddgfx
) : 0;
1333 table
->UvdLevel
[count
].MinVoltage
.Vddci
=
1334 phm_get_voltage_id(&data
->vddci_voltage_table
,
1335 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1336 table
->UvdLevel
[count
].MinVoltage
.Phases
= 1;
1338 /* retrieve divider value for VBIOS */
1339 result
= atomctrl_get_dfs_pll_dividers_vi(
1341 table
->UvdLevel
[count
].VclkFrequency
,
1344 PP_ASSERT_WITH_CODE((!result
),
1345 "can not find divide id for Vclk clock",
1348 table
->UvdLevel
[count
].VclkDivider
= (uint8_t)dividers
.pll_post_divider
;
1350 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1351 table
->UvdLevel
[count
].DclkFrequency
, ÷rs
);
1352 PP_ASSERT_WITH_CODE((!result
),
1353 "can not find divide id for Dclk clock",
1356 table
->UvdLevel
[count
].DclkDivider
=
1357 (uint8_t)dividers
.pll_post_divider
;
1359 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].VclkFrequency
);
1360 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].DclkFrequency
);
1367 static int tonga_populate_smc_vce_level(struct pp_hwmgr
*hwmgr
,
1368 SMU72_Discrete_DpmTable
*table
)
1373 pp_atomctrl_clock_dividers_vi dividers
;
1374 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1375 struct phm_ppt_v1_information
*pptable_info
=
1376 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1377 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1378 pptable_info
->mm_dep_table
;
1380 table
->VceLevelCount
= (uint8_t) (mm_table
->count
);
1381 table
->VceBootLevel
= 0;
1383 for (count
= 0; count
< table
->VceLevelCount
; count
++) {
1384 table
->VceLevel
[count
].Frequency
=
1385 mm_table
->entries
[count
].eclk
;
1386 table
->VceLevel
[count
].MinVoltage
.Vddc
=
1387 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1388 mm_table
->entries
[count
].vddc
);
1389 table
->VceLevel
[count
].MinVoltage
.VddGfx
=
1390 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1391 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1392 mm_table
->entries
[count
].vddgfx
) : 0;
1393 table
->VceLevel
[count
].MinVoltage
.Vddci
=
1394 phm_get_voltage_id(&data
->vddci_voltage_table
,
1395 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1396 table
->VceLevel
[count
].MinVoltage
.Phases
= 1;
1398 /* retrieve divider value for VBIOS */
1399 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1400 table
->VceLevel
[count
].Frequency
, ÷rs
);
1401 PP_ASSERT_WITH_CODE((!result
),
1402 "can not find divide id for VCE engine clock",
1405 table
->VceLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1407 CONVERT_FROM_HOST_TO_SMC_UL(table
->VceLevel
[count
].Frequency
);
1413 static int tonga_populate_smc_acp_level(struct pp_hwmgr
*hwmgr
,
1414 SMU72_Discrete_DpmTable
*table
)
1418 pp_atomctrl_clock_dividers_vi dividers
;
1419 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1420 struct phm_ppt_v1_information
*pptable_info
=
1421 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1422 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1423 pptable_info
->mm_dep_table
;
1425 table
->AcpLevelCount
= (uint8_t) (mm_table
->count
);
1426 table
->AcpBootLevel
= 0;
1428 for (count
= 0; count
< table
->AcpLevelCount
; count
++) {
1429 table
->AcpLevel
[count
].Frequency
=
1430 pptable_info
->mm_dep_table
->entries
[count
].aclk
;
1431 table
->AcpLevel
[count
].MinVoltage
.Vddc
=
1432 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1433 mm_table
->entries
[count
].vddc
);
1434 table
->AcpLevel
[count
].MinVoltage
.VddGfx
=
1435 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1436 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1437 mm_table
->entries
[count
].vddgfx
) : 0;
1438 table
->AcpLevel
[count
].MinVoltage
.Vddci
=
1439 phm_get_voltage_id(&data
->vddci_voltage_table
,
1440 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1441 table
->AcpLevel
[count
].MinVoltage
.Phases
= 1;
1443 /* retrieve divider value for VBIOS */
1444 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1445 table
->AcpLevel
[count
].Frequency
, ÷rs
);
1446 PP_ASSERT_WITH_CODE((!result
),
1447 "can not find divide id for engine clock", return result
);
1449 table
->AcpLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1451 CONVERT_FROM_HOST_TO_SMC_UL(table
->AcpLevel
[count
].Frequency
);
1457 static int tonga_populate_memory_timing_parameters(
1458 struct pp_hwmgr
*hwmgr
,
1459 uint32_t engine_clock
,
1460 uint32_t memory_clock
,
1461 struct SMU72_Discrete_MCArbDramTimingTableEntry
*arb_regs
1464 uint32_t dramTiming
;
1465 uint32_t dramTiming2
;
1469 result
= atomctrl_set_engine_dram_timings_rv770(hwmgr
,
1470 engine_clock
, memory_clock
);
1472 PP_ASSERT_WITH_CODE(result
== 0,
1473 "Error calling VBIOS to set DRAM_TIMING.", return result
);
1475 dramTiming
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING
);
1476 dramTiming2
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING2
);
1477 burstTime
= PHM_READ_FIELD(hwmgr
->device
, MC_ARB_BURST_TIME
, STATE0
);
1479 arb_regs
->McArbDramTiming
= PP_HOST_TO_SMC_UL(dramTiming
);
1480 arb_regs
->McArbDramTiming2
= PP_HOST_TO_SMC_UL(dramTiming2
);
1481 arb_regs
->McArbBurstTime
= (uint8_t)burstTime
;
1486 static int tonga_program_memory_timing_parameters(struct pp_hwmgr
*hwmgr
)
1488 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1489 struct tonga_smumgr
*smu_data
=
1490 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1492 SMU72_Discrete_MCArbDramTimingTable arb_regs
;
1495 memset(&arb_regs
, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable
));
1497 for (i
= 0; i
< data
->dpm_table
.sclk_table
.count
; i
++) {
1498 for (j
= 0; j
< data
->dpm_table
.mclk_table
.count
; j
++) {
1499 result
= tonga_populate_memory_timing_parameters
1500 (hwmgr
, data
->dpm_table
.sclk_table
.dpm_levels
[i
].value
,
1501 data
->dpm_table
.mclk_table
.dpm_levels
[j
].value
,
1502 &arb_regs
.entries
[i
][j
]);
1510 result
= smu7_copy_bytes_to_smc(
1512 smu_data
->smu7_data
.arb_table_start
,
1513 (uint8_t *)&arb_regs
,
1514 sizeof(SMU72_Discrete_MCArbDramTimingTable
),
1522 static int tonga_populate_smc_boot_level(struct pp_hwmgr
*hwmgr
,
1523 SMU72_Discrete_DpmTable
*table
)
1526 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1527 struct tonga_smumgr
*smu_data
=
1528 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1529 table
->GraphicsBootLevel
= 0;
1530 table
->MemoryBootLevel
= 0;
1532 /* find boot level from dpm table*/
1533 result
= phm_find_boot_level(&(data
->dpm_table
.sclk_table
),
1534 data
->vbios_boot_state
.sclk_bootup_value
,
1535 (uint32_t *)&(smu_data
->smc_state_table
.GraphicsBootLevel
));
1538 smu_data
->smc_state_table
.GraphicsBootLevel
= 0;
1539 pr_err("[powerplay] VBIOS did not find boot engine "
1540 "clock value in dependency table. "
1541 "Using Graphics DPM level 0 !");
1545 result
= phm_find_boot_level(&(data
->dpm_table
.mclk_table
),
1546 data
->vbios_boot_state
.mclk_bootup_value
,
1547 (uint32_t *)&(smu_data
->smc_state_table
.MemoryBootLevel
));
1550 smu_data
->smc_state_table
.MemoryBootLevel
= 0;
1551 pr_err("[powerplay] VBIOS did not find boot "
1552 "engine clock value in dependency table."
1553 "Using Memory DPM level 0 !");
1557 table
->BootVoltage
.Vddc
=
1558 phm_get_voltage_id(&(data
->vddc_voltage_table
),
1559 data
->vbios_boot_state
.vddc_bootup_value
);
1560 table
->BootVoltage
.VddGfx
=
1561 phm_get_voltage_id(&(data
->vddgfx_voltage_table
),
1562 data
->vbios_boot_state
.vddgfx_bootup_value
);
1563 table
->BootVoltage
.Vddci
=
1564 phm_get_voltage_id(&(data
->vddci_voltage_table
),
1565 data
->vbios_boot_state
.vddci_bootup_value
);
1566 table
->BootMVdd
= data
->vbios_boot_state
.mvdd_bootup_value
;
1568 CONVERT_FROM_HOST_TO_SMC_US(table
->BootMVdd
);
1573 static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr
*hwmgr
)
1575 uint32_t ro
, efuse
, efuse2
, clock_freq
, volt_without_cks
,
1576 volt_with_cks
, value
;
1577 uint16_t clock_freq_u16
;
1578 struct tonga_smumgr
*smu_data
=
1579 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1580 uint8_t type
, i
, j
, cks_setting
, stretch_amount
, stretch_amount2
,
1582 struct phm_ppt_v1_information
*table_info
=
1583 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1584 struct phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
=
1585 table_info
->vdd_dep_on_sclk
;
1586 uint32_t hw_revision
, dev_id
;
1587 struct amdgpu_device
*adev
= hwmgr
->adev
;
1589 stretch_amount
= (uint8_t)table_info
->cac_dtp_table
->usClockStretchAmount
;
1591 hw_revision
= adev
->pdev
->revision
;
1592 dev_id
= adev
->pdev
->device
;
1594 /* Read SMU_Eefuse to read and calculate RO and determine
1595 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1597 efuse
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1598 ixSMU_EFUSE_0
+ (146 * 4));
1599 efuse2
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1600 ixSMU_EFUSE_0
+ (148 * 4));
1601 efuse
&= 0xFF000000;
1602 efuse
= efuse
>> 24;
1606 ro
= (2300 - 1350) * efuse
/ 255 + 1350;
1608 ro
= (2500 - 1000) * efuse
/ 255 + 1000;
1615 /* Populate Stretch amount */
1616 smu_data
->smc_state_table
.ClockStretcherAmount
= stretch_amount
;
1619 /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1620 for (i
= 0; i
< sclk_table
->count
; i
++) {
1621 smu_data
->smc_state_table
.Sclk_CKS_masterEn0_7
|=
1622 sclk_table
->entries
[i
].cks_enable
<< i
;
1623 if (ASICID_IS_TONGA_P(dev_id
, hw_revision
)) {
1624 volt_without_cks
= (uint32_t)((7732 + 60 - ro
- 20838 *
1625 (sclk_table
->entries
[i
].clk
/100) / 10000) * 1000 /
1626 (8730 - (5301 * (sclk_table
->entries
[i
].clk
/100) / 1000)));
1627 volt_with_cks
= (uint32_t)((5250 + 51 - ro
- 2404 *
1628 (sclk_table
->entries
[i
].clk
/100) / 100000) * 1000 /
1629 (6146 - (3193 * (sclk_table
->entries
[i
].clk
/100) / 1000)));
1631 volt_without_cks
= (uint32_t)((14041 *
1632 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3571 + 75 - ro
) * 1000 /
1633 (4026 - (13924 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1634 volt_with_cks
= (uint32_t)((13946 *
1635 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3320 + 45 - ro
) * 1000 /
1636 (3664 - (11454 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1638 if (volt_without_cks
>= volt_with_cks
)
1639 volt_offset
= (uint8_t)(((volt_without_cks
- volt_with_cks
+
1640 sclk_table
->entries
[i
].cks_voffset
) * 100 / 625) + 1);
1641 smu_data
->smc_state_table
.Sclk_voltageOffset
[i
] = volt_offset
;
1644 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1645 STRETCH_ENABLE
, 0x0);
1646 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1648 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1650 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1653 /* Populate CKS Lookup Table */
1654 if (stretch_amount
== 1 || stretch_amount
== 2 || stretch_amount
== 5)
1655 stretch_amount2
= 0;
1656 else if (stretch_amount
== 3 || stretch_amount
== 4)
1657 stretch_amount2
= 1;
1659 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
1660 PHM_PlatformCaps_ClockStretcher
);
1661 PP_ASSERT_WITH_CODE(false,
1662 "Stretch Amount in PPTable not supported",
1666 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1668 value
&= 0xFFC2FF87;
1669 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].minFreq
=
1670 tonga_clock_stretcher_lookup_table
[stretch_amount2
][0];
1671 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].maxFreq
=
1672 tonga_clock_stretcher_lookup_table
[stretch_amount2
][1];
1673 clock_freq_u16
= (uint16_t)(PP_SMC_TO_HOST_UL(smu_data
->smc_state_table
.
1674 GraphicsLevel
[smu_data
->smc_state_table
.GraphicsDpmLevelCount
- 1].
1675 SclkFrequency
) / 100);
1676 if (tonga_clock_stretcher_lookup_table
[stretch_amount2
][0] <
1678 tonga_clock_stretcher_lookup_table
[stretch_amount2
][1] >
1680 /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
1681 value
|= (tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 16;
1682 /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
1683 value
|= (tonga_clock_stretcher_lookup_table
[stretch_amount2
][2]) << 18;
1684 /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
1685 value
|= (tonga_clock_stretch_amount_conversion
1686 [tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]]
1687 [stretch_amount
]) << 3;
1689 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1690 CKS_LOOKUPTableEntry
[0].minFreq
);
1691 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1692 CKS_LOOKUPTableEntry
[0].maxFreq
);
1693 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
=
1694 tonga_clock_stretcher_lookup_table
[stretch_amount2
][2] & 0x7F;
1695 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
|=
1696 (tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 7;
1698 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1699 ixPWR_CKS_CNTL
, value
);
1701 /* Populate DDT Lookup Table */
1702 for (i
= 0; i
< 4; i
++) {
1703 /* Assign the minimum and maximum VID stored
1704 * in the last row of Clock Stretcher Voltage Table.
1706 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1707 ClockStretcherDataTableEntry
[i
].minVID
=
1708 (uint8_t) tonga_clock_stretcher_ddt_table
[type
][i
][2];
1709 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1710 ClockStretcherDataTableEntry
[i
].maxVID
=
1711 (uint8_t) tonga_clock_stretcher_ddt_table
[type
][i
][3];
1712 /* Loop through each SCLK and check the frequency
1713 * to see if it lies within the frequency for clock stretcher.
1715 for (j
= 0; j
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; j
++) {
1717 clock_freq
= PP_SMC_TO_HOST_UL(
1718 smu_data
->smc_state_table
.GraphicsLevel
[j
].SclkFrequency
);
1719 /* Check the allowed frequency against the sclk level[j].
1720 * Sclk's endianness has already been converted,
1721 * and it's in 10Khz unit,
1722 * as opposed to Data table, which is in Mhz unit.
1724 if (clock_freq
>= tonga_clock_stretcher_ddt_table
[type
][i
][0] * 100) {
1726 if (clock_freq
< tonga_clock_stretcher_ddt_table
[type
][i
][1] * 100)
1729 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1730 ClockStretcherDataTableEntry
[i
].setting
|= cks_setting
<< (j
* 2);
1732 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.
1733 ClockStretcherDataTable
.
1734 ClockStretcherDataTableEntry
[i
].setting
);
1737 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1739 value
&= 0xFFFFFFFE;
1740 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1741 ixPWR_CKS_CNTL
, value
);
1746 static int tonga_populate_vr_config(struct pp_hwmgr
*hwmgr
,
1747 SMU72_Discrete_DpmTable
*table
)
1749 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1752 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vdd_gfx_control
) {
1754 config
= VR_SVI2_PLANE_1
;
1755 table
->VRConfig
|= (config
<<VRCONF_VDDGFX_SHIFT
);
1757 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
1758 config
= VR_SVI2_PLANE_2
;
1759 table
->VRConfig
|= config
;
1761 pr_err("VDDC and VDDGFX should "
1762 "be both on SVI2 control in splitted mode !\n");
1766 config
= VR_MERGED_WITH_VDDC
;
1767 table
->VRConfig
|= (config
<<VRCONF_VDDGFX_SHIFT
);
1769 /* Set Vddc Voltage Controller */
1770 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
1771 config
= VR_SVI2_PLANE_1
;
1772 table
->VRConfig
|= config
;
1774 pr_err("VDDC should be on "
1775 "SVI2 control in merged mode !\n");
1779 /* Set Vddci Voltage Controller */
1780 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vddci_control
) {
1781 config
= VR_SVI2_PLANE_2
; /* only in merged mode */
1782 table
->VRConfig
|= (config
<<VRCONF_VDDCI_SHIFT
);
1783 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->vddci_control
) {
1784 config
= VR_SMIO_PATTERN_1
;
1785 table
->VRConfig
|= (config
<<VRCONF_VDDCI_SHIFT
);
1788 /* Set Mvdd Voltage Controller */
1789 if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->mvdd_control
) {
1790 config
= VR_SMIO_PATTERN_2
;
1791 table
->VRConfig
|= (config
<<VRCONF_MVDD_SHIFT
);
1797 static int tonga_init_arb_table_index(struct pp_hwmgr
*hwmgr
)
1799 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1804 * This is a read-modify-write on the first byte of the ARB table.
1805 * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure
1806 * is the field 'current'.
1807 * This solution is ugly, but we never write the whole table only
1808 * individual fields in it.
1809 * In reality this field should not be in that structure
1810 * but in a soft register.
1812 result
= smu7_read_smc_sram_dword(hwmgr
,
1813 smu_data
->smu7_data
.arb_table_start
, &tmp
, SMC_RAM_END
);
1819 tmp
|= ((uint32_t)MC_CG_ARB_FREQ_F1
) << 24;
1821 return smu7_write_smc_sram_dword(hwmgr
,
1822 smu_data
->smu7_data
.arb_table_start
, tmp
, SMC_RAM_END
);
1826 static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr
*hwmgr
)
1828 struct tonga_smumgr
*smu_data
=
1829 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1830 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1831 SMU72_Discrete_DpmTable
*dpm_table
= &(smu_data
->smc_state_table
);
1832 struct phm_ppt_v1_information
*table_info
=
1833 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1834 struct phm_cac_tdp_table
*cac_dtp_table
= table_info
->cac_dtp_table
;
1836 const uint16_t *pdef1
, *pdef2
;
1838 dpm_table
->DefaultTdp
= PP_HOST_TO_SMC_US(
1839 (uint16_t)(cac_dtp_table
->usTDP
* 256));
1840 dpm_table
->TargetTdp
= PP_HOST_TO_SMC_US(
1841 (uint16_t)(cac_dtp_table
->usConfigurableTDP
* 256));
1843 PP_ASSERT_WITH_CODE(cac_dtp_table
->usTargetOperatingTemp
<= 255,
1844 "Target Operating Temp is out of Range !",
1847 dpm_table
->GpuTjMax
= (uint8_t)(cac_dtp_table
->usTargetOperatingTemp
);
1848 dpm_table
->GpuTjHyst
= 8;
1850 dpm_table
->DTEAmbientTempBase
= defaults
->dte_ambient_temp_base
;
1852 dpm_table
->BAPM_TEMP_GRADIENT
=
1853 PP_HOST_TO_SMC_UL(defaults
->bapm_temp_gradient
);
1854 pdef1
= defaults
->bapmti_r
;
1855 pdef2
= defaults
->bapmti_rc
;
1857 for (i
= 0; i
< SMU72_DTE_ITERATIONS
; i
++) {
1858 for (j
= 0; j
< SMU72_DTE_SOURCES
; j
++) {
1859 for (k
= 0; k
< SMU72_DTE_SINKS
; k
++) {
1860 dpm_table
->BAPMTI_R
[i
][j
][k
] =
1861 PP_HOST_TO_SMC_US(*pdef1
);
1862 dpm_table
->BAPMTI_RC
[i
][j
][k
] =
1863 PP_HOST_TO_SMC_US(*pdef2
);
1873 static int tonga_populate_svi_load_line(struct pp_hwmgr
*hwmgr
)
1875 struct tonga_smumgr
*smu_data
=
1876 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1877 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1879 smu_data
->power_tune_table
.SviLoadLineEn
= defaults
->svi_load_line_en
;
1880 smu_data
->power_tune_table
.SviLoadLineVddC
= defaults
->svi_load_line_vddC
;
1881 smu_data
->power_tune_table
.SviLoadLineTrimVddC
= 3;
1882 smu_data
->power_tune_table
.SviLoadLineOffsetVddC
= 0;
1887 static int tonga_populate_tdc_limit(struct pp_hwmgr
*hwmgr
)
1890 struct tonga_smumgr
*smu_data
=
1891 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1892 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1893 struct phm_ppt_v1_information
*table_info
=
1894 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1896 /* TDC number of fraction bits are changed from 8 to 7
1897 * for Fiji as requested by SMC team
1899 tdc_limit
= (uint16_t)(table_info
->cac_dtp_table
->usTDC
* 256);
1900 smu_data
->power_tune_table
.TDC_VDDC_PkgLimit
=
1901 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit
);
1902 smu_data
->power_tune_table
.TDC_VDDC_ThrottleReleaseLimitPerc
=
1903 defaults
->tdc_vddc_throttle_release_limit_perc
;
1904 smu_data
->power_tune_table
.TDC_MAWt
= defaults
->tdc_mawt
;
1909 static int tonga_populate_dw8(struct pp_hwmgr
*hwmgr
, uint32_t fuse_table_offset
)
1911 struct tonga_smumgr
*smu_data
=
1912 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1913 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1916 if (smu7_read_smc_sram_dword(hwmgr
,
1918 offsetof(SMU72_Discrete_PmFuses
, TdcWaterfallCtl
),
1919 (uint32_t *)&temp
, SMC_RAM_END
))
1920 PP_ASSERT_WITH_CODE(false,
1921 "Attempt to read PmFuses.DW6 "
1922 "(SviLoadLineEn) from SMC Failed !",
1925 smu_data
->power_tune_table
.TdcWaterfallCtl
= defaults
->tdc_waterfall_ctl
;
1930 static int tonga_populate_temperature_scaler(struct pp_hwmgr
*hwmgr
)
1933 struct tonga_smumgr
*smu_data
=
1934 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1936 /* Currently not used. Set all to zero. */
1937 for (i
= 0; i
< 16; i
++)
1938 smu_data
->power_tune_table
.LPMLTemperatureScaler
[i
] = 0;
1943 static int tonga_populate_fuzzy_fan(struct pp_hwmgr
*hwmgr
)
1945 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1947 if ((hwmgr
->thermal_controller
.advanceFanControlParameters
.
1948 usFanOutputSensitivity
& (1 << 15)) ||
1949 (hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
== 0))
1950 hwmgr
->thermal_controller
.advanceFanControlParameters
.
1951 usFanOutputSensitivity
= hwmgr
->thermal_controller
.
1952 advanceFanControlParameters
.usDefaultFanOutputSensitivity
;
1954 smu_data
->power_tune_table
.FuzzyFan_PwmSetDelta
=
1955 PP_HOST_TO_SMC_US(hwmgr
->thermal_controller
.
1956 advanceFanControlParameters
.usFanOutputSensitivity
);
1960 static int tonga_populate_gnb_lpml(struct pp_hwmgr
*hwmgr
)
1963 struct tonga_smumgr
*smu_data
=
1964 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1966 /* Currently not used. Set all to zero. */
1967 for (i
= 0; i
< 16; i
++)
1968 smu_data
->power_tune_table
.GnbLPML
[i
] = 0;
1973 static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr
*hwmgr
)
1975 struct tonga_smumgr
*smu_data
=
1976 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1977 struct phm_ppt_v1_information
*table_info
=
1978 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1979 uint16_t hi_sidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
;
1980 uint16_t lo_sidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
;
1981 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
1983 hi_sidd
= (uint16_t)(cac_table
->usHighCACLeakage
/ 100 * 256);
1984 lo_sidd
= (uint16_t)(cac_table
->usLowCACLeakage
/ 100 * 256);
1986 smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
=
1987 CONVERT_FROM_HOST_TO_SMC_US(hi_sidd
);
1988 smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
=
1989 CONVERT_FROM_HOST_TO_SMC_US(lo_sidd
);
1994 static int tonga_populate_pm_fuses(struct pp_hwmgr
*hwmgr
)
1996 struct tonga_smumgr
*smu_data
=
1997 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
1998 uint32_t pm_fuse_table_offset
;
2000 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2001 PHM_PlatformCaps_PowerContainment
)) {
2002 if (smu7_read_smc_sram_dword(hwmgr
,
2003 SMU72_FIRMWARE_HEADER_LOCATION
+
2004 offsetof(SMU72_Firmware_Header
, PmFuseTable
),
2005 &pm_fuse_table_offset
, SMC_RAM_END
))
2006 PP_ASSERT_WITH_CODE(false,
2007 "Attempt to get pm_fuse_table_offset Failed !",
2011 if (tonga_populate_svi_load_line(hwmgr
))
2012 PP_ASSERT_WITH_CODE(false,
2013 "Attempt to populate SviLoadLine Failed !",
2016 if (tonga_populate_tdc_limit(hwmgr
))
2017 PP_ASSERT_WITH_CODE(false,
2018 "Attempt to populate TDCLimit Failed !",
2021 if (tonga_populate_dw8(hwmgr
, pm_fuse_table_offset
))
2022 PP_ASSERT_WITH_CODE(false,
2023 "Attempt to populate TdcWaterfallCtl Failed !",
2027 if (tonga_populate_temperature_scaler(hwmgr
) != 0)
2028 PP_ASSERT_WITH_CODE(false,
2029 "Attempt to populate LPMLTemperatureScaler Failed !",
2033 if (tonga_populate_fuzzy_fan(hwmgr
))
2034 PP_ASSERT_WITH_CODE(false,
2035 "Attempt to populate Fuzzy Fan "
2036 "Control parameters Failed !",
2040 if (tonga_populate_gnb_lpml(hwmgr
))
2041 PP_ASSERT_WITH_CODE(false,
2042 "Attempt to populate GnbLPML Failed !",
2046 if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr
))
2047 PP_ASSERT_WITH_CODE(
2049 "Attempt to populate BapmVddCBaseLeakage "
2050 "Hi and Lo Sidd Failed !",
2053 if (smu7_copy_bytes_to_smc(hwmgr
, pm_fuse_table_offset
,
2054 (uint8_t *)&smu_data
->power_tune_table
,
2055 sizeof(struct SMU72_Discrete_PmFuses
), SMC_RAM_END
))
2056 PP_ASSERT_WITH_CODE(false,
2057 "Attempt to download PmFuseTable Failed !",
2063 static int tonga_populate_mc_reg_address(struct pp_hwmgr
*hwmgr
,
2064 SMU72_Discrete_MCRegisters
*mc_reg_table
)
2066 const struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)hwmgr
->smu_backend
;
2070 for (i
= 0, j
= 0; j
< smu_data
->mc_reg_table
.last
; j
++) {
2071 if (smu_data
->mc_reg_table
.validflag
& 1<<j
) {
2072 PP_ASSERT_WITH_CODE(
2073 i
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
,
2074 "Index of mc_reg_table->address[] array "
2077 mc_reg_table
->address
[i
].s0
=
2078 PP_HOST_TO_SMC_US(smu_data
->mc_reg_table
.mc_reg_address
[j
].s0
);
2079 mc_reg_table
->address
[i
].s1
=
2080 PP_HOST_TO_SMC_US(smu_data
->mc_reg_table
.mc_reg_address
[j
].s1
);
2085 mc_reg_table
->last
= (uint8_t)i
;
2090 /*convert register values from driver to SMC format */
2091 static void tonga_convert_mc_registers(
2092 const struct tonga_mc_reg_entry
*entry
,
2093 SMU72_Discrete_MCRegisterSet
*data
,
2094 uint32_t num_entries
, uint32_t valid_flag
)
2098 for (i
= 0, j
= 0; j
< num_entries
; j
++) {
2099 if (valid_flag
& 1<<j
) {
2100 data
->value
[i
] = PP_HOST_TO_SMC_UL(entry
->mc_data
[j
]);
2106 static int tonga_convert_mc_reg_table_entry_to_smc(
2107 struct pp_hwmgr
*hwmgr
,
2108 const uint32_t memory_clock
,
2109 SMU72_Discrete_MCRegisterSet
*mc_reg_table_data
2112 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2115 for (i
= 0; i
< smu_data
->mc_reg_table
.num_entries
; i
++) {
2117 smu_data
->mc_reg_table
.mc_reg_table_entry
[i
].mclk_max
) {
2122 if ((i
== smu_data
->mc_reg_table
.num_entries
) && (i
> 0))
2125 tonga_convert_mc_registers(&smu_data
->mc_reg_table
.mc_reg_table_entry
[i
],
2126 mc_reg_table_data
, smu_data
->mc_reg_table
.last
,
2127 smu_data
->mc_reg_table
.validflag
);
2132 static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr
*hwmgr
,
2133 SMU72_Discrete_MCRegisters
*mc_regs
)
2136 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2140 for (i
= 0; i
< data
->dpm_table
.mclk_table
.count
; i
++) {
2141 res
= tonga_convert_mc_reg_table_entry_to_smc(
2143 data
->dpm_table
.mclk_table
.dpm_levels
[i
].value
,
2154 static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr
*hwmgr
)
2156 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2157 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2161 if (0 == (data
->need_update_smu7_dpm_table
& DPMTABLE_OD_UPDATE_MCLK
))
2165 memset(&smu_data
->mc_regs
, 0, sizeof(SMU72_Discrete_MCRegisters
));
2167 result
= tonga_convert_mc_reg_table_to_smc(hwmgr
, &(smu_data
->mc_regs
));
2173 address
= smu_data
->smu7_data
.mc_reg_table_start
+
2174 (uint32_t)offsetof(SMU72_Discrete_MCRegisters
, data
[0]);
2176 return smu7_copy_bytes_to_smc(
2178 (uint8_t *)&smu_data
->mc_regs
.data
[0],
2179 sizeof(SMU72_Discrete_MCRegisterSet
) *
2180 data
->dpm_table
.mclk_table
.count
,
2184 static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr
*hwmgr
)
2187 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2189 memset(&smu_data
->mc_regs
, 0x00, sizeof(SMU72_Discrete_MCRegisters
));
2190 result
= tonga_populate_mc_reg_address(hwmgr
, &(smu_data
->mc_regs
));
2191 PP_ASSERT_WITH_CODE(!result
,
2192 "Failed to initialize MCRegTable for the MC register addresses !",
2195 result
= tonga_convert_mc_reg_table_to_smc(hwmgr
, &smu_data
->mc_regs
);
2196 PP_ASSERT_WITH_CODE(!result
,
2197 "Failed to initialize MCRegTable for driver state !",
2200 return smu7_copy_bytes_to_smc(hwmgr
, smu_data
->smu7_data
.mc_reg_table_start
,
2201 (uint8_t *)&smu_data
->mc_regs
, sizeof(SMU72_Discrete_MCRegisters
), SMC_RAM_END
);
2204 static void tonga_initialize_power_tune_defaults(struct pp_hwmgr
*hwmgr
)
2206 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2207 struct phm_ppt_v1_information
*table_info
=
2208 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2211 table_info
->cac_dtp_table
->usPowerTuneDataSetID
<= POWERTUNE_DEFAULT_SET_MAX
&&
2212 table_info
->cac_dtp_table
->usPowerTuneDataSetID
)
2213 smu_data
->power_tune_defaults
=
2214 &tonga_power_tune_data_set_array
2215 [table_info
->cac_dtp_table
->usPowerTuneDataSetID
- 1];
2217 smu_data
->power_tune_defaults
= &tonga_power_tune_data_set_array
[0];
2220 static int tonga_init_smc_table(struct pp_hwmgr
*hwmgr
)
2223 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2224 struct tonga_smumgr
*smu_data
=
2225 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2226 SMU72_Discrete_DpmTable
*table
= &(smu_data
->smc_state_table
);
2227 struct phm_ppt_v1_information
*table_info
=
2228 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2231 pp_atomctrl_gpio_pin_assignment gpio_pin_assignment
;
2234 memset(&(smu_data
->smc_state_table
), 0x00, sizeof(smu_data
->smc_state_table
));
2236 tonga_initialize_power_tune_defaults(hwmgr
);
2238 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->voltage_control
)
2239 tonga_populate_smc_voltage_tables(hwmgr
, table
);
2241 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2242 PHM_PlatformCaps_AutomaticDCTransition
))
2243 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GPIO_DC
;
2246 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2247 PHM_PlatformCaps_StepVddc
))
2248 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_STEPVDDC
;
2250 if (data
->is_memory_gddr5
)
2251 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GDDR5
;
2253 i
= PHM_READ_FIELD(hwmgr
->device
, CC_MC_MAX_CHANNEL
, NOOFCHAN
);
2255 if (i
== 1 || i
== 0)
2256 table
->SystemFlags
|= 0x40;
2258 if (data
->ulv_supported
&& table_info
->us_ulv_voltage_offset
) {
2259 result
= tonga_populate_ulv_state(hwmgr
, table
);
2260 PP_ASSERT_WITH_CODE(!result
,
2261 "Failed to initialize ULV state !",
2264 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
2265 ixCG_ULV_PARAMETER
, 0x40035);
2268 result
= tonga_populate_smc_link_level(hwmgr
, table
);
2269 PP_ASSERT_WITH_CODE(!result
,
2270 "Failed to initialize Link Level !", return result
);
2272 result
= tonga_populate_all_graphic_levels(hwmgr
);
2273 PP_ASSERT_WITH_CODE(!result
,
2274 "Failed to initialize Graphics Level !", return result
);
2276 result
= tonga_populate_all_memory_levels(hwmgr
);
2277 PP_ASSERT_WITH_CODE(!result
,
2278 "Failed to initialize Memory Level !", return result
);
2280 result
= tonga_populate_smc_acpi_level(hwmgr
, table
);
2281 PP_ASSERT_WITH_CODE(!result
,
2282 "Failed to initialize ACPI Level !", return result
);
2284 result
= tonga_populate_smc_vce_level(hwmgr
, table
);
2285 PP_ASSERT_WITH_CODE(!result
,
2286 "Failed to initialize VCE Level !", return result
);
2288 result
= tonga_populate_smc_acp_level(hwmgr
, table
);
2289 PP_ASSERT_WITH_CODE(!result
,
2290 "Failed to initialize ACP Level !", return result
);
2292 /* Since only the initial state is completely set up at this
2293 * point (the other states are just copies of the boot state) we only
2294 * need to populate the ARB settings for the initial state.
2296 result
= tonga_program_memory_timing_parameters(hwmgr
);
2297 PP_ASSERT_WITH_CODE(!result
,
2298 "Failed to Write ARB settings for the initial state.",
2301 result
= tonga_populate_smc_uvd_level(hwmgr
, table
);
2302 PP_ASSERT_WITH_CODE(!result
,
2303 "Failed to initialize UVD Level !", return result
);
2305 result
= tonga_populate_smc_boot_level(hwmgr
, table
);
2306 PP_ASSERT_WITH_CODE(!result
,
2307 "Failed to initialize Boot Level !", return result
);
2309 tonga_populate_bapm_parameters_in_dpm_table(hwmgr
);
2310 PP_ASSERT_WITH_CODE(!result
,
2311 "Failed to populate BAPM Parameters !", return result
);
2313 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2314 PHM_PlatformCaps_ClockStretcher
)) {
2315 result
= tonga_populate_clock_stretcher_data_table(hwmgr
);
2316 PP_ASSERT_WITH_CODE(!result
,
2317 "Failed to populate Clock Stretcher Data Table !",
2320 table
->GraphicsVoltageChangeEnable
= 1;
2321 table
->GraphicsThermThrottleEnable
= 1;
2322 table
->GraphicsInterval
= 1;
2323 table
->VoltageInterval
= 1;
2324 table
->ThermalInterval
= 1;
2325 table
->TemperatureLimitHigh
=
2326 table_info
->cac_dtp_table
->usTargetOperatingTemp
*
2327 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2328 table
->TemperatureLimitLow
=
2329 (table_info
->cac_dtp_table
->usTargetOperatingTemp
- 1) *
2330 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2331 table
->MemoryVoltageChangeEnable
= 1;
2332 table
->MemoryInterval
= 1;
2333 table
->VoltageResponseTime
= 0;
2334 table
->PhaseResponseTime
= 0;
2335 table
->MemoryThermThrottleEnable
= 1;
2338 * Cail reads current link status and reports it as cap (we cannot
2339 * change this due to some previous issues we had)
2340 * SMC drops the link status to lowest level after enabling
2341 * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again
2342 * but this time Cail reads current link status which was set to low by
2343 * SMC and reports it as cap to powerplay
2344 * To avoid it, we set PCIeBootLinkLevel to highest dpm level
2346 PP_ASSERT_WITH_CODE((1 <= data
->dpm_table
.pcie_speed_table
.count
),
2347 "There must be 1 or more PCIE levels defined in PPTable.",
2350 table
->PCIeBootLinkLevel
= (uint8_t) (data
->dpm_table
.pcie_speed_table
.count
);
2352 table
->PCIeGenInterval
= 1;
2354 result
= tonga_populate_vr_config(hwmgr
, table
);
2355 PP_ASSERT_WITH_CODE(!result
,
2356 "Failed to populate VRConfig setting !", return result
);
2357 data
->vr_config
= table
->VRConfig
;
2358 table
->ThermGpio
= 17;
2359 table
->SclkStepSize
= 0x4000;
2361 if (atomctrl_get_pp_assign_pin(hwmgr
, VDDC_VRHOT_GPIO_PINID
,
2362 &gpio_pin_assignment
)) {
2363 table
->VRHotGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2364 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2365 PHM_PlatformCaps_RegulatorHot
);
2367 table
->VRHotGpio
= SMU7_UNUSED_GPIO_PIN
;
2368 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2369 PHM_PlatformCaps_RegulatorHot
);
2372 if (atomctrl_get_pp_assign_pin(hwmgr
, PP_AC_DC_SWITCH_GPIO_PINID
,
2373 &gpio_pin_assignment
)) {
2374 table
->AcDcGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2375 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2376 PHM_PlatformCaps_AutomaticDCTransition
);
2378 table
->AcDcGpio
= SMU7_UNUSED_GPIO_PIN
;
2379 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2380 PHM_PlatformCaps_AutomaticDCTransition
);
2383 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2384 PHM_PlatformCaps_Falcon_QuickTransition
);
2387 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2388 PHM_PlatformCaps_AutomaticDCTransition
);
2389 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2390 PHM_PlatformCaps_Falcon_QuickTransition
);
2393 if (atomctrl_get_pp_assign_pin(hwmgr
,
2394 THERMAL_INT_OUTPUT_GPIO_PINID
, &gpio_pin_assignment
)) {
2395 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2396 PHM_PlatformCaps_ThermalOutGPIO
);
2398 table
->ThermOutGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2400 table
->ThermOutPolarity
=
2401 (0 == (cgs_read_register(hwmgr
->device
, mmGPIOPAD_A
) &
2402 (1 << gpio_pin_assignment
.uc_gpio_pin_bit_shift
))) ? 1 : 0;
2404 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_ONLY
;
2406 /* if required, combine VRHot/PCC with thermal out GPIO*/
2407 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2408 PHM_PlatformCaps_RegulatorHot
) &&
2409 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2410 PHM_PlatformCaps_CombinePCCWithThermalSignal
)){
2411 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_VRHOT
;
2414 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2415 PHM_PlatformCaps_ThermalOutGPIO
);
2417 table
->ThermOutGpio
= 17;
2418 table
->ThermOutPolarity
= 1;
2419 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_DISABLE
;
2422 for (i
= 0; i
< SMU72_MAX_ENTRIES_SMIO
; i
++)
2423 table
->Smio
[i
] = PP_HOST_TO_SMC_UL(table
->Smio
[i
]);
2424 CONVERT_FROM_HOST_TO_SMC_UL(table
->SystemFlags
);
2425 CONVERT_FROM_HOST_TO_SMC_UL(table
->VRConfig
);
2426 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask1
);
2427 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask2
);
2428 CONVERT_FROM_HOST_TO_SMC_UL(table
->SclkStepSize
);
2429 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitHigh
);
2430 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitLow
);
2431 CONVERT_FROM_HOST_TO_SMC_US(table
->VoltageResponseTime
);
2432 CONVERT_FROM_HOST_TO_SMC_US(table
->PhaseResponseTime
);
2434 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2435 result
= smu7_copy_bytes_to_smc(
2437 smu_data
->smu7_data
.dpm_table_start
+ offsetof(SMU72_Discrete_DpmTable
, SystemFlags
),
2438 (uint8_t *)&(table
->SystemFlags
),
2439 sizeof(SMU72_Discrete_DpmTable
) - 3 * sizeof(SMU72_PIDController
),
2442 PP_ASSERT_WITH_CODE(!result
,
2443 "Failed to upload dpm data to SMC memory !", return result
;);
2445 result
= tonga_init_arb_table_index(hwmgr
);
2446 PP_ASSERT_WITH_CODE(!result
,
2447 "Failed to upload arb data to SMC memory !", return result
);
2449 tonga_populate_pm_fuses(hwmgr
);
2450 PP_ASSERT_WITH_CODE((!result
),
2451 "Failed to populate initialize pm fuses !", return result
);
2453 result
= tonga_populate_initial_mc_reg_table(hwmgr
);
2454 PP_ASSERT_WITH_CODE((!result
),
2455 "Failed to populate initialize MC Reg table !", return result
);
2460 static int tonga_thermal_setup_fan_table(struct pp_hwmgr
*hwmgr
)
2462 struct tonga_smumgr
*smu_data
=
2463 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2464 SMU72_Discrete_FanTable fan_table
= { FDO_MODE_HARDWARE
};
2466 uint32_t t_diff1
, t_diff2
, pwm_diff1
, pwm_diff2
;
2467 uint16_t fdo_min
, slope1
, slope2
;
2468 uint32_t reference_clock
;
2472 if (!phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2473 PHM_PlatformCaps_MicrocodeFanControl
))
2476 if (hwmgr
->thermal_controller
.fanInfo
.bNoFan
) {
2477 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2478 PHM_PlatformCaps_MicrocodeFanControl
);
2482 if (0 == smu_data
->smu7_data
.fan_table_start
) {
2483 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2484 PHM_PlatformCaps_MicrocodeFanControl
);
2488 duty100
= PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
,
2490 CG_FDO_CTRL1
, FMAX_DUTY100
);
2493 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2494 PHM_PlatformCaps_MicrocodeFanControl
);
2498 tmp64
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
* duty100
;
2499 do_div(tmp64
, 10000);
2500 fdo_min
= (uint16_t)tmp64
;
2502 t_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
-
2503 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
;
2504 t_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
-
2505 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
;
2507 pwm_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
-
2508 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
;
2509 pwm_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
-
2510 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
;
2512 slope1
= (uint16_t)((50 + ((16 * duty100
* pwm_diff1
) / t_diff1
)) / 100);
2513 slope2
= (uint16_t)((50 + ((16 * duty100
* pwm_diff2
) / t_diff2
)) / 100);
2515 fan_table
.TempMin
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
) / 100);
2516 fan_table
.TempMed
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
) / 100);
2517 fan_table
.TempMax
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
) / 100);
2519 fan_table
.Slope1
= cpu_to_be16(slope1
);
2520 fan_table
.Slope2
= cpu_to_be16(slope2
);
2522 fan_table
.FdoMin
= cpu_to_be16(fdo_min
);
2524 fan_table
.HystDown
= cpu_to_be16(hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
);
2526 fan_table
.HystUp
= cpu_to_be16(1);
2528 fan_table
.HystSlope
= cpu_to_be16(1);
2530 fan_table
.TempRespLim
= cpu_to_be16(5);
2532 reference_clock
= amdgpu_asic_get_xclk((struct amdgpu_device
*)hwmgr
->adev
);
2534 fan_table
.RefreshPeriod
= cpu_to_be32((hwmgr
->thermal_controller
.advanceFanControlParameters
.ulCycleDelay
* reference_clock
) / 1600);
2536 fan_table
.FdoMax
= cpu_to_be16((uint16_t)duty100
);
2538 fan_table
.TempSrc
= (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, CG_MULT_THERMAL_CTRL
, TEMP_SEL
);
2540 fan_table
.FanControl_GL_Flag
= 1;
2542 res
= smu7_copy_bytes_to_smc(hwmgr
,
2543 smu_data
->smu7_data
.fan_table_start
,
2544 (uint8_t *)&fan_table
,
2545 (uint32_t)sizeof(fan_table
),
2552 static int tonga_program_mem_timing_parameters(struct pp_hwmgr
*hwmgr
)
2554 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2556 if (data
->need_update_smu7_dpm_table
&
2557 (DPMTABLE_OD_UPDATE_SCLK
+ DPMTABLE_OD_UPDATE_MCLK
))
2558 return tonga_program_memory_timing_parameters(hwmgr
);
2563 static int tonga_update_sclk_threshold(struct pp_hwmgr
*hwmgr
)
2565 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2566 struct tonga_smumgr
*smu_data
=
2567 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2570 uint32_t low_sclk_interrupt_threshold
= 0;
2572 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2573 PHM_PlatformCaps_SclkThrottleLowNotification
)
2574 && (data
->low_sclk_interrupt_threshold
!= 0)) {
2575 low_sclk_interrupt_threshold
=
2576 data
->low_sclk_interrupt_threshold
;
2578 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold
);
2580 result
= smu7_copy_bytes_to_smc(
2582 smu_data
->smu7_data
.dpm_table_start
+
2583 offsetof(SMU72_Discrete_DpmTable
,
2584 LowSclkInterruptThreshold
),
2585 (uint8_t *)&low_sclk_interrupt_threshold
,
2590 result
= tonga_update_and_upload_mc_reg_table(hwmgr
);
2592 PP_ASSERT_WITH_CODE((!result
),
2593 "Failed to upload MC reg table !",
2596 result
= tonga_program_mem_timing_parameters(hwmgr
);
2597 PP_ASSERT_WITH_CODE((result
== 0),
2598 "Failed to program memory timing parameters !",
2604 static uint32_t tonga_get_offsetof(uint32_t type
, uint32_t member
)
2607 case SMU_SoftRegisters
:
2609 case HandshakeDisables
:
2610 return offsetof(SMU72_SoftRegisters
, HandshakeDisables
);
2611 case VoltageChangeTimeout
:
2612 return offsetof(SMU72_SoftRegisters
, VoltageChangeTimeout
);
2613 case AverageGraphicsActivity
:
2614 return offsetof(SMU72_SoftRegisters
, AverageGraphicsActivity
);
2615 case AverageMemoryActivity
:
2616 return offsetof(SMU72_SoftRegisters
, AverageMemoryActivity
);
2618 return offsetof(SMU72_SoftRegisters
, PreVBlankGap
);
2620 return offsetof(SMU72_SoftRegisters
, VBlankTimeout
);
2621 case UcodeLoadStatus
:
2622 return offsetof(SMU72_SoftRegisters
, UcodeLoadStatus
);
2623 case DRAM_LOG_ADDR_H
:
2624 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_ADDR_H
);
2625 case DRAM_LOG_ADDR_L
:
2626 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_ADDR_L
);
2627 case DRAM_LOG_PHY_ADDR_H
:
2628 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_PHY_ADDR_H
);
2629 case DRAM_LOG_PHY_ADDR_L
:
2630 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_PHY_ADDR_L
);
2631 case DRAM_LOG_BUFF_SIZE
:
2632 return offsetof(SMU72_SoftRegisters
, DRAM_LOG_BUFF_SIZE
);
2635 case SMU_Discrete_DpmTable
:
2638 return offsetof(SMU72_Discrete_DpmTable
, UvdBootLevel
);
2640 return offsetof(SMU72_Discrete_DpmTable
, VceBootLevel
);
2641 case LowSclkInterruptThreshold
:
2642 return offsetof(SMU72_Discrete_DpmTable
, LowSclkInterruptThreshold
);
2646 pr_warn("can't get the offset of type %x member %x\n", type
, member
);
2650 static uint32_t tonga_get_mac_definition(uint32_t value
)
2653 case SMU_MAX_LEVELS_GRAPHICS
:
2654 return SMU72_MAX_LEVELS_GRAPHICS
;
2655 case SMU_MAX_LEVELS_MEMORY
:
2656 return SMU72_MAX_LEVELS_MEMORY
;
2657 case SMU_MAX_LEVELS_LINK
:
2658 return SMU72_MAX_LEVELS_LINK
;
2659 case SMU_MAX_ENTRIES_SMIO
:
2660 return SMU72_MAX_ENTRIES_SMIO
;
2661 case SMU_MAX_LEVELS_VDDC
:
2662 return SMU72_MAX_LEVELS_VDDC
;
2663 case SMU_MAX_LEVELS_VDDGFX
:
2664 return SMU72_MAX_LEVELS_VDDGFX
;
2665 case SMU_MAX_LEVELS_VDDCI
:
2666 return SMU72_MAX_LEVELS_VDDCI
;
2667 case SMU_MAX_LEVELS_MVDD
:
2668 return SMU72_MAX_LEVELS_MVDD
;
2670 pr_warn("can't get the mac value %x\n", value
);
2675 static int tonga_update_uvd_smc_table(struct pp_hwmgr
*hwmgr
)
2677 struct tonga_smumgr
*smu_data
=
2678 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2679 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2680 struct phm_ppt_v1_information
*table_info
=
2681 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2683 smu_data
->smc_state_table
.UvdBootLevel
= 0;
2684 if (table_info
->mm_dep_table
->count
> 0)
2685 smu_data
->smc_state_table
.UvdBootLevel
=
2686 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2687 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2688 offsetof(SMU72_Discrete_DpmTable
, UvdBootLevel
);
2689 mm_boot_level_offset
/= 4;
2690 mm_boot_level_offset
*= 4;
2691 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2692 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2693 mm_boot_level_value
&= 0x00FFFFFF;
2694 mm_boot_level_value
|= smu_data
->smc_state_table
.UvdBootLevel
<< 24;
2695 cgs_write_ind_register(hwmgr
->device
,
2697 mm_boot_level_offset
, mm_boot_level_value
);
2699 if (!phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2700 PHM_PlatformCaps_UVDDPM
) ||
2701 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2702 PHM_PlatformCaps_StablePState
))
2703 smum_send_msg_to_smc_with_parameter(hwmgr
,
2704 PPSMC_MSG_UVDDPM_SetEnabledMask
,
2705 (uint32_t)(1 << smu_data
->smc_state_table
.UvdBootLevel
));
2709 static int tonga_update_vce_smc_table(struct pp_hwmgr
*hwmgr
)
2711 struct tonga_smumgr
*smu_data
=
2712 (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2713 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2714 struct phm_ppt_v1_information
*table_info
=
2715 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2718 smu_data
->smc_state_table
.VceBootLevel
=
2719 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2721 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2722 offsetof(SMU72_Discrete_DpmTable
, VceBootLevel
);
2723 mm_boot_level_offset
/= 4;
2724 mm_boot_level_offset
*= 4;
2725 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2726 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2727 mm_boot_level_value
&= 0xFF00FFFF;
2728 mm_boot_level_value
|= smu_data
->smc_state_table
.VceBootLevel
<< 16;
2729 cgs_write_ind_register(hwmgr
->device
,
2730 CGS_IND_REG__SMC
, mm_boot_level_offset
, mm_boot_level_value
);
2732 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2733 PHM_PlatformCaps_StablePState
))
2734 smum_send_msg_to_smc_with_parameter(hwmgr
,
2735 PPSMC_MSG_VCEDPM_SetEnabledMask
,
2736 (uint32_t)1 << smu_data
->smc_state_table
.VceBootLevel
);
2740 static int tonga_update_smc_table(struct pp_hwmgr
*hwmgr
, uint32_t type
)
2744 tonga_update_uvd_smc_table(hwmgr
);
2747 tonga_update_vce_smc_table(hwmgr
);
2755 static int tonga_process_firmware_header(struct pp_hwmgr
*hwmgr
)
2757 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2758 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
2764 result
= smu7_read_smc_sram_dword(hwmgr
,
2765 SMU72_FIRMWARE_HEADER_LOCATION
+
2766 offsetof(SMU72_Firmware_Header
, DpmTable
),
2770 smu_data
->smu7_data
.dpm_table_start
= tmp
;
2772 error
|= (result
!= 0);
2774 result
= smu7_read_smc_sram_dword(hwmgr
,
2775 SMU72_FIRMWARE_HEADER_LOCATION
+
2776 offsetof(SMU72_Firmware_Header
, SoftRegisters
),
2780 data
->soft_regs_start
= tmp
;
2781 smu_data
->smu7_data
.soft_regs_start
= tmp
;
2784 error
|= (result
!= 0);
2787 result
= smu7_read_smc_sram_dword(hwmgr
,
2788 SMU72_FIRMWARE_HEADER_LOCATION
+
2789 offsetof(SMU72_Firmware_Header
, mcRegisterTable
),
2793 smu_data
->smu7_data
.mc_reg_table_start
= tmp
;
2795 result
= smu7_read_smc_sram_dword(hwmgr
,
2796 SMU72_FIRMWARE_HEADER_LOCATION
+
2797 offsetof(SMU72_Firmware_Header
, FanTable
),
2801 smu_data
->smu7_data
.fan_table_start
= tmp
;
2803 error
|= (result
!= 0);
2805 result
= smu7_read_smc_sram_dword(hwmgr
,
2806 SMU72_FIRMWARE_HEADER_LOCATION
+
2807 offsetof(SMU72_Firmware_Header
, mcArbDramTimingTable
),
2811 smu_data
->smu7_data
.arb_table_start
= tmp
;
2813 error
|= (result
!= 0);
2815 result
= smu7_read_smc_sram_dword(hwmgr
,
2816 SMU72_FIRMWARE_HEADER_LOCATION
+
2817 offsetof(SMU72_Firmware_Header
, Version
),
2821 hwmgr
->microcode_version_info
.SMC
= tmp
;
2823 error
|= (result
!= 0);
2825 return error
? 1 : 0;
2828 /*---------------------------MC----------------------------*/
2830 static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr
*hwmgr
)
2832 return (uint8_t) (0xFF & (cgs_read_register(hwmgr
->device
, mmBIOS_SCRATCH_4
) >> 16));
2835 static bool tonga_check_s0_mc_reg_index(uint16_t in_reg
, uint16_t *out_reg
)
2840 case mmMC_SEQ_RAS_TIMING
:
2841 *out_reg
= mmMC_SEQ_RAS_TIMING_LP
;
2844 case mmMC_SEQ_DLL_STBY
:
2845 *out_reg
= mmMC_SEQ_DLL_STBY_LP
;
2848 case mmMC_SEQ_G5PDX_CMD0
:
2849 *out_reg
= mmMC_SEQ_G5PDX_CMD0_LP
;
2852 case mmMC_SEQ_G5PDX_CMD1
:
2853 *out_reg
= mmMC_SEQ_G5PDX_CMD1_LP
;
2856 case mmMC_SEQ_G5PDX_CTRL
:
2857 *out_reg
= mmMC_SEQ_G5PDX_CTRL_LP
;
2860 case mmMC_SEQ_CAS_TIMING
:
2861 *out_reg
= mmMC_SEQ_CAS_TIMING_LP
;
2864 case mmMC_SEQ_MISC_TIMING
:
2865 *out_reg
= mmMC_SEQ_MISC_TIMING_LP
;
2868 case mmMC_SEQ_MISC_TIMING2
:
2869 *out_reg
= mmMC_SEQ_MISC_TIMING2_LP
;
2872 case mmMC_SEQ_PMG_DVS_CMD
:
2873 *out_reg
= mmMC_SEQ_PMG_DVS_CMD_LP
;
2876 case mmMC_SEQ_PMG_DVS_CTL
:
2877 *out_reg
= mmMC_SEQ_PMG_DVS_CTL_LP
;
2880 case mmMC_SEQ_RD_CTL_D0
:
2881 *out_reg
= mmMC_SEQ_RD_CTL_D0_LP
;
2884 case mmMC_SEQ_RD_CTL_D1
:
2885 *out_reg
= mmMC_SEQ_RD_CTL_D1_LP
;
2888 case mmMC_SEQ_WR_CTL_D0
:
2889 *out_reg
= mmMC_SEQ_WR_CTL_D0_LP
;
2892 case mmMC_SEQ_WR_CTL_D1
:
2893 *out_reg
= mmMC_SEQ_WR_CTL_D1_LP
;
2896 case mmMC_PMG_CMD_EMRS
:
2897 *out_reg
= mmMC_SEQ_PMG_CMD_EMRS_LP
;
2900 case mmMC_PMG_CMD_MRS
:
2901 *out_reg
= mmMC_SEQ_PMG_CMD_MRS_LP
;
2904 case mmMC_PMG_CMD_MRS1
:
2905 *out_reg
= mmMC_SEQ_PMG_CMD_MRS1_LP
;
2908 case mmMC_SEQ_PMG_TIMING
:
2909 *out_reg
= mmMC_SEQ_PMG_TIMING_LP
;
2912 case mmMC_PMG_CMD_MRS2
:
2913 *out_reg
= mmMC_SEQ_PMG_CMD_MRS2_LP
;
2916 case mmMC_SEQ_WR_CTL_2
:
2917 *out_reg
= mmMC_SEQ_WR_CTL_2_LP
;
2928 static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table
*table
)
2933 for (i
= 0; i
< table
->last
; i
++) {
2934 table
->mc_reg_address
[i
].s0
=
2935 tonga_check_s0_mc_reg_index(table
->mc_reg_address
[i
].s1
,
2938 table
->mc_reg_address
[i
].s1
;
2943 static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table
*table
,
2944 struct tonga_mc_reg_table
*ni_table
)
2948 PP_ASSERT_WITH_CODE((table
->last
<= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
2949 "Invalid VramInfo table.", return -EINVAL
);
2950 PP_ASSERT_WITH_CODE((table
->num_entries
<= MAX_AC_TIMING_ENTRIES
),
2951 "Invalid VramInfo table.", return -EINVAL
);
2953 for (i
= 0; i
< table
->last
; i
++)
2954 ni_table
->mc_reg_address
[i
].s1
= table
->mc_reg_address
[i
].s1
;
2956 ni_table
->last
= table
->last
;
2958 for (i
= 0; i
< table
->num_entries
; i
++) {
2959 ni_table
->mc_reg_table_entry
[i
].mclk_max
=
2960 table
->mc_reg_table_entry
[i
].mclk_max
;
2961 for (j
= 0; j
< table
->last
; j
++) {
2962 ni_table
->mc_reg_table_entry
[i
].mc_data
[j
] =
2963 table
->mc_reg_table_entry
[i
].mc_data
[j
];
2967 ni_table
->num_entries
= table
->num_entries
;
2972 static int tonga_set_mc_special_registers(struct pp_hwmgr
*hwmgr
,
2973 struct tonga_mc_reg_table
*table
)
2977 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2979 for (i
= 0, j
= table
->last
; i
< table
->last
; i
++) {
2980 PP_ASSERT_WITH_CODE((j
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
2981 "Invalid VramInfo table.", return -EINVAL
);
2983 switch (table
->mc_reg_address
[i
].s1
) {
2985 case mmMC_SEQ_MISC1
:
2986 temp_reg
= cgs_read_register(hwmgr
->device
,
2988 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_EMRS
;
2989 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_EMRS_LP
;
2990 for (k
= 0; k
< table
->num_entries
; k
++) {
2991 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
2992 ((temp_reg
& 0xffff0000)) |
2993 ((table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0xffff0000) >> 16);
2997 PP_ASSERT_WITH_CODE((j
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
2998 "Invalid VramInfo table.", return -EINVAL
);
2999 temp_reg
= cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS
);
3000 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_MRS
;
3001 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_MRS_LP
;
3002 for (k
= 0; k
< table
->num_entries
; k
++) {
3003 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3004 (temp_reg
& 0xffff0000) |
3005 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0x0000ffff);
3007 if (!data
->is_memory_gddr5
)
3008 table
->mc_reg_table_entry
[k
].mc_data
[j
] |= 0x100;
3012 if (!data
->is_memory_gddr5
) {
3013 PP_ASSERT_WITH_CODE((j
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
3014 "Invalid VramInfo table.", return -EINVAL
);
3015 table
->mc_reg_address
[j
].s1
= mmMC_PMG_AUTO_CMD
;
3016 table
->mc_reg_address
[j
].s0
= mmMC_PMG_AUTO_CMD
;
3017 for (k
= 0; k
< table
->num_entries
; k
++)
3018 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3019 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0xffff0000) >> 16;
3025 case mmMC_SEQ_RESERVE_M
:
3026 temp_reg
= cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS1
);
3027 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_MRS1
;
3028 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_MRS1_LP
;
3029 for (k
= 0; k
< table
->num_entries
; k
++) {
3030 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3031 (temp_reg
& 0xffff0000) |
3032 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0x0000ffff);
3048 static int tonga_set_valid_flag(struct tonga_mc_reg_table
*table
)
3052 for (i
= 0; i
< table
->last
; i
++) {
3053 for (j
= 1; j
< table
->num_entries
; j
++) {
3054 if (table
->mc_reg_table_entry
[j
-1].mc_data
[i
] !=
3055 table
->mc_reg_table_entry
[j
].mc_data
[i
]) {
3056 table
->validflag
|= (1<<i
);
3065 static int tonga_initialize_mc_reg_table(struct pp_hwmgr
*hwmgr
)
3068 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smu_backend
);
3069 pp_atomctrl_mc_reg_table
*table
;
3070 struct tonga_mc_reg_table
*ni_table
= &smu_data
->mc_reg_table
;
3071 uint8_t module_index
= tonga_get_memory_modile_index(hwmgr
);
3073 table
= kzalloc(sizeof(pp_atomctrl_mc_reg_table
), GFP_KERNEL
);
3078 /* Program additional LP registers that are no longer programmed by VBIOS */
3079 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING_LP
,
3080 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING
));
3081 cgs_write_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING_LP
,
3082 cgs_read_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING
));
3083 cgs_write_register(hwmgr
->device
, mmMC_SEQ_DLL_STBY_LP
,
3084 cgs_read_register(hwmgr
->device
, mmMC_SEQ_DLL_STBY
));
3085 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD0_LP
,
3086 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD0
));
3087 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD1_LP
,
3088 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD1
));
3089 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CTRL_LP
,
3090 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CTRL
));
3091 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CMD_LP
,
3092 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CMD
));
3093 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CTL_LP
,
3094 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CTL
));
3095 cgs_write_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING_LP
,
3096 cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING
));
3097 cgs_write_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2_LP
,
3098 cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2
));
3099 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_EMRS_LP
,
3100 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_EMRS
));
3101 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS_LP
,
3102 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS
));
3103 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS1_LP
,
3104 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS1
));
3105 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D0_LP
,
3106 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D0
));
3107 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1_LP
,
3108 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1
));
3109 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0_LP
,
3110 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0
));
3111 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1_LP
,
3112 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1
));
3113 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING_LP
,
3114 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING
));
3115 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS2_LP
,
3116 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS2
));
3117 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_2_LP
,
3118 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_2
));
3120 result
= atomctrl_initialize_mc_reg_table(hwmgr
, module_index
, table
);
3123 result
= tonga_copy_vbios_smc_reg_table(table
, ni_table
);
3126 tonga_set_s0_mc_reg_index(ni_table
);
3127 result
= tonga_set_mc_special_registers(hwmgr
, ni_table
);
3131 tonga_set_valid_flag(ni_table
);
3138 static bool tonga_is_dpm_running(struct pp_hwmgr
*hwmgr
)
3140 return (1 == PHM_READ_INDIRECT_FIELD(hwmgr
->device
,
3141 CGS_IND_REG__SMC
, FEATURE_STATUS
, VOLTAGE_CONTROLLER_ON
))
3145 static int tonga_update_dpm_settings(struct pp_hwmgr
*hwmgr
,
3146 void *profile_setting
)
3148 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
3149 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)
3150 (hwmgr
->smu_backend
);
3151 struct profile_mode_setting
*setting
;
3152 struct SMU72_Discrete_GraphicsLevel
*levels
=
3153 smu_data
->smc_state_table
.GraphicsLevel
;
3154 uint32_t array
= smu_data
->smu7_data
.dpm_table_start
+
3155 offsetof(SMU72_Discrete_DpmTable
, GraphicsLevel
);
3157 uint32_t mclk_array
= smu_data
->smu7_data
.dpm_table_start
+
3158 offsetof(SMU72_Discrete_DpmTable
, MemoryLevel
);
3159 struct SMU72_Discrete_MemoryLevel
*mclk_levels
=
3160 smu_data
->smc_state_table
.MemoryLevel
;
3162 uint32_t offset
, up_hyst_offset
, down_hyst_offset
, clk_activity_offset
, tmp
;
3164 if (profile_setting
== NULL
)
3167 setting
= (struct profile_mode_setting
*)profile_setting
;
3169 if (setting
->bupdate_sclk
) {
3170 if (!data
->sclk_dpm_key_disabled
)
3171 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_SCLKDPM_FreezeLevel
);
3172 for (i
= 0; i
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; i
++) {
3173 if (levels
[i
].ActivityLevel
!=
3174 cpu_to_be16(setting
->sclk_activity
)) {
3175 levels
[i
].ActivityLevel
= cpu_to_be16(setting
->sclk_activity
);
3177 clk_activity_offset
= array
+ (sizeof(SMU72_Discrete_GraphicsLevel
) * i
)
3178 + offsetof(SMU72_Discrete_GraphicsLevel
, ActivityLevel
);
3179 offset
= clk_activity_offset
& ~0x3;
3180 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
3181 tmp
= phm_set_field_to_u32(clk_activity_offset
, tmp
, levels
[i
].ActivityLevel
, sizeof(uint16_t));
3182 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
3185 if (levels
[i
].UpHyst
!= setting
->sclk_up_hyst
||
3186 levels
[i
].DownHyst
!= setting
->sclk_down_hyst
) {
3187 levels
[i
].UpHyst
= setting
->sclk_up_hyst
;
3188 levels
[i
].DownHyst
= setting
->sclk_down_hyst
;
3189 up_hyst_offset
= array
+ (sizeof(SMU72_Discrete_GraphicsLevel
) * i
)
3190 + offsetof(SMU72_Discrete_GraphicsLevel
, UpHyst
);
3191 down_hyst_offset
= array
+ (sizeof(SMU72_Discrete_GraphicsLevel
) * i
)
3192 + offsetof(SMU72_Discrete_GraphicsLevel
, DownHyst
);
3193 offset
= up_hyst_offset
& ~0x3;
3194 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
3195 tmp
= phm_set_field_to_u32(up_hyst_offset
, tmp
, levels
[i
].UpHyst
, sizeof(uint8_t));
3196 tmp
= phm_set_field_to_u32(down_hyst_offset
, tmp
, levels
[i
].DownHyst
, sizeof(uint8_t));
3197 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
3200 if (!data
->sclk_dpm_key_disabled
)
3201 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_SCLKDPM_UnfreezeLevel
);
3204 if (setting
->bupdate_mclk
) {
3205 if (!data
->mclk_dpm_key_disabled
)
3206 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_MCLKDPM_FreezeLevel
);
3207 for (i
= 0; i
< smu_data
->smc_state_table
.MemoryDpmLevelCount
; i
++) {
3208 if (mclk_levels
[i
].ActivityLevel
!=
3209 cpu_to_be16(setting
->mclk_activity
)) {
3210 mclk_levels
[i
].ActivityLevel
= cpu_to_be16(setting
->mclk_activity
);
3212 clk_activity_offset
= mclk_array
+ (sizeof(SMU72_Discrete_MemoryLevel
) * i
)
3213 + offsetof(SMU72_Discrete_MemoryLevel
, ActivityLevel
);
3214 offset
= clk_activity_offset
& ~0x3;
3215 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
3216 tmp
= phm_set_field_to_u32(clk_activity_offset
, tmp
, mclk_levels
[i
].ActivityLevel
, sizeof(uint16_t));
3217 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
3220 if (mclk_levels
[i
].UpHyst
!= setting
->mclk_up_hyst
||
3221 mclk_levels
[i
].DownHyst
!= setting
->mclk_down_hyst
) {
3222 mclk_levels
[i
].UpHyst
= setting
->mclk_up_hyst
;
3223 mclk_levels
[i
].DownHyst
= setting
->mclk_down_hyst
;
3224 up_hyst_offset
= mclk_array
+ (sizeof(SMU72_Discrete_MemoryLevel
) * i
)
3225 + offsetof(SMU72_Discrete_MemoryLevel
, UpHyst
);
3226 down_hyst_offset
= mclk_array
+ (sizeof(SMU72_Discrete_MemoryLevel
) * i
)
3227 + offsetof(SMU72_Discrete_MemoryLevel
, DownHyst
);
3228 offset
= up_hyst_offset
& ~0x3;
3229 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
3230 tmp
= phm_set_field_to_u32(up_hyst_offset
, tmp
, mclk_levels
[i
].UpHyst
, sizeof(uint8_t));
3231 tmp
= phm_set_field_to_u32(down_hyst_offset
, tmp
, mclk_levels
[i
].DownHyst
, sizeof(uint8_t));
3232 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
3235 if (!data
->mclk_dpm_key_disabled
)
3236 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_MCLKDPM_UnfreezeLevel
);
3241 const struct pp_smumgr_func tonga_smu_funcs
= {
3242 .name
= "tonga_smu",
3243 .smu_init
= &tonga_smu_init
,
3244 .smu_fini
= &smu7_smu_fini
,
3245 .start_smu
= &tonga_start_smu
,
3246 .check_fw_load_finish
= &smu7_check_fw_load_finish
,
3247 .request_smu_load_fw
= &smu7_request_smu_load_fw
,
3248 .request_smu_load_specific_fw
= NULL
,
3249 .send_msg_to_smc
= &smu7_send_msg_to_smc
,
3250 .send_msg_to_smc_with_parameter
= &smu7_send_msg_to_smc_with_parameter
,
3251 .download_pptable_settings
= NULL
,
3252 .upload_pptable_settings
= NULL
,
3253 .update_smc_table
= tonga_update_smc_table
,
3254 .get_offsetof
= tonga_get_offsetof
,
3255 .process_firmware_header
= tonga_process_firmware_header
,
3256 .init_smc_table
= tonga_init_smc_table
,
3257 .update_sclk_threshold
= tonga_update_sclk_threshold
,
3258 .thermal_setup_fan_table
= tonga_thermal_setup_fan_table
,
3259 .populate_all_graphic_levels
= tonga_populate_all_graphic_levels
,
3260 .populate_all_memory_levels
= tonga_populate_all_memory_levels
,
3261 .get_mac_definition
= tonga_get_mac_definition
,
3262 .initialize_mc_reg_table
= tonga_initialize_mc_reg_table
,
3263 .is_dpm_running
= tonga_is_dpm_running
,
3264 .update_dpm_settings
= tonga_update_dpm_settings
,