summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/smu_v11_0.c')
-rw-r--r--drivers/gpu/drm/amd/powerplay/smu_v11_0.c99
1 files changed, 95 insertions, 4 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index 632a20587c8b..a87b86ae2cc5 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -40,6 +40,7 @@
#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"
@@ -67,9 +68,9 @@ static int smu_v11_0_read_arg(struct smu_context *smu, uint32_t *arg)
static int smu_v11_0_wait_for_response(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- uint32_t cur_value, i;
+ uint32_t cur_value, i, timeout = adev->usec_timeout * 10;
- for (i = 0; i < adev->usec_timeout; i++) {
+ for (i = 0; i < timeout; i++) {
cur_value = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
if ((cur_value & MP1_C2PMSG_90__CONTENT_MASK) != 0)
break;
@@ -77,7 +78,7 @@ static int smu_v11_0_wait_for_response(struct smu_context *smu)
}
/* timeout means wrong logic */
- if (i == adev->usec_timeout)
+ if (i == timeout)
return -ETIME;
return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90) == 0x1 ? 0 : -EIO;
@@ -1088,7 +1089,7 @@ static int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
uint32_t *value)
{
int ret = 0;
- uint32_t freq;
+ uint32_t freq = 0;
if (clk_id >= SMU_CLK_COUNT || !value)
return -EINVAL;
@@ -1642,6 +1643,92 @@ static int smu_v11_0_set_azalia_d3_pme(struct smu_context *smu)
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);
+}
+
+static 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);
+ baco_support = smu_baco->platform_support;
+ mutex_unlock(&smu_baco->mutex);
+
+ if (!baco_support)
+ return false;
+
+ if (!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;
+}
+
+static enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu)
+{
+ struct smu_baco_context *smu_baco = &smu->smu_baco;
+ enum smu_baco_state baco_state = SMU_BACO_STATE_EXIT;
+
+ mutex_lock(&smu_baco->mutex);
+ baco_state = smu_baco->state;
+ mutex_unlock(&smu_baco->mutex);
+
+ return baco_state;
+}
+
+static 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;
+ int ret = 0;
+
+ if (smu_v11_0_baco_get_state(smu) == state)
+ return 0;
+
+ mutex_lock(&smu_baco->mutex);
+
+ if (state == SMU_BACO_STATE_ENTER)
+ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, BACO_SEQ_BACO);
+ else
+ ret = smu_send_smc_msg(smu, SMU_MSG_ExitBaco);
+ if (ret)
+ goto out;
+
+ smu_baco->state = state;
+out:
+ mutex_unlock(&smu_baco->mutex);
+ return ret;
+}
+
+static int smu_v11_0_baco_reset(struct smu_context *smu)
+{
+ int ret = 0;
+
+ ret = smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO);
+ if (ret)
+ return ret;
+
+ ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_ENTER);
+ if (ret)
+ return ret;
+
+ msleep(10);
+
+ ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_EXIT);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
static const struct smu_funcs smu_v11_0_funcs = {
.init_microcode = smu_v11_0_init_microcode,
.load_microcode = smu_v11_0_load_microcode,
@@ -1690,6 +1777,10 @@ static const struct smu_funcs smu_v11_0_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_get_state = smu_v11_0_baco_get_state,
+ .baco_set_state = smu_v11_0_baco_set_state,
+ .baco_reset = smu_v11_0_baco_reset,
};
void smu_v11_0_set_smu_funcs(struct smu_context *smu)