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 "fiji_hwmgr.h"
27 #include "fiji_powertune.h"
28 #include "fiji_smumgr.h"
29 #include "smu73_discrete.h"
32 #define VOLTAGE_SCALE 4
33 #define POWERTUNE_DEFAULT_SET_MAX 1
35 const struct fiji_pt_defaults fiji_power_tune_data_set_array
[POWERTUNE_DEFAULT_SET_MAX
] = {
36 /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */
38 /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */
42 void fiji_initialize_power_tune_defaults(struct pp_hwmgr
*hwmgr
)
44 struct fiji_hwmgr
*fiji_hwmgr
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
45 struct phm_ppt_v1_information
*table_info
=
46 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
50 table_info
->cac_dtp_table
->usPowerTuneDataSetID
<= POWERTUNE_DEFAULT_SET_MAX
&&
51 table_info
->cac_dtp_table
->usPowerTuneDataSetID
)
52 fiji_hwmgr
->power_tune_defaults
=
53 &fiji_power_tune_data_set_array
54 [table_info
->cac_dtp_table
->usPowerTuneDataSetID
- 1];
56 fiji_hwmgr
->power_tune_defaults
= &fiji_power_tune_data_set_array
[0];
59 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
60 PHM_PlatformCaps_CAC
);
61 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
62 PHM_PlatformCaps_SQRamping
);
63 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
64 PHM_PlatformCaps_DBRamping
);
65 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
66 PHM_PlatformCaps_TDRamping
);
67 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
68 PHM_PlatformCaps_TCPRamping
);
70 fiji_hwmgr
->dte_tj_offset
= tmp
;
73 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
74 PHM_PlatformCaps_CAC
);
76 fiji_hwmgr
->fast_watermark_threshold
= 100;
78 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
79 PHM_PlatformCaps_PowerContainment
)) {
81 fiji_hwmgr
->enable_dte_feature
= tmp
? false : true;
82 fiji_hwmgr
->enable_tdc_limit_feature
= tmp
? true : false;
83 fiji_hwmgr
->enable_pkg_pwr_tracking_feature
= tmp
? true : false;
88 /* PPGen has the gain setting generated in x * 100 unit
89 * This function is to convert the unit to x * 4096(0x1000) unit.
90 * This is the unit expected by SMC firmware
92 static uint16_t scale_fan_gain_settings(uint16_t raw_setting
)
95 tmp
= raw_setting
* 4096 / 100;
99 static void get_scl_sda_value(uint8_t line
, uint8_t *scl
, uint8_t* sda
)
102 case Fiji_I2CLineID_DDC1
:
103 *scl
= Fiji_I2C_DDC1CLK
;
104 *sda
= Fiji_I2C_DDC1DATA
;
106 case Fiji_I2CLineID_DDC2
:
107 *scl
= Fiji_I2C_DDC2CLK
;
108 *sda
= Fiji_I2C_DDC2DATA
;
110 case Fiji_I2CLineID_DDC3
:
111 *scl
= Fiji_I2C_DDC3CLK
;
112 *sda
= Fiji_I2C_DDC3DATA
;
114 case Fiji_I2CLineID_DDC4
:
115 *scl
= Fiji_I2C_DDC4CLK
;
116 *sda
= Fiji_I2C_DDC4DATA
;
118 case Fiji_I2CLineID_DDC5
:
119 *scl
= Fiji_I2C_DDC5CLK
;
120 *sda
= Fiji_I2C_DDC5DATA
;
122 case Fiji_I2CLineID_DDC6
:
123 *scl
= Fiji_I2C_DDC6CLK
;
124 *sda
= Fiji_I2C_DDC6DATA
;
126 case Fiji_I2CLineID_SCLSDA
:
130 case Fiji_I2CLineID_DDCVGA
:
131 *scl
= Fiji_I2C_DDCVGACLK
;
132 *sda
= Fiji_I2C_DDCVGADATA
;
141 int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr
*hwmgr
)
143 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
144 const struct fiji_pt_defaults
*defaults
= data
->power_tune_defaults
;
145 SMU73_Discrete_DpmTable
*dpm_table
= &(data
->smc_state_table
);
146 struct phm_ppt_v1_information
*table_info
=
147 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
148 struct phm_cac_tdp_table
*cac_dtp_table
= table_info
->cac_dtp_table
;
149 struct pp_advance_fan_control_parameters
*fan_table
=
150 &hwmgr
->thermal_controller
.advanceFanControlParameters
;
151 uint8_t uc_scl
, uc_sda
;
153 /* TDP number of fraction bits are changed from 8 to 7 for Fiji
154 * as requested by SMC team
156 dpm_table
->DefaultTdp
= PP_HOST_TO_SMC_US(
157 (uint16_t)(cac_dtp_table
->usTDP
* 128));
158 dpm_table
->TargetTdp
= PP_HOST_TO_SMC_US(
159 (uint16_t)(cac_dtp_table
->usTDP
* 128));
161 PP_ASSERT_WITH_CODE(cac_dtp_table
->usTargetOperatingTemp
<= 255,
162 "Target Operating Temp is out of Range!",);
164 dpm_table
->GpuTjMax
= (uint8_t)(cac_dtp_table
->usTargetOperatingTemp
);
165 dpm_table
->GpuTjHyst
= 8;
167 dpm_table
->DTEAmbientTempBase
= defaults
->DTEAmbientTempBase
;
169 /* The following are for new Fiji Multi-input fan/thermal control */
170 dpm_table
->TemperatureLimitEdge
= PP_HOST_TO_SMC_US(
171 cac_dtp_table
->usTargetOperatingTemp
* 256);
172 dpm_table
->TemperatureLimitHotspot
= PP_HOST_TO_SMC_US(
173 cac_dtp_table
->usTemperatureLimitHotspot
* 256);
174 dpm_table
->TemperatureLimitLiquid1
= PP_HOST_TO_SMC_US(
175 cac_dtp_table
->usTemperatureLimitLiquid1
* 256);
176 dpm_table
->TemperatureLimitLiquid2
= PP_HOST_TO_SMC_US(
177 cac_dtp_table
->usTemperatureLimitLiquid2
* 256);
178 dpm_table
->TemperatureLimitVrVddc
= PP_HOST_TO_SMC_US(
179 cac_dtp_table
->usTemperatureLimitVrVddc
* 256);
180 dpm_table
->TemperatureLimitVrMvdd
= PP_HOST_TO_SMC_US(
181 cac_dtp_table
->usTemperatureLimitVrMvdd
* 256);
182 dpm_table
->TemperatureLimitPlx
= PP_HOST_TO_SMC_US(
183 cac_dtp_table
->usTemperatureLimitPlx
* 256);
185 dpm_table
->FanGainEdge
= PP_HOST_TO_SMC_US(
186 scale_fan_gain_settings(fan_table
->usFanGainEdge
));
187 dpm_table
->FanGainHotspot
= PP_HOST_TO_SMC_US(
188 scale_fan_gain_settings(fan_table
->usFanGainHotspot
));
189 dpm_table
->FanGainLiquid
= PP_HOST_TO_SMC_US(
190 scale_fan_gain_settings(fan_table
->usFanGainLiquid
));
191 dpm_table
->FanGainVrVddc
= PP_HOST_TO_SMC_US(
192 scale_fan_gain_settings(fan_table
->usFanGainVrVddc
));
193 dpm_table
->FanGainVrMvdd
= PP_HOST_TO_SMC_US(
194 scale_fan_gain_settings(fan_table
->usFanGainVrMvdd
));
195 dpm_table
->FanGainPlx
= PP_HOST_TO_SMC_US(
196 scale_fan_gain_settings(fan_table
->usFanGainPlx
));
197 dpm_table
->FanGainHbm
= PP_HOST_TO_SMC_US(
198 scale_fan_gain_settings(fan_table
->usFanGainHbm
));
200 dpm_table
->Liquid1_I2C_address
= cac_dtp_table
->ucLiquid1_I2C_address
;
201 dpm_table
->Liquid2_I2C_address
= cac_dtp_table
->ucLiquid2_I2C_address
;
202 dpm_table
->Vr_I2C_address
= cac_dtp_table
->ucVr_I2C_address
;
203 dpm_table
->Plx_I2C_address
= cac_dtp_table
->ucPlx_I2C_address
;
205 get_scl_sda_value(cac_dtp_table
->ucLiquid_I2C_Line
, &uc_scl
, &uc_sda
);
206 dpm_table
->Liquid_I2C_LineSCL
= uc_scl
;
207 dpm_table
->Liquid_I2C_LineSDA
= uc_sda
;
209 get_scl_sda_value(cac_dtp_table
->ucVr_I2C_Line
, &uc_scl
, &uc_sda
);
210 dpm_table
->Vr_I2C_LineSCL
= uc_scl
;
211 dpm_table
->Vr_I2C_LineSDA
= uc_sda
;
213 get_scl_sda_value(cac_dtp_table
->ucPlx_I2C_Line
, &uc_scl
, &uc_sda
);
214 dpm_table
->Plx_I2C_LineSCL
= uc_scl
;
215 dpm_table
->Plx_I2C_LineSDA
= uc_sda
;
220 static int fiji_populate_svi_load_line(struct pp_hwmgr
*hwmgr
)
222 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
223 const struct fiji_pt_defaults
*defaults
= data
->power_tune_defaults
;
225 data
->power_tune_table
.SviLoadLineEn
= defaults
->SviLoadLineEn
;
226 data
->power_tune_table
.SviLoadLineVddC
= defaults
->SviLoadLineVddC
;
227 data
->power_tune_table
.SviLoadLineTrimVddC
= 3;
228 data
->power_tune_table
.SviLoadLineOffsetVddC
= 0;
233 static int fiji_populate_tdc_limit(struct pp_hwmgr
*hwmgr
)
236 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
237 struct phm_ppt_v1_information
*table_info
=
238 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
239 const struct fiji_pt_defaults
*defaults
= data
->power_tune_defaults
;
241 /* TDC number of fraction bits are changed from 8 to 7
242 * for Fiji as requested by SMC team
244 tdc_limit
= (uint16_t)(table_info
->cac_dtp_table
->usTDC
* 128);
245 data
->power_tune_table
.TDC_VDDC_PkgLimit
=
246 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit
);
247 data
->power_tune_table
.TDC_VDDC_ThrottleReleaseLimitPerc
=
248 defaults
->TDC_VDDC_ThrottleReleaseLimitPerc
;
249 data
->power_tune_table
.TDC_MAWt
= defaults
->TDC_MAWt
;
254 static int fiji_populate_dw8(struct pp_hwmgr
*hwmgr
, uint32_t fuse_table_offset
)
256 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
257 const struct fiji_pt_defaults
*defaults
= data
->power_tune_defaults
;
260 if (fiji_read_smc_sram_dword(hwmgr
->smumgr
,
262 offsetof(SMU73_Discrete_PmFuses
, TdcWaterfallCtl
),
263 (uint32_t *)&temp
, data
->sram_end
))
264 PP_ASSERT_WITH_CODE(false,
265 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
268 data
->power_tune_table
.TdcWaterfallCtl
= defaults
->TdcWaterfallCtl
;
269 data
->power_tune_table
.LPMLTemperatureMin
=
270 (uint8_t)((temp
>> 16) & 0xff);
271 data
->power_tune_table
.LPMLTemperatureMax
=
272 (uint8_t)((temp
>> 8) & 0xff);
273 data
->power_tune_table
.Reserved
= (uint8_t)(temp
& 0xff);
278 static int fiji_populate_temperature_scaler(struct pp_hwmgr
*hwmgr
)
281 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
283 /* Currently not used. Set all to zero. */
284 for (i
= 0; i
< 16; i
++)
285 data
->power_tune_table
.LPMLTemperatureScaler
[i
] = 0;
290 static int fiji_populate_fuzzy_fan(struct pp_hwmgr
*hwmgr
)
292 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
294 if( (hwmgr
->thermal_controller
.advanceFanControlParameters
.
295 usFanOutputSensitivity
& (1 << 15)) ||
296 0 == hwmgr
->thermal_controller
.advanceFanControlParameters
.
297 usFanOutputSensitivity
)
298 hwmgr
->thermal_controller
.advanceFanControlParameters
.
299 usFanOutputSensitivity
= hwmgr
->thermal_controller
.
300 advanceFanControlParameters
.usDefaultFanOutputSensitivity
;
302 data
->power_tune_table
.FuzzyFan_PwmSetDelta
=
303 PP_HOST_TO_SMC_US(hwmgr
->thermal_controller
.
304 advanceFanControlParameters
.usFanOutputSensitivity
);
308 static int fiji_populate_gnb_lpml(struct pp_hwmgr
*hwmgr
)
311 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
313 /* Currently not used. Set all to zero. */
314 for (i
= 0; i
< 16; i
++)
315 data
->power_tune_table
.GnbLPML
[i
] = 0;
320 static int fiji_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr
*hwmgr
)
323 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
324 uint8_t * pHiVID = data->power_tune_table.BapmVddCVidHiSidd;
325 uint8_t * pLoVID = data->power_tune_table.BapmVddCVidLoSidd;
327 min = max = pHiVID[0];
328 for (i = 0; i < 8; i++) {
329 if (0 != pHiVID[i]) {
336 if (0 != pLoVID[i]) {
344 PP_ASSERT_WITH_CODE((0 != min) && (0 != max), "BapmVddcVidSidd table does not exist!", return int_Failed);
345 data->power_tune_table.GnbLPMLMaxVid = (uint8_t)max;
346 data->power_tune_table.GnbLPMLMinVid = (uint8_t)min;
351 static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr
*hwmgr
)
353 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
354 struct phm_ppt_v1_information
*table_info
=
355 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
356 uint16_t HiSidd
= data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
;
357 uint16_t LoSidd
= data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
;
358 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
360 HiSidd
= (uint16_t)(cac_table
->usHighCACLeakage
/ 100 * 256);
361 LoSidd
= (uint16_t)(cac_table
->usLowCACLeakage
/ 100 * 256);
363 data
->power_tune_table
.BapmVddCBaseLeakageHiSidd
=
364 CONVERT_FROM_HOST_TO_SMC_US(HiSidd
);
365 data
->power_tune_table
.BapmVddCBaseLeakageLoSidd
=
366 CONVERT_FROM_HOST_TO_SMC_US(LoSidd
);
371 int fiji_populate_pm_fuses(struct pp_hwmgr
*hwmgr
)
373 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
374 uint32_t pm_fuse_table_offset
;
376 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
377 PHM_PlatformCaps_PowerContainment
)) {
378 if (fiji_read_smc_sram_dword(hwmgr
->smumgr
,
379 SMU7_FIRMWARE_HEADER_LOCATION
+
380 offsetof(SMU73_Firmware_Header
, PmFuseTable
),
381 &pm_fuse_table_offset
, data
->sram_end
))
382 PP_ASSERT_WITH_CODE(false,
383 "Attempt to get pm_fuse_table_offset Failed!",
387 if (fiji_populate_svi_load_line(hwmgr
))
388 PP_ASSERT_WITH_CODE(false,
389 "Attempt to populate SviLoadLine Failed!",
392 if (fiji_populate_tdc_limit(hwmgr
))
393 PP_ASSERT_WITH_CODE(false,
394 "Attempt to populate TDCLimit Failed!", return -EINVAL
);
396 if (fiji_populate_dw8(hwmgr
, pm_fuse_table_offset
))
397 PP_ASSERT_WITH_CODE(false,
398 "Attempt to populate TdcWaterfallCtl, "
399 "LPMLTemperature Min and Max Failed!",
403 if (0 != fiji_populate_temperature_scaler(hwmgr
))
404 PP_ASSERT_WITH_CODE(false,
405 "Attempt to populate LPMLTemperatureScaler Failed!",
409 if(fiji_populate_fuzzy_fan(hwmgr
))
410 PP_ASSERT_WITH_CODE(false,
411 "Attempt to populate Fuzzy Fan Control parameters Failed!",
415 if (fiji_populate_gnb_lpml(hwmgr
))
416 PP_ASSERT_WITH_CODE(false,
417 "Attempt to populate GnbLPML Failed!",
421 if (fiji_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr
))
422 PP_ASSERT_WITH_CODE(false,
423 "Attempt to populate GnbLPML Min and Max Vid Failed!",
427 if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr
))
428 PP_ASSERT_WITH_CODE(false,
429 "Attempt to populate BapmVddCBaseLeakage Hi and Lo "
430 "Sidd Failed!", return -EINVAL
);
432 if (fiji_copy_bytes_to_smc(hwmgr
->smumgr
, pm_fuse_table_offset
,
433 (uint8_t *)&data
->power_tune_table
,
434 sizeof(struct SMU73_Discrete_PmFuses
), data
->sram_end
))
435 PP_ASSERT_WITH_CODE(false,
436 "Attempt to download PmFuseTable Failed!",
442 int fiji_enable_smc_cac(struct pp_hwmgr
*hwmgr
)
444 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
447 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
448 PHM_PlatformCaps_CAC
)) {
450 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
451 (uint16_t)(PPSMC_MSG_EnableCac
));
452 PP_ASSERT_WITH_CODE((0 == smc_result
),
453 "Failed to enable CAC in SMC.", result
= -1);
455 data
->cac_enabled
= (0 == smc_result
) ? true : false;
460 int fiji_disable_smc_cac(struct pp_hwmgr
*hwmgr
)
462 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
465 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
466 PHM_PlatformCaps_CAC
) && data
->cac_enabled
) {
467 int smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
468 (uint16_t)(PPSMC_MSG_DisableCac
));
469 PP_ASSERT_WITH_CODE((smc_result
== 0),
470 "Failed to disable CAC in SMC.", result
= -1);
472 data
->cac_enabled
= false;
477 int fiji_set_power_limit(struct pp_hwmgr
*hwmgr
, uint32_t n
)
479 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
481 if(data
->power_containment_features
&
482 POWERCONTAINMENT_FEATURE_PkgPwrLimit
)
483 return smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
484 PPSMC_MSG_PkgPwrSetLimit
, n
);
488 static int fiji_set_overdriver_target_tdp(struct pp_hwmgr
*pHwMgr
, uint32_t target_tdp
)
490 return smum_send_msg_to_smc_with_parameter(pHwMgr
->smumgr
,
491 PPSMC_MSG_OverDriveSetTargetTdp
, target_tdp
);
494 int fiji_enable_power_containment(struct pp_hwmgr
*hwmgr
)
496 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
497 struct phm_ppt_v1_information
*table_info
=
498 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
502 data
->power_containment_features
= 0;
503 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
504 PHM_PlatformCaps_PowerContainment
)) {
505 if (data
->enable_dte_feature
) {
506 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
507 (uint16_t)(PPSMC_MSG_EnableDTE
));
508 PP_ASSERT_WITH_CODE((0 == smc_result
),
509 "Failed to enable DTE in SMC.", result
= -1;);
511 data
->power_containment_features
|= POWERCONTAINMENT_FEATURE_DTE
;
514 if (data
->enable_tdc_limit_feature
) {
515 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
516 (uint16_t)(PPSMC_MSG_TDCLimitEnable
));
517 PP_ASSERT_WITH_CODE((0 == smc_result
),
518 "Failed to enable TDCLimit in SMC.", result
= -1;);
520 data
->power_containment_features
|=
521 POWERCONTAINMENT_FEATURE_TDCLimit
;
524 if (data
->enable_pkg_pwr_tracking_feature
) {
525 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
526 (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable
));
527 PP_ASSERT_WITH_CODE((0 == smc_result
),
528 "Failed to enable PkgPwrTracking in SMC.", result
= -1;);
529 if (0 == smc_result
) {
530 struct phm_cac_tdp_table
*cac_table
=
531 table_info
->cac_dtp_table
;
532 uint32_t default_limit
=
533 (uint32_t)(cac_table
->usMaximumPowerDeliveryLimit
* 256);
535 data
->power_containment_features
|=
536 POWERCONTAINMENT_FEATURE_PkgPwrLimit
;
538 if (fiji_set_power_limit(hwmgr
, default_limit
))
539 printk(KERN_ERR
"Failed to set Default Power Limit in SMC!");
546 int fiji_disable_power_containment(struct pp_hwmgr
*hwmgr
)
548 struct fiji_hwmgr
*data
= (struct fiji_hwmgr
*)(hwmgr
->backend
);
551 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
552 PHM_PlatformCaps_PowerContainment
) &&
553 data
->power_containment_features
) {
556 if (data
->power_containment_features
&
557 POWERCONTAINMENT_FEATURE_TDCLimit
) {
558 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
559 (uint16_t)(PPSMC_MSG_TDCLimitDisable
));
560 PP_ASSERT_WITH_CODE((smc_result
== 0),
561 "Failed to disable TDCLimit in SMC.",
562 result
= smc_result
);
565 if (data
->power_containment_features
&
566 POWERCONTAINMENT_FEATURE_DTE
) {
567 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
568 (uint16_t)(PPSMC_MSG_DisableDTE
));
569 PP_ASSERT_WITH_CODE((smc_result
== 0),
570 "Failed to disable DTE in SMC.",
571 result
= smc_result
);
574 if (data
->power_containment_features
&
575 POWERCONTAINMENT_FEATURE_PkgPwrLimit
) {
576 smc_result
= smum_send_msg_to_smc(hwmgr
->smumgr
,
577 (uint16_t)(PPSMC_MSG_PkgPwrLimitDisable
));
578 PP_ASSERT_WITH_CODE((smc_result
== 0),
579 "Failed to disable PkgPwrTracking in SMC.",
580 result
= smc_result
);
582 data
->power_containment_features
= 0;
588 int fiji_power_control_set_level(struct pp_hwmgr
*hwmgr
)
590 struct phm_ppt_v1_information
*table_info
=
591 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
592 struct phm_cac_tdp_table
*cac_table
= table_info
->cac_dtp_table
;
593 int adjust_percent
, target_tdp
;
596 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
597 PHM_PlatformCaps_PowerContainment
)) {
598 /* adjustment percentage has already been validated */
599 adjust_percent
= hwmgr
->platform_descriptor
.TDPAdjustmentPolarity
?
600 hwmgr
->platform_descriptor
.TDPAdjustment
:
601 (-1 * hwmgr
->platform_descriptor
.TDPAdjustment
);
602 /* SMC requested that target_tdp to be 7 bit fraction in DPM table
603 * but message to be 8 bit fraction for messages
605 target_tdp
= ((100 + adjust_percent
) * (int)(cac_table
->usTDP
* 256)) / 100;
606 result
= fiji_set_overdriver_target_tdp(hwmgr
, (uint32_t)target_tdp
);