Merge remote-tracking branch 'ftrace/for-next'
[deliverable/linux.git] / drivers / gpu / drm / amd / powerplay / hwmgr / polaris10_thermal.c
CommitLineData
eede5262
EH
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
ba391646 24#include <asm/div64.h>
2cc0c0b5
FC
25#include "polaris10_thermal.h"
26#include "polaris10_hwmgr.h"
27#include "polaris10_smumgr.h"
28#include "polaris10_ppsmc.h"
eede5262
EH
29#include "smu/smu_7_1_3_d.h"
30#include "smu/smu_7_1_3_sh_mask.h"
31
2cc0c0b5 32int polaris10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
eede5262
EH
33 struct phm_fan_speed_info *fan_speed_info)
34{
35 if (hwmgr->thermal_controller.fanInfo.bNoFan)
36 return 0;
37
38 fan_speed_info->supports_percent_read = true;
39 fan_speed_info->supports_percent_write = true;
40 fan_speed_info->min_percent = 0;
41 fan_speed_info->max_percent = 100;
42
43 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
44 PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
45 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
46 fan_speed_info->supports_rpm_read = true;
47 fan_speed_info->supports_rpm_write = true;
48 fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM;
49 fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
50 } else {
51 fan_speed_info->min_rpm = 0;
52 fan_speed_info->max_rpm = 0;
53 }
54
55 return 0;
56}
57
2cc0c0b5 58int polaris10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
eede5262
EH
59 uint32_t *speed)
60{
61 uint32_t duty100;
62 uint32_t duty;
63 uint64_t tmp64;
64
65 if (hwmgr->thermal_controller.fanInfo.bNoFan)
66 return 0;
67
68 duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
69 CG_FDO_CTRL1, FMAX_DUTY100);
70 duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
71 CG_THERMAL_STATUS, FDO_PWM_DUTY);
72
73 if (duty100 == 0)
74 return -EINVAL;
75
76
77 tmp64 = (uint64_t)duty * 100;
78 do_div(tmp64, duty100);
79 *speed = (uint32_t)tmp64;
80
81 if (*speed > 100)
82 *speed = 100;
83
84 return 0;
85}
86
2cc0c0b5 87int polaris10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
eede5262
EH
88{
89 uint32_t tach_period;
90 uint32_t crystal_clock_freq;
91
92 if (hwmgr->thermal_controller.fanInfo.bNoFan ||
93 (hwmgr->thermal_controller.fanInfo.
94 ucTachometerPulsesPerRevolution == 0))
95 return 0;
96
97 tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
98 CG_TACH_STATUS, TACH_PERIOD);
99
100 if (tach_period == 0)
101 return -EINVAL;
102
103 crystal_clock_freq = tonga_get_xclk(hwmgr);
104
105 *speed = 60 * crystal_clock_freq * 10000 / tach_period;
106
107 return 0;
108}
109
110/**
111* Set Fan Speed Control to static mode, so that the user can decide what speed to use.
112* @param hwmgr the address of the powerplay hardware manager.
113* mode the fan control mode, 0 default, 1 by percent, 5, by RPM
114* @exception Should always succeed.
115*/
2cc0c0b5 116int polaris10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
eede5262
EH
117{
118
119 if (hwmgr->fan_ctrl_is_in_default_mode) {
120 hwmgr->fan_ctrl_default_mode =
121 PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
122 CG_FDO_CTRL2, FDO_PWM_MODE);
123 hwmgr->tmin =
124 PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
125 CG_FDO_CTRL2, TMIN);
126 hwmgr->fan_ctrl_is_in_default_mode = false;
127 }
128
129 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
130 CG_FDO_CTRL2, TMIN, 0);
131 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
132 CG_FDO_CTRL2, FDO_PWM_MODE, mode);
133
134 return 0;
135}
136
137/**
138* Reset Fan Speed Control to default mode.
139* @param hwmgr the address of the powerplay hardware manager.
140* @exception Should always succeed.
141*/
2cc0c0b5 142int polaris10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
eede5262
EH
143{
144 if (!hwmgr->fan_ctrl_is_in_default_mode) {
145 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
146 CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode);
147 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
148 CG_FDO_CTRL2, TMIN, hwmgr->tmin);
149 hwmgr->fan_ctrl_is_in_default_mode = true;
150 }
151
152 return 0;
153}
154
2cc0c0b5 155int polaris10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
eede5262
EH
156{
157 int result;
158
159 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
160 PHM_PlatformCaps_ODFuzzyFanControlSupport)) {
161 cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY);
162 result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl);
163
164 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
165 PHM_PlatformCaps_FanSpeedInTableIsRPM))
166 hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr,
167 hwmgr->thermal_controller.
168 advanceFanControlParameters.usMaxFanRPM);
169 else
170 hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr,
171 hwmgr->thermal_controller.
172 advanceFanControlParameters.usMaxFanPWM);
173
174 } else {
175 cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE);
176 result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl);
177 }
178
179 if (!result && hwmgr->thermal_controller.
180 advanceFanControlParameters.ucTargetTemperature)
181 result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
182 PPSMC_MSG_SetFanTemperatureTarget,
183 hwmgr->thermal_controller.
184 advanceFanControlParameters.ucTargetTemperature);
185
186 return result;
187}
188
189
2cc0c0b5 190int polaris10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
eede5262
EH
191{
192 return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl);
193}
194
195/**
196* Set Fan Speed in percent.
197* @param hwmgr the address of the powerplay hardware manager.
198* @param speed is the percentage value (0% - 100%) to be set.
199* @exception Fails is the 100% setting appears to be 0.
200*/
2cc0c0b5 201int polaris10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
eede5262
EH
202 uint32_t speed)
203{
204 uint32_t duty100;
205 uint32_t duty;
206 uint64_t tmp64;
207
208 if (hwmgr->thermal_controller.fanInfo.bNoFan)
209 return 0;
210
211 if (speed > 100)
212 speed = 100;
213
214 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
215 PHM_PlatformCaps_MicrocodeFanControl))
2cc0c0b5 216 polaris10_fan_ctrl_stop_smc_fan_control(hwmgr);
eede5262
EH
217
218 duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
219 CG_FDO_CTRL1, FMAX_DUTY100);
220
221 if (duty100 == 0)
222 return -EINVAL;
223
51224389
EH
224 tmp64 = (uint64_t)speed * duty100;
225 do_div(tmp64, 100);
eede5262
EH
226 duty = (uint32_t)tmp64;
227
228 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
229 CG_FDO_CTRL0, FDO_STATIC_DUTY, duty);
230
2cc0c0b5 231 return polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
eede5262
EH
232}
233
234/**
235* Reset Fan Speed to default.
236* @param hwmgr the address of the powerplay hardware manager.
237* @exception Always succeeds.
238*/
2cc0c0b5 239int polaris10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
eede5262
EH
240{
241 int result;
242
243 if (hwmgr->thermal_controller.fanInfo.bNoFan)
244 return 0;
245
246 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
247 PHM_PlatformCaps_MicrocodeFanControl)) {
2cc0c0b5 248 result = polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
eede5262 249 if (!result)
2cc0c0b5 250 result = polaris10_fan_ctrl_start_smc_fan_control(hwmgr);
eede5262 251 } else
2cc0c0b5 252 result = polaris10_fan_ctrl_set_default_mode(hwmgr);
eede5262
EH
253
254 return result;
255}
256
257/**
258* Set Fan Speed in RPM.
259* @param hwmgr the address of the powerplay hardware manager.
260* @param speed is the percentage value (min - max) to be set.
261* @exception Fails is the speed not lie between min and max.
262*/
2cc0c0b5 263int polaris10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
eede5262
EH
264{
265 uint32_t tach_period;
266 uint32_t crystal_clock_freq;
267
268 if (hwmgr->thermal_controller.fanInfo.bNoFan ||
269 (hwmgr->thermal_controller.fanInfo.
270 ucTachometerPulsesPerRevolution == 0) ||
271 (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
272 (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
273 return 0;
274
275 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
276 PHM_PlatformCaps_MicrocodeFanControl))
2cc0c0b5 277 polaris10_fan_ctrl_stop_smc_fan_control(hwmgr);
eede5262
EH
278
279 crystal_clock_freq = tonga_get_xclk(hwmgr);
280
281 tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
282
283 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
284 CG_TACH_STATUS, TACH_PERIOD, tach_period);
285
2cc0c0b5 286 return polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
eede5262
EH
287}
288
289/**
290* Reads the remote temperature from the SIslands thermal controller.
291*
292* @param hwmgr The address of the hardware manager.
293*/
2cc0c0b5 294int polaris10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
eede5262
EH
295{
296 int temp;
297
298 temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
299 CG_MULT_THERMAL_STATUS, CTF_TEMP);
300
301 /* Bit 9 means the reading is lower than the lowest usable value. */
302 if (temp & 0x200)
2cc0c0b5 303 temp = POLARIS10_THERMAL_MAXIMUM_TEMP_READING;
eede5262
EH
304 else
305 temp = temp & 0x1ff;
306
307 temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
308
309 return temp;
310}
311
312/**
313* Set the requested temperature range for high and low alert signals
314*
315* @param hwmgr The address of the hardware manager.
316* @param range Temperature range to be programmed for high and low alert signals
317* @exception PP_Result_BadInput if the input data is not valid.
318*/
2cc0c0b5 319static int polaris10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
eede5262
EH
320 uint32_t low_temp, uint32_t high_temp)
321{
2cc0c0b5 322 uint32_t low = POLARIS10_THERMAL_MINIMUM_ALERT_TEMP *
eede5262 323 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2cc0c0b5 324 uint32_t high = POLARIS10_THERMAL_MAXIMUM_ALERT_TEMP *
eede5262
EH
325 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
326
327 if (low < low_temp)
328 low = low_temp;
329 if (high > high_temp)
330 high = high_temp;
331
332 if (low > high)
333 return -EINVAL;
334
335 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
336 CG_THERMAL_INT, DIG_THERM_INTH,
337 (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
338 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
339 CG_THERMAL_INT, DIG_THERM_INTL,
340 (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
341 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
342 CG_THERMAL_CTRL, DIG_THERM_DPM,
343 (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
344
345 return 0;
346}
347
348/**
349* Programs thermal controller one-time setting registers
350*
351* @param hwmgr The address of the hardware manager.
352*/
2cc0c0b5 353static int polaris10_thermal_initialize(struct pp_hwmgr *hwmgr)
eede5262
EH
354{
355 if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution)
356 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
357 CG_TACH_CTRL, EDGE_PER_REV,
358 hwmgr->thermal_controller.fanInfo.
359 ucTachometerPulsesPerRevolution - 1);
360
361 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
362 CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28);
363
364 return 0;
365}
366
367/**
368* Enable thermal alerts on the RV770 thermal controller.
369*
370* @param hwmgr The address of the hardware manager.
371*/
2cc0c0b5 372static int polaris10_thermal_enable_alert(struct pp_hwmgr *hwmgr)
eede5262
EH
373{
374 uint32_t alert;
375
376 alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
377 CG_THERMAL_INT, THERM_INT_MASK);
2cc0c0b5 378 alert &= ~(POLARIS10_THERMAL_HIGH_ALERT_MASK | POLARIS10_THERMAL_LOW_ALERT_MASK);
eede5262
EH
379 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
380 CG_THERMAL_INT, THERM_INT_MASK, alert);
381
382 /* send message to SMU to enable internal thermal interrupts */
383 return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable);
384}
385
386/**
387* Disable thermal alerts on the RV770 thermal controller.
388* @param hwmgr The address of the hardware manager.
389*/
2cc0c0b5 390static int polaris10_thermal_disable_alert(struct pp_hwmgr *hwmgr)
eede5262
EH
391{
392 uint32_t alert;
393
394 alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
395 CG_THERMAL_INT, THERM_INT_MASK);
2cc0c0b5 396 alert |= (POLARIS10_THERMAL_HIGH_ALERT_MASK | POLARIS10_THERMAL_LOW_ALERT_MASK);
eede5262
EH
397 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
398 CG_THERMAL_INT, THERM_INT_MASK, alert);
399
400 /* send message to SMU to disable internal thermal interrupts */
401 return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable);
402}
403
404/**
405* Uninitialize the thermal controller.
406* Currently just disables alerts.
407* @param hwmgr The address of the hardware manager.
408*/
2cc0c0b5 409int polaris10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
eede5262 410{
2cc0c0b5 411 int result = polaris10_thermal_disable_alert(hwmgr);
eede5262
EH
412
413 if (!hwmgr->thermal_controller.fanInfo.bNoFan)
2cc0c0b5 414 polaris10_fan_ctrl_set_default_mode(hwmgr);
eede5262
EH
415
416 return result;
417}
418
419/**
420* Set up the fan table to control the fan using the SMC.
421* @param hwmgr the address of the powerplay hardware manager.
422* @param pInput the pointer to input data
423* @param pOutput the pointer to output data
424* @param pStorage the pointer to temporary storage
425* @param Result the last failure code
426* @return result from set temperature range routine
427*/
2cc0c0b5 428int tf_polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr,
eede5262
EH
429 void *input, void *output, void *storage, int result)
430{
2cc0c0b5 431 struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
eede5262
EH
432 SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
433 uint32_t duty100;
434 uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
435 uint16_t fdo_min, slope1, slope2;
436 uint32_t reference_clock;
437 int res;
438 uint64_t tmp64;
439
440 if (data->fan_table_start == 0) {
441 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
442 PHM_PlatformCaps_MicrocodeFanControl);
443 return 0;
444 }
445
446 duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
447 CG_FDO_CTRL1, FMAX_DUTY100);
448
449 if (duty100 == 0) {
450 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
451 PHM_PlatformCaps_MicrocodeFanControl);
452 return 0;
453 }
454
455 tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.
456 usPWMMin * duty100;
457 do_div(tmp64, 10000);
458 fdo_min = (uint16_t)tmp64;
459
460 t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed -
461 hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
462 t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh -
463 hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
464
465 pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed -
466 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
467 pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh -
468 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
469
470 slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
471 slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
472
473 fan_table.TempMin = cpu_to_be16((50 + hwmgr->
474 thermal_controller.advanceFanControlParameters.usTMin) / 100);
475 fan_table.TempMed = cpu_to_be16((50 + hwmgr->
476 thermal_controller.advanceFanControlParameters.usTMed) / 100);
477 fan_table.TempMax = cpu_to_be16((50 + hwmgr->
478 thermal_controller.advanceFanControlParameters.usTMax) / 100);
479
480 fan_table.Slope1 = cpu_to_be16(slope1);
481 fan_table.Slope2 = cpu_to_be16(slope2);
482
483 fan_table.FdoMin = cpu_to_be16(fdo_min);
484
485 fan_table.HystDown = cpu_to_be16(hwmgr->
486 thermal_controller.advanceFanControlParameters.ucTHyst);
487
488 fan_table.HystUp = cpu_to_be16(1);
489
490 fan_table.HystSlope = cpu_to_be16(1);
491
492 fan_table.TempRespLim = cpu_to_be16(5);
493
494 reference_clock = tonga_get_xclk(hwmgr);
495
496 fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
497 thermal_controller.advanceFanControlParameters.ulCycleDelay *
498 reference_clock) / 1600);
499
500 fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
501
502 fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(
503 hwmgr->device, CGS_IND_REG__SMC,
504 CG_MULT_THERMAL_CTRL, TEMP_SEL);
505
2cc0c0b5 506 res = polaris10_copy_bytes_to_smc(hwmgr->smumgr, data->fan_table_start,
eede5262
EH
507 (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table),
508 data->sram_end);
509
510 if (!res && hwmgr->thermal_controller.
511 advanceFanControlParameters.ucMinimumPWMLimit)
512 res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
513 PPSMC_MSG_SetFanMinPwm,
514 hwmgr->thermal_controller.
515 advanceFanControlParameters.ucMinimumPWMLimit);
516
517 if (!res && hwmgr->thermal_controller.
518 advanceFanControlParameters.ulMinFanSCLKAcousticLimit)
519 res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
520 PPSMC_MSG_SetFanSclkTarget,
521 hwmgr->thermal_controller.
522 advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
523
524 if (res)
525 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
526 PHM_PlatformCaps_MicrocodeFanControl);
527
528 return 0;
529}
530
531/**
532* Start the fan control on the SMC.
533* @param hwmgr the address of the powerplay hardware manager.
534* @param pInput the pointer to input data
535* @param pOutput the pointer to output data
536* @param pStorage the pointer to temporary storage
537* @param Result the last failure code
538* @return result from set temperature range routine
539*/
2cc0c0b5 540int tf_polaris10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr,
eede5262
EH
541 void *input, void *output, void *storage, int result)
542{
543/* If the fantable setup has failed we could have disabled
544 * PHM_PlatformCaps_MicrocodeFanControl even after
545 * this function was included in the table.
546 * Make sure that we still think controlling the fan is OK.
547*/
548 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
549 PHM_PlatformCaps_MicrocodeFanControl)) {
2cc0c0b5
FC
550 polaris10_fan_ctrl_start_smc_fan_control(hwmgr);
551 polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
eede5262
EH
552 }
553
554 return 0;
555}
556
557/**
558* Set temperature range for high and low alerts
559* @param hwmgr the address of the powerplay hardware manager.
560* @param pInput the pointer to input data
561* @param pOutput the pointer to output data
562* @param pStorage the pointer to temporary storage
563* @param Result the last failure code
564* @return result from set temperature range routine
565*/
2cc0c0b5 566int tf_polaris10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
eede5262
EH
567 void *input, void *output, void *storage, int result)
568{
569 struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input;
570
571 if (range == NULL)
572 return -EINVAL;
573
2cc0c0b5 574 return polaris10_thermal_set_temperature_range(hwmgr, range->min, range->max);
eede5262
EH
575}
576
577/**
578* Programs one-time setting registers
579* @param hwmgr the address of the powerplay hardware manager.
580* @param pInput the pointer to input data
581* @param pOutput the pointer to output data
582* @param pStorage the pointer to temporary storage
583* @param Result the last failure code
584* @return result from initialize thermal controller routine
585*/
2cc0c0b5 586int tf_polaris10_thermal_initialize(struct pp_hwmgr *hwmgr,
eede5262
EH
587 void *input, void *output, void *storage, int result)
588{
2cc0c0b5 589 return polaris10_thermal_initialize(hwmgr);
eede5262
EH
590}
591
592/**
593* Enable high and low alerts
594* @param hwmgr the address of the powerplay hardware manager.
595* @param pInput the pointer to input data
596* @param pOutput the pointer to output data
597* @param pStorage the pointer to temporary storage
598* @param Result the last failure code
599* @return result from enable alert routine
600*/
2cc0c0b5 601int tf_polaris10_thermal_enable_alert(struct pp_hwmgr *hwmgr,
eede5262
EH
602 void *input, void *output, void *storage, int result)
603{
2cc0c0b5 604 return polaris10_thermal_enable_alert(hwmgr);
eede5262
EH
605}
606
607/**
608* Disable high and low alerts
609* @param hwmgr the address of the powerplay hardware manager.
610* @param pInput the pointer to input data
611* @param pOutput the pointer to output data
612* @param pStorage the pointer to temporary storage
613* @param Result the last failure code
614* @return result from disable alert routine
615*/
2cc0c0b5 616static int tf_polaris10_thermal_disable_alert(struct pp_hwmgr *hwmgr,
eede5262
EH
617 void *input, void *output, void *storage, int result)
618{
2cc0c0b5 619 return polaris10_thermal_disable_alert(hwmgr);
eede5262
EH
620}
621
2cc0c0b5 622static int tf_polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr,
eede5262
EH
623 void *input, void *output, void *storage, int result)
624{
625 int ret;
626 struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr);
2cc0c0b5 627 struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
432c3a3c 628 struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
eede5262 629
432c3a3c 630 if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
eede5262
EH
631 return 0;
632
432c3a3c
RZ
633 ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
634 PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting);
635
eede5262
EH
636 ret = (smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs) == 0) ?
637 0 : -1;
638
639 if (!ret)
640 /* If this param is not changed, this function could fire unnecessarily */
641 smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY;
642
643 return ret;
644}
645
909a0631 646static const struct phm_master_table_item
2cc0c0b5
FC
647polaris10_thermal_start_thermal_controller_master_list[] = {
648 {NULL, tf_polaris10_thermal_initialize},
649 {NULL, tf_polaris10_thermal_set_temperature_range},
650 {NULL, tf_polaris10_thermal_enable_alert},
651 {NULL, tf_polaris10_thermal_avfs_enable},
eede5262
EH
652/* We should restrict performance levels to low before we halt the SMC.
653 * On the other hand we are still in boot state when we do this
654 * so it would be pointless.
655 * If this assumption changes we have to revisit this table.
656 */
2cc0c0b5
FC
657 {NULL, tf_polaris10_thermal_setup_fan_table},
658 {NULL, tf_polaris10_thermal_start_smc_fan_control},
eede5262
EH
659 {NULL, NULL}
660};
661
909a0631 662static const struct phm_master_table_header
2cc0c0b5 663polaris10_thermal_start_thermal_controller_master = {
eede5262
EH
664 0,
665 PHM_MasterTableFlag_None,
2cc0c0b5 666 polaris10_thermal_start_thermal_controller_master_list
eede5262
EH
667};
668
909a0631 669static const struct phm_master_table_item
2cc0c0b5
FC
670polaris10_thermal_set_temperature_range_master_list[] = {
671 {NULL, tf_polaris10_thermal_disable_alert},
672 {NULL, tf_polaris10_thermal_set_temperature_range},
673 {NULL, tf_polaris10_thermal_enable_alert},
eede5262
EH
674 {NULL, NULL}
675};
676
909a0631 677static const struct phm_master_table_header
2cc0c0b5 678polaris10_thermal_set_temperature_range_master = {
eede5262
EH
679 0,
680 PHM_MasterTableFlag_None,
2cc0c0b5 681 polaris10_thermal_set_temperature_range_master_list
eede5262
EH
682};
683
2cc0c0b5 684int polaris10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
eede5262
EH
685{
686 if (!hwmgr->thermal_controller.fanInfo.bNoFan)
2cc0c0b5 687 polaris10_fan_ctrl_set_default_mode(hwmgr);
eede5262
EH
688 return 0;
689}
690
691/**
692* Initializes the thermal controller related functions in the Hardware Manager structure.
693* @param hwmgr The address of the hardware manager.
694* @exception Any error code from the low-level communication.
695*/
2cc0c0b5 696int pp_polaris10_thermal_initialize(struct pp_hwmgr *hwmgr)
eede5262
EH
697{
698 int result;
699
700 result = phm_construct_table(hwmgr,
2cc0c0b5 701 &polaris10_thermal_set_temperature_range_master,
eede5262
EH
702 &(hwmgr->set_temperature_range));
703
704 if (!result) {
705 result = phm_construct_table(hwmgr,
2cc0c0b5 706 &polaris10_thermal_start_thermal_controller_master,
eede5262
EH
707 &(hwmgr->start_thermal_controller));
708 if (result)
709 phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range));
710 }
711
712 if (!result)
713 hwmgr->fan_ctrl_is_in_default_mode = true;
714 return result;
715}
716
This page took 0.105901 seconds and 5 git commands to generate.