summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLikun Gao <Likun.Gao@amd.com>2025-03-13 14:36:35 +0800
committerAlex Deucher <alexander.deucher@amd.com>2026-04-24 10:57:02 -0400
commit9e09187b6b6aaffe2a862b87811f892eadf4e4ca (patch)
tree55a0b7e7a0fd654c0a42ebc07c71e0fa08c27ebe /drivers
parent44101a4a415abe2b95d731248e3a307312743a61 (diff)
drm/amdgpu: add doorbell range function for nbio v6_3_2
Add doorbell range and ih control related function for NBIO version 6.3.2. v2: squash in doorbell range fixes v3: squash in xcd doorbell fix Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v6_3_2.c201
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc_v1_0.c2
2 files changed, 203 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_3_2.c b/drivers/gpu/drm/amd/amdgpu/nbio_v6_3_2.c
index c21e5d2fe839..5e8f466f23ad 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_3_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_3_2.c
@@ -71,6 +71,13 @@ static void nbio_v6_3_2_mc_access_enable(struct amdgpu_device *adev,
WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN, 0);
}
+static void nbio_v6_3_2_init_registers(struct amdgpu_device *adev)
+{
+ WREG32_SOC15(NBIO, 0, regXCD_DOORBELL_FENCE_1,
+ (0xff & ~(adev->gfx.xcc_mask)) <<
+ XCD_DOORBELL_FENCE_1__XCD_0_DOORBELL_DISABLE__SHIFT);
+}
+
static u32 nbio_v6_3_2_get_memsize(struct amdgpu_device *adev)
{
return RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF0_RCC_CONFIG_MEMSIZE);
@@ -114,6 +121,194 @@ static void nbio_v6_3_2_enable_doorbell_interrupt(struct amdgpu_device *adev,
DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1);
}
+static void nbio_v6_3_2_ih_control(struct amdgpu_device *adev)
+{
+ u32 interrupt_cntl;
+
+ /* setup interrupt control */
+ WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL2, adev->dummy_page_addr >> 8);
+
+ interrupt_cntl = RREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL);
+ /*
+ * BIF_BX0_INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=0 - dummy read disabled with msi, enabled without msi
+ * BIF_BX0_INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK=1 - dummy read controlled by IH_DUMMY_RD_EN
+ */
+ interrupt_cntl = REG_SET_FIELD(interrupt_cntl, BIF_BX0_INTERRUPT_CNTL,
+ IH_DUMMY_RD_OVERRIDE, 0);
+
+ /* BIF_BX0_INTERRUPT_CNTL__IH_REQ_NONSNOOP_EN_MASK=1 if ring is in non-cacheable memory, e.g., vram */
+ interrupt_cntl = REG_SET_FIELD(interrupt_cntl, BIF_BX0_INTERRUPT_CNTL,
+ IH_REQ_NONSNOOP_EN, 0);
+
+ WREG32_SOC15(NBIO, 0, regBIF_BX0_INTERRUPT_CNTL, interrupt_cntl);
+}
+
+static void nbio_v6_3_2_ih_doorbell_range(struct amdgpu_device *adev,
+ bool use_doorbell, int doorbell_index)
+{
+ u32 ih_doorbell_range = 0;
+ u32 ih_doorbell_range1 = 0;
+
+ if (use_doorbell) {
+ ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL,
+ S2A_DOORBELL_PORT1_ENABLE,
+ 0x1);
+ ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL,
+ S2A_DOORBELL_PORT1_AWID,
+ 0x0);
+ ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL,
+ S2A_DOORBELL_PORT1_RANGE_OFFSET,
+ doorbell_index);
+ ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL,
+ S2A_DOORBELL_PORT1_RANGE_SIZE,
+ 8);
+ ih_doorbell_range = REG_SET_FIELD(ih_doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL,
+ S2A_DOORBELL_PORT1_AWADDR_31_28_VALUE,
+ 0x0);
+ ih_doorbell_range1 = REG_SET_FIELD(ih_doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1,
+ S2A_DOORBELL_PORT1_TARGET_PORT_TYPE,
+ 0x3);
+ ih_doorbell_range1 = REG_SET_FIELD(ih_doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1,
+ S2A_DOORBELL_PORT1_TARGET_DIEID,
+ 0x0);
+ ih_doorbell_range1 = REG_SET_FIELD(ih_doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1,
+ S2A_DOORBELL_PORT1_TARGET_PORT_ID,
+ 0x0);
+ }
+
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL, ih_doorbell_range);
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_1_CTRL1, ih_doorbell_range1);
+}
+
+static void nbio_v6_3_2_gc_doorbell_init(struct amdgpu_device *adev)
+{
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL, 0x30000007);
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_0_CTRL1, 0x3);
+}
+
+static void nbio_v6_3_2_sdma_doorbell_range(struct amdgpu_device *adev,
+ int instance, bool use_doorbell,
+ int doorbell_index,
+ int doorbell_size)
+{
+ if (instance == 0) {
+ u32 doorbell_range = 0;
+ u32 doorbell_range1 = 0;
+
+ if (use_doorbell) {
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL,
+ S2A_DOORBELL_PORT6_ENABLE,
+ 0x1);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL,
+ S2A_DOORBELL_PORT6_AWID,
+ 0xe);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL,
+ S2A_DOORBELL_PORT6_RANGE_OFFSET,
+ doorbell_index);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL,
+ S2A_DOORBELL_PORT6_RANGE_SIZE,
+ doorbell_size);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL,
+ S2A_DOORBELL_PORT6_AWADDR_31_28_VALUE,
+ 0xe);
+ doorbell_range1 = REG_SET_FIELD(doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL1,
+ S2A_DOORBELL_PORT6_TARGET_PORT_TYPE,
+ 0x3);
+ doorbell_range1 = REG_SET_FIELD(doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL1,
+ S2A_DOORBELL_PORT6_TARGET_DIEID,
+ 0x0);
+ doorbell_range1 = REG_SET_FIELD(doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL1,
+ S2A_DOORBELL_PORT6_TARGET_PORT_ID,
+ 0x0);
+ }
+
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL, doorbell_range);
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_6_CTRL1, doorbell_range1);
+ }
+}
+
+static void nbio_v6_3_2_vcn_doorbell_range(struct amdgpu_device *adev,
+ bool use_doorbell, int doorbell_index,
+ int instance)
+{
+ u32 doorbell_range = 0;
+ u32 doorbell_range1 = 0;
+
+ if (use_doorbell) {
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL,
+ S2A_DOORBELL_PORT2_ENABLE,
+ 0x1);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL,
+ S2A_DOORBELL_PORT2_AWID,
+ (instance % adev->vcn.num_inst_per_aid) ? 0x7 : 0x4);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL,
+ S2A_DOORBELL_PORT2_RANGE_OFFSET,
+ doorbell_index);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL,
+ S2A_DOORBELL_PORT2_RANGE_SIZE,
+ 8);
+ doorbell_range = REG_SET_FIELD(doorbell_range,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL,
+ S2A_DOORBELL_PORT2_AWADDR_31_28_VALUE,
+ (instance % adev->vcn.num_inst_per_aid) ? 0x7 : 0x4);
+ doorbell_range1 = REG_SET_FIELD(doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1,
+ S2A_DOORBELL_PORT2_TARGET_PORT_TYPE,
+ 0x3);
+ doorbell_range1 = REG_SET_FIELD(doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1,
+ S2A_DOORBELL_PORT2_TARGET_DIEID,
+ (instance / adev->vcn.num_inst_per_aid) ? 0x3 : 0x0);
+ doorbell_range1 = REG_SET_FIELD(doorbell_range1,
+ GDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1,
+ S2A_DOORBELL_PORT2_TARGET_PORT_ID,
+ 0x0);
+ }
+
+ switch (instance) {
+ case 0:
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL, doorbell_range);
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_2_CTRL1, doorbell_range1);
+ break;
+ case 1:
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL, doorbell_range);
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_3_CTRL1, doorbell_range1);
+ break;
+ case 2:
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL, doorbell_range);
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_4_CTRL1, doorbell_range1);
+ break;
+ case 3:
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL, doorbell_range);
+ WREG32_SOC15(NBIO, 0, regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1, doorbell_range1);
+ break;
+ default:
+ dev_err(adev->dev,
+ "amdgpu: invalid vcn instance set when program doorbell range\n");
+ break;
+ }
+}
+
static int nbio_v6_3_2_get_compute_partition_mode(struct amdgpu_device *adev)
{
u32 tmp, px;
@@ -165,4 +360,10 @@ const struct amdgpu_nbio_funcs nbio_v6_3_2_funcs = {
.get_compute_partition_mode = nbio_v6_3_2_get_compute_partition_mode,
.get_memory_partition_mode = nbio_v6_3_2_get_memory_partition_mode,
.is_nps_switch_requested = nbio_v6_3_2_is_nps_switch_requested,
+ .ih_control = nbio_v6_3_2_ih_control,
+ .ih_doorbell_range = nbio_v6_3_2_ih_doorbell_range,
+ .gc_doorbell_init = nbio_v6_3_2_gc_doorbell_init,
+ .sdma_doorbell_range = nbio_v6_3_2_sdma_doorbell_range,
+ .vcn_doorbell_range = nbio_v6_3_2_vcn_doorbell_range,
+ .init_registers = nbio_v6_3_2_init_registers,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c
index 709b1669b07b..d06953c237ed 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c
@@ -330,6 +330,8 @@ static int soc_v1_0_common_early_init(struct amdgpu_ip_block *ip_block)
return -EINVAL;
}
+ adev->nbio.funcs->init_registers(adev);
+
return 0;
}