aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/si.c
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-11-15 16:35:55 -0500
committerAlex Deucher <alexander.deucher@amd.com>2014-01-08 18:42:24 -0500
commit4a5c8ea59f8360f354158fca039ee7fbef0fa4dd (patch)
treea3f90a21e8fc301d7e03d0145c853c0abd06c5ea /drivers/gpu/drm/radeon/si.c
parentb5470b036e14d063655cc01d22ea5d727042860a (diff)
drm/radeon: implement pci config reset for SI (v2)
pci config reset is a low level reset that resets the entire chip from the bus interface. It can be more reliable if soft reset fails. v2: hide behind module parameter Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/si.c')
-rw-r--r--drivers/gpu/drm/radeon/si.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index c698e3fe007a..626163ef483d 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -80,6 +80,8 @@ extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
80extern bool evergreen_is_display_hung(struct radeon_device *rdev); 80extern bool evergreen_is_display_hung(struct radeon_device *rdev);
81static void si_enable_gui_idle_interrupt(struct radeon_device *rdev, 81static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
82 bool enable); 82 bool enable);
83static void si_init_pg(struct radeon_device *rdev);
84static void si_init_cg(struct radeon_device *rdev);
83static void si_fini_pg(struct radeon_device *rdev); 85static void si_fini_pg(struct radeon_device *rdev);
84static void si_fini_cg(struct radeon_device *rdev); 86static void si_fini_cg(struct radeon_device *rdev);
85static void si_rlc_stop(struct radeon_device *rdev); 87static void si_rlc_stop(struct radeon_device *rdev);
@@ -3722,6 +3724,106 @@ static void si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
3722 evergreen_print_gpu_status_regs(rdev); 3724 evergreen_print_gpu_status_regs(rdev);
3723} 3725}
3724 3726
3727static void si_set_clk_bypass_mode(struct radeon_device *rdev)
3728{
3729 u32 tmp, i;
3730
3731 tmp = RREG32(CG_SPLL_FUNC_CNTL);
3732 tmp |= SPLL_BYPASS_EN;
3733 WREG32(CG_SPLL_FUNC_CNTL, tmp);
3734
3735 tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
3736 tmp |= SPLL_CTLREQ_CHG;
3737 WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
3738
3739 for (i = 0; i < rdev->usec_timeout; i++) {
3740 if (RREG32(SPLL_STATUS) & SPLL_CHG_STATUS)
3741 break;
3742 udelay(1);
3743 }
3744
3745 tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
3746 tmp &= ~(SPLL_CTLREQ_CHG | SCLK_MUX_UPDATE);
3747 WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
3748
3749 tmp = RREG32(MPLL_CNTL_MODE);
3750 tmp &= ~MPLL_MCLK_SEL;
3751 WREG32(MPLL_CNTL_MODE, tmp);
3752}
3753
3754static void si_spll_powerdown(struct radeon_device *rdev)
3755{
3756 u32 tmp;
3757
3758 tmp = RREG32(SPLL_CNTL_MODE);
3759 tmp |= SPLL_SW_DIR_CONTROL;
3760 WREG32(SPLL_CNTL_MODE, tmp);
3761
3762 tmp = RREG32(CG_SPLL_FUNC_CNTL);
3763 tmp |= SPLL_RESET;
3764 WREG32(CG_SPLL_FUNC_CNTL, tmp);
3765
3766 tmp = RREG32(CG_SPLL_FUNC_CNTL);
3767 tmp |= SPLL_SLEEP;
3768 WREG32(CG_SPLL_FUNC_CNTL, tmp);
3769
3770 tmp = RREG32(SPLL_CNTL_MODE);
3771 tmp &= ~SPLL_SW_DIR_CONTROL;
3772 WREG32(SPLL_CNTL_MODE, tmp);
3773}
3774
3775static void si_gpu_pci_config_reset(struct radeon_device *rdev)
3776{
3777 struct evergreen_mc_save save;
3778 u32 tmp, i;
3779
3780 dev_info(rdev->dev, "GPU pci config reset\n");
3781
3782 /* disable dpm? */
3783
3784 /* disable cg/pg */
3785 si_fini_pg(rdev);
3786 si_fini_cg(rdev);
3787
3788 /* Disable CP parsing/prefetching */
3789 WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
3790 /* dma0 */
3791 tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
3792 tmp &= ~DMA_RB_ENABLE;
3793 WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
3794 /* dma1 */
3795 tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
3796 tmp &= ~DMA_RB_ENABLE;
3797 WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
3798 /* XXX other engines? */
3799
3800 /* halt the rlc, disable cp internal ints */
3801 si_rlc_stop(rdev);
3802
3803 udelay(50);
3804
3805 /* disable mem access */
3806 evergreen_mc_stop(rdev, &save);
3807 if (evergreen_mc_wait_for_idle(rdev)) {
3808 dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
3809 }
3810
3811 /* set mclk/sclk to bypass */
3812 si_set_clk_bypass_mode(rdev);
3813 /* powerdown spll */
3814 si_spll_powerdown(rdev);
3815 /* disable BM */
3816 pci_clear_master(rdev->pdev);
3817 /* reset */
3818 radeon_pci_config_reset(rdev);
3819 /* wait for asic to come out of reset */
3820 for (i = 0; i < rdev->usec_timeout; i++) {
3821 if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
3822 break;
3823 udelay(1);
3824 }
3825}
3826
3725int si_asic_reset(struct radeon_device *rdev) 3827int si_asic_reset(struct radeon_device *rdev)
3726{ 3828{
3727 u32 reset_mask; 3829 u32 reset_mask;
@@ -3731,10 +3833,17 @@ int si_asic_reset(struct radeon_device *rdev)
3731 if (reset_mask) 3833 if (reset_mask)
3732 r600_set_bios_scratch_engine_hung(rdev, true); 3834 r600_set_bios_scratch_engine_hung(rdev, true);
3733 3835
3836 /* try soft reset */
3734 si_gpu_soft_reset(rdev, reset_mask); 3837 si_gpu_soft_reset(rdev, reset_mask);
3735 3838
3736 reset_mask = si_gpu_check_soft_reset(rdev); 3839 reset_mask = si_gpu_check_soft_reset(rdev);
3737 3840
3841 /* try pci config reset */
3842 if (reset_mask && radeon_hard_reset)
3843 si_gpu_pci_config_reset(rdev);
3844
3845 reset_mask = si_gpu_check_soft_reset(rdev);
3846
3738 if (!reset_mask) 3847 if (!reset_mask)
3739 r600_set_bios_scratch_engine_hung(rdev, false); 3848 r600_set_bios_scratch_engine_hung(rdev, false);
3740 3849