]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drm/radeon/kms: add pcie get/set lane support for r6xx/r7xx/evergreen
authorAlex Deucher <alexdeucher@gmail.com>
Thu, 6 Jan 2011 23:49:34 +0000 (18:49 -0500)
committerDave Airlie <airlied@redhat.com>
Fri, 7 Jan 2011 04:11:13 +0000 (14:11 +1000)
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_reg.h

index 23fee54c3b753fe928d615a5214f096ecd94f568..fae5e709f270683db849c9dbce92aacca6f773fc 100644 (file)
@@ -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);
+       link_width_cntl = RREG32_PCIE(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:
index 279794c391e992c27f4e3e1e83c5409dc46722bc..60ad8c03081a51d6d4592f826e100a0d36f13dcf 100644 (file)
@@ -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;
+       }
+}
+
index aff8080026a16020716fe5da69e859772e48a85e..e9fb64c1e20bfea038dae94609ca5f2fd3aac886 100644 (file)
@@ -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)  ||    \
index 3d73fe484f4266d8892e6608766bf3a32ab22c94..53c62404795d4e63a75ea40186140c6a2e72701c 100644 (file)
@@ -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,
index 4970eda1bd4152c63c54191f228cdee5e57d8bf6..9ac71b8d1b9de3a1e72e80490c806a3aa6c6f5b2 100644 (file)
@@ -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
index 0a310b7f71c35a26dc50b6f780505376faf7f66a..3369ce984af15945967ce226a48091ec73fe7bb6 100644 (file)
 #       define RADEON_PCIE_LC_RECONFIG_NOW         (1 << 8)
 #       define RADEON_PCIE_LC_RECONFIG_LATER       (1 << 9)
 #       define RADEON_PCIE_LC_SHORT_RECONFIG_EN    (1 << 10)
+#       define R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE   (1 << 7)
+#       define R600_PCIE_LC_RENEGOTIATION_SUPPORT  (1 << 9)
+#       define R600_PCIE_LC_RENEGOTIATE_EN         (1 << 10)
+#       define R600_PCIE_LC_SHORT_RECONFIG_EN      (1 << 11)
+#       define R600_PCIE_LC_UPCONFIGURE_SUPPORT    (1 << 12)
+#       define R600_PCIE_LC_UPCONFIGURE_DIS        (1 << 13)
+
+#define R600_TARGET_AND_CURRENT_PROFILE_INDEX      0x70c
+#define R700_TARGET_AND_CURRENT_PROFILE_INDEX      0x66c
 
 #define RADEON_CACHE_CNTL                   0x1724
 #define RADEON_CACHE_LINE                   0x0f0c /* PCI */