drm/radeon/cik: Read back SDMA WPTR register after writing it
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / radeon / cik_sdma.c
index 8e9d0f1d858ef56d4038ab1361f339a2ba593f8f..db8ce30ff31ff7cbe222211c54dac68fa089020b 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/firmware.h>
 #include <drm/drmP.h>
 #include "radeon.h"
+#include "radeon_ucode.h"
 #include "radeon_asic.h"
 #include "radeon_trace.h"
 #include "cikd.h"
@@ -118,6 +119,7 @@ void cik_sdma_set_wptr(struct radeon_device *rdev,
                reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
 
        WREG32(reg, (ring->wptr << 2) & 0x3fffc);
+       (void)RREG32(reg);
 }
 
 /**
@@ -419,7 +421,6 @@ static int cik_sdma_rlc_resume(struct radeon_device *rdev)
  */
 static int cik_sdma_load_microcode(struct radeon_device *rdev)
 {
-       const __be32 *fw_data;
        int i;
 
        if (!rdev->sdma_fw)
@@ -428,19 +429,48 @@ static int cik_sdma_load_microcode(struct radeon_device *rdev)
        /* halt the MEs */
        cik_sdma_enable(rdev, false);
 
-       /* sdma0 */
-       fw_data = (const __be32 *)rdev->sdma_fw->data;
-       WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
-       for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
-               WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++));
-       WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
-
-       /* sdma1 */
-       fw_data = (const __be32 *)rdev->sdma_fw->data;
-       WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
-       for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
-               WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++));
-       WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+       if (rdev->new_fw) {
+               const struct sdma_firmware_header_v1_0 *hdr =
+                       (const struct sdma_firmware_header_v1_0 *)rdev->sdma_fw->data;
+               const __le32 *fw_data;
+               u32 fw_size;
+
+               radeon_ucode_print_sdma_hdr(&hdr->header);
+
+               /* sdma0 */
+               fw_data = (const __le32 *)
+                       (rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+               fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+               WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
+               for (i = 0; i < fw_size; i++)
+                       WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, le32_to_cpup(fw_data++));
+               WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+
+               /* sdma1 */
+               fw_data = (const __le32 *)
+                       (rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+               fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+               WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
+               for (i = 0; i < fw_size; i++)
+                       WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, le32_to_cpup(fw_data++));
+               WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+       } else {
+               const __be32 *fw_data;
+
+               /* sdma0 */
+               fw_data = (const __be32 *)rdev->sdma_fw->data;
+               WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
+               for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
+                       WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++));
+               WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+
+               /* sdma1 */
+               fw_data = (const __be32 *)rdev->sdma_fw->data;
+               WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
+               for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
+                       WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++));
+               WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+       }
 
        WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
        WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
@@ -742,7 +772,7 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
 
        trace_radeon_vm_set_page(pe, addr, count, incr, flags);
 
-       if (flags == R600_PTE_GART) {
+       if ((flags & R600_PTE_GART_MASK) == R600_PTE_GART_MASK) {
                uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8;
                while (count) {
                        unsigned bytes = count * 8;