|
@@ -58,6 +58,10 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
|
|
|
ixgbe_link_speed speed,
|
|
|
bool autoneg_wait_to_complete);
|
|
|
static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
|
|
|
+static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
|
|
|
+ u8 dev_addr, u8 *data);
|
|
|
+static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
|
|
|
+ u8 dev_addr, u8 data);
|
|
|
|
|
|
static bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
|
|
|
{
|
|
@@ -219,6 +223,25 @@ static s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
|
|
|
struct ixgbe_mac_info *mac = &hw->mac;
|
|
|
struct ixgbe_phy_info *phy = &hw->phy;
|
|
|
s32 ret_val = 0;
|
|
|
+ u32 esdp;
|
|
|
+
|
|
|
+ if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
|
|
|
+ /* Store flag indicating I2C bus access control unit. */
|
|
|
+ hw->phy.qsfp_shared_i2c_bus = true;
|
|
|
+
|
|
|
+ /* Initialize access to QSFP+ I2C bus */
|
|
|
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
|
+ esdp |= IXGBE_ESDP_SDP0_DIR;
|
|
|
+ esdp &= ~IXGBE_ESDP_SDP1_DIR;
|
|
|
+ esdp &= ~IXGBE_ESDP_SDP0;
|
|
|
+ esdp &= ~IXGBE_ESDP_SDP0_NATIVE;
|
|
|
+ esdp &= ~IXGBE_ESDP_SDP1_NATIVE;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+
|
|
|
+ phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_82599;
|
|
|
+ phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_82599;
|
|
|
+ }
|
|
|
|
|
|
/* Identify the PHY or SFP module */
|
|
|
ret_val = phy->ops.identify(hw);
|
|
@@ -397,6 +420,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
|
|
|
case IXGBE_DEV_ID_82599_LS:
|
|
|
media_type = ixgbe_media_type_fiber_lco;
|
|
|
break;
|
|
|
+ case IXGBE_DEV_ID_82599_QSFP_SF_QP:
|
|
|
+ media_type = ixgbe_media_type_fiber_qsfp;
|
|
|
+ break;
|
|
|
default:
|
|
|
media_type = ixgbe_media_type_unknown;
|
|
|
break;
|
|
@@ -1951,7 +1977,7 @@ static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
|
|
|
if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
|
|
|
goto out;
|
|
|
else
|
|
|
- status = ixgbe_identify_sfp_module_generic(hw);
|
|
|
+ status = ixgbe_identify_module_generic(hw);
|
|
|
}
|
|
|
|
|
|
/* Set PHY type none if no PHY detected */
|
|
@@ -2057,10 +2083,12 @@ sfp_check:
|
|
|
switch (hw->phy.type) {
|
|
|
case ixgbe_phy_sfp_passive_tyco:
|
|
|
case ixgbe_phy_sfp_passive_unknown:
|
|
|
+ case ixgbe_phy_qsfp_passive_unknown:
|
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
|
|
|
break;
|
|
|
case ixgbe_phy_sfp_ftl_active:
|
|
|
case ixgbe_phy_sfp_active_unknown:
|
|
|
+ case ixgbe_phy_qsfp_active_unknown:
|
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
|
|
|
break;
|
|
|
case ixgbe_phy_sfp_avago:
|
|
@@ -2078,6 +2106,15 @@ sfp_check:
|
|
|
else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
|
|
|
physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T;
|
|
|
break;
|
|
|
+ case ixgbe_phy_qsfp_intel:
|
|
|
+ case ixgbe_phy_qsfp_unknown:
|
|
|
+ hw->phy.ops.read_i2c_eeprom(hw,
|
|
|
+ IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g);
|
|
|
+ if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
|
|
|
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
|
|
|
+ else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
|
|
|
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
|
|
|
+ break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
@@ -2315,6 +2352,112 @@ reset_pipeline_out:
|
|
|
return ret_val;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
+ * @byte_offset: byte offset to read
|
|
|
+ * @data: value read
|
|
|
+ *
|
|
|
+ * Performs byte read operation to SFP module's EEPROM over I2C interface at
|
|
|
+ * a specified device address.
|
|
|
+ **/
|
|
|
+static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
|
|
|
+ u8 dev_addr, u8 *data)
|
|
|
+{
|
|
|
+ u32 esdp;
|
|
|
+ s32 status;
|
|
|
+ s32 timeout = 200;
|
|
|
+
|
|
|
+ if (hw->phy.qsfp_shared_i2c_bus == true) {
|
|
|
+ /* Acquire I2C bus ownership. */
|
|
|
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
|
+ esdp |= IXGBE_ESDP_SDP0;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+
|
|
|
+ while (timeout) {
|
|
|
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
|
+ if (esdp & IXGBE_ESDP_SDP1)
|
|
|
+ break;
|
|
|
+
|
|
|
+ usleep_range(5000, 10000);
|
|
|
+ timeout--;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!timeout) {
|
|
|
+ hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
|
|
|
+ status = IXGBE_ERR_I2C;
|
|
|
+ goto release_i2c_access;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data);
|
|
|
+
|
|
|
+release_i2c_access:
|
|
|
+ if (hw->phy.qsfp_shared_i2c_bus == true) {
|
|
|
+ /* Release I2C bus ownership. */
|
|
|
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
|
+ esdp &= ~IXGBE_ESDP_SDP0;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+ }
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
+ * @byte_offset: byte offset to write
|
|
|
+ * @data: value to write
|
|
|
+ *
|
|
|
+ * Performs byte write operation to SFP module's EEPROM over I2C interface at
|
|
|
+ * a specified device address.
|
|
|
+ **/
|
|
|
+static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
|
|
|
+ u8 dev_addr, u8 data)
|
|
|
+{
|
|
|
+ u32 esdp;
|
|
|
+ s32 status;
|
|
|
+ s32 timeout = 200;
|
|
|
+
|
|
|
+ if (hw->phy.qsfp_shared_i2c_bus == true) {
|
|
|
+ /* Acquire I2C bus ownership. */
|
|
|
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
|
+ esdp |= IXGBE_ESDP_SDP0;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+
|
|
|
+ while (timeout) {
|
|
|
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
|
+ if (esdp & IXGBE_ESDP_SDP1)
|
|
|
+ break;
|
|
|
+
|
|
|
+ usleep_range(5000, 10000);
|
|
|
+ timeout--;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!timeout) {
|
|
|
+ hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
|
|
|
+ status = IXGBE_ERR_I2C;
|
|
|
+ goto release_i2c_access;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data);
|
|
|
+
|
|
|
+release_i2c_access:
|
|
|
+ if (hw->phy.qsfp_shared_i2c_bus == true) {
|
|
|
+ /* Release I2C bus ownership. */
|
|
|
+ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
|
+ esdp &= ~IXGBE_ESDP_SDP0;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+ }
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
static struct ixgbe_mac_operations mac_ops_82599 = {
|
|
|
.init_hw = &ixgbe_init_hw_generic,
|
|
|
.reset_hw = &ixgbe_reset_hw_82599,
|
|
@@ -2379,7 +2522,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82599 = {
|
|
|
|
|
|
static struct ixgbe_phy_operations phy_ops_82599 = {
|
|
|
.identify = &ixgbe_identify_phy_82599,
|
|
|
- .identify_sfp = &ixgbe_identify_sfp_module_generic,
|
|
|
+ .identify_sfp = &ixgbe_identify_module_generic,
|
|
|
.init = &ixgbe_init_phy_ops_82599,
|
|
|
.reset = &ixgbe_reset_phy_generic,
|
|
|
.read_reg = &ixgbe_read_phy_reg_generic,
|