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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
10 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
11 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
12 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
13 * OTHER DEALINGS IN THE SOFTWARE.
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
24 #include "tonga_smc.h"
25 #include "smu7_dyn_defaults.h"
27 #include "smu7_hwmgr.h"
28 #include "hardwaremanager.h"
29 #include "ppatomctrl.h"
31 #include "cgs_common.h"
33 #include "tonga_smumgr.h"
34 #include "pppcielanes.h"
35 #include "pp_endian.h"
36 #include "smu7_ppsmc.h"
38 #include "smu72_discrete.h"
40 #include "smu/smu_7_1_2_d.h"
41 #include "smu/smu_7_1_2_sh_mask.h"
43 #include "gmc/gmc_8_1_d.h"
44 #include "gmc/gmc_8_1_sh_mask.h"
46 #include "bif/bif_5_0_d.h"
47 #include "bif/bif_5_0_sh_mask.h"
49 #include "dce/dce_10_0_d.h"
50 #include "dce/dce_10_0_sh_mask.h"
53 #define VOLTAGE_SCALE 4
54 #define POWERTUNE_DEFAULT_SET_MAX 1
55 #define VOLTAGE_VID_OFFSET_SCALE1 625
56 #define VOLTAGE_VID_OFFSET_SCALE2 100
57 #define MC_CG_ARB_FREQ_F1 0x0b
58 #define VDDC_VDDCI_DELTA 200
61 static const struct tonga_pt_defaults tonga_power_tune_data_set_array
[POWERTUNE_DEFAULT_SET_MAX
] = {
62 /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
63 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
67 {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8,
68 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
69 {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203,
70 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4}
74 /* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */
75 static const uint16_t tonga_clock_stretcher_lookup_table
[2][4] = {
80 /* [FF, SS] type, [] 4 voltage ranges,
81 * and [Floor Freq, Boundary Freq, VID min , VID max]
83 static const uint32_t tonga_clock_stretcher_ddt_table
[2][4][4] = {
84 { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
85 { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} }
88 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */
89 static const uint8_t tonga_clock_stretch_amount_conversion
[2][6] = {
94 /* PPGen has the gain setting generated in x * 100 unit
95 * This function is to convert the unit to x * 4096(0x1000) unit.
96 * This is the unit expected by SMC firmware
100 static int tonga_get_dependecy_volt_by_clk(struct pp_hwmgr
*hwmgr
,
101 phm_ppt_v1_clock_voltage_dependency_table
*allowed_clock_voltage_table
,
102 uint32_t clock
, SMU_VoltageLevel
*voltage
, uint32_t *mvdd
)
105 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
106 struct phm_ppt_v1_information
*pptable_info
=
107 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
109 /* clock - voltage dependency table is empty table */
110 if (allowed_clock_voltage_table
->count
== 0)
113 for (i
= 0; i
< allowed_clock_voltage_table
->count
; i
++) {
114 /* find first sclk bigger than request */
115 if (allowed_clock_voltage_table
->entries
[i
].clk
>= clock
) {
116 voltage
->VddGfx
= phm_get_voltage_index(
117 pptable_info
->vddgfx_lookup_table
,
118 allowed_clock_voltage_table
->entries
[i
].vddgfx
);
119 voltage
->Vddc
= phm_get_voltage_index(
120 pptable_info
->vddc_lookup_table
,
121 allowed_clock_voltage_table
->entries
[i
].vddc
);
123 if (allowed_clock_voltage_table
->entries
[i
].vddci
)
125 phm_get_voltage_id(&data
->vddci_voltage_table
, allowed_clock_voltage_table
->entries
[i
].vddci
);
128 phm_get_voltage_id(&data
->vddci_voltage_table
,
129 allowed_clock_voltage_table
->entries
[i
].vddc
- VDDC_VDDCI_DELTA
);
132 if (allowed_clock_voltage_table
->entries
[i
].mvdd
)
133 *mvdd
= (uint32_t) allowed_clock_voltage_table
->entries
[i
].mvdd
;
140 /* sclk is bigger than max sclk in the dependence table */
141 voltage
->VddGfx
= phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
142 allowed_clock_voltage_table
->entries
[i
-1].vddgfx
);
143 voltage
->Vddc
= phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
144 allowed_clock_voltage_table
->entries
[i
-1].vddc
);
146 if (allowed_clock_voltage_table
->entries
[i
-1].vddci
)
147 voltage
->Vddci
= phm_get_voltage_id(&data
->vddci_voltage_table
,
148 allowed_clock_voltage_table
->entries
[i
-1].vddci
);
150 if (allowed_clock_voltage_table
->entries
[i
-1].mvdd
)
151 *mvdd
= (uint32_t) allowed_clock_voltage_table
->entries
[i
-1].mvdd
;
158 * Vddc table preparation for SMC.
160 * @param hwmgr the address of the hardware manager
161 * @param table the SMC DPM table structure to be populated
164 static int tonga_populate_smc_vddc_table(struct pp_hwmgr
*hwmgr
,
165 SMU72_Discrete_DpmTable
*table
)
168 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
170 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
171 table
->VddcLevelCount
= data
->vddc_voltage_table
.count
;
172 for (count
= 0; count
< table
->VddcLevelCount
; count
++) {
173 table
->VddcTable
[count
] =
174 PP_HOST_TO_SMC_US(data
->vddc_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
176 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddcLevelCount
);
182 * VddGfx table preparation for SMC.
184 * @param hwmgr the address of the hardware manager
185 * @param table the SMC DPM table structure to be populated
188 static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr
*hwmgr
,
189 SMU72_Discrete_DpmTable
*table
)
192 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
194 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vdd_gfx_control
) {
195 table
->VddGfxLevelCount
= data
->vddgfx_voltage_table
.count
;
196 for (count
= 0; count
< data
->vddgfx_voltage_table
.count
; count
++) {
197 table
->VddGfxTable
[count
] =
198 PP_HOST_TO_SMC_US(data
->vddgfx_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
200 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddGfxLevelCount
);
206 * Vddci table preparation for SMC.
208 * @param *hwmgr The address of the hardware manager.
209 * @param *table The SMC DPM table structure to be populated.
212 static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr
*hwmgr
,
213 SMU72_Discrete_DpmTable
*table
)
215 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
218 table
->VddciLevelCount
= data
->vddci_voltage_table
.count
;
219 for (count
= 0; count
< table
->VddciLevelCount
; count
++) {
220 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vddci_control
) {
221 table
->VddciTable
[count
] =
222 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
223 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->vddci_control
) {
224 table
->SmioTable1
.Pattern
[count
].Voltage
=
225 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
226 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */
227 table
->SmioTable1
.Pattern
[count
].Smio
=
229 table
->Smio
[count
] |=
230 data
->vddci_voltage_table
.entries
[count
].smio_low
;
231 table
->VddciTable
[count
] =
232 PP_HOST_TO_SMC_US(data
->vddci_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
236 table
->SmioMask1
= data
->vddci_voltage_table
.mask_low
;
237 CONVERT_FROM_HOST_TO_SMC_UL(table
->VddciLevelCount
);
243 * Mvdd table preparation for SMC.
245 * @param *hwmgr The address of the hardware manager.
246 * @param *table The SMC DPM table structure to be populated.
249 static int tonga_populate_smc_mvdd_table(struct pp_hwmgr
*hwmgr
,
250 SMU72_Discrete_DpmTable
*table
)
252 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
255 if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->mvdd_control
) {
256 table
->MvddLevelCount
= data
->mvdd_voltage_table
.count
;
257 for (count
= 0; count
< table
->MvddLevelCount
; count
++) {
258 table
->SmioTable2
.Pattern
[count
].Voltage
=
259 PP_HOST_TO_SMC_US(data
->mvdd_voltage_table
.entries
[count
].value
* VOLTAGE_SCALE
);
260 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
261 table
->SmioTable2
.Pattern
[count
].Smio
=
263 table
->Smio
[count
] |=
264 data
->mvdd_voltage_table
.entries
[count
].smio_low
;
266 table
->SmioMask2
= data
->mvdd_voltage_table
.mask_low
;
268 CONVERT_FROM_HOST_TO_SMC_UL(table
->MvddLevelCount
);
275 * Preparation of vddc and vddgfx CAC tables for SMC.
277 * @param hwmgr the address of the hardware manager
278 * @param table the SMC DPM table structure to be populated
281 static int tonga_populate_cac_tables(struct pp_hwmgr
*hwmgr
,
282 SMU72_Discrete_DpmTable
*table
)
286 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
287 struct phm_ppt_v1_information
*pptable_info
=
288 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
289 struct phm_ppt_v1_voltage_lookup_table
*vddgfx_lookup_table
=
290 pptable_info
->vddgfx_lookup_table
;
291 struct phm_ppt_v1_voltage_lookup_table
*vddc_lookup_table
=
292 pptable_info
->vddc_lookup_table
;
294 /* table is already swapped, so in order to use the value from it
295 * we need to swap it back.
297 uint32_t vddc_level_count
= PP_SMC_TO_HOST_UL(table
->VddcLevelCount
);
298 uint32_t vddgfx_level_count
= PP_SMC_TO_HOST_UL(table
->VddGfxLevelCount
);
300 for (count
= 0; count
< vddc_level_count
; count
++) {
301 /* We are populating vddc CAC data to BapmVddc table in split and merged mode */
302 index
= phm_get_voltage_index(vddc_lookup_table
,
303 data
->vddc_voltage_table
.entries
[count
].value
);
304 table
->BapmVddcVidLoSidd
[count
] =
305 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_low
);
306 table
->BapmVddcVidHiSidd
[count
] =
307 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_mid
);
308 table
->BapmVddcVidHiSidd2
[count
] =
309 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_high
);
312 if ((data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
)) {
313 /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */
314 for (count
= 0; count
< vddgfx_level_count
; count
++) {
315 index
= phm_get_voltage_index(vddgfx_lookup_table
,
316 convert_to_vid(vddgfx_lookup_table
->entries
[index
].us_cac_mid
));
317 table
->BapmVddGfxVidHiSidd2
[count
] =
318 convert_to_vid(vddgfx_lookup_table
->entries
[index
].us_cac_high
);
321 for (count
= 0; count
< vddc_level_count
; count
++) {
322 index
= phm_get_voltage_index(vddc_lookup_table
,
323 data
->vddc_voltage_table
.entries
[count
].value
);
324 table
->BapmVddGfxVidLoSidd
[count
] =
325 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_low
);
326 table
->BapmVddGfxVidHiSidd
[count
] =
327 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_mid
);
328 table
->BapmVddGfxVidHiSidd2
[count
] =
329 convert_to_vid(vddc_lookup_table
->entries
[index
].us_cac_high
);
337 * Preparation of voltage tables for SMC.
339 * @param hwmgr the address of the hardware manager
340 * @param table the SMC DPM table structure to be populated
344 static int tonga_populate_smc_voltage_tables(struct pp_hwmgr
*hwmgr
,
345 SMU72_Discrete_DpmTable
*table
)
349 result
= tonga_populate_smc_vddc_table(hwmgr
, table
);
350 PP_ASSERT_WITH_CODE(!result
,
351 "can not populate VDDC voltage table to SMC",
354 result
= tonga_populate_smc_vdd_ci_table(hwmgr
, table
);
355 PP_ASSERT_WITH_CODE(!result
,
356 "can not populate VDDCI voltage table to SMC",
359 result
= tonga_populate_smc_vdd_gfx_table(hwmgr
, table
);
360 PP_ASSERT_WITH_CODE(!result
,
361 "can not populate VDDGFX voltage table to SMC",
364 result
= tonga_populate_smc_mvdd_table(hwmgr
, table
);
365 PP_ASSERT_WITH_CODE(!result
,
366 "can not populate MVDD voltage table to SMC",
369 result
= tonga_populate_cac_tables(hwmgr
, table
);
370 PP_ASSERT_WITH_CODE(!result
,
371 "can not populate CAC voltage tables to SMC",
377 static int tonga_populate_ulv_level(struct pp_hwmgr
*hwmgr
,
378 struct SMU72_Discrete_Ulv
*state
)
380 struct phm_ppt_v1_information
*table_info
=
381 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
383 state
->CcPwrDynRm
= 0;
384 state
->CcPwrDynRm1
= 0;
386 state
->VddcOffset
= (uint16_t) table_info
->us_ulv_voltage_offset
;
387 state
->VddcOffsetVid
= (uint8_t)(table_info
->us_ulv_voltage_offset
*
388 VOLTAGE_VID_OFFSET_SCALE2
/ VOLTAGE_VID_OFFSET_SCALE1
);
390 state
->VddcPhase
= 1;
392 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm
);
393 CONVERT_FROM_HOST_TO_SMC_UL(state
->CcPwrDynRm1
);
394 CONVERT_FROM_HOST_TO_SMC_US(state
->VddcOffset
);
399 static int tonga_populate_ulv_state(struct pp_hwmgr
*hwmgr
,
400 struct SMU72_Discrete_DpmTable
*table
)
402 return tonga_populate_ulv_level(hwmgr
, &table
->Ulv
);
405 static int tonga_populate_smc_link_level(struct pp_hwmgr
*hwmgr
, SMU72_Discrete_DpmTable
*table
)
407 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
408 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
409 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
412 /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
413 for (i
= 0; i
<= dpm_table
->pcie_speed_table
.count
; i
++) {
414 table
->LinkLevel
[i
].PcieGenSpeed
=
415 (uint8_t)dpm_table
->pcie_speed_table
.dpm_levels
[i
].value
;
416 table
->LinkLevel
[i
].PcieLaneCount
=
417 (uint8_t)encode_pcie_lane_width(dpm_table
->pcie_speed_table
.dpm_levels
[i
].param1
);
418 table
->LinkLevel
[i
].EnabledForActivity
=
420 table
->LinkLevel
[i
].SPC
=
421 (uint8_t)(data
->pcie_spc_cap
& 0xff);
422 table
->LinkLevel
[i
].DownThreshold
=
423 PP_HOST_TO_SMC_UL(5);
424 table
->LinkLevel
[i
].UpThreshold
=
425 PP_HOST_TO_SMC_UL(30);
428 smu_data
->smc_state_table
.LinkLevelCount
=
429 (uint8_t)dpm_table
->pcie_speed_table
.count
;
430 data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
=
431 phm_get_dpm_level_enable_mask_value(&dpm_table
->pcie_speed_table
);
437 * Calculates the SCLK dividers using the provided engine clock
439 * @param hwmgr the address of the hardware manager
440 * @param engine_clock the engine clock to use to populate the structure
441 * @param sclk the SMC SCLK structure to be populated
443 static int tonga_calculate_sclk_params(struct pp_hwmgr
*hwmgr
,
444 uint32_t engine_clock
, SMU72_Discrete_GraphicsLevel
*sclk
)
446 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
447 pp_atomctrl_clock_dividers_vi dividers
;
448 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
449 uint32_t spll_func_cntl_3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
450 uint32_t spll_func_cntl_4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
451 uint32_t cg_spll_spread_spectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
452 uint32_t cg_spll_spread_spectrum_2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
453 uint32_t reference_clock
;
454 uint32_t reference_divider
;
458 /* get the engine clock dividers for this clock value*/
459 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
, engine_clock
, ÷rs
);
461 PP_ASSERT_WITH_CODE(result
== 0,
462 "Error retrieving Engine Clock dividers from VBIOS.", return result
);
464 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
465 reference_clock
= atomctrl_get_reference_clock(hwmgr
);
467 reference_divider
= 1 + dividers
.uc_pll_ref_div
;
469 /* low 14 bits is fraction and high 12 bits is divider*/
470 fbdiv
= dividers
.ul_fb_div
.ul_fb_divider
& 0x3FFFFFF;
472 /* SPLL_FUNC_CNTL setup*/
473 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
,
474 CG_SPLL_FUNC_CNTL
, SPLL_REF_DIV
, dividers
.uc_pll_ref_div
);
475 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
,
476 CG_SPLL_FUNC_CNTL
, SPLL_PDIV_A
, dividers
.uc_pll_post_div
);
478 /* SPLL_FUNC_CNTL_3 setup*/
479 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
,
480 CG_SPLL_FUNC_CNTL_3
, SPLL_FB_DIV
, fbdiv
);
482 /* set to use fractional accumulation*/
483 spll_func_cntl_3
= PHM_SET_FIELD(spll_func_cntl_3
,
484 CG_SPLL_FUNC_CNTL_3
, SPLL_DITHEN
, 1);
486 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
487 PHM_PlatformCaps_EngineSpreadSpectrumSupport
)) {
488 pp_atomctrl_internal_ss_info ss_info
;
490 uint32_t vcoFreq
= engine_clock
* dividers
.uc_pll_post_div
;
491 if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr
, vcoFreq
, &ss_info
)) {
493 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
494 * ss_info.speed_spectrum_rate -- in unit of khz
496 /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
497 uint32_t clkS
= reference_clock
* 5 / (reference_divider
* ss_info
.speed_spectrum_rate
);
499 /* clkv = 2 * D * fbdiv / NS */
500 uint32_t clkV
= 4 * ss_info
.speed_spectrum_percentage
* fbdiv
/ (clkS
* 10000);
502 cg_spll_spread_spectrum
=
503 PHM_SET_FIELD(cg_spll_spread_spectrum
, CG_SPLL_SPREAD_SPECTRUM
, CLKS
, clkS
);
504 cg_spll_spread_spectrum
=
505 PHM_SET_FIELD(cg_spll_spread_spectrum
, CG_SPLL_SPREAD_SPECTRUM
, SSEN
, 1);
506 cg_spll_spread_spectrum_2
=
507 PHM_SET_FIELD(cg_spll_spread_spectrum_2
, CG_SPLL_SPREAD_SPECTRUM_2
, CLKV
, clkV
);
511 sclk
->SclkFrequency
= engine_clock
;
512 sclk
->CgSpllFuncCntl3
= spll_func_cntl_3
;
513 sclk
->CgSpllFuncCntl4
= spll_func_cntl_4
;
514 sclk
->SpllSpreadSpectrum
= cg_spll_spread_spectrum
;
515 sclk
->SpllSpreadSpectrum2
= cg_spll_spread_spectrum_2
;
516 sclk
->SclkDid
= (uint8_t)dividers
.pll_post_divider
;
522 * Populates single SMC SCLK structure using the provided engine clock
524 * @param hwmgr the address of the hardware manager
525 * @param engine_clock the engine clock to use to populate the structure
526 * @param sclk the SMC SCLK structure to be populated
528 static int tonga_populate_single_graphic_level(struct pp_hwmgr
*hwmgr
,
529 uint32_t engine_clock
,
530 uint16_t sclk_activity_level_threshold
,
531 SMU72_Discrete_GraphicsLevel
*graphic_level
)
535 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
536 struct phm_ppt_v1_information
*pptable_info
=
537 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
539 result
= tonga_calculate_sclk_params(hwmgr
, engine_clock
, graphic_level
);
541 /* populate graphics levels*/
542 result
= tonga_get_dependecy_volt_by_clk(hwmgr
,
543 pptable_info
->vdd_dep_on_sclk
, engine_clock
,
544 &graphic_level
->MinVoltage
, &mvdd
);
545 PP_ASSERT_WITH_CODE((!result
),
546 "can not find VDDC voltage value for VDDC "
547 "engine clock dependency table", return result
);
549 /* SCLK frequency in units of 10KHz*/
550 graphic_level
->SclkFrequency
= engine_clock
;
551 /* Indicates maximum activity level for this performance level. 50% for now*/
552 graphic_level
->ActivityLevel
= sclk_activity_level_threshold
;
554 graphic_level
->CcPwrDynRm
= 0;
555 graphic_level
->CcPwrDynRm1
= 0;
556 /* this level can be used if activity is high enough.*/
557 graphic_level
->EnabledForActivity
= 0;
558 /* this level can be used for throttling.*/
559 graphic_level
->EnabledForThrottle
= 1;
560 graphic_level
->UpHyst
= 0;
561 graphic_level
->DownHyst
= 0;
562 graphic_level
->VoltageDownHyst
= 0;
563 graphic_level
->PowerThrottle
= 0;
565 data
->display_timing
.min_clock_in_sr
=
566 hwmgr
->display_config
.min_core_set_clock_in_sr
;
568 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
569 PHM_PlatformCaps_SclkDeepSleep
))
570 graphic_level
->DeepSleepDivId
=
571 smu7_get_sleep_divider_id_from_clock(engine_clock
,
572 data
->display_timing
.min_clock_in_sr
);
574 /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
575 graphic_level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
578 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/
579 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/
580 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SclkFrequency
);
581 CONVERT_FROM_HOST_TO_SMC_US(graphic_level
->ActivityLevel
);
582 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CgSpllFuncCntl3
);
583 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CgSpllFuncCntl4
);
584 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SpllSpreadSpectrum
);
585 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->SpllSpreadSpectrum2
);
586 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CcPwrDynRm
);
587 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level
->CcPwrDynRm1
);
594 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
596 * @param hwmgr the address of the hardware manager
598 int tonga_populate_all_graphic_levels(struct pp_hwmgr
*hwmgr
)
600 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
601 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
602 struct phm_ppt_v1_information
*pptable_info
= (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
603 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
604 struct phm_ppt_v1_pcie_table
*pcie_table
= pptable_info
->pcie_table
;
605 uint8_t pcie_entry_count
= (uint8_t) data
->dpm_table
.pcie_speed_table
.count
;
606 uint32_t level_array_address
= smu_data
->smu7_data
.dpm_table_start
+
607 offsetof(SMU72_Discrete_DpmTable
, GraphicsLevel
);
609 uint32_t level_array_size
= sizeof(SMU72_Discrete_GraphicsLevel
) *
610 SMU72_MAX_LEVELS_GRAPHICS
;
612 SMU72_Discrete_GraphicsLevel
*levels
= smu_data
->smc_state_table
.GraphicsLevel
;
614 uint32_t i
, max_entry
;
615 uint8_t highest_pcie_level_enabled
= 0;
616 uint8_t lowest_pcie_level_enabled
= 0, mid_pcie_level_enabled
= 0;
620 memset(levels
, 0x00, level_array_size
);
622 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++) {
623 result
= tonga_populate_single_graphic_level(hwmgr
,
624 dpm_table
->sclk_table
.dpm_levels
[i
].value
,
625 (uint16_t)smu_data
->activity_target
[i
],
626 &(smu_data
->smc_state_table
.GraphicsLevel
[i
]));
630 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
632 smu_data
->smc_state_table
.GraphicsLevel
[i
].DeepSleepDivId
= 0;
635 /* Only enable level 0 for now. */
636 smu_data
->smc_state_table
.GraphicsLevel
[0].EnabledForActivity
= 1;
638 /* set highest level watermark to high */
639 if (dpm_table
->sclk_table
.count
> 1)
640 smu_data
->smc_state_table
.GraphicsLevel
[dpm_table
->sclk_table
.count
-1].DisplayWatermark
=
641 PPSMC_DISPLAY_WATERMARK_HIGH
;
643 smu_data
->smc_state_table
.GraphicsDpmLevelCount
=
644 (uint8_t)dpm_table
->sclk_table
.count
;
645 data
->dpm_level_enable_mask
.sclk_dpm_enable_mask
=
646 phm_get_dpm_level_enable_mask_value(&dpm_table
->sclk_table
);
648 if (pcie_table
!= NULL
) {
649 PP_ASSERT_WITH_CODE((pcie_entry_count
>= 1),
650 "There must be 1 or more PCIE levels defined in PPTable.",
652 max_entry
= pcie_entry_count
- 1; /* for indexing, we need to decrement by 1.*/
653 for (i
= 0; i
< dpm_table
->sclk_table
.count
; i
++) {
654 smu_data
->smc_state_table
.GraphicsLevel
[i
].pcieDpmLevel
=
655 (uint8_t) ((i
< max_entry
) ? i
: max_entry
);
658 if (0 == data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
)
659 printk(KERN_ERR
"[ powerplay ] Pcie Dpm Enablemask is 0 !");
661 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
662 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
663 (1<<(highest_pcie_level_enabled
+1))) != 0)) {
664 highest_pcie_level_enabled
++;
667 while (data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&&
668 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
669 (1<<lowest_pcie_level_enabled
)) == 0)) {
670 lowest_pcie_level_enabled
++;
673 while ((count
< highest_pcie_level_enabled
) &&
674 ((data
->dpm_level_enable_mask
.pcie_dpm_enable_mask
&
675 (1<<(lowest_pcie_level_enabled
+1+count
))) == 0)) {
678 mid_pcie_level_enabled
= (lowest_pcie_level_enabled
+1+count
) < highest_pcie_level_enabled
?
679 (lowest_pcie_level_enabled
+1+count
) : highest_pcie_level_enabled
;
682 /* set pcieDpmLevel to highest_pcie_level_enabled*/
683 for (i
= 2; i
< dpm_table
->sclk_table
.count
; i
++)
684 smu_data
->smc_state_table
.GraphicsLevel
[i
].pcieDpmLevel
= highest_pcie_level_enabled
;
686 /* set pcieDpmLevel to lowest_pcie_level_enabled*/
687 smu_data
->smc_state_table
.GraphicsLevel
[0].pcieDpmLevel
= lowest_pcie_level_enabled
;
689 /* set pcieDpmLevel to mid_pcie_level_enabled*/
690 smu_data
->smc_state_table
.GraphicsLevel
[1].pcieDpmLevel
= mid_pcie_level_enabled
;
692 /* level count will send to smc once at init smc table and never change*/
693 result
= smu7_copy_bytes_to_smc(hwmgr
->smumgr
, level_array_address
,
694 (uint8_t *)levels
, (uint32_t)level_array_size
,
701 * Populates the SMC MCLK structure using the provided memory clock
703 * @param hwmgr the address of the hardware manager
704 * @param memory_clock the memory clock to use to populate the structure
705 * @param sclk the SMC SCLK structure to be populated
707 static int tonga_calculate_mclk_params(
708 struct pp_hwmgr
*hwmgr
,
709 uint32_t memory_clock
,
710 SMU72_Discrete_MemoryLevel
*mclk
,
715 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
717 uint32_t dll_cntl
= data
->clock_registers
.vDLL_CNTL
;
718 uint32_t mclk_pwrmgt_cntl
= data
->clock_registers
.vMCLK_PWRMGT_CNTL
;
719 uint32_t mpll_ad_func_cntl
= data
->clock_registers
.vMPLL_AD_FUNC_CNTL
;
720 uint32_t mpll_dq_func_cntl
= data
->clock_registers
.vMPLL_DQ_FUNC_CNTL
;
721 uint32_t mpll_func_cntl
= data
->clock_registers
.vMPLL_FUNC_CNTL
;
722 uint32_t mpll_func_cntl_1
= data
->clock_registers
.vMPLL_FUNC_CNTL_1
;
723 uint32_t mpll_func_cntl_2
= data
->clock_registers
.vMPLL_FUNC_CNTL_2
;
724 uint32_t mpll_ss1
= data
->clock_registers
.vMPLL_SS1
;
725 uint32_t mpll_ss2
= data
->clock_registers
.vMPLL_SS2
;
727 pp_atomctrl_memory_clock_param mpll_param
;
730 result
= atomctrl_get_memory_pll_dividers_si(hwmgr
,
731 memory_clock
, &mpll_param
, strobe_mode
);
734 "Error retrieving Memory Clock Parameters from VBIOS.",
737 /* MPLL_FUNC_CNTL setup*/
738 mpll_func_cntl
= PHM_SET_FIELD(mpll_func_cntl
, MPLL_FUNC_CNTL
, BWCTRL
,
741 /* MPLL_FUNC_CNTL_1 setup*/
742 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
743 MPLL_FUNC_CNTL_1
, CLKF
,
744 mpll_param
.mpll_fb_divider
.cl_kf
);
745 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
746 MPLL_FUNC_CNTL_1
, CLKFRAC
,
747 mpll_param
.mpll_fb_divider
.clk_frac
);
748 mpll_func_cntl_1
= PHM_SET_FIELD(mpll_func_cntl_1
,
749 MPLL_FUNC_CNTL_1
, VCO_MODE
,
750 mpll_param
.vco_mode
);
752 /* MPLL_AD_FUNC_CNTL setup*/
753 mpll_ad_func_cntl
= PHM_SET_FIELD(mpll_ad_func_cntl
,
754 MPLL_AD_FUNC_CNTL
, YCLK_POST_DIV
,
755 mpll_param
.mpll_post_divider
);
757 if (data
->is_memory_gddr5
) {
758 /* MPLL_DQ_FUNC_CNTL setup*/
759 mpll_dq_func_cntl
= PHM_SET_FIELD(mpll_dq_func_cntl
,
760 MPLL_DQ_FUNC_CNTL
, YCLK_SEL
,
761 mpll_param
.yclk_sel
);
762 mpll_dq_func_cntl
= PHM_SET_FIELD(mpll_dq_func_cntl
,
763 MPLL_DQ_FUNC_CNTL
, YCLK_POST_DIV
,
764 mpll_param
.mpll_post_divider
);
767 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
768 PHM_PlatformCaps_MemorySpreadSpectrumSupport
)) {
770 ************************************
771 Fref = Reference Frequency
772 NF = Feedback divider ratio
773 NR = Reference divider ratio
774 Fnom = Nominal VCO output frequency = Fref * NF / NR
776 D = Percentage down-spread / 2
777 Fint = Reference input frequency to PFD = Fref / NR
778 NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
779 CLKS = NS - 1 = ISS_STEP_NUM[11:0]
780 NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
781 CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
782 *************************************
784 pp_atomctrl_internal_ss_info ss_info
;
787 uint32_t reference_clock
= atomctrl_get_mpll_reference_clock(hwmgr
);
789 /* for GDDR5 for all modes and DDR3 */
790 if (1 == mpll_param
.qdr
)
791 freq_nom
= memory_clock
* 4 * (1 << mpll_param
.mpll_post_divider
);
793 freq_nom
= memory_clock
* 2 * (1 << mpll_param
.mpll_post_divider
);
795 /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/
796 tmp
= (freq_nom
/ reference_clock
);
799 if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr
, freq_nom
, &ss_info
)) {
800 /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
801 /* ss.Info.speed_spectrum_rate -- in unit of khz */
802 /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
803 /* = reference_clock * 5 / speed_spectrum_rate */
804 uint32_t clks
= reference_clock
* 5 / ss_info
.speed_spectrum_rate
;
806 /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
807 /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
809 (uint32_t)((((131 * ss_info
.speed_spectrum_percentage
*
810 ss_info
.speed_spectrum_rate
) / 100) * tmp
) / freq_nom
);
812 mpll_ss1
= PHM_SET_FIELD(mpll_ss1
, MPLL_SS1
, CLKV
, clkv
);
813 mpll_ss2
= PHM_SET_FIELD(mpll_ss2
, MPLL_SS2
, CLKS
, clks
);
817 /* MCLK_PWRMGT_CNTL setup */
818 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
819 MCLK_PWRMGT_CNTL
, DLL_SPEED
, mpll_param
.dll_speed
);
820 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
821 MCLK_PWRMGT_CNTL
, MRDCK0_PDNB
, dllStateOn
);
822 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
823 MCLK_PWRMGT_CNTL
, MRDCK1_PDNB
, dllStateOn
);
825 /* Save the result data to outpupt memory level structure */
826 mclk
->MclkFrequency
= memory_clock
;
827 mclk
->MpllFuncCntl
= mpll_func_cntl
;
828 mclk
->MpllFuncCntl_1
= mpll_func_cntl_1
;
829 mclk
->MpllFuncCntl_2
= mpll_func_cntl_2
;
830 mclk
->MpllAdFuncCntl
= mpll_ad_func_cntl
;
831 mclk
->MpllDqFuncCntl
= mpll_dq_func_cntl
;
832 mclk
->MclkPwrmgtCntl
= mclk_pwrmgt_cntl
;
833 mclk
->DllCntl
= dll_cntl
;
834 mclk
->MpllSs1
= mpll_ss1
;
835 mclk
->MpllSs2
= mpll_ss2
;
840 static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock
,
843 uint8_t mc_para_index
;
846 if (memory_clock
< 12500)
847 mc_para_index
= 0x00;
848 else if (memory_clock
> 47500)
849 mc_para_index
= 0x0f;
851 mc_para_index
= (uint8_t)((memory_clock
- 10000) / 2500);
853 if (memory_clock
< 65000)
854 mc_para_index
= 0x00;
855 else if (memory_clock
> 135000)
856 mc_para_index
= 0x0f;
858 mc_para_index
= (uint8_t)((memory_clock
- 60000) / 5000);
861 return mc_para_index
;
864 static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock
)
866 uint8_t mc_para_index
;
868 if (memory_clock
< 10000)
870 else if (memory_clock
>= 80000)
871 mc_para_index
= 0x0f;
873 mc_para_index
= (uint8_t)((memory_clock
- 10000) / 5000 + 1);
875 return mc_para_index
;
879 static int tonga_populate_single_memory_level(
880 struct pp_hwmgr
*hwmgr
,
881 uint32_t memory_clock
,
882 SMU72_Discrete_MemoryLevel
*memory_level
886 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
887 struct phm_ppt_v1_information
*pptable_info
=
888 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
891 struct cgs_display_info info
= {0};
892 uint32_t mclk_edc_wr_enable_threshold
= 40000;
893 uint32_t mclk_stutter_mode_threshold
= 30000;
894 uint32_t mclk_edc_enable_threshold
= 40000;
895 uint32_t mclk_strobe_mode_threshold
= 40000;
897 if (NULL
!= pptable_info
->vdd_dep_on_mclk
) {
898 result
= tonga_get_dependecy_volt_by_clk(hwmgr
,
899 pptable_info
->vdd_dep_on_mclk
,
901 &memory_level
->MinVoltage
, &mvdd
);
904 "can not find MinVddc voltage value from memory VDDC "
905 "voltage dependency table",
909 if (data
->mvdd_control
== SMU7_VOLTAGE_CONTROL_NONE
)
910 memory_level
->MinMvdd
= data
->vbios_boot_state
.mvdd_bootup_value
;
912 memory_level
->MinMvdd
= mvdd
;
914 memory_level
->EnabledForThrottle
= 1;
915 memory_level
->EnabledForActivity
= 0;
916 memory_level
->UpHyst
= 0;
917 memory_level
->DownHyst
= 100;
918 memory_level
->VoltageDownHyst
= 0;
920 /* Indicates maximum activity level for this performance level.*/
921 memory_level
->ActivityLevel
= (uint16_t)data
->mclk_activity_target
;
922 memory_level
->StutterEnable
= 0;
923 memory_level
->StrobeEnable
= 0;
924 memory_level
->EdcReadEnable
= 0;
925 memory_level
->EdcWriteEnable
= 0;
926 memory_level
->RttEnable
= 0;
928 /* default set to low watermark. Highest level will be set to high later.*/
929 memory_level
->DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
931 cgs_get_active_displays_info(hwmgr
->device
, &info
);
932 data
->display_timing
.num_existing_displays
= info
.display_count
;
934 if ((mclk_stutter_mode_threshold
!= 0) &&
935 (memory_clock
<= mclk_stutter_mode_threshold
) &&
936 (!data
->is_uvd_enabled
)
937 && (PHM_READ_FIELD(hwmgr
->device
, DPG_PIPE_STUTTER_CONTROL
, STUTTER_ENABLE
) & 0x1)
938 && (data
->display_timing
.num_existing_displays
<= 2)
939 && (data
->display_timing
.num_existing_displays
!= 0))
940 memory_level
->StutterEnable
= 1;
942 /* decide strobe mode*/
943 memory_level
->StrobeEnable
= (mclk_strobe_mode_threshold
!= 0) &&
944 (memory_clock
<= mclk_strobe_mode_threshold
);
946 /* decide EDC mode and memory clock ratio*/
947 if (data
->is_memory_gddr5
) {
948 memory_level
->StrobeRatio
= tonga_get_mclk_frequency_ratio(memory_clock
,
949 memory_level
->StrobeEnable
);
951 if ((mclk_edc_enable_threshold
!= 0) &&
952 (memory_clock
> mclk_edc_enable_threshold
)) {
953 memory_level
->EdcReadEnable
= 1;
956 if ((mclk_edc_wr_enable_threshold
!= 0) &&
957 (memory_clock
> mclk_edc_wr_enable_threshold
)) {
958 memory_level
->EdcWriteEnable
= 1;
961 if (memory_level
->StrobeEnable
) {
962 if (tonga_get_mclk_frequency_ratio(memory_clock
, 1) >=
963 ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC7
) >> 16) & 0xf)) {
964 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC5
) >> 1) & 0x1) ? 1 : 0;
966 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC6
) >> 1) & 0x1) ? 1 : 0;
970 dll_state_on
= data
->dll_default_on
;
973 memory_level
->StrobeRatio
=
974 tonga_get_ddr3_mclk_frequency_ratio(memory_clock
);
975 dll_state_on
= ((cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC5
) >> 1) & 0x1) ? 1 : 0;
978 result
= tonga_calculate_mclk_params(hwmgr
,
979 memory_clock
, memory_level
, memory_level
->StrobeEnable
, dll_state_on
);
982 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MinMvdd
);
983 /* MCLK frequency in units of 10KHz*/
984 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MclkFrequency
);
985 /* Indicates maximum activity level for this performance level.*/
986 CONVERT_FROM_HOST_TO_SMC_US(memory_level
->ActivityLevel
);
987 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl
);
988 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl_1
);
989 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllFuncCntl_2
);
990 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllAdFuncCntl
);
991 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllDqFuncCntl
);
992 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MclkPwrmgtCntl
);
993 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->DllCntl
);
994 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllSs1
);
995 CONVERT_FROM_HOST_TO_SMC_UL(memory_level
->MpllSs2
);
1001 int tonga_populate_all_memory_levels(struct pp_hwmgr
*hwmgr
)
1003 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1004 struct tonga_smumgr
*smu_data
=
1005 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1006 struct smu7_dpm_table
*dpm_table
= &data
->dpm_table
;
1009 /* populate MCLK dpm table to SMU7 */
1010 uint32_t level_array_address
=
1011 smu_data
->smu7_data
.dpm_table_start
+
1012 offsetof(SMU72_Discrete_DpmTable
, MemoryLevel
);
1013 uint32_t level_array_size
=
1014 sizeof(SMU72_Discrete_MemoryLevel
) *
1015 SMU72_MAX_LEVELS_MEMORY
;
1016 SMU72_Discrete_MemoryLevel
*levels
=
1017 smu_data
->smc_state_table
.MemoryLevel
;
1020 memset(levels
, 0x00, level_array_size
);
1022 for (i
= 0; i
< dpm_table
->mclk_table
.count
; i
++) {
1023 PP_ASSERT_WITH_CODE((0 != dpm_table
->mclk_table
.dpm_levels
[i
].value
),
1024 "can not populate memory level as memory clock is zero",
1026 result
= tonga_populate_single_memory_level(
1028 dpm_table
->mclk_table
.dpm_levels
[i
].value
,
1029 &(smu_data
->smc_state_table
.MemoryLevel
[i
]));
1034 /* Only enable level 0 for now.*/
1035 smu_data
->smc_state_table
.MemoryLevel
[0].EnabledForActivity
= 1;
1038 * in order to prevent MC activity from stutter mode to push DPM up.
1039 * the UVD change complements this by putting the MCLK in a higher state
1040 * by default such that we are not effected by up threshold or and MCLK DPM latency.
1042 smu_data
->smc_state_table
.MemoryLevel
[0].ActivityLevel
= 0x1F;
1043 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.MemoryLevel
[0].ActivityLevel
);
1045 smu_data
->smc_state_table
.MemoryDpmLevelCount
= (uint8_t)dpm_table
->mclk_table
.count
;
1046 data
->dpm_level_enable_mask
.mclk_dpm_enable_mask
= phm_get_dpm_level_enable_mask_value(&dpm_table
->mclk_table
);
1047 /* set highest level watermark to high*/
1048 smu_data
->smc_state_table
.MemoryLevel
[dpm_table
->mclk_table
.count
-1].DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_HIGH
;
1050 /* level count will send to smc once at init smc table and never change*/
1051 result
= smu7_copy_bytes_to_smc(hwmgr
->smumgr
,
1052 level_array_address
, (uint8_t *)levels
, (uint32_t)level_array_size
,
1058 static int tonga_populate_mvdd_value(struct pp_hwmgr
*hwmgr
,
1059 uint32_t mclk
, SMIO_Pattern
*smio_pattern
)
1061 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1062 struct phm_ppt_v1_information
*table_info
=
1063 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1066 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->mvdd_control
) {
1067 /* find mvdd value which clock is more than request */
1068 for (i
= 0; i
< table_info
->vdd_dep_on_mclk
->count
; i
++) {
1069 if (mclk
<= table_info
->vdd_dep_on_mclk
->entries
[i
].clk
) {
1070 /* Always round to higher voltage. */
1071 smio_pattern
->Voltage
=
1072 data
->mvdd_voltage_table
.entries
[i
].value
;
1077 PP_ASSERT_WITH_CODE(i
< table_info
->vdd_dep_on_mclk
->count
,
1078 "MVDD Voltage is outside the supported range.",
1088 static int tonga_populate_smc_acpi_level(struct pp_hwmgr
*hwmgr
,
1089 SMU72_Discrete_DpmTable
*table
)
1092 struct tonga_smumgr
*smu_data
=
1093 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1094 const struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1095 struct pp_atomctrl_clock_dividers_vi dividers
;
1097 SMIO_Pattern voltage_level
;
1098 uint32_t spll_func_cntl
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL
;
1099 uint32_t spll_func_cntl_2
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_2
;
1100 uint32_t dll_cntl
= data
->clock_registers
.vDLL_CNTL
;
1101 uint32_t mclk_pwrmgt_cntl
= data
->clock_registers
.vMCLK_PWRMGT_CNTL
;
1103 /* The ACPI state should not do DPM on DC (or ever).*/
1104 table
->ACPILevel
.Flags
&= ~PPSMC_SWSTATE_FLAG_DC
;
1106 table
->ACPILevel
.MinVoltage
=
1107 smu_data
->smc_state_table
.GraphicsLevel
[0].MinVoltage
;
1109 /* assign zero for now*/
1110 table
->ACPILevel
.SclkFrequency
= atomctrl_get_reference_clock(hwmgr
);
1112 /* get the engine clock dividers for this clock value*/
1113 result
= atomctrl_get_engine_pll_dividers_vi(hwmgr
,
1114 table
->ACPILevel
.SclkFrequency
, ÷rs
);
1116 PP_ASSERT_WITH_CODE(result
== 0,
1117 "Error retrieving Engine Clock dividers from VBIOS.",
1120 /* divider ID for required SCLK*/
1121 table
->ACPILevel
.SclkDid
= (uint8_t)dividers
.pll_post_divider
;
1122 table
->ACPILevel
.DisplayWatermark
= PPSMC_DISPLAY_WATERMARK_LOW
;
1123 table
->ACPILevel
.DeepSleepDivId
= 0;
1125 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1127 spll_func_cntl
= PHM_SET_FIELD(spll_func_cntl
, CG_SPLL_FUNC_CNTL
,
1129 spll_func_cntl_2
= PHM_SET_FIELD(spll_func_cntl_2
, CG_SPLL_FUNC_CNTL_2
,
1132 table
->ACPILevel
.CgSpllFuncCntl
= spll_func_cntl
;
1133 table
->ACPILevel
.CgSpllFuncCntl2
= spll_func_cntl_2
;
1134 table
->ACPILevel
.CgSpllFuncCntl3
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_3
;
1135 table
->ACPILevel
.CgSpllFuncCntl4
= data
->clock_registers
.vCG_SPLL_FUNC_CNTL_4
;
1136 table
->ACPILevel
.SpllSpreadSpectrum
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM
;
1137 table
->ACPILevel
.SpllSpreadSpectrum2
= data
->clock_registers
.vCG_SPLL_SPREAD_SPECTRUM_2
;
1138 table
->ACPILevel
.CcPwrDynRm
= 0;
1139 table
->ACPILevel
.CcPwrDynRm1
= 0;
1142 /* For various features to be enabled/disabled while this level is active.*/
1143 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.Flags
);
1144 /* SCLK frequency in units of 10KHz*/
1145 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SclkFrequency
);
1146 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl
);
1147 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl2
);
1148 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl3
);
1149 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CgSpllFuncCntl4
);
1150 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum
);
1151 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.SpllSpreadSpectrum2
);
1152 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm
);
1153 CONVERT_FROM_HOST_TO_SMC_UL(table
->ACPILevel
.CcPwrDynRm1
);
1155 /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
1156 table
->MemoryACPILevel
.MinVoltage
=
1157 smu_data
->smc_state_table
.MemoryLevel
[0].MinVoltage
;
1159 /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/
1161 if (0 == tonga_populate_mvdd_value(hwmgr
, 0, &voltage_level
))
1162 table
->MemoryACPILevel
.MinMvdd
=
1163 PP_HOST_TO_SMC_UL(voltage_level
.Voltage
* VOLTAGE_SCALE
);
1165 table
->MemoryACPILevel
.MinMvdd
= 0;
1167 /* Force reset on DLL*/
1168 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1169 MCLK_PWRMGT_CNTL
, MRDCK0_RESET
, 0x1);
1170 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1171 MCLK_PWRMGT_CNTL
, MRDCK1_RESET
, 0x1);
1173 /* Disable DLL in ACPIState*/
1174 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1175 MCLK_PWRMGT_CNTL
, MRDCK0_PDNB
, 0);
1176 mclk_pwrmgt_cntl
= PHM_SET_FIELD(mclk_pwrmgt_cntl
,
1177 MCLK_PWRMGT_CNTL
, MRDCK1_PDNB
, 0);
1179 /* Enable DLL bypass signal*/
1180 dll_cntl
= PHM_SET_FIELD(dll_cntl
,
1181 DLL_CNTL
, MRDCK0_BYPASS
, 0);
1182 dll_cntl
= PHM_SET_FIELD(dll_cntl
,
1183 DLL_CNTL
, MRDCK1_BYPASS
, 0);
1185 table
->MemoryACPILevel
.DllCntl
=
1186 PP_HOST_TO_SMC_UL(dll_cntl
);
1187 table
->MemoryACPILevel
.MclkPwrmgtCntl
=
1188 PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl
);
1189 table
->MemoryACPILevel
.MpllAdFuncCntl
=
1190 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_AD_FUNC_CNTL
);
1191 table
->MemoryACPILevel
.MpllDqFuncCntl
=
1192 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_DQ_FUNC_CNTL
);
1193 table
->MemoryACPILevel
.MpllFuncCntl
=
1194 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL
);
1195 table
->MemoryACPILevel
.MpllFuncCntl_1
=
1196 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL_1
);
1197 table
->MemoryACPILevel
.MpllFuncCntl_2
=
1198 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_FUNC_CNTL_2
);
1199 table
->MemoryACPILevel
.MpllSs1
=
1200 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_SS1
);
1201 table
->MemoryACPILevel
.MpllSs2
=
1202 PP_HOST_TO_SMC_UL(data
->clock_registers
.vMPLL_SS2
);
1204 table
->MemoryACPILevel
.EnabledForThrottle
= 0;
1205 table
->MemoryACPILevel
.EnabledForActivity
= 0;
1206 table
->MemoryACPILevel
.UpHyst
= 0;
1207 table
->MemoryACPILevel
.DownHyst
= 100;
1208 table
->MemoryACPILevel
.VoltageDownHyst
= 0;
1209 /* Indicates maximum activity level for this performance level.*/
1210 table
->MemoryACPILevel
.ActivityLevel
=
1211 PP_HOST_TO_SMC_US((uint16_t)data
->mclk_activity_target
);
1213 table
->MemoryACPILevel
.StutterEnable
= 0;
1214 table
->MemoryACPILevel
.StrobeEnable
= 0;
1215 table
->MemoryACPILevel
.EdcReadEnable
= 0;
1216 table
->MemoryACPILevel
.EdcWriteEnable
= 0;
1217 table
->MemoryACPILevel
.RttEnable
= 0;
1222 static int tonga_populate_smc_uvd_level(struct pp_hwmgr
*hwmgr
,
1223 SMU72_Discrete_DpmTable
*table
)
1228 pp_atomctrl_clock_dividers_vi dividers
;
1229 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1230 struct phm_ppt_v1_information
*pptable_info
=
1231 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1232 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1233 pptable_info
->mm_dep_table
;
1235 table
->UvdLevelCount
= (uint8_t) (mm_table
->count
);
1236 table
->UvdBootLevel
= 0;
1238 for (count
= 0; count
< table
->UvdLevelCount
; count
++) {
1239 table
->UvdLevel
[count
].VclkFrequency
= mm_table
->entries
[count
].vclk
;
1240 table
->UvdLevel
[count
].DclkFrequency
= mm_table
->entries
[count
].dclk
;
1241 table
->UvdLevel
[count
].MinVoltage
.Vddc
=
1242 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1243 mm_table
->entries
[count
].vddc
);
1244 table
->UvdLevel
[count
].MinVoltage
.VddGfx
=
1245 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1246 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1247 mm_table
->entries
[count
].vddgfx
) : 0;
1248 table
->UvdLevel
[count
].MinVoltage
.Vddci
=
1249 phm_get_voltage_id(&data
->vddci_voltage_table
,
1250 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1251 table
->UvdLevel
[count
].MinVoltage
.Phases
= 1;
1253 /* retrieve divider value for VBIOS */
1254 result
= atomctrl_get_dfs_pll_dividers_vi(
1256 table
->UvdLevel
[count
].VclkFrequency
,
1259 PP_ASSERT_WITH_CODE((!result
),
1260 "can not find divide id for Vclk clock",
1263 table
->UvdLevel
[count
].VclkDivider
= (uint8_t)dividers
.pll_post_divider
;
1265 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1266 table
->UvdLevel
[count
].DclkFrequency
, ÷rs
);
1267 PP_ASSERT_WITH_CODE((!result
),
1268 "can not find divide id for Dclk clock",
1271 table
->UvdLevel
[count
].DclkDivider
=
1272 (uint8_t)dividers
.pll_post_divider
;
1274 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].VclkFrequency
);
1275 CONVERT_FROM_HOST_TO_SMC_UL(table
->UvdLevel
[count
].DclkFrequency
);
1282 static int tonga_populate_smc_vce_level(struct pp_hwmgr
*hwmgr
,
1283 SMU72_Discrete_DpmTable
*table
)
1288 pp_atomctrl_clock_dividers_vi dividers
;
1289 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1290 struct phm_ppt_v1_information
*pptable_info
=
1291 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1292 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1293 pptable_info
->mm_dep_table
;
1295 table
->VceLevelCount
= (uint8_t) (mm_table
->count
);
1296 table
->VceBootLevel
= 0;
1298 for (count
= 0; count
< table
->VceLevelCount
; count
++) {
1299 table
->VceLevel
[count
].Frequency
=
1300 mm_table
->entries
[count
].eclk
;
1301 table
->VceLevel
[count
].MinVoltage
.Vddc
=
1302 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1303 mm_table
->entries
[count
].vddc
);
1304 table
->VceLevel
[count
].MinVoltage
.VddGfx
=
1305 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1306 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1307 mm_table
->entries
[count
].vddgfx
) : 0;
1308 table
->VceLevel
[count
].MinVoltage
.Vddci
=
1309 phm_get_voltage_id(&data
->vddci_voltage_table
,
1310 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1311 table
->VceLevel
[count
].MinVoltage
.Phases
= 1;
1313 /* retrieve divider value for VBIOS */
1314 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1315 table
->VceLevel
[count
].Frequency
, ÷rs
);
1316 PP_ASSERT_WITH_CODE((!result
),
1317 "can not find divide id for VCE engine clock",
1320 table
->VceLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1322 CONVERT_FROM_HOST_TO_SMC_UL(table
->VceLevel
[count
].Frequency
);
1328 static int tonga_populate_smc_acp_level(struct pp_hwmgr
*hwmgr
,
1329 SMU72_Discrete_DpmTable
*table
)
1333 pp_atomctrl_clock_dividers_vi dividers
;
1334 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1335 struct phm_ppt_v1_information
*pptable_info
=
1336 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1337 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1338 pptable_info
->mm_dep_table
;
1340 table
->AcpLevelCount
= (uint8_t) (mm_table
->count
);
1341 table
->AcpBootLevel
= 0;
1343 for (count
= 0; count
< table
->AcpLevelCount
; count
++) {
1344 table
->AcpLevel
[count
].Frequency
=
1345 pptable_info
->mm_dep_table
->entries
[count
].aclk
;
1346 table
->AcpLevel
[count
].MinVoltage
.Vddc
=
1347 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1348 mm_table
->entries
[count
].vddc
);
1349 table
->AcpLevel
[count
].MinVoltage
.VddGfx
=
1350 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1351 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1352 mm_table
->entries
[count
].vddgfx
) : 0;
1353 table
->AcpLevel
[count
].MinVoltage
.Vddci
=
1354 phm_get_voltage_id(&data
->vddci_voltage_table
,
1355 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1356 table
->AcpLevel
[count
].MinVoltage
.Phases
= 1;
1358 /* retrieve divider value for VBIOS */
1359 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1360 table
->AcpLevel
[count
].Frequency
, ÷rs
);
1361 PP_ASSERT_WITH_CODE((!result
),
1362 "can not find divide id for engine clock", return result
);
1364 table
->AcpLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1366 CONVERT_FROM_HOST_TO_SMC_UL(table
->AcpLevel
[count
].Frequency
);
1372 static int tonga_populate_smc_samu_level(struct pp_hwmgr
*hwmgr
,
1373 SMU72_Discrete_DpmTable
*table
)
1377 pp_atomctrl_clock_dividers_vi dividers
;
1378 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1379 struct phm_ppt_v1_information
*pptable_info
=
1380 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1381 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
=
1382 pptable_info
->mm_dep_table
;
1384 table
->SamuBootLevel
= 0;
1385 table
->SamuLevelCount
= (uint8_t) (mm_table
->count
);
1387 for (count
= 0; count
< table
->SamuLevelCount
; count
++) {
1388 /* not sure whether we need evclk or not */
1389 table
->SamuLevel
[count
].Frequency
=
1390 pptable_info
->mm_dep_table
->entries
[count
].samclock
;
1391 table
->SamuLevel
[count
].MinVoltage
.Vddc
=
1392 phm_get_voltage_index(pptable_info
->vddc_lookup_table
,
1393 mm_table
->entries
[count
].vddc
);
1394 table
->SamuLevel
[count
].MinVoltage
.VddGfx
=
1395 (data
->vdd_gfx_control
== SMU7_VOLTAGE_CONTROL_BY_SVID2
) ?
1396 phm_get_voltage_index(pptable_info
->vddgfx_lookup_table
,
1397 mm_table
->entries
[count
].vddgfx
) : 0;
1398 table
->SamuLevel
[count
].MinVoltage
.Vddci
=
1399 phm_get_voltage_id(&data
->vddci_voltage_table
,
1400 mm_table
->entries
[count
].vddc
- VDDC_VDDCI_DELTA
);
1401 table
->SamuLevel
[count
].MinVoltage
.Phases
= 1;
1403 /* retrieve divider value for VBIOS */
1404 result
= atomctrl_get_dfs_pll_dividers_vi(hwmgr
,
1405 table
->SamuLevel
[count
].Frequency
, ÷rs
);
1406 PP_ASSERT_WITH_CODE((!result
),
1407 "can not find divide id for samu clock", return result
);
1409 table
->SamuLevel
[count
].Divider
= (uint8_t)dividers
.pll_post_divider
;
1411 CONVERT_FROM_HOST_TO_SMC_UL(table
->SamuLevel
[count
].Frequency
);
1417 static int tonga_populate_memory_timing_parameters(
1418 struct pp_hwmgr
*hwmgr
,
1419 uint32_t engine_clock
,
1420 uint32_t memory_clock
,
1421 struct SMU72_Discrete_MCArbDramTimingTableEntry
*arb_regs
1424 uint32_t dramTiming
;
1425 uint32_t dramTiming2
;
1429 result
= atomctrl_set_engine_dram_timings_rv770(hwmgr
,
1430 engine_clock
, memory_clock
);
1432 PP_ASSERT_WITH_CODE(result
== 0,
1433 "Error calling VBIOS to set DRAM_TIMING.", return result
);
1435 dramTiming
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING
);
1436 dramTiming2
= cgs_read_register(hwmgr
->device
, mmMC_ARB_DRAM_TIMING2
);
1437 burstTime
= PHM_READ_FIELD(hwmgr
->device
, MC_ARB_BURST_TIME
, STATE0
);
1439 arb_regs
->McArbDramTiming
= PP_HOST_TO_SMC_UL(dramTiming
);
1440 arb_regs
->McArbDramTiming2
= PP_HOST_TO_SMC_UL(dramTiming2
);
1441 arb_regs
->McArbBurstTime
= (uint8_t)burstTime
;
1447 * Setup parameters for the MC ARB.
1449 * @param hwmgr the address of the powerplay hardware manager.
1451 * This function is to be called from the SetPowerState table.
1453 static int tonga_program_memory_timing_parameters(struct pp_hwmgr
*hwmgr
)
1455 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1456 struct tonga_smumgr
*smu_data
=
1457 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1459 SMU72_Discrete_MCArbDramTimingTable arb_regs
;
1462 memset(&arb_regs
, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable
));
1464 for (i
= 0; i
< data
->dpm_table
.sclk_table
.count
; i
++) {
1465 for (j
= 0; j
< data
->dpm_table
.mclk_table
.count
; j
++) {
1466 result
= tonga_populate_memory_timing_parameters
1467 (hwmgr
, data
->dpm_table
.sclk_table
.dpm_levels
[i
].value
,
1468 data
->dpm_table
.mclk_table
.dpm_levels
[j
].value
,
1469 &arb_regs
.entries
[i
][j
]);
1477 result
= smu7_copy_bytes_to_smc(
1479 smu_data
->smu7_data
.arb_table_start
,
1480 (uint8_t *)&arb_regs
,
1481 sizeof(SMU72_Discrete_MCArbDramTimingTable
),
1489 static int tonga_populate_smc_boot_level(struct pp_hwmgr
*hwmgr
,
1490 SMU72_Discrete_DpmTable
*table
)
1493 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1494 struct tonga_smumgr
*smu_data
=
1495 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1496 table
->GraphicsBootLevel
= 0;
1497 table
->MemoryBootLevel
= 0;
1499 /* find boot level from dpm table*/
1500 result
= phm_find_boot_level(&(data
->dpm_table
.sclk_table
),
1501 data
->vbios_boot_state
.sclk_bootup_value
,
1502 (uint32_t *)&(smu_data
->smc_state_table
.GraphicsBootLevel
));
1505 smu_data
->smc_state_table
.GraphicsBootLevel
= 0;
1506 printk(KERN_ERR
"[powerplay] VBIOS did not find boot engine "
1507 "clock value in dependency table. "
1508 "Using Graphics DPM level 0 !");
1512 result
= phm_find_boot_level(&(data
->dpm_table
.mclk_table
),
1513 data
->vbios_boot_state
.mclk_bootup_value
,
1514 (uint32_t *)&(smu_data
->smc_state_table
.MemoryBootLevel
));
1517 smu_data
->smc_state_table
.MemoryBootLevel
= 0;
1518 printk(KERN_ERR
"[powerplay] VBIOS did not find boot "
1519 "engine clock value in dependency table."
1520 "Using Memory DPM level 0 !");
1524 table
->BootVoltage
.Vddc
=
1525 phm_get_voltage_id(&(data
->vddc_voltage_table
),
1526 data
->vbios_boot_state
.vddc_bootup_value
);
1527 table
->BootVoltage
.VddGfx
=
1528 phm_get_voltage_id(&(data
->vddgfx_voltage_table
),
1529 data
->vbios_boot_state
.vddgfx_bootup_value
);
1530 table
->BootVoltage
.Vddci
=
1531 phm_get_voltage_id(&(data
->vddci_voltage_table
),
1532 data
->vbios_boot_state
.vddci_bootup_value
);
1533 table
->BootMVdd
= data
->vbios_boot_state
.mvdd_bootup_value
;
1535 CONVERT_FROM_HOST_TO_SMC_US(table
->BootMVdd
);
1540 static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr
*hwmgr
)
1542 uint32_t ro
, efuse
, efuse2
, clock_freq
, volt_without_cks
,
1543 volt_with_cks
, value
;
1544 uint16_t clock_freq_u16
;
1545 struct tonga_smumgr
*smu_data
=
1546 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1547 uint8_t type
, i
, j
, cks_setting
, stretch_amount
, stretch_amount2
,
1549 struct phm_ppt_v1_information
*table_info
=
1550 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1551 struct phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
=
1552 table_info
->vdd_dep_on_sclk
;
1553 uint32_t hw_revision
, dev_id
;
1554 struct cgs_system_info sys_info
= {0};
1556 stretch_amount
= (uint8_t)table_info
->cac_dtp_table
->usClockStretchAmount
;
1558 sys_info
.size
= sizeof(struct cgs_system_info
);
1560 sys_info
.info_id
= CGS_SYSTEM_INFO_PCIE_REV
;
1561 cgs_query_system_info(hwmgr
->device
, &sys_info
);
1562 hw_revision
= (uint32_t)sys_info
.value
;
1564 sys_info
.info_id
= CGS_SYSTEM_INFO_PCIE_DEV
;
1565 cgs_query_system_info(hwmgr
->device
, &sys_info
);
1566 dev_id
= (uint32_t)sys_info
.value
;
1568 /* Read SMU_Eefuse to read and calculate RO and determine
1569 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1571 efuse
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1572 ixSMU_EFUSE_0
+ (146 * 4));
1573 efuse2
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1574 ixSMU_EFUSE_0
+ (148 * 4));
1575 efuse
&= 0xFF000000;
1576 efuse
= efuse
>> 24;
1580 ro
= (2300 - 1350) * efuse
/ 255 + 1350;
1582 ro
= (2500 - 1000) * efuse
/ 255 + 1000;
1589 /* Populate Stretch amount */
1590 smu_data
->smc_state_table
.ClockStretcherAmount
= stretch_amount
;
1593 /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1594 for (i
= 0; i
< sclk_table
->count
; i
++) {
1595 smu_data
->smc_state_table
.Sclk_CKS_masterEn0_7
|=
1596 sclk_table
->entries
[i
].cks_enable
<< i
;
1597 if (ASICID_IS_TONGA_P(dev_id
, hw_revision
)) {
1598 volt_without_cks
= (uint32_t)((7732 + 60 - ro
- 20838 *
1599 (sclk_table
->entries
[i
].clk
/100) / 10000) * 1000 /
1600 (8730 - (5301 * (sclk_table
->entries
[i
].clk
/100) / 1000)));
1601 volt_with_cks
= (uint32_t)((5250 + 51 - ro
- 2404 *
1602 (sclk_table
->entries
[i
].clk
/100) / 100000) * 1000 /
1603 (6146 - (3193 * (sclk_table
->entries
[i
].clk
/100) / 1000)));
1605 volt_without_cks
= (uint32_t)((14041 *
1606 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3571 + 75 - ro
) * 1000 /
1607 (4026 - (13924 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1608 volt_with_cks
= (uint32_t)((13946 *
1609 (sclk_table
->entries
[i
].clk
/100) / 10000 + 3320 + 45 - ro
) * 1000 /
1610 (3664 - (11454 * (sclk_table
->entries
[i
].clk
/100) / 10000)));
1612 if (volt_without_cks
>= volt_with_cks
)
1613 volt_offset
= (uint8_t)(((volt_without_cks
- volt_with_cks
+
1614 sclk_table
->entries
[i
].cks_voffset
) * 100 / 625) + 1);
1615 smu_data
->smc_state_table
.Sclk_voltageOffset
[i
] = volt_offset
;
1618 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1619 STRETCH_ENABLE
, 0x0);
1620 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1622 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1624 PHM_WRITE_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, PWR_CKS_ENABLE
,
1627 /* Populate CKS Lookup Table */
1628 if (stretch_amount
== 1 || stretch_amount
== 2 || stretch_amount
== 5)
1629 stretch_amount2
= 0;
1630 else if (stretch_amount
== 3 || stretch_amount
== 4)
1631 stretch_amount2
= 1;
1633 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
1634 PHM_PlatformCaps_ClockStretcher
);
1635 PP_ASSERT_WITH_CODE(false,
1636 "Stretch Amount in PPTable not supported\n",
1640 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1642 value
&= 0xFFC2FF87;
1643 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].minFreq
=
1644 tonga_clock_stretcher_lookup_table
[stretch_amount2
][0];
1645 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].maxFreq
=
1646 tonga_clock_stretcher_lookup_table
[stretch_amount2
][1];
1647 clock_freq_u16
= (uint16_t)(PP_SMC_TO_HOST_UL(smu_data
->smc_state_table
.
1648 GraphicsLevel
[smu_data
->smc_state_table
.GraphicsDpmLevelCount
- 1].
1649 SclkFrequency
) / 100);
1650 if (tonga_clock_stretcher_lookup_table
[stretch_amount2
][0] <
1652 tonga_clock_stretcher_lookup_table
[stretch_amount2
][1] >
1654 /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
1655 value
|= (tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 16;
1656 /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
1657 value
|= (tonga_clock_stretcher_lookup_table
[stretch_amount2
][2]) << 18;
1658 /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
1659 value
|= (tonga_clock_stretch_amount_conversion
1660 [tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]]
1661 [stretch_amount
]) << 3;
1663 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1664 CKS_LOOKUPTableEntry
[0].minFreq
);
1665 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.CKS_LOOKUPTable
.
1666 CKS_LOOKUPTableEntry
[0].maxFreq
);
1667 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
=
1668 tonga_clock_stretcher_lookup_table
[stretch_amount2
][2] & 0x7F;
1669 smu_data
->smc_state_table
.CKS_LOOKUPTable
.CKS_LOOKUPTableEntry
[0].setting
|=
1670 (tonga_clock_stretcher_lookup_table
[stretch_amount2
][3]) << 7;
1672 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1673 ixPWR_CKS_CNTL
, value
);
1675 /* Populate DDT Lookup Table */
1676 for (i
= 0; i
< 4; i
++) {
1677 /* Assign the minimum and maximum VID stored
1678 * in the last row of Clock Stretcher Voltage Table.
1680 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1681 ClockStretcherDataTableEntry
[i
].minVID
=
1682 (uint8_t) tonga_clock_stretcher_ddt_table
[type
][i
][2];
1683 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1684 ClockStretcherDataTableEntry
[i
].maxVID
=
1685 (uint8_t) tonga_clock_stretcher_ddt_table
[type
][i
][3];
1686 /* Loop through each SCLK and check the frequency
1687 * to see if it lies within the frequency for clock stretcher.
1689 for (j
= 0; j
< smu_data
->smc_state_table
.GraphicsDpmLevelCount
; j
++) {
1691 clock_freq
= PP_SMC_TO_HOST_UL(
1692 smu_data
->smc_state_table
.GraphicsLevel
[j
].SclkFrequency
);
1693 /* Check the allowed frequency against the sclk level[j].
1694 * Sclk's endianness has already been converted,
1695 * and it's in 10Khz unit,
1696 * as opposed to Data table, which is in Mhz unit.
1698 if (clock_freq
>= tonga_clock_stretcher_ddt_table
[type
][i
][0] * 100) {
1700 if (clock_freq
< tonga_clock_stretcher_ddt_table
[type
][i
][1] * 100)
1703 smu_data
->smc_state_table
.ClockStretcherDataTable
.
1704 ClockStretcherDataTableEntry
[i
].setting
|= cks_setting
<< (j
* 2);
1706 CONVERT_FROM_HOST_TO_SMC_US(smu_data
->smc_state_table
.
1707 ClockStretcherDataTable
.
1708 ClockStretcherDataTableEntry
[i
].setting
);
1711 value
= cgs_read_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1713 value
&= 0xFFFFFFFE;
1714 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
1715 ixPWR_CKS_CNTL
, value
);
1721 * Populates the SMC VRConfig field in DPM table.
1723 * @param hwmgr the address of the hardware manager
1724 * @param table the SMC DPM table structure to be populated
1727 static int tonga_populate_vr_config(struct pp_hwmgr
*hwmgr
,
1728 SMU72_Discrete_DpmTable
*table
)
1730 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
1733 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vdd_gfx_control
) {
1735 config
= VR_SVI2_PLANE_1
;
1736 table
->VRConfig
|= (config
<<VRCONF_VDDGFX_SHIFT
);
1738 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
1739 config
= VR_SVI2_PLANE_2
;
1740 table
->VRConfig
|= config
;
1742 printk(KERN_ERR
"[ powerplay ] VDDC and VDDGFX should "
1743 "be both on SVI2 control in splitted mode !\n");
1747 config
= VR_MERGED_WITH_VDDC
;
1748 table
->VRConfig
|= (config
<<VRCONF_VDDGFX_SHIFT
);
1750 /* Set Vddc Voltage Controller */
1751 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->voltage_control
) {
1752 config
= VR_SVI2_PLANE_1
;
1753 table
->VRConfig
|= config
;
1755 printk(KERN_ERR
"[ powerplay ] VDDC should be on "
1756 "SVI2 control in merged mode !\n");
1760 /* Set Vddci Voltage Controller */
1761 if (SMU7_VOLTAGE_CONTROL_BY_SVID2
== data
->vddci_control
) {
1762 config
= VR_SVI2_PLANE_2
; /* only in merged mode */
1763 table
->VRConfig
|= (config
<<VRCONF_VDDCI_SHIFT
);
1764 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->vddci_control
) {
1765 config
= VR_SMIO_PATTERN_1
;
1766 table
->VRConfig
|= (config
<<VRCONF_VDDCI_SHIFT
);
1769 /* Set Mvdd Voltage Controller */
1770 if (SMU7_VOLTAGE_CONTROL_BY_GPIO
== data
->mvdd_control
) {
1771 config
= VR_SMIO_PATTERN_2
;
1772 table
->VRConfig
|= (config
<<VRCONF_MVDD_SHIFT
);
1780 * Initialize the ARB DRAM timing table's index field.
1782 * @param hwmgr the address of the powerplay hardware manager.
1785 static int tonga_init_arb_table_index(struct pp_smumgr
*smumgr
)
1787 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(smumgr
->backend
);
1792 * This is a read-modify-write on the first byte of the ARB table.
1793 * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure
1794 * is the field 'current'.
1795 * This solution is ugly, but we never write the whole table only
1796 * individual fields in it.
1797 * In reality this field should not be in that structure
1798 * but in a soft register.
1800 result
= smu7_read_smc_sram_dword(smumgr
,
1801 smu_data
->smu7_data
.arb_table_start
, &tmp
, SMC_RAM_END
);
1807 tmp
|= ((uint32_t)MC_CG_ARB_FREQ_F1
) << 24;
1809 return smu7_write_smc_sram_dword(smumgr
,
1810 smu_data
->smu7_data
.arb_table_start
, tmp
, SMC_RAM_END
);
1814 static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr
*hwmgr
)
1816 struct tonga_smumgr
*smu_data
=
1817 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1818 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1819 SMU72_Discrete_DpmTable
*dpm_table
= &(smu_data
->smc_state_table
);
1820 struct phm_ppt_v1_information
*table_info
=
1821 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1822 struct phm_cac_tdp_table
*cac_dtp_table
= table_info
->cac_dtp_table
;
1824 const uint16_t *pdef1
, *pdef2
;
1826 dpm_table
->DefaultTdp
= PP_HOST_TO_SMC_US(
1827 (uint16_t)(cac_dtp_table
->usTDP
* 256));
1828 dpm_table
->TargetTdp
= PP_HOST_TO_SMC_US(
1829 (uint16_t)(cac_dtp_table
->usConfigurableTDP
* 256));
1831 PP_ASSERT_WITH_CODE(cac_dtp_table
->usTargetOperatingTemp
<= 255,
1832 "Target Operating Temp is out of Range !",
1835 dpm_table
->GpuTjMax
= (uint8_t)(cac_dtp_table
->usTargetOperatingTemp
);
1836 dpm_table
->GpuTjHyst
= 8;
1838 dpm_table
->DTEAmbientTempBase
= defaults
->dte_ambient_temp_base
;
1840 dpm_table
->BAPM_TEMP_GRADIENT
=
1841 PP_HOST_TO_SMC_UL(defaults
->bamp_temp_gradient
);
1842 pdef1
= defaults
->bapmti_r
;
1843 pdef2
= defaults
->bapmti_rc
;
1845 for (i
= 0; i
< SMU72_DTE_ITERATIONS
; i
++) {
1846 for (j
= 0; j
< SMU72_DTE_SOURCES
; j
++) {
1847 for (k
= 0; k
< SMU72_DTE_SINKS
; k
++) {
1848 dpm_table
->BAPMTI_R
[i
][j
][k
] =
1849 PP_HOST_TO_SMC_US(*pdef1
);
1850 dpm_table
->BAPMTI_RC
[i
][j
][k
] =
1851 PP_HOST_TO_SMC_US(*pdef2
);
1861 static int tonga_populate_svi_load_line(struct pp_hwmgr
*hwmgr
)
1863 struct tonga_smumgr
*smu_data
=
1864 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1865 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1867 smu_data
->power_tune_table
.SviLoadLineEn
= defaults
->svi_load_line_en
;
1868 smu_data
->power_tune_table
.SviLoadLineVddC
= defaults
->svi_load_line_vddC
;
1869 smu_data
->power_tune_table
.SviLoadLineTrimVddC
= 3;
1870 smu_data
->power_tune_table
.SviLoadLineOffsetVddC
= 0;
1875 static int tonga_populate_tdc_limit(struct pp_hwmgr
*hwmgr
)
1878 struct tonga_smumgr
*smu_data
=
1879 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1880 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1881 struct phm_ppt_v1_information
*table_info
=
1882 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1884 /* TDC number of fraction bits are changed from 8 to 7
1885 * for Fiji as requested by SMC team
1887 tdc_limit
= (uint16_t)(table_info
->cac_dtp_table
->usTDC
* 256);
1888 smu_data
->power_tune_table
.TDC_VDDC_PkgLimit
=
1889 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit
);
1890 smu_data
->power_tune_table
.TDC_VDDC_ThrottleReleaseLimitPerc
=
1891 defaults
->tdc_vddc_throttle_release_limit_perc
;
1892 smu_data
->power_tune_table
.TDC_MAWt
= defaults
->tdc_mawt
;
1897 static int tonga_populate_dw8(struct pp_hwmgr
*hwmgr
, uint32_t fuse_table_offset
)
1899 struct tonga_smumgr
*smu_data
=
1900 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1901 const struct tonga_pt_defaults
*defaults
= smu_data
->power_tune_defaults
;
1904 if (smu7_read_smc_sram_dword(hwmgr
->smumgr
,
1906 offsetof(SMU72_Discrete_PmFuses
, TdcWaterfallCtl
),
1907 (uint32_t *)&temp
, SMC_RAM_END
))
1908 PP_ASSERT_WITH_CODE(false,
1909 "Attempt to read PmFuses.DW6 "
1910 "(SviLoadLineEn) from SMC Failed !",
1913 smu_data
->power_tune_table
.TdcWaterfallCtl
= defaults
->tdc_waterfall_ctl
;
1918 static int tonga_populate_temperature_scaler(struct pp_hwmgr
*hwmgr
)
1921 struct tonga_smumgr
*smu_data
=
1922 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1924 /* Currently not used. Set all to zero. */
1925 for (i
= 0; i
< 16; i
++)
1926 smu_data
->power_tune_table
.LPMLTemperatureScaler
[i
] = 0;
1931 static int tonga_populate_fuzzy_fan(struct pp_hwmgr
*hwmgr
)
1933 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1935 if ((hwmgr
->thermal_controller
.advanceFanControlParameters
.
1936 usFanOutputSensitivity
& (1 << 15)) ||
1937 (hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
== 0))
1938 hwmgr
->thermal_controller
.advanceFanControlParameters
.
1939 usFanOutputSensitivity
= hwmgr
->thermal_controller
.
1940 advanceFanControlParameters
.usDefaultFanOutputSensitivity
;
1942 smu_data
->power_tune_table
.FuzzyFan_PwmSetDelta
=
1943 PP_HOST_TO_SMC_US(hwmgr
->thermal_controller
.
1944 advanceFanControlParameters
.usFanOutputSensitivity
);
1948 static int tonga_populate_gnb_lpml(struct pp_hwmgr
*hwmgr
)
1951 struct tonga_smumgr
*smu_data
=
1952 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1954 /* Currently not used. Set all to zero. */
1955 for (i
= 0; i
< 16; i
++)
1956 smu_data
->power_tune_table
.GnbLPML
[i
] = 0;
1961 static int tonga_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr
*hwmgr
)
1966 static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr
*hwmgr
)
1968 struct tonga_smumgr
*smu_data
=
1969 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1970 struct phm_ppt_v1_information
*table_info
=
1971 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1972 uint16_t hi_sidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
;
1973 uint16_t lo_sidd
= smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
;
1974 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
1976 hi_sidd
= (uint16_t)(cac_table
->usHighCACLeakage
/ 100 * 256);
1977 lo_sidd
= (uint16_t)(cac_table
->usLowCACLeakage
/ 100 * 256);
1979 smu_data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
=
1980 CONVERT_FROM_HOST_TO_SMC_US(hi_sidd
);
1981 smu_data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
=
1982 CONVERT_FROM_HOST_TO_SMC_US(lo_sidd
);
1987 static int tonga_populate_pm_fuses(struct pp_hwmgr
*hwmgr
)
1989 struct tonga_smumgr
*smu_data
=
1990 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
1991 uint32_t pm_fuse_table_offset
;
1993 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
1994 PHM_PlatformCaps_PowerContainment
)) {
1995 if (smu7_read_smc_sram_dword(hwmgr
->smumgr
,
1996 SMU72_FIRMWARE_HEADER_LOCATION
+
1997 offsetof(SMU72_Firmware_Header
, PmFuseTable
),
1998 &pm_fuse_table_offset
, SMC_RAM_END
))
1999 PP_ASSERT_WITH_CODE(false,
2000 "Attempt to get pm_fuse_table_offset Failed !",
2004 if (tonga_populate_svi_load_line(hwmgr
))
2005 PP_ASSERT_WITH_CODE(false,
2006 "Attempt to populate SviLoadLine Failed !",
2009 if (tonga_populate_tdc_limit(hwmgr
))
2010 PP_ASSERT_WITH_CODE(false,
2011 "Attempt to populate TDCLimit Failed !",
2014 if (tonga_populate_dw8(hwmgr
, pm_fuse_table_offset
))
2015 PP_ASSERT_WITH_CODE(false,
2016 "Attempt to populate TdcWaterfallCtl Failed !",
2020 if (tonga_populate_temperature_scaler(hwmgr
) != 0)
2021 PP_ASSERT_WITH_CODE(false,
2022 "Attempt to populate LPMLTemperatureScaler Failed !",
2026 if (tonga_populate_fuzzy_fan(hwmgr
))
2027 PP_ASSERT_WITH_CODE(false,
2028 "Attempt to populate Fuzzy Fan "
2029 "Control parameters Failed !",
2033 if (tonga_populate_gnb_lpml(hwmgr
))
2034 PP_ASSERT_WITH_CODE(false,
2035 "Attempt to populate GnbLPML Failed !",
2039 if (tonga_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr
))
2040 PP_ASSERT_WITH_CODE(false,
2041 "Attempt to populate GnbLPML "
2042 "Min and Max Vid Failed !",
2046 if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr
))
2047 PP_ASSERT_WITH_CODE(
2049 "Attempt to populate BapmVddCBaseLeakage "
2050 "Hi and Lo Sidd Failed !",
2053 if (smu7_copy_bytes_to_smc(hwmgr
->smumgr
, pm_fuse_table_offset
,
2054 (uint8_t *)&smu_data
->power_tune_table
,
2055 sizeof(struct SMU72_Discrete_PmFuses
), SMC_RAM_END
))
2056 PP_ASSERT_WITH_CODE(false,
2057 "Attempt to download PmFuseTable Failed !",
2063 static int tonga_populate_mc_reg_address(struct pp_smumgr
*smumgr
,
2064 SMU72_Discrete_MCRegisters
*mc_reg_table
)
2066 const struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)smumgr
->backend
;
2070 for (i
= 0, j
= 0; j
< smu_data
->mc_reg_table
.last
; j
++) {
2071 if (smu_data
->mc_reg_table
.validflag
& 1<<j
) {
2072 PP_ASSERT_WITH_CODE(
2073 i
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
,
2074 "Index of mc_reg_table->address[] array "
2077 mc_reg_table
->address
[i
].s0
=
2078 PP_HOST_TO_SMC_US(smu_data
->mc_reg_table
.mc_reg_address
[j
].s0
);
2079 mc_reg_table
->address
[i
].s1
=
2080 PP_HOST_TO_SMC_US(smu_data
->mc_reg_table
.mc_reg_address
[j
].s1
);
2085 mc_reg_table
->last
= (uint8_t)i
;
2090 /*convert register values from driver to SMC format */
2091 static void tonga_convert_mc_registers(
2092 const struct tonga_mc_reg_entry
*entry
,
2093 SMU72_Discrete_MCRegisterSet
*data
,
2094 uint32_t num_entries
, uint32_t valid_flag
)
2098 for (i
= 0, j
= 0; j
< num_entries
; j
++) {
2099 if (valid_flag
& 1<<j
) {
2100 data
->value
[i
] = PP_HOST_TO_SMC_UL(entry
->mc_data
[j
]);
2106 static int tonga_convert_mc_reg_table_entry_to_smc(
2107 struct pp_smumgr
*smumgr
,
2108 const uint32_t memory_clock
,
2109 SMU72_Discrete_MCRegisterSet
*mc_reg_table_data
2112 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(smumgr
->backend
);
2115 for (i
= 0; i
< smu_data
->mc_reg_table
.num_entries
; i
++) {
2117 smu_data
->mc_reg_table
.mc_reg_table_entry
[i
].mclk_max
) {
2122 if ((i
== smu_data
->mc_reg_table
.num_entries
) && (i
> 0))
2125 tonga_convert_mc_registers(&smu_data
->mc_reg_table
.mc_reg_table_entry
[i
],
2126 mc_reg_table_data
, smu_data
->mc_reg_table
.last
,
2127 smu_data
->mc_reg_table
.validflag
);
2132 static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr
*hwmgr
,
2133 SMU72_Discrete_MCRegisters
*mc_regs
)
2136 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2140 for (i
= 0; i
< data
->dpm_table
.mclk_table
.count
; i
++) {
2141 res
= tonga_convert_mc_reg_table_entry_to_smc(
2143 data
->dpm_table
.mclk_table
.dpm_levels
[i
].value
,
2154 static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr
*hwmgr
)
2156 struct pp_smumgr
*smumgr
= hwmgr
->smumgr
;
2157 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(smumgr
->backend
);
2158 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2162 if (0 == (data
->need_update_smu7_dpm_table
& DPMTABLE_OD_UPDATE_MCLK
))
2166 memset(&smu_data
->mc_regs
, 0, sizeof(SMU72_Discrete_MCRegisters
));
2168 result
= tonga_convert_mc_reg_table_to_smc(hwmgr
, &(smu_data
->mc_regs
));
2174 address
= smu_data
->smu7_data
.mc_reg_table_start
+
2175 (uint32_t)offsetof(SMU72_Discrete_MCRegisters
, data
[0]);
2177 return smu7_copy_bytes_to_smc(
2178 hwmgr
->smumgr
, address
,
2179 (uint8_t *)&smu_data
->mc_regs
.data
[0],
2180 sizeof(SMU72_Discrete_MCRegisterSet
) *
2181 data
->dpm_table
.mclk_table
.count
,
2185 static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr
*hwmgr
)
2188 struct pp_smumgr
*smumgr
= hwmgr
->smumgr
;
2189 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(smumgr
->backend
);
2191 memset(&smu_data
->mc_regs
, 0x00, sizeof(SMU72_Discrete_MCRegisters
));
2192 result
= tonga_populate_mc_reg_address(smumgr
, &(smu_data
->mc_regs
));
2193 PP_ASSERT_WITH_CODE(!result
,
2194 "Failed to initialize MCRegTable for the MC register addresses !",
2197 result
= tonga_convert_mc_reg_table_to_smc(hwmgr
, &smu_data
->mc_regs
);
2198 PP_ASSERT_WITH_CODE(!result
,
2199 "Failed to initialize MCRegTable for driver state !",
2202 return smu7_copy_bytes_to_smc(smumgr
, smu_data
->smu7_data
.mc_reg_table_start
,
2203 (uint8_t *)&smu_data
->mc_regs
, sizeof(SMU72_Discrete_MCRegisters
), SMC_RAM_END
);
2206 static void tonga_initialize_power_tune_defaults(struct pp_hwmgr
*hwmgr
)
2208 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
2209 struct phm_ppt_v1_information
*table_info
=
2210 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2213 table_info
->cac_dtp_table
->usPowerTuneDataSetID
<= POWERTUNE_DEFAULT_SET_MAX
&&
2214 table_info
->cac_dtp_table
->usPowerTuneDataSetID
)
2215 smu_data
->power_tune_defaults
=
2216 &tonga_power_tune_data_set_array
2217 [table_info
->cac_dtp_table
->usPowerTuneDataSetID
- 1];
2219 smu_data
->power_tune_defaults
= &tonga_power_tune_data_set_array
[0];
2223 * Initializes the SMC table and uploads it
2225 * @param hwmgr the address of the powerplay hardware manager.
2226 * @param pInput the pointer to input data (PowerState)
2229 int tonga_init_smc_table(struct pp_hwmgr
*hwmgr
)
2232 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2233 struct tonga_smumgr
*smu_data
=
2234 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
2235 SMU72_Discrete_DpmTable
*table
= &(smu_data
->smc_state_table
);
2236 struct phm_ppt_v1_information
*table_info
=
2237 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2240 pp_atomctrl_gpio_pin_assignment gpio_pin_assignment
;
2243 memset(&(smu_data
->smc_state_table
), 0x00, sizeof(smu_data
->smc_state_table
));
2245 tonga_initialize_power_tune_defaults(hwmgr
);
2247 if (SMU7_VOLTAGE_CONTROL_NONE
!= data
->voltage_control
)
2248 tonga_populate_smc_voltage_tables(hwmgr
, table
);
2250 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2251 PHM_PlatformCaps_AutomaticDCTransition
))
2252 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GPIO_DC
;
2255 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2256 PHM_PlatformCaps_StepVddc
))
2257 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_STEPVDDC
;
2259 if (data
->is_memory_gddr5
)
2260 table
->SystemFlags
|= PPSMC_SYSTEMFLAG_GDDR5
;
2262 i
= PHM_READ_FIELD(hwmgr
->device
, CC_MC_MAX_CHANNEL
, NOOFCHAN
);
2264 if (i
== 1 || i
== 0)
2265 table
->SystemFlags
|= 0x40;
2267 if (data
->ulv_supported
&& table_info
->us_ulv_voltage_offset
) {
2268 result
= tonga_populate_ulv_state(hwmgr
, table
);
2269 PP_ASSERT_WITH_CODE(!result
,
2270 "Failed to initialize ULV state !",
2273 cgs_write_ind_register(hwmgr
->device
, CGS_IND_REG__SMC
,
2274 ixCG_ULV_PARAMETER
, 0x40035);
2277 result
= tonga_populate_smc_link_level(hwmgr
, table
);
2278 PP_ASSERT_WITH_CODE(!result
,
2279 "Failed to initialize Link Level !", return result
);
2281 result
= tonga_populate_all_graphic_levels(hwmgr
);
2282 PP_ASSERT_WITH_CODE(!result
,
2283 "Failed to initialize Graphics Level !", return result
);
2285 result
= tonga_populate_all_memory_levels(hwmgr
);
2286 PP_ASSERT_WITH_CODE(!result
,
2287 "Failed to initialize Memory Level !", return result
);
2289 result
= tonga_populate_smc_acpi_level(hwmgr
, table
);
2290 PP_ASSERT_WITH_CODE(!result
,
2291 "Failed to initialize ACPI Level !", return result
);
2293 result
= tonga_populate_smc_vce_level(hwmgr
, table
);
2294 PP_ASSERT_WITH_CODE(!result
,
2295 "Failed to initialize VCE Level !", return result
);
2297 result
= tonga_populate_smc_acp_level(hwmgr
, table
);
2298 PP_ASSERT_WITH_CODE(!result
,
2299 "Failed to initialize ACP Level !", return result
);
2301 result
= tonga_populate_smc_samu_level(hwmgr
, table
);
2302 PP_ASSERT_WITH_CODE(!result
,
2303 "Failed to initialize SAMU Level !", return result
);
2305 /* Since only the initial state is completely set up at this
2306 * point (the other states are just copies of the boot state) we only
2307 * need to populate the ARB settings for the initial state.
2309 result
= tonga_program_memory_timing_parameters(hwmgr
);
2310 PP_ASSERT_WITH_CODE(!result
,
2311 "Failed to Write ARB settings for the initial state.",
2314 result
= tonga_populate_smc_uvd_level(hwmgr
, table
);
2315 PP_ASSERT_WITH_CODE(!result
,
2316 "Failed to initialize UVD Level !", return result
);
2318 result
= tonga_populate_smc_boot_level(hwmgr
, table
);
2319 PP_ASSERT_WITH_CODE(!result
,
2320 "Failed to initialize Boot Level !", return result
);
2322 tonga_populate_bapm_parameters_in_dpm_table(hwmgr
);
2323 PP_ASSERT_WITH_CODE(!result
,
2324 "Failed to populate BAPM Parameters !", return result
);
2326 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2327 PHM_PlatformCaps_ClockStretcher
)) {
2328 result
= tonga_populate_clock_stretcher_data_table(hwmgr
);
2329 PP_ASSERT_WITH_CODE(!result
,
2330 "Failed to populate Clock Stretcher Data Table !",
2333 table
->GraphicsVoltageChangeEnable
= 1;
2334 table
->GraphicsThermThrottleEnable
= 1;
2335 table
->GraphicsInterval
= 1;
2336 table
->VoltageInterval
= 1;
2337 table
->ThermalInterval
= 1;
2338 table
->TemperatureLimitHigh
=
2339 table_info
->cac_dtp_table
->usTargetOperatingTemp
*
2340 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2341 table
->TemperatureLimitLow
=
2342 (table_info
->cac_dtp_table
->usTargetOperatingTemp
- 1) *
2343 SMU7_Q88_FORMAT_CONVERSION_UNIT
;
2344 table
->MemoryVoltageChangeEnable
= 1;
2345 table
->MemoryInterval
= 1;
2346 table
->VoltageResponseTime
= 0;
2347 table
->PhaseResponseTime
= 0;
2348 table
->MemoryThermThrottleEnable
= 1;
2351 * Cail reads current link status and reports it as cap (we cannot
2352 * change this due to some previous issues we had)
2353 * SMC drops the link status to lowest level after enabling
2354 * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again
2355 * but this time Cail reads current link status which was set to low by
2356 * SMC and reports it as cap to powerplay
2357 * To avoid it, we set PCIeBootLinkLevel to highest dpm level
2359 PP_ASSERT_WITH_CODE((1 <= data
->dpm_table
.pcie_speed_table
.count
),
2360 "There must be 1 or more PCIE levels defined in PPTable.",
2363 table
->PCIeBootLinkLevel
= (uint8_t) (data
->dpm_table
.pcie_speed_table
.count
);
2365 table
->PCIeGenInterval
= 1;
2367 result
= tonga_populate_vr_config(hwmgr
, table
);
2368 PP_ASSERT_WITH_CODE(!result
,
2369 "Failed to populate VRConfig setting !", return result
);
2371 table
->ThermGpio
= 17;
2372 table
->SclkStepSize
= 0x4000;
2374 if (atomctrl_get_pp_assign_pin(hwmgr
, VDDC_VRHOT_GPIO_PINID
,
2375 &gpio_pin_assignment
)) {
2376 table
->VRHotGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2377 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2378 PHM_PlatformCaps_RegulatorHot
);
2380 table
->VRHotGpio
= SMU7_UNUSED_GPIO_PIN
;
2381 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2382 PHM_PlatformCaps_RegulatorHot
);
2385 if (atomctrl_get_pp_assign_pin(hwmgr
, PP_AC_DC_SWITCH_GPIO_PINID
,
2386 &gpio_pin_assignment
)) {
2387 table
->AcDcGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2388 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2389 PHM_PlatformCaps_AutomaticDCTransition
);
2391 table
->AcDcGpio
= SMU7_UNUSED_GPIO_PIN
;
2392 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2393 PHM_PlatformCaps_AutomaticDCTransition
);
2396 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2397 PHM_PlatformCaps_Falcon_QuickTransition
);
2400 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2401 PHM_PlatformCaps_AutomaticDCTransition
);
2402 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2403 PHM_PlatformCaps_Falcon_QuickTransition
);
2406 if (atomctrl_get_pp_assign_pin(hwmgr
,
2407 THERMAL_INT_OUTPUT_GPIO_PINID
, &gpio_pin_assignment
)) {
2408 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
2409 PHM_PlatformCaps_ThermalOutGPIO
);
2411 table
->ThermOutGpio
= gpio_pin_assignment
.uc_gpio_pin_bit_shift
;
2413 table
->ThermOutPolarity
=
2414 (0 == (cgs_read_register(hwmgr
->device
, mmGPIOPAD_A
) &
2415 (1 << gpio_pin_assignment
.uc_gpio_pin_bit_shift
))) ? 1 : 0;
2417 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_ONLY
;
2419 /* if required, combine VRHot/PCC with thermal out GPIO*/
2420 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2421 PHM_PlatformCaps_RegulatorHot
) &&
2422 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2423 PHM_PlatformCaps_CombinePCCWithThermalSignal
)){
2424 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_THERM_VRHOT
;
2427 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2428 PHM_PlatformCaps_ThermalOutGPIO
);
2430 table
->ThermOutGpio
= 17;
2431 table
->ThermOutPolarity
= 1;
2432 table
->ThermOutMode
= SMU7_THERM_OUT_MODE_DISABLE
;
2435 for (i
= 0; i
< SMU72_MAX_ENTRIES_SMIO
; i
++)
2436 table
->Smio
[i
] = PP_HOST_TO_SMC_UL(table
->Smio
[i
]);
2438 CONVERT_FROM_HOST_TO_SMC_UL(table
->SystemFlags
);
2439 CONVERT_FROM_HOST_TO_SMC_UL(table
->VRConfig
);
2440 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask1
);
2441 CONVERT_FROM_HOST_TO_SMC_UL(table
->SmioMask2
);
2442 CONVERT_FROM_HOST_TO_SMC_UL(table
->SclkStepSize
);
2443 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitHigh
);
2444 CONVERT_FROM_HOST_TO_SMC_US(table
->TemperatureLimitLow
);
2445 CONVERT_FROM_HOST_TO_SMC_US(table
->VoltageResponseTime
);
2446 CONVERT_FROM_HOST_TO_SMC_US(table
->PhaseResponseTime
);
2448 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
2449 result
= smu7_copy_bytes_to_smc(
2451 smu_data
->smu7_data
.dpm_table_start
+ offsetof(SMU72_Discrete_DpmTable
, SystemFlags
),
2452 (uint8_t *)&(table
->SystemFlags
),
2453 sizeof(SMU72_Discrete_DpmTable
) - 3 * sizeof(SMU72_PIDController
),
2456 PP_ASSERT_WITH_CODE(!result
,
2457 "Failed to upload dpm data to SMC memory !", return result
;);
2459 result
= tonga_init_arb_table_index(hwmgr
->smumgr
);
2460 PP_ASSERT_WITH_CODE(!result
,
2461 "Failed to upload arb data to SMC memory !", return result
);
2463 tonga_populate_pm_fuses(hwmgr
);
2464 PP_ASSERT_WITH_CODE((!result
),
2465 "Failed to populate initialize pm fuses !", return result
);
2467 result
= tonga_populate_initial_mc_reg_table(hwmgr
);
2468 PP_ASSERT_WITH_CODE((!result
),
2469 "Failed to populate initialize MC Reg table !", return result
);
2475 * Set up the fan table to control the fan using the SMC.
2476 * @param hwmgr the address of the powerplay hardware manager.
2477 * @param pInput the pointer to input data
2478 * @param pOutput the pointer to output data
2479 * @param pStorage the pointer to temporary storage
2480 * @param Result the last failure code
2481 * @return result from set temperature range routine
2483 int tonga_thermal_setup_fan_table(struct pp_hwmgr
*hwmgr
)
2485 struct tonga_smumgr
*smu_data
=
2486 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
2487 SMU72_Discrete_FanTable fan_table
= { FDO_MODE_HARDWARE
};
2489 uint32_t t_diff1
, t_diff2
, pwm_diff1
, pwm_diff2
;
2490 uint16_t fdo_min
, slope1
, slope2
;
2491 uint32_t reference_clock
;
2495 if (!phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2496 PHM_PlatformCaps_MicrocodeFanControl
))
2499 if (hwmgr
->thermal_controller
.fanInfo
.bNoFan
) {
2500 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2501 PHM_PlatformCaps_MicrocodeFanControl
);
2505 if (0 == smu_data
->smu7_data
.fan_table_start
) {
2506 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2507 PHM_PlatformCaps_MicrocodeFanControl
);
2511 duty100
= PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
,
2513 CG_FDO_CTRL1
, FMAX_DUTY100
);
2516 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
2517 PHM_PlatformCaps_MicrocodeFanControl
);
2521 tmp64
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
* duty100
;
2522 do_div(tmp64
, 10000);
2523 fdo_min
= (uint16_t)tmp64
;
2525 t_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
-
2526 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
;
2527 t_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
-
2528 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
;
2530 pwm_diff1
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
-
2531 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
;
2532 pwm_diff2
= hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
-
2533 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
;
2535 slope1
= (uint16_t)((50 + ((16 * duty100
* pwm_diff1
) / t_diff1
)) / 100);
2536 slope2
= (uint16_t)((50 + ((16 * duty100
* pwm_diff2
) / t_diff2
)) / 100);
2538 fan_table
.TempMin
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
) / 100);
2539 fan_table
.TempMed
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
) / 100);
2540 fan_table
.TempMax
= cpu_to_be16((50 + hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
) / 100);
2542 fan_table
.Slope1
= cpu_to_be16(slope1
);
2543 fan_table
.Slope2
= cpu_to_be16(slope2
);
2545 fan_table
.FdoMin
= cpu_to_be16(fdo_min
);
2547 fan_table
.HystDown
= cpu_to_be16(hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
);
2549 fan_table
.HystUp
= cpu_to_be16(1);
2551 fan_table
.HystSlope
= cpu_to_be16(1);
2553 fan_table
.TempRespLim
= cpu_to_be16(5);
2555 reference_clock
= smu7_get_xclk(hwmgr
);
2557 fan_table
.RefreshPeriod
= cpu_to_be32((hwmgr
->thermal_controller
.advanceFanControlParameters
.ulCycleDelay
* reference_clock
) / 1600);
2559 fan_table
.FdoMax
= cpu_to_be16((uint16_t)duty100
);
2561 fan_table
.TempSrc
= (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr
->device
, CGS_IND_REG__SMC
, CG_MULT_THERMAL_CTRL
, TEMP_SEL
);
2563 fan_table
.FanControl_GL_Flag
= 1;
2565 res
= smu7_copy_bytes_to_smc(hwmgr
->smumgr
,
2566 smu_data
->smu7_data
.fan_table_start
,
2567 (uint8_t *)&fan_table
,
2568 (uint32_t)sizeof(fan_table
),
2575 static int tonga_program_mem_timing_parameters(struct pp_hwmgr
*hwmgr
)
2577 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2579 if (data
->need_update_smu7_dpm_table
&
2580 (DPMTABLE_OD_UPDATE_SCLK
+ DPMTABLE_OD_UPDATE_MCLK
))
2581 return tonga_program_memory_timing_parameters(hwmgr
);
2586 int tonga_update_sclk_threshold(struct pp_hwmgr
*hwmgr
)
2588 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2589 struct tonga_smumgr
*smu_data
=
2590 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
2593 uint32_t low_sclk_interrupt_threshold
= 0;
2595 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2596 PHM_PlatformCaps_SclkThrottleLowNotification
)
2597 && (hwmgr
->gfx_arbiter
.sclk_threshold
!=
2598 data
->low_sclk_interrupt_threshold
)) {
2599 data
->low_sclk_interrupt_threshold
=
2600 hwmgr
->gfx_arbiter
.sclk_threshold
;
2601 low_sclk_interrupt_threshold
=
2602 data
->low_sclk_interrupt_threshold
;
2604 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold
);
2606 result
= smu7_copy_bytes_to_smc(
2608 smu_data
->smu7_data
.dpm_table_start
+
2609 offsetof(SMU72_Discrete_DpmTable
,
2610 LowSclkInterruptThreshold
),
2611 (uint8_t *)&low_sclk_interrupt_threshold
,
2616 result
= tonga_update_and_upload_mc_reg_table(hwmgr
);
2618 PP_ASSERT_WITH_CODE((!result
),
2619 "Failed to upload MC reg table !",
2622 result
= tonga_program_mem_timing_parameters(hwmgr
);
2623 PP_ASSERT_WITH_CODE((result
== 0),
2624 "Failed to program memory timing parameters !",
2630 uint32_t tonga_get_offsetof(uint32_t type
, uint32_t member
)
2633 case SMU_SoftRegisters
:
2635 case HandshakeDisables
:
2636 return offsetof(SMU72_SoftRegisters
, HandshakeDisables
);
2637 case VoltageChangeTimeout
:
2638 return offsetof(SMU72_SoftRegisters
, VoltageChangeTimeout
);
2639 case AverageGraphicsActivity
:
2640 return offsetof(SMU72_SoftRegisters
, AverageGraphicsActivity
);
2642 return offsetof(SMU72_SoftRegisters
, PreVBlankGap
);
2644 return offsetof(SMU72_SoftRegisters
, VBlankTimeout
);
2645 case UcodeLoadStatus
:
2646 return offsetof(SMU72_SoftRegisters
, UcodeLoadStatus
);
2648 case SMU_Discrete_DpmTable
:
2651 return offsetof(SMU72_Discrete_DpmTable
, UvdBootLevel
);
2653 return offsetof(SMU72_Discrete_DpmTable
, VceBootLevel
);
2655 return offsetof(SMU72_Discrete_DpmTable
, SamuBootLevel
);
2656 case LowSclkInterruptThreshold
:
2657 return offsetof(SMU72_Discrete_DpmTable
, LowSclkInterruptThreshold
);
2660 printk(KERN_WARNING
"can't get the offset of type %x member %x\n", type
, member
);
2664 uint32_t tonga_get_mac_definition(uint32_t value
)
2667 case SMU_MAX_LEVELS_GRAPHICS
:
2668 return SMU72_MAX_LEVELS_GRAPHICS
;
2669 case SMU_MAX_LEVELS_MEMORY
:
2670 return SMU72_MAX_LEVELS_MEMORY
;
2671 case SMU_MAX_LEVELS_LINK
:
2672 return SMU72_MAX_LEVELS_LINK
;
2673 case SMU_MAX_ENTRIES_SMIO
:
2674 return SMU72_MAX_ENTRIES_SMIO
;
2675 case SMU_MAX_LEVELS_VDDC
:
2676 return SMU72_MAX_LEVELS_VDDC
;
2677 case SMU_MAX_LEVELS_VDDGFX
:
2678 return SMU72_MAX_LEVELS_VDDGFX
;
2679 case SMU_MAX_LEVELS_VDDCI
:
2680 return SMU72_MAX_LEVELS_VDDCI
;
2681 case SMU_MAX_LEVELS_MVDD
:
2682 return SMU72_MAX_LEVELS_MVDD
;
2684 printk(KERN_WARNING
"can't get the mac value %x\n", value
);
2690 static int tonga_update_uvd_smc_table(struct pp_hwmgr
*hwmgr
)
2692 struct tonga_smumgr
*smu_data
=
2693 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
2694 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2695 struct phm_ppt_v1_information
*table_info
=
2696 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2698 smu_data
->smc_state_table
.UvdBootLevel
= 0;
2699 if (table_info
->mm_dep_table
->count
> 0)
2700 smu_data
->smc_state_table
.UvdBootLevel
=
2701 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2702 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2703 offsetof(SMU72_Discrete_DpmTable
, UvdBootLevel
);
2704 mm_boot_level_offset
/= 4;
2705 mm_boot_level_offset
*= 4;
2706 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2707 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2708 mm_boot_level_value
&= 0x00FFFFFF;
2709 mm_boot_level_value
|= smu_data
->smc_state_table
.UvdBootLevel
<< 24;
2710 cgs_write_ind_register(hwmgr
->device
,
2712 mm_boot_level_offset
, mm_boot_level_value
);
2714 if (!phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2715 PHM_PlatformCaps_UVDDPM
) ||
2716 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2717 PHM_PlatformCaps_StablePState
))
2718 smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
2719 PPSMC_MSG_UVDDPM_SetEnabledMask
,
2720 (uint32_t)(1 << smu_data
->smc_state_table
.UvdBootLevel
));
2724 static int tonga_update_vce_smc_table(struct pp_hwmgr
*hwmgr
)
2726 struct tonga_smumgr
*smu_data
=
2727 (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
2728 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2729 struct phm_ppt_v1_information
*table_info
=
2730 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
2733 smu_data
->smc_state_table
.VceBootLevel
=
2734 (uint8_t) (table_info
->mm_dep_table
->count
- 1);
2736 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2737 offsetof(SMU72_Discrete_DpmTable
, VceBootLevel
);
2738 mm_boot_level_offset
/= 4;
2739 mm_boot_level_offset
*= 4;
2740 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2741 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2742 mm_boot_level_value
&= 0xFF00FFFF;
2743 mm_boot_level_value
|= smu_data
->smc_state_table
.VceBootLevel
<< 16;
2744 cgs_write_ind_register(hwmgr
->device
,
2745 CGS_IND_REG__SMC
, mm_boot_level_offset
, mm_boot_level_value
);
2747 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2748 PHM_PlatformCaps_StablePState
))
2749 smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
2750 PPSMC_MSG_VCEDPM_SetEnabledMask
,
2751 (uint32_t)1 << smu_data
->smc_state_table
.VceBootLevel
);
2755 static int tonga_update_samu_smc_table(struct pp_hwmgr
*hwmgr
)
2757 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
2758 uint32_t mm_boot_level_offset
, mm_boot_level_value
;
2760 smu_data
->smc_state_table
.SamuBootLevel
= 0;
2761 mm_boot_level_offset
= smu_data
->smu7_data
.dpm_table_start
+
2762 offsetof(SMU72_Discrete_DpmTable
, SamuBootLevel
);
2764 mm_boot_level_offset
/= 4;
2765 mm_boot_level_offset
*= 4;
2766 mm_boot_level_value
= cgs_read_ind_register(hwmgr
->device
,
2767 CGS_IND_REG__SMC
, mm_boot_level_offset
);
2768 mm_boot_level_value
&= 0xFFFFFF00;
2769 mm_boot_level_value
|= smu_data
->smc_state_table
.SamuBootLevel
<< 0;
2770 cgs_write_ind_register(hwmgr
->device
,
2771 CGS_IND_REG__SMC
, mm_boot_level_offset
, mm_boot_level_value
);
2773 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
2774 PHM_PlatformCaps_StablePState
))
2775 smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
2776 PPSMC_MSG_SAMUDPM_SetEnabledMask
,
2777 (uint32_t)(1 << smu_data
->smc_state_table
.SamuBootLevel
));
2781 int tonga_update_smc_table(struct pp_hwmgr
*hwmgr
, uint32_t type
)
2785 tonga_update_uvd_smc_table(hwmgr
);
2788 tonga_update_vce_smc_table(hwmgr
);
2790 case SMU_SAMU_TABLE
:
2791 tonga_update_samu_smc_table(hwmgr
);
2801 * Get the location of various tables inside the FW image.
2803 * @param hwmgr the address of the powerplay hardware manager.
2806 int tonga_process_firmware_header(struct pp_hwmgr
*hwmgr
)
2808 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
2809 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
2815 result
= smu7_read_smc_sram_dword(hwmgr
->smumgr
,
2816 SMU72_FIRMWARE_HEADER_LOCATION
+
2817 offsetof(SMU72_Firmware_Header
, DpmTable
),
2821 smu_data
->smu7_data
.dpm_table_start
= tmp
;
2823 error
|= (result
!= 0);
2825 result
= smu7_read_smc_sram_dword(hwmgr
->smumgr
,
2826 SMU72_FIRMWARE_HEADER_LOCATION
+
2827 offsetof(SMU72_Firmware_Header
, SoftRegisters
),
2831 data
->soft_regs_start
= tmp
;
2832 smu_data
->smu7_data
.soft_regs_start
= tmp
;
2835 error
|= (result
!= 0);
2838 result
= smu7_read_smc_sram_dword(hwmgr
->smumgr
,
2839 SMU72_FIRMWARE_HEADER_LOCATION
+
2840 offsetof(SMU72_Firmware_Header
, mcRegisterTable
),
2844 smu_data
->smu7_data
.mc_reg_table_start
= tmp
;
2846 result
= smu7_read_smc_sram_dword(hwmgr
->smumgr
,
2847 SMU72_FIRMWARE_HEADER_LOCATION
+
2848 offsetof(SMU72_Firmware_Header
, FanTable
),
2852 smu_data
->smu7_data
.fan_table_start
= tmp
;
2854 error
|= (result
!= 0);
2856 result
= smu7_read_smc_sram_dword(hwmgr
->smumgr
,
2857 SMU72_FIRMWARE_HEADER_LOCATION
+
2858 offsetof(SMU72_Firmware_Header
, mcArbDramTimingTable
),
2862 smu_data
->smu7_data
.arb_table_start
= tmp
;
2864 error
|= (result
!= 0);
2866 result
= smu7_read_smc_sram_dword(hwmgr
->smumgr
,
2867 SMU72_FIRMWARE_HEADER_LOCATION
+
2868 offsetof(SMU72_Firmware_Header
, Version
),
2872 hwmgr
->microcode_version_info
.SMC
= tmp
;
2874 error
|= (result
!= 0);
2876 return error
? 1 : 0;
2879 /*---------------------------MC----------------------------*/
2881 static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr
*hwmgr
)
2883 return (uint8_t) (0xFF & (cgs_read_register(hwmgr
->device
, mmBIOS_SCRATCH_4
) >> 16));
2886 static bool tonga_check_s0_mc_reg_index(uint16_t in_reg
, uint16_t *out_reg
)
2891 case mmMC_SEQ_RAS_TIMING
:
2892 *out_reg
= mmMC_SEQ_RAS_TIMING_LP
;
2895 case mmMC_SEQ_DLL_STBY
:
2896 *out_reg
= mmMC_SEQ_DLL_STBY_LP
;
2899 case mmMC_SEQ_G5PDX_CMD0
:
2900 *out_reg
= mmMC_SEQ_G5PDX_CMD0_LP
;
2903 case mmMC_SEQ_G5PDX_CMD1
:
2904 *out_reg
= mmMC_SEQ_G5PDX_CMD1_LP
;
2907 case mmMC_SEQ_G5PDX_CTRL
:
2908 *out_reg
= mmMC_SEQ_G5PDX_CTRL_LP
;
2911 case mmMC_SEQ_CAS_TIMING
:
2912 *out_reg
= mmMC_SEQ_CAS_TIMING_LP
;
2915 case mmMC_SEQ_MISC_TIMING
:
2916 *out_reg
= mmMC_SEQ_MISC_TIMING_LP
;
2919 case mmMC_SEQ_MISC_TIMING2
:
2920 *out_reg
= mmMC_SEQ_MISC_TIMING2_LP
;
2923 case mmMC_SEQ_PMG_DVS_CMD
:
2924 *out_reg
= mmMC_SEQ_PMG_DVS_CMD_LP
;
2927 case mmMC_SEQ_PMG_DVS_CTL
:
2928 *out_reg
= mmMC_SEQ_PMG_DVS_CTL_LP
;
2931 case mmMC_SEQ_RD_CTL_D0
:
2932 *out_reg
= mmMC_SEQ_RD_CTL_D0_LP
;
2935 case mmMC_SEQ_RD_CTL_D1
:
2936 *out_reg
= mmMC_SEQ_RD_CTL_D1_LP
;
2939 case mmMC_SEQ_WR_CTL_D0
:
2940 *out_reg
= mmMC_SEQ_WR_CTL_D0_LP
;
2943 case mmMC_SEQ_WR_CTL_D1
:
2944 *out_reg
= mmMC_SEQ_WR_CTL_D1_LP
;
2947 case mmMC_PMG_CMD_EMRS
:
2948 *out_reg
= mmMC_SEQ_PMG_CMD_EMRS_LP
;
2951 case mmMC_PMG_CMD_MRS
:
2952 *out_reg
= mmMC_SEQ_PMG_CMD_MRS_LP
;
2955 case mmMC_PMG_CMD_MRS1
:
2956 *out_reg
= mmMC_SEQ_PMG_CMD_MRS1_LP
;
2959 case mmMC_SEQ_PMG_TIMING
:
2960 *out_reg
= mmMC_SEQ_PMG_TIMING_LP
;
2963 case mmMC_PMG_CMD_MRS2
:
2964 *out_reg
= mmMC_SEQ_PMG_CMD_MRS2_LP
;
2967 case mmMC_SEQ_WR_CTL_2
:
2968 *out_reg
= mmMC_SEQ_WR_CTL_2_LP
;
2979 static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table
*table
)
2984 for (i
= 0; i
< table
->last
; i
++) {
2985 table
->mc_reg_address
[i
].s0
=
2986 tonga_check_s0_mc_reg_index(table
->mc_reg_address
[i
].s1
,
2989 table
->mc_reg_address
[i
].s1
;
2994 static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table
*table
,
2995 struct tonga_mc_reg_table
*ni_table
)
2999 PP_ASSERT_WITH_CODE((table
->last
<= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
3000 "Invalid VramInfo table.", return -EINVAL
);
3001 PP_ASSERT_WITH_CODE((table
->num_entries
<= MAX_AC_TIMING_ENTRIES
),
3002 "Invalid VramInfo table.", return -EINVAL
);
3004 for (i
= 0; i
< table
->last
; i
++)
3005 ni_table
->mc_reg_address
[i
].s1
= table
->mc_reg_address
[i
].s1
;
3007 ni_table
->last
= table
->last
;
3009 for (i
= 0; i
< table
->num_entries
; i
++) {
3010 ni_table
->mc_reg_table_entry
[i
].mclk_max
=
3011 table
->mc_reg_table_entry
[i
].mclk_max
;
3012 for (j
= 0; j
< table
->last
; j
++) {
3013 ni_table
->mc_reg_table_entry
[i
].mc_data
[j
] =
3014 table
->mc_reg_table_entry
[i
].mc_data
[j
];
3018 ni_table
->num_entries
= table
->num_entries
;
3024 * VBIOS omits some information to reduce size, we need to recover them here.
3025 * 1. when we see mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to
3026 * mmMC_PMG_CMD_EMRS /_LP[15:0]. Bit[15:0] MRS, need to be update
3027 * mmMC_PMG_CMD_MRS/_LP[15:0]
3028 * 2. when we see mmMC_SEQ_RESERVE_M, bit[15:0] EMRS2, need to be write to
3029 * mmMC_PMG_CMD_MRS1/_LP[15:0].
3030 * 3. need to set these data for each clock range
3031 * @param hwmgr the address of the powerplay hardware manager.
3032 * @param table the address of MCRegTable
3035 static int tonga_set_mc_special_registers(struct pp_hwmgr
*hwmgr
,
3036 struct tonga_mc_reg_table
*table
)
3040 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
3042 for (i
= 0, j
= table
->last
; i
< table
->last
; i
++) {
3043 PP_ASSERT_WITH_CODE((j
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
3044 "Invalid VramInfo table.", return -EINVAL
);
3046 switch (table
->mc_reg_address
[i
].s1
) {
3048 case mmMC_SEQ_MISC1
:
3049 temp_reg
= cgs_read_register(hwmgr
->device
,
3051 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_EMRS
;
3052 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_EMRS_LP
;
3053 for (k
= 0; k
< table
->num_entries
; k
++) {
3054 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3055 ((temp_reg
& 0xffff0000)) |
3056 ((table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0xffff0000) >> 16);
3059 PP_ASSERT_WITH_CODE((j
< SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
3060 "Invalid VramInfo table.", return -EINVAL
);
3062 temp_reg
= cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS
);
3063 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_MRS
;
3064 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_MRS_LP
;
3065 for (k
= 0; k
< table
->num_entries
; k
++) {
3066 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3067 (temp_reg
& 0xffff0000) |
3068 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0x0000ffff);
3070 if (!data
->is_memory_gddr5
)
3071 table
->mc_reg_table_entry
[k
].mc_data
[j
] |= 0x100;
3074 PP_ASSERT_WITH_CODE((j
<= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
3075 "Invalid VramInfo table.", return -EINVAL
);
3077 if (!data
->is_memory_gddr5
) {
3078 table
->mc_reg_address
[j
].s1
= mmMC_PMG_AUTO_CMD
;
3079 table
->mc_reg_address
[j
].s0
= mmMC_PMG_AUTO_CMD
;
3080 for (k
= 0; k
< table
->num_entries
; k
++)
3081 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3082 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0xffff0000) >> 16;
3084 PP_ASSERT_WITH_CODE((j
<= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
3085 "Invalid VramInfo table.", return -EINVAL
);
3090 case mmMC_SEQ_RESERVE_M
:
3091 temp_reg
= cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS1
);
3092 table
->mc_reg_address
[j
].s1
= mmMC_PMG_CMD_MRS1
;
3093 table
->mc_reg_address
[j
].s0
= mmMC_SEQ_PMG_CMD_MRS1_LP
;
3094 for (k
= 0; k
< table
->num_entries
; k
++) {
3095 table
->mc_reg_table_entry
[k
].mc_data
[j
] =
3096 (temp_reg
& 0xffff0000) |
3097 (table
->mc_reg_table_entry
[k
].mc_data
[i
] & 0x0000ffff);
3100 PP_ASSERT_WITH_CODE((j
<= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE
),
3101 "Invalid VramInfo table.", return -EINVAL
);
3115 static int tonga_set_valid_flag(struct tonga_mc_reg_table
*table
)
3119 for (i
= 0; i
< table
->last
; i
++) {
3120 for (j
= 1; j
< table
->num_entries
; j
++) {
3121 if (table
->mc_reg_table_entry
[j
-1].mc_data
[i
] !=
3122 table
->mc_reg_table_entry
[j
].mc_data
[i
]) {
3123 table
->validflag
|= (1<<i
);
3132 int tonga_initialize_mc_reg_table(struct pp_hwmgr
*hwmgr
)
3135 struct tonga_smumgr
*smu_data
= (struct tonga_smumgr
*)(hwmgr
->smumgr
->backend
);
3136 pp_atomctrl_mc_reg_table
*table
;
3137 struct tonga_mc_reg_table
*ni_table
= &smu_data
->mc_reg_table
;
3138 uint8_t module_index
= tonga_get_memory_modile_index(hwmgr
);
3140 table
= kzalloc(sizeof(pp_atomctrl_mc_reg_table
), GFP_KERNEL
);
3145 /* Program additional LP registers that are no longer programmed by VBIOS */
3146 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING_LP
,
3147 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RAS_TIMING
));
3148 cgs_write_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING_LP
,
3149 cgs_read_register(hwmgr
->device
, mmMC_SEQ_CAS_TIMING
));
3150 cgs_write_register(hwmgr
->device
, mmMC_SEQ_DLL_STBY_LP
,
3151 cgs_read_register(hwmgr
->device
, mmMC_SEQ_DLL_STBY
));
3152 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD0_LP
,
3153 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD0
));
3154 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD1_LP
,
3155 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CMD1
));
3156 cgs_write_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CTRL_LP
,
3157 cgs_read_register(hwmgr
->device
, mmMC_SEQ_G5PDX_CTRL
));
3158 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CMD_LP
,
3159 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CMD
));
3160 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CTL_LP
,
3161 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_DVS_CTL
));
3162 cgs_write_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING_LP
,
3163 cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING
));
3164 cgs_write_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2_LP
,
3165 cgs_read_register(hwmgr
->device
, mmMC_SEQ_MISC_TIMING2
));
3166 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_EMRS_LP
,
3167 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_EMRS
));
3168 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS_LP
,
3169 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS
));
3170 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS1_LP
,
3171 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS1
));
3172 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D0_LP
,
3173 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D0
));
3174 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1_LP
,
3175 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_D1
));
3176 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0_LP
,
3177 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D0
));
3178 cgs_write_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1_LP
,
3179 cgs_read_register(hwmgr
->device
, mmMC_SEQ_RD_CTL_D1
));
3180 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING_LP
,
3181 cgs_read_register(hwmgr
->device
, mmMC_SEQ_PMG_TIMING
));
3182 cgs_write_register(hwmgr
->device
, mmMC_SEQ_PMG_CMD_MRS2_LP
,
3183 cgs_read_register(hwmgr
->device
, mmMC_PMG_CMD_MRS2
));
3184 cgs_write_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_2_LP
,
3185 cgs_read_register(hwmgr
->device
, mmMC_SEQ_WR_CTL_2
));
3187 memset(table
, 0x00, sizeof(pp_atomctrl_mc_reg_table
));
3189 result
= atomctrl_initialize_mc_reg_table(hwmgr
, module_index
, table
);
3192 result
= tonga_copy_vbios_smc_reg_table(table
, ni_table
);
3195 tonga_set_s0_mc_reg_index(ni_table
);
3196 result
= tonga_set_mc_special_registers(hwmgr
, ni_table
);
3200 tonga_set_valid_flag(ni_table
);
3207 bool tonga_is_dpm_running(struct pp_hwmgr
*hwmgr
)
3209 return (1 == PHM_READ_INDIRECT_FIELD(hwmgr
->device
,
3210 CGS_IND_REG__SMC
, FEATURE_STATUS
, VOLTAGE_CONTROLLER_ON
))