net/ixgbe/base: add SGMII link for X550
authorBeilei Xing <beilei.xing@intel.com>
Thu, 23 Jun 2016 07:22:10 +0000 (15:22 +0800)
committerBruce Richardson <bruce.richardson@intel.com>
Mon, 27 Jun 2016 14:17:52 +0000 (16:17 +0200)
This patch adds new phy type and media type to support
SGMII link for X550, and add ixgbe_setup_sgmii to support
SGMII link setup.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
drivers/net/ixgbe/base/ixgbe_type.h
drivers/net/ixgbe/base/ixgbe_x550.c

index 4dce2ac..493bd46 100644 (file)
@@ -3511,6 +3511,8 @@ enum ixgbe_phy_type {
        ixgbe_phy_qsfp_intel,
        ixgbe_phy_qsfp_unknown,
        ixgbe_phy_sfp_unsupported, /*Enforce bit set with unsupported module*/
+       ixgbe_phy_sgmii,
+       ixgbe_phy_m88,
        ixgbe_phy_generic
 };
 
@@ -3554,6 +3556,7 @@ enum ixgbe_media_type {
        ixgbe_media_type_fiber_lco,
        ixgbe_media_type_copper,
        ixgbe_media_type_backplane,
+       ixgbe_media_type_sgmii,
        ixgbe_media_type_cx4,
        ixgbe_media_type_virtual
 };
