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>
This commit is contained in:
Likun Gao
2025-03-13 14:36:35 +08:00
committed by Alex Deucher
parent 44101a4a41
commit 9e09187b6b
2 changed files with 203 additions and 0 deletions

View File

@@ -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,
};

View File

@@ -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;
}