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 | ||
f498d9ed | 35 | const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { |
aabcb7c1 EH |
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 */ | |
aabcb7c1 EH |
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) { | |
aabcb7c1 EH |
73 | phm_cap_set(hwmgr->platform_descriptor.platformCaps, |
74 | PHM_PlatformCaps_CAC); | |
75 | ||
76 | fiji_hwmgr->fast_watermark_threshold = 100; | |
77 | ||
af223dfa RZ |
78 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, |
79 | PHM_PlatformCaps_PowerContainment)) { | |
6bb6b297 HR |
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 | } | |
aabcb7c1 EH |
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 | { | |
75ac63db RZ |
94 | uint32_t tmp; |
95 | tmp = raw_setting * 4096 / 100; | |
96 | return (uint16_t)tmp; | |
aabcb7c1 EH |
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); | |
f498d9ed | 144 | const struct fiji_pt_defaults *defaults = data->power_tune_defaults; |
aabcb7c1 EH |
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); | |
f498d9ed | 223 | const struct fiji_pt_defaults *defaults = data->power_tune_defaults; |
aabcb7c1 EH |
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); | |
f498d9ed | 239 | const struct fiji_pt_defaults *defaults = data->power_tune_defaults; |
aabcb7c1 EH |
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); | |
f498d9ed | 257 | const struct fiji_pt_defaults *defaults = data->power_tune_defaults; |
aabcb7c1 EH |
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 | ||
55d74fc9 EH |
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 | ||
aabcb7c1 EH |
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 | ||
55d74fc9 EH |
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 | ||
aabcb7c1 EH |
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; | |
75ac63db RZ |
606 | result = fiji_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp); |
607 | } | |
aabcb7c1 | 608 | |
75ac63db | 609 | return result; |
aabcb7c1 | 610 | } |