radeon: add function to configure PCIE lanes
authorAlex Deucher <alexdeucher@gmail.com>
Thu, 18 Sep 2008 20:07:41 +0000 (16:07 -0400)
committerAlex Deucher <alexdeucher@gmail.com>
Thu, 18 Sep 2008 20:07:41 +0000 (16:07 -0400)
linux-core/radeon_pm.c
linux-core/radeon_reg.h
shared-core/radeon_cp.c
shared-core/radeon_drv.h

index e9a6130..5d14384 100644 (file)
@@ -178,3 +178,63 @@ int radeon_resume(struct drm_device *dev)
 
        return 0;
 }
+
+bool radeon_set_pcie_lanes(struct drm_device *dev, int lanes)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       uint32_t link_width_cntl, mask;
+
+       /* 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 = RADEON_READ_PCIE(dev_priv, 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 true;
+
+       link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK |
+                            RADEON_PCIE_LC_RECONFIG_NOW |
+                            RADEON_PCIE_LC_RECONFIG_LATER |
+                            RADEON_PCIE_LC_SHORT_RECONFIG_EN);
+       link_width_cntl |= mask;
+       RADEON_WRITE_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+       RADEON_WRITE_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl | RADEON_PCIE_LC_RECONFIG_NOW);
+
+       /* wait for lane set to complete */
+       link_width_cntl = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+       while (link_width_cntl == 0xffffffff)
+               link_width_cntl = RADEON_READ_PCIE(dev_priv, 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 true;
+       else
+               return false;
+}
+
index e7f3081..c4bc7a8 100644 (file)
 #define RADEON_BUS_CNTL1                    0x0034
 #       define RADEON_BUS_WAIT_ON_LOCK_EN    (1 << 4)
 
+//#define RADEON_PCIE_INDEX                   0x0030
+//#define RADEON_PCIE_DATA                    0x0034
+#define RADEON_PCIE_LC_LINK_WIDTH_CNTL             0xa2 /* PCIE */
+#       define RADEON_PCIE_LC_LINK_WIDTH_SHIFT     0
+#       define RADEON_PCIE_LC_LINK_WIDTH_MASK      0x7
+#       define RADEON_PCIE_LC_LINK_WIDTH_X0        0
+#       define RADEON_PCIE_LC_LINK_WIDTH_X1        1
+#       define RADEON_PCIE_LC_LINK_WIDTH_X2        2
+#       define RADEON_PCIE_LC_LINK_WIDTH_X4        3
+#       define RADEON_PCIE_LC_LINK_WIDTH_X8        4
+#       define RADEON_PCIE_LC_LINK_WIDTH_X12       5
+#       define RADEON_PCIE_LC_LINK_WIDTH_X16       6
+#       define RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT  4
+#       define RADEON_PCIE_LC_LINK_WIDTH_RD_MASK   0x70
+#       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 RADEON_CACHE_CNTL                   0x1724
 #define RADEON_CACHE_LINE                   0x0f0c /* PCI */
 #define RADEON_CAPABILITIES_ID              0x0f50 /* PCI */
index 1ad005b..b934d3b 100644 (file)
@@ -235,7 +235,7 @@ void RADEON_WRITE_PLL(struct drm_radeon_private *dev_priv, int addr, uint32_t da
        radeon_pll_errata_after_data(dev_priv);
 }
 
-static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
+u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
 {
        RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
        return RADEON_READ(RADEON_PCIE_DATA);
index 82d9d00..25a07e3 100644 (file)
@@ -1298,6 +1298,7 @@ int radeon_resume(struct drm_device *dev);
 
 extern u32 RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr);
 extern void RADEON_WRITE_PLL(struct drm_radeon_private *dev_priv, int addr, uint32_t data);
+extern u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr);
 
 #define RADEON_WRITE_P(reg, val, mask)         \
 do {                                           \