aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c')
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c115
1 files changed, 101 insertions, 14 deletions
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index b6453ee6f8e6..b279dbbbce6b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -91,6 +91,11 @@ int smu_v11_0_init_microcode(struct smu_context *smu)
const struct common_firmware_header *header;
struct amdgpu_firmware_info *ucode = NULL;
+ if (amdgpu_sriov_vf(adev) &&
+ ((adev->asic_type == CHIP_NAVI12) ||
+ (adev->asic_type == CHIP_SIENNA_CICHLID)))
+ return 0;
+
switch (adev->asic_type) {
case CHIP_ARCTURUS:
chip_name = "arcturus";
@@ -216,6 +221,7 @@ int smu_v11_0_check_fw_status(struct smu_context *smu)
int smu_v11_0_check_fw_version(struct smu_context *smu)
{
+ struct amdgpu_device *adev = smu->adev;
uint32_t if_version = 0xff, smu_version = 0xff;
uint16_t smu_major;
uint8_t smu_minor, smu_debug;
@@ -228,6 +234,8 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
smu_major = (smu_version >> 16) & 0xffff;
smu_minor = (smu_version >> 8) & 0xff;
smu_debug = (smu_version >> 0) & 0xff;
+ if (smu->is_apu)
+ adev->pm.fw_version = smu_version;
switch (smu->adev->asic_type) {
case CHIP_ARCTURUS:
@@ -336,8 +344,7 @@ 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) ||
- adev->asic_type == CHIP_DIMGREY_CAVEFISH) {
+ if (version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) {
dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id);
switch (version_minor) {
case 0:
@@ -435,11 +442,13 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu)
kfree(smu_table->overdrive_table);
kfree(smu_table->max_sustainable_clocks);
kfree(smu_table->driver_pptable);
+ kfree(smu_table->clocks_table);
smu_table->gpu_metrics_table = NULL;
smu_table->boot_overdrive_table = NULL;
smu_table->overdrive_table = NULL;
smu_table->max_sustainable_clocks = NULL;
smu_table->driver_pptable = NULL;
+ smu_table->clocks_table = NULL;
kfree(smu_table->hardcode_pptable);
smu_table->hardcode_pptable = NULL;
@@ -466,11 +475,11 @@ int smu_v11_0_init_power(struct smu_context *smu)
{
struct smu_power_context *smu_power = &smu->smu_power;
- smu_power->power_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
+ smu_power->power_context = kzalloc(sizeof(struct smu_11_0_power_context),
GFP_KERNEL);
if (!smu_power->power_context)
return -ENOMEM;
- smu_power->power_context_size = sizeof(struct smu_11_0_dpm_context);
+ smu_power->power_context_size = sizeof(struct smu_11_0_power_context);
return 0;
}
@@ -550,6 +559,7 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
smu->smu_table.boot_values.vdd_gfx = v_3_1->bootup_vddgfx_mv;
smu->smu_table.boot_values.cooling_id = v_3_1->coolingsolution_id;
smu->smu_table.boot_values.pp_table_id = 0;
+ smu->smu_table.boot_values.firmware_caps = v_3_1->firmware_capability;
break;
case 3:
default:
@@ -565,6 +575,7 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
smu->smu_table.boot_values.vdd_gfx = v_3_3->bootup_vddgfx_mv;
smu->smu_table.boot_values.cooling_id = v_3_3->coolingsolution_id;
smu->smu_table.boot_values.pp_table_id = v_3_3->pplib_pptable_id;
+ smu->smu_table.boot_values.firmware_caps = v_3_3->firmware_capability;
}
smu->smu_table.boot_values.format_revision = header->format_revision;
@@ -925,9 +936,13 @@ int smu_v11_0_get_current_power_limit(struct smu_context *smu,
if (power_src < 0)
return -EINVAL;
+ /*
+ * BIT 24-31: ControllerId (only PPT0 is supported for now)
+ * BIT 16-23: PowerSource
+ */
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_GetPptLimit,
- power_src << 16,
+ (0 << 24) | (power_src << 16),
power_limit);
if (ret)
dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
@@ -937,6 +952,7 @@ 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 power_src;
int ret = 0;
if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
@@ -944,6 +960,22 @@ int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
return -EOPNOTSUPP;
}
+ power_src = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_PWR,
+ smu->adev->pm.ac_power ?
+ SMU_POWER_SOURCE_AC :
+ SMU_POWER_SOURCE_DC);
+ if (power_src < 0)
+ return -EINVAL;
+
+ /*
+ * BIT 24-31: ControllerId (only PPT0 is supported for now)
+ * BIT 16-23: PowerSource
+ * BIT 0-15: PowerLimit
+ */
+ n &= 0xFFFF;
+ n |= 0 << 24;
+ n |= (power_src) << 16;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n, NULL);
if (ret) {
dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
@@ -1183,7 +1215,12 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
if (ret)
return ret;
- crystal_clock_freq = amdgpu_asic_get_xclk(adev);
+ /*
+ * crystal_clock_freq div by 4 is required since the fan control
+ * module refers to 25MHz
+ */
+
+ crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
@@ -1481,6 +1518,9 @@ enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu)
return baco_state;
}
+#define D3HOT_BACO_SEQUENCE 0
+#define D3HOT_BAMACO_SEQUENCE 2
+
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;
@@ -1495,15 +1535,34 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
mutex_lock(&smu_baco->mutex);
if (state == SMU_BACO_STATE_ENTER) {
- if (!ras || !ras->supported) {
- data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
- data |= 0x80000000;
- WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
-
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
- } else {
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL);
+ switch (adev->asic_type) {
+ case CHIP_SIENNA_CICHLID:
+ case CHIP_NAVY_FLOUNDER:
+ case CHIP_DIMGREY_CAVEFISH:
+ if (amdgpu_runtime_pm == 2)
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_EnterBaco,
+ D3HOT_BAMACO_SEQUENCE,
+ NULL);
+ else
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_EnterBaco,
+ D3HOT_BACO_SEQUENCE,
+ NULL);
+ break;
+ default:
+ if (!ras || !ras->supported) {
+ data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
+ data |= 0x80000000;
+ WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
+ } else {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL);
+ }
+ break;
}
+
} else {
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL);
if (ret)
@@ -1996,6 +2055,18 @@ void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics)
gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
}
+void smu_v11_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics)
+{
+ memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0));
+
+ gpu_metrics->common_header.structure_size =
+ sizeof(struct gpu_metrics_v2_0);
+ gpu_metrics->common_header.format_revision = 2;
+ gpu_metrics->common_header.content_revision = 0;
+
+ gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
+}
+
int smu_v11_0_gfx_ulv_control(struct smu_context *smu,
bool enablement)
{
@@ -2021,6 +2092,22 @@ int smu_v11_0_deep_sleep_control(struct smu_context *smu,
}
}
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_UCLK_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_UCLK_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s UCLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_FCLK_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_FCLK_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s FCLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_SOCCLK_BIT)) {
ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_SOCCLK_BIT, enablement);
if (ret) {