diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2011-03-03 04:07:33 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-03-03 04:51:21 +0300 |
commit | b9952a8ae5814b0ef2a6596c7443efd85b92e069 (patch) | |
tree | 2e259e9cde37c717a2f45c88c0084e2c23f141de /drivers/gpu/drm/radeon/ni.c | |
parent | 127278099f25a14b00c502f64b120472b512528d (diff) | |
download | linux-b9952a8ae5814b0ef2a6596c7443efd85b92e069.tar.xz |
drm/radeon/kms: add cayman asic reset support
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/ni.c')
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 0fecad240007..3a3fdf5b5dd2 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -33,6 +33,10 @@ #include "ni_reg.h" #include "cayman_blit_shaders.h" +extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); +extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); +extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); + #define EVERGREEN_PFP_UCODE_SIZE 1120 #define EVERGREEN_PM4_UCODE_SIZE 1376 #define EVERGREEN_RLC_UCODE_SIZE 768 @@ -1249,3 +1253,96 @@ int cayman_cp_resume(struct radeon_device *rdev) return 0; } +bool cayman_gpu_is_lockup(struct radeon_device *rdev) +{ + u32 srbm_status; + u32 grbm_status; + u32 grbm_status_se0, grbm_status_se1; + struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup; + int r; + + srbm_status = RREG32(SRBM_STATUS); + grbm_status = RREG32(GRBM_STATUS); + grbm_status_se0 = RREG32(GRBM_STATUS_SE0); + grbm_status_se1 = RREG32(GRBM_STATUS_SE1); + if (!(grbm_status & GUI_ACTIVE)) { + r100_gpu_lockup_update(lockup, &rdev->cp); + return false; + } + /* force CP activities */ + r = radeon_ring_lock(rdev, 2); + if (!r) { + /* PACKET2 NOP */ + radeon_ring_write(rdev, 0x80000000); + radeon_ring_write(rdev, 0x80000000); + radeon_ring_unlock_commit(rdev); + } + /* XXX deal with CP0,1,2 */ + rdev->cp.rptr = RREG32(CP_RB0_RPTR); + return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); +} + +static int cayman_gpu_soft_reset(struct radeon_device *rdev) +{ + struct evergreen_mc_save save; + u32 grbm_reset = 0; + + if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) + return 0; + + dev_info(rdev->dev, "GPU softreset \n"); + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); + evergreen_mc_stop(rdev, &save); + if (evergreen_mc_wait_for_idle(rdev)) { + dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); + } + /* Disable CP parsing/prefetching */ + WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); + + /* reset all the gfx blocks */ + grbm_reset = (SOFT_RESET_CP | + SOFT_RESET_CB | + SOFT_RESET_DB | + SOFT_RESET_GDS | + SOFT_RESET_PA | + SOFT_RESET_SC | + SOFT_RESET_SPI | + SOFT_RESET_SH | + SOFT_RESET_SX | + SOFT_RESET_TC | + SOFT_RESET_TA | + SOFT_RESET_VGT | + SOFT_RESET_IA); + + dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); + WREG32(GRBM_SOFT_RESET, grbm_reset); + (void)RREG32(GRBM_SOFT_RESET); + udelay(50); + WREG32(GRBM_SOFT_RESET, 0); + (void)RREG32(GRBM_SOFT_RESET); + /* Wait a little for things to settle down */ + udelay(50); + dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", + RREG32(GRBM_STATUS)); + dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", + RREG32(GRBM_STATUS_SE0)); + dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", + RREG32(GRBM_STATUS_SE1)); + dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", + RREG32(SRBM_STATUS)); + evergreen_mc_resume(rdev, &save); + return 0; +} + +int cayman_asic_reset(struct radeon_device *rdev) +{ + return cayman_gpu_soft_reset(rdev); +} + |