aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-11-01 19:01:36 -0400
committerAlex Deucher <alexander.deucher@amd.com>2014-01-08 18:42:22 -0500
commitde9ae7447aaa2fed8ae4aa9e6b7260915e5b4f7b (patch)
tree3866f2fcf1aa0868dc4d9ec53b1bfd5dad50cf74 /drivers
parent1a0041b8f99656a4600b587a491a1caa0e979e18 (diff)
drm/radeon: implement pci config reset for r6xx/7xx (v3)
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. There's not much information still available on r6xx, so r6xx is based on guess-work. v2: put behind module parameter v3: add IGP check Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/radeon/r600.c69
-rw-r--r--drivers/gpu/drm/radeon/r600d.h7
-rw-r--r--drivers/gpu/drm/radeon/rv770.c29
-rw-r--r--drivers/gpu/drm/radeon/rv770d.h7
4 files changed, 112 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index bf0792cf0729..ad99bae2e85c 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -105,6 +105,7 @@ void r600_fini(struct radeon_device *rdev);
105void r600_irq_disable(struct radeon_device *rdev); 105void r600_irq_disable(struct radeon_device *rdev);
106static void r600_pcie_gen2_enable(struct radeon_device *rdev); 106static void r600_pcie_gen2_enable(struct radeon_device *rdev);
107extern int evergreen_rlc_resume(struct radeon_device *rdev); 107extern int evergreen_rlc_resume(struct radeon_device *rdev);
108extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
108 109
109/** 110/**
110 * r600_get_xclk - get the xclk 111 * r600_get_xclk - get the xclk
@@ -1644,6 +1645,67 @@ static void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
1644 r600_print_gpu_status_regs(rdev); 1645 r600_print_gpu_status_regs(rdev);
1645} 1646}
1646 1647
1648static void r600_gpu_pci_config_reset(struct radeon_device *rdev)
1649{
1650 struct rv515_mc_save save;
1651 u32 tmp, i;
1652
1653 dev_info(rdev->dev, "GPU pci config reset\n");
1654
1655 /* disable dpm? */
1656
1657 /* Disable CP parsing/prefetching */
1658 if (rdev->family >= CHIP_RV770)
1659 WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1));
1660 else
1661 WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
1662
1663 /* disable the RLC */
1664 WREG32(RLC_CNTL, 0);
1665
1666 /* Disable DMA */
1667 tmp = RREG32(DMA_RB_CNTL);
1668 tmp &= ~DMA_RB_ENABLE;
1669 WREG32(DMA_RB_CNTL, tmp);
1670
1671 mdelay(50);
1672
1673 /* set mclk/sclk to bypass */
1674 if (rdev->family >= CHIP_RV770)
1675 rv770_set_clk_bypass_mode(rdev);
1676 /* disable BM */
1677 pci_clear_master(rdev->pdev);
1678 /* disable mem access */
1679 rv515_mc_stop(rdev, &save);
1680 if (r600_mc_wait_for_idle(rdev)) {
1681 dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
1682 }
1683
1684 /* BIF reset workaround. Not sure if this is needed on 6xx */
1685 tmp = RREG32(BUS_CNTL);
1686 tmp |= VGA_COHE_SPEC_TIMER_DIS;
1687 WREG32(BUS_CNTL, tmp);
1688
1689 tmp = RREG32(BIF_SCRATCH0);
1690
1691 /* reset */
1692 radeon_pci_config_reset(rdev);
1693 mdelay(1);
1694
1695 /* BIF reset workaround. Not sure if this is needed on 6xx */
1696 tmp = SOFT_RESET_BIF;
1697 WREG32(SRBM_SOFT_RESET, tmp);
1698 mdelay(1);
1699 WREG32(SRBM_SOFT_RESET, 0);
1700
1701 /* wait for asic to come out of reset */
1702 for (i = 0; i < rdev->usec_timeout; i++) {
1703 if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
1704 break;
1705 udelay(1);
1706 }
1707}
1708
1647int r600_asic_reset(struct radeon_device *rdev) 1709int r600_asic_reset(struct radeon_device *rdev)
1648{ 1710{
1649 u32 reset_mask; 1711 u32 reset_mask;
@@ -1653,10 +1715,17 @@ int r600_asic_reset(struct radeon_device *rdev)
1653 if (reset_mask) 1715 if (reset_mask)
1654 r600_set_bios_scratch_engine_hung(rdev, true); 1716 r600_set_bios_scratch_engine_hung(rdev, true);
1655 1717
1718 /* try soft reset */
1656 r600_gpu_soft_reset(rdev, reset_mask); 1719 r600_gpu_soft_reset(rdev, reset_mask);
1657 1720
1658 reset_mask = r600_gpu_check_soft_reset(rdev); 1721 reset_mask = r600_gpu_check_soft_reset(rdev);
1659 1722
1723 /* try pci config reset */
1724 if (reset_mask && radeon_hard_reset)
1725 r600_gpu_pci_config_reset(rdev);
1726
1727 reset_mask = r600_gpu_check_soft_reset(rdev);
1728
1660 if (!reset_mask) 1729 if (!reset_mask)
1661 r600_set_bios_scratch_engine_hung(rdev, false); 1730 r600_set_bios_scratch_engine_hung(rdev, false);
1662 1731
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index ebe38724a976..3fca4b9c65ad 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -701,11 +701,18 @@
701#define RLC_UCODE_DATA 0x3f30 701#define RLC_UCODE_DATA 0x3f30
702 702
703#define SRBM_SOFT_RESET 0xe60 703#define SRBM_SOFT_RESET 0xe60
704# define SOFT_RESET_BIF (1 << 1)
704# define SOFT_RESET_DMA (1 << 12) 705# define SOFT_RESET_DMA (1 << 12)
705# define SOFT_RESET_RLC (1 << 13) 706# define SOFT_RESET_RLC (1 << 13)
706# define SOFT_RESET_UVD (1 << 18) 707# define SOFT_RESET_UVD (1 << 18)
707# define RV770_SOFT_RESET_DMA (1 << 20) 708# define RV770_SOFT_RESET_DMA (1 << 20)
708 709
710#define BIF_SCRATCH0 0x5438
711
712#define BUS_CNTL 0x5420
713# define BIOS_ROM_DIS (1 << 1)
714# define VGA_COHE_SPEC_TIMER_DIS (1 << 9)
715
709#define CP_INT_CNTL 0xc124 716#define CP_INT_CNTL 0xc124
710# define CNTX_BUSY_INT_ENABLE (1 << 19) 717# define CNTX_BUSY_INT_ENABLE (1 << 19)
711# define CNTX_EMPTY_INT_ENABLE (1 << 20) 718# define CNTX_EMPTY_INT_ENABLE (1 << 20)
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 82e06e9a76d2..18e02889ec7d 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -1123,6 +1123,35 @@ void r700_cp_fini(struct radeon_device *rdev)
1123 radeon_scratch_free(rdev, ring->rptr_save_reg); 1123 radeon_scratch_free(rdev, ring->rptr_save_reg);
1124} 1124}
1125 1125
1126void rv770_set_clk_bypass_mode(struct radeon_device *rdev)
1127{
1128 u32 tmp, i;
1129
1130 if (rdev->flags & RADEON_IS_IGP)
1131 return;
1132
1133 tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
1134 tmp &= SCLK_MUX_SEL_MASK;
1135 tmp |= SCLK_MUX_SEL(1) | SCLK_MUX_UPDATE;
1136 WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
1137
1138 for (i = 0; i < rdev->usec_timeout; i++) {
1139 if (RREG32(CG_SPLL_STATUS) & SPLL_CHG_STATUS)
1140 break;
1141 udelay(1);
1142 }
1143
1144 tmp &= ~SCLK_MUX_UPDATE;
1145 WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
1146
1147 tmp = RREG32(MPLL_CNTL_MODE);
1148 if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
1149 tmp &= ~RV730_MPLL_MCLK_SEL;
1150 else
1151 tmp &= ~MPLL_MCLK_SEL;
1152 WREG32(MPLL_CNTL_MODE, tmp);
1153}
1154
1126/* 1155/*
1127 * Core functions 1156 * Core functions
1128 */ 1157 */
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index 1ae277152cc7..3cf1e2921545 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -100,14 +100,21 @@
100#define CG_SPLL_FUNC_CNTL_2 0x604 100#define CG_SPLL_FUNC_CNTL_2 0x604
101#define SCLK_MUX_SEL(x) ((x) << 0) 101#define SCLK_MUX_SEL(x) ((x) << 0)
102#define SCLK_MUX_SEL_MASK (0x1ff << 0) 102#define SCLK_MUX_SEL_MASK (0x1ff << 0)
103#define SCLK_MUX_UPDATE (1 << 26)
103#define CG_SPLL_FUNC_CNTL_3 0x608 104#define CG_SPLL_FUNC_CNTL_3 0x608
104#define SPLL_FB_DIV(x) ((x) << 0) 105#define SPLL_FB_DIV(x) ((x) << 0)
105#define SPLL_FB_DIV_MASK (0x3ffffff << 0) 106#define SPLL_FB_DIV_MASK (0x3ffffff << 0)
106#define SPLL_DITHEN (1 << 28) 107#define SPLL_DITHEN (1 << 28)
108#define CG_SPLL_STATUS 0x60c
109#define SPLL_CHG_STATUS (1 << 1)
107 110
108#define SPLL_CNTL_MODE 0x610 111#define SPLL_CNTL_MODE 0x610
109#define SPLL_DIV_SYNC (1 << 5) 112#define SPLL_DIV_SYNC (1 << 5)
110 113
114#define MPLL_CNTL_MODE 0x61c
115# define MPLL_MCLK_SEL (1 << 11)
116# define RV730_MPLL_MCLK_SEL (1 << 25)
117
111#define MPLL_AD_FUNC_CNTL 0x624 118#define MPLL_AD_FUNC_CNTL 0x624
112#define CLKF(x) ((x) << 0) 119#define CLKF(x) ((x) << 0)
113#define CLKF_MASK (0x7f << 0) 120#define CLKF_MASK (0x7f << 0)