diff options
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.c | 140 |
1 files changed, 123 insertions, 17 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 2380759ddf48..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 @@ -62,6 +62,7 @@ MODULE_FIRMWARE("amdgpu/navi14_smc.bin"); MODULE_FIRMWARE("amdgpu/navi12_smc.bin"); MODULE_FIRMWARE("amdgpu/sienna_cichlid_smc.bin"); MODULE_FIRMWARE("amdgpu/navy_flounder_smc.bin"); +MODULE_FIRMWARE("amdgpu/dimgrey_cavefish_smc.bin"); #define SMU11_VOLTAGE_SCALE 4 @@ -84,12 +85,17 @@ int smu_v11_0_init_microcode(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; const char *chip_name; - char fw_name[30]; + char fw_name[SMU_FW_NAME_LEN]; int err = 0; const struct smc_firmware_header_v1_0 *hdr; 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"; @@ -109,6 +115,9 @@ int smu_v11_0_init_microcode(struct smu_context *smu) case CHIP_NAVY_FLOUNDER: chip_name = "navy_flounder"; break; + case CHIP_DIMGREY_CAVEFISH: + chip_name = "dimgrey_cavefish"; + break; default: dev_err(adev->dev, "Unsupported ASIC type %d\n", adev->asic_type); return -EINVAL; @@ -212,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; @@ -224,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: @@ -244,6 +256,12 @@ int smu_v11_0_check_fw_version(struct smu_context *smu) case CHIP_NAVY_FLOUNDER: smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder; break; + case CHIP_VANGOGH: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_VANGOGH; + break; + case CHIP_DIMGREY_CAVEFISH: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish; + break; default: dev_err(smu->adev->dev, "smu unsupported asic type:%d.\n", smu->adev->asic_type); smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV; @@ -326,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_NAVY_FLOUNDER) { + 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: @@ -425,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; @@ -456,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; } @@ -540,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: @@ -555,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; @@ -592,6 +613,11 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu) (uint8_t)SMU11_SYSPLL1_2_ID, &smu->smu_table.boot_values.fclk); + smu_v11_0_atom_get_smu_clockinfo(smu->adev, + (uint8_t)SMU11_SYSPLL3_1_LCLK_ID, + (uint8_t)SMU11_SYSPLL3_1_ID, + &smu->smu_table.boot_values.lclk); + return 0; } @@ -699,8 +725,11 @@ int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count) { struct amdgpu_device *adev = smu->adev; - /* Navy_Flounder do not support to change display num currently */ - if (adev->asic_type == CHIP_NAVY_FLOUNDER) + /* Navy_Flounder/Dimgrey_Cavefish do not support to change + * display num currently + */ + if (adev->asic_type >= CHIP_NAVY_FLOUNDER && + adev->asic_type <= CHIP_DIMGREY_CAVEFISH) return 0; return smu_cmn_send_smc_msg_with_param(smu, @@ -907,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__); @@ -919,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)) { @@ -926,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__); @@ -1068,6 +1118,7 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable) case CHIP_NAVI12: case CHIP_SIENNA_CICHLID: case CHIP_NAVY_FLOUNDER: + case CHIP_DIMGREY_CAVEFISH: if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) @@ -1164,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), @@ -1462,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; @@ -1476,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) @@ -1977,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) { @@ -2002,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) { |