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/Tonga/Fiji/Polaris/Iceland

(v2) Squashed the two sensor patches into one.

Signed-off-by: Tom St Denis <tom.stde...@amd.com>
---
 drivers/gpu/drm/amd/powerplay/amd_powerplay.c      | 20 +++++
 drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c     | 96 ++++++++++++++++++++++
 drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c   | 34 ++++++++
 .../gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c    | 34 ++++++++
 .../gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c  | 33 ++++++++
 drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c  | 33 ++++++++
 drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h  | 12 +++
 drivers/gpu/drm/amd/powerplay/inc/hwmgr.h          |  1 +
 8 files changed, 263 insertions(+)

diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c 
b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index b1d19409bf86..ee0368381e82 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -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);
 }
 
+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 = {
        .get_temperature = pp_dpm_get_temperature,
        .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,
        .get_mclk_od = pp_dpm_get_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,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
index 5ecef1732e20..9f3c5a8a903c 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
@@ -1857,6 +1857,101 @@ static int cz_get_max_high_clocks(struct pp_hwmgr 
*hwmgr, struct amd_pp_simple_c
        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 = {
        .backend_init = cz_hwmgr_backend_init,
        .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_clock_by_type = cz_get_clock_by_type,
        .get_max_high_clocks = cz_get_max_high_clocks,
+       .read_sensor = cz_read_sensor,
 };
 
 int cz_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
index 0d4c99b9e3f9..06aacefe5df1 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
@@ -5104,6 +5104,39 @@ static void fiji_print_current_perforce_level(
        seq_printf(m, "vce    %sabled\n", data->vce_power_gated ? "dis" : "en");
 }
 
+static int fiji_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)
+{
+       uint32_t sclk, mclk, activity_percent;
+       uint32_t offset;
+       struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+       switch (idx) {
+       case AMDGPU_PP_SENSOR_GFX_SCLK:
+               smum_send_msg_to_smc(hwmgr->smumgr, 
(PPSMC_Msg)(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)(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 + offsetof(SMU73_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 = fiji_thermal_get_temperature(hwmgr);
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+
 static int fiji_program_display_gap(struct pp_hwmgr *hwmgr)
 {
        struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
@@ -5590,6 +5623,7 @@ static const struct pp_hwmgr_func fiji_hwmgr_funcs = {
        .set_sclk_od = fiji_set_sclk_od,
        .get_mclk_od = fiji_get_mclk_od,
        .set_mclk_od = fiji_set_mclk_od,
+       .read_sensor = fiji_read_sensor,
 };
 
 int fiji_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c
index 5abe43360ec0..79b4b47d65f3 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c
@@ -5134,6 +5134,39 @@ iceland_print_current_perforce_level(struct pp_hwmgr 
*hwmgr, struct seq_file *m)
        seq_printf(m, "vce    %sabled\n", data->vce_power_gated ? "dis" : "en");
 }
 
+static int iceland_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)
+{
+       uint32_t sclk, mclk, activity_percent;
+       uint32_t offset;
+       struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
+
+       switch (idx) {
+       case AMDGPU_PP_SENSOR_GFX_SCLK:
+               smum_send_msg_to_smc(hwmgr->smumgr, 
(PPSMC_Msg)(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)(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 + offsetof(SMU71_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 = iceland_thermal_get_temperature(hwmgr);
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+
 int iceland_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr 
*hwmgr)
 {
        uint32_t num_active_displays = 0;
@@ -5663,6 +5696,7 @@ static const struct pp_hwmgr_func iceland_hwmgr_funcs = {
        .set_sclk_od = iceland_set_sclk_od,
        .get_mclk_od = iceland_get_mclk_od,
        .set_mclk_od = iceland_set_mclk_od,
+       .read_sensor = iceland_read_sensor,
 };
 
 int iceland_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c
index 970e3930452d..9e482a1a8009 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c
@@ -4009,6 +4009,38 @@ polaris10_print_current_perforce_level(struct pp_hwmgr 
*hwmgr, struct seq_file *
        seq_printf(m, "vce    %sabled\n", data->vce_power_gated ? "dis" : "en");
 }
 
+static int polaris10_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t 
*value)
+{
+       uint32_t sclk, mclk, activity_percent;
+       uint32_t offset;
+       struct polaris10_hwmgr *data = (struct polaris10_hwmgr 
*)(hwmgr->backend);
+
+       switch (idx) {
+       case AMDGPU_PP_SENSOR_GFX_SCLK:
+               smum_send_msg_to_smc(hwmgr->smumgr, 
(PPSMC_Msg)(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)(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 + offsetof(SMU74_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 = polaris10_thermal_get_temperature(hwmgr);
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
 static int polaris10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr 
*hwmgr, const void *input)
 {
        const struct phm_set_power_state_input *states =
@@ -5278,6 +5310,7 @@ static const struct pp_hwmgr_func polaris10_hwmgr_funcs = 
{
        .set_sclk_od = polaris10_set_sclk_od,
        .get_mclk_od = polaris10_get_mclk_od,
        .set_mclk_od = polaris10_set_mclk_od,
+       .read_sensor = polaris10_read_sensor,
 };
 
 int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
index 42783bf7647c..ea92a6bc4945 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
@@ -6314,6 +6314,38 @@ static int tonga_set_mclk_od(struct pp_hwmgr *hwmgr, 
uint32_t value)
        return 0;
 }
 
+static int tonga_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)
+{
+       uint32_t sclk, mclk, activity_percent;
+       uint32_t offset;
+       struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
+
+       switch (idx) {
+       case AMDGPU_PP_SENSOR_GFX_SCLK:
+               smum_send_msg_to_smc(hwmgr->smumgr, 
(PPSMC_Msg)(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)(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 + offsetof(SMU72_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 = tonga_thermal_get_temperature(hwmgr);
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
 static const struct pp_hwmgr_func tonga_hwmgr_funcs = {
        .backend_init = &tonga_hwmgr_backend_init,
        .backend_fini = &tonga_hwmgr_backend_fini,
@@ -6359,6 +6391,7 @@ static const struct pp_hwmgr_func tonga_hwmgr_funcs = {
        .set_sclk_od = tonga_set_sclk_od,
        .get_mclk_od = tonga_get_mclk_od,
        .set_mclk_od = tonga_set_mclk_od,
+       .read_sensor = tonga_read_sensor,
 };
 
 int tonga_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h 
b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
index 18f39e89a7aa..39f25e604ff3 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
@@ -29,6 +29,17 @@
 #include "amd_shared.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 {
        AMD_PP_EVENT_INITIALIZE = 0,
@@ -346,6 +357,7 @@ struct amd_powerplay_funcs {
        int (*set_sclk_od)(void *handle, uint32_t value);
        int (*get_mclk_od)(void *handle);
        int (*set_mclk_od)(void *handle, uint32_t value);
+       int (*read_sensor)(void *handle, int idx, int32_t *value);
 };
 
 struct amd_powerplay {
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h 
b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index e98748344801..310ba0ce2934 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -359,6 +359,7 @@ struct pp_hwmgr_func {
        int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
        int (*get_mclk_od)(struct pp_hwmgr *hwmgr);
        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 {
-- 
2.10.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to