diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/rs600.c')
-rw-r--r-- | drivers/gpu/drm/radeon/rs600.c | 77 |
1 files changed, 74 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index a81bc7a21e1..5e3f21861f4 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -147,6 +147,78 @@ void rs600_hpd_fini(struct radeon_device *rdev) } } +void rs600_bm_disable(struct radeon_device *rdev) +{ + u32 tmp; + + /* disable bus mastering */ + pci_read_config_word(rdev->pdev, 0x4, (u16*)&tmp); + pci_write_config_word(rdev->pdev, 0x4, tmp & 0xFFFB); + mdelay(1); +} + +int rs600_asic_reset(struct radeon_device *rdev) +{ + u32 status, tmp; + + struct rv515_mc_save save; + + /* Stops all mc clients */ + rv515_mc_stop(rdev, &save); + status = RREG32(R_000E40_RBBM_STATUS); + if (!G_000E40_GUI_ACTIVE(status)) { + return 0; + } + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* stop CP */ + WREG32(RADEON_CP_CSQ_CNTL, 0); + tmp = RREG32(RADEON_CP_RB_CNTL); + WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); + WREG32(RADEON_CP_RB_RPTR_WR, 0); + WREG32(RADEON_CP_RB_WPTR, 0); + WREG32(RADEON_CP_RB_CNTL, tmp); + pci_save_state(rdev->pdev); + /* disable bus mastering */ + rs600_bm_disable(rdev); + /* reset GA+VAP */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) | + S_0000F0_SOFT_RESET_GA(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + mdelay(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + mdelay(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* reset CP */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + mdelay(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + mdelay(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* reset MC */ + WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_MC(1)); + RREG32(R_0000F0_RBBM_SOFT_RESET); + mdelay(500); + WREG32(R_0000F0_RBBM_SOFT_RESET, 0); + mdelay(1); + status = RREG32(R_000E40_RBBM_STATUS); + dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); + /* restore PCI & busmastering */ + pci_restore_state(rdev->pdev); + /* Check if GPU is idle */ + if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { + dev_err(rdev->dev, "failed to reset GPU\n"); + rdev->gpu_lockup = true; + return -1; + } + rv515_mc_resume(rdev, &save); + dev_info(rdev->dev, "GPU reset succeed\n"); + return 0; +} + /* * GART. */ @@ -454,7 +526,6 @@ int rs600_mc_wait_for_idle(struct radeon_device *rdev) void rs600_gpu_init(struct radeon_device *rdev) { - r100_hdp_reset(rdev); r420_pipes_init(rdev); /* Wait for mc idle */ if (rs600_mc_wait_for_idle(rdev)) @@ -601,7 +672,7 @@ int rs600_resume(struct radeon_device *rdev) /* Resume clock before doing reset */ rv515_clock_startup(rdev); /* Reset gpu before posting otherwise ATOM will enter infinite loop */ - if (radeon_gpu_reset(rdev)) { + if (radeon_asic_reset(rdev)) { dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", RREG32(R_000E40_RBBM_STATUS), RREG32(R_0007C0_CP_STAT)); @@ -664,7 +735,7 @@ int rs600_init(struct radeon_device *rdev) return -EINVAL; } /* Reset gpu before posting otherwise ATOM will enter infinite loop */ - if (radeon_gpu_reset(rdev)) { + if (radeon_asic_reset(rdev)) { dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", RREG32(R_000E40_RBBM_STATUS), |