Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2016 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 
0024 #include "vega10_thermal.h"
0025 #include "vega10_hwmgr.h"
0026 #include "vega10_smumgr.h"
0027 #include "vega10_ppsmc.h"
0028 #include "vega10_inc.h"
0029 #include "soc15_common.h"
0030 #include "pp_debug.h"
0031 
0032 static int vega10_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
0033 {
0034     smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentRpm, current_rpm);
0035     return 0;
0036 }
0037 
0038 int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
0039         struct phm_fan_speed_info *fan_speed_info)
0040 {
0041 
0042     if (hwmgr->thermal_controller.fanInfo.bNoFan)
0043         return 0;
0044 
0045     fan_speed_info->supports_percent_read = true;
0046     fan_speed_info->supports_percent_write = true;
0047     fan_speed_info->min_percent = 0;
0048     fan_speed_info->max_percent = 100;
0049 
0050     if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
0051         hwmgr->thermal_controller.fanInfo.
0052         ucTachometerPulsesPerRevolution) {
0053         fan_speed_info->supports_rpm_read = true;
0054         fan_speed_info->supports_rpm_write = true;
0055         fan_speed_info->min_rpm =
0056                 hwmgr->thermal_controller.fanInfo.ulMinRPM;
0057         fan_speed_info->max_rpm =
0058                 hwmgr->thermal_controller.fanInfo.ulMaxRPM;
0059     } else {
0060         fan_speed_info->min_rpm = 0;
0061         fan_speed_info->max_rpm = 0;
0062     }
0063 
0064     return 0;
0065 }
0066 
0067 int vega10_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr,
0068         uint32_t *speed)
0069 {
0070     uint32_t current_rpm;
0071     uint32_t percent = 0;
0072 
0073     if (hwmgr->thermal_controller.fanInfo.bNoFan)
0074         return 0;
0075 
0076     if (vega10_get_current_rpm(hwmgr, &current_rpm))
0077         return -1;
0078 
0079     if (hwmgr->thermal_controller.
0080             advanceFanControlParameters.usMaxFanRPM != 0)
0081         percent = current_rpm * 255 /
0082             hwmgr->thermal_controller.
0083             advanceFanControlParameters.usMaxFanRPM;
0084 
0085     *speed = MIN(percent, 255);
0086 
0087     return 0;
0088 }
0089 
0090 int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
0091 {
0092     struct amdgpu_device *adev = hwmgr->adev;
0093     struct vega10_hwmgr *data = hwmgr->backend;
0094     uint32_t tach_period;
0095     uint32_t crystal_clock_freq;
0096     int result = 0;
0097 
0098     if (hwmgr->thermal_controller.fanInfo.bNoFan)
0099         return -1;
0100 
0101     if (data->smu_features[GNLD_FAN_CONTROL].supported) {
0102         result = vega10_get_current_rpm(hwmgr, speed);
0103     } else {
0104         tach_period =
0105             REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_STATUS),
0106                       CG_TACH_STATUS,
0107                       TACH_PERIOD);
0108 
0109         if (tach_period == 0)
0110             return -EINVAL;
0111 
0112         crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
0113 
0114         *speed = 60 * crystal_clock_freq * 10000 / tach_period;
0115     }
0116 
0117     return result;
0118 }
0119 
0120 /**
0121  * vega10_fan_ctrl_set_static_mode - Set Fan Speed Control to static mode,
0122  * so that the user can decide what speed to use.
0123  * @hwmgr:  the address of the powerplay hardware manager.
0124  * @mode: the fan control mode, 0 default, 1 by percent, 5, by RPM
0125  * Exception: Should always succeed.
0126  */
0127 int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
0128 {
0129     struct amdgpu_device *adev = hwmgr->adev;
0130 
0131     if (hwmgr->fan_ctrl_is_in_default_mode) {
0132         hwmgr->fan_ctrl_default_mode =
0133             REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0134                 CG_FDO_CTRL2, FDO_PWM_MODE);
0135         hwmgr->tmin =
0136             REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0137                 CG_FDO_CTRL2, TMIN);
0138         hwmgr->fan_ctrl_is_in_default_mode = false;
0139     }
0140 
0141     WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
0142             REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0143                 CG_FDO_CTRL2, TMIN, 0));
0144     WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
0145             REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0146                 CG_FDO_CTRL2, FDO_PWM_MODE, mode));
0147 
0148     return 0;
0149 }
0150 
0151 /**
0152  * vega10_fan_ctrl_set_default_mode - Reset Fan Speed Control to default mode.
0153  * @hwmgr:  the address of the powerplay hardware manager.
0154  * Exception: Should always succeed.
0155  */
0156 int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
0157 {
0158     struct amdgpu_device *adev = hwmgr->adev;
0159 
0160     if (!hwmgr->fan_ctrl_is_in_default_mode) {
0161         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
0162             REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0163                 CG_FDO_CTRL2, FDO_PWM_MODE,
0164                 hwmgr->fan_ctrl_default_mode));
0165         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
0166             REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0167                 CG_FDO_CTRL2, TMIN,
0168                 hwmgr->tmin << CG_FDO_CTRL2__TMIN__SHIFT));
0169         hwmgr->fan_ctrl_is_in_default_mode = true;
0170     }
0171 
0172     return 0;
0173 }
0174 
0175 /**
0176  * vega10_enable_fan_control_feature - Enables the SMC Fan Control Feature.
0177  *
0178  * @hwmgr: the address of the powerplay hardware manager.
0179  * Return:   0 on success. -1 otherwise.
0180  */
0181 static int vega10_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
0182 {
0183     struct vega10_hwmgr *data = hwmgr->backend;
0184 
0185     if (data->smu_features[GNLD_FAN_CONTROL].supported) {
0186         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(
0187                 hwmgr, true,
0188                 data->smu_features[GNLD_FAN_CONTROL].
0189                 smu_feature_bitmap),
0190                 "Attempt to Enable FAN CONTROL feature Failed!",
0191                 return -1);
0192         data->smu_features[GNLD_FAN_CONTROL].enabled = true;
0193     }
0194 
0195     return 0;
0196 }
0197 
0198 static int vega10_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
0199 {
0200     struct vega10_hwmgr *data = hwmgr->backend;
0201 
0202     if (data->smu_features[GNLD_FAN_CONTROL].supported) {
0203         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(
0204                 hwmgr, false,
0205                 data->smu_features[GNLD_FAN_CONTROL].
0206                 smu_feature_bitmap),
0207                 "Attempt to Enable FAN CONTROL feature Failed!",
0208                 return -1);
0209         data->smu_features[GNLD_FAN_CONTROL].enabled = false;
0210     }
0211 
0212     return 0;
0213 }
0214 
0215 int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
0216 {
0217     if (hwmgr->thermal_controller.fanInfo.bNoFan)
0218         return -1;
0219 
0220     PP_ASSERT_WITH_CODE(!vega10_enable_fan_control_feature(hwmgr),
0221             "Attempt to Enable SMC FAN CONTROL Feature Failed!",
0222             return -1);
0223 
0224     return 0;
0225 }
0226 
0227 
0228 int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
0229 {
0230     struct vega10_hwmgr *data = hwmgr->backend;
0231 
0232     if (hwmgr->thermal_controller.fanInfo.bNoFan)
0233         return -1;
0234 
0235     if (data->smu_features[GNLD_FAN_CONTROL].supported) {
0236         PP_ASSERT_WITH_CODE(!vega10_disable_fan_control_feature(hwmgr),
0237                 "Attempt to Disable SMC FAN CONTROL Feature Failed!",
0238                 return -1);
0239     }
0240     return 0;
0241 }
0242 
0243 /**
0244  * vega10_fan_ctrl_set_fan_speed_pwm - Set Fan Speed in PWM.
0245  * @hwmgr:  the address of the powerplay hardware manager.
0246  * @speed: is the percentage value (0 - 255) to be set.
0247  */
0248 int vega10_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr,
0249         uint32_t speed)
0250 {
0251     struct amdgpu_device *adev = hwmgr->adev;
0252     uint32_t duty100;
0253     uint32_t duty;
0254     uint64_t tmp64;
0255 
0256     if (hwmgr->thermal_controller.fanInfo.bNoFan)
0257         return 0;
0258 
0259     speed = MIN(speed, 255);
0260 
0261     if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
0262         vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
0263 
0264     duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
0265                     CG_FDO_CTRL1, FMAX_DUTY100);
0266 
0267     if (duty100 == 0)
0268         return -EINVAL;
0269 
0270     tmp64 = (uint64_t)speed * duty100;
0271     do_div(tmp64, 255);
0272     duty = (uint32_t)tmp64;
0273 
0274     WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
0275         REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
0276             CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
0277 
0278     return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
0279 }
0280 
0281 /**
0282  * vega10_fan_ctrl_reset_fan_speed_to_default - Reset Fan Speed to default.
0283  * @hwmgr:  the address of the powerplay hardware manager.
0284  * Exception: Always succeeds.
0285  */
0286 int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
0287 {
0288     if (hwmgr->thermal_controller.fanInfo.bNoFan)
0289         return 0;
0290 
0291     if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
0292         return vega10_fan_ctrl_start_smc_fan_control(hwmgr);
0293     else
0294         return vega10_fan_ctrl_set_default_mode(hwmgr);
0295 }
0296 
0297 /**
0298  * vega10_fan_ctrl_set_fan_speed_rpm - Set Fan Speed in RPM.
0299  * @hwmgr:  the address of the powerplay hardware manager.
0300  * @speed: is the percentage value (min - max) to be set.
0301  * Exception: Fails is the speed not lie between min and max.
0302  */
0303 int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
0304 {
0305     struct amdgpu_device *adev = hwmgr->adev;
0306     uint32_t tach_period;
0307     uint32_t crystal_clock_freq;
0308     int result = 0;
0309 
0310     if (hwmgr->thermal_controller.fanInfo.bNoFan ||
0311         speed == 0 ||
0312         (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
0313         (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
0314         return -1;
0315 
0316     if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
0317         result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
0318 
0319     if (!result) {
0320         crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
0321         tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
0322         WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
0323                 REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
0324                     CG_TACH_CTRL, TARGET_PERIOD,
0325                     tach_period));
0326     }
0327     return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
0328 }
0329 
0330 /**
0331  * vega10_thermal_get_temperature - Reads the remote temperature from the SIslands thermal controller.
0332  *
0333  * @hwmgr: The address of the hardware manager.
0334  */
0335 int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
0336 {
0337     struct amdgpu_device *adev = hwmgr->adev;
0338     int temp;
0339 
0340     temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
0341 
0342     temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
0343             CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
0344 
0345     temp = temp & 0x1ff;
0346 
0347     temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
0348 
0349     return temp;
0350 }
0351 
0352 /**
0353  * vega10_thermal_set_temperature_range - Set the requested temperature range for high and low alert signals
0354  *
0355  * @hwmgr: The address of the hardware manager.
0356  * @range: Temperature range to be programmed for
0357  *           high and low alert signals
0358  * Exception: PP_Result_BadInput if the input data is not valid.
0359  */
0360 static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
0361         struct PP_TemperatureRange *range)
0362 {
0363     struct phm_ppt_v2_information *pp_table_info =
0364         (struct phm_ppt_v2_information *)(hwmgr->pptable);
0365     struct phm_tdp_table *tdp_table = pp_table_info->tdp_table;
0366     struct amdgpu_device *adev = hwmgr->adev;
0367     int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP;
0368     int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP;
0369     uint32_t val;
0370 
0371     /* compare them in unit celsius degree */
0372     if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
0373         low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
0374 
0375     /*
0376      * As a common sense, usSoftwareShutdownTemp should be bigger
0377      * than ThotspotLimit. For any invalid usSoftwareShutdownTemp,
0378      * we will just use the max possible setting VEGA10_THERMAL_MAXIMUM_ALERT_TEMP
0379      * to avoid false alarms.
0380      */
0381     if ((tdp_table->usSoftwareShutdownTemp >
0382          range->hotspot_crit_max / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)) {
0383         if (high > tdp_table->usSoftwareShutdownTemp)
0384             high = tdp_table->usSoftwareShutdownTemp;
0385     }
0386 
0387     if (low > high)
0388         return -EINVAL;
0389 
0390     val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
0391 
0392     val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
0393     val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
0394     val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
0395     val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
0396     val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) &
0397             (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) &
0398             (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK);
0399 
0400     WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
0401 
0402     return 0;
0403 }
0404 
0405 /**
0406  * vega10_thermal_initialize - Programs thermal controller one-time setting registers
0407  *
0408  * @hwmgr: The address of the hardware manager.
0409  */
0410 static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr)
0411 {
0412     struct amdgpu_device *adev = hwmgr->adev;
0413 
0414     if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
0415         WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
0416             REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
0417                 CG_TACH_CTRL, EDGE_PER_REV,
0418                 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1));
0419     }
0420 
0421     WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
0422         REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
0423             CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28));
0424 
0425     return 0;
0426 }
0427 
0428 /**
0429  * vega10_thermal_enable_alert - Enable thermal alerts on the RV770 thermal controller.
0430  *
0431  * @hwmgr: The address of the hardware manager.
0432  */
0433 static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr)
0434 {
0435     struct amdgpu_device *adev = hwmgr->adev;
0436     struct vega10_hwmgr *data = hwmgr->backend;
0437     uint32_t val = 0;
0438 
0439     if (data->smu_features[GNLD_FW_CTF].supported) {
0440         if (data->smu_features[GNLD_FW_CTF].enabled)
0441             printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n");
0442 
0443         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
0444                 true,
0445                 data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
0446                 "Attempt to Enable FW CTF feature Failed!",
0447                 return -1);
0448         data->smu_features[GNLD_FW_CTF].enabled = true;
0449     }
0450 
0451     val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
0452     val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
0453     val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
0454 
0455     WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
0456 
0457     return 0;
0458 }
0459 
0460 /**
0461  * vega10_thermal_disable_alert - Disable thermal alerts on the RV770 thermal controller.
0462  * @hwmgr: The address of the hardware manager.
0463  */
0464 int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr)
0465 {
0466     struct amdgpu_device *adev = hwmgr->adev;
0467     struct vega10_hwmgr *data = hwmgr->backend;
0468 
0469     if (data->smu_features[GNLD_FW_CTF].supported) {
0470         if (!data->smu_features[GNLD_FW_CTF].enabled)
0471             printk("[Thermal_EnableAlert] FW CTF Already disabled!\n");
0472 
0473 
0474         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
0475             false,
0476             data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
0477             "Attempt to disable FW CTF feature Failed!",
0478             return -1);
0479         data->smu_features[GNLD_FW_CTF].enabled = false;
0480     }
0481 
0482     WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
0483 
0484     return 0;
0485 }
0486 
0487 /**
0488  * vega10_thermal_stop_thermal_controller - Uninitialize the thermal controller.
0489  * Currently just disables alerts.
0490  * @hwmgr: The address of the hardware manager.
0491  */
0492 int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
0493 {
0494     int result = vega10_thermal_disable_alert(hwmgr);
0495 
0496     if (!hwmgr->thermal_controller.fanInfo.bNoFan)
0497         vega10_fan_ctrl_set_default_mode(hwmgr);
0498 
0499     return result;
0500 }
0501 
0502 /**
0503  * vega10_thermal_setup_fan_table - Set up the fan table to control the fan using the SMC.
0504  * @hwmgr:  the address of the powerplay hardware manager.
0505  * Return:   result from set temperature range routine
0506  */
0507 static int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
0508 {
0509     int ret;
0510     struct vega10_hwmgr *data = hwmgr->backend;
0511     PPTable_t *table = &(data->smc_state_table.pp_table);
0512 
0513     if (!data->smu_features[GNLD_FAN_CONTROL].supported)
0514         return 0;
0515 
0516     table->FanMaximumRpm = (uint16_t)hwmgr->thermal_controller.
0517             advanceFanControlParameters.usMaxFanRPM;
0518     table->FanThrottlingRpm = hwmgr->thermal_controller.
0519             advanceFanControlParameters.usFanRPMMaxLimit;
0520     table->FanAcousticLimitRpm = (uint16_t)(hwmgr->thermal_controller.
0521             advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
0522     table->FanTargetTemperature = hwmgr->thermal_controller.
0523             advanceFanControlParameters.usTMax;
0524 
0525     smum_send_msg_to_smc_with_parameter(hwmgr,
0526                 PPSMC_MSG_SetFanTemperatureTarget,
0527                 (uint32_t)table->FanTargetTemperature,
0528                 NULL);
0529 
0530     table->FanPwmMin = hwmgr->thermal_controller.
0531             advanceFanControlParameters.usPWMMin * 255 / 100;
0532     table->FanTargetGfxclk = (uint16_t)(hwmgr->thermal_controller.
0533             advanceFanControlParameters.ulTargetGfxClk);
0534     table->FanGainEdge = hwmgr->thermal_controller.
0535             advanceFanControlParameters.usFanGainEdge;
0536     table->FanGainHotspot = hwmgr->thermal_controller.
0537             advanceFanControlParameters.usFanGainHotspot;
0538     table->FanGainLiquid = hwmgr->thermal_controller.
0539             advanceFanControlParameters.usFanGainLiquid;
0540     table->FanGainVrVddc = hwmgr->thermal_controller.
0541             advanceFanControlParameters.usFanGainVrVddc;
0542     table->FanGainVrMvdd = hwmgr->thermal_controller.
0543             advanceFanControlParameters.usFanGainVrMvdd;
0544     table->FanGainPlx = hwmgr->thermal_controller.
0545             advanceFanControlParameters.usFanGainPlx;
0546     table->FanGainHbm = hwmgr->thermal_controller.
0547             advanceFanControlParameters.usFanGainHbm;
0548     table->FanZeroRpmEnable = hwmgr->thermal_controller.
0549             advanceFanControlParameters.ucEnableZeroRPM;
0550     table->FanStopTemp = hwmgr->thermal_controller.
0551             advanceFanControlParameters.usZeroRPMStopTemperature;
0552     table->FanStartTemp = hwmgr->thermal_controller.
0553             advanceFanControlParameters.usZeroRPMStartTemperature;
0554 
0555     ret = smum_smc_table_manager(hwmgr,
0556                 (uint8_t *)(&(data->smc_state_table.pp_table)),
0557                 PPTABLE, false);
0558     if (ret)
0559         pr_info("Failed to update Fan Control Table in PPTable!");
0560 
0561     return ret;
0562 }
0563 
0564 int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr)
0565 {
0566     struct vega10_hwmgr *data = hwmgr->backend;
0567     PPTable_t *table = &(data->smc_state_table.pp_table);
0568     int ret;
0569 
0570     if (!data->smu_features[GNLD_FAN_CONTROL].supported)
0571         return 0;
0572 
0573     if (!hwmgr->thermal_controller.advanceFanControlParameters.
0574             usMGpuThrottlingRPMLimit)
0575         return 0;
0576 
0577     table->FanThrottlingRpm = hwmgr->thermal_controller.
0578             advanceFanControlParameters.usMGpuThrottlingRPMLimit;
0579 
0580     ret = smum_smc_table_manager(hwmgr,
0581                 (uint8_t *)(&(data->smc_state_table.pp_table)),
0582                 PPTABLE, false);
0583     if (ret) {
0584         pr_info("Failed to update fan control table in pptable!");
0585         return ret;
0586     }
0587 
0588     ret = vega10_disable_fan_control_feature(hwmgr);
0589     if (ret) {
0590         pr_info("Attempt to disable SMC fan control feature failed!");
0591         return ret;
0592     }
0593 
0594     ret = vega10_enable_fan_control_feature(hwmgr);
0595     if (ret)
0596         pr_info("Attempt to enable SMC fan control feature failed!");
0597 
0598     return ret;
0599 }
0600 
0601 /**
0602  * vega10_thermal_start_smc_fan_control - Start the fan control on the SMC.
0603  * @hwmgr:  the address of the powerplay hardware manager.
0604  * Return:   result from set temperature range routine
0605  */
0606 static int vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr)
0607 {
0608 /* If the fantable setup has failed we could have disabled
0609  * PHM_PlatformCaps_MicrocodeFanControl even after
0610  * this function was included in the table.
0611  * Make sure that we still think controlling the fan is OK.
0612 */
0613     if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
0614         vega10_fan_ctrl_start_smc_fan_control(hwmgr);
0615 
0616     return 0;
0617 }
0618 
0619 
0620 int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr,
0621                 struct PP_TemperatureRange *range)
0622 {
0623     int ret = 0;
0624 
0625     if (range == NULL)
0626         return -EINVAL;
0627 
0628     vega10_thermal_initialize(hwmgr);
0629     ret = vega10_thermal_set_temperature_range(hwmgr, range);
0630     if (ret)
0631         return -EINVAL;
0632 
0633     vega10_thermal_enable_alert(hwmgr);
0634 /* We should restrict performance levels to low before we halt the SMC.
0635  * On the other hand we are still in boot state when we do this
0636  * so it would be pointless.
0637  * If this assumption changes we have to revisit this table.
0638  */
0639     ret = vega10_thermal_setup_fan_table(hwmgr);
0640     if (ret)
0641         return -EINVAL;
0642 
0643     vega10_thermal_start_smc_fan_control(hwmgr);
0644 
0645     return 0;
0646 };
0647 
0648 
0649 
0650 
0651 int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
0652 {
0653     if (!hwmgr->thermal_controller.fanInfo.bNoFan) {
0654         vega10_fan_ctrl_set_default_mode(hwmgr);
0655         vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
0656     }
0657     return 0;
0658 }