/** * Set the requested temperature range for high and low alert signals * * @param hwmgr The address of the hardware manager. * @param range Temperature range to be programmed for high and low alert signals * @exception PP_Result_BadInput if the input data is not valid. */ static int smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, uint32_t low_temp, uint32_t high_temp) { uint32_t low = SMU7_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; uint32_t high = SMU7_THERMAL_MAXIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (low < low_temp) low = low_temp; if (high > high_temp) high = high_temp; if (low > high) return -EINVAL; PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL, DIG_THERM_DPM, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); return 0; }
/** * Reset Fan Speed Control to default mode. * @param hwmgr the address of the powerplay hardware manager. * @exception Should always succeed. */ static int iceland_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) { if (!hwmgr->fan_ctrl_is_in_default_mode) { PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN, hwmgr->tmin); hwmgr->fan_ctrl_is_in_default_mode = true; } return 0; }
/** * Programs thermal controller one-time setting registers * * @param hwmgr The address of the hardware manager. */ static int iceland_thermal_initialize(struct pp_hwmgr *hwmgr) { if (0 != hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_TACH_CTRL, EDGE_PER_REV, hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28); return 0; }
/** * Set Fan Speed Control to static mode, so that the user can decide what speed to use. * @param hwmgr the address of the powerplay hardware manager. * mode the fan control mode, 0 default, 1 by percent, 5, by RPM * @exception Should always succeed. */ int iceland_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) { if (hwmgr->fan_ctrl_is_in_default_mode) { hwmgr->fan_ctrl_default_mode = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE); hwmgr->tmin = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN); hwmgr->fan_ctrl_is_in_default_mode = false; } PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN, 0); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE, mode); return 0; }
/** * Set Fan Speed in percent. * @param hwmgr the address of the powerplay hardware manager. * @param speed is the percentage value (0% - 100%) to be set. * @exception Fails is the 100% setting appears to be 0. */ int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed) { uint32_t duty100; uint32_t duty; uint64_t tmp64; if (hwmgr->thermal_controller.fanInfo.bNoFan) return 0; if (speed > 100) speed = 100; if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) smu7_fan_ctrl_stop_smc_fan_control(hwmgr); duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); if (duty100 == 0) return -EINVAL; tmp64 = (uint64_t)speed * duty100; do_div(tmp64, 100); duty = (uint32_t)tmp64; PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL0, FDO_STATIC_DUTY, duty); return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); }
/** * Set Fan Speed in RPM. * @param hwmgr the address of the powerplay hardware manager. * @param speed is the percentage value (min - max) to be set. * @exception Fails is the speed not lie between min and max. */ int polaris10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) { uint32_t tach_period; uint32_t crystal_clock_freq; if (hwmgr->thermal_controller.fanInfo.bNoFan || (hwmgr->thermal_controller.fanInfo. ucTachometerPulsesPerRevolution == 0) || (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) return 0; if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) polaris10_fan_ctrl_stop_smc_fan_control(hwmgr); crystal_clock_freq = tonga_get_xclk(hwmgr); tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_TACH_STATUS, TACH_PERIOD, tach_period); return polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); }
/** * Set Fan Speed in percent. * @param hwmgr the address of the powerplay hardware manager. * @param speed is the percentage value (0% - 100%) to be set. * @exception Fails is the 100% setting appears to be 0. */ int iceland_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed) { uint32_t duty100; uint32_t duty; uint64_t tmp64; if (hwmgr->thermal_controller.fanInfo.bNoFan) return -EINVAL; if (speed > 100) { pr_warning("Cannot set more than 100%% duty cycle. Set it to 100.\n"); speed = 100; } if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) iceland_fan_ctrl_stop_smc_fan_control(hwmgr); duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); if (0 == duty100) return -EINVAL; tmp64 = (uint64_t)speed * duty100; do_div(tmp64, 100); duty = (uint32_t)tmp64; PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL0, FDO_STATIC_DUTY, duty); return iceland_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); }
/** * Disable thermal alerts on the RV770 thermal controller. * @param hwmgr The address of the hardware manager. */ static int iceland_thermal_disable_alert(struct pp_hwmgr *hwmgr) { uint32_t alert; alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK); alert |= (ICELAND_THERMAL_HIGH_ALERT_MASK | ICELAND_THERMAL_LOW_ALERT_MASK); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK, alert); /* send message to SMU to disable internal thermal interrupts */ return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable) == 0) ? 0 : -1; }
/** * Enable thermal alerts on the RV770 thermal controller. * * @param hwmgr The address of the hardware manager. */ static void smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) { uint32_t alert; alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK); alert &= ~(SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK, alert); /* send message to SMU to enable internal thermal interrupts */ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Enable); }
/** * Set Fan Speed in RPM. * @param hwmgr the address of the powerplay hardware manager. * @param speed is the percentage value (min - max) to be set. * @exception Fails is the speed not lie between min and max. */ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) { uint32_t tach_period; uint32_t crystal_clock_freq; if (hwmgr->thermal_controller.fanInfo.bNoFan || (hwmgr->thermal_controller.fanInfo. ucTachometerPulsesPerRevolution == 0) || (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) return 0; if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) smu7_fan_ctrl_stop_smc_fan_control(hwmgr); crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_TACH_STATUS, TACH_PERIOD, tach_period); return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); }