Commit d719cef3 authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/radeon: update rlc programming sequence on SI



This is required for certain power management features.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8ba10463
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
@@ -4418,14 +4418,93 @@ int si_rlc_init(struct radeon_device *rdev)
	return 0;
}

static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
					 bool enable)
{
	u32 tmp = RREG32(CP_INT_CNTL_RING0);
	u32 mask;
	int i;

	if (enable)
		tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
	else
		tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
	WREG32(CP_INT_CNTL_RING0, tmp);

	if (!enable) {
		/* read a gfx register */
		tmp = RREG32(DB_DEPTH_INFO);

		mask = RLC_BUSY_STATUS | GFX_POWER_STATUS | GFX_CLOCK_STATUS | GFX_LS_STATUS;
		for (i = 0; i < rdev->usec_timeout; i++) {
			if ((RREG32(RLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS))
				break;
			udelay(1);
		}
	}
}

static void si_wait_for_rlc_serdes(struct radeon_device *rdev)
{
	int i;

	for (i = 0; i < rdev->usec_timeout; i++) {
		if (RREG32(RLC_SERDES_MASTER_BUSY_0) == 0)
			break;
		udelay(1);
	}

	for (i = 0; i < rdev->usec_timeout; i++) {
		if (RREG32(RLC_SERDES_MASTER_BUSY_1) == 0)
			break;
		udelay(1);
	}
}

static void si_rlc_stop(struct radeon_device *rdev)
{
	WREG32(RLC_CNTL, 0);

	si_enable_gui_idle_interrupt(rdev, false);

	si_wait_for_rlc_serdes(rdev);
}

static void si_rlc_start(struct radeon_device *rdev)
{
	WREG32(RLC_CNTL, RLC_ENABLE);

	si_enable_gui_idle_interrupt(rdev, true);

	udelay(50);
}

static bool si_lbpw_supported(struct radeon_device *rdev)
{
	u32 tmp;

	/* Enable LBPW only for DDR3 */
	tmp = RREG32(MC_SEQ_MISC0);
	if ((tmp & 0xF0000000) == 0xB0000000)
		return true;
	return false;
}

static void si_enable_lbpw(struct radeon_device *rdev, bool enable)
{
	u32 tmp;

	tmp = RREG32(RLC_LB_CNTL);
	if (enable)
		tmp |= LOAD_BALANCE_ENABLE;
	else
		tmp &= ~LOAD_BALANCE_ENABLE;
	WREG32(RLC_LB_CNTL, tmp);

	if (!enable) {
		si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
		WREG32(SPI_LB_CU_MASK, 0x00ff);
	}
}

static int si_rlc_resume(struct radeon_device *rdev)
@@ -4443,6 +4522,7 @@ static int si_rlc_resume(struct radeon_device *rdev)
	WREG32(RLC_LB_CNTL, 0);
	WREG32(RLC_LB_CNTR_MAX, 0xffffffff);
	WREG32(RLC_LB_CNTR_INIT, 0);
	WREG32(RLC_LB_INIT_CU_MASK, 0xffffffff);

	WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
	WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
@@ -4457,6 +4537,8 @@ static int si_rlc_resume(struct radeon_device *rdev)
	}
	WREG32(RLC_UCODE_ADDR, 0);

	si_enable_lbpw(rdev, si_lbpw_supported(rdev));

	si_rlc_start(rdev);

	return 0;
+17 −0
Original line number Diff line number Diff line
@@ -275,6 +275,8 @@
#define MC_IO_PAD_CNTL_D0           			0x29d0
#define		MEM_FALL_OUT_CMD      			(1 << 8)

#define MC_SEQ_MISC0           				0x2a00

#define MC_SEQ_IO_DEBUG_INDEX           		0x2a44
#define MC_SEQ_IO_DEBUG_DATA           			0x2a48

@@ -638,6 +640,8 @@
#define		TCC_DISABLE_MASK				0xFFFF0000
#define		TCC_DISABLE_SHIFT				16

#define	SPI_LB_CU_MASK					0x9354

#define	TA_CNTL_AUX					0x9508

#define CC_RB_BACKEND_DISABLE				0x98F4
@@ -790,6 +794,7 @@
#define RLC_RL_BASE                                       0xC304
#define RLC_RL_SIZE                                       0xC308
#define RLC_LB_CNTL                                       0xC30C
#       define LOAD_BALANCE_ENABLE                        (1 << 0)
#define RLC_SAVE_AND_RESTORE_BASE                         0xC310
#define RLC_LB_CNTR_MAX                                   0xC314
#define RLC_LB_CNTR_INIT                                  0xC318
@@ -804,6 +809,18 @@
#define RLC_CAPTURE_GPU_CLOCK_COUNT                       0xC340
#define RLC_MC_CNTL                                       0xC344
#define RLC_UCODE_CNTL                                    0xC348
#define RLC_STAT                                          0xC34C
#       define RLC_BUSY_STATUS                            (1 << 0)
#       define GFX_POWER_STATUS                           (1 << 1)
#       define GFX_CLOCK_STATUS                           (1 << 2)
#       define GFX_LS_STATUS                              (1 << 3)

#define RLC_LB_INIT_CU_MASK                               0xC41C

#define RLC_SERDES_MASTER_BUSY_0                          0xC464
#define RLC_SERDES_MASTER_BUSY_1                          0xC468

#define DB_DEPTH_INFO                                   0x2803c

#define PA_SC_RASTER_CONFIG                             0x28350
#       define RASTER_CONFIG_RB_MAP_0                   0