net/ixgbe/base: refactor internal PHY mode determination
[dpdk.git] / drivers / net / ixgbe / base / ixgbe_phy.c
index eb89071..6ed685e 100644 (file)
@@ -109,8 +109,8 @@ STATIC u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2)
  *
  * Returns an error code on error.
  */
-STATIC s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
-                                              u16 reg, u16 *val, bool lock)
+s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg,
+                                       u16 *val, bool lock)
 {
        u32 swfw_mask = hw->phy.phy_semaphore_mask;
        int max_retry = 10;
@@ -121,6 +121,8 @@ STATIC s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
        u8 reg_high;
        u8 csum;
 
+       if (hw->mac.type >= ixgbe_mac_X550)
+               max_retry = 3;
        reg_high = ((reg >> 7) & 0xFE) | 1;     /* Indicate read combined */
        csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF);
        csum = ~csum;
@@ -177,37 +179,6 @@ fail:
        return IXGBE_ERR_I2C;
 }
 
-/**
- * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
- * @hw: pointer to the hardware structure
- * @addr: I2C bus address to read from
- * @reg: I2C device register to read from
- * @val: pointer to location to receive read value
- *
- * Returns an error code on error.
- **/
-STATIC s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
-                                          u16 reg, u16 *val)
-{
-       return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
-}
-
-/**
- * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
- * @hw: pointer to the hardware structure
- * @addr: I2C bus address to read from
- * @reg: I2C device register to read from
- * @val: pointer to location to receive read value
- *
- * Returns an error code on error.
- **/
-STATIC s32
-ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
-                                        u16 reg, u16 *val)
-{
-       return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
-}
-
 /**
  * ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation
  * @hw: pointer to the hardware structure
@@ -218,8 +189,8 @@ ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
  *
  * Returns an error code on error.
  */
-STATIC s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
-                                               u16 reg, u16 val, bool lock)
+s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg,
+                                        u16 val, bool lock)
 {
        u32 swfw_mask = hw->phy.phy_semaphore_mask;
        int max_retry = 1;
@@ -273,37 +244,6 @@ fail:
        return IXGBE_ERR_I2C;
 }
 
-/**
- * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
- * @hw: pointer to the hardware structure
- * @addr: I2C bus address to write to
- * @reg: I2C device register to write to
- * @val: value to write
- *
- * Returns an error code on error.
- **/
-STATIC s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
-                                           u8 addr, u16 reg, u16 val)
-{
-       return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
-}
-
-/**
- * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
- * @hw: pointer to the hardware structure
- * @addr: I2C bus address to write to
- * @reg: I2C device register to write to
- * @val: value to write
- *
- * Returns an error code on error.
- **/
-STATIC s32
-ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
-                                         u8 addr, u16 reg, u16 val)
-{
-       return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
-}
-
 /**
  *  ixgbe_init_phy_ops_generic - Inits PHY function ptrs
  *  @hw: pointer to the hardware structure
@@ -335,12 +275,6 @@ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw)
        phy->ops.i2c_bus_clear = ixgbe_i2c_bus_clear;
        phy->ops.identify_sfp = ixgbe_identify_module_generic;
        phy->sfp_type = ixgbe_sfp_type_unknown;
-       phy->ops.read_i2c_combined = ixgbe_read_i2c_combined_generic;
-       phy->ops.write_i2c_combined = ixgbe_write_i2c_combined_generic;
-       phy->ops.read_i2c_combined_unlocked =
-                               ixgbe_read_i2c_combined_generic_unlocked;
-       phy->ops.write_i2c_combined_unlocked =
-                               ixgbe_write_i2c_combined_generic_unlocked;
        phy->ops.read_i2c_byte_unlocked = ixgbe_read_i2c_byte_generic_unlocked;
        phy->ops.write_i2c_byte_unlocked =
                                ixgbe_write_i2c_byte_generic_unlocked;
@@ -492,7 +426,7 @@ s32 ixgbe_get_phy_id(struct ixgbe_hw *hw)
 
 /**
  *  ixgbe_get_phy_type_from_id - Get the phy type
- *  @hw: pointer to hardware structure
+ *  @phy_id: PHY ID information
  *
  **/
 enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
@@ -505,7 +439,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
        case TN1010_PHY_ID:
                phy_type = ixgbe_phy_tn;
                break;
-       case X550_PHY_ID:
+       case X550_PHY_ID1:
+       case X550_PHY_ID2:
+       case X550_PHY_ID3:
        case X540_PHY_ID:
                phy_type = ixgbe_phy_aq;
                break;
