From b55c83a7438da50126e6a2c98dcf4476ce2fd0fd Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Fri, 21 Jun 2019 10:49:22 -0500 Subject: [PATCH] drm/amd/powerplay: implement smc firmware v2.1 for smu11 1.add smc_firmware_header_v2_1 hfirmware support, support more pptable in smc firmware. 2.optimization current pptable load framework. 3.rename read_pptable_from_vbios with setup_pptable. Signed-off-by: Kevin Wang Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 13 +++ drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2 +- .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 6 +- drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 93 +++++++++++++------ 4 files changed, 84 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index 9b096228a02f..eaafea87aa3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -56,6 +56,19 @@ struct smc_firmware_header_v2_0 { uint32_t ppt_size_bytes; /* soft pptable size */ }; +struct smc_soft_pptable_entry { + uint32_t id; + uint32_t ppt_offset_bytes; + uint32_t ppt_size_bytes; +}; + +/* version_major=2, version_minor=1 */ +struct smc_firmware_header_v2_1 { + struct smc_firmware_header_v1_0 v1_0; + uint32_t pptable_count; + uint32_t pptable_entry_offset; +}; + /* version_major=1, version_minor=0 */ struct psp_firmware_header_v1_0 { struct common_firmware_header header; diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index b9b56ec1aacf..2de67e16e5e3 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -633,7 +633,7 @@ static int smu_smc_table_hw_init(struct smu_context *smu, if (ret) return ret; - ret = smu_read_pptable_from_vbios(smu); + ret = smu_setup_pptable(smu); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 73d70eaa837e..350380065535 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -486,7 +486,7 @@ struct smu_funcs int (*fini_power)(struct smu_context *smu); int (*load_microcode)(struct smu_context *smu); int (*check_fw_status)(struct smu_context *smu); - int (*read_pptable_from_vbios)(struct smu_context *smu); + int (*setup_pptable)(struct smu_context *smu); int (*get_vbios_bootup_values)(struct smu_context *smu); int (*get_clk_info_from_vbios)(struct smu_context *smu); int (*check_pptable)(struct smu_context *smu); @@ -570,8 +570,8 @@ struct smu_funcs ((smu)->funcs->load_microcode ? (smu)->funcs->load_microcode((smu)) : 0) #define smu_check_fw_status(smu) \ ((smu)->funcs->check_fw_status ? (smu)->funcs->check_fw_status((smu)) : 0) -#define smu_read_pptable_from_vbios(smu) \ - ((smu)->funcs->read_pptable_from_vbios ? (smu)->funcs->read_pptable_from_vbios((smu)) : 0) +#define smu_setup_pptable(smu) \ + ((smu)->funcs->setup_pptable ? (smu)->funcs->setup_pptable((smu)) : 0) #define smu_get_vbios_bootup_values(smu) \ ((smu)->funcs->get_vbios_bootup_values ? (smu)->funcs->get_vbios_bootup_values((smu)) : 0) #define smu_get_clk_info_from_vbios(smu) \ diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index a358bbd8159c..7e09d1ff2050 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -143,18 +143,6 @@ smu_v11_0_send_msg_with_param(struct smu_context *smu, uint16_t msg, return ret; } -static void smu_v11_0_init_smu_ext_microcode(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - const struct smc_firmware_header_v2_0 *v2; - - v2 = (const struct smc_firmware_header_v2_0 *) adev->pm.fw->data; - - smu->ppt_offset_bytes = le32_to_cpu(v2->ppt_offset_bytes); - smu->ppt_size_bytes = le32_to_cpu(v2->ppt_size_bytes); - smu->ppt_start_addr = (uint8_t *)v2 + smu->ppt_offset_bytes; -} - static int smu_v11_0_init_microcode(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -164,7 +152,6 @@ static int smu_v11_0_init_microcode(struct smu_context *smu) const struct smc_firmware_header_v1_0 *hdr; const struct common_firmware_header *header; struct amdgpu_firmware_info *ucode = NULL; - uint32_t version_major, version_minor; switch (adev->asic_type) { case CHIP_VEGA20: @@ -190,11 +177,6 @@ static int smu_v11_0_init_microcode(struct smu_context *smu) amdgpu_ucode_print_smc_hdr(&hdr->header); adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version); - version_major = le16_to_cpu(hdr->header.header_version_major); - version_minor = le16_to_cpu(hdr->header.header_version_minor); - if (version_major == 2 && version_minor == 0) - smu_v11_0_init_smu_ext_microcode(smu); /* with soft pptable */ - if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC]; ucode->ucode_id = AMDGPU_UCODE_ID_SMC; @@ -293,22 +275,82 @@ static int smu_v11_0_check_fw_version(struct smu_context *smu) return ret; } -static int smu_v11_0_read_pptable_from_vbios(struct smu_context *smu) +static int smu_v11_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t ppt_offset_bytes; + const struct smc_firmware_header_v2_0 *v2; + + v2 = (const struct smc_firmware_header_v2_0 *) adev->pm.fw->data; + + ppt_offset_bytes = le32_to_cpu(v2->ppt_offset_bytes); + *size = le32_to_cpu(v2->ppt_size_bytes); + *table = (uint8_t *)v2 + ppt_offset_bytes; + + return 0; +} + +static int smu_v11_0_set_pptable_v2_1(struct smu_context *smu, void **table, uint32_t *size, uint32_t pptable_id) +{ + struct amdgpu_device *adev = smu->adev; + const struct smc_firmware_header_v2_1 *v2_1; + struct smc_soft_pptable_entry *entries; + uint32_t pptable_count = 0; + int i = 0; + + v2_1 = (const struct smc_firmware_header_v2_1 *) adev->pm.fw->data; + entries = (struct smc_soft_pptable_entry *) + ((uint8_t *)v2_1 + le32_to_cpu(v2_1->pptable_entry_offset)); + pptable_count = le32_to_cpu(v2_1->pptable_count); + for (i = 0; i < pptable_count; i++) { + if (le32_to_cpu(entries[i].id) == pptable_id) { + *table = ((uint8_t *)v2_1 + le32_to_cpu(entries[i].ppt_offset_bytes)); + *size = le32_to_cpu(entries[i].ppt_size_bytes); + break; + } + } + + if (i == pptable_count) + return -EINVAL; + + return 0; +} + +static int smu_v11_0_setup_pptable(struct smu_context *smu) { + struct amdgpu_device *adev = smu->adev; + const struct smc_firmware_header_v1_0 *hdr; int ret, index; - uint16_t size; + uint32_t size; uint8_t frev, crev; void *table; + uint16_t version_major, version_minor; + + 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) { + switch (version_minor) { + case 0: + ret = smu_v11_0_set_pptable_v2_0(smu, &table, &size); + break; + case 1: + ret = smu_v11_0_set_pptable_v2_1(smu, &table, &size, + smu->smu_table.boot_values.pp_table_id); + break; + default: + ret = -EINVAL; + break; + } + if (ret) + return ret; - if (smu->smu_table.boot_values.pp_table_id > 0 && smu->ppt_start_addr) { - /* load soft pptable */ - table = (void *)smu->ppt_start_addr; - size= smu->ppt_size_bytes; } else { index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, powerplayinfo); - ret = smu_get_atom_data_table(smu, index, &size, &frev, &crev, + ret = smu_get_atom_data_table(smu, index, (uint16_t *)&size, &frev, &crev, (uint8_t **)&table); if (ret) return ret; @@ -1836,7 +1878,6 @@ static const struct smu_funcs smu_v11_0_funcs = { .send_smc_msg = smu_v11_0_send_msg, .send_smc_msg_with_param = smu_v11_0_send_msg_with_param, .read_smc_arg = smu_v11_0_read_arg, - .read_pptable_from_vbios = smu_v11_0_read_pptable_from_vbios, .setup_pptable = smu_v11_0_setup_pptable, .init_smc_tables = smu_v11_0_init_smc_tables, .fini_smc_tables = smu_v11_0_fini_smc_tables, -- 2.30.2