diff options
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay')
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 281 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 878 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/smu_types.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 656 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 277 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/renoir_ppt.h | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 714 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/smu_internal.h | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 461 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/powerplay/smu_v12_0.c | 121 |
14 files changed, 1694 insertions, 1873 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index fe4948aa662f..03125c8a2145 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -33,6 +33,7 @@ #include "navi10_ppt.h" #include "sienna_cichlid_ppt.h" #include "renoir_ppt.h" +#include "amd_pcie.h" /* * DO NOT use these for err/warn/info/debug messages. @@ -238,169 +239,48 @@ int smu_get_smc_version(struct smu_context *smu, uint32_t *if_version, uint32_t return ret; } -int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t min, uint32_t max, bool lock_needed) +int smu_set_soft_freq_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t min, + uint32_t max) { int ret = 0; if (!smu_clk_dpm_is_enabled(smu, clk_type)) return 0; - if (lock_needed) - mutex_lock(&smu->mutex); - ret = smu_set_soft_freq_limited_range(smu, clk_type, min, max); - if (lock_needed) - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_hard_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t min, uint32_t max) -{ - int ret = 0, clk_id = 0; - uint32_t param; - - if (min <= 0 && max <= 0) - return -EINVAL; - - if (!smu_clk_dpm_is_enabled(smu, clk_type)) - return 0; - - clk_id = smu_clk_get_index(smu, clk_type); - if (clk_id < 0) - return clk_id; - - if (max > 0) { - param = (uint32_t)((clk_id << 16) | (max & 0xffff)); - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMaxByFreq, - param, NULL); - if (ret) - return ret; - } + mutex_lock(&smu->mutex); - if (min > 0) { - param = (uint32_t)((clk_id << 16) | (min & 0xffff)); - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, - param, NULL); - if (ret) - return ret; - } + if (smu->ppt_funcs->set_soft_freq_limited_range) + ret = smu->ppt_funcs->set_soft_freq_limited_range(smu, + clk_type, + min, + max); + mutex_unlock(&smu->mutex); return ret; } -int smu_get_dpm_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *min, uint32_t *max, bool lock_needed) +int smu_get_dpm_freq_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) { - uint32_t clock_limit; int ret = 0; if (!min && !max) return -EINVAL; - if (lock_needed) - mutex_lock(&smu->mutex); - - if (!smu_clk_dpm_is_enabled(smu, clk_type)) { - switch (clk_type) { - case SMU_MCLK: - case SMU_UCLK: - clock_limit = smu->smu_table.boot_values.uclk; - break; - case SMU_GFXCLK: - case SMU_SCLK: - clock_limit = smu->smu_table.boot_values.gfxclk; - break; - case SMU_SOCCLK: - clock_limit = smu->smu_table.boot_values.socclk; - break; - default: - clock_limit = 0; - break; - } - - /* clock in Mhz unit */ - if (min) - *min = clock_limit / 100; - if (max) - *max = clock_limit / 100; - } else { - /* - * Todo: Use each asic(ASIC_ppt funcs) control the callbacks exposed to the - * core driver and then have helpers for stuff that is common(SMU_v11_x | SMU_v12_x funcs). - */ - ret = smu_get_dpm_ultimate_freq(smu, clk_type, min, max); - } - - if (lock_needed) - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_dpm_freq_by_index(struct smu_context *smu, enum smu_clk_type clk_type, - uint16_t level, uint32_t *value) -{ - int ret = 0, clk_id = 0; - uint32_t param; - - if (!value) - return -EINVAL; - - if (!smu_clk_dpm_is_enabled(smu, clk_type)) - return 0; - - clk_id = smu_clk_get_index(smu, clk_type); - if (clk_id < 0) - return clk_id; - - param = (uint32_t)(((clk_id & 0xffff) << 16) | (level & 0xffff)); - - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmFreqByIndex, - param, value); - if (ret) - return ret; - - /* BIT31: 0 - Fine grained DPM, 1 - Dicrete DPM - * now, we un-support it */ - *value = *value & 0x7fffffff; - - return ret; -} - -int smu_get_dpm_level_count(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *value) -{ - return smu_get_dpm_freq_by_index(smu, clk_type, 0xff, value); -} - -int smu_get_dpm_level_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *min_value, uint32_t *max_value) -{ - int ret = 0; - uint32_t level_count = 0; - - if (!min_value && !max_value) - return -EINVAL; - - if (min_value) { - /* by default, level 0 clock value as min value */ - ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, min_value); - if (ret) - return ret; - } + mutex_lock(&smu->mutex); - if (max_value) { - ret = smu_get_dpm_level_count(smu, clk_type, &level_count); - if (ret) - return ret; + if (smu->ppt_funcs->get_dpm_ultimate_freq) + ret = smu->ppt_funcs->get_dpm_ultimate_freq(smu, + clk_type, + min, + max); - ret = smu_get_dpm_freq_by_index(smu, clk_type, level_count - 1, max_value); - if (ret) - return ret; - } + mutex_unlock(&smu->mutex); return ret; } @@ -722,6 +602,7 @@ static int smu_set_funcs(struct amdgpu_device *adev) smu->od_enabled =false; break; case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: sienna_cichlid_set_ppt_funcs(smu); break; case CHIP_RENOIR: @@ -1111,9 +992,37 @@ static int smu_sw_fini(void *handle) return 0; } +static int smu_get_thermal_temperature_range(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + struct smu_temperature_range *range = + &smu->thermal_range; + int ret = 0; + + if (!smu->ppt_funcs->get_thermal_temperature_range) + return 0; + + ret = smu->ppt_funcs->get_thermal_temperature_range(smu, range); + if (ret) + return ret; + + adev->pm.dpm.thermal.min_temp = range->min; + adev->pm.dpm.thermal.max_temp = range->max; + adev->pm.dpm.thermal.max_edge_emergency_temp = range->edge_emergency_max; + adev->pm.dpm.thermal.min_hotspot_temp = range->hotspot_min; + adev->pm.dpm.thermal.max_hotspot_crit_temp = range->hotspot_crit_max; + adev->pm.dpm.thermal.max_hotspot_emergency_temp = range->hotspot_emergency_max; + adev->pm.dpm.thermal.min_mem_temp = range->mem_min; + adev->pm.dpm.thermal.max_mem_crit_temp = range->mem_crit_max; + adev->pm.dpm.thermal.max_mem_emergency_temp = range->mem_emergency_max; + + return ret; +} + static int smu_smc_hw_setup(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; + uint32_t pcie_gen = 0, pcie_width = 0; int ret; if (smu_is_dpm_running(smu) && adev->in_suspend) { @@ -1183,9 +1092,42 @@ static int smu_smc_hw_setup(struct smu_context *smu) if (!smu_is_dpm_running(smu)) dev_info(adev->dev, "dpm has been disabled\n"); - ret = smu_override_pcie_parameters(smu); - if (ret) + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) + pcie_gen = 3; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) + pcie_gen = 2; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) + pcie_gen = 1; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) + pcie_gen = 0; + + /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 + * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 + * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 + */ + if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) + pcie_width = 6; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) + pcie_width = 5; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) + pcie_width = 4; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) + pcie_width = 3; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) + pcie_width = 2; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) + pcie_width = 1; + ret = smu_update_pcie_parameters(smu, pcie_gen, pcie_width); + if (ret) { + dev_err(adev->dev, "Attempt to override pcie params failed!\n"); + return ret; + } + + ret = smu_get_thermal_temperature_range(smu); + if (ret) { + dev_err(adev->dev, "Failed to get thermal temperature ranges!\n"); return ret; + } ret = smu_enable_thermal_alert(smu); if (ret) { @@ -1885,8 +1827,7 @@ int smu_set_display_count(struct smu_context *smu, uint32_t count) int smu_force_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t mask, - bool lock_needed) + uint32_t mask) { struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); int ret = 0; @@ -1899,14 +1840,12 @@ int smu_force_clk_levels(struct smu_context *smu, return -EINVAL; } - if (lock_needed) - mutex_lock(&smu->mutex); + mutex_lock(&smu->mutex); if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels) ret = smu->ppt_funcs->force_clk_levels(smu, clk_type, mask); - if (lock_needed) - mutex_unlock(&smu->mutex); + mutex_unlock(&smu->mutex); return ret; } @@ -2289,6 +2228,8 @@ int smu_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor, void *data, uint32_t *size) { + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) @@ -2301,11 +2242,11 @@ int smu_read_sensor(struct smu_context *smu, switch (sensor) { case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK: - *((uint32_t *)data) = smu->pstate_sclk; + *((uint32_t *)data) = pstate_table->gfxclk_pstate.standard * 100; *size = 4; break; case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK: - *((uint32_t *)data) = smu->pstate_mclk; + *((uint32_t *)data) = pstate_table->uclk_pstate.standard * 100; *size = 4; break; case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: @@ -2737,6 +2678,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; diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index d93f8a43a96f..56dc20a617fd 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -56,10 +56,6 @@ #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) -#define CTF_OFFSET_EDGE 5 -#define CTF_OFFSET_HOTSPOT 5 -#define CTF_OFFSET_HBM 5 - #define MSG_MAP(msg, index, valid_in_vf) \ [SMU_MSG_##msg] = {1, (index), (valid_in_vf)} #define ARCTURUS_FEA_MAP(smu_feature, arcturus_feature) \ @@ -291,7 +287,6 @@ static int arcturus_get_pwr_src_index(struct smu_context *smc, uint32_t index) return mapping.map_to; } - static int arcturus_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile) { struct smu_11_0_cmn2aisc_mapping mapping; @@ -338,23 +333,11 @@ static int arcturus_allocate_dpm_context(struct smu_context *smu) { struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - if (smu_dpm->dpm_context) - return -EINVAL; - - smu_dpm->dpm_context = kzalloc(sizeof(struct arcturus_dpm_table), + smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), GFP_KERNEL); if (!smu_dpm->dpm_context) return -ENOMEM; - - if (smu_dpm->golden_dpm_context) - return -EINVAL; - - smu_dpm->golden_dpm_context = kzalloc(sizeof(struct arcturus_dpm_table), - GFP_KERNEL); - if (!smu_dpm->golden_dpm_context) - return -ENOMEM; - - smu_dpm->dpm_context_size = sizeof(struct arcturus_dpm_table); + smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state), GFP_KERNEL); @@ -382,119 +365,84 @@ arcturus_get_allowed_feature_mask(struct smu_context *smu, return 0; } -static int -arcturus_set_single_dpm_table(struct smu_context *smu, - struct arcturus_single_dpm_table *single_dpm_table, - PPCLK_e clk_id) -{ - int ret = 0; - uint32_t i, num_of_levels = 0, clk; - - ret = smu_send_smc_msg_with_param(smu, - SMU_MSG_GetDpmFreqByIndex, - (clk_id << 16 | 0xFF), - &num_of_levels); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get dpm levels!\n", __func__); - return ret; - } - - single_dpm_table->count = num_of_levels; - for (i = 0; i < num_of_levels; i++) { - ret = smu_send_smc_msg_with_param(smu, - SMU_MSG_GetDpmFreqByIndex, - (clk_id << 16 | i), - &clk); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get dpm freq by index!\n", __func__); - return ret; - } - single_dpm_table->dpm_levels[i].value = clk; - single_dpm_table->dpm_levels[i].enabled = true; - } - return 0; -} - -static void arcturus_init_single_dpm_state(struct arcturus_dpm_state *dpm_state) -{ - dpm_state->soft_min_level = 0x0; - dpm_state->soft_max_level = 0xffff; - dpm_state->hard_min_level = 0x0; - dpm_state->hard_max_level = 0xffff; -} - static int arcturus_set_default_dpm_table(struct smu_context *smu) { - int ret; - - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct arcturus_dpm_table *dpm_table = NULL; - struct arcturus_single_dpm_table *single_dpm_table; - - dpm_table = smu_dpm->dpm_context; + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *driver_ppt = smu->smu_table.driver_pptable; + struct smu_11_0_dpm_table *dpm_table = NULL; + int ret = 0; - /* socclk */ - single_dpm_table = &(dpm_table->soc_table); + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - ret = arcturus_set_single_dpm_table(smu, single_dpm_table, - PPCLK_SOCCLK); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get socclk dpm levels!\n", __func__); + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) return ret; - } + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; } else { - single_dpm_table->count = 1; - single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; } - arcturus_init_single_dpm_state(&(single_dpm_table->dpm_state)); - /* gfxclk */ - single_dpm_table = &(dpm_table->gfx_table); + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { - ret = arcturus_set_single_dpm_table(smu, single_dpm_table, - PPCLK_GFXCLK); - if (ret) { - dev_err(smu->adev->dev, "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!"); + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) return ret; - } + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; } else { - single_dpm_table->count = 1; - single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; } - arcturus_init_single_dpm_state(&(single_dpm_table->dpm_state)); - /* memclk */ - single_dpm_table = &(dpm_table->mem_table); + /* memclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = arcturus_set_single_dpm_table(smu, single_dpm_table, - PPCLK_UCLK); - if (ret) { - dev_err(smu->adev->dev, "[SetupDefaultDpmTable] failed to get memclk dpm levels!"); + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) return ret; - } + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; } else { - single_dpm_table->count = 1; - single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; } - arcturus_init_single_dpm_state(&(single_dpm_table->dpm_state)); - /* fclk */ - single_dpm_table = &(dpm_table->fclk_table); + /* fclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.fclk_table; if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { - ret = arcturus_set_single_dpm_table(smu, single_dpm_table, - PPCLK_FCLK); - if (ret) { - dev_err(smu->adev->dev, "[SetupDefaultDpmTable] failed to get fclk dpm levels!"); + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_FCLK, + dpm_table); + if (ret) return ret; - } + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete; } else { - single_dpm_table->count = 1; - single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; } - arcturus_init_single_dpm_state(&(single_dpm_table->dpm_state)); - - memcpy(smu_dpm->golden_dpm_context, dpm_table, - sizeof(struct arcturus_dpm_table)); return 0; } @@ -596,33 +544,50 @@ static int arcturus_run_btc(struct smu_context *smu) static int arcturus_populate_umd_state_clk(struct smu_context *smu) { - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct arcturus_dpm_table *dpm_table = NULL; - struct arcturus_single_dpm_table *gfx_table = NULL; - struct arcturus_single_dpm_table *mem_table = NULL; - - dpm_table = smu_dpm->dpm_context; - gfx_table = &(dpm_table->gfx_table); - mem_table = &(dpm_table->mem_table); - - smu->pstate_sclk = gfx_table->dpm_levels[0].value; - smu->pstate_mclk = mem_table->dpm_levels[0].value; + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + + pstate_table->gfxclk_pstate.min = gfx_table->min; + pstate_table->gfxclk_pstate.peak = gfx_table->max; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; if (gfx_table->count > ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL && - mem_table->count > ARCTURUS_UMD_PSTATE_MCLK_LEVEL) { - smu->pstate_sclk = gfx_table->dpm_levels[ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL].value; - smu->pstate_mclk = mem_table->dpm_levels[ARCTURUS_UMD_PSTATE_MCLK_LEVEL].value; + mem_table->count > ARCTURUS_UMD_PSTATE_MCLK_LEVEL && + soc_table->count > ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL) { + pstate_table->gfxclk_pstate.standard = + gfx_table->dpm_levels[ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL].value; + pstate_table->uclk_pstate.standard = + mem_table->dpm_levels[ARCTURUS_UMD_PSTATE_MCLK_LEVEL].value; + pstate_table->socclk_pstate.standard = + soc_table->dpm_levels[ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL].value; + } else { + pstate_table->gfxclk_pstate.standard = + pstate_table->gfxclk_pstate.min; + pstate_table->uclk_pstate.standard = + pstate_table->uclk_pstate.min; + pstate_table->socclk_pstate.standard = + pstate_table->socclk_pstate.min; } - smu->pstate_sclk = smu->pstate_sclk * 100; - smu->pstate_mclk = smu->pstate_mclk * 100; - return 0; } static int arcturus_get_clk_table(struct smu_context *smu, struct pp_clock_levels_with_latency *clocks, - struct arcturus_single_dpm_table *dpm_table) + struct smu_11_0_dpm_table *dpm_table) { int i, count; @@ -644,30 +609,204 @@ static int arcturus_freqs_in_same_level(int32_t frequency1, return (abs(frequency1 - frequency2) <= EPSILON); } +static int arcturus_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + if (!smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + ret = smu_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + mutex_unlock(&smu->metrics_lock); + return ret; + } + smu_table->metrics_time = jiffies; + } + + switch (member) { + case METRICS_CURR_GFXCLK: + *value = metrics->CurrClock[PPCLK_GFXCLK]; + break; + case METRICS_CURR_SOCCLK: + *value = metrics->CurrClock[PPCLK_SOCCLK]; + break; + case METRICS_CURR_UCLK: + *value = metrics->CurrClock[PPCLK_UCLK]; + break; + case METRICS_CURR_VCLK: + *value = metrics->CurrClock[PPCLK_VCLK]; + break; + case METRICS_CURR_DCLK: + *value = metrics->CurrClock[PPCLK_DCLK]; + break; + case METRICS_CURR_FCLK: + *value = metrics->CurrClock[PPCLK_FCLK]; + break; + case METRICS_AVERAGE_GFXCLK: + *value = metrics->AverageGfxclkFrequency; + break; + case METRICS_AVERAGE_SOCCLK: + *value = metrics->AverageSocclkFrequency; + break; + case METRICS_AVERAGE_UCLK: + *value = metrics->AverageUclkFrequency; + break; + case METRICS_AVERAGE_VCLK: + *value = metrics->AverageVclkFrequency; + break; + case METRICS_AVERAGE_DCLK: + *value = metrics->AverageDclkFrequency; + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = metrics->AverageGfxActivity; + break; + case METRICS_AVERAGE_MEMACTIVITY: + *value = metrics->AverageUclkActivity; + break; + case METRICS_AVERAGE_VCNACTIVITY: + *value = metrics->VcnActivityPercentage; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = metrics->AverageSocketPower << 8; + break; + case METRICS_TEMPERATURE_EDGE: + *value = metrics->TemperatureEdge * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = metrics->TemperatureHotspot * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_MEM: + *value = metrics->TemperatureHBM * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRGFX: + *value = metrics->TemperatureVrGfx * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRSOC: + *value = metrics->TemperatureVrSoc * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRMEM: + *value = metrics->TemperatureVrMem * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_THROTTLER_STATUS: + *value = metrics->ThrottlerStatus; + break; + case METRICS_CURR_FANSPEED: + *value = metrics->CurrFanSpeed; + break; + default: + *value = UINT_MAX; + break; + } + + mutex_unlock(&smu->metrics_lock); + + return ret; +} + +static int arcturus_get_current_clk_freq_by_table(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + MetricsMember_t member_type; + int clk_id = 0; + + if (!value) + return -EINVAL; + + clk_id = smu_clk_get_index(smu, clk_type); + if (clk_id < 0) + return -EINVAL; + + switch (clk_id) { + case PPCLK_GFXCLK: + /* + * CurrClock[clk_id] can provide accurate + * output only when the dpm feature is enabled. + * We can use Average_* for dpm disabled case. + * But this is available for gfxclk/uclk/socclk/vclk/dclk. + */ + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) + member_type = METRICS_CURR_GFXCLK; + else + member_type = METRICS_AVERAGE_GFXCLK; + break; + case PPCLK_UCLK: + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) + member_type = METRICS_CURR_UCLK; + else + member_type = METRICS_AVERAGE_UCLK; + break; + case PPCLK_SOCCLK: + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) + member_type = METRICS_CURR_SOCCLK; + else + member_type = METRICS_AVERAGE_SOCCLK; + break; + case PPCLK_VCLK: + if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) + member_type = METRICS_CURR_VCLK; + else + member_type = METRICS_AVERAGE_VCLK; + break; + case PPCLK_DCLK: + if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) + member_type = METRICS_CURR_DCLK; + else + member_type = METRICS_AVERAGE_DCLK; + break; + case PPCLK_FCLK: + member_type = METRICS_CURR_FCLK; + break; + default: + return -EINVAL; + } + + return arcturus_get_smu_metrics_data(smu, + member_type, + value); +} + static int arcturus_print_clk_levels(struct smu_context *smu, enum smu_clk_type type, char *buf) { int i, now, size = 0; int ret = 0; struct pp_clock_levels_with_latency clocks; - struct arcturus_single_dpm_table *single_dpm_table; + struct smu_11_0_dpm_table *single_dpm_table; struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct arcturus_dpm_table *dpm_table = NULL; + struct smu_11_0_dpm_context *dpm_context = NULL; if (amdgpu_ras_intr_triggered()) return snprintf(buf, PAGE_SIZE, "unavailable\n"); - dpm_table = smu_dpm->dpm_context; + dpm_context = smu_dpm->dpm_context; switch (type) { case SMU_SCLK: - ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now); + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now); if (ret) { dev_err(smu->adev->dev, "Attempt to get current gfx clk Failed!"); return ret; } - single_dpm_table = &(dpm_table->gfx_table); + single_dpm_table = &(dpm_context->dpm_tables.gfx_table); ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); if (ret) { dev_err(smu->adev->dev, "Attempt to get gfx clk levels Failed!"); @@ -684,17 +823,17 @@ static int arcturus_print_clk_levels(struct smu_context *smu, (clocks.num_levels == 1) ? "*" : (arcturus_freqs_in_same_level( clocks.data[i].clocks_in_khz / 1000, - now / 100) ? "*" : "")); + now) ? "*" : "")); break; case SMU_MCLK: - ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now); + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_UCLK, &now); if (ret) { dev_err(smu->adev->dev, "Attempt to get current mclk Failed!"); return ret; } - single_dpm_table = &(dpm_table->mem_table); + single_dpm_table = &(dpm_context->dpm_tables.uclk_table); ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); if (ret) { dev_err(smu->adev->dev, "Attempt to get memory clk levels Failed!"); @@ -707,17 +846,17 @@ static int arcturus_print_clk_levels(struct smu_context *smu, (clocks.num_levels == 1) ? "*" : (arcturus_freqs_in_same_level( clocks.data[i].clocks_in_khz / 1000, - now / 100) ? "*" : "")); + now) ? "*" : "")); break; case SMU_SOCCLK: - ret = smu_get_current_clk_freq(smu, SMU_SOCCLK, &now); + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_SOCCLK, &now); if (ret) { dev_err(smu->adev->dev, "Attempt to get current socclk Failed!"); return ret; } - single_dpm_table = &(dpm_table->soc_table); + single_dpm_table = &(dpm_context->dpm_tables.soc_table); ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); if (ret) { dev_err(smu->adev->dev, "Attempt to get socclk levels Failed!"); @@ -730,17 +869,17 @@ static int arcturus_print_clk_levels(struct smu_context *smu, (clocks.num_levels == 1) ? "*" : (arcturus_freqs_in_same_level( clocks.data[i].clocks_in_khz / 1000, - now / 100) ? "*" : "")); + now) ? "*" : "")); break; case SMU_FCLK: - ret = smu_get_current_clk_freq(smu, SMU_FCLK, &now); + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_FCLK, &now); if (ret) { dev_err(smu->adev->dev, "Attempt to get current fclk Failed!"); return ret; } - single_dpm_table = &(dpm_table->fclk_table); + single_dpm_table = &(dpm_context->dpm_tables.fclk_table); ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); if (ret) { dev_err(smu->adev->dev, "Attempt to get fclk levels Failed!"); @@ -753,7 +892,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu, (clocks.num_levels == 1) ? "*" : (arcturus_freqs_in_same_level( clocks.data[i].clocks_in_khz / 1000, - now / 100) ? "*" : "")); + now) ? "*" : "")); break; default: @@ -763,20 +902,19 @@ static int arcturus_print_clk_levels(struct smu_context *smu, return size; } -static int arcturus_upload_dpm_level(struct smu_context *smu, bool max, - uint32_t feature_mask) +static int arcturus_upload_dpm_level(struct smu_context *smu, + bool max, + uint32_t feature_mask, + uint32_t level) { - struct arcturus_single_dpm_table *single_dpm_table; - struct arcturus_dpm_table *dpm_table = + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; uint32_t freq; int ret = 0; if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) && (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { - single_dpm_table = &(dpm_table->gfx_table); - freq = max ? single_dpm_table->dpm_state.soft_max_level : - single_dpm_table->dpm_state.soft_min_level; + freq = dpm_context->dpm_tables.gfx_table.dpm_levels[level].value; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), (PPCLK_GFXCLK << 16) | (freq & 0xffff), @@ -790,9 +928,7 @@ static int arcturus_upload_dpm_level(struct smu_context *smu, bool max, if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) && (feature_mask & FEATURE_DPM_UCLK_MASK)) { - single_dpm_table = &(dpm_table->mem_table); - freq = max ? single_dpm_table->dpm_state.soft_max_level : - single_dpm_table->dpm_state.soft_min_level; + freq = dpm_context->dpm_tables.uclk_table.dpm_levels[level].value; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), (PPCLK_UCLK << 16) | (freq & 0xffff), @@ -806,9 +942,7 @@ static int arcturus_upload_dpm_level(struct smu_context *smu, bool max, if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) && (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { - single_dpm_table = &(dpm_table->soc_table); - freq = max ? single_dpm_table->dpm_state.soft_max_level : - single_dpm_table->dpm_state.soft_min_level; + freq = dpm_context->dpm_tables.soc_table.dpm_levels[level].value; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), (PPCLK_SOCCLK << 16) | (freq & 0xffff), @@ -826,8 +960,8 @@ static int arcturus_upload_dpm_level(struct smu_context *smu, bool max, static int arcturus_force_clk_levels(struct smu_context *smu, enum smu_clk_type type, uint32_t mask) { - struct arcturus_dpm_table *dpm_table; - struct arcturus_single_dpm_table *single_dpm_table; + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *single_dpm_table = NULL; uint32_t soft_min_level, soft_max_level; uint32_t smu_version; int ret = 0; @@ -847,12 +981,9 @@ static int arcturus_force_clk_levels(struct smu_context *smu, soft_min_level = mask ? (ffs(mask) - 1) : 0; soft_max_level = mask ? (fls(mask) - 1) : 0; - dpm_table = smu->smu_dpm.dpm_context; - switch (type) { case SMU_SCLK: - single_dpm_table = &(dpm_table->gfx_table); - + single_dpm_table = &(dpm_context->dpm_tables.gfx_table); if (soft_max_level >= single_dpm_table->count) { dev_err(smu->adev->dev, "Clock level specified %d is over max allowed %d\n", soft_max_level, single_dpm_table->count - 1); @@ -860,18 +991,19 @@ static int arcturus_force_clk_levels(struct smu_context *smu, break; } - single_dpm_table->dpm_state.soft_min_level = - single_dpm_table->dpm_levels[soft_min_level].value; - single_dpm_table->dpm_state.soft_max_level = - single_dpm_table->dpm_levels[soft_max_level].value; - - ret = arcturus_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK); + ret = arcturus_upload_dpm_level(smu, + false, + FEATURE_DPM_GFXCLK_MASK, + soft_min_level); if (ret) { dev_err(smu->adev->dev, "Failed to upload boot level to lowest!\n"); break; } - ret = arcturus_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK); + ret = arcturus_upload_dpm_level(smu, + true, + FEATURE_DPM_GFXCLK_MASK, + soft_max_level); if (ret) dev_err(smu->adev->dev, "Failed to upload dpm max level to highest!\n"); @@ -897,11 +1029,16 @@ static int arcturus_force_clk_levels(struct smu_context *smu, static int arcturus_get_thermal_temperature_range(struct smu_context *smu, struct smu_temperature_range *range) { + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; PPTable_t *pptable = smu->smu_table.driver_pptable; if (!range) return -EINVAL; + memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); + range->max = pptable->TedgeLimit * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) * @@ -912,123 +1049,13 @@ static int arcturus_get_thermal_temperature_range(struct smu_context *smu, SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; range->mem_crit_max = pptable->TmemLimit * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_HBM)* + range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)* SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->software_shutdown_temp = powerplay_table->software_shutdown_temp; return 0; } -static int arcturus_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) -{ - struct smu_table_context *smu_table= &smu->smu_table; - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; - int ret = 0; - - mutex_lock(&smu->metrics_lock); - - if (!smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); - return ret; - } - smu_table->metrics_time = jiffies; - } - - switch (member) { - case METRICS_CURR_GFXCLK: - *value = metrics->CurrClock[PPCLK_GFXCLK]; - break; - case METRICS_CURR_SOCCLK: - *value = metrics->CurrClock[PPCLK_SOCCLK]; - break; - case METRICS_CURR_UCLK: - *value = metrics->CurrClock[PPCLK_UCLK]; - break; - case METRICS_CURR_VCLK: - *value = metrics->CurrClock[PPCLK_VCLK]; - break; - case METRICS_CURR_DCLK: - *value = metrics->CurrClock[PPCLK_DCLK]; - break; - case METRICS_CURR_FCLK: - *value = metrics->CurrClock[PPCLK_FCLK]; - break; - case METRICS_AVERAGE_GFXCLK: - *value = metrics->AverageGfxclkFrequency; - break; - case METRICS_AVERAGE_SOCCLK: - *value = metrics->AverageSocclkFrequency; - break; - case METRICS_AVERAGE_UCLK: - *value = metrics->AverageUclkFrequency; - break; - case METRICS_AVERAGE_VCLK: - *value = metrics->AverageVclkFrequency; - break; - case METRICS_AVERAGE_DCLK: - *value = metrics->AverageDclkFrequency; - break; - case METRICS_AVERAGE_GFXACTIVITY: - *value = metrics->AverageGfxActivity; - break; - case METRICS_AVERAGE_MEMACTIVITY: - *value = metrics->AverageUclkActivity; - break; - case METRICS_AVERAGE_VCNACTIVITY: - *value = metrics->VcnActivityPercentage; - break; - case METRICS_AVERAGE_SOCKETPOWER: - *value = metrics->AverageSocketPower << 8; - break; - case METRICS_TEMPERATURE_EDGE: - *value = metrics->TemperatureEdge * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_HOTSPOT: - *value = metrics->TemperatureHotspot * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_MEM: - *value = metrics->TemperatureHBM * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRGFX: - *value = metrics->TemperatureVrGfx * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRSOC: - *value = metrics->TemperatureVrSoc * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRMEM: - *value = metrics->TemperatureVrMem * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_THROTTLER_STATUS: - *value = metrics->ThrottlerStatus; - break; - case METRICS_CURR_FANSPEED: - *value = metrics->CurrFanSpeed; - break; - default: - *value = UINT_MAX; - break; - } - - mutex_unlock(&smu->metrics_lock); - - return ret; -} - static int arcturus_get_current_activity_percent(struct smu_context *smu, enum amd_pp_sensors sensor, uint32_t *value) @@ -1138,8 +1165,24 @@ static int arcturus_read_sensor(struct smu_context *smu, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + /* the output clock frequency in 10K unit */ + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); + *size = 4; + break; default: - ret = smu_v11_0_read_sensor(smu, sensor, data, size); + ret = -EOPNOTSUPP; + break; } mutex_unlock(&smu->sensor_lock); @@ -1177,238 +1220,6 @@ static int arcturus_get_fan_speed_percent(struct smu_context *smu, return ret; } -static int arcturus_get_current_clk_freq_by_table(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) -{ - MetricsMember_t member_type; - int clk_id = 0; - - if (!value) - return -EINVAL; - - clk_id = smu_clk_get_index(smu, clk_type); - if (clk_id < 0) - return -EINVAL; - - switch (clk_id) { - case PPCLK_GFXCLK: - /* - * CurrClock[clk_id] can provide accurate - * output only when the dpm feature is enabled. - * We can use Average_* for dpm disabled case. - * But this is available for gfxclk/uclk/socclk/vclk/dclk. - */ - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) - member_type = METRICS_CURR_GFXCLK; - else - member_type = METRICS_AVERAGE_GFXCLK; - break; - case PPCLK_UCLK: - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) - member_type = METRICS_CURR_UCLK; - else - member_type = METRICS_AVERAGE_UCLK; - break; - case PPCLK_SOCCLK: - if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) - member_type = METRICS_CURR_SOCCLK; - else - member_type = METRICS_AVERAGE_SOCCLK; - break; - case PPCLK_VCLK: - if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) - member_type = METRICS_CURR_VCLK; - else - member_type = METRICS_AVERAGE_VCLK; - break; - case PPCLK_DCLK: - if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) - member_type = METRICS_CURR_DCLK; - else - member_type = METRICS_AVERAGE_DCLK; - break; - case PPCLK_FCLK: - member_type = METRICS_CURR_FCLK; - break; - default: - return -EINVAL; - } - - return arcturus_get_smu_metrics_data(smu, - member_type, - value); -} - -static uint32_t arcturus_find_lowest_dpm_level(struct arcturus_single_dpm_table *table) -{ - uint32_t i; - - for (i = 0; i < table->count; i++) { - if (table->dpm_levels[i].enabled) - break; - } - if (i >= table->count) { - i = 0; - table->dpm_levels[i].enabled = true; - } - - return i; -} - -static uint32_t arcturus_find_highest_dpm_level(struct smu_context *smu, - struct arcturus_single_dpm_table *table) -{ - int i = 0; - - if (table->count <= 0) { - dev_err(smu->adev->dev, "[%s] DPM Table has no entry!", __func__); - return 0; - } - if (table->count > MAX_DPM_NUMBER) { - dev_err(smu->adev->dev, "[%s] DPM Table has too many entries!", __func__); - return MAX_DPM_NUMBER - 1; - } - - for (i = table->count - 1; i >= 0; i--) { - if (table->dpm_levels[i].enabled) - break; - } - if (i < 0) { - i = 0; - table->dpm_levels[i].enabled = true; - } - - return i; -} - - - -static int arcturus_force_dpm_limit_value(struct smu_context *smu, bool highest) -{ - struct arcturus_dpm_table *dpm_table = - (struct arcturus_dpm_table *)smu->smu_dpm.dpm_context; - struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(smu->adev, 0); - uint32_t soft_level; - int ret = 0; - - /* gfxclk */ - if (highest) - soft_level = arcturus_find_highest_dpm_level(smu, &(dpm_table->gfx_table)); - else - soft_level = arcturus_find_lowest_dpm_level(&(dpm_table->gfx_table)); - - dpm_table->gfx_table.dpm_state.soft_min_level = - dpm_table->gfx_table.dpm_state.soft_max_level = - dpm_table->gfx_table.dpm_levels[soft_level].value; - - ret = arcturus_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK); - if (ret) { - dev_err(smu->adev->dev, "Failed to upload boot level to %s!\n", - highest ? "highest" : "lowest"); - return ret; - } - - ret = arcturus_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK); - if (ret) { - dev_err(smu->adev->dev, "Failed to upload dpm max level to %s!\n!", - highest ? "highest" : "lowest"); - return ret; - } - - if (hive) - /* - * Force XGMI Pstate to highest or lowest - * TODO: revise this when xgmi dpm is functional - */ - ret = smu_v11_0_set_xgmi_pstate(smu, highest ? 1 : 0); - - return ret; -} - -static int arcturus_unforce_dpm_levels(struct smu_context *smu) -{ - struct arcturus_dpm_table *dpm_table = - (struct arcturus_dpm_table *)smu->smu_dpm.dpm_context; - struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(smu->adev, 0); - uint32_t soft_min_level, soft_max_level; - int ret = 0; - - /* gfxclk */ - soft_min_level = arcturus_find_lowest_dpm_level(&(dpm_table->gfx_table)); - soft_max_level = arcturus_find_highest_dpm_level(smu, &(dpm_table->gfx_table)); - dpm_table->gfx_table.dpm_state.soft_min_level = - dpm_table->gfx_table.dpm_levels[soft_min_level].value; - dpm_table->gfx_table.dpm_state.soft_max_level = - dpm_table->gfx_table.dpm_levels[soft_max_level].value; - - ret = arcturus_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK); - if (ret) { - dev_err(smu->adev->dev, "Failed to upload DPM Bootup Levels!"); - return ret; - } - - ret = arcturus_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK); - if (ret) { - dev_err(smu->adev->dev, "Failed to upload DPM Max Levels!"); - return ret; - } - - if (hive) - /* - * Reset XGMI Pstate back to default - * TODO: revise this when xgmi dpm is functional - */ - ret = smu_v11_0_set_xgmi_pstate(smu, 0); - - return ret; -} - -static int -arcturus_get_profiling_clk_mask(struct smu_context *smu, - enum amd_dpm_forced_level level, - uint32_t *sclk_mask, - uint32_t *mclk_mask, - uint32_t *soc_mask) -{ - struct arcturus_dpm_table *dpm_table = - (struct arcturus_dpm_table *)smu->smu_dpm.dpm_context; - struct arcturus_single_dpm_table *gfx_dpm_table; - struct arcturus_single_dpm_table *mem_dpm_table; - struct arcturus_single_dpm_table *soc_dpm_table; - - if (!smu->smu_dpm.dpm_context) - return -EINVAL; - - gfx_dpm_table = &dpm_table->gfx_table; - mem_dpm_table = &dpm_table->mem_table; - soc_dpm_table = &dpm_table->soc_table; - - *sclk_mask = 0; - *mclk_mask = 0; - *soc_mask = 0; - - if (gfx_dpm_table->count > ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL && - mem_dpm_table->count > ARCTURUS_UMD_PSTATE_MCLK_LEVEL && - soc_dpm_table->count > ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL) { - *sclk_mask = ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL; - *mclk_mask = ARCTURUS_UMD_PSTATE_MCLK_LEVEL; - *soc_mask = ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL; - } - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - *sclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - *mclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - *sclk_mask = gfx_dpm_table->count - 1; - *mclk_mask = mem_dpm_table->count - 1; - *soc_mask = soc_dpm_table->count - 1; - } - - return 0; -} - static int arcturus_get_power_limit(struct smu_context *smu) { struct smu_11_0_powerplay_table *powerplay_table = @@ -2136,7 +1947,6 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) return ret; } - static void arcturus_fill_eeprom_i2c_req(SwI2cRequest_t *req, bool write, uint8_t address, uint32_t numbytes, uint8_t *data) @@ -2504,37 +2314,6 @@ static void arcturus_log_thermal_throttling_event(struct smu_context *smu) log_buf); } -static int arcturus_set_thermal_range(struct smu_context *smu, - struct smu_temperature_range range) -{ - struct amdgpu_device *adev = smu->adev; - int low = SMU_THERMAL_MINIMUM_ALERT_TEMP; - int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP; - uint32_t val; - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table; - - low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, - range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES); - high = min((uint16_t)SMU_THERMAL_MAXIMUM_ALERT_TEMP, powerplay_table->software_shutdown_temp); - - if (low > high) - return -EINVAL; - - val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff)); - val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); - - return 0; -} - static const struct pptable_funcs arcturus_ppt_funcs = { /* translate smu index into arcturus specific index */ .get_smu_msg_index = arcturus_get_smu_msg_index, @@ -2554,15 +2333,11 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .set_default_dpm_table = arcturus_set_default_dpm_table, .populate_umd_state_clk = arcturus_populate_umd_state_clk, .get_thermal_temperature_range = arcturus_get_thermal_temperature_range, - .get_current_clk_freq_by_table = arcturus_get_current_clk_freq_by_table, .print_clk_levels = arcturus_print_clk_levels, .force_clk_levels = arcturus_force_clk_levels, .read_sensor = arcturus_read_sensor, .get_fan_speed_percent = arcturus_get_fan_speed_percent, .get_fan_speed_rpm = arcturus_get_fan_speed_rpm, - .force_dpm_limit_value = arcturus_force_dpm_limit_value, - .unforce_dpm_levels = arcturus_unforce_dpm_levels, - .get_profiling_clk_mask = arcturus_get_profiling_clk_mask, .get_power_profile_mode = arcturus_get_power_profile_mode, .set_power_profile_mode = arcturus_set_power_profile_mode, .set_performance_level = arcturus_set_performance_level, @@ -2597,7 +2372,6 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .get_enabled_mask = smu_v11_0_get_enabled_mask, .notify_display_change = NULL, .set_power_limit = smu_v11_0_set_power_limit, - .get_current_clk_freq = smu_v11_0_get_current_clk_freq, .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, .enable_thermal_alert = smu_v11_0_enable_thermal_alert, .disable_thermal_alert = smu_v11_0_disable_thermal_alert, @@ -2619,11 +2393,9 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .baco_exit = smu_v11_0_baco_exit, .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, - .override_pcie_parameters = NULL, .set_df_cstate = arcturus_set_df_cstate, .allow_xgmi_power_down = arcturus_allow_xgmi_power_down, .log_thermal_throttling_event = arcturus_log_thermal_throttling_event, - .set_thermal_range = arcturus_set_thermal_range, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 7b349e038972..70181ba7ee0c 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -119,6 +119,7 @@ struct smu_temperature_range { int mem_min; int mem_crit_max; int mem_emergency_max; + int software_shutdown_temp; }; struct smu_state_validation_block { @@ -145,7 +146,6 @@ struct smu_power_state { struct smu_state_pcie_block pcie; struct smu_state_display_block display; struct smu_state_memroy_block memory; - struct smu_temperature_range temperatures; struct smu_state_software_algorithm_block software; struct smu_uvd_clocks uvd_clocks; struct smu_hw_power_state hardware; @@ -352,6 +352,20 @@ struct smu_baco_context bool platform_support; }; +struct pstates_clk_freq { + uint32_t min; + uint32_t standard; + uint32_t peak; +}; + +struct smu_umd_pstate_table { + struct pstates_clk_freq gfxclk_pstate; + struct pstates_clk_freq socclk_pstate; + struct pstates_clk_freq uclk_pstate; + struct pstates_clk_freq vclk_pstate; + struct pstates_clk_freq dclk_pstate; +}; + #define WORKLOAD_POLICY_MAX 7 struct smu_context { @@ -371,11 +385,13 @@ struct smu_context struct smu_feature smu_feature; struct amd_pp_display_configuration *display_config; struct smu_baco_context smu_baco; + struct smu_temperature_range thermal_range; void *od_settings; #if defined(CONFIG_DEBUG_FS) struct dentry *debugfs_sclk; #endif + struct smu_umd_pstate_table pstate_table; uint32_t pstate_sclk; uint32_t pstate_mclk; @@ -461,24 +477,13 @@ struct pptable_funcs { int (*display_config_changed)(struct smu_context *smu); int (*apply_clocks_adjust_rules)(struct smu_context *smu); int (*notify_smc_display_config)(struct smu_context *smu); - int (*force_dpm_limit_value)(struct smu_context *smu, bool highest); - int (*unforce_dpm_levels)(struct smu_context *smu); - int (*get_profiling_clk_mask)(struct smu_context *smu, - enum amd_dpm_forced_level level, - uint32_t *sclk_mask, - uint32_t *mclk_mask, - uint32_t *soc_mask); int (*set_cpu_power_state)(struct smu_context *smu); bool (*is_dpm_running)(struct smu_context *smu); int (*tables_init)(struct smu_context *smu, struct smu_table *tables); - int (*set_thermal_fan_table)(struct smu_context *smu); int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed); int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed); int (*set_watermarks_table)(struct smu_context *smu, void *watermarks, struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); - int (*get_current_clk_freq_by_table)(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value); int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range); int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states); int (*set_default_od_settings)(struct smu_context *smu); @@ -486,8 +491,6 @@ struct pptable_funcs { int (*display_disable_memory_clock_switch)(struct smu_context *smu, bool disable_memory_clock_switch); void (*dump_pptable)(struct smu_context *smu); int (*get_power_limit)(struct smu_context *smu); - int (*get_dpm_clk_limited)(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t dpm_level, uint32_t *freq); int (*set_df_cstate)(struct smu_context *smu, enum pp_df_cstate state); int (*allow_xgmi_power_down)(struct smu_context *smu, bool en); int (*update_pcie_parameters)(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap); @@ -521,7 +524,6 @@ struct pptable_funcs { int (*get_enabled_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); int (*notify_display_change)(struct smu_context *smu); int (*set_power_limit)(struct smu_context *smu, uint32_t n); - int (*get_current_clk_freq)(struct smu_context *smu, enum smu_clk_type clk_id, uint32_t *value); int (*init_max_sustainable_clocks)(struct smu_context *smu); int (*enable_thermal_alert)(struct smu_context *smu); int (*disable_thermal_alert)(struct smu_context *smu); @@ -561,14 +563,14 @@ 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); - int (*override_pcie_parameters)(struct smu_context *smu); int (*disable_umc_cdr_12gbps_workaround)(struct smu_context *smu); int (*set_power_source)(struct smu_context *smu, enum smu_power_src_type power_src); void (*log_thermal_throttling_event)(struct smu_context *smu); - int (*set_thermal_range)(struct smu_context *smu, struct smu_temperature_range range); }; typedef enum { @@ -672,6 +674,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, @@ -719,18 +723,10 @@ int smu_switch_power_profile(struct smu_context *smu, enum PP_SMC_POWER_PROFILE type, bool en); int smu_get_smc_version(struct smu_context *smu, uint32_t *if_version, uint32_t *smu_version); -int smu_get_dpm_freq_by_index(struct smu_context *smu, enum smu_clk_type clk_type, - uint16_t level, uint32_t *value); -int smu_get_dpm_level_count(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *value); int smu_get_dpm_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *min, uint32_t *max, bool lock_needed); + uint32_t *min, uint32_t *max); int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t min, uint32_t max, bool lock_needed); -int smu_set_hard_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max); -int smu_get_dpm_level_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *min_value, uint32_t *max_value); enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu); int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level); int smu_set_display_count(struct smu_context *smu, uint32_t count); @@ -742,8 +738,7 @@ size_t smu_sys_get_pp_feature_mask(struct smu_context *smu, char *buf); int smu_sys_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask); int smu_force_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t mask, - bool lock_needed); + uint32_t mask); int smu_set_mp1_state(struct smu_context *smu, enum pp_mp1_state mp1_state); int smu_set_df_cstate(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h index 5322f6da3071..b2232e24d82f 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h @@ -27,9 +27,9 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define SMU11_DRIVER_IF_VERSION 0x31 +#define SMU11_DRIVER_IF_VERSION 0x33 -#define PPTABLE_Sienna_Cichlid_SMU_VERSION 4 +#define PPTABLE_Sienna_Cichlid_SMU_VERSION 5 #define NUM_GFXCLK_DPM_LEVELS 16 #define NUM_SMNCLK_DPM_LEVELS 2 @@ -128,7 +128,7 @@ #define FEATURE_2_STEP_PSTATE_BIT 46 #define FEATURE_SMNCLK_DPM_BIT 47 #define FEATURE_SPARE_48_BIT 48 -#define FEATURE_SPARE_49_BIT 49 +#define FEATURE_GFX_EDC_BIT 49 #define FEATURE_SPARE_50_BIT 50 #define FEATURE_SPARE_51_BIT 51 #define FEATURE_SPARE_52_BIT 52 @@ -564,6 +564,12 @@ typedef enum { TDC_THROTTLER_COUNT } TDC_THROTTLER_e; +typedef enum { + CUSTOMER_VARIANT_ROW, + CUSTOMER_VARIANT_FALCON, + CUSTOMER_VARIANT_COUNT, +} CUSTOMER_VARIANT_e; + // Used for 2-step UCLK DPM change workaround typedef struct { uint16_t Fmin; @@ -786,7 +792,10 @@ typedef struct { QuadraticInt_t ReservedEquation3; // SECTION: Sku Reserved - uint32_t SkuReserved[15]; + uint8_t CustomerVariant; + uint8_t Spare[3]; + uint32_t SkuReserved[14]; + // MAJOR SECTION: BOARD PARAMETERS @@ -865,8 +874,7 @@ typedef struct { uint16_t DfllGfxclkSpreadFreq; // kHz // UCLK Spread Spectrum - uint8_t UclkSpreadEnabled; // on or off - uint8_t UclkSpreadPercent; // Q4.4 + uint16_t UclkSpreadPadding; uint16_t UclkSpreadFreq; // kHz // FCLK Spread Spectrum @@ -896,8 +904,11 @@ typedef struct { uint8_t VddqOffEnabled; uint8_t PaddingUmcFlags[2]; + // UCLK Spread Spectrum + uint8_t UclkSpreadPercent[16]; + // SECTION: Board Reserved - uint32_t BoardReserved[15]; + uint32_t BoardReserved[11]; // SECTION: Structure Padding @@ -936,10 +947,12 @@ typedef struct { int16_t OverDrivePct; // % uint16_t FanMaximumRpm; uint16_t FanMinimumPwm; + uint16_t FanAcousticLimitRpm; uint16_t FanTargetTemperature; // Degree Celcius uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS]; uint8_t FanLinearTempPoints[NUM_OD_FAN_MAX_POINTS]; uint16_t MaxOpTemp; // Degree Celcius + uint16_t Padding_16[1]; uint8_t FanZeroRpmEnable; uint8_t FanZeroRpmStopTemp; uint8_t FanMode; diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_types.h b/drivers/gpu/drm/amd/powerplay/inc/smu_types.h index dff2295705be..7b585e205a5a 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_types.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_types.h @@ -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 diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index 4fb911d8b49c..f06158511f93 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -30,7 +30,8 @@ #define SMU11_DRIVER_IF_VERSION_NV10 0x36 #define SMU11_DRIVER_IF_VERSION_NV12 0x33 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 -#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x31 +#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x33 +#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x2B /* MP Apertures */ #define MP0_Public 0x03800000 @@ -48,6 +49,7 @@ #define SMU11_TOOL_SIZE 0x19000 +#define MAX_DPM_LEVELS 16 #define MAX_PCIE_CONF 2 #define CLK_MAP(clk, index) \ @@ -65,6 +67,10 @@ #define WORKLOAD_MAP(profile, workload) \ [profile] = {1, (workload)} +#define CTF_OFFSET_EDGE 5 +#define CTF_OFFSET_HOTSPOT 5 +#define CTF_OFFSET_MEM 5 + static const struct smu_temperature_range smu11_thermal_policy[] = { {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, @@ -91,9 +97,17 @@ struct smu_11_0_max_sustainable_clocks { uint32_t soc_clock; }; +struct smu_11_0_dpm_clk_level { + bool enabled; + uint32_t value; +}; + struct smu_11_0_dpm_table { - uint32_t min; /* MHz */ - uint32_t max; /* MHz */ + uint32_t min; /* MHz */ + uint32_t max; /* MHz */ + uint32_t count; + bool is_fine_grained; + struct smu_11_0_dpm_clk_level dpm_levels[MAX_DPM_LEVELS]; }; struct smu_11_0_pcie_table { @@ -107,7 +121,9 @@ struct smu_11_0_dpm_tables { struct smu_11_0_dpm_table uclk_table; struct smu_11_0_dpm_table eclk_table; struct smu_11_0_dpm_table vclk_table; + struct smu_11_0_dpm_table vclk1_table; struct smu_11_0_dpm_table dclk_table; + struct smu_11_0_dpm_table dclk1_table; struct smu_11_0_dpm_table dcef_table; struct smu_11_0_dpm_table pixel_table; struct smu_11_0_dpm_table display_table; @@ -197,19 +213,13 @@ int smu_v11_0_get_current_power_limit(struct smu_context *smu, int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n); -int smu_v11_0_get_current_clk_freq(struct smu_context *smu, - enum smu_clk_type clk_id, - uint32_t *value); - int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu); int smu_v11_0_enable_thermal_alert(struct smu_context *smu); int smu_v11_0_disable_thermal_alert(struct smu_context *smu); -int smu_v11_0_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size); +int smu_v11_0_get_gfx_vdd(struct smu_context *smu, uint32_t *value); int smu_v11_0_set_min_deep_sleep_dcefclk(struct smu_context *smu, uint32_t clk); @@ -252,13 +262,18 @@ 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); int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max); -int smu_v11_0_override_pcie_parameters(struct smu_context *smu); +int smu_v11_0_set_hard_freq_limited_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t min, + uint32_t max); int smu_v11_0_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level); @@ -266,4 +281,22 @@ int smu_v11_0_set_performance_level(struct smu_context *smu, int smu_v11_0_set_power_source(struct smu_context *smu, enum smu_power_src_type power_src); +int smu_v11_0_get_dpm_freq_by_index(struct smu_context *smu, + enum smu_clk_type clk_type, + uint16_t level, + uint32_t *value); + +int smu_v11_0_get_dpm_level_count(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value); + +int smu_v11_0_set_single_dpm_table(struct smu_context *smu, + enum smu_clk_type clk_type, + struct smu_11_0_dpm_table *single_dpm_table); + +int smu_v11_0_get_dpm_level_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min_value, + uint32_t *max_value); + #endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h index d29f75223987..fd83a723f32c 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h @@ -60,10 +60,6 @@ int smu_v12_0_powergate_jpeg(struct smu_context *smu, bool gate); int smu_v12_0_set_gfx_cgpg(struct smu_context *smu, bool enable); -int smu_v12_0_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size); - uint32_t smu_v12_0_get_gfxoff_status(struct smu_context *smu); int smu_v12_0_gfx_off_control(struct smu_context *smu, bool enable); @@ -77,13 +73,6 @@ int smu_v12_0_set_default_dpm_tables(struct smu_context *smu); int smu_v12_0_get_enabled_mask(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); -int smu_v12_0_get_current_clk_freq(struct smu_context *smu, - enum smu_clk_type clk_id, - uint32_t *value); - -int smu_v12_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *min, uint32_t *max); - int smu_v12_0_mode2_reset(struct smu_context *smu); int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type, diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 42ade9df0d6a..ead135f39c7e 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -689,44 +689,171 @@ static int navi10_allocate_dpm_context(struct smu_context *smu) static int navi10_set_default_dpm_table(struct smu_context *smu) { - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; - PPTable_t *driver_ppt = NULL; - int i; - - driver_ppt = table_context->driver_pptable; - - dpm_context->dpm_tables.soc_table.min = driver_ppt->FreqTableSocclk[0]; - dpm_context->dpm_tables.soc_table.max = driver_ppt->FreqTableSocclk[NUM_SOCCLK_DPM_LEVELS - 1]; + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *driver_ppt = smu->smu_table.driver_pptable; + struct smu_11_0_dpm_table *dpm_table; + int ret = 0; - dpm_context->dpm_tables.gfx_table.min = driver_ppt->FreqTableGfx[0]; - dpm_context->dpm_tables.gfx_table.max = driver_ppt->FreqTableGfx[NUM_GFXCLK_DPM_LEVELS - 1]; + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.uclk_table.min = driver_ppt->FreqTableUclk[0]; - dpm_context->dpm_tables.uclk_table.max = driver_ppt->FreqTableUclk[NUM_UCLK_DPM_LEVELS - 1]; + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.vclk_table.min = driver_ppt->FreqTableVclk[0]; - dpm_context->dpm_tables.vclk_table.max = driver_ppt->FreqTableVclk[NUM_VCLK_DPM_LEVELS - 1]; + /* uclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.dclk_table.min = driver_ppt->FreqTableDclk[0]; - dpm_context->dpm_tables.dclk_table.max = driver_ppt->FreqTableDclk[NUM_DCLK_DPM_LEVELS - 1]; + /* vclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.vclk_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_VCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.dcef_table.min = driver_ppt->FreqTableDcefclk[0]; - dpm_context->dpm_tables.dcef_table.max = driver_ppt->FreqTableDcefclk[NUM_DCEFCLK_DPM_LEVELS - 1]; + /* dclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dclk_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.pixel_table.min = driver_ppt->FreqTablePixclk[0]; - dpm_context->dpm_tables.pixel_table.max = driver_ppt->FreqTablePixclk[NUM_PIXCLK_DPM_LEVELS - 1]; + /* dcefclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dcef_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCEFCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.display_table.min = driver_ppt->FreqTableDispclk[0]; - dpm_context->dpm_tables.display_table.max = driver_ppt->FreqTableDispclk[NUM_DISPCLK_DPM_LEVELS - 1]; + /* pixelclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.pixel_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PIXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.phy_table.min = driver_ppt->FreqTablePhyclk[0]; - dpm_context->dpm_tables.phy_table.max = driver_ppt->FreqTablePhyclk[NUM_PHYCLK_DPM_LEVELS - 1]; + /* displayclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.display_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DISPCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - for (i = 0; i < MAX_PCIE_CONF; i++) { - dpm_context->dpm_tables.pcie_table.pcie_gen[i] = driver_ppt->PcieGenSpeed[i]; - dpm_context->dpm_tables.pcie_table.pcie_lane[i] = driver_ppt->PcieLaneCount[i]; + /* phyclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.phy_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PHYCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; } return 0; @@ -877,20 +1004,17 @@ static int navi10_print_clk_levels(struct smu_context *smu, case SMU_UCLK: case SMU_FCLK: case SMU_DCEFCLK: - ret = smu_get_current_clk_freq(smu, clk_type, &cur_value); + ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value); if (ret) return size; - /* 10KHz -> MHz */ - cur_value = cur_value / 100; - - ret = smu_get_dpm_level_count(smu, clk_type, &count); + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); if (ret) return size; if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) { for (i = 0; i < count; i++) { - ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value); if (ret) return size; @@ -898,10 +1022,10 @@ static int navi10_print_clk_levels(struct smu_context *smu, cur_value == value ? "*" : ""); } } else { - ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); if (ret) return size; - ret = smu_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); if (ret) return size; @@ -978,7 +1102,7 @@ static int navi10_print_clk_levels(struct smu_context *smu, default: break; } - size += sprintf(buf + size, "%d: %uMHz @ %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE); + size += sprintf(buf + size, "%d: %uMHz %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE); } break; case SMU_OD_RANGE: @@ -1061,15 +1185,15 @@ static int navi10_force_clk_levels(struct smu_context *smu, soft_min_level = (soft_min_level >= 1 ? 1 : 0); } - ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); if (ret) return size; - ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); if (ret) return size; - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); + ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); if (ret) return size; break; @@ -1082,22 +1206,93 @@ static int navi10_force_clk_levels(struct smu_context *smu, static int navi10_populate_umd_state_clk(struct smu_context *smu) { - int ret = 0; - uint32_t min_sclk_freq = 0, min_mclk_freq = 0; - - ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, NULL, false); - if (ret) - return ret; - - smu->pstate_sclk = min_sclk_freq * 100; - - ret = smu_get_dpm_freq_range(smu, SMU_MCLK, &min_mclk_freq, NULL, false); - if (ret) - return ret; + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + struct amdgpu_device *adev = smu->adev; + uint32_t sclk_freq; - smu->pstate_mclk = min_mclk_freq * 100; + pstate_table->gfxclk_pstate.min = gfx_table->min; + switch (adev->asic_type) { + case CHIP_NAVI10: + switch (adev->pdev->revision) { + case 0xf0: /* XTX */ + case 0xc0: + sclk_freq = NAVI10_PEAK_SCLK_XTX; + break; + case 0xf1: /* XT */ + case 0xc1: + sclk_freq = NAVI10_PEAK_SCLK_XT; + break; + default: /* XL */ + sclk_freq = NAVI10_PEAK_SCLK_XL; + break; + } + break; + case CHIP_NAVI14: + switch (adev->pdev->revision) { + case 0xc7: /* XT */ + case 0xf4: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK; + break; + case 0xc1: /* XTM */ + case 0xf2: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK; + break; + case 0xc3: /* XLM */ + case 0xf3: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; + break; + case 0xc5: /* XTX */ + case 0xf6: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; + break; + default: /* XL */ + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK; + break; + } + break; + case CHIP_NAVI12: + sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK; + break; + default: + sclk_freq = gfx_table->dpm_levels[gfx_table->count - 1].value; + break; + } + pstate_table->gfxclk_pstate.peak = sclk_freq; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; + + if (gfx_table->max > NAVI10_UMD_PSTATE_PROFILING_GFXCLK && + mem_table->max > NAVI10_UMD_PSTATE_PROFILING_MEMCLK && + soc_table->max > NAVI10_UMD_PSTATE_PROFILING_SOCCLK) { + pstate_table->gfxclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_GFXCLK; + pstate_table->uclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_MEMCLK; + pstate_table->socclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_SOCCLK; + } else { + pstate_table->gfxclk_pstate.standard = + pstate_table->gfxclk_pstate.min; + pstate_table->uclk_pstate.standard = + pstate_table->uclk_pstate.min; + pstate_table->socclk_pstate.standard = + pstate_table->socclk_pstate.min; + } - return ret; + return 0; } static int navi10_get_clock_by_type_with_latency(struct smu_context *smu, @@ -1113,7 +1308,7 @@ static int navi10_get_clock_by_type_with_latency(struct smu_context *smu, case SMU_SOCCLK: case SMU_MCLK: case SMU_UCLK: - ret = smu_get_dpm_level_count(smu, clk_type, &level_count); + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &level_count); if (ret) return ret; @@ -1121,7 +1316,7 @@ static int navi10_get_clock_by_type_with_latency(struct smu_context *smu, clocks->num_levels = level_count; for (i = 0; i < level_count; i++) { - ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &freq); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &freq); if (ret) return ret; @@ -1146,10 +1341,10 @@ static int navi10_pre_display_config_changed(struct smu_context *smu) return ret; if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &max_freq, false); + ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq); if (ret) return ret; - ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, max_freq); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq); if (ret) return ret; } @@ -1174,59 +1369,6 @@ static int navi10_display_config_changed(struct smu_context *smu) return ret; } -static int navi10_force_dpm_limit_value(struct smu_context *smu, bool highest) -{ - int ret = 0, i = 0; - uint32_t min_freq, max_freq, force_freq; - enum smu_clk_type clk_type; - - enum smu_clk_type clks[] = { - SMU_GFXCLK, - SMU_MCLK, - SMU_SOCCLK, - }; - - for (i = 0; i < ARRAY_SIZE(clks); i++) { - clk_type = clks[i]; - ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq, false); - if (ret) - return ret; - - force_freq = highest ? max_freq : min_freq; - ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq, false); - if (ret) - return ret; - } - - return ret; -} - -static int navi10_unforce_dpm_levels(struct smu_context *smu) -{ - int ret = 0, i = 0; - uint32_t min_freq, max_freq; - enum smu_clk_type clk_type; - - enum smu_clk_type clks[] = { - SMU_GFXCLK, - SMU_MCLK, - SMU_SOCCLK, - }; - - for (i = 0; i < ARRAY_SIZE(clks); i++) { - clk_type = clks[i]; - ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq, false); - if (ret) - return ret; - - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); - if (ret) - return ret; - } - - return ret; -} - static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value) { if (!value) @@ -1479,47 +1621,6 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u return ret; } -static int navi10_get_profiling_clk_mask(struct smu_context *smu, - enum amd_dpm_forced_level level, - uint32_t *sclk_mask, - uint32_t *mclk_mask, - uint32_t *soc_mask) -{ - int ret = 0; - uint32_t level_count = 0; - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - if (sclk_mask) - *sclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - if (mclk_mask) - *mclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - if(sclk_mask) { - ret = smu_get_dpm_level_count(smu, SMU_SCLK, &level_count); - if (ret) - return ret; - *sclk_mask = level_count - 1; - } - - if(mclk_mask) { - ret = smu_get_dpm_level_count(smu, SMU_MCLK, &level_count); - if (ret) - return ret; - *mclk_mask = level_count - 1; - } - - if(soc_mask) { - ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, &level_count); - if (ret) - return ret; - *soc_mask = level_count - 1; - } - } - - return ret; -} - static int navi10_notify_smc_display_config(struct smu_context *smu) { struct smu_clocks min_clocks = {0}; @@ -1552,7 +1653,7 @@ static int navi10_notify_smc_display_config(struct smu_context *smu) } if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); if (ret) { dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__); return ret; @@ -1700,8 +1801,23 @@ static int navi10_read_sensor(struct smu_context *smu, ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = navi10_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = navi10_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); + *size = 4; + break; default: - ret = smu_v11_0_read_sensor(smu, sensor, data, size); + ret = -EOPNOTSUPP; + break; } mutex_unlock(&smu->sensor_lock); @@ -1737,160 +1853,32 @@ static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_ return 0; } -static int navi10_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level); - -static int navi10_set_standard_performance_level(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - uint32_t sclk_freq = 0, uclk_freq = 0; - - switch (adev->asic_type) { - case CHIP_NAVI10: - sclk_freq = NAVI10_UMD_PSTATE_PROFILING_GFXCLK; - uclk_freq = NAVI10_UMD_PSTATE_PROFILING_MEMCLK; - break; - case CHIP_NAVI14: - sclk_freq = NAVI14_UMD_PSTATE_PROFILING_GFXCLK; - uclk_freq = NAVI14_UMD_PSTATE_PROFILING_MEMCLK; - break; - default: - /* by default, this is same as auto performance level */ - return navi10_set_performance_level(smu, AMD_DPM_FORCED_LEVEL_AUTO); - } - - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false); - if (ret) - return ret; - ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); - if (ret) - return ret; - - return ret; -} - -static int navi10_set_peak_performance_level(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - uint32_t sclk_freq = 0, uclk_freq = 0; - - switch (adev->asic_type) { - case CHIP_NAVI10: - switch (adev->pdev->revision) { - case 0xf0: /* XTX */ - case 0xc0: - sclk_freq = NAVI10_PEAK_SCLK_XTX; - break; - case 0xf1: /* XT */ - case 0xc1: - sclk_freq = NAVI10_PEAK_SCLK_XT; - break; - default: /* XL */ - sclk_freq = NAVI10_PEAK_SCLK_XL; - break; - } - break; - case CHIP_NAVI14: - switch (adev->pdev->revision) { - case 0xc7: /* XT */ - case 0xf4: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK; - break; - case 0xc1: /* XTM */ - case 0xf2: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK; - break; - case 0xc3: /* XLM */ - case 0xf3: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; - break; - case 0xc5: /* XTX */ - case 0xf6: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; - break; - default: /* XL */ - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK; - break; - } - break; - case CHIP_NAVI12: - sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK; - break; - default: - ret = smu_get_dpm_level_range(smu, SMU_SCLK, NULL, &sclk_freq); - if (ret) - return ret; - } - - ret = smu_get_dpm_level_range(smu, SMU_UCLK, NULL, &uclk_freq); - if (ret) - return ret; - - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false); - if (ret) - return ret; - ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); - if (ret) - return ret; - - return ret; -} - -static int navi10_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level) -{ - int ret = 0; - uint32_t sclk_mask, mclk_mask, soc_mask; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = smu_force_dpm_limit_value(smu, true); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - ret = smu_force_dpm_limit_value(smu, false); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = smu_unforce_dpm_levels(smu); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - ret = navi10_set_standard_performance_level(smu); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - ret = smu_get_profiling_clk_mask(smu, level, - &sclk_mask, - &mclk_mask, - &soc_mask); - if (ret) - return ret; - smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask, false); - smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask, false); - smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask, false); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = navi10_set_peak_performance_level(smu); - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: - break; - } - return ret; -} - static int navi10_get_thermal_temperature_range(struct smu_context *smu, struct smu_temperature_range *range) { struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; - if (!range || !powerplay_table) + if (!range) return -EINVAL; - range->max = powerplay_table->software_shutdown_temp * + memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); + + range->max = pptable->TedgeLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_crit_max = pptable->ThotspotLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_crit_max = pptable->TmemLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)* + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->software_shutdown_temp = powerplay_table->software_shutdown_temp; return 0; } @@ -1909,9 +1897,9 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu, return 0; if(disable_memory_clock_switch) - ret = smu_set_hard_freq_range(smu, SMU_UCLK, max_memory_clock, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0); else - ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_memory_clock, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0); if(!ret) smu->disable_uclk_switch = disable_memory_clock_switch; @@ -1956,12 +1944,16 @@ static int navi10_update_pcie_parameters(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap) { + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; PPTable_t *pptable = smu->smu_table.driver_pptable; - int ret, i; uint32_t smu_pcie_arg; + int ret, i; - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; + /* lclk dpm table setup */ + for (i = 0; i < MAX_PCIE_CONF; i++) { + dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i]; + dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i]; + } for (i = 0; i < NUM_LINK_LEVELS; i++) { smu_pcie_arg = (i << 16) | @@ -2039,7 +2031,7 @@ static bool navi10_is_baco_supported(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; uint32_t val; - if (!smu_v11_0_baco_is_support(smu)) + if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu))) return false; val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); @@ -2319,25 +2311,25 @@ static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) if (smu_version < 0x2A3200) return 0; - ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_count); + ret = smu_v11_0_get_dpm_level_count(smu, SMU_UCLK, &uclk_count); if (ret) return ret; - ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min); + ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min); if (ret) return ret; - ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max); + ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max); if (ret) return ret; /* Force UCLK out of the highest DPM */ - ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, uclk_min); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_min); if (ret) return ret; /* Revert the UCLK Hardmax */ - ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, uclk_max); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_max); if (ret) return ret; @@ -2348,37 +2340,6 @@ static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) return navi10_dummy_pstate_control(smu, true); } -static int navi10_set_thermal_range(struct smu_context *smu, - struct smu_temperature_range range) -{ - struct amdgpu_device *adev = smu->adev; - int low = SMU_THERMAL_MINIMUM_ALERT_TEMP; - int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP; - uint32_t val; - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table; - - low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, - range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES); - high = min((uint16_t)SMU_THERMAL_MAXIMUM_ALERT_TEMP, powerplay_table->software_shutdown_temp); - - if (low > high) - return -EINVAL; - - val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff)); - val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); - - return 0; -} - static const struct pptable_funcs navi10_ppt_funcs = { .tables_init = navi10_tables_init, .alloc_dpm_context = navi10_allocate_dpm_context, @@ -2392,7 +2353,6 @@ static const struct pptable_funcs navi10_ppt_funcs = { .set_default_dpm_table = navi10_set_default_dpm_table, .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable, .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable, - .get_current_clk_freq_by_table = navi10_get_current_clk_freq_by_table, .print_clk_levels = navi10_print_clk_levels, .force_clk_levels = navi10_force_clk_levels, .populate_umd_state_clk = navi10_populate_umd_state_clk, @@ -2400,18 +2360,15 @@ static const struct pptable_funcs navi10_ppt_funcs = { .pre_display_config_changed = navi10_pre_display_config_changed, .display_config_changed = navi10_display_config_changed, .notify_smc_display_config = navi10_notify_smc_display_config, - .force_dpm_limit_value = navi10_force_dpm_limit_value, - .unforce_dpm_levels = navi10_unforce_dpm_levels, .is_dpm_running = navi10_is_dpm_running, .get_fan_speed_percent = navi10_get_fan_speed_percent, .get_fan_speed_rpm = navi10_get_fan_speed_rpm, .get_power_profile_mode = navi10_get_power_profile_mode, .set_power_profile_mode = navi10_set_power_profile_mode, - .get_profiling_clk_mask = navi10_get_profiling_clk_mask, .set_watermarks_table = navi10_set_watermarks_table, .read_sensor = navi10_read_sensor, .get_uclk_dpm_states = navi10_get_uclk_dpm_states, - .set_performance_level = navi10_set_performance_level, + .set_performance_level = smu_v11_0_set_performance_level, .get_thermal_temperature_range = navi10_get_thermal_temperature_range, .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch, .get_power_limit = navi10_get_power_limit, @@ -2438,7 +2395,6 @@ static const struct pptable_funcs navi10_ppt_funcs = { .get_enabled_mask = smu_v11_0_get_enabled_mask, .notify_display_change = smu_v11_0_notify_display_change, .set_power_limit = smu_v11_0_set_power_limit, - .get_current_clk_freq = smu_v11_0_get_current_clk_freq, .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, .enable_thermal_alert = smu_v11_0_enable_thermal_alert, .disable_thermal_alert = smu_v11_0_disable_thermal_alert, @@ -2460,13 +2416,11 @@ static const struct pptable_funcs navi10_ppt_funcs = { .baco_exit = smu_v11_0_baco_exit, .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, - .override_pcie_parameters = smu_v11_0_override_pcie_parameters, .set_default_od_settings = navi10_set_default_od_settings, .od_edit_dpm_table = navi10_od_edit_dpm_table, .run_btc = navi10_run_btc, .disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround, .set_power_source = smu_v11_0_set_power_source, - .set_thermal_range = navi10_set_thermal_range, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index f286c1e1934f..79cadc2df0d5 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -236,23 +236,173 @@ static int renoir_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type if (!clk_table || clk_type >= SMU_CLK_COUNT) return -EINVAL; - GET_DPM_CUR_FREQ(clk_table, clk_type, dpm_level, *freq); + switch (clk_type) { + case SMU_SOCCLK: + if (dpm_level >= NUM_SOCCLK_DPM_LEVELS) + return -EINVAL; + *freq = clk_table->SocClocks[dpm_level].Freq; + break; + case SMU_MCLK: + if (dpm_level >= NUM_FCLK_DPM_LEVELS) + return -EINVAL; + *freq = clk_table->FClocks[dpm_level].Freq; + break; + case SMU_DCEFCLK: + if (dpm_level >= NUM_DCFCLK_DPM_LEVELS) + return -EINVAL; + *freq = clk_table->DcfClocks[dpm_level].Freq; + break; + case SMU_FCLK: + if (dpm_level >= NUM_FCLK_DPM_LEVELS) + return -EINVAL; + *freq = clk_table->FClocks[dpm_level].Freq; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int renoir_get_profiling_clk_mask(struct smu_context *smu, + enum amd_dpm_forced_level level, + uint32_t *sclk_mask, + uint32_t *mclk_mask, + uint32_t *soc_mask) +{ + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + if (sclk_mask) + *sclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { + if (mclk_mask) + *mclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + if(sclk_mask) + /* The sclk as gfxclk and has three level about max/min/current */ + *sclk_mask = 3 - 1; + + if(mclk_mask) + *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1; + + if(soc_mask) + *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1; + } return 0; } +static int renoir_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + int ret = 0; + uint32_t mclk_mask, soc_mask; + uint32_t clock_limit; + + if (!smu_clk_dpm_is_enabled(smu, clk_type)) { + switch (clk_type) { + case SMU_MCLK: + case SMU_UCLK: + clock_limit = smu->smu_table.boot_values.uclk; + break; + case SMU_GFXCLK: + case SMU_SCLK: + clock_limit = smu->smu_table.boot_values.gfxclk; + break; + case SMU_SOCCLK: + clock_limit = smu->smu_table.boot_values.socclk; + break; + default: + clock_limit = 0; + break; + } + + /* clock in Mhz unit */ + if (min) + *min = clock_limit / 100; + if (max) + *max = clock_limit / 100; + + return 0; + } + + if (max) { + ret = renoir_get_profiling_clk_mask(smu, + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK, + NULL, + &mclk_mask, + &soc_mask); + if (ret) + goto failed; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + ret = smu_send_smc_msg(smu, SMU_MSG_GetMaxGfxclkFrequency, max); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get max GX frequency from SMC Failed !\n"); + goto failed; + } + break; + case SMU_UCLK: + case SMU_FCLK: + case SMU_MCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, mclk_mask, max); + if (ret) + goto failed; + break; + case SMU_SOCCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, soc_mask, max); + if (ret) + goto failed; + break; + default: + ret = -EINVAL; + goto failed; + } + } + + if (min) { + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + ret = smu_send_smc_msg(smu, SMU_MSG_GetMinGfxclkFrequency, min); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get min GX frequency from SMC Failed !\n"); + goto failed; + } + break; + case SMU_UCLK: + case SMU_FCLK: + case SMU_MCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min); + if (ret) + goto failed; + break; + case SMU_SOCCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min); + if (ret) + goto failed; + break; + default: + ret = -EINVAL; + goto failed; + } + } +failed: + return ret; +} + static int renoir_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { int i, size = 0, ret = 0; uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0; - DpmClocks_t *clk_table = smu->smu_table.clocks_table; SmuMetrics_t metrics; bool cur_value_match_level = false; - if (!clk_table || clk_type >= SMU_CLK_COUNT) - return -EINVAL; - memset(&metrics, 0, sizeof(metrics)); ret = renoir_get_metrics_table(smu, &metrics); @@ -264,7 +414,7 @@ static int renoir_print_clk_levels(struct smu_context *smu, case SMU_SCLK: /* retirve table returned paramters unit is MHz */ cur_value = metrics.ClockFrequency[CLOCK_GFXCLK]; - ret = smu_get_dpm_freq_range(smu, SMU_GFXCLK, &min, &max, false); + ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min, &max); if (!ret) { /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */ if (cur_value == max) @@ -304,7 +454,9 @@ static int renoir_print_clk_levels(struct smu_context *smu, } for (i = 0; i < count; i++) { - GET_DPM_CUR_FREQ(clk_table, clk_type, i, value); + ret = renoir_get_dpm_clk_limited(smu, clk_type, i, &value); + if (ret) + return ret; if (!value) continue; size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, @@ -434,12 +586,12 @@ static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest) for (i = 0; i < ARRAY_SIZE(clks); i++) { clk_type = clks[i]; - ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq, false); + ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); if (ret) return ret; force_freq = highest ? max_freq : min_freq; - ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq, false); + ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq); if (ret) return ret; } @@ -468,11 +620,11 @@ static int renoir_unforce_dpm_levels(struct smu_context *smu) { clk_type = clk_feature_map[i].clk_type; - ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq, false); + ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); if (ret) return ret; - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); + ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); if (ret) return ret; } @@ -552,33 +704,6 @@ static int renoir_get_workload_type(struct smu_context *smu, uint32_t profile) return pplib_workload; } -static int renoir_get_profiling_clk_mask(struct smu_context *smu, - enum amd_dpm_forced_level level, - uint32_t *sclk_mask, - uint32_t *mclk_mask, - uint32_t *soc_mask) -{ - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - if (sclk_mask) - *sclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - if (mclk_mask) - *mclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - if(sclk_mask) - /* The sclk as gfxclk and has three level about max/min/current */ - *sclk_mask = 3 - 1; - - if(mclk_mask) - *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1; - - if(soc_mask) - *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1; - } - - return 0; -} /** * This interface get dpm clock table for dc @@ -620,7 +745,6 @@ static int renoir_force_clk_levels(struct smu_context *smu, int ret = 0 ; uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; - DpmClocks_t *clk_table = smu->smu_table.clocks_table; soft_min_level = mask ? (ffs(mask) - 1) : 0; soft_max_level = mask ? (fls(mask) - 1) : 0; @@ -633,7 +757,7 @@ static int renoir_force_clk_levels(struct smu_context *smu, return -EINVAL; } - ret = smu_get_dpm_freq_range(smu, SMU_GFXCLK, &min_freq, &max_freq, false); + ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min_freq, &max_freq); if (ret) return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, @@ -650,8 +774,12 @@ static int renoir_force_clk_levels(struct smu_context *smu, return ret; break; case SMU_SOCCLK: - GET_DPM_CUR_FREQ(clk_table, clk_type, soft_min_level, min_freq); - GET_DPM_CUR_FREQ(clk_table, clk_type, soft_max_level, max_freq); + ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq); + if (ret) + return ret; + ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq); + if (ret) + return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq, NULL); if (ret) return ret; @@ -661,8 +789,12 @@ static int renoir_force_clk_levels(struct smu_context *smu, break; case SMU_MCLK: case SMU_FCLK: - GET_DPM_CUR_FREQ(clk_table, clk_type, soft_min_level, min_freq); - GET_DPM_CUR_FREQ(clk_table, clk_type, soft_max_level, max_freq); + ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq); + if (ret) + return ret; + ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq); + if (ret) + return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq, NULL); if (ret) return ret; @@ -683,22 +815,22 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u uint32_t profile_mode = input[size]; if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { - dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode); + dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode); return -EINVAL; } /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = smu_workload_get_type(smu, smu->power_profile_mode); + workload_type = smu_workload_get_type(smu, profile_mode); if (workload_type < 0) { /* * TODO: If some case need switch to powersave/default power mode * then can consider enter WORKLOAD_COMPUTE/WORKLOAD_CUSTOM for power saving. */ - dev_err_once(smu->adev->dev, "Unsupported power profile mode %d on RENOIR\n",smu->power_profile_mode); + dev_err_once(smu->adev->dev, "Unsupported power profile mode %d on RENOIR\n", profile_mode); return -EINVAL; } - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify, 1 << workload_type, NULL); if (ret) { @@ -716,19 +848,19 @@ static int renoir_set_peak_clock_by_device(struct smu_context *smu) int ret = 0; uint32_t sclk_freq = 0, uclk_freq = 0; - ret = smu_get_dpm_freq_range(smu, SMU_SCLK, NULL, &sclk_freq, false); + ret = renoir_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_freq); if (ret) return ret; - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false); + ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk_freq, sclk_freq); if (ret) return ret; - ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &uclk_freq, false); + ret = renoir_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &uclk_freq); if (ret) return ret; - ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); + ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_UCLK, uclk_freq, uclk_freq); if (ret) return ret; @@ -743,26 +875,26 @@ static int renoir_set_performance_level(struct smu_context *smu, switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: - ret = smu_force_dpm_limit_value(smu, true); + ret = renoir_force_dpm_limit_value(smu, true); break; case AMD_DPM_FORCED_LEVEL_LOW: - ret = smu_force_dpm_limit_value(smu, false); + ret = renoir_force_dpm_limit_value(smu, false); break; case AMD_DPM_FORCED_LEVEL_AUTO: case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - ret = smu_unforce_dpm_levels(smu); + ret = renoir_unforce_dpm_levels(smu); break; case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - ret = smu_get_profiling_clk_mask(smu, level, - &sclk_mask, - &mclk_mask, - &soc_mask); + ret = renoir_get_profiling_clk_mask(smu, level, + &sclk_mask, + &mclk_mask, + &soc_mask); if (ret) return ret; - smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask, false); - smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask, false); - smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask, false); + renoir_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask); + renoir_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask); + renoir_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask); break; case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: ret = renoir_set_peak_clock_by_device(smu); @@ -896,8 +1028,19 @@ static int renoir_read_sensor(struct smu_context *smu, ret = renoir_get_gpu_temperature(smu, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = renoir_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = renoir_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; default: - ret = smu_v12_0_read_sensor(smu, sensor, data, size); + ret = -EOPNOTSUPP; + break; } mutex_unlock(&smu->sensor_lock); @@ -926,16 +1069,11 @@ static const struct pptable_funcs renoir_ppt_funcs = { .get_smu_table_index = renoir_get_smu_table_index, .tables_init = renoir_tables_init, .set_power_state = NULL, - .get_dpm_clk_limited = renoir_get_dpm_clk_limited, .print_clk_levels = renoir_print_clk_levels, .get_current_power_state = renoir_get_current_power_state, .dpm_set_vcn_enable = renoir_dpm_set_vcn_enable, .dpm_set_jpeg_enable = renoir_dpm_set_jpeg_enable, - .get_current_clk_freq_by_table = renoir_get_current_clk_freq_by_table, - .force_dpm_limit_value = renoir_force_dpm_limit_value, - .unforce_dpm_levels = renoir_unforce_dpm_levels, .get_workload_type = renoir_get_workload_type, - .get_profiling_clk_mask = renoir_get_profiling_clk_mask, .force_clk_levels = renoir_force_clk_levels, .set_power_profile_mode = renoir_set_power_profile_mode, .set_performance_level = renoir_set_performance_level, @@ -953,8 +1091,7 @@ static const struct pptable_funcs renoir_ppt_funcs = { .fini_smc_tables = smu_v12_0_fini_smc_tables, .set_default_dpm_table = smu_v12_0_set_default_dpm_tables, .get_enabled_mask = smu_v12_0_get_enabled_mask, - .get_current_clk_freq = smu_v12_0_get_current_clk_freq, - .get_dpm_ultimate_freq = smu_v12_0_get_dpm_ultimate_freq, + .get_dpm_ultimate_freq = renoir_get_dpm_ultimate_freq, .mode2_reset = smu_v12_0_mode2_reset, .set_soft_freq_limited_range = smu_v12_0_set_soft_freq_limited_range, .set_driver_table_location = smu_v12_0_set_driver_table_location, diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.h b/drivers/gpu/drm/amd/powerplay/renoir_ppt.h index 89cd6da118a3..8c3f004cdf8d 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.h +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.h @@ -30,24 +30,4 @@ extern void renoir_set_ppt_funcs(struct smu_context *smu); #define RENOIR_UMD_PSTATE_SOCCLK 678 #define RENOIR_UMD_PSTATE_FCLK 800 -#define GET_DPM_CUR_FREQ(table, clk_type, dpm_level, freq) \ - do { \ - switch (clk_type) { \ - case SMU_SOCCLK: \ - freq = table->SocClocks[dpm_level].Freq; \ - break; \ - case SMU_MCLK: \ - freq = table->FClocks[dpm_level].Freq; \ - break; \ - case SMU_DCEFCLK: \ - freq = table->DcfClocks[dpm_level].Freq; \ - break; \ - case SMU_FCLK: \ - freq = table->FClocks[dpm_level].Freq; \ - break; \ - default: \ - break; \ - } \ - } while (0) - #endif diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 1378dabb6463..5faef41b63a3 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -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] = { @@ -394,7 +395,6 @@ static int sienna_cichlid_append_powerplay_table(struct smu_context *smu) PPTable_t *smc_pptable = table_context->driver_pptable; struct atom_smc_dpm_info_v4_9 *smc_dpm_table; int index, ret; - int i; index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, smc_dpm_info); @@ -405,92 +405,8 @@ static int sienna_cichlid_append_powerplay_table(struct smu_context *smu) return ret; memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers, - sizeof(I2cControllerConfig_t) * NUM_I2C_CONTROLLERS); - - /* SVI2 Board Parameters */ - smc_pptable->VddGfxVrMapping = smc_dpm_table->VddGfxVrMapping; - smc_pptable->VddSocVrMapping = smc_dpm_table->VddSocVrMapping; - smc_pptable->VddMem0VrMapping = smc_dpm_table->VddMem0VrMapping; - smc_pptable->VddMem1VrMapping = smc_dpm_table->VddMem1VrMapping; - smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->GfxUlvPhaseSheddingMask; - smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->SocUlvPhaseSheddingMask; - smc_pptable->VddciUlvPhaseSheddingMask = smc_dpm_table->VddciUlvPhaseSheddingMask; - smc_pptable->MvddUlvPhaseSheddingMask = smc_dpm_table->MvddUlvPhaseSheddingMask; - - /* Telemetry Settings */ - smc_pptable->GfxMaxCurrent = smc_dpm_table->GfxMaxCurrent; - smc_pptable->GfxOffset = smc_dpm_table->GfxOffset; - smc_pptable->Padding_TelemetryGfx = smc_dpm_table->Padding_TelemetryGfx; - smc_pptable->SocMaxCurrent = smc_dpm_table->SocMaxCurrent; - smc_pptable->SocOffset = smc_dpm_table->SocOffset; - smc_pptable->Padding_TelemetrySoc = smc_dpm_table->Padding_TelemetrySoc; - smc_pptable->Mem0MaxCurrent = smc_dpm_table->Mem0MaxCurrent; - smc_pptable->Mem0Offset = smc_dpm_table->Mem0Offset; - smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->Padding_TelemetryMem0; - smc_pptable->Mem1MaxCurrent = smc_dpm_table->Mem1MaxCurrent; - smc_pptable->Mem1Offset = smc_dpm_table->Mem1Offset; - smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->Padding_TelemetryMem1; - smc_pptable->MvddRatio = smc_dpm_table->MvddRatio; - - /* GPIO Settings */ - smc_pptable->AcDcGpio = smc_dpm_table->AcDcGpio; - smc_pptable->AcDcPolarity = smc_dpm_table->AcDcPolarity; - smc_pptable->VR0HotGpio = smc_dpm_table->VR0HotGpio; - smc_pptable->VR0HotPolarity = smc_dpm_table->VR0HotPolarity; - smc_pptable->VR1HotGpio = smc_dpm_table->VR1HotGpio; - smc_pptable->VR1HotPolarity = smc_dpm_table->VR1HotPolarity; - smc_pptable->GthrGpio = smc_dpm_table->GthrGpio; - smc_pptable->GthrPolarity = smc_dpm_table->GthrPolarity; - - /* LED Display Settings */ - smc_pptable->LedPin0 = smc_dpm_table->LedPin0; - smc_pptable->LedPin1 = smc_dpm_table->LedPin1; - smc_pptable->LedPin2 = smc_dpm_table->LedPin2; - smc_pptable->LedEnableMask = smc_dpm_table->LedEnableMask; - smc_pptable->LedPcie = smc_dpm_table->LedPcie; - smc_pptable->LedError = smc_dpm_table->LedError; - smc_pptable->LedSpare1[0] = smc_dpm_table->LedSpare1[0]; - smc_pptable->LedSpare1[1] = smc_dpm_table->LedSpare1[1]; - - /* GFXCLK PLL Spread Spectrum */ - smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->PllGfxclkSpreadEnabled; - smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->PllGfxclkSpreadPercent; - smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->PllGfxclkSpreadFreq; - - /* GFXCLK DFLL Spread Spectrum */ - smc_pptable->DfllGfxclkSpreadEnabled = smc_dpm_table->DfllGfxclkSpreadEnabled; - smc_pptable->DfllGfxclkSpreadPercent = smc_dpm_table->DfllGfxclkSpreadPercent; - smc_pptable->DfllGfxclkSpreadFreq = smc_dpm_table->DfllGfxclkSpreadFreq; - - /* UCLK Spread Spectrum */ - smc_pptable->UclkSpreadEnabled = smc_dpm_table->UclkSpreadEnabled; - smc_pptable->UclkSpreadPercent = smc_dpm_table->UclkSpreadPercent; - smc_pptable->UclkSpreadFreq = smc_dpm_table->UclkSpreadFreq; - - /* FCLK Spred Spectrum */ - smc_pptable->FclkSpreadEnabled = smc_dpm_table->FclkSpreadEnabled; - smc_pptable->FclkSpreadPercent = smc_dpm_table->FclkSpreadPercent; - smc_pptable->FclkSpreadFreq = smc_dpm_table->FclkSpreadFreq; - - /* Memory Config */ - smc_pptable->MemoryChannelEnabled = smc_dpm_table->MemoryChannelEnabled; - smc_pptable->DramBitWidth = smc_dpm_table->DramBitWidth; - smc_pptable->PaddingMem1[0] = smc_dpm_table->PaddingMem1[0]; - smc_pptable->PaddingMem1[1] = smc_dpm_table->PaddingMem1[1]; - smc_pptable->PaddingMem1[2] = smc_dpm_table->PaddingMem1[2]; - - /* Total board power */ - smc_pptable->TotalBoardPower = smc_dpm_table->TotalBoardPower; - smc_pptable->BoardPowerPadding = smc_dpm_table->BoardPowerPadding; - - /* XGMI Training */ - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) { - smc_pptable->XgmiLinkSpeed[i] = smc_dpm_table->XgmiLinkSpeed[i]; - smc_pptable->XgmiLinkWidth[i] = smc_dpm_table->XgmiLinkWidth[i]; - smc_pptable->XgmiFclkFreq[i] = smc_dpm_table->XgmiFclkFreq[i]; - smc_pptable->XgmiSocVoltage[i] = smc_dpm_table->XgmiSocVoltage[i]; - } - + sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header)); + return 0; } @@ -682,44 +598,225 @@ static int sienna_cichlid_allocate_dpm_context(struct smu_context *smu) static int sienna_cichlid_set_default_dpm_table(struct smu_context *smu) { - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; - PPTable_t *driver_ppt = NULL; - int i; + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *driver_ppt = smu->smu_table.driver_pptable; + struct smu_11_0_dpm_table *dpm_table; + int ret = 0; - driver_ppt = table_context->driver_pptable; + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.soc_table.min = driver_ppt->FreqTableSocclk[0]; - dpm_context->dpm_tables.soc_table.max = driver_ppt->FreqTableSocclk[NUM_SOCCLK_DPM_LEVELS - 1]; + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.gfx_table.min = driver_ppt->FreqTableGfx[0]; - dpm_context->dpm_tables.gfx_table.max = driver_ppt->FreqTableGfx[NUM_GFXCLK_DPM_LEVELS - 1]; + /* uclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.uclk_table.min = driver_ppt->FreqTableUclk[0]; - dpm_context->dpm_tables.uclk_table.max = driver_ppt->FreqTableUclk[NUM_UCLK_DPM_LEVELS - 1]; + /* fclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.fclk_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_FCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.vclk_table.min = driver_ppt->FreqTableVclk[0]; - dpm_context->dpm_tables.vclk_table.max = driver_ppt->FreqTableVclk[NUM_VCLK_DPM_LEVELS - 1]; + /* vclk0 dpm table setup */ + dpm_table = &dpm_context->dpm_tables.vclk_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_VCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_VCLK_0].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.dclk_table.min = driver_ppt->FreqTableDclk[0]; - dpm_context->dpm_tables.dclk_table.max = driver_ppt->FreqTableDclk[NUM_DCLK_DPM_LEVELS - 1]; + /* vclk1 dpm table setup */ + dpm_table = &dpm_context->dpm_tables.vclk1_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_VCLK1, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_VCLK_1].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.dcef_table.min = driver_ppt->FreqTableDcefclk[0]; - dpm_context->dpm_tables.dcef_table.max = driver_ppt->FreqTableDcefclk[NUM_DCEFCLK_DPM_LEVELS - 1]; + /* dclk0 dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dclk_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCLK_0].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.pixel_table.min = driver_ppt->FreqTablePixclk[0]; - dpm_context->dpm_tables.pixel_table.max = driver_ppt->FreqTablePixclk[NUM_PIXCLK_DPM_LEVELS - 1]; + /* dclk1 dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dclk1_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCLK1, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCLK_1].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.display_table.min = driver_ppt->FreqTableDispclk[0]; - dpm_context->dpm_tables.display_table.max = driver_ppt->FreqTableDispclk[NUM_DISPCLK_DPM_LEVELS - 1]; + /* dcefclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dcef_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCEFCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - dpm_context->dpm_tables.phy_table.min = driver_ppt->FreqTablePhyclk[0]; - dpm_context->dpm_tables.phy_table.max = driver_ppt->FreqTablePhyclk[NUM_PHYCLK_DPM_LEVELS - 1]; + /* pixelclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.pixel_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PIXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } - for (i = 0; i < MAX_PCIE_CONF; i++) { - dpm_context->dpm_tables.pcie_table.pcie_gen[i] = driver_ppt->PcieGenSpeed[i]; - dpm_context->dpm_tables.pcie_table.pcie_lane[i] = driver_ppt->PcieLaneCount[i]; + /* displayclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.display_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DISPCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* phyclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.phy_table; + if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PHYCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; } return 0; @@ -729,6 +826,8 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; + struct amdgpu_device *adev = smu->adev; + int ret = 0; if (enable) { @@ -737,9 +836,12 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); if (ret) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0x10000, NULL); - if (ret) - return ret; + if (adev->asic_type == CHIP_SIENNA_CICHLID) { + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, + 0x10000, NULL); + if (ret) + return ret; + } } power_gate->vcn_gated = false; } else { @@ -747,9 +849,12 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); if (ret) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0x10000, NULL); - if (ret) - return ret; + if (adev->asic_type == CHIP_SIENNA_CICHLID) { + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, + 0x10000, NULL); + if (ret) + return ret; + } } power_gate->vcn_gated = true; } @@ -866,24 +971,21 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, case SMU_UCLK: case SMU_FCLK: case SMU_DCEFCLK: - ret = smu_get_current_clk_freq(smu, clk_type, &cur_value); + ret = sienna_cichlid_get_current_clk_freq_by_table(smu, clk_type, &cur_value); if (ret) goto print_clk_out; - /* 10KHz -> MHz */ - cur_value = cur_value / 100; - /* no need to disable gfxoff when retrieving the current gfxclk */ if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) amdgpu_gfx_off_ctrl(adev, false); - ret = smu_get_dpm_level_count(smu, clk_type, &count); + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); if (ret) goto print_clk_out; if (!sienna_cichlid_is_support_fine_grained_dpm(smu, clk_type)) { for (i = 0; i < count; i++) { - ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value); if (ret) goto print_clk_out; @@ -891,10 +993,10 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, cur_value == value ? "*" : ""); } } else { - ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); if (ret) goto print_clk_out; - ret = smu_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); if (ret) goto print_clk_out; @@ -973,15 +1075,15 @@ static int sienna_cichlid_force_clk_levels(struct smu_context *smu, soft_min_level = (soft_min_level >= 1 ? 1 : 0); } - ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); if (ret) goto forec_level_out; - ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); if (ret) goto forec_level_out; - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); + ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); if (ret) goto forec_level_out; break; @@ -998,22 +1100,27 @@ forec_level_out: static int sienna_cichlid_populate_umd_state_clk(struct smu_context *smu) { - int ret = 0; - uint32_t min_sclk_freq = 0, min_mclk_freq = 0; - - ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, NULL, false); - if (ret) - return ret; - - smu->pstate_sclk = min_sclk_freq * 100; + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + + pstate_table->gfxclk_pstate.min = gfx_table->min; + pstate_table->gfxclk_pstate.peak = gfx_table->max; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; - ret = smu_get_dpm_freq_range(smu, SMU_MCLK, &min_mclk_freq, NULL, false); - if (ret) - return ret; - - smu->pstate_mclk = min_mclk_freq * 100; - - return ret; + return 0; } static int sienna_cichlid_pre_display_config_changed(struct smu_context *smu) @@ -1030,10 +1137,10 @@ static int sienna_cichlid_pre_display_config_changed(struct smu_context *smu) #endif if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &max_freq, false); + ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq); if (ret) return ret; - ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, max_freq); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq); if (ret) return ret; } @@ -1060,59 +1167,6 @@ static int sienna_cichlid_display_config_changed(struct smu_context *smu) return ret; } -static int sienna_cichlid_force_dpm_limit_value(struct smu_context *smu, bool highest) -{ - int ret = 0, i = 0; - uint32_t min_freq, max_freq, force_freq; - enum smu_clk_type clk_type; - - enum smu_clk_type clks[] = { - SMU_GFXCLK, - SMU_MCLK, - SMU_SOCCLK, - }; - - for (i = 0; i < ARRAY_SIZE(clks); i++) { - clk_type = clks[i]; - ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq, false); - if (ret) - return ret; - - force_freq = highest ? max_freq : min_freq; - ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq, false); - if (ret) - return ret; - } - - return ret; -} - -static int sienna_cichlid_unforce_dpm_levels(struct smu_context *smu) -{ - int ret = 0, i = 0; - uint32_t min_freq, max_freq; - enum smu_clk_type clk_type; - - enum smu_clk_type clks[] = { - SMU_GFXCLK, - SMU_MCLK, - SMU_SOCCLK, - }; - - for (i = 0; i < ARRAY_SIZE(clks); i++) { - clk_type = clks[i]; - ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq, false); - if (ret) - return ret; - - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); - if (ret) - return ret; - } - - return ret; -} - static int sienna_cichlid_get_gpu_power(struct smu_context *smu, uint32_t *value) { if (!value) @@ -1365,50 +1419,6 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long * return ret; } -static int sienna_cichlid_get_profiling_clk_mask(struct smu_context *smu, - enum amd_dpm_forced_level level, - uint32_t *sclk_mask, - uint32_t *mclk_mask, - uint32_t *soc_mask) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - uint32_t level_count = 0; - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - if (sclk_mask) - *sclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - if (mclk_mask) - *mclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - if(sclk_mask) { - amdgpu_gfx_off_ctrl(adev, false); - ret = smu_get_dpm_level_count(smu, SMU_SCLK, &level_count); - amdgpu_gfx_off_ctrl(adev, true); - if (ret) - return ret; - *sclk_mask = level_count - 1; - } - - if(mclk_mask) { - ret = smu_get_dpm_level_count(smu, SMU_MCLK, &level_count); - if (ret) - return ret; - *mclk_mask = level_count - 1; - } - - if(soc_mask) { - ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, &level_count); - if (ret) - return ret; - *soc_mask = level_count - 1; - } - } - - return ret; -} - static int sienna_cichlid_notify_smc_display_config(struct smu_context *smu) { struct smu_clocks min_clocks = {0}; @@ -1441,7 +1451,7 @@ static int sienna_cichlid_notify_smc_display_config(struct smu_context *smu) } if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); if (ret) { dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__); return ret; @@ -1588,8 +1598,23 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu, ret = sienna_cichlid_thermal_get_temperature(smu, sensor, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); + *size = 4; + break; default: - ret = smu_v11_0_read_sensor(smu, sensor, data, size); + ret = -EOPNOTSUPP; + break; } mutex_unlock(&smu->sensor_lock); @@ -1625,93 +1650,32 @@ static int sienna_cichlid_get_uclk_dpm_states(struct smu_context *smu, uint32_t return 0; } -static int sienna_cichlid_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level); - -static int sienna_cichlid_set_standard_performance_level(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - uint32_t sclk_freq = 0, uclk_freq = 0; - - switch (adev->asic_type) { - /* TODO: need to set specify clk value by asic type, not support yet*/ - default: - /* by default, this is same as auto performance level */ - return sienna_cichlid_set_performance_level(smu, AMD_DPM_FORCED_LEVEL_AUTO); - } - - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false); - if (ret) - return ret; - ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); - if (ret) - return ret; - - return ret; -} - -static int sienna_cichlid_set_peak_performance_level(struct smu_context *smu) -{ - int ret = 0; - - /* TODO: not support yet*/ - return ret; -} - -static int sienna_cichlid_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level) -{ - int ret = 0; - uint32_t sclk_mask, mclk_mask, soc_mask; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = smu_force_dpm_limit_value(smu, true); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - ret = smu_force_dpm_limit_value(smu, false); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = smu_unforce_dpm_levels(smu); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - ret = sienna_cichlid_set_standard_performance_level(smu); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - ret = smu_get_profiling_clk_mask(smu, level, - &sclk_mask, - &mclk_mask, - &soc_mask); - if (ret) - return ret; - smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask, false); - smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask, false); - smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask, false); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = sienna_cichlid_set_peak_performance_level(smu); - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: - break; - } - return ret; -} - static int sienna_cichlid_get_thermal_temperature_range(struct smu_context *smu, struct smu_temperature_range *range) { struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_7_powerplay_table *powerplay_table = table_context->power_play_table; + struct smu_11_0_7_powerplay_table *powerplay_table = + table_context->power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; - if (!range || !powerplay_table) + if (!range) return -EINVAL; - range->max = powerplay_table->software_shutdown_temp * + memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); + + range->max = pptable->TemperatureLimit[TEMP_EDGE] * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->edge_emergency_max = (pptable->TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_crit_max = pptable->TemperatureLimit[TEMP_HOTSPOT] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_emergency_max = (pptable->TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_crit_max = pptable->TemperatureLimit[TEMP_MEM] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_emergency_max = (pptable->TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)* + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->software_shutdown_temp = powerplay_table->software_shutdown_temp; return 0; } @@ -1730,9 +1694,9 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context return 0; if(disable_memory_clock_switch) - ret = smu_set_hard_freq_range(smu, SMU_UCLK, max_memory_clock, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0); else - ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_memory_clock, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0); if(!ret) smu->disable_uclk_switch = disable_memory_clock_switch; @@ -1775,12 +1739,16 @@ static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap) { + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; PPTable_t *pptable = smu->smu_table.driver_pptable; - int ret, i; uint32_t smu_pcie_arg; + int ret, i; - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; + /* lclk dpm table setup */ + for (i = 0; i < MAX_PCIE_CONF; i++) { + dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i]; + dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i]; + } for (i = 0; i < NUM_LINK_LEVELS; i++) { smu_pcie_arg = (i << 16) | @@ -1824,63 +1792,38 @@ static int sienna_cichlid_get_dpm_ultimate_freq(struct smu_context *smu, return ret; } -static int sienna_cichlid_set_soft_freq_limited_range(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t min, uint32_t max) -{ - struct amdgpu_device *adev = smu->adev; - int ret; - - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, false); - ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min, max); - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, true); - - return ret; -} - static bool sienna_cichlid_is_baco_supported(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; uint32_t val; - if (!smu_v11_0_baco_is_support(smu)) + if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu))) return false; val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; } -static int sienna_cichlid_set_thermal_range(struct smu_context *smu, - struct smu_temperature_range range) +static bool sienna_cichlid_is_mode1_reset_supported(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; - int low = SMU_THERMAL_MINIMUM_ALERT_TEMP; - int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_7_powerplay_table *powerplay_table = table_context->power_play_table; - - low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, - range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES); - high = min((uint16_t)SMU_THERMAL_MAXIMUM_ALERT_TEMP, powerplay_table->software_shutdown_temp); - - if (low > high) - return -EINVAL; - - val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff)); - val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, 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; - return 0; + /** + * 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 void sienna_cichlid_dump_pptable(struct smu_context *smu) @@ -2402,7 +2345,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu) dev_info(smu->adev->dev, "SkuReserved[11] = 0x%x\n", pptable->SkuReserved[11]); dev_info(smu->adev->dev, "SkuReserved[12] = 0x%x\n", pptable->SkuReserved[12]); dev_info(smu->adev->dev, "SkuReserved[13] = 0x%x\n", pptable->SkuReserved[13]); - dev_info(smu->adev->dev, "SkuReserved[14] = 0x%x\n", pptable->SkuReserved[14]); dev_info(smu->adev->dev, "GamingClk[0] = 0x%x\n", pptable->GamingClk[0]); dev_info(smu->adev->dev, "GamingClk[1] = 0x%x\n", pptable->GamingClk[1]); @@ -2489,8 +2431,7 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu) dev_info(smu->adev->dev, "DfllGfxclkSpreadPercent = 0x%x\n", pptable->DfllGfxclkSpreadPercent); dev_info(smu->adev->dev, "DfllGfxclkSpreadFreq = 0x%x\n", pptable->DfllGfxclkSpreadFreq); - dev_info(smu->adev->dev, "UclkSpreadEnabled = 0x%x\n", pptable->UclkSpreadEnabled); - dev_info(smu->adev->dev, "UclkSpreadPercent = 0x%x\n", pptable->UclkSpreadPercent); + dev_info(smu->adev->dev, "UclkSpreadPadding = 0x%x\n", pptable->UclkSpreadPadding); dev_info(smu->adev->dev, "UclkSpreadFreq = 0x%x\n", pptable->UclkSpreadFreq); dev_info(smu->adev->dev, "FclkSpreadEnabled = 0x%x\n", pptable->FclkSpreadEnabled); @@ -2535,10 +2476,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu) dev_info(smu->adev->dev, "BoardReserved[8] = 0x%x\n", pptable->BoardReserved[8]); dev_info(smu->adev->dev, "BoardReserved[9] = 0x%x\n", pptable->BoardReserved[9]); dev_info(smu->adev->dev, "BoardReserved[10] = 0x%x\n", pptable->BoardReserved[10]); - dev_info(smu->adev->dev, "BoardReserved[11] = 0x%x\n", pptable->BoardReserved[11]); - dev_info(smu->adev->dev, "BoardReserved[12] = 0x%x\n", pptable->BoardReserved[12]); - dev_info(smu->adev->dev, "BoardReserved[13] = 0x%x\n", pptable->BoardReserved[13]); - dev_info(smu->adev->dev, "BoardReserved[14] = 0x%x\n", pptable->BoardReserved[14]); dev_info(smu->adev->dev, "MmHubPadding[0] = 0x%x\n", pptable->MmHubPadding[0]); dev_info(smu->adev->dev, "MmHubPadding[1] = 0x%x\n", pptable->MmHubPadding[1]); @@ -2563,25 +2500,21 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .set_default_dpm_table = sienna_cichlid_set_default_dpm_table, .dpm_set_vcn_enable = sienna_cichlid_dpm_set_vcn_enable, .dpm_set_jpeg_enable = sienna_cichlid_dpm_set_jpeg_enable, - .get_current_clk_freq_by_table = sienna_cichlid_get_current_clk_freq_by_table, .print_clk_levels = sienna_cichlid_print_clk_levels, .force_clk_levels = sienna_cichlid_force_clk_levels, .populate_umd_state_clk = sienna_cichlid_populate_umd_state_clk, .pre_display_config_changed = sienna_cichlid_pre_display_config_changed, .display_config_changed = sienna_cichlid_display_config_changed, .notify_smc_display_config = sienna_cichlid_notify_smc_display_config, - .force_dpm_limit_value = sienna_cichlid_force_dpm_limit_value, - .unforce_dpm_levels = sienna_cichlid_unforce_dpm_levels, .is_dpm_running = sienna_cichlid_is_dpm_running, .get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent, .get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm, .get_power_profile_mode = sienna_cichlid_get_power_profile_mode, .set_power_profile_mode = sienna_cichlid_set_power_profile_mode, - .get_profiling_clk_mask = sienna_cichlid_get_profiling_clk_mask, .set_watermarks_table = sienna_cichlid_set_watermarks_table, .read_sensor = sienna_cichlid_read_sensor, .get_uclk_dpm_states = sienna_cichlid_get_uclk_dpm_states, - .set_performance_level = sienna_cichlid_set_performance_level, + .set_performance_level = smu_v11_0_set_performance_level, .get_thermal_temperature_range = sienna_cichlid_get_thermal_temperature_range, .display_disable_memory_clock_switch = sienna_cichlid_display_disable_memory_clock_switch, .get_power_limit = sienna_cichlid_get_power_limit, @@ -2608,7 +2541,6 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_enabled_mask = smu_v11_0_get_enabled_mask, .notify_display_change = NULL, .set_power_limit = smu_v11_0_set_power_limit, - .get_current_clk_freq = smu_v11_0_get_current_clk_freq, .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, .enable_thermal_alert = smu_v11_0_enable_thermal_alert, .disable_thermal_alert = smu_v11_0_disable_thermal_alert, @@ -2628,10 +2560,10 @@ 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, - .set_thermal_range = sienna_cichlid_set_thermal_range, + .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/powerplay/smu_internal.h index afd786b6c0b4..afb3ef874fc5 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_internal.h +++ b/drivers/gpu/drm/amd/powerplay/smu_internal.h @@ -59,9 +59,7 @@ #define smu_set_default_dpm_table(smu) smu_ppt_funcs(set_default_dpm_table, 0, smu) #define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu) #define smu_set_default_od8_settings(smu) smu_ppt_funcs(set_default_od8_settings, 0, smu) -#define smu_get_current_clk_freq(smu, clk_id, value) smu_ppt_funcs(get_current_clk_freq, 0, smu, clk_id, value) #define smu_tables_init(smu, tab) smu_ppt_funcs(tables_init, 0, smu, tab) -#define smu_set_thermal_fan_table(smu) smu_ppt_funcs(set_thermal_fan_table, 0, smu) #define smu_enable_thermal_alert(smu) smu_ppt_funcs(enable_thermal_alert, 0, smu) #define smu_disable_thermal_alert(smu) smu_ppt_funcs(disable_thermal_alert, 0, smu) #define smu_smc_read_sensor(smu, sensor, data, size) smu_ppt_funcs(read_sensor, -EINVAL, smu, sensor, data, size) @@ -69,15 +67,13 @@ #define smu_display_config_changed(smu) smu_ppt_funcs(display_config_changed, 0 , smu) #define smu_apply_clocks_adjust_rules(smu) smu_ppt_funcs(apply_clocks_adjust_rules, 0, smu) #define smu_notify_smc_display_config(smu) smu_ppt_funcs(notify_smc_display_config, 0, smu) -#define smu_force_dpm_limit_value(smu, highest) smu_ppt_funcs(force_dpm_limit_value, 0, smu, highest) -#define smu_unforce_dpm_levels(smu) smu_ppt_funcs(unforce_dpm_levels, 0, smu) #define smu_set_cpu_power_state(smu) smu_ppt_funcs(set_cpu_power_state, 0, smu) #define smu_msg_get_index(smu, msg) smu_ppt_funcs(get_smu_msg_index, -EINVAL, smu, msg) #define smu_clk_get_index(smu, clk) smu_ppt_funcs(get_smu_clk_index, -EINVAL, smu, clk) #define smu_feature_get_index(smu, fea) smu_ppt_funcs(get_smu_feature_index, -EINVAL, smu, fea) #define smu_table_get_index(smu, tab) smu_ppt_funcs(get_smu_table_index, -EINVAL, smu, tab) #define smu_power_get_index(smu, src) smu_ppt_funcs(get_smu_power_index, -EINVAL, smu, src) -#define smu_workload_get_type(smu, type) smu_ppt_funcs(get_smu_power_index, -EINVAL, smu, type) +#define smu_workload_get_type(smu, type) smu_ppt_funcs(get_workload_type, -EINVAL, smu, type) #define smu_run_btc(smu) smu_ppt_funcs(run_btc, 0, smu) #define smu_get_allowed_feature_mask(smu, feature_mask, num) smu_ppt_funcs(get_allowed_feature_mask, 0, smu, feature_mask, num) #define smu_store_cc6_data(smu, st, cc6_dis, pst_dis, pst_sw_dis) smu_ppt_funcs(store_cc6_data, 0, smu, st, cc6_dis, pst_dis, pst_sw_dis) @@ -87,18 +83,12 @@ #define smu_dpm_set_vcn_enable(smu, enable) smu_ppt_funcs(dpm_set_vcn_enable, 0, smu, enable) #define smu_dpm_set_jpeg_enable(smu, enable) smu_ppt_funcs(dpm_set_jpeg_enable, 0, smu, enable) #define smu_set_watermarks_table(smu, tab, clock_ranges) smu_ppt_funcs(set_watermarks_table, 0, smu, tab, clock_ranges) -#define smu_get_current_clk_freq_by_table(smu, clk_type, value) smu_ppt_funcs(get_current_clk_freq_by_table, 0, smu, clk_type, value) #define smu_thermal_temperature_range_update(smu, range, rw) smu_ppt_funcs(thermal_temperature_range_update, 0, smu, range, rw) -#define smu_get_thermal_temperature_range(smu, range) smu_ppt_funcs(get_thermal_temperature_range, 0, smu, range) #define smu_register_irq_handler(smu) smu_ppt_funcs(register_irq_handler, 0, smu) #define smu_get_dpm_ultimate_freq(smu, param, min, max) smu_ppt_funcs(get_dpm_ultimate_freq, 0, smu, param, min, max) #define smu_asic_set_performance_level(smu, level) smu_ppt_funcs(set_performance_level, -EINVAL, smu, level) #define smu_dump_pptable(smu) smu_ppt_funcs(dump_pptable, 0, smu) -#define smu_get_dpm_clk_limited(smu, clk_type, dpm_level, freq) smu_ppt_funcs(get_dpm_clk_limited, -EINVAL, smu, clk_type, dpm_level, freq) -#define smu_set_soft_freq_limited_range(smu, clk_type, min, max) smu_ppt_funcs(set_soft_freq_limited_range, -EINVAL, smu, clk_type, min, max) -#define smu_override_pcie_parameters(smu) smu_ppt_funcs(override_pcie_parameters, 0, smu) #define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) smu_ppt_funcs(update_pcie_parameters, 0, smu, pcie_gen_cap, pcie_width_cap) -#define smu_set_thermal_range(smu, range) smu_ppt_funcs(set_thermal_range, 0, smu, range) #define smu_disable_umc_cdr_12gbps_workaround(smu) smu_ppt_funcs(disable_umc_cdr_12gbps_workaround, 0, smu) #define smu_set_power_source(smu, power_src) smu_ppt_funcs(set_power_source, 0, smu, power_src) #define smu_i2c_eeprom_init(smu, control) smu_ppt_funcs(i2c_eeprom_init, 0, smu, control) @@ -106,7 +96,5 @@ #define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu) #define smu_log_thermal_throttling(smu) smu_ppt_funcs(log_thermal_throttling_event, 0, smu) #define smu_get_asic_power_limits(smu) smu_ppt_funcs(get_power_limit, 0, smu) -#define smu_get_profiling_clk_mask(smu, level, sclk_mask, mclk_mask, soc_mask) \ - smu_ppt_funcs(get_profiling_clk_mask, 0, smu, level, sclk_mask, mclk_mask, soc_mask) #endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index f24983a8876d..a7336556dc36 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -35,7 +35,6 @@ #include "smu_v11_0.h" #include "soc15_common.h" #include "atom.h" -#include "amd_pcie.h" #include "amdgpu_ras.h" #include "asic_reg/thm/thm_11_0_2_offset.h" @@ -60,9 +59,12 @@ MODULE_FIRMWARE("amdgpu/navi10_smc.bin"); MODULE_FIRMWARE("amdgpu/navi14_smc.bin"); MODULE_FIRMWARE("amdgpu/navi12_smc.bin"); MODULE_FIRMWARE("amdgpu/sienna_cichlid_smc.bin"); +MODULE_FIRMWARE("amdgpu/navy_flounder_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) { @@ -172,8 +174,12 @@ int smu_v11_0_init_microcode(struct smu_context *smu) case CHIP_SIENNA_CICHLID: chip_name = "sienna_cichlid"; break; + case CHIP_NAVY_FLOUNDER: + chip_name = "navy_flounder"; + break; default: - BUG(); + dev_err(adev->dev, "Unsupported ASIC type %d\n", adev->asic_type); + return -EINVAL; } snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name); @@ -303,6 +309,9 @@ int smu_v11_0_check_fw_version(struct smu_context *smu) case CHIP_SIENNA_CICHLID: smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Sienna_Cichlid; break; + case CHIP_NAVY_FLOUNDER: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder; + break; default: dev_err(smu->adev->dev, "smu unsupported asic type:%d.\n", smu->adev->asic_type); smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV; @@ -384,7 +393,8 @@ int smu_v11_0_setup_pptable(struct smu_context *smu) hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; version_major = le16_to_cpu(hdr->header.header_version_major); version_minor = le16_to_cpu(hdr->header.header_version_minor); - if (version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) { + if ((version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) || + adev->asic_type == CHIP_NAVY_FLOUNDER) { dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id); switch (version_minor) { case 0: @@ -816,6 +826,11 @@ int smu_v11_0_set_tool_table_location(struct smu_context *smu) int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count) { int ret = 0; + struct amdgpu_device *adev = smu->adev; + + /* Navy_Flounder do not support to change display num currently */ + if (adev->asic_type == CHIP_NAVY_FLOUNDER) + return 0; if (!smu->pm_enabled) return ret; @@ -1083,63 +1098,12 @@ int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n) return 0; } -int smu_v11_0_get_current_clk_freq(struct smu_context *smu, - enum smu_clk_type clk_id, - uint32_t *value) -{ - int ret = 0; - uint32_t freq = 0; - - if (clk_id >= SMU_CLK_COUNT || !value) - return -EINVAL; - - ret = smu_get_current_clk_freq_by_table(smu, clk_id, &freq); - if (ret) - return ret; - - freq *= 100; - *value = freq; - - return ret; -} - int smu_v11_0_enable_thermal_alert(struct smu_context *smu) { - int ret = 0; - struct smu_temperature_range range; - struct amdgpu_device *adev = smu->adev; - - memcpy(&range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); - - ret = smu_get_thermal_temperature_range(smu, &range); - if (ret) - return ret; + if (smu->smu_table.thermal_controller_type) + return amdgpu_irq_get(smu->adev, &smu->irq_source, 0); - if (smu->smu_table.thermal_controller_type) { - ret = smu_set_thermal_range(smu, range); - if (ret) - return ret; - - ret = amdgpu_irq_get(adev, &smu->irq_source, 0); - if (ret) - return ret; - - ret = smu_set_thermal_fan_table(smu); - if (ret) - return ret; - } - - adev->pm.dpm.thermal.min_temp = range.min; - adev->pm.dpm.thermal.max_temp = range.max; - adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max; - adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min; - adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max; - adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max; - adev->pm.dpm.thermal.min_mem_temp = range.mem_min; - adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max; - adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max; - - return ret; + return 0; } int smu_v11_0_disable_thermal_alert(struct smu_context *smu) @@ -1152,7 +1116,7 @@ static uint16_t convert_to_vddc(uint8_t vid) return (uint16_t) ((6200 - (vid * 25)) / SMU11_VOLTAGE_SCALE); } -static int smu_v11_0_get_gfx_vdd(struct smu_context *smu, uint32_t *value) +int smu_v11_0_get_gfx_vdd(struct smu_context *smu, uint32_t *value) { struct amdgpu_device *adev = smu->adev; uint32_t vdd = 0, val_vid = 0; @@ -1171,39 +1135,6 @@ static int smu_v11_0_get_gfx_vdd(struct smu_context *smu, uint32_t *value) } -int smu_v11_0_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - int ret = 0; - - if(!data || !size) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = smu_get_current_clk_freq(smu, SMU_UCLK, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_VDDGFX: - ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); - *size = 4; - break; - default: - ret = -EOPNOTSUPP; - break; - } - - if (ret) - *size = 0; - - return ret; -} - int smu_v11_0_display_clock_voltage_request(struct smu_context *smu, struct pp_display_clock_request @@ -1244,7 +1175,7 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu, if (clk_select == SMU_UCLK && smu->disable_uclk_switch) return 0; - ret = smu_set_hard_freq_range(smu, clk_select, clk_freq, 0); + ret = smu_v11_0_set_hard_freq_limited_range(smu, clk_select, clk_freq, 0); if(clk_select == SMU_UCLK) smu->hard_min_uclk_req_from_dal = clk_freq; @@ -1417,6 +1348,8 @@ static int smu_v11_0_set_irq_state(struct amdgpu_device *adev, unsigned tyep, enum amdgpu_interrupt_state state) { + struct smu_context *smu = &adev->smu; + uint32_t low, high; uint32_t val = 0; switch (state) { @@ -1437,9 +1370,19 @@ static int smu_v11_0_set_irq_state(struct amdgpu_device *adev, break; case AMDGPU_IRQ_STATE_ENABLE: /* For THM irqs */ + low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, + smu->thermal_range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES); + high = min(SMU_THERMAL_MAXIMUM_ALERT_TEMP, + smu->thermal_range.software_shutdown_temp); + val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff)); + val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); val = (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); @@ -1746,11 +1689,50 @@ 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) { int ret = 0, clk_id = 0; uint32_t param = 0; + uint32_t clock_limit; + + if (!smu_clk_dpm_is_enabled(smu, clk_type)) { + switch (clk_type) { + case SMU_MCLK: + case SMU_UCLK: + clock_limit = smu->smu_table.boot_values.uclk; + break; + case SMU_GFXCLK: + case SMU_SCLK: + clock_limit = smu->smu_table.boot_values.gfxclk; + break; + case SMU_SOCCLK: + clock_limit = smu->smu_table.boot_values.socclk; + break; + default: + clock_limit = 0; + break; + } + + /* clock in Mhz unit */ + if (min) + *min = clock_limit / 100; + if (max) + *max = clock_limit / 100; + + return 0; + } clk_id = smu_clk_get_index(smu, clk_type); if (clk_id < 0) { @@ -1775,9 +1757,12 @@ failed: return ret; } -int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t min, uint32_t max) +int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t min, + uint32_t max) { + struct amdgpu_device *adev = smu->adev; int ret = 0, clk_id = 0; uint32_t param; @@ -1785,12 +1770,15 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_ if (clk_id < 0) return clk_id; + if (clk_type == SMU_GFXCLK) + amdgpu_gfx_off_ctrl(adev, false); + if (max > 0) { param = (uint32_t)((clk_id << 16) | (max & 0xffff)); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq, param, NULL); if (ret) - return ret; + goto out; } if (min > 0) { @@ -1798,88 +1786,151 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq, param, NULL); if (ret) - return ret; + goto out; } +out: + if (clk_type == SMU_GFXCLK) + amdgpu_gfx_off_ctrl(adev, true); + return ret; } -int smu_v11_0_override_pcie_parameters(struct smu_context *smu) +int smu_v11_0_set_hard_freq_limited_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t min, + uint32_t max) { - struct amdgpu_device *adev = smu->adev; - uint32_t pcie_gen = 0, pcie_width = 0; - int ret; + int ret = 0, clk_id = 0; + uint32_t param; - if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) - pcie_gen = 3; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) - pcie_gen = 2; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) - pcie_gen = 1; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) - pcie_gen = 0; - - /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 - * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 - * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 - */ - if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) - pcie_width = 6; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) - pcie_width = 5; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) - pcie_width = 4; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) - pcie_width = 3; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) - pcie_width = 2; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) - pcie_width = 1; - - ret = smu_update_pcie_parameters(smu, pcie_gen, pcie_width); + if (min <= 0 && max <= 0) + return -EINVAL; - if (ret) - dev_err(adev->dev, "[%s] Attempt to override pcie params failed!\n", __func__); + if (!smu_clk_dpm_is_enabled(smu, clk_type)) + return 0; - return ret; + clk_id = smu_clk_get_index(smu, clk_type); + if (clk_id < 0) + return clk_id; + if (max > 0) { + param = (uint32_t)((clk_id << 16) | (max & 0xffff)); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMaxByFreq, + param, NULL); + if (ret) + return ret; + } + + if (min > 0) { + param = (uint32_t)((clk_id << 16) | (min & 0xffff)); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, + param, NULL); + if (ret) + return ret; + } + + return ret; } int smu_v11_0_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level) { + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + struct amdgpu_device *adev = smu->adev; + uint32_t sclk_min = 0, sclk_max = 0; + uint32_t mclk_min = 0, mclk_max = 0; + uint32_t socclk_min = 0, socclk_max = 0; int ret = 0; - uint32_t sclk_mask, mclk_mask, soc_mask; switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: - ret = smu_force_dpm_limit_value(smu, true); + sclk_min = sclk_max = gfx_table->max; + mclk_min = mclk_max = mem_table->max; + socclk_min = socclk_max = soc_table->max; break; case AMD_DPM_FORCED_LEVEL_LOW: - ret = smu_force_dpm_limit_value(smu, false); + sclk_min = sclk_max = gfx_table->min; + mclk_min = mclk_max = mem_table->min; + socclk_min = socclk_max = soc_table->min; break; case AMD_DPM_FORCED_LEVEL_AUTO: + sclk_min = gfx_table->min; + sclk_max = gfx_table->max; + mclk_min = mem_table->min; + mclk_max = mem_table->max; + socclk_min = soc_table->min; + socclk_max = soc_table->max; + break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - ret = smu_unforce_dpm_levels(smu); + sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard; + mclk_min = mclk_max = pstate_table->uclk_pstate.standard; + socclk_min = socclk_max = pstate_table->socclk_pstate.standard; break; case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + sclk_min = sclk_max = pstate_table->gfxclk_pstate.min; + break; case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + mclk_min = mclk_max = pstate_table->uclk_pstate.min; + break; case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = smu_get_profiling_clk_mask(smu, level, - &sclk_mask, - &mclk_mask, - &soc_mask); - if (ret) - return ret; - smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask, false); - smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask, false); - smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask, false); + sclk_min = sclk_max = pstate_table->gfxclk_pstate.peak; + mclk_min = mclk_max = pstate_table->uclk_pstate.peak; + socclk_min = socclk_max = pstate_table->socclk_pstate.peak; break; case AMD_DPM_FORCED_LEVEL_MANUAL: case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + return 0; default: - break; + dev_err(adev->dev, "Invalid performance level %d\n", level); + return -EINVAL; + } + + /* + * Separate MCLK and SOCCLK soft min/max settings are not allowed + * on Arcturus. + */ + if (adev->asic_type == CHIP_ARCTURUS) { + mclk_min = mclk_max = 0; + socclk_min = socclk_max = 0; + } + + if (sclk_min && sclk_max) { + ret = smu_v11_0_set_soft_freq_limited_range(smu, + SMU_GFXCLK, + sclk_min, + sclk_max); + if (ret) + return ret; + } + + if (mclk_min && mclk_max) { + ret = smu_v11_0_set_soft_freq_limited_range(smu, + SMU_MCLK, + mclk_min, + mclk_max); + if (ret) + return ret; } + + if (socclk_min && socclk_max) { + ret = smu_v11_0_set_soft_freq_limited_range(smu, + SMU_SOCCLK, + socclk_min, + socclk_max); + if (ret) + return ret; + } + return ret; } @@ -1898,3 +1949,125 @@ int smu_v11_0_set_power_source(struct smu_context *smu, NULL); } +int smu_v11_0_get_dpm_freq_by_index(struct smu_context *smu, + enum smu_clk_type clk_type, + uint16_t level, + uint32_t *value) +{ + int ret = 0, clk_id = 0; + uint32_t param; + + if (!value) + return -EINVAL; + + if (!smu_clk_dpm_is_enabled(smu, clk_type)) + return 0; + + clk_id = smu_clk_get_index(smu, clk_type); + if (clk_id < 0) + return clk_id; + + param = (uint32_t)(((clk_id & 0xffff) << 16) | (level & 0xffff)); + + ret = smu_send_smc_msg_with_param(smu, + SMU_MSG_GetDpmFreqByIndex, + param, + value); + if (ret) + return ret; + + /* + * BIT31: 0 - Fine grained DPM, 1 - Dicrete DPM + * now, we un-support it + */ + *value = *value & 0x7fffffff; + + return ret; +} + +int smu_v11_0_get_dpm_level_count(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + return smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + 0xff, + value); +} + +int smu_v11_0_set_single_dpm_table(struct smu_context *smu, + enum smu_clk_type clk_type, + struct smu_11_0_dpm_table *single_dpm_table) +{ + int ret = 0; + uint32_t clk; + int i; + + ret = smu_v11_0_get_dpm_level_count(smu, + clk_type, + &single_dpm_table->count); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get dpm levels!\n", __func__); + return ret; + } + + for (i = 0; i < single_dpm_table->count; i++) { + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + i, + &clk); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get dpm freq by index!\n", __func__); + return ret; + } + + single_dpm_table->dpm_levels[i].value = clk; + single_dpm_table->dpm_levels[i].enabled = true; + + if (i == 0) + single_dpm_table->min = clk; + else if (i == single_dpm_table->count - 1) + single_dpm_table->max = clk; + } + + return 0; +} + +int smu_v11_0_get_dpm_level_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min_value, + uint32_t *max_value) +{ + uint32_t level_count = 0; + int ret = 0; + + if (!min_value && !max_value) + return -EINVAL; + + if (min_value) { + /* by default, level 0 clock value as min value */ + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + 0, + min_value); + if (ret) + return ret; + } + + if (max_value) { + ret = smu_v11_0_get_dpm_level_count(smu, + clk_type, + &level_count); + if (ret) + return ret; + + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + level_count - 1, + max_value); + if (ret) + return ret; + } + + return ret; +} diff --git a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c index b03127273d56..4e1b11d07438 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c @@ -203,35 +203,6 @@ int smu_v12_0_set_gfx_cgpg(struct smu_context *smu, bool enable) NULL); } -int smu_v12_0_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - int ret = 0; - - if(!data || !size) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = smu_get_current_clk_freq(smu, SMU_UCLK, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, (uint32_t *)data); - *size = 4; - break; - default: - ret = -EOPNOTSUPP; - break; - } - - if (ret) - *size = 0; - - return ret; -} - /** * smu_v12_0_get_gfxoff_status - get gfxoff status * @@ -345,98 +316,6 @@ int smu_v12_0_get_enabled_mask(struct smu_context *smu, return ret; } -int smu_v12_0_get_current_clk_freq(struct smu_context *smu, - enum smu_clk_type clk_id, - uint32_t *value) -{ - int ret = 0; - uint32_t freq = 0; - - if (clk_id >= SMU_CLK_COUNT || !value) - return -EINVAL; - - ret = smu_get_current_clk_freq_by_table(smu, clk_id, &freq); - if (ret) - return ret; - - freq *= 100; - *value = freq; - - return ret; -} - -int smu_v12_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *min, uint32_t *max) -{ - int ret = 0; - uint32_t mclk_mask, soc_mask; - - if (max) { - ret = smu_get_profiling_clk_mask(smu, AMD_DPM_FORCED_LEVEL_PROFILE_PEAK, - NULL, - &mclk_mask, - &soc_mask); - if (ret) - goto failed; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - ret = smu_send_smc_msg(smu, SMU_MSG_GetMaxGfxclkFrequency, max); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get max GX frequency from SMC Failed !\n"); - goto failed; - } - break; - case SMU_UCLK: - case SMU_FCLK: - case SMU_MCLK: - ret = smu_get_dpm_clk_limited(smu, clk_type, mclk_mask, max); - if (ret) - goto failed; - break; - case SMU_SOCCLK: - ret = smu_get_dpm_clk_limited(smu, clk_type, soc_mask, max); - if (ret) - goto failed; - break; - default: - ret = -EINVAL; - goto failed; - } - } - - if (min) { - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - ret = smu_send_smc_msg(smu, SMU_MSG_GetMinGfxclkFrequency, min); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get min GX frequency from SMC Failed !\n"); - goto failed; - } - break; - case SMU_UCLK: - case SMU_FCLK: - case SMU_MCLK: - ret = smu_get_dpm_clk_limited(smu, clk_type, 0, min); - if (ret) - goto failed; - break; - case SMU_SOCCLK: - ret = smu_get_dpm_clk_limited(smu, clk_type, 0, min); - if (ret) - goto failed; - break; - default: - ret = -EINVAL; - goto failed; - } - } -failed: - return ret; -} - int smu_v12_0_mode2_reset(struct smu_context *smu){ return smu_v12_0_send_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, SMU_RESET_MODE_2, NULL); } |