[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 = ®s[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