vfio: fix FreeBSD build
[dpdk.git] / lib / librte_eal / linuxapp / kni / ethtool / igb / e1000_phy.c
index f6e4503..1934a30 100644 (file)
@@ -1,23 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2012 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
+  Copyright(c) 2007-2013 Intel Corporation.
 
   Contact Information:
   e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
@@ -27,7 +12,7 @@
 
 #include "e1000_api.h"
 
-static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
+static s32 e1000_wait_autoneg(struct e1000_hw *hw);
 /* Cable length tables */
 static const u16 e1000_m88_cable_length_table[] = {
        0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
@@ -90,7 +75,8 @@ void e1000_init_phy_ops_generic(struct e1000_hw *hw)
  *  e1000_null_set_page - No-op function, return 0
  *  @hw: pointer to the HW structure
  **/
-s32 e1000_null_set_page(struct e1000_hw *hw, u16 data)
+s32 e1000_null_set_page(struct e1000_hw E1000_UNUSEDARG *hw,
+                       u16 E1000_UNUSEDARG data)
 {
        DEBUGFUNC("e1000_null_set_page");
        return E1000_SUCCESS;
@@ -100,7 +86,8 @@ s32 e1000_null_set_page(struct e1000_hw *hw, u16 data)
  *  e1000_null_read_reg - No-op function, return 0
  *  @hw: pointer to the HW structure
  **/
-s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 e1000_null_read_reg(struct e1000_hw E1000_UNUSEDARG *hw,
+                       u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG *data)
 {
        DEBUGFUNC("e1000_null_read_reg");
        return E1000_SUCCESS;
@@ -110,7 +97,7 @@ s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data)
  *  e1000_null_phy_generic - No-op function, return void
  *  @hw: pointer to the HW structure
  **/
-void e1000_null_phy_generic(struct e1000_hw *hw)
+void e1000_null_phy_generic(struct e1000_hw E1000_UNUSEDARG *hw)
 {
        DEBUGFUNC("e1000_null_phy_generic");
        return;
@@ -120,7 +107,8 @@ void e1000_null_phy_generic(struct e1000_hw *hw)
  *  e1000_null_lplu_state - No-op function, return 0
  *  @hw: pointer to the HW structure
  **/
-s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active)
+s32 e1000_null_lplu_state(struct e1000_hw E1000_UNUSEDARG *hw,
+                         bool E1000_UNUSEDARG active)
 {
        DEBUGFUNC("e1000_null_lplu_state");
        return E1000_SUCCESS;
@@ -130,7 +118,8 @@ s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active)
  *  e1000_null_write_reg - No-op function, return 0
  *  @hw: pointer to the HW structure
  **/
-s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data)
+s32 e1000_null_write_reg(struct e1000_hw E1000_UNUSEDARG *hw,
+                        u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG data)
 {
        DEBUGFUNC("e1000_null_write_reg");
        return E1000_SUCCESS;
@@ -144,8 +133,10 @@ s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data)
  *  @data: data value read
  *
  **/
-s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
-                            u8 dev_addr, u8 *data)
+s32 e1000_read_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
+                            u8 E1000_UNUSEDARG byte_offset,
+                            u8 E1000_UNUSEDARG dev_addr,
+                            u8 E1000_UNUSEDARG *data)
 {
        DEBUGFUNC("e1000_read_i2c_byte_null");
        return E1000_SUCCESS;
@@ -159,8 +150,10 @@ s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
  *  @data: data value to write
  *
  **/
-s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset,
-                             u8 dev_addr, u8 data)
+s32 e1000_write_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
+                             u8 E1000_UNUSEDARG byte_offset,
+                             u8 E1000_UNUSEDARG dev_addr,
+                             u8 E1000_UNUSEDARG data)
 {
        DEBUGFUNC("e1000_write_i2c_byte_null");
        return E1000_SUCCESS;
@@ -264,8 +257,7 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                return -E1000_ERR_PARAM;
        }
 
-       /*
-        * Set up Op-code, Phy Address, and register offset in the MDI
+       /* Set up Op-code, Phy Address, and register offset in the MDI
         * Control register.  The MAC will take care of interfacing with the
         * PHY to retrieve the desired data.
         */
@@ -275,13 +267,12 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 
        E1000_WRITE_REG(hw, E1000_MDIC, mdic);
 
-       /*
-        * Poll the ready bit to see if the MDI read completed
+       /* Poll the ready bit to see if the MDI read completed
         * Increasing the time out as testing showed failures with
         * the lower time out
         */
        for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
-               usec_delay(50);
+               usec_delay_irq(50);
                mdic = E1000_READ_REG(hw, E1000_MDIC);
                if (mdic & E1000_MDIC_READY)
                        break;
