Add identification support for new SFP/QSFP module types (e.g., 25G SR/CR) in the Amber-Lite NIC configuration flow.
Signed-off-by: Zaiyu Wang <zaiyuw...@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.c | 92 ++++++++++++++++++++++++----- drivers/net/txgbe/base/txgbe_phy.h | 23 ++++++++ drivers/net/txgbe/base/txgbe_regs.h | 5 +- drivers/net/txgbe/base/txgbe_type.h | 12 ++++ 4 files changed, 117 insertions(+), 15 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index ce6882e262..81e9aee295 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -774,10 +774,21 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) u8 identifier = 0; u8 comp_codes_1g = 0; u8 comp_codes_10g = 0; + u8 comp_codes_25g = 0; + u8 comp_copper_len = 0; u8 oui_bytes[3] = {0, 0, 0}; u8 cable_tech = 0; u8 cable_spec = 0; u16 enforce_sfp = 0; + u32 value; + + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) { + hw->phy.sfp_type = txgbe_sfp_type_not_present; + return TXGBE_ERR_SFP_NOT_PRESENT; + } + } if (hw->phy.media_type != txgbe_media_type_fiber) { hw->phy.sfp_type = txgbe_sfp_type_not_present; @@ -811,6 +822,16 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) if (err != 0) goto ERR_I2C; + err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_25GBE_COMP_CODES, + &comp_codes_25g); + if (err != 0) + goto ERR_I2C; + + err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_COPPER_LENGTH, + &comp_copper_len); + if (err != 0) + goto ERR_I2C; + err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_CABLE_TECHNOLOGY, &cable_tech); if (err != 0) @@ -832,12 +853,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) * 11 SFP_1g_sx_CORE0 - chip-specific * 12 SFP_1g_sx_CORE1 - chip-specific */ - if (cable_tech & TXGBE_SFF_CABLE_DA_PASSIVE) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; - } else if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_CABLE_SPEC_COMP, &cable_spec); if (err != 0) @@ -849,6 +865,17 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) } else { hw->phy.sfp_type = txgbe_sfp_type_unknown; } + } else if (comp_codes_25g == TXGBE_SFF_25GBASESR_CAPABLE || + comp_codes_25g == TXGBE_SFF_25GBASEER_CAPABLE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_sfp_type_25g_sr_core0; + else + hw->phy.sfp_type = txgbe_sfp_type_25g_sr_core1; + } else if (comp_codes_25g == TXGBE_SFF_25GBASELR_CAPABLE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_sfp_type_25g_lr_core0; + else + hw->phy.sfp_type = txgbe_sfp_type_25g_lr_core1; } else if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | TXGBE_SFF_10GBASELR_CAPABLE)) { @@ -876,11 +903,20 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) /* Determine if the SFP+ PHY is dual speed or not. */ hw->phy.multispeed_fiber = false; - if (((comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE)) || - ((comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE))) - hw->phy.multispeed_fiber = true; + if (hw->mac.type == txgbe_mac_aml) { + if ((comp_codes_25g == TXGBE_SFF_25GBASESR_CAPABLE || + comp_codes_25g == TXGBE_SFF_25GBASELR_CAPABLE || + comp_codes_25g == TXGBE_SFF_25GBASEER_CAPABLE) && + ((comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE) || + (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE))) + hw->phy.multispeed_fiber = true; + } else { + if (((comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) && + (comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE)) || + ((comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) && + (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE))) + hw->phy.multispeed_fiber = true; + } /* Determine PHY vendor */ if (hw->phy.type != txgbe_phy_nl) { @@ -938,7 +974,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) } /* Verify supported 1G SFP modules */ - if (comp_codes_10g == 0 && + if (comp_codes_10g == 0 && comp_codes_25g == 0 && !(hw->phy.sfp_type == txgbe_sfp_type_1g_cu_core1 || hw->phy.sfp_type == txgbe_sfp_type_1g_cu_core0 || hw->phy.sfp_type == txgbe_sfp_type_1g_lx_core0 || @@ -986,6 +1022,7 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) u8 cable_length = 0; u8 device_tech = 0; bool active_cable = false; + u32 value; if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { hw->phy.sfp_type = txgbe_sfp_type_not_present; @@ -993,6 +1030,16 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) goto out; } + if (hw->mac.type == txgbe_mac_aml40) { + /* config GPIO before read i2c */ + wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) { + hw->phy.sfp_type = txgbe_sfp_type_not_present; + return TXGBE_ERR_SFP_NOT_PRESENT; + } + } + err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, &identifier); ERR_I2C: @@ -1024,10 +1071,27 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) if (comp_codes_10g & TXGBE_SFF_QSFP_DA_PASSIVE_CABLE) { hw->phy.type = txgbe_phy_qsfp_unknown_passive; + if (hw->mac.type == txgbe_mac_aml40) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core1; + } else { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; + else + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; + } + } else if (comp_codes_10g & TXGBE_SFF_40GBASE_SR4) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; + } else if (comp_codes_10g & TXGBE_SFF_40GBASE_LR4) { if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; else - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } else if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | TXGBE_SFF_10GBASELR_CAPABLE)) { if (hw->bus.lan_id == 0) diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 4dfe18930c..79b866ea57 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -249,6 +249,8 @@ #define TXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define TXGBE_SFF_1GBE_COMP_CODES 0x06 #define TXGBE_SFF_10GBE_COMP_CODES 0x03 +#define TXGBE_SFF_25GBE_COMP_CODES 0x24 +#define TXGBE_SFF_COPPER_LENGTH 0x12 #define TXGBE_SFF_CABLE_TECHNOLOGY 0x08 #define TXGBE_SFF_CABLE_DA_PASSIVE 0x4 #define TXGBE_SFF_CABLE_DA_ACTIVE 0x8 @@ -275,6 +277,23 @@ #define TXGBE_SFF_1GBASET_CAPABLE 0x8 #define TXGBE_SFF_10GBASESR_CAPABLE 0x10 #define TXGBE_SFF_10GBASELR_CAPABLE 0x20 +#define TXGBE_SFF_25GBASESR_CAPABLE 0x2 +#define TXGBE_SFF_25GBASELR_CAPABLE 0x3 +#define TXGBE_SFF_25GBASEER_CAPABLE 0x4 +#define TXGBE_SFF_25GBASECR_91FEC 0xB +#define TXGBE_SFF_25GBASECR_74FEC 0xC +#define TXGBE_SFF_25GBASECR_NOFEC 0xD +#define TXGBE_SFF_40GBASE_SR_CAPABLE 0x10 +#define TXGBE_SFF_4x10GBASESR_CAP 0x11 +#define TXGBE_SFF_40GBASEPSM4_Parallel 0x12 +#define TXGBE_SFF_40GBASE_SWMD4_CAP 0x1f + +#define TXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4 +#define TXGBE_SFF_25GAUI_C2M_AOC_BER_5 0x1 +#define TXGBE_SFF_25GAUI_C2M_ACC_BER_5 0x8 +#define TXGBE_SFF_25GAUI_C2M_AOC_BER_12 0x18 +#define TXGBE_SFF_25GAUI_C2M_ACC_BER_12 0x19 + #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_1G 0x0 @@ -290,6 +309,10 @@ #define TXGBE_I2C_EEPROM_STATUS_FAIL 0x2 #define TXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3 +#define TXGBE_SFF_40GBASE_CR4 0x8 +#define TXGBE_SFF_40GBASE_SR4 0x4 +#define TXGBE_SFF_40GBASE_LR4 0x2 + /* EEPROM for SFF-8472 (dev_addr = 0xA2) */ #define TXGBE_I2C_EEPROM_DEV_ADDR2 0xA2 diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index a608206f28..03c517f055 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1601,7 +1601,10 @@ enum txgbe_5tuple_protocol { #define TXGBE_GPIOINTSTAT 0x014840 #define TXGBE_GPIORAWINTSTAT 0x014844 #define TXGBE_GPIOEOI 0x01484C - +#define TXGBE_GPIOEXT 0x014850 +#define TXGBE_SFP1_MOD_ABS_LS MS(2, 0x1) /* GPIO_EXT SFP ABSENT*/ +#define TXGBE_SFP1_RX_LOS_LS MS(3, 0x1) /* GPIO_EXT RX LOSS */ +#define TXGBE_SFP1_MOD_PRST_LS MS(4, 0x1) /* GPIO_EXT SFP ABSENT*/ #define TXGBE_ARBPOOLIDX 0x01820C #define TXGBE_ARBTXRATE 0x018404 diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index ab7e45a0bf..b6dce31473 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -214,6 +214,18 @@ enum txgbe_sfp_type { txgbe_sfp_type_1g_sx_core1, txgbe_sfp_type_1g_lx_core0, txgbe_sfp_type_1g_lx_core1, + txgbe_sfp_type_25g_sr_core0, + txgbe_sfp_type_25g_sr_core1, + txgbe_sfp_type_25g_lr_core0, + txgbe_sfp_type_25g_lr_core1, + txgbe_sfp_type_25g_aoc_core0, + txgbe_sfp_type_25g_aoc_core1, + txgbe_qsfp_type_40g_cu_core0, + txgbe_qsfp_type_40g_cu_core1, + txgbe_qsfp_type_40g_sr_core0, + txgbe_qsfp_type_40g_sr_core1, + txgbe_qsfp_type_40g_lr_core0, + txgbe_qsfp_type_40g_lr_core1, txgbe_sfp_type_not_present = 0xFFFE, txgbe_sfp_type_not_known = 0xFFFF }; -- 2.21.0.windows.1