Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2017 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 "vega12_thermal.h"
0025 #include "vega12_hwmgr.h"
0026 #include "vega12_smumgr.h"
0027 #include "vega12_ppsmc.h"
0028 #include "vega12_inc.h"
0029 #include "soc15_common.h"
0030 #include "pp_debug.h"
0031 
0032 static int vega12_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
0033 {
0034     PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
0035                 PPSMC_MSG_GetCurrentRpm,
0036                 current_rpm),
0037             "Attempt to get current RPM from SMC Failed!",
0038             return -EINVAL);
0039 
0040     return 0;
0041 }
0042 
0043 int vega12_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
0044         struct phm_fan_speed_info *fan_speed_info)
0045 {
0046     memset(fan_speed_info, 0, sizeof(*fan_speed_info));
0047     fan_speed_info->supports_percent_read = false;
0048     fan_speed_info->supports_percent_write = false;
0049     fan_speed_info->supports_rpm_read = true;
0050     fan_speed_info->supports_rpm_write = true;
0051 
0052     return 0;
0053 }
0054 
0055 int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
0056 {
0057     *speed = 0;
0058 
0059     return vega12_get_current_rpm(hwmgr, speed);
0060 }
0061 
0062 /**
0063  * vega12_enable_fan_control_feature -Enables the SMC Fan Control Feature.
0064  *
0065  * @hwmgr: the address of the powerplay hardware manager.
0066  * Return:   0 on success. -1 otherwise.
0067  */
0068 static int vega12_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
0069 {
0070 #if 0
0071     struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
0072 
0073     if (data->smu_features[GNLD_FAN_CONTROL].supported) {
0074         PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(
0075                 hwmgr, true,
0076                 data->smu_features[GNLD_FAN_CONTROL].
0077                 smu_feature_bitmap),
0078                 "Attempt to Enable FAN CONTROL feature Failed!",
0079                 return -1);
0080         data->smu_features[GNLD_FAN_CONTROL].enabled = true;
0081     }
0082 #endif
0083     return 0;
0084 }
0085 
0086 static int vega12_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
0087 {
0088 #if 0
0089     struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
0090 
0091     if (data->smu_features[GNLD_FAN_CONTROL].supported) {
0092         PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(
0093                 hwmgr, false,
0094                 data->smu_features[GNLD_FAN_CONTROL].
0095                 smu_feature_bitmap),
0096                 "Attempt to Enable FAN CONTROL feature Failed!",
0097                 return -1);
0098         data->smu_features[GNLD_FAN_CONTROL].enabled = false;
0099     }
0100 #endif
0101     return 0;
0102 }
0103 
0104 int vega12_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
0105 {
0106     struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
0107 
0108     if (data->smu_features[GNLD_FAN_CONTROL].supported)
0109         PP_ASSERT_WITH_CODE(
0110                 !vega12_enable_fan_control_feature(hwmgr),
0111                 "Attempt to Enable SMC FAN CONTROL Feature Failed!",
0112                 return -1);
0113 
0114     return 0;
0115 }
0116 
0117 
0118 int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
0119 {
0120     struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
0121 
0122     if (data->smu_features[GNLD_FAN_CONTROL].supported)
0123         PP_ASSERT_WITH_CODE(!vega12_disable_fan_control_feature(hwmgr),
0124                 "Attempt to Disable SMC FAN CONTROL Feature Failed!",
0125                 return -1);
0126 
0127     return 0;
0128 }
0129 
0130 /**
0131  * vega12_fan_ctrl_reset_fan_speed_to_default - Reset Fan Speed to default.
0132  * @hwmgr:  the address of the powerplay hardware manager.
0133  * Exception Always succeeds.
0134  */
0135 int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
0136 {
0137     return vega12_fan_ctrl_start_smc_fan_control(hwmgr);
0138 }
0139 
0140 /**
0141  * vega12_thermal_get_temperature - Reads the remote temperature from the SIslands thermal controller.
0142  *
0143  * @hwmgr: The address of the hardware manager.
0144  */
0145 int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr)
0146 {
0147     struct amdgpu_device *adev = hwmgr->adev;
0148     int temp = 0;
0149 
0150     temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
0151 
0152     temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
0153             CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
0154 
0155     temp = temp & 0x1ff;
0156 
0157     temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
0158     return temp;
0159 }
0160 
0161 /**
0162  * vega12_thermal_set_temperature_range - Set the requested temperature range
0163  *                                        for high and low alert signals
0164  *
0165  * @hwmgr: The address of the hardware manager.
0166  * @range: Temperature range to be programmed for
0167  *           high and low alert signals
0168  * Exception: PP_Result_BadInput if the input data is not valid.
0169  */
0170 static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
0171         struct PP_TemperatureRange *range)
0172 {
0173     struct phm_ppt_v3_information *pptable_information =
0174         (struct phm_ppt_v3_information *)hwmgr->pptable;
0175     struct amdgpu_device *adev = hwmgr->adev;
0176     int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP;
0177     int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP;
0178     uint32_t val;
0179 
0180     /* compare them in unit celsius degree */
0181     if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
0182         low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
0183     if (high > pptable_information->us_software_shutdown_temp)
0184         high = pptable_information->us_software_shutdown_temp;
0185 
0186     if (low > high)
0187         return -EINVAL;
0188 
0189     val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
0190 
0191     val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
0192     val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
0193     val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
0194     val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
0195     val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
0196 
0197     WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
0198 
0199     return 0;
0200 }
0201 
0202 /**
0203  * vega12_thermal_enable_alert - Enable thermal alerts on the RV770 thermal controller.
0204  *
0205  * @hwmgr: The address of the hardware manager.
0206  */
0207 static int vega12_thermal_enable_alert(struct pp_hwmgr *hwmgr)
0208 {
0209     struct amdgpu_device *adev = hwmgr->adev;
0210     uint32_t val = 0;
0211 
0212     val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
0213     val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
0214     val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
0215 
0216     WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
0217 
0218     return 0;
0219 }
0220 
0221 /**
0222  * vega12_thermal_disable_alert - Disable thermal alerts on the RV770 thermal controller.
0223  * @hwmgr: The address of the hardware manager.
0224  */
0225 int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr)
0226 {
0227     struct amdgpu_device *adev = hwmgr->adev;
0228 
0229     WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
0230 
0231     return 0;
0232 }
0233 
0234 /**
0235  * vega12_thermal_stop_thermal_controller - Uninitialize the thermal controller.
0236  * Currently just disables alerts.
0237  * @hwmgr: The address of the hardware manager.
0238  */
0239 int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
0240 {
0241     int result = vega12_thermal_disable_alert(hwmgr);
0242 
0243     return result;
0244 }
0245 
0246 /**
0247  * vega12_thermal_setup_fan_table - Set up the fan table to control the fan using the SMC.
0248  * @hwmgr:  the address of the powerplay hardware manager.
0249  */
0250 static int vega12_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
0251 {
0252     int ret;
0253     struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
0254     PPTable_t *table = &(data->smc_state_table.pp_table);
0255 
0256     ret = smum_send_msg_to_smc_with_parameter(hwmgr,
0257                 PPSMC_MSG_SetFanTemperatureTarget,
0258                 (uint32_t)table->FanTargetTemperature,
0259                 NULL);
0260 
0261     return ret;
0262 }
0263 
0264 /**
0265  * vega12_thermal_start_smc_fan_control - Start the fan control on the SMC.
0266  * @hwmgr:  the address of the powerplay hardware manager.
0267  * Return:  result from set temperature range routine
0268  */
0269 static int vega12_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr)
0270 {
0271     /* If the fantable setup has failed we could have disabled
0272      * PHM_PlatformCaps_MicrocodeFanControl even after
0273      * this function was included in the table.
0274      * Make sure that we still think controlling the fan is OK.
0275      */
0276     if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
0277         vega12_fan_ctrl_start_smc_fan_control(hwmgr);
0278 
0279     return 0;
0280 }
0281 
0282 
0283 int vega12_start_thermal_controller(struct pp_hwmgr *hwmgr,
0284                 struct PP_TemperatureRange *range)
0285 {
0286     int ret = 0;
0287 
0288     if (range == NULL)
0289         return -EINVAL;
0290 
0291     ret = vega12_thermal_set_temperature_range(hwmgr, range);
0292     if (ret)
0293         return -EINVAL;
0294 
0295     vega12_thermal_enable_alert(hwmgr);
0296     /* We should restrict performance levels to low before we halt the SMC.
0297      * On the other hand we are still in boot state when we do this
0298      * so it would be pointless.
0299      * If this assumption changes we have to revisit this table.
0300      */
0301     ret = vega12_thermal_setup_fan_table(hwmgr);
0302     if (ret)
0303         return -EINVAL;
0304 
0305     vega12_thermal_start_smc_fan_control(hwmgr);
0306 
0307     return 0;
0308 };