]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
drm/amdgpu/psp11: simplify the ucode register logic
[linux.git] / drivers / gpu / drm / amd / amdgpu / psp_v11_0.c
index b91df7bd1d98e56350246f66c11029294bf40978..61744e2d16fbc5cb82a4b44ddfb45d72f5840ac1 100644 (file)
@@ -21,6 +21,8 @@
  */
 
 #include <linux/firmware.h>
+#include <linux/module.h>
+
 #include "amdgpu.h"
 #include "amdgpu_psp.h"
 #include "amdgpu_ucode.h"
 MODULE_FIRMWARE("amdgpu/vega20_sos.bin");
 MODULE_FIRMWARE("amdgpu/vega20_asd.bin");
 MODULE_FIRMWARE("amdgpu/vega20_ta.bin");
+MODULE_FIRMWARE("amdgpu/navi10_sos.bin");
+MODULE_FIRMWARE("amdgpu/navi10_asd.bin");
 
 /* address block */
 #define smnMP1_FIRMWARE_FLAGS          0x3010024
+/* navi10 reg offset define */
+#define mmRLC_GPM_UCODE_ADDR_NV10      0x5b61
+#define mmRLC_GPM_UCODE_DATA_NV10      0x5b62
+#define mmSDMA0_UCODE_ADDR_NV10                0x5880
+#define mmSDMA0_UCODE_DATA_NV10                0x5881
 
 static int psp_v11_0_init_microcode(struct psp_context *psp)
 {
@@ -50,6 +59,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
        char fw_name[30];
        int err = 0;
        const struct psp_firmware_header_v1_0 *sos_hdr;
+       const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
        const struct psp_firmware_header_v1_0 *asd_hdr;
        const struct ta_firmware_header_v1_0 *ta_hdr;
 
@@ -59,6 +69,9 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
        case CHIP_VEGA20:
                chip_name = "vega20";
                break;
+       case CHIP_NAVI10:
+               chip_name = "navi10";
+               break;
        default:
                BUG();
        }
@@ -73,15 +86,31 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
                goto out;
 
        sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data;
-       adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
-       adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->ucode_feature_version);
-       adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos_size_bytes);
-       adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->header.ucode_size_bytes) -
-                                       le32_to_cpu(sos_hdr->sos_size_bytes);
-       adev->psp.sys_start_addr = (uint8_t *)sos_hdr +
+       amdgpu_ucode_print_psp_hdr(&sos_hdr->header);
+
+       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->ucode_feature_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 +
+               adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr +
                                le32_to_cpu(sos_hdr->sos_offset_bytes);
+               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);
+                       adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr +
+                                       le32_to_cpu(sos_hdr_v1_1->toc_offset_bytes);
+               }
+               break;
+       default:
+               dev_err(adev->dev,
+                       "Unsupported psp sos firmware\n");
+               err = -EINVAL;
+               goto out;
+       }
 
        snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name);
        err = request_firmware(&adev->psp.asd_fw, fw_name, adev->dev);
@@ -99,30 +128,36 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
        adev->psp.asd_start_addr = (uint8_t *)asd_hdr +
                                le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes);
 
-       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) {
-               release_firmware(adev->psp.ta_fw);
-               adev->psp.ta_fw = NULL;
-               dev_info(adev->dev,
-                        "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
-       } else {
-               err = amdgpu_ucode_validate(adev->psp.ta_fw);
-               if (err)
-                       goto out2;
-
-               ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
-               adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
-               adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
-               adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
-                       le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
-
-               adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
-
-               adev->psp.ta_ras_ucode_version = le32_to_cpu(ta_hdr->ta_ras_ucode_version);
-               adev->psp.ta_ras_ucode_size = le32_to_cpu(ta_hdr->ta_ras_size_bytes);
-               adev->psp.ta_ras_start_addr = (uint8_t *)adev->psp.ta_xgmi_start_addr +
-                       le32_to_cpu(ta_hdr->ta_ras_offset_bytes);
+       switch (adev->asic_type) {
+       case CHIP_VEGA20:
+               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) {
+                       release_firmware(adev->psp.ta_fw);
+                       adev->psp.ta_fw = NULL;
+                       dev_info(adev->dev,
+                                "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
+               } else {
+                       err = amdgpu_ucode_validate(adev->psp.ta_fw);
+                       if (err)
+                               goto out2;
+
+                       ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
+                       adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
+                       adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
+                       adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
+                               le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+                       adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
+                       adev->psp.ta_ras_ucode_version = le32_to_cpu(ta_hdr->ta_ras_ucode_version);
+                       adev->psp.ta_ras_ucode_size = le32_to_cpu(ta_hdr->ta_ras_size_bytes);
+                       adev->psp.ta_ras_start_addr = (uint8_t *)adev->psp.ta_xgmi_start_addr +
+                               le32_to_cpu(ta_hdr->ta_ras_offset_bytes);
+               }
+               break;
+       case CHIP_NAVI10:
+               break;
+       default:
+               BUG();
        }
 
        return 0;
@@ -499,14 +534,24 @@ psp_v11_0_sram_map(struct amdgpu_device *adev,
 
        case AMDGPU_UCODE_ID_RLC_G:
                *sram_offset = 0x2000;
-               *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR);
-               *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_DATA);
+               if (adev->asic_type < CHIP_NAVI10) {
+                       *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR);
+                       *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_DATA);
+               } else {
+                       *sram_addr_reg_offset = adev->reg_offset[GC_HWIP][0][1] + mmRLC_GPM_UCODE_ADDR_NV10;
+                       *sram_data_reg_offset = adev->reg_offset[GC_HWIP][0][1] + mmRLC_GPM_UCODE_DATA_NV10;
+               }
                break;
 
        case AMDGPU_UCODE_ID_SDMA0:
                *sram_offset = 0x0;
-               *sram_addr_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_ADDR);
-               *sram_data_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_DATA);
+               if (adev->asic_type < CHIP_NAVI10) {
+                       *sram_addr_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_ADDR);
+                       *sram_data_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_DATA);
+               } else {
+                       *sram_addr_reg_offset = adev->reg_offset[GC_HWIP][0][1] + mmSDMA0_UCODE_ADDR_NV10;
+                       *sram_data_reg_offset = adev->reg_offset[GC_HWIP][0][1] + mmSDMA0_UCODE_DATA_NV10;
+               }
                break;
 
 /* TODO: needs to confirm */
@@ -770,6 +815,11 @@ static int psp_v11_0_ras_cure_posion(struct psp_context *psp, uint64_t *mode_ptr
 #endif
 }
 
+static int psp_v11_0_rlc_autoload_start(struct psp_context *psp)
+{
+       return psp_rlc_autoload_start(psp);
+}
+
 static const struct psp_funcs psp_v11_0_funcs = {
        .init_microcode = psp_v11_0_init_microcode,
        .bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv,
@@ -788,6 +838,7 @@ static const struct psp_funcs psp_v11_0_funcs = {
        .support_vmr_ring = psp_v11_0_support_vmr_ring,
        .ras_trigger_error = psp_v11_0_ras_trigger_error,
        .ras_cure_posion = psp_v11_0_ras_cure_posion,
+       .rlc_autoload_start = psp_v11_0_rlc_autoload_start,
 };
 
 void psp_v11_0_set_psp_funcs(struct psp_context *psp)