drm/amdgpu: Added support for loading auxiliary PSP FW
authorJohn Clements <john.clements@amd.com>
Wed, 9 Jun 2021 05:34:38 +0000 (13:34 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 10 Jun 2021 15:44:24 +0000 (11:44 -0400)
In the case with xgmi connected to cpu load alternate psp fw

Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: John Clements <john.clements@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c

index 8838f542c18936151150e87e5a8bf9553c1fd3de..2570c2908b25554b91871991a1d51d6ad40c90c3 100644 (file)
@@ -2797,6 +2797,48 @@ out:
        return err;
 }
 
+static int psp_init_sos_base_fw(struct amdgpu_device *adev)
+{
+       const struct psp_firmware_header_v1_0 *sos_hdr;
+       const struct psp_firmware_header_v1_3 *sos_hdr_v1_3;
+
+       sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data;
+
+       if (adev->gmc.xgmi.connected_to_cpu || (adev->asic_type != CHIP_ALDEBARAN)) {
+               adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
+               adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->sos.fw_version);
+
+               adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos.offset_bytes);
+               adev->psp.sys_start_addr = (uint8_t *)sos_hdr +
+                               le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
+
+               adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos.size_bytes);
+               adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+                               le32_to_cpu(sos_hdr->sos.offset_bytes);
+       } else {
+               /* Load alternate PSP SOS FW */
+               sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data;
+
+               adev->psp.sos_fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
+               adev->psp.sos_feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
+
+               adev->psp.sys_bin_size = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes);
+               adev->psp.sys_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+                       le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes);
+
+               adev->psp.sos_bin_size = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes);
+               adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+                       le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes);
+       }
+
+       if ((adev->psp.sys_bin_size == 0) || (adev->psp.sos_bin_size == 0)) {
+               dev_warn(adev->dev, "PSP SOS FW not available");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 int psp_init_sos_microcode(struct psp_context *psp,
                           const char *chip_name)
 {
@@ -2827,14 +2869,10 @@ int psp_init_sos_microcode(struct psp_context *psp,
 
        switch (sos_hdr->header.header_version_major) {
        case 1:
-               adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
-               adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->sos.fw_version);
-               adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos.size_bytes);
-               adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos.offset_bytes);
-               adev->psp.sys_start_addr = (uint8_t *)sos_hdr +
-                               le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
-               adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr +
-                               le32_to_cpu(sos_hdr->sos.offset_bytes);
+               err = psp_init_sos_base_fw(adev);
+               if (err)
+                       goto out;
+
                if (sos_hdr->header.header_version_minor == 1) {
                        sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data;
                        adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes);