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>
This commit is contained in:
parent
de9ae7447a
commit
b5470b036e
|
@ -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 void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
|
||||||
extern u32 cik_get_csb_size(struct radeon_device *rdev);
|
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 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[] =
|
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);
|
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)
|
int evergreen_asic_reset(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
u32 reset_mask;
|
u32 reset_mask;
|
||||||
|
@ -3876,10 +3919,17 @@ int evergreen_asic_reset(struct radeon_device *rdev)
|
||||||
if (reset_mask)
|
if (reset_mask)
|
||||||
r600_set_bios_scratch_engine_hung(rdev, true);
|
r600_set_bios_scratch_engine_hung(rdev, true);
|
||||||
|
|
||||||
|
/* try soft reset */
|
||||||
evergreen_gpu_soft_reset(rdev, reset_mask);
|
evergreen_gpu_soft_reset(rdev, reset_mask);
|
||||||
|
|
||||||
reset_mask = evergreen_gpu_check_soft_reset(rdev);
|
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)
|
if (!reset_mask)
|
||||||
r600_set_bios_scratch_engine_hung(rdev, false);
|
r600_set_bios_scratch_engine_hung(rdev, false);
|
||||||
|
|
||||||
|
|
|
@ -82,12 +82,16 @@
|
||||||
#define CG_SPLL_FUNC_CNTL_2 0x604
|
#define CG_SPLL_FUNC_CNTL_2 0x604
|
||||||
#define SCLK_MUX_SEL(x) ((x) << 0)
|
#define SCLK_MUX_SEL(x) ((x) << 0)
|
||||||
#define SCLK_MUX_SEL_MASK (0x1ff << 0)
|
#define SCLK_MUX_SEL_MASK (0x1ff << 0)
|
||||||
|
#define SCLK_MUX_UPDATE (1 << 26)
|
||||||
#define CG_SPLL_FUNC_CNTL_3 0x608
|
#define CG_SPLL_FUNC_CNTL_3 0x608
|
||||||
#define SPLL_FB_DIV(x) ((x) << 0)
|
#define SPLL_FB_DIV(x) ((x) << 0)
|
||||||
#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
|
#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
|
||||||
#define SPLL_DITHEN (1 << 28)
|
#define SPLL_DITHEN (1 << 28)
|
||||||
|
#define CG_SPLL_STATUS 0x60c
|
||||||
|
#define SPLL_CHG_STATUS (1 << 1)
|
||||||
|
|
||||||
#define MPLL_CNTL_MODE 0x61c
|
#define MPLL_CNTL_MODE 0x61c
|
||||||
|
# define MPLL_MCLK_SEL (1 << 11)
|
||||||
# define SS_SSEN (1 << 24)
|
# define SS_SSEN (1 << 24)
|
||||||
# define SS_DSMODE_EN (1 << 25)
|
# define SS_DSMODE_EN (1 << 25)
|
||||||
|
|
||||||
|
|
|
@ -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 evergreen_program_aspm(struct radeon_device *rdev);
|
||||||
extern void sumo_rlc_fini(struct radeon_device *rdev);
|
extern void sumo_rlc_fini(struct radeon_device *rdev);
|
||||||
extern int sumo_rlc_init(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 */
|
/* Firmware Names */
|
||||||
MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
|
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);
|
reset_mask = cayman_gpu_check_soft_reset(rdev);
|
||||||
|
|
||||||
if (!reset_mask)
|
if (reset_mask)
|
||||||
r600_set_bios_scratch_engine_hung(rdev, false);
|
evergreen_gpu_pci_config_reset(rdev);
|
||||||
|
|
||||||
|
r600_set_bios_scratch_engine_hung(rdev, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue