|
@@ -46,6 +46,8 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
|
|
ixgbe_link_speed speed,
|
|
ixgbe_link_speed speed,
|
|
bool autoneg,
|
|
bool autoneg,
|
|
bool autoneg_wait_to_complete);
|
|
bool autoneg_wait_to_complete);
|
|
|
|
+static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
|
|
|
|
+ u8 *eeprom_data);
|
|
|
|
|
|
/**
|
|
/**
|
|
*/
|
|
*/
|
|
@@ -53,6 +55,8 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
|
|
{
|
|
{
|
|
struct ixgbe_mac_info *mac = &hw->mac;
|
|
struct ixgbe_mac_info *mac = &hw->mac;
|
|
struct ixgbe_phy_info *phy = &hw->phy;
|
|
struct ixgbe_phy_info *phy = &hw->phy;
|
|
|
|
+ s32 ret_val = 0;
|
|
|
|
+ u16 list_offset, data_offset;
|
|
|
|
|
|
/* Call PHY identify routine to get the phy type */
|
|
/* Call PHY identify routine to get the phy type */
|
|
ixgbe_identify_phy_generic(hw);
|
|
ixgbe_identify_phy_generic(hw);
|
|
@@ -64,6 +68,27 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
|
|
phy->ops.get_firmware_version =
|
|
phy->ops.get_firmware_version =
|
|
&ixgbe_get_phy_firmware_version_tnx;
|
|
&ixgbe_get_phy_firmware_version_tnx;
|
|
break;
|
|
break;
|
|
|
|
+ case ixgbe_phy_nl:
|
|
|
|
+ phy->ops.reset = &ixgbe_reset_phy_nl;
|
|
|
|
+
|
|
|
|
+ /* Call SFP+ identify routine to get the SFP+ module type */
|
|
|
|
+ ret_val = phy->ops.identify_sfp(hw);
|
|
|
|
+ if (ret_val != 0)
|
|
|
|
+ goto out;
|
|
|
|
+ else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {
|
|
|
|
+ ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Check to see if SFP+ module is supported */
|
|
|
|
+ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
|
|
|
|
+ &list_offset,
|
|
|
|
+ &data_offset);
|
|
|
|
+ if (ret_val != 0) {
|
|
|
|
+ ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -82,7 +107,8 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
|
|
mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
|
|
mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
|
|
mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
|
|
mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+out:
|
|
|
|
+ return ret_val;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -191,7 +217,10 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
|
|
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
|
|
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
|
|
case IXGBE_DEV_ID_82598EB_CX4:
|
|
case IXGBE_DEV_ID_82598EB_CX4:
|
|
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
|
|
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
|
|
|
|
+ case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
|
|
|
|
+ case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
|
|
case IXGBE_DEV_ID_82598EB_XF_LR:
|
|
case IXGBE_DEV_ID_82598EB_XF_LR:
|
|
|
|
+ case IXGBE_DEV_ID_82598EB_SFP_LOM:
|
|
media_type = ixgbe_media_type_fiber;
|
|
media_type = ixgbe_media_type_fiber;
|
|
break;
|
|
break;
|
|
case IXGBE_DEV_ID_82598AT:
|
|
case IXGBE_DEV_ID_82598AT:
|
|
@@ -399,6 +428,46 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
|
|
{
|
|
{
|
|
u32 links_reg;
|
|
u32 links_reg;
|
|
u32 i;
|
|
u32 i;
|
|
|
|
+ u16 link_reg, adapt_comp_reg;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * SERDES PHY requires us to read link status from register 0xC79F.
|
|
|
|
+ * Bit 0 set indicates link is up/ready; clear indicates link down.
|
|
|
|
+ * 0xC00C is read to check that the XAUI lanes are active. Bit 0
|
|
|
|
+ * clear indicates active; set indicates inactive.
|
|
|
|
+ */
|
|
|
|
+ if (hw->phy.type == ixgbe_phy_nl) {
|
|
|
|
+ hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
|
|
|
|
+ hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
|
|
|
|
+ hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
|
|
|
|
+ &adapt_comp_reg);
|
|
|
|
+ if (link_up_wait_to_complete) {
|
|
|
|
+ for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
|
|
|
|
+ if ((link_reg & 1) &&
|
|
|
|
+ ((adapt_comp_reg & 1) == 0)) {
|
|
|
|
+ *link_up = true;
|
|
|
|
+ break;
|
|
|
|
+ } else {
|
|
|
|
+ *link_up = false;
|
|
|
|
+ }
|
|
|
|
+ msleep(100);
|
|
|
|
+ hw->phy.ops.read_reg(hw, 0xC79F,
|
|
|
|
+ IXGBE_TWINAX_DEV,
|
|
|
|
+ &link_reg);
|
|
|
|
+ hw->phy.ops.read_reg(hw, 0xC00C,
|
|
|
|
+ IXGBE_TWINAX_DEV,
|
|
|
|
+ &adapt_comp_reg);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0))
|
|
|
|
+ *link_up = true;
|
|
|
|
+ else
|
|
|
|
+ *link_up = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (*link_up == false)
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
|
|
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
|
|
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
|
|
if (link_up_wait_to_complete) {
|
|
if (link_up_wait_to_complete) {
|
|
@@ -424,6 +493,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
|
|
else
|
|
else
|
|
*speed = IXGBE_LINK_SPEED_1GB_FULL;
|
|
*speed = IXGBE_LINK_SPEED_1GB_FULL;
|
|
|
|
|
|
|
|
+out:
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -858,6 +928,69 @@ s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * ixgbe_read_i2c_eeprom_82598 - Read 8 bit EEPROM word of an SFP+ module
|
|
|
|
+ * over I2C interface through an intermediate phy.
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ * @byte_offset: EEPROM byte offset to read
|
|
|
|
+ * @eeprom_data: value read
|
|
|
|
+ *
|
|
|
|
+ * Performs byte read operation to SFP module's EEPROM over I2C interface.
|
|
|
|
+ **/
|
|
|
|
+s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
|
|
|
|
+ u8 *eeprom_data)
|
|
|
|
+{
|
|
|
|
+ s32 status = 0;
|
|
|
|
+ u16 sfp_addr = 0;
|
|
|
|
+ u16 sfp_data = 0;
|
|
|
|
+ u16 sfp_stat = 0;
|
|
|
|
+ u32 i;
|
|
|
|
+
|
|
|
|
+ if (hw->phy.type == ixgbe_phy_nl) {
|
|
|
|
+ /*
|
|
|
|
+ * phy SDA/SCL registers are at addresses 0xC30A to
|
|
|
|
+ * 0xC30D. These registers are used to talk to the SFP+
|
|
|
|
+ * module's EEPROM through the SDA/SCL (I2C) interface.
|
|
|
|
+ */
|
|
|
|
+ sfp_addr = (IXGBE_I2C_EEPROM_DEV_ADDR << 8) + byte_offset;
|
|
|
|
+ sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
|
|
|
|
+ hw->phy.ops.write_reg(hw,
|
|
|
|
+ IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
|
|
|
|
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
|
|
|
|
+ sfp_addr);
|
|
|
|
+
|
|
|
|
+ /* Poll status */
|
|
|
|
+ for (i = 0; i < 100; i++) {
|
|
|
|
+ hw->phy.ops.read_reg(hw,
|
|
|
|
+ IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
|
|
|
|
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
|
|
|
|
+ &sfp_stat);
|
|
|
|
+ sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
|
|
|
|
+ if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
|
|
|
|
+ break;
|
|
|
|
+ msleep(10);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) {
|
|
|
|
+ hw_dbg(hw, "EEPROM read did not pass.\n");
|
|
|
|
+ status = IXGBE_ERR_SFP_NOT_PRESENT;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Read data */
|
|
|
|
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
|
|
|
|
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);
|
|
|
|
+
|
|
|
|
+ *eeprom_data = (u8)(sfp_data >> 8);
|
|
|
|
+ } else {
|
|
|
|
+ status = IXGBE_ERR_PHY;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ return status;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
|
|
* ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
|
|
* @hw: pointer to hardware structure
|
|
* @hw: pointer to hardware structure
|
|
@@ -873,8 +1006,12 @@ s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
|
|
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
|
|
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
|
|
break;
|
|
break;
|
|
|
|
+ case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
|
|
|
|
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
|
|
|
|
+ break;
|
|
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
|
|
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
|
|
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
|
|
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
|
|
|
|
+ case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
|
|
break;
|
|
break;
|
|
case IXGBE_DEV_ID_82598EB_XF_LR:
|
|
case IXGBE_DEV_ID_82598EB_XF_LR:
|
|
@@ -884,6 +1021,24 @@ s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
|
|
physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
|
|
physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
|
|
IXGBE_PHYSICAL_LAYER_1000BASE_T);
|
|
IXGBE_PHYSICAL_LAYER_1000BASE_T);
|
|
break;
|
|
break;
|
|
|
|
+ case IXGBE_DEV_ID_82598EB_SFP_LOM:
|
|
|
|
+ hw->phy.ops.identify_sfp(hw);
|
|
|
|
+
|
|
|
|
+ switch (hw->phy.sfp_type) {
|
|
|
|
+ case ixgbe_sfp_type_da_cu:
|
|
|
|
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
|
|
|
|
+ break;
|
|
|
|
+ case ixgbe_sfp_type_sr:
|
|
|
|
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
|
|
|
|
+ break;
|
|
|
|
+ case ixgbe_sfp_type_lr:
|
|
|
|
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
|
|
default:
|
|
default:
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
|
|
@@ -935,12 +1090,13 @@ static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
|
|
|
|
|
|
static struct ixgbe_phy_operations phy_ops_82598 = {
|
|
static struct ixgbe_phy_operations phy_ops_82598 = {
|
|
.identify = &ixgbe_identify_phy_generic,
|
|
.identify = &ixgbe_identify_phy_generic,
|
|
- /* .identify_sfp = &ixgbe_identify_sfp_module_generic, */
|
|
|
|
|
|
+ .identify_sfp = &ixgbe_identify_sfp_module_generic,
|
|
.reset = &ixgbe_reset_phy_generic,
|
|
.reset = &ixgbe_reset_phy_generic,
|
|
.read_reg = &ixgbe_read_phy_reg_generic,
|
|
.read_reg = &ixgbe_read_phy_reg_generic,
|
|
.write_reg = &ixgbe_write_phy_reg_generic,
|
|
.write_reg = &ixgbe_write_phy_reg_generic,
|
|
.setup_link = &ixgbe_setup_phy_link_generic,
|
|
.setup_link = &ixgbe_setup_phy_link_generic,
|
|
.setup_link_speed = &ixgbe_setup_phy_link_speed_generic,
|
|
.setup_link_speed = &ixgbe_setup_phy_link_speed_generic,
|
|
|
|
+ .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598,
|
|
};
|
|
};
|
|
|
|
|
|
struct ixgbe_info ixgbe_82598_info = {
|
|
struct ixgbe_info ixgbe_82598_info = {
|