@@ -294,6 +285,12 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                DEBUGOUT("MDI Error\n");
                return -E1000_ERR_PHY;
        }
+       if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
+               DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n",
+                         offset,
+                         (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
+               return -E1000_ERR_PHY;
+       }
        *data = (u16) mdic;
 
        return E1000_SUCCESS;
@@ -319,8 +316,7 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                return -E1000_ERR_PARAM;
        }
 
-       /*
-        * Set up Op-code, Phy Address, and register offset in the MDI
+       /* Set up Op-code, Phy Address, and register offset in the MDI
         * Control register.  The MAC will take care of interfacing with the
         * PHY to retrieve the desired data.
         */
@@ -331,13 +327,12 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 
        E1000_WRITE_REG(hw, E1000_MDIC, mdic);
 
-       /*
-        * Poll the ready bit to see if the MDI read completed
+       /* Poll the ready bit to see if the MDI read completed
         * Increasing the time out as testing showed failures with
         * the lower time out
         */
        for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
-               usec_delay(50);
+               usec_delay_irq(50);
                mdic = E1000_READ_REG(hw, E1000_MDIC);
                if (mdic & E1000_MDIC_READY)
                        break;
@@ -350,6 +345,12 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                DEBUGOUT("MDI Error\n");
                return -E1000_ERR_PHY;
        }
+       if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
+               DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n",
+                         offset,
+                         (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
+               return -E1000_ERR_PHY;
+       }
 
        return E1000_SUCCESS;
 }
@@ -370,8 +371,7 @@ s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data)
 
        DEBUGFUNC("e1000_read_phy_reg_i2c");
 
-       /*
-        * Set up Op-code, Phy Address, and register address in the I2CCMD
+       /* Set up Op-code, Phy Address, and register address in the I2CCMD
         * register.  The MAC will take care of interfacing with the
         * PHY to retrieve the desired data.
         */
@@ -429,8 +429,7 @@ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
        /* Swap the data bytes for the I2C interface */
        phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
 
-       /*
-        * Set up Op-code, Phy Address, and register address in the I2CCMD
+       /* Set up Op-code, Phy Address, and register address in the I2CCMD
         * register.  The MAC will take care of interfacing with the
         * PHY to retrieve the desired data.
         */
@@ -486,8 +485,7 @@ s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data)
                return -E1000_ERR_PHY;
        }
 
-       /*
-        * Set up Op-code, EEPROM Address,in the I2CCMD
+       /* Set up Op-code, EEPROM Address,in the I2CCMD
         * register. The MAC will take care of interfacing with the
         * EEPROM to retrieve the desired data.
         */
@@ -541,14 +539,12 @@ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
                DEBUGOUT("I2CCMD command address exceeds upper limit\n");
                return -E1000_ERR_PHY;
        }
-       /*
-        * The programming interface is 16 bits wide
+       /* The programming interface is 16 bits wide
         * so we need to read the whole word first
         * then update appropriate byte lane and write
         * the updated word back.
         */
-       /*
-        * Set up Op-code, EEPROM Address,in the I2CCMD
+       /* Set up Op-code, EEPROM Address,in the I2CCMD
         * register. The MAC will take care of interfacing
         * with an EEPROM to write the data given.
         */
@@ -558,8 +554,7 @@ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
        E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
        for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
                usec_delay(50);
-               /*
-                * Poll the ready bit to see if lastly
+               /* Poll the ready bit to see if lastly
                 * launched I2C operation completed
                 */
                i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
@@ -567,8 +562,7 @@ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
                        /* Check if this is READ or WRITE phase */
                        if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) ==
                            E1000_I2CCMD_OPCODE_READ) {
-                               /*
-                                * Write the selected byte
+                               /* Write the selected byte
                                 * lane and update whole word
                                 */
                                data_local = i2ccmd & 0xFF00;
@@ -1035,6 +1029,31 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
+       /* Set MDI/MDIX mode */
+       ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
+       if (ret_val)
+               return ret_val;
+       phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
+       /* Options:
+        *   0 - Auto (default)
+        *   1 - MDI mode
+        *   2 - MDI-X mode
+        */
+       switch (hw->phy.mdix) {
+       case 1:
+               break;
+       case 2:
+               phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX;
+               break;
+       case 0:
+       default:
+               phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX;
+               break;
+       }
+       ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
+       if (ret_val)
+               return ret_val;
+
        return e1000_set_master_slave_mode(hw);
 }
 
@@ -1063,8 +1082,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
 
        phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
 
