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.
26 #include "smu7_dyn_defaults.h"
28 #include "smu_ucode_xfer_vi.h"
29 #include "fiji_smumgr.h"
30 #include "fiji_ppsmc.h"
31 #include "smu73_discrete.h"
32 #include "ppatomctrl.h"
33 #include "smu/smu_7_1_3_d.h"
34 #include "smu/smu_7_1_3_sh_mask.h"
35 #include "gmc/gmc_8_1_d.h"
36 #include "gmc/gmc_8_1_sh_mask.h"
37 #include "oss/oss_3_0_d.h"
38 #include "gca/gfx_8_0_d.h"
39 #include "bif/bif_5_0_d.h"
40 #include "bif/bif_5_0_sh_mask.h"
41 #include "dce/dce_10_0_d.h"
42 #include "dce/dce_10_0_sh_mask.h"
43 #include "hardwaremanager.h"
44 #include "cgs_common.h"
46 #include "pppcielanes.h"
48 #include "smu7_hwmgr.h"
51 #define AVFS_EN_MSB 1568
52 #define AVFS_EN_LSB 1568
54 #define FIJI_SMC_SIZE 0x20000
56 #define POWERTUNE_DEFAULT_SET_MAX 1
57 #define VDDC_VDDCI_DELTA 300
58 #define MC_CG_ARB_FREQ_F1 0x0b
60 /* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs
61 * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ]
63 static const uint16_t fiji_clock_stretcher_lookup_table
[2][4] = {
64 {600, 1050, 3, 0}, {600, 1050, 6, 1} };
66 /* [FF, SS] type, [] 4 voltage ranges, and
67 * [Floor Freq, Boundary Freq, VID min , VID max]
69 static const uint32_t fiji_clock_stretcher_ddt_table
[2][4][4] = {
70 { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
71 { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
73 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%]
74 * (coming from PWR_CKS_CNTL.stretch_amount reg spec)
76 static const uint8_t fiji_clock_stretch_amount_conversion
[2][6] = {
77 {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} };
79 static const struct fiji_pt_defaults fiji_power_tune_data_set_array
[POWERTUNE_DEFAULT_SET_MAX
] = {
80 /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */
82 /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */
86 static const struct SMU73_Discrete_GraphicsLevel avfs_graphics_level
[8] = {
87 /* Min Sclk pcie DeepSleep Activity CgSpll CgSpll spllSpread SpllSpread CcPwr CcPwr Sclk Display Enabled Enabled Voltage Power */
88 /* Voltage, Frequency, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, Spectrum, Spectrum2, DynRm, DynRm1 Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */
89 { 0x3c0fd047, 0x30750000, 0x00, 0x03, 0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
90 { 0xa00fd047, 0x409c0000, 0x01, 0x04, 0x1e00, 0x00800510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
91 { 0x0410d047, 0x50c30000, 0x01, 0x00, 0x1e00, 0x00600410, 0x87020000, 0x21680000, 0x0d000000, 0, 0, 0x0e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
92 { 0x6810d047, 0x60ea0000, 0x01, 0x00, 0x1e00, 0x00800410, 0x87020000, 0x21680000, 0x0e000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
93 { 0xcc10d047, 0xe8fd0000, 0x01, 0x00, 0x1e00, 0x00e00410, 0x87020000, 0x21680000, 0x0f000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
94 { 0x3011d047, 0x70110100, 0x01, 0x00, 0x1e00, 0x00400510, 0x87020000, 0x21680000, 0x10000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
95 { 0x9411d047, 0xf8240100, 0x01, 0x00, 0x1e00, 0x00a00510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
96 { 0xf811d047, 0x80380100, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000, 0, 0, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }
99 static int fiji_start_smu_in_protection_mode(struct pp_hwmgr
*hwmgr
)
103 /* Wait for smc boot up */
104 /* PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND,
105 RCU_UC_EVENTS, boot_seq_done, 0); */
107 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
108 SMC_SYSCON_RESET_CNTL
, rst_reg
, 1);
110 result
= smu7_upload_smu_firmware_image(hwmgr
);
115 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
118 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
119 SMC_SYSCON_CLOCK_CNTL_0
, ck_disable
, 0);
121 /* De-assert reset */
122 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
123 SMC_SYSCON_RESET_CNTL
, rst_reg
, 0);
125 /* Wait for ROM firmware to initialize interrupt hendler */
126 /*SMUM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, SMC_IND,
127 SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */
129 /* Set SMU Auto Start */
130 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
131 SMU_INPUT_DATA
, AUTO_START
, 1);
133 /* Clear firmware interrupt enable flag */
134 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
135 ixFIRMWARE_FLAGS
, 0);
137 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
, RCU_UC_EVENTS
,
138 INTERRUPTS_ENABLED
, 1);
140 cgs_write_register(hwmgr
->device
, mmSMC_MSG_ARG_0
, 0x20000);
141 cgs_write_register(hwmgr
->device
, mmSMC_MESSAGE_0
, PPSMC_MSG_Test
);
142 PHM_WAIT_FIELD_UNEQUAL(hwmgr
, SMC_RESP_0
, SMC_RESP
, 0);
144 /* Wait for done bit to be set */
145 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr
, SMC_IND
,
146 SMU_STATUS
, SMU_DONE
, 0);
148 /* Check pass/failed indicator */
149 if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
150 SMU_STATUS
, SMU_PASS
) != 1) {
151 PP_ASSERT_WITH_CODE(false,
152 "SMU Firmware start failed!", return -1);
155 /* Wait for firmware to initialize */
156 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
,
157 FIRMWARE_FLAGS
, INTERRUPTS_ENABLED
, 1);
162 static int fiji_start_smu_in_non_protection_mode(struct pp_hwmgr
*hwmgr
)
166 /* wait for smc boot up */
167 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr
, SMC_IND
,
168 RCU_UC_EVENTS
, boot_seq_done
, 0);
170 /* Clear firmware interrupt enable flag */
171 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
172 ixFIRMWARE_FLAGS
, 0);
175 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
176 SMC_SYSCON_RESET_CNTL
, rst_reg
, 1);
178 result
= smu7_upload_smu_firmware_image(hwmgr
);
182 /* Set smc instruct start point at 0x0 */
183 smu7_program_jump_on_start(hwmgr
);
186 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
187 SMC_SYSCON_CLOCK_CNTL_0
, ck_disable
, 0);
189 /* De-assert reset */
190 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
191 SMC_SYSCON_RESET_CNTL
, rst_reg
, 0);
193 /* Wait for firmware to initialize */
194 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr
, SMC_IND
,
195 FIRMWARE_FLAGS
, INTERRUPTS_ENABLED
, 1);
200 static int fiji_start_avfs_btc(struct pp_hwmgr
*hwmgr
)
203 struct smu7_smumgr
*smu_data
= (struct smu7_smumgr
*)(hwmgr
->smu_backend
);
205 if (0 != smu_data
->avfs_btc_param
) {
206 if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr
,
207 PPSMC_MSG_PerformBtc
, smu_data
->avfs_btc_param
)) {
208 pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed");
212 /* Soft-Reset to reset the engine before loading uCode */
214 cgs_write_register(hwmgr
->device
, mmCP_MEC_CNTL
, 0x50000000);
215 /* reset everything */
216 cgs_write_register(hwmgr
->device
, mmGRBM_SOFT_RESET
, 0xffffffff);
218 cgs_write_register(hwmgr
->device
, mmGRBM_SOFT_RESET
, 0);
223 static int fiji_setup_graphics_level_structure(struct pp_hwmgr
*hwmgr
)
226 uint32_t table_start
;
227 uint32_t level_addr
, vr_config_addr
;
228 uint32_t level_size
= sizeof(avfs_graphics_level
);
230 PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr
,
231 SMU7_FIRMWARE_HEADER_LOCATION
+
232 offsetof(SMU73_Firmware_Header
, DpmTable
),
233 &table_start
, 0x40000),
234 "[AVFS][Fiji_SetupGfxLvlStruct] SMU could not "
235 "communicate starting address of DPM table",
238 /* Default value for vr_config =
239 * VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */
240 vr_config
= 0x01000500; /* Real value:0x50001 */
242 vr_config_addr
= table_start
+
243 offsetof(SMU73_Discrete_DpmTable
, VRConfig
);
245 PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr
, vr_config_addr
,
246 (uint8_t *)&vr_config
, sizeof(int32_t), 0x40000),
247 "[AVFS][Fiji_SetupGfxLvlStruct] Problems copying "
248 "vr_config value over to SMC",
251 level_addr
= table_start
+ offsetof(SMU73_Discrete_DpmTable
, GraphicsLevel
);
253 PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr
, level_addr
,
254 (uint8_t *)(&avfs_graphics_level
), level_size
, 0x40000),
255 "[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!",
261 static int fiji_avfs_event_mgr(struct pp_hwmgr
*hwmgr
)
263 if (!hwmgr
->avfs_supported
)
266 PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr
),
267 "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level"
268 " table over to SMU",
270 PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr
),
271 "[AVFS][fiji_avfs_event_mgr] Could not setup "
272 "Pwr Virus for AVFS ",
274 PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr
),
275 "[AVFS][fiji_avfs_event_mgr] Failure at "
276 "fiji_start_avfs_btc. AVFS Disabled",
282 static int fiji_start_smu(struct pp_hwmgr
*hwmgr
)
285 struct fiji_smumgr
*priv
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
287 /* Only start SMC if SMC RAM is not running */
288 if (!smu7_is_smc_ram_running(hwmgr
) && hwmgr
->not_vf
) {
289 /* Check if SMU is running in protected mode */
290 if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
,
292 SMU_FIRMWARE
, SMU_MODE
)) {
293 result
= fiji_start_smu_in_non_protection_mode(hwmgr
);
297 result
= fiji_start_smu_in_protection_mode(hwmgr
);
301 if (fiji_avfs_event_mgr(hwmgr
))
302 hwmgr
->avfs_supported
= false;
305 /* Setup SoftRegsStart here for register lookup in case
306 * DummyBackEnd is used and ProcessFirmwareHeader is not executed
308 smu7_read_smc_sram_dword(hwmgr
,
309 SMU7_FIRMWARE_HEADER_LOCATION
+
310 offsetof(SMU73_Firmware_Header
, SoftRegisters
),
311 &(priv
->smu7_data
.soft_regs_start
), 0x40000);
313 result
= smu7_request_smu_load_fw(hwmgr
);
318 static bool fiji_is_hw_avfs_present(struct pp_hwmgr
*hwmgr
)
322 uint32_t mask
= (1 << ((AVFS_EN_MSB
- AVFS_EN_LSB
) + 1)) - 1;
327 if (!atomctrl_read_efuse(hwmgr
, AVFS_EN_LSB
, AVFS_EN_MSB
,
335 static int fiji_smu_init(struct pp_hwmgr
*hwmgr
)
337 struct fiji_smumgr
*fiji_priv
= NULL
;
339 fiji_priv
= kzalloc(sizeof(struct fiji_smumgr
), GFP_KERNEL
);
341 if (fiji_priv
== NULL
)
344 hwmgr
->smu_backend
= fiji_priv
;
346 if (smu7_init(hwmgr
)) {
354 static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr
*hwmgr
,
355 struct phm_ppt_v1_clock_voltage_dependency_table
*dep_table
,
356 uint32_t clock
, uint32_t *voltage
, uint32_t *mvdd
)
360 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
361 *voltage
= *mvdd
= 0;
364 /* clock - voltage dependency table is empty table */
365 if (dep_table
->count
== 0)
368 for (i
= 0; i
< dep_table
->count
; i
++) {
369 /* find first sclk bigger than request */
370 if (dep_table
->entries
[i
].clk
>= clock
) {
371 *voltage
|= (dep_table
->entries
[i
].vddc
*
372 VOLTAGE_SCALE
) << VDDC_SHIFT
;
373 if (SMU7_VOLTAGE_CONTROL_NONE
== data
->vddci_control
)
374 *voltage
|= (data
->vbios_boot_state
.vddci_bootup_value
*
375 VOLTAGE_SCALE
) << VDDCI_SHIFT
;
376 else if (dep_table
->entries
[i
].vddci
)
377 *voltage
|= (dep_table
->entries
[i
].vddci
*
378 VOLTAGE_SCALE
) << VDDCI_SHIFT
;
380 vddci
= phm_find_closest_vddci(&(data
->vddci_voltage_table
),
381 (dep_table
->entries
[i
].vddc
-
383 *voltage
|= (vddci
* VOLTAGE_SCALE
) << VDDCI_SHIFT
;
386 if (SMU7_VOLTAGE_CONTROL_NONE
== data
->mvdd_control
)
387 *mvdd
= data
->vbios_boot_state
.mvdd_bootup_value
*
389 else if (dep_table
->entries
[i
].mvdd
)
390 *mvdd
= (uint32_t) dep_table
->entries
[i
].mvdd
*
393 *voltage
|= 1 << PHASES_SHIFT
;
398 /* sclk is bigger than max sclk in the dependence table */
399 *voltage
|= (dep_table
->entries
[i
- 1].vddc
* VOLTAGE_SCALE
) << VDDC_SHIFT
;
401 if (SMU7_VOLTAGE_CONTROL_NONE
== data
->vddci_control
)
402 *voltage
|= (data
->vbios_boot_state
.vddci_bootup_value
*
403 VOLTAGE_SCALE
) << VDDCI_SHIFT
;
404 else if (dep_table
->entries
[i
-1].vddci
) {
405 vddci
= phm_find_closest_vddci(&(data
->vddci_voltage_table
),
406 (dep_table
->entries
[i
].vddc
-
408 *voltage
|= (vddci
* VOLTAGE_SCALE
) << VDDCI_SHIFT
;
411 if (SMU7_VOLTAGE_CONTROL_NONE
== data
->mvdd_control
)
412 *mvdd
= data
->vbios_boot_state
.mvdd_bootup_value
* VOLTAGE_SCALE
;
413 else if (dep_table
->entries
[i
].mvdd
)
414 *mvdd
= (uint32_t) dep_table
->entries
[i
- 1].mvdd
* VOLTAGE_SCALE
;
420 static uint16_t scale_fan_gain_settings(uint16_t raw_setting
)
423 tmp
= raw_setting
* 4096 / 100;
424 return (uint16_t)tmp
;
427 static void get_scl_sda_value(uint8_t line
, uint8_t *scl
, uint8_t *sda
)
430 case SMU7_I2CLineID_DDC1
:
431 *scl
= SMU7_I2C_DDC1CLK
;
432 *sda
= SMU7_I2C_DDC1DATA
;
434 case SMU7_I2CLineID_DDC2
:
435 *scl
= SMU7_I2C_DDC2CLK
;
436 *sda
= SMU7_I2C_DDC2DATA
;
438 case SMU7_I2CLineID_DDC3
:
439 *scl
= SMU7_I2C_DDC3CLK
;
440 *sda
= SMU7_I2C_DDC3DATA
;
442 case SMU7_I2CLineID_DDC4
:
443 *scl
= SMU7_I2C_DDC4CLK
;
444 *sda
= SMU7_I2C_DDC4DATA
;
446 case SMU7_I2CLineID_DDC5
:
447 *scl
= SMU7_I2C_DDC5CLK
;
448 *sda
= SMU7_I2C_DDC5DATA
;
450 case SMU7_I2CLineID_DDC6
:
451 *scl
= SMU7_I2C_DDC6CLK
;
452 *sda
= SMU7_I2C_DDC6DATA
;
454 case SMU7_I2CLineID_SCLSDA
:
458 case SMU7_I2CLineID_DDCVGA
:
459 *scl
= SMU7_I2C_DDCVGACLK
;
460 *sda
= SMU7_I2C_DDCVGADATA
;
469 static void fiji_initialize_power_tune_defaults(struct pp_hwmgr
*hwmgr
)
471 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
472 struct phm_ppt_v1_information
*table_info
=
473 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
476 table_info
->cac_dtp_table
->usPowerTuneDataSetID
<= POWERTUNE_DEFAULT_SET_MAX
&&
477 table_info
->cac_dtp_table
->usPowerTuneDataSetID
)
478 smu_data
->power_tune_defaults
=
479 &fiji_power_tune_data_set_array
480 [table_info
->cac_dtp_table
->usPowerTuneDataSetID
- 1];
482 smu_data
->power_tune_defaults
= &fiji_power_tune_data_set_array
[0];
486 static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr
*hwmgr
)
489 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
490 const struct fiji_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
492 SMU73_Discrete_DpmTable
*dpm_table
= &(smu_data
->smc_state_table
);
494 struct phm_ppt_v1_information
*table_info
=
495 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
496 struct phm_cac_tdp_table
*cac_dtp_table
= table_info
->cac_dtp_table
;
497 struct pp_advance_fan_control_parameters
*fan_table
=
498 &hwmgr
->thermal_controller
.advanceFanControlParameters
;
499 uint8_t uc_scl
, uc_sda
;
501 /* TDP number of fraction bits are changed from 8 to 7 for Fiji
502 * as requested by SMC team
504 dpm_table
->DefaultTdp
= PP_HOST_TO_SMC_US(
505 (uint16_t)(cac_dtp_table
->usTDP
* 128));
506 dpm_table
->TargetTdp
= PP_HOST_TO_SMC_US(
507 (uint16_t)(cac_dtp_table
->usTDP
* 128));
509 PP_ASSERT_WITH_CODE(cac_dtp_table
->usTargetOperatingTemp
<= 255,
510 "Target Operating Temp is out of Range!",
513 dpm_table
->GpuTjMax
= (uint8_t)(cac_dtp_table
->usTargetOperatingTemp
);
514 dpm_table
->GpuTjHyst
= 8;
516 dpm_table
->DTEAmbientTempBase
= defaults
->DTEAmbientTempBase
;
518 /* The following are for new Fiji Multi-input fan/thermal control */
519 dpm_table
->TemperatureLimitEdge
= PP_HOST_TO_SMC_US(
520 cac_dtp_table
->usTargetOperatingTemp
* 256);
521 dpm_table
->TemperatureLimitHotspot
= PP_HOST_TO_SMC_US(
522 cac_dtp_table
->usTemperatureLimitHotspot
* 256);
523 dpm_table
->TemperatureLimitLiquid1
= PP_HOST_TO_SMC_US(
524 cac_dtp_table
->usTemperatureLimitLiquid1
* 256);
525 dpm_table
->TemperatureLimitLiquid2
= PP_HOST_TO_SMC_US(
526 cac_dtp_table
->usTemperatureLimitLiquid2
* 256);
527 dpm_table
->TemperatureLimitVrVddc
= PP_HOST_TO_SMC_US(
528 cac_dtp_table
->usTemperatureLimitVrVddc
* 256);
529 dpm_table
->TemperatureLimitVrMvdd
= PP_HOST_TO_SMC_US(
530 cac_dtp_table
->usTemperatureLimitVrMvdd
* 256);
531 dpm_table
->TemperatureLimitPlx
= PP_HOST_TO_SMC_US(
532 cac_dtp_table
->usTemperatureLimitPlx
* 256);
534 dpm_table
->FanGainEdge
= PP_HOST_TO_SMC_US(
535 scale_fan_gain_settings(fan_table
->usFanGainEdge
));
536 dpm_table
->FanGainHotspot
= PP_HOST_TO_SMC_US(
537 scale_fan_gain_settings(fan_table
->usFanGainHotspot
));
538 dpm_table
->FanGainLiquid
= PP_HOST_TO_SMC_US(
539 scale_fan_gain_settings(fan_table
->usFanGainLiquid
));
540 dpm_table
->FanGainVrVddc
= PP_HOST_TO_SMC_US(
541 scale_fan_gain_settings(fan_table
->usFanGainVrVddc
));
542 dpm_table
->FanGainVrMvdd
= PP_HOST_TO_SMC_US(
543 scale_fan_gain_settings(fan_table
->usFanGainVrMvdd
));
544 dpm_table
->FanGainPlx
= PP_HOST_TO_SMC_US(
545 scale_fan_gain_settings(fan_table
->usFanGainPlx
));
546 dpm_table
->FanGainHbm
= PP_HOST_TO_SMC_US(
547 scale_fan_gain_settings(fan_table
->usFanGainHbm
));
549 dpm_table
->Liquid1_I2C_address
= cac_dtp_table
->ucLiquid1_I2C_address
;
550 dpm_table
->Liquid2_I2C_address
= cac_dtp_table
->ucLiquid2_I2C_address
;
551 dpm_table
->Vr_I2C_address
= cac_dtp_table
->ucVr_I2C_address
;
552 dpm_table
->Plx_I2C_address
= cac_dtp_table
->ucPlx_I2C_address
;
554 get_scl_sda_value(cac_dtp_table
->ucLiquid_I2C_Line
, &uc_scl
, &uc_sda
);
555 dpm_table
->Liquid_I2C_LineSCL
= uc_scl
;
556 dpm_table
->Liquid_I2C_LineSDA
= uc_sda
;
558 get_scl_sda_value(cac_dtp_table
->ucVr_I2C_Line
, &uc_scl
, &uc_sda
);
559 dpm_table
->Vr_I2C_LineSCL
= uc_scl
;
560 dpm_table
->Vr_I2C_LineSDA
= uc_sda
;
562 get_scl_sda_value(cac_dtp_table
->ucPlx_I2C_Line
, &uc_scl
, &uc_sda
);
563 dpm_table
->Plx_I2C_LineSCL
= uc_scl
;
564 dpm_table
->Plx_I2C_LineSDA
= uc_sda
;
570 static int fiji_populate_svi_load_line(struct pp_hwmgr
*hwmgr
)
572 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
573 const struct fiji_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
575 smu_data
->power_tune_table
.SviLoadLineEn
= defaults
->SviLoadLineEn
;
576 smu_data
->power_tune_table
.SviLoadLineVddC
= defaults
->SviLoadLineVddC
;
577 smu_data
->power_tune_table
.SviLoadLineTrimVddC
= 3;
578 smu_data
->power_tune_table
.SviLoadLineOffsetVddC
= 0;
584 static int fiji_populate_tdc_limit(struct pp_hwmgr
*hwmgr
)
587 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
588 struct phm_ppt_v1_information
*table_info
=
589 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
590 const struct fiji_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
592 /* TDC number of fraction bits are changed from 8 to 7
593 * for Fiji as requested by SMC team
595 tdc_limit
= (uint16_t)(table_info
->cac_dtp_table
->usTDC
* 128);
596 smu_data
->power_tune_table
.TDC_VDDC_PkgLimit
=
597 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit
);
598 smu_data
->power_tune_table
.TDC_VDDC_ThrottleReleaseLimitPerc
=
599 defaults
->TDC_VDDC_ThrottleReleaseLimitPerc
;
600 smu_data
->power_tune_table
.TDC_MAWt
= defaults
->TDC_MAWt
;
605 static int fiji_populate_dw8(struct pp_hwmgr
*hwmgr
, uint32_t fuse_table_offset
)
607 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
608 const struct fiji_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
611 if (smu7_read_smc_sram_dword(hwmgr
,
613 offsetof(SMU73_Discrete_PmFuses
, TdcWaterfallCtl
),
614 (uint32_t *)&temp
, SMC_RAM_END
))
615 PP_ASSERT_WITH_CODE(false,
616 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
619 smu_data
->power_tune_table
.TdcWaterfallCtl
= defaults
->TdcWaterfallCtl
;
620 smu_data
->power_tune_table
.LPMLTemperatureMin
=
621 (uint8_t)((temp
>> 16) & 0xff);
622 smu_data
->power_tune_table
.LPMLTemperatureMax
=
623 (uint8_t)((temp
>> 8) & 0xff);
624 smu_data
->power_tune_table
.Reserved
= (uint8_t)(temp
& 0xff);
629 static int fiji_populate_temperature_scaler(struct pp_hwmgr
*hwmgr
)
632 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
634 /* Currently not used. Set all to zero. */
635 for (i
= 0; i
< 16; i
++)
636 smu_data
->power_tune_table
.LPMLTemperatureScaler
[i
] = 0;
641 static int fiji_populate_fuzzy_fan(struct pp_hwmgr
*hwmgr
)
643 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
645 if ((hwmgr
->thermal_controller
.advanceFanControlParameters
.
646 usFanOutputSensitivity
& (1 << 15)) ||
647 0 == hwmgr
->thermal_controller
.advanceFanControlParameters
.
648 usFanOutputSensitivity
)
649 hwmgr
->thermal_controller
.advanceFanControlParameters
.
650 usFanOutputSensitivity
= hwmgr
->thermal_controller
.
651 advanceFanControlParameters
.usDefaultFanOutputSensitivity
;
653 smu_data
->power_tune_table
.FuzzyFan_PwmSetDelta
=
654 PP_HOST_TO_SMC_US(hwmgr
->thermal_controller
.
655 advanceFanControlParameters
.usFanOutputSensitivity
);
659 static int fiji_populate_gnb_lpml(struct pp_hwmgr
*hwmgr
)
662 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
664 /* Currently not used. Set all to zero. */
665 for (i
= 0; i
< 16; i
++)
666 smu_data
->power_tune_table
.GnbLPML
[i
] = 0;
671 static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr
*hwmgr
)
673 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
674 struct phm_ppt_v1_information
*table_info
=
675 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
676 uint16_t HiSidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
;
677 uint16_t LoSidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
;
678 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
680 HiSidd
= (uint16_t)(cac_table
->usHighCACLeakage
/ 100 * 256);
681 LoSidd
= (uint16_t)(cac_table
->usLowCACLeakage
/ 100 * 256);
683 smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
=
684 CONVERT_FROM_HOST_TO_SMC_US(HiSidd
);
685 smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
=
686 CONVERT_FROM_HOST_TO_SMC_US(LoSidd
);
691 static int fiji_populate_pm_fuses(struct pp_hwmgr
*hwmgr
)
693 uint32_t pm_fuse_table_offset
;
694 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
696 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
697 PHM_PlatformCaps_PowerContainment
)) {
698 if (smu7_read_smc_sram_dword(hwmgr
,
699 SMU7_FIRMWARE_HEADER_LOCATION
+
700 offsetof(SMU73_Firmware_Header
, PmFuseTable
),
701 &pm_fuse_table_offset
, SMC_RAM_END
))
702 PP_ASSERT_WITH_CODE(false,
703 "Attempt to get pm_fuse_table_offset Failed!",
707 if (fiji_populate_svi_load_line(hwmgr
))
708 PP_ASSERT_WITH_CODE(false,
709 "Attempt to populate SviLoadLine Failed!",
712 if (fiji_populate_tdc_limit(hwmgr
))
713 PP_ASSERT_WITH_CODE(false,
714 "Attempt to populate TDCLimit Failed!", return -EINVAL
);
716 if (fiji_populate_dw8(hwmgr
, pm_fuse_table_offset
))
717 PP_ASSERT_WITH_CODE(false,
718 "Attempt to populate TdcWaterfallCtl, "
719 "LPMLTemperature Min and Max Failed!",
723 if (0 != fiji_populate_temperature_scaler(hwmgr
))
724 PP_ASSERT_WITH_CODE(false,
725 "Attempt to populate LPMLTemperatureScaler Failed!",
729 if (fiji_populate_fuzzy_fan(hwmgr
))
730 PP_ASSERT_WITH_CODE(false,
731 "Attempt to populate Fuzzy Fan Control parameters Failed!",
735 if (fiji_populate_gnb_lpml(hwmgr
))
736 PP_ASSERT_WITH_CODE(false,
737 "Attempt to populate GnbLPML Failed!",
741 if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr
))
742 PP_ASSERT_WITH_CODE(false,
743 "Attempt to populate BapmVddCBaseLeakage Hi and Lo "
744 "Sidd Failed!", return -EINVAL
);
746 if (smu7_copy_bytes_to_smc(hwmgr
, pm_fuse_table_offset
,
747 (uint8_t *)&smu_data
->power_tune_table
,
748 sizeof(struct SMU73_Discrete_PmFuses
), SMC_RAM_END
))
749 PP_ASSERT_WITH_CODE(false,
750 "Attempt to download PmFuseTable Failed!",
756 static int fiji_populate_cac_table(struct pp_hwmgr
*hwmgr
,
757 struct SMU73_Discrete_DpmTable
*table
)
761 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
762 struct phm_ppt_v1_information
*table_info
=
763 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
764 struct phm_ppt_v1_voltage_lookup_table
*lookup_table
=
765 table_info
->vddc_lookup_table
;
766 /* tables is already swapped, so in order to use the value from it,
767 * we need to swap it back.
768 * We are populating vddc CAC data to BapmVddc table
769 * in split and merged mode
772 for (count
= 0; count
< lookup_table
->count
; count
++) {
773 index
= phm_get_voltage_index(lookup_table
,
774 data
->vddc_voltage_table
.entries
[count
].value
);
775 table
->BapmVddcVidLoSidd
[count
] =
776 convert_to_vid(lookup_table
->entries
[index
].us_cac_low
);
777 table
->BapmVddcVidHiSidd
[count
] =
778 convert_to_vid(lookup_table
->entries
[index
].us_cac_high
);
784 static int fiji_populate_smc_voltage_tables(struct pp_hwmgr
*hwmgr
,
785 struct SMU73_Discrete_DpmTable
*table
)
789 result
= fiji_populate_cac_table(hwmgr
, table
);
790 PP_ASSERT_WITH_CODE(0 == result
,
791 "can not populate CAC voltage tables to SMC",
797 static int fiji_populate_ulv_level(struct pp_hwmgr
*hwmgr
,
798 struct SMU73_Discrete_Ulv
*state
)
802 struct phm_ppt_v1_information
*table_info
=
803 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
805 state
->CcPwrDynRm
= 0;
806 state
->CcPwrDynRm1
= 0;
808 state
->VddcOffset
= (uint16_t) table_info
->us_ulv_voltage_offset
;
809 state
->VddcOffsetVid
= (uint8_t)(table_info
->us_ulv_voltage_offset
*
810 VOLTAGE_VID_OFFSET_SCALE2
/ VOLTAGE_VID_OFFSET_SCALE1
);
812 state
->VddcPhase
= 1;
815 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm
);
816 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm1
);
817 CONVERT_FROM_HOST_TO_SMC_US(state
->VddcOffset
);
822 static int fiji_populate_ulv_state(struct pp_hwmgr
*hwmgr
,
823 struct SMU73_Discrete_DpmTable
*table
)
825 return fiji_populate_ulv_level(hwmgr
, &table
->Ulv
);
828 static int fiji_populate_smc_link_level(struct pp_hwmgr
*hwmgr
,
829 struct SMU73_Discrete_DpmTable
*table
)
831 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
832 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
833 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
836 /* Index (dpm_table->pcie_speed_table.count)
837 * is reserved for PCIE boot level. */
838 for (i
= 0; i
<= dpm_table
->pcie_speed_table
.count
; i
++) {
839 table
->LinkLevel
[i
].PcieGenSpeed
=
840 (uint8_t)dpm_table
->pcie_speed_table
.dpm_levels
[i
].value
;
841 table
->LinkLevel
[i
].PcieLaneCount
= (uint8_t)encode_pcie_lane_width(
842 dpm_table
->pcie_speed_table
.dpm_levels
[i
].param1
);
843 table
->LinkLevel
[i
].EnabledForActivity
= 1;
844 table
->LinkLevel
[i
].SPC
= (uint8_t)(data
->pcie_spc_cap
& 0xff);
845 table
->LinkLevel
[i
].DownThreshold
= PP_HOST_TO_SMC_UL(5);
846 table
->LinkLevel
[i
].UpThreshold
= PP_HOST_TO_SMC_UL(30);
849 smu_data
->smc_state_table
.LinkLevelCount
=
850 (uint8_t)dpm_table
->pcie_speed_table
.count
;
851 data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
=
852 phm_get_dpm_level_enable_mask_value(&dpm_table
->pcie_speed_table
);
857 static int fiji_calculate_sclk_params(struct pp_hwmgr
*hwmgr
,
858 uint32_t clock
, struct SMU73_Discrete_GraphicsLevel
*sclk
)
860 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
861 struct pp_atomctrl_clock_dividers_vi dividers
;
862 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
863 uint32_t spll_func_cntl_3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
864 uint32_t spll_func_cntl_4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
865 uint32_t cg_spll_spread_spectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
866 uint32_t cg_spll_spread_spectrum_2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
868 uint32_t ref_divider
;
872 /* get the engine clock dividers for this clock value */
873 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
, clock
, ÷rs
);
875 PP_ASSERT_WITH_CODE(result
== 0,
876 "Error retrieving Engine Clock dividers from VBIOS.",
879 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */
880 ref_clock
= atomctrl_get_reference_clock(hwmgr
);
881 ref_divider
= 1 + dividers
.uc_pll_ref_div
;
883 /* low 14 bits is fraction and high 12 bits is divider */
884 fbdiv
= dividers
.ul_fb_div
.ul_fb_divider
& 0x3FFFFFF;
886 /* SPLL_FUNC_CNTL setup */
887 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
888 SPLL_REF_DIV
, dividers
.uc_pll_ref_div
);
889 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
890 SPLL_PDIV_A
, dividers
.uc_pll_post_div
);
892 /* SPLL_FUNC_CNTL_3 setup*/
893 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
, CG_SPLL_FUNC_CNTL_3
,
896 /* set to use fractional accumulation*/
897 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
, CG_SPLL_FUNC_CNTL_3
,
900 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
901 PHM_PlatformCaps_EngineSpreadSpectrumSupport
)) {
902 struct pp_atomctrl_internal_ss_info ssInfo
;
904 uint32_t vco_freq
= clock
* dividers
.uc_pll_post_div
;
905 if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr
,
906 vco_freq
, &ssInfo
)) {
908 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
909 * ss_info.speed_spectrum_rate -- in unit of khz
911 * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2
913 uint32_t clk_s
= ref_clock
* 5 /
914 (ref_divider
* ssInfo
.speed_spectrum_rate
);
915 /* clkv = 2 * D * fbdiv / NS */
916 uint32_t clk_v
= 4 * ssInfo
.speed_spectrum_percentage
*
917 fbdiv
/ (clk_s
* 10000);
919 cg_spll_spread_spectrum
= PHM_SET_FIELD(cg_spll_spread_spectrum
,
920 CG_SPLL_SPREAD_SPECTRUM
, CLKS
, clk_s
);
921 cg_spll_spread_spectrum
= PHM_SET_FIELD(cg_spll_spread_spectrum
,
922 CG_SPLL_SPREAD_SPECTRUM
, SSEN
, 1);
923 cg_spll_spread_spectrum_2
= PHM_SET_FIELD(cg_spll_spread_spectrum_2
,
924 CG_SPLL_SPREAD_SPECTRUM_2
, CLKV
, clk_v
);
928 sclk
->SclkFrequency
= clock
;
929 sclk
->CgSpllFuncCntl3
= spll_func_cntl_3
;
930 sclk
->CgSpllFuncCntl4
= spll_func_cntl_4
;
931 sclk
->SpllSpreadSpectrum
= cg_spll_spread_spectrum
;
932 sclk
->SpllSpreadSpectrum2
= cg_spll_spread_spectrum_2
;
933 sclk
->SclkDid
= (uint8_t)dividers
.pll_post_divider
;
938 static int fiji_populate_single_graphic_level(struct pp_hwmgr
*hwmgr
,
939 uint32_t clock
, struct SMU73_Discrete_GraphicsLevel
*level
)
942 /* PP_Clocks minClocks; */
944 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
945 struct phm_ppt_v1_information
*table_info
=
946 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
947 phm_ppt_v1_clock_voltage_dependency_table
*vdd_dep_table
= NULL
;
949 result
= fiji_calculate_sclk_params(hwmgr
, clock
, level
);
951 if (hwmgr
->od_enabled
)
952 vdd_dep_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)&data
->odn_dpm_table
.vdd_dependency_on_sclk
;
954 vdd_dep_table
= table_info
->vdd_dep_on_sclk
;
956 /* populate graphics levels */
957 result
= fiji_get_dependency_volt_by_clk(hwmgr
,
958 vdd_dep_table
, clock
,
959 (uint32_t *)(&level
->MinVoltage
), &mvdd
);
960 PP_ASSERT_WITH_CODE((0 == result
),
961 "can not find VDDC voltage value for "
962 "VDDC engine clock dependency table",
965 level
->SclkFrequency
= clock
;
966 level
->ActivityLevel
= data
->current_profile_setting
.sclk_activity
;
967 level
->CcPwrDynRm
= 0;
968 level
->CcPwrDynRm1
= 0;
969 level
->EnabledForActivity
= 0;
970 level
->EnabledForThrottle
= 1;
971 level
->UpHyst
= data
->current_profile_setting
.sclk_up_hyst
;
972 level
->DownHyst
= data
->current_profile_setting
.sclk_down_hyst
;
973 level
->VoltageDownHyst
= 0;
974 level
->PowerThrottle
= 0;
976 data
->display_timing
.min_clock_in_sr
= hwmgr
->display_config
->min_core_set_clock_in_sr
;
978 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
, PHM_PlatformCaps_SclkDeepSleep
))
979 level
->DeepSleepDivId
= smu7_get_sleep_divider_id_from_clock(clock
,
980 hwmgr
->display_config
->min_core_set_clock_in_sr
);
983 /* Default to slow, highest DPM level will be
984 * set to PPSMC_DISPLAY_WATERMARK_LOW later.
986 level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
988 CONVERT_FROM_HOST_TO_SMC_UL(level
->MinVoltage
);
989 CONVERT_FROM_HOST_TO_SMC_UL(level
->SclkFrequency
);
990 CONVERT_FROM_HOST_TO_SMC_US(level
->ActivityLevel
);
991 CONVERT_FROM_HOST_TO_SMC_UL(level
->CgSpllFuncCntl3
);
992 CONVERT_FROM_HOST_TO_SMC_UL(level
->CgSpllFuncCntl4
);
993 CONVERT_FROM_HOST_TO_SMC_UL(level
->SpllSpreadSpectrum
);
994 CONVERT_FROM_HOST_TO_SMC_UL(level
->SpllSpreadSpectrum2
);
995 CONVERT_FROM_HOST_TO_SMC_UL(level
->CcPwrDynRm
);
996 CONVERT_FROM_HOST_TO_SMC_UL(level
->CcPwrDynRm1
);
1001 static int fiji_populate_all_graphic_levels(struct pp_hwmgr
*hwmgr
)
1003 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1004 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1006 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
1007 struct phm_ppt_v1_information
*table_info
=
1008 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1009 struct phm_ppt_v1_pcie_table
*pcie_table
= table_info
->pcie_table
;
1010 uint8_t pcie_entry_cnt
= (uint8_t) data
->dpm_table
.pcie_speed_table
.count
;
1012 uint32_t array
= smu_data
->smu7_data
.dpm_table_start
+
1013 offsetof(SMU73_Discrete_DpmTable
, GraphicsLevel
);
1014 uint32_t array_size
= sizeof(struct SMU73_Discrete_GraphicsLevel
) *
1015 SMU73_MAX_LEVELS_GRAPHICS
;
1016 struct SMU73_Discrete_GraphicsLevel
*levels
=
1017 smu_data
->smc_state_table
.GraphicsLevel
;
1018 uint32_t i
, max_entry
;
1019 uint8_t hightest_pcie_level_enabled
= 0,
1020 lowest_pcie_level_enabled
= 0,
1021 mid_pcie_level_enabled
= 0,
1024 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++) {
1025 result
= fiji_populate_single_graphic_level(hwmgr
,
1026 dpm_table
->sclk_table
.dpm_levels
[i
].value
,
1031 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
1033 levels
[i
].DeepSleepDivId
= 0;
1036 /* Only enable level 0 for now.*/
1037 levels
[0].EnabledForActivity
= 1;
1039 /* set highest level watermark to high */
1040 levels
[dpm_table
->sclk_table
.count
- 1].DisplayWatermark
=
1041 PPSMC_DISPLAY_WATERMARK_HIGH
;
1043 smu_data
->smc_state_table
.GraphicsDpmLevelCount
=
1044 (uint8_t)dpm_table
->sclk_table
.count
;
1045 data
->dpm_level_enable_mask
.sclk_dpm_enable_mask
=
1046 phm_get_dpm_level_enable_mask_value(&dpm_table
->sclk_table
);
1048 if (pcie_table
!= NULL
) {
1049 PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt
),
1050 "There must be 1 or more PCIE levels defined in PPTable.",
1052 max_entry
= pcie_entry_cnt
- 1;
1053 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++)
1054 levels
[i
].pcieDpmLevel
=
1055 (uint8_t) ((i
< max_entry
) ? i
: max_entry
);
1057 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
1058 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
1059 (1 << (hightest_pcie_level_enabled
+ 1))) != 0))
1060 hightest_pcie_level_enabled
++;
1062 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
1063 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
1064 (1 << lowest_pcie_level_enabled
)) == 0))
1065 lowest_pcie_level_enabled
++;
1067 while ((count
< hightest_pcie_level_enabled
) &&
1068 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
1069 (1 << (lowest_pcie_level_enabled
+ 1 + count
))) == 0))
1072 mid_pcie_level_enabled
= (lowest_pcie_level_enabled
+ 1 + count
) <
1073 hightest_pcie_level_enabled
?
1074 (lowest_pcie_level_enabled
+ 1 + count
) :
1075 hightest_pcie_level_enabled
;
1077 /* set pcieDpmLevel to hightest_pcie_level_enabled */
1078 for (i
= 2; i
< dpm_table
->sclk_table
.count
; i
++)
1079 levels
[i
].pcieDpmLevel
= hightest_pcie_level_enabled
;
1081 /* set pcieDpmLevel to lowest_pcie_level_enabled */
1082 levels
[0].pcieDpmLevel
= lowest_pcie_level_enabled
;
1084 /* set pcieDpmLevel to mid_pcie_level_enabled */
1085 levels
[1].pcieDpmLevel
= mid_pcie_level_enabled
;
1087 /* level count will send to smc once at init smc table and never change */
1088 result
= smu7_copy_bytes_to_smc(hwmgr
, array
, (uint8_t *)levels
,
1089 (uint32_t)array_size
, SMC_RAM_END
);
1096 * MCLK Frequency Ratio
1097 * SEQ_CG_RESP Bit[31:24] - 0x0
1098 * Bit[27:24] \96 DDR3 Frequency ratio
1099 * 0x0 <= 100MHz, 450 < 0x8 <= 500MHz
1100 * 100 < 0x1 <= 150MHz, 500 < 0x9 <= 550MHz
1101 * 150 < 0x2 <= 200MHz, 550 < 0xA <= 600MHz
1102 * 200 < 0x3 <= 250MHz, 600 < 0xB <= 650MHz
1103 * 250 < 0x4 <= 300MHz, 650 < 0xC <= 700MHz
1104 * 300 < 0x5 <= 350MHz, 700 < 0xD <= 750MHz
1105 * 350 < 0x6 <= 400MHz, 750 < 0xE <= 800MHz
1106 * 400 < 0x7 <= 450MHz, 800 < 0xF
1108 static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock
)
1110 if (mem_clock
<= 10000)
1112 if (mem_clock
<= 15000)
1114 if (mem_clock
<= 20000)
1116 if (mem_clock
<= 25000)
1118 if (mem_clock
<= 30000)
1120 if (mem_clock
<= 35000)
1122 if (mem_clock
<= 40000)
1124 if (mem_clock
<= 45000)
1126 if (mem_clock
<= 50000)
1128 if (mem_clock
<= 55000)
1130 if (mem_clock
<= 60000)
1132 if (mem_clock
<= 65000)
1134 if (mem_clock
<= 70000)
1136 if (mem_clock
<= 75000)
1138 if (mem_clock
<= 80000)
1140 /* mem_clock > 800MHz */
1144 static int fiji_calculate_mclk_params(struct pp_hwmgr
*hwmgr
,
1145 uint32_t clock
, struct SMU73_Discrete_MemoryLevel
*mclk
)
1147 struct pp_atomctrl_memory_clock_param mem_param
;
1150 result
= atomctrl_get_memory_pll_dividers_vi(hwmgr
, clock
, &mem_param
);
1151 PP_ASSERT_WITH_CODE((0 == result
),
1152 "Failed to get Memory PLL Dividers.",
1155 /* Save the result data to outpupt memory level structure */
1156 mclk
->MclkFrequency
= clock
;
1157 mclk
->MclkDivider
= (uint8_t)mem_param
.mpll_post_divider
;
1158 mclk
->FreqRange
= fiji_get_mclk_frequency_ratio(clock
);
1163 static int fiji_populate_single_memory_level(struct pp_hwmgr
*hwmgr
,
1164 uint32_t clock
, struct SMU73_Discrete_MemoryLevel
*mem_level
)
1166 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1167 struct phm_ppt_v1_information
*table_info
=
1168 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1170 uint32_t mclk_stutter_mode_threshold
= 60000;
1171 phm_ppt_v1_clock_voltage_dependency_table
*vdd_dep_table
= NULL
;
1173 if (hwmgr
->od_enabled
)
1174 vdd_dep_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)&data
->odn_dpm_table
.vdd_dependency_on_mclk
;
1176 vdd_dep_table
= table_info
->vdd_dep_on_mclk
;
1178 if (vdd_dep_table
) {
1179 result
= fiji_get_dependency_volt_by_clk(hwmgr
,
1180 vdd_dep_table
, clock
,
1181 (uint32_t *)(&mem_level
->MinVoltage
), &mem_level
->MinMvdd
);
1182 PP_ASSERT_WITH_CODE((0 == result
),
1183 "can not find MinVddc voltage value from memory "
1184 "VDDC voltage dependency table", return result
);
1187 mem_level
->EnabledForThrottle
= 1;
1188 mem_level
->EnabledForActivity
= 0;
1189 mem_level
->UpHyst
= data
->current_profile_setting
.mclk_up_hyst
;
1190 mem_level
->DownHyst
= data
->current_profile_setting
.mclk_down_hyst
;
1191 mem_level
->VoltageDownHyst
= 0;
1192 mem_level
->ActivityLevel
= data
->current_profile_setting
.mclk_activity
;
1193 mem_level
->StutterEnable
= false;
1195 mem_level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1197 /* enable stutter mode if all the follow condition applied
1198 * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI,
1199 * &(data->DisplayTiming.numExistingDisplays));
1201 data
->display_timing
.num_existing_displays
= hwmgr
->display_config
->num_display
;
1202 data
->display_timing
.vrefresh
= hwmgr
->display_config
->vrefresh
;
1204 if (mclk_stutter_mode_threshold
&&
1205 (clock
<= mclk_stutter_mode_threshold
) &&
1206 (!data
->is_uvd_enabled
) &&
1207 (PHM_READ_FIELD(hwmgr
->device
, DPG_PIPE_STUTTER_CONTROL
,
1208 STUTTER_ENABLE
) & 0x1))
1209 mem_level
->StutterEnable
= true;
1211 result
= fiji_calculate_mclk_params(hwmgr
, clock
, mem_level
);
1213 CONVERT_FROM_HOST_TO_SMC_UL(mem_level
->MinMvdd
);
1214 CONVERT_FROM_HOST_TO_SMC_UL(mem_level
->MclkFrequency
);
1215 CONVERT_FROM_HOST_TO_SMC_US(mem_level
->ActivityLevel
);
1216 CONVERT_FROM_HOST_TO_SMC_UL(mem_level
->MinVoltage
);
1221 static int fiji_populate_all_memory_levels(struct pp_hwmgr
*hwmgr
)
1223 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1224 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1225 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
1227 /* populate MCLK dpm table to SMU7 */
1228 uint32_t array
= smu_data
->smu7_data
.dpm_table_start
+
1229 offsetof(SMU73_Discrete_DpmTable
, MemoryLevel
);
1230 uint32_t array_size
= sizeof(SMU73_Discrete_MemoryLevel
) *
1231 SMU73_MAX_LEVELS_MEMORY
;
1232 struct SMU73_Discrete_MemoryLevel
*levels
=
1233 smu_data
->smc_state_table
.MemoryLevel
;
1236 for (i
= 0; i
< dpm_table
->mclk_table
.count
; i
++) {
1237 PP_ASSERT_WITH_CODE((0 != dpm_table
->mclk_table
.dpm_levels
[i
].value
),
1238 "can not populate memory level as memory clock is zero",
1240 result
= fiji_populate_single_memory_level(hwmgr
,
1241 dpm_table
->mclk_table
.dpm_levels
[i
].value
,
1247 /* Only enable level 0 for now. */
1248 levels
[0].EnabledForActivity
= 1;
1250 /* in order to prevent MC activity from stutter mode to push DPM up.
1251 * the UVD change complements this by putting the MCLK in
1252 * a higher state by default such that we are not effected by
1253 * up threshold or and MCLK DPM latency.
1255 levels
[0].ActivityLevel
= (uint16_t)data
->mclk_dpm0_activity_target
;
1256 CONVERT_FROM_HOST_TO_SMC_US(levels
[0].ActivityLevel
);
1258 smu_data
->smc_state_table
.MemoryDpmLevelCount
=
1259 (uint8_t)dpm_table
->mclk_table
.count
;
1260 data
->dpm_level_enable_mask
.mclk_dpm_enable_mask
=
1261 phm_get_dpm_level_enable_mask_value(&dpm_table
->mclk_table
);
1262 /* set highest level watermark to high */
1263 levels
[dpm_table
->mclk_table
.count
- 1].DisplayWatermark
=
1264 PPSMC_DISPLAY_WATERMARK_HIGH
;
1266 /* level count will send to smc once at init smc table and never change */
1267 result
= smu7_copy_bytes_to_smc(hwmgr
, array
, (uint8_t *)levels
,
1268 (uint32_t)array_size
, SMC_RAM_END
);
1273 static int fiji_populate_mvdd_value(struct pp_hwmgr
*hwmgr
,
1274 uint32_t mclk
, SMIO_Pattern
*smio_pat
)
1276 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1277 struct phm_ppt_v1_information
*table_info
=
1278 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1281 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->mvdd_control
) {
1282 /* find mvdd value which clock is more than request */
1283 for (i
= 0; i
< table_info
->vdd_dep_on_mclk
->count
; i
++) {
1284 if (mclk
<= table_info
->vdd_dep_on_mclk
->entries
[i
].clk
) {
1285 smio_pat
->Voltage
= data
->mvdd_voltage_table
.entries
[i
].value
;
1289 PP_ASSERT_WITH_CODE(i
< table_info
->vdd_dep_on_mclk
->count
,
1290 "MVDD Voltage is outside the supported range.",
1298 static int fiji_populate_smc_acpi_level(struct pp_hwmgr
*hwmgr
,
1299 SMU73_Discrete_DpmTable
*table
)
1302 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1303 struct phm_ppt_v1_information
*table_info
=
1304 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1305 struct pp_atomctrl_clock_dividers_vi dividers
;
1306 SMIO_Pattern vol_level
;
1309 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
1310 uint32_t spll_func_cntl_2
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_2
;
1312 table
->ACPILevel
.Flags
&= ~PPSMC_SWSTATE_FLAG_DC
;
1314 if (!data
->sclk_dpm_key_disabled
) {
1315 /* Get MinVoltage and Frequency from DPM0,
1316 * already converted to SMC_UL */
1317 table
->ACPILevel
.SclkFrequency
=
1318 data
->dpm_table
.sclk_table
.dpm_levels
[0].value
;
1319 result
= fiji_get_dependency_volt_by_clk(hwmgr
,
1320 table_info
->vdd_dep_on_sclk
,
1321 table
->ACPILevel
.SclkFrequency
,
1322 (uint32_t *)(&table
->ACPILevel
.MinVoltage
), &mvdd
);
1323 PP_ASSERT_WITH_CODE((0 == result
),
1324 "Cannot find ACPI VDDC voltage value " \
1325 "in Clock Dependency Table",
1328 table
->ACPILevel
.SclkFrequency
=
1329 data
->vbios_boot_state
.sclk_bootup_value
;
1330 table
->ACPILevel
.MinVoltage
=
1331 data
->vbios_boot_state
.vddc_bootup_value
* VOLTAGE_SCALE
;
1334 /* get the engine clock dividers for this clock value */
1335 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
,
1336 table
->ACPILevel
.SclkFrequency
, ÷rs
);
1337 PP_ASSERT_WITH_CODE(result
== 0,
1338 "Error retrieving Engine Clock dividers from VBIOS.",
1341 table
->ACPILevel
.SclkDid
= (uint8_t)dividers
.pll_post_divider
;
1342 table
->ACPILevel
.DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1343 table
->ACPILevel
.DeepSleepDivId
= 0;
1345 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1347 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1349 spll_func_cntl_2
= PHM_SET_FIELD(spll_func_cntl_2
, CG_SPLL_FUNC_CNTL_2
,
1352 table
->ACPILevel
.CgSpllFuncCntl
= spll_func_cntl
;
1353 table
->ACPILevel
.CgSpllFuncCntl2
= spll_func_cntl_2
;
1354 table
->ACPILevel
.CgSpllFuncCntl3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
1355 table
->ACPILevel
.CgSpllFuncCntl4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
1356 table
->ACPILevel
.SpllSpreadSpectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
1357 table
->ACPILevel
.SpllSpreadSpectrum2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
1358 table
->ACPILevel
.CcPwrDynRm
= 0;
1359 table
->ACPILevel
.CcPwrDynRm1
= 0;
1361 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.Flags
);
1362 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SclkFrequency
);
1363 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.MinVoltage
);
1364 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl
);
1365 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl2
);
1366 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl3
);
1367 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl4
);
1368 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum
);
1369 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum2
);
1370 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm
);
1371 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm1
);
1373 if (!data
->mclk_dpm_key_disabled
) {
1374 /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */
1375 table
->MemoryACPILevel
.MclkFrequency
=
1376 data
->dpm_table
.mclk_table
.dpm_levels
[0].value
;
1377 result
= fiji_get_dependency_volt_by_clk(hwmgr
,
1378 table_info
->vdd_dep_on_mclk
,
1379 table
->MemoryACPILevel
.MclkFrequency
,
1380 (uint32_t *)(&table
->MemoryACPILevel
.MinVoltage
), &mvdd
);
1381 PP_ASSERT_WITH_CODE((0 == result
),
1382 "Cannot find ACPI VDDCI voltage value in Clock Dependency Table",
1385 table
->MemoryACPILevel
.MclkFrequency
=
1386 data
->vbios_boot_state
.mclk_bootup_value
;
1387 table
->MemoryACPILevel
.MinVoltage
=
1388 data
->vbios_boot_state
.vddci_bootup_value
* VOLTAGE_SCALE
;
1392 if ((SMU7_VOLTAGE_CONTROL_NONE
== data
->mvdd_control
) ||
1393 (data
->mclk_dpm_key_disabled
))
1394 us_mvdd
= data
->vbios_boot_state
.mvdd_bootup_value
;
1396 if (!fiji_populate_mvdd_value(hwmgr
,
1397 data
->dpm_table
.mclk_table
.dpm_levels
[0].value
,
1399 us_mvdd
= vol_level
.Voltage
;
1402 table
->MemoryACPILevel
.MinMvdd
=
1403 PP_HOST_TO_SMC_UL(us_mvdd
* VOLTAGE_SCALE
);
1405 table
->MemoryACPILevel
.EnabledForThrottle
= 0;
1406 table
->MemoryACPILevel
.EnabledForActivity
= 0;
1407 table
->MemoryACPILevel
.UpHyst
= 0;
1408 table
->MemoryACPILevel
.DownHyst
= 100;
1409 table
->MemoryACPILevel
.VoltageDownHyst
= 0;
1410 table
->MemoryACPILevel
.ActivityLevel
=
1411 PP_HOST_TO_SMC_US(data
->current_profile_setting
.mclk_activity
);
1413 table
->MemoryACPILevel
.StutterEnable
= false;
1414 CONVERT_FROM_HOST_TO_SMC_UL(table
->MemoryACPILevel
.MclkFrequency
);
1415 CONVERT_FROM_HOST_TO_SMC_UL(table
->MemoryACPILevel
.MinVoltage
);
1420 static int fiji_populate_smc_vce_level(struct pp_hwmgr
*hwmgr
,
1421 SMU73_Discrete_DpmTable
*table
)
1423 int result
= -EINVAL
;
1425 struct pp_atomctrl_clock_dividers_vi dividers
;
1426 struct phm_ppt_v1_information
*table_info
=
1427 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1428 struct phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1429 table_info
->mm_dep_table
;
1431 table
->VceLevelCount
= (uint8_t)(mm_table
->count
);
1432 table
->VceBootLevel
= 0;
1434 for (count
= 0; count
< table
->VceLevelCount
; count
++) {
1435 table
->VceLevel
[count
].Frequency
= mm_table
->entries
[count
].eclk
;
1436 table
->VceLevel
[count
].MinVoltage
= 0;
1437 table
->VceLevel
[count
].MinVoltage
|=
1438 (mm_table
->entries
[count
].vddc
* VOLTAGE_SCALE
) << VDDC_SHIFT
;
1439 table
->VceLevel
[count
].MinVoltage
|=
1440 ((mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
) *
1441 VOLTAGE_SCALE
) << VDDCI_SHIFT
;
1442 table
->VceLevel
[count
].MinVoltage
|= 1 << PHASES_SHIFT
;
1444 /*retrieve divider value for VBIOS */
1445 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1446 table
->VceLevel
[count
].Frequency
, ÷rs
);
1447 PP_ASSERT_WITH_CODE((0 == result
),
1448 "can not find divide id for VCE engine clock",
1451 table
->VceLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1453 CONVERT_FROM_HOST_TO_SMC_UL(table
->VceLevel
[count
].Frequency
);
1454 CONVERT_FROM_HOST_TO_SMC_UL(table
->VceLevel
[count
].MinVoltage
);
1459 static int fiji_populate_smc_acp_level(struct pp_hwmgr
*hwmgr
,
1460 SMU73_Discrete_DpmTable
*table
)
1462 int result
= -EINVAL
;
1464 struct pp_atomctrl_clock_dividers_vi dividers
;
1465 struct phm_ppt_v1_information
*table_info
=
1466 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1467 struct phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1468 table_info
->mm_dep_table
;
1470 table
->AcpLevelCount
= (uint8_t)(mm_table
->count
);
1471 table
->AcpBootLevel
= 0;
1473 for (count
= 0; count
< table
->AcpLevelCount
; count
++) {
1474 table
->AcpLevel
[count
].Frequency
= mm_table
->entries
[count
].aclk
;
1475 table
->AcpLevel
[count
].MinVoltage
|= (mm_table
->entries
[count
].vddc
*
1476 VOLTAGE_SCALE
) << VDDC_SHIFT
;
1477 table
->AcpLevel
[count
].MinVoltage
|= ((mm_table
->entries
[count
].vddc
-
1478 VDDC_VDDCI_DELTA
) * VOLTAGE_SCALE
) << VDDCI_SHIFT
;
1479 table
->AcpLevel
[count
].MinVoltage
|= 1 << PHASES_SHIFT
;
1481 /* retrieve divider value for VBIOS */
1482 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1483 table
->AcpLevel
[count
].Frequency
, ÷rs
);
1484 PP_ASSERT_WITH_CODE((0 == result
),
1485 "can not find divide id for engine clock", return result
);
1487 table
->AcpLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1489 CONVERT_FROM_HOST_TO_SMC_UL(table
->AcpLevel
[count
].Frequency
);
1490 CONVERT_FROM_HOST_TO_SMC_UL(table
->AcpLevel
[count
].MinVoltage
);
1495 static int fiji_populate_memory_timing_parameters(struct pp_hwmgr
*hwmgr
,
1496 int32_t eng_clock
, int32_t mem_clock
,
1497 struct SMU73_Discrete_MCArbDramTimingTableEntry
*arb_regs
)
1499 uint32_t dram_timing
;
1500 uint32_t dram_timing2
;
1505 result
= atomctrl_set_engine_dram_timings_rv770(hwmgr
,
1506 eng_clock
, mem_clock
);
1507 PP_ASSERT_WITH_CODE(result
== 0,
1508 "Error calling VBIOS to set DRAM_TIMING.", return result
);
1510 dram_timing
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING
);
1511 dram_timing2
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING2
);
1512 burstTime
= cgs_read_register(hwmgr
->device
, mmMC_ARB_BURST_TIME
);
1514 trrds
= PHM_GET_FIELD(burstTime
, MC_ARB_BURST_TIME
, TRRDS0
);
1515 trrdl
= PHM_GET_FIELD(burstTime
, MC_ARB_BURST_TIME
, TRRDL0
);
1517 arb_regs
->McArbDramTiming
= PP_HOST_TO_SMC_UL(dram_timing
);
1518 arb_regs
->McArbDramTiming2
= PP_HOST_TO_SMC_UL(dram_timing2
);
1519 arb_regs
->McArbBurstTime
= (uint8_t)burstTime
;
1520 arb_regs
->TRRDS
= (uint8_t)trrds
;
1521 arb_regs
->TRRDL
= (uint8_t)trrdl
;
1526 static int fiji_program_memory_timing_parameters(struct pp_hwmgr
*hwmgr
)
1528 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1529 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1530 struct SMU73_Discrete_MCArbDramTimingTable arb_regs
;
1534 for (i
= 0; i
< data
->dpm_table
.sclk_table
.count
; i
++) {
1535 for (j
= 0; j
< data
->dpm_table
.mclk_table
.count
; j
++) {
1536 result
= fiji_populate_memory_timing_parameters(hwmgr
,
1537 data
->dpm_table
.sclk_table
.dpm_levels
[i
].value
,
1538 data
->dpm_table
.mclk_table
.dpm_levels
[j
].value
,
1539 &arb_regs
.entries
[i
][j
]);
1546 result
= smu7_copy_bytes_to_smc(
1548 smu_data
->smu7_data
.arb_table_start
,
1549 (uint8_t *)&arb_regs
,
1550 sizeof(SMU73_Discrete_MCArbDramTimingTable
),
1555 static int fiji_populate_smc_uvd_level(struct pp_hwmgr
*hwmgr
,
1556 struct SMU73_Discrete_DpmTable
*table
)
1558 int result
= -EINVAL
;
1560 struct pp_atomctrl_clock_dividers_vi dividers
;
1561 struct phm_ppt_v1_information
*table_info
=
1562 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1563 struct phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1564 table_info
->mm_dep_table
;
1566 table
->UvdLevelCount
= (uint8_t)(mm_table
->count
);
1567 table
->UvdBootLevel
= 0;
1569 for (count
= 0; count
< table
->UvdLevelCount
; count
++) {
1570 table
->UvdLevel
[count
].MinVoltage
= 0;
1571 table
->UvdLevel
[count
].VclkFrequency
= mm_table
->entries
[count
].vclk
;
1572 table
->UvdLevel
[count
].DclkFrequency
= mm_table
->entries
[count
].dclk
;
1573 table
->UvdLevel
[count
].MinVoltage
|= (mm_table
->entries
[count
].vddc
*
1574 VOLTAGE_SCALE
) << VDDC_SHIFT
;
1575 table
->UvdLevel
[count
].MinVoltage
|= ((mm_table
->entries
[count
].vddc
-
1576 VDDC_VDDCI_DELTA
) * VOLTAGE_SCALE
) << VDDCI_SHIFT
;
1577 table
->UvdLevel
[count
].MinVoltage
|= 1 << PHASES_SHIFT
;
1579 /* retrieve divider value for VBIOS */
1580 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1581 table
->UvdLevel
[count
].VclkFrequency
, ÷rs
);
1582 PP_ASSERT_WITH_CODE((0 == result
),
1583 "can not find divide id for Vclk clock", return result
);
1585 table
->UvdLevel
[count
].VclkDivider
= (uint8_t)dividers
.pll_post_divider
;
1587 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1588 table
->UvdLevel
[count
].DclkFrequency
, ÷rs
);
1589 PP_ASSERT_WITH_CODE((0 == result
),
1590 "can not find divide id for Dclk clock", return result
);
1592 table
->UvdLevel
[count
].DclkDivider
= (uint8_t)dividers
.pll_post_divider
;
1594 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].VclkFrequency
);
1595 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].DclkFrequency
);
1596 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].MinVoltage
);
1602 static int fiji_populate_smc_boot_level(struct pp_hwmgr
*hwmgr
,
1603 struct SMU73_Discrete_DpmTable
*table
)
1606 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1608 table
->GraphicsBootLevel
= 0;
1609 table
->MemoryBootLevel
= 0;
1611 /* find boot level from dpm table */
1612 result
= phm_find_boot_level(&(data
->dpm_table
.sclk_table
),
1613 data
->vbios_boot_state
.sclk_bootup_value
,
1614 (uint32_t *)&(table
->GraphicsBootLevel
));
1616 result
= phm_find_boot_level(&(data
->dpm_table
.mclk_table
),
1617 data
->vbios_boot_state
.mclk_bootup_value
,
1618 (uint32_t *)&(table
->MemoryBootLevel
));
1620 table
->BootVddc
= data
->vbios_boot_state
.vddc_bootup_value
*
1622 table
->BootVddci
= data
->vbios_boot_state
.vddci_bootup_value
*
1624 table
->BootMVdd
= data
->vbios_boot_state
.mvdd_bootup_value
*
1627 CONVERT_FROM_HOST_TO_SMC_US(table
->BootVddc
);
1628 CONVERT_FROM_HOST_TO_SMC_US(table
->BootVddci
);
1629 CONVERT_FROM_HOST_TO_SMC_US(table
->BootMVdd
);
1634 static int fiji_populate_smc_initailial_state(struct pp_hwmgr
*hwmgr
)
1636 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1637 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1638 struct phm_ppt_v1_information
*table_info
=
1639 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1640 uint8_t count
, level
;
1642 count
= (uint8_t)(table_info
->vdd_dep_on_sclk
->count
);
1643 for (level
= 0; level
< count
; level
++) {
1644 if (table_info
->vdd_dep_on_sclk
->entries
[level
].clk
>=
1645 data
->vbios_boot_state
.sclk_bootup_value
) {
1646 smu_data
->smc_state_table
.GraphicsBootLevel
= level
;
1651 count
= (uint8_t)(table_info
->vdd_dep_on_mclk
->count
);
1652 for (level
= 0; level
< count
; level
++) {
1653 if (table_info
->vdd_dep_on_mclk
->entries
[level
].clk
>=
1654 data
->vbios_boot_state
.mclk_bootup_value
) {
1655 smu_data
->smc_state_table
.MemoryBootLevel
= level
;
1663 static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr
*hwmgr
)
1665 uint32_t ro
, efuse
, efuse2
, clock_freq
, volt_without_cks
,
1666 volt_with_cks
, value
;
1667 uint16_t clock_freq_u16
;
1668 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1669 uint8_t type
, i
, j
, cks_setting
, stretch_amount
, stretch_amount2
,
1671 struct phm_ppt_v1_information
*table_info
=
1672 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1673 struct phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
=
1674 table_info
->vdd_dep_on_sclk
;
1676 stretch_amount
= (uint8_t)table_info
->cac_dtp_table
->usClockStretchAmount
;
1678 /* Read SMU_Eefuse to read and calculate RO and determine
1679 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1681 efuse
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1682 ixSMU_EFUSE_0
+ (146 * 4));
1683 efuse2
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1684 ixSMU_EFUSE_0
+ (148 * 4));
1685 efuse
&= 0xFF000000;
1686 efuse
= efuse
>> 24;
1690 ro
= (2300 - 1350) * efuse
/ 255 + 1350;
1692 ro
= (2500 - 1000) * efuse
/ 255 + 1000;
1699 /* Populate Stretch amount */
1700 smu_data
->smc_state_table
.ClockStretcherAmount
= stretch_amount
;
1702 /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1703 for (i
= 0; i
< sclk_table
->count
; i
++) {
1704 smu_data
->smc_state_table
.Sclk_CKS_masterEn0_7
|=
1705 sclk_table
->entries
[i
].cks_enable
<< i
;
1706 volt_without_cks
= (uint32_t)((14041 *
1707 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3571 + 75 - ro
) * 1000 /
1708 (4026 - (13924 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1709 volt_with_cks
= (uint32_t)((13946 *
1710 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3320 + 45 - ro
) * 1000 /
1711 (3664 - (11454 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1712 if (volt_without_cks
>= volt_with_cks
)
1713 volt_offset
= (uint8_t)(((volt_without_cks
- volt_with_cks
+
1714 sclk_table
->entries
[i
].cks_voffset
) * 100 / 625) + 1);
1715 smu_data
->smc_state_table
.Sclk_voltageOffset
[i
] = volt_offset
;
1718 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1719 STRETCH_ENABLE
, 0x0);
1720 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1722 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1724 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1727 /* Populate CKS Lookup Table */
1728 if (stretch_amount
== 1 || stretch_amount
== 2 || stretch_amount
== 5)
1729 stretch_amount2
= 0;
1730 else if (stretch_amount
== 3 || stretch_amount
== 4)
1731 stretch_amount2
= 1;
1733 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
1734 PHM_PlatformCaps_ClockStretcher
);
1735 PP_ASSERT_WITH_CODE(false,
1736 "Stretch Amount in PPTable not supported",
1740 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1742 value
&= 0xFFC2FF87;
1743 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].minFreq
=
1744 fiji_clock_stretcher_lookup_table
[stretch_amount2
][0];
1745 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].maxFreq
=
1746 fiji_clock_stretcher_lookup_table
[stretch_amount2
][1];
1747 clock_freq_u16
= (uint16_t)(PP_SMC_TO_HOST_UL(smu_data
->smc_state_table
.
1748 GraphicsLevel
[smu_data
->smc_state_table
.GraphicsDpmLevelCount
- 1].
1749 SclkFrequency
) / 100);
1750 if (fiji_clock_stretcher_lookup_table
[stretch_amount2
][0] <
1752 fiji_clock_stretcher_lookup_table
[stretch_amount2
][1] >
1754 /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
1755 value
|= (fiji_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 16;
1756 /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
1757 value
|= (fiji_clock_stretcher_lookup_table
[stretch_amount2
][2]) << 18;
1758 /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
1759 value
|= (fiji_clock_stretch_amount_conversion
1760 [fiji_clock_stretcher_lookup_table
[stretch_amount2
][3]]
1761 [stretch_amount
]) << 3;
1763 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1764 CKS_LOOKUPTableEntry
[0].minFreq
);
1765 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1766 CKS_LOOKUPTableEntry
[0].maxFreq
);
1767 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
=
1768 fiji_clock_stretcher_lookup_table
[stretch_amount2
][2] & 0x7F;
1769 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
|=
1770 (fiji_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 7;
1772 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1773 ixPWR_CKS_CNTL
, value
);
1775 /* Populate DDT Lookup Table */
1776 for (i
= 0; i
< 4; i
++) {
1777 /* Assign the minimum and maximum VID stored
1778 * in the last row of Clock Stretcher Voltage Table.
1780 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1781 ClockStretcherDataTableEntry
[i
].minVID
=
1782 (uint8_t) fiji_clock_stretcher_ddt_table
[type
][i
][2];
1783 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1784 ClockStretcherDataTableEntry
[i
].maxVID
=
1785 (uint8_t) fiji_clock_stretcher_ddt_table
[type
][i
][3];
1786 /* Loop through each SCLK and check the frequency
1787 * to see if it lies within the frequency for clock stretcher.
1789 for (j
= 0; j
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; j
++) {
1791 clock_freq
= PP_SMC_TO_HOST_UL(
1792 smu_data
->smc_state_table
.GraphicsLevel
[j
].SclkFrequency
);
1793 /* Check the allowed frequency against the sclk level[j].
1794 * Sclk's endianness has already been converted,
1795 * and it's in 10Khz unit,
1796 * as opposed to Data table, which is in Mhz unit.
1799 (fiji_clock_stretcher_ddt_table
[type
][i
][0]) * 100) {
1802 (fiji_clock_stretcher_ddt_table
[type
][i
][1]) * 100)
1805 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1806 ClockStretcherDataTableEntry
[i
].setting
|= cks_setting
<< (j
* 2);
1808 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.
1809 ClockStretcherDataTable
.
1810 ClockStretcherDataTableEntry
[i
].setting
);
1813 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, ixPWR_CKS_CNTL
);
1814 value
&= 0xFFFFFFFE;
1815 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, ixPWR_CKS_CNTL
, value
);
1820 static int fiji_populate_vr_config(struct pp_hwmgr
*hwmgr
,
1821 struct SMU73_Discrete_DpmTable
*table
)
1823 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1826 config
= VR_MERGED_WITH_VDDC
;
1827 table
->VRConfig
|= (config
<< VRCONF_VDDGFX_SHIFT
);
1829 /* Set Vddc Voltage Controller */
1830 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
1831 config
= VR_SVI2_PLANE_1
;
1832 table
->VRConfig
|= config
;
1834 PP_ASSERT_WITH_CODE(false,
1835 "VDDC should be on SVI2 control in merged mode!",
1838 /* Set Vddci Voltage Controller */
1839 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vddci_control
) {
1840 config
= VR_SVI2_PLANE_2
; /* only in merged mode */
1841 table
->VRConfig
|= (config
<< VRCONF_VDDCI_SHIFT
);
1842 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->vddci_control
) {
1843 config
= VR_SMIO_PATTERN_1
;
1844 table
->VRConfig
|= (config
<< VRCONF_VDDCI_SHIFT
);
1846 config
= VR_STATIC_VOLTAGE
;
1847 table
->VRConfig
|= (config
<< VRCONF_VDDCI_SHIFT
);
1849 /* Set Mvdd Voltage Controller */
1850 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->mvdd_control
) {
1851 config
= VR_SVI2_PLANE_2
;
1852 table
->VRConfig
|= (config
<< VRCONF_MVDD_SHIFT
);
1853 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->mvdd_control
) {
1854 config
= VR_SMIO_PATTERN_2
;
1855 table
->VRConfig
|= (config
<< VRCONF_MVDD_SHIFT
);
1857 config
= VR_STATIC_VOLTAGE
;
1858 table
->VRConfig
|= (config
<< VRCONF_MVDD_SHIFT
);
1864 static int fiji_init_arb_table_index(struct pp_hwmgr
*hwmgr
)
1866 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1870 /* This is a read-modify-write on the first byte of the ARB table.
1871 * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure
1872 * is the field 'current'.
1873 * This solution is ugly, but we never write the whole table only
1874 * individual fields in it.
1875 * In reality this field should not be in that structure
1876 * but in a soft register.
1878 result
= smu7_read_smc_sram_dword(hwmgr
,
1879 smu_data
->smu7_data
.arb_table_start
, &tmp
, SMC_RAM_END
);
1885 tmp
|= ((uint32_t)MC_CG_ARB_FREQ_F1
) << 24;
1887 return smu7_write_smc_sram_dword(hwmgr
,
1888 smu_data
->smu7_data
.arb_table_start
, tmp
, SMC_RAM_END
);
1891 static int fiji_setup_dpm_led_config(struct pp_hwmgr
*hwmgr
)
1893 pp_atomctrl_voltage_table param_led_dpm
;
1897 result
= atomctrl_get_voltage_table_v3(hwmgr
,
1898 VOLTAGE_TYPE_LEDDPM
, VOLTAGE_OBJ_GPIO_LUT
,
1902 u32 tmp
= param_led_dpm
.mask_low
;
1904 for (i
= 0, j
= 0; i
< 32; i
++) {
1906 mask
|= (i
<< (8 * j
));
1914 smum_send_msg_to_smc_with_parameter(hwmgr
,
1915 PPSMC_MSG_LedConfig
,
1920 static int fiji_init_smc_table(struct pp_hwmgr
*hwmgr
)
1923 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1924 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1925 struct phm_ppt_v1_information
*table_info
=
1926 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1927 struct SMU73_Discrete_DpmTable
*table
= &(smu_data
->smc_state_table
);
1929 struct pp_atomctrl_gpio_pin_assignment gpio_pin
;
1931 fiji_initialize_power_tune_defaults(hwmgr
);
1933 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->voltage_control
)
1934 fiji_populate_smc_voltage_tables(hwmgr
, table
);
1936 table
->SystemFlags
= 0;
1938 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
1939 PHM_PlatformCaps_AutomaticDCTransition
))
1940 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GPIO_DC
;
1942 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
1943 PHM_PlatformCaps_StepVddc
))
1944 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_STEPVDDC
;
1946 if (data
->is_memory_gddr5
)
1947 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GDDR5
;
1949 if (data
->ulv_supported
&& table_info
->us_ulv_voltage_offset
) {
1950 result
= fiji_populate_ulv_state(hwmgr
, table
);
1951 PP_ASSERT_WITH_CODE(0 == result
,
1952 "Failed to initialize ULV state!", return result
);
1953 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1954 ixCG_ULV_PARAMETER
, 0x40035);
1957 result
= fiji_populate_smc_link_level(hwmgr
, table
);
1958 PP_ASSERT_WITH_CODE(0 == result
,
1959 "Failed to initialize Link Level!", return result
);
1961 result
= fiji_populate_all_graphic_levels(hwmgr
);
1962 PP_ASSERT_WITH_CODE(0 == result
,
1963 "Failed to initialize Graphics Level!", return result
);
1965 result
= fiji_populate_all_memory_levels(hwmgr
);
1966 PP_ASSERT_WITH_CODE(0 == result
,
1967 "Failed to initialize Memory Level!", return result
);
1969 result
= fiji_populate_smc_acpi_level(hwmgr
, table
);
1970 PP_ASSERT_WITH_CODE(0 == result
,
1971 "Failed to initialize ACPI Level!", return result
);
1973 result
= fiji_populate_smc_vce_level(hwmgr
, table
);
1974 PP_ASSERT_WITH_CODE(0 == result
,
1975 "Failed to initialize VCE Level!", return result
);
1977 result
= fiji_populate_smc_acp_level(hwmgr
, table
);
1978 PP_ASSERT_WITH_CODE(0 == result
,
1979 "Failed to initialize ACP Level!", return result
);
1981 /* Since only the initial state is completely set up at this point
1982 * (the other states are just copies of the boot state) we only
1983 * need to populate the ARB settings for the initial state.
1985 result
= fiji_program_memory_timing_parameters(hwmgr
);
1986 PP_ASSERT_WITH_CODE(0 == result
,
1987 "Failed to Write ARB settings for the initial state.", return result
);
1989 result
= fiji_populate_smc_uvd_level(hwmgr
, table
);
1990 PP_ASSERT_WITH_CODE(0 == result
,
1991 "Failed to initialize UVD Level!", return result
);
1993 result
= fiji_populate_smc_boot_level(hwmgr
, table
);
1994 PP_ASSERT_WITH_CODE(0 == result
,
1995 "Failed to initialize Boot Level!", return result
);
1997 result
= fiji_populate_smc_initailial_state(hwmgr
);
1998 PP_ASSERT_WITH_CODE(0 == result
,
1999 "Failed to initialize Boot State!", return result
);
2001 result
= fiji_populate_bapm_parameters_in_dpm_table(hwmgr
);
2002 PP_ASSERT_WITH_CODE(0 == result
,
2003 "Failed to populate BAPM Parameters!", return result
);
2005 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2006 PHM_PlatformCaps_ClockStretcher
)) {
2007 result
= fiji_populate_clock_stretcher_data_table(hwmgr
);
2008 PP_ASSERT_WITH_CODE(0 == result
,
2009 "Failed to populate Clock Stretcher Data Table!",
2013 table
->GraphicsVoltageChangeEnable
= 1;
2014 table
->GraphicsThermThrottleEnable
= 1;
2015 table
->GraphicsInterval
= 1;
2016 table
->VoltageInterval
= 1;
2017 table
->ThermalInterval
= 1;
2018 table
->TemperatureLimitHigh
=
2019 table_info
->cac_dtp_table
->usTargetOperatingTemp
*
2020 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2021 table
->TemperatureLimitLow
=
2022 (table_info
->cac_dtp_table
->usTargetOperatingTemp
- 1) *
2023 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2024 table
->MemoryVoltageChangeEnable
= 1;
2025 table
->MemoryInterval
= 1;
2026 table
->VoltageResponseTime
= 0;
2027 table
->PhaseResponseTime
= 0;
2028 table
->MemoryThermThrottleEnable
= 1;
2029 table
->PCIeBootLinkLevel
= 0; /* 0:Gen1 1:Gen2 2:Gen3*/
2030 table
->PCIeGenInterval
= 1;
2031 table
->VRConfig
= 0;
2033 result
= fiji_populate_vr_config(hwmgr
, table
);
2034 PP_ASSERT_WITH_CODE(0 == result
,
2035 "Failed to populate VRConfig setting!", return result
);
2036 data
->vr_config
= table
->VRConfig
;
2037 table
->ThermGpio
= 17;
2038 table
->SclkStepSize
= 0x4000;
2040 if (atomctrl_get_pp_assign_pin(hwmgr
, VDDC_VRHOT_GPIO_PINID
, &gpio_pin
)) {
2041 table
->VRHotGpio
= gpio_pin
.uc_gpio_pin_bit_shift
;
2042 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2043 PHM_PlatformCaps_RegulatorHot
);
2045 table
->VRHotGpio
= SMU7_UNUSED_GPIO_PIN
;
2046 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2047 PHM_PlatformCaps_RegulatorHot
);
2050 if (atomctrl_get_pp_assign_pin(hwmgr
, PP_AC_DC_SWITCH_GPIO_PINID
,
2052 table
->AcDcGpio
= gpio_pin
.uc_gpio_pin_bit_shift
;
2053 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2054 PHM_PlatformCaps_AutomaticDCTransition
);
2056 table
->AcDcGpio
= SMU7_UNUSED_GPIO_PIN
;
2057 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2058 PHM_PlatformCaps_AutomaticDCTransition
);
2061 /* Thermal Output GPIO */
2062 if (atomctrl_get_pp_assign_pin(hwmgr
, THERMAL_INT_OUTPUT_GPIO_PINID
,
2064 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2065 PHM_PlatformCaps_ThermalOutGPIO
);
2067 table
->ThermOutGpio
= gpio_pin
.uc_gpio_pin_bit_shift
;
2069 /* For porlarity read GPIOPAD_A with assigned Gpio pin
2070 * since VBIOS will program this register to set 'inactive state',
2071 * driver can then determine 'active state' from this and
2072 * program SMU with correct polarity
2074 table
->ThermOutPolarity
= (0 == (cgs_read_register(hwmgr
->device
, mmGPIOPAD_A
) &
2075 (1 << gpio_pin
.uc_gpio_pin_bit_shift
))) ? 1:0;
2076 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_ONLY
;
2078 /* if required, combine VRHot/PCC with thermal out GPIO */
2079 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2080 PHM_PlatformCaps_RegulatorHot
) &&
2081 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2082 PHM_PlatformCaps_CombinePCCWithThermalSignal
))
2083 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_VRHOT
;
2085 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2086 PHM_PlatformCaps_ThermalOutGPIO
);
2087 table
->ThermOutGpio
= 17;
2088 table
->ThermOutPolarity
= 1;
2089 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_DISABLE
;
2092 for (i
= 0; i
< SMU73_MAX_ENTRIES_SMIO
; i
++)
2093 table
->Smio
[i
] = PP_HOST_TO_SMC_UL(table
->Smio
[i
]);
2095 CONVERT_FROM_HOST_TO_SMC_UL(table
->SystemFlags
);
2096 CONVERT_FROM_HOST_TO_SMC_UL(table
->VRConfig
);
2097 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask1
);
2098 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask2
);
2099 CONVERT_FROM_HOST_TO_SMC_UL(table
->SclkStepSize
);
2100 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitHigh
);
2101 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitLow
);
2102 CONVERT_FROM_HOST_TO_SMC_US(table
->VoltageResponseTime
);
2103 CONVERT_FROM_HOST_TO_SMC_US(table
->PhaseResponseTime
);
2105 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2106 result
= smu7_copy_bytes_to_smc(hwmgr
,
2107 smu_data
->smu7_data
.dpm_table_start
+
2108 offsetof(SMU73_Discrete_DpmTable
, SystemFlags
),
2109 (uint8_t *)&(table
->SystemFlags
),
2110 sizeof(SMU73_Discrete_DpmTable
) - 3 * sizeof(SMU73_PIDController
),
2112 PP_ASSERT_WITH_CODE(0 == result
,
2113 "Failed to upload dpm data to SMC memory!", return result
);
2115 result
= fiji_init_arb_table_index(hwmgr
);
2116 PP_ASSERT_WITH_CODE(0 == result
,
2117 "Failed to upload arb data to SMC memory!", return result
);
2119 result
= fiji_populate_pm_fuses(hwmgr
);
2120 PP_ASSERT_WITH_CODE(0 == result
,
2121 "Failed to populate PM fuses to SMC memory!", return result
);
2123 result
= fiji_setup_dpm_led_config(hwmgr
);
2124 PP_ASSERT_WITH_CODE(0 == result
,
2125 "Failed to setup dpm led config", return result
);
2130 static int fiji_thermal_setup_fan_table(struct pp_hwmgr
*hwmgr
)
2132 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2134 SMU73_Discrete_FanTable fan_table
= { FDO_MODE_HARDWARE
};
2136 uint32_t t_diff1
, t_diff2
, pwm_diff1
, pwm_diff2
;
2137 uint16_t fdo_min
, slope1
, slope2
;
2138 uint32_t reference_clock
;
2142 if (hwmgr
->thermal_controller
.fanInfo
.bNoFan
) {
2143 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2144 PHM_PlatformCaps_MicrocodeFanControl
);
2148 if (smu_data
->smu7_data
.fan_table_start
== 0) {
2149 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2150 PHM_PlatformCaps_MicrocodeFanControl
);
2154 duty100
= PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
2155 CG_FDO_CTRL1
, FMAX_DUTY100
);
2158 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2159 PHM_PlatformCaps_MicrocodeFanControl
);
2163 tmp64
= hwmgr
->thermal_controller
.advanceFanControlParameters
.
2165 do_div(tmp64
, 10000);
2166 fdo_min
= (uint16_t)tmp64
;
2168 t_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
-
2169 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
;
2170 t_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
-
2171 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
;
2173 pwm_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
-
2174 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
;
2175 pwm_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
-
2176 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
;
2178 slope1
= (uint16_t)((50 + ((16 * duty100
* pwm_diff1
) / t_diff1
)) / 100);
2179 slope2
= (uint16_t)((50 + ((16 * duty100
* pwm_diff2
) / t_diff2
)) / 100);
2181 fan_table
.TempMin
= cpu_to_be16((50 + hwmgr
->
2182 thermal_controller
.advanceFanControlParameters
.usTMin
) / 100);
2183 fan_table
.TempMed
= cpu_to_be16((50 + hwmgr
->
2184 thermal_controller
.advanceFanControlParameters
.usTMed
) / 100);
2185 fan_table
.TempMax
= cpu_to_be16((50 + hwmgr
->
2186 thermal_controller
.advanceFanControlParameters
.usTMax
) / 100);
2188 fan_table
.Slope1
= cpu_to_be16(slope1
);
2189 fan_table
.Slope2
= cpu_to_be16(slope2
);
2191 fan_table
.FdoMin
= cpu_to_be16(fdo_min
);
2193 fan_table
.HystDown
= cpu_to_be16(hwmgr
->
2194 thermal_controller
.advanceFanControlParameters
.ucTHyst
);
2196 fan_table
.HystUp
= cpu_to_be16(1);
2198 fan_table
.HystSlope
= cpu_to_be16(1);
2200 fan_table
.TempRespLim
= cpu_to_be16(5);
2202 reference_clock
= amdgpu_asic_get_xclk((struct amdgpu_device
*)hwmgr
->adev
);
2204 fan_table
.RefreshPeriod
= cpu_to_be32((hwmgr
->
2205 thermal_controller
.advanceFanControlParameters
.ulCycleDelay
*
2206 reference_clock
) / 1600);
2208 fan_table
.FdoMax
= cpu_to_be16((uint16_t)duty100
);
2210 fan_table
.TempSrc
= (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(
2211 hwmgr
->device
, CGS_IND_REG__SMC
,
2212 CG_MULT_THERMAL_CTRL
, TEMP_SEL
);
2214 res
= smu7_copy_bytes_to_smc(hwmgr
, smu_data
->smu7_data
.fan_table_start
,
2215 (uint8_t *)&fan_table
, (uint32_t)sizeof(fan_table
),
2218 if (!res
&& hwmgr
->thermal_controller
.
2219 advanceFanControlParameters
.ucMinimumPWMLimit
)
2220 res
= smum_send_msg_to_smc_with_parameter(hwmgr
,
2221 PPSMC_MSG_SetFanMinPwm
,
2222 hwmgr
->thermal_controller
.
2223 advanceFanControlParameters
.ucMinimumPWMLimit
);
2225 if (!res
&& hwmgr
->thermal_controller
.
2226 advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
)
2227 res
= smum_send_msg_to_smc_with_parameter(hwmgr
,
2228 PPSMC_MSG_SetFanSclkTarget
,
2229 hwmgr
->thermal_controller
.
2230 advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
);
2233 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2234 PHM_PlatformCaps_MicrocodeFanControl
);
2240 static int fiji_thermal_avfs_enable(struct pp_hwmgr
*hwmgr
)
2242 if (!hwmgr
->avfs_supported
)
2245 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_EnableAvfs
);
2250 static int fiji_program_mem_timing_parameters(struct pp_hwmgr
*hwmgr
)
2252 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2254 if (data
->need_update_smu7_dpm_table
&
2255 (DPMTABLE_OD_UPDATE_SCLK
+ DPMTABLE_OD_UPDATE_MCLK
))
2256 return fiji_program_memory_timing_parameters(hwmgr
);
2261 static int fiji_update_sclk_threshold(struct pp_hwmgr
*hwmgr
)
2263 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2264 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2267 uint32_t low_sclk_interrupt_threshold
= 0;
2269 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2270 PHM_PlatformCaps_SclkThrottleLowNotification
)
2271 && (data
->low_sclk_interrupt_threshold
!= 0)) {
2272 low_sclk_interrupt_threshold
=
2273 data
->low_sclk_interrupt_threshold
;
2275 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold
);
2277 result
= smu7_copy_bytes_to_smc(
2279 smu_data
->smu7_data
.dpm_table_start
+
2280 offsetof(SMU73_Discrete_DpmTable
,
2281 LowSclkInterruptThreshold
),
2282 (uint8_t *)&low_sclk_interrupt_threshold
,
2286 result
= fiji_program_mem_timing_parameters(hwmgr
);
2287 PP_ASSERT_WITH_CODE((result
== 0),
2288 "Failed to program memory timing parameters!",
2293 static uint32_t fiji_get_offsetof(uint32_t type
, uint32_t member
)
2296 case SMU_SoftRegisters
:
2298 case HandshakeDisables
:
2299 return offsetof(SMU73_SoftRegisters
, HandshakeDisables
);
2300 case VoltageChangeTimeout
:
2301 return offsetof(SMU73_SoftRegisters
, VoltageChangeTimeout
);
2302 case AverageGraphicsActivity
:
2303 return offsetof(SMU73_SoftRegisters
, AverageGraphicsActivity
);
2304 case AverageMemoryActivity
:
2305 return offsetof(SMU73_SoftRegisters
, AverageMemoryActivity
);
2307 return offsetof(SMU73_SoftRegisters
, PreVBlankGap
);
2309 return offsetof(SMU73_SoftRegisters
, VBlankTimeout
);
2310 case UcodeLoadStatus
:
2311 return offsetof(SMU73_SoftRegisters
, UcodeLoadStatus
);
2312 case DRAM_LOG_ADDR_H
:
2313 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_ADDR_H
);
2314 case DRAM_LOG_ADDR_L
:
2315 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_ADDR_L
);
2316 case DRAM_LOG_PHY_ADDR_H
:
2317 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_PHY_ADDR_H
);
2318 case DRAM_LOG_PHY_ADDR_L
:
2319 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_PHY_ADDR_L
);
2320 case DRAM_LOG_BUFF_SIZE
:
2321 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_BUFF_SIZE
);
2324 case SMU_Discrete_DpmTable
:
2327 return offsetof(SMU73_Discrete_DpmTable
, UvdBootLevel
);
2329 return offsetof(SMU73_Discrete_DpmTable
, VceBootLevel
);
2330 case LowSclkInterruptThreshold
:
2331 return offsetof(SMU73_Discrete_DpmTable
, LowSclkInterruptThreshold
);
2335 pr_warn("can't get the offset of type %x member %x\n", type
, member
);
2339 static uint32_t fiji_get_mac_definition(uint32_t value
)
2342 case SMU_MAX_LEVELS_GRAPHICS
:
2343 return SMU73_MAX_LEVELS_GRAPHICS
;
2344 case SMU_MAX_LEVELS_MEMORY
:
2345 return SMU73_MAX_LEVELS_MEMORY
;
2346 case SMU_MAX_LEVELS_LINK
:
2347 return SMU73_MAX_LEVELS_LINK
;
2348 case SMU_MAX_ENTRIES_SMIO
:
2349 return SMU73_MAX_ENTRIES_SMIO
;
2350 case SMU_MAX_LEVELS_VDDC
:
2351 return SMU73_MAX_LEVELS_VDDC
;
2352 case SMU_MAX_LEVELS_VDDGFX
:
2353 return SMU73_MAX_LEVELS_VDDGFX
;
2354 case SMU_MAX_LEVELS_VDDCI
:
2355 return SMU73_MAX_LEVELS_VDDCI
;
2356 case SMU_MAX_LEVELS_MVDD
:
2357 return SMU73_MAX_LEVELS_MVDD
;
2360 pr_warn("can't get the mac of %x\n", value
);
2365 static int fiji_update_uvd_smc_table(struct pp_hwmgr
*hwmgr
)
2367 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2368 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2369 struct phm_ppt_v1_information
*table_info
=
2370 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2372 smu_data
->smc_state_table
.UvdBootLevel
= 0;
2373 if (table_info
->mm_dep_table
->count
> 0)
2374 smu_data
->smc_state_table
.UvdBootLevel
=
2375 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2376 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+ offsetof(SMU73_Discrete_DpmTable
,
2378 mm_boot_level_offset
/= 4;
2379 mm_boot_level_offset
*= 4;
2380 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2381 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2382 mm_boot_level_value
&= 0x00FFFFFF;
2383 mm_boot_level_value
|= smu_data
->smc_state_table
.UvdBootLevel
<< 24;
2384 cgs_write_ind_register(hwmgr
->device
,
2385 CGS_IND_REG__SMC
, mm_boot_level_offset
, mm_boot_level_value
);
2387 if (!phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2388 PHM_PlatformCaps_UVDDPM
) ||
2389 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2390 PHM_PlatformCaps_StablePState
))
2391 smum_send_msg_to_smc_with_parameter(hwmgr
,
2392 PPSMC_MSG_UVDDPM_SetEnabledMask
,
2393 (uint32_t)(1 << smu_data
->smc_state_table
.UvdBootLevel
));
2397 static int fiji_update_vce_smc_table(struct pp_hwmgr
*hwmgr
)
2399 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2400 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2401 struct phm_ppt_v1_information
*table_info
=
2402 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2404 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2405 PHM_PlatformCaps_StablePState
))
2406 smu_data
->smc_state_table
.VceBootLevel
=
2407 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2409 smu_data
->smc_state_table
.VceBootLevel
= 0;
2411 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2412 offsetof(SMU73_Discrete_DpmTable
, VceBootLevel
);
2413 mm_boot_level_offset
/= 4;
2414 mm_boot_level_offset
*= 4;
2415 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2416 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2417 mm_boot_level_value
&= 0xFF00FFFF;
2418 mm_boot_level_value
|= smu_data
->smc_state_table
.VceBootLevel
<< 16;
2419 cgs_write_ind_register(hwmgr
->device
,
2420 CGS_IND_REG__SMC
, mm_boot_level_offset
, mm_boot_level_value
);
2422 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
, PHM_PlatformCaps_StablePState
))
2423 smum_send_msg_to_smc_with_parameter(hwmgr
,
2424 PPSMC_MSG_VCEDPM_SetEnabledMask
,
2425 (uint32_t)1 << smu_data
->smc_state_table
.VceBootLevel
);
2429 static int fiji_update_smc_table(struct pp_hwmgr
*hwmgr
, uint32_t type
)
2433 fiji_update_uvd_smc_table(hwmgr
);
2436 fiji_update_vce_smc_table(hwmgr
);
2444 static int fiji_process_firmware_header(struct pp_hwmgr
*hwmgr
)
2446 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2447 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2452 result
= smu7_read_smc_sram_dword(hwmgr
,
2453 SMU7_FIRMWARE_HEADER_LOCATION
+
2454 offsetof(SMU73_Firmware_Header
, DpmTable
),
2458 smu_data
->smu7_data
.dpm_table_start
= tmp
;
2460 error
|= (0 != result
);
2462 result
= smu7_read_smc_sram_dword(hwmgr
,
2463 SMU7_FIRMWARE_HEADER_LOCATION
+
2464 offsetof(SMU73_Firmware_Header
, SoftRegisters
),
2468 data
->soft_regs_start
= tmp
;
2469 smu_data
->smu7_data
.soft_regs_start
= tmp
;
2472 error
|= (0 != result
);
2474 result
= smu7_read_smc_sram_dword(hwmgr
,
2475 SMU7_FIRMWARE_HEADER_LOCATION
+
2476 offsetof(SMU73_Firmware_Header
, mcRegisterTable
),
2480 smu_data
->smu7_data
.mc_reg_table_start
= tmp
;
2482 result
= smu7_read_smc_sram_dword(hwmgr
,
2483 SMU7_FIRMWARE_HEADER_LOCATION
+
2484 offsetof(SMU73_Firmware_Header
, FanTable
),
2488 smu_data
->smu7_data
.fan_table_start
= tmp
;
2490 error
|= (0 != result
);
2492 result
= smu7_read_smc_sram_dword(hwmgr
,
2493 SMU7_FIRMWARE_HEADER_LOCATION
+
2494 offsetof(SMU73_Firmware_Header
, mcArbDramTimingTable
),
2498 smu_data
->smu7_data
.arb_table_start
= tmp
;
2500 error
|= (0 != result
);
2502 result
= smu7_read_smc_sram_dword(hwmgr
,
2503 SMU7_FIRMWARE_HEADER_LOCATION
+
2504 offsetof(SMU73_Firmware_Header
, Version
),
2508 hwmgr
->microcode_version_info
.SMC
= tmp
;
2510 error
|= (0 != result
);
2512 return error
? -1 : 0;
2515 static int fiji_initialize_mc_reg_table(struct pp_hwmgr
*hwmgr
)
2518 /* Program additional LP registers
2519 * that are no longer programmed by VBIOS
2521 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING_LP
,
2522 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING
));
2523 cgs_write_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING_LP
,
2524 cgs_read_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING
));
2525 cgs_write_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2_LP
,
2526 cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2
));
2527 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1_LP
,
2528 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1
));
2529 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0_LP
,
2530 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0
));
2531 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1_LP
,
2532 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1
));
2533 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING_LP
,
2534 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING
));
2539 static bool fiji_is_dpm_running(struct pp_hwmgr
*hwmgr
)
2541 return (1 == PHM_READ_INDIRECT_FIELD(hwmgr
->device
,
2542 CGS_IND_REG__SMC
, FEATURE_STATUS
, VOLTAGE_CONTROLLER_ON
))
2546 static int fiji_update_dpm_settings(struct pp_hwmgr
*hwmgr
,
2547 void *profile_setting
)
2549 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2550 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)
2551 (hwmgr
->smu_backend
);
2552 struct profile_mode_setting
*setting
;
2553 struct SMU73_Discrete_GraphicsLevel
*levels
=
2554 smu_data
->smc_state_table
.GraphicsLevel
;
2555 uint32_t array
= smu_data
->smu7_data
.dpm_table_start
+
2556 offsetof(SMU73_Discrete_DpmTable
, GraphicsLevel
);
2558 uint32_t mclk_array
= smu_data
->smu7_data
.dpm_table_start
+
2559 offsetof(SMU73_Discrete_DpmTable
, MemoryLevel
);
2560 struct SMU73_Discrete_MemoryLevel
*mclk_levels
=
2561 smu_data
->smc_state_table
.MemoryLevel
;
2563 uint32_t offset
, up_hyst_offset
, down_hyst_offset
, clk_activity_offset
, tmp
;
2565 if (profile_setting
== NULL
)
2568 setting
= (struct profile_mode_setting
*)profile_setting
;
2570 if (setting
->bupdate_sclk
) {
2571 if (!data
->sclk_dpm_key_disabled
)
2572 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_SCLKDPM_FreezeLevel
);
2573 for (i
= 0; i
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; i
++) {
2574 if (levels
[i
].ActivityLevel
!=
2575 cpu_to_be16(setting
->sclk_activity
)) {
2576 levels
[i
].ActivityLevel
= cpu_to_be16(setting
->sclk_activity
);
2578 clk_activity_offset
= array
+ (sizeof(SMU73_Discrete_GraphicsLevel
) * i
)
2579 + offsetof(SMU73_Discrete_GraphicsLevel
, ActivityLevel
);
2580 offset
= clk_activity_offset
& ~0x3;
2581 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
2582 tmp
= phm_set_field_to_u32(clk_activity_offset
, tmp
, levels
[i
].ActivityLevel
, sizeof(uint16_t));
2583 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
2586 if (levels
[i
].UpHyst
!= setting
->sclk_up_hyst
||
2587 levels
[i
].DownHyst
!= setting
->sclk_down_hyst
) {
2588 levels
[i
].UpHyst
= setting
->sclk_up_hyst
;
2589 levels
[i
].DownHyst
= setting
->sclk_down_hyst
;
2590 up_hyst_offset
= array
+ (sizeof(SMU73_Discrete_GraphicsLevel
) * i
)
2591 + offsetof(SMU73_Discrete_GraphicsLevel
, UpHyst
);
2592 down_hyst_offset
= array
+ (sizeof(SMU73_Discrete_GraphicsLevel
) * i
)
2593 + offsetof(SMU73_Discrete_GraphicsLevel
, DownHyst
);
2594 offset
= up_hyst_offset
& ~0x3;
2595 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
2596 tmp
= phm_set_field_to_u32(up_hyst_offset
, tmp
, levels
[i
].UpHyst
, sizeof(uint8_t));
2597 tmp
= phm_set_field_to_u32(down_hyst_offset
, tmp
, levels
[i
].DownHyst
, sizeof(uint8_t));
2598 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
2601 if (!data
->sclk_dpm_key_disabled
)
2602 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_SCLKDPM_UnfreezeLevel
);
2605 if (setting
->bupdate_mclk
) {
2606 if (!data
->mclk_dpm_key_disabled
)
2607 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_MCLKDPM_FreezeLevel
);
2608 for (i
= 0; i
< smu_data
->smc_state_table
.MemoryDpmLevelCount
; i
++) {
2609 if (mclk_levels
[i
].ActivityLevel
!=
2610 cpu_to_be16(setting
->mclk_activity
)) {
2611 mclk_levels
[i
].ActivityLevel
= cpu_to_be16(setting
->mclk_activity
);
2613 clk_activity_offset
= mclk_array
+ (sizeof(SMU73_Discrete_MemoryLevel
) * i
)
2614 + offsetof(SMU73_Discrete_MemoryLevel
, ActivityLevel
);
2615 offset
= clk_activity_offset
& ~0x3;
2616 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
2617 tmp
= phm_set_field_to_u32(clk_activity_offset
, tmp
, mclk_levels
[i
].ActivityLevel
, sizeof(uint16_t));
2618 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
2621 if (mclk_levels
[i
].UpHyst
!= setting
->mclk_up_hyst
||
2622 mclk_levels
[i
].DownHyst
!= setting
->mclk_down_hyst
) {
2623 mclk_levels
[i
].UpHyst
= setting
->mclk_up_hyst
;
2624 mclk_levels
[i
].DownHyst
= setting
->mclk_down_hyst
;
2625 up_hyst_offset
= mclk_array
+ (sizeof(SMU73_Discrete_MemoryLevel
) * i
)
2626 + offsetof(SMU73_Discrete_MemoryLevel
, UpHyst
);
2627 down_hyst_offset
= mclk_array
+ (sizeof(SMU73_Discrete_MemoryLevel
) * i
)
2628 + offsetof(SMU73_Discrete_MemoryLevel
, DownHyst
);
2629 offset
= up_hyst_offset
& ~0x3;
2630 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
2631 tmp
= phm_set_field_to_u32(up_hyst_offset
, tmp
, mclk_levels
[i
].UpHyst
, sizeof(uint8_t));
2632 tmp
= phm_set_field_to_u32(down_hyst_offset
, tmp
, mclk_levels
[i
].DownHyst
, sizeof(uint8_t));
2633 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
2636 if (!data
->mclk_dpm_key_disabled
)
2637 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_MCLKDPM_UnfreezeLevel
);
2642 const struct pp_smumgr_func fiji_smu_funcs
= {
2644 .smu_init
= &fiji_smu_init
,
2645 .smu_fini
= &smu7_smu_fini
,
2646 .start_smu
= &fiji_start_smu
,
2647 .check_fw_load_finish
= &smu7_check_fw_load_finish
,
2648 .request_smu_load_fw
= &smu7_reload_firmware
,
2649 .request_smu_load_specific_fw
= NULL
,
2650 .send_msg_to_smc
= &smu7_send_msg_to_smc
,
2651 .send_msg_to_smc_with_parameter
= &smu7_send_msg_to_smc_with_parameter
,
2652 .download_pptable_settings
= NULL
,
2653 .upload_pptable_settings
= NULL
,
2654 .update_smc_table
= fiji_update_smc_table
,
2655 .get_offsetof
= fiji_get_offsetof
,
2656 .process_firmware_header
= fiji_process_firmware_header
,
2657 .init_smc_table
= fiji_init_smc_table
,
2658 .update_sclk_threshold
= fiji_update_sclk_threshold
,
2659 .thermal_setup_fan_table
= fiji_thermal_setup_fan_table
,
2660 .thermal_avfs_enable
= fiji_thermal_avfs_enable
,
2661 .populate_all_graphic_levels
= fiji_populate_all_graphic_levels
,
2662 .populate_all_memory_levels
= fiji_populate_all_memory_levels
,
2663 .get_mac_definition
= fiji_get_mac_definition
,
2664 .initialize_mc_reg_table
= fiji_initialize_mc_reg_table
,
2665 .is_dpm_running
= fiji_is_dpm_running
,
2666 .is_hw_avfs_present
= fiji_is_hw_avfs_present
,
2667 .update_dpm_settings
= fiji_update_dpm_settings
,