Merge tag 'drm-vc4-next-2016-08-29' of https://github.com/anholt/linux into drm-next
[deliverable/linux.git] / drivers / gpu / drm / amd / powerplay / hwmgr / fiji_powertune.c
1 /*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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.
21 *
22 */
23
24 #include "hwmgr.h"
25 #include "smumgr.h"
26 #include "fiji_hwmgr.h"
27 #include "fiji_powertune.h"
28 #include "fiji_smumgr.h"
29 #include "smu73_discrete.h"
30 #include "pp_debug.h"
31
32 #define VOLTAGE_SCALE 4
33 #define POWERTUNE_DEFAULT_SET_MAX 1
34
35 const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
36 /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */
37 {1, 0xF, 0xFD,
38 /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */
39 0x19, 5, 45}
40 };
41
42 void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
43 {
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);
47 uint32_t tmp = 0;
48
49 if(table_info &&
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];
55 else
56 fiji_hwmgr->power_tune_defaults = &fiji_power_tune_data_set_array[0];
57
58 /* Assume disabled */
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);
69
70 fiji_hwmgr->dte_tj_offset = tmp;
71
72 if (!tmp) {
73 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
74 PHM_PlatformCaps_CAC);
75
76 fiji_hwmgr->fast_watermark_threshold = 100;
77
78 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
79 PHM_PlatformCaps_PowerContainment)) {
80 tmp = 1;
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;
84 }
85 }
86 }
87
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
91 */
92 static uint16_t scale_fan_gain_settings(uint16_t raw_setting)
93 {
94 uint32_t tmp;
95 tmp = raw_setting * 4096 / 100;
96 return (uint16_t)tmp;
97 }
98
99 static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda)
100 {
101 switch (line) {
102 case Fiji_I2CLineID_DDC1 :
103 *scl = Fiji_I2C_DDC1CLK;
104 *sda = Fiji_I2C_DDC1DATA;
105 break;
106 case Fiji_I2CLineID_DDC2 :
107 *scl = Fiji_I2C_DDC2CLK;
108 *sda = Fiji_I2C_DDC2DATA;
109 break;
110 case Fiji_I2CLineID_DDC3 :
111 *scl = Fiji_I2C_DDC3CLK;
112 *sda = Fiji_I2C_DDC3DATA;
113 break;
114 case Fiji_I2CLineID_DDC4 :
115 *scl = Fiji_I2C_DDC4CLK;
116 *sda = Fiji_I2C_DDC4DATA;
117 break;
118 case Fiji_I2CLineID_DDC5 :
119 *scl = Fiji_I2C_DDC5CLK;
120 *sda = Fiji_I2C_DDC5DATA;
121 break;
122 case Fiji_I2CLineID_DDC6 :
123 *scl = Fiji_I2C_DDC6CLK;
124 *sda = Fiji_I2C_DDC6DATA;
125 break;
126 case Fiji_I2CLineID_SCLSDA :
127 *scl = Fiji_I2C_SCL;
128 *sda = Fiji_I2C_SDA;
129 break;
130 case Fiji_I2CLineID_DDCVGA :
131 *scl = Fiji_I2C_DDCVGACLK;
132 *sda = Fiji_I2C_DDCVGADATA;
133 break;
134 default:
135 *scl = 0;
136 *sda = 0;
137 break;
138 }
139 }
140
141 int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
142 {
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;
152
153 /* TDP number of fraction bits are changed from 8 to 7 for Fiji
154 * as requested by SMC team
155 */
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));
160
161 PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
162 "Target Operating Temp is out of Range!",);
163
164 dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp);
165 dpm_table->GpuTjHyst = 8;
166
167 dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase;
168
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);
184
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));
199
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;
204
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;
208
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;
212
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;
216
217 return 0;
218 }
219
220 static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr)
221 {
222 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
223 const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
224
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;
229
230 return 0;
231 }
232
233 static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr)
234 {
235 uint16_t tdc_limit;
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;
240
241 /* TDC number of fraction bits are changed from 8 to 7
242 * for Fiji as requested by SMC team
243 */
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;
250
251 return 0;
252 }
253
254 static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
255 {
256 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
257 const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
258 uint32_t temp;
259
260 if (fiji_read_smc_sram_dword(hwmgr->smumgr,
261 fuse_table_offset +
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!",
266 return -EINVAL);
267 else {
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);
274 }
275 return 0;
276 }
277
278 static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
279 {
280 int i;
281 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
282
283 /* Currently not used. Set all to zero. */
284 for (i = 0; i < 16; i++)
285 data->power_tune_table.LPMLTemperatureScaler[i] = 0;
286
287 return 0;
288 }
289
290 static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
291 {
292 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
293
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;
301
302 data->power_tune_table.FuzzyFan_PwmSetDelta =
303 PP_HOST_TO_SMC_US(hwmgr->thermal_controller.
304 advanceFanControlParameters.usFanOutputSensitivity);
305 return 0;
306 }
307
308 static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
309 {
310 int i;
311 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
312
313 /* Currently not used. Set all to zero. */
314 for (i = 0; i < 16; i++)
315 data->power_tune_table.GnbLPML[i] = 0;
316
317 return 0;
318 }
319
320 static int fiji_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr)
321 {
322 /* int i, min, max;
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;
326
327 min = max = pHiVID[0];
328 for (i = 0; i < 8; i++) {
329 if (0 != pHiVID[i]) {
330 if (min > pHiVID[i])
331 min = pHiVID[i];
332 if (max < pHiVID[i])
333 max = pHiVID[i];
334 }
335
336 if (0 != pLoVID[i]) {
337 if (min > pLoVID[i])
338 min = pLoVID[i];
339 if (max < pLoVID[i])
340 max = pLoVID[i];
341 }
342 }
343
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;
347 */
348 return 0;
349 }
350
351 static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
352 {
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;
359
360 HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
361 LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
362
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);
367
368 return 0;
369 }
370
371 int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr)
372 {
373 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
374 uint32_t pm_fuse_table_offset;
375
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!",
384 return -EINVAL);
385
386 /* DW6 */
387 if (fiji_populate_svi_load_line(hwmgr))
388 PP_ASSERT_WITH_CODE(false,
389 "Attempt to populate SviLoadLine Failed!",
390 return -EINVAL);
391 /* DW7 */
392 if (fiji_populate_tdc_limit(hwmgr))
393 PP_ASSERT_WITH_CODE(false,
394 "Attempt to populate TDCLimit Failed!", return -EINVAL);
395 /* DW8 */
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!",
400 return -EINVAL);
401
402 /* DW9-DW12 */
403 if (0 != fiji_populate_temperature_scaler(hwmgr))
404 PP_ASSERT_WITH_CODE(false,
405 "Attempt to populate LPMLTemperatureScaler Failed!",
406 return -EINVAL);
407
408 /* DW13-DW14 */
409 if(fiji_populate_fuzzy_fan(hwmgr))
410 PP_ASSERT_WITH_CODE(false,
411 "Attempt to populate Fuzzy Fan Control parameters Failed!",
412 return -EINVAL);
413
414 /* DW15-DW18 */
415 if (fiji_populate_gnb_lpml(hwmgr))
416 PP_ASSERT_WITH_CODE(false,
417 "Attempt to populate GnbLPML Failed!",
418 return -EINVAL);
419
420 /* DW19 */
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!",
424 return -EINVAL);
425
426 /* DW20 */
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);
431
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!",
437 return -EINVAL);
438 }
439 return 0;
440 }
441
442 int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr)
443 {
444 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
445 int result = 0;
446
447 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
448 PHM_PlatformCaps_CAC)) {
449 int smc_result;
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);
454
455 data->cac_enabled = (0 == smc_result) ? true : false;
456 }
457 return result;
458 }
459
460 int fiji_disable_smc_cac(struct pp_hwmgr *hwmgr)
461 {
462 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
463 int result = 0;
464
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);
471
472 data->cac_enabled = false;
473 }
474 return result;
475 }
476
477 int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
478 {
479 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
480
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);
485 return 0;
486 }
487
488 static int fiji_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp)
489 {
490 return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr,
491 PPSMC_MSG_OverDriveSetTargetTdp, target_tdp);
492 }
493
494 int fiji_enable_power_containment(struct pp_hwmgr *hwmgr)
495 {
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);
499 int smc_result;
500 int result = 0;
501
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;);
510 if (0 == smc_result)
511 data->power_containment_features |= POWERCONTAINMENT_FEATURE_DTE;
512 }
513
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;);
519 if (0 == smc_result)
520 data->power_containment_features |=
521 POWERCONTAINMENT_FEATURE_TDCLimit;
522 }
523
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);
534
535 data->power_containment_features |=
536 POWERCONTAINMENT_FEATURE_PkgPwrLimit;
537
538 if (fiji_set_power_limit(hwmgr, default_limit))
539 printk(KERN_ERR "Failed to set Default Power Limit in SMC!");
540 }
541 }
542 }
543 return result;
544 }
545
546 int fiji_disable_power_containment(struct pp_hwmgr *hwmgr)
547 {
548 struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
549 int result = 0;
550
551 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
552 PHM_PlatformCaps_PowerContainment) &&
553 data->power_containment_features) {
554 int smc_result;
555
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);
563 }
564
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);
572 }
573
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);
581 }
582 data->power_containment_features = 0;
583 }
584
585 return result;
586 }
587
588 int fiji_power_control_set_level(struct pp_hwmgr *hwmgr)
589 {
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;
594 int result = 0;
595
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
604 */
605 target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100;
606 result = fiji_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp);
607 }
608
609 return result;
610 }
This page took 0.043898 seconds and 6 git commands to generate.