-       /*
-        * Options:
+       /* Options:
         *   MDI/MDI-X = 0 (default)
         *   0 - Auto for all speeds
         *   1 - MDI mode
@@ -1089,15 +1107,14 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
                break;
        }
 
-       /*
-        * Options:
+       /* Options:
         *   disable_polarity_correction = 0 (default)
         *       Automatic Correction for Reversed Cable Polarity
         *   0 - Disabled
         *   1 - Enabled
         */
        phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
-       if (phy->disable_polarity_correction == 1)
+       if (phy->disable_polarity_correction)
                phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
 
        ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
@@ -1105,8 +1122,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
                return ret_val;
 
        if (phy->revision < E1000_REVISION_4) {
-               /*
-                * Force TX_CLK in the Extended PHY Specific Control Register
+               /* Force TX_CLK in the Extended PHY Specific Control Register
                 * to 25MHz clock.
                 */
                ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
@@ -1167,8 +1183,7 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Options:
+       /* Options:
         *   MDI/MDI-X = 0 (default)
         *   0 - Auto for all speeds
         *   1 - MDI mode
@@ -1196,18 +1211,31 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
                break;
        }
 
-       /*
-        * Options:
+       /* Options:
         *   disable_polarity_correction = 0 (default)
         *       Automatic Correction for Reversed Cable Polarity
         *   0 - Disabled
         *   1 - Enabled
         */
        phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
-       if (phy->disable_polarity_correction == 1)
+       if (phy->disable_polarity_correction)
                phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
 
        /* Enable downshift and setting it to X6 */
+       if (phy->id == M88E1543_E_PHY_ID) {
+               phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE;
+               ret_val =
+                   phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val = phy->ops.commit(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error committing the PHY changes\n");
+                       return ret_val;
+               }
+       }
+
        phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
        phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
        phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
@@ -1223,6 +1251,10 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
                return ret_val;
        }
 
+       ret_val = e1000_set_master_slave_mode(hw);
+       if (ret_val)
+               return ret_val;
+
        return E1000_SUCCESS;
 }
 
@@ -1250,8 +1282,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
                return ret_val;
        }
 
-       /*
-        * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
+       /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid
         * timeout issues when LFS is enabled.
         */
        msec_delay(100);
@@ -1289,8 +1320,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
 
        /* set auto-master slave resolution settings */
        if (hw->mac.autoneg) {
-               /*
-                * when autonegotiation advertisement is only 1000Mbps then we
+               /* when autonegotiation advertisement is only 1000Mbps then we
                 * should disable SmartSpeed and enable Auto MasterSlave
                 * resolution as hardware default.
                 */
@@ -1359,16 +1389,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                        return ret_val;
        }
 
-       /*
-        * Need to parse both autoneg_advertised and fc and set up
+       /* Need to parse both autoneg_advertised and fc and set up
         * the appropriate PHY registers.  First we will parse for
         * autoneg_advertised software override.  Since we can advertise
         * a plethora of combinations, we need to check each bit
         * individually.
         */
 
-       /*
-        * First we clear all the 10/100 mb speed bits in the Auto-Neg
+       /* First we clear all the 10/100 mb speed bits in the Auto-Neg
         * Advertisement Register (Address 4) and the 1000 mb speed bits in
         * the  1000Base-T Control Register (Address 9).
         */
@@ -1414,8 +1442,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
        }
 
-       /*
-        * Check for a software override of the flow control settings, and
+       /* Check for a software override of the flow control settings, and
         * setup the PHY advertisement registers accordingly.  If
         * auto-negotiation is enabled, then software will have to set the
         * "PAUSE" bits to the correct value in the Auto-Negotiation
@@ -1434,15 +1461,13 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
         */
        switch (hw->fc.current_mode) {
        case e1000_fc_none:
-               /*
-                * Flow control (Rx & Tx) is completely disabled by a
+               /* Flow control (Rx & Tx) is completely disabled by a
                 * software over-ride.
                 */
                mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
                break;
        case e1000_fc_rx_pause:
-               /*
-                * Rx Flow control is enabled, and Tx Flow control is
+               /* Rx Flow control is enabled, and Tx Flow control is
                 * disabled, by a software over-ride.
                 *
                 * Since there really isn't a way to advertise that we are
@@ -1454,16 +1479,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
                break;
        case e1000_fc_tx_pause:
-               /*
-                * Tx Flow control is enabled, and Rx Flow control is
+               /* Tx Flow control is enabled, and Rx Flow control is
                 * disabled, by a software over-ride.
                 */
                mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
                mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
                break;
        case e1000_fc_full:
-               /*
-                * Flow control (both Rx and Tx) is enabled by a software
+               /* Flow control (both Rx and Tx) is enabled by a software
                 * over-ride.
                 */
                mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
@@ -1503,17 +1526,15 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_copper_link_autoneg");
 
-       /*
-        * Perform some bounds checking on the autoneg advertisement
+       /* Perform some bounds checking on the autoneg advertisement
         * parameter.
         */
        phy->autoneg_advertised &= phy->autoneg_mask;
 
-       /*
-        * If autoneg_advertised is zero, we assume it was not defaulted
+       /* If autoneg_advertised is zero, we assume it was not defaulted
         * by the calling code so we set to advertise full capability.
         */
-       if (phy->autoneg_advertised == 0)
+       if (!phy->autoneg_advertised)
                phy->autoneg_advertised = phy->autoneg_mask;
 
        DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
@@ -1524,8 +1545,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
        }
        DEBUGOUT("Restarting Auto-Neg\n");
 
