drm/amdgpu: revise init_rlc_save_restore_list behavior to support latest register_lis...
authorHuang Rui <ray.huang@amd.com>
Thu, 21 Dec 2017 08:13:02 +0000 (16:13 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 15 May 2018 18:43:37 +0000 (13:43 -0500)
RLC save/restore list will be used on CGPG and GFXOFF function, it loads two bin
table of register_list_format/register_restore in RLC firmware.

Signed-off-by: Huang Rui <ray.huang@amd.com>
Acked-by: Hawking Zhang <Hawking.Zhang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c

index eff1fd14b01fe8198ea55b50fb6fc1d1693808dd..3abd91f27e316c9b1409014182174928aa3861a2 100644 (file)
@@ -184,6 +184,30 @@ static const struct soc15_reg_golden golden_settings_gc_9_2_1_vg12[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x01bd9f33, 0x01000000)
 };
 
+static const u32 GFX_RLC_SRM_INDEX_CNTL_ADDR_OFFSETS[] =
+{
+       mmRLC_SRM_INDEX_CNTL_ADDR_0 - mmRLC_SRM_INDEX_CNTL_ADDR_0,
+       mmRLC_SRM_INDEX_CNTL_ADDR_1 - mmRLC_SRM_INDEX_CNTL_ADDR_0,
+       mmRLC_SRM_INDEX_CNTL_ADDR_2 - mmRLC_SRM_INDEX_CNTL_ADDR_0,
+       mmRLC_SRM_INDEX_CNTL_ADDR_3 - mmRLC_SRM_INDEX_CNTL_ADDR_0,
+       mmRLC_SRM_INDEX_CNTL_ADDR_4 - mmRLC_SRM_INDEX_CNTL_ADDR_0,
+       mmRLC_SRM_INDEX_CNTL_ADDR_5 - mmRLC_SRM_INDEX_CNTL_ADDR_0,
+       mmRLC_SRM_INDEX_CNTL_ADDR_6 - mmRLC_SRM_INDEX_CNTL_ADDR_0,
+       mmRLC_SRM_INDEX_CNTL_ADDR_7 - mmRLC_SRM_INDEX_CNTL_ADDR_0,
+};
+
+static const u32 GFX_RLC_SRM_INDEX_CNTL_DATA_OFFSETS[] =
+{
+       mmRLC_SRM_INDEX_CNTL_DATA_0 - mmRLC_SRM_INDEX_CNTL_DATA_0,
+       mmRLC_SRM_INDEX_CNTL_DATA_1 - mmRLC_SRM_INDEX_CNTL_DATA_0,
+       mmRLC_SRM_INDEX_CNTL_DATA_2 - mmRLC_SRM_INDEX_CNTL_DATA_0,
+       mmRLC_SRM_INDEX_CNTL_DATA_3 - mmRLC_SRM_INDEX_CNTL_DATA_0,
+       mmRLC_SRM_INDEX_CNTL_DATA_4 - mmRLC_SRM_INDEX_CNTL_DATA_0,
+       mmRLC_SRM_INDEX_CNTL_DATA_5 - mmRLC_SRM_INDEX_CNTL_DATA_0,
+       mmRLC_SRM_INDEX_CNTL_DATA_6 - mmRLC_SRM_INDEX_CNTL_DATA_0,
+       mmRLC_SRM_INDEX_CNTL_DATA_7 - mmRLC_SRM_INDEX_CNTL_DATA_0,
+};
+
 #define VEGA10_GB_ADDR_CONFIG_GOLDEN 0x2a114042
 #define VEGA12_GB_ADDR_CONFIG_GOLDEN 0x24104041
 #define RAVEN_GB_ADDR_CONFIG_GOLDEN 0x24000042
@@ -1763,55 +1787,42 @@ static void gfx_v9_0_init_csb(struct amdgpu_device *adev)
                        adev->gfx.rlc.clear_state_size);
 }
 
