root/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vega20_disable_fan_control_feature
  2. vega20_fan_ctrl_stop_smc_fan_control
  3. vega20_enable_fan_control_feature
  4. vega20_fan_ctrl_start_smc_fan_control
  5. vega20_fan_ctrl_set_static_mode
  6. vega20_get_current_rpm
  7. vega20_fan_ctrl_get_fan_speed_percent
  8. vega20_fan_ctrl_set_fan_speed_percent
  9. vega20_fan_ctrl_get_fan_speed_info
  10. vega20_fan_ctrl_get_fan_speed_rpm
  11. vega20_fan_ctrl_set_fan_speed_rpm
  12. vega20_thermal_get_temperature
  13. vega20_thermal_set_temperature_range
  14. vega20_thermal_enable_alert
  15. vega20_thermal_disable_alert
  16. vega20_thermal_stop_thermal_controller
  17. vega20_thermal_setup_fan_table
  18. vega20_start_thermal_controller

   1 /*
   2  * Copyright 2018 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 "vega20_thermal.h"
  25 #include "vega20_hwmgr.h"
  26 #include "vega20_smumgr.h"
  27 #include "vega20_ppsmc.h"
  28 #include "vega20_inc.h"
  29 #include "soc15_common.h"
  30 #include "pp_debug.h"
  31 
  32 static int vega20_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
  33 {
  34         struct vega20_hwmgr *data = hwmgr->backend;
  35         int ret = 0;
  36 
  37         if (data->smu_features[GNLD_FAN_CONTROL].supported) {
  38                 ret = vega20_enable_smc_features(
  39                                 hwmgr, false,
  40                                 data->smu_features[GNLD_FAN_CONTROL].
  41                                 smu_feature_bitmap);
  42                 PP_ASSERT_WITH_CODE(!ret,
  43                                 "Disable FAN CONTROL feature Failed!",
  44                                 return ret);
  45                 data->smu_features[GNLD_FAN_CONTROL].enabled = false;
  46         }
  47 
  48         return ret;
  49 }
  50 
  51 int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
  52 {
  53         struct vega20_hwmgr *data = hwmgr->backend;
  54 
  55         if (data->smu_features[GNLD_FAN_CONTROL].supported)
  56                 return vega20_disable_fan_control_feature(hwmgr);
  57 
  58         return 0;
  59 }
  60 
  61 static int vega20_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
  62 {
  63         struct vega20_hwmgr *data = hwmgr->backend;
  64         int ret = 0;
  65 
  66         if (data->smu_features[GNLD_FAN_CONTROL].supported) {
  67                 ret = vega20_enable_smc_features(
  68                                 hwmgr, true,
  69                                 data->smu_features[GNLD_FAN_CONTROL].
  70                                 smu_feature_bitmap);
  71                 PP_ASSERT_WITH_CODE(!ret,
  72                                 "Enable FAN CONTROL feature Failed!",
  73                                 return ret);
  74                 data->smu_features[GNLD_FAN_CONTROL].enabled = true;
  75         }
  76 
  77         return ret;
  78 }
  79 
  80 int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
  81 {
  82         struct vega20_hwmgr *data = hwmgr->backend;
  83 
  84         if (data->smu_features[GNLD_FAN_CONTROL].supported)
  85                 return vega20_enable_fan_control_feature(hwmgr);
  86 
  87         return 0;
  88 }
  89 
  90 static int vega20_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
  91 {
  92         struct amdgpu_device *adev = hwmgr->adev;
  93 
  94         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
  95                         REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
  96                                 CG_FDO_CTRL2, TMIN, 0));
  97         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
  98                         REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
  99                                 CG_FDO_CTRL2, FDO_PWM_MODE, mode));
 100 
 101         return 0;
 102 }
 103 
 104 static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
 105 {
 106         int ret = 0;
 107 
 108         PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
 109                                 PPSMC_MSG_GetCurrentRpm)) == 0,
 110                         "Attempt to get current RPM from SMC Failed!",
 111                         return ret);
 112         *current_rpm = smum_get_argument(hwmgr);
 113 
 114         return 0;
 115 }
 116 
 117 int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
 118                 uint32_t *speed)
 119 {
 120         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
 121         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
 122         uint32_t current_rpm, percent = 0;
 123         int ret = 0;
 124 
 125         ret = vega20_get_current_rpm(hwmgr, &current_rpm);
 126         if (ret)
 127                 return ret;
 128 
 129         percent = current_rpm * 100 / pp_table->FanMaximumRpm;
 130 
 131         *speed = percent > 100 ? 100 : percent;
 132 
 133         return 0;
 134 }
 135 
 136 int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
 137                 uint32_t speed)
 138 {
 139         struct amdgpu_device *adev = hwmgr->adev;
 140         uint32_t duty100;
 141         uint32_t duty;
 142         uint64_t tmp64;
 143 
 144         if (speed > 100)
 145                 speed = 100;
 146 
 147         if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
 148                 vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
 149 
 150         duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
 151                                     CG_FDO_CTRL1, FMAX_DUTY100);
 152 
 153         if (duty100 == 0)
 154                 return -EINVAL;
 155 
 156         tmp64 = (uint64_t)speed * duty100;
 157         do_div(tmp64, 100);
 158         duty = (uint32_t)tmp64;
 159 
 160         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
 161                 REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
 162                         CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
 163 
 164         return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
 165 }
 166 
 167 int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
 168                 struct phm_fan_speed_info *fan_speed_info)
 169 {
 170         memset(fan_speed_info, 0, sizeof(*fan_speed_info));
 171         fan_speed_info->supports_percent_read = true;
 172         fan_speed_info->supports_percent_write = true;
 173         fan_speed_info->supports_rpm_read = true;
 174         fan_speed_info->supports_rpm_write = true;
 175 
 176         return 0;
 177 }
 178 
 179 int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
 180 {
 181         *speed = 0;
 182 
 183         return vega20_get_current_rpm(hwmgr, speed);
 184 }
 185 
 186 int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
 187 {
 188         struct amdgpu_device *adev = hwmgr->adev;
 189         uint32_t tach_period, crystal_clock_freq;
 190         int result = 0;
 191 
 192         if (!speed)
 193                 return -EINVAL;
 194 
 195         if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) {
 196                 result = vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
 197                 if (result)
 198                         return result;
 199         }
 200 
 201         crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
 202         tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
 203         WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
 204                         REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
 205                                 CG_TACH_CTRL, TARGET_PERIOD,
 206                                 tach_period));
 207 
 208         return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
 209 }
 210 
 211 /**
 212 * Reads the remote temperature from the SIslands thermal controller.
 213 *
 214 * @param    hwmgr The address of the hardware manager.
 215 */
 216 int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr)
 217 {
 218         struct amdgpu_device *adev = hwmgr->adev;
 219         int temp = 0;
 220 
 221         temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
 222 
 223         temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
 224                         CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
 225 
 226         temp = temp & 0x1ff;
 227 
 228         temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 229         return temp;
 230 }
 231 
 232 /**
 233 * Set the requested temperature range for high and low alert signals
 234 *
 235 * @param    hwmgr The address of the hardware manager.
 236 * @param    range Temperature range to be programmed for
 237 *           high and low alert signals
 238 * @exception PP_Result_BadInput if the input data is not valid.
 239 */
 240 static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
 241                 struct PP_TemperatureRange *range)
 242 {
 243         struct amdgpu_device *adev = hwmgr->adev;
 244         int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP *
 245                         PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 246         int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP *
 247                         PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 248         uint32_t val;
 249 
 250         if (low < range->min)
 251                 low = range->min;
 252         if (high > range->max)
 253                 high = range->max;
 254 
 255         if (low > high)
 256                 return -EINVAL;
 257 
 258         val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
 259 
 260         val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
 261         val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
 262         val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
 263         val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
 264         val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
 265 
 266         WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
 267 
 268         return 0;
 269 }
 270 
 271 /**
 272 * Enable thermal alerts on the RV770 thermal controller.
 273 *
 274 * @param    hwmgr The address of the hardware manager.
 275 */
 276 static int vega20_thermal_enable_alert(struct pp_hwmgr *hwmgr)
 277 {
 278         struct amdgpu_device *adev = hwmgr->adev;
 279         uint32_t val = 0;
 280 
 281         val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
 282         val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
 283         val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
 284 
 285         WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
 286 
 287         return 0;
 288 }
 289 
 290 /**
 291 * Disable thermal alerts on the RV770 thermal controller.
 292 * @param    hwmgr The address of the hardware manager.
 293 */
 294 int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr)
 295 {
 296         struct amdgpu_device *adev = hwmgr->adev;
 297 
 298         WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
 299 
 300         return 0;
 301 }
 302 
 303 /**
 304 * Uninitialize the thermal controller.
 305 * Currently just disables alerts.
 306 * @param    hwmgr The address of the hardware manager.
 307 */
 308 int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
 309 {
 310         int result = vega20_thermal_disable_alert(hwmgr);
 311 
 312         return result;
 313 }
 314 
 315 /**
 316 * Set up the fan table to control the fan using the SMC.
 317 * @param    hwmgr  the address of the powerplay hardware manager.
 318 * @param    pInput the pointer to input data
 319 * @param    pOutput the pointer to output data
 320 * @param    pStorage the pointer to temporary storage
 321 * @param    Result the last failure code
 322 * @return   result from set temperature range routine
 323 */
 324 static int vega20_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
 325 {
 326         int ret;
 327         struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
 328         PPTable_t *table = &(data->smc_state_table.pp_table);
 329 
 330         ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 331                                 PPSMC_MSG_SetFanTemperatureTarget,
 332                                 (uint32_t)table->FanTargetTemperature);
 333 
 334         return ret;
 335 }
 336 
 337 int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr,
 338                                 struct PP_TemperatureRange *range)
 339 {
 340         int ret = 0;
 341 
 342         if (range == NULL)
 343                 return -EINVAL;
 344 
 345         ret = vega20_thermal_set_temperature_range(hwmgr, range);
 346         if (ret)
 347                 return ret;
 348 
 349         ret = vega20_thermal_enable_alert(hwmgr);
 350         if (ret)
 351                 return ret;
 352 
 353         ret = vega20_thermal_setup_fan_table(hwmgr);
 354 
 355         return ret;
 356 };

/* [<][>][^][v][top][bottom][index][help] */