-       /*
-        * Restart auto-negotiation by setting the Auto Neg Enable bit and
+       /* Restart auto-negotiation by setting the Auto Neg Enable bit and
         * the Auto Neg Restart bit in the PHY control register.
         */
        ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
@@ -1537,12 +1557,11 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Does the user want to wait for Auto-Neg to complete here, or
+       /* Does the user want to wait for Auto-Neg to complete here, or
         * check at a later time (for example, callback routine).
         */
        if (phy->autoneg_wait_to_complete) {
-               ret_val = hw->mac.ops.wait_autoneg(hw);
+               ret_val = e1000_wait_autoneg(hw);
                if (ret_val) {
                        DEBUGOUT("Error while waiting for autoneg to complete\n");
                        return ret_val;
@@ -1571,16 +1590,14 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
        DEBUGFUNC("e1000_setup_copper_link_generic");
 
        if (hw->mac.autoneg) {
-               /*
-                * Setup autoneg and flow control advertisement and perform
+               /* Setup autoneg and flow control advertisement and perform
                 * autonegotiation.
                 */
                ret_val = e1000_copper_link_autoneg(hw);
                if (ret_val)
                        return ret_val;
        } else {
-               /*
-                * PHY will be set to 10H, 10F, 100H or 100F
+               /* PHY will be set to 10H, 10F, 100H or 100F
                 * depending on user settings.
                 */
                DEBUGOUT("Forcing Speed and Duplex\n");
@@ -1591,8 +1608,7 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
                }
        }
 
-       /*
-        * Check link status. Wait up to 100 microseconds for link to become
+       /* Check link status. Wait up to 100 microseconds for link to become
         * valid.
         */
        ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
@@ -1638,8 +1654,7 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Clear Auto-Crossover to force MDI manually.  IGP requires MDI
+       /* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
         * forced whenever speed and duplex are forced.
         */
        ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
@@ -1695,18 +1710,22 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_phy_force_speed_duplex_m88");
 
-       /*
-        * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
-        * forced whenever speed and duplex are forced.
-        */
-       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-       if (ret_val)
-               return ret_val;
+       /* I210 and I211 devices support Auto-Crossover in forced operation. */
+       if (phy->type != e1000_phy_i210) {
+               /* Clear Auto-Crossover to force MDI manually.  M88E1000
+                * requires MDI forced whenever speed and duplex are forced.
+                */
+               ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                           &phy_data);
+               if (ret_val)
+                       return ret_val;
 
-       phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-       ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-       if (ret_val)
-               return ret_val;
+               phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+               ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                            phy_data);
+               if (ret_val)
+                       return ret_val;
+       }
 
        DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
 
@@ -1740,6 +1759,8 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                        case I347AT4_E_PHY_ID:
                        case M88E1340M_E_PHY_ID:
                        case M88E1112_E_PHY_ID:
+                       case M88E1543_E_PHY_ID:
+                       case I210_I_PHY_ID:
                                reset_dsp = false;
                                break;
                        default:
@@ -1751,8 +1772,7 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                        if (!reset_dsp) {
                                DEBUGOUT("Link taking longer than expected.\n");
                        } else {
-                               /*
-                                * We didn't get link.
+                               /* We didn't get link.
                                 * Reset the DSP and cross our fingers.
                                 */
                                ret_val = phy->ops.write_reg(hw,
@@ -1780,12 +1800,15 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                hw->phy.id == M88E1340M_E_PHY_ID ||
                hw->phy.id == M88E1112_E_PHY_ID)
                return E1000_SUCCESS;
+       if (hw->phy.id == I210_I_PHY_ID)
+               return E1000_SUCCESS;
+       if ((hw->phy.id == M88E1543_E_PHY_ID))
+               return E1000_SUCCESS;
        ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
        if (ret_val)
                return ret_val;
 
-       /*
-        * Resetting the phy means we need to re-force TX_CLK in the
+       /* Resetting the phy means we need to re-force TX_CLK in the
         * Extended PHY Specific Control Register to 25MHz clock from
         * the reset value of 2.5MHz.
         */
@@ -1794,8 +1817,7 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * In addition, we must re-enable CRS on Tx for both half and full
+       /* In addition, we must re-enable CRS on Tx for both half and full
         * duplex.
         */
        ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
@@ -1920,11 +1942,10 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
        if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) {
                ctrl |= E1000_CTRL_SPD_100;
                *phy_ctrl |= MII_CR_SPEED_100;
-               *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
+               *phy_ctrl &= ~MII_CR_SPEED_1000;
                DEBUGOUT("Forcing 100mb\n");
        } else {
                ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
-               *phy_ctrl |= MII_CR_SPEED_10;
                *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
                DEBUGOUT("Forcing 10mb\n");
        }
