2 * Copyright 2015 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "tonga_hwmgr.h"
27 #include "tonga_powertune.h"
28 #include "tonga_smumgr.h"
29 #include "smu72_discrete.h"
31 #include "tonga_ppsmc.h"
33 #define VOLTAGE_SCALE 4
34 #define POWERTUNE_DEFAULT_SET_MAX 1
36 struct tonga_pt_defaults tonga_power_tune_data_set_array
[POWERTUNE_DEFAULT_SET_MAX
] = {
37 /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */
38 {1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
39 {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
40 {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } },
43 void tonga_initialize_power_tune_defaults(struct pp_hwmgr
*hwmgr
)
45 struct tonga_hwmgr
*tonga_hwmgr
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
46 struct phm_ppt_v1_information
*table_info
=
47 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
51 table_info
->cac_dtp_table
->usPowerTuneDataSetID
<= POWERTUNE_DEFAULT_SET_MAX
&&
52 table_info
->cac_dtp_table
->usPowerTuneDataSetID
)
53 tonga_hwmgr
->power_tune_defaults
=
54 &tonga_power_tune_data_set_array
55 [table_info
->cac_dtp_table
->usPowerTuneDataSetID
- 1];
57 tonga_hwmgr
->power_tune_defaults
= &tonga_power_tune_data_set_array
[0];
60 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
61 PHM_PlatformCaps_PowerContainment
);
62 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
63 PHM_PlatformCaps_CAC
);
64 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
65 PHM_PlatformCaps_SQRamping
);
66 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
67 PHM_PlatformCaps_DBRamping
);
68 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
69 PHM_PlatformCaps_TDRamping
);
70 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
71 PHM_PlatformCaps_TCPRamping
);
73 tonga_hwmgr
->dte_tj_offset
= tmp
;
76 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
77 PHM_PlatformCaps_CAC
);
79 tonga_hwmgr
->fast_watermark_threshold
= 100;
81 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
82 PHM_PlatformCaps_PowerContainment
)) {
84 tonga_hwmgr
->enable_dte_feature
= tmp
? false : true;
85 tonga_hwmgr
->enable_tdc_limit_feature
= tmp
? true : false;
86 tonga_hwmgr
->enable_pkg_pwr_tracking_feature
= tmp
? true : false;
92 int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr
*hwmgr
)
94 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
95 struct tonga_pt_defaults
*defaults
= data
->power_tune_defaults
;
96 SMU72_Discrete_DpmTable
*dpm_table
= &(data
->smc_state_table
);
97 struct phm_ppt_v1_information
*table_info
=
98 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
99 struct phm_cac_tdp_table
*cac_dtp_table
= table_info
->cac_dtp_table
;
105 /* TDP number of fraction bits are changed from 8 to 7 for Fiji
106 * as requested by SMC team
108 dpm_table
->DefaultTdp
= PP_HOST_TO_SMC_US(
109 (uint16_t)(cac_dtp_table
->usTDP
* 256));
110 dpm_table
->TargetTdp
= PP_HOST_TO_SMC_US(
111 (uint16_t)(cac_dtp_table
->usConfigurableTDP
* 256));
113 PP_ASSERT_WITH_CODE(cac_dtp_table
->usTargetOperatingTemp
<= 255,
114 "Target Operating Temp is out of Range!",
117 dpm_table
->GpuTjMax
= (uint8_t)(cac_dtp_table
->usTargetOperatingTemp
);
118 dpm_table
->GpuTjHyst
= 8;
120 dpm_table
->DTEAmbientTempBase
= defaults
->dte_ambient_temp_base
;
122 dpm_table
->BAPM_TEMP_GRADIENT
= PP_HOST_TO_SMC_UL(defaults
->bamp_temp_gradient
);
123 pdef1
= defaults
->bapmti_r
;
124 pdef2
= defaults
->bapmti_rc
;
126 for (i
= 0; i
< SMU72_DTE_ITERATIONS
; i
++) {
127 for (j
= 0; j
< SMU72_DTE_SOURCES
; j
++) {
128 for (k
= 0; k
< SMU72_DTE_SINKS
; k
++) {
129 dpm_table
->BAPMTI_R
[i
][j
][k
] = PP_HOST_TO_SMC_US(*pdef1
);
130 dpm_table
->BAPMTI_RC
[i
][j
][k
] = PP_HOST_TO_SMC_US(*pdef2
);
140 static int tonga_populate_svi_load_line(struct pp_hwmgr
*hwmgr
)
142 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
143 const struct tonga_pt_defaults
*defaults
= data
->power_tune_defaults
;
145 data
->power_tune_table
.SviLoadLineEn
= defaults
->svi_load_line_en
;
146 data
->power_tune_table
.SviLoadLineVddC
= defaults
->svi_load_line_vddC
;
147 data
->power_tune_table
.SviLoadLineTrimVddC
= 3;
148 data
->power_tune_table
.SviLoadLineOffsetVddC
= 0;
153 static int tonga_populate_tdc_limit(struct pp_hwmgr
*hwmgr
)
156 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
157 struct phm_ppt_v1_information
*table_info
=
158 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
159 const struct tonga_pt_defaults
*defaults
= data
->power_tune_defaults
;
161 /* TDC number of fraction bits are changed from 8 to 7
162 * for Fiji as requested by SMC team
164 tdc_limit
= (uint16_t)(table_info
->cac_dtp_table
->usTDC
* 256);
165 data
->power_tune_table
.TDC_VDDC_PkgLimit
=
166 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit
);
167 data
->power_tune_table
.TDC_VDDC_ThrottleReleaseLimitPerc
=
168 defaults
->tdc_vddc_throttle_release_limit_perc
;
169 data
->power_tune_table
.TDC_MAWt
= defaults
->tdc_mawt
;
174 static int tonga_populate_dw8(struct pp_hwmgr
*hwmgr
, uint32_t fuse_table_offset
)
176 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
177 const struct tonga_pt_defaults
*defaults
= data
->power_tune_defaults
;
180 if (tonga_read_smc_sram_dword(hwmgr
->smumgr
,
182 offsetof(SMU72_Discrete_PmFuses
, TdcWaterfallCtl
),
183 (uint32_t *)&temp
, data
->sram_end
))
184 PP_ASSERT_WITH_CODE(false,
185 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
188 data
->power_tune_table
.TdcWaterfallCtl
= defaults
->tdc_waterfall_ctl
;
193 static int tonga_populate_temperature_scaler(struct pp_hwmgr
*hwmgr
)
196 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
198 /* Currently not used. Set all to zero. */
199 for (i
= 0; i
< 16; i
++)
200 data
->power_tune_table
.LPMLTemperatureScaler
[i
] = 0;
205 static int tonga_populate_fuzzy_fan(struct pp_hwmgr
*hwmgr
)
207 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
209 if ((hwmgr
->thermal_controller
.advanceFanControlParameters
.
210 usFanOutputSensitivity
& (1 << 15)) ||
211 (hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
== 0))
212 hwmgr
->thermal_controller
.advanceFanControlParameters
.
213 usFanOutputSensitivity
= hwmgr
->thermal_controller
.
214 advanceFanControlParameters
.usDefaultFanOutputSensitivity
;
216 data
->power_tune_table
.FuzzyFan_PwmSetDelta
=
217 PP_HOST_TO_SMC_US(hwmgr
->thermal_controller
.
218 advanceFanControlParameters
.usFanOutputSensitivity
);
222 static int tonga_populate_gnb_lpml(struct pp_hwmgr
*hwmgr
)
225 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
227 /* Currently not used. Set all to zero. */
228 for (i
= 0; i
< 16; i
++)
229 data
->power_tune_table
.GnbLPML
[i
] = 0;
234 static int tonga_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr
*hwmgr
)
239 static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr
*hwmgr
)
241 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
242 struct phm_ppt_v1_information
*table_info
=
243 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
244 uint16_t hi_sidd
= data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
;
245 uint16_t lo_sidd
= data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
;
246 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
248 hi_sidd
= (uint16_t)(cac_table
->usHighCACLeakage
/ 100 * 256);
249 lo_sidd
= (uint16_t)(cac_table
->usLowCACLeakage
/ 100 * 256);
251 data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
=
252 CONVERT_FROM_HOST_TO_SMC_US(hi_sidd
);
253 data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
=
254 CONVERT_FROM_HOST_TO_SMC_US(lo_sidd
);
259 int tonga_populate_pm_fuses(struct pp_hwmgr
*hwmgr
)
261 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
262 uint32_t pm_fuse_table_offset
;
264 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
265 PHM_PlatformCaps_PowerContainment
)) {
266 if (tonga_read_smc_sram_dword(hwmgr
->smumgr
,
267 SMU72_FIRMWARE_HEADER_LOCATION
+
268 offsetof(SMU72_Firmware_Header
, PmFuseTable
),
269 &pm_fuse_table_offset
, data
->sram_end
))
270 PP_ASSERT_WITH_CODE(false,
271 "Attempt to get pm_fuse_table_offset Failed!",
275 if (tonga_populate_svi_load_line(hwmgr
))
276 PP_ASSERT_WITH_CODE(false,
277 "Attempt to populate SviLoadLine Failed!",
280 if (tonga_populate_tdc_limit(hwmgr
))
281 PP_ASSERT_WITH_CODE(false,
282 "Attempt to populate TDCLimit Failed!", return -EINVAL
);
284 if (tonga_populate_dw8(hwmgr
, pm_fuse_table_offset
))
285 PP_ASSERT_WITH_CODE(false,
286 "Attempt to populate TdcWaterfallCtl Failed !",
290 if (tonga_populate_temperature_scaler(hwmgr
) != 0)
291 PP_ASSERT_WITH_CODE(false,
292 "Attempt to populate LPMLTemperatureScaler Failed!",
296 if (tonga_populate_fuzzy_fan(hwmgr
))
297 PP_ASSERT_WITH_CODE(false,
298 "Attempt to populate Fuzzy Fan Control parameters Failed!",
302 if (tonga_populate_gnb_lpml(hwmgr
))
303 PP_ASSERT_WITH_CODE(false,
304 "Attempt to populate GnbLPML Failed!",
308 if (tonga_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr
))
309 PP_ASSERT_WITH_CODE(false,
310 "Attempt to populate GnbLPML Min and Max Vid Failed!",
314 if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr
))
315 PP_ASSERT_WITH_CODE(false,
316 "Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!",
319 if (tonga_copy_bytes_to_smc(hwmgr
->smumgr
, pm_fuse_table_offset
,
320 (uint8_t *)&data
->power_tune_table
,
321 sizeof(struct SMU72_Discrete_PmFuses
), data
->sram_end
))
322 PP_ASSERT_WITH_CODE(false,
323 "Attempt to download PmFuseTable Failed!",
329 int tonga_enable_smc_cac(struct pp_hwmgr
*hwmgr
)
331 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
334 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
335 PHM_PlatformCaps_CAC
)) {
338 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
339 (uint16_t)(PPSMC_MSG_EnableCac
));
340 PP_ASSERT_WITH_CODE((smc_result
== 0),
341 "Failed to enable CAC in SMC.", result
= -1);
343 data
->cac_enabled
= (smc_result
== 0) ? true : false;
348 int tonga_disable_smc_cac(struct pp_hwmgr
*hwmgr
)
350 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
353 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
354 PHM_PlatformCaps_CAC
) && data
->cac_enabled
) {
355 int smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
356 (uint16_t)(PPSMC_MSG_DisableCac
));
357 PP_ASSERT_WITH_CODE((smc_result
== 0),
358 "Failed to disable CAC in SMC.", result
= -1);
360 data
->cac_enabled
= false;
365 int tonga_set_power_limit(struct pp_hwmgr
*hwmgr
, uint32_t n
)
367 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
369 if (data
->power_containment_features
&
370 POWERCONTAINMENT_FEATURE_PkgPwrLimit
)
371 return smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
372 PPSMC_MSG_PkgPwrSetLimit
, n
);
376 static int tonga_set_overdriver_target_tdp(struct pp_hwmgr
*pHwMgr
, uint32_t target_tdp
)
378 return smum_send_msg_to_smc_with_parameter(pHwMgr
->smumgr
,
379 PPSMC_MSG_OverDriveSetTargetTdp
, target_tdp
);
382 int tonga_enable_power_containment(struct pp_hwmgr
*hwmgr
)
384 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
385 struct phm_ppt_v1_information
*table_info
=
386 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
390 data
->power_containment_features
= 0;
391 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
392 PHM_PlatformCaps_PowerContainment
)) {
393 if (data
->enable_dte_feature
) {
394 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
395 (uint16_t)(PPSMC_MSG_EnableDTE
));
396 PP_ASSERT_WITH_CODE((smc_result
== 0),
397 "Failed to enable DTE in SMC.", result
= -1;);
399 data
->power_containment_features
|= POWERCONTAINMENT_FEATURE_DTE
;
402 if (data
->enable_tdc_limit_feature
) {
403 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
404 (uint16_t)(PPSMC_MSG_TDCLimitEnable
));
405 PP_ASSERT_WITH_CODE((smc_result
== 0),
406 "Failed to enable TDCLimit in SMC.", result
= -1;);
408 data
->power_containment_features
|=
409 POWERCONTAINMENT_FEATURE_TDCLimit
;
412 if (data
->enable_pkg_pwr_tracking_feature
) {
413 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
414 (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable
));
415 PP_ASSERT_WITH_CODE((smc_result
== 0),
416 "Failed to enable PkgPwrTracking in SMC.", result
= -1;);
417 if (smc_result
== 0) {
418 struct phm_cac_tdp_table
*cac_table
=
419 table_info
->cac_dtp_table
;
420 uint32_t default_limit
=
421 (uint32_t)(cac_table
->usMaximumPowerDeliveryLimit
* 256);
423 data
->power_containment_features
|=
424 POWERCONTAINMENT_FEATURE_PkgPwrLimit
;
426 if (tonga_set_power_limit(hwmgr
, default_limit
))
427 printk(KERN_ERR
"Failed to set Default Power Limit in SMC!");
434 int tonga_disable_power_containment(struct pp_hwmgr
*hwmgr
)
436 struct tonga_hwmgr
*data
= (struct tonga_hwmgr
*)(hwmgr
->backend
);
439 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
440 PHM_PlatformCaps_PowerContainment
) &&
441 data
->power_containment_features
) {
444 if (data
->power_containment_features
&
445 POWERCONTAINMENT_FEATURE_TDCLimit
) {
446 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
447 (uint16_t)(PPSMC_MSG_TDCLimitDisable
));
448 PP_ASSERT_WITH_CODE((smc_result
== 0),
449 "Failed to disable TDCLimit in SMC.",
450 result
= smc_result
);
453 if (data
->power_containment_features
&
454 POWERCONTAINMENT_FEATURE_DTE
) {
455 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
456 (uint16_t)(PPSMC_MSG_DisableDTE
));
457 PP_ASSERT_WITH_CODE((smc_result
== 0),
458 "Failed to disable DTE in SMC.",
459 result
= smc_result
);
462 if (data
->power_containment_features
&
463 POWERCONTAINMENT_FEATURE_PkgPwrLimit
) {
464 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
465 (uint16_t)(PPSMC_MSG_PkgPwrLimitDisable
));
466 PP_ASSERT_WITH_CODE((smc_result
== 0),
467 "Failed to disable PkgPwrTracking in SMC.",
468 result
= smc_result
);
470 data
->power_containment_features
= 0;
476 int tonga_power_control_set_level(struct pp_hwmgr
*hwmgr
)
478 struct phm_ppt_v1_information
*table_info
=
479 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
480 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
481 int adjust_percent
, target_tdp
;
484 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
485 PHM_PlatformCaps_PowerContainment
)) {
486 /* adjustment percentage has already been validated */
487 adjust_percent
= hwmgr
->platform_descriptor
.TDPAdjustmentPolarity
?
488 hwmgr
->platform_descriptor
.TDPAdjustment
:
489 (-1 * hwmgr
->platform_descriptor
.TDPAdjustment
);
490 /* SMC requested that target_tdp to be 7 bit fraction in DPM table
491 * but message to be 8 bit fraction for messages
493 target_tdp
= ((100 + adjust_percent
) * (int)(cac_table
->usTDP
* 256)) / 100;
494 result
= tonga_set_overdriver_target_tdp(hwmgr
, (uint32_t)target_tdp
);