]>
Commit | Line | Data |
---|---|---|
599a7e9f RZ |
1 | /* |
2 | * Copyright 2016 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 <asm/div64.h> | |
25 | #include "smu7_thermal.h" | |
26 | #include "smu7_hwmgr.h" | |
27 | #include "smu7_common.h" | |
28 | ||
29 | int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, | |
30 | struct phm_fan_speed_info *fan_speed_info) | |
31 | { | |
32 | if (hwmgr->thermal_controller.fanInfo.bNoFan) | |
91efdb27 | 33 | return -ENODEV; |
599a7e9f RZ |
34 | |
35 | fan_speed_info->supports_percent_read = true; | |
36 | fan_speed_info->supports_percent_write = true; | |
37 | fan_speed_info->min_percent = 0; | |
38 | fan_speed_info->max_percent = 100; | |
39 | ||
40 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
41 | PHM_PlatformCaps_FanSpeedInTableIsRPM) && | |
42 | hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { | |
43 | fan_speed_info->supports_rpm_read = true; | |
44 | fan_speed_info->supports_rpm_write = true; | |
45 | fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM; | |
46 | fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM; | |
47 | } else { | |
48 | fan_speed_info->min_rpm = 0; | |
49 | fan_speed_info->max_rpm = 0; | |
50 | } | |
51 | ||
52 | return 0; | |
53 | } | |
54 | ||
55 | int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, | |
56 | uint32_t *speed) | |
57 | { | |
58 | uint32_t duty100; | |
59 | uint32_t duty; | |
60 | uint64_t tmp64; | |
61 | ||
62 | if (hwmgr->thermal_controller.fanInfo.bNoFan) | |
91efdb27 | 63 | return -ENODEV; |
599a7e9f RZ |
64 | |
65 | duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
66 | CG_FDO_CTRL1, FMAX_DUTY100); | |
67 | duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
68 | CG_THERMAL_STATUS, FDO_PWM_DUTY); | |
69 | ||
70 | if (duty100 == 0) | |
71 | return -EINVAL; | |
72 | ||
73 | ||
74 | tmp64 = (uint64_t)duty * 100; | |
75 | do_div(tmp64, duty100); | |
76 | *speed = (uint32_t)tmp64; | |
77 | ||
78 | if (*speed > 100) | |
79 | *speed = 100; | |
80 | ||
81 | return 0; | |
82 | } | |
83 | ||
84 | int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) | |
85 | { | |
86 | uint32_t tach_period; | |
87 | uint32_t crystal_clock_freq; | |
88 | ||
89 | if (hwmgr->thermal_controller.fanInfo.bNoFan || | |
90 | (hwmgr->thermal_controller.fanInfo. | |
91 | ucTachometerPulsesPerRevolution == 0)) | |
91efdb27 | 92 | return -ENODEV; |
599a7e9f RZ |
93 | |
94 | tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
95 | CG_TACH_STATUS, TACH_PERIOD); | |
96 | ||
97 | if (tach_period == 0) | |
98 | return -EINVAL; | |
99 | ||
100 | crystal_clock_freq = smu7_get_xclk(hwmgr); | |
101 | ||
102 | *speed = 60 * crystal_clock_freq * 10000 / tach_period; | |
103 | ||
104 | return 0; | |
105 | } | |
106 | ||
107 | /** | |
108 | * Set Fan Speed Control to static mode, so that the user can decide what speed to use. | |
109 | * @param hwmgr the address of the powerplay hardware manager. | |
110 | * mode the fan control mode, 0 default, 1 by percent, 5, by RPM | |
111 | * @exception Should always succeed. | |
112 | */ | |
113 | int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) | |
114 | { | |
115 | ||
116 | if (hwmgr->fan_ctrl_is_in_default_mode) { | |
117 | hwmgr->fan_ctrl_default_mode = | |
118 | PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
119 | CG_FDO_CTRL2, FDO_PWM_MODE); | |
120 | hwmgr->tmin = | |
121 | PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
122 | CG_FDO_CTRL2, TMIN); | |
123 | hwmgr->fan_ctrl_is_in_default_mode = false; | |
124 | } | |
125 | ||
126 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
127 | CG_FDO_CTRL2, TMIN, 0); | |
128 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
129 | CG_FDO_CTRL2, FDO_PWM_MODE, mode); | |
130 | ||
131 | return 0; | |
132 | } | |
133 | ||
134 | /** | |
135 | * Reset Fan Speed Control to default mode. | |
136 | * @param hwmgr the address of the powerplay hardware manager. | |
137 | * @exception Should always succeed. | |
138 | */ | |
139 | int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) | |
140 | { | |
141 | if (!hwmgr->fan_ctrl_is_in_default_mode) { | |
142 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
143 | CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode); | |
144 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
145 | CG_FDO_CTRL2, TMIN, hwmgr->tmin); | |
146 | hwmgr->fan_ctrl_is_in_default_mode = true; | |
147 | } | |
148 | ||
149 | return 0; | |
150 | } | |
151 | ||
152 | static int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) | |
153 | { | |
154 | int result; | |
155 | ||
156 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
157 | PHM_PlatformCaps_ODFuzzyFanControlSupport)) { | |
158 | cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY); | |
159 | result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl); | |
160 | ||
161 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
162 | PHM_PlatformCaps_FanSpeedInTableIsRPM)) | |
163 | hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr, | |
164 | hwmgr->thermal_controller. | |
165 | advanceFanControlParameters.usMaxFanRPM); | |
166 | else | |
167 | hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr, | |
168 | hwmgr->thermal_controller. | |
169 | advanceFanControlParameters.usMaxFanPWM); | |
170 | ||
171 | } else { | |
172 | cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE); | |
173 | result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl); | |
174 | } | |
175 | ||
176 | if (!result && hwmgr->thermal_controller. | |
177 | advanceFanControlParameters.ucTargetTemperature) | |
178 | result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, | |
179 | PPSMC_MSG_SetFanTemperatureTarget, | |
180 | hwmgr->thermal_controller. | |
181 | advanceFanControlParameters.ucTargetTemperature); | |
182 | ||
183 | return result; | |
184 | } | |
185 | ||
186 | ||
187 | int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) | |
188 | { | |
189 | return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl); | |
190 | } | |
191 | ||
192 | /** | |
193 | * Set Fan Speed in percent. | |
194 | * @param hwmgr the address of the powerplay hardware manager. | |
195 | * @param speed is the percentage value (0% - 100%) to be set. | |
196 | * @exception Fails is the 100% setting appears to be 0. | |
197 | */ | |
198 | int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, | |
199 | uint32_t speed) | |
200 | { | |
201 | uint32_t duty100; | |
202 | uint32_t duty; | |
203 | uint64_t tmp64; | |
204 | ||
205 | if (hwmgr->thermal_controller.fanInfo.bNoFan) | |
206 | return 0; | |
207 | ||
208 | if (speed > 100) | |
209 | speed = 100; | |
210 | ||
211 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
212 | PHM_PlatformCaps_MicrocodeFanControl)) | |
213 | smu7_fan_ctrl_stop_smc_fan_control(hwmgr); | |
214 | ||
215 | duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
216 | CG_FDO_CTRL1, FMAX_DUTY100); | |
217 | ||
218 | if (duty100 == 0) | |
219 | return -EINVAL; | |
220 | ||
221 | tmp64 = (uint64_t)speed * duty100; | |
222 | do_div(tmp64, 100); | |
223 | duty = (uint32_t)tmp64; | |
224 | ||
225 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
226 | CG_FDO_CTRL0, FDO_STATIC_DUTY, duty); | |
227 | ||
228 | return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); | |
229 | } | |
230 | ||
231 | /** | |
232 | * Reset Fan Speed to default. | |
233 | * @param hwmgr the address of the powerplay hardware manager. | |
234 | * @exception Always succeeds. | |
235 | */ | |
236 | int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) | |
237 | { | |
238 | int result; | |
239 | ||
240 | if (hwmgr->thermal_controller.fanInfo.bNoFan) | |
241 | return 0; | |
242 | ||
243 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
244 | PHM_PlatformCaps_MicrocodeFanControl)) { | |
245 | result = smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); | |
246 | if (!result) | |
247 | result = smu7_fan_ctrl_start_smc_fan_control(hwmgr); | |
248 | } else | |
249 | result = smu7_fan_ctrl_set_default_mode(hwmgr); | |
250 | ||
251 | return result; | |
252 | } | |
253 | ||
254 | /** | |
255 | * Set Fan Speed in RPM. | |
256 | * @param hwmgr the address of the powerplay hardware manager. | |
257 | * @param speed is the percentage value (min - max) to be set. | |
258 | * @exception Fails is the speed not lie between min and max. | |
259 | */ | |
260 | int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) | |
261 | { | |
262 | uint32_t tach_period; | |
263 | uint32_t crystal_clock_freq; | |
264 | ||
265 | if (hwmgr->thermal_controller.fanInfo.bNoFan || | |
266 | (hwmgr->thermal_controller.fanInfo. | |
267 | ucTachometerPulsesPerRevolution == 0) || | |
268 | (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || | |
269 | (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) | |
270 | return 0; | |
271 | ||
272 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
273 | PHM_PlatformCaps_MicrocodeFanControl)) | |
274 | smu7_fan_ctrl_stop_smc_fan_control(hwmgr); | |
275 | ||
276 | crystal_clock_freq = smu7_get_xclk(hwmgr); | |
277 | ||
278 | tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); | |
279 | ||
280 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
281 | CG_TACH_STATUS, TACH_PERIOD, tach_period); | |
282 | ||
283 | return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); | |
284 | } | |
285 | ||
286 | /** | |
287 | * Reads the remote temperature from the SIslands thermal controller. | |
288 | * | |
289 | * @param hwmgr The address of the hardware manager. | |
290 | */ | |
291 | int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr) | |
292 | { | |
293 | int temp; | |
294 | ||
295 | temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
296 | CG_MULT_THERMAL_STATUS, CTF_TEMP); | |
297 | ||
298 | /* Bit 9 means the reading is lower than the lowest usable value. */ | |
299 | if (temp & 0x200) | |
300 | temp = SMU7_THERMAL_MAXIMUM_TEMP_READING; | |
301 | else | |
302 | temp = temp & 0x1ff; | |
303 | ||
304 | temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; | |
305 | ||
306 | return temp; | |
307 | } | |
308 | ||
309 | /** | |
310 | * Set the requested temperature range for high and low alert signals | |
311 | * | |
312 | * @param hwmgr The address of the hardware manager. | |
313 | * @param range Temperature range to be programmed for high and low alert signals | |
314 | * @exception PP_Result_BadInput if the input data is not valid. | |
315 | */ | |
316 | static int smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, | |
317 | uint32_t low_temp, uint32_t high_temp) | |
318 | { | |
319 | uint32_t low = SMU7_THERMAL_MINIMUM_ALERT_TEMP * | |
320 | PP_TEMPERATURE_UNITS_PER_CENTIGRADES; | |
321 | uint32_t high = SMU7_THERMAL_MAXIMUM_ALERT_TEMP * | |
322 | PP_TEMPERATURE_UNITS_PER_CENTIGRADES; | |
323 | ||
324 | if (low < low_temp) | |
325 | low = low_temp; | |
326 | if (high > high_temp) | |
327 | high = high_temp; | |
328 | ||
329 | if (low > high) | |
330 | return -EINVAL; | |
331 | ||
332 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
333 | CG_THERMAL_INT, DIG_THERM_INTH, | |
334 | (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); | |
335 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
336 | CG_THERMAL_INT, DIG_THERM_INTL, | |
337 | (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); | |
338 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
339 | CG_THERMAL_CTRL, DIG_THERM_DPM, | |
340 | (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); | |
341 | ||
342 | return 0; | |
343 | } | |
344 | ||
345 | /** | |
346 | * Programs thermal controller one-time setting registers | |
347 | * | |
348 | * @param hwmgr The address of the hardware manager. | |
349 | */ | |
350 | static int smu7_thermal_initialize(struct pp_hwmgr *hwmgr) | |
351 | { | |
352 | if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) | |
353 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
354 | CG_TACH_CTRL, EDGE_PER_REV, | |
355 | hwmgr->thermal_controller.fanInfo. | |
356 | ucTachometerPulsesPerRevolution - 1); | |
357 | ||
358 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
359 | CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28); | |
360 | ||
361 | return 0; | |
362 | } | |
363 | ||
364 | /** | |
365 | * Enable thermal alerts on the RV770 thermal controller. | |
366 | * | |
367 | * @param hwmgr The address of the hardware manager. | |
368 | */ | |
369 | int smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) | |
370 | { | |
371 | uint32_t alert; | |
372 | ||
373 | alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
374 | CG_THERMAL_INT, THERM_INT_MASK); | |
375 | alert &= ~(SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK); | |
376 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
377 | CG_THERMAL_INT, THERM_INT_MASK, alert); | |
378 | ||
379 | /* send message to SMU to enable internal thermal interrupts */ | |
380 | return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable); | |
381 | } | |
382 | ||
383 | /** | |
384 | * Disable thermal alerts on the RV770 thermal controller. | |
385 | * @param hwmgr The address of the hardware manager. | |
386 | */ | |
387 | int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr) | |
388 | { | |
389 | uint32_t alert; | |
390 | ||
391 | alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
392 | CG_THERMAL_INT, THERM_INT_MASK); | |
393 | alert |= (SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK); | |
394 | PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, | |
395 | CG_THERMAL_INT, THERM_INT_MASK, alert); | |
396 | ||
397 | /* send message to SMU to disable internal thermal interrupts */ | |
398 | return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable); | |
399 | } | |
400 | ||
401 | /** | |
402 | * Uninitialize the thermal controller. | |
403 | * Currently just disables alerts. | |
404 | * @param hwmgr The address of the hardware manager. | |
405 | */ | |
406 | int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) | |
407 | { | |
408 | int result = smu7_thermal_disable_alert(hwmgr); | |
409 | ||
410 | if (!hwmgr->thermal_controller.fanInfo.bNoFan) | |
411 | smu7_fan_ctrl_set_default_mode(hwmgr); | |
412 | ||
413 | return result; | |
414 | } | |
415 | ||
416 | /** | |
417 | * Start the fan control on the SMC. | |
418 | * @param hwmgr the address of the powerplay hardware manager. | |
419 | * @param pInput the pointer to input data | |
420 | * @param pOutput the pointer to output data | |
421 | * @param pStorage the pointer to temporary storage | |
422 | * @param Result the last failure code | |
423 | * @return result from set temperature range routine | |
424 | */ | |
425 | static int tf_smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, | |
426 | void *input, void *output, void *storage, int result) | |
427 | { | |
428 | /* If the fantable setup has failed we could have disabled | |
429 | * PHM_PlatformCaps_MicrocodeFanControl even after | |
430 | * this function was included in the table. | |
431 | * Make sure that we still think controlling the fan is OK. | |
432 | */ | |
433 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, | |
434 | PHM_PlatformCaps_MicrocodeFanControl)) { | |
435 | smu7_fan_ctrl_start_smc_fan_control(hwmgr); | |
436 | smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); | |
437 | } | |
438 | ||
439 | return 0; | |
440 | } | |
441 | ||
442 | /** | |
443 | * Set temperature range for high and low alerts | |
444 | * @param hwmgr the address of the powerplay hardware manager. | |
445 | * @param pInput the pointer to input data | |
446 | * @param pOutput the pointer to output data | |
447 | * @param pStorage the pointer to temporary storage | |
448 | * @param Result the last failure code | |
449 | * @return result from set temperature range routine | |
450 | */ | |
451 | static int tf_smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, | |
452 | void *input, void *output, void *storage, int result) | |
453 | { | |
454 | struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input; | |
455 | ||
456 | if (range == NULL) | |
457 | return -EINVAL; | |
458 | ||
459 | return smu7_thermal_set_temperature_range(hwmgr, range->min, range->max); | |
460 | } | |
461 | ||
462 | /** | |
463 | * Programs one-time setting registers | |
464 | * @param hwmgr the address of the powerplay hardware manager. | |
465 | * @param pInput the pointer to input data | |
466 | * @param pOutput the pointer to output data | |
467 | * @param pStorage the pointer to temporary storage | |
468 | * @param Result the last failure code | |
469 | * @return result from initialize thermal controller routine | |
470 | */ | |
471 | static int tf_smu7_thermal_initialize(struct pp_hwmgr *hwmgr, | |
472 | void *input, void *output, void *storage, int result) | |
473 | { | |
474 | return smu7_thermal_initialize(hwmgr); | |
475 | } | |
476 | ||
477 | /** | |
478 | * Enable high and low alerts | |
479 | * @param hwmgr the address of the powerplay hardware manager. | |
480 | * @param pInput the pointer to input data | |
481 | * @param pOutput the pointer to output data | |
482 | * @param pStorage the pointer to temporary storage | |
483 | * @param Result the last failure code | |
484 | * @return result from enable alert routine | |
485 | */ | |
486 | static int tf_smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr, | |
487 | void *input, void *output, void *storage, int result) | |
488 | { | |
489 | return smu7_thermal_enable_alert(hwmgr); | |
490 | } | |
491 | ||
492 | /** | |
493 | * Disable high and low alerts | |
494 | * @param hwmgr the address of the powerplay hardware manager. | |
495 | * @param pInput the pointer to input data | |
496 | * @param pOutput the pointer to output data | |
497 | * @param pStorage the pointer to temporary storage | |
498 | * @param Result the last failure code | |
499 | * @return result from disable alert routine | |
500 | */ | |
501 | static int tf_smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr, | |
502 | void *input, void *output, void *storage, int result) | |
503 | { | |
504 | return smu7_thermal_disable_alert(hwmgr); | |
505 | } | |
506 | ||
507 | static const struct phm_master_table_item | |
508 | phm_thermal_start_thermal_controller_master_list[] = { | |
509 | {NULL, tf_smu7_thermal_initialize}, | |
510 | {NULL, tf_smu7_thermal_set_temperature_range}, | |
511 | {NULL, tf_smu7_thermal_enable_alert}, | |
512 | {NULL, smum_thermal_avfs_enable}, | |
513 | /* We should restrict performance levels to low before we halt the SMC. | |
514 | * On the other hand we are still in boot state when we do this | |
515 | * so it would be pointless. | |
516 | * If this assumption changes we have to revisit this table. | |
517 | */ | |
518 | {NULL, smum_thermal_setup_fan_table}, | |
519 | {NULL, tf_smu7_thermal_start_smc_fan_control}, | |
520 | {NULL, NULL} | |
521 | }; | |
522 | ||
523 | static const struct phm_master_table_header | |
524 | phm_thermal_start_thermal_controller_master = { | |
525 | 0, | |
526 | PHM_MasterTableFlag_None, | |
527 | phm_thermal_start_thermal_controller_master_list | |
528 | }; | |
529 | ||
530 | static const struct phm_master_table_item | |
531 | phm_thermal_set_temperature_range_master_list[] = { | |
532 | {NULL, tf_smu7_thermal_disable_alert}, | |
533 | {NULL, tf_smu7_thermal_set_temperature_range}, | |
534 | {NULL, tf_smu7_thermal_enable_alert}, | |
535 | {NULL, NULL} | |
536 | }; | |
537 | ||
538 | static const struct phm_master_table_header | |
539 | phm_thermal_set_temperature_range_master = { | |
540 | 0, | |
541 | PHM_MasterTableFlag_None, | |
542 | phm_thermal_set_temperature_range_master_list | |
543 | }; | |
544 | ||
545 | int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) | |
546 | { | |
547 | if (!hwmgr->thermal_controller.fanInfo.bNoFan) | |
548 | smu7_fan_ctrl_set_default_mode(hwmgr); | |
549 | return 0; | |
550 | } | |
551 | ||
552 | /** | |
553 | * Initializes the thermal controller related functions in the Hardware Manager structure. | |
554 | * @param hwmgr The address of the hardware manager. | |
555 | * @exception Any error code from the low-level communication. | |
556 | */ | |
557 | int pp_smu7_thermal_initialize(struct pp_hwmgr *hwmgr) | |
558 | { | |
559 | int result; | |
560 | ||
561 | result = phm_construct_table(hwmgr, | |
562 | &phm_thermal_set_temperature_range_master, | |
563 | &(hwmgr->set_temperature_range)); | |
564 | ||
565 | if (!result) { | |
566 | result = phm_construct_table(hwmgr, | |
567 | &phm_thermal_start_thermal_controller_master, | |
568 | &(hwmgr->start_thermal_controller)); | |
569 | if (result) | |
570 | phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range)); | |
571 | } | |
572 | ||
573 | if (!result) | |
574 | hwmgr->fan_ctrl_is_in_default_mode = true; | |
575 | return result; | |
576 | } | |
577 |