aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/si.c
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-02-15 16:49:59 -0500
committerAlex Deucher <alexander.deucher@amd.com>2013-06-27 19:16:29 -0400
commitd719cef316d6377a7d6b5df495de118afb3a9fc2 (patch)
tree9b513e9940dd7c1b315ce54aae395d21bbbdd726 /drivers/gpu/drm/radeon/si.c
parent8ba104637b5901cdc52fb0455cefcc73dc4b10e4 (diff)
drm/radeon: update rlc programming sequence on SI
This is required for certain power management features. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/si.c')
-rw-r--r--drivers/gpu/drm/radeon/si.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 9fd0bc379f36..84ed3325a0d9 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -4418,14 +4418,93 @@ int si_rlc_init(struct radeon_device *rdev)
4418 return 0; 4418 return 0;
4419} 4419}
4420 4420
4421static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
4422 bool enable)
4423{
4424 u32 tmp = RREG32(CP_INT_CNTL_RING0);
4425 u32 mask;
4426 int i;
4427
4428 if (enable)
4429 tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
4430 else
4431 tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
4432 WREG32(CP_INT_CNTL_RING0, tmp);
4433
4434 if (!enable) {
4435 /* read a gfx register */
4436 tmp = RREG32(DB_DEPTH_INFO);
4437
4438 mask = RLC_BUSY_STATUS | GFX_POWER_STATUS | GFX_CLOCK_STATUS | GFX_LS_STATUS;
4439 for (i = 0; i < rdev->usec_timeout; i++) {
4440 if ((RREG32(RLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS))
4441 break;
4442 udelay(1);
4443 }
4444 }
4445}
4446
4447static void si_wait_for_rlc_serdes(struct radeon_device *rdev)
4448{
4449 int i;
4450
4451 for (i = 0; i < rdev->usec_timeout; i++) {
4452 if (RREG32(RLC_SERDES_MASTER_BUSY_0) == 0)
4453 break;
4454 udelay(1);
4455 }
4456
4457 for (i = 0; i < rdev->usec_timeout; i++) {
4458 if (RREG32(RLC_SERDES_MASTER_BUSY_1) == 0)
4459 break;
4460 udelay(1);
4461 }
4462}
4463
4421static void si_rlc_stop(struct radeon_device *rdev) 4464static void si_rlc_stop(struct radeon_device *rdev)
4422{ 4465{
4423 WREG32(RLC_CNTL, 0); 4466 WREG32(RLC_CNTL, 0);
4467
4468 si_enable_gui_idle_interrupt(rdev, false);
4469
4470 si_wait_for_rlc_serdes(rdev);
4424} 4471}
4425 4472
4426static void si_rlc_start(struct radeon_device *rdev) 4473static void si_rlc_start(struct radeon_device *rdev)
4427{ 4474{
4428 WREG32(RLC_CNTL, RLC_ENABLE); 4475 WREG32(RLC_CNTL, RLC_ENABLE);
4476
4477 si_enable_gui_idle_interrupt(rdev, true);
4478
4479 udelay(50);
4480}
4481
4482static bool si_lbpw_supported(struct radeon_device *rdev)
4483{
4484 u32 tmp;
4485
4486 /* Enable LBPW only for DDR3 */
4487 tmp = RREG32(MC_SEQ_MISC0);
4488 if ((tmp & 0xF0000000) == 0xB0000000)
4489 return true;
4490 return false;
4491}
4492
4493static void si_enable_lbpw(struct radeon_device *rdev, bool enable)
4494{
4495 u32 tmp;
4496
4497 tmp = RREG32(RLC_LB_CNTL);
4498 if (enable)
4499 tmp |= LOAD_BALANCE_ENABLE;
4500 else
4501 tmp &= ~LOAD_BALANCE_ENABLE;
4502 WREG32(RLC_LB_CNTL, tmp);
4503
4504 if (!enable) {
4505 si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
4506 WREG32(SPI_LB_CU_MASK, 0x00ff);
4507 }
4429} 4508}
4430 4509
4431static int si_rlc_resume(struct radeon_device *rdev) 4510static int si_rlc_resume(struct radeon_device *rdev)
@@ -4443,6 +4522,7 @@ static int si_rlc_resume(struct radeon_device *rdev)
4443 WREG32(RLC_LB_CNTL, 0); 4522 WREG32(RLC_LB_CNTL, 0);
4444 WREG32(RLC_LB_CNTR_MAX, 0xffffffff); 4523 WREG32(RLC_LB_CNTR_MAX, 0xffffffff);
4445 WREG32(RLC_LB_CNTR_INIT, 0); 4524 WREG32(RLC_LB_CNTR_INIT, 0);
4525 WREG32(RLC_LB_INIT_CU_MASK, 0xffffffff);
4446 4526
4447 WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); 4527 WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
4448 WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); 4528 WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
@@ -4457,6 +4537,8 @@ static int si_rlc_resume(struct radeon_device *rdev)
4457 } 4537 }
4458 WREG32(RLC_UCODE_ADDR, 0); 4538 WREG32(RLC_UCODE_ADDR, 0);
4459 4539
4540 si_enable_lbpw(rdev, si_lbpw_supported(rdev));
4541
4460 si_rlc_start(rdev); 4542 si_rlc_start(rdev);
4461 4543
4462 return 0; 4544 return 0;