cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vega20_thermal.c (9926B)


      1/*
      2 * Copyright 2018 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 */
     23
     24#include "vega20_thermal.h"
     25#include "vega20_hwmgr.h"
     26#include "vega20_smumgr.h"
     27#include "vega20_ppsmc.h"
     28#include "vega20_inc.h"
     29#include "soc15_common.h"
     30#include "pp_debug.h"
     31
     32static 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
     51int 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
     61static 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
     80int 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
     90static 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
    104static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
    105{
    106	int ret = 0;
    107
    108	PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
    109				PPSMC_MSG_GetCurrentRpm,
    110				current_rpm)) == 0,
    111			"Attempt to get current RPM from SMC Failed!",
    112			return ret);
    113
    114	return 0;
    115}
    116
    117int vega20_fan_ctrl_get_fan_speed_pwm(struct pp_hwmgr *hwmgr,
    118		uint32_t *speed)
    119{
    120	struct amdgpu_device *adev = hwmgr->adev;
    121	uint32_t duty100, duty;
    122	uint64_t tmp64;
    123
    124	duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
    125				CG_FDO_CTRL1, FMAX_DUTY100);
    126	duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS),
    127				CG_THERMAL_STATUS, FDO_PWM_DUTY);
    128
    129	if (!duty100)
    130		return -EINVAL;
    131
    132	tmp64 = (uint64_t)duty * 255;
    133	do_div(tmp64, duty100);
    134	*speed = MIN((uint32_t)tmp64, 255);
    135
    136	return 0;
    137}
    138
    139int vega20_fan_ctrl_set_fan_speed_pwm(struct pp_hwmgr *hwmgr,
    140		uint32_t speed)
    141{
    142	struct amdgpu_device *adev = hwmgr->adev;
    143	uint32_t duty100;
    144	uint32_t duty;
    145	uint64_t tmp64;
    146
    147	speed = MIN(speed, 255);
    148
    149	if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
    150		vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
    151
    152	duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
    153				    CG_FDO_CTRL1, FMAX_DUTY100);
    154
    155	if (duty100 == 0)
    156		return -EINVAL;
    157
    158	tmp64 = (uint64_t)speed * duty100;
    159	do_div(tmp64, 255);
    160	duty = (uint32_t)tmp64;
    161
    162	WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
    163		REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
    164			CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
    165
    166	return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
    167}
    168
    169int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
    170		struct phm_fan_speed_info *fan_speed_info)
    171{
    172	memset(fan_speed_info, 0, sizeof(*fan_speed_info));
    173	fan_speed_info->supports_percent_read = true;
    174	fan_speed_info->supports_percent_write = true;
    175	fan_speed_info->supports_rpm_read = true;
    176	fan_speed_info->supports_rpm_write = true;
    177
    178	return 0;
    179}
    180
    181int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
    182{
    183	*speed = 0;
    184
    185	return vega20_get_current_rpm(hwmgr, speed);
    186}
    187
    188int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
    189{
    190	struct amdgpu_device *adev = hwmgr->adev;
    191	uint32_t tach_period, crystal_clock_freq;
    192	int result = 0;
    193
    194	if (!speed)
    195		return -EINVAL;
    196
    197	if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) {
    198		result = vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
    199		if (result)
    200			return result;
    201	}
    202
    203	crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
    204	tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
    205	WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
    206			REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
    207				CG_TACH_CTRL, TARGET_PERIOD,
    208				tach_period));
    209
    210	return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
    211}
    212
    213/**
    214 * vega20_thermal_get_temperature - Reads the remote temperature from the SIslands thermal controller.
    215 *
    216 * @hwmgr: The address of the hardware manager.
    217 */
    218int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr)
    219{
    220	struct amdgpu_device *adev = hwmgr->adev;
    221	int temp = 0;
    222
    223	temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
    224
    225	temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
    226			CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
    227
    228	temp = temp & 0x1ff;
    229
    230	temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
    231	return temp;
    232}
    233
    234/**
    235 * vega20_thermal_set_temperature_range - Set the requested temperature range for high and low alert signals
    236 *
    237 * @hwmgr: The address of the hardware manager.
    238 * @range: Temperature range to be programmed for high and low alert signals
    239 * Exception: PP_Result_BadInput if the input data is not valid.
    240 */
    241static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
    242		struct PP_TemperatureRange *range)
    243{
    244	struct phm_ppt_v3_information *pptable_information =
    245		(struct phm_ppt_v3_information *)hwmgr->pptable;
    246	struct amdgpu_device *adev = hwmgr->adev;
    247	int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP;
    248	int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP;
    249	uint32_t val;
    250
    251	/* compare them in unit celsius degree */
    252	if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
    253		low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
    254	if (high > pptable_information->us_software_shutdown_temp)
    255		high = pptable_information->us_software_shutdown_temp;
    256
    257	if (low > high)
    258		return -EINVAL;
    259
    260	val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
    261
    262	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
    263	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
    264	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
    265	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
    266	val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
    267
    268	WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
    269
    270	return 0;
    271}
    272
    273/**
    274 * vega20_thermal_enable_alert - Enable thermal alerts on the RV770 thermal controller.
    275 *
    276 * @hwmgr: The address of the hardware manager.
    277 */
    278static int vega20_thermal_enable_alert(struct pp_hwmgr *hwmgr)
    279{
    280	struct amdgpu_device *adev = hwmgr->adev;
    281	uint32_t val = 0;
    282
    283	val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
    284	val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
    285	val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
    286
    287	WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
    288
    289	return 0;
    290}
    291
    292/**
    293 * vega20_thermal_disable_alert - Disable thermal alerts on the RV770 thermal controller.
    294 * @hwmgr: The address of the hardware manager.
    295 */
    296int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr)
    297{
    298	struct amdgpu_device *adev = hwmgr->adev;
    299
    300	WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
    301
    302	return 0;
    303}
    304
    305/**
    306 * vega20_thermal_stop_thermal_controller - Uninitialize the thermal controller.
    307 * Currently just disables alerts.
    308 * @hwmgr: The address of the hardware manager.
    309 */
    310int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
    311{
    312	int result = vega20_thermal_disable_alert(hwmgr);
    313
    314	return result;
    315}
    316
    317/**
    318 * vega20_thermal_setup_fan_table - Set up the fan table to control the fan using the SMC.
    319 * @hwmgr:  the address of the powerplay hardware manager.
    320 */
    321static int vega20_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
    322{
    323	int ret;
    324	struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
    325	PPTable_t *table = &(data->smc_state_table.pp_table);
    326
    327	ret = smum_send_msg_to_smc_with_parameter(hwmgr,
    328				PPSMC_MSG_SetFanTemperatureTarget,
    329				(uint32_t)table->FanTargetTemperature,
    330				NULL);
    331
    332	return ret;
    333}
    334
    335int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr,
    336				struct PP_TemperatureRange *range)
    337{
    338	int ret = 0;
    339
    340	if (range == NULL)
    341		return -EINVAL;
    342
    343	ret = vega20_thermal_set_temperature_range(hwmgr, range);
    344	if (ret)
    345		return ret;
    346
    347	ret = vega20_thermal_enable_alert(hwmgr);
    348	if (ret)
    349		return ret;
    350
    351	ret = vega20_thermal_setup_fan_table(hwmgr);
    352
    353	return ret;
    354};