diff mbox

[017/165] drm/radeon: Add support for RLC init on CIK (v4)

Message ID 1372253045-17042-18-git-send-email-alexdeucher@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Alex Deucher June 26, 2013, 1:21 p.m. UTC
From: Alex Deucher <alexander.deucher@amd.com>

RLC handles the interrupt controller and other tasks
on the GPU.

v2: add documentation
v3: update programming sequence
v4: additional setup

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/radeon/cik.c  |  142 +++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/cikd.h |   47 ++++++++++++++
 2 files changed, 189 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index ba242eb..a44ede6 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -2777,3 +2777,145 @@  void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
 	radeon_ring_write(ring, 0x0);
 }
 
+/*
+ * RLC
+ * The RLC is a multi-purpose microengine that handles a
+ * variety of functions, the most important of which is
+ * the interrupt controller.
+ */
+/**
+ * cik_rlc_stop - stop the RLC ME
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Halt the RLC ME (MicroEngine) (CIK).
+ */
+static void cik_rlc_stop(struct radeon_device *rdev)
+{
+	int i, j, k;
+	u32 mask, tmp;
+
+	tmp = RREG32(CP_INT_CNTL_RING0);
+	tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+	WREG32(CP_INT_CNTL_RING0, tmp);
+
+	RREG32(CB_CGTT_SCLK_CTRL);
+	RREG32(CB_CGTT_SCLK_CTRL);
+	RREG32(CB_CGTT_SCLK_CTRL);
+	RREG32(CB_CGTT_SCLK_CTRL);
+
+	tmp = RREG32(RLC_CGCG_CGLS_CTRL) & 0xfffffffc;
+	WREG32(RLC_CGCG_CGLS_CTRL, tmp);
+
+	WREG32(RLC_CNTL, 0);
+
+	for (i = 0; i < rdev->config.cik.max_shader_engines; i++) {
+		for (j = 0; j < rdev->config.cik.max_sh_per_se; j++) {
+			cik_select_se_sh(rdev, i, j);
+			for (k = 0; k < rdev->usec_timeout; k++) {
+				if (RREG32(RLC_SERDES_CU_MASTER_BUSY) == 0)
+					break;
+				udelay(1);
+			}
+		}
+	}
+	cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
+
+	mask = SE_MASTER_BUSY_MASK | GC_MASTER_BUSY | TC0_MASTER_BUSY | TC1_MASTER_BUSY;
+	for (k = 0; k < rdev->usec_timeout; k++) {
+		if ((RREG32(RLC_SERDES_NONCU_MASTER_BUSY) & mask) == 0)
+			break;
+		udelay(1);
+	}
+}
+
+/**
+ * cik_rlc_start - start the RLC ME
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Unhalt the RLC ME (MicroEngine) (CIK).
+ */
+static void cik_rlc_start(struct radeon_device *rdev)
+{
+	u32 tmp;
+
+	WREG32(RLC_CNTL, RLC_ENABLE);
+
+	tmp = RREG32(CP_INT_CNTL_RING0);
+	tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+	WREG32(CP_INT_CNTL_RING0, tmp);
+
+	udelay(50);
+}
+
+/**
+ * cik_rlc_resume - setup the RLC hw
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Initialize the RLC registers, load the ucode,
+ * and start the RLC (CIK).
+ * Returns 0 for success, -EINVAL if the ucode is not available.
+ */
+static int cik_rlc_resume(struct radeon_device *rdev)
+{
+	u32 i, size;
+	u32 clear_state_info[3];
+	const __be32 *fw_data;
+
+	if (!rdev->rlc_fw)
+		return -EINVAL;
+
+	switch (rdev->family) {
+	case CHIP_BONAIRE:
+	default:
+		size = BONAIRE_RLC_UCODE_SIZE;
+		break;
+	case CHIP_KAVERI:
+		size = KV_RLC_UCODE_SIZE;
+		break;
+	case CHIP_KABINI:
+		size = KB_RLC_UCODE_SIZE;
+		break;
+	}
+
+	cik_rlc_stop(rdev);
+
+	WREG32(GRBM_SOFT_RESET, SOFT_RESET_RLC);
+	RREG32(GRBM_SOFT_RESET);
+	udelay(50);
+	WREG32(GRBM_SOFT_RESET, 0);
+	RREG32(GRBM_SOFT_RESET);
+	udelay(50);
+
+	WREG32(RLC_LB_CNTR_INIT, 0);
+	WREG32(RLC_LB_CNTR_MAX, 0x00008000);
+
+	cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
+	WREG32(RLC_LB_INIT_CU_MASK, 0xffffffff);
+	WREG32(RLC_LB_PARAMS, 0x00600408);
+	WREG32(RLC_LB_CNTL, 0x80000004);
+
+	WREG32(RLC_MC_CNTL, 0);
+	WREG32(RLC_UCODE_CNTL, 0);
+
+	fw_data = (const __be32 *)rdev->rlc_fw->data;
+		WREG32(RLC_GPM_UCODE_ADDR, 0);
+	for (i = 0; i < size; i++)
+		WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++));
+	WREG32(RLC_GPM_UCODE_ADDR, 0);
+
+	/* XXX */
+	clear_state_info[0] = 0;//upper_32_bits(rdev->rlc.save_restore_gpu_addr);
+	clear_state_info[1] = 0;//rdev->rlc.save_restore_gpu_addr;
+	clear_state_info[2] = 0;//cik_default_size;
+	WREG32(RLC_GPM_SCRATCH_ADDR, 0x3d);
+	for (i = 0; i < 3; i++)
+		WREG32(RLC_GPM_SCRATCH_DATA, clear_state_info[i]);
+	WREG32(RLC_DRIVER_DMA_STATUS, 0);
+
+	cik_rlc_start(rdev);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
index 783cf60..a116020 100644
--- a/drivers/gpu/drm/radeon/cikd.h
+++ b/drivers/gpu/drm/radeon/cikd.h
@@ -497,10 +497,55 @@ 
 #define	CP_MEC_ME2_UCODE_ADDR				0xC178
 #define	CP_MEC_ME2_UCODE_DATA				0xC17C
 
