Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/powerplay/vega20: enable fan RPM and pwm settings V2

Manual fan RPM and pwm setting on vega20 are
available now.

V2: correct the register for fan speed setting and
avoid divide-by-zero

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Evan Quan and committed by
Alex Deucher
031db090 42fae995

+207 -4
+12
drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
··· 26 26 #define mmCG_MULT_THERMAL_STATUS 0x005f 27 27 #define mmCG_MULT_THERMAL_STATUS_BASE_IDX 0 28 28 29 + #define mmCG_FDO_CTRL0 0x0067 30 + #define mmCG_FDO_CTRL0_BASE_IDX 0 31 + 32 + #define mmCG_FDO_CTRL1 0x0068 33 + #define mmCG_FDO_CTRL1_BASE_IDX 0 34 + 35 + #define mmCG_FDO_CTRL2 0x0069 36 + #define mmCG_FDO_CTRL2_BASE_IDX 0 37 + 38 + #define mmCG_TACH_CTRL 0x006a 39 + #define mmCG_TACH_CTRL_BASE_IDX 0 40 + 29 41 #define mmTHM_THERMAL_INT_ENA 0x000a 30 42 #define mmTHM_THERMAL_INT_ENA_BASE_IDX 0 31 43 #define mmTHM_THERMAL_INT_CTRL 0x000b
+10
drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h
··· 28 28 #define CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT 0x9 29 29 #define CG_MULT_THERMAL_STATUS__ASIC_MAX_TEMP_MASK 0x000001FFL 30 30 #define CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK 0x0003FE00L 31 + #define CG_FDO_CTRL2__TMIN__SHIFT 0x0 32 + #define CG_FDO_CTRL2__TMIN_MASK 0x000000FFL 33 + #define CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT 0xb 34 + #define CG_FDO_CTRL2__FDO_PWM_MODE_MASK 0x00003800L 35 + #define CG_FDO_CTRL1__FMAX_DUTY100__SHIFT 0x0 36 + #define CG_FDO_CTRL1__FMAX_DUTY100_MASK 0x000000FFL 37 + #define CG_FDO_CTRL0__FDO_STATIC_DUTY__SHIFT 0x0 38 + #define CG_FDO_CTRL0__FDO_STATIC_DUTY_MASK 0x000000FFL 39 + #define CG_TACH_CTRL__TARGET_PERIOD__SHIFT 0x3 40 + #define CG_TACH_CTRL__TARGET_PERIOD_MASK 0xFFFFFFF8L 31 41 32 42 //THM_THERMAL_INT_ENA 33 43 #define THM_THERMAL_INT_ENA__THERM_INTH_SET__SHIFT 0x0
+27
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
··· 2289 2289 return AMD_FAN_CTRL_AUTO; 2290 2290 } 2291 2291 2292 + static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) 2293 + { 2294 + switch (mode) { 2295 + case AMD_FAN_CTRL_NONE: 2296 + vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100); 2297 + break; 2298 + case AMD_FAN_CTRL_MANUAL: 2299 + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 2300 + vega20_fan_ctrl_stop_smc_fan_control(hwmgr); 2301 + break; 2302 + case AMD_FAN_CTRL_AUTO: 2303 + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 2304 + vega20_fan_ctrl_start_smc_fan_control(hwmgr); 2305 + break; 2306 + default: 2307 + break; 2308 + } 2309 + } 2310 + 2292 2311 static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr, 2293 2312 struct amd_pp_simple_clock_info *info) 2294 2313 { ··· 3471 3452 .disable_smc_firmware_ctf = 3472 3453 vega20_thermal_disable_alert, 3473 3454 /* fan control related */ 3455 + .get_fan_speed_percent = 3456 + vega20_fan_ctrl_get_fan_speed_percent, 3457 + .set_fan_speed_percent = 3458 + vega20_fan_ctrl_set_fan_speed_percent, 3474 3459 .get_fan_speed_info = 3475 3460 vega20_fan_ctrl_get_fan_speed_info, 3476 3461 .get_fan_speed_rpm = 3477 3462 vega20_fan_ctrl_get_fan_speed_rpm, 3463 + .set_fan_speed_rpm = 3464 + vega20_fan_ctrl_set_fan_speed_rpm, 3478 3465 .get_fan_control_mode = 3479 3466 vega20_get_fan_control_mode, 3467 + .set_fan_control_mode = 3468 + vega20_set_fan_control_mode, 3480 3469 /* smu memory related */ 3481 3470 .notify_cac_buffer_info = 3482 3471 vega20_notify_cac_buffer_info,
+149 -2
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c
··· 29 29 #include "soc15_common.h" 30 30 #include "pp_debug.h" 31 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 + 32 104 static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm) 33 105 { 34 106 int ret = 0; ··· 114 42 return 0; 115 43 } 116 44 45 + int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, 46 + uint32_t *speed) 47 + { 48 + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 49 + PPTable_t *pp_table = &(data->smc_state_table.pp_table); 50 + uint32_t current_rpm, percent = 0; 51 + int ret = 0; 52 + 53 + ret = vega20_get_current_rpm(hwmgr, &current_rpm); 54 + if (ret) 55 + return ret; 56 + 57 + percent = current_rpm * 100 / pp_table->FanMaximumRpm; 58 + 59 + *speed = percent > 100 ? 100 : percent; 60 + 61 + return 0; 62 + } 63 + 64 + int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, 65 + uint32_t speed) 66 + { 67 + struct amdgpu_device *adev = hwmgr->adev; 68 + uint32_t duty100; 69 + uint32_t duty; 70 + uint64_t tmp64; 71 + 72 + if (speed > 100) 73 + speed = 100; 74 + 75 + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 76 + vega20_fan_ctrl_stop_smc_fan_control(hwmgr); 77 + 78 + duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), 79 + CG_FDO_CTRL1, FMAX_DUTY100); 80 + 81 + if (duty100 == 0) 82 + return -EINVAL; 83 + 84 + tmp64 = (uint64_t)speed * duty100; 85 + do_div(tmp64, 100); 86 + duty = (uint32_t)tmp64; 87 + 88 + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, 89 + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), 90 + CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); 91 + 92 + return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); 93 + } 94 + 117 95 int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, 118 96 struct phm_fan_speed_info *fan_speed_info) 119 97 { 120 98 memset(fan_speed_info, 0, sizeof(*fan_speed_info)); 121 - fan_speed_info->supports_percent_read = false; 122 - fan_speed_info->supports_percent_write = false; 99 + fan_speed_info->supports_percent_read = true; 100 + fan_speed_info->supports_percent_write = true; 123 101 fan_speed_info->supports_rpm_read = true; 124 102 fan_speed_info->supports_rpm_write = true; 125 103 ··· 181 59 *speed = 0; 182 60 183 61 return vega20_get_current_rpm(hwmgr, speed); 62 + } 63 + 64 + int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) 65 + { 66 + struct amdgpu_device *adev = hwmgr->adev; 67 + uint32_t tach_period, crystal_clock_freq; 68 + int result = 0; 69 + 70 + if (!speed) 71 + return -EINVAL; 72 + 73 + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { 74 + result = vega20_fan_ctrl_stop_smc_fan_control(hwmgr); 75 + if (result) 76 + return result; 77 + } 78 + 79 + crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); 80 + tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); 81 + WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, 82 + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), 83 + CG_TACH_CTRL, TARGET_PERIOD, 84 + tach_period)); 85 + 86 + return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); 184 87 } 185 88 186 89 /**
+9 -2
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h
··· 50 50 #define FDO_PWM_MODE_STATIC_RPM 5 51 51 52 52 extern int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr); 53 - extern int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); 54 53 extern int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, 55 54 struct phm_fan_speed_info *fan_speed_info); 56 - extern int vega20_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); 57 55 extern int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, 58 56 uint32_t *speed); 57 + extern int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, 58 + uint32_t speed); 59 + extern int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, 60 + uint32_t *speed); 61 + extern int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, 62 + uint32_t speed); 63 + extern int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); 64 + extern int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); 59 65 extern int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr); 60 66 extern int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr, 61 67 struct PP_TemperatureRange *range); 68 + extern int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); 62 69 63 70 #endif 64 71