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 /* To initialize all clock gating before RLC loaded and running.*/
306 amdgpu_device_ip_set_clockgating_state(hwmgr
->adev
,
307 AMD_IP_BLOCK_TYPE_GFX
, AMD_CG_STATE_GATE
);
308 amdgpu_device_ip_set_clockgating_state(hwmgr
->adev
,
309 AMD_IP_BLOCK_TYPE_GMC
, AMD_CG_STATE_GATE
);
310 amdgpu_device_ip_set_clockgating_state(hwmgr
->adev
,
311 AMD_IP_BLOCK_TYPE_SDMA
, AMD_CG_STATE_GATE
);
312 amdgpu_device_ip_set_clockgating_state(hwmgr
->adev
,
313 AMD_IP_BLOCK_TYPE_COMMON
, AMD_CG_STATE_GATE
);
315 /* Setup SoftRegsStart here for register lookup in case
316 * DummyBackEnd is used and ProcessFirmwareHeader is not executed
318 smu7_read_smc_sram_dword(hwmgr
,
319 SMU7_FIRMWARE_HEADER_LOCATION
+
320 offsetof(SMU73_Firmware_Header
, SoftRegisters
),
321 &(priv
->smu7_data
.soft_regs_start
), 0x40000);
323 result
= smu7_request_smu_load_fw(hwmgr
);
328 static bool fiji_is_hw_avfs_present(struct pp_hwmgr
*hwmgr
)
332 uint32_t mask
= (1 << ((AVFS_EN_MSB
- AVFS_EN_LSB
) + 1)) - 1;
337 if (!atomctrl_read_efuse(hwmgr
, AVFS_EN_LSB
, AVFS_EN_MSB
,
345 static int fiji_smu_init(struct pp_hwmgr
*hwmgr
)
347 struct fiji_smumgr
*fiji_priv
= NULL
;
349 fiji_priv
= kzalloc(sizeof(struct fiji_smumgr
), GFP_KERNEL
);
351 if (fiji_priv
== NULL
)
354 hwmgr
->smu_backend
= fiji_priv
;
356 if (smu7_init(hwmgr
)) {
364 static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr
*hwmgr
,
365 struct phm_ppt_v1_clock_voltage_dependency_table
*dep_table
,
366 uint32_t clock
, uint32_t *voltage
, uint32_t *mvdd
)
370 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
371 *voltage
= *mvdd
= 0;
374 /* clock - voltage dependency table is empty table */
375 if (dep_table
->count
== 0)
378 for (i
= 0; i
< dep_table
->count
; i
++) {
379 /* find first sclk bigger than request */
380 if (dep_table
->entries
[i
].clk
>= clock
) {
381 *voltage
|= (dep_table
->entries
[i
].vddc
*
382 VOLTAGE_SCALE
) << VDDC_SHIFT
;
383 if (SMU7_VOLTAGE_CONTROL_NONE
== data
->vddci_control
)
384 *voltage
|= (data
->vbios_boot_state
.vddci_bootup_value
*
385 VOLTAGE_SCALE
) << VDDCI_SHIFT
;
386 else if (dep_table
->entries
[i
].vddci
)
387 *voltage
|= (dep_table
->entries
[i
].vddci
*
388 VOLTAGE_SCALE
) << VDDCI_SHIFT
;
390 vddci
= phm_find_closest_vddci(&(data
->vddci_voltage_table
),
391 (dep_table
->entries
[i
].vddc
-
393 *voltage
|= (vddci
* VOLTAGE_SCALE
) << VDDCI_SHIFT
;
396 if (SMU7_VOLTAGE_CONTROL_NONE
== data
->mvdd_control
)
397 *mvdd
= data
->vbios_boot_state
.mvdd_bootup_value
*
399 else if (dep_table
->entries
[i
].mvdd
)
400 *mvdd
= (uint32_t) dep_table
->entries
[i
].mvdd
*
403 *voltage
|= 1 << PHASES_SHIFT
;
408 /* sclk is bigger than max sclk in the dependence table */
409 *voltage
|= (dep_table
->entries
[i
- 1].vddc
* VOLTAGE_SCALE
) << VDDC_SHIFT
;
411 if (SMU7_VOLTAGE_CONTROL_NONE
== data
->vddci_control
)
412 *voltage
|= (data
->vbios_boot_state
.vddci_bootup_value
*
413 VOLTAGE_SCALE
) << VDDCI_SHIFT
;
414 else if (dep_table
->entries
[i
-1].vddci
) {
415 vddci
= phm_find_closest_vddci(&(data
->vddci_voltage_table
),
416 (dep_table
->entries
[i
].vddc
-
418 *voltage
|= (vddci
* VOLTAGE_SCALE
) << VDDCI_SHIFT
;
421 if (SMU7_VOLTAGE_CONTROL_NONE
== data
->mvdd_control
)
422 *mvdd
= data
->vbios_boot_state
.mvdd_bootup_value
* VOLTAGE_SCALE
;
423 else if (dep_table
->entries
[i
].mvdd
)
424 *mvdd
= (uint32_t) dep_table
->entries
[i
- 1].mvdd
* VOLTAGE_SCALE
;
430 static uint16_t scale_fan_gain_settings(uint16_t raw_setting
)
433 tmp
= raw_setting
* 4096 / 100;
434 return (uint16_t)tmp
;
437 static void get_scl_sda_value(uint8_t line
, uint8_t *scl
, uint8_t *sda
)
440 case SMU7_I2CLineID_DDC1
:
441 *scl
= SMU7_I2C_DDC1CLK
;
442 *sda
= SMU7_I2C_DDC1DATA
;
444 case SMU7_I2CLineID_DDC2
:
445 *scl
= SMU7_I2C_DDC2CLK
;
446 *sda
= SMU7_I2C_DDC2DATA
;
448 case SMU7_I2CLineID_DDC3
:
449 *scl
= SMU7_I2C_DDC3CLK
;
450 *sda
= SMU7_I2C_DDC3DATA
;
452 case SMU7_I2CLineID_DDC4
:
453 *scl
= SMU7_I2C_DDC4CLK
;
454 *sda
= SMU7_I2C_DDC4DATA
;
456 case SMU7_I2CLineID_DDC5
:
457 *scl
= SMU7_I2C_DDC5CLK
;
458 *sda
= SMU7_I2C_DDC5DATA
;
460 case SMU7_I2CLineID_DDC6
:
461 *scl
= SMU7_I2C_DDC6CLK
;
462 *sda
= SMU7_I2C_DDC6DATA
;
464 case SMU7_I2CLineID_SCLSDA
:
468 case SMU7_I2CLineID_DDCVGA
:
469 *scl
= SMU7_I2C_DDCVGACLK
;
470 *sda
= SMU7_I2C_DDCVGADATA
;
479 static void fiji_initialize_power_tune_defaults(struct pp_hwmgr
*hwmgr
)
481 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
482 struct phm_ppt_v1_information
*table_info
=
483 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
486 table_info
->cac_dtp_table
->usPowerTuneDataSetID
<= POWERTUNE_DEFAULT_SET_MAX
&&
487 table_info
->cac_dtp_table
->usPowerTuneDataSetID
)
488 smu_data
->power_tune_defaults
=
489 &fiji_power_tune_data_set_array
490 [table_info
->cac_dtp_table
->usPowerTuneDataSetID
- 1];
492 smu_data
->power_tune_defaults
= &fiji_power_tune_data_set_array
[0];
496 static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr
*hwmgr
)
499 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
500 const struct fiji_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
502 SMU73_Discrete_DpmTable
*dpm_table
= &(smu_data
->smc_state_table
);
504 struct phm_ppt_v1_information
*table_info
=
505 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
506 struct phm_cac_tdp_table
*cac_dtp_table
= table_info
->cac_dtp_table
;
507 struct pp_advance_fan_control_parameters
*fan_table
=
508 &hwmgr
->thermal_controller
.advanceFanControlParameters
;
509 uint8_t uc_scl
, uc_sda
;
511 /* TDP number of fraction bits are changed from 8 to 7 for Fiji
512 * as requested by SMC team
514 dpm_table
->DefaultTdp
= PP_HOST_TO_SMC_US(
515 (uint16_t)(cac_dtp_table
->usTDP
* 128));
516 dpm_table
->TargetTdp
= PP_HOST_TO_SMC_US(
517 (uint16_t)(cac_dtp_table
->usTDP
* 128));
519 PP_ASSERT_WITH_CODE(cac_dtp_table
->usTargetOperatingTemp
<= 255,
520 "Target Operating Temp is out of Range!",
523 dpm_table
->GpuTjMax
= (uint8_t)(cac_dtp_table
->usTargetOperatingTemp
);
524 dpm_table
->GpuTjHyst
= 8;
526 dpm_table
->DTEAmbientTempBase
= defaults
->DTEAmbientTempBase
;
528 /* The following are for new Fiji Multi-input fan/thermal control */
529 dpm_table
->TemperatureLimitEdge
= PP_HOST_TO_SMC_US(
530 cac_dtp_table
->usTargetOperatingTemp
* 256);
531 dpm_table
->TemperatureLimitHotspot
= PP_HOST_TO_SMC_US(
532 cac_dtp_table
->usTemperatureLimitHotspot
* 256);
533 dpm_table
->TemperatureLimitLiquid1
= PP_HOST_TO_SMC_US(
534 cac_dtp_table
->usTemperatureLimitLiquid1
* 256);
535 dpm_table
->TemperatureLimitLiquid2
= PP_HOST_TO_SMC_US(
536 cac_dtp_table
->usTemperatureLimitLiquid2
* 256);
537 dpm_table
->TemperatureLimitVrVddc
= PP_HOST_TO_SMC_US(
538 cac_dtp_table
->usTemperatureLimitVrVddc
* 256);
539 dpm_table
->TemperatureLimitVrMvdd
= PP_HOST_TO_SMC_US(
540 cac_dtp_table
->usTemperatureLimitVrMvdd
* 256);
541 dpm_table
->TemperatureLimitPlx
= PP_HOST_TO_SMC_US(
542 cac_dtp_table
->usTemperatureLimitPlx
* 256);
544 dpm_table
->FanGainEdge
= PP_HOST_TO_SMC_US(
545 scale_fan_gain_settings(fan_table
->usFanGainEdge
));
546 dpm_table
->FanGainHotspot
= PP_HOST_TO_SMC_US(
547 scale_fan_gain_settings(fan_table
->usFanGainHotspot
));
548 dpm_table
->FanGainLiquid
= PP_HOST_TO_SMC_US(
549 scale_fan_gain_settings(fan_table
->usFanGainLiquid
));
550 dpm_table
->FanGainVrVddc
= PP_HOST_TO_SMC_US(
551 scale_fan_gain_settings(fan_table
->usFanGainVrVddc
));
552 dpm_table
->FanGainVrMvdd
= PP_HOST_TO_SMC_US(
553 scale_fan_gain_settings(fan_table
->usFanGainVrMvdd
));
554 dpm_table
->FanGainPlx
= PP_HOST_TO_SMC_US(
555 scale_fan_gain_settings(fan_table
->usFanGainPlx
));
556 dpm_table
->FanGainHbm
= PP_HOST_TO_SMC_US(
557 scale_fan_gain_settings(fan_table
->usFanGainHbm
));
559 dpm_table
->Liquid1_I2C_address
= cac_dtp_table
->ucLiquid1_I2C_address
;
560 dpm_table
->Liquid2_I2C_address
= cac_dtp_table
->ucLiquid2_I2C_address
;
561 dpm_table
->Vr_I2C_address
= cac_dtp_table
->ucVr_I2C_address
;
562 dpm_table
->Plx_I2C_address
= cac_dtp_table
->ucPlx_I2C_address
;
564 get_scl_sda_value(cac_dtp_table
->ucLiquid_I2C_Line
, &uc_scl
, &uc_sda
);
565 dpm_table
->Liquid_I2C_LineSCL
= uc_scl
;
566 dpm_table
->Liquid_I2C_LineSDA
= uc_sda
;
568 get_scl_sda_value(cac_dtp_table
->ucVr_I2C_Line
, &uc_scl
, &uc_sda
);
569 dpm_table
->Vr_I2C_LineSCL
= uc_scl
;
570 dpm_table
->Vr_I2C_LineSDA
= uc_sda
;
572 get_scl_sda_value(cac_dtp_table
->ucPlx_I2C_Line
, &uc_scl
, &uc_sda
);
573 dpm_table
->Plx_I2C_LineSCL
= uc_scl
;
574 dpm_table
->Plx_I2C_LineSDA
= uc_sda
;
580 static int fiji_populate_svi_load_line(struct pp_hwmgr
*hwmgr
)
582 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
583 const struct fiji_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
585 smu_data
->power_tune_table
.SviLoadLineEn
= defaults
->SviLoadLineEn
;
586 smu_data
->power_tune_table
.SviLoadLineVddC
= defaults
->SviLoadLineVddC
;
587 smu_data
->power_tune_table
.SviLoadLineTrimVddC
= 3;
588 smu_data
->power_tune_table
.SviLoadLineOffsetVddC
= 0;
594 static int fiji_populate_tdc_limit(struct pp_hwmgr
*hwmgr
)
597 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
598 struct phm_ppt_v1_information
*table_info
=
599 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
600 const struct fiji_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
602 /* TDC number of fraction bits are changed from 8 to 7
603 * for Fiji as requested by SMC team
605 tdc_limit
= (uint16_t)(table_info
->cac_dtp_table
->usTDC
* 128);
606 smu_data
->power_tune_table
.TDC_VDDC_PkgLimit
=
607 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit
);
608 smu_data
->power_tune_table
.TDC_VDDC_ThrottleReleaseLimitPerc
=
609 defaults
->TDC_VDDC_ThrottleReleaseLimitPerc
;
610 smu_data
->power_tune_table
.TDC_MAWt
= defaults
->TDC_MAWt
;
615 static int fiji_populate_dw8(struct pp_hwmgr
*hwmgr
, uint32_t fuse_table_offset
)
617 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
618 const struct fiji_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
621 if (smu7_read_smc_sram_dword(hwmgr
,
623 offsetof(SMU73_Discrete_PmFuses
, TdcWaterfallCtl
),
624 (uint32_t *)&temp
, SMC_RAM_END
))
625 PP_ASSERT_WITH_CODE(false,
626 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
629 smu_data
->power_tune_table
.TdcWaterfallCtl
= defaults
->TdcWaterfallCtl
;
630 smu_data
->power_tune_table
.LPMLTemperatureMin
=
631 (uint8_t)((temp
>> 16) & 0xff);
632 smu_data
->power_tune_table
.LPMLTemperatureMax
=
633 (uint8_t)((temp
>> 8) & 0xff);
634 smu_data
->power_tune_table
.Reserved
= (uint8_t)(temp
& 0xff);
639 static int fiji_populate_temperature_scaler(struct pp_hwmgr
*hwmgr
)
642 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
644 /* Currently not used. Set all to zero. */
645 for (i
= 0; i
< 16; i
++)
646 smu_data
->power_tune_table
.LPMLTemperatureScaler
[i
] = 0;
651 static int fiji_populate_fuzzy_fan(struct pp_hwmgr
*hwmgr
)
653 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
655 if ((hwmgr
->thermal_controller
.advanceFanControlParameters
.
656 usFanOutputSensitivity
& (1 << 15)) ||
657 0 == hwmgr
->thermal_controller
.advanceFanControlParameters
.
658 usFanOutputSensitivity
)
659 hwmgr
->thermal_controller
.advanceFanControlParameters
.
660 usFanOutputSensitivity
= hwmgr
->thermal_controller
.
661 advanceFanControlParameters
.usDefaultFanOutputSensitivity
;
663 smu_data
->power_tune_table
.FuzzyFan_PwmSetDelta
=
664 PP_HOST_TO_SMC_US(hwmgr
->thermal_controller
.
665 advanceFanControlParameters
.usFanOutputSensitivity
);
669 static int fiji_populate_gnb_lpml(struct pp_hwmgr
*hwmgr
)
672 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
674 /* Currently not used. Set all to zero. */
675 for (i
= 0; i
< 16; i
++)
676 smu_data
->power_tune_table
.GnbLPML
[i
] = 0;
681 static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr
*hwmgr
)
683 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
684 struct phm_ppt_v1_information
*table_info
=
685 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
686 uint16_t HiSidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
;
687 uint16_t LoSidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
;
688 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
690 HiSidd
= (uint16_t)(cac_table
->usHighCACLeakage
/ 100 * 256);
691 LoSidd
= (uint16_t)(cac_table
->usLowCACLeakage
/ 100 * 256);
693 smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
=
694 CONVERT_FROM_HOST_TO_SMC_US(HiSidd
);
695 smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
=
696 CONVERT_FROM_HOST_TO_SMC_US(LoSidd
);
701 static int fiji_populate_pm_fuses(struct pp_hwmgr
*hwmgr
)
703 uint32_t pm_fuse_table_offset
;
704 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
706 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
707 PHM_PlatformCaps_PowerContainment
)) {
708 if (smu7_read_smc_sram_dword(hwmgr
,
709 SMU7_FIRMWARE_HEADER_LOCATION
+
710 offsetof(SMU73_Firmware_Header
, PmFuseTable
),
711 &pm_fuse_table_offset
, SMC_RAM_END
))
712 PP_ASSERT_WITH_CODE(false,
713 "Attempt to get pm_fuse_table_offset Failed!",
717 if (fiji_populate_svi_load_line(hwmgr
))
718 PP_ASSERT_WITH_CODE(false,
719 "Attempt to populate SviLoadLine Failed!",
722 if (fiji_populate_tdc_limit(hwmgr
))
723 PP_ASSERT_WITH_CODE(false,
724 "Attempt to populate TDCLimit Failed!", return -EINVAL
);
726 if (fiji_populate_dw8(hwmgr
, pm_fuse_table_offset
))
727 PP_ASSERT_WITH_CODE(false,
728 "Attempt to populate TdcWaterfallCtl, "
729 "LPMLTemperature Min and Max Failed!",
733 if (0 != fiji_populate_temperature_scaler(hwmgr
))
734 PP_ASSERT_WITH_CODE(false,
735 "Attempt to populate LPMLTemperatureScaler Failed!",
739 if (fiji_populate_fuzzy_fan(hwmgr
))
740 PP_ASSERT_WITH_CODE(false,
741 "Attempt to populate Fuzzy Fan Control parameters Failed!",
745 if (fiji_populate_gnb_lpml(hwmgr
))
746 PP_ASSERT_WITH_CODE(false,
747 "Attempt to populate GnbLPML Failed!",
751 if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr
))
752 PP_ASSERT_WITH_CODE(false,
753 "Attempt to populate BapmVddCBaseLeakage Hi and Lo "
754 "Sidd Failed!", return -EINVAL
);
756 if (smu7_copy_bytes_to_smc(hwmgr
, pm_fuse_table_offset
,
757 (uint8_t *)&smu_data
->power_tune_table
,
758 sizeof(struct SMU73_Discrete_PmFuses
), SMC_RAM_END
))
759 PP_ASSERT_WITH_CODE(false,
760 "Attempt to download PmFuseTable Failed!",
766 static int fiji_populate_cac_table(struct pp_hwmgr
*hwmgr
,
767 struct SMU73_Discrete_DpmTable
*table
)
771 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
772 struct phm_ppt_v1_information
*table_info
=
773 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
774 struct phm_ppt_v1_voltage_lookup_table
*lookup_table
=
775 table_info
->vddc_lookup_table
;
776 /* tables is already swapped, so in order to use the value from it,
777 * we need to swap it back.
778 * We are populating vddc CAC data to BapmVddc table
779 * in split and merged mode
782 for (count
= 0; count
< lookup_table
->count
; count
++) {
783 index
= phm_get_voltage_index(lookup_table
,
784 data
->vddc_voltage_table
.entries
[count
].value
);
785 table
->BapmVddcVidLoSidd
[count
] =
786 convert_to_vid(lookup_table
->entries
[index
].us_cac_low
);
787 table
->BapmVddcVidHiSidd
[count
] =
788 convert_to_vid(lookup_table
->entries
[index
].us_cac_high
);
794 static int fiji_populate_smc_voltage_tables(struct pp_hwmgr
*hwmgr
,
795 struct SMU73_Discrete_DpmTable
*table
)
799 result
= fiji_populate_cac_table(hwmgr
, table
);
800 PP_ASSERT_WITH_CODE(0 == result
,
801 "can not populate CAC voltage tables to SMC",
807 static int fiji_populate_ulv_level(struct pp_hwmgr
*hwmgr
,
808 struct SMU73_Discrete_Ulv
*state
)
812 struct phm_ppt_v1_information
*table_info
=
813 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
815 state
->CcPwrDynRm
= 0;
816 state
->CcPwrDynRm1
= 0;
818 state
->VddcOffset
= (uint16_t) table_info
->us_ulv_voltage_offset
;
819 state
->VddcOffsetVid
= (uint8_t)(table_info
->us_ulv_voltage_offset
*
820 VOLTAGE_VID_OFFSET_SCALE2
/ VOLTAGE_VID_OFFSET_SCALE1
);
822 state
->VddcPhase
= 1;
825 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm
);
826 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm1
);
827 CONVERT_FROM_HOST_TO_SMC_US(state
->VddcOffset
);
832 static int fiji_populate_ulv_state(struct pp_hwmgr
*hwmgr
,
833 struct SMU73_Discrete_DpmTable
*table
)
835 return fiji_populate_ulv_level(hwmgr
, &table
->Ulv
);
838 static int fiji_populate_smc_link_level(struct pp_hwmgr
*hwmgr
,
839 struct SMU73_Discrete_DpmTable
*table
)
841 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
842 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
843 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
846 /* Index (dpm_table->pcie_speed_table.count)
847 * is reserved for PCIE boot level. */
848 for (i
= 0; i
<= dpm_table
->pcie_speed_table
.count
; i
++) {
849 table
->LinkLevel
[i
].PcieGenSpeed
=
850 (uint8_t)dpm_table
->pcie_speed_table
.dpm_levels
[i
].value
;
851 table
->LinkLevel
[i
].PcieLaneCount
= (uint8_t)encode_pcie_lane_width(
852 dpm_table
->pcie_speed_table
.dpm_levels
[i
].param1
);
853 table
->LinkLevel
[i
].EnabledForActivity
= 1;
854 table
->LinkLevel
[i
].SPC
= (uint8_t)(data
->pcie_spc_cap
& 0xff);
855 table
->LinkLevel
[i
].DownThreshold
= PP_HOST_TO_SMC_UL(5);
856 table
->LinkLevel
[i
].UpThreshold
= PP_HOST_TO_SMC_UL(30);
859 smu_data
->smc_state_table
.LinkLevelCount
=
860 (uint8_t)dpm_table
->pcie_speed_table
.count
;
861 data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
=
862 phm_get_dpm_level_enable_mask_value(&dpm_table
->pcie_speed_table
);
867 static int fiji_calculate_sclk_params(struct pp_hwmgr
*hwmgr
,
868 uint32_t clock
, struct SMU73_Discrete_GraphicsLevel
*sclk
)
870 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
871 struct pp_atomctrl_clock_dividers_vi dividers
;
872 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
873 uint32_t spll_func_cntl_3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
874 uint32_t spll_func_cntl_4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
875 uint32_t cg_spll_spread_spectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
876 uint32_t cg_spll_spread_spectrum_2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
878 uint32_t ref_divider
;
882 /* get the engine clock dividers for this clock value */
883 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
, clock
, ÷rs
);
885 PP_ASSERT_WITH_CODE(result
== 0,
886 "Error retrieving Engine Clock dividers from VBIOS.",
889 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */
890 ref_clock
= atomctrl_get_reference_clock(hwmgr
);
891 ref_divider
= 1 + dividers
.uc_pll_ref_div
;
893 /* low 14 bits is fraction and high 12 bits is divider */
894 fbdiv
= dividers
.ul_fb_div
.ul_fb_divider
& 0x3FFFFFF;
896 /* SPLL_FUNC_CNTL setup */
897 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
898 SPLL_REF_DIV
, dividers
.uc_pll_ref_div
);
899 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
900 SPLL_PDIV_A
, dividers
.uc_pll_post_div
);
902 /* SPLL_FUNC_CNTL_3 setup*/
903 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
, CG_SPLL_FUNC_CNTL_3
,
906 /* set to use fractional accumulation*/
907 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
, CG_SPLL_FUNC_CNTL_3
,
910 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
911 PHM_PlatformCaps_EngineSpreadSpectrumSupport
)) {
912 struct pp_atomctrl_internal_ss_info ssInfo
;
914 uint32_t vco_freq
= clock
* dividers
.uc_pll_post_div
;
915 if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr
,
916 vco_freq
, &ssInfo
)) {
918 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
919 * ss_info.speed_spectrum_rate -- in unit of khz
921 * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2
923 uint32_t clk_s
= ref_clock
* 5 /
924 (ref_divider
* ssInfo
.speed_spectrum_rate
);
925 /* clkv = 2 * D * fbdiv / NS */
926 uint32_t clk_v
= 4 * ssInfo
.speed_spectrum_percentage
*
927 fbdiv
/ (clk_s
* 10000);
929 cg_spll_spread_spectrum
= PHM_SET_FIELD(cg_spll_spread_spectrum
,
930 CG_SPLL_SPREAD_SPECTRUM
, CLKS
, clk_s
);
931 cg_spll_spread_spectrum
= PHM_SET_FIELD(cg_spll_spread_spectrum
,
932 CG_SPLL_SPREAD_SPECTRUM
, SSEN
, 1);
933 cg_spll_spread_spectrum_2
= PHM_SET_FIELD(cg_spll_spread_spectrum_2
,
934 CG_SPLL_SPREAD_SPECTRUM_2
, CLKV
, clk_v
);
938 sclk
->SclkFrequency
= clock
;
939 sclk
->CgSpllFuncCntl3
= spll_func_cntl_3
;
940 sclk
->CgSpllFuncCntl4
= spll_func_cntl_4
;
941 sclk
->SpllSpreadSpectrum
= cg_spll_spread_spectrum
;
942 sclk
->SpllSpreadSpectrum2
= cg_spll_spread_spectrum_2
;
943 sclk
->SclkDid
= (uint8_t)dividers
.pll_post_divider
;
948 static int fiji_populate_single_graphic_level(struct pp_hwmgr
*hwmgr
,
949 uint32_t clock
, struct SMU73_Discrete_GraphicsLevel
*level
)
952 /* PP_Clocks minClocks; */
953 uint32_t threshold
, mvdd
;
954 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
955 struct phm_ppt_v1_information
*table_info
=
956 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
957 phm_ppt_v1_clock_voltage_dependency_table
*vdd_dep_table
= NULL
;
959 result
= fiji_calculate_sclk_params(hwmgr
, clock
, level
);
961 if (hwmgr
->od_enabled
)
962 vdd_dep_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)&data
->odn_dpm_table
.vdd_dependency_on_sclk
;
964 vdd_dep_table
= table_info
->vdd_dep_on_sclk
;
966 /* populate graphics levels */
967 result
= fiji_get_dependency_volt_by_clk(hwmgr
,
968 vdd_dep_table
, clock
,
969 (uint32_t *)(&level
->MinVoltage
), &mvdd
);
970 PP_ASSERT_WITH_CODE((0 == result
),
971 "can not find VDDC voltage value for "
972 "VDDC engine clock dependency table",
975 level
->SclkFrequency
= clock
;
976 level
->ActivityLevel
= data
->current_profile_setting
.sclk_activity
;
977 level
->CcPwrDynRm
= 0;
978 level
->CcPwrDynRm1
= 0;
979 level
->EnabledForActivity
= 0;
980 level
->EnabledForThrottle
= 1;
981 level
->UpHyst
= data
->current_profile_setting
.sclk_up_hyst
;
982 level
->DownHyst
= data
->current_profile_setting
.sclk_down_hyst
;
983 level
->VoltageDownHyst
= 0;
984 level
->PowerThrottle
= 0;
986 threshold
= clock
* data
->fast_watermark_threshold
/ 100;
988 data
->display_timing
.min_clock_in_sr
= hwmgr
->display_config
->min_core_set_clock_in_sr
;
990 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
, PHM_PlatformCaps_SclkDeepSleep
))
991 level
->DeepSleepDivId
= smu7_get_sleep_divider_id_from_clock(clock
,
992 hwmgr
->display_config
->min_core_set_clock_in_sr
);
995 /* Default to slow, highest DPM level will be
996 * set to PPSMC_DISPLAY_WATERMARK_LOW later.
998 level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1000 CONVERT_FROM_HOST_TO_SMC_UL(level
->MinVoltage
);
1001 CONVERT_FROM_HOST_TO_SMC_UL(level
->SclkFrequency
);
1002 CONVERT_FROM_HOST_TO_SMC_US(level
->ActivityLevel
);
1003 CONVERT_FROM_HOST_TO_SMC_UL(level
->CgSpllFuncCntl3
);
1004 CONVERT_FROM_HOST_TO_SMC_UL(level
->CgSpllFuncCntl4
);
1005 CONVERT_FROM_HOST_TO_SMC_UL(level
->SpllSpreadSpectrum
);
1006 CONVERT_FROM_HOST_TO_SMC_UL(level
->SpllSpreadSpectrum2
);
1007 CONVERT_FROM_HOST_TO_SMC_UL(level
->CcPwrDynRm
);
1008 CONVERT_FROM_HOST_TO_SMC_UL(level
->CcPwrDynRm1
);
1013 static int fiji_populate_all_graphic_levels(struct pp_hwmgr
*hwmgr
)
1015 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1016 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1018 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
1019 struct phm_ppt_v1_information
*table_info
=
1020 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1021 struct phm_ppt_v1_pcie_table
*pcie_table
= table_info
->pcie_table
;
1022 uint8_t pcie_entry_cnt
= (uint8_t) data
->dpm_table
.pcie_speed_table
.count
;
1024 uint32_t array
= smu_data
->smu7_data
.dpm_table_start
+
1025 offsetof(SMU73_Discrete_DpmTable
, GraphicsLevel
);
1026 uint32_t array_size
= sizeof(struct SMU73_Discrete_GraphicsLevel
) *
1027 SMU73_MAX_LEVELS_GRAPHICS
;
1028 struct SMU73_Discrete_GraphicsLevel
*levels
=
1029 smu_data
->smc_state_table
.GraphicsLevel
;
1030 uint32_t i
, max_entry
;
1031 uint8_t hightest_pcie_level_enabled
= 0,
1032 lowest_pcie_level_enabled
= 0,
1033 mid_pcie_level_enabled
= 0,
1036 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++) {
1037 result
= fiji_populate_single_graphic_level(hwmgr
,
1038 dpm_table
->sclk_table
.dpm_levels
[i
].value
,
1043 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
1045 levels
[i
].DeepSleepDivId
= 0;
1048 /* Only enable level 0 for now.*/
1049 levels
[0].EnabledForActivity
= 1;
1051 /* set highest level watermark to high */
1052 levels
[dpm_table
->sclk_table
.count
- 1].DisplayWatermark
=
1053 PPSMC_DISPLAY_WATERMARK_HIGH
;
1055 smu_data
->smc_state_table
.GraphicsDpmLevelCount
=
1056 (uint8_t)dpm_table
->sclk_table
.count
;
1057 data
->dpm_level_enable_mask
.sclk_dpm_enable_mask
=
1058 phm_get_dpm_level_enable_mask_value(&dpm_table
->sclk_table
);
1060 if (pcie_table
!= NULL
) {
1061 PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt
),
1062 "There must be 1 or more PCIE levels defined in PPTable.",
1064 max_entry
= pcie_entry_cnt
- 1;
1065 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++)
1066 levels
[i
].pcieDpmLevel
=
1067 (uint8_t) ((i
< max_entry
) ? i
: max_entry
);
1069 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
1070 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
1071 (1 << (hightest_pcie_level_enabled
+ 1))) != 0))
1072 hightest_pcie_level_enabled
++;
1074 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
1075 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
1076 (1 << lowest_pcie_level_enabled
)) == 0))
1077 lowest_pcie_level_enabled
++;
1079 while ((count
< hightest_pcie_level_enabled
) &&
1080 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
1081 (1 << (lowest_pcie_level_enabled
+ 1 + count
))) == 0))
1084 mid_pcie_level_enabled
= (lowest_pcie_level_enabled
+ 1 + count
) <
1085 hightest_pcie_level_enabled
?
1086 (lowest_pcie_level_enabled
+ 1 + count
) :
1087 hightest_pcie_level_enabled
;
1089 /* set pcieDpmLevel to hightest_pcie_level_enabled */
1090 for (i
= 2; i
< dpm_table
->sclk_table
.count
; i
++)
1091 levels
[i
].pcieDpmLevel
= hightest_pcie_level_enabled
;
1093 /* set pcieDpmLevel to lowest_pcie_level_enabled */
1094 levels
[0].pcieDpmLevel
= lowest_pcie_level_enabled
;
1096 /* set pcieDpmLevel to mid_pcie_level_enabled */
1097 levels
[1].pcieDpmLevel
= mid_pcie_level_enabled
;
1099 /* level count will send to smc once at init smc table and never change */
1100 result
= smu7_copy_bytes_to_smc(hwmgr
, array
, (uint8_t *)levels
,
1101 (uint32_t)array_size
, SMC_RAM_END
);
1108 * MCLK Frequency Ratio
1109 * SEQ_CG_RESP Bit[31:24] - 0x0
1110 * Bit[27:24] \96 DDR3 Frequency ratio
1111 * 0x0 <= 100MHz, 450 < 0x8 <= 500MHz
1112 * 100 < 0x1 <= 150MHz, 500 < 0x9 <= 550MHz
1113 * 150 < 0x2 <= 200MHz, 550 < 0xA <= 600MHz
1114 * 200 < 0x3 <= 250MHz, 600 < 0xB <= 650MHz
1115 * 250 < 0x4 <= 300MHz, 650 < 0xC <= 700MHz
1116 * 300 < 0x5 <= 350MHz, 700 < 0xD <= 750MHz
1117 * 350 < 0x6 <= 400MHz, 750 < 0xE <= 800MHz
1118 * 400 < 0x7 <= 450MHz, 800 < 0xF
1120 static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock
)
1122 if (mem_clock
<= 10000)
1124 if (mem_clock
<= 15000)
1126 if (mem_clock
<= 20000)
1128 if (mem_clock
<= 25000)
1130 if (mem_clock
<= 30000)
1132 if (mem_clock
<= 35000)
1134 if (mem_clock
<= 40000)
1136 if (mem_clock
<= 45000)
1138 if (mem_clock
<= 50000)
1140 if (mem_clock
<= 55000)
1142 if (mem_clock
<= 60000)
1144 if (mem_clock
<= 65000)
1146 if (mem_clock
<= 70000)
1148 if (mem_clock
<= 75000)
1150 if (mem_clock
<= 80000)
1152 /* mem_clock > 800MHz */
1156 static int fiji_calculate_mclk_params(struct pp_hwmgr
*hwmgr
,
1157 uint32_t clock
, struct SMU73_Discrete_MemoryLevel
*mclk
)
1159 struct pp_atomctrl_memory_clock_param mem_param
;
1162 result
= atomctrl_get_memory_pll_dividers_vi(hwmgr
, clock
, &mem_param
);
1163 PP_ASSERT_WITH_CODE((0 == result
),
1164 "Failed to get Memory PLL Dividers.",
1167 /* Save the result data to outpupt memory level structure */
1168 mclk
->MclkFrequency
= clock
;
1169 mclk
->MclkDivider
= (uint8_t)mem_param
.mpll_post_divider
;
1170 mclk
->FreqRange
= fiji_get_mclk_frequency_ratio(clock
);
1175 static int fiji_populate_single_memory_level(struct pp_hwmgr
*hwmgr
,
1176 uint32_t clock
, struct SMU73_Discrete_MemoryLevel
*mem_level
)
1178 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1179 struct phm_ppt_v1_information
*table_info
=
1180 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1182 uint32_t mclk_stutter_mode_threshold
= 60000;
1183 phm_ppt_v1_clock_voltage_dependency_table
*vdd_dep_table
= NULL
;
1185 if (hwmgr
->od_enabled
)
1186 vdd_dep_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)&data
->odn_dpm_table
.vdd_dependency_on_mclk
;
1188 vdd_dep_table
= table_info
->vdd_dep_on_mclk
;
1190 if (vdd_dep_table
) {
1191 result
= fiji_get_dependency_volt_by_clk(hwmgr
,
1192 vdd_dep_table
, clock
,
1193 (uint32_t *)(&mem_level
->MinVoltage
), &mem_level
->MinMvdd
);
1194 PP_ASSERT_WITH_CODE((0 == result
),
1195 "can not find MinVddc voltage value from memory "
1196 "VDDC voltage dependency table", return result
);
1199 mem_level
->EnabledForThrottle
= 1;
1200 mem_level
->EnabledForActivity
= 0;
1201 mem_level
->UpHyst
= data
->current_profile_setting
.mclk_up_hyst
;
1202 mem_level
->DownHyst
= data
->current_profile_setting
.mclk_down_hyst
;
1203 mem_level
->VoltageDownHyst
= 0;
1204 mem_level
->ActivityLevel
= data
->current_profile_setting
.mclk_activity
;
1205 mem_level
->StutterEnable
= false;
1207 mem_level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1209 /* enable stutter mode if all the follow condition applied
1210 * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI,
1211 * &(data->DisplayTiming.numExistingDisplays));
1213 data
->display_timing
.num_existing_displays
= 1;
1215 if (mclk_stutter_mode_threshold
&&
1216 (clock
<= mclk_stutter_mode_threshold
) &&
1217 (!data
->is_uvd_enabled
) &&
1218 (PHM_READ_FIELD(hwmgr
->device
, DPG_PIPE_STUTTER_CONTROL
,
1219 STUTTER_ENABLE
) & 0x1))
1220 mem_level
->StutterEnable
= true;
1222 result
= fiji_calculate_mclk_params(hwmgr
, clock
, mem_level
);
1224 CONVERT_FROM_HOST_TO_SMC_UL(mem_level
->MinMvdd
);
1225 CONVERT_FROM_HOST_TO_SMC_UL(mem_level
->MclkFrequency
);
1226 CONVERT_FROM_HOST_TO_SMC_US(mem_level
->ActivityLevel
);
1227 CONVERT_FROM_HOST_TO_SMC_UL(mem_level
->MinVoltage
);
1232 static int fiji_populate_all_memory_levels(struct pp_hwmgr
*hwmgr
)
1234 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1235 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1236 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
1238 /* populate MCLK dpm table to SMU7 */
1239 uint32_t array
= smu_data
->smu7_data
.dpm_table_start
+
1240 offsetof(SMU73_Discrete_DpmTable
, MemoryLevel
);
1241 uint32_t array_size
= sizeof(SMU73_Discrete_MemoryLevel
) *
1242 SMU73_MAX_LEVELS_MEMORY
;
1243 struct SMU73_Discrete_MemoryLevel
*levels
=
1244 smu_data
->smc_state_table
.MemoryLevel
;
1247 for (i
= 0; i
< dpm_table
->mclk_table
.count
; i
++) {
1248 PP_ASSERT_WITH_CODE((0 != dpm_table
->mclk_table
.dpm_levels
[i
].value
),
1249 "can not populate memory level as memory clock is zero",
1251 result
= fiji_populate_single_memory_level(hwmgr
,
1252 dpm_table
->mclk_table
.dpm_levels
[i
].value
,
1258 /* Only enable level 0 for now. */
1259 levels
[0].EnabledForActivity
= 1;
1261 /* in order to prevent MC activity from stutter mode to push DPM up.
1262 * the UVD change complements this by putting the MCLK in
1263 * a higher state by default such that we are not effected by
1264 * up threshold or and MCLK DPM latency.
1266 levels
[0].ActivityLevel
= (uint16_t)data
->mclk_dpm0_activity_target
;
1267 CONVERT_FROM_HOST_TO_SMC_US(levels
[0].ActivityLevel
);
1269 smu_data
->smc_state_table
.MemoryDpmLevelCount
=
1270 (uint8_t)dpm_table
->mclk_table
.count
;
1271 data
->dpm_level_enable_mask
.mclk_dpm_enable_mask
=
1272 phm_get_dpm_level_enable_mask_value(&dpm_table
->mclk_table
);
1273 /* set highest level watermark to high */
1274 levels
[dpm_table
->mclk_table
.count
- 1].DisplayWatermark
=
1275 PPSMC_DISPLAY_WATERMARK_HIGH
;
1277 /* level count will send to smc once at init smc table and never change */
1278 result
= smu7_copy_bytes_to_smc(hwmgr
, array
, (uint8_t *)levels
,
1279 (uint32_t)array_size
, SMC_RAM_END
);
1284 static int fiji_populate_mvdd_value(struct pp_hwmgr
*hwmgr
,
1285 uint32_t mclk
, SMIO_Pattern
*smio_pat
)
1287 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1288 struct phm_ppt_v1_information
*table_info
=
1289 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1292 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->mvdd_control
) {
1293 /* find mvdd value which clock is more than request */
1294 for (i
= 0; i
< table_info
->vdd_dep_on_mclk
->count
; i
++) {
1295 if (mclk
<= table_info
->vdd_dep_on_mclk
->entries
[i
].clk
) {
1296 smio_pat
->Voltage
= data
->mvdd_voltage_table
.entries
[i
].value
;
1300 PP_ASSERT_WITH_CODE(i
< table_info
->vdd_dep_on_mclk
->count
,
1301 "MVDD Voltage is outside the supported range.",
1309 static int fiji_populate_smc_acpi_level(struct pp_hwmgr
*hwmgr
,
1310 SMU73_Discrete_DpmTable
*table
)
1313 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1314 struct phm_ppt_v1_information
*table_info
=
1315 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1316 struct pp_atomctrl_clock_dividers_vi dividers
;
1317 SMIO_Pattern vol_level
;
1320 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
1321 uint32_t spll_func_cntl_2
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_2
;
1323 table
->ACPILevel
.Flags
&= ~PPSMC_SWSTATE_FLAG_DC
;
1325 if (!data
->sclk_dpm_key_disabled
) {
1326 /* Get MinVoltage and Frequency from DPM0,
1327 * already converted to SMC_UL */
1328 table
->ACPILevel
.SclkFrequency
=
1329 data
->dpm_table
.sclk_table
.dpm_levels
[0].value
;
1330 result
= fiji_get_dependency_volt_by_clk(hwmgr
,
1331 table_info
->vdd_dep_on_sclk
,
1332 table
->ACPILevel
.SclkFrequency
,
1333 (uint32_t *)(&table
->ACPILevel
.MinVoltage
), &mvdd
);
1334 PP_ASSERT_WITH_CODE((0 == result
),
1335 "Cannot find ACPI VDDC voltage value " \
1336 "in Clock Dependency Table",
1339 table
->ACPILevel
.SclkFrequency
=
1340 data
->vbios_boot_state
.sclk_bootup_value
;
1341 table
->ACPILevel
.MinVoltage
=
1342 data
->vbios_boot_state
.vddc_bootup_value
* VOLTAGE_SCALE
;
1345 /* get the engine clock dividers for this clock value */
1346 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
,
1347 table
->ACPILevel
.SclkFrequency
, ÷rs
);
1348 PP_ASSERT_WITH_CODE(result
== 0,
1349 "Error retrieving Engine Clock dividers from VBIOS.",
1352 table
->ACPILevel
.SclkDid
= (uint8_t)dividers
.pll_post_divider
;
1353 table
->ACPILevel
.DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1354 table
->ACPILevel
.DeepSleepDivId
= 0;
1356 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1358 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1360 spll_func_cntl_2
= PHM_SET_FIELD(spll_func_cntl_2
, CG_SPLL_FUNC_CNTL_2
,
1363 table
->ACPILevel
.CgSpllFuncCntl
= spll_func_cntl
;
1364 table
->ACPILevel
.CgSpllFuncCntl2
= spll_func_cntl_2
;
1365 table
->ACPILevel
.CgSpllFuncCntl3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
1366 table
->ACPILevel
.CgSpllFuncCntl4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
1367 table
->ACPILevel
.SpllSpreadSpectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
1368 table
->ACPILevel
.SpllSpreadSpectrum2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
1369 table
->ACPILevel
.CcPwrDynRm
= 0;
1370 table
->ACPILevel
.CcPwrDynRm1
= 0;
1372 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.Flags
);
1373 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SclkFrequency
);
1374 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.MinVoltage
);
1375 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl
);
1376 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl2
);
1377 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl3
);
1378 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl4
);
1379 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum
);
1380 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum2
);
1381 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm
);
1382 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm1
);
1384 if (!data
->mclk_dpm_key_disabled
) {
1385 /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */
1386 table
->MemoryACPILevel
.MclkFrequency
=
1387 data
->dpm_table
.mclk_table
.dpm_levels
[0].value
;
1388 result
= fiji_get_dependency_volt_by_clk(hwmgr
,
1389 table_info
->vdd_dep_on_mclk
,
1390 table
->MemoryACPILevel
.MclkFrequency
,
1391 (uint32_t *)(&table
->MemoryACPILevel
.MinVoltage
), &mvdd
);
1392 PP_ASSERT_WITH_CODE((0 == result
),
1393 "Cannot find ACPI VDDCI voltage value in Clock Dependency Table",
1396 table
->MemoryACPILevel
.MclkFrequency
=
1397 data
->vbios_boot_state
.mclk_bootup_value
;
1398 table
->MemoryACPILevel
.MinVoltage
=
1399 data
->vbios_boot_state
.vddci_bootup_value
* VOLTAGE_SCALE
;
1403 if ((SMU7_VOLTAGE_CONTROL_NONE
== data
->mvdd_control
) ||
1404 (data
->mclk_dpm_key_disabled
))
1405 us_mvdd
= data
->vbios_boot_state
.mvdd_bootup_value
;
1407 if (!fiji_populate_mvdd_value(hwmgr
,
1408 data
->dpm_table
.mclk_table
.dpm_levels
[0].value
,
1410 us_mvdd
= vol_level
.Voltage
;
1413 table
->MemoryACPILevel
.MinMvdd
=
1414 PP_HOST_TO_SMC_UL(us_mvdd
* VOLTAGE_SCALE
);
1416 table
->MemoryACPILevel
.EnabledForThrottle
= 0;
1417 table
->MemoryACPILevel
.EnabledForActivity
= 0;
1418 table
->MemoryACPILevel
.UpHyst
= 0;
1419 table
->MemoryACPILevel
.DownHyst
= 100;
1420 table
->MemoryACPILevel
.VoltageDownHyst
= 0;
1421 table
->MemoryACPILevel
.ActivityLevel
=
1422 PP_HOST_TO_SMC_US(data
->current_profile_setting
.mclk_activity
);
1424 table
->MemoryACPILevel
.StutterEnable
= false;
1425 CONVERT_FROM_HOST_TO_SMC_UL(table
->MemoryACPILevel
.MclkFrequency
);
1426 CONVERT_FROM_HOST_TO_SMC_UL(table
->MemoryACPILevel
.MinVoltage
);
1431 static int fiji_populate_smc_vce_level(struct pp_hwmgr
*hwmgr
,
1432 SMU73_Discrete_DpmTable
*table
)
1434 int result
= -EINVAL
;
1436 struct pp_atomctrl_clock_dividers_vi dividers
;
1437 struct phm_ppt_v1_information
*table_info
=
1438 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1439 struct phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1440 table_info
->mm_dep_table
;
1442 table
->VceLevelCount
= (uint8_t)(mm_table
->count
);
1443 table
->VceBootLevel
= 0;
1445 for (count
= 0; count
< table
->VceLevelCount
; count
++) {
1446 table
->VceLevel
[count
].Frequency
= mm_table
->entries
[count
].eclk
;
1447 table
->VceLevel
[count
].MinVoltage
= 0;
1448 table
->VceLevel
[count
].MinVoltage
|=
1449 (mm_table
->entries
[count
].vddc
* VOLTAGE_SCALE
) << VDDC_SHIFT
;
1450 table
->VceLevel
[count
].MinVoltage
|=
1451 ((mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
) *
1452 VOLTAGE_SCALE
) << VDDCI_SHIFT
;
1453 table
->VceLevel
[count
].MinVoltage
|= 1 << PHASES_SHIFT
;
1455 /*retrieve divider value for VBIOS */
1456 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1457 table
->VceLevel
[count
].Frequency
, ÷rs
);
1458 PP_ASSERT_WITH_CODE((0 == result
),
1459 "can not find divide id for VCE engine clock",
1462 table
->VceLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1464 CONVERT_FROM_HOST_TO_SMC_UL(table
->VceLevel
[count
].Frequency
);
1465 CONVERT_FROM_HOST_TO_SMC_UL(table
->VceLevel
[count
].MinVoltage
);
1470 static int fiji_populate_smc_acp_level(struct pp_hwmgr
*hwmgr
,
1471 SMU73_Discrete_DpmTable
*table
)
1473 int result
= -EINVAL
;
1475 struct pp_atomctrl_clock_dividers_vi dividers
;
1476 struct phm_ppt_v1_information
*table_info
=
1477 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1478 struct phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1479 table_info
->mm_dep_table
;
1481 table
->AcpLevelCount
= (uint8_t)(mm_table
->count
);
1482 table
->AcpBootLevel
= 0;
1484 for (count
= 0; count
< table
->AcpLevelCount
; count
++) {
1485 table
->AcpLevel
[count
].Frequency
= mm_table
->entries
[count
].aclk
;
1486 table
->AcpLevel
[count
].MinVoltage
|= (mm_table
->entries
[count
].vddc
*
1487 VOLTAGE_SCALE
) << VDDC_SHIFT
;
1488 table
->AcpLevel
[count
].MinVoltage
|= ((mm_table
->entries
[count
].vddc
-
1489 VDDC_VDDCI_DELTA
) * VOLTAGE_SCALE
) << VDDCI_SHIFT
;
1490 table
->AcpLevel
[count
].MinVoltage
|= 1 << PHASES_SHIFT
;
1492 /* retrieve divider value for VBIOS */
1493 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1494 table
->AcpLevel
[count
].Frequency
, ÷rs
);
1495 PP_ASSERT_WITH_CODE((0 == result
),
1496 "can not find divide id for engine clock", return result
);
1498 table
->AcpLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1500 CONVERT_FROM_HOST_TO_SMC_UL(table
->AcpLevel
[count
].Frequency
);
1501 CONVERT_FROM_HOST_TO_SMC_UL(table
->AcpLevel
[count
].MinVoltage
);
1506 static int fiji_populate_memory_timing_parameters(struct pp_hwmgr
*hwmgr
,
1507 int32_t eng_clock
, int32_t mem_clock
,
1508 struct SMU73_Discrete_MCArbDramTimingTableEntry
*arb_regs
)
1510 uint32_t dram_timing
;
1511 uint32_t dram_timing2
;
1513 ULONG state
, trrds
, trrdl
;
1516 result
= atomctrl_set_engine_dram_timings_rv770(hwmgr
,
1517 eng_clock
, mem_clock
);
1518 PP_ASSERT_WITH_CODE(result
== 0,
1519 "Error calling VBIOS to set DRAM_TIMING.", return result
);
1521 dram_timing
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING
);
1522 dram_timing2
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING2
);
1523 burstTime
= cgs_read_register(hwmgr
->device
, mmMC_ARB_BURST_TIME
);
1525 state
= PHM_GET_FIELD(burstTime
, MC_ARB_BURST_TIME
, STATE0
);
1526 trrds
= PHM_GET_FIELD(burstTime
, MC_ARB_BURST_TIME
, TRRDS0
);
1527 trrdl
= PHM_GET_FIELD(burstTime
, MC_ARB_BURST_TIME
, TRRDL0
);
1529 arb_regs
->McArbDramTiming
= PP_HOST_TO_SMC_UL(dram_timing
);
1530 arb_regs
->McArbDramTiming2
= PP_HOST_TO_SMC_UL(dram_timing2
);
1531 arb_regs
->McArbBurstTime
= (uint8_t)burstTime
;
1532 arb_regs
->TRRDS
= (uint8_t)trrds
;
1533 arb_regs
->TRRDL
= (uint8_t)trrdl
;
1538 static int fiji_program_memory_timing_parameters(struct pp_hwmgr
*hwmgr
)
1540 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1541 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1542 struct SMU73_Discrete_MCArbDramTimingTable arb_regs
;
1546 for (i
= 0; i
< data
->dpm_table
.sclk_table
.count
; i
++) {
1547 for (j
= 0; j
< data
->dpm_table
.mclk_table
.count
; j
++) {
1548 result
= fiji_populate_memory_timing_parameters(hwmgr
,
1549 data
->dpm_table
.sclk_table
.dpm_levels
[i
].value
,
1550 data
->dpm_table
.mclk_table
.dpm_levels
[j
].value
,
1551 &arb_regs
.entries
[i
][j
]);
1558 result
= smu7_copy_bytes_to_smc(
1560 smu_data
->smu7_data
.arb_table_start
,
1561 (uint8_t *)&arb_regs
,
1562 sizeof(SMU73_Discrete_MCArbDramTimingTable
),
1567 static int fiji_populate_smc_uvd_level(struct pp_hwmgr
*hwmgr
,
1568 struct SMU73_Discrete_DpmTable
*table
)
1570 int result
= -EINVAL
;
1572 struct pp_atomctrl_clock_dividers_vi dividers
;
1573 struct phm_ppt_v1_information
*table_info
=
1574 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1575 struct phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1576 table_info
->mm_dep_table
;
1578 table
->UvdLevelCount
= (uint8_t)(mm_table
->count
);
1579 table
->UvdBootLevel
= 0;
1581 for (count
= 0; count
< table
->UvdLevelCount
; count
++) {
1582 table
->UvdLevel
[count
].MinVoltage
= 0;
1583 table
->UvdLevel
[count
].VclkFrequency
= mm_table
->entries
[count
].vclk
;
1584 table
->UvdLevel
[count
].DclkFrequency
= mm_table
->entries
[count
].dclk
;
1585 table
->UvdLevel
[count
].MinVoltage
|= (mm_table
->entries
[count
].vddc
*
1586 VOLTAGE_SCALE
) << VDDC_SHIFT
;
1587 table
->UvdLevel
[count
].MinVoltage
|= ((mm_table
->entries
[count
].vddc
-
1588 VDDC_VDDCI_DELTA
) * VOLTAGE_SCALE
) << VDDCI_SHIFT
;
1589 table
->UvdLevel
[count
].MinVoltage
|= 1 << PHASES_SHIFT
;
1591 /* retrieve divider value for VBIOS */
1592 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1593 table
->UvdLevel
[count
].VclkFrequency
, ÷rs
);
1594 PP_ASSERT_WITH_CODE((0 == result
),
1595 "can not find divide id for Vclk clock", return result
);
1597 table
->UvdLevel
[count
].VclkDivider
= (uint8_t)dividers
.pll_post_divider
;
1599 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1600 table
->UvdLevel
[count
].DclkFrequency
, ÷rs
);
1601 PP_ASSERT_WITH_CODE((0 == result
),
1602 "can not find divide id for Dclk clock", return result
);
1604 table
->UvdLevel
[count
].DclkDivider
= (uint8_t)dividers
.pll_post_divider
;
1606 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].VclkFrequency
);
1607 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].DclkFrequency
);
1608 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].MinVoltage
);
1614 static int fiji_populate_smc_boot_level(struct pp_hwmgr
*hwmgr
,
1615 struct SMU73_Discrete_DpmTable
*table
)
1618 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1620 table
->GraphicsBootLevel
= 0;
1621 table
->MemoryBootLevel
= 0;
1623 /* find boot level from dpm table */
1624 result
= phm_find_boot_level(&(data
->dpm_table
.sclk_table
),
1625 data
->vbios_boot_state
.sclk_bootup_value
,
1626 (uint32_t *)&(table
->GraphicsBootLevel
));
1628 result
= phm_find_boot_level(&(data
->dpm_table
.mclk_table
),
1629 data
->vbios_boot_state
.mclk_bootup_value
,
1630 (uint32_t *)&(table
->MemoryBootLevel
));
1632 table
->BootVddc
= data
->vbios_boot_state
.vddc_bootup_value
*
1634 table
->BootVddci
= data
->vbios_boot_state
.vddci_bootup_value
*
1636 table
->BootMVdd
= data
->vbios_boot_state
.mvdd_bootup_value
*
1639 CONVERT_FROM_HOST_TO_SMC_US(table
->BootVddc
);
1640 CONVERT_FROM_HOST_TO_SMC_US(table
->BootVddci
);
1641 CONVERT_FROM_HOST_TO_SMC_US(table
->BootMVdd
);
1646 static int fiji_populate_smc_initailial_state(struct pp_hwmgr
*hwmgr
)
1648 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1649 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1650 struct phm_ppt_v1_information
*table_info
=
1651 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1652 uint8_t count
, level
;
1654 count
= (uint8_t)(table_info
->vdd_dep_on_sclk
->count
);
1655 for (level
= 0; level
< count
; level
++) {
1656 if (table_info
->vdd_dep_on_sclk
->entries
[level
].clk
>=
1657 data
->vbios_boot_state
.sclk_bootup_value
) {
1658 smu_data
->smc_state_table
.GraphicsBootLevel
= level
;
1663 count
= (uint8_t)(table_info
->vdd_dep_on_mclk
->count
);
1664 for (level
= 0; level
< count
; level
++) {
1665 if (table_info
->vdd_dep_on_mclk
->entries
[level
].clk
>=
1666 data
->vbios_boot_state
.mclk_bootup_value
) {
1667 smu_data
->smc_state_table
.MemoryBootLevel
= level
;
1675 static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr
*hwmgr
)
1677 uint32_t ro
, efuse
, efuse2
, clock_freq
, volt_without_cks
,
1678 volt_with_cks
, value
;
1679 uint16_t clock_freq_u16
;
1680 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1681 uint8_t type
, i
, j
, cks_setting
, stretch_amount
, stretch_amount2
,
1683 struct phm_ppt_v1_information
*table_info
=
1684 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1685 struct phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
=
1686 table_info
->vdd_dep_on_sclk
;
1688 stretch_amount
= (uint8_t)table_info
->cac_dtp_table
->usClockStretchAmount
;
1690 /* Read SMU_Eefuse to read and calculate RO and determine
1691 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1693 efuse
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1694 ixSMU_EFUSE_0
+ (146 * 4));
1695 efuse2
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1696 ixSMU_EFUSE_0
+ (148 * 4));
1697 efuse
&= 0xFF000000;
1698 efuse
= efuse
>> 24;
1702 ro
= (2300 - 1350) * efuse
/ 255 + 1350;
1704 ro
= (2500 - 1000) * efuse
/ 255 + 1000;
1711 /* Populate Stretch amount */
1712 smu_data
->smc_state_table
.ClockStretcherAmount
= stretch_amount
;
1714 /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1715 for (i
= 0; i
< sclk_table
->count
; i
++) {
1716 smu_data
->smc_state_table
.Sclk_CKS_masterEn0_7
|=
1717 sclk_table
->entries
[i
].cks_enable
<< i
;
1718 volt_without_cks
= (uint32_t)((14041 *
1719 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3571 + 75 - ro
) * 1000 /
1720 (4026 - (13924 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1721 volt_with_cks
= (uint32_t)((13946 *
1722 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3320 + 45 - ro
) * 1000 /
1723 (3664 - (11454 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1724 if (volt_without_cks
>= volt_with_cks
)
1725 volt_offset
= (uint8_t)(((volt_without_cks
- volt_with_cks
+
1726 sclk_table
->entries
[i
].cks_voffset
) * 100 / 625) + 1);
1727 smu_data
->smc_state_table
.Sclk_voltageOffset
[i
] = volt_offset
;
1730 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1731 STRETCH_ENABLE
, 0x0);
1732 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1734 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1736 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1739 /* Populate CKS Lookup Table */
1740 if (stretch_amount
== 1 || stretch_amount
== 2 || stretch_amount
== 5)
1741 stretch_amount2
= 0;
1742 else if (stretch_amount
== 3 || stretch_amount
== 4)
1743 stretch_amount2
= 1;
1745 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
1746 PHM_PlatformCaps_ClockStretcher
);
1747 PP_ASSERT_WITH_CODE(false,
1748 "Stretch Amount in PPTable not supported",
1752 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1754 value
&= 0xFFC2FF87;
1755 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].minFreq
=
1756 fiji_clock_stretcher_lookup_table
[stretch_amount2
][0];
1757 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].maxFreq
=
1758 fiji_clock_stretcher_lookup_table
[stretch_amount2
][1];
1759 clock_freq_u16
= (uint16_t)(PP_SMC_TO_HOST_UL(smu_data
->smc_state_table
.
1760 GraphicsLevel
[smu_data
->smc_state_table
.GraphicsDpmLevelCount
- 1].
1761 SclkFrequency
) / 100);
1762 if (fiji_clock_stretcher_lookup_table
[stretch_amount2
][0] <
1764 fiji_clock_stretcher_lookup_table
[stretch_amount2
][1] >
1766 /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
1767 value
|= (fiji_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 16;
1768 /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
1769 value
|= (fiji_clock_stretcher_lookup_table
[stretch_amount2
][2]) << 18;
1770 /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
1771 value
|= (fiji_clock_stretch_amount_conversion
1772 [fiji_clock_stretcher_lookup_table
[stretch_amount2
][3]]
1773 [stretch_amount
]) << 3;
1775 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1776 CKS_LOOKUPTableEntry
[0].minFreq
);
1777 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1778 CKS_LOOKUPTableEntry
[0].maxFreq
);
1779 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
=
1780 fiji_clock_stretcher_lookup_table
[stretch_amount2
][2] & 0x7F;
1781 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
|=
1782 (fiji_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 7;
1784 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1785 ixPWR_CKS_CNTL
, value
);
1787 /* Populate DDT Lookup Table */
1788 for (i
= 0; i
< 4; i
++) {
1789 /* Assign the minimum and maximum VID stored
1790 * in the last row of Clock Stretcher Voltage Table.
1792 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1793 ClockStretcherDataTableEntry
[i
].minVID
=
1794 (uint8_t) fiji_clock_stretcher_ddt_table
[type
][i
][2];
1795 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1796 ClockStretcherDataTableEntry
[i
].maxVID
=
1797 (uint8_t) fiji_clock_stretcher_ddt_table
[type
][i
][3];
1798 /* Loop through each SCLK and check the frequency
1799 * to see if it lies within the frequency for clock stretcher.
1801 for (j
= 0; j
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; j
++) {
1803 clock_freq
= PP_SMC_TO_HOST_UL(
1804 smu_data
->smc_state_table
.GraphicsLevel
[j
].SclkFrequency
);
1805 /* Check the allowed frequency against the sclk level[j].
1806 * Sclk's endianness has already been converted,
1807 * and it's in 10Khz unit,
1808 * as opposed to Data table, which is in Mhz unit.
1811 (fiji_clock_stretcher_ddt_table
[type
][i
][0]) * 100) {
1814 (fiji_clock_stretcher_ddt_table
[type
][i
][1]) * 100)
1817 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1818 ClockStretcherDataTableEntry
[i
].setting
|= cks_setting
<< (j
* 2);
1820 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.
1821 ClockStretcherDataTable
.
1822 ClockStretcherDataTableEntry
[i
].setting
);
1825 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, ixPWR_CKS_CNTL
);
1826 value
&= 0xFFFFFFFE;
1827 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, ixPWR_CKS_CNTL
, value
);
1832 static int fiji_populate_vr_config(struct pp_hwmgr
*hwmgr
,
1833 struct SMU73_Discrete_DpmTable
*table
)
1835 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1838 config
= VR_MERGED_WITH_VDDC
;
1839 table
->VRConfig
|= (config
<< VRCONF_VDDGFX_SHIFT
);
1841 /* Set Vddc Voltage Controller */
1842 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
1843 config
= VR_SVI2_PLANE_1
;
1844 table
->VRConfig
|= config
;
1846 PP_ASSERT_WITH_CODE(false,
1847 "VDDC should be on SVI2 control in merged mode!",
1850 /* Set Vddci Voltage Controller */
1851 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vddci_control
) {
1852 config
= VR_SVI2_PLANE_2
; /* only in merged mode */
1853 table
->VRConfig
|= (config
<< VRCONF_VDDCI_SHIFT
);
1854 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->vddci_control
) {
1855 config
= VR_SMIO_PATTERN_1
;
1856 table
->VRConfig
|= (config
<< VRCONF_VDDCI_SHIFT
);
1858 config
= VR_STATIC_VOLTAGE
;
1859 table
->VRConfig
|= (config
<< VRCONF_VDDCI_SHIFT
);
1861 /* Set Mvdd Voltage Controller */
1862 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->mvdd_control
) {
1863 config
= VR_SVI2_PLANE_2
;
1864 table
->VRConfig
|= (config
<< VRCONF_MVDD_SHIFT
);
1865 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->mvdd_control
) {
1866 config
= VR_SMIO_PATTERN_2
;
1867 table
->VRConfig
|= (config
<< VRCONF_MVDD_SHIFT
);
1869 config
= VR_STATIC_VOLTAGE
;
1870 table
->VRConfig
|= (config
<< VRCONF_MVDD_SHIFT
);
1876 static int fiji_init_arb_table_index(struct pp_hwmgr
*hwmgr
)
1878 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1882 /* This is a read-modify-write on the first byte of the ARB table.
1883 * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure
1884 * is the field 'current'.
1885 * This solution is ugly, but we never write the whole table only
1886 * individual fields in it.
1887 * In reality this field should not be in that structure
1888 * but in a soft register.
1890 result
= smu7_read_smc_sram_dword(hwmgr
,
1891 smu_data
->smu7_data
.arb_table_start
, &tmp
, SMC_RAM_END
);
1897 tmp
|= ((uint32_t)MC_CG_ARB_FREQ_F1
) << 24;
1899 return smu7_write_smc_sram_dword(hwmgr
,
1900 smu_data
->smu7_data
.arb_table_start
, tmp
, SMC_RAM_END
);
1903 static int fiji_setup_dpm_led_config(struct pp_hwmgr
*hwmgr
)
1905 pp_atomctrl_voltage_table param_led_dpm
;
1909 result
= atomctrl_get_voltage_table_v3(hwmgr
,
1910 VOLTAGE_TYPE_LEDDPM
, VOLTAGE_OBJ_GPIO_LUT
,
1914 u32 tmp
= param_led_dpm
.mask_low
;
1916 for (i
= 0, j
= 0; i
< 32; i
++) {
1918 mask
|= (i
<< (8 * j
));
1926 smum_send_msg_to_smc_with_parameter(hwmgr
,
1927 PPSMC_MSG_LedConfig
,
1932 static int fiji_init_smc_table(struct pp_hwmgr
*hwmgr
)
1935 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1936 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
1937 struct phm_ppt_v1_information
*table_info
=
1938 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1939 struct SMU73_Discrete_DpmTable
*table
= &(smu_data
->smc_state_table
);
1941 struct pp_atomctrl_gpio_pin_assignment gpio_pin
;
1943 fiji_initialize_power_tune_defaults(hwmgr
);
1945 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->voltage_control
)
1946 fiji_populate_smc_voltage_tables(hwmgr
, table
);
1948 table
->SystemFlags
= 0;
1950 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
1951 PHM_PlatformCaps_AutomaticDCTransition
))
1952 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GPIO_DC
;
1954 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
1955 PHM_PlatformCaps_StepVddc
))
1956 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_STEPVDDC
;
1958 if (data
->is_memory_gddr5
)
1959 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GDDR5
;
1961 if (data
->ulv_supported
&& table_info
->us_ulv_voltage_offset
) {
1962 result
= fiji_populate_ulv_state(hwmgr
, table
);
1963 PP_ASSERT_WITH_CODE(0 == result
,
1964 "Failed to initialize ULV state!", return result
);
1965 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1966 ixCG_ULV_PARAMETER
, 0x40035);
1969 result
= fiji_populate_smc_link_level(hwmgr
, table
);
1970 PP_ASSERT_WITH_CODE(0 == result
,
1971 "Failed to initialize Link Level!", return result
);
1973 result
= fiji_populate_all_graphic_levels(hwmgr
);
1974 PP_ASSERT_WITH_CODE(0 == result
,
1975 "Failed to initialize Graphics Level!", return result
);
1977 result
= fiji_populate_all_memory_levels(hwmgr
);
1978 PP_ASSERT_WITH_CODE(0 == result
,
1979 "Failed to initialize Memory Level!", return result
);
1981 result
= fiji_populate_smc_acpi_level(hwmgr
, table
);
1982 PP_ASSERT_WITH_CODE(0 == result
,
1983 "Failed to initialize ACPI Level!", return result
);
1985 result
= fiji_populate_smc_vce_level(hwmgr
, table
);
1986 PP_ASSERT_WITH_CODE(0 == result
,
1987 "Failed to initialize VCE Level!", return result
);
1989 result
= fiji_populate_smc_acp_level(hwmgr
, table
);
1990 PP_ASSERT_WITH_CODE(0 == result
,
1991 "Failed to initialize ACP Level!", return result
);
1993 /* Since only the initial state is completely set up at this point
1994 * (the other states are just copies of the boot state) we only
1995 * need to populate the ARB settings for the initial state.
1997 result
= fiji_program_memory_timing_parameters(hwmgr
);
1998 PP_ASSERT_WITH_CODE(0 == result
,
1999 "Failed to Write ARB settings for the initial state.", return result
);
2001 result
= fiji_populate_smc_uvd_level(hwmgr
, table
);
2002 PP_ASSERT_WITH_CODE(0 == result
,
2003 "Failed to initialize UVD Level!", return result
);
2005 result
= fiji_populate_smc_boot_level(hwmgr
, table
);
2006 PP_ASSERT_WITH_CODE(0 == result
,
2007 "Failed to initialize Boot Level!", return result
);
2009 result
= fiji_populate_smc_initailial_state(hwmgr
);
2010 PP_ASSERT_WITH_CODE(0 == result
,
2011 "Failed to initialize Boot State!", return result
);
2013 result
= fiji_populate_bapm_parameters_in_dpm_table(hwmgr
);
2014 PP_ASSERT_WITH_CODE(0 == result
,
2015 "Failed to populate BAPM Parameters!", return result
);
2017 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2018 PHM_PlatformCaps_ClockStretcher
)) {
2019 result
= fiji_populate_clock_stretcher_data_table(hwmgr
);
2020 PP_ASSERT_WITH_CODE(0 == result
,
2021 "Failed to populate Clock Stretcher Data Table!",
2025 table
->GraphicsVoltageChangeEnable
= 1;
2026 table
->GraphicsThermThrottleEnable
= 1;
2027 table
->GraphicsInterval
= 1;
2028 table
->VoltageInterval
= 1;
2029 table
->ThermalInterval
= 1;
2030 table
->TemperatureLimitHigh
=
2031 table_info
->cac_dtp_table
->usTargetOperatingTemp
*
2032 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2033 table
->TemperatureLimitLow
=
2034 (table_info
->cac_dtp_table
->usTargetOperatingTemp
- 1) *
2035 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2036 table
->MemoryVoltageChangeEnable
= 1;
2037 table
->MemoryInterval
= 1;
2038 table
->VoltageResponseTime
= 0;
2039 table
->PhaseResponseTime
= 0;
2040 table
->MemoryThermThrottleEnable
= 1;
2041 table
->PCIeBootLinkLevel
= 0; /* 0:Gen1 1:Gen2 2:Gen3*/
2042 table
->PCIeGenInterval
= 1;
2043 table
->VRConfig
= 0;
2045 result
= fiji_populate_vr_config(hwmgr
, table
);
2046 PP_ASSERT_WITH_CODE(0 == result
,
2047 "Failed to populate VRConfig setting!", return result
);
2048 data
->vr_config
= table
->VRConfig
;
2049 table
->ThermGpio
= 17;
2050 table
->SclkStepSize
= 0x4000;
2052 if (atomctrl_get_pp_assign_pin(hwmgr
, VDDC_VRHOT_GPIO_PINID
, &gpio_pin
)) {
2053 table
->VRHotGpio
= gpio_pin
.uc_gpio_pin_bit_shift
;
2054 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2055 PHM_PlatformCaps_RegulatorHot
);
2057 table
->VRHotGpio
= SMU7_UNUSED_GPIO_PIN
;
2058 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2059 PHM_PlatformCaps_RegulatorHot
);
2062 if (atomctrl_get_pp_assign_pin(hwmgr
, PP_AC_DC_SWITCH_GPIO_PINID
,
2064 table
->AcDcGpio
= gpio_pin
.uc_gpio_pin_bit_shift
;
2065 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2066 PHM_PlatformCaps_AutomaticDCTransition
);
2068 table
->AcDcGpio
= SMU7_UNUSED_GPIO_PIN
;
2069 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2070 PHM_PlatformCaps_AutomaticDCTransition
);
2073 /* Thermal Output GPIO */
2074 if (atomctrl_get_pp_assign_pin(hwmgr
, THERMAL_INT_OUTPUT_GPIO_PINID
,
2076 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2077 PHM_PlatformCaps_ThermalOutGPIO
);
2079 table
->ThermOutGpio
= gpio_pin
.uc_gpio_pin_bit_shift
;
2081 /* For porlarity read GPIOPAD_A with assigned Gpio pin
2082 * since VBIOS will program this register to set 'inactive state',
2083 * driver can then determine 'active state' from this and
2084 * program SMU with correct polarity
2086 table
->ThermOutPolarity
= (0 == (cgs_read_register(hwmgr
->device
, mmGPIOPAD_A
) &
2087 (1 << gpio_pin
.uc_gpio_pin_bit_shift
))) ? 1:0;
2088 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_ONLY
;
2090 /* if required, combine VRHot/PCC with thermal out GPIO */
2091 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2092 PHM_PlatformCaps_RegulatorHot
) &&
2093 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2094 PHM_PlatformCaps_CombinePCCWithThermalSignal
))
2095 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_VRHOT
;
2097 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2098 PHM_PlatformCaps_ThermalOutGPIO
);
2099 table
->ThermOutGpio
= 17;
2100 table
->ThermOutPolarity
= 1;
2101 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_DISABLE
;
2104 for (i
= 0; i
< SMU73_MAX_ENTRIES_SMIO
; i
++)
2105 table
->Smio
[i
] = PP_HOST_TO_SMC_UL(table
->Smio
[i
]);
2107 CONVERT_FROM_HOST_TO_SMC_UL(table
->SystemFlags
);
2108 CONVERT_FROM_HOST_TO_SMC_UL(table
->VRConfig
);
2109 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask1
);
2110 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask2
);
2111 CONVERT_FROM_HOST_TO_SMC_UL(table
->SclkStepSize
);
2112 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitHigh
);
2113 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitLow
);
2114 CONVERT_FROM_HOST_TO_SMC_US(table
->VoltageResponseTime
);
2115 CONVERT_FROM_HOST_TO_SMC_US(table
->PhaseResponseTime
);
2117 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2118 result
= smu7_copy_bytes_to_smc(hwmgr
,
2119 smu_data
->smu7_data
.dpm_table_start
+
2120 offsetof(SMU73_Discrete_DpmTable
, SystemFlags
),
2121 (uint8_t *)&(table
->SystemFlags
),
2122 sizeof(SMU73_Discrete_DpmTable
) - 3 * sizeof(SMU73_PIDController
),
2124 PP_ASSERT_WITH_CODE(0 == result
,
2125 "Failed to upload dpm data to SMC memory!", return result
);
2127 result
= fiji_init_arb_table_index(hwmgr
);
2128 PP_ASSERT_WITH_CODE(0 == result
,
2129 "Failed to upload arb data to SMC memory!", return result
);
2131 result
= fiji_populate_pm_fuses(hwmgr
);
2132 PP_ASSERT_WITH_CODE(0 == result
,
2133 "Failed to populate PM fuses to SMC memory!", return result
);
2135 result
= fiji_setup_dpm_led_config(hwmgr
);
2136 PP_ASSERT_WITH_CODE(0 == result
,
2137 "Failed to setup dpm led config", return result
);
2142 static int fiji_thermal_setup_fan_table(struct pp_hwmgr
*hwmgr
)
2144 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2146 SMU73_Discrete_FanTable fan_table
= { FDO_MODE_HARDWARE
};
2148 uint32_t t_diff1
, t_diff2
, pwm_diff1
, pwm_diff2
;
2149 uint16_t fdo_min
, slope1
, slope2
;
2150 uint32_t reference_clock
;
2154 if (hwmgr
->thermal_controller
.fanInfo
.bNoFan
) {
2155 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2156 PHM_PlatformCaps_MicrocodeFanControl
);
2160 if (smu_data
->smu7_data
.fan_table_start
== 0) {
2161 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2162 PHM_PlatformCaps_MicrocodeFanControl
);
2166 duty100
= PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
,
2167 CG_FDO_CTRL1
, FMAX_DUTY100
);
2170 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2171 PHM_PlatformCaps_MicrocodeFanControl
);
2175 tmp64
= hwmgr
->thermal_controller
.advanceFanControlParameters
.
2177 do_div(tmp64
, 10000);
2178 fdo_min
= (uint16_t)tmp64
;
2180 t_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
-
2181 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
;
2182 t_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
-
2183 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
;
2185 pwm_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
-
2186 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
;
2187 pwm_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
-
2188 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
;
2190 slope1
= (uint16_t)((50 + ((16 * duty100
* pwm_diff1
) / t_diff1
)) / 100);
2191 slope2
= (uint16_t)((50 + ((16 * duty100
* pwm_diff2
) / t_diff2
)) / 100);
2193 fan_table
.TempMin
= cpu_to_be16((50 + hwmgr
->
2194 thermal_controller
.advanceFanControlParameters
.usTMin
) / 100);
2195 fan_table
.TempMed
= cpu_to_be16((50 + hwmgr
->
2196 thermal_controller
.advanceFanControlParameters
.usTMed
) / 100);
2197 fan_table
.TempMax
= cpu_to_be16((50 + hwmgr
->
2198 thermal_controller
.advanceFanControlParameters
.usTMax
) / 100);
2200 fan_table
.Slope1
= cpu_to_be16(slope1
);
2201 fan_table
.Slope2
= cpu_to_be16(slope2
);
2203 fan_table
.FdoMin
= cpu_to_be16(fdo_min
);
2205 fan_table
.HystDown
= cpu_to_be16(hwmgr
->
2206 thermal_controller
.advanceFanControlParameters
.ucTHyst
);
2208 fan_table
.HystUp
= cpu_to_be16(1);
2210 fan_table
.HystSlope
= cpu_to_be16(1);
2212 fan_table
.TempRespLim
= cpu_to_be16(5);
2214 reference_clock
= amdgpu_asic_get_xclk((struct amdgpu_device
*)hwmgr
->adev
);
2216 fan_table
.RefreshPeriod
= cpu_to_be32((hwmgr
->
2217 thermal_controller
.advanceFanControlParameters
.ulCycleDelay
*
2218 reference_clock
) / 1600);
2220 fan_table
.FdoMax
= cpu_to_be16((uint16_t)duty100
);
2222 fan_table
.TempSrc
= (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(
2223 hwmgr
->device
, CGS_IND_REG__SMC
,
2224 CG_MULT_THERMAL_CTRL
, TEMP_SEL
);
2226 res
= smu7_copy_bytes_to_smc(hwmgr
, smu_data
->smu7_data
.fan_table_start
,
2227 (uint8_t *)&fan_table
, (uint32_t)sizeof(fan_table
),
2230 if (!res
&& hwmgr
->thermal_controller
.
2231 advanceFanControlParameters
.ucMinimumPWMLimit
)
2232 res
= smum_send_msg_to_smc_with_parameter(hwmgr
,
2233 PPSMC_MSG_SetFanMinPwm
,
2234 hwmgr
->thermal_controller
.
2235 advanceFanControlParameters
.ucMinimumPWMLimit
);
2237 if (!res
&& hwmgr
->thermal_controller
.
2238 advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
)
2239 res
= smum_send_msg_to_smc_with_parameter(hwmgr
,
2240 PPSMC_MSG_SetFanSclkTarget
,
2241 hwmgr
->thermal_controller
.
2242 advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
);
2245 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2246 PHM_PlatformCaps_MicrocodeFanControl
);
2252 static int fiji_thermal_avfs_enable(struct pp_hwmgr
*hwmgr
)
2254 if (!hwmgr
->avfs_supported
)
2257 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_EnableAvfs
);
2262 static int fiji_program_mem_timing_parameters(struct pp_hwmgr
*hwmgr
)
2264 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2266 if (data
->need_update_smu7_dpm_table
&
2267 (DPMTABLE_OD_UPDATE_SCLK
+ DPMTABLE_OD_UPDATE_MCLK
))
2268 return fiji_program_memory_timing_parameters(hwmgr
);
2273 static int fiji_update_sclk_threshold(struct pp_hwmgr
*hwmgr
)
2275 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2276 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2279 uint32_t low_sclk_interrupt_threshold
= 0;
2281 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2282 PHM_PlatformCaps_SclkThrottleLowNotification
)
2283 && (data
->low_sclk_interrupt_threshold
!= 0)) {
2284 low_sclk_interrupt_threshold
=
2285 data
->low_sclk_interrupt_threshold
;
2287 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold
);
2289 result
= smu7_copy_bytes_to_smc(
2291 smu_data
->smu7_data
.dpm_table_start
+
2292 offsetof(SMU73_Discrete_DpmTable
,
2293 LowSclkInterruptThreshold
),
2294 (uint8_t *)&low_sclk_interrupt_threshold
,
2298 result
= fiji_program_mem_timing_parameters(hwmgr
);
2299 PP_ASSERT_WITH_CODE((result
== 0),
2300 "Failed to program memory timing parameters!",
2305 static uint32_t fiji_get_offsetof(uint32_t type
, uint32_t member
)
2308 case SMU_SoftRegisters
:
2310 case HandshakeDisables
:
2311 return offsetof(SMU73_SoftRegisters
, HandshakeDisables
);
2312 case VoltageChangeTimeout
:
2313 return offsetof(SMU73_SoftRegisters
, VoltageChangeTimeout
);
2314 case AverageGraphicsActivity
:
2315 return offsetof(SMU73_SoftRegisters
, AverageGraphicsActivity
);
2317 return offsetof(SMU73_SoftRegisters
, PreVBlankGap
);
2319 return offsetof(SMU73_SoftRegisters
, VBlankTimeout
);
2320 case UcodeLoadStatus
:
2321 return offsetof(SMU73_SoftRegisters
, UcodeLoadStatus
);
2322 case DRAM_LOG_ADDR_H
:
2323 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_ADDR_H
);
2324 case DRAM_LOG_ADDR_L
:
2325 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_ADDR_L
);
2326 case DRAM_LOG_PHY_ADDR_H
:
2327 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_PHY_ADDR_H
);
2328 case DRAM_LOG_PHY_ADDR_L
:
2329 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_PHY_ADDR_L
);
2330 case DRAM_LOG_BUFF_SIZE
:
2331 return offsetof(SMU73_SoftRegisters
, DRAM_LOG_BUFF_SIZE
);
2334 case SMU_Discrete_DpmTable
:
2337 return offsetof(SMU73_Discrete_DpmTable
, UvdBootLevel
);
2339 return offsetof(SMU73_Discrete_DpmTable
, VceBootLevel
);
2340 case LowSclkInterruptThreshold
:
2341 return offsetof(SMU73_Discrete_DpmTable
, LowSclkInterruptThreshold
);
2345 pr_warn("can't get the offset of type %x member %x\n", type
, member
);
2349 static uint32_t fiji_get_mac_definition(uint32_t value
)
2352 case SMU_MAX_LEVELS_GRAPHICS
:
2353 return SMU73_MAX_LEVELS_GRAPHICS
;
2354 case SMU_MAX_LEVELS_MEMORY
:
2355 return SMU73_MAX_LEVELS_MEMORY
;
2356 case SMU_MAX_LEVELS_LINK
:
2357 return SMU73_MAX_LEVELS_LINK
;
2358 case SMU_MAX_ENTRIES_SMIO
:
2359 return SMU73_MAX_ENTRIES_SMIO
;
2360 case SMU_MAX_LEVELS_VDDC
:
2361 return SMU73_MAX_LEVELS_VDDC
;
2362 case SMU_MAX_LEVELS_VDDGFX
:
2363 return SMU73_MAX_LEVELS_VDDGFX
;
2364 case SMU_MAX_LEVELS_VDDCI
:
2365 return SMU73_MAX_LEVELS_VDDCI
;
2366 case SMU_MAX_LEVELS_MVDD
:
2367 return SMU73_MAX_LEVELS_MVDD
;
2370 pr_warn("can't get the mac of %x\n", value
);
2375 static int fiji_update_uvd_smc_table(struct pp_hwmgr
*hwmgr
)
2377 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2378 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2379 struct phm_ppt_v1_information
*table_info
=
2380 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2382 smu_data
->smc_state_table
.UvdBootLevel
= 0;
2383 if (table_info
->mm_dep_table
->count
> 0)
2384 smu_data
->smc_state_table
.UvdBootLevel
=
2385 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2386 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+ offsetof(SMU73_Discrete_DpmTable
,
2388 mm_boot_level_offset
/= 4;
2389 mm_boot_level_offset
*= 4;
2390 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2391 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2392 mm_boot_level_value
&= 0x00FFFFFF;
2393 mm_boot_level_value
|= smu_data
->smc_state_table
.UvdBootLevel
<< 24;
2394 cgs_write_ind_register(hwmgr
->device
,
2395 CGS_IND_REG__SMC
, mm_boot_level_offset
, mm_boot_level_value
);
2397 if (!phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2398 PHM_PlatformCaps_UVDDPM
) ||
2399 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2400 PHM_PlatformCaps_StablePState
))
2401 smum_send_msg_to_smc_with_parameter(hwmgr
,
2402 PPSMC_MSG_UVDDPM_SetEnabledMask
,
2403 (uint32_t)(1 << smu_data
->smc_state_table
.UvdBootLevel
));
2407 static int fiji_update_vce_smc_table(struct pp_hwmgr
*hwmgr
)
2409 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2410 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2411 struct phm_ppt_v1_information
*table_info
=
2412 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2414 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2415 PHM_PlatformCaps_StablePState
))
2416 smu_data
->smc_state_table
.VceBootLevel
=
2417 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2419 smu_data
->smc_state_table
.VceBootLevel
= 0;
2421 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2422 offsetof(SMU73_Discrete_DpmTable
, VceBootLevel
);
2423 mm_boot_level_offset
/= 4;
2424 mm_boot_level_offset
*= 4;
2425 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2426 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2427 mm_boot_level_value
&= 0xFF00FFFF;
2428 mm_boot_level_value
|= smu_data
->smc_state_table
.VceBootLevel
<< 16;
2429 cgs_write_ind_register(hwmgr
->device
,
2430 CGS_IND_REG__SMC
, mm_boot_level_offset
, mm_boot_level_value
);
2432 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
, PHM_PlatformCaps_StablePState
))
2433 smum_send_msg_to_smc_with_parameter(hwmgr
,
2434 PPSMC_MSG_VCEDPM_SetEnabledMask
,
2435 (uint32_t)1 << smu_data
->smc_state_table
.VceBootLevel
);
2439 static int fiji_update_smc_table(struct pp_hwmgr
*hwmgr
, uint32_t type
)
2443 fiji_update_uvd_smc_table(hwmgr
);
2446 fiji_update_vce_smc_table(hwmgr
);
2454 static int fiji_process_firmware_header(struct pp_hwmgr
*hwmgr
)
2456 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2457 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)(hwmgr
->smu_backend
);
2462 result
= smu7_read_smc_sram_dword(hwmgr
,
2463 SMU7_FIRMWARE_HEADER_LOCATION
+
2464 offsetof(SMU73_Firmware_Header
, DpmTable
),
2468 smu_data
->smu7_data
.dpm_table_start
= tmp
;
2470 error
|= (0 != result
);
2472 result
= smu7_read_smc_sram_dword(hwmgr
,
2473 SMU7_FIRMWARE_HEADER_LOCATION
+
2474 offsetof(SMU73_Firmware_Header
, SoftRegisters
),
2478 data
->soft_regs_start
= tmp
;
2479 smu_data
->smu7_data
.soft_regs_start
= tmp
;
2482 error
|= (0 != result
);
2484 result
= smu7_read_smc_sram_dword(hwmgr
,
2485 SMU7_FIRMWARE_HEADER_LOCATION
+
2486 offsetof(SMU73_Firmware_Header
, mcRegisterTable
),
2490 smu_data
->smu7_data
.mc_reg_table_start
= tmp
;
2492 result
= smu7_read_smc_sram_dword(hwmgr
,
2493 SMU7_FIRMWARE_HEADER_LOCATION
+
2494 offsetof(SMU73_Firmware_Header
, FanTable
),
2498 smu_data
->smu7_data
.fan_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
, mcArbDramTimingTable
),
2508 smu_data
->smu7_data
.arb_table_start
= tmp
;
2510 error
|= (0 != result
);
2512 result
= smu7_read_smc_sram_dword(hwmgr
,
2513 SMU7_FIRMWARE_HEADER_LOCATION
+
2514 offsetof(SMU73_Firmware_Header
, Version
),
2518 hwmgr
->microcode_version_info
.SMC
= tmp
;
2520 error
|= (0 != result
);
2522 return error
? -1 : 0;
2525 static int fiji_initialize_mc_reg_table(struct pp_hwmgr
*hwmgr
)
2528 /* Program additional LP registers
2529 * that are no longer programmed by VBIOS
2531 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING_LP
,
2532 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING
));
2533 cgs_write_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING_LP
,
2534 cgs_read_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING
));
2535 cgs_write_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2_LP
,
2536 cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2
));
2537 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1_LP
,
2538 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1
));
2539 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0_LP
,
2540 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0
));
2541 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1_LP
,
2542 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1
));
2543 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING_LP
,
2544 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING
));
2549 static bool fiji_is_dpm_running(struct pp_hwmgr
*hwmgr
)
2551 return (1 == PHM_READ_INDIRECT_FIELD(hwmgr
->device
,
2552 CGS_IND_REG__SMC
, FEATURE_STATUS
, VOLTAGE_CONTROLLER_ON
))
2556 static int fiji_update_dpm_settings(struct pp_hwmgr
*hwmgr
,
2557 void *profile_setting
)
2559 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2560 struct fiji_smumgr
*smu_data
= (struct fiji_smumgr
*)
2561 (hwmgr
->smu_backend
);
2562 struct profile_mode_setting
*setting
;
2563 struct SMU73_Discrete_GraphicsLevel
*levels
=
2564 smu_data
->smc_state_table
.GraphicsLevel
;
2565 uint32_t array
= smu_data
->smu7_data
.dpm_table_start
+
2566 offsetof(SMU73_Discrete_DpmTable
, GraphicsLevel
);
2568 uint32_t mclk_array
= smu_data
->smu7_data
.dpm_table_start
+
2569 offsetof(SMU73_Discrete_DpmTable
, MemoryLevel
);
2570 struct SMU73_Discrete_MemoryLevel
*mclk_levels
=
2571 smu_data
->smc_state_table
.MemoryLevel
;
2573 uint32_t offset
, up_hyst_offset
, down_hyst_offset
, clk_activity_offset
, tmp
;
2575 if (profile_setting
== NULL
)
2578 setting
= (struct profile_mode_setting
*)profile_setting
;
2580 if (setting
->bupdate_sclk
) {
2581 if (!data
->sclk_dpm_key_disabled
)
2582 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_SCLKDPM_FreezeLevel
);
2583 for (i
= 0; i
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; i
++) {
2584 if (levels
[i
].ActivityLevel
!=
2585 cpu_to_be16(setting
->sclk_activity
)) {
2586 levels
[i
].ActivityLevel
= cpu_to_be16(setting
->sclk_activity
);
2588 clk_activity_offset
= array
+ (sizeof(SMU73_Discrete_GraphicsLevel
) * i
)
2589 + offsetof(SMU73_Discrete_GraphicsLevel
, ActivityLevel
);
2590 offset
= clk_activity_offset
& ~0x3;
2591 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
2592 tmp
= phm_set_field_to_u32(clk_activity_offset
, tmp
, levels
[i
].ActivityLevel
, sizeof(uint16_t));
2593 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
2596 if (levels
[i
].UpHyst
!= setting
->sclk_up_hyst
||
2597 levels
[i
].DownHyst
!= setting
->sclk_down_hyst
) {
2598 levels
[i
].UpHyst
= setting
->sclk_up_hyst
;
2599 levels
[i
].DownHyst
= setting
->sclk_down_hyst
;
2600 up_hyst_offset
= array
+ (sizeof(SMU73_Discrete_GraphicsLevel
) * i
)
2601 + offsetof(SMU73_Discrete_GraphicsLevel
, UpHyst
);
2602 down_hyst_offset
= array
+ (sizeof(SMU73_Discrete_GraphicsLevel
) * i
)
2603 + offsetof(SMU73_Discrete_GraphicsLevel
, DownHyst
);
2604 offset
= up_hyst_offset
& ~0x3;
2605 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
2606 tmp
= phm_set_field_to_u32(up_hyst_offset
, tmp
, levels
[i
].UpHyst
, sizeof(uint8_t));
2607 tmp
= phm_set_field_to_u32(down_hyst_offset
, tmp
, levels
[i
].DownHyst
, sizeof(uint8_t));
2608 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
2611 if (!data
->sclk_dpm_key_disabled
)
2612 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_SCLKDPM_UnfreezeLevel
);
2615 if (setting
->bupdate_mclk
) {
2616 if (!data
->mclk_dpm_key_disabled
)
2617 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_MCLKDPM_FreezeLevel
);
2618 for (i
= 0; i
< smu_data
->smc_state_table
.MemoryDpmLevelCount
; i
++) {
2619 if (mclk_levels
[i
].ActivityLevel
!=
2620 cpu_to_be16(setting
->mclk_activity
)) {
2621 mclk_levels
[i
].ActivityLevel
= cpu_to_be16(setting
->mclk_activity
);
2623 clk_activity_offset
= mclk_array
+ (sizeof(SMU73_Discrete_MemoryLevel
) * i
)
2624 + offsetof(SMU73_Discrete_MemoryLevel
, ActivityLevel
);
2625 offset
= clk_activity_offset
& ~0x3;
2626 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
2627 tmp
= phm_set_field_to_u32(clk_activity_offset
, tmp
, mclk_levels
[i
].ActivityLevel
, sizeof(uint16_t));
2628 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
2631 if (mclk_levels
[i
].UpHyst
!= setting
->mclk_up_hyst
||
2632 mclk_levels
[i
].DownHyst
!= setting
->mclk_down_hyst
) {
2633 mclk_levels
[i
].UpHyst
= setting
->mclk_up_hyst
;
2634 mclk_levels
[i
].DownHyst
= setting
->mclk_down_hyst
;
2635 up_hyst_offset
= mclk_array
+ (sizeof(SMU73_Discrete_MemoryLevel
) * i
)
2636 + offsetof(SMU73_Discrete_MemoryLevel
, UpHyst
);
2637 down_hyst_offset
= mclk_array
+ (sizeof(SMU73_Discrete_MemoryLevel
) * i
)
2638 + offsetof(SMU73_Discrete_MemoryLevel
, DownHyst
);
2639 offset
= up_hyst_offset
& ~0x3;
2640 tmp
= PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
));
2641 tmp
= phm_set_field_to_u32(up_hyst_offset
, tmp
, mclk_levels
[i
].UpHyst
, sizeof(uint8_t));
2642 tmp
= phm_set_field_to_u32(down_hyst_offset
, tmp
, mclk_levels
[i
].DownHyst
, sizeof(uint8_t));
2643 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
, offset
, PP_HOST_TO_SMC_UL(tmp
));
2646 if (!data
->mclk_dpm_key_disabled
)
2647 smum_send_msg_to_smc(hwmgr
, PPSMC_MSG_MCLKDPM_UnfreezeLevel
);
2652 const struct pp_smumgr_func fiji_smu_funcs
= {
2653 .smu_init
= &fiji_smu_init
,
2654 .smu_fini
= &smu7_smu_fini
,
2655 .start_smu
= &fiji_start_smu
,
2656 .check_fw_load_finish
= &smu7_check_fw_load_finish
,
2657 .request_smu_load_fw
= &smu7_reload_firmware
,
2658 .request_smu_load_specific_fw
= NULL
,
2659 .send_msg_to_smc
= &smu7_send_msg_to_smc
,
2660 .send_msg_to_smc_with_parameter
= &smu7_send_msg_to_smc_with_parameter
,
2661 .download_pptable_settings
= NULL
,
2662 .upload_pptable_settings
= NULL
,
2663 .update_smc_table
= fiji_update_smc_table
,
2664 .get_offsetof
= fiji_get_offsetof
,
2665 .process_firmware_header
= fiji_process_firmware_header
,
2666 .init_smc_table
= fiji_init_smc_table
,
2667 .update_sclk_threshold
= fiji_update_sclk_threshold
,
2668 .thermal_setup_fan_table
= fiji_thermal_setup_fan_table
,
2669 .thermal_avfs_enable
= fiji_thermal_avfs_enable
,
2670 .populate_all_graphic_levels
= fiji_populate_all_graphic_levels
,
2671 .populate_all_memory_levels
= fiji_populate_all_memory_levels
,
2672 .get_mac_definition
= fiji_get_mac_definition
,
2673 .initialize_mc_reg_table
= fiji_initialize_mc_reg_table
,
2674 .is_dpm_running
= fiji_is_dpm_running
,
2675 .is_hw_avfs_present
= fiji_is_hw_avfs_present
,
2676 .update_dpm_settings
= fiji_update_dpm_settings
,