@@ -1969,8 +1990,7 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
                                             data);
                if (ret_val)
                        return ret_val;
-               /*
-                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
                 * during Dx states where the power conservation is most
                 * important.  During driver activity we should enable
                 * SmartSpeed, so performance is maintained.
@@ -2042,6 +2062,7 @@ s32 e1000_check_downshift_generic(struct e1000_hw *hw)
        DEBUGFUNC("e1000_check_downshift_generic");
 
        switch (phy->type) {
+       case e1000_phy_i210:
        case e1000_phy_m88:
        case e1000_phy_gg82563:
                offset = M88E1000_PHY_SPEC_STATUS;
@@ -2085,9 +2106,9 @@ s32 e1000_check_polarity_m88(struct e1000_hw *hw)
        ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data);
 
        if (!ret_val)
-               phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY)
-                                     ? e1000_rev_polarity_reversed
-                                     : e1000_rev_polarity_normal;
+               phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY)
+                                      ? e1000_rev_polarity_reversed
+                                      : e1000_rev_polarity_normal);
 
        return ret_val;
 }
@@ -2109,8 +2130,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_check_polarity_igp");
 
-       /*
-        * Polarity is determined based on the speed of
+       /* Polarity is determined based on the speed of
         * our connection.
         */
        ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
@@ -2122,8 +2142,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
                offset = IGP01E1000_PHY_PCS_INIT_REG;
                mask = IGP01E1000_PHY_POLARITY_MASK;
        } else {
-               /*
-                * This really only applies to 10Mbps since
+               /* This really only applies to 10Mbps since
                 * there is no polarity for 100Mbps (always 0).
                 */
                offset = IGP01E1000_PHY_PORT_STATUS;
@@ -2133,9 +2152,9 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
        ret_val = phy->ops.read_reg(hw, offset, &data);
 
        if (!ret_val)
-               phy->cable_polarity = (data & mask)
-                                     ? e1000_rev_polarity_reversed
-                                     : e1000_rev_polarity_normal;
+               phy->cable_polarity = ((data & mask)
+                                      ? e1000_rev_polarity_reversed
+                                      : e1000_rev_polarity_normal);
 
        return ret_val;
 }
@@ -2154,8 +2173,7 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_check_polarity_ife");
 
-       /*
-        * Polarity is determined based on the reversal feature being enabled.
+       /* Polarity is determined based on the reversal feature being enabled.
         */
        if (phy->polarity_correction) {
                offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
@@ -2168,26 +2186,26 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw)
        ret_val = phy->ops.read_reg(hw, offset, &phy_data);
 
        if (!ret_val)
-               phy->cable_polarity = (phy_data & mask)
+               phy->cable_polarity = ((phy_data & mask)
                                       ? e1000_rev_polarity_reversed
-                                      : e1000_rev_polarity_normal;
+                                      : e1000_rev_polarity_normal);
 
        return ret_val;
 }
 
 /**
- *  e1000_wait_autoneg_generic - Wait for auto-neg completion
+ *  e1000_wait_autoneg - Wait for auto-neg completion
  *  @hw: pointer to the HW structure
  *
  *  Waits for auto-negotiation to complete or for the auto-negotiation time
  *  limit to expire, which ever happens first.
  **/
-s32 e1000_wait_autoneg_generic(struct e1000_hw *hw)
+static s32 e1000_wait_autoneg(struct e1000_hw *hw)
 {
        s32 ret_val = E1000_SUCCESS;
        u16 i, phy_status;
 
-       DEBUGFUNC("e1000_wait_autoneg_generic");
+       DEBUGFUNC("e1000_wait_autoneg");
 
        if (!hw->phy.ops.read_reg)
                return E1000_SUCCESS;
@@ -2205,8 +2223,7 @@ s32 e1000_wait_autoneg_generic(struct e1000_hw *hw)
                msec_delay(100);
        }
 
