aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0739-drm-amd-amdgpu-add-gfx-clock-gating-support-for-Fiji.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0739-drm-amd-amdgpu-add-gfx-clock-gating-support-for-Fiji.patch')
-rw-r--r--common/recipes-kernel/linux/files/0739-drm-amd-amdgpu-add-gfx-clock-gating-support-for-Fiji.patch291
1 files changed, 291 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0739-drm-amd-amdgpu-add-gfx-clock-gating-support-for-Fiji.patch b/common/recipes-kernel/linux/files/0739-drm-amd-amdgpu-add-gfx-clock-gating-support-for-Fiji.patch
new file mode 100644
index 00000000..23f49346
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0739-drm-amd-amdgpu-add-gfx-clock-gating-support-for-Fiji.patch
@@ -0,0 +1,291 @@
+From 0dfd0250e38eb307b9faba99577d20adae3d01d9 Mon Sep 17 00:00:00 2001
+From: Eric Huang <JinHuiEric.Huang@amd.com>
+Date: Tue, 10 Nov 2015 10:50:25 -0500
+Subject: [PATCH 0739/1050] drm/amd/amdgpu: add gfx clock gating support for
+ Fiji.
+
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com>
+Signed-off-by: Eric Huang <JinHuiEric.Huang@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 254 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 254 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+index 2dff28a..679d98a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+@@ -66,6 +66,27 @@
+ #define MACRO_TILE_ASPECT(x) ((x) << GB_MACROTILE_MODE0__MACRO_TILE_ASPECT__SHIFT)
+ #define NUM_BANKS(x) ((x) << GB_MACROTILE_MODE0__NUM_BANKS__SHIFT)
+
++#define RLC_CGTT_MGCG_OVERRIDE__CPF_MASK 0x00000001L
++#define RLC_CGTT_MGCG_OVERRIDE__RLC_MASK 0x00000002L
++#define RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK 0x00000004L
++#define RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK 0x00000008L
++#define RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK 0x00000010L
++#define RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK 0x00000020L
++
++/* BPM SERDES CMD */
++#define SET_BPM_SERDES_CMD 1
++#define CLE_BPM_SERDES_CMD 0
++
++/* BPM Register Address*/
++enum {
++ BPM_REG_CGLS_EN = 0, /* Enable/Disable CGLS */
++ BPM_REG_CGLS_ON, /* ON/OFF CGLS: shall be controlled by RLC FW */
++ BPM_REG_CGCG_OVERRIDE, /* Set/Clear CGCG Override */
++ BPM_REG_MGCG_OVERRIDE, /* Set/Clear MGCG Override */
++ BPM_REG_FGCG_OVERRIDE, /* Set/Clear FGCG Override */
++ BPM_REG_FGCG_MAX
++};
++
+ MODULE_FIRMWARE("amdgpu/carrizo_ce.bin");
+ MODULE_FIRMWARE("amdgpu/carrizo_pfp.bin");
+ MODULE_FIRMWARE("amdgpu/carrizo_me.bin");
+@@ -4468,9 +4489,242 @@ static int gfx_v8_0_set_powergating_state(void *handle,
+ return 0;
+ }
+
++static void fiji_send_serdes_cmd(struct amdgpu_device *adev,
++ uint32_t reg_addr, uint32_t cmd)
++{
++ uint32_t data;
++
++ gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff);
++
++ WREG32(mmRLC_SERDES_WR_CU_MASTER_MASK, 0xffffffff);
++ WREG32(mmRLC_SERDES_WR_NONCU_MASTER_MASK, 0xffffffff);
++
++ data = RREG32(mmRLC_SERDES_WR_CTRL);
++ data &= ~(RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK |
++ RLC_SERDES_WR_CTRL__READ_COMMAND_MASK |
++ RLC_SERDES_WR_CTRL__P1_SELECT_MASK |
++ RLC_SERDES_WR_CTRL__P2_SELECT_MASK |
++ RLC_SERDES_WR_CTRL__RDDATA_RESET_MASK |
++ RLC_SERDES_WR_CTRL__POWER_DOWN_MASK |
++ RLC_SERDES_WR_CTRL__POWER_UP_MASK |
++ RLC_SERDES_WR_CTRL__SHORT_FORMAT_MASK |
++ RLC_SERDES_WR_CTRL__BPM_DATA_MASK |
++ RLC_SERDES_WR_CTRL__REG_ADDR_MASK |
++ RLC_SERDES_WR_CTRL__SRBM_OVERRIDE_MASK);
++ data |= (RLC_SERDES_WR_CTRL__RSVD_BPM_ADDR_MASK |
++ (cmd << RLC_SERDES_WR_CTRL__BPM_DATA__SHIFT) |
++ (reg_addr << RLC_SERDES_WR_CTRL__REG_ADDR__SHIFT) |
++ (0xff << RLC_SERDES_WR_CTRL__BPM_ADDR__SHIFT));
++
++ WREG32(mmRLC_SERDES_WR_CTRL, data);
++}
++
++static void fiji_update_medium_grain_clock_gating(struct amdgpu_device *adev,
++ bool enable)
++{
++ uint32_t temp, data;
++
++ /* It is disabled by HW by default */
++ if (enable) {
++ /* 1 - RLC memory Light sleep */
++ temp = data = RREG32(mmRLC_MEM_SLP_CNTL);
++ data |= RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
++ if (temp != data)
++ WREG32(mmRLC_MEM_SLP_CNTL, data);
++
++ /* 2 - CP memory Light sleep */
++ temp = data = RREG32(mmCP_MEM_SLP_CNTL);
++ data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
++ if (temp != data)
++ WREG32(mmCP_MEM_SLP_CNTL, data);
++
++ /* 3 - RLC_CGTT_MGCG_OVERRIDE */
++ temp = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
++ data &= ~(RLC_CGTT_MGCG_OVERRIDE__CPF_MASK |
++ RLC_CGTT_MGCG_OVERRIDE__RLC_MASK |
++ RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK |
++ RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK);
++
++ if (temp != data)
++ WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
++
++ /* 4 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
++ gfx_v8_0_wait_for_rlc_serdes(adev);
++
++ /* 5 - clear mgcg override */
++ fiji_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
++
++ /* 6 - Enable CGTS(Tree Shade) MGCG /MGLS */
++ temp = data = RREG32(mmCGTS_SM_CTRL_REG);
++ data &= ~(CGTS_SM_CTRL_REG__SM_MODE_MASK);
++ data |= (0x2 << CGTS_SM_CTRL_REG__SM_MODE__SHIFT);
++ data |= CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK;
++ data &= ~CGTS_SM_CTRL_REG__OVERRIDE_MASK;
++ data &= ~CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK;
++ data |= CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK;
++ data |= (0x96 << CGTS_SM_CTRL_REG__ON_MONITOR_ADD__SHIFT);
++ if (temp != data)
++ WREG32(mmCGTS_SM_CTRL_REG, data);
++ udelay(50);
++
++ /* 7 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
++ gfx_v8_0_wait_for_rlc_serdes(adev);
++ } else {
++ /* 1 - MGCG_OVERRIDE[0] for CP and MGCG_OVERRIDE[1] for RLC */
++ temp = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
++ data |= (RLC_CGTT_MGCG_OVERRIDE__CPF_MASK |
++ RLC_CGTT_MGCG_OVERRIDE__RLC_MASK |
++ RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK |
++ RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK);
++ if (temp != data)
++ WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
++
++ /* 2 - disable MGLS in RLC */
++ data = RREG32(mmRLC_MEM_SLP_CNTL);
++ if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK) {
++ data &= ~RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
++ WREG32(mmRLC_MEM_SLP_CNTL, data);
++ }
++
++ /* 3 - disable MGLS in CP */
++ data = RREG32(mmCP_MEM_SLP_CNTL);
++ if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) {
++ data &= ~CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
++ WREG32(mmCP_MEM_SLP_CNTL, data);
++ }
++
++ /* 4 - Disable CGTS(Tree Shade) MGCG and MGLS */
++ temp = data = RREG32(mmCGTS_SM_CTRL_REG);
++ data |= (CGTS_SM_CTRL_REG__OVERRIDE_MASK |
++ CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK);
++ if (temp != data)
++ WREG32(mmCGTS_SM_CTRL_REG, data);
++
++ /* 5 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
++ gfx_v8_0_wait_for_rlc_serdes(adev);
++
++ /* 6 - set mgcg override */
++ fiji_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, SET_BPM_SERDES_CMD);
++
++ udelay(50);
++
++ /* 7- wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
++ gfx_v8_0_wait_for_rlc_serdes(adev);
++ }
++}
++
++static void fiji_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
++ bool enable)
++{
++ uint32_t temp, temp1, data, data1;
++
++ temp = data = RREG32(mmRLC_CGCG_CGLS_CTRL);
++
++ if (enable) {
++ /* 1 enable cntx_empty_int_enable/cntx_busy_int_enable/
++ * Cmp_busy/GFX_Idle interrupts
++ */
++ gfx_v8_0_enable_gui_idle_interrupt(adev, true);
++
++ temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
++ data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK;
++ if (temp1 != data1)
++ WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
++
++ /* 2 wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
++ gfx_v8_0_wait_for_rlc_serdes(adev);
++
++ /* 3 - clear cgcg override */
++ fiji_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
++
++ /* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
++ gfx_v8_0_wait_for_rlc_serdes(adev);
++
++ /* 4 - write cmd to set CGLS */
++ fiji_send_serdes_cmd(adev, BPM_REG_CGLS_EN, SET_BPM_SERDES_CMD);
++
++ /* 5 - enable cgcg */
++ data |= RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
++
++ /* enable cgls*/
++ data |= RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
++
++ temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
++ data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK;
++
++ if (temp1 != data1)
++ WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
++
++ if (temp != data)
++ WREG32(mmRLC_CGCG_CGLS_CTRL, data);
++ } else {
++ /* disable cntx_empty_int_enable & GFX Idle interrupt */
++ gfx_v8_0_enable_gui_idle_interrupt(adev, false);
++
++ /* TEST CGCG */
++ temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
++ data1 |= (RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK |
++ RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK);
++ if (temp1 != data1)
++ WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
++
++ /* read gfx register to wake up cgcg */
++ RREG32(mmCB_CGTT_SCLK_CTRL);
++ RREG32(mmCB_CGTT_SCLK_CTRL);
++ RREG32(mmCB_CGTT_SCLK_CTRL);
++ RREG32(mmCB_CGTT_SCLK_CTRL);
++
++ /* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
++ gfx_v8_0_wait_for_rlc_serdes(adev);
++
++ /* write cmd to Set CGCG Overrride */
++ fiji_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, SET_BPM_SERDES_CMD);
++
++ /* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
++ gfx_v8_0_wait_for_rlc_serdes(adev);
++
++ /* write cmd to Clear CGLS */
++ fiji_send_serdes_cmd(adev, BPM_REG_CGLS_EN, CLE_BPM_SERDES_CMD);
++
++ /* disable cgcg, cgls should be disabled too. */
++ data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK |
++ RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
++ if (temp != data)
++ WREG32(mmRLC_CGCG_CGLS_CTRL, data);
++ }
++}
++static int fiji_update_gfx_clock_gating(struct amdgpu_device *adev,
++ bool enable)
++{
++ if (enable) {
++ /* CGCG/CGLS should be enabled after MGCG/MGLS/TS(CG/LS)
++ * === MGCG + MGLS + TS(CG/LS) ===
++ */
++ fiji_update_medium_grain_clock_gating(adev, enable);
++ fiji_update_coarse_grain_clock_gating(adev, enable);
++ } else {
++ /* CGCG/CGLS should be disabled before MGCG/MGLS/TS(CG/LS)
++ * === CGCG + CGLS ===
++ */
++ fiji_update_coarse_grain_clock_gating(adev, enable);
++ fiji_update_medium_grain_clock_gating(adev, enable);
++ }
++ return 0;
++}
++
+ static int gfx_v8_0_set_clockgating_state(void *handle,
+ enum amd_clockgating_state state)
+ {
++ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
++
++ switch (adev->asic_type) {
++ case CHIP_FIJI:
++ fiji_update_gfx_clock_gating(adev,
++ state == AMD_CG_STATE_GATE ? true : false);
++ break;
++ default:
++ break;
++ }
+ return 0;
+ }
+
+--
+1.9.1
+