+#define CP_INT_CNTL_RING0                               0xC1A8
+#       define CNTX_BUSY_INT_ENABLE                     (1 << 19)
+#       define CNTX_EMPTY_INT_ENABLE                    (1 << 20)
+#       define PRIV_INSTR_INT_ENABLE                    (1 << 22)
+#       define PRIV_REG_INT_ENABLE                      (1 << 23)
+#       define TIME_STAMP_INT_ENABLE                    (1 << 26)
+#       define CP_RINGID2_INT_ENABLE                    (1 << 29)
+#       define CP_RINGID1_INT_ENABLE                    (1 << 30)
+#       define CP_RINGID0_INT_ENABLE                    (1 << 31)
+
 #define	CP_MAX_CONTEXT					0xC2B8
 
 #define	CP_RB0_BASE_HI					0xC2C4
 
+#define RLC_CNTL                                          0xC300
+#       define RLC_ENABLE                                 (1 << 0)
+
+#define RLC_MC_CNTL                                       0xC30C
+
+#define RLC_LB_CNTR_MAX                                   0xC348
+
+#define RLC_LB_CNTL                                       0xC364
+
+#define RLC_LB_CNTR_INIT                                  0xC36C
+
+#define RLC_SAVE_AND_RESTORE_BASE                         0xC374
+#define RLC_DRIVER_DMA_STATUS                             0xC378
+
+#define RLC_GPM_UCODE_ADDR                                0xC388
+#define RLC_GPM_UCODE_DATA                                0xC38C
+
+#define RLC_UCODE_CNTL                                    0xC39C
+
+#define RLC_CGCG_CGLS_CTRL                                0xC424
+
+#define RLC_LB_INIT_CU_MASK                               0xC43C
+
+#define RLC_LB_PARAMS                                     0xC444
+
+#define RLC_SERDES_CU_MASTER_BUSY                         0xC484
+#define RLC_SERDES_NONCU_MASTER_BUSY                      0xC488
+#       define SE_MASTER_BUSY_MASK                        0x0000ffff
+#       define GC_MASTER_BUSY                             (1 << 16)
+#       define TC0_MASTER_BUSY                            (1 << 17)
+#       define TC1_MASTER_BUSY                            (1 << 18)
+
+#define RLC_GPM_SCRATCH_ADDR                              0xC4B0
+#define RLC_GPM_SCRATCH_DATA                              0xC4B4
+
 #define PA_SC_RASTER_CONFIG                             0x28350
 #       define RASTER_CONFIG_RB_MAP_0                   0
 #       define RASTER_CONFIG_RB_MAP_1                   1
@@ -599,6 +644,8 @@ 
 #define		TCC_DISABLE_MASK				0xFFFF0000
 #define		TCC_DISABLE_SHIFT				16
 
+#define	CB_CGTT_SCLK_CTRL				0x3c2a0
+
 /*
  * PM4
  */