@@ -522,8 +458,6 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
                phy_type = ixgbe_phy_unknown;
                break;
        }
-
-       DEBUGOUT1("phy type found is %d\n", phy_type);
        return phy_type;
 }
 
@@ -827,7 +761,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
 
        if (hw->mac.type == ixgbe_mac_X550) {
                if (speed & IXGBE_LINK_SPEED_5GB_FULL) {
-                       /* Set or unset auto-negotiation 1G advertisement */
+                       /* Set or unset auto-negotiation 5G advertisement */
                        hw->phy.ops.read_reg(hw,
                                IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
                                IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
@@ -845,7 +779,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
                }
 
                if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) {
-                       /* Set or unset auto-negotiation 1G advertisement */
+                       /* Set or unset auto-negotiation 2.5G advertisement */
                        hw->phy.ops.read_reg(hw,
                                IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
                                IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
@@ -947,54 +881,70 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
                hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
 
        /* Setup link based on the new speed settings */
-       hw->phy.ops.setup_link(hw);
+       ixgbe_setup_phy_link(hw);
 
        return IXGBE_SUCCESS;
 }
 
 /**
- *  ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
- *  @hw: pointer to hardware structure
- *  @speed: pointer to link speed
- *  @autoneg: boolean auto-negotiation value
+ * ixgbe_get_copper_speeds_supported - Get copper link speeds from phy
+ * @hw: pointer to hardware structure
  *
- *  Determines the supported link capabilities by reading the PHY auto
- *  negotiation register.
+ * Determines the supported link capabilities by reading the PHY auto
+ * negotiation register.
  **/
-s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
-                                              ixgbe_link_speed *speed,
-                                              bool *autoneg)
+static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)
 {
        s32 status;
        u16 speed_ability;
 
-       DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic");
-
-       *speed = 0;
-       *autoneg = true;
-
        status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
                                      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
                                      &speed_ability);
+       if (status)
+               return status;
 
-       if (status == IXGBE_SUCCESS) {
-               if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
-                       *speed |= IXGBE_LINK_SPEED_10GB_FULL;
-               if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
-                       *speed |= IXGBE_LINK_SPEED_1GB_FULL;
-               if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M)
-                       *speed |= IXGBE_LINK_SPEED_100_FULL;
+       if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL;
+       if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL;
+       if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M)
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_X550:
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
+               hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
+               break;
+       case ixgbe_mac_X550EM_x:
+               hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
+               break;
+       default:
+               break;
        }
 
-       /* Internal PHY does not support 100 Mbps */
-       if (hw->mac.type == ixgbe_mac_X550EM_x)
-               *speed &= ~IXGBE_LINK_SPEED_100_FULL;
+       return status;
+}
 
-       if (hw->mac.type == ixgbe_mac_X550) {
-               *speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
-               *speed |= IXGBE_LINK_SPEED_5GB_FULL;
-       }
+/**
+ *  ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
+ *  @hw: pointer to hardware structure
+ *  @speed: pointer to link speed
+ *  @autoneg: boolean auto-negotiation value
+ **/
+s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
+                                              ixgbe_link_speed *speed,
+                                              bool *autoneg)
+{
+       s32 status = IXGBE_SUCCESS;
 
+       DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic");
+
+       *autoneg = true;
+       if (!hw->phy.speeds_supported)
+               status = ixgbe_get_copper_speeds_supported(hw);
+
+       *speed = hw->phy.speeds_supported;
        return status;
 }
 
@@ -1690,6 +1640,9 @@ s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
                goto out;
        }
 
+       /* LAN ID is needed for I2C access */
+       hw->mac.ops.set_lan_id(hw);
+
        status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
                                             &identifier);
 
@@ -1704,9 +1657,6 @@ s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
 
        hw->phy.id = identifier;
 
-       /* LAN ID is needed for sfp_type determination */
-       hw->mac.ops.set_lan_id(hw);
-
        status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_10GBE_COMP,
                                             &comp_codes_10g);
 
@@ -2045,6 +1995,8 @@ STATIC s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset,
 
        DEBUGFUNC("ixgbe_read_i2c_byte_generic");
 
+       if (hw->mac.type >= ixgbe_mac_X550)
+               max_retry = 3;
        if (ixgbe_is_sfp_probe(hw, byte_offset, dev_addr))
                max_retry = IXGBE_SFP_DETECT_RETRIES;
 
@@ -2711,6 +2663,9 @@ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on)
        u32 status;
        u16 reg;
 
+       if (!on && ixgbe_mng_present(hw))
+               return 0;
+
        status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
                                      &reg);