-static void gfx_v9_0_parse_ind_reg_list(int *register_list_format,
+static void gfx_v9_1_parse_ind_reg_list(int *register_list_format,
                                int indirect_offset,
                                int list_size,
                                int *unique_indirect_regs,
                                int *unique_indirect_reg_count,
-                               int max_indirect_reg_count,
                                int *indirect_start_offsets,
-                               int *indirect_start_offsets_count,
-                               int max_indirect_start_offsets_count)
+                               int *indirect_start_offsets_count)
 {
        int idx;
-       bool new_entry = true;
 
        for (; indirect_offset < list_size; indirect_offset++) {
+               indirect_start_offsets[*indirect_start_offsets_count] = indirect_offset;
+               *indirect_start_offsets_count = *indirect_start_offsets_count + 1;
 
-               if (new_entry) {
-                       new_entry = false;
-                       indirect_start_offsets[*indirect_start_offsets_count] = indirect_offset;
-                       *indirect_start_offsets_count = *indirect_start_offsets_count + 1;
-                       BUG_ON(*indirect_start_offsets_count >= max_indirect_start_offsets_count);
-               }
+               while (register_list_format[indirect_offset] != 0xFFFFFFFF) {
+                       indirect_offset += 2;
 
-               if (register_list_format[indirect_offset] == 0xFFFFFFFF) {
-                       new_entry = true;
-                       continue;
-               }
+                       /* look for the matching indice */
+                       for (idx = 0; idx < *unique_indirect_reg_count; idx++) {
+                               if (unique_indirect_regs[idx] ==
+                                       register_list_format[indirect_offset] ||
+                                       !unique_indirect_regs[idx])
+                                       break;
+                       }
 
-               indirect_offset += 2;
+                       BUG_ON(idx >= *unique_indirect_reg_count);
 
-               /* look for the matching indice */
-               for (idx = 0; idx < *unique_indirect_reg_count; idx++) {
-                       if (unique_indirect_regs[idx] ==
-                               register_list_format[indirect_offset])
-                               break;
-               }
+                       if (!unique_indirect_regs[idx])
+                               unique_indirect_regs[idx] = register_list_format[indirect_offset];
 
-               if (idx >= *unique_indirect_reg_count) {
-                       unique_indirect_regs[*unique_indirect_reg_count] =
-                               register_list_format[indirect_offset];
-                       idx = *unique_indirect_reg_count;
-                       *unique_indirect_reg_count = *unique_indirect_reg_count + 1;
-                       BUG_ON(*unique_indirect_reg_count >= max_indirect_reg_count);
+                       indirect_offset++;
                }
-
-               register_list_format[indirect_offset] = idx;
        }
 }
 
-static int gfx_v9_0_init_rlc_save_restore_list(struct amdgpu_device *adev)
+static int gfx_v9_1_init_rlc_save_restore_list(struct amdgpu_device *adev)
 {
        int unique_indirect_regs[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
        int unique_indirect_reg_count = 0;
@@ -1820,7 +1831,7 @@ static int gfx_v9_0_init_rlc_save_restore_list(struct amdgpu_device *adev)
        int indirect_start_offsets_count = 0;
 
        int list_size = 0;
-       int i = 0;
+       int i = 0, j = 0;
        u32 tmp = 0;
 
        u32 *register_list_format =
@@ -1831,15 +1842,14 @@ static int gfx_v9_0_init_rlc_save_restore_list(struct amdgpu_device *adev)
                adev->gfx.rlc.reg_list_format_size_bytes);
 
        /* setup unique_indirect_regs array and indirect_start_offsets array */
-       gfx_v9_0_parse_ind_reg_list(register_list_format,
-                               adev->gfx.rlc.reg_list_format_direct_reg_list_length,
-                               adev->gfx.rlc.reg_list_format_size_bytes >> 2,
-                               unique_indirect_regs,
-                               &unique_indirect_reg_count,
-                               ARRAY_SIZE(unique_indirect_regs),
-                               indirect_start_offsets,
-                               &indirect_start_offsets_count,
-                               ARRAY_SIZE(indirect_start_offsets));
+       unique_indirect_reg_count = ARRAY_SIZE(unique_indirect_regs);
+       gfx_v9_1_parse_ind_reg_list(register_list_format,
+                                   adev->gfx.rlc.reg_list_format_direct_reg_list_length,
+                                   adev->gfx.rlc.reg_list_format_size_bytes >> 2,
+                                   unique_indirect_regs,
+                                   &unique_indirect_reg_count,
+                                   indirect_start_offsets,
+                                   &indirect_start_offsets_count);
 
        /* enable auto inc in case it is disabled */
        tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_CNTL));