@@ -4059,6 +4062,7 @@ struct ixgbe_hw {
 #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010)
 #define IXGBE_KRM_LINK_CTRL_1(P)       ((P) ? 0x820C : 0x420C)
 #define IXGBE_KRM_AN_CNTL_1(P)         ((P) ? 0x822C : 0x422C)
+#define IXGBE_KRM_SGMII_CTRL(P)                ((P) ? 0x82A0 : 0x42A0)
 #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634)
 #define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638)
 #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P)        ((P) ? 0x8B00 : 0x4B00)
@@ -4072,6 +4076,8 @@ struct ixgbe_hw {
 #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK    (0x7 << 8)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G      (2 << 8)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G     (4 << 8)
+#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN         (1 << 12)
+#define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN     (1 << 13)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ          (1 << 14)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC          (1 << 15)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX           (1 << 16)
@@ -4084,6 +4090,9 @@ struct ixgbe_hw {
 #define IXGBE_KRM_AN_CNTL_1_SYM_PAUSE                  (1 << 28)
 #define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE                  (1 << 29)
 
+#define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D       (1 << 12)
+#define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D                (1 << 19)
+
 #define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN                        (1 << 6)
 #define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN           (1 << 15)
 #define IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN          (1 << 16)
index 0bbaa55..6c00b2a 100644 (file)
@@ -328,6 +328,39 @@ STATIC void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
        IXGBE_WRITE_FLUSH(hw);
 }
 
+/**
+ * ixgbe_identify_phy_1g - Get 1g PHY type based on device id
+ * @hw: pointer to hardware structure
+ *
+ * Returns error code
+ */
+static s32 ixgbe_identify_phy_1g(struct ixgbe_hw *hw)
+{
+       u16 phy_id_high;
+       u16 phy_id_low;
+       u32 val = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
+
+       hw->phy.addr = (val >> 3) & 0x1F;
+       val = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH,
+                                  hw->phy.addr, &phy_id_high);
+       if (val || phy_id_high == 0xFFFF) {
+               hw->phy.type = ixgbe_phy_sgmii;
+               return 0;
+       }
+
+       val = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW,
+                                  hw->phy.addr, &phy_id_low);
+       if (val)
+               return val;
+
+       hw->phy.id = (u32)phy_id_high << 16;
+       hw->phy.id |= phy_id_low & IXGBE_PHY_REVISION_MASK;
+       hw->phy.revision = (u32)phy_id_low & ~IXGBE_PHY_REVISION_MASK;
+       hw->phy.type = ixgbe_phy_m88;
+
+       return 0;
+}
+
 /**
  * ixgbe_identify_phy_x550em - Get PHY type based on device id
  * @hw: pointer to hardware structure
@@ -364,10 +397,11 @@ STATIC s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
                break;
        case IXGBE_DEV_ID_X550EM_X_1G_T:
        case IXGBE_DEV_ID_X550EM_X_10G_T:
-       case IXGBE_DEV_ID_X550EM_A_1G_T:
-       case IXGBE_DEV_ID_X550EM_A_1G_T_L:
        case IXGBE_DEV_ID_X550EM_A_10G_T:
                return ixgbe_identify_phy_generic(hw);
+       case IXGBE_DEV_ID_X550EM_A_1G_T:
+       case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+               return ixgbe_identify_phy_1g(hw);
        default:
                break;
        }
@@ -1286,11 +1320,14 @@ enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
                break;
        case IXGBE_DEV_ID_X550EM_X_1G_T:
        case IXGBE_DEV_ID_X550EM_X_10G_T:
-       case IXGBE_DEV_ID_X550EM_A_1G_T:
-       case IXGBE_DEV_ID_X550EM_A_1G_T_L:
        case IXGBE_DEV_ID_X550EM_A_10G_T:
                media_type = ixgbe_media_type_copper;
                break;
+       case IXGBE_DEV_ID_X550EM_A_1G_T:
+       case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+               media_type = ixgbe_media_type_sgmii;
+               hw->phy.type = ixgbe_phy_sgmii;
+               break;
        default:
                media_type = ixgbe_media_type_unknown;
                break;
@@ -1381,6 +1418,57 @@ s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
        return IXGBE_SUCCESS;
 }
 
+/**
+ * ixgbe_setup_sgmii - Set up link for sgmii
+ * @hw: pointer to hardware structure
+ */
+static s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+                            bool autoneg_wait_to_complete)
+{
+       struct ixgbe_mac_info *mac = &hw->mac;
+       u32 lval, sval;
+       s32 rc;
+       UNREFERENCED_2PARAMETER(speed, autoneg_wait_to_complete);
+
+       rc = mac->ops.read_iosf_sb_reg(hw,
+                                      IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                                      IXGBE_SB_IOSF_TARGET_KR_PHY, &lval);
+       if (rc)
+               return rc;
+
+       lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
+       lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
+       lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN;
+       lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN;
+       lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
+       rc = mac->ops.write_iosf_sb_reg(hw,
+                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                                       IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
+       if (rc)
+               return rc;
+
+       rc = mac->ops.read_iosf_sb_reg(hw,
+                                      IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
+                                      IXGBE_SB_IOSF_TARGET_KR_PHY, &sval);
+       if (rc)
+               return rc;
+
+       sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D;
+       sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D;
+       rc = mac->ops.write_iosf_sb_reg(hw,
+                                       IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id),
+                                       IXGBE_SB_IOSF_TARGET_KR_PHY, sval);
+       if (rc)
+               return rc;
+
+       lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+       rc = mac->ops.write_iosf_sb_reg(hw,
+                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                                       IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
+
+       return rc;
+}
+
 /**
  *  ixgbe_init_mac_link_ops_X550em - init mac link function pointers
  *  @hw: pointer to hardware structure
@@ -1391,8 +1479,8 @@ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_init_mac_link_ops_X550em");
 
-        switch (hw->mac.ops.get_media_type(hw)) {
-        case ixgbe_media_type_fiber:
+       switch (hw->mac.ops.get_media_type(hw)) {
+       case ixgbe_media_type_fiber:
                /* CS4227 does not support autoneg, so disable the laser control
                 * functions for SFP+ fiber
                 */
@@ -1408,9 +1496,14 @@ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
                mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
                mac->ops.check_link = ixgbe_check_link_t_X550em;
                break;
+       case ixgbe_media_type_backplane:
+               break;
+       case ixgbe_media_type_sgmii:
+               mac->ops.setup_link = ixgbe_setup_sgmii;
+               break;
        default:
                break;
-        }
+       }
 }
 
 /**
@@ -1447,8 +1540,19 @@ s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
                else
                        *speed = IXGBE_LINK_SPEED_10GB_FULL;
        } else {
-               *speed = IXGBE_LINK_SPEED_10GB_FULL |
-                        IXGBE_LINK_SPEED_1GB_FULL;
+               switch (hw->phy.type) {
+               case ixgbe_phy_m88:
+                       *speed = IXGBE_LINK_SPEED_100_FULL |
+                                IXGBE_LINK_SPEED_1GB_FULL;
+                       break;
+               case ixgbe_phy_sgmii:
+                       *speed = IXGBE_LINK_SPEED_1GB_FULL;
+                       break;
+               default:
+                       *speed = IXGBE_LINK_SPEED_10GB_FULL |
+                                IXGBE_LINK_SPEED_1GB_FULL;
+                       break;
+               }
                *autoneg = true;
        }
 
@@ -1742,6 +1846,11 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
                phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
                phy->ops.reset = ixgbe_reset_phy_t_X550em;
                break;
+       case ixgbe_phy_sgmii:
+               phy->ops.setup_link = NULL;
+               break;
+       case ixgbe_phy_m88:
+               break;
        default:
                break;
        }