diff options
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay')
21 files changed, 633 insertions, 318 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index c195575366a3..8e2acb4df860 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -319,12 +319,12 @@ static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, if (*level & profile_mode_mask) { hwmgr->saved_dpm_level = hwmgr->dpm_level; hwmgr->en_umd_pstate = true; - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); amdgpu_device_ip_set_powergating_state(hwmgr->adev, AMD_IP_BLOCK_TYPE_GFX, AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); } } else { /* exit umd pstate, restore level, enable gfx cg*/ @@ -1435,7 +1435,8 @@ static int pp_get_asic_baco_capability(void *handle, bool *cap) if (!hwmgr) return -EINVAL; - if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_capability) + if (!(hwmgr->not_vf && amdgpu_dpm) || + !hwmgr->hwmgr_func->get_asic_baco_capability) return 0; mutex_lock(&hwmgr->smu_lock); @@ -1469,7 +1470,8 @@ static int pp_set_asic_baco_state(void *handle, int state) if (!hwmgr) return -EINVAL; - if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_asic_baco_state) + if (!(hwmgr->not_vf && amdgpu_dpm) || + !hwmgr->hwmgr_func->set_asic_baco_state) return 0; mutex_lock(&hwmgr->smu_lock); diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 96e81c7bc266..e77046931e4c 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -23,15 +23,12 @@ #include <linux/firmware.h> #include <linux/pci.h> -#include "pp_debug.h" #include "amdgpu.h" #include "amdgpu_smu.h" #include "smu_internal.h" -#include "soc15_common.h" #include "smu_v11_0.h" #include "smu_v12_0.h" #include "atom.h" -#include "amd_pcie.h" #include "vega20_ppt.h" #include "arcturus_ppt.h" #include "navi10_ppt.h" @@ -121,20 +118,20 @@ static int smu_feature_update_enable_state(struct smu_context *smu, if (enabled) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesLow, - feature_low); + feature_low, NULL); if (ret) return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnableSmuFeaturesHigh, - feature_high); + feature_high, NULL); if (ret) return ret; } else { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow, - feature_low); + feature_low, NULL); if (ret) return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesHigh, - feature_high); + feature_high, NULL); if (ret) return ret; } @@ -195,21 +192,13 @@ int smu_get_smc_version(struct smu_context *smu, uint32_t *if_version, uint32_t return -EINVAL; if (if_version) { - ret = smu_send_smc_msg(smu, SMU_MSG_GetDriverIfVersion); - if (ret) - return ret; - - ret = smu_read_smc_arg(smu, if_version); + ret = smu_send_smc_msg(smu, SMU_MSG_GetDriverIfVersion, if_version); if (ret) return ret; } if (smu_version) { - ret = smu_send_smc_msg(smu, SMU_MSG_GetSmuVersion); - if (ret) - return ret; - - ret = smu_read_smc_arg(smu, smu_version); + ret = smu_send_smc_msg(smu, SMU_MSG_GetSmuVersion, smu_version); if (ret) return ret; } @@ -218,17 +207,19 @@ int smu_get_smc_version(struct smu_context *smu, uint32_t *if_version, uint32_t } int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t min, uint32_t max) + uint32_t min, uint32_t max, bool lock_needed) { int ret = 0; - if (min < 0 && max < 0) - return -EINVAL; - 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; } @@ -251,7 +242,7 @@ int smu_set_hard_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, if (max > 0) { param = (uint32_t)((clk_id << 16) | (max & 0xffff)); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMaxByFreq, - param); + param, NULL); if (ret) return ret; } @@ -259,7 +250,7 @@ int smu_set_hard_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, if (min > 0) { param = (uint32_t)((clk_id << 16) | (min & 0xffff)); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, - param); + param, NULL); if (ret) return ret; } @@ -335,12 +326,8 @@ int smu_get_dpm_freq_by_index(struct smu_context *smu, enum smu_clk_type clk_typ param = (uint32_t)(((clk_id & 0xffff) << 16) | (level & 0xffff)); - ret = smu_send_smc_msg_with_param(smu,SMU_MSG_GetDpmFreqByIndex, - param); - if (ret) - return ret; - - ret = smu_read_smc_arg(smu, ¶m); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmFreqByIndex, + param, ¶m); if (ret) return ret; @@ -542,7 +529,8 @@ int smu_update_table(struct smu_context *smu, enum smu_table_id table_index, int ret = smu_send_smc_msg_with_param(smu, drv2smu ? SMU_MSG_TransferTableDram2Smu : SMU_MSG_TransferTableSmu2Dram, - table_id | ((argument & 0xFFFF) << 16)); + table_id | ((argument & 0xFFFF) << 16), + NULL); if (ret) return ret; @@ -900,6 +888,7 @@ static int smu_sw_init(void *handle) mutex_init(&smu->sensor_lock); mutex_init(&smu->metrics_lock); + mutex_init(&smu->message_lock); smu->watermarks_bitmap = 0; smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; @@ -943,6 +932,13 @@ static int smu_sw_init(void *handle) return ret; } + if (adev->smu.ppt_funcs->i2c_eeprom_init) { + ret = smu_i2c_eeprom_init(smu, &adev->pm.smu_i2c); + + if (ret) + return ret; + } + return 0; } @@ -952,6 +948,9 @@ static int smu_sw_fini(void *handle) struct smu_context *smu = &adev->smu; int ret; + if (adev->smu.ppt_funcs->i2c_eeprom_fini) + smu_i2c_eeprom_fini(smu, &adev->pm.smu_i2c); + kfree(smu->irq_source); smu->irq_source = NULL; @@ -1113,12 +1112,12 @@ static int smu_smc_table_hw_init(struct smu_context *smu, return ret; } + ret = smu_set_driver_table_location(smu); + if (ret) + return ret; + /* smu_dump_pptable(smu); */ if (!amdgpu_sriov_vf(adev)) { - ret = smu_set_driver_table_location(smu); - if (ret) - return ret; - /* * Copy pptable bo in the vram to smc with SMU MSGs such as * SetDriverDramAddr and TransferTableDram2Smu. @@ -1155,6 +1154,21 @@ static int smu_smc_table_hw_init(struct smu_context *smu, } } } + + if (smu->ppt_funcs->set_power_source) { + /* + * For Navi1X, manually switch it to AC mode as PMFW + * may boot it with DC mode. + */ + if (adev->pm.ac_power) + ret = smu_set_power_source(smu, SMU_POWER_SOURCE_AC); + else + ret = smu_set_power_source(smu, SMU_POWER_SOURCE_DC); + if (ret) { + pr_err("Failed to switch to %s mode!\n", adev->pm.ac_power ? "AC" : "DC"); + return ret; + } + } } if (adev->asic_type != CHIP_ARCTURUS) { ret = smu_notify_display_change(smu); @@ -1454,29 +1468,84 @@ int smu_reset(struct smu_context *smu) return ret; } +static int smu_disable_dpm(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t smu_version; + int ret = 0; + bool use_baco = !smu->is_apu && + ((adev->in_gpu_reset && + (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || + ((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev))); + + ret = smu_get_smc_version(smu, NULL, &smu_version); + if (ret) { + pr_err("Failed to get smu version.\n"); + return ret; + } + + /* + * Disable all enabled SMU features. + * This should be handled in SMU FW, as a backup + * driver can issue call to SMU FW until sequence + * in SMU FW is operational. + */ + ret = smu_system_features_control(smu, false); + if (ret) { + pr_err("Failed to disable smu features.\n"); + return ret; + } + + /* + * Arcturus does not have BACO bit in disable feature mask. + * Enablement of BACO bit on Arcturus should be skipped. + */ + if (adev->asic_type == CHIP_ARCTURUS) { + if (use_baco && (smu_version > 0x360e00)) + return 0; + } + + /* For baco, need to leave BACO feature enabled */ + if (use_baco) { + /* + * Correct the way for checking whether SMU_FEATURE_BACO_BIT + * is supported. + * + * Since 'smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)' will + * always return false as the 'smu_system_features_control(smu, false)' + * was just issued above which disabled all SMU features. + * + * Thus 'smu_feature_get_index(smu, SMU_FEATURE_BACO_BIT)' is used + * now for the checking. + */ + if (smu_feature_get_index(smu, SMU_FEATURE_BACO_BIT) >= 0) { + ret = smu_feature_set_enabled(smu, SMU_FEATURE_BACO_BIT, true); + if (ret) { + pr_warn("set BACO feature enabled failed, return %d\n", ret); + return ret; + } + } + } + + return ret; +} + static int smu_suspend(void *handle) { - int ret; struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct smu_context *smu = &adev->smu; - bool baco_feature_is_enabled = false; + int ret; - if (!smu->pm_enabled) + if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) return 0; - if(!smu->is_apu) - baco_feature_is_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT); - - ret = smu_system_features_control(smu, false); - if (ret) - return ret; + if (!smu->pm_enabled) + return 0; - if (baco_feature_is_enabled) { - ret = smu_feature_set_enabled(smu, SMU_FEATURE_BACO_BIT, true); - if (ret) { - pr_warn("set BACO feature enabled failed, return %d\n", ret); + if(!amdgpu_sriov_vf(adev)) { + ret = smu_disable_dpm(smu); + if (ret) return ret; - } } smu->watermarks_bitmap &= ~(WATERMARKS_LOADED); @@ -1675,12 +1744,12 @@ static int smu_enable_umd_pstate(void *handle, if (*level & profile_mode_mask) { smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level; smu_dpm_ctx->enable_umd_pstate = true; - amdgpu_device_ip_set_clockgating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); amdgpu_device_ip_set_powergating_state(smu->adev, AMD_IP_BLOCK_TYPE_GFX, AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_clockgating_state(smu->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); } } else { /* exit umd pstate, restore level, enable gfx cg*/ @@ -1942,7 +2011,7 @@ int smu_set_mp1_state(struct smu_context *smu, return 0; } - ret = smu_send_smc_msg(smu, msg); + ret = smu_send_smc_msg(smu, msg, NULL); if (ret) pr_err("[PrepareMp1] Failed!\n"); @@ -2018,6 +2087,29 @@ int smu_set_watermarks_for_clock_ranges(struct smu_context *smu, return 0; } +int smu_set_ac_dc(struct smu_context *smu) +{ + int ret = 0; + + /* controlled by firmware */ + if (smu->dc_controlled_by_gpio) + return 0; + + mutex_lock(&smu->mutex); + if (smu->ppt_funcs->set_power_source) { + if (smu->adev->pm.ac_power) + ret = smu_set_power_source(smu, SMU_POWER_SOURCE_AC); + else + ret = smu_set_power_source(smu, SMU_POWER_SOURCE_DC); + if (ret) + pr_err("Failed to switch to %s mode!\n", + smu->adev->pm.ac_power ? "AC" : "DC"); + } + mutex_unlock(&smu->mutex); + + return ret; +} + const struct amd_ip_funcs smu_ip_funcs = { .name = "smu", .early_init = smu_early_init, @@ -2620,12 +2712,3 @@ uint32_t smu_get_pptable_power_limit(struct smu_context *smu) return ret; } - -int smu_send_smc_msg(struct smu_context *smu, - enum smu_message_type msg) -{ - int ret; - - ret = smu_send_smc_msg_with_param(smu, msg, 0); - return ret; -} diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 14ba6aa876e2..1ef0923f7190 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -21,7 +21,6 @@ * */ -#include "pp_debug.h" #include <linux/firmware.h> #include "amdgpu.h" #include "amdgpu_smu.h" @@ -36,13 +35,14 @@ #include "arcturus_ppt.h" #include "smu_v11_0_pptable.h" #include "arcturus_ppsmc.h" +#include "nbio/nbio_7_4_offset.h" #include "nbio/nbio_7_4_sh_mask.h" #include "amdgpu_xgmi.h" #include <linux/i2c.h> #include <linux/pci.h> #include "amdgpu_ras.h" -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control.eeprom_accessor))->adev +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) #define CTF_OFFSET_EDGE 5 #define CTF_OFFSET_HOTSPOT 5 @@ -127,6 +127,7 @@ static struct smu_11_0_cmn2aisc_mapping arcturus_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(WaflTest, PPSMC_MSG_WaflTest), MSG_MAP(SetXgmiMode, PPSMC_MSG_SetXgmiMode), MSG_MAP(SetMemoryChannelEnable, PPSMC_MSG_SetMemoryChannelEnable), + MSG_MAP(DFCstateControl, PPSMC_MSG_DFCstateControl), }; static struct smu_11_0_cmn2aisc_mapping arcturus_clk_map[SMU_CLK_COUNT] = { @@ -373,13 +374,13 @@ arcturus_set_single_dpm_table(struct smu_context *smu, ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmFreqByIndex, - (clk_id << 16 | 0xFF)); + (clk_id << 16 | 0xFF), + &num_of_levels); if (ret) { pr_err("[%s] failed to get dpm levels!\n", __func__); return ret; } - smu_read_smc_arg(smu, &num_of_levels); if (!num_of_levels) { pr_err("[%s] number of clk levels is invalid!\n", __func__); return -EINVAL; @@ -389,12 +390,12 @@ arcturus_set_single_dpm_table(struct smu_context *smu, for (i = 0; i < num_of_levels; i++) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmFreqByIndex, - (clk_id << 16 | i)); + (clk_id << 16 | i), + &clk); if (ret) { pr_err("[%s] failed to get dpm freq by index!\n", __func__); return ret; } - smu_read_smc_arg(smu, &clk); if (!clk) { pr_err("[%s] clk value is invalid!\n", __func__); return -EINVAL; @@ -552,13 +553,13 @@ static int arcturus_run_btc(struct smu_context *smu) { int ret = 0; - ret = smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc); + ret = smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc, NULL); if (ret) { pr_err("RunAfllBtc failed!\n"); return ret; } - return smu_send_smc_msg(smu, SMU_MSG_RunDcBtc); + return smu_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL); } static int arcturus_populate_umd_state_clk(struct smu_context *smu) @@ -743,7 +744,8 @@ static int arcturus_upload_dpm_level(struct smu_context *smu, bool max, single_dpm_table->dpm_state.soft_min_level; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_GFXCLK << 16) | (freq & 0xffff)); + (PPCLK_GFXCLK << 16) | (freq & 0xffff), + NULL); if (ret) { pr_err("Failed to set soft %s gfxclk !\n", max ? "max" : "min"); @@ -758,7 +760,8 @@ static int arcturus_upload_dpm_level(struct smu_context *smu, bool max, single_dpm_table->dpm_state.soft_min_level; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_UCLK << 16) | (freq & 0xffff)); + (PPCLK_UCLK << 16) | (freq & 0xffff), + NULL); if (ret) { pr_err("Failed to set soft %s memclk !\n", max ? "max" : "min"); @@ -773,7 +776,8 @@ static int arcturus_upload_dpm_level(struct smu_context *smu, bool max, single_dpm_table->dpm_state.soft_min_level; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_SOCCLK << 16) | (freq & 0xffff)); + (PPCLK_SOCCLK << 16) | (freq & 0xffff), + NULL); if (ret) { pr_err("Failed to set soft %s socclk !\n", max ? "max" : "min"); @@ -790,8 +794,21 @@ static int arcturus_force_clk_levels(struct smu_context *smu, struct arcturus_dpm_table *dpm_table; struct arcturus_single_dpm_table *single_dpm_table; uint32_t soft_min_level, soft_max_level; + uint32_t smu_version; int ret = 0; + ret = smu_get_smc_version(smu, NULL, &smu_version); + if (ret) { + pr_err("Failed to get smu version!\n"); + return ret; + } + + if (smu_version >= 0x361200) { + pr_err("Forcing clock level is not supported with " + "54.18 and onwards SMU firmwares\n"); + return -EOPNOTSUPP; + } + soft_min_level = mask ? (ffs(mask) - 1) : 0; soft_max_level = mask ? (fls(mask) - 1) : 0; @@ -1288,12 +1305,11 @@ static int arcturus_get_power_limit(struct smu_context *smu, return -EINVAL; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit, - power_src << 16); + power_src << 16, &asic_default_power_limit); if (ret) { pr_err("[%s] get PPT limit failed!", __func__); return ret; } - smu_read_smc_arg(smu, &asic_default_power_limit); } else { /* the last hope to figure out the ppt limit */ if (!pptable) { @@ -1497,7 +1513,8 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu, ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, - 1 << workload_type); + 1 << workload_type, + NULL); if (ret) { pr_err("Fail to set workload type %d\n", workload_type); return ret; @@ -1508,6 +1525,38 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu, return 0; } +static int arcturus_set_performance_level(struct smu_context *smu, + enum amd_dpm_forced_level level) +{ + uint32_t smu_version; + int ret; + + ret = smu_get_smc_version(smu, NULL, &smu_version); + if (ret) { + pr_err("Failed to get smu version!\n"); + return ret; + } + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + case AMD_DPM_FORCED_LEVEL_LOW: + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + if (smu_version >= 0x361200) { + pr_err("Forcing clock level is not supported with " + "54.18 and onwards SMU firmwares\n"); + return -EOPNOTSUPP; + } + break; + default: + break; + } + + return smu_v11_0_set_performance_level(smu, level); +} + static void arcturus_dump_pptable(struct smu_context *smu) { struct smu_table_context *table_context = &smu->smu_table; @@ -2187,7 +2236,7 @@ static int arcturus_i2c_eeprom_control_init(struct i2c_adapter *control) control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; control->algo = &arcturus_i2c_eeprom_i2c_algo; - snprintf(control->name, sizeof(control->name), "RAS EEPROM"); + snprintf(control->name, sizeof(control->name), "AMDGPU EEPROM"); res = i2c_add_adapter(control); if (res) @@ -2207,6 +2256,18 @@ static void arcturus_i2c_eeprom_control_fini(struct i2c_adapter *control) i2c_del_adapter(control); } +static bool arcturus_is_baco_supported(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t val; + + if (!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 uint32_t arcturus_get_pptable_power_limit(struct smu_context *smu) { PPTable_t *pptable = smu->smu_table.driver_pptable; @@ -2214,6 +2275,27 @@ static uint32_t arcturus_get_pptable_power_limit(struct smu_context *smu) return pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; } +static int arcturus_set_df_cstate(struct smu_context *smu, + enum pp_df_cstate state) +{ + uint32_t smu_version; + int ret; + + ret = smu_get_smc_version(smu, NULL, &smu_version); + if (ret) { + pr_err("Failed to get smu version!\n"); + return ret; + } + + /* PPSMC_MSG_DFCstateControl is supported by 54.15.0 and onwards */ + if (smu_version < 0x360F00) { + pr_err("DFCstateControl is only supported by PMFW 54.15.0 and onwards\n"); + return -EINVAL; + } + + return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state, NULL); +} + static const struct pptable_funcs arcturus_ppt_funcs = { /* translate smu index into arcturus specific index */ .get_smu_msg_index = arcturus_get_smu_msg_index, @@ -2248,7 +2330,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .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 = smu_v11_0_set_performance_level, + .set_performance_level = arcturus_set_performance_level, /* debug (internal used) */ .dump_pptable = arcturus_dump_pptable, .get_power_limit = arcturus_get_power_limit, @@ -2277,7 +2359,6 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, .system_features_control = smu_v11_0_system_features_control, .send_smc_msg_with_param = smu_v11_0_send_msg_with_param, - .read_smc_arg = smu_v11_0_read_arg, .init_display_count = smu_v11_0_init_display_count, .set_allowed_mask = smu_v11_0_set_allowed_mask, .get_enabled_mask = smu_v11_0_get_enabled_mask, @@ -2298,7 +2379,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .register_irq_handler = smu_v11_0_register_irq_handler, .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support= smu_v11_0_baco_is_support, + .baco_is_support= arcturus_is_baco_supported, .baco_get_state = smu_v11_0_baco_get_state, .baco_set_state = smu_v11_0_baco_set_state, .baco_enter = smu_v11_0_baco_enter, @@ -2307,6 +2388,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, .override_pcie_parameters = smu_v11_0_override_pcie_parameters, .get_pptable_power_limit = arcturus_get_pptable_power_limit, + .set_df_cstate = arcturus_set_df_cstate, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c index 77c14671866c..719597c5d27d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c @@ -984,6 +984,32 @@ static int init_thermal_controller( struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) { + hwmgr->thermal_controller.ucType = + powerplay_table->sThermalController.ucType; + hwmgr->thermal_controller.ucI2cLine = + powerplay_table->sThermalController.ucI2cLine; + hwmgr->thermal_controller.ucI2cAddress = + powerplay_table->sThermalController.ucI2cAddress; + + hwmgr->thermal_controller.fanInfo.bNoFan = + (0 != (powerplay_table->sThermalController.ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN)); + + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = + powerplay_table->sThermalController.ucFanParameters & + ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + + hwmgr->thermal_controller.fanInfo.ulMinRPM + = powerplay_table->sThermalController.ucFanMinRPM * 100UL; + hwmgr->thermal_controller.fanInfo.ulMaxRPM + = powerplay_table->sThermalController.ucFanMaxRPM * 100UL; + + set_hw_cap(hwmgr, + ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, + PHM_PlatformCaps_ThermalController); + + hwmgr->thermal_controller.use_hw_fan_control = 1; + return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index bf04cfefb283..4795eb66b2b2 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -1250,7 +1250,7 @@ static void smu7_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources) switch (sources) { default: pr_err("Unknown throttling event sources."); - /* fall through */ + fallthrough; case 0: protection = false; /* src is unused */ @@ -3698,12 +3698,12 @@ static int smu7_request_link_speed_change_before_state_change( data->force_pcie_gen = PP_PCIEGen2; if (current_link_speed == PP_PCIEGen2) break; - /* fall through */ + fallthrough; case PP_PCIEGen2: if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN2, false)) break; + fallthrough; #endif - /* fall through */ default: data->force_pcie_gen = smu7_get_current_pcie_speed(hwmgr); break; @@ -3804,9 +3804,12 @@ static int smu7_trim_single_dpm_states(struct pp_hwmgr *hwmgr, { uint32_t i; + /* force the trim if mclk_switching is disabled to prevent flicker */ + bool force_trim = (low_limit == high_limit); for (i = 0; i < dpm_table->count; i++) { /*skip the trim if od is enabled*/ - if (!hwmgr->od_enabled && (dpm_table->dpm_levels[i].value < low_limit + if ((!hwmgr->od_enabled || force_trim) + && (dpm_table->dpm_levels[i].value < low_limit || dpm_table->dpm_levels[i].value > high_limit)) dpm_table->dpm_levels[i].enabled = false; else diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 92a65e3daff4..f29f95be1e56 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -3382,7 +3382,7 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels( } if (data->need_update_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK + DPMTABLE_UPDATE_SOCCLK)) { + (DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK | DPMTABLE_UPDATE_SOCCLK)) { result = vega10_populate_all_graphic_levels(hwmgr); PP_ASSERT_WITH_CODE((0 == result), "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", @@ -3390,7 +3390,7 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels( } if (data->need_update_dpm_table & - (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) { + (DPMTABLE_OD_UPDATE_MCLK | DPMTABLE_UPDATE_MCLK)) { result = vega10_populate_all_memory_levels(hwmgr); PP_ASSERT_WITH_CODE((0 == result), "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 3b3ec5666051..08b6ba39a6d7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -487,15 +487,16 @@ static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); int ret = 0; + bool use_baco = (adev->in_gpu_reset && + (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || + (adev->in_runpm && amdgpu_asic_supports_baco(adev)); ret = vega20_init_sclk_threshold(hwmgr); PP_ASSERT_WITH_CODE(!ret, "Failed to init sclk threshold!", return ret); - if (adev->in_gpu_reset && - (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) { - + if (use_baco) { ret = vega20_baco_apply_vdci_flush_workaround(hwmgr); if (ret) pr_err("Failed to apply vega20 baco workaround!\n"); diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 97b6714e83e6..ae2c318dd6fa 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -362,6 +362,7 @@ struct smu_context struct mutex mutex; struct mutex sensor_lock; struct mutex metrics_lock; + struct mutex message_lock; uint64_t pool_size; struct smu_table_context smu_table; @@ -371,6 +372,9 @@ struct smu_context struct amd_pp_display_configuration *display_config; struct smu_baco_context smu_baco; void *od_settings; +#if defined(CONFIG_DEBUG_FS) + struct dentry *debugfs_sclk; +#endif uint32_t pstate_sclk; uint32_t pstate_mclk; @@ -404,6 +408,7 @@ struct smu_context uint32_t smc_if_version; bool uploading_custom_pp_table; + bool dc_controlled_by_gpio; }; struct i2c_adapter; @@ -514,8 +519,7 @@ struct pptable_funcs { int (*set_last_dcef_min_deep_sleep_clk)(struct smu_context *smu); int (*system_features_control)(struct smu_context *smu, bool en); int (*send_smc_msg_with_param)(struct smu_context *smu, - enum smu_message_type msg, uint32_t param); - int (*read_smc_arg)(struct smu_context *smu, uint32_t *arg); + enum smu_message_type msg, uint32_t param, uint32_t *read_arg); int (*init_display_count)(struct smu_context *smu, uint32_t count); int (*set_allowed_mask)(struct smu_context *smu); int (*get_enabled_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); @@ -567,6 +571,7 @@ struct pptable_funcs { int (*override_pcie_parameters)(struct smu_context *smu); uint32_t (*get_pptable_power_limit)(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); }; int smu_load_microcode(struct smu_context *smu); @@ -707,7 +712,7 @@ int smu_get_dpm_level_count(struct smu_context *smu, enum smu_clk_type clk_type, 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_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t min, uint32_t max); + 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, @@ -715,6 +720,7 @@ int smu_get_dpm_level_range(struct smu_context *smu, enum smu_clk_type clk_type, 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); +int smu_set_ac_dc(struct smu_context *smu); bool smu_clk_dpm_is_enabled(struct smu_context *smu, enum smu_clk_type clk_type); const char *smu_get_message_name(struct smu_context *smu, enum smu_message_type type); const char *smu_get_feature_name(struct smu_context *smu, enum smu_feature_mask feature); diff --git a/drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h index e3291259b249..f736d773f9d6 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h @@ -110,7 +110,11 @@ //Others #define PPSMC_MSG_SetMemoryChannelEnable 0x39 -#define PPSMC_Message_Count 0x3A +//OOB +#define PPSMC_MSG_SetNumBadHbmPagesRetired 0x3A + +#define PPSMC_MSG_DFCstateControl 0x3B +#define PPSMC_Message_Count 0x3C typedef uint32_t PPSMC_Result; typedef uint32_t PPSMC_Msg; diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h index 822cd8b5bf90..cea65093b6ad 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h @@ -37,7 +37,7 @@ #define PP_ASSERT_WITH_CODE(cond, msg, code) \ do { \ if (!(cond)) { \ - pr_warn("%s\n", msg); \ + pr_warn_ratelimited("%s\n", msg); \ code; \ } \ } while (0) @@ -45,7 +45,7 @@ #define PP_ASSERT(cond, msg) \ do { \ if (!(cond)) { \ - pr_warn("%s\n", msg); \ + pr_warn_ratelimited("%s\n", msg); \ } \ } while (0) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h index ac0120e384be..4b2da98afcd2 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h @@ -701,7 +701,8 @@ typedef struct { // APCC Settings uint16_t PccThresholdLow; uint16_t PccThresholdHigh; - uint32_t PaddingAPCC[6]; //FIXME pending SPEC + uint32_t MGpuFanBoostLimitRpm; + uint32_t PaddingAPCC[5]; // Temperature Dependent Vmin uint16_t VDDGFX_TVmin; //Celcius 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 d5314d12628a..674e426ed59b 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -28,8 +28,9 @@ #define SMU11_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU11_DRIVER_IF_VERSION_VG20 0x13 #define SMU11_DRIVER_IF_VERSION_ARCT 0x12 -#define SMU11_DRIVER_IF_VERSION_NV10 0x33 -#define SMU11_DRIVER_IF_VERSION_NV14 0x34 +#define SMU11_DRIVER_IF_VERSION_NV10 0x35 +#define SMU11_DRIVER_IF_VERSION_NV12 0x33 +#define SMU11_DRIVER_IF_VERSION_NV14 0x36 /* MP Apertures */ #define MP0_Public 0x03800000 @@ -182,9 +183,8 @@ int smu_v11_0_system_features_control(struct smu_context *smu, int smu_v11_0_send_msg_with_param(struct smu_context *smu, enum smu_message_type msg, - uint32_t param); - -int smu_v11_0_read_arg(struct smu_context *smu, uint32_t *arg); + uint32_t param, + uint32_t *read_arg); int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count); @@ -267,4 +267,7 @@ uint32_t smu_v11_0_get_max_power_limit(struct smu_context *smu); int smu_v11_0_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level); +int smu_v11_0_set_power_source(struct smu_context *smu, + enum smu_power_src_type power_src); + #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 d79e54b5ebf6..7fbebc1979cf 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h @@ -40,14 +40,13 @@ struct smu_12_0_cmn2aisc_mapping { int smu_v12_0_send_msg_without_waiting(struct smu_context *smu, uint16_t msg); -int smu_v12_0_read_arg(struct smu_context *smu, uint32_t *arg); - int smu_v12_0_wait_for_response(struct smu_context *smu); int smu_v12_0_send_msg_with_param(struct smu_context *smu, enum smu_message_type msg, - uint32_t param); + uint32_t param, + uint32_t *read_arg); int smu_v12_0_check_fw_status(struct smu_context *smu); diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index aed4d6e60907..15030284b444 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -21,7 +21,6 @@ * */ -#include "pp_debug.h" #include <linux/firmware.h> #include <linux/pci.h> #include "amdgpu.h" @@ -29,14 +28,15 @@ #include "smu_internal.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" +#include "soc15_common.h" #include "smu_v11_0.h" #include "smu11_driver_if_navi10.h" -#include "soc15_common.h" #include "atom.h" #include "navi10_ppt.h" #include "smu_v11_0_pptable.h" #include "smu_v11_0_ppsmc.h" -#include "nbio/nbio_7_4_sh_mask.h" +#include "nbio/nbio_2_3_offset.h" +#include "nbio/nbio_2_3_sh_mask.h" #include "asic_reg/mp/mp_11_0_sh_mask.h" @@ -349,7 +349,6 @@ navi10_get_allowed_feature_mask(struct smu_context *smu, | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) | FEATURE_MASK(FEATURE_FW_DSTATE_BIT) | FEATURE_MASK(FEATURE_BACO_BIT) - | FEATURE_MASK(FEATURE_ACDC_BIT) | FEATURE_MASK(FEATURE_GFX_SS_BIT) | FEATURE_MASK(FEATURE_APCC_DFLL_BIT) | FEATURE_MASK(FEATURE_FW_CTF_BIT) @@ -393,6 +392,9 @@ navi10_get_allowed_feature_mask(struct smu_context *smu, if (smu->adev->pg_flags & AMD_PG_SUPPORT_JPEG) *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_JPEG_PG_BIT); + if (smu->dc_controlled_by_gpio) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ACDC_BIT); + /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */ if (is_asic_secure(smu)) { /* only for navi10 A0 */ @@ -527,6 +529,9 @@ static int navi10_store_powerplay_table(struct smu_context *smu) table_context->thermal_controller_type = powerplay_table->thermal_controller_type; + if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC) + smu->dc_controlled_by_gpio = true; + mutex_lock(&smu_baco->mutex); if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) @@ -661,14 +666,14 @@ static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable) if (enable) { /* vcn dpm on is a prerequisite for vcn power gate messages */ if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1, NULL); if (ret) return ret; } power_gate->vcn_gated = false; } else { if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn); + ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); if (ret) return ret; } @@ -686,14 +691,14 @@ static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) if (enable) { if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_send_smc_msg(smu, SMU_MSG_PowerUpJpeg); + ret = smu_send_smc_msg(smu, SMU_MSG_PowerUpJpeg, NULL); if (ret) return ret; } power_gate->jpeg_gated = false; } else { if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownJpeg); + ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL); if (ret) return ret; } @@ -970,7 +975,7 @@ static int navi10_force_clk_levels(struct smu_context *smu, if (ret) return size; - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq); + ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); if (ret) return size; break; @@ -1042,7 +1047,7 @@ static int navi10_pre_display_config_changed(struct smu_context *smu) int ret = 0; uint32_t max_freq = 0; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL); if (ret) return ret; @@ -1066,7 +1071,8 @@ static int navi10_display_config_changed(struct smu_context *smu) smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, - smu->display_config->num_display); + smu->display_config->num_display, + NULL); if (ret) return ret; } @@ -1093,7 +1099,7 @@ static int navi10_force_dpm_limit_value(struct smu_context *smu, bool highest) return ret; force_freq = highest ? max_freq : min_freq; - ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq); + ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq, false); if (ret) return ret; } @@ -1119,7 +1125,7 @@ static int navi10_unforce_dpm_levels(struct smu_context *smu) if (ret) return ret; - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq); + ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); if (ret) return ret; } @@ -1391,7 +1397,7 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u if (workload_type < 0) return -EINVAL; smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, - 1 << workload_type); + 1 << workload_type, NULL); return ret; } @@ -1456,7 +1462,8 @@ static int navi10_notify_smc_display_config(struct smu_context *smu) if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetMinDeepSleepDcefclk, - min_clocks.dcef_clock_in_sr/100); + min_clocks.dcef_clock_in_sr/100, + NULL); if (ret) { pr_err("Attempt to set divider for DCEFCLK Failed!"); return ret; @@ -1678,10 +1685,10 @@ static int navi10_set_standard_performance_level(struct smu_context *smu) return navi10_set_performance_level(smu, AMD_DPM_FORCED_LEVEL_AUTO); } - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq); + 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); + ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); if (ret) return ret; @@ -1746,10 +1753,10 @@ static int navi10_set_peak_performance_level(struct smu_context *smu) if (ret) return ret; - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq); + 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); + ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); if (ret) return ret; @@ -1859,12 +1866,11 @@ static int navi10_get_power_limit(struct smu_context *smu, return -EINVAL; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit, - power_src << 16); + power_src << 16, &asic_default_power_limit); if (ret) { pr_err("[%s] get PPT limit failed!", __func__); return ret; } - smu_read_smc_arg(smu, &asic_default_power_limit); } else { /* the last hope to figure out the ppt limit */ if (!pptable) { @@ -1904,7 +1910,8 @@ static int navi10_update_pcie_parameters(struct smu_context *smu, pptable->PcieLaneCount[i] : pcie_width_cap); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_OverridePcieParameters, - smu_pcie_arg); + smu_pcie_arg, + NULL); if (ret) return ret; @@ -1950,13 +1957,13 @@ static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu, ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetVoltageByDpm, - param); + param, + &value); if (ret) { pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!"); return ret; } - smu_read_smc_arg(smu, &value); *voltage = (uint16_t)value; return 0; @@ -1980,6 +1987,18 @@ static int navi10_setup_od_limits(struct smu_context *smu) { return 0; } +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)) + return false; + + val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); + return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; +} + static int navi10_set_default_od_settings(struct smu_context *smu, bool initialize) { OverDriveTable_t *od_table, *boot_od_table; int ret = 0; @@ -2213,7 +2232,7 @@ static int navi10_run_btc(struct smu_context *smu) { int ret = 0; - ret = smu_send_smc_msg(smu, SMU_MSG_RunBtc); + ret = smu_send_smc_msg(smu, SMU_MSG_RunBtc, NULL); if (ret) pr_err("RunBtc failed!\n"); @@ -2225,9 +2244,9 @@ static int navi10_dummy_pstate_control(struct smu_context *smu, bool enable) int result = 0; if (!enable) - result = smu_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE); + result = smu_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE, NULL); else - result = smu_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE); + result = smu_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL); return result; } @@ -2336,7 +2355,6 @@ static const struct pptable_funcs navi10_ppt_funcs = { .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, .system_features_control = smu_v11_0_system_features_control, .send_smc_msg_with_param = smu_v11_0_send_msg_with_param, - .read_smc_arg = smu_v11_0_read_arg, .init_display_count = smu_v11_0_init_display_count, .set_allowed_mask = smu_v11_0_set_allowed_mask, .get_enabled_mask = smu_v11_0_get_enabled_mask, @@ -2357,7 +2375,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .register_irq_handler = smu_v11_0_register_irq_handler, .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support= smu_v11_0_baco_is_support, + .baco_is_support= navi10_is_baco_supported, .baco_get_state = smu_v11_0_baco_get_state, .baco_set_state = smu_v11_0_baco_set_state, .baco_enter = smu_v11_0_baco_enter, @@ -2370,6 +2388,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .get_pptable_power_limit = navi10_get_pptable_power_limit, .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, }; 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 3ad0f4aa3aa3..b0ed1b3fe79a 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -24,7 +24,6 @@ #include "amdgpu.h" #include "amdgpu_smu.h" #include "smu_internal.h" -#include "soc15_common.h" #include "smu_v12_0_ppsmc.h" #include "smu12_driver_if.h" #include "smu_v12_0.h" @@ -240,6 +239,7 @@ static int renoir_print_clk_levels(struct smu_context *smu, 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; @@ -298,8 +298,13 @@ static int renoir_print_clk_levels(struct smu_context *smu, GET_DPM_CUR_FREQ(clk_table, clk_type, i, value); size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, cur_value == value ? "*" : ""); + if (cur_value == value) + cur_value_match_level = true; } + if (!cur_value_match_level) + size += sprintf(buf + size, " %uMhz *\n", cur_value); + return size; } @@ -342,14 +347,14 @@ static int renoir_dpm_set_uvd_enable(struct smu_context *smu, bool enable) if (enable) { /* vcn dpm on is a prerequisite for vcn power gate messages */ if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); if (ret) return ret; } power_gate->vcn_gated = false; } else { if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn); + ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); if (ret) return ret; } @@ -367,14 +372,14 @@ static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) if (enable) { if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); if (ret) return ret; } power_gate->jpeg_gated = false; } else { if (smu_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); if (ret) return ret; } @@ -423,7 +428,7 @@ static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest) return ret; force_freq = highest ? max_freq : min_freq; - ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq); + ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq, false); if (ret) return ret; } @@ -456,7 +461,7 @@ static int renoir_unforce_dpm_levels(struct smu_context *smu) { if (ret) return ret; - ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq); + ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq, false); if (ret) return ret; } @@ -622,22 +627,24 @@ static int renoir_force_clk_levels(struct smu_context *smu, return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, soft_max_level == 0 ? min_freq : - soft_max_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : max_freq); + soft_max_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : max_freq, + NULL); if (ret) return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, soft_min_level == 2 ? max_freq : - soft_min_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : min_freq); + soft_min_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : min_freq, + NULL); if (ret) 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 = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq, NULL); if (ret) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min_freq); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min_freq, NULL); if (ret) return ret; break; @@ -645,10 +652,10 @@ static int renoir_force_clk_levels(struct smu_context *smu, 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 = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq, NULL); if (ret) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min_freq); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min_freq, NULL); if (ret) return ret; break; @@ -672,14 +679,19 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ workload_type = smu_workload_get_type(smu, smu->power_profile_mode); if (workload_type < 0) { - pr_err("Unsupported power profile mode %d on RENOIR\n",smu->power_profile_mode); + /* + * TODO: If some case need switch to powersave/default power mode + * then can consider enter WORKLOAD_COMPUTE/WORKLOAD_CUSTOM for power saving. + */ + pr_err_once("Unsupported power profile mode %d on RENOIR\n",smu->power_profile_mode); return -EINVAL; } ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, - 1 << workload_type); + 1 << workload_type, + NULL); if (ret) { - pr_err("Fail to set workload type %d\n", workload_type); + pr_err_once("Fail to set workload type %d\n", workload_type); return ret; } @@ -697,7 +709,7 @@ static int renoir_set_peak_clock_by_device(struct smu_context *smu) if (ret) return ret; - ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq); + ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false); if (ret) return ret; @@ -705,7 +717,7 @@ static int renoir_set_peak_clock_by_device(struct smu_context *smu) if (ret) return ret; - ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq); + ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false); if (ret) return ret; @@ -881,6 +893,22 @@ static int renoir_read_sensor(struct smu_context *smu, return ret; } +static bool renoir_is_dpm_running(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + /* + * Util now, the pmfw hasn't exported the interface of SMU + * feature mask to APU SKU so just force on all the feature + * at early initial stage. + */ + if (adev->in_suspend) + return false; + else + return true; + +} + static const struct pptable_funcs renoir_ppt_funcs = { .get_smu_msg_index = renoir_get_smu_msg_index, .get_smu_clk_index = renoir_get_smu_clk_index, @@ -910,7 +938,6 @@ static const struct pptable_funcs renoir_ppt_funcs = { .powergate_vcn = smu_v12_0_powergate_vcn, .powergate_jpeg = smu_v12_0_powergate_jpeg, .send_smc_msg_with_param = smu_v12_0_send_msg_with_param, - .read_smc_arg = smu_v12_0_read_arg, .set_gfx_cgpg = smu_v12_0_set_gfx_cgpg, .gfx_off_control = smu_v12_0_gfx_off_control, .init_smc_tables = smu_v12_0_init_smc_tables, @@ -922,6 +949,7 @@ static const struct pptable_funcs renoir_ppt_funcs = { .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, + .is_dpm_running = renoir_is_dpm_running, }; void renoir_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.h b/drivers/gpu/drm/amd/powerplay/renoir_ppt.h index 2a390ddd37dd..89cd6da118a3 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.h +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.h @@ -37,7 +37,7 @@ extern void renoir_set_ppt_funcs(struct smu_context *smu); freq = table->SocClocks[dpm_level].Freq; \ break; \ case SMU_MCLK: \ - freq = table->MemClocks[dpm_level].Freq; \ + freq = table->FClocks[dpm_level].Freq; \ break; \ case SMU_DCEFCLK: \ freq = table->DcfClocks[dpm_level].Freq; \ diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/powerplay/smu_internal.h index 7bd200ffcda8..40c35bcc5a0a 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_internal.h +++ b/drivers/gpu/drm/amd/powerplay/smu_internal.h @@ -79,12 +79,13 @@ #define smu_set_default_od_settings(smu, initialize) \ ((smu)->ppt_funcs->set_default_od_settings ? (smu)->ppt_funcs->set_default_od_settings((smu), (initialize)) : 0) -int smu_send_smc_msg(struct smu_context *smu, enum smu_message_type msg); +#define smu_send_smc_msg_with_param(smu, msg, param, read_arg) \ + ((smu)->ppt_funcs->send_smc_msg_with_param? (smu)->ppt_funcs->send_smc_msg_with_param((smu), (msg), (param), (read_arg)) : 0) + +static inline int smu_send_smc_msg(struct smu_context *smu, enum smu_message_type msg, uint32_t *read_arg) { + return smu_send_smc_msg_with_param(smu, msg, 0, read_arg); +} -#define smu_send_smc_msg_with_param(smu, msg, param) \ - ((smu)->ppt_funcs->send_smc_msg_with_param? (smu)->ppt_funcs->send_smc_msg_with_param((smu), (msg), (param)) : 0) -#define smu_read_smc_arg(smu, arg) \ - ((smu)->ppt_funcs->read_smc_arg? (smu)->ppt_funcs->read_smc_arg((smu), (arg)) : 0) #define smu_alloc_dpm_context(smu) \ ((smu)->ppt_funcs->alloc_dpm_context ? (smu)->ppt_funcs->alloc_dpm_context((smu)) : 0) #define smu_init_display_count(smu, count) \ @@ -210,4 +211,7 @@ int smu_send_smc_msg(struct smu_context *smu, enum smu_message_type msg); #define smu_disable_umc_cdr_12gbps_workaround(smu) \ ((smu)->ppt_funcs->disable_umc_cdr_12gbps_workaround ? (smu)->ppt_funcs->disable_umc_cdr_12gbps_workaround((smu)) : 0) +#define smu_set_power_source(smu, power_src) \ + ((smu)->ppt_funcs->set_power_source ? (smu)->ppt_funcs->set_power_source((smu), (power_src)) : 0) + #endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index c9e5ce135fd4..655ba4fb05dc 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -26,7 +26,6 @@ #define SMU_11_0_PARTIAL_PPTABLE -#include "pp_debug.h" #include "amdgpu.h" #include "amdgpu_smu.h" #include "smu_internal.h" @@ -43,8 +42,6 @@ #include "asic_reg/thm/thm_11_0_2_sh_mask.h" #include "asic_reg/mp/mp_11_0_offset.h" #include "asic_reg/mp/mp_11_0_sh_mask.h" -#include "asic_reg/nbio/nbio_7_4_offset.h" -#include "asic_reg/nbio/nbio_7_4_sh_mask.h" #include "asic_reg/smuio/smuio_11_0_0_offset.h" #include "asic_reg/smuio/smuio_11_0_0_sh_mask.h" @@ -64,7 +61,7 @@ static int smu_v11_0_send_msg_without_waiting(struct smu_context *smu, return 0; } -int smu_v11_0_read_arg(struct smu_context *smu, uint32_t *arg) +static int smu_v11_0_read_arg(struct smu_context *smu, uint32_t *arg) { struct amdgpu_device *adev = smu->adev; @@ -92,7 +89,8 @@ static int smu_v11_0_wait_for_response(struct smu_context *smu) int smu_v11_0_send_msg_with_param(struct smu_context *smu, enum smu_message_type msg, - uint32_t param) + uint32_t param, + uint32_t *read_arg) { struct amdgpu_device *adev = smu->adev; int ret = 0, index = 0; @@ -101,11 +99,12 @@ smu_v11_0_send_msg_with_param(struct smu_context *smu, if (index < 0) return index; + mutex_lock(&smu->message_lock); ret = smu_v11_0_wait_for_response(smu); if (ret) { pr_err("Msg issuing pre-check failed and " "SMU may be not in the right state!\n"); - return ret; + goto out; } WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); @@ -115,10 +114,21 @@ smu_v11_0_send_msg_with_param(struct smu_context *smu, smu_v11_0_send_msg_without_waiting(smu, (uint16_t)index); ret = smu_v11_0_wait_for_response(smu); - if (ret) + if (ret) { pr_err("failed send message: %10s (%d) \tparam: 0x%08x response %#x\n", smu_get_message_name(smu, msg), index, param, ret); - + goto out; + } + if (read_arg) { + ret = smu_v11_0_read_arg(smu, read_arg); + if (ret) { + pr_err("failed to read message arg: %10s (%d) \tparam: 0x%08x response %#x\n", + smu_get_message_name(smu, msg), index, param, ret); + goto out; + } + } +out: + mutex_unlock(&smu->message_lock); return ret; } @@ -262,6 +272,9 @@ int smu_v11_0_check_fw_version(struct smu_context *smu) case CHIP_NAVI10: smu->smc_if_version = SMU11_DRIVER_IF_VERSION_NV10; break; + case CHIP_NAVI12: + smu->smc_if_version = SMU11_DRIVER_IF_VERSION_NV12; + break; case CHIP_NAVI14: smu->smc_if_version = SMU11_DRIVER_IF_VERSION_NV14; break; @@ -671,12 +684,14 @@ int smu_v11_0_notify_memory_pool_location(struct smu_context *smu) ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSystemVirtualDramAddrHigh, - address_high); + address_high, + NULL); if (ret) return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSystemVirtualDramAddrLow, - address_low); + address_low, + NULL); if (ret) return ret; @@ -685,15 +700,15 @@ int smu_v11_0_notify_memory_pool_location(struct smu_context *smu) address_low = (uint32_t)lower_32_bits(address); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrHigh, - address_high); + address_high, NULL); if (ret) return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrLow, - address_low); + address_low, NULL); if (ret) return ret; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramSize, - (uint32_t)memory_pool->size); + (uint32_t)memory_pool->size, NULL); if (ret) return ret; @@ -757,7 +772,7 @@ int smu_v11_0_set_deep_sleep_dcefclk(struct smu_context *smu, uint32_t clk) int ret; ret = smu_send_smc_msg_with_param(smu, - SMU_MSG_SetMinDeepSleepDcefclk, clk); + SMU_MSG_SetMinDeepSleepDcefclk, clk, NULL); if (ret) pr_err("SMU11 attempt to set divider for DCEFCLK Failed!"); @@ -784,11 +799,13 @@ int smu_v11_0_set_driver_table_location(struct smu_context *smu) if (driver_table->mc_address) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetDriverDramAddrHigh, - upper_32_bits(driver_table->mc_address)); + upper_32_bits(driver_table->mc_address), + NULL); if (!ret) ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetDriverDramAddrLow, - lower_32_bits(driver_table->mc_address)); + lower_32_bits(driver_table->mc_address), + NULL); } return ret; @@ -802,11 +819,13 @@ int smu_v11_0_set_tool_table_location(struct smu_context *smu) if (tool_table->mc_address) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetToolsDramAddrHigh, - upper_32_bits(tool_table->mc_address)); + upper_32_bits(tool_table->mc_address), + NULL); if (!ret) ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetToolsDramAddrLow, - lower_32_bits(tool_table->mc_address)); + lower_32_bits(tool_table->mc_address), + NULL); } return ret; @@ -819,7 +838,7 @@ int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count) if (!smu->pm_enabled) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, count); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, count, NULL); return ret; } @@ -837,12 +856,12 @@ int smu_v11_0_set_allowed_mask(struct smu_context *smu) bitmap_copy((unsigned long *)feature_mask, feature->allowed, 64); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskHigh, - feature_mask[1]); + feature_mask[1], NULL); if (ret) goto failed; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskLow, - feature_mask[0]); + feature_mask[0], NULL); if (ret) goto failed; @@ -862,17 +881,11 @@ int smu_v11_0_get_enabled_mask(struct smu_context *smu, return -EINVAL; if (bitmap_empty(feature->enabled, feature->feature_num)) { - ret = smu_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesHigh); - if (ret) - return ret; - ret = smu_read_smc_arg(smu, &feature_mask_high); + ret = smu_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesHigh, &feature_mask_high); if (ret) return ret; - ret = smu_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesLow); - if (ret) - return ret; - ret = smu_read_smc_arg(smu, &feature_mask_low); + ret = smu_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesLow, &feature_mask_low); if (ret) return ret; @@ -894,7 +907,7 @@ int smu_v11_0_system_features_control(struct smu_context *smu, int ret = 0; ret = smu_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : - SMU_MSG_DisableAllSmuFeatures)); + SMU_MSG_DisableAllSmuFeatures), NULL); if (ret) return ret; @@ -923,7 +936,7 @@ int smu_v11_0_notify_display_change(struct smu_context *smu) return ret; if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) && smu->adev->gmc.vram_type == AMDGPU_VRAM_TYPE_HBM) - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetUclkFastSwitch, 1); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetUclkFastSwitch, 1, NULL); return ret; } @@ -947,30 +960,24 @@ smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock, return -EINVAL; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq, - clk_id << 16); + clk_id << 16, clock); if (ret) { pr_err("[GetMaxSustainableClock] Failed to get max DC clock from SMC!"); return ret; } - ret = smu_read_smc_arg(smu, clock); - if (ret) - return ret; - if (*clock != 0) return 0; /* if DC limit is zero, return AC limit */ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, - clk_id << 16); + clk_id << 16, clock); if (ret) { pr_err("[GetMaxSustainableClock] failed to get max AC clock from SMC!"); return ret; } - ret = smu_read_smc_arg(smu, clock); - - return ret; + return 0; } int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu) @@ -1106,7 +1113,7 @@ int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n) return -EOPNOTSUPP; } - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n, NULL); if (ret) { pr_err("[%s] Set power limit Failed!\n", __func__); return ret; @@ -1136,11 +1143,7 @@ int smu_v11_0_get_current_clk_freq(struct smu_context *smu, ret = smu_get_current_clk_freq_by_table(smu, clk_id, &freq); else { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmClockFreq, - (asic_clk_id << 16)); - if (ret) - return ret; - - ret = smu_read_smc_arg(smu, &freq); + (asic_clk_id << 16), &freq); if (ret) return ret; } @@ -1375,9 +1378,9 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable) if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) - ret = smu_send_smc_msg(smu, SMU_MSG_AllowGfxOff); + ret = smu_send_smc_msg(smu, SMU_MSG_AllowGfxOff, NULL); else - ret = smu_send_smc_msg(smu, SMU_MSG_DisallowGfxOff); + ret = smu_send_smc_msg(smu, SMU_MSG_DisallowGfxOff, NULL); break; default: break; @@ -1515,10 +1518,18 @@ int smu_v11_0_set_xgmi_pstate(struct smu_context *smu, int ret = 0; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetXgmiMode, - pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3); + pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, + NULL); return ret; } +static int smu_v11_0_ack_ac_dc_interrupt(struct smu_context *smu) +{ + return smu_send_smc_msg(smu, + SMU_MSG_ReenableAcDcInterrupt, + NULL); +} + #define THM_11_0__SRCID__THM_DIG_THERM_L2H 0 /* ASIC_TEMP > CG_THERMAL_INT.DIG_THERM_INTH */ #define THM_11_0__SRCID__THM_DIG_THERM_H2L 1 /* ASIC_TEMP < CG_THERMAL_INT.DIG_THERM_INTL */ @@ -1552,6 +1563,9 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev, break; } + } else if (client_id == SOC15_IH_CLIENTID_MP1) { + if (src_id == 0xfe) + smu_v11_0_ack_ac_dc_interrupt(&adev->smu); } return 0; @@ -1591,6 +1605,12 @@ int smu_v11_0_register_irq_handler(struct smu_context *smu) if (ret) return ret; + ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_MP1, + 0xfe, + irq_src); + if (ret) + return ret; + return ret; } @@ -1628,21 +1648,19 @@ int smu_v11_0_set_azalia_d3_pme(struct smu_context *smu) { int ret = 0; - ret = smu_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME); + ret = smu_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME, NULL); return ret; } static int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_v11_0_baco_seq baco_seq) { - return smu_send_smc_msg_with_param(smu, SMU_MSG_ArmD3, baco_seq); + return smu_send_smc_msg_with_param(smu, SMU_MSG_ArmD3, baco_seq, NULL); } bool smu_v11_0_baco_is_support(struct smu_context *smu) { - struct amdgpu_device *adev = smu->adev; struct smu_baco_context *smu_baco = &smu->smu_baco; - uint32_t val; bool baco_support; mutex_lock(&smu_baco->mutex); @@ -1657,11 +1675,7 @@ bool smu_v11_0_baco_is_support(struct smu_context *smu) !smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) return false; - val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); - if (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) - return true; - - return false; + return true; } enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu) @@ -1678,11 +1692,9 @@ enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu) int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) { - struct smu_baco_context *smu_baco = &smu->smu_baco; struct amdgpu_device *adev = smu->adev; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - uint32_t bif_doorbell_intr_cntl; uint32_t data; int ret = 0; @@ -1691,32 +1703,26 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) mutex_lock(&smu_baco->mutex); - bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL); - if (state == SMU_BACO_STATE_ENTER) { - bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl, - BIF_DOORBELL_INT_CNTL, - DOORBELL_INTERRUPT_DISABLE, 1); - WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl); - if (!ras || !ras->supported) { data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL); data |= 0x80000000; WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data); - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL); } else { - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL); } } else { - ret = smu_send_smc_msg(smu, SMU_MSG_ExitBaco); + ret = smu_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL); if (ret) goto out; - bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl, - BIF_DOORBELL_INT_CNTL, - DOORBELL_INTERRUPT_DISABLE, 0); - WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl); + if (ras && ras->supported) { + ret = smu_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL); + if (ret) + goto out; + } /* clear vbios scratch 6 and 7 for coming asic reinit */ WREG32(adev->bios_scratch_reg_offset + 6, 0); @@ -1777,19 +1783,13 @@ int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c param = (clk_id & 0xffff) << 16; if (max) { - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param); - if (ret) - goto failed; - ret = smu_read_smc_arg(smu, max); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param, max); if (ret) goto failed; } if (min) { - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMinDpmFreq, param); - if (ret) - goto failed; - ret = smu_read_smc_arg(smu, min); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMinDpmFreq, param, min); if (ret) goto failed; } @@ -1811,7 +1811,7 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_ if (max > 0) { param = (uint32_t)((clk_id << 16) | (max & 0xffff)); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq, - param); + param, NULL); if (ret) return ret; } @@ -1819,7 +1819,7 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_ if (min > 0) { param = (uint32_t)((clk_id << 16) | (min & 0xffff)); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq, - param); + param, NULL); if (ret) return ret; } @@ -1939,3 +1939,18 @@ int smu_v11_0_set_performance_level(struct smu_context *smu, return ret; } +int smu_v11_0_set_power_source(struct smu_context *smu, + enum smu_power_src_type power_src) +{ + int pwr_source; + + pwr_source = smu_power_get_index(smu, (uint32_t)power_src); + if (pwr_source < 0) + return -EINVAL; + + return smu_send_smc_msg_with_param(smu, + SMU_MSG_NotifyPowerSource, + pwr_source, + NULL); +} + diff --git a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c index 518e6597bf2d..169ebdad87b8 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c @@ -20,7 +20,6 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "pp_debug.h" #include <linux/firmware.h> #include "amdgpu.h" #include "amdgpu_smu.h" @@ -50,7 +49,7 @@ int smu_v12_0_send_msg_without_waiting(struct smu_context *smu, return 0; } -int smu_v12_0_read_arg(struct smu_context *smu, uint32_t *arg) +static int smu_v12_0_read_arg(struct smu_context *smu, uint32_t *arg) { struct amdgpu_device *adev = smu->adev; @@ -78,7 +77,8 @@ int smu_v12_0_wait_for_response(struct smu_context *smu) int smu_v12_0_send_msg_with_param(struct smu_context *smu, enum smu_message_type msg, - uint32_t param) + uint32_t param, + uint32_t *read_arg) { struct amdgpu_device *adev = smu->adev; int ret = 0, index = 0; @@ -87,11 +87,12 @@ smu_v12_0_send_msg_with_param(struct smu_context *smu, if (index < 0) return index; + mutex_lock(&smu->message_lock); ret = smu_v12_0_wait_for_response(smu); if (ret) { pr_err("Msg issuing pre-check failed and " "SMU may be not in the right state!\n"); - return ret; + goto out; } WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); @@ -101,10 +102,21 @@ smu_v12_0_send_msg_with_param(struct smu_context *smu, smu_v12_0_send_msg_without_waiting(smu, (uint16_t)index); ret = smu_v12_0_wait_for_response(smu); - if (ret) + if (ret) { pr_err("Failed to send message 0x%x, response 0x%x param 0x%x\n", index, ret, param); - + goto out; + } + if (read_arg) { + ret = smu_v12_0_read_arg(smu, read_arg); + if (ret) { + pr_err("Failed to read message arg 0x%x, response 0x%x param 0x%x\n", + index, ret, param); + goto out; + } + } +out: + mutex_unlock(&smu->message_lock); return ret; } @@ -163,9 +175,9 @@ int smu_v12_0_powergate_sdma(struct smu_context *smu, bool gate) return 0; if (gate) - return smu_send_smc_msg(smu, SMU_MSG_PowerDownSdma); + return smu_send_smc_msg(smu, SMU_MSG_PowerDownSdma, NULL); else - return smu_send_smc_msg(smu, SMU_MSG_PowerUpSdma); + return smu_send_smc_msg(smu, SMU_MSG_PowerUpSdma, NULL); } int smu_v12_0_powergate_vcn(struct smu_context *smu, bool gate) @@ -174,9 +186,9 @@ int smu_v12_0_powergate_vcn(struct smu_context *smu, bool gate) return 0; if (gate) - return smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn); + return smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); else - return smu_send_smc_msg(smu, SMU_MSG_PowerUpVcn); + return smu_send_smc_msg(smu, SMU_MSG_PowerUpVcn, NULL); } int smu_v12_0_powergate_jpeg(struct smu_context *smu, bool gate) @@ -185,9 +197,9 @@ int smu_v12_0_powergate_jpeg(struct smu_context *smu, bool gate) return 0; if (gate) - return smu_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0); + return smu_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); else - return smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0); + return smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); } int smu_v12_0_set_gfx_cgpg(struct smu_context *smu, bool enable) @@ -196,7 +208,9 @@ int smu_v12_0_set_gfx_cgpg(struct smu_context *smu, bool enable) return 0; return smu_v12_0_send_msg_with_param(smu, - SMU_MSG_SetGfxCGPG, enable ? 1 : 0); + SMU_MSG_SetGfxCGPG, + enable ? 1 : 0, + NULL); } int smu_v12_0_read_sensor(struct smu_context *smu, @@ -262,10 +276,10 @@ int smu_v12_0_gfx_off_control(struct smu_context *smu, bool enable) int ret = 0, timeout = 500; if (enable) { - ret = smu_send_smc_msg(smu, SMU_MSG_AllowGfxOff); + ret = smu_send_smc_msg(smu, SMU_MSG_AllowGfxOff, NULL); } else { - ret = smu_send_smc_msg(smu, SMU_MSG_DisallowGfxOff); + ret = smu_send_smc_msg(smu, SMU_MSG_DisallowGfxOff, NULL); /* confirm gfx is back to "on" state, timeout is 0.5 second */ while (!(smu_v12_0_get_gfxoff_status(smu) == 2)) { @@ -331,17 +345,11 @@ int smu_v12_0_get_enabled_mask(struct smu_context *smu, if (!feature_mask || num < 2) return -EINVAL; - ret = smu_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesHigh); - if (ret) - return ret; - ret = smu_read_smc_arg(smu, &feature_mask_high); + ret = smu_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesHigh, &feature_mask_high); if (ret) return ret; - ret = smu_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesLow); - if (ret) - return ret; - ret = smu_read_smc_arg(smu, &feature_mask_low); + ret = smu_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesLow, &feature_mask_low); if (ret) return ret; @@ -388,14 +396,11 @@ int smu_v12_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c switch (clk_type) { case SMU_GFXCLK: case SMU_SCLK: - ret = smu_send_smc_msg(smu, SMU_MSG_GetMaxGfxclkFrequency); + ret = smu_send_smc_msg(smu, SMU_MSG_GetMaxGfxclkFrequency, max); if (ret) { pr_err("Attempt to get max GX frequency from SMC Failed !\n"); goto failed; } - ret = smu_read_smc_arg(smu, max); - if (ret) - goto failed; break; case SMU_UCLK: case SMU_FCLK: @@ -419,14 +424,11 @@ int smu_v12_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c switch (clk_type) { case SMU_GFXCLK: case SMU_SCLK: - ret = smu_send_smc_msg(smu, SMU_MSG_GetMinGfxclkFrequency); + ret = smu_send_smc_msg(smu, SMU_MSG_GetMinGfxclkFrequency, min); if (ret) { pr_err("Attempt to get min GX frequency from SMC Failed !\n"); goto failed; } - ret = smu_read_smc_arg(smu, min); - if (ret) - goto failed; break; case SMU_UCLK: case SMU_FCLK: @@ -450,7 +452,7 @@ failed: } 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); + return smu_v12_0_send_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, SMU_RESET_MODE_2, NULL); } int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type, @@ -461,39 +463,39 @@ int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_ switch (clk_type) { case SMU_GFXCLK: case SMU_SCLK: - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, min); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, min, NULL); if (ret) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, max); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, max, NULL); if (ret) return ret; break; case SMU_FCLK: case SMU_MCLK: - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min, NULL); if (ret) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max, NULL); if (ret) return ret; break; case SMU_SOCCLK: - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min, NULL); if (ret) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max, NULL); if (ret) return ret; break; case SMU_VCLK: - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn, min); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn, min, NULL); if (ret) return ret; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn, max); + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn, max, NULL); if (ret) return ret; break; @@ -512,11 +514,13 @@ int smu_v12_0_set_driver_table_location(struct smu_context *smu) if (driver_table->mc_address) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetDriverDramAddrHigh, - upper_32_bits(driver_table->mc_address)); + upper_32_bits(driver_table->mc_address), + NULL); if (!ret) ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetDriverDramAddrLow, - lower_32_bits(driver_table->mc_address)); + lower_32_bits(driver_table->mc_address), + NULL); } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c index 49e5ef3e3876..16aa171971d3 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c @@ -33,6 +33,8 @@ #include "smu7_smumgr.h" #include "vega20_hwmgr.h" +#include "smu_v11_0_i2c.h" + /* MP Apertures */ #define MP0_Public 0x03800000 #define MP0_SRAM 0x03900000 @@ -406,6 +408,7 @@ static int vega20_smu_init(struct pp_hwmgr *hwmgr) struct vega20_smumgr *priv; unsigned long tools_size = 0x19000; int ret = 0; + struct amdgpu_device *adev = hwmgr->adev; struct cgs_firmware_info info = {0}; @@ -505,6 +508,10 @@ static int vega20_smu_init(struct pp_hwmgr *hwmgr) priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].version = 0x01; priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t); + ret = smu_v11_0_i2c_eeprom_control_init(&adev->pm.smu_i2c); + if (ret) + goto err4; + return 0; err4: @@ -537,6 +544,9 @@ static int vega20_smu_fini(struct pp_hwmgr *hwmgr) { struct vega20_smumgr *priv = (struct vega20_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + + smu_v11_0_i2c_eeprom_control_fini(&adev->pm.smu_i2c); if (priv) { amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, @@ -560,6 +570,7 @@ static int vega20_smu_fini(struct pp_hwmgr *hwmgr) kfree(hwmgr->smu_backend); hwmgr->smu_backend = NULL; } + return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c index 4ad8d6c14ee5..3f1044326dcb 100644 --- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c @@ -21,7 +21,6 @@ * */ -#include "pp_debug.h" #include <linux/firmware.h> #include "amdgpu.h" #include "amdgpu_smu.h" @@ -36,6 +35,7 @@ #include "vega20_ppt.h" #include "vega20_pptable.h" #include "vega20_ppsmc.h" +#include "nbio/nbio_7_4_offset.h" #include "nbio/nbio_7_4_sh_mask.h" #include "asic_reg/thm/thm_11_0_2_offset.h" #include "asic_reg/thm/thm_11_0_2_sh_mask.h" @@ -587,7 +587,7 @@ static int vega20_check_powerplay_table(struct smu_context *smu) static int vega20_run_btc_afll(struct smu_context *smu) { - return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc); + return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc, NULL); } #define FEATURE_MASK(feature) (1ULL << feature) @@ -670,13 +670,13 @@ vega20_set_single_dpm_table(struct smu_context *smu, ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmFreqByIndex, - (clk_id << 16 | 0xFF)); + (clk_id << 16 | 0xFF), + &num_of_levels); if (ret) { pr_err("[GetNumOfDpmLevel] failed to get dpm levels!"); return ret; } - smu_read_smc_arg(smu, &num_of_levels); if (!num_of_levels) { pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!"); return -EINVAL; @@ -687,12 +687,12 @@ vega20_set_single_dpm_table(struct smu_context *smu, for (i = 0; i < num_of_levels; i++) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmFreqByIndex, - (clk_id << 16 | i)); + (clk_id << 16 | i), + &clk); if (ret) { pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!"); return ret; } - smu_read_smc_arg(smu, &clk); if (!clk) { pr_err("[GetDpmFreqByIndex] clk value is invalid!"); return -EINVAL; @@ -1200,7 +1200,8 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max, single_dpm_table->dpm_state.soft_min_level; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_GFXCLK << 16) | (freq & 0xffff)); + (PPCLK_GFXCLK << 16) | (freq & 0xffff), + NULL); if (ret) { pr_err("Failed to set soft %s gfxclk !\n", max ? "max" : "min"); @@ -1215,7 +1216,8 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max, single_dpm_table->dpm_state.soft_min_level; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_UCLK << 16) | (freq & 0xffff)); + (PPCLK_UCLK << 16) | (freq & 0xffff), + NULL); if (ret) { pr_err("Failed to set soft %s memclk !\n", max ? "max" : "min"); @@ -1230,7 +1232,8 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max, single_dpm_table->dpm_state.soft_min_level; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_SOCCLK << 16) | (freq & 0xffff)); + (PPCLK_SOCCLK << 16) | (freq & 0xffff), + NULL); if (ret) { pr_err("Failed to set soft %s socclk !\n", max ? "max" : "min"); @@ -1245,7 +1248,8 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max, single_dpm_table->dpm_state.soft_min_level; ret = smu_send_smc_msg_with_param(smu, (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_FCLK << 16) | (freq & 0xffff)); + (PPCLK_FCLK << 16) | (freq & 0xffff), + NULL); if (ret) { pr_err("Failed to set soft %s fclk !\n", max ? "max" : "min"); @@ -1260,7 +1264,8 @@ static int vega20_upload_dpm_level(struct smu_context *smu, bool max, if (!max) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, - (PPCLK_DCEFCLK << 16) | (freq & 0xffff)); + (PPCLK_DCEFCLK << 16) | (freq & 0xffff), + NULL); if (ret) { pr_err("Failed to set hard min dcefclk !\n"); return ret; @@ -1421,7 +1426,9 @@ static int vega20_force_clk_levels(struct smu_context *smu, } ret = smu_send_smc_msg_with_param(smu, - SMU_MSG_SetMinLinkDpmByIndex, soft_min_level); + SMU_MSG_SetMinLinkDpmByIndex, + soft_min_level, + NULL); if (ret) pr_err("Failed to set min link dpm level!\n"); @@ -1477,13 +1484,13 @@ static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu, ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetAVFSVoltageByDpm, - ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq)); + ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq), + voltage); if (ret) { pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!"); return ret; } - smu_read_smc_arg(smu, voltage); *voltage = *voltage / VOLTAGE_SCALE; return 0; @@ -1956,8 +1963,10 @@ static int vega20_set_power_profile_mode(struct smu_context *smu, long *input, u workload_type = smu_workload_get_type(smu, smu->power_profile_mode); if (workload_type < 0) return -EINVAL; - smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, - 1 << workload_type); + smu_send_smc_msg_with_param(smu, + SMU_MSG_SetWorkloadMask, + 1 << workload_type, + NULL); return ret; } @@ -2029,7 +2038,8 @@ vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu, dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, - (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level); + (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level, + NULL); if (ret) { pr_err("[%s] Set hard min uclk failed!", __func__); return ret; @@ -2047,7 +2057,7 @@ static int vega20_pre_display_config_changed(struct smu_context *smu) if (!smu->smu_dpm.dpm_context) return -EINVAL; - smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0); + smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL); ret = vega20_set_uclk_to_highest_dpm_level(smu, &dpm_table->mem_table); if (ret) @@ -2074,7 +2084,8 @@ static int vega20_display_config_changed(struct smu_context *smu) smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, - smu->display_config->num_display); + smu->display_config->num_display, + NULL); } return ret; @@ -2247,7 +2258,8 @@ vega20_notify_smc_display_config(struct smu_context *smu) if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetMinDeepSleepDcefclk, - min_clocks.dcef_clock_in_sr/100); + min_clocks.dcef_clock_in_sr/100, + NULL); if (ret) { pr_err("Attempt to set divider for DCEFCLK Failed!"); return ret; @@ -2262,7 +2274,8 @@ vega20_notify_smc_display_config(struct smu_context *smu) memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100; ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, - (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level); + (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level, + NULL); if (ret) { pr_err("[%s] Set hard min uclk failed!", __func__); return ret; @@ -2853,8 +2866,10 @@ static int vega20_set_thermal_fan_table(struct smu_context *smu) struct smu_table_context *table_context = &smu->smu_table; PPTable_t *pptable = table_context->driver_pptable; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget, - (uint32_t)pptable->FanTargetTemperature); + ret = smu_send_smc_msg_with_param(smu, + SMU_MSG_SetFanTemperatureTarget, + (uint32_t)pptable->FanTargetTemperature, + NULL); return ret; } @@ -2864,15 +2879,13 @@ static int vega20_get_fan_speed_rpm(struct smu_context *smu, { int ret; - ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm); + ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm, speed); if (ret) { pr_err("Attempt to get current RPM from SMC Failed!\n"); return ret; } - smu_read_smc_arg(smu, speed); - return 0; } @@ -3137,7 +3150,7 @@ static int vega20_set_df_cstate(struct smu_context *smu, return -EINVAL; } - return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state); + return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state, NULL); } static int vega20_update_pcie_parameters(struct smu_context *smu, @@ -3155,12 +3168,24 @@ static int vega20_update_pcie_parameters(struct smu_context *smu, pptable->PcieLaneCount[i] : pcie_width_cap); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_OverridePcieParameters, - smu_pcie_arg); + smu_pcie_arg, + NULL); } return ret; } +static bool vega20_is_baco_supported(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t val; + + if (!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 const struct pptable_funcs vega20_ppt_funcs = { .tables_init = vega20_tables_init, @@ -3229,7 +3254,6 @@ static const struct pptable_funcs vega20_ppt_funcs = { .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, .system_features_control = smu_v11_0_system_features_control, .send_smc_msg_with_param = smu_v11_0_send_msg_with_param, - .read_smc_arg = smu_v11_0_read_arg, .init_display_count = smu_v11_0_init_display_count, .set_allowed_mask = smu_v11_0_set_allowed_mask, .get_enabled_mask = smu_v11_0_get_enabled_mask, @@ -3250,7 +3274,7 @@ static const struct pptable_funcs vega20_ppt_funcs = { .register_irq_handler = smu_v11_0_register_irq_handler, .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support= smu_v11_0_baco_is_support, + .baco_is_support= vega20_is_baco_supported, .baco_get_state = smu_v11_0_baco_get_state, .baco_set_state = smu_v11_0_baco_set_state, .baco_enter = smu_v11_0_baco_enter, |