aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-11-01 16:25:10 -0400
committerAlex Deucher <alexander.deucher@amd.com>2014-01-08 18:42:23 -0500
commitb5470b036e14d063655cc01d22ea5d727042860a (patch)
tree8420fd1eb90c039550fd922ea86a75f043b834bd /drivers
parentde9ae7447aaa2fed8ae4aa9e6b7260915e5b4f7b (diff)
drm/radeon: implement pci config reset for evergreen/cayman (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: put behind module parameter Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c50
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h4
-rw-r--r--drivers/gpu/drm/radeon/ni.c7
3 files changed, 59 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 21d975007037..4116d0279596 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -146,6 +146,7 @@ extern u32 si_get_csb_size(struct radeon_device *rdev);
146extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); 146extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
147extern u32 cik_get_csb_size(struct radeon_device *rdev); 147extern u32 cik_get_csb_size(struct radeon_device *rdev);
148extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); 148extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
149extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
149 150
150static const u32 evergreen_golden_registers[] = 151static const u32 evergreen_golden_registers[] =
151{ 152{
@@ -3867,6 +3868,48 @@ static void evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
3867 evergreen_print_gpu_status_regs(rdev); 3868 evergreen_print_gpu_status_regs(rdev);
3868} 3869}
3869 3870
3871void evergreen_gpu_pci_config_reset(struct radeon_device *rdev)
3872{
3873 struct evergreen_mc_save save;
3874 u32 tmp, i;
3875
3876 dev_info(rdev->dev, "GPU pci config reset\n");
3877
3878 /* disable dpm? */
3879
3880 /* Disable CP parsing/prefetching */
3881 WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
3882 udelay(50);
3883 /* Disable DMA */
3884 tmp = RREG32(DMA_RB_CNTL);
3885 tmp &= ~DMA_RB_ENABLE;
3886 WREG32(DMA_RB_CNTL, tmp);
3887 /* XXX other engines? */
3888
3889 /* halt the rlc */
3890 r600_rlc_stop(rdev);
3891
3892 udelay(50);
3893
3894 /* set mclk/sclk to bypass */
3895 rv770_set_clk_bypass_mode(rdev);
3896 /* disable BM */
3897 pci_clear_master(rdev->pdev);
3898 /* disable mem access */
3899 evergreen_mc_stop(rdev, &save);
3900 if (evergreen_mc_wait_for_idle(rdev)) {
3901 dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
3902 }
3903 /* reset */
3904 radeon_pci_config_reset(rdev);
3905 /* wait for asic to come out of reset */
3906 for (i = 0; i < rdev->usec_timeout; i++) {
3907 if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
3908 break;
3909 udelay(1);
3910 }
3911}
3912
3870int evergreen_asic_reset(struct radeon_device *rdev) 3913int evergreen_asic_reset(struct radeon_device *rdev)
3871{ 3914{
3872 u32 reset_mask; 3915 u32 reset_mask;
@@ -3876,10 +3919,17 @@ int evergreen_asic_reset(struct radeon_device *rdev)
3876 if (reset_mask) 3919 if (reset_mask)
3877 r600_set_bios_scratch_engine_hung(rdev, true); 3920 r600_set_bios_scratch_engine_hung(rdev, true);
3878 3921
3922 /* try soft reset */
3879 evergreen_gpu_soft_reset(rdev, reset_mask); 3923 evergreen_gpu_soft_reset(rdev, reset_mask);
3880 3924
3881 reset_mask = evergreen_gpu_check_soft_reset(rdev); 3925 reset_mask = evergreen_gpu_check_soft_reset(rdev);
3882 3926
3927 /* try pci config reset */
3928 if (reset_mask && radeon_hard_reset)
3929 evergreen_gpu_pci_config_reset(rdev);
3930
3931 reset_mask = evergreen_gpu_check_soft_reset(rdev);
3932
3883 if (!reset_mask) 3933 if (!reset_mask)
3884 r600_set_bios_scratch_engine_hung(rdev, false); 3934 r600_set_bios_scratch_engine_hung(rdev, false);
3885 3935
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 17f990798992..f9c7963b3ee6 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -82,12 +82,16 @@
82#define CG_SPLL_FUNC_CNTL_2 0x604 82#define CG_SPLL_FUNC_CNTL_2 0x604
83#define SCLK_MUX_SEL(x) ((x) << 0) 83#define SCLK_MUX_SEL(x) ((x) << 0)
84#define SCLK_MUX_SEL_MASK (0x1ff << 0) 84#define SCLK_MUX_SEL_MASK (0x1ff << 0)
85#define SCLK_MUX_UPDATE (1 << 26)
85#define CG_SPLL_FUNC_CNTL_3 0x608 86#define CG_SPLL_FUNC_CNTL_3 0x608
86#define SPLL_FB_DIV(x) ((x) << 0) 87#define SPLL_FB_DIV(x) ((x) << 0)
87#define SPLL_FB_DIV_MASK (0x3ffffff << 0) 88#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
88#define SPLL_DITHEN (1 << 28) 89#define SPLL_DITHEN (1 << 28)
90#define CG_SPLL_STATUS 0x60c
91#define SPLL_CHG_STATUS (1 << 1)
89 92
90#define MPLL_CNTL_MODE 0x61c 93#define MPLL_CNTL_MODE 0x61c
94# define MPLL_MCLK_SEL (1 << 11)
91# define SS_SSEN (1 << 24) 95# define SS_SSEN (1 << 24)
92# define SS_DSMODE_EN (1 << 25) 96# define SS_DSMODE_EN (1 << 25)
93 97
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 05a900945613..9f11a55962b5 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -174,6 +174,7 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
174extern void evergreen_program_aspm(struct radeon_device *rdev); 174extern void evergreen_program_aspm(struct radeon_device *rdev);
175extern void sumo_rlc_fini(struct radeon_device *rdev); 175extern void sumo_rlc_fini(struct radeon_device *rdev);
176extern int sumo_rlc_init(struct radeon_device *rdev); 176extern int sumo_rlc_init(struct radeon_device *rdev);
177extern void evergreen_gpu_pci_config_reset(struct radeon_device *rdev);
177 178
178/* Firmware Names */ 179/* Firmware Names */
179MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); 180MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
@@ -1878,8 +1879,10 @@ int cayman_asic_reset(struct radeon_device *rdev)
1878 1879
1879 reset_mask = cayman_gpu_check_soft_reset(rdev); 1880 reset_mask = cayman_gpu_check_soft_reset(rdev);
1880 1881
1881 if (!reset_mask) 1882 if (reset_mask)
1882 r600_set_bios_scratch_engine_hung(rdev, false); 1883 evergreen_gpu_pci_config_reset(rdev);
1884
1885 r600_set_bios_scratch_engine_hung(rdev, false);
1883 1886
1884 return 0; 1887 return 0;
1885} 1888}