-       /*
-        * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
+       /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
         * has completed.
         */
        return ret_val;
@@ -2233,15 +2250,13 @@ s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                return E1000_SUCCESS;
 
        for (i = 0; i < iterations; i++) {
-               /*
-                * Some PHYs require the PHY_STATUS register to be read
+               /* Some PHYs require the PHY_STATUS register to be read
                 * twice due to the link bit being sticky.  No harm doing
                 * it across the board.
                 */
                ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
                if (ret_val)
-                       /*
-                        * If the first read fails, another entity may have
+                       /* If the first read fails, another entity may have
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
@@ -2289,8 +2304,8 @@ s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
-               M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+       index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+                M88E1000_PSSR_CABLE_LENGTH_SHIFT);
 
        if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
                return -E1000_ERR_PHY;
@@ -2307,11 +2322,34 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
-       u16 phy_data, phy_data2, index, default_page, is_cm;
+       u16 phy_data, phy_data2, is_cm;
+       u16 index, default_page;
 
        DEBUGFUNC("e1000_get_cable_length_m88_gen2");
 
        switch (hw->phy.id) {
+       case I210_I_PHY_ID:
+               /* Get cable length from PHY Cable Diagnostics Control Reg */
+               ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+                                           (I347AT4_PCDL + phy->addr),
+                                           &phy_data);
+               if (ret_val)
+                       return ret_val;
+
+               /* Check if the unit of cable length is meters or cm */
+               ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+                                           I347AT4_PCDC, &phy_data2);
+               if (ret_val)
+                       return ret_val;
+
+               is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+               /* Populate the phy structure with cable length in meters */
+               phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->cable_length = phy_data / (is_cm ? 100 : 1);
+               break;
+       case M88E1543_E_PHY_ID:
        case M88E1340M_E_PHY_ID:
        case I347AT4_E_PHY_ID:
                /* Remember the original page select and set it to 7 */
@@ -2424,14 +2462,13 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
                if (ret_val)
                        return ret_val;
 
-               /*
-                * Getting bits 15:9, which represent the combination of
+               /* Getting bits 15:9, which represent the combination of
                 * coarse and fine gain values.  The result is a number
                 * that can be put into the lookup table to obtain the
                 * approximate cable length.
                 */
-               cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
-                               IGP02E1000_AGC_LENGTH_MASK;
+               cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
+                                IGP02E1000_AGC_LENGTH_MASK);
 
                /* Array index bound check. */
                if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
@@ -2454,8 +2491,8 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
        agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
 
        /* Calculate cable length with the error range of +/- 10 meters. */
-       phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
-                                (agc_value - IGP02E1000_AGC_RANGE) : 0;
+       phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
+                                (agc_value - IGP02E1000_AGC_RANGE) : 0);
        phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE;
 
        phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
@@ -2639,9 +2676,9 @@ s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
                        return ret_val;
        } else {
                /* Polarity is forced */
-               phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)
-                                     ? e1000_rev_polarity_reversed
-                                     : e1000_rev_polarity_normal;
+               phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY)
+                                      ? e1000_rev_polarity_reversed
+                                      : e1000_rev_polarity_normal);
        }
 
        ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
@@ -2706,9 +2743,11 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_phy_hw_reset_generic");
 
-       ret_val = phy->ops.check_reset_block(hw);
-       if (ret_val)
-               return E1000_SUCCESS;
+       if (phy->ops.check_reset_block) {
+               ret_val = phy->ops.check_reset_block(hw);
+               if (ret_val)
+                       return E1000_SUCCESS;
+       }
 
        ret_val = phy->ops.acquire(hw);
        if (ret_val)
@@ -2737,7 +2776,7 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
  *  Generic function to wait 10 milli-seconds for configuration to complete
  *  and return success.
  **/
