mirror of
https://github.com/torvalds/linux.git
synced 2024-11-19 02:21:47 +00:00
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:
parent
792edd6957
commit
f52382d73e
@ -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);
|
||||
}
|
||||
|
@ -1323,7 +1323,48 @@
|
||||
#define DMA_PACKET_CONSTANT_FILL 0xd
|
||||
#define DMA_PACKET_NOP 0xf
|
||||
|
||||
/* PCIE link stuff */
|
||||
/* PIF PHY0 indirect regs */
|
||||
#define PB0_PIF_CNTL 0x10
|
||||
# define LS2_EXIT_TIME(x) ((x) << 17)
|
||||
# define LS2_EXIT_TIME_MASK (0x7 << 17)
|
||||
# define LS2_EXIT_TIME_SHIFT 17
|
||||
#define PB0_PIF_PAIRING 0x11
|
||||
# define MULTI_PIF (1 << 25)
|
||||
#define PB0_PIF_PWRDOWN_0 0x12
|
||||
# define PLL_POWER_STATE_IN_TXS2_0(x) ((x) << 7)
|
||||
# define PLL_POWER_STATE_IN_TXS2_0_MASK (0x7 << 7)
|
||||
# define PLL_POWER_STATE_IN_TXS2_0_SHIFT 7
|
||||
# define PLL_POWER_STATE_IN_OFF_0(x) ((x) << 10)
|
||||
# define PLL_POWER_STATE_IN_OFF_0_MASK (0x7 << 10)
|
||||
# define PLL_POWER_STATE_IN_OFF_0_SHIFT 10
|
||||
# define PLL_RAMP_UP_TIME_0(x) ((x) << 24)
|
||||
# define PLL_RAMP_UP_TIME_0_MASK (0x7 << 24)
|
||||
# define PLL_RAMP_UP_TIME_0_SHIFT 24
|
||||
#define PB0_PIF_PWRDOWN_1 0x13
|
||||
# define PLL_POWER_STATE_IN_TXS2_1(x) ((x) << 7)
|
||||
# define PLL_POWER_STATE_IN_TXS2_1_MASK (0x7 << 7)
|
||||
# define PLL_POWER_STATE_IN_TXS2_1_SHIFT 7
|
||||
# define PLL_POWER_STATE_IN_OFF_1(x) ((x) << 10)
|
||||
# define PLL_POWER_STATE_IN_OFF_1_MASK (0x7 << 10)
|
||||
# define PLL_POWER_STATE_IN_OFF_1_SHIFT 10
|
||||
# define PLL_RAMP_UP_TIME_1(x) ((x) << 24)
|
||||
# define PLL_RAMP_UP_TIME_1_MASK (0x7 << 24)
|
||||
# define PLL_RAMP_UP_TIME_1_SHIFT 24
|
||||
/* PIF PHY1 indirect regs */
|
||||
#define PB1_PIF_CNTL 0x10
|
||||
#define PB1_PIF_PAIRING 0x11
|
||||
#define PB1_PIF_PWRDOWN_0 0x12
|
||||
#define PB1_PIF_PWRDOWN_1 0x13
|
||||
/* PCIE PORT indirect regs */
|
||||
#define PCIE_LC_CNTL 0xa0
|
||||
# define LC_L0S_INACTIVITY(x) ((x) << 8)
|
||||
# define LC_L0S_INACTIVITY_MASK (0xf << 8)
|
||||
# define LC_L0S_INACTIVITY_SHIFT 8
|
||||
# define LC_L1_INACTIVITY(x) ((x) << 12)
|
||||
# define LC_L1_INACTIVITY_MASK (0xf << 12)
|
||||
# define LC_L1_INACTIVITY_SHIFT 12
|
||||
# define LC_PMI_TO_L1_DIS (1 << 16)
|
||||
# define LC_ASPM_TO_L1_DIS (1 << 24)
|
||||
#define PCIE_LC_TRAINING_CNTL 0xa1 /* PCIE_P */
|
||||
#define PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE_P */
|
||||
# define LC_LINK_WIDTH_SHIFT 0
|
||||
@ -1343,6 +1384,9 @@
|
||||
# define LC_SHORT_RECONFIG_EN (1 << 11)
|
||||
# define LC_UPCONFIGURE_SUPPORT (1 << 12)
|
||||
# define LC_UPCONFIGURE_DIS (1 << 13)
|
||||
# define LC_DYN_LANES_PWR_STATE(x) ((x) << 21)
|
||||
# define LC_DYN_LANES_PWR_STATE_MASK (0x3 << 21)
|
||||
# define LC_DYN_LANES_PWR_STATE_SHIFT 21
|
||||
#define PCIE_LC_SPEED_CNTL 0xa4 /* PCIE_P */
|
||||
# define LC_GEN2_EN_STRAP (1 << 0)
|
||||
# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 1)
|
||||
|
@ -173,6 +173,7 @@ extern void evergreen_irq_suspend(struct radeon_device *rdev);
|
||||
extern int evergreen_mc_init(struct radeon_device *rdev);
|
||||
extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
|
||||
extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
|
||||
extern void evergreen_program_aspm(struct radeon_device *rdev);
|
||||
extern void sumo_rlc_fini(struct radeon_device *rdev);
|
||||
extern int sumo_rlc_init(struct radeon_device *rdev);
|
||||
|
||||
@ -2076,6 +2077,8 @@ static int cayman_startup(struct radeon_device *rdev)
|
||||
|
||||
/* enable pcie gen2 link */
|
||||
evergreen_pcie_gen2_enable(rdev);
|
||||
/* enable aspm */
|
||||
evergreen_program_aspm(rdev);
|
||||
|
||||
if (rdev->flags & RADEON_IS_IGP) {
|
||||
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
|
||||
|
Loading…
Reference in New Issue
Block a user