Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3313e3d4 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie
Browse files

drm/radeon/kms: add pcie get/set lane support for r6xx/r7xx/evergreen

parent f598aa75
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -558,10 +558,7 @@ int rv370_get_pcie_lanes(struct radeon_device *rdev)

	/* FIXME wait for idle */

	if (rdev->family < CHIP_R600)
	link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
	else
		link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL);

	switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) {
	case RADEON_PCIE_LC_LINK_WIDTH_X0:
+118 −0
Original line number Diff line number Diff line
@@ -3531,3 +3531,121 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
	} else
		WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
}

void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes)
{
	u32 link_width_cntl, mask, target_reg;

	if (rdev->flags & RADEON_IS_IGP)
		return;

	if (!(rdev->flags & RADEON_IS_PCIE))
		return;

	/* x2 cards have a special sequence */
	if (ASIC_IS_X2(rdev))
		return;

	/* FIXME wait for idle */

	switch (lanes) {
	case 0:
		mask = RADEON_PCIE_LC_LINK_WIDTH_X0;
		break;
	case 1:
		mask = RADEON_PCIE_LC_LINK_WIDTH_X1;
		break;
	case 2:
		mask = RADEON_PCIE_LC_LINK_WIDTH_X2;
		break;
	case 4:
		mask = RADEON_PCIE_LC_LINK_WIDTH_X4;
		break;
	case 8:
		mask = RADEON_PCIE_LC_LINK_WIDTH_X8;
		break;
	case 12:
		mask = RADEON_PCIE_LC_LINK_WIDTH_X12;
		break;
	case 16:
	default:
		mask = RADEON_PCIE_LC_LINK_WIDTH_X16;
		break;
	}

	link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL);

	if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) ==
	    (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT))
		return;

	if (link_width_cntl & R600_PCIE_LC_UPCONFIGURE_DIS)
		return;

	link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK |
			     RADEON_PCIE_LC_RECONFIG_NOW |
			     R600_PCIE_LC_RENEGOTIATE_EN |
			     R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE);
	link_width_cntl |= mask;

	WREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);

        /* some northbridges can renegotiate the link rather than requiring                                  
         * a complete re-config.                                                                             
         * e.g., AMD 780/790 northbridges (pci ids: 0x5956, 0x5957, 0x5958, etc.)                            
         */
        if (link_width_cntl & R600_PCIE_LC_RENEGOTIATION_SUPPORT)
		link_width_cntl |= R600_PCIE_LC_RENEGOTIATE_EN | R600_PCIE_LC_UPCONFIGURE_SUPPORT;
        else
		link_width_cntl |= R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE;

	WREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl |
						       RADEON_PCIE_LC_RECONFIG_NOW));

        if (rdev->family >= CHIP_RV770)
		target_reg = R700_TARGET_AND_CURRENT_PROFILE_INDEX;
        else
		target_reg = R600_TARGET_AND_CURRENT_PROFILE_INDEX;

        /* wait for lane set to complete */
        link_width_cntl = RREG32(target_reg);
        while (link_width_cntl == 0xffffffff)
		link_width_cntl = RREG32(target_reg);

}

int r600_get_pcie_lanes(struct radeon_device *rdev)
{
	u32 link_width_cntl;

	if (rdev->flags & RADEON_IS_IGP)
		return 0;

	if (!(rdev->flags & RADEON_IS_PCIE))
		return 0;

	/* x2 cards have a special sequence */
	if (ASIC_IS_X2(rdev))
		return 0;

	/* FIXME wait for idle */

	link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL);

	switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) {
	case RADEON_PCIE_LC_LINK_WIDTH_X0:
		return 0;
	case RADEON_PCIE_LC_LINK_WIDTH_X1:
		return 1;
	case RADEON_PCIE_LC_LINK_WIDTH_X2:
		return 2;
	case RADEON_PCIE_LC_LINK_WIDTH_X4:
		return 4;
	case RADEON_PCIE_LC_LINK_WIDTH_X8:
		return 8;
	case RADEON_PCIE_LC_LINK_WIDTH_X16:
	default:
		return 16;
	}
}
+8 −0
Original line number Diff line number Diff line
@@ -1317,6 +1317,14 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
		(rdev->family == CHIP_RV410) ||			\
		(rdev->family == CHIP_RS400) ||			\
		(rdev->family == CHIP_RS480))
