diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2011-03-02 20:07:33 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-03-02 20:51:21 -0500 |
commit | b9952a8ae5814b0ef2a6596c7443efd85b92e069 (patch) | |
tree | 2e259e9cde37c717a2f45c88c0084e2c23f141de /drivers/gpu/drm/radeon | |
parent | 127278099f25a14b00c502f64b120472b512528d (diff) |
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')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 97 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/nid.h | 1 |
3 files changed, 101 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index ffdc8332b76e..0a3d6fc13c2d 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -804,7 +804,7 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) | |||
804 | } | 804 | } |
805 | } | 805 | } |
806 | 806 | ||
807 | static int evergreen_mc_wait_for_idle(struct radeon_device *rdev) | 807 | int evergreen_mc_wait_for_idle(struct radeon_device *rdev) |
808 | { | 808 | { |
809 | unsigned i; | 809 | unsigned i; |
810 | u32 tmp; | 810 | u32 tmp; |
@@ -957,7 +957,7 @@ void evergreen_agp_enable(struct radeon_device *rdev) | |||
957 | WREG32(VM_CONTEXT1_CNTL, 0); | 957 | WREG32(VM_CONTEXT1_CNTL, 0); |
958 | } | 958 | } |
959 | 959 | ||
960 | static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) | 960 | void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) |
961 | { | 961 | { |
962 | save->vga_control[0] = RREG32(D1VGA_CONTROL); | 962 | save->vga_control[0] = RREG32(D1VGA_CONTROL); |
963 | save->vga_control[1] = RREG32(D2VGA_CONTROL); | 963 | save->vga_control[1] = RREG32(D2VGA_CONTROL); |
@@ -1011,7 +1011,7 @@ static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_sa | |||
1011 | WREG32(EVERGREEN_D6VGA_CONTROL, 0); | 1011 | WREG32(EVERGREEN_D6VGA_CONTROL, 0); |
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) | 1014 | void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) |
1015 | { | 1015 | { |
1016 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, | 1016 | WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, |
1017 | upper_32_bits(rdev->mc.vram_start)); | 1017 | upper_32_bits(rdev->mc.vram_start)); |
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 @@ | |||
33 | #include "ni_reg.h" | 33 | #include "ni_reg.h" |
34 | #include "cayman_blit_shaders.h" | 34 | #include "cayman_blit_shaders.h" |
35 | 35 | ||
36 | extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); | ||
37 | extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); | ||
38 | extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); | ||
39 | |||
36 | #define EVERGREEN_PFP_UCODE_SIZE 1120 | 40 | #define EVERGREEN_PFP_UCODE_SIZE 1120 |
37 | #define EVERGREEN_PM4_UCODE_SIZE 1376 | 41 | #define EVERGREEN_PM4_UCODE_SIZE 1376 |
38 | #define EVERGREEN_RLC_UCODE_SIZE 768 | 42 | #define EVERGREEN_RLC_UCODE_SIZE 768 |
@@ -1249,3 +1253,96 @@ int cayman_cp_resume(struct radeon_device *rdev) | |||
1249 | return 0; | 1253 | return 0; |
1250 | } | 1254 | } |
1251 | 1255 | ||
1256 | bool cayman_gpu_is_lockup(struct radeon_device *rdev) | ||
1257 | { | ||
1258 | u32 srbm_status; | ||
1259 | u32 grbm_status; | ||
1260 | u32 grbm_status_se0, grbm_status_se1; | ||
1261 | struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup; | ||
1262 | int r; | ||
1263 | |||
1264 | srbm_status = RREG32(SRBM_STATUS); | ||
1265 | grbm_status = RREG32(GRBM_STATUS); | ||
1266 | grbm_status_se0 = RREG32(GRBM_STATUS_SE0); | ||
1267 | grbm_status_se1 = RREG32(GRBM_STATUS_SE1); | ||
1268 | if (!(grbm_status & GUI_ACTIVE)) { | ||
1269 | r100_gpu_lockup_update(lockup, &rdev->cp); | ||
1270 | return false; | ||
1271 | } | ||
1272 | /* force CP activities */ | ||
1273 | r = radeon_ring_lock(rdev, 2); | ||
1274 | if (!r) { | ||
1275 | /* PACKET2 NOP */ | ||
1276 | radeon_ring_write(rdev, 0x80000000); | ||
1277 | radeon_ring_write(rdev, 0x80000000); | ||
1278 | radeon_ring_unlock_commit(rdev); | ||
1279 | } | ||
1280 | /* XXX deal with CP0,1,2 */ | ||
1281 | rdev->cp.rptr = RREG32(CP_RB0_RPTR); | ||
1282 | return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); | ||
1283 | } | ||
1284 | |||
1285 | static int cayman_gpu_soft_reset(struct radeon_device *rdev) | ||
1286 | { | ||
1287 | struct evergreen_mc_save save; | ||
1288 | u32 grbm_reset = 0; | ||
1289 | |||
1290 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
1291 | return 0; | ||
1292 | |||
1293 | dev_info(rdev->dev, "GPU softreset \n"); | ||
1294 | dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", | ||
1295 | RREG32(GRBM_STATUS)); | ||
1296 | dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", | ||
1297 | RREG32(GRBM_STATUS_SE0)); | ||
1298 | dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", | ||
1299 | RREG32(GRBM_STATUS_SE1)); | ||
1300 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | ||
1301 | RREG32(SRBM_STATUS)); | ||
1302 | evergreen_mc_stop(rdev, &save); | ||
1303 | if (evergreen_mc_wait_for_idle(rdev)) { | ||
1304 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | ||
1305 | } | ||
1306 | /* Disable CP parsing/prefetching */ | ||
1307 | WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); | ||
1308 | |||
1309 | /* reset all the gfx blocks */ | ||
1310 | grbm_reset = (SOFT_RESET_CP | | ||
1311 | SOFT_RESET_CB | | ||
1312 | SOFT_RESET_DB | | ||
1313 | SOFT_RESET_GDS | | ||
1314 | SOFT_RESET_PA | | ||
1315 | SOFT_RESET_SC | | ||
1316 | SOFT_RESET_SPI | | ||
1317 | SOFT_RESET_SH | | ||
1318 | SOFT_RESET_SX | | ||
1319 | SOFT_RESET_TC | | ||
1320 | SOFT_RESET_TA | | ||
1321 | SOFT_RESET_VGT | | ||
1322 | SOFT_RESET_IA); | ||
1323 | |||
1324 | dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); | ||
1325 | WREG32(GRBM_SOFT_RESET, grbm_reset); | ||
1326 | (void)RREG32(GRBM_SOFT_RESET); | ||
1327 | udelay(50); | ||
1328 | WREG32(GRBM_SOFT_RESET, 0); | ||
1329 | (void)RREG32(GRBM_SOFT_RESET); | ||
1330 | /* Wait a little for things to settle down */ | ||
1331 | udelay(50); | ||
1332 | dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", | ||
1333 | RREG32(GRBM_STATUS)); | ||
1334 | dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", | ||
1335 | RREG32(GRBM_STATUS_SE0)); | ||
1336 | dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", | ||
1337 | RREG32(GRBM_STATUS_SE1)); | ||
1338 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | ||
1339 | RREG32(SRBM_STATUS)); | ||
1340 | evergreen_mc_resume(rdev, &save); | ||
1341 | return 0; | ||
1342 | } | ||
1343 | |||
1344 | int cayman_asic_reset(struct radeon_device *rdev) | ||
1345 | { | ||
1346 | return cayman_gpu_soft_reset(rdev); | ||
1347 | } | ||
1348 | |||
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 57062f14acc9..0f9a08b53fbd 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define CAYMAN_MAX_TCC_MASK 0xFF | 42 | #define CAYMAN_MAX_TCC_MASK 0xFF |
43 | 43 | ||
44 | #define DMIF_ADDR_CONFIG 0xBD4 | 44 | #define DMIF_ADDR_CONFIG 0xBD4 |
45 | #define SRBM_STATUS 0x0E50 | ||
45 | 46 | ||
46 | #define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 | 47 | #define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 |
47 | #define REQUEST_TYPE(x) (((x) & 0xf) << 0) | 48 | #define REQUEST_TYPE(x) (((x) & 0xf) << 0) |