|
@@ -105,6 +105,7 @@ void r600_fini(struct radeon_device *rdev);
|
|
|
void r600_irq_disable(struct radeon_device *rdev);
|
|
|
static void r600_pcie_gen2_enable(struct radeon_device *rdev);
|
|
|
extern int evergreen_rlc_resume(struct radeon_device *rdev);
|
|
|
+extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
|
|
|
|
|
|
/**
|
|
|
* r600_get_xclk - get the xclk
|
|
@@ -1644,6 +1645,67 @@ static void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
|
|
|
r600_print_gpu_status_regs(rdev);
|
|
|
}
|
|
|
|
|
|
+static void r600_gpu_pci_config_reset(struct radeon_device *rdev)
|
|
|
+{
|
|
|
+ struct rv515_mc_save save;
|
|
|
+ u32 tmp, i;
|
|
|
+
|
|
|
+ dev_info(rdev->dev, "GPU pci config reset\n");
|
|
|
+
|
|
|
+ /* disable dpm? */
|
|
|
+
|
|
|
+ /* Disable CP parsing/prefetching */
|
|
|
+ if (rdev->family >= CHIP_RV770)
|
|
|
+ WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1));
|
|
|
+ else
|
|
|
+ WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
|
|
|
+
|
|
|
+ /* disable the RLC */
|
|
|
+ WREG32(RLC_CNTL, 0);
|
|
|
+
|
|
|
+ /* Disable DMA */
|
|
|
+ tmp = RREG32(DMA_RB_CNTL);
|
|
|
+ tmp &= ~DMA_RB_ENABLE;
|
|
|
+ WREG32(DMA_RB_CNTL, tmp);
|
|
|
+
|
|
|
+ mdelay(50);
|
|
|
+
|
|
|
+ /* set mclk/sclk to bypass */
|
|
|
+ if (rdev->family >= CHIP_RV770)
|
|
|
+ rv770_set_clk_bypass_mode(rdev);
|
|
|
+ /* disable BM */
|
|
|
+ pci_clear_master(rdev->pdev);
|
|
|
+ /* disable mem access */
|
|
|
+ rv515_mc_stop(rdev, &save);
|
|
|
+ if (r600_mc_wait_for_idle(rdev)) {
|
|
|
+ dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ /* BIF reset workaround. Not sure if this is needed on 6xx */
|
|
|
+ tmp = RREG32(BUS_CNTL);
|
|
|
+ tmp |= VGA_COHE_SPEC_TIMER_DIS;
|
|
|
+ WREG32(BUS_CNTL, tmp);
|
|
|
+
|
|
|
+ tmp = RREG32(BIF_SCRATCH0);
|
|
|
+
|
|
|
+ /* reset */
|
|
|
+ radeon_pci_config_reset(rdev);
|
|
|
+ mdelay(1);
|
|
|
+
|
|
|
+ /* BIF reset workaround. Not sure if this is needed on 6xx */
|
|
|
+ tmp = SOFT_RESET_BIF;
|
|
|
+ WREG32(SRBM_SOFT_RESET, tmp);
|
|
|
+ mdelay(1);
|
|
|
+ WREG32(SRBM_SOFT_RESET, 0);
|
|
|
+
|
|
|
+ /* wait for asic to come out of reset */
|
|
|
+ for (i = 0; i < rdev->usec_timeout; i++) {
|
|
|
+ if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
|
|
|
+ break;
|
|
|
+ udelay(1);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
int r600_asic_reset(struct radeon_device *rdev)
|
|
|
{
|
|
|
u32 reset_mask;
|
|
@@ -1653,10 +1715,17 @@ int r600_asic_reset(struct radeon_device *rdev)
|
|
|
if (reset_mask)
|
|
|
r600_set_bios_scratch_engine_hung(rdev, true);
|
|
|
|
|
|
+ /* try soft reset */
|
|
|
r600_gpu_soft_reset(rdev, reset_mask);
|
|
|
|
|
|
reset_mask = r600_gpu_check_soft_reset(rdev);
|
|
|
|
|
|
+ /* try pci config reset */
|
|
|
+ if (reset_mask && radeon_hard_reset)
|
|
|
+ r600_gpu_pci_config_reset(rdev);
|
|
|
+
|
|
|
+ reset_mask = r600_gpu_check_soft_reset(rdev);
|
|
|
+
|
|
|
if (!reset_mask)
|
|
|
r600_set_bios_scratch_engine_hung(rdev, false);
|
|
|
|