diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-11-01 16:25:10 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2014-01-08 18:42:23 -0500 |
commit | b5470b036e14d063655cc01d22ea5d727042860a (patch) | |
tree | 8420fd1eb90c039550fd922ea86a75f043b834bd /drivers/gpu/drm | |
parent | de9ae7447aaa2fed8ae4aa9e6b7260915e5b4f7b (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/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 50 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/evergreend.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 7 |
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); | |||
146 | extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); | 146 | extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); |
147 | extern u32 cik_get_csb_size(struct radeon_device *rdev); | 147 | extern u32 cik_get_csb_size(struct radeon_device *rdev); |
148 | extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); | 148 | extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer); |
149 | extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev); | ||
149 | 150 | ||
150 | static const u32 evergreen_golden_registers[] = | 151 | static 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 | ||
3871 | void 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 | |||
3870 | int evergreen_asic_reset(struct radeon_device *rdev) | 3913 | int 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); | |||
174 | extern void evergreen_program_aspm(struct radeon_device *rdev); | 174 | extern void evergreen_program_aspm(struct radeon_device *rdev); |
175 | extern void sumo_rlc_fini(struct radeon_device *rdev); | 175 | extern void sumo_rlc_fini(struct radeon_device *rdev); |
176 | extern int sumo_rlc_init(struct radeon_device *rdev); | 176 | extern int sumo_rlc_init(struct radeon_device *rdev); |
177 | extern void evergreen_gpu_pci_config_reset(struct radeon_device *rdev); | ||
177 | 178 | ||
178 | /* Firmware Names */ | 179 | /* Firmware Names */ |
179 | MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); | 180 | MODULE_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 | } |