-s32 e1000_get_cfg_done_generic(struct e1000_hw *hw)
+s32 e1000_get_cfg_done_generic(struct e1000_hw E1000_UNUSEDARG *hw)
 {
        DEBUGFUNC("e1000_get_cfg_done_generic");
 
@@ -2809,15 +2848,13 @@ s32 e1000_phy_init_script_igp3(struct e1000_hw *hw)
        hw->phy.ops.write_reg(hw, 0x1796, 0x0008);
        /* Change cg_icount + enable integbp for channels BCD */
        hw->phy.ops.write_reg(hw, 0x1798, 0xD008);
-       /*
-        * Change cg_icount + enable integbp + change prop_factor_master
+       /* Change cg_icount + enable integbp + change prop_factor_master
         * to 8 for channel A
         */
        hw->phy.ops.write_reg(hw, 0x1898, 0xD918);
        /* Disable AHT in Slave mode on channel A */
        hw->phy.ops.write_reg(hw, 0x187A, 0x0800);
-       /*
-        * Enable LPLU and disable AN to 1000 in non-D0a states,
+       /* Enable LPLU and disable AN to 1000 in non-D0a states,
         * Enable SPD+B2B
         */
        hw->phy.ops.write_reg(hw, 0x0019, 0x008D);
@@ -2846,6 +2883,7 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
        case M88E1000_E_PHY_ID:
        case M88E1111_I_PHY_ID:
        case M88E1011_I_PHY_ID:
+       case M88E1543_E_PHY_ID:
        case I347AT4_E_PHY_ID:
        case M88E1112_E_PHY_ID:
        case M88E1340M_E_PHY_ID:
@@ -2868,6 +2906,9 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
        case I82580_I_PHY_ID:
                phy_type = e1000_phy_82580;
                break;
+       case I210_I_PHY_ID:
+               phy_type = e1000_phy_i210;
+               break;
        default:
                phy_type = e1000_phy_unknown;
                break;
@@ -2899,8 +2940,7 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw)
                        e1000_get_phy_id(hw);
                        phy_type = e1000_get_phy_type_from_id(hw->phy.id);
 
-                       /*
-                        * If phy_type is valid, break - we found our
+                       /* If phy_type is valid, break - we found our
                         * PHY address
                         */
                        if (phy_type != e1000_phy_unknown)
@@ -2925,10 +2965,16 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw)
 void e1000_power_up_phy_copper(struct e1000_hw *hw)
 {
        u16 mii_reg = 0;
+       u16 power_reg = 0;
 
        /* The PHY will retain its settings across a power down/up cycle */
        hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
        mii_reg &= ~MII_CR_POWER_DOWN;
+       if (hw->phy.type == e1000_phy_i210) {
+               hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+               power_reg &= ~GS40G_CS_POWER_DOWN;
+               hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+       }
        hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
 }
 
@@ -2943,10 +2989,17 @@ void e1000_power_up_phy_copper(struct e1000_hw *hw)
 void e1000_power_down_phy_copper(struct e1000_hw *hw)
 {
        u16 mii_reg = 0;
+       u16 power_reg = 0;
 
        /* The PHY will retain its settings across a power down/up cycle */
        hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
        mii_reg |= MII_CR_POWER_DOWN;
+       /* i210 Phy requires an additional bit for power up/down */
+       if (hw->phy.type == e1000_phy_i210) {
+               hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+               power_reg |= GS40G_CS_POWER_DOWN;
+               hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+       }
        hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
        msec_delay(1);
 }
@@ -2970,9 +3023,9 @@ s32 e1000_check_polarity_82577(struct e1000_hw *hw)
        ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
 
        if (!ret_val)
-               phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY)
-                                     ? e1000_rev_polarity_reversed
-                                     : e1000_rev_polarity_normal;
+               phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY)
+                                      ? e1000_rev_polarity_reversed
+                                      : e1000_rev_polarity_normal);
 
        return ret_val;
 }
@@ -3107,13 +3160,233 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
-                I82577_DSTATUS_CABLE_LENGTH_SHIFT;
+       length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
+                 I82577_DSTATUS_CABLE_LENGTH_SHIFT);
 
        if (length == E1000_CABLE_LENGTH_UNDEFINED)
-               ret_val = -E1000_ERR_PHY;
+               return -E1000_ERR_PHY;
 
        phy->cable_length = length;
 
        return E1000_SUCCESS;
 }