#define ASIC_IS_X2(rdev) ((rdev->ddev->pdev->device == 0x9441) || \
		(rdev->ddev->pdev->device == 0x9443) || \
		(rdev->ddev->pdev->device == 0x944B) || \
		(rdev->ddev->pdev->device == 0x9506) || \
		(rdev->ddev->pdev->device == 0x9509) || \
		(rdev->ddev->pdev->device == 0x950F) || \
		(rdev->ddev->pdev->device == 0x689C) || \
		(rdev->ddev->pdev->device == 0x689D))
#define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600))
#define ASIC_IS_DCE2(rdev) ((rdev->family == CHIP_RS600)  ||	\
			    (rdev->family == CHIP_RS690)  ||	\
+7 −7
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ static void radeon_register_accessor_init(struct radeon_device *rdev)
		rdev->mc_rreg = &rs600_mc_rreg;
		rdev->mc_wreg = &rs600_mc_wreg;
	}
	if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_RV740)) {
	if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_HEMLOCK)) {
		rdev->pciep_rreg = &r600_pciep_rreg;
		rdev->pciep_wreg = &r600_pciep_wreg;
	}
@@ -631,8 +631,8 @@ static struct radeon_asic r600_asic = {
	.set_engine_clock = &radeon_atom_set_engine_clock,
	.get_memory_clock = &radeon_atom_get_memory_clock,
	.set_memory_clock = &radeon_atom_set_memory_clock,
	.get_pcie_lanes = &rv370_get_pcie_lanes,
	.set_pcie_lanes = NULL,
	.get_pcie_lanes = &r600_get_pcie_lanes,
	.set_pcie_lanes = &r600_set_pcie_lanes,
	.set_clock_gating = NULL,
	.set_surface_reg = r600_set_surface_reg,
	.clear_surface_reg = r600_clear_surface_reg,
@@ -725,8 +725,8 @@ static struct radeon_asic rv770_asic = {
	.set_engine_clock = &radeon_atom_set_engine_clock,
	.get_memory_clock = &radeon_atom_get_memory_clock,
	.set_memory_clock = &radeon_atom_set_memory_clock,
	.get_pcie_lanes = &rv370_get_pcie_lanes,
	.set_pcie_lanes = NULL,
	.get_pcie_lanes = &r600_get_pcie_lanes,
	.set_pcie_lanes = &r600_set_pcie_lanes,
	.set_clock_gating = &radeon_atom_set_clock_gating,
	.set_surface_reg = r600_set_surface_reg,
	.clear_surface_reg = r600_clear_surface_reg,
@@ -772,8 +772,8 @@ static struct radeon_asic evergreen_asic = {
	.set_engine_clock = &radeon_atom_set_engine_clock,
	.get_memory_clock = &radeon_atom_get_memory_clock,
	.set_memory_clock = &radeon_atom_set_memory_clock,
	.get_pcie_lanes = NULL,
	.set_pcie_lanes = NULL,
	.get_pcie_lanes = &r600_get_pcie_lanes,
	.set_pcie_lanes = &r600_set_pcie_lanes,
	.set_clock_gating = NULL,
	.set_surface_reg = r600_set_surface_reg,
	.clear_surface_reg = r600_clear_surface_reg,
+2 −0
Original line number Diff line number Diff line
@@ -284,6 +284,8 @@ extern void r600_pm_misc(struct radeon_device *rdev);
extern void r600_pm_init_profile(struct radeon_device *rdev);
extern void rs780_pm_init_profile(struct radeon_device *rdev);
extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes);
extern int r600_get_pcie_lanes(struct radeon_device *rdev);

/*
 * rv770,rv730,rv710,rv740
Loading