drm/radeon: implement pci config reset for evergreen/cayman (v2)
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 1 Nov 2013 20:25:10 +0000 (16:25 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 8 Jan 2014 23:42:23 +0000 (18:42 -0500)
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: put behind module parameter

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c

index 21d975007037a902e99feeac53fb126f13d4ed76..4116d0279596605d0447d9687c6d9f5698ea27de 100644 (file)
@@ -146,6 +146,7 @@ extern u32 si_get_csb_size(struct radeon_device *rdev);
 extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
 extern u32 cik_get_csb_size(struct radeon_device *rdev);
 extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
+extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
 
 static const u32 evergreen_golden_registers[] =
 {
@@ -3867,6 +3868,48 @@ static void evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        evergreen_print_gpu_status_regs(rdev);
 }
 
+void evergreen_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct evergreen_mc_save save;
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* Disable CP parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
+       udelay(50);
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+       /* XXX other engines? */
+
+       /* halt the rlc */
+       r600_rlc_stop(rdev);
+
+       udelay(50);
+
+       /* set mclk/sclk to bypass */
+       rv770_set_clk_bypass_mode(rdev);
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* disable mem access */
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
+       }
+       /* reset */
+       radeon_pci_config_reset(rdev);
+       /* 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 evergreen_asic_reset(struct radeon_device *rdev)
 {
        u32 reset_mask;
@@ -3876,10 +3919,17 @@ int evergreen_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        evergreen_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = evergreen_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               evergreen_gpu_pci_config_reset(rdev);
+
+       reset_mask = evergreen_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
index 17f990798992dae5d6335726a8f3b4c259659f89..f9c7963b3ee6b38730cdf6d422c2b612f0d1c904 100644 (file)
 #define        CG_SPLL_FUNC_CNTL_2                             0x604
 #define                SCLK_MUX_SEL(x)                         ((x) << 0)
 #define                SCLK_MUX_SEL_MASK                       (0x1ff << 0)
+#define                SCLK_MUX_UPDATE                         (1 << 26)
 #define        CG_SPLL_FUNC_CNTL_3                             0x608
 #define                SPLL_FB_DIV(x)                          ((x) << 0)
 #define                SPLL_FB_DIV_MASK                        (0x3ffffff << 0)
 #define                SPLL_DITHEN                             (1 << 28)
+#define        CG_SPLL_STATUS                                  0x60c
+#define                SPLL_CHG_STATUS                         (1 << 1)
 
 #define MPLL_CNTL_MODE                                  0x61c
+#       define MPLL_MCLK_SEL                            (1 << 11)
 #       define SS_SSEN                                  (1 << 24)
 #       define SS_DSMODE_EN                             (1 << 25)
 
index 05a90094561397f2f367d3794191078688479d77..9f11a55962b5a10011304e2f8296d46f293b85ae 100644 (file)
@@ -174,6 +174,7 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 extern void evergreen_program_aspm(struct radeon_device *rdev);
 extern void sumo_rlc_fini(struct radeon_device *rdev);
 extern int sumo_rlc_init(struct radeon_device *rdev);
+extern void evergreen_gpu_pci_config_reset(struct radeon_device *rdev);
 
 /* Firmware Names */
 MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
@@ -1878,8 +1879,10 @@ int cayman_asic_reset(struct radeon_device *rdev)
 
        reset_mask = cayman_gpu_check_soft_reset(rdev);
 
-       if (!reset_mask)
-               r600_set_bios_scratch_engine_hung(rdev, false);
+       if (reset_mask)
+               evergreen_gpu_pci_config_reset(rdev);
+
+       r600_set_bios_scratch_engine_hung(rdev, false);
 
        return 0;
 }
This page took 0.047814 seconds and 5 git commands to generate.