|
@@ -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);
|
|
|
+}
|
|
|
+
|