@@ -1853,19 +1863,37 @@ static int gfx_v9_0_init_rlc_save_restore_list(struct amdgpu_device *adev)
                WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_ARAM_DATA),
                        adev->gfx.rlc.register_restore[i]);
 
-       /* load direct register */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_ARAM_ADDR), 0);
-       for (i = 0; i < adev->gfx.rlc.reg_list_size_bytes >> 2; i++)
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_ARAM_DATA),
-                       adev->gfx.rlc.register_restore[i]);
-
        /* load indirect register */
        WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_SCRATCH_ADDR),
                adev->gfx.rlc.reg_list_format_start);
-       for (i = 0; i < adev->gfx.rlc.reg_list_format_size_bytes >> 2; i++)
+
+       /* direct register portion */
+       for (i = 0; i < adev->gfx.rlc.reg_list_format_direct_reg_list_length; i++)
                WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_SCRATCH_DATA),
                        register_list_format[i]);
 
+       /* indirect register portion */
+       while (i < (adev->gfx.rlc.reg_list_format_size_bytes >> 2)) {
+               if (register_list_format[i] == 0xFFFFFFFF) {
+                       WREG32_SOC15(GC, 0, mmRLC_GPM_SCRATCH_DATA, register_list_format[i++]);
+                       continue;
+               }
+
+               WREG32_SOC15(GC, 0, mmRLC_GPM_SCRATCH_DATA, register_list_format[i++]);
+               WREG32_SOC15(GC, 0, mmRLC_GPM_SCRATCH_DATA, register_list_format[i++]);
+
+               for (j = 0; j < unique_indirect_reg_count; j++) {
+                       if (register_list_format[i] == unique_indirect_regs[j]) {
+                               WREG32_SOC15(GC, 0, mmRLC_GPM_SCRATCH_DATA, j);
+                               break;
+                       }
+               }
+
+               BUG_ON(j >= unique_indirect_reg_count);
+
+               i++;
+       }
+
        /* set save/restore list size */
        list_size = adev->gfx.rlc.reg_list_size_bytes >> 2;
        list_size = list_size >> 1;
@@ -1878,14 +1906,19 @@ static int gfx_v9_0_init_rlc_save_restore_list(struct amdgpu_device *adev)
                adev->gfx.rlc.starting_offsets_start);
        for (i = 0; i < ARRAY_SIZE(indirect_start_offsets); i++)
                WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_SCRATCH_DATA),
-                       indirect_start_offsets[i]);
+                      indirect_start_offsets[i]);
 
        /* load unique indirect regs*/
        for (i = 0; i < ARRAY_SIZE(unique_indirect_regs); i++) {
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_INDEX_CNTL_ADDR_0) + i,
-                       unique_indirect_regs[i] & 0x3FFFF);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_INDEX_CNTL_DATA_0) + i,
-                       unique_indirect_regs[i] >> 20);
+               if (unique_indirect_regs[i] != 0) {
+                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_INDEX_CNTL_ADDR_0)
+                              + GFX_RLC_SRM_INDEX_CNTL_ADDR_OFFSETS[i],
+                              unique_indirect_regs[i] & 0x3FFFF);
+
+                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_INDEX_CNTL_DATA_0)
+                              + GFX_RLC_SRM_INDEX_CNTL_DATA_OFFSETS[i],
+                              unique_indirect_regs[i] >> 20);
+               }
        }
 
        kfree(register_list_format);
@@ -2075,7 +2108,7 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev)
                              AMD_PG_SUPPORT_GDS |
                              AMD_PG_SUPPORT_RLC_SMU_HS)) {
                gfx_v9_0_init_csb(adev);
-               gfx_v9_0_init_rlc_save_restore_list(adev);
+               gfx_v9_1_init_rlc_save_restore_list(adev);
                gfx_v9_0_enable_save_restore_machine(adev);
 
                WREG32(mmRLC_JUMP_TABLE_RESTORE,