+
+/**
+ *  e1000_write_phy_reg_gs40g - Write GS40G  PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       s32 ret_val;
+       u16 page = offset >> GS40G_PAGE_SHIFT;
+
+       DEBUGFUNC("e1000_write_phy_reg_gs40g");
+
+       offset = offset & GS40G_OFFSET_MASK;
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               return ret_val;
+
+       ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+       if (ret_val)
+               goto release;
+       ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
+
+release:
+       hw->phy.ops.release(hw);
+       return ret_val;
+}
+
+/**
+ *  e1000_read_phy_reg_gs40g - Read GS40G  PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: lower half is register offset to read to
+ *     upper half is page to use.
+ *  @data: data to read at register offset
+ *
+ *  Acquires semaphore, if necessary, then reads the data in the PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       s32 ret_val;
+       u16 page = offset >> GS40G_PAGE_SHIFT;
+
+       DEBUGFUNC("e1000_read_phy_reg_gs40g");
+
+       offset = offset & GS40G_OFFSET_MASK;
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               return ret_val;
+
+       ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+       if (ret_val)
+               goto release;
+       ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
+
+release:
+       hw->phy.ops.release(hw);
+       return ret_val;
+}
+
+/**
+ *  e1000_read_phy_reg_mphy - Read mPHY control register
+ *  @hw: pointer to the HW structure
+ *  @address: address to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the mPHY control register in the PHY at offset and stores the
+ *  information read to data.
+ **/
+s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data)
+{
+       u32 mphy_ctrl = 0;
+       bool locked = false;
+       bool ready = false;
+
+       DEBUGFUNC("e1000_read_phy_reg_mphy");
+
+       /* Check if mPHY is ready to read/write operations */
+       ready = e1000_is_mphy_ready(hw);
+       if (!ready)
+               return -E1000_ERR_PHY;
+
+       /* Check if mPHY access is disabled and enable it if so */
+       mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
+       if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
+               locked = true;
+               ready = e1000_is_mphy_ready(hw);
+               if (!ready)
+                       return -E1000_ERR_PHY;
+               mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
+               E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
+       }
+
+       /* Set the address that we want to read */
+       ready = e1000_is_mphy_ready(hw);
+       if (!ready)
+               return -E1000_ERR_PHY;
+
+       /* We mask address, because we want to use only current lane */
+       mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK &
+               ~E1000_MPHY_ADDRESS_FNC_OVERRIDE) |
+               (address & E1000_MPHY_ADDRESS_MASK);
+       E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
+
+       /* Read data from the address */
+       ready = e1000_is_mphy_ready(hw);
+       if (!ready)
+               return -E1000_ERR_PHY;
+       *data = E1000_READ_REG(hw, E1000_MPHY_DATA);
+
+       /* Disable access to mPHY if it was originally disabled */
+       if (locked) {
+               ready = e1000_is_mphy_ready(hw);
+               if (!ready)
+                       return -E1000_ERR_PHY;
+               E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
+                               E1000_MPHY_DIS_ACCESS);
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_write_phy_reg_mphy - Write mPHY control register
+ *  @hw: pointer to the HW structure
+ *  @address: address to write to
+ *  @data: data to write to register at offset
+ *  @line_override: used when we want to use different line than default one
+ *
+ *  Writes data to mPHY control register.
+ **/
+s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data,
+                            bool line_override)
+{
+       u32 mphy_ctrl = 0;
+       bool locked = false;
+       bool ready = false;
+
+       DEBUGFUNC("e1000_write_phy_reg_mphy");
+
+       /* Check if mPHY is ready to read/write operations */
+       ready = e1000_is_mphy_ready(hw);
+       if (!ready)
+               return -E1000_ERR_PHY;
+
+       /* Check if mPHY access is disabled and enable it if so */
+       mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
+       if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
+               locked = true;
+               ready = e1000_is_mphy_ready(hw);
+               if (!ready)
+                       return -E1000_ERR_PHY;
+               mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
+               E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
+       }
+
+       /* Set the address that we want to read */
+       ready = e1000_is_mphy_ready(hw);
+       if (!ready)
+               return -E1000_ERR_PHY;
+
+       /* We mask address, because we want to use only current lane */
+       if (line_override)
+               mphy_ctrl |= E1000_MPHY_ADDRESS_FNC_OVERRIDE;
+       else
+               mphy_ctrl &= ~E1000_MPHY_ADDRESS_FNC_OVERRIDE;
+       mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK) |
+               (address & E1000_MPHY_ADDRESS_MASK);
+       E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
+
+       /* Read data from the address */
+       ready = e1000_is_mphy_ready(hw);
+       if (!ready)
+               return -E1000_ERR_PHY;
+       E1000_WRITE_REG(hw, E1000_MPHY_DATA, data);
+
+       /* Disable access to mPHY if it was originally disabled */
+       if (locked) {
+               ready = e1000_is_mphy_ready(hw);
+               if (!ready)
+                       return -E1000_ERR_PHY;
+               E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
+                               E1000_MPHY_DIS_ACCESS);
+       }
+
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_is_mphy_ready - Check if mPHY control register is not busy
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns mPHY control register status.
+ **/
+bool e1000_is_mphy_ready(struct e1000_hw *hw)
+{
+       u16 retry_count = 0;
+       u32 mphy_ctrl = 0;
+       bool ready = false;
+
+       while (retry_count < 2) {
+               mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
+               if (mphy_ctrl & E1000_MPHY_BUSY) {
+                       usec_delay(20);
+                       retry_count++;
+                       continue;
+               }
+               ready = true;
+               break;
+       }
+
+       if (!ready)
+               DEBUGOUT("ERROR READING mPHY control register, phy is busy.\n");
+
+       return ready;
+}