drm/amd/powerplay: Add read_sensor() callback to hwmgr (v3)
Provides standardized interface to read various sensors. The API is extensible (by adding to the end of the amd_pp_sensors enumeration list. Support has been added to Carrizo/smu7 (v2) Squashed the two sensor patches into one. (v3) Updated to apply to smu7_hwmgr instead Signed-off-by: Tom St Denis <tom.stdenis@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
167ac5733c
commit
a6e3695221
|
@ -894,6 +894,25 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
|
||||||
return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
|
return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value)
|
||||||
|
{
|
||||||
|
struct pp_hwmgr *hwmgr;
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
hwmgr = ((struct pp_instance *)handle)->hwmgr;
|
||||||
|
|
||||||
|
PP_CHECK_HW(hwmgr);
|
||||||
|
|
||||||
|
if (hwmgr->hwmgr_func->read_sensor == NULL) {
|
||||||
|
printk(KERN_INFO "%s was not implemented.\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value);
|
||||||
|
}
|
||||||
|
|
||||||
const struct amd_powerplay_funcs pp_dpm_funcs = {
|
const struct amd_powerplay_funcs pp_dpm_funcs = {
|
||||||
.get_temperature = pp_dpm_get_temperature,
|
.get_temperature = pp_dpm_get_temperature,
|
||||||
.load_firmware = pp_dpm_load_fw,
|
.load_firmware = pp_dpm_load_fw,
|
||||||
|
@ -920,6 +939,7 @@ const struct amd_powerplay_funcs pp_dpm_funcs = {
|
||||||
.set_sclk_od = pp_dpm_set_sclk_od,
|
.set_sclk_od = pp_dpm_set_sclk_od,
|
||||||
.get_mclk_od = pp_dpm_get_mclk_od,
|
.get_mclk_od = pp_dpm_get_mclk_od,
|
||||||
.set_mclk_od = pp_dpm_set_mclk_od,
|
.set_mclk_od = pp_dpm_set_mclk_od,
|
||||||
|
.read_sensor = pp_dpm_read_sensor,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int amd_pp_instance_init(struct amd_pp_init *pp_init,
|
static int amd_pp_instance_init(struct amd_pp_init *pp_init,
|
||||||
|
|
|
@ -1857,6 +1857,101 @@ static int cz_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_c
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)
|
||||||
|
{
|
||||||
|
struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
|
||||||
|
|
||||||
|
struct phm_clock_voltage_dependency_table *table =
|
||||||
|
hwmgr->dyn_state.vddc_dependency_on_sclk;
|
||||||
|
|
||||||
|
struct phm_vce_clock_voltage_dependency_table *vce_table =
|
||||||
|
hwmgr->dyn_state.vce_clock_voltage_dependency_table;
|
||||||
|
|
||||||
|
struct phm_uvd_clock_voltage_dependency_table *uvd_table =
|
||||||
|
hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
|
||||||
|
|
||||||
|
uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX),
|
||||||
|
TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX);
|
||||||
|
uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
|
||||||
|
TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX);
|
||||||
|
uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
|
||||||
|
TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);
|
||||||
|
|
||||||
|
uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent;
|
||||||
|
uint16_t vddnb, vddgfx;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
switch (idx) {
|
||||||
|
case AMDGPU_PP_SENSOR_GFX_SCLK:
|
||||||
|
if (sclk_index < NUM_SCLK_LEVELS) {
|
||||||
|
sclk = table->entries[sclk_index].clk;
|
||||||
|
*value = sclk;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
case AMDGPU_PP_SENSOR_VDDNB:
|
||||||
|
tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) &
|
||||||
|
CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT;
|
||||||
|
vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp);
|
||||||
|
*value = vddnb;
|
||||||
|
return 0;
|
||||||
|
case AMDGPU_PP_SENSOR_VDDGFX:
|
||||||
|
tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) &
|
||||||
|
CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT;
|
||||||
|
vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp);
|
||||||
|
*value = vddgfx;
|
||||||
|
return 0;
|
||||||
|
case AMDGPU_PP_SENSOR_UVD_VCLK:
|
||||||
|
if (!cz_hwmgr->uvd_power_gated) {
|
||||||
|
if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
|
||||||
|
return -EINVAL;
|
||||||
|
} else {
|
||||||
|
vclk = uvd_table->entries[uvd_index].vclk;
|
||||||
|
*value = vclk;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*value = 0;
|
||||||
|
return 0;
|
||||||
|
case AMDGPU_PP_SENSOR_UVD_DCLK:
|
||||||
|
if (!cz_hwmgr->uvd_power_gated) {
|
||||||
|
if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
|
||||||
|
return -EINVAL;
|
||||||
|
} else {
|
||||||
|
dclk = uvd_table->entries[uvd_index].dclk;
|
||||||
|
*value = dclk;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*value = 0;
|
||||||
|
return 0;
|
||||||
|
case AMDGPU_PP_SENSOR_VCE_ECCLK:
|
||||||
|
if (!cz_hwmgr->vce_power_gated) {
|
||||||
|
if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
|
||||||
|
return -EINVAL;
|
||||||
|
} else {
|
||||||
|
ecclk = vce_table->entries[vce_index].ecclk;
|
||||||
|
*value = ecclk;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*value = 0;
|
||||||
|
return 0;
|
||||||
|
case AMDGPU_PP_SENSOR_GPU_LOAD:
|
||||||
|
result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity);
|
||||||
|
if (0 == result) {
|
||||||
|
activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0);
|
||||||
|
activity_percent = activity_percent > 100 ? 100 : activity_percent;
|
||||||
|
} else {
|
||||||
|
activity_percent = 50;
|
||||||
|
}
|
||||||
|
*value = activity_percent;
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct pp_hwmgr_func cz_hwmgr_funcs = {
|
static const struct pp_hwmgr_func cz_hwmgr_funcs = {
|
||||||
.backend_init = cz_hwmgr_backend_init,
|
.backend_init = cz_hwmgr_backend_init,
|
||||||
.backend_fini = cz_hwmgr_backend_fini,
|
.backend_fini = cz_hwmgr_backend_fini,
|
||||||
|
@ -1882,6 +1977,7 @@ static const struct pp_hwmgr_func cz_hwmgr_funcs = {
|
||||||
.get_current_shallow_sleep_clocks = cz_get_current_shallow_sleep_clocks,
|
.get_current_shallow_sleep_clocks = cz_get_current_shallow_sleep_clocks,
|
||||||
.get_clock_by_type = cz_get_clock_by_type,
|
.get_clock_by_type = cz_get_clock_by_type,
|
||||||
.get_max_high_clocks = cz_get_max_high_clocks,
|
.get_max_high_clocks = cz_get_max_high_clocks,
|
||||||
|
.read_sensor = cz_read_sensor,
|
||||||
};
|
};
|
||||||
|
|
||||||
int cz_hwmgr_init(struct pp_hwmgr *hwmgr)
|
int cz_hwmgr_init(struct pp_hwmgr *hwmgr)
|
||||||
|
|
|
@ -3144,6 +3144,41 @@ smu7_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
|
||||||
seq_printf(m, "vce %sabled\n", data->vce_power_gated ? "dis" : "en");
|
seq_printf(m, "vce %sabled\n", data->vce_power_gated ? "dis" : "en");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)
|
||||||
|
{
|
||||||
|
uint32_t sclk, mclk, activity_percent;
|
||||||
|
uint32_t offset;
|
||||||
|
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
|
||||||
|
|
||||||
|
switch (idx) {
|
||||||
|
case AMDGPU_PP_SENSOR_GFX_SCLK:
|
||||||
|
smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency);
|
||||||
|
sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
|
||||||
|
*value = sclk;
|
||||||
|
return 0;
|
||||||
|
case AMDGPU_PP_SENSOR_GFX_MCLK:
|
||||||
|
smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency);
|
||||||
|
mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
|
||||||
|
*value = mclk;
|
||||||
|
return 0;
|
||||||
|
case AMDGPU_PP_SENSOR_GPU_LOAD:
|
||||||
|
offset = data->soft_regs_start + smum_get_offsetof(hwmgr->smumgr,
|
||||||
|
SMU_SoftRegisters,
|
||||||
|
AverageGraphicsActivity);
|
||||||
|
|
||||||
|
activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
|
||||||
|
activity_percent += 0x80;
|
||||||
|
activity_percent >>= 8;
|
||||||
|
*value = activity_percent > 100 ? 100 : activity_percent;
|
||||||
|
return 0;
|
||||||
|
case AMDGPU_PP_SENSOR_GPU_TEMP:
|
||||||
|
*value = smu7_thermal_get_temperature(hwmgr);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
|
static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
|
||||||
{
|
{
|
||||||
const struct phm_set_power_state_input *states =
|
const struct phm_set_power_state_input *states =
|
||||||
|
@ -4315,6 +4350,7 @@ static struct pp_hwmgr_func smu7_hwmgr_funcs = {
|
||||||
.get_mclk_od = smu7_get_mclk_od,
|
.get_mclk_od = smu7_get_mclk_od,
|
||||||
.set_mclk_od = smu7_set_mclk_od,
|
.set_mclk_od = smu7_set_mclk_od,
|
||||||
.get_clock_by_type = smu7_get_clock_by_type,
|
.get_clock_by_type = smu7_get_clock_by_type,
|
||||||
|
.read_sensor = smu7_read_sensor,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
|
uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
|
||||||
|
|
|
@ -29,6 +29,17 @@
|
||||||
#include "amd_shared.h"
|
#include "amd_shared.h"
|
||||||
#include "cgs_common.h"
|
#include "cgs_common.h"
|
||||||
|
|
||||||
|
enum amd_pp_sensors {
|
||||||
|
AMDGPU_PP_SENSOR_GFX_SCLK = 0,
|
||||||
|
AMDGPU_PP_SENSOR_VDDNB,
|
||||||
|
AMDGPU_PP_SENSOR_VDDGFX,
|
||||||
|
AMDGPU_PP_SENSOR_UVD_VCLK,
|
||||||
|
AMDGPU_PP_SENSOR_UVD_DCLK,
|
||||||
|
AMDGPU_PP_SENSOR_VCE_ECCLK,
|
||||||
|
AMDGPU_PP_SENSOR_GPU_LOAD,
|
||||||
|
AMDGPU_PP_SENSOR_GFX_MCLK,
|
||||||
|
AMDGPU_PP_SENSOR_GPU_TEMP,
|
||||||
|
};
|
||||||
|
|
||||||
enum amd_pp_event {
|
enum amd_pp_event {
|
||||||
AMD_PP_EVENT_INITIALIZE = 0,
|
AMD_PP_EVENT_INITIALIZE = 0,
|
||||||
|
@ -347,6 +358,7 @@ struct amd_powerplay_funcs {
|
||||||
int (*set_sclk_od)(void *handle, uint32_t value);
|
int (*set_sclk_od)(void *handle, uint32_t value);
|
||||||
int (*get_mclk_od)(void *handle);
|
int (*get_mclk_od)(void *handle);
|
||||||
int (*set_mclk_od)(void *handle, uint32_t value);
|
int (*set_mclk_od)(void *handle, uint32_t value);
|
||||||
|
int (*read_sensor)(void *handle, int idx, int32_t *value);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct amd_powerplay {
|
struct amd_powerplay {
|
||||||
|
|
|
@ -359,6 +359,7 @@ struct pp_hwmgr_func {
|
||||||
int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
|
int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
|
||||||
int (*get_mclk_od)(struct pp_hwmgr *hwmgr);
|
int (*get_mclk_od)(struct pp_hwmgr *hwmgr);
|
||||||
int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
|
int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
|
||||||
|
int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, int32_t *value);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pp_table_func {
|
struct pp_table_func {
|
||||||
|
|
Loading…
Reference in New Issue