drm/radeon: add support for ASPM on evergreen asics
Enables PCIE ASPM (Active State Power Management) on evergreen-cayman asics. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@@ -136,6 +136,7 @@ static u32 sumo_rlc_save_restore_register_list_size = ARRAY_SIZE(sumo_rlc_save_r
|
||||
static void evergreen_gpu_init(struct radeon_device *rdev);
|
||||
void evergreen_fini(struct radeon_device *rdev);
|
||||
void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
|
||||
void evergreen_program_aspm(struct radeon_device *rdev);
|
||||
extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev,
|
||||
int ring, u32 cp_int_cntl);
|
||||
|
||||
@@ -5071,6 +5072,8 @@ static int evergreen_startup(struct radeon_device *rdev)
|
||||
|
||||
/* enable pcie gen2 link */
|
||||
evergreen_pcie_gen2_enable(rdev);
|
||||
/* enable aspm */
|
||||
evergreen_program_aspm(rdev);
|
||||
|
||||
if (ASIC_IS_DCE5(rdev)) {
|
||||
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
|
||||
@@ -5468,3 +5471,150 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
|
||||
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
|
||||
}
|
||||
}
|
||||
|
||||
void evergreen_program_aspm(struct radeon_device *rdev)
|
||||
{
|
||||
u32 data, orig;
|
||||
u32 pcie_lc_cntl, pcie_lc_cntl_old;
|
||||
bool disable_l0s, disable_l1 = false, disable_plloff_in_l1 = false;
|
||||
/* fusion_platform = true
|
||||
* if the system is a fusion system
|
||||
* (APU or DGPU in a fusion system).
|
||||
* todo: check if the system is a fusion platform.
|
||||
*/
|
||||
bool fusion_platform = false;
|
||||
|
||||
if (!(rdev->flags & RADEON_IS_PCIE))
|
||||
return;
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_CYPRESS:
|
||||
case CHIP_HEMLOCK:
|
||||
case CHIP_JUNIPER:
|
||||
case CHIP_REDWOOD:
|
||||
case CHIP_CEDAR:
|
||||
case CHIP_SUMO:
|
||||
case CHIP_SUMO2:
|
||||
case CHIP_PALM:
|
||||
case CHIP_ARUBA:
|
||||
disable_l0s = true;
|
||||
break;
|
||||
default:
|
||||
disable_l0s = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
fusion_platform = true; /* XXX also dGPUs in a fusion system */
|
||||
|
||||
data = orig = RREG32_PIF_PHY0(PB0_PIF_PAIRING);
|
||||
if (fusion_platform)
|
||||
data &= ~MULTI_PIF;
|
||||
else
|
||||
data |= MULTI_PIF;
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY0(PB0_PIF_PAIRING, data);
|
||||
|
||||
data = orig = RREG32_PIF_PHY1(PB1_PIF_PAIRING);
|
||||
if (fusion_platform)
|
||||
data &= ~MULTI_PIF;
|
||||
else
|
||||
data |= MULTI_PIF;
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY1(PB1_PIF_PAIRING, data);
|
||||
|
||||
pcie_lc_cntl = pcie_lc_cntl_old = RREG32_PCIE_PORT(PCIE_LC_CNTL);
|
||||
pcie_lc_cntl &= ~(LC_L0S_INACTIVITY_MASK | LC_L1_INACTIVITY_MASK);
|
||||
if (!disable_l0s) {
|
||||
if (rdev->family >= CHIP_BARTS)
|
||||
pcie_lc_cntl |= LC_L0S_INACTIVITY(7);
|
||||
else
|
||||
pcie_lc_cntl |= LC_L0S_INACTIVITY(3);
|
||||
}
|
||||
|
||||
if (!disable_l1) {
|
||||
if (rdev->family >= CHIP_BARTS)
|
||||
pcie_lc_cntl |= LC_L1_INACTIVITY(7);
|
||||
else
|
||||
pcie_lc_cntl |= LC_L1_INACTIVITY(8);
|
||||
|
||||
if (!disable_plloff_in_l1) {
|
||||
data = orig = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0);
|
||||
data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK);
|
||||
data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0, data);
|
||||
|
||||
data = orig = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1);
|
||||
data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK);
|
||||
data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1, data);
|
||||
|
||||
data = orig = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0);
|
||||
data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK);
|
||||
data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0, data);
|
||||
|
||||
data = orig = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1);
|
||||
data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK);
|
||||
data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1, data);
|
||||
|
||||
if (rdev->family >= CHIP_BARTS) {
|
||||
data = orig = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0);
|
||||
data &= ~PLL_RAMP_UP_TIME_0_MASK;
|
||||
data |= PLL_RAMP_UP_TIME_0(4);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0, data);
|
||||
|
||||
data = orig = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1);
|
||||
data &= ~PLL_RAMP_UP_TIME_1_MASK;
|
||||
data |= PLL_RAMP_UP_TIME_1(4);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1, data);
|
||||
|
||||
data = orig = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0);
|
||||
data &= ~PLL_RAMP_UP_TIME_0_MASK;
|
||||
data |= PLL_RAMP_UP_TIME_0(4);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0, data);
|
||||
|
||||
data = orig = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1);
|
||||
data &= ~PLL_RAMP_UP_TIME_1_MASK;
|
||||
data |= PLL_RAMP_UP_TIME_1(4);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1, data);
|
||||
}
|
||||
|
||||
data = orig = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL);
|
||||
data &= ~LC_DYN_LANES_PWR_STATE_MASK;
|
||||
data |= LC_DYN_LANES_PWR_STATE(3);
|
||||
if (data != orig)
|
||||
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data);
|
||||
|
||||
if (rdev->family >= CHIP_BARTS) {
|
||||
data = orig = RREG32_PIF_PHY0(PB0_PIF_CNTL);
|
||||
data &= ~LS2_EXIT_TIME_MASK;
|
||||
data |= LS2_EXIT_TIME(1);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY0(PB0_PIF_CNTL, data);
|
||||
|
||||
data = orig = RREG32_PIF_PHY1(PB1_PIF_CNTL);
|
||||
data &= ~LS2_EXIT_TIME_MASK;
|
||||
data |= LS2_EXIT_TIME(1);
|
||||
if (data != orig)
|
||||
WREG32_PIF_PHY1(PB1_PIF_CNTL, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* evergreen parts only */
|
||||
if (rdev->family < CHIP_BARTS)
|
||||
pcie_lc_cntl |= LC_PMI_TO_L1_DIS;
|
||||
|
||||
if (pcie_lc_cntl != pcie_lc_cntl_old)
|
||||
WREG32_PCIE_PORT(PCIE_LC_CNTL, pcie_lc_cntl);
|
||||
}
|
||||
|
Reference in New Issue
Block a user