drm/amd/powerplay: add SMU mode1 reset

From PM FW 58.26.0 for sienna cichlid, SMU mode1 reset
is support, driver sends PPSMC_MSG_Mode1Reset message
to PM FW could trigger this reset.

v2: add mode1 reset dpm interface
v3: change maro name

Signed-off-by: Likun Gao <Likun.Gao@amd.com>
Signed-off-by: Wenhui Sheng <Wenhui.Sheng@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Wenhui Sheng 2020-07-10 17:39:24 +08:00 committed by Alex Deucher
parent a4497974ed
commit ea8139d8d5
8 changed files with 104 additions and 2 deletions

View File

@ -1139,6 +1139,26 @@ int amdgpu_dpm_baco_reset(struct amdgpu_device *adev)
return 0;
}
bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev)
{
struct smu_context *smu = &adev->smu;
if (is_support_sw_smu(adev))
return smu_mode1_reset_is_support(smu);
return false;
}
int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev)
{
struct smu_context *smu = &adev->smu;
if (is_support_sw_smu(adev))
return smu_mode1_reset(smu);
return -EOPNOTSUPP;
}
int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
enum PP_SMC_POWER_PROFILE type,
bool en)

View File

@ -529,6 +529,9 @@ int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev);
bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev);
bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev);
int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev);
int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
enum pp_mp1_state mp1_state);

View File

@ -2616,6 +2616,40 @@ int smu_baco_exit(struct smu_context *smu)
return ret;
}
bool smu_mode1_reset_is_support(struct smu_context *smu)
{
bool ret = false;
if (!smu->pm_enabled)
return false;
mutex_lock(&smu->mutex);
if (smu->ppt_funcs && smu->ppt_funcs->mode1_reset_is_support)
ret = smu->ppt_funcs->mode1_reset_is_support(smu);
mutex_unlock(&smu->mutex);
return ret;
}
int smu_mode1_reset(struct smu_context *smu)
{
int ret = 0;
if (!smu->pm_enabled)
return -EOPNOTSUPP;
mutex_lock(&smu->mutex);
if (smu->ppt_funcs->mode1_reset)
ret = smu->ppt_funcs->mode1_reset(smu);
mutex_unlock(&smu->mutex);
return ret;
}
int smu_mode2_reset(struct smu_context *smu)
{
int ret = 0;

View File

@ -557,6 +557,8 @@ struct pptable_funcs {
int (*baco_set_state)(struct smu_context *smu, enum smu_baco_state state);
int (*baco_enter)(struct smu_context *smu);
int (*baco_exit)(struct smu_context *smu);
bool (*mode1_reset_is_support)(struct smu_context *smu);
int (*mode1_reset)(struct smu_context *smu);
int (*mode2_reset)(struct smu_context *smu);
int (*get_dpm_ultimate_freq)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max);
int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max);
@ -668,6 +670,8 @@ int smu_baco_get_state(struct smu_context *smu, enum smu_baco_state *state);
int smu_baco_enter(struct smu_context *smu);
int smu_baco_exit(struct smu_context *smu);
bool smu_mode1_reset_is_support(struct smu_context *smu);
int smu_mode1_reset(struct smu_context *smu);
int smu_mode2_reset(struct smu_context *smu);
extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table,

View File

@ -173,6 +173,7 @@
__SMU_DUMMY_MAP(GmiPwrDnControl), \
__SMU_DUMMY_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE), \
__SMU_DUMMY_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE), \
__SMU_DUMMY_MAP(Mode1Reset), \
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type

View File

@ -246,6 +246,8 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
int smu_v11_0_baco_enter(struct smu_context *smu);
int smu_v11_0_baco_exit(struct smu_context *smu);
int smu_v11_0_mode1_reset(struct smu_context *smu);
int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type,
uint32_t *min, uint32_t *max);

View File

@ -39,8 +39,8 @@
#include "nbio/nbio_2_3_sh_mask.h"
#include "thm/thm_11_0_2_offset.h"
#include "thm/thm_11_0_2_sh_mask.h"
#include "asic_reg/mp/mp_11_0_sh_mask.h"
#include "mp/mp_11_0_offset.h"
#include "mp/mp_11_0_sh_mask.h"
/*
* DO NOT use these for err/warn/info/debug messages.
@ -116,6 +116,7 @@ static struct smu_11_0_cmn2aisc_mapping sienna_cichlid_message_map[SMU_MSG_MAX_C
MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg),
MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME),
MSG_MAP(ArmD3, PPSMC_MSG_ArmD3),
MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset),
};
static struct smu_11_0_cmn2aisc_mapping sienna_cichlid_clk_map[SMU_CLK_COUNT] = {
@ -1779,6 +1780,28 @@ static bool sienna_cichlid_is_baco_supported(struct smu_context *smu)
return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false;
}
static bool sienna_cichlid_is_mode1_reset_supported(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
uint32_t val;
u32 smu_version;
/**
* SRIOV env will not support SMU mode1 reset
* PM FW support mode1 reset from 58.26
*/
smu_get_smc_version(smu, NULL, &smu_version);
if (amdgpu_sriov_vf(adev) || (smu_version < 0x003a1a00))
return false;
/**
* mode1 reset relies on PSP, so we should check if
* PSP is alive.
*/
val = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
return val != 0x0;
}
static int sienna_cichlid_set_thermal_range(struct smu_context *smu,
struct smu_temperature_range range)
{
@ -2547,6 +2570,8 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.baco_set_state = smu_v11_0_baco_set_state,
.baco_enter = smu_v11_0_baco_enter,
.baco_exit = smu_v11_0_baco_exit,
.mode1_reset_is_support = sienna_cichlid_is_mode1_reset_supported,
.mode1_reset = smu_v11_0_mode1_reset,
.get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq,
.set_soft_freq_limited_range = sienna_cichlid_set_soft_freq_limited_range,
.override_pcie_parameters = smu_v11_0_override_pcie_parameters,

View File

@ -63,6 +63,8 @@ MODULE_FIRMWARE("amdgpu/sienna_cichlid_smc.bin");
#define SMU11_VOLTAGE_SCALE 4
#define SMU11_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms
static int smu_v11_0_send_msg_without_waiting(struct smu_context *smu,
uint16_t msg)
{
@ -1694,6 +1696,17 @@ int smu_v11_0_baco_exit(struct smu_context *smu)
return ret;
}
int smu_v11_0_mode1_reset(struct smu_context *smu)
{
int ret = 0;
ret = smu_send_smc_msg(smu, SMU_MSG_Mode1Reset, NULL);
if (!ret)
msleep(SMU11_MODE1_RESET_WAIT_TIME_IN_MS);
return ret;
}
int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type,
uint32_t *min, uint32_t *max)
{