net/ixgbe/base: add link MAC setup for X550a SFP+
authorBeilei Xing <beilei.xing@intel.com>
Thu, 23 Jun 2016 07:22:17 +0000 (15:22 +0800)
committerBruce Richardson <bruce.richardson@intel.com>
Mon, 27 Jun 2016 14:17:52 +0000 (16:17 +0200)
This patch updates ixgbe_setup_mac_link_sfp_x550a for X550 SFP+.
ixgbe_set_lan_id_multi_port_pcie has been updated to set the MAC
instance(0/1) which is needed when configuring the external PHY,
since X550a has two instances of MGPK. The MAC instance is read
from the EEPROM.

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

index ec61408..82a8416 100644 (file)
@@ -1020,13 +1020,15 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
  *  ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
  *  @hw: pointer to the HW structure
  *
- *  Determines the LAN function id by reading memory-mapped registers
- *  and swaps the port value if requested.
+ *  Determines the LAN function id by reading memory-mapped registers and swaps
+ *  the port value if requested, and set MAC instance for devices that share
+ *  CS4227.
  **/
 void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
 {
        struct ixgbe_bus_info *bus = &hw->bus;
        u32 reg;
+       u16 ee_ctrl_4;
 
        DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
 
@@ -1038,6 +1040,13 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
        reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
        if (reg & IXGBE_FACTPS_LFS)
                bus->func ^= 0x1;
+
+       /* Get MAC instance from EEPROM for configuring CS4227 */
+       if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) {
+               hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4);
+               bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >>
+                       IXGBE_EE_CTRL_4_INST_ID_SHIFT;
+       }
 }
 
 /**
index 1a5affe..281f9fa 100644 (file)
@@ -89,8 +89,11 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #define IXGBE_CS4227                   0xBE    /* CS4227 address */
 #define IXGBE_CS4227_GLOBAL_ID_LSB     0
+#define IXGBE_CS4227_GLOBAL_ID_MSB     1
 #define IXGBE_CS4227_SCRATCH           2
 #define IXGBE_CS4227_GLOBAL_ID_VALUE   0x03E5
+#define IXGBE_CS4223_PHY_ID            0x7003/* Quad port */
+#define IXGBE_CS4227_PHY_ID            0x3003/* Dual port */
 #define IXGBE_CS4227_RESET_PENDING     0x1357
 #define IXGBE_CS4227_RESET_COMPLETE    0x5AA5
 #define IXGBE_CS4227_RETRIES           15
index 7bd6f2c..0a35891 100644 (file)
@@ -1472,6 +1472,7 @@ struct ixgbe_dmac_config {
 #define IXGBE_CORECTL_WRITE_CMD                0x00010000
 
 /* Device Type definitions for new protocol MDIO commands */
+#define IXGBE_MDIO_ZERO_DEV_TYPE               0x0
 #define IXGBE_MDIO_PMA_PMD_DEV_TYPE            0x1
 #define IXGBE_MDIO_PCS_DEV_TYPE                        0x3
 #define IXGBE_MDIO_PHY_XS_DEV_TYPE             0x4
@@ -2247,6 +2248,9 @@ enum {
 #define IXGBE_PBANUM_PTR_GUARD         0xFAFA
 #define IXGBE_EEPROM_CHECKSUM          0x3F
 #define IXGBE_EEPROM_SUM               0xBABA
+#define IXGBE_EEPROM_CTRL_4            0x45
+#define IXGBE_EE_CTRL_4_INST_ID                0x10
+#define IXGBE_EE_CTRL_4_INST_ID_SHIFT  4
 #define IXGBE_PCIE_ANALOG_PTR          0x03
 #define IXGBE_ATLAS0_CONFIG_PTR                0x04
 #define IXGBE_PHY_PTR                  0x04
@@ -3630,6 +3634,7 @@ struct ixgbe_bus_info {
 
        u16 func;
        u16 lan_id;
+       u16 instance_id;
 };
 
 /* Flow control parameters */
@@ -4130,5 +4135,8 @@ struct ixgbe_hw {
 
 #define IXGBE_NW_MNG_IF_SEL            0x00011178
 #define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24)
+#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT 3
+#define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD       \
+               (0x1F << IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT)
 
 #endif /* _IXGBE_TYPE_H_ */
index 1834549..f129e8c 100644 (file)
@@ -1551,7 +1551,8 @@ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
                mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
                mac->ops.set_rate_select_speed =
                                        ixgbe_set_soft_rate_select_speed;
-               if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N)
+               if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) ||
+                   (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP))
                        mac->ops.setup_mac_link =
                                ixgbe_setup_mac_link_sfp_x550a;
                else
@@ -2207,8 +2208,9 @@ s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
                                   bool autoneg_wait_to_complete)
 {
        s32 ret_val;
-       u32 reg_val;
+       u16 reg_phy_ext;
        bool setup_linear = false;
+       u32 reg_slice, reg_phy_int, slice_offset;
 
        UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
 
@@ -2224,32 +2226,73 @@ s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
        if (ret_val != IXGBE_SUCCESS)
                return ret_val;
 
-       /* Configure internal PHY for native SFI */
-       ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
-                      IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
-                      IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) {
+               /* Configure internal PHY for native SFI */
+               ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
+                              IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
+                              IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
 
-       if (ret_val != IXGBE_SUCCESS)
-               return ret_val;
+               if (ret_val != IXGBE_SUCCESS)
+                       return ret_val;
+
+               if (setup_linear) {
+                       reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING;
+                       reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR;
+               } else {
+                       reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING;
+                       reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR;
+               }
+
+               ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
+                               IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
+                               IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
 
-       if (setup_linear) {
-               reg_val &= ~IXGBE_KRM_AN_CNTL_8_LIMITING;
-               reg_val |= IXGBE_KRM_AN_CNTL_8_LINEAR;
+               if (ret_val != IXGBE_SUCCESS)
+                       return ret_val;
+
+               /* Setup XFI/SFI internal link. */
+               ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
        } else {
-               reg_val |= IXGBE_KRM_AN_CNTL_8_LIMITING;
-               reg_val &= ~IXGBE_KRM_AN_CNTL_8_LINEAR;
-       }
+               /* Configure internal PHY for KR/KX. */
+               ixgbe_setup_kr_speed_x550em(hw, speed);
 
-       ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
-                       IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
-                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+               /* Get CS4227 MDIO address */
+               hw->phy.addr =
+                       (hw->phy.nw_mng_if_sel &
+                        IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD)
+                       >> IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
 
-       if (ret_val != IXGBE_SUCCESS)
-               return ret_val;
+               if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) {
+                       /* Find Address */
+                       DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n");
+                       return IXGBE_ERR_PHY_ADDR_INVALID;
+               }
+
+               /* Get external PHY device id */
+               ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,
+                                      IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
 
-       /* Setup XFI/SFI internal link. */
-       ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
+               if (ret_val != IXGBE_SUCCESS)
+                       return ret_val;
 
+               /* When configuring quad port CS4223, the MAC instance is part
+                * of the slice offset.
+                */
+               if (reg_phy_ext == IXGBE_CS4223_PHY_ID)
+                       slice_offset = (hw->bus.lan_id +
+                                       (hw->bus.instance_id << 1)) << 12;
+               else
+                       slice_offset = hw->bus.lan_id << 12;
+
+               /* Configure CS4227/CS4223 LINE side to proper mode. */
+               reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
+               if (setup_linear)
+                       reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+               else
+                       reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+               ret_val = hw->phy.ops.write_reg(hw, reg_slice,
+                                       IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
+       }
        return ret_val;
 }