From 8d99994ec50da579ba438525788ced469fb9bef8 Mon Sep 17 00:00:00 2001 From: Wenzhuo Lu Date: Wed, 24 Jun 2015 11:26:08 +0800 Subject: [PATCH] ixgbe/base: add X550em KR/iXFI internal link mode support This patch adds support for x550em KR/iXFI internal link modes. The initial x550em-10GBASET and x550em-SFP designs use iXFI internal link mode between the internal PHY and the external PHY. However future designs will use a KR internal link. This patch is intended to future proof the driver by adding the KR internal link support in the driver now. Signed-off-by: Wenzhuo Lu Acked-by: Helin Zhang --- drivers/net/ixgbe/base/ixgbe_type.h | 4 + drivers/net/ixgbe/base/ixgbe_x550.c | 123 +++++++++++++++++++--------- 2 files changed, 89 insertions(+), 38 deletions(-) diff --git a/drivers/net/ixgbe/base/ixgbe_type.h b/drivers/net/ixgbe/base/ixgbe_type.h index f2b9de3aea..e3e4eb591e 100644 --- a/drivers/net/ixgbe/base/ixgbe_type.h +++ b/drivers/net/ixgbe/base/ixgbe_type.h @@ -3732,6 +3732,7 @@ struct ixgbe_phy_info { bool multispeed_fiber; bool reset_if_overtemp; bool qsfp_shared_i2c_bus; + u32 nw_mng_if_sel; }; #include "ixgbe_mbx.h" @@ -3907,4 +3908,7 @@ struct ixgbe_hw { #define IXGBE_SB_IOSF_TARGET_KX4_PHY 1 #define IXGBE_SB_IOSF_TARGET_KX4_PCS 2 +#define IXGBE_NW_MNG_IF_SEL 0x00011178 +#define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24) + #endif /* _IXGBE_TYPE_H_ */ diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c index 9590fe1c28..5d65c60098 100644 --- a/drivers/net/ixgbe/base/ixgbe_x550.c +++ b/drivers/net/ixgbe/base/ixgbe_x550.c @@ -1418,6 +1418,48 @@ STATIC s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) return status; } +/** + * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. + * @hw: pointer to hardware structure + * @speed: link speed + * + * Configures the integrated KR PHY. + **/ +STATIC s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, + ixgbe_link_speed speed) +{ + s32 status; + u32 reg_val; + + status = ixgbe_read_iosf_sb_reg_x550(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + if (status) + return status; + + reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; + reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | + IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); + reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | + IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); + + /* Advertise 10G support. */ + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; + + /* Advertise 1G support. */ + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; + + /* Restart auto-negotiation. */ + reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; + status = ixgbe_write_iosf_sb_reg_x550(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + + return status; +} + /** * ixgbe_init_phy_ops_X550em - PHY/SFP specific init * @hw: pointer to hardware structure @@ -1429,6 +1471,7 @@ STATIC s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) { struct ixgbe_phy_info *phy = &hw->phy; + ixgbe_link_speed speed; s32 ret_val; DEBUGFUNC("ixgbe_init_phy_ops_X550em"); @@ -1439,6 +1482,18 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; ixgbe_setup_mux_ctl(hw); + /* Save NW management interface connected on board. This is used + * to determine internal PHY mode. + */ + phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); + + /* If internal PHY mode is KR, then initialize KR link */ + if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { + speed = IXGBE_LINK_SPEED_10GB_FULL | + IXGBE_LINK_SPEED_1GB_FULL; + ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); + } + phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em; } @@ -1465,8 +1520,23 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) phy->ops.write_reg = ixgbe_write_phy_reg_x550em; break; case ixgbe_phy_x550em_ext_t: - phy->ops.setup_internal_link = - ixgbe_setup_internal_phy_t_x550em; + /* Save NW management interface connected on board. This is used + * to determine internal PHY mode + */ + phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); + + /* If internal link mode is XFI, then setup iXFI internal link, + * else setup KR now. + */ + if (!(phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { + phy->ops.setup_internal_link = + ixgbe_setup_internal_phy_t_x550em; + } else { + speed = IXGBE_LINK_SPEED_10GB_FULL | + IXGBE_LINK_SPEED_1GB_FULL; + ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); + } + phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; phy->ops.reset = ixgbe_reset_phy_t_X550em; @@ -1640,34 +1710,7 @@ s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) **/ s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) { - s32 status; - u32 reg_val; - - status = ixgbe_read_iosf_sb_reg_x550(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); - if (status) - return status; - - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; - reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | - IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); - - /* Advertise 10G support. */ - if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; - - /* Advertise 1G support. */ - if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; - - /* Restart auto-negotiation. */ - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; - status = ixgbe_write_iosf_sb_reg_x550(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); - - return status; + return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); } /** @@ -1821,10 +1864,10 @@ STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) } /** - * ixgbe_setup_mac_link_sfp_x550em - Configure the CS4227 & KR PHY for SFP + * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP * @hw: pointer to hardware structure * - * Configure the external CS4227 PHY and the integrated KR PHY for SFP support. + * Configure the external PHY and the integrated KR PHY for SFP support. **/ s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, ixgbe_link_speed speed, @@ -1876,8 +1919,9 @@ s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, reg_val); - /* Configure the internal PHY. */ - ret_val = ixgbe_setup_ixfi_x550em(hw, &speed); + /* If internal link mode is XFI, then setup XFI internal link. */ + if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) + ret_val = ixgbe_setup_ixfi_x550em(hw, &speed); return ret_val; } @@ -2939,7 +2983,7 @@ s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) return status; if (lsc) - return ixgbe_setup_internal_phy_t_x550em(hw); + return ixgbe_setup_internal_phy(hw); return IXGBE_SUCCESS; } @@ -2972,10 +3016,13 @@ s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, else force_speed = IXGBE_LINK_SPEED_1GB_FULL; - status = ixgbe_setup_ixfi_x550em(hw, &force_speed); + /* If internal link mode is XFI, then setup XFI internal link. */ + if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { + status = ixgbe_setup_ixfi_x550em(hw, &force_speed); - if (status != IXGBE_SUCCESS) - return status; + if (status != IXGBE_SUCCESS) + return status; + } return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete); } -- 2.20.1