0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "vega20_thermal.h"
0025 #include "vega20_hwmgr.h"
0026 #include "vega20_smumgr.h"
0027 #include "vega20_ppsmc.h"
0028 #include "vega20_inc.h"
0029 #include "soc15_common.h"
0030 #include "pp_debug.h"
0031
0032 static int vega20_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
0033 {
0034 struct vega20_hwmgr *data = hwmgr->backend;
0035 int ret = 0;
0036
0037 if (data->smu_features[GNLD_FAN_CONTROL].supported) {
0038 ret = vega20_enable_smc_features(
0039 hwmgr, false,
0040 data->smu_features[GNLD_FAN_CONTROL].
0041 smu_feature_bitmap);
0042 PP_ASSERT_WITH_CODE(!ret,
0043 "Disable FAN CONTROL feature Failed!",
0044 return ret);
0045 data->smu_features[GNLD_FAN_CONTROL].enabled = false;
0046 }
0047
0048 return ret;
0049 }
0050
0051 int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
0052 {
0053 struct vega20_hwmgr *data = hwmgr->backend;
0054
0055 if (data->smu_features[GNLD_FAN_CONTROL].supported)
0056 return vega20_disable_fan_control_feature(hwmgr);
0057
0058 return 0;
0059 }
0060
0061 static int vega20_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
0062 {
0063 struct vega20_hwmgr *data = hwmgr->backend;
0064 int ret = 0;
0065
0066 if (data->smu_features[GNLD_FAN_CONTROL].supported) {
0067 ret = vega20_enable_smc_features(
0068 hwmgr, true,
0069 data->smu_features[GNLD_FAN_CONTROL].
0070 smu_feature_bitmap);
0071 PP_ASSERT_WITH_CODE(!ret,
0072 "Enable FAN CONTROL feature Failed!",
0073 return ret);
0074 data->smu_features[GNLD_FAN_CONTROL].enabled = true;
0075 }
0076
0077 return ret;
0078 }
0079
0080 int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
0081 {
0082 struct vega20_hwmgr *data = hwmgr->backend;
0083
0084 if (data->smu_features[GNLD_FAN_CONTROL].supported)
0085 return vega20_enable_fan_control_feature(hwmgr);
0086
0087 return 0;
0088 }
0089
0090 static int vega20_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
0091 {
0092 struct amdgpu_device *adev = hwmgr->adev;
0093
0094 WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
0095 REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0096 CG_FDO_CTRL2, TMIN, 0));
0097 WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
0098 REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0099 CG_FDO_CTRL2, FDO_PWM_MODE, mode));
0100
0101 return 0;
0102 }
0103
0104 static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
0105 {
0106 int ret = 0;
0107
0108 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
0109 PPSMC_MSG_GetCurrentRpm,
0110 current_rpm)) == 0,
0111 "Attempt to get current RPM from SMC Failed!",
0112 return ret);
0113
0114 return 0;
0115 }
0116
0117 int vega20_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr,
0118 uint32_t *speed)
0119 {
0120 struct amdgpu_device *adev = hwmgr->adev;
0121 uint32_t duty100, duty;
0122 uint64_t tmp64;
0123
0124 duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
0125 CG_FDO_CTRL1, FMAX_DUTY100);
0126 duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS),
0127 CG_THERMAL_STATUS, FDO_PWM_DUTY);
0128
0129 if (!duty100)
0130 return -EINVAL;
0131
0132 tmp64 = (uint64_t)duty * 255;
0133 do_div(tmp64, duty100);
0134 *speed = MIN((uint32_t)tmp64, 255);
0135
0136 return 0;
0137 }
0138
0139 int vega20_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr,
0140 uint32_t speed)
0141 {
0142 struct amdgpu_device *adev = hwmgr->adev;
0143 uint32_t duty100;
0144 uint32_t duty;
0145 uint64_t tmp64;
0146
0147 speed = MIN(speed, 255);
0148
0149 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
0150 vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
0151
0152 duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
0153 CG_FDO_CTRL1, FMAX_DUTY100);
0154
0155 if (duty100 == 0)
0156 return -EINVAL;
0157
0158 tmp64 = (uint64_t)speed * duty100;
0159 do_div(tmp64, 255);
0160 duty = (uint32_t)tmp64;
0161
0162 WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
0163 REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
0164 CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
0165
0166 return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
0167 }
0168
0169 int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
0170 struct phm_fan_speed_info *fan_speed_info)
0171 {
0172 memset(fan_speed_info, 0, sizeof(*fan_speed_info));
0173 fan_speed_info->supports_percent_read = true;
0174 fan_speed_info->supports_percent_write = true;
0175 fan_speed_info->supports_rpm_read = true;
0176 fan_speed_info->supports_rpm_write = true;
0177
0178 return 0;
0179 }
0180
0181 int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
0182 {
0183 *speed = 0;
0184
0185 return vega20_get_current_rpm(hwmgr, speed);
0186 }
0187
0188 int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
0189 {
0190 struct amdgpu_device *adev = hwmgr->adev;
0191 uint32_t tach_period, crystal_clock_freq;
0192 int result = 0;
0193
0194 if (!speed)
0195 return -EINVAL;
0196
0197 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) {
0198 result = vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
0199 if (result)
0200 return result;
0201 }
0202
0203 crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
0204 tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
0205 WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
0206 REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
0207 CG_TACH_CTRL, TARGET_PERIOD,
0208 tach_period));
0209
0210 return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
0211 }
0212
0213
0214
0215
0216
0217
0218 int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr)
0219 {
0220 struct amdgpu_device *adev = hwmgr->adev;
0221 int temp = 0;
0222
0223 temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
0224
0225 temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
0226 CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
0227
0228 temp = temp & 0x1ff;
0229
0230 temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
0231 return temp;
0232 }
0233
0234
0235
0236
0237
0238
0239
0240
0241 static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
0242 struct PP_TemperatureRange *range)
0243 {
0244 struct phm_ppt_v3_information *pptable_information =
0245 (struct phm_ppt_v3_information *)hwmgr->pptable;
0246 struct amdgpu_device *adev = hwmgr->adev;
0247 int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP;
0248 int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP;
0249 uint32_t val;
0250
0251
0252 if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
0253 low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
0254 if (high > pptable_information->us_software_shutdown_temp)
0255 high = pptable_information->us_software_shutdown_temp;
0256
0257 if (low > high)
0258 return -EINVAL;
0259
0260 val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
0261
0262 val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
0263 val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
0264 val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
0265 val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
0266 val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
0267
0268 WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
0269
0270 return 0;
0271 }
0272
0273
0274
0275
0276
0277
0278 static int vega20_thermal_enable_alert(struct pp_hwmgr *hwmgr)
0279 {
0280 struct amdgpu_device *adev = hwmgr->adev;
0281 uint32_t val = 0;
0282
0283 val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
0284 val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
0285 val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
0286
0287 WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
0288
0289 return 0;
0290 }
0291
0292
0293
0294
0295
0296 int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr)
0297 {
0298 struct amdgpu_device *adev = hwmgr->adev;
0299
0300 WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
0301
0302 return 0;
0303 }
0304
0305
0306
0307
0308
0309
0310 int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
0311 {
0312 int result = vega20_thermal_disable_alert(hwmgr);
0313
0314 return result;
0315 }
0316
0317
0318
0319
0320
0321 static int vega20_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
0322 {
0323 int ret;
0324 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
0325 PPTable_t *table = &(data->smc_state_table.pp_table);
0326
0327 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
0328 PPSMC_MSG_SetFanTemperatureTarget,
0329 (uint32_t)table->FanTargetTemperature,
0330 NULL);
0331
0332 return ret;
0333 }
0334
0335 int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr,
0336 struct PP_TemperatureRange *range)
0337 {
0338 int ret = 0;
0339
0340 if (range == NULL)
0341 return -EINVAL;
0342
0343 ret = vega20_thermal_set_temperature_range(hwmgr, range);
0344 if (ret)
0345 return ret;
0346
0347 ret = vega20_thermal_enable_alert(hwmgr);
0348 if (ret)
0349 return ret;
0350
0351 ret = vega20_thermal_setup_fan_table(hwmgr);
0352
0353 return ret;
0354 };