drm/amd/powerplay: enable backdoor smu fw loading (v2)
authorKenneth Feng <kenneth.feng@amd.com>
Sat, 2 Feb 2019 03:43:12 +0000 (11:43 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 21 Jun 2019 23:59:24 +0000 (18:59 -0500)
enable backdoor smu fw loading on navi10

v2: squash in define fix (Alex)

Signed-off-by: Kenneth Feng <kenneth.feng@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
drivers/gpu/drm/amd/powerplay/smu_v11_0.c

index 02c965d64256f63c80640a3155d36f2f48614da9..cd5e66b82ce1b39f79b986cb48f70c03c0a3ab62 100644 (file)
@@ -30,6 +30,7 @@
 #define MP0_SRAM                       0x03900000
 #define MP1_Public                     0x03b00000
 #define MP1_SRAM                       0x03c00004
+#define MP1_SMC_SIZE           0x40000
 
 /* address block */
 #define smnMP1_FIRMWARE_FLAGS          0x3010024
index 4dcbf6ee7e8ef40d07f644382eff0ba2940613ee..2d55b825497f8383d0b7cd1a52dcca58ae5b3b20 100644 (file)
@@ -207,6 +207,39 @@ out:
 
 static int smu_v11_0_load_microcode(struct smu_context *smu)
 {
+       struct amdgpu_device *adev = smu->adev;
+       const uint32_t *src;
+       const struct smc_firmware_header_v1_0 *hdr;
+       uint32_t addr_start = MP1_SRAM;
+       uint32_t i;
+       uint32_t mp1_fw_flags;
+
+       hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
+       src = (const uint32_t *)(adev->pm.fw->data +
+               le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+
+       for (i = 1; i < MP1_SMC_SIZE/4 - 1; i++) {
+               WREG32_PCIE(addr_start, src[i]);
+               addr_start += 4;
+       }
+
+       WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff),
+               1 & MP1_SMN_PUB_CTRL__RESET_MASK);
+       WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff),
+               1 & ~MP1_SMN_PUB_CTRL__RESET_MASK);
+
+       for (i = 0; i < adev->usec_timeout; i++) {
+               mp1_fw_flags = RREG32_PCIE(MP1_Public |
+                       (smnMP1_FIRMWARE_FLAGS & 0xffffffff));
+               if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
+                       MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
+                       break;
+               udelay(1);
+       }
+
+       if (i == adev->usec_timeout)
+               return -ETIME;
+
        return 0;
 }