diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index b7dc019fee3a..a057bba5c3a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -3617,21 +3617,6 @@ static void gfx_v7_0_enable_mgcg(struct amdgpu_device *adev, bool enable) } } -static void gfx_v7_0_update_cg(struct amdgpu_device *adev, - bool enable) -{ - gfx_v7_0_enable_gui_idle_interrupt(adev, false); - /* order matters! */ - if (enable) { - gfx_v7_0_enable_mgcg(adev, true); - gfx_v7_0_enable_cgcg(adev, true); - } else { - gfx_v7_0_enable_cgcg(adev, false); - gfx_v7_0_enable_mgcg(adev, false); - } - gfx_v7_0_enable_gui_idle_interrupt(adev, true); -} - static void gfx_v7_0_enable_sclk_slowdown_on_pu(struct amdgpu_device *adev, bool enable) { @@ -4550,80 +4535,99 @@ static int gfx_v7_0_wait_for_idle(struct amdgpu_ip_block *ip_block) static int gfx_v7_0_soft_reset(struct amdgpu_ip_block *ip_block) { + struct amdgpu_device *adev = ip_block->adev; u32 grbm_soft_reset = 0, srbm_soft_reset = 0; u32 tmp; - struct amdgpu_device *adev = ip_block->adev; + int i; + int r; - /* GRBM_STATUS */ - tmp = RREG32(mmGRBM_STATUS); - if (tmp & (GRBM_STATUS__PA_BUSY_MASK | GRBM_STATUS__SC_BUSY_MASK | - GRBM_STATUS__BCI_BUSY_MASK | GRBM_STATUS__SX_BUSY_MASK | - GRBM_STATUS__TA_BUSY_MASK | GRBM_STATUS__VGT_BUSY_MASK | - GRBM_STATUS__DB_BUSY_MASK | GRBM_STATUS__CB_BUSY_MASK | - GRBM_STATUS__GDS_BUSY_MASK | GRBM_STATUS__SPI_BUSY_MASK | - GRBM_STATUS__IA_BUSY_MASK | GRBM_STATUS__IA_BUSY_NO_DMA_MASK)) - grbm_soft_reset |= GRBM_SOFT_RESET__SOFT_RESET_CP_MASK | - GRBM_SOFT_RESET__SOFT_RESET_GFX_MASK; + grbm_soft_reset = + REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_RLC, 1) | + REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_GFX, 1) | + REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CP, 1) | + REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPF, 1) | + REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPC, 1) | + REG_SET_FIELD(0, GRBM_SOFT_RESET, SOFT_RESET_CPG, 1); - if (tmp & (GRBM_STATUS__CP_BUSY_MASK | GRBM_STATUS__CP_COHERENCY_BUSY_MASK)) { - grbm_soft_reset |= GRBM_SOFT_RESET__SOFT_RESET_CP_MASK; - srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_GRBM_MASK; - } + srbm_soft_reset = + REG_SET_FIELD(0, SRBM_SOFT_RESET, SOFT_RESET_GRBM, 1) | + REG_SET_FIELD(0, SRBM_SOFT_RESET, SOFT_RESET_SEM, 1); - /* GRBM_STATUS2 */ - tmp = RREG32(mmGRBM_STATUS2); - if (tmp & GRBM_STATUS2__RLC_BUSY_MASK) - grbm_soft_reset |= GRBM_SOFT_RESET__SOFT_RESET_RLC_MASK; + for (i = 0; i < adev->gfx.num_compute_rings; i++) { + struct amdgpu_ring *ring = &adev->gfx.compute_ring[i]; - /* SRBM_STATUS */ - tmp = RREG32(mmSRBM_STATUS); - if (tmp & SRBM_STATUS__GRBM_RQ_PENDING_MASK) - srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_GRBM_MASK; + mutex_lock(&adev->srbm_mutex); + cik_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0); + gfx_v7_0_deactivate_hqd(adev, 2); + cik_srbm_select(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); - if (grbm_soft_reset || srbm_soft_reset) { - /* disable CG/PG */ - gfx_v7_0_fini_pg(adev); - gfx_v7_0_update_cg(adev, false); - - /* stop the rlc */ - adev->gfx.rlc.funcs->stop(adev); - - /* Disable GFX parsing/prefetching */ - WREG32(mmCP_ME_CNTL, CP_ME_CNTL__ME_HALT_MASK | CP_ME_CNTL__PFP_HALT_MASK | CP_ME_CNTL__CE_HALT_MASK); - - /* Disable MEC parsing/prefetching */ - WREG32(mmCP_MEC_CNTL, CP_MEC_CNTL__MEC_ME1_HALT_MASK | CP_MEC_CNTL__MEC_ME2_HALT_MASK); - - if (grbm_soft_reset) { - tmp = RREG32(mmGRBM_SOFT_RESET); - tmp |= grbm_soft_reset; - dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp); - WREG32(mmGRBM_SOFT_RESET, tmp); - tmp = RREG32(mmGRBM_SOFT_RESET); - - udelay(50); - - tmp &= ~grbm_soft_reset; - WREG32(mmGRBM_SOFT_RESET, tmp); - tmp = RREG32(mmGRBM_SOFT_RESET); - } - - if (srbm_soft_reset) { - tmp = RREG32(mmSRBM_SOFT_RESET); - tmp |= srbm_soft_reset; - dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); - WREG32(mmSRBM_SOFT_RESET, tmp); - tmp = RREG32(mmSRBM_SOFT_RESET); - - udelay(50); - - tmp &= ~srbm_soft_reset; - WREG32(mmSRBM_SOFT_RESET, tmp); - tmp = RREG32(mmSRBM_SOFT_RESET); - } - /* Wait a little for things to settle down */ udelay(50); } + + ip_block->version->funcs->set_clockgating_state(ip_block, AMD_CG_STATE_UNGATE); + ip_block->version->funcs->set_powergating_state(ip_block, AMD_PG_STATE_UNGATE); + ip_block->version->funcs->suspend(ip_block); + + if (grbm_soft_reset || srbm_soft_reset) { + tmp = RREG32(mmGMCON_DEBUG); + tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_STALL, 1); + tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_CLEAR, 1); + WREG32(mmGMCON_DEBUG, tmp); + + udelay(100); + } + + if (grbm_soft_reset) { + tmp = RREG32(mmGRBM_SOFT_RESET); + tmp |= grbm_soft_reset; + dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(mmGRBM_SOFT_RESET, tmp); + tmp = RREG32(mmGRBM_SOFT_RESET); + + udelay(100); + + tmp &= ~grbm_soft_reset; + WREG32(mmGRBM_SOFT_RESET, tmp); + tmp = RREG32(mmGRBM_SOFT_RESET); + + udelay(100); + } + + if (srbm_soft_reset) { + tmp = RREG32(mmSRBM_SOFT_RESET); + tmp |= srbm_soft_reset; + dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); + WREG32(mmSRBM_SOFT_RESET, tmp); + tmp = RREG32(mmSRBM_SOFT_RESET); + + udelay(100); + + tmp &= ~srbm_soft_reset; + WREG32(mmSRBM_SOFT_RESET, tmp); + tmp = RREG32(mmSRBM_SOFT_RESET); + + udelay(100); + } + + if (grbm_soft_reset || srbm_soft_reset) { + tmp = RREG32(mmGMCON_DEBUG); + tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_STALL, 0); + tmp = REG_SET_FIELD(tmp, GMCON_DEBUG, GFX_CLEAR, 0); + WREG32(mmGMCON_DEBUG, tmp); + } + + /* Wait a little for things to settle down */ + udelay(100); + + r = ip_block->version->funcs->resume(ip_block); + r |= ip_block->version->funcs->late_init(ip_block); + if (r) + return r; + + ip_block->version->funcs->set_clockgating_state(ip_block, AMD_CG_STATE_GATE); + ip_block->version->funcs->set_powergating_state(ip_block, AMD_PG_STATE_GATE); + return 0; }