drm/radeon: add support for ASPM on CIK asics

Enables PCIE ASPM (Active State Power Management) on
CIK asics.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alex Deucher 2013-04-04 13:58:09 -04:00
parent 8a7cd27679
commit 7235711a43
2 changed files with 222 additions and 1 deletions

View File

@ -62,6 +62,7 @@ extern void si_rlc_fini(struct radeon_device *rdev);
extern int si_rlc_init(struct radeon_device *rdev);
static void cik_rlc_stop(struct radeon_device *rdev);
static void cik_pcie_gen3_enable(struct radeon_device *rdev);
static void cik_program_aspm(struct radeon_device *rdev);
/*
* Indirect registers accessor
@ -5952,6 +5953,8 @@ static int cik_startup(struct radeon_device *rdev)
/* enable pcie gen2/3 link */
cik_pcie_gen3_enable(rdev);
/* enable aspm */
cik_program_aspm(rdev);
cik_mc_program(rdev);
@ -7212,3 +7215,151 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev)
udelay(1);
}
}
static void cik_program_aspm(struct radeon_device *rdev)
{
u32 data, orig;
bool disable_l0s = false, disable_l1 = false, disable_plloff_in_l1 = false;
bool disable_clkreq = false;
if (radeon_aspm == 0)
return;
/* XXX double check IGPs */
if (rdev->flags & RADEON_IS_IGP)
return;
if (!(rdev->flags & RADEON_IS_PCIE))
return;
orig = data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL);
data &= ~LC_XMIT_N_FTS_MASK;
data |= LC_XMIT_N_FTS(0x24) | LC_XMIT_N_FTS_OVERRIDE_EN;
if (orig != data)
WREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL, data);
orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL3);
data |= LC_GO_TO_RECOVERY;
if (orig != data)
WREG32_PCIE_PORT(PCIE_LC_CNTL3, data);
orig = data = RREG32_PCIE_PORT(PCIE_P_CNTL);
data |= P_IGNORE_EDB_ERR;
if (orig != data)
WREG32_PCIE_PORT(PCIE_P_CNTL, data);
orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL);
data &= ~(LC_L0S_INACTIVITY_MASK | LC_L1_INACTIVITY_MASK);
data |= LC_PMI_TO_L1_DIS;
if (!disable_l0s)
data |= LC_L0S_INACTIVITY(7);
if (!disable_l1) {
data |= LC_L1_INACTIVITY(7);
data &= ~LC_PMI_TO_L1_DIS;
if (orig != data)
WREG32_PCIE_PORT(PCIE_LC_CNTL, data);
if (!disable_plloff_in_l1) {
bool clk_req_support;
orig = data = RREG32_PCIE_PORT(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 (orig != data)
WREG32_PCIE_PORT(PB0_PIF_PWRDOWN_0, data);
orig = data = RREG32_PCIE_PORT(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 (orig != data)
WREG32_PCIE_PORT(PB0_PIF_PWRDOWN_1, data);
orig = data = RREG32_PCIE_PORT(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 (orig != data)
WREG32_PCIE_PORT(PB1_PIF_PWRDOWN_0, data);
orig = data = RREG32_PCIE_PORT(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 (orig != data)
WREG32_PCIE_PORT(PB1_PIF_PWRDOWN_1, data);
orig = data = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL);
data &= ~LC_DYN_LANES_PWR_STATE_MASK;
data |= LC_DYN_LANES_PWR_STATE(3);
if (orig != data)
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data);
if (!disable_clkreq) {
struct pci_dev *root = rdev->pdev->bus->self;
u32 lnkcap;
clk_req_support = false;
pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap);
if (lnkcap & PCI_EXP_LNKCAP_CLKPM)
clk_req_support = true;
} else {
clk_req_support = false;
}
if (clk_req_support) {
orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL2);
data |= LC_ALLOW_PDWN_IN_L1 | LC_ALLOW_PDWN_IN_L23;
if (orig != data)
WREG32_PCIE_PORT(PCIE_LC_CNTL2, data);
orig = data = RREG32_SMC(THM_CLK_CNTL);
data &= ~(CMON_CLK_SEL_MASK | TMON_CLK_SEL_MASK);
data |= CMON_CLK_SEL(1) | TMON_CLK_SEL(1);
if (orig != data)
WREG32_SMC(THM_CLK_CNTL, data);
orig = data = RREG32_SMC(MISC_CLK_CTRL);
data &= ~(DEEP_SLEEP_CLK_SEL_MASK | ZCLK_SEL_MASK);
data |= DEEP_SLEEP_CLK_SEL(1) | ZCLK_SEL(1);
if (orig != data)
WREG32_SMC(MISC_CLK_CTRL, data);
orig = data = RREG32_SMC(CG_CLKPIN_CNTL);
data &= ~BCLK_AS_XCLK;
if (orig != data)
WREG32_SMC(CG_CLKPIN_CNTL, data);
orig = data = RREG32_SMC(CG_CLKPIN_CNTL_2);
data &= ~FORCE_BIF_REFCLK_EN;
if (orig != data)
WREG32_SMC(CG_CLKPIN_CNTL_2, data);
orig = data = RREG32_SMC(MPLL_BYPASSCLK_SEL);
data &= ~MPLL_CLKOUT_SEL_MASK;
data |= MPLL_CLKOUT_SEL(4);
if (orig != data)
WREG32_SMC(MPLL_BYPASSCLK_SEL, data);
}
}
} else {
if (orig != data)
WREG32_PCIE_PORT(PCIE_LC_CNTL, data);
}
orig = data = RREG32_PCIE_PORT(PCIE_CNTL2);
data |= SLV_MEM_LS_EN | MST_MEM_LS_EN | REPLAY_MEM_LS_EN;
if (orig != data)
WREG32_PCIE_PORT(PCIE_CNTL2, data);
if (!disable_l0s) {
data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL);
if((data & LC_N_FTS_MASK) == LC_N_FTS_MASK) {
data = RREG32_PCIE_PORT(PCIE_LC_STATUS1);
if ((data & LC_REVERSE_XMIT) && (data & LC_REVERSE_RCVR)) {
orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL);
data &= ~LC_L0S_INACTIVITY_MASK;
if (orig != data)
WREG32_PCIE_PORT(PCIE_LC_CNTL, data);
}
}
}
}

View File

@ -32,10 +32,53 @@
#define GENERAL_PWRMGT 0xC0200000
# define GPU_COUNTER_CLK (1 << 15)
#define MPLL_BYPASSCLK_SEL 0xC050019C
# define MPLL_CLKOUT_SEL(x) ((x) << 8)
# define MPLL_CLKOUT_SEL_MASK 0xFF00
#define CG_CLKPIN_CNTL 0xC05001A0
# define XTALIN_DIVIDE (1 << 1)
# define BCLK_AS_XCLK (1 << 2)
#define CG_CLKPIN_CNTL_2 0xC05001A4
# define FORCE_BIF_REFCLK_EN (1 << 3)
# define MUX_TCLK_TO_XCLK (1 << 8)
#define THM_CLK_CNTL 0xC05001A8
# define CMON_CLK_SEL(x) ((x) << 0)
# define CMON_CLK_SEL_MASK 0xFF
# define TMON_CLK_SEL(x) ((x) << 8)
# define TMON_CLK_SEL_MASK 0xFF00
#define MISC_CLK_CTRL 0xC05001AC
# define DEEP_SLEEP_CLK_SEL(x) ((x) << 0)
# define DEEP_SLEEP_CLK_SEL_MASK 0xFF
# define ZCLK_SEL(x) ((x) << 8)
# define ZCLK_SEL_MASK 0xFF00
/* PCIE registers idx/data 0x38/0x3c */
#define PB0_PIF_PWRDOWN_0 0x1100012 /* PCIE */
# 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 0x1100013 /* PCIE */
# 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
#define PCIE_CNTL2 0x1001001c /* PCIE */
# define SLV_MEM_LS_EN (1 << 16)
# define MST_MEM_LS_EN (1 << 18)
# define REPLAY_MEM_LS_EN (1 << 19)
#define PCIE_LC_STATUS1 0x1400028 /* PCIE */
# define LC_REVERSE_RCVR (1 << 0)
# define LC_REVERSE_XMIT (1 << 1)
@ -44,6 +87,22 @@
# define LC_DETECTED_LINK_WIDTH_MASK (0x7 << 5)
# define LC_DETECTED_LINK_WIDTH_SHIFT 5
#define PCIE_P_CNTL 0x1400040 /* PCIE */
# define P_IGNORE_EDB_ERR (1 << 6)
#define PB1_PIF_PWRDOWN_0 0x2100012 /* PCIE */
#define PB1_PIF_PWRDOWN_1 0x2100013 /* PCIE */
#define PCIE_LC_CNTL 0x100100A0 /* PCIE */
# 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_LINK_WIDTH_CNTL 0x100100A2 /* PCIE */
# define LC_LINK_WIDTH_SHIFT 0
# define LC_LINK_WIDTH_MASK 0x7
@ -65,7 +124,12 @@
# 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_N_FTS_CNTL 0x100100a3 /* PCIE */
# define LC_XMIT_N_FTS(x) ((x) << 0)
# define LC_XMIT_N_FTS_MASK (0xff << 0)
# define LC_XMIT_N_FTS_SHIFT 0
# define LC_XMIT_N_FTS_OVERRIDE_EN (1 << 8)
# define LC_N_FTS_MASK (0xff << 24)
#define PCIE_LC_SPEED_CNTL 0x100100A4 /* PCIE */
# define LC_GEN2_EN_STRAP (1 << 0)
# define LC_GEN3_EN_STRAP (1 << 1)
@ -87,6 +151,12 @@
# define LC_OTHER_SIDE_EVER_SENT_GEN3 (1 << 20)
# define LC_OTHER_SIDE_SUPPORTS_GEN3 (1 << 21)
#define PCIE_LC_CNTL2 0x100100B1 /* PCIE */
# define LC_ALLOW_PDWN_IN_L1 (1 << 17)
# define LC_ALLOW_PDWN_IN_L23 (1 << 18)
#define PCIE_LC_CNTL3 0x100100B5 /* PCIE */
# define LC_GO_TO_RECOVERY (1 << 30)
#define PCIE_LC_CNTL4 0x100100B6 /* PCIE */
# define LC_REDO_EQ (1 << 5)
# define LC_SET_QUIESCE (1 << 13)