Commit | Line | Data |
---|---|---|
aabcb7c1 EH |
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 | 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_PowerContainment); | |
61 | phm_cap_unset(hwmgr->platform_descriptor.platformCaps, | |
62 | PHM_PlatformCaps_CAC); | |
63 | phm_cap_unset(hwmgr->platform_descriptor.platformCaps, | |
64 | PHM_PlatformCaps_SQRamping); | |
65 | phm_cap_unset(hwmgr->platform_descriptor.platformCaps, | |
66 | PHM_PlatformCaps_DBRamping); | |
67 | phm_cap_unset(hwmgr->platform_descriptor.platformCaps, | |
68 | PHM_PlatformCaps_TDRamping); | |
69 | phm_cap_unset(hwmgr->platform_descriptor.platformCaps, | |
70 | PHM_PlatformCaps_TCPRamping); | |
71 | ||
72 | fiji_hwmgr->dte_tj_offset = tmp; | |
73 | ||
74 | if (!tmp) { | |
75 | phm_cap_set(hwmgr->platform_descriptor.platformCaps, | |
76 | PHM_PlatformCaps_PowerContainment); | |
77 | ||
78 | phm_cap_set(hwmgr->platform_descriptor.platformCaps, | |
79 | PHM_PlatformCaps_CAC); | |
80 | ||
81 | fiji_hwmgr->fast_watermark_threshold = 100; | |
82 | ||
83 | tmp = 1; | |
84 | fiji_hwmgr->enable_dte_feature = tmp ? false : true; | |
85 | fiji_hwmgr->enable_tdc_limit_feature = tmp ? true : false; | |
86 | fiji_hwmgr->enable_pkg_pwr_tracking_feature = tmp ? true : false; | |
87 | } | |
88 | } | |
89 | ||
90 | /* PPGen has the gain setting generated in x * 100 unit | |
91 | * This function is to convert the unit to x * 4096(0x1000) unit. | |
92 | * This is the unit expected by SMC firmware | |
93 | */ | |
94 | static uint16_t scale_fan_gain_settings(uint16_t raw_setting) | |
95 | { | |
75ac63db RZ |
96 | uint32_t tmp; |
97 | tmp = raw_setting * 4096 / 100; | |
98 | return (uint16_t)tmp; | |
aabcb7c1 EH |
99 | } |
100 | ||
101 | static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda) | |
102 | { | |
103 | switch (line) { | |
104 | case Fiji_I2CLineID_DDC1 : | |
105 | *scl = Fiji_I2C_DDC1CLK; | |
106 | *sda = Fiji_I2C_DDC1DATA; | |
107 | break; | |
108 | case Fiji_I2CLineID_DDC2 : | |
109 | *scl = Fiji_I2C_DDC2CLK; | |
110 | *sda = Fiji_I2C_DDC2DATA; | |
111 | break; | |
112 | case Fiji_I2CLineID_DDC3 : | |
113 | *scl = Fiji_I2C_DDC3CLK; | |
114 | *sda = Fiji_I2C_DDC3DATA; | |
115 | break; | |
116 | case Fiji_I2CLineID_DDC4 : | |
117 | *scl = Fiji_I2C_DDC4CLK; | |
118 | *sda = Fiji_I2C_DDC4DATA; | |
119 | break; | |
120 | case Fiji_I2CLineID_DDC5 : | |
121 | *scl = Fiji_I2C_DDC5CLK; | |
122 | *sda = Fiji_I2C_DDC5DATA; | |
123 | break; | |
124 | case Fiji_I2CLineID_DDC6 : | |
125 | *scl = Fiji_I2C_DDC6CLK; | |
126 | *sda = Fiji_I2C_DDC6DATA; | |
127 | break; | |
128 | case Fiji_I2CLineID_SCLSDA : | |
129 | *scl = Fiji_I2C_SCL; | |
130 | *sda = Fiji_I2C_SDA; | |
131 | break; | |
132 | case Fiji_I2CLineID_DDCVGA : | |
133 | *scl = Fiji_I2C_DDCVGACLK; | |
134 | *sda = Fiji_I2C_DDCVGADATA; | |
135 | break; | |
136 | default: | |
137 | *scl = 0; | |
138 | *sda = 0; | |
139 | break; | |
140 | } | |
141 | } | |
142 | ||
143 | int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) | |
144 | { | |
145 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
146 | struct fiji_pt_defaults *defaults = data->power_tune_defaults; | |
147 | SMU73_Discrete_DpmTable *dpm_table = &(data->smc_state_table); | |
148 | struct phm_ppt_v1_information *table_info = | |
149 | (struct phm_ppt_v1_information *)(hwmgr->pptable); | |
150 | struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; | |
151 | struct pp_advance_fan_control_parameters *fan_table= | |
152 | &hwmgr->thermal_controller.advanceFanControlParameters; | |
153 | uint8_t uc_scl, uc_sda; | |
154 | ||
155 | /* TDP number of fraction bits are changed from 8 to 7 for Fiji | |
156 | * as requested by SMC team | |
157 | */ | |
158 | dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( | |
159 | (uint16_t)(cac_dtp_table->usTDP * 128)); | |
160 | dpm_table->TargetTdp = PP_HOST_TO_SMC_US( | |
161 | (uint16_t)(cac_dtp_table->usTDP * 128)); | |
162 | ||
163 | PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, | |
164 | "Target Operating Temp is out of Range!",); | |
165 | ||
166 | dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); | |
167 | dpm_table->GpuTjHyst = 8; | |
168 | ||
169 | dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase; | |
170 | ||
171 | /* The following are for new Fiji Multi-input fan/thermal control */ | |
172 | dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( | |
173 | cac_dtp_table->usTargetOperatingTemp * 256); | |
174 | dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( | |
175 | cac_dtp_table->usTemperatureLimitHotspot * 256); | |
176 | dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US( | |
177 | cac_dtp_table->usTemperatureLimitLiquid1 * 256); | |
178 | dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US( | |
179 | cac_dtp_table->usTemperatureLimitLiquid2 * 256); | |
180 | dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US( | |
181 | cac_dtp_table->usTemperatureLimitVrVddc * 256); | |
182 | dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US( | |
183 | cac_dtp_table->usTemperatureLimitVrMvdd * 256); | |
184 | dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US( | |
185 | cac_dtp_table->usTemperatureLimitPlx * 256); | |
186 | ||
187 | dpm_table->FanGainEdge = PP_HOST_TO_SMC_US( | |
188 | scale_fan_gain_settings(fan_table->usFanGainEdge)); | |
189 | dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US( | |
190 | scale_fan_gain_settings(fan_table->usFanGainHotspot)); | |
191 | dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US( | |
192 | scale_fan_gain_settings(fan_table->usFanGainLiquid)); | |
193 | dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US( | |
194 | scale_fan_gain_settings(fan_table->usFanGainVrVddc)); | |
195 | dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US( | |
196 | scale_fan_gain_settings(fan_table->usFanGainVrMvdd)); | |
197 | dpm_table->FanGainPlx = PP_HOST_TO_SMC_US( | |
198 | scale_fan_gain_settings(fan_table->usFanGainPlx)); | |
199 | dpm_table->FanGainHbm = PP_HOST_TO_SMC_US( | |
200 | scale_fan_gain_settings(fan_table->usFanGainHbm)); | |
201 | ||
202 | dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address; | |
203 | dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address; | |
204 | dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address; | |
205 | dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address; | |
206 | ||
207 | get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda); | |
208 | dpm_table->Liquid_I2C_LineSCL = uc_scl; | |
209 | dpm_table->Liquid_I2C_LineSDA = uc_sda; | |
210 | ||
211 | get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda); | |
212 | dpm_table->Vr_I2C_LineSCL = uc_scl; | |
213 | dpm_table->Vr_I2C_LineSDA = uc_sda; | |
214 | ||
215 | get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda); | |
216 | dpm_table->Plx_I2C_LineSCL = uc_scl; | |
217 | dpm_table->Plx_I2C_LineSDA = uc_sda; | |
218 | ||
219 | return 0; | |
220 | } | |
221 | ||
222 | static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) | |
223 | { | |
224 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
225 | struct fiji_pt_defaults *defaults = data->power_tune_defaults; | |
226 | ||
227 | data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; | |
228 | data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; | |
229 | data->power_tune_table.SviLoadLineTrimVddC = 3; | |
230 | data->power_tune_table.SviLoadLineOffsetVddC = 0; | |
231 | ||
232 | return 0; | |
233 | } | |
234 | ||
235 | static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) | |
236 | { | |
237 | uint16_t tdc_limit; | |
238 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
239 | struct phm_ppt_v1_information *table_info = | |
240 | (struct phm_ppt_v1_information *)(hwmgr->pptable); | |
241 | struct fiji_pt_defaults *defaults = data->power_tune_defaults; | |
242 | ||
243 | /* TDC number of fraction bits are changed from 8 to 7 | |
244 | * for Fiji as requested by SMC team | |
245 | */ | |
246 | tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); | |
247 | data->power_tune_table.TDC_VDDC_PkgLimit = | |
248 | CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); | |
249 | data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = | |
250 | defaults->TDC_VDDC_ThrottleReleaseLimitPerc; | |
251 | data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; | |
252 | ||
253 | return 0; | |
254 | } | |
255 | ||
256 | static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) | |
257 | { | |
258 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
259 | struct fiji_pt_defaults *defaults = data->power_tune_defaults; | |
260 | uint32_t temp; | |
261 | ||
262 | if (fiji_read_smc_sram_dword(hwmgr->smumgr, | |
263 | fuse_table_offset + | |
264 | offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl), | |
265 | (uint32_t *)&temp, data->sram_end)) | |
266 | PP_ASSERT_WITH_CODE(false, | |
267 | "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", | |
268 | return -EINVAL); | |
269 | else { | |
270 | data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; | |
271 | data->power_tune_table.LPMLTemperatureMin = | |
272 | (uint8_t)((temp >> 16) & 0xff); | |
273 | data->power_tune_table.LPMLTemperatureMax = | |
274 | (uint8_t)((temp >> 8) & 0xff); | |
275 | data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); | |
276 | } | |
277 | return 0; | |
278 | } | |
279 | ||
280 | static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) | |
281 | { | |
282 | int i; | |
283 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
284 | ||
285 | /* Currently not used. Set all to zero. */ | |
286 | for (i = 0; i < 16; i++) | |
287 | data->power_tune_table.LPMLTemperatureScaler[i] = 0; | |
288 | ||
289 | return 0; | |
290 | } | |
291 | ||
292 | static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) | |
293 | { | |
294 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
295 | ||
296 | if( (hwmgr->thermal_controller.advanceFanControlParameters. | |
297 | usFanOutputSensitivity & (1 << 15)) || | |
298 | 0 == hwmgr->thermal_controller.advanceFanControlParameters. | |
299 | usFanOutputSensitivity ) | |
300 | hwmgr->thermal_controller.advanceFanControlParameters. | |
301 | usFanOutputSensitivity = hwmgr->thermal_controller. | |
302 | advanceFanControlParameters.usDefaultFanOutputSensitivity; | |
303 | ||
304 | data->power_tune_table.FuzzyFan_PwmSetDelta = | |
305 | PP_HOST_TO_SMC_US(hwmgr->thermal_controller. | |
306 | advanceFanControlParameters.usFanOutputSensitivity); | |
307 | return 0; | |
308 | } | |
309 | ||
310 | static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) | |
311 | { | |
312 | int i; | |
313 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
314 | ||
315 | /* Currently not used. Set all to zero. */ | |
316 | for (i = 0; i < 16; i++) | |
317 | data->power_tune_table.GnbLPML[i] = 0; | |
318 | ||
319 | return 0; | |
320 | } | |
321 | ||
322 | static int fiji_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr) | |
323 | { | |
324 | /* int i, min, max; | |
325 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
326 | uint8_t * pHiVID = data->power_tune_table.BapmVddCVidHiSidd; | |
327 | uint8_t * pLoVID = data->power_tune_table.BapmVddCVidLoSidd; | |
328 | ||
329 | min = max = pHiVID[0]; | |
330 | for (i = 0; i < 8; i++) { | |
331 | if (0 != pHiVID[i]) { | |
332 | if (min > pHiVID[i]) | |
333 | min = pHiVID[i]; | |
334 | if (max < pHiVID[i]) | |
335 | max = pHiVID[i]; | |
336 | } | |
337 | ||
338 | if (0 != pLoVID[i]) { | |
339 | if (min > pLoVID[i]) | |
340 | min = pLoVID[i]; | |
341 | if (max < pLoVID[i]) | |
342 | max = pLoVID[i]; | |
343 | } | |
344 | } | |
345 | ||
346 | PP_ASSERT_WITH_CODE((0 != min) && (0 != max), "BapmVddcVidSidd table does not exist!", return int_Failed); | |
347 | data->power_tune_table.GnbLPMLMaxVid = (uint8_t)max; | |
348 | data->power_tune_table.GnbLPMLMinVid = (uint8_t)min; | |
349 | */ | |
350 | return 0; | |
351 | } | |
352 | ||
353 | static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) | |
354 | { | |
355 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
356 | struct phm_ppt_v1_information *table_info = | |
357 | (struct phm_ppt_v1_information *)(hwmgr->pptable); | |
358 | uint16_t HiSidd = data->power_tune_table.BapmVddCBaseLeakageHiSidd; | |
359 | uint16_t LoSidd = data->power_tune_table.BapmVddCBaseLeakageLoSidd; | |
360 | struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; | |
361 | ||
362 | HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); | |
363 | LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); | |
364 | ||
365 | data->power_tune_table.BapmVddCBaseLeakageHiSidd = | |
366 | CONVERT_FROM_HOST_TO_SMC_US(HiSidd); | |
367 | data->power_tune_table.BapmVddCBaseLeakageLoSidd = | |
368 | CONVERT_FROM_HOST_TO_SMC_US(LoSidd); | |
369 | ||
370 | return 0; | |
371 | } | |
372 | ||
373 | int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) | |
374 | { | |
375 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
376 | uint32_t pm_fuse_table_offset; | |
377 | ||
378 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
379 | PHM_PlatformCaps_PowerContainment)) { | |
380 | if (fiji_read_smc_sram_dword(hwmgr->smumgr, | |
381 | SMU7_FIRMWARE_HEADER_LOCATION + | |
382 | offsetof(SMU73_Firmware_Header, PmFuseTable), | |
383 | &pm_fuse_table_offset, data->sram_end)) | |
384 | PP_ASSERT_WITH_CODE(false, | |
385 | "Attempt to get pm_fuse_table_offset Failed!", | |
386 | return -EINVAL); | |
387 | ||
388 | /* DW6 */ | |
389 | if (fiji_populate_svi_load_line(hwmgr)) | |
390 | PP_ASSERT_WITH_CODE(false, | |
391 | "Attempt to populate SviLoadLine Failed!", | |
392 | return -EINVAL); | |
393 | /* DW7 */ | |
394 | if (fiji_populate_tdc_limit(hwmgr)) | |
395 | PP_ASSERT_WITH_CODE(false, | |
396 | "Attempt to populate TDCLimit Failed!", return -EINVAL); | |
397 | /* DW8 */ | |
398 | if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset)) | |
399 | PP_ASSERT_WITH_CODE(false, | |
400 | "Attempt to populate TdcWaterfallCtl, " | |
401 | "LPMLTemperature Min and Max Failed!", | |
402 | return -EINVAL); | |
403 | ||
404 | /* DW9-DW12 */ | |
405 | if (0 != fiji_populate_temperature_scaler(hwmgr)) | |
406 | PP_ASSERT_WITH_CODE(false, | |
407 | "Attempt to populate LPMLTemperatureScaler Failed!", | |
408 | return -EINVAL); | |
409 | ||
410 | /* DW13-DW14 */ | |
411 | if(fiji_populate_fuzzy_fan(hwmgr)) | |
412 | PP_ASSERT_WITH_CODE(false, | |
413 | "Attempt to populate Fuzzy Fan Control parameters Failed!", | |
414 | return -EINVAL); | |
415 | ||
416 | /* DW15-DW18 */ | |
417 | if (fiji_populate_gnb_lpml(hwmgr)) | |
418 | PP_ASSERT_WITH_CODE(false, | |
419 | "Attempt to populate GnbLPML Failed!", | |
420 | return -EINVAL); | |
421 | ||
422 | /* DW19 */ | |
423 | if (fiji_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr)) | |
424 | PP_ASSERT_WITH_CODE(false, | |
425 | "Attempt to populate GnbLPML Min and Max Vid Failed!", | |
426 | return -EINVAL); | |
427 | ||
428 | /* DW20 */ | |
429 | if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr)) | |
430 | PP_ASSERT_WITH_CODE(false, | |
431 | "Attempt to populate BapmVddCBaseLeakage Hi and Lo " | |
432 | "Sidd Failed!", return -EINVAL); | |
433 | ||
434 | if (fiji_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset, | |
435 | (uint8_t *)&data->power_tune_table, | |
436 | sizeof(struct SMU73_Discrete_PmFuses), data->sram_end)) | |
437 | PP_ASSERT_WITH_CODE(false, | |
438 | "Attempt to download PmFuseTable Failed!", | |
439 | return -EINVAL); | |
440 | } | |
441 | return 0; | |
442 | } | |
443 | ||
444 | int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr) | |
445 | { | |
446 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
447 | int result = 0; | |
448 | ||
449 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
450 | PHM_PlatformCaps_CAC)) { | |
451 | int smc_result; | |
452 | smc_result = smum_send_msg_to_smc(hwmgr->smumgr, | |
453 | (uint16_t)(PPSMC_MSG_EnableCac)); | |
454 | PP_ASSERT_WITH_CODE((0 == smc_result), | |
455 | "Failed to enable CAC in SMC.", result = -1); | |
456 | ||
457 | data->cac_enabled = (0 == smc_result) ? true : false; | |
458 | } | |
459 | return result; | |
460 | } | |
461 | ||
462 | int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) | |
463 | { | |
464 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
465 | ||
466 | if(data->power_containment_features & | |
467 | POWERCONTAINMENT_FEATURE_PkgPwrLimit) | |
468 | return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, | |
469 | PPSMC_MSG_PkgPwrSetLimit, n); | |
470 | return 0; | |
471 | } | |
472 | ||
473 | static int fiji_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp) | |
474 | { | |
475 | return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr, | |
476 | PPSMC_MSG_OverDriveSetTargetTdp, target_tdp); | |
477 | } | |
478 | ||
479 | int fiji_enable_power_containment(struct pp_hwmgr *hwmgr) | |
480 | { | |
481 | struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); | |
482 | struct phm_ppt_v1_information *table_info = | |
483 | (struct phm_ppt_v1_information *)(hwmgr->pptable); | |
484 | int smc_result; | |
485 | int result = 0; | |
486 | ||
487 | data->power_containment_features = 0; | |
488 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
489 | PHM_PlatformCaps_PowerContainment)) { | |
490 | if (data->enable_dte_feature) { | |
491 | smc_result = smum_send_msg_to_smc(hwmgr->smumgr, | |
492 | (uint16_t)(PPSMC_MSG_EnableDTE)); | |
493 | PP_ASSERT_WITH_CODE((0 == smc_result), | |
494 | "Failed to enable DTE in SMC.", result = -1;); | |
495 | if (0 == smc_result) | |
496 | data->power_containment_features |= POWERCONTAINMENT_FEATURE_DTE; | |
497 | } | |
498 | ||
499 | if (data->enable_tdc_limit_feature) { | |
500 | smc_result = smum_send_msg_to_smc(hwmgr->smumgr, | |
501 | (uint16_t)(PPSMC_MSG_TDCLimitEnable)); | |
502 | PP_ASSERT_WITH_CODE((0 == smc_result), | |
503 | "Failed to enable TDCLimit in SMC.", result = -1;); | |
504 | if (0 == smc_result) | |
505 | data->power_containment_features |= | |
506 | POWERCONTAINMENT_FEATURE_TDCLimit; | |
507 | } | |
508 | ||
509 | if (data->enable_pkg_pwr_tracking_feature) { | |
510 | smc_result = smum_send_msg_to_smc(hwmgr->smumgr, | |
511 | (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable)); | |
512 | PP_ASSERT_WITH_CODE((0 == smc_result), | |
513 | "Failed to enable PkgPwrTracking in SMC.", result = -1;); | |
514 | if (0 == smc_result) { | |
515 | struct phm_cac_tdp_table *cac_table = | |
516 | table_info->cac_dtp_table; | |
517 | uint32_t default_limit = | |
518 | (uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256); | |
519 | ||
520 | data->power_containment_features |= | |
521 | POWERCONTAINMENT_FEATURE_PkgPwrLimit; | |
522 | ||
523 | if (fiji_set_power_limit(hwmgr, default_limit)) | |
524 | printk(KERN_ERR "Failed to set Default Power Limit in SMC!"); | |
525 | } | |
526 | } | |
527 | } | |
528 | return result; | |
529 | } | |
530 | ||
531 | int fiji_power_control_set_level(struct pp_hwmgr *hwmgr) | |
532 | { | |
533 | struct phm_ppt_v1_information *table_info = | |
534 | (struct phm_ppt_v1_information *)(hwmgr->pptable); | |
535 | struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; | |
536 | int adjust_percent, target_tdp; | |
537 | int result = 0; | |
538 | ||
539 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
540 | PHM_PlatformCaps_PowerContainment)) { | |
541 | /* adjustment percentage has already been validated */ | |
542 | adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ? | |
543 | hwmgr->platform_descriptor.TDPAdjustment : | |
544 | (-1 * hwmgr->platform_descriptor.TDPAdjustment); | |
545 | /* SMC requested that target_tdp to be 7 bit fraction in DPM table | |
546 | * but message to be 8 bit fraction for messages | |
547 | */ | |
548 | target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100; | |
75ac63db RZ |
549 | result = fiji_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp); |
550 | } | |
aabcb7c1 | 551 | |
75ac63db | 552 | return result; |
aabcb7c1 | 553 | } |