2 * Copyright 2016 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Author: Huang Rui <ray.huang@amd.com>
29 #include "iceland_hwmgr.h"
30 #include "iceland_powertune.h"
31 #include "iceland_smumgr.h"
32 #include "smu71_discrete.h"
35 #include "cgs_common.h"
36 #include "pp_endian.h"
38 #include "bif/bif_5_0_d.h"
39 #include "bif/bif_5_0_sh_mask.h"
41 #define VOLTAGE_SCALE 4
42 #define POWERTUNE_DEFAULT_SET_MAX 1
44 #define DEVICE_ID_VI_ICELAND_M_6900 0x6900
45 #define DEVICE_ID_VI_ICELAND_M_6901 0x6901
46 #define DEVICE_ID_VI_ICELAND_M_6902 0x6902
47 #define DEVICE_ID_VI_ICELAND_M_6903 0x6903
50 struct iceland_pt_defaults defaults_iceland
=
53 * sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc,
54 * TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
56 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
57 { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 },
58 { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 }
62 struct iceland_pt_defaults defaults_icelandxt
=
65 * sviLoadLIneEn, SviLoadLineVddC,
66 * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
67 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac,
70 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0,
71 { 0xA7, 0x0, 0x0, 0xB5, 0x0, 0x0, 0x9F, 0x0, 0x0, 0xD6, 0x0, 0x0, 0xD7, 0x0, 0x0},
72 { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0}
76 struct iceland_pt_defaults defaults_icelandpro
=
79 * sviLoadLIneEn, SviLoadLineVddC,
80 * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
81 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac,
84 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0,
85 { 0xB7, 0x0, 0x0, 0xC3, 0x0, 0x0, 0xB5, 0x0, 0x0, 0xEA, 0x0, 0x0, 0xE6, 0x0, 0x0},
86 { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0}
89 void iceland_initialize_power_tune_defaults(struct pp_hwmgr
*hwmgr
)
91 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
93 struct cgs_system_info sys_info
= {0};
96 sys_info
.size
= sizeof(struct cgs_system_info
);
97 sys_info
.info_id
= CGS_SYSTEM_INFO_PCIE_DEV
;
98 cgs_query_system_info(hwmgr
->device
, &sys_info
);
99 pdev_id
= (uint32_t)sys_info
.value
;
102 case DEVICE_ID_VI_ICELAND_M_6900
:
103 case DEVICE_ID_VI_ICELAND_M_6903
:
104 data
->power_tune_defaults
= &defaults_icelandxt
;
107 case DEVICE_ID_VI_ICELAND_M_6901
:
108 case DEVICE_ID_VI_ICELAND_M_6902
:
109 data
->power_tune_defaults
= &defaults_icelandpro
;
112 /* TODO: need to assign valid defaults */
113 data
->power_tune_defaults
= &defaults_iceland
;
114 pr_warning("Unknown V.I. Device ID.\n");
118 /* Assume disabled */
119 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
120 PHM_PlatformCaps_PowerContainment
);
121 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
122 PHM_PlatformCaps_CAC
);
123 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
124 PHM_PlatformCaps_SQRamping
);
125 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
126 PHM_PlatformCaps_DBRamping
);
127 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
128 PHM_PlatformCaps_TDRamping
);
129 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
130 PHM_PlatformCaps_TCPRamping
);
132 data
->ul_dte_tj_offset
= tmp
;
135 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
136 PHM_PlatformCaps_CAC
);
138 data
->fast_watermark_threshold
= 100;
140 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
141 PHM_PlatformCaps_PowerContainment
)) {
143 data
->enable_dte_feature
= tmp
? false : true;
144 data
->enable_tdc_limit_feature
= tmp
? true : false;
145 data
->enable_pkg_pwr_tracking_feature
= tmp
? true : false;
150 int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr
*hwmgr
)
152 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
153 struct iceland_pt_defaults
*defaults
= data
->power_tune_defaults
;
154 SMU71_Discrete_DpmTable
*dpm_table
= &(data
->smc_state_table
);
155 struct phm_cac_tdp_table
*cac_dtp_table
= hwmgr
->dyn_state
.cac_dtp_table
;
156 struct phm_ppm_table
*ppm
= hwmgr
->dyn_state
.ppm_parameter_table
;
157 uint16_t *def1
, *def2
;
161 * TDP number of fraction bits are changed from 8 to 7 for Iceland
162 * as requested by SMC team
164 dpm_table
->DefaultTdp
= PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table
->usTDP
* 256));
165 dpm_table
->TargetTdp
= PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table
->usConfigurableTDP
* 256));
167 dpm_table
->DTETjOffset
= (uint8_t)data
->ul_dte_tj_offset
;
169 dpm_table
->GpuTjMax
= (uint8_t)(data
->thermal_temp_setting
.temperature_high
/ PP_TEMPERATURE_UNITS_PER_CENTIGRADES
);
170 dpm_table
->GpuTjHyst
= 8;
172 dpm_table
->DTEAmbientTempBase
= defaults
->dte_ambient_temp_base
;
174 /* The following are for new Iceland Multi-input fan/thermal control */
176 dpm_table
->PPM_PkgPwrLimit
= (uint16_t)ppm
->dgpu_tdp
* 256 / 1000;
177 dpm_table
->PPM_TemperatureLimit
= (uint16_t)ppm
->tj_max
* 256;
179 dpm_table
->PPM_PkgPwrLimit
= 0;
180 dpm_table
->PPM_TemperatureLimit
= 0;
183 CONVERT_FROM_HOST_TO_SMC_US(dpm_table
->PPM_PkgPwrLimit
);
184 CONVERT_FROM_HOST_TO_SMC_US(dpm_table
->PPM_TemperatureLimit
);
186 dpm_table
->BAPM_TEMP_GRADIENT
= PP_HOST_TO_SMC_UL(defaults
->bamp_temp_gradient
);
187 def1
= defaults
->bapmti_r
;
188 def2
= defaults
->bapmti_rc
;
190 for (i
= 0; i
< SMU71_DTE_ITERATIONS
; i
++) {
191 for (j
= 0; j
< SMU71_DTE_SOURCES
; j
++) {
192 for (k
= 0; k
< SMU71_DTE_SINKS
; k
++) {
193 dpm_table
->BAPMTI_R
[i
][j
][k
] = PP_HOST_TO_SMC_US(*def1
);
194 dpm_table
->BAPMTI_RC
[i
][j
][k
] = PP_HOST_TO_SMC_US(*def2
);
204 static int iceland_populate_svi_load_line(struct pp_hwmgr
*hwmgr
)
206 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
207 const struct iceland_pt_defaults
*defaults
= data
->power_tune_defaults
;
209 data
->power_tune_table
.SviLoadLineEn
= defaults
->svi_load_line_en
;
210 data
->power_tune_table
.SviLoadLineVddC
= defaults
->svi_load_line_vddc
;
211 data
->power_tune_table
.SviLoadLineTrimVddC
= 3;
212 data
->power_tune_table
.SviLoadLineOffsetVddC
= 0;
217 static int iceland_populate_tdc_limit(struct pp_hwmgr
*hwmgr
)
220 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
221 const struct iceland_pt_defaults
*defaults
= data
->power_tune_defaults
;
223 /* TDC number of fraction bits are changed from 8 to 7
224 * for Iceland as requested by SMC team
226 tdc_limit
= (uint16_t)(hwmgr
->dyn_state
.cac_dtp_table
->usTDC
* 256);
227 data
->power_tune_table
.TDC_VDDC_PkgLimit
=
228 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit
);
229 data
->power_tune_table
.TDC_VDDC_ThrottleReleaseLimitPerc
=
230 defaults
->tdc_vddc_throttle_release_limit_perc
;
231 data
->power_tune_table
.TDC_MAWt
= defaults
->tdc_mawt
;
236 static int iceland_populate_dw8(struct pp_hwmgr
*hwmgr
, uint32_t fuse_table_offset
)
238 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
239 const struct iceland_pt_defaults
*defaults
= data
->power_tune_defaults
;
242 if (iceland_read_smc_sram_dword(hwmgr
->smumgr
,
244 offsetof(SMU71_Discrete_PmFuses
, TdcWaterfallCtl
),
245 (uint32_t *)&temp
, data
->sram_end
))
246 PP_ASSERT_WITH_CODE(false,
247 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
250 data
->power_tune_table
.TdcWaterfallCtl
= defaults
->tdc_waterfall_ctl
;
255 static int iceland_populate_temperature_scaler(struct pp_hwmgr
*hwmgr
)
260 static int iceland_populate_gnb_lpml(struct pp_hwmgr
*hwmgr
)
263 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
265 /* Currently not used. Set all to zero. */
266 for (i
= 0; i
< 8; i
++)
267 data
->power_tune_table
.GnbLPML
[i
] = 0;
272 static int iceland_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr
*hwmgr
)
277 static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr
*hwmgr
)
279 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
280 uint16_t HiSidd
= data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
;
281 uint16_t LoSidd
= data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
;
282 struct phm_cac_tdp_table
*cac_table
= hwmgr
->dyn_state
.cac_dtp_table
;
284 HiSidd
= (uint16_t)(cac_table
->usHighCACLeakage
/ 100 * 256);
285 LoSidd
= (uint16_t)(cac_table
->usLowCACLeakage
/ 100 * 256);
287 data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
=
288 CONVERT_FROM_HOST_TO_SMC_US(HiSidd
);
289 data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
=
290 CONVERT_FROM_HOST_TO_SMC_US(LoSidd
);
295 int iceland_populate_pm_fuses(struct pp_hwmgr
*hwmgr
)
297 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
298 uint32_t pm_fuse_table_offset
;
300 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
301 PHM_PlatformCaps_PowerContainment
)) {
302 if (iceland_read_smc_sram_dword(hwmgr
->smumgr
,
303 SMU71_FIRMWARE_HEADER_LOCATION
+
304 offsetof(SMU71_Firmware_Header
, PmFuseTable
),
305 &pm_fuse_table_offset
, data
->sram_end
))
306 PP_ASSERT_WITH_CODE(false,
307 "Attempt to get pm_fuse_table_offset Failed!",
311 if (iceland_populate_bapm_vddc_vid_sidd(hwmgr
))
312 PP_ASSERT_WITH_CODE(false,
313 "Attempt to populate bapm vddc vid Failed!",
317 if (iceland_populate_vddc_vid(hwmgr
))
318 PP_ASSERT_WITH_CODE(false,
319 "Attempt to populate vddc vid Failed!",
323 if (iceland_populate_svi_load_line(hwmgr
))
324 PP_ASSERT_WITH_CODE(false,
325 "Attempt to populate SviLoadLine Failed!",
328 if (iceland_populate_tdc_limit(hwmgr
))
329 PP_ASSERT_WITH_CODE(false,
330 "Attempt to populate TDCLimit Failed!", return -EINVAL
);
332 if (iceland_populate_dw8(hwmgr
, pm_fuse_table_offset
))
333 PP_ASSERT_WITH_CODE(false,
334 "Attempt to populate TdcWaterfallCtl, "
335 "LPMLTemperature Min and Max Failed!",
339 if (0 != iceland_populate_temperature_scaler(hwmgr
))
340 PP_ASSERT_WITH_CODE(false,
341 "Attempt to populate LPMLTemperatureScaler Failed!",
345 if (iceland_populate_gnb_lpml(hwmgr
))
346 PP_ASSERT_WITH_CODE(false,
347 "Attempt to populate GnbLPML Failed!",
351 if (iceland_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr
))
352 PP_ASSERT_WITH_CODE(false,
353 "Attempt to populate GnbLPML Min and Max Vid Failed!",
357 if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr
))
358 PP_ASSERT_WITH_CODE(false,
359 "Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!",
362 if (iceland_copy_bytes_to_smc(hwmgr
->smumgr
, pm_fuse_table_offset
,
363 (uint8_t *)&data
->power_tune_table
,
364 sizeof(struct SMU71_Discrete_PmFuses
), data
->sram_end
))
365 PP_ASSERT_WITH_CODE(false,
366 "Attempt to download PmFuseTable Failed!",
372 int iceland_enable_smc_cac(struct pp_hwmgr
*hwmgr
)
374 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
377 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
378 PHM_PlatformCaps_CAC
)) {
380 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
381 (uint16_t)(PPSMC_MSG_EnableCac
));
382 PP_ASSERT_WITH_CODE((0 == smc_result
),
383 "Failed to enable CAC in SMC.", result
= -1);
385 data
->cac_enabled
= (0 == smc_result
) ? true : false;
390 static int iceland_set_power_limit(struct pp_hwmgr
*hwmgr
, uint32_t n
)
392 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
394 if(data
->power_containment_features
&
395 POWERCONTAINMENT_FEATURE_PkgPwrLimit
)
396 return smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
397 PPSMC_MSG_PkgPwrSetLimit
, n
);
401 static int iceland_set_overdriver_target_tdp(struct pp_hwmgr
*pHwMgr
, uint32_t target_tdp
)
403 return smum_send_msg_to_smc_with_parameter(pHwMgr
->smumgr
,
404 PPSMC_MSG_OverDriveSetTargetTdp
, target_tdp
);
407 int iceland_enable_power_containment(struct pp_hwmgr
*hwmgr
)
409 struct iceland_hwmgr
*data
= (struct iceland_hwmgr
*)(hwmgr
->backend
);
410 SMU71_Discrete_DpmTable
*dpm_table
= &data
->smc_state_table
;
413 uint32_t is_asic_kicker
;
415 data
->power_containment_features
= 0;
416 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
417 PHM_PlatformCaps_PowerContainment
)) {
418 is_asic_kicker
= cgs_read_register(hwmgr
->device
, mmCC_BIF_BX_STRAP2
);
419 is_asic_kicker
= (is_asic_kicker
>> 12) & 0x01;
421 if (data
->enable_bapm_feature
&&
423 phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
424 PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
))) {
425 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
426 (uint16_t)(PPSMC_MSG_EnableDTE
));
427 PP_ASSERT_WITH_CODE((0 == smc_result
),
428 "Failed to enable BAPM in SMC.", result
= -1;);
430 data
->power_containment_features
|= POWERCONTAINMENT_FEATURE_BAPM
;
433 if (is_asic_kicker
&& !phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
434 PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
))
435 dpm_table
->DTEMode
= 2;
437 if (data
->enable_tdc_limit_feature
) {
438 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
439 (uint16_t)(PPSMC_MSG_TDCLimitEnable
));
440 PP_ASSERT_WITH_CODE((0 == smc_result
),
441 "Failed to enable TDCLimit in SMC.", result
= -1;);
443 data
->power_containment_features
|=
444 POWERCONTAINMENT_FEATURE_TDCLimit
;
447 if (data
->enable_pkg_pwr_tracking_feature
) {
448 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
449 (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable
));
450 PP_ASSERT_WITH_CODE((0 == smc_result
),
451 "Failed to enable PkgPwrTracking in SMC.", result
= -1;);
452 if (0 == smc_result
) {
453 struct phm_cac_tdp_table
*cac_table
=
454 hwmgr
->dyn_state
.cac_dtp_table
;
455 uint32_t default_limit
=
456 (uint32_t)(cac_table
->usMaximumPowerDeliveryLimit
* 256);
458 data
->power_containment_features
|=
459 POWERCONTAINMENT_FEATURE_PkgPwrLimit
;
461 if (iceland_set_power_limit(hwmgr
, default_limit
))
462 printk(KERN_ERR
"Failed to set Default Power Limit in SMC!");
469 int iceland_power_control_set_level(struct pp_hwmgr
*hwmgr
)
471 struct phm_cac_tdp_table
*cac_table
= hwmgr
->dyn_state
.cac_dtp_table
;
472 int adjust_percent
, target_tdp
;
475 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
476 PHM_PlatformCaps_PowerContainment
)) {
477 /* adjustment percentage has already been validated */
478 adjust_percent
= hwmgr
->platform_descriptor
.TDPAdjustmentPolarity
?
479 hwmgr
->platform_descriptor
.TDPAdjustment
:
480 (-1 * hwmgr
->platform_descriptor
.TDPAdjustment
);
482 * SMC requested that target_tdp to be 7 bit fraction in DPM table
483 * but message to be 8 bit fraction for messages
485 target_tdp
= ((100 + adjust_percent
) * (int)(cac_table
->usTDP
* 256)) / 100;
486 result
= iceland_set_overdriver_target_tdp(hwmgr
, (uint32_t)target_tdp
);