drm/amdgpu: add TOC firmware support for apu (v3)
authorHuang Rui <ray.huang@amd.com>
Thu, 27 Aug 2020 21:33:32 +0000 (17:33 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 5 Oct 2020 19:15:28 +0000 (15:15 -0400)
APU needs load toc firmware for gfx10 series on psp front door loading.

v2: rebase against latest code
v3: clarify error message

Signed-off-by: Huang Rui <ray.huang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c

index a5aaff15f7ec052d3d4310ad00e98e8833461fa3..011c36e317ec4d1290b280db6ec61780909d00ef 100644 (file)
@@ -325,6 +325,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
                fw_info->ver = adev->dm.dmcub_fw_version;
                fw_info->feature = 0;
                break;
+       case AMDGPU_INFO_FW_TOC:
+               fw_info->ver = adev->psp.toc_fw_version;
+               fw_info->feature = adev->psp.toc_feature_version;
+               break;
        default:
                return -EINVAL;
        }
@@ -1466,6 +1470,13 @@ static int amdgpu_debugfs_firmware_info(struct seq_file *m, void *data)
        seq_printf(m, "DMCUB feature version: %u, firmware version: 0x%08x\n",
                   fw_info.feature, fw_info.ver);
 
+       /* TOC */
+       query_fw.fw_type = AMDGPU_INFO_FW_TOC;
+       ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
+       if (ret)
+               return ret;
+       seq_printf(m, "TOC feature version: %u, firmware version: 0x%08x\n",
+                  fw_info.feature, fw_info.ver);
 
        seq_printf(m, "VBIOS version: %s\n", ctx->vbios_version);
 
index 18be544d8c1ea28b2e789af2edaf06f0b925f881..62ae7b4ff275747368540a2489fee6ad25c828dd 100644 (file)
@@ -2415,6 +2415,42 @@ out:
        return err;
 }
 
+int psp_init_toc_microcode(struct psp_context *psp,
+                          const char *chip_name)
+{
+       struct amdgpu_device *adev = psp->adev;
+       char fw_name[30];
+       const struct psp_firmware_header_v1_0 *toc_hdr;
+       int err = 0;
+
+       if (!chip_name) {
+               dev_err(adev->dev, "invalid chip name for toc microcode\n");
+               return -EINVAL;
+       }
+
+       snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name);
+       err = request_firmware(&adev->psp.toc_fw, fw_name, adev->dev);
+       if (err)
+               goto out;
+
+       err = amdgpu_ucode_validate(adev->psp.toc_fw);
+       if (err)
+               goto out;
+
+       toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data;
+       adev->psp.toc_fw_version = le32_to_cpu(toc_hdr->header.ucode_version);
+       adev->psp.toc_feature_version = le32_to_cpu(toc_hdr->ucode_feature_version);
+       adev->psp.toc_bin_size = le32_to_cpu(toc_hdr->header.ucode_size_bytes);
+       adev->psp.toc_start_addr = (uint8_t *)toc_hdr +
+                               le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes);
+       return 0;
+out:
+       dev_err(adev->dev, "fail to request/validate toc microcode\n");
+       release_firmware(adev->psp.toc_fw);
+       adev->psp.toc_fw = NULL;
+       return err;
+}
+
 int psp_init_sos_microcode(struct psp_context *psp,
                           const char *chip_name)
 {
index 919d2fb7427b151358e4aea2be1c33a5e41355c5..13f56618660ad82d3560ffd7e52806c5c6c282b6 100644 (file)
@@ -253,6 +253,11 @@ struct psp_context
        uint32_t                        asd_ucode_size;
        uint8_t                         *asd_start_addr;
 
+       /* toc firmware */
+       const struct firmware           *toc_fw;
+       uint32_t                        toc_fw_version;
+       uint32_t                        toc_feature_version;
+
        /* fence buffer */
        struct amdgpu_bo                *fence_buf_bo;
        uint64_t                        fence_buf_mc_addr;
@@ -386,6 +391,8 @@ int psp_ring_cmd_submit(struct psp_context *psp,
                        int index);
 int psp_init_asd_microcode(struct psp_context *psp,
                           const char *chip_name);
+int psp_init_toc_microcode(struct psp_context *psp,
+                          const char *chip_name);
 int psp_init_sos_microcode(struct psp_context *psp,
                           const char *chip_name);
 int psp_init_ta_microcode(struct psp_context *psp,
index 6c5d9612abcb6dea02e46b36bd20f79267a02ced..f2d6b2518eee205454132bbf75d786b9a7d23538 100644 (file)
@@ -109,20 +109,16 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
                BUG();
        }
 
-       err = psp_init_sos_microcode(psp, chip_name);
-       if (err)
-               return err;
-
-       if (adev->asic_type != CHIP_SIENNA_CICHLID &&
-           adev->asic_type != CHIP_NAVY_FLOUNDER) {
-               err = psp_init_asd_microcode(psp, chip_name);
-               if (err)
-                       return err;
-       }
 
        switch (adev->asic_type) {
        case CHIP_VEGA20:
        case CHIP_ARCTURUS:
+               err = psp_init_sos_microcode(psp, chip_name);
+               if (err)
+                       return err;
+               err = psp_init_asd_microcode(psp, chip_name);
+               if (err)
+                       return err;
                snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
                err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
                if (err) {
@@ -150,6 +146,12 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
        case CHIP_NAVI10:
        case CHIP_NAVI14:
        case CHIP_NAVI12:
+               err = psp_init_sos_microcode(psp, chip_name);
+               if (err)
+                       return err;
+               err = psp_init_asd_microcode(psp, chip_name);
+               if (err)
+                       return err;
                if (amdgpu_sriov_vf(adev))
                        break;
                snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
@@ -180,10 +182,21 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
                break;
        case CHIP_SIENNA_CICHLID:
        case CHIP_NAVY_FLOUNDER:
+               err = psp_init_sos_microcode(psp, chip_name);
+               if (err)
+                       return err;
                err = psp_init_ta_microcode(&adev->psp, chip_name);
                if (err)
                        return err;
                break;
+       case CHIP_VANGOGH:
+               err = psp_init_asd_microcode(psp, chip_name);
+               if (err)
+                       return err;
+               err = psp_init_toc_microcode(psp, chip_name);
+               if (err)
+                       return err;
+               break;
        default:
                BUG();
        }