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

vega12_thermal.c (9220B)


      1/*
      2 * Copyright 2017 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 "vega12_thermal.h"
     25#include "vega12_hwmgr.h"
     26#include "vega12_smumgr.h"
     27#include "vega12_ppsmc.h"
     28#include "vega12_inc.h"
     29#include "soc15_common.h"
     30#include "pp_debug.h"
     31
     32static int vega12_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
     33{
     34	PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
     35				PPSMC_MSG_GetCurrentRpm,
     36				current_rpm),
     37			"Attempt to get current RPM from SMC Failed!",
     38			return -EINVAL);
     39
     40	return 0;
     41}
     42
     43int vega12_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
     44		struct phm_fan_speed_info *fan_speed_info)
     45{
     46	memset(fan_speed_info, 0, sizeof(*fan_speed_info));
     47	fan_speed_info->supports_percent_read = false;
     48	fan_speed_info->supports_percent_write = false;
     49	fan_speed_info->supports_rpm_read = true;
     50	fan_speed_info->supports_rpm_write = true;
     51
     52	return 0;
     53}
     54
     55int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
     56{
     57	*speed = 0;
     58
     59	return vega12_get_current_rpm(hwmgr, speed);
     60}
     61
     62/**
     63 * vega12_enable_fan_control_feature -Enables the SMC Fan Control Feature.
     64 *
     65 * @hwmgr: the address of the powerplay hardware manager.
     66 * Return:   0 on success. -1 otherwise.
     67 */
     68static int vega12_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
     69{
     70#if 0
     71	struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
     72
     73	if (data->smu_features[GNLD_FAN_CONTROL].supported) {
     74		PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(
     75				hwmgr, true,
     76				data->smu_features[GNLD_FAN_CONTROL].
     77				smu_feature_bitmap),
     78				"Attempt to Enable FAN CONTROL feature Failed!",
     79				return -1);
     80		data->smu_features[GNLD_FAN_CONTROL].enabled = true;
     81	}
     82#endif
     83	return 0;
     84}
     85
     86static int vega12_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
     87{
     88#if 0
     89	struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
     90
     91	if (data->smu_features[GNLD_FAN_CONTROL].supported) {
     92		PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(
     93				hwmgr, false,
     94				data->smu_features[GNLD_FAN_CONTROL].
     95				smu_feature_bitmap),
     96				"Attempt to Enable FAN CONTROL feature Failed!",
     97				return -1);
     98		data->smu_features[GNLD_FAN_CONTROL].enabled = false;
     99	}
    100#endif
    101	return 0;
    102}
    103
    104int vega12_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
    105{
    106	struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
    107
    108	if (data->smu_features[GNLD_FAN_CONTROL].supported)
    109		PP_ASSERT_WITH_CODE(
    110				!vega12_enable_fan_control_feature(hwmgr),
    111				"Attempt to Enable SMC FAN CONTROL Feature Failed!",
    112				return -1);
    113
    114	return 0;
    115}
    116
    117
    118int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
    119{
    120	struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
    121
    122	if (data->smu_features[GNLD_FAN_CONTROL].supported)
    123		PP_ASSERT_WITH_CODE(!vega12_disable_fan_control_feature(hwmgr),
    124				"Attempt to Disable SMC FAN CONTROL Feature Failed!",
    125				return -1);
    126
    127	return 0;
    128}
    129
    130/**
    131 * vega12_fan_ctrl_reset_fan_speed_to_default - Reset Fan Speed to default.
    132 * @hwmgr:  the address of the powerplay hardware manager.
    133 * Exception Always succeeds.
    134 */
    135int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
    136{
    137	return vega12_fan_ctrl_start_smc_fan_control(hwmgr);
    138}
    139
    140/**
    141 * vega12_thermal_get_temperature - Reads the remote temperature from the SIslands thermal controller.
    142 *
    143 * @hwmgr: The address of the hardware manager.
    144 */
    145int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr)
    146{
    147	struct amdgpu_device *adev = hwmgr->adev;
    148	int temp = 0;
    149
    150	temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
    151
    152	temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
    153			CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
    154
    155	temp = temp & 0x1ff;
    156
    157	temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
    158	return temp;
    159}
    160
    161/**
    162 * vega12_thermal_set_temperature_range - Set the requested temperature range
    163 *                                        for high and low alert signals
    164 *
    165 * @hwmgr: The address of the hardware manager.
    166 * @range: Temperature range to be programmed for
    167 *           high and low alert signals
    168 * Exception: PP_Result_BadInput if the input data is not valid.
    169 */
    170static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
    171		struct PP_TemperatureRange *range)
    172{
    173	struct phm_ppt_v3_information *pptable_information =
    174		(struct phm_ppt_v3_information *)hwmgr->pptable;
    175	struct amdgpu_device *adev = hwmgr->adev;
    176	int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP;
    177	int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP;
    178	uint32_t val;
    179
    180	/* compare them in unit celsius degree */
    181	if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
    182		low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
    183	if (high > pptable_information->us_software_shutdown_temp)
    184		high = pptable_information->us_software_shutdown_temp;
    185
    186	if (low > high)
    187		return -EINVAL;
    188
    189	val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
    190
    191	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
    192	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
    193	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
    194	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
    195	val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
    196
    197	WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
    198
    199	return 0;
    200}
    201
    202/**
    203 * vega12_thermal_enable_alert - Enable thermal alerts on the RV770 thermal controller.
    204 *
    205 * @hwmgr: The address of the hardware manager.
    206 */
    207static int vega12_thermal_enable_alert(struct pp_hwmgr *hwmgr)
    208{
    209	struct amdgpu_device *adev = hwmgr->adev;
    210	uint32_t val = 0;
    211
    212	val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
    213	val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
    214	val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
    215
    216	WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
    217
    218	return 0;
    219}
    220
    221/**
    222 * vega12_thermal_disable_alert - Disable thermal alerts on the RV770 thermal controller.
    223 * @hwmgr: The address of the hardware manager.
    224 */
    225int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr)
    226{
    227	struct amdgpu_device *adev = hwmgr->adev;
    228
    229	WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
    230
    231	return 0;
    232}
    233
    234/**
    235 * vega12_thermal_stop_thermal_controller - Uninitialize the thermal controller.
    236 * Currently just disables alerts.
    237 * @hwmgr: The address of the hardware manager.
    238 */
    239int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
    240{
    241	int result = vega12_thermal_disable_alert(hwmgr);
    242
    243	return result;
    244}
    245
    246/**
    247 * vega12_thermal_setup_fan_table - Set up the fan table to control the fan using the SMC.
    248 * @hwmgr:  the address of the powerplay hardware manager.
    249 */
    250static int vega12_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
    251{
    252	int ret;
    253	struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
    254	PPTable_t *table = &(data->smc_state_table.pp_table);
    255
    256	ret = smum_send_msg_to_smc_with_parameter(hwmgr,
    257				PPSMC_MSG_SetFanTemperatureTarget,
    258				(uint32_t)table->FanTargetTemperature,
    259				NULL);
    260
    261	return ret;
    262}
    263
    264/**
    265 * vega12_thermal_start_smc_fan_control - Start the fan control on the SMC.
    266 * @hwmgr:  the address of the powerplay hardware manager.
    267 * Return:  result from set temperature range routine
    268 */
    269static int vega12_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr)
    270{
    271	/* If the fantable setup has failed we could have disabled
    272	 * PHM_PlatformCaps_MicrocodeFanControl even after
    273	 * this function was included in the table.
    274	 * Make sure that we still think controlling the fan is OK.
    275	 */
    276	if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
    277		vega12_fan_ctrl_start_smc_fan_control(hwmgr);
    278
    279	return 0;
    280}
    281
    282
    283int vega12_start_thermal_controller(struct pp_hwmgr *hwmgr,
    284				struct PP_TemperatureRange *range)
    285{
    286	int ret = 0;
    287
    288	if (range == NULL)
    289		return -EINVAL;
    290
    291	ret = vega12_thermal_set_temperature_range(hwmgr, range);
    292	if (ret)
    293		return -EINVAL;
    294
    295	vega12_thermal_enable_alert(hwmgr);
    296	/* We should restrict performance levels to low before we halt the SMC.
    297	 * On the other hand we are still in boot state when we do this
    298	 * so it would be pointless.
    299	 * If this assumption changes we have to revisit this table.
    300	 */
    301	ret = vega12_thermal_setup_fan_table(hwmgr);
    302	if (ret)
    303		return -EINVAL;
    304
    305	vega12_thermal_start_smc_fan_control(hwmgr);
    306
    307	return 0;
    308};