|
@@ -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);
|
|
|
+}
|