net: thunderx: Add QSGMII interface type support
authorSunil Goutham <sgoutham@cavium.com>
Fri, 12 Aug 2016 11:21:32 +0000 (16:51 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sat, 13 Aug 2016 18:59:31 +0000 (11:59 -0700)
This patch adds support for QSGMII interface type to
the BGX driver. This type of interface is supported by
81xx SOC.

Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.h

index 9c3c273f45351555870b0d7eb50288e5784d8f45..0bf8d244185bf6a780b910edeed3827c85bb9756 100644 (file)
@@ -379,8 +379,9 @@ void bgx_lmac_internal_loopback(int node, int bgx_idx,
 }
 EXPORT_SYMBOL(bgx_lmac_internal_loopback);
 
-static int bgx_lmac_sgmii_init(struct bgx *bgx, int lmacid)
+static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
 {
+       int lmacid = lmac->lmacid;
        u64 cfg;
 
        bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_THRESH, 0x30);
@@ -409,6 +410,14 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, int lmacid)
        cfg |= (PCS_MRX_CTL_RST_AN | PCS_MRX_CTL_AN_EN);
        bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, cfg);
 
+       if (lmac->lmac_type == BGX_MODE_QSGMII) {
+               /* Disable disparity check for QSGMII */
+               cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_PCS_MISCX_CTL);
+               cfg &= ~PCS_MISC_CTL_DISP_EN;
+               bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MISCX_CTL, cfg);
+               return 0;
+       }
+
        if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
                         PCS_MRX_STATUS_AN_CPT, false)) {
                dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n");
@@ -650,6 +659,14 @@ static void bgx_poll_for_link(struct work_struct *work)
        queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 2);
 }
 
+static int phy_interface_mode(u8 lmac_type)
+{
+       if (lmac_type == BGX_MODE_QSGMII)
+               return PHY_INTERFACE_MODE_QSGMII;
+
+       return PHY_INTERFACE_MODE_SGMII;
+}
+
 static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
 {
        struct lmac *lmac;
@@ -658,9 +675,10 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
        lmac = &bgx->lmac[lmacid];
        lmac->bgx = bgx;
 
-       if (lmac->lmac_type == BGX_MODE_SGMII) {
+       if ((lmac->lmac_type == BGX_MODE_SGMII) ||
+           (lmac->lmac_type == BGX_MODE_QSGMII)) {
                lmac->is_sgmii = 1;
-               if (bgx_lmac_sgmii_init(bgx, lmacid))
+               if (bgx_lmac_sgmii_init(bgx, lmac))
                        return -1;
        } else {
                lmac->is_sgmii = 0;
@@ -697,7 +715,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
 
                if (phy_connect_direct(&lmac->netdev, lmac->phydev,
                                       bgx_lmac_handler,
-                                      PHY_INTERFACE_MODE_SGMII))
+                                      phy_interface_mode(lmac->lmac_type)))
                        return -ENODEV;
 
                phy_start_aneg(lmac->phydev);
@@ -799,6 +817,11 @@ static void bgx_init_hw(struct bgx *bgx)
                bgx_reg_write(bgx, 0, BGX_CMR_RX_STREERING + (i * 8), 0x00);
 }
 
+static u8 bgx_get_lane2sds_cfg(struct bgx *bgx, struct lmac *lmac)
+{
+       return (u8)(bgx_reg_read(bgx, lmac->lmacid, BGX_CMRX_CFG) & 0xFF);
+}
+
 static void bgx_print_qlm_mode(struct bgx *bgx, u8 lmacid)
 {
        struct device *dev = &bgx->pdev->dev;
@@ -838,12 +861,22 @@ static void bgx_print_qlm_mode(struct bgx *bgx, u8 lmacid)
                else
                        dev_info(dev, "%s: 40G_KR4\n", (char *)str);
                break;
-       default:
-               dev_info(dev, "%s: INVALID\n", (char *)str);
+       case BGX_MODE_QSGMII:
+               if ((lmacid == 0) &&
+                   (bgx_get_lane2sds_cfg(bgx, lmac) != lmacid))
+                       return;
+               if ((lmacid == 2) &&
+                   (bgx_get_lane2sds_cfg(bgx, lmac) == lmacid))
+                       return;
+               dev_info(dev, "%s: QSGMII\n", (char *)str);
+               break;
+       case BGX_MODE_INVALID:
+               /* Nothing to do */
+               break;
        }
 }
 
-static void lmac_set_lane2sds(struct lmac *lmac)
+static void lmac_set_lane2sds(struct bgx *bgx, struct lmac *lmac)
 {
        switch (lmac->lmac_type) {
        case BGX_MODE_SGMII:
@@ -857,6 +890,14 @@ static void lmac_set_lane2sds(struct lmac *lmac)
        case BGX_MODE_RXAUI:
                lmac->lane_to_sds = (lmac->lmacid) ? 0xE : 0x4;
                break;
+       case BGX_MODE_QSGMII:
+               /* There is no way to determine if DLM0/2 is QSGMII or
+                * DLM1/3 is configured to QSGMII as bootloader will
+                * configure all LMACs, so take whatever is configured
+                * by low level firmware.
+                */
+               lmac->lane_to_sds = bgx_get_lane2sds_cfg(bgx, lmac);
+               break;
        default:
                lmac->lane_to_sds = 0;
                break;
@@ -882,7 +923,7 @@ static void bgx_set_lmac_config(struct bgx *bgx, u8 idx)
                lmac->use_training =
                        bgx_reg_read(bgx, 0, BGX_SPUX_BR_PMD_CRTL) &
                                SPU_PMD_CRTL_TRAIN_EN;
-               lmac_set_lane2sds(lmac);
+               lmac_set_lane2sds(bgx, lmac);
                return;
        }
 
@@ -901,7 +942,7 @@ static void bgx_set_lmac_config(struct bgx *bgx, u8 idx)
                lmac->use_training =
                        bgx_reg_read(bgx, idx, BGX_SPUX_BR_PMD_CRTL) &
                                SPU_PMD_CRTL_TRAIN_EN;
-               lmac_set_lane2sds(lmac);
+               lmac_set_lane2sds(bgx, lmac);
 
                /* Set LMAC type of other lmac on same DLM i.e LMAC 1/3 */
                olmac = &bgx->lmac[idx + 1];
@@ -909,7 +950,7 @@ static void bgx_set_lmac_config(struct bgx *bgx, u8 idx)
                olmac->use_training =
                bgx_reg_read(bgx, idx + 1, BGX_SPUX_BR_PMD_CRTL) &
                        SPU_PMD_CRTL_TRAIN_EN;
-               lmac_set_lane2sds(olmac);
+               lmac_set_lane2sds(bgx, olmac);
        }
 }
 
@@ -920,7 +961,7 @@ static bool is_dlm0_in_bgx_mode(struct bgx *bgx)
        if (!bgx->is_81xx)
                return true;
 
-       lmac = &bgx->lmac[1];
+       lmac = &bgx->lmac[0];
        if (lmac->lmac_type == BGX_MODE_INVALID)
                return false;
 
@@ -946,7 +987,7 @@ static void bgx_get_qlm_mode(struct bgx *bgx)
        if (bgx->lmac_count > MAX_LMAC_PER_BGX)
                bgx->lmac_count = MAX_LMAC_PER_BGX;
 
-       for (idx = 0; idx < bgx->lmac_count; idx++)
+       for (idx = 0; idx < MAX_LMAC_PER_BGX; idx++)
                bgx_set_lmac_config(bgx, idx);
 
        if (!bgx->is_81xx) {
index 38e9fb4ae8c4a61857bbedb6aeb49d9a773497ff..0705863d2915e24360aaa3d26f7085bba516ac22 100644 (file)
 #define BGX_GMP_PCS_ANX_AN_RESULTS     0x30020
 #define BGX_GMP_PCS_SGM_AN_ADV         0x30068
 #define BGX_GMP_PCS_MISCX_CTL          0x30078
+#define  PCS_MISC_CTL_DISP_EN                  BIT_ULL(13)
 #define  PCS_MISC_CTL_GMX_ENO                  BIT_ULL(11)
 #define  PCS_MISC_CTL_SAMP_PT_MASK     0x7Full
 #define BGX_GMP_GMI_PRTX_CFG           0x38020