[PATCH] drm/amdgpu/gfx10: add workaround for register aliasing bug

Alex Deucher alexdeucher at gmail.com
Thu Sep 19 15:03:42 UTC 2019


We need a special programming sequence for updating
mmUTCL1_CGTT_CLK_CTRL golden settings.

Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 96 +++++++++++++++++++++-----
 1 file changed, 78 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index db28823891ac..24f5e928e7b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -353,32 +353,92 @@ static void gfx_v10_0_set_kiq_pm4_funcs(struct amdgpu_device *adev)
 	adev->gfx.kiq.pmf = &gfx_v10_0_kiq_pm4_funcs;
 }
 
+/**
+ * gfx_v10_0_program_register_sequence - program an array of registers.
+ *
+ * @adev: amdgpu_device pointer
+ * @regs: pointer to the register array
+ * @array_size: size of the register array
+ *
+ * Programs an array or registers with and and or masks.
+ * This is a helper for setting golden registers.
+ */
+
+static void gfx_v10_0_program_register_sequence(struct amdgpu_device *adev,
+						const struct soc15_reg_golden *regs,
+						const u32 array_size)
+{
+	const struct soc15_reg_golden *entry;
+	u32 tmp, reg, gcrd = 0;
+	int i;
+
+	for (i = 0; i < array_size; ++i) {
+		entry = &regs[i];
+		reg =  adev->reg_offset[entry->hwip][entry->instance][entry->segment] + entry->reg;
+
+		if (adev->asic_type == CHIP_NAVI10 ||
+		    adev->asic_type == CHIP_NAVI14 ||
+		    adev->asic_type == CHIP_NAVI12) {
+			/* Navi1x has an aliasing bug between these two registers.
+			 * Writes to mmUTCL1_CGTT_CLK_CTRL will change both
+			 * mmUTCL1_CGTT_CLK_CTRL and mmGCRD_SA_TARGETS_DISABLE.
+			 * Reads from mmUTCL1_CGTT_CLK_CTRL will have incorrect data
+			 * if mmGCRD_SA_TARGETS_DISABLE is non-0. Reads and writes
+			 * from/to mmGCRD_SA_TARGETS_DISABLE will be correct.
+			 */
+			if (reg == SOC15_REG_OFFSET(GC, 0, mmUTCL1_CGTT_CLK_CTRL)) {
+				gcrd = RREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE);
+				WREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE, 0);
+			}
+		}
+
+		if (entry->and_mask == 0xffffffff) {
+			tmp = entry->or_mask;
+		} else {
+			tmp = RREG32(reg);
+			tmp &= ~(entry->and_mask);
+			tmp |= (entry->or_mask & entry->and_mask);
+		}
+
+		WREG32(reg, tmp);
+
+		if (adev->asic_type == CHIP_NAVI10 ||
+		    adev->asic_type == CHIP_NAVI14 ||
+		    adev->asic_type == CHIP_NAVI12) {
+			if (reg == SOC15_REG_OFFSET(GC, 0, mmUTCL1_CGTT_CLK_CTRL)) {
+				WREG32_SOC15(GC, 0, mmGCRD_SA_TARGETS_DISABLE, gcrd);
+			}
+		}
+	}
+
+}
+
 static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev)
 {
 	switch (adev->asic_type) {
 	case CHIP_NAVI10:
-		soc15_program_register_sequence(adev,
-						golden_settings_gc_10_1,
-						(const u32)ARRAY_SIZE(golden_settings_gc_10_1));
-		soc15_program_register_sequence(adev,
-						golden_settings_gc_10_0_nv10,
-						(const u32)ARRAY_SIZE(golden_settings_gc_10_0_nv10));
+		gfx_v10_0_program_register_sequence(adev,
+						    golden_settings_gc_10_1,
+						    (const u32)ARRAY_SIZE(golden_settings_gc_10_1));
+		gfx_v10_0_program_register_sequence(adev,
+						    golden_settings_gc_10_0_nv10,
+						    (const u32)ARRAY_SIZE(golden_settings_gc_10_0_nv10));
 		break;
 	case CHIP_NAVI14:
-		soc15_program_register_sequence(adev,
-						golden_settings_gc_10_1_1,
-						(const u32)ARRAY_SIZE(golden_settings_gc_10_1_1));
-		soc15_program_register_sequence(adev,
-						golden_settings_gc_10_1_nv14,
-						(const u32)ARRAY_SIZE(golden_settings_gc_10_1_nv14));
+		gfx_v10_0_program_register_sequence(adev,
+						    golden_settings_gc_10_1_1,
+						    (const u32)ARRAY_SIZE(golden_settings_gc_10_1_1));
+		gfx_v10_0_program_register_sequence(adev,
+						    golden_settings_gc_10_1_nv14,
+						    (const u32)ARRAY_SIZE(golden_settings_gc_10_1_nv14));
 		break;
 	case CHIP_NAVI12:
-		soc15_program_register_sequence(adev,
-						golden_settings_gc_10_1_2,
-						(const u32)ARRAY_SIZE(golden_settings_gc_10_1_2));
-		soc15_program_register_sequence(adev,
-						golden_settings_gc_10_1_2_nv12,
-						(const u32)ARRAY_SIZE(golden_settings_gc_10_1_2_nv12));
+		gfx_v10_0_program_register_sequence(adev,
+						    golden_settings_gc_10_1_2,
+						    (const u32)ARRAY_SIZE(golden_settings_gc_10_1_2));
+		gfx_v10_0_program_register_sequence(adev,
+						    golden_settings_gc_10_1_2_nv12,
+						    (const u32)ARRAY_SIZE(golden_settings_gc_10_1_2_nv12));
 		break;
 	default:
 		break;
-- 
2.20.1



More information about the amd-gfx mailing list