[RFC,1/7] net/igc: base driver
diff mbox series

Message ID 1578625225-110361-1-git-send-email-alvinx.zhang@intel.com
State Changes Requested
Delegated to: Ferruh Yigit
Headers show
Series
  • [RFC,1/7] net/igc: base driver
Related show

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/checkpatch warning coding style issues

Commit Message

Zhang, AlvinX Jan. 10, 2020, 3 a.m. UTC
From: Alvin Zhang <alvinx.zhang@intel.com>

Add shared code source files to support basic operations to be
called in poll mode driver.

Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
---
 drivers/net/igc/base/e1000_80003es2lan.c | 1495 ++++++++
 drivers/net/igc/base/e1000_80003es2lan.h |   71 +
 drivers/net/igc/base/e1000_82540.c       |  688 ++++
 drivers/net/igc/base/e1000_82541.c       | 1239 ++++++
 drivers/net/igc/base/e1000_82541.h       |   62 +
 drivers/net/igc/base/e1000_82542.c       |  561 +++
 drivers/net/igc/base/e1000_82543.c       | 1524 ++++++++
 drivers/net/igc/base/e1000_82543.h       |   27 +
 drivers/net/igc/base/e1000_82571.c       | 2001 ++++++++++
 drivers/net/igc/base/e1000_82571.h       |   36 +
 drivers/net/igc/base/e1000_82575.c       | 3586 ++++++++++++++++++
 drivers/net/igc/base/e1000_82575.h       |  381 ++
 drivers/net/igc/base/e1000_api.c         | 1369 +++++++
 drivers/net/igc/base/e1000_api.h         |  138 +
 drivers/net/igc/base/e1000_base.c        |  193 +
 drivers/net/igc/base/e1000_base.h        |  127 +
 drivers/net/igc/base/e1000_defines.h     | 1644 ++++++++
 drivers/net/igc/base/e1000_hw.h          | 1060 ++++++
 drivers/net/igc/base/e1000_i210.c        |  943 +++++
 drivers/net/igc/base/e1000_i210.h        |   77 +
 drivers/net/igc/base/e1000_i225.c        | 1390 +++++++
 drivers/net/igc/base/e1000_i225.h        |  110 +
 drivers/net/igc/base/e1000_ich8lan.c     | 6090 ++++++++++++++++++++++++++++++
 drivers/net/igc/base/e1000_ich8lan.h     |  298 ++
 drivers/net/igc/base/e1000_impl_guide.c  |   78 +
 drivers/net/igc/base/e1000_mac.c         | 2100 +++++++++++
 drivers/net/igc/base/e1000_mac.h         |   64 +
 drivers/net/igc/base/e1000_manage.c      |  547 +++
 drivers/net/igc/base/e1000_manage.h      |   65 +
 drivers/net/igc/base/e1000_mbx.c         |  767 ++++
 drivers/net/igc/base/e1000_mbx.h         |   76 +
 drivers/net/igc/base/e1000_nvm.c         | 1365 +++++++
 drivers/net/igc/base/e1000_nvm.h         |   69 +
 drivers/net/igc/base/e1000_osdep.c       |   64 +
 drivers/net/igc/base/e1000_osdep.h       |  188 +
 drivers/net/igc/base/e1000_phy.c         | 4423 ++++++++++++++++++++++
 drivers/net/igc/base/e1000_phy.h         |  326 ++
 drivers/net/igc/base/e1000_regs.h        |  730 ++++
 drivers/net/igc/base/e1000_vf.c          |  559 +++
 drivers/net/igc/base/e1000_vf.h          |  266 ++
 40 files changed, 36797 insertions(+)
 create mode 100644 drivers/net/igc/base/e1000_80003es2lan.c
 create mode 100644 drivers/net/igc/base/e1000_80003es2lan.h
 create mode 100644 drivers/net/igc/base/e1000_82540.c
 create mode 100644 drivers/net/igc/base/e1000_82541.c
 create mode 100644 drivers/net/igc/base/e1000_82541.h
 create mode 100644 drivers/net/igc/base/e1000_82542.c
 create mode 100644 drivers/net/igc/base/e1000_82543.c
 create mode 100644 drivers/net/igc/base/e1000_82543.h
 create mode 100644 drivers/net/igc/base/e1000_82571.c
 create mode 100644 drivers/net/igc/base/e1000_82571.h
 create mode 100644 drivers/net/igc/base/e1000_82575.c
 create mode 100644 drivers/net/igc/base/e1000_82575.h
 create mode 100644 drivers/net/igc/base/e1000_api.c
 create mode 100644 drivers/net/igc/base/e1000_api.h
 create mode 100644 drivers/net/igc/base/e1000_base.c
 create mode 100644 drivers/net/igc/base/e1000_base.h
 create mode 100644 drivers/net/igc/base/e1000_defines.h
 create mode 100644 drivers/net/igc/base/e1000_hw.h
 create mode 100644 drivers/net/igc/base/e1000_i210.c
 create mode 100644 drivers/net/igc/base/e1000_i210.h
 create mode 100644 drivers/net/igc/base/e1000_i225.c
 create mode 100644 drivers/net/igc/base/e1000_i225.h
 create mode 100644 drivers/net/igc/base/e1000_ich8lan.c
 create mode 100644 drivers/net/igc/base/e1000_ich8lan.h
 create mode 100644 drivers/net/igc/base/e1000_impl_guide.c
 create mode 100644 drivers/net/igc/base/e1000_mac.c
 create mode 100644 drivers/net/igc/base/e1000_mac.h
 create mode 100644 drivers/net/igc/base/e1000_manage.c
 create mode 100644 drivers/net/igc/base/e1000_manage.h
 create mode 100644 drivers/net/igc/base/e1000_mbx.c
 create mode 100644 drivers/net/igc/base/e1000_mbx.h
 create mode 100644 drivers/net/igc/base/e1000_nvm.c
 create mode 100644 drivers/net/igc/base/e1000_nvm.h
 create mode 100644 drivers/net/igc/base/e1000_osdep.c
 create mode 100644 drivers/net/igc/base/e1000_osdep.h
 create mode 100644 drivers/net/igc/base/e1000_phy.c
 create mode 100644 drivers/net/igc/base/e1000_phy.h
 create mode 100644 drivers/net/igc/base/e1000_regs.h
 create mode 100644 drivers/net/igc/base/e1000_vf.c
 create mode 100644 drivers/net/igc/base/e1000_vf.h

Comments

Ferruh Yigit Jan. 21, 2020, 4:27 p.m. UTC | #1
On 1/10/2020 3:00 AM, alvinx.zhang@intel.com wrote:
> From: Alvin Zhang <alvinx.zhang@intel.com>
> 
> Add shared code source files to support basic operations to be
> called in poll mode driver.
> 
> Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>

Hi Alvin,

I would suggest a different organization of the patches.

Currently first patch dumps all shared code, second all the DPDK driver files.
Later patches does in each patch, Makefile based build system, meson based build
system and documentation.

First question if all shared code are used, if not please drop the ones that are
not used as much as possible.

Second please try to split into the logical pieces, like a logical piece can be
setting MTU (just a sample) and you can put shared code, dpdk code and
documentation related to it in same patch.

Also can you please start the series with a skeleton, which introduces the build
system files, configs, Maintainer file update, generic docs. At this stage code
can be empty, and the driver can be disabled by default.
And if you have to, second patch can have a minimum required shared code drop.
After this the driver can be built gradually feature by feature, perhaps
starting from the probe/remove support.

Thanks,
ferruh
Zhang, AlvinX Feb. 24, 2020, 3:58 a.m. UTC | #2
Hi Ferruh,

I have add some new features to the module last few weeks,  I'm going to resubmit all codes as you suggest.
Thanks very much

BR,
Alvin

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, January 22, 2020 12:27 AM
> To: Zhang, AlvinX <alvinx.zhang@intel.com>; Wang, Haiyue
> <haiyue.wang@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>; Xing, Beilei
> <beilei.xing@intel.com>; Ye, Xiaolong <xiaolong.ye@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC 1/7] net/igc: base driver
> 
> On 1/10/2020 3:00 AM, alvinx.zhang@intel.com wrote:
> > From: Alvin Zhang <alvinx.zhang@intel.com>
> >
> > Add shared code source files to support basic operations to be called
> > in poll mode driver.
> >
> > Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
> 
> Hi Alvin,
> 
> I would suggest a different organization of the patches.
> 
> Currently first patch dumps all shared code, second all the DPDK driver files.
> Later patches does in each patch, Makefile based build system, meson based
> build system and documentation.
> 
> First question if all shared code are used, if not please drop the ones that are
> not used as much as possible.
> 
> Second please try to split into the logical pieces, like a logical piece can be
> setting MTU (just a sample) and you can put shared code, dpdk code and
> documentation related to it in same patch.
> 
> Also can you please start the series with a skeleton, which introduces the
> build system files, configs, Maintainer file update, generic docs. At this stage
> code can be empty, and the driver can be disabled by default.
> And if you have to, second patch can have a minimum required shared code
> drop.
> After this the driver can be built gradually feature by feature, perhaps
> starting from the probe/remove support.
> 
> Thanks,
> ferruh

Patch
diff mbox series

diff --git a/drivers/net/igc/base/e1000_80003es2lan.c b/drivers/net/igc/base/e1000_80003es2lan.c
new file mode 100644
index 0000000..c40e523
--- /dev/null
+++ b/drivers/net/igc/base/e1000_80003es2lan.c
@@ -0,0 +1,1495 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+/* 80003ES2LAN Gigabit Ethernet Controller (Copper)
+ * 80003ES2LAN Gigabit Ethernet Controller (Serdes)
+ */
+
+#include "e1000_api.h"
+
+STATIC s32  igc_acquire_phy_80003es2lan(struct igc_hw *hw);
+STATIC void igc_release_phy_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_acquire_nvm_80003es2lan(struct igc_hw *hw);
+STATIC void igc_release_nvm_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_read_phy_reg_gg82563_80003es2lan(struct igc_hw *hw,
+						   u32 offset,
+						   u16 *data);
+STATIC s32  igc_write_phy_reg_gg82563_80003es2lan(struct igc_hw *hw,
+						    u32 offset,
+						    u16 data);
+STATIC s32  igc_write_nvm_80003es2lan(struct igc_hw *hw, u16 offset,
+					u16 words, u16 *data);
+STATIC s32  igc_get_cfg_done_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_phy_force_speed_duplex_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_get_cable_length_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_get_link_up_info_80003es2lan(struct igc_hw *hw, u16 *speed,
+					       u16 *duplex);
+STATIC s32  igc_reset_hw_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_init_hw_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_setup_copper_link_80003es2lan(struct igc_hw *hw);
+STATIC void igc_clear_hw_cntrs_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_acquire_swfw_sync_80003es2lan(struct igc_hw *hw, u16 mask);
+STATIC s32  igc_cfg_kmrn_10_100_80003es2lan(struct igc_hw *hw, u16 duplex);
+STATIC s32  igc_cfg_kmrn_1000_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_cfg_on_link_up_80003es2lan(struct igc_hw *hw);
+STATIC s32  igc_read_kmrn_reg_80003es2lan(struct igc_hw *hw, u32 offset,
+					    u16 *data);
+STATIC s32  igc_write_kmrn_reg_80003es2lan(struct igc_hw *hw, u32 offset,
+					     u16 data);
+STATIC void igc_initialize_hw_bits_80003es2lan(struct igc_hw *hw);
+STATIC void igc_release_swfw_sync_80003es2lan(struct igc_hw *hw, u16 mask);
+STATIC s32  igc_read_mac_addr_80003es2lan(struct igc_hw *hw);
+STATIC void igc_power_down_phy_copper_80003es2lan(struct igc_hw *hw);
+
+/* A table for the GG82563 cable length where the range is defined
+ * with a lower bound at "index" and the upper bound at
+ * "index + 5".
+ */
+STATIC const u16 igc_gg82563_cable_length_table[] = {
+	0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
+#define GG82563_CABLE_LENGTH_TABLE_SIZE \
+		(sizeof(igc_gg82563_cable_length_table) / \
+		 sizeof(igc_gg82563_cable_length_table[0]))
+
+/**
+ *  igc_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_phy_params_80003es2lan(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_init_phy_params_80003es2lan");
+
+	if (hw->phy.media_type != igc_media_type_copper) {
+		phy->type = igc_phy_none;
+		return IGC_SUCCESS;
+	} else {
+		phy->ops.power_up = igc_power_up_phy_copper;
+		phy->ops.power_down = igc_power_down_phy_copper_80003es2lan;
+	}
+
+	phy->addr		= 1;
+	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+	phy->reset_delay_us	= 100;
+	phy->type		= igc_phy_gg82563;
+
+	phy->ops.acquire	= igc_acquire_phy_80003es2lan;
+	phy->ops.check_polarity	= igc_check_polarity_m88;
+	phy->ops.check_reset_block = igc_check_reset_block_generic;
+	phy->ops.commit		= igc_phy_sw_reset_generic;
+	phy->ops.get_cfg_done	= igc_get_cfg_done_80003es2lan;
+	phy->ops.get_info	= igc_get_phy_info_m88;
+	phy->ops.release	= igc_release_phy_80003es2lan;
+	phy->ops.reset		= igc_phy_hw_reset_generic;
+	phy->ops.set_d3_lplu_state = igc_set_d3_lplu_state_generic;
+
+	phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_80003es2lan;
+	phy->ops.get_cable_length = igc_get_cable_length_80003es2lan;
+	phy->ops.read_reg	= igc_read_phy_reg_gg82563_80003es2lan;
+	phy->ops.write_reg	= igc_write_phy_reg_gg82563_80003es2lan;
+
+	phy->ops.cfg_on_link_up = igc_cfg_on_link_up_80003es2lan;
+
+	/* This can only be done after all function pointers are setup. */
+	ret_val = igc_get_phy_id(hw);
+
+	/* Verify phy id */
+	if (phy->id != GG82563_E_PHY_ID)
+		return -IGC_ERR_PHY;
+
+	return ret_val;
+}
+
+/**
+ *  igc_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_nvm_params_80003es2lan(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	u32 eecd = IGC_READ_REG(hw, IGC_EECD);
+	u16 size;
+
+	DEBUGFUNC("igc_init_nvm_params_80003es2lan");
+
+	nvm->opcode_bits = 8;
+	nvm->delay_usec = 1;
+	switch (nvm->override) {
+	case igc_nvm_override_spi_large:
+		nvm->page_size = 32;
+		nvm->address_bits = 16;
+		break;
+	case igc_nvm_override_spi_small:
+		nvm->page_size = 8;
+		nvm->address_bits = 8;
+		break;
+	default:
+		nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
+		nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ? 16 : 8;
+		break;
+	}
+
+	nvm->type = igc_nvm_eeprom_spi;
+
+	size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
+		     IGC_EECD_SIZE_EX_SHIFT);
+
+	/* Added to a constant, "size" becomes the left-shift value
+	 * for setting word_size.
+	 */
+	size += NVM_WORD_SIZE_BASE_SHIFT;
+
+	/* EEPROM access above 16k is unsupported */
+	if (size > 14)
+		size = 14;
+	nvm->word_size = 1 << size;
+
+	/* Function Pointers */
+	nvm->ops.acquire	= igc_acquire_nvm_80003es2lan;
+	nvm->ops.read		= igc_read_nvm_eerd;
+	nvm->ops.release	= igc_release_nvm_80003es2lan;
+	nvm->ops.update		= igc_update_nvm_checksum_generic;
+	nvm->ops.valid_led_default = igc_valid_led_default_generic;
+	nvm->ops.validate	= igc_validate_nvm_checksum_generic;
+	nvm->ops.write		= igc_write_nvm_80003es2lan;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_mac_params_80003es2lan(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+
+	DEBUGFUNC("igc_init_mac_params_80003es2lan");
+
+	/* Set media type and media-dependent function pointers */
+	switch (hw->device_id) {
+	case IGC_DEV_ID_80003ES2LAN_SERDES_DPT:
+		hw->phy.media_type = igc_media_type_internal_serdes;
+		mac->ops.check_for_link = igc_check_for_serdes_link_generic;
+		mac->ops.setup_physical_interface =
+					igc_setup_fiber_serdes_link_generic;
+		break;
+	default:
+		hw->phy.media_type = igc_media_type_copper;
+		mac->ops.check_for_link = igc_check_for_copper_link_generic;
+		mac->ops.setup_physical_interface =
+					igc_setup_copper_link_80003es2lan;
+		break;
+	}
+
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	mac->rar_entry_count = IGC_RAR_ENTRIES;
+	/* Set if part includes ASF firmware */
+	mac->asf_firmware_present = true;
+	/* FWSM register */
+	mac->has_fwsm = true;
+	/* ARC supported; valid only if manageability features are enabled. */
+	mac->arc_subsystem_valid = !!(IGC_READ_REG(hw, IGC_FWSM) &
+				      IGC_FWSM_MODE_MASK);
+	/* Adaptive IFS not supported */
+	mac->adaptive_ifs = false;
+
+	/* Function pointers */
+
+	/* bus type/speed/width */
+	mac->ops.get_bus_info = igc_get_bus_info_pcie_generic;
+	/* reset */
+	mac->ops.reset_hw = igc_reset_hw_80003es2lan;
+	/* hw initialization */
+	mac->ops.init_hw = igc_init_hw_80003es2lan;
+	/* link setup */
+	mac->ops.setup_link = igc_setup_link_generic;
+	/* check management mode */
+	mac->ops.check_mng_mode = igc_check_mng_mode_generic;
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
+	/* writing VFTA */
+	mac->ops.write_vfta = igc_write_vfta_generic;
+	/* clearing VFTA */
+	mac->ops.clear_vfta = igc_clear_vfta_generic;
+	/* read mac address */
+	mac->ops.read_mac_addr = igc_read_mac_addr_80003es2lan;
+	/* ID LED init */
+	mac->ops.id_led_init = igc_id_led_init_generic;
+	/* blink LED */
+	mac->ops.blink_led = igc_blink_led_generic;
+	/* setup LED */
+	mac->ops.setup_led = igc_setup_led_generic;
+	/* cleanup LED */
+	mac->ops.cleanup_led = igc_cleanup_led_generic;
+	/* turn on/off LED */
+	mac->ops.led_on = igc_led_on_generic;
+	mac->ops.led_off = igc_led_off_generic;
+	/* clear hardware counters */
+	mac->ops.clear_hw_cntrs = igc_clear_hw_cntrs_80003es2lan;
+	/* link info */
+	mac->ops.get_link_up_info = igc_get_link_up_info_80003es2lan;
+
+	/* set lan id for port to determine which phy lock to use */
+	hw->mac.ops.set_lan_id(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_function_pointers_80003es2lan - Init ESB2 func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void igc_init_function_pointers_80003es2lan(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_init_function_pointers_80003es2lan");
+
+	hw->mac.ops.init_params = igc_init_mac_params_80003es2lan;
+	hw->nvm.ops.init_params = igc_init_nvm_params_80003es2lan;
+	hw->phy.ops.init_params = igc_init_phy_params_80003es2lan;
+}
+
+/**
+ *  igc_acquire_phy_80003es2lan - Acquire rights to access PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  A wrapper to acquire access rights to the correct PHY.
+ **/
+STATIC s32 igc_acquire_phy_80003es2lan(struct igc_hw *hw)
+{
+	u16 mask;
+
+	DEBUGFUNC("igc_acquire_phy_80003es2lan");
+
+	mask = hw->bus.func ? IGC_SWFW_PHY1_SM : IGC_SWFW_PHY0_SM;
+	return igc_acquire_swfw_sync_80003es2lan(hw, mask);
+}
+
+/**
+ *  igc_release_phy_80003es2lan - Release rights to access PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  A wrapper to release access rights to the correct PHY.
+ **/
+STATIC void igc_release_phy_80003es2lan(struct igc_hw *hw)
+{
+	u16 mask;
+
+	DEBUGFUNC("igc_release_phy_80003es2lan");
+
+	mask = hw->bus.func ? IGC_SWFW_PHY1_SM : IGC_SWFW_PHY0_SM;
+	igc_release_swfw_sync_80003es2lan(hw, mask);
+}
+
+/**
+ *  igc_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the semaphore to access the Kumeran interface.
+ *
+ **/
+STATIC s32 igc_acquire_mac_csr_80003es2lan(struct igc_hw *hw)
+{
+	u16 mask;
+
+	DEBUGFUNC("igc_acquire_mac_csr_80003es2lan");
+
+	mask = IGC_SWFW_CSR_SM;
+
+	return igc_acquire_swfw_sync_80003es2lan(hw, mask);
+}
+
+/**
+ *  igc_release_mac_csr_80003es2lan - Release right to access Kumeran Register
+ *  @hw: pointer to the HW structure
+ *
+ *  Release the semaphore used to access the Kumeran interface
+ **/
+STATIC void igc_release_mac_csr_80003es2lan(struct igc_hw *hw)
+{
+	u16 mask;
+
+	DEBUGFUNC("igc_release_mac_csr_80003es2lan");
+
+	mask = IGC_SWFW_CSR_SM;
+
+	igc_release_swfw_sync_80003es2lan(hw, mask);
+}
+
+/**
+ *  igc_acquire_nvm_80003es2lan - Acquire rights to access NVM
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the semaphore to access the EEPROM.
+ **/
+STATIC s32 igc_acquire_nvm_80003es2lan(struct igc_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_acquire_nvm_80003es2lan");
+
+	ret_val = igc_acquire_swfw_sync_80003es2lan(hw, IGC_SWFW_EEP_SM);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = igc_acquire_nvm_generic(hw);
+
+	if (ret_val)
+		igc_release_swfw_sync_80003es2lan(hw, IGC_SWFW_EEP_SM);
+
+	return ret_val;
+}
+
+/**
+ *  igc_release_nvm_80003es2lan - Relinquish rights to access NVM
+ *  @hw: pointer to the HW structure
+ *
+ *  Release the semaphore used to access the EEPROM.
+ **/
+STATIC void igc_release_nvm_80003es2lan(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_release_nvm_80003es2lan");
+
+	igc_release_nvm_generic(hw);
+	igc_release_swfw_sync_80003es2lan(hw, IGC_SWFW_EEP_SM);
+}
+
+/**
+ *  igc_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore
+ *  @hw: pointer to the HW structure
+ *  @mask: specifies which semaphore to acquire
+ *
+ *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
+ *  will also specify which port we're acquiring the lock for.
+ **/
+STATIC s32 igc_acquire_swfw_sync_80003es2lan(struct igc_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+	u32 swmask = mask;
+	u32 fwmask = mask << 16;
+	s32 i = 0;
+	s32 timeout = 50;
+
+	DEBUGFUNC("igc_acquire_swfw_sync_80003es2lan");
+
+	while (i < timeout) {
+		if (igc_get_hw_semaphore_generic(hw))
+			return -IGC_ERR_SWFW_SYNC;
+
+		swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
+		if (!(swfw_sync & (fwmask | swmask)))
+			break;
+
+		/* Firmware currently using resource (fwmask)
+		 * or other software thread using resource (swmask)
+		 */
+		igc_put_hw_semaphore_generic(hw);
+		msec_delay_irq(5);
+		i++;
+	}
+
+	if (i == timeout) {
+		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
+		return -IGC_ERR_SWFW_SYNC;
+	}
+
+	swfw_sync |= swmask;
+	IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
+
+	igc_put_hw_semaphore_generic(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_release_swfw_sync_80003es2lan - Release SW/FW semaphore
+ *  @hw: pointer to the HW structure
+ *  @mask: specifies which semaphore to acquire
+ *
+ *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
+ *  will also specify which port we're releasing the lock for.
+ **/
+STATIC void igc_release_swfw_sync_80003es2lan(struct igc_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+
+	DEBUGFUNC("igc_release_swfw_sync_80003es2lan");
+
+	while (igc_get_hw_semaphore_generic(hw) != IGC_SUCCESS)
+		; /* Empty */
+
+	swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
+	swfw_sync &= ~mask;
+	IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
+
+	igc_put_hw_semaphore_generic(hw);
+}
+
+/**
+ *  igc_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: offset of the register to read
+ *  @data: pointer to the data returned from the operation
+ *
+ *  Read the GG82563 PHY register.
+ **/
+STATIC s32 igc_read_phy_reg_gg82563_80003es2lan(struct igc_hw *hw,
+						  u32 offset, u16 *data)
+{
+	s32 ret_val;
+	u32 page_select;
+	u16 temp;
+
+	DEBUGFUNC("igc_read_phy_reg_gg82563_80003es2lan");
+
+	ret_val = igc_acquire_phy_80003es2lan(hw);
+	if (ret_val)
+		return ret_val;
+
+	/* Select Configuration Page */
+	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+		page_select = GG82563_PHY_PAGE_SELECT;
+	} else {
+		/* Use Alternative Page Select register to access
+		 * registers 30 and 31
+		 */
+		page_select = GG82563_PHY_PAGE_SELECT_ALT;
+	}
+
+	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
+	ret_val = igc_write_phy_reg_mdic(hw, page_select, temp);
+	if (ret_val) {
+		igc_release_phy_80003es2lan(hw);
+		return ret_val;
+	}
+
+	if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
+		/* The "ready" bit in the MDIC register may be incorrectly set
+		 * before the device has completed the "Page Select" MDI
+		 * transaction.  So we wait 200us after each MDI command...
+		 */
+		usec_delay(200);
+
+		/* ...and verify the command was successful. */
+		ret_val = igc_read_phy_reg_mdic(hw, page_select, &temp);
+
+		if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
+			igc_release_phy_80003es2lan(hw);
+			return -IGC_ERR_PHY;
+		}
+
+		usec_delay(200);
+
+		ret_val = igc_read_phy_reg_mdic(hw,
+						  MAX_PHY_REG_ADDRESS & offset,
+						  data);
+
+		usec_delay(200);
+	} else {
+		ret_val = igc_read_phy_reg_mdic(hw,
+						  MAX_PHY_REG_ADDRESS & offset,
+						  data);
+	}
+
+	igc_release_phy_80003es2lan(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: offset of the register to read
+ *  @data: value to write to the register
+ *
+ *  Write to the GG82563 PHY register.
+ **/
+STATIC s32 igc_write_phy_reg_gg82563_80003es2lan(struct igc_hw *hw,
+						   u32 offset, u16 data)
+{
+	s32 ret_val;
+	u32 page_select;
+	u16 temp;
+
+	DEBUGFUNC("igc_write_phy_reg_gg82563_80003es2lan");
+
+	ret_val = igc_acquire_phy_80003es2lan(hw);
+	if (ret_val)
+		return ret_val;
+
+	/* Select Configuration Page */
+	if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
+		page_select = GG82563_PHY_PAGE_SELECT;
+	} else {
+		/* Use Alternative Page Select register to access
+		 * registers 30 and 31
+		 */
+		page_select = GG82563_PHY_PAGE_SELECT_ALT;
+	}
+
+	temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
+	ret_val = igc_write_phy_reg_mdic(hw, page_select, temp);
+	if (ret_val) {
+		igc_release_phy_80003es2lan(hw);
+		return ret_val;
+	}
+
+	if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
+		/* The "ready" bit in the MDIC register may be incorrectly set
+		 * before the device has completed the "Page Select" MDI
+		 * transaction.  So we wait 200us after each MDI command...
+		 */
+		usec_delay(200);
+
+		/* ...and verify the command was successful. */
+		ret_val = igc_read_phy_reg_mdic(hw, page_select, &temp);
+
+		if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
+			igc_release_phy_80003es2lan(hw);
+			return -IGC_ERR_PHY;
+		}
+
+		usec_delay(200);
+
+		ret_val = igc_write_phy_reg_mdic(hw,
+						  MAX_PHY_REG_ADDRESS & offset,
+						  data);
+
+		usec_delay(200);
+	} else {
+		ret_val = igc_write_phy_reg_mdic(hw,
+						  MAX_PHY_REG_ADDRESS & offset,
+						  data);
+	}
+
+	igc_release_phy_80003es2lan(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_write_nvm_80003es2lan - Write to ESB2 NVM
+ *  @hw: pointer to the HW structure
+ *  @offset: offset of the register to read
+ *  @words: number of words to write
+ *  @data: buffer of data to write to the NVM
+ *
+ *  Write "words" of data to the ESB2 NVM.
+ **/
+STATIC s32 igc_write_nvm_80003es2lan(struct igc_hw *hw, u16 offset,
+				       u16 words, u16 *data)
+{
+	DEBUGFUNC("igc_write_nvm_80003es2lan");
+
+	return igc_write_nvm_spi(hw, offset, words, data);
+}
+
+/**
+ *  igc_get_cfg_done_80003es2lan - Wait for configuration to complete
+ *  @hw: pointer to the HW structure
+ *
+ *  Wait a specific amount of time for manageability processes to complete.
+ *  This is a function pointer entry point called by the phy module.
+ **/
+STATIC s32 igc_get_cfg_done_80003es2lan(struct igc_hw *hw)
+{
+	s32 timeout = PHY_CFG_TIMEOUT;
+	u32 mask = IGC_NVM_CFG_DONE_PORT_0;
+
+	DEBUGFUNC("igc_get_cfg_done_80003es2lan");
+
+	if (hw->bus.func == 1)
+		mask = IGC_NVM_CFG_DONE_PORT_1;
+
+	while (timeout) {
+		if (IGC_READ_REG(hw, IGC_EEMNGCTL) & mask)
+			break;
+		msec_delay(1);
+		timeout--;
+	}
+	if (!timeout) {
+		DEBUGOUT("MNG configuration cycle has not completed.\n");
+		return -IGC_ERR_RESET;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex
+ *  @hw: pointer to the HW structure
+ *
+ *  Force the speed and duplex settings onto the PHY.  This is a
+ *  function pointer entry point called by the phy module.
+ **/
+STATIC s32 igc_phy_force_speed_duplex_80003es2lan(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u16 phy_data;
+	bool link;
+
+	DEBUGFUNC("igc_phy_force_speed_duplex_80003es2lan");
+
+	if (!(hw->phy.ops.read_reg))
+		return IGC_SUCCESS;
+
+	/* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
+	 * forced whenever speed and duplex are forced.
+	 */
+	ret_val = hw->phy.ops.read_reg(hw, M88IGC_PHY_SPEC_CTRL, &phy_data);
+	if (ret_val)
+		return ret_val;
+
+	phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO;
+	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
+	if (ret_val)
+		return ret_val;
+
+	DEBUGOUT1("GG82563 PSCR: %X\n", phy_data);
+
+	ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data);
+	if (ret_val)
+		return ret_val;
+
+	igc_phy_force_speed_duplex_setup(hw, &phy_data);
+
+	/* Reset the phy to commit changes. */
+	phy_data |= MII_CR_RESET;
+
+	ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data);
+	if (ret_val)
+		return ret_val;
+
+	usec_delay(1);
+
+	if (hw->phy.autoneg_wait_to_complete) {
+		DEBUGOUT("Waiting for forced speed/duplex link on GG82563 phy.\n");
+
+		ret_val = igc_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+						     100000, &link);
+		if (ret_val)
+			return ret_val;
+
+		if (!link) {
+			/* We didn't get link.
+			 * Reset the DSP and cross our fingers.
+			 */
+			ret_val = igc_phy_reset_dsp_generic(hw);
+			if (ret_val)
+				return ret_val;
+		}
+
+		/* Try once more */
+		ret_val = igc_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
+						     100000, &link);
+		if (ret_val)
+			return ret_val;
+	}
+
+	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+				       &phy_data);
+	if (ret_val)
+		return ret_val;
+
+	/* Resetting the phy means we need to verify the TX_CLK corresponds
+	 * to the link speed.  10Mbps -> 2.5MHz, else 25MHz.
+	 */
+	phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
+	if (hw->mac.forced_speed_duplex & IGC_ALL_10_SPEED)
+		phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5;
+	else
+		phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
+
+	/* In addition, we must re-enable CRS on Tx for both half and full
+	 * duplex.
+	 */
+	phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+					phy_data);
+
+	return ret_val;
+}
+
+/**
+ *  igc_get_cable_length_80003es2lan - Set approximate cable length
+ *  @hw: pointer to the HW structure
+ *
+ *  Find the approximate cable length as measured by the GG82563 PHY.
+ *  This is a function pointer entry point called by the phy module.
+ **/
+STATIC s32 igc_get_cable_length_80003es2lan(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data, index;
+
+	DEBUGFUNC("igc_get_cable_length_80003es2lan");
+
+	if (!(hw->phy.ops.read_reg))
+		return IGC_SUCCESS;
+
+	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
+	if (ret_val)
+		return ret_val;
+
+	index = phy_data & GG82563_DSPD_CABLE_LENGTH;
+
+	if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5)
+		return -IGC_ERR_PHY;
+
+	phy->min_cable_length = igc_gg82563_cable_length_table[index];
+	phy->max_cable_length = igc_gg82563_cable_length_table[index + 5];
+
+	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_get_link_up_info_80003es2lan - Report speed and duplex
+ *  @hw: pointer to the HW structure
+ *  @speed: pointer to speed buffer
+ *  @duplex: pointer to duplex buffer
+ *
+ *  Retrieve the current speed and duplex configuration.
+ **/
+STATIC s32 igc_get_link_up_info_80003es2lan(struct igc_hw *hw, u16 *speed,
+					      u16 *duplex)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_get_link_up_info_80003es2lan");
+
+	if (hw->phy.media_type == igc_media_type_copper) {
+		ret_val = igc_get_speed_and_duplex_copper_generic(hw, speed,
+								    duplex);
+		hw->phy.ops.cfg_on_link_up(hw);
+	} else {
+		ret_val = igc_get_speed_and_duplex_fiber_serdes_generic(hw,
+								  speed,
+								  duplex);
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_reset_hw_80003es2lan - Reset the ESB2 controller
+ *  @hw: pointer to the HW structure
+ *
+ *  Perform a global reset to the ESB2 controller.
+ **/
+STATIC s32 igc_reset_hw_80003es2lan(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+	u16 kum_reg_data;
+
+	DEBUGFUNC("igc_reset_hw_80003es2lan");
+
+	/* Prevent the PCI-E bus from sticking if there is no TLP connection
+	 * on the last TLP read/write transaction when MAC is reset.
+	 */
+	ret_val = igc_disable_pcie_master_generic(hw);
+	if (ret_val)
+		DEBUGOUT("PCI-E Master disable polling has failed.\n");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
+	IGC_WRITE_FLUSH(hw);
+
+	msec_delay(10);
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	ret_val = igc_acquire_phy_80003es2lan(hw);
+	if (ret_val)
+		return ret_val;
+
+	DEBUGOUT("Issuing a global reset to MAC\n");
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+	igc_release_phy_80003es2lan(hw);
+
+	/* Disable IBIST slave mode (far-end loopback) */
+	ret_val = igc_read_kmrn_reg_80003es2lan(hw,
+				IGC_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data);
+	if (!ret_val) {
+		kum_reg_data |= IGC_KMRNCTRLSTA_IBIST_DISABLE;
+		ret_val = igc_write_kmrn_reg_80003es2lan(hw,
+						 IGC_KMRNCTRLSTA_INBAND_PARAM,
+						 kum_reg_data);
+		if (ret_val)
+			DEBUGOUT("Error disabling far-end loopback\n");
+	} else
+		DEBUGOUT("Error disabling far-end loopback\n");
+
+	ret_val = igc_get_auto_rd_done_generic(hw);
+	if (ret_val)
+		/* We don't want to continue accessing MAC registers. */
+		return ret_val;
+
+	/* Clear any pending interrupt events. */
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_READ_REG(hw, IGC_ICR);
+
+	return igc_check_alt_mac_addr_generic(hw);
+}
+
+/**
+ *  igc_init_hw_80003es2lan - Initialize the ESB2 controller
+ *  @hw: pointer to the HW structure
+ *
+ *  Initialize the hw bits, LED, VFTA, MTA, link and hw counters.
+ **/
+STATIC s32 igc_init_hw_80003es2lan(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	u32 reg_data;
+	s32 ret_val;
+	u16 kum_reg_data;
+	u16 i;
+
+	DEBUGFUNC("igc_init_hw_80003es2lan");
+
+	igc_initialize_hw_bits_80003es2lan(hw);
+
+	/* Initialize identification LED */
+	ret_val = mac->ops.id_led_init(hw);
+	/* An error is not fatal and we should not stop init due to this */
+	if (ret_val)
+		DEBUGOUT("Error initializing identification LED\n");
+
+	/* Disabling VLAN filtering */
+	DEBUGOUT("Initializing the IEEE VLAN\n");
+	mac->ops.clear_vfta(hw);
+
+	/* Setup the receive address. */
+	igc_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for (i = 0; i < mac->mta_reg_count; i++)
+		IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
+
+	/* Setup link and flow control */
+	ret_val = mac->ops.setup_link(hw);
+	if (ret_val)
+		return ret_val;
+
+	/* Disable IBIST slave mode (far-end loopback) */
+	ret_val =
+	    igc_read_kmrn_reg_80003es2lan(hw, IGC_KMRNCTRLSTA_INBAND_PARAM,
+					    &kum_reg_data);
+	if (!ret_val) {
+		kum_reg_data |= IGC_KMRNCTRLSTA_IBIST_DISABLE;
+		ret_val = igc_write_kmrn_reg_80003es2lan(hw,
+						 IGC_KMRNCTRLSTA_INBAND_PARAM,
+						 kum_reg_data);
+		if (ret_val)
+			DEBUGOUT("Error disabling far-end loopback\n");
+	} else
+		DEBUGOUT("Error disabling far-end loopback\n");
+
+	/* Set the transmit descriptor write-back policy */
+	reg_data = IGC_READ_REG(hw, IGC_TXDCTL(0));
+	reg_data = ((reg_data & ~IGC_TXDCTL_WTHRESH) |
+		    IGC_TXDCTL_FULL_TX_DESC_WB | IGC_TXDCTL_COUNT_DESC);
+	IGC_WRITE_REG(hw, IGC_TXDCTL(0), reg_data);
+
+	/* ...for both queues. */
+	reg_data = IGC_READ_REG(hw, IGC_TXDCTL(1));
+	reg_data = ((reg_data & ~IGC_TXDCTL_WTHRESH) |
+		    IGC_TXDCTL_FULL_TX_DESC_WB | IGC_TXDCTL_COUNT_DESC);
+	IGC_WRITE_REG(hw, IGC_TXDCTL(1), reg_data);
+
+	/* Enable retransmit on late collisions */
+	reg_data = IGC_READ_REG(hw, IGC_TCTL);
+	reg_data |= IGC_TCTL_RTLC;
+	IGC_WRITE_REG(hw, IGC_TCTL, reg_data);
+
+	/* Configure Gigabit Carry Extend Padding */
+	reg_data = IGC_READ_REG(hw, IGC_TCTL_EXT);
+	reg_data &= ~IGC_TCTL_EXT_GCEX_MASK;
+	reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN;
+	IGC_WRITE_REG(hw, IGC_TCTL_EXT, reg_data);
+
+	/* Configure Transmit Inter-Packet Gap */
+	reg_data = IGC_READ_REG(hw, IGC_TIPG);
+	reg_data &= ~IGC_TIPG_IPGT_MASK;
+	reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
+	IGC_WRITE_REG(hw, IGC_TIPG, reg_data);
+
+	reg_data = IGC_READ_REG_ARRAY(hw, IGC_FFLT, 0x0001);
+	reg_data &= ~0x00100000;
+	IGC_WRITE_REG_ARRAY(hw, IGC_FFLT, 0x0001, reg_data);
+
+	/* default to true to enable the MDIC W/A */
+	hw->dev_spec._80003es2lan.mdic_wa_enable = true;
+
+	ret_val =
+	    igc_read_kmrn_reg_80003es2lan(hw, IGC_KMRNCTRLSTA_OFFSET >>
+					    IGC_KMRNCTRLSTA_OFFSET_SHIFT, &i);
+	if (!ret_val) {
+		if ((i & IGC_KMRNCTRLSTA_OPMODE_MASK) ==
+		     IGC_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
+			hw->dev_spec._80003es2lan.mdic_wa_enable = false;
+	}
+
+	/* Clear all of the statistics registers (clear on read).  It is
+	 * important that we do this after we have tried to establish link
+	 * because the symbol error count will increment wildly if there
+	 * is no link.
+	 */
+	igc_clear_hw_cntrs_80003es2lan(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_initialize_hw_bits_80003es2lan - Init hw bits of ESB2
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes required hardware-dependent bits needed for normal operation.
+ **/
+STATIC void igc_initialize_hw_bits_80003es2lan(struct igc_hw *hw)
+{
+	u32 reg;
+
+	DEBUGFUNC("igc_initialize_hw_bits_80003es2lan");
+
+	/* Transmit Descriptor Control 0 */
+	reg = IGC_READ_REG(hw, IGC_TXDCTL(0));
+	reg |= (1 << 22);
+	IGC_WRITE_REG(hw, IGC_TXDCTL(0), reg);
+
+	/* Transmit Descriptor Control 1 */
+	reg = IGC_READ_REG(hw, IGC_TXDCTL(1));
+	reg |= (1 << 22);
+	IGC_WRITE_REG(hw, IGC_TXDCTL(1), reg);
+
+	/* Transmit Arbitration Control 0 */
+	reg = IGC_READ_REG(hw, IGC_TARC(0));
+	reg &= ~(0xF << 27); /* 30:27 */
+	if (hw->phy.media_type != igc_media_type_copper)
+		reg &= ~(1 << 20);
+	IGC_WRITE_REG(hw, IGC_TARC(0), reg);
+
+	/* Transmit Arbitration Control 1 */
+	reg = IGC_READ_REG(hw, IGC_TARC(1));
+	if (IGC_READ_REG(hw, IGC_TCTL) & IGC_TCTL_MULR)
+		reg &= ~(1 << 28);
+	else
+		reg |= (1 << 28);
+	IGC_WRITE_REG(hw, IGC_TARC(1), reg);
+
+	/* Disable IPv6 extension header parsing because some malformed
+	 * IPv6 headers can hang the Rx.
+	 */
+	reg = IGC_READ_REG(hw, IGC_RFCTL);
+	reg |= (IGC_RFCTL_IPV6_EX_DIS | IGC_RFCTL_NEW_IPV6_EXT_DIS);
+	IGC_WRITE_REG(hw, IGC_RFCTL, reg);
+
+	return;
+}
+
+/**
+ *  igc_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link
+ *  @hw: pointer to the HW structure
+ *
+ *  Setup some GG82563 PHY registers for obtaining link
+ **/
+STATIC s32 igc_copper_link_setup_gg82563_80003es2lan(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u32 reg;
+	u16 data;
+
+	DEBUGFUNC("igc_copper_link_setup_gg82563_80003es2lan");
+
+	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
+	if (ret_val)
+		return ret_val;
+
+	data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+	/* Use 25MHz for both link down and 1000Base-T for Tx clock. */
+	data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
+
+	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
+	if (ret_val)
+		return ret_val;
+
+	/* Options:
+	 *   MDI/MDI-X = 0 (default)
+	 *   0 - Auto for all speeds
+	 *   1 - MDI mode
+	 *   2 - MDI-X mode
+	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+	 */
+	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data);
+	if (ret_val)
+		return ret_val;
+
+	data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
+
+	switch (phy->mdix) {
+	case 1:
+		data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
+		break;
+	case 2:
+		data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
+		break;
+	case 0:
+	default:
+		data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
+		break;
+	}
+
+	/* Options:
+	 *   disable_polarity_correction = 0 (default)
+	 *       Automatic Correction for Reversed Cable Polarity
+	 *   0 - Disabled
+	 *   1 - Enabled
+	 */
+	data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
+	if (phy->disable_polarity_correction)
+		data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
+
+	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data);
+	if (ret_val)
+		return ret_val;
+
+	/* SW Reset the PHY so all changes take effect */
+	ret_val = hw->phy.ops.commit(hw);
+	if (ret_val) {
+		DEBUGOUT("Error Resetting the PHY\n");
+		return ret_val;
+	}
+
+	/* Bypass Rx and Tx FIFO's */
+	reg = IGC_KMRNCTRLSTA_OFFSET_FIFO_CTRL;
+	data = (IGC_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
+		IGC_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
+	ret_val = igc_write_kmrn_reg_80003es2lan(hw, reg, data);
+	if (ret_val)
+		return ret_val;
+
+	reg = IGC_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE;
+	ret_val = igc_read_kmrn_reg_80003es2lan(hw, reg, &data);
+	if (ret_val)
+		return ret_val;
+	data |= IGC_KMRNCTRLSTA_OPMODE_E_IDLE;
+	ret_val = igc_write_kmrn_reg_80003es2lan(hw, reg, data);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data);
+	if (ret_val)
+		return ret_val;
+
+	data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
+	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data);
+	if (ret_val)
+		return ret_val;
+
+	reg = IGC_READ_REG(hw, IGC_CTRL_EXT);
+	reg &= ~IGC_CTRL_EXT_LINK_MODE_MASK;
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, reg);
+
+	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
+	if (ret_val)
+		return ret_val;
+
+	/* Do not init these registers when the HW is in IAMT mode, since the
+	 * firmware will have already initialized them.  We only initialize
+	 * them if the HW is not in IAMT mode.
+	 */
+	if (!hw->mac.ops.check_mng_mode(hw)) {
+		/* Enable Electrical Idle on the PHY */
+		data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
+		ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+						data);
+		if (ret_val)
+			return ret_val;
+
+		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+					       &data);
+		if (ret_val)
+			return ret_val;
+
+		data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+		ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+						data);
+		if (ret_val)
+			return ret_val;
+	}
+
+	/* Workaround: Disable padding in Kumeran interface in the MAC
+	 * and in the PHY to avoid CRC errors.
+	 */
+	ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data);
+	if (ret_val)
+		return ret_val;
+
+	data |= GG82563_ICR_DIS_PADDING;
+	ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data);
+	if (ret_val)
+		return ret_val;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_setup_copper_link_80003es2lan - Setup Copper Link for ESB2
+ *  @hw: pointer to the HW structure
+ *
+ *  Essentially a wrapper for setting up all things "copper" related.
+ *  This is a function pointer entry point called by the mac module.
+ **/
+STATIC s32 igc_setup_copper_link_80003es2lan(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+	u16 reg_data;
+
+	DEBUGFUNC("igc_setup_copper_link_80003es2lan");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	ctrl |= IGC_CTRL_SLU;
+	ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	/* Set the mac to wait the maximum time between each
+	 * iteration and increase the max iterations when
+	 * polling the phy; this fixes erroneous timeouts at 10Mbps.
+	 */
+	ret_val = igc_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
+						   0xFFFF);
+	if (ret_val)
+		return ret_val;
+	ret_val = igc_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
+						  &reg_data);
+	if (ret_val)
+		return ret_val;
+	reg_data |= 0x3F;
+	ret_val = igc_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
+						   reg_data);
+	if (ret_val)
+		return ret_val;
+	ret_val =
+	    igc_read_kmrn_reg_80003es2lan(hw,
+					    IGC_KMRNCTRLSTA_OFFSET_INB_CTRL,
+					    &reg_data);
+	if (ret_val)
+		return ret_val;
+	reg_data |= IGC_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
+	ret_val =
+	    igc_write_kmrn_reg_80003es2lan(hw,
+					     IGC_KMRNCTRLSTA_OFFSET_INB_CTRL,
+					     reg_data);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = igc_copper_link_setup_gg82563_80003es2lan(hw);
+	if (ret_val)
+		return ret_val;
+
+	return igc_setup_copper_link_generic(hw);
+}
+
+/**
+ *  igc_cfg_on_link_up_80003es2lan - es2 link configuration after link-up
+ *  @hw: pointer to the HW structure
+ *
+ *  Configure the KMRN interface by applying last minute quirks for
+ *  10/100 operation.
+ **/
+STATIC s32 igc_cfg_on_link_up_80003es2lan(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	u16 speed;
+	u16 duplex;
+
+	DEBUGFUNC("igc_configure_on_link_up");
+
+	if (hw->phy.media_type == igc_media_type_copper) {
+		ret_val = igc_get_speed_and_duplex_copper_generic(hw, &speed,
+								    &duplex);
+		if (ret_val)
+			return ret_val;
+
+		if (speed == SPEED_1000)
+			ret_val = igc_cfg_kmrn_1000_80003es2lan(hw);
+		else
+			ret_val = igc_cfg_kmrn_10_100_80003es2lan(hw, duplex);
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation
+ *  @hw: pointer to the HW structure
+ *  @duplex: current duplex setting
+ *
+ *  Configure the KMRN interface by applying last minute quirks for
+ *  10/100 operation.
+ **/
+STATIC s32 igc_cfg_kmrn_10_100_80003es2lan(struct igc_hw *hw, u16 duplex)
+{
+	s32 ret_val;
+	u32 tipg;
+	u32 i = 0;
+	u16 reg_data, reg_data2;
+
+	DEBUGFUNC("igc_configure_kmrn_for_10_100");
+
+	reg_data = IGC_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
+	ret_val =
+	    igc_write_kmrn_reg_80003es2lan(hw,
+					     IGC_KMRNCTRLSTA_OFFSET_HD_CTRL,
+					     reg_data);
+	if (ret_val)
+		return ret_val;
+
+	/* Configure Transmit Inter-Packet Gap */
+	tipg = IGC_READ_REG(hw, IGC_TIPG);
+	tipg &= ~IGC_TIPG_IPGT_MASK;
+	tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
+	IGC_WRITE_REG(hw, IGC_TIPG, tipg);
+
+	do {
+		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+					       &reg_data);
+		if (ret_val)
+			return ret_val;
+
+		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+					       &reg_data2);
+		if (ret_val)
+			return ret_val;
+		i++;
+	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
+
+	if (duplex == HALF_DUPLEX)
+		reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
+	else
+		reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+
+	return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+}
+
+/**
+ *  igc_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation
+ *  @hw: pointer to the HW structure
+ *
+ *  Configure the KMRN interface by applying last minute quirks for
+ *  gigabit operation.
+ **/
+STATIC s32 igc_cfg_kmrn_1000_80003es2lan(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u16 reg_data, reg_data2;
+	u32 tipg;
+	u32 i = 0;
+
+	DEBUGFUNC("igc_configure_kmrn_for_1000");
+
+	reg_data = IGC_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
+	ret_val =
+	    igc_write_kmrn_reg_80003es2lan(hw,
+					     IGC_KMRNCTRLSTA_OFFSET_HD_CTRL,
+					     reg_data);
+	if (ret_val)
+		return ret_val;
+
+	/* Configure Transmit Inter-Packet Gap */
+	tipg = IGC_READ_REG(hw, IGC_TIPG);
+	tipg &= ~IGC_TIPG_IPGT_MASK;
+	tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
+	IGC_WRITE_REG(hw, IGC_TIPG, tipg);
+
+	do {
+		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+					       &reg_data);
+		if (ret_val)
+			return ret_val;
+
+		ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+					       &reg_data2);
+		if (ret_val)
+			return ret_val;
+		i++;
+	} while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
+
+	reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+
+	return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+}
+
+/**
+ *  igc_read_kmrn_reg_80003es2lan - Read kumeran register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Acquire semaphore, then read the PHY register at offset
+ *  using the kumeran interface.  The information retrieved is stored in data.
+ *  Release the semaphore before exiting.
+ **/
+STATIC s32 igc_read_kmrn_reg_80003es2lan(struct igc_hw *hw, u32 offset,
+					   u16 *data)
+{
+	u32 kmrnctrlsta;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_read_kmrn_reg_80003es2lan");
+
+	ret_val = igc_acquire_mac_csr_80003es2lan(hw);
+	if (ret_val)
+		return ret_val;
+
+	kmrnctrlsta = ((offset << IGC_KMRNCTRLSTA_OFFSET_SHIFT) &
+		       IGC_KMRNCTRLSTA_OFFSET) | IGC_KMRNCTRLSTA_REN;
+	IGC_WRITE_REG(hw, IGC_KMRNCTRLSTA, kmrnctrlsta);
+	IGC_WRITE_FLUSH(hw);
+
+	usec_delay(2);
+
+	kmrnctrlsta = IGC_READ_REG(hw, IGC_KMRNCTRLSTA);
+	*data = (u16)kmrnctrlsta;
+
+	igc_release_mac_csr_80003es2lan(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_write_kmrn_reg_80003es2lan - Write kumeran register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquire semaphore, then write the data to PHY register
+ *  at the offset using the kumeran interface.  Release semaphore
+ *  before exiting.
+ **/
+STATIC s32 igc_write_kmrn_reg_80003es2lan(struct igc_hw *hw, u32 offset,
+					    u16 data)
+{
+	u32 kmrnctrlsta;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_write_kmrn_reg_80003es2lan");
+
+	ret_val = igc_acquire_mac_csr_80003es2lan(hw);
+	if (ret_val)
+		return ret_val;
+
+	kmrnctrlsta = ((offset << IGC_KMRNCTRLSTA_OFFSET_SHIFT) &
+		       IGC_KMRNCTRLSTA_OFFSET) | data;
+	IGC_WRITE_REG(hw, IGC_KMRNCTRLSTA, kmrnctrlsta);
+	IGC_WRITE_FLUSH(hw);
+
+	usec_delay(2);
+
+	igc_release_mac_csr_80003es2lan(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_read_mac_addr_80003es2lan - Read device MAC address
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_read_mac_addr_80003es2lan(struct igc_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_read_mac_addr_80003es2lan");
+
+	/* If there's an alternate MAC address place it in RAR0
+	 * so that it will override the Si installed default perm
+	 * address.
+	 */
+	ret_val = igc_check_alt_mac_addr_generic(hw);
+	if (ret_val)
+		return ret_val;
+
+	return igc_read_mac_addr_generic(hw);
+}
+
+/**
+ * igc_power_down_phy_copper_80003es2lan - Remove link during PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+STATIC void igc_power_down_phy_copper_80003es2lan(struct igc_hw *hw)
+{
+	/* If the management interface is not enabled, then power down */
+	if (!(hw->mac.ops.check_mng_mode(hw) ||
+	      hw->phy.ops.check_reset_block(hw)))
+		igc_power_down_phy_copper(hw);
+
+	return;
+}
+
+/**
+ *  igc_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+STATIC void igc_clear_hw_cntrs_80003es2lan(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_clear_hw_cntrs_80003es2lan");
+
+	igc_clear_hw_cntrs_base_generic(hw);
+
+	IGC_READ_REG(hw, IGC_PRC64);
+	IGC_READ_REG(hw, IGC_PRC127);
+	IGC_READ_REG(hw, IGC_PRC255);
+	IGC_READ_REG(hw, IGC_PRC511);
+	IGC_READ_REG(hw, IGC_PRC1023);
+	IGC_READ_REG(hw, IGC_PRC1522);
+	IGC_READ_REG(hw, IGC_PTC64);
+	IGC_READ_REG(hw, IGC_PTC127);
+	IGC_READ_REG(hw, IGC_PTC255);
+	IGC_READ_REG(hw, IGC_PTC511);
+	IGC_READ_REG(hw, IGC_PTC1023);
+	IGC_READ_REG(hw, IGC_PTC1522);
+
+	IGC_READ_REG(hw, IGC_ALGNERRC);
+	IGC_READ_REG(hw, IGC_RXERRC);
+	IGC_READ_REG(hw, IGC_TNCRS);
+	IGC_READ_REG(hw, IGC_CEXTERR);
+	IGC_READ_REG(hw, IGC_TSCTC);
+	IGC_READ_REG(hw, IGC_TSCTFC);
+
+	IGC_READ_REG(hw, IGC_MGTPRC);
+	IGC_READ_REG(hw, IGC_MGTPDC);
+	IGC_READ_REG(hw, IGC_MGTPTC);
+
+	IGC_READ_REG(hw, IGC_IAC);
+	IGC_READ_REG(hw, IGC_ICRXOC);
+
+	IGC_READ_REG(hw, IGC_ICRXPTC);
+	IGC_READ_REG(hw, IGC_ICRXATC);
+	IGC_READ_REG(hw, IGC_ICTXPTC);
+	IGC_READ_REG(hw, IGC_ICTXATC);
+	IGC_READ_REG(hw, IGC_ICTXQEC);
+	IGC_READ_REG(hw, IGC_ICTXQMTC);
+	IGC_READ_REG(hw, IGC_ICRXDMTC);
+}
diff --git a/drivers/net/igc/base/e1000_80003es2lan.h b/drivers/net/igc/base/e1000_80003es2lan.h
new file mode 100644
index 0000000..ba06fba
--- /dev/null
+++ b/drivers/net/igc/base/e1000_80003es2lan.h
@@ -0,0 +1,71 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_80003ES2LAN_H_
+#define _IGC_80003ES2LAN_H_
+
+#define IGC_KMRNCTRLSTA_OFFSET_FIFO_CTRL	0x00
+#define IGC_KMRNCTRLSTA_OFFSET_INB_CTRL	0x02
+#define IGC_KMRNCTRLSTA_OFFSET_HD_CTRL	0x10
+#define IGC_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE	0x1F
+
+#define IGC_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS	0x0008
+#define IGC_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS	0x0800
+#define IGC_KMRNCTRLSTA_INB_CTRL_DIS_PADDING	0x0010
+
+#define IGC_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004
+#define IGC_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT	0x0000
+#define IGC_KMRNCTRLSTA_OPMODE_E_IDLE		0x2000
+
+#define IGC_KMRNCTRLSTA_OPMODE_MASK		0x000C
+#define IGC_KMRNCTRLSTA_OPMODE_INBAND_MDIO	0x0004
+
+#define IGC_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gig Carry Extend Padding */
+#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN	0x00010000
+
+#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN	0x8
+#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN	0x9
+
+/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
+#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE	0x0002 /* 1=Reversal Dis */
+#define GG82563_PSCR_CROSSOVER_MODE_MASK	0x0060
+#define GG82563_PSCR_CROSSOVER_MODE_MDI		0x0000 /* 00=Manual MDI */
+#define GG82563_PSCR_CROSSOVER_MODE_MDIX	0x0020 /* 01=Manual MDIX */
+#define GG82563_PSCR_CROSSOVER_MODE_AUTO	0x0060 /* 11=Auto crossover */
+
+/* PHY Specific Control Register 2 (Page 0, Register 26) */
+#define GG82563_PSCR2_REVERSE_AUTO_NEG		0x2000 /* 1=Reverse Auto-Neg */
+
+/* MAC Specific Control Register (Page 2, Register 21) */
+/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
+#define GG82563_MSCR_TX_CLK_MASK		0x0007
+#define GG82563_MSCR_TX_CLK_10MBPS_2_5		0x0004
+#define GG82563_MSCR_TX_CLK_100MBPS_25		0x0005
+#define GG82563_MSCR_TX_CLK_1000MBPS_25		0x0007
+
+#define GG82563_MSCR_ASSERT_CRS_ON_TX		0x0010 /* 1=Assert */
+
+/* DSP Distance Register (Page 5, Register 26)
+ * 0 = <50M
+ * 1 = 50-80M
+ * 2 = 80-100M
+ * 3 = 110-140M
+ * 4 = >140M
+ */
+#define GG82563_DSPD_CABLE_LENGTH		0x0007
+
+/* Kumeran Mode Control Register (Page 193, Register 16) */
+#define GG82563_KMCR_PASS_FALSE_CARRIER		0x0800
+
+/* Max number of times Kumeran read/write should be validated */
+#define GG82563_MAX_KMRN_RETRY			0x5
+
+/* Power Management Control Register (Page 193, Register 20) */
+/* 1=Enable SERDES Electrical Idle */
+#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE	0x0001
+
+/* In-Band Control Register (Page 194, Register 18) */
+#define GG82563_ICR_DIS_PADDING			0x0010 /* Disable Padding */
+
+#endif
diff --git a/drivers/net/igc/base/e1000_82540.c b/drivers/net/igc/base/e1000_82540.c
new file mode 100644
index 0000000..6a96949
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82540.c
@@ -0,0 +1,688 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+/*
+ * 82540EM Gigabit Ethernet Controller
+ * 82540EP Gigabit Ethernet Controller
+ * 82545EM Gigabit Ethernet Controller (Copper)
+ * 82545EM Gigabit Ethernet Controller (Fiber)
+ * 82545GM Gigabit Ethernet Controller
+ * 82546EB Gigabit Ethernet Controller (Copper)
+ * 82546EB Gigabit Ethernet Controller (Fiber)
+ * 82546GB Gigabit Ethernet Controller
+ */
+
+#include "e1000_api.h"
+
+STATIC s32  igc_init_phy_params_82540(struct igc_hw *hw);
+STATIC s32  igc_init_nvm_params_82540(struct igc_hw *hw);
+STATIC s32  igc_init_mac_params_82540(struct igc_hw *hw);
+STATIC s32  igc_adjust_serdes_amplitude_82540(struct igc_hw *hw);
+STATIC void igc_clear_hw_cntrs_82540(struct igc_hw *hw);
+STATIC s32  igc_init_hw_82540(struct igc_hw *hw);
+STATIC s32  igc_reset_hw_82540(struct igc_hw *hw);
+STATIC s32  igc_set_phy_mode_82540(struct igc_hw *hw);
+STATIC s32  igc_set_vco_speed_82540(struct igc_hw *hw);
+STATIC s32  igc_setup_copper_link_82540(struct igc_hw *hw);
+STATIC s32  igc_setup_fiber_serdes_link_82540(struct igc_hw *hw);
+STATIC void igc_power_down_phy_copper_82540(struct igc_hw *hw);
+STATIC s32  igc_read_mac_addr_82540(struct igc_hw *hw);
+
+/**
+ * igc_init_phy_params_82540 - Init PHY func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_phy_params_82540(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+
+	phy->addr		= 1;
+	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+	phy->reset_delay_us	= 10000;
+	phy->type		= igc_phy_m88;
+
+	/* Function Pointers */
+	phy->ops.check_polarity	= igc_check_polarity_m88;
+	phy->ops.commit		= igc_phy_sw_reset_generic;
+	phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_m88;
+	phy->ops.get_cable_length = igc_get_cable_length_m88;
+	phy->ops.get_cfg_done	= igc_get_cfg_done_generic;
+	phy->ops.read_reg	= igc_read_phy_reg_m88;
+	phy->ops.reset		= igc_phy_hw_reset_generic;
+	phy->ops.write_reg	= igc_write_phy_reg_m88;
+	phy->ops.get_info	= igc_get_phy_info_m88;
+	phy->ops.power_up	= igc_power_up_phy_copper;
+	phy->ops.power_down	= igc_power_down_phy_copper_82540;
+
+	ret_val = igc_get_phy_id(hw);
+	if (ret_val)
+		goto out;
+
+	/* Verify phy id */
+	switch (hw->mac.type) {
+	case igc_82540:
+	case igc_82545:
+	case igc_82545_rev_3:
+	case igc_82546:
+	case igc_82546_rev_3:
+		if (phy->id == M88E1011_I_PHY_ID)
+			break;
+		/* Fall Through */
+	default:
+		ret_val = -IGC_ERR_PHY;
+		goto out;
+		break;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ * igc_init_nvm_params_82540 - Init NVM func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_nvm_params_82540(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	u32 eecd = IGC_READ_REG(hw, IGC_EECD);
+
+	DEBUGFUNC("igc_init_nvm_params_82540");
+
+	nvm->type = igc_nvm_eeprom_microwire;
+	nvm->delay_usec = 50;
+	nvm->opcode_bits = 3;
+	switch (nvm->override) {
+	case igc_nvm_override_microwire_large:
+		nvm->address_bits = 8;
+		nvm->word_size = 256;
+		break;
+	case igc_nvm_override_microwire_small:
+		nvm->address_bits = 6;
+		nvm->word_size = 64;
+		break;
+	default:
+		nvm->address_bits = eecd & IGC_EECD_SIZE ? 8 : 6;
+		nvm->word_size = eecd & IGC_EECD_SIZE ? 256 : 64;
+		break;
+	}
+
+	/* Function Pointers */
+	nvm->ops.acquire	= igc_acquire_nvm_generic;
+	nvm->ops.read		= igc_read_nvm_microwire;
+	nvm->ops.release	= igc_release_nvm_generic;
+	nvm->ops.update		= igc_update_nvm_checksum_generic;
+	nvm->ops.valid_led_default = igc_valid_led_default_generic;
+	nvm->ops.validate	= igc_validate_nvm_checksum_generic;
+	nvm->ops.write		= igc_write_nvm_microwire;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ * igc_init_mac_params_82540 - Init MAC func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_mac_params_82540(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_init_mac_params_82540");
+
+	/* Set media type */
+	switch (hw->device_id) {
+	case IGC_DEV_ID_82545EM_FIBER:
+	case IGC_DEV_ID_82545GM_FIBER:
+	case IGC_DEV_ID_82546EB_FIBER:
+	case IGC_DEV_ID_82546GB_FIBER:
+		hw->phy.media_type = igc_media_type_fiber;
+		break;
+	case IGC_DEV_ID_82545GM_SERDES:
+	case IGC_DEV_ID_82546GB_SERDES:
+		hw->phy.media_type = igc_media_type_internal_serdes;
+		break;
+	default:
+		hw->phy.media_type = igc_media_type_copper;
+		break;
+	}
+
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	mac->rar_entry_count = IGC_RAR_ENTRIES;
+
+	/* Function pointers */
+
+	/* bus type/speed/width */
+	mac->ops.get_bus_info = igc_get_bus_info_pci_generic;
+	/* function id */
+	mac->ops.set_lan_id = igc_set_lan_id_multi_port_pci;
+	/* reset */
+	mac->ops.reset_hw = igc_reset_hw_82540;
+	/* hw initialization */
+	mac->ops.init_hw = igc_init_hw_82540;
+	/* link setup */
+	mac->ops.setup_link = igc_setup_link_generic;
+	/* physical interface setup */
+	mac->ops.setup_physical_interface =
+		(hw->phy.media_type == igc_media_type_copper)
+			? igc_setup_copper_link_82540
+			: igc_setup_fiber_serdes_link_82540;
+	/* check for link */
+	switch (hw->phy.media_type) {
+	case igc_media_type_copper:
+		mac->ops.check_for_link = igc_check_for_copper_link_generic;
+		break;
+	case igc_media_type_fiber:
+		mac->ops.check_for_link = igc_check_for_fiber_link_generic;
+		break;
+	case igc_media_type_internal_serdes:
+		mac->ops.check_for_link = igc_check_for_serdes_link_generic;
+		break;
+	default:
+		ret_val = -IGC_ERR_CONFIG;
+		goto out;
+		break;
+	}
+	/* link info */
+	mac->ops.get_link_up_info =
+		(hw->phy.media_type == igc_media_type_copper)
+			? igc_get_speed_and_duplex_copper_generic
+			: igc_get_speed_and_duplex_fiber_serdes_generic;
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
+	/* writing VFTA */
+	mac->ops.write_vfta = igc_write_vfta_generic;
+	/* clearing VFTA */
+	mac->ops.clear_vfta = igc_clear_vfta_generic;
+	/* read mac address */
+	mac->ops.read_mac_addr = igc_read_mac_addr_82540;
+	/* ID LED init */
+	mac->ops.id_led_init = igc_id_led_init_generic;
+	/* setup LED */
+	mac->ops.setup_led = igc_setup_led_generic;
+	/* cleanup LED */
+	mac->ops.cleanup_led = igc_cleanup_led_generic;
+	/* turn on/off LED */
+	mac->ops.led_on = igc_led_on_generic;
+	mac->ops.led_off = igc_led_off_generic;
+	/* clear hardware counters */
+	mac->ops.clear_hw_cntrs = igc_clear_hw_cntrs_82540;
+
+out:
+	return ret_val;
+}
+
+/**
+ * igc_init_function_pointers_82540 - Init func ptrs.
+ * @hw: pointer to the HW structure
+ *
+ * Called to initialize all function pointers and parameters.
+ **/
+void igc_init_function_pointers_82540(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_init_function_pointers_82540");
+
+	hw->mac.ops.init_params = igc_init_mac_params_82540;
+	hw->nvm.ops.init_params = igc_init_nvm_params_82540;
+	hw->phy.ops.init_params = igc_init_phy_params_82540;
+}
+
+/**
+ *  igc_reset_hw_82540 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 igc_reset_hw_82540(struct igc_hw *hw)
+{
+	u32 ctrl, manc;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_reset_hw_82540");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xFFFFFFFF);
+
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
+	IGC_WRITE_FLUSH(hw);
+
+	/*
+	 * Delay to allow any outstanding PCI transactions to complete
+	 * before resetting the device.
+	 */
+	msec_delay(10);
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGOUT("Issuing a global reset to 82540/82545/82546 MAC\n");
+	switch (hw->mac.type) {
+	case igc_82545_rev_3:
+	case igc_82546_rev_3:
+		IGC_WRITE_REG(hw, IGC_CTRL_DUP, ctrl | IGC_CTRL_RST);
+		break;
+	default:
+		/*
+		 * These controllers can't ack the 64-bit write when
+		 * issuing the reset, so we use IO-mapping as a
+		 * workaround to issue the reset.
+		 */
+		IGC_WRITE_REG_IO(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+		break;
+	}
+
+	/* Wait for EEPROM reload */
+	msec_delay(5);
+
+	/* Disable HW ARPs on ASF enabled adapters */
+	manc = IGC_READ_REG(hw, IGC_MANC);
+	manc &= ~IGC_MANC_ARP_EN;
+	IGC_WRITE_REG(hw, IGC_MANC, manc);
+
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_READ_REG(hw, IGC_ICR);
+
+	return ret_val;
+}
+
+/**
+ *  igc_init_hw_82540 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+STATIC s32 igc_init_hw_82540(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	u32 txdctl, ctrl_ext;
+	s32 ret_val;
+	u16 i;
+
+	DEBUGFUNC("igc_init_hw_82540");
+
+	/* Initialize identification LED */
+	ret_val = mac->ops.id_led_init(hw);
+	if (ret_val) {
+		DEBUGOUT("Error initializing identification LED\n");
+		/* This is not fatal and we should not stop init due to this */
+	}
+
+	/* Disabling VLAN filtering */
+	DEBUGOUT("Initializing the IEEE VLAN\n");
+	if (mac->type < igc_82545_rev_3)
+		IGC_WRITE_REG(hw, IGC_VET, 0);
+
+	mac->ops.clear_vfta(hw);
+
+	/* Setup the receive address. */
+	igc_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for (i = 0; i < mac->mta_reg_count; i++) {
+		IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
+		/*
+		 * Avoid back to back register writes by adding the register
+		 * read (flush).  This is to protect against some strange
+		 * bridge configurations that may issue Memory Write Block
+		 * (MWB) to our register space.  The *_rev_3 hardware at
+		 * least doesn't respond correctly to every other dword in an
+		 * MWB to our register space.
+		 */
+		IGC_WRITE_FLUSH(hw);
+	}
+
+	if (mac->type < igc_82545_rev_3)
+		igc_pcix_mmrbc_workaround_generic(hw);
+
+	/* Setup link and flow control */
+	ret_val = mac->ops.setup_link(hw);
+
+	txdctl = IGC_READ_REG(hw, IGC_TXDCTL(0));
+	txdctl = (txdctl & ~IGC_TXDCTL_WTHRESH) |
+		  IGC_TXDCTL_FULL_TX_DESC_WB;
+	IGC_WRITE_REG(hw, IGC_TXDCTL(0), txdctl);
+
+	/*
+	 * Clear all of the statistics registers (clear on read).  It is
+	 * important that we do this after we have tried to establish link
+	 * because the symbol error count will increment wildly if there
+	 * is no link.
+	 */
+	igc_clear_hw_cntrs_82540(hw);
+
+	if ((hw->device_id == IGC_DEV_ID_82546GB_QUAD_COPPER) ||
+	    (hw->device_id == IGC_DEV_ID_82546GB_QUAD_COPPER_KSP3)) {
+		ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+		/*
+		 * Relaxed ordering must be disabled to avoid a parity
+		 * error crash in a PCI slot.
+		 */
+		ctrl_ext |= IGC_CTRL_EXT_RO_DIS;
+		IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_setup_copper_link_82540 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the appropriate function to configure the link for auto-neg or forced
+ *  speed and duplex.  Then we check for link, once link is established calls
+ *  to configure collision distance and flow control are called.  If link is
+ *  not established, we return -IGC_ERR_PHY (-2).
+ **/
+STATIC s32 igc_setup_copper_link_82540(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+	u16 data;
+
+	DEBUGFUNC("igc_setup_copper_link_82540");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	ctrl |= IGC_CTRL_SLU;
+	ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	ret_val = igc_set_phy_mode_82540(hw);
+	if (ret_val)
+		goto out;
+
+	if (hw->mac.type == igc_82545_rev_3 ||
+	    hw->mac.type == igc_82546_rev_3) {
+		ret_val = hw->phy.ops.read_reg(hw, M88IGC_PHY_SPEC_CTRL,
+					       &data);
+		if (ret_val)
+			goto out;
+		data |= 0x00000008;
+		ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_SPEC_CTRL,
+						data);
+		if (ret_val)
+			goto out;
+	}
+
+	ret_val = igc_copper_link_setup_m88(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igc_setup_copper_link_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_setup_fiber_serdes_link_82540 - Setup link for fiber/serdes
+ *  @hw: pointer to the HW structure
+ *
+ *  Set the output amplitude to the value in the EEPROM and adjust the VCO
+ *  speed to improve Bit Error Rate (BER) performance.  Configures collision
+ *  distance and flow control for fiber and serdes links.  Upon successful
+ *  setup, poll for link.
+ **/
+STATIC s32 igc_setup_fiber_serdes_link_82540(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_setup_fiber_serdes_link_82540");
+
+	switch (mac->type) {
+	case igc_82545_rev_3:
+	case igc_82546_rev_3:
+		if (hw->phy.media_type == igc_media_type_internal_serdes) {
+			/*
+			 * If we're on serdes media, adjust the output
+			 * amplitude to value set in the EEPROM.
+			 */
+			ret_val = igc_adjust_serdes_amplitude_82540(hw);
+			if (ret_val)
+				goto out;
+		}
+		/* Adjust VCO speed to improve BER performance */
+		ret_val = igc_set_vco_speed_82540(hw);
+		if (ret_val)
+			goto out;
+	default:
+		break;
+	}
+
+	ret_val = igc_setup_fiber_serdes_link_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_adjust_serdes_amplitude_82540 - Adjust amplitude based on EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Adjust the SERDES output amplitude based on the EEPROM settings.
+ **/
+STATIC s32 igc_adjust_serdes_amplitude_82540(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u16 nvm_data;
+
+	DEBUGFUNC("igc_adjust_serdes_amplitude_82540");
+
+	ret_val = hw->nvm.ops.read(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data);
+	if (ret_val)
+		goto out;
+
+	if (nvm_data != NVM_RESERVED_WORD) {
+		/* Adjust serdes output amplitude only. */
+		nvm_data &= NVM_SERDES_AMPLITUDE_MASK;
+		ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_EXT_CTRL,
+						nvm_data);
+		if (ret_val)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_set_vco_speed_82540 - Set VCO speed for better performance
+ *  @hw: pointer to the HW structure
+ *
+ *  Set the VCO speed to improve Bit Error Rate (BER) performance.
+ **/
+STATIC s32 igc_set_vco_speed_82540(struct igc_hw *hw)
+{
+	s32  ret_val;
+	u16 default_page = 0;
+	u16 phy_data;
+
+	DEBUGFUNC("igc_set_vco_speed_82540");
+
+	/* Set PHY register 30, page 5, bit 8 to 0 */
+
+	ret_val = hw->phy.ops.read_reg(hw, M88IGC_PHY_PAGE_SELECT,
+				       &default_page);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_PAGE_SELECT, 0x0005);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.read_reg(hw, M88IGC_PHY_GEN_CONTROL, &phy_data);
+	if (ret_val)
+		goto out;
+
+	phy_data &= ~M88IGC_PHY_VCO_REG_BIT8;
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_GEN_CONTROL, phy_data);
+	if (ret_val)
+		goto out;
+
+	/* Set PHY register 30, page 4, bit 11 to 1 */
+
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_PAGE_SELECT, 0x0004);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.read_reg(hw, M88IGC_PHY_GEN_CONTROL, &phy_data);
+	if (ret_val)
+		goto out;
+
+	phy_data |= M88IGC_PHY_VCO_REG_BIT11;
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_GEN_CONTROL, phy_data);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_PAGE_SELECT,
+					default_page);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_set_phy_mode_82540 - Set PHY to class A mode
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets the PHY to class A mode and assumes the following operations will
+ *  follow to enable the new class mode:
+ *    1.  Do a PHY soft reset.
+ *    2.  Restart auto-negotiation or force link.
+ **/
+STATIC s32 igc_set_phy_mode_82540(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	u16 nvm_data;
+
+	DEBUGFUNC("igc_set_phy_mode_82540");
+
+	if (hw->mac.type != igc_82545_rev_3)
+		goto out;
+
+	ret_val = hw->nvm.ops.read(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data);
+	if (ret_val) {
+		ret_val = -IGC_ERR_PHY;
+		goto out;
+	}
+
+	if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) {
+		ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_PAGE_SELECT,
+						0x000B);
+		if (ret_val) {
+			ret_val = -IGC_ERR_PHY;
+			goto out;
+		}
+		ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_GEN_CONTROL,
+						0x8104);
+		if (ret_val) {
+			ret_val = -IGC_ERR_PHY;
+			goto out;
+		}
+
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ * igc_power_down_phy_copper_82540 - Remove link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+STATIC void igc_power_down_phy_copper_82540(struct igc_hw *hw)
+{
+	/* If the management interface is not enabled, then power down */
+	if (!(IGC_READ_REG(hw, IGC_MANC) & IGC_MANC_SMBUS_EN))
+		igc_power_down_phy_copper(hw);
+
+	return;
+}
+
+/**
+ *  igc_clear_hw_cntrs_82540 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+STATIC void igc_clear_hw_cntrs_82540(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_clear_hw_cntrs_82540");
+
+	igc_clear_hw_cntrs_base_generic(hw);
+
+	IGC_READ_REG(hw, IGC_PRC64);
+	IGC_READ_REG(hw, IGC_PRC127);
+	IGC_READ_REG(hw, IGC_PRC255);
+	IGC_READ_REG(hw, IGC_PRC511);
+	IGC_READ_REG(hw, IGC_PRC1023);
+	IGC_READ_REG(hw, IGC_PRC1522);
+	IGC_READ_REG(hw, IGC_PTC64);
+	IGC_READ_REG(hw, IGC_PTC127);
+	IGC_READ_REG(hw, IGC_PTC255);
+	IGC_READ_REG(hw, IGC_PTC511);
+	IGC_READ_REG(hw, IGC_PTC1023);
+	IGC_READ_REG(hw, IGC_PTC1522);
+
+	IGC_READ_REG(hw, IGC_ALGNERRC);
+	IGC_READ_REG(hw, IGC_RXERRC);
+	IGC_READ_REG(hw, IGC_TNCRS);
+	IGC_READ_REG(hw, IGC_CEXTERR);
+	IGC_READ_REG(hw, IGC_TSCTC);
+	IGC_READ_REG(hw, IGC_TSCTFC);
+
+	IGC_READ_REG(hw, IGC_MGTPRC);
+	IGC_READ_REG(hw, IGC_MGTPDC);
+	IGC_READ_REG(hw, IGC_MGTPTC);
+}
+
+/**
+ *  igc_read_mac_addr_82540 - Read device MAC address
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the device MAC address from the EEPROM and stores the value.
+ *  Since devices with two ports use the same EEPROM, we increment the
+ *  last bit in the MAC address for the second port.
+ *
+ *  This version is being used over generic because of customer issues
+ *  with VmWare and Virtual Box when using generic. It seems in
+ *  the emulated 82545, RAR[0] does NOT have a valid address after a
+ *  reset, this older method works and using this breaks nothing for
+ *  these legacy adapters.
+ **/
+s32 igc_read_mac_addr_82540(struct igc_hw *hw)
+{
+	s32  ret_val = IGC_SUCCESS;
+	u16 offset, nvm_data, i;
+
+	DEBUGFUNC("igc_read_mac_addr");
+
+	for (i = 0; i < ETH_ADDR_LEN; i += 2) {
+		offset = i >> 1;
+		ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
+		if (ret_val) {
+			DEBUGOUT("NVM Read Error\n");
+			goto out;
+		}
+		hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
+		hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
+	}
+
+	/* Flip last bit of mac address if we're on second port */
+	if (hw->bus.func == IGC_FUNC_1)
+		hw->mac.perm_addr[5] ^= 1;
+
+	for (i = 0; i < ETH_ADDR_LEN; i++)
+		hw->mac.addr[i] = hw->mac.perm_addr[i];
+
+out:
+	return ret_val;
+}
diff --git a/drivers/net/igc/base/e1000_82541.c b/drivers/net/igc/base/e1000_82541.c
new file mode 100644
index 0000000..83c3a45
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82541.c
@@ -0,0 +1,1239 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+/*
+ * 82541EI Gigabit Ethernet Controller
+ * 82541ER Gigabit Ethernet Controller
+ * 82541GI Gigabit Ethernet Controller
+ * 82541PI Gigabit Ethernet Controller
+ * 82547EI Gigabit Ethernet Controller
+ * 82547GI Gigabit Ethernet Controller
+ */
+
+#include "e1000_api.h"
+
+STATIC s32  igc_init_phy_params_82541(struct igc_hw *hw);
+STATIC s32  igc_init_nvm_params_82541(struct igc_hw *hw);
+STATIC s32  igc_init_mac_params_82541(struct igc_hw *hw);
+STATIC s32  igc_reset_hw_82541(struct igc_hw *hw);
+STATIC s32  igc_init_hw_82541(struct igc_hw *hw);
+STATIC s32  igc_get_link_up_info_82541(struct igc_hw *hw, u16 *speed,
+					 u16 *duplex);
+STATIC s32  igc_phy_hw_reset_82541(struct igc_hw *hw);
+STATIC s32  igc_setup_copper_link_82541(struct igc_hw *hw);
+STATIC s32  igc_check_for_link_82541(struct igc_hw *hw);
+STATIC s32  igc_get_cable_length_igp_82541(struct igc_hw *hw);
+STATIC s32  igc_set_d3_lplu_state_82541(struct igc_hw *hw,
+					  bool active);
+STATIC s32  igc_setup_led_82541(struct igc_hw *hw);
+STATIC s32  igc_cleanup_led_82541(struct igc_hw *hw);
+STATIC void igc_clear_hw_cntrs_82541(struct igc_hw *hw);
+STATIC s32  igc_config_dsp_after_link_change_82541(struct igc_hw *hw,
+						     bool link_up);
+STATIC s32  igc_phy_init_script_82541(struct igc_hw *hw);
+STATIC void igc_power_down_phy_copper_82541(struct igc_hw *hw);
+
+STATIC const u16 igc_igp_cable_length_table[] = {
+	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10,
+	10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30,
+	40, 40, 40, 40, 40, 40, 40, 40, 40, 50, 50, 50, 50, 50, 50, 50, 60, 60,
+	60, 60, 60, 60, 60, 60, 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80,
+	80, 90, 90, 90, 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100,
+	100, 100, 100, 100, 100, 100, 100, 100, 110, 110, 110, 110, 110, 110,
+	110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 120, 120,
+	120, 120, 120, 120, 120, 120, 120, 120};
+#define IGP01IGC_AGC_LENGTH_TABLE_SIZE \
+		(sizeof(igc_igp_cable_length_table) / \
+		 sizeof(igc_igp_cable_length_table[0]))
+
+/**
+ *  igc_init_phy_params_82541 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_phy_params_82541(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_init_phy_params_82541");
+
+	phy->addr		= 1;
+	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+	phy->reset_delay_us	= 10000;
+	phy->type		= igc_phy_igp;
+
+	/* Function Pointers */
+	phy->ops.check_polarity	= igc_check_polarity_igp;
+	phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_igp;
+	phy->ops.get_cable_length = igc_get_cable_length_igp_82541;
+	phy->ops.get_cfg_done	= igc_get_cfg_done_generic;
+	phy->ops.get_info	= igc_get_phy_info_igp;
+	phy->ops.read_reg	= igc_read_phy_reg_igp;
+	phy->ops.reset		= igc_phy_hw_reset_82541;
+	phy->ops.set_d3_lplu_state = igc_set_d3_lplu_state_82541;
+	phy->ops.write_reg	= igc_write_phy_reg_igp;
+	phy->ops.power_up	= igc_power_up_phy_copper;
+	phy->ops.power_down	= igc_power_down_phy_copper_82541;
+
+	ret_val = igc_get_phy_id(hw);
+	if (ret_val)
+		goto out;
+
+	/* Verify phy id */
+	if (phy->id != IGP01IGC_I_PHY_ID) {
+		ret_val = -IGC_ERR_PHY;
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_init_nvm_params_82541 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_nvm_params_82541(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	s32 ret_val = IGC_SUCCESS;
+	u32 eecd = IGC_READ_REG(hw, IGC_EECD);
+	u16 size;
+
+	DEBUGFUNC("igc_init_nvm_params_82541");
+
+	switch (nvm->override) {
+	case igc_nvm_override_spi_large:
+		nvm->type = igc_nvm_eeprom_spi;
+		eecd |= IGC_EECD_ADDR_BITS;
+		break;
+	case igc_nvm_override_spi_small:
+		nvm->type = igc_nvm_eeprom_spi;
+		eecd &= ~IGC_EECD_ADDR_BITS;
+		break;
+	case igc_nvm_override_microwire_large:
+		nvm->type = igc_nvm_eeprom_microwire;
+		eecd |= IGC_EECD_SIZE;
+		break;
+	case igc_nvm_override_microwire_small:
+		nvm->type = igc_nvm_eeprom_microwire;
+		eecd &= ~IGC_EECD_SIZE;
+		break;
+	default:
+		nvm->type = eecd & IGC_EECD_TYPE ? igc_nvm_eeprom_spi
+			    : igc_nvm_eeprom_microwire;
+		break;
+	}
+
+	if (nvm->type == igc_nvm_eeprom_spi) {
+		nvm->address_bits = (eecd & IGC_EECD_ADDR_BITS) ? 16 : 8;
+		nvm->delay_usec = 1;
+		nvm->opcode_bits = 8;
+		nvm->page_size = (eecd & IGC_EECD_ADDR_BITS) ? 32 : 8;
+
+		/* Function Pointers */
+		nvm->ops.acquire	= igc_acquire_nvm_generic;
+		nvm->ops.read		= igc_read_nvm_spi;
+		nvm->ops.release	= igc_release_nvm_generic;
+		nvm->ops.update		= igc_update_nvm_checksum_generic;
+		nvm->ops.valid_led_default = igc_valid_led_default_generic;
+		nvm->ops.validate	= igc_validate_nvm_checksum_generic;
+		nvm->ops.write		= igc_write_nvm_spi;
+
+		/*
+		 * nvm->word_size must be discovered after the pointers
+		 * are set so we can verify the size from the nvm image
+		 * itself.  Temporarily set it to a dummy value so the
+		 * read will work.
+		 */
+		nvm->word_size = 64;
+		ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size);
+		if (ret_val)
+			goto out;
+		size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT;
+		/*
+		 * if size != 0, it can be added to a constant and become
+		 * the left-shift value to set the word_size.  Otherwise,
+		 * word_size stays at 64.
+		 */
+		if (size) {
+			size += NVM_WORD_SIZE_BASE_SHIFT_82541;
+			nvm->word_size = 1 << size;
+		}
+	} else {
+		nvm->address_bits = (eecd & IGC_EECD_ADDR_BITS) ? 8 : 6;
+		nvm->delay_usec = 50;
+		nvm->opcode_bits = 3;
+		nvm->word_size = (eecd & IGC_EECD_ADDR_BITS) ? 256 : 64;
+
+		/* Function Pointers */
+		nvm->ops.acquire	= igc_acquire_nvm_generic;
+		nvm->ops.read		= igc_read_nvm_microwire;
+		nvm->ops.release	= igc_release_nvm_generic;
+		nvm->ops.update		= igc_update_nvm_checksum_generic;
+		nvm->ops.valid_led_default = igc_valid_led_default_generic;
+		nvm->ops.validate	= igc_validate_nvm_checksum_generic;
+		nvm->ops.write		= igc_write_nvm_microwire;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_init_mac_params_82541 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_mac_params_82541(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+
+	DEBUGFUNC("igc_init_mac_params_82541");
+
+	/* Set media type */
+	hw->phy.media_type = igc_media_type_copper;
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	mac->rar_entry_count = IGC_RAR_ENTRIES;
+	/* Set if part includes ASF firmware */
+	mac->asf_firmware_present = true;
+
+	/* Function Pointers */
+
+	/* bus type/speed/width */
+	mac->ops.get_bus_info = igc_get_bus_info_pci_generic;
+	/* function id */
+	mac->ops.set_lan_id = igc_set_lan_id_single_port;
+	/* reset */
+	mac->ops.reset_hw = igc_reset_hw_82541;
+	/* hw initialization */
+	mac->ops.init_hw = igc_init_hw_82541;
+	/* link setup */
+	mac->ops.setup_link = igc_setup_link_generic;
+	/* physical interface link setup */
+	mac->ops.setup_physical_interface = igc_setup_copper_link_82541;
+	/* check for link */
+	mac->ops.check_for_link = igc_check_for_link_82541;
+	/* link info */
+	mac->ops.get_link_up_info = igc_get_link_up_info_82541;
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
+	/* writing VFTA */
+	mac->ops.write_vfta = igc_write_vfta_generic;
+	/* clearing VFTA */
+	mac->ops.clear_vfta = igc_clear_vfta_generic;
+	/* ID LED init */
+	mac->ops.id_led_init = igc_id_led_init_generic;
+	/* setup LED */
+	mac->ops.setup_led = igc_setup_led_82541;
+	/* cleanup LED */
+	mac->ops.cleanup_led = igc_cleanup_led_82541;
+	/* turn on/off LED */
+	mac->ops.led_on = igc_led_on_generic;
+	mac->ops.led_off = igc_led_off_generic;
+	/* clear hardware counters */
+	mac->ops.clear_hw_cntrs = igc_clear_hw_cntrs_82541;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_function_pointers_82541 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void igc_init_function_pointers_82541(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_init_function_pointers_82541");
+
+	hw->mac.ops.init_params = igc_init_mac_params_82541;
+	hw->nvm.ops.init_params = igc_init_nvm_params_82541;
+	hw->phy.ops.init_params = igc_init_phy_params_82541;
+}
+
+/**
+ *  igc_reset_hw_82541 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 igc_reset_hw_82541(struct igc_hw *hw)
+{
+	u32 ledctl, ctrl, manc;
+
+	DEBUGFUNC("igc_reset_hw_82541");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xFFFFFFFF);
+
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
+	IGC_WRITE_FLUSH(hw);
+
+	/*
+	 * Delay to allow any outstanding PCI transactions to complete
+	 * before resetting the device.
+	 */
+	msec_delay(10);
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	/* Must reset the Phy before resetting the MAC */
+	if ((hw->mac.type == igc_82541) || (hw->mac.type == igc_82547)) {
+		IGC_WRITE_REG(hw, IGC_CTRL, (ctrl | IGC_CTRL_PHY_RST));
+		IGC_WRITE_FLUSH(hw);
+		msec_delay(5);
+	}
+
+	DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n");
+	switch (hw->mac.type) {
+	case igc_82541:
+	case igc_82541_rev_2:
+		/*
+		 * These controllers can't ack the 64-bit write when
+		 * issuing the reset, so we use IO-mapping as a
+		 * workaround to issue the reset.
+		 */
+		IGC_WRITE_REG_IO(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+		break;
+	default:
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+		break;
+	}
+
+	/* Wait for NVM reload */
+	msec_delay(20);
+
+	/* Disable HW ARPs on ASF enabled adapters */
+	manc = IGC_READ_REG(hw, IGC_MANC);
+	manc &= ~IGC_MANC_ARP_EN;
+	IGC_WRITE_REG(hw, IGC_MANC, manc);
+
+	if ((hw->mac.type == igc_82541) || (hw->mac.type == igc_82547)) {
+		igc_phy_init_script_82541(hw);
+
+		/* Configure activity LED after Phy reset */
+		ledctl = IGC_READ_REG(hw, IGC_LEDCTL);
+		ledctl &= IGP_ACTIVITY_LED_MASK;
+		ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+		IGC_WRITE_REG(hw, IGC_LEDCTL, ledctl);
+	}
+
+	/* Once again, mask the interrupts */
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xFFFFFFFF);
+
+	/* Clear any pending interrupt events. */
+	IGC_READ_REG(hw, IGC_ICR);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_hw_82541 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+STATIC s32 igc_init_hw_82541(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	struct igc_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+	u32 i, txdctl;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_init_hw_82541");
+
+	/* Initialize identification LED */
+	ret_val = mac->ops.id_led_init(hw);
+	if (ret_val) {
+		DEBUGOUT("Error initializing identification LED\n");
+		/* This is not fatal and we should not stop init due to this */
+	}
+
+	/* Storing the Speed Power Down  value for later use */
+	ret_val = hw->phy.ops.read_reg(hw, IGP01IGC_GMII_FIFO,
+				       &dev_spec->spd_default);
+	if (ret_val)
+		goto out;
+
+	/* Disabling VLAN filtering */
+	DEBUGOUT("Initializing the IEEE VLAN\n");
+	mac->ops.clear_vfta(hw);
+
+	/* Setup the receive address. */
+	igc_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for (i = 0; i < mac->mta_reg_count; i++) {
+		IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
+		/*
+		 * Avoid back to back register writes by adding the register
+		 * read (flush).  This is to protect against some strange
+		 * bridge configurations that may issue Memory Write Block
+		 * (MWB) to our register space.
+		 */
+		IGC_WRITE_FLUSH(hw);
+	}
+
+	/* Setup link and flow control */
+	ret_val = mac->ops.setup_link(hw);
+
+	txdctl = IGC_READ_REG(hw, IGC_TXDCTL(0));
+	txdctl = (txdctl & ~IGC_TXDCTL_WTHRESH) |
+		  IGC_TXDCTL_FULL_TX_DESC_WB;
+	IGC_WRITE_REG(hw, IGC_TXDCTL(0), txdctl);
+
+	/*
+	 * Clear all of the statistics registers (clear on read).  It is
+	 * important that we do this after we have tried to establish link
+	 * because the symbol error count will increment wildly if there
+	 * is no link.
+	 */
+	igc_clear_hw_cntrs_82541(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ * igc_get_link_up_info_82541 - Report speed and duplex
+ * @hw: pointer to the HW structure
+ * @speed: pointer to speed buffer
+ * @duplex: pointer to duplex buffer
+ *
+ * Retrieve the current speed and duplex configuration.
+ **/
+STATIC s32 igc_get_link_up_info_82541(struct igc_hw *hw, u16 *speed,
+					u16 *duplex)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+
+	DEBUGFUNC("igc_get_link_up_info_82541");
+
+	ret_val = igc_get_speed_and_duplex_copper_generic(hw, speed, duplex);
+	if (ret_val)
+		goto out;
+
+	if (!phy->speed_downgraded)
+		goto out;
+
+	/*
+	 * IGP01 PHY may advertise full duplex operation after speed
+	 * downgrade even if it is operating at half duplex.
+	 * Here we set the duplex settings to match the duplex in the
+	 * link partner's capabilities.
+	 */
+	ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data);
+	if (ret_val)
+		goto out;
+
+	if (!(data & NWAY_ER_LP_NWAY_CAPS)) {
+		*duplex = HALF_DUPLEX;
+	} else {
+		ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data);
+		if (ret_val)
+			goto out;
+
+		if (*speed == SPEED_100) {
+			if (!(data & NWAY_LPAR_100TX_FD_CAPS))
+				*duplex = HALF_DUPLEX;
+		} else if (*speed == SPEED_10) {
+			if (!(data & NWAY_LPAR_10T_FD_CAPS))
+				*duplex = HALF_DUPLEX;
+		}
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_phy_hw_reset_82541 - PHY hardware reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Verify the reset block is not blocking us from resetting.  Acquire
+ *  semaphore (if necessary) and read/set/write the device control reset
+ *  bit in the PHY.  Wait the appropriate delay time for the device to
+ *  reset and release the semaphore (if necessary).
+ **/
+STATIC s32 igc_phy_hw_reset_82541(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u32 ledctl;
+
+	DEBUGFUNC("igc_phy_hw_reset_82541");
+
+	ret_val = igc_phy_hw_reset_generic(hw);
+	if (ret_val)
+		goto out;
+
+	igc_phy_init_script_82541(hw);
+
+	if ((hw->mac.type == igc_82541) || (hw->mac.type == igc_82547)) {
+		/* Configure activity LED after PHY reset */
+		ledctl = IGC_READ_REG(hw, IGC_LEDCTL);
+		ledctl &= IGP_ACTIVITY_LED_MASK;
+		ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+		IGC_WRITE_REG(hw, IGC_LEDCTL, ledctl);
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_setup_copper_link_82541 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the appropriate function to configure the link for auto-neg or forced
+ *  speed and duplex.  Then we check for link, once link is established calls
+ *  to configure collision distance and flow control are called.  If link is
+ *  not established, we return -IGC_ERR_PHY (-2).
+ **/
+STATIC s32 igc_setup_copper_link_82541(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	struct igc_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+	s32  ret_val;
+	u32 ctrl, ledctl;
+
+	DEBUGFUNC("igc_setup_copper_link_82541");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	ctrl |= IGC_CTRL_SLU;
+	ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+
+	/* Earlier revs of the IGP phy require us to force MDI. */
+	if (hw->mac.type == igc_82541 || hw->mac.type == igc_82547) {
+		dev_spec->dsp_config = igc_dsp_config_disabled;
+		phy->mdix = 1;
+	} else {
+		dev_spec->dsp_config = igc_dsp_config_enabled;
+	}
+
+	ret_val = igc_copper_link_setup_igp(hw);
+	if (ret_val)
+		goto out;
+
+	if (hw->mac.autoneg) {
+		if (dev_spec->ffe_config == igc_ffe_config_active)
+			dev_spec->ffe_config = igc_ffe_config_enabled;
+	}
+
+	/* Configure activity LED after Phy reset */
+	ledctl = IGC_READ_REG(hw, IGC_LEDCTL);
+	ledctl &= IGP_ACTIVITY_LED_MASK;
+	ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+	IGC_WRITE_REG(hw, IGC_LEDCTL, ledctl);
+
+	ret_val = igc_setup_copper_link_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_check_for_link_82541 - Check/Store link connection
+ *  @hw: pointer to the HW structure
+ *
+ *  This checks the link condition of the adapter and stores the
+ *  results in the hw->mac structure.
+ **/
+STATIC s32 igc_check_for_link_82541(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	s32 ret_val;
+	bool link;
+
+	DEBUGFUNC("igc_check_for_link_82541");
+
+	/*
+	 * We only want to go out to the PHY registers to see if Auto-Neg
+	 * has completed and/or if our link status has changed.  The
+	 * get_link_status flag is set upon receiving a Link Status
+	 * Change or Rx Sequence Error interrupt.
+	 */
+	if (!mac->get_link_status) {
+		ret_val = IGC_SUCCESS;
+		goto out;
+	}
+
+	/*
+	 * First we want to see if the MII Status Register reports
+	 * link.  If so, then we want to get the current speed/duplex
+	 * of the PHY.
+	 */
+	ret_val = igc_phy_has_link_generic(hw, 1, 0, &link);
+	if (ret_val)
+		goto out;
+
+	if (!link) {
+		ret_val = igc_config_dsp_after_link_change_82541(hw, false);
+		goto out; /* No link detected */
+	}
+
+	mac->get_link_status = false;
+
+	/*
+	 * Check if there was DownShift, must be checked
+	 * immediately after link-up
+	 */
+	igc_check_downshift_generic(hw);
+
+	/*
+	 * If we are forcing speed/duplex, then we simply return since
+	 * we have already determined whether we have link or not.
+	 */
+	if (!mac->autoneg) {
+		ret_val = -IGC_ERR_CONFIG;
+		goto out;
+	}
+
+	ret_val = igc_config_dsp_after_link_change_82541(hw, true);
+
+	/*
+	 * Auto-Neg is enabled.  Auto Speed Detection takes care
+	 * of MAC speed/duplex configuration.  So we only need to
+	 * configure Collision Distance in the MAC.
+	 */
+	mac->ops.config_collision_dist(hw);
+
+	/*
+	 * Configure Flow Control now that Auto-Neg has completed.
+	 * First, we need to restore the desired flow control
+	 * settings because we may have had to re-autoneg with a
+	 * different link partner.
+	 */
+	ret_val = igc_config_fc_after_link_up_generic(hw);
+	if (ret_val)
+		DEBUGOUT("Error configuring flow control\n");
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_config_dsp_after_link_change_82541 - Config DSP after link
+ *  @hw: pointer to the HW structure
+ *  @link_up: boolean flag for link up status
+ *
+ *  Return IGC_ERR_PHY when failing to read/write the PHY, else IGC_SUCCESS
+ *  at any other case.
+ *
+ *  82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
+ *  gigabit link is achieved to improve link quality.
+ **/
+STATIC s32 igc_config_dsp_after_link_change_82541(struct igc_hw *hw,
+						    bool link_up)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	struct igc_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+	s32 ret_val;
+	u32 idle_errs = 0;
+	u16 phy_data, phy_saved_data, speed, duplex, i;
+	u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
+	u16 dsp_reg_array[IGP01IGC_PHY_CHANNEL_NUM] = {
+						IGP01IGC_PHY_AGC_PARAM_A,
+						IGP01IGC_PHY_AGC_PARAM_B,
+						IGP01IGC_PHY_AGC_PARAM_C,
+						IGP01IGC_PHY_AGC_PARAM_D};
+
+	DEBUGFUNC("igc_config_dsp_after_link_change_82541");
+
+	if (link_up) {
+		ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
+		if (ret_val) {
+			DEBUGOUT("Error getting link speed and duplex\n");
+			goto out;
+		}
+
+		if (speed != SPEED_1000) {
+			ret_val = IGC_SUCCESS;
+			goto out;
+		}
+
+		ret_val = phy->ops.get_cable_length(hw);
+		if (ret_val)
+			goto out;
+
+		if ((dev_spec->dsp_config == igc_dsp_config_enabled) &&
+		    phy->min_cable_length >= 50) {
+
+			for (i = 0; i < IGP01IGC_PHY_CHANNEL_NUM; i++) {
+				ret_val = phy->ops.read_reg(hw,
+							    dsp_reg_array[i],
+							    &phy_data);
+				if (ret_val)
+					goto out;
+
+				phy_data &= ~IGP01IGC_PHY_EDAC_MU_INDEX;
+
+				ret_val = phy->ops.write_reg(hw,
+							     dsp_reg_array[i],
+							     phy_data);
+				if (ret_val)
+					goto out;
+			}
+			dev_spec->dsp_config = igc_dsp_config_activated;
+		}
+
+		if ((dev_spec->ffe_config != igc_ffe_config_enabled) ||
+		    (phy->min_cable_length >= 50)) {
+			ret_val = IGC_SUCCESS;
+			goto out;
+		}
+
+		/* clear previous idle error counts */
+		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
+		if (ret_val)
+			goto out;
+
+		for (i = 0; i < ffe_idle_err_timeout; i++) {
+			usec_delay(1000);
+			ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS,
+						    &phy_data);
+			if (ret_val)
+				goto out;
+
+			idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
+			if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
+				dev_spec->ffe_config = igc_ffe_config_active;
+
+				ret_val = phy->ops.write_reg(hw,
+						  IGP01IGC_PHY_DSP_FFE,
+						  IGP01IGC_PHY_DSP_FFE_CM_CP);
+				if (ret_val)
+					goto out;
+				break;
+			}
+
+			if (idle_errs)
+				ffe_idle_err_timeout =
+						 FFE_IDLE_ERR_COUNT_TIMEOUT_100;
+		}
+	} else {
+		if (dev_spec->dsp_config == igc_dsp_config_activated) {
+			/*
+			 * Save off the current value of register 0x2F5B
+			 * to be restored at the end of the routines.
+			 */
+			ret_val = phy->ops.read_reg(hw, 0x2F5B,
+						    &phy_saved_data);
+			if (ret_val)
+				goto out;
+
+			/* Disable the PHY transmitter */
+			ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
+			if (ret_val)
+				goto out;
+
+			msec_delay_irq(20);
+
+			ret_val = phy->ops.write_reg(hw, 0x0000,
+						     IGP01IGC_IEEE_FORCE_GIG);
+			if (ret_val)
+				goto out;
+			for (i = 0; i < IGP01IGC_PHY_CHANNEL_NUM; i++) {
+				ret_val = phy->ops.read_reg(hw,
+							    dsp_reg_array[i],
+							    &phy_data);
+				if (ret_val)
+					goto out;
+
+				phy_data &= ~IGP01IGC_PHY_EDAC_MU_INDEX;
+				phy_data |= IGP01IGC_PHY_EDAC_SIGN_EXT_9_BITS;
+
+				ret_val = phy->ops.write_reg(hw,
+							     dsp_reg_array[i],
+							     phy_data);
+				if (ret_val)
+					goto out;
+			}
+
+			ret_val = phy->ops.write_reg(hw, 0x0000,
+					       IGP01IGC_IEEE_RESTART_AUTONEG);
+			if (ret_val)
+				goto out;
+
+			msec_delay_irq(20);
+
+			/* Now enable the transmitter */
+			ret_val = phy->ops.write_reg(hw, 0x2F5B,
+						     phy_saved_data);
+			if (ret_val)
+				goto out;
+
+			dev_spec->dsp_config = igc_dsp_config_enabled;
+		}
+
+		if (dev_spec->ffe_config != igc_ffe_config_active) {
+			ret_val = IGC_SUCCESS;
+			goto out;
+		}
+
+		/*
+		 * Save off the current value of register 0x2F5B
+		 * to be restored at the end of the routines.
+		 */
+		ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data);
+		if (ret_val)
+			goto out;
+
+		/* Disable the PHY transmitter */
+		ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
+		if (ret_val)
+			goto out;
+
+		msec_delay_irq(20);
+
+		ret_val = phy->ops.write_reg(hw, 0x0000,
+					     IGP01IGC_IEEE_FORCE_GIG);
+		if (ret_val)
+			goto out;
+
+		ret_val = phy->ops.write_reg(hw, IGP01IGC_PHY_DSP_FFE,
+					     IGP01IGC_PHY_DSP_FFE_DEFAULT);
+		if (ret_val)
+			goto out;
+
+		ret_val = phy->ops.write_reg(hw, 0x0000,
+					     IGP01IGC_IEEE_RESTART_AUTONEG);
+		if (ret_val)
+			goto out;
+
+		msec_delay_irq(20);
+
+		/* Now enable the transmitter */
+		ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data);
+
+		if (ret_val)
+			goto out;
+
+		dev_spec->ffe_config = igc_ffe_config_enabled;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_get_cable_length_igp_82541 - Determine cable length for igp PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  The automatic gain control (agc) normalizes the amplitude of the
+ *  received signal, adjusting for the attenuation produced by the
+ *  cable.  By reading the AGC registers, which represent the
+ *  combination of coarse and fine gain value, the value can be put
+ *  into a lookup table to obtain the approximate cable length
+ *  for each channel.
+ **/
+STATIC s32 igc_get_cable_length_igp_82541(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+	u16 i, data;
+	u16 cur_agc_value, agc_value = 0;
+	u16 min_agc_value = IGP01IGC_AGC_LENGTH_TABLE_SIZE;
+	u16 agc_reg_array[IGP01IGC_PHY_CHANNEL_NUM] = {IGP01IGC_PHY_AGC_A,
+							 IGP01IGC_PHY_AGC_B,
+							 IGP01IGC_PHY_AGC_C,
+							 IGP01IGC_PHY_AGC_D};
+
+	DEBUGFUNC("igc_get_cable_length_igp_82541");
+
+	/* Read the AGC registers for all channels */
+	for (i = 0; i < IGP01IGC_PHY_CHANNEL_NUM; i++) {
+		ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data);
+		if (ret_val)
+			goto out;
+
+		cur_agc_value = data >> IGP01IGC_AGC_LENGTH_SHIFT;
+
+		/* Bounds checking */
+		if ((cur_agc_value >= IGP01IGC_AGC_LENGTH_TABLE_SIZE - 1) ||
+		    (cur_agc_value == 0)) {
+			ret_val = -IGC_ERR_PHY;
+			goto out;
+		}
+
+		agc_value += cur_agc_value;
+
+		if (min_agc_value > cur_agc_value)
+			min_agc_value = cur_agc_value;
+	}
+
+	/* Remove the minimal AGC result for length < 50m */
+	if (agc_value < IGP01IGC_PHY_CHANNEL_NUM * 50) {
+		agc_value -= min_agc_value;
+		/* Average the three remaining channels for the length. */
+		agc_value /= (IGP01IGC_PHY_CHANNEL_NUM - 1);
+	} else {
+		/* Average the channels for the length. */
+		agc_value /= IGP01IGC_PHY_CHANNEL_NUM;
+	}
+
+	phy->min_cable_length = (igc_igp_cable_length_table[agc_value] >
+				 IGP01IGC_AGC_RANGE)
+				? (igc_igp_cable_length_table[agc_value] -
+				   IGP01IGC_AGC_RANGE)
+				: 0;
+	phy->max_cable_length = igc_igp_cable_length_table[agc_value] +
+				IGP01IGC_AGC_RANGE;
+
+	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_set_d3_lplu_state_82541 - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  Success returns 0, Failure returns 1
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  and SmartSpeed is disabled when active is true, else clear lplu for D3
+ *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.
+ **/
+STATIC s32 igc_set_d3_lplu_state_82541(struct igc_hw *hw, bool active)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+
+	DEBUGFUNC("igc_set_d3_lplu_state_82541");
+
+	switch (hw->mac.type) {
+	case igc_82541_rev_2:
+	case igc_82547_rev_2:
+		break;
+	default:
+		ret_val = igc_set_d3_lplu_state_generic(hw, active);
+		goto out;
+		break;
+	}
+
+	ret_val = phy->ops.read_reg(hw, IGP01IGC_GMII_FIFO, &data);
+	if (ret_val)
+		goto out;
+
+	if (!active) {
+		data &= ~IGP01IGC_GMII_FLEX_SPD;
+		ret_val = phy->ops.write_reg(hw, IGP01IGC_GMII_FIFO, data);
+		if (ret_val)
+			goto out;
+
+		/*
+		 * 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.
+		 */
+		if (phy->smart_speed == igc_smart_speed_on) {
+			ret_val = phy->ops.read_reg(hw,
+						    IGP01IGC_PHY_PORT_CONFIG,
+						    &data);
+			if (ret_val)
+				goto out;
+
+			data |= IGP01IGC_PSCFR_SMART_SPEED;
+			ret_val = phy->ops.write_reg(hw,
+						     IGP01IGC_PHY_PORT_CONFIG,
+						     data);
+			if (ret_val)
+				goto out;
+		} else if (phy->smart_speed == igc_smart_speed_off) {
+			ret_val = phy->ops.read_reg(hw,
+						    IGP01IGC_PHY_PORT_CONFIG,
+						    &data);
+			if (ret_val)
+				goto out;
+
+			data &= ~IGP01IGC_PSCFR_SMART_SPEED;
+			ret_val = phy->ops.write_reg(hw,
+						     IGP01IGC_PHY_PORT_CONFIG,
+						     data);
+			if (ret_val)
+				goto out;
+		}
+	} else if ((phy->autoneg_advertised == IGC_ALL_SPEED_DUPLEX) ||
+		   (phy->autoneg_advertised == IGC_ALL_NOT_GIG) ||
+		   (phy->autoneg_advertised == IGC_ALL_10_SPEED)) {
+		data |= IGP01IGC_GMII_FLEX_SPD;
+		ret_val = phy->ops.write_reg(hw, IGP01IGC_GMII_FIFO, data);
+		if (ret_val)
+			goto out;
+
+		/* When LPLU is enabled, we should disable SmartSpeed */
+		ret_val = phy->ops.read_reg(hw, IGP01IGC_PHY_PORT_CONFIG,
+					    &data);
+		if (ret_val)
+			goto out;
+
+		data &= ~IGP01IGC_PSCFR_SMART_SPEED;
+		ret_val = phy->ops.write_reg(hw, IGP01IGC_PHY_PORT_CONFIG,
+					     data);
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_setup_led_82541 - Configures SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This prepares the SW controllable LED for use and saves the current state
+ *  of the LED so it can be later restored.
+ **/
+STATIC s32 igc_setup_led_82541(struct igc_hw *hw)
+{
+	struct igc_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_setup_led_82541");
+
+	ret_val = hw->phy.ops.read_reg(hw, IGP01IGC_GMII_FIFO,
+				       &dev_spec->spd_default);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.write_reg(hw, IGP01IGC_GMII_FIFO,
+					(u16)(dev_spec->spd_default &
+					~IGP01IGC_GMII_SPD));
+	if (ret_val)
+		goto out;
+
+	IGC_WRITE_REG(hw, IGC_LEDCTL, hw->mac.ledctl_mode1);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_cleanup_led_82541 - Set LED config to default operation
+ *  @hw: pointer to the HW structure
+ *
+ *  Remove the current LED configuration and set the LED configuration
+ *  to the default value, saved from the EEPROM.
+ **/
+STATIC s32 igc_cleanup_led_82541(struct igc_hw *hw)
+{
+	struct igc_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_cleanup_led_82541");
+
+	ret_val = hw->phy.ops.write_reg(hw, IGP01IGC_GMII_FIFO,
+					dev_spec->spd_default);
+	if (ret_val)
+		goto out;
+
+	IGC_WRITE_REG(hw, IGC_LEDCTL, hw->mac.ledctl_default);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_phy_init_script_82541 - Initialize GbE PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes the IGP PHY.
+ **/
+STATIC s32 igc_phy_init_script_82541(struct igc_hw *hw)
+{
+	struct igc_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+	u32 ret_val;
+	u16 phy_saved_data;
+
+	DEBUGFUNC("igc_phy_init_script_82541");
+
+	if (!dev_spec->phy_init_script) {
+		ret_val = IGC_SUCCESS;
+		goto out;
+	}
+
+	/* Delay after phy reset to enable NVM configuration to load */
+	msec_delay(20);
+
+	/*
+	 * Save off the current value of register 0x2F5B to be restored at
+	 * the end of this routine.
+	 */
+	ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data);
+
+	/* Disabled the PHY transmitter */
+	hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003);
+
+	msec_delay(20);
+
+	hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
+
+	msec_delay(5);
+
+	switch (hw->mac.type) {
+	case igc_82541:
+	case igc_82547:
+		hw->phy.ops.write_reg(hw, 0x1F95, 0x0001);
+
+		hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21);
+
+		hw->phy.ops.write_reg(hw, 0x1F79, 0x0018);
+
+		hw->phy.ops.write_reg(hw, 0x1F30, 0x1600);
+
+		hw->phy.ops.write_reg(hw, 0x1F31, 0x0014);
+
+		hw->phy.ops.write_reg(hw, 0x1F32, 0x161C);
+
+		hw->phy.ops.write_reg(hw, 0x1F94, 0x0003);
+
+		hw->phy.ops.write_reg(hw, 0x1F96, 0x003F);
+
+		hw->phy.ops.write_reg(hw, 0x2010, 0x0008);
+		break;
+	case igc_82541_rev_2:
+	case igc_82547_rev_2:
+		hw->phy.ops.write_reg(hw, 0x1F73, 0x0099);
+		break;
+	default:
+		break;
+	}
+
+	hw->phy.ops.write_reg(hw, 0x0000, 0x3300);
+
+	msec_delay(20);
+
+	/* Now enable the transmitter */
+	hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data);
+
+	if (hw->mac.type == igc_82547) {
+		u16 fused, fine, coarse;
+
+		/* Move to analog registers page */
+		hw->phy.ops.read_reg(hw, IGP01IGC_ANALOG_SPARE_FUSE_STATUS,
+				     &fused);
+
+		if (!(fused & IGP01IGC_ANALOG_SPARE_FUSE_ENABLED)) {
+			hw->phy.ops.read_reg(hw, IGP01IGC_ANALOG_FUSE_STATUS,
+					     &fused);
+
+			fine = fused & IGP01IGC_ANALOG_FUSE_FINE_MASK;
+			coarse = fused & IGP01IGC_ANALOG_FUSE_COARSE_MASK;
+
+			if (coarse > IGP01IGC_ANALOG_FUSE_COARSE_THRESH) {
+				coarse -= IGP01IGC_ANALOG_FUSE_COARSE_10;
+				fine -= IGP01IGC_ANALOG_FUSE_FINE_1;
+			} else if (coarse ==
+				   IGP01IGC_ANALOG_FUSE_COARSE_THRESH)
+				fine -= IGP01IGC_ANALOG_FUSE_FINE_10;
+
+			fused = (fused & IGP01IGC_ANALOG_FUSE_POLY_MASK) |
+				(fine & IGP01IGC_ANALOG_FUSE_FINE_MASK) |
+				(coarse & IGP01IGC_ANALOG_FUSE_COARSE_MASK);
+
+			hw->phy.ops.write_reg(hw,
+					      IGP01IGC_ANALOG_FUSE_CONTROL,
+					      fused);
+			hw->phy.ops.write_reg(hw,
+				      IGP01IGC_ANALOG_FUSE_BYPASS,
+				      IGP01IGC_ANALOG_FUSE_ENABLE_SW_CONTROL);
+		}
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_init_script_state_82541 - Enable/Disable PHY init script
+ *  @hw: pointer to the HW structure
+ *  @state: boolean value used to enable/disable PHY init script
+ *
+ *  Allows the driver to enable/disable the PHY init script, if the PHY is an
+ *  IGP PHY.
+ **/
+void igc_init_script_state_82541(struct igc_hw *hw, bool state)
+{
+	struct igc_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
+
+	DEBUGFUNC("igc_init_script_state_82541");
+
+	if (hw->phy.type != igc_phy_igp) {
+		DEBUGOUT("Initialization script not necessary.\n");
+		goto out;
+	}
+
+	dev_spec->phy_init_script = state;
+
+out:
+	return;
+}
+
+/**
+ * igc_power_down_phy_copper_82541 - Remove link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+STATIC void igc_power_down_phy_copper_82541(struct igc_hw *hw)
+{
+	/* If the management interface is not enabled, then power down */
+	if (!(IGC_READ_REG(hw, IGC_MANC) & IGC_MANC_SMBUS_EN))
+		igc_power_down_phy_copper(hw);
+
+	return;
+}
+
+/**
+ *  igc_clear_hw_cntrs_82541 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+STATIC void igc_clear_hw_cntrs_82541(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_clear_hw_cntrs_82541");
+
+	igc_clear_hw_cntrs_base_generic(hw);
+
+	IGC_READ_REG(hw, IGC_PRC64);
+	IGC_READ_REG(hw, IGC_PRC127);
+	IGC_READ_REG(hw, IGC_PRC255);
+	IGC_READ_REG(hw, IGC_PRC511);
+	IGC_READ_REG(hw, IGC_PRC1023);
+	IGC_READ_REG(hw, IGC_PRC1522);
+	IGC_READ_REG(hw, IGC_PTC64);
+	IGC_READ_REG(hw, IGC_PTC127);
+	IGC_READ_REG(hw, IGC_PTC255);
+	IGC_READ_REG(hw, IGC_PTC511);
+	IGC_READ_REG(hw, IGC_PTC1023);
+	IGC_READ_REG(hw, IGC_PTC1522);
+
+	IGC_READ_REG(hw, IGC_ALGNERRC);
+	IGC_READ_REG(hw, IGC_RXERRC);
+	IGC_READ_REG(hw, IGC_TNCRS);
+	IGC_READ_REG(hw, IGC_CEXTERR);
+	IGC_READ_REG(hw, IGC_TSCTC);
+	IGC_READ_REG(hw, IGC_TSCTFC);
+
+	IGC_READ_REG(hw, IGC_MGTPRC);
+	IGC_READ_REG(hw, IGC_MGTPDC);
+	IGC_READ_REG(hw, IGC_MGTPTC);
+}
diff --git a/drivers/net/igc/base/e1000_82541.h b/drivers/net/igc/base/e1000_82541.h
new file mode 100644
index 0000000..20091d1
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82541.h
@@ -0,0 +1,62 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_82541_H_
+#define _IGC_82541_H_
+
+#define NVM_WORD_SIZE_BASE_SHIFT_82541 (NVM_WORD_SIZE_BASE_SHIFT + 1)
+
+#define IGP01IGC_PHY_CHANNEL_NUM		4
+
+#define IGP01IGC_PHY_AGC_A			0x1172
+#define IGP01IGC_PHY_AGC_B			0x1272
+#define IGP01IGC_PHY_AGC_C			0x1472
+#define IGP01IGC_PHY_AGC_D			0x1872
+
+#define IGP01IGC_PHY_AGC_PARAM_A		0x1171
+#define IGP01IGC_PHY_AGC_PARAM_B		0x1271
+#define IGP01IGC_PHY_AGC_PARAM_C		0x1471
+#define IGP01IGC_PHY_AGC_PARAM_D		0x1871
+
+#define IGP01IGC_PHY_EDAC_MU_INDEX		0xC000
+#define IGP01IGC_PHY_EDAC_SIGN_EXT_9_BITS	0x8000
+
+#define IGP01IGC_PHY_DSP_RESET		0x1F33
+
+#define IGP01IGC_PHY_DSP_FFE			0x1F35
+#define IGP01IGC_PHY_DSP_FFE_CM_CP		0x0069
+#define IGP01IGC_PHY_DSP_FFE_DEFAULT		0x002A
+
+#define IGP01IGC_IEEE_FORCE_GIG		0x0140
+#define IGP01IGC_IEEE_RESTART_AUTONEG		0x3300
+
+#define IGP01IGC_AGC_LENGTH_SHIFT		7
+#define IGP01IGC_AGC_RANGE			10
+
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_20		20
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_100		100
+
+#define IGP01IGC_ANALOG_FUSE_STATUS		0x20D0
+#define IGP01IGC_ANALOG_SPARE_FUSE_STATUS	0x20D1
+#define IGP01IGC_ANALOG_FUSE_CONTROL		0x20DC
+#define IGP01IGC_ANALOG_FUSE_BYPASS		0x20DE
+
+#define IGP01IGC_ANALOG_SPARE_FUSE_ENABLED	0x0100
+#define IGP01IGC_ANALOG_FUSE_FINE_MASK	0x0F80
+#define IGP01IGC_ANALOG_FUSE_COARSE_MASK	0x0070
+#define IGP01IGC_ANALOG_FUSE_COARSE_THRESH	0x0040
+#define IGP01IGC_ANALOG_FUSE_COARSE_10	0x0010
+#define IGP01IGC_ANALOG_FUSE_FINE_1		0x0080
+#define IGP01IGC_ANALOG_FUSE_FINE_10		0x0500
+#define IGP01IGC_ANALOG_FUSE_POLY_MASK	0xF000
+#define IGP01IGC_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002
+
+#define IGP01IGC_MSE_CHANNEL_D		0x000F
+#define IGP01IGC_MSE_CHANNEL_C		0x00F0
+#define IGP01IGC_MSE_CHANNEL_B		0x0F00
+#define IGP01IGC_MSE_CHANNEL_A		0xF000
+
+
+void igc_init_script_state_82541(struct igc_hw *hw, bool state);
+#endif
diff --git a/drivers/net/igc/base/e1000_82542.c b/drivers/net/igc/base/e1000_82542.c
new file mode 100644
index 0000000..b75a5f9
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82542.c
@@ -0,0 +1,561 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+/*
+ * 82542 Gigabit Ethernet Controller
+ */
+
+#include "e1000_api.h"
+
+STATIC s32  igc_init_phy_params_82542(struct igc_hw *hw);
+STATIC s32  igc_init_nvm_params_82542(struct igc_hw *hw);
+STATIC s32  igc_init_mac_params_82542(struct igc_hw *hw);
+STATIC s32  igc_get_bus_info_82542(struct igc_hw *hw);
+STATIC s32  igc_reset_hw_82542(struct igc_hw *hw);
+STATIC s32  igc_init_hw_82542(struct igc_hw *hw);
+STATIC s32  igc_setup_link_82542(struct igc_hw *hw);
+STATIC s32  igc_led_on_82542(struct igc_hw *hw);
+STATIC s32  igc_led_off_82542(struct igc_hw *hw);
+STATIC int  igc_rar_set_82542(struct igc_hw *hw, u8 *addr, u32 index);
+STATIC void igc_clear_hw_cntrs_82542(struct igc_hw *hw);
+STATIC s32  igc_read_mac_addr_82542(struct igc_hw *hw);
+
+/**
+ *  igc_init_phy_params_82542 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_phy_params_82542(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_init_phy_params_82542");
+
+	phy->type = igc_phy_none;
+
+	return ret_val;
+}
+
+/**
+ *  igc_init_nvm_params_82542 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_nvm_params_82542(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+
+	DEBUGFUNC("igc_init_nvm_params_82542");
+
+	nvm->address_bits	=  6;
+	nvm->delay_usec		= 50;
+	nvm->opcode_bits	=  3;
+	nvm->type		= igc_nvm_eeprom_microwire;
+	nvm->word_size		= 64;
+
+	/* Function Pointers */
+	nvm->ops.read		= igc_read_nvm_microwire;
+	nvm->ops.release	= igc_stop_nvm;
+	nvm->ops.write		= igc_write_nvm_microwire;
+	nvm->ops.update		= igc_update_nvm_checksum_generic;
+	nvm->ops.validate	= igc_validate_nvm_checksum_generic;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_mac_params_82542 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_mac_params_82542(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+
+	DEBUGFUNC("igc_init_mac_params_82542");
+
+	/* Set media type */
+	hw->phy.media_type = igc_media_type_fiber;
+
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	mac->rar_entry_count = IGC_RAR_ENTRIES;
+
+	/* Function pointers */
+
+	/* bus type/speed/width */
+	mac->ops.get_bus_info = igc_get_bus_info_82542;
+	/* function id */
+	mac->ops.set_lan_id = igc_set_lan_id_multi_port_pci;
+	/* reset */
+	mac->ops.reset_hw = igc_reset_hw_82542;
+	/* hw initialization */
+	mac->ops.init_hw = igc_init_hw_82542;
+	/* link setup */
+	mac->ops.setup_link = igc_setup_link_82542;
+	/* phy/fiber/serdes setup */
+	mac->ops.setup_physical_interface =
+					igc_setup_fiber_serdes_link_generic;
+	/* check for link */
+	mac->ops.check_for_link = igc_check_for_fiber_link_generic;
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
+	/* writing VFTA */
+	mac->ops.write_vfta = igc_write_vfta_generic;
+	/* clearing VFTA */
+	mac->ops.clear_vfta = igc_clear_vfta_generic;
+	/* read mac address */
+	mac->ops.read_mac_addr = igc_read_mac_addr_82542;
+	/* set RAR */
+	mac->ops.rar_set = igc_rar_set_82542;
+	/* turn on/off LED */
+	mac->ops.led_on = igc_led_on_82542;
+	mac->ops.led_off = igc_led_off_82542;
+	/* clear hardware counters */
+	mac->ops.clear_hw_cntrs = igc_clear_hw_cntrs_82542;
+	/* link info */
+	mac->ops.get_link_up_info =
+				igc_get_speed_and_duplex_fiber_serdes_generic;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_function_pointers_82542 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void igc_init_function_pointers_82542(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_init_function_pointers_82542");
+
+	hw->mac.ops.init_params = igc_init_mac_params_82542;
+	hw->nvm.ops.init_params = igc_init_nvm_params_82542;
+	hw->phy.ops.init_params = igc_init_phy_params_82542;
+}
+
+/**
+ *  igc_get_bus_info_82542 - Obtain bus information for adapter
+ *  @hw: pointer to the HW structure
+ *
+ *  This will obtain information about the HW bus for which the
+ *  adapter is attached and stores it in the hw structure.
+ **/
+STATIC s32 igc_get_bus_info_82542(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_get_bus_info_82542");
+
+	hw->bus.type = igc_bus_type_pci;
+	hw->bus.speed = igc_bus_speed_unknown;
+	hw->bus.width = igc_bus_width_unknown;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_reset_hw_82542 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 igc_reset_hw_82542(struct igc_hw *hw)
+{
+	struct igc_bus_info *bus = &hw->bus;
+	s32 ret_val = IGC_SUCCESS;
+	u32 ctrl;
+
+	DEBUGFUNC("igc_reset_hw_82542");
+
+	if (hw->revision_id == IGC_REVISION_2) {
+		DEBUGOUT("Disabling MWI on 82542 rev 2\n");
+		igc_pci_clear_mwi(hw);
+	}
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
+	IGC_WRITE_FLUSH(hw);
+
+	/*
+	 * Delay to allow any outstanding PCI transactions to complete before
+	 * resetting the device
+	 */
+	msec_delay(10);
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGOUT("Issuing a global reset to 82542/82543 MAC\n");
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+
+	hw->nvm.ops.reload(hw);
+	msec_delay(2);
+
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_READ_REG(hw, IGC_ICR);
+
+	if (hw->revision_id == IGC_REVISION_2) {
+		if (bus->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
+			igc_pci_set_mwi(hw);
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_init_hw_82542 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+STATIC s32 igc_init_hw_82542(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	struct igc_dev_spec_82542 *dev_spec = &hw->dev_spec._82542;
+	s32 ret_val = IGC_SUCCESS;
+	u32 ctrl;
+	u16 i;
+
+	DEBUGFUNC("igc_init_hw_82542");
+
+	/* Disabling VLAN filtering */
+	IGC_WRITE_REG(hw, IGC_VET, 0);
+	mac->ops.clear_vfta(hw);
+
+	/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
+	if (hw->revision_id == IGC_REVISION_2) {
+		DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+		igc_pci_clear_mwi(hw);
+		IGC_WRITE_REG(hw, IGC_RCTL, IGC_RCTL_RST);
+		IGC_WRITE_FLUSH(hw);
+		msec_delay(5);
+	}
+
+	/* Setup the receive address. */
+	igc_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+	/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
+	if (hw->revision_id == IGC_REVISION_2) {
+		IGC_WRITE_REG(hw, IGC_RCTL, 0);
+		IGC_WRITE_FLUSH(hw);
+		msec_delay(1);
+		if (hw->bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
+			igc_pci_set_mwi(hw);
+	}
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for (i = 0; i < mac->mta_reg_count; i++)
+		IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
+
+	/*
+	 * Set the PCI priority bit correctly in the CTRL register.  This
+	 * determines if the adapter gives priority to receives, or if it
+	 * gives equal priority to transmits and receives.
+	 */
+	if (dev_spec->dma_fairness) {
+		ctrl = IGC_READ_REG(hw, IGC_CTRL);
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_PRIOR);
+	}
+
+	/* Setup link and flow control */
+	ret_val = igc_setup_link_82542(hw);
+
+	/*
+	 * Clear all of the statistics registers (clear on read).  It is
+	 * important that we do this after we have tried to establish link
+	 * because the symbol error count will increment wildly if there
+	 * is no link.
+	 */
+	igc_clear_hw_cntrs_82542(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_setup_link_82542 - Setup flow control and link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines which flow control settings to use, then configures flow
+ *  control.  Calls the appropriate media-specific link configuration
+ *  function.  Assuming the adapter has a valid link partner, a valid link
+ *  should be established.  Assumes the hardware has previously been reset
+ *  and the transmitter and receiver are not enabled.
+ **/
+STATIC s32 igc_setup_link_82542(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_setup_link_82542");
+
+	ret_val = igc_set_default_fc_generic(hw);
+	if (ret_val)
+		goto out;
+
+	hw->fc.requested_mode &= ~igc_fc_tx_pause;
+
+	if (mac->report_tx_early)
+		hw->fc.requested_mode &= ~igc_fc_rx_pause;
+
+	/*
+	 * Save off the requested flow control mode for use later.  Depending
+	 * on the link partner's capabilities, we may or may not use this mode.
+	 */
+	hw->fc.current_mode = hw->fc.requested_mode;
+
+	DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
+		  hw->fc.current_mode);
+
+	/* Call the necessary subroutine to configure the link. */
+	ret_val = mac->ops.setup_physical_interface(hw);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * Initialize the flow control address, type, and PAUSE timer
+	 * registers to their default values.  This is done even if flow
+	 * control is disabled, because it does not hurt anything to
+	 * initialize these registers.
+	 */
+	DEBUGOUT("Initializing Flow Control address, type and timer regs\n");
+
+	IGC_WRITE_REG(hw, IGC_FCAL, FLOW_CONTROL_ADDRESS_LOW);
+	IGC_WRITE_REG(hw, IGC_FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+	IGC_WRITE_REG(hw, IGC_FCT, FLOW_CONTROL_TYPE);
+
+	IGC_WRITE_REG(hw, IGC_FCTTV, hw->fc.pause_time);
+
+	ret_val = igc_set_fc_watermarks_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_led_on_82542 - Turn on SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED on.
+ **/
+STATIC s32 igc_led_on_82542(struct igc_hw *hw)
+{
+	u32 ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGFUNC("igc_led_on_82542");
+
+	ctrl |= IGC_CTRL_SWDPIN0;
+	ctrl |= IGC_CTRL_SWDPIO0;
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_led_off_82542 - Turn off SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED off.
+ **/
+STATIC s32 igc_led_off_82542(struct igc_hw *hw)
+{
+	u32 ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGFUNC("igc_led_off_82542");
+
+	ctrl &= ~IGC_CTRL_SWDPIN0;
+	ctrl |= IGC_CTRL_SWDPIO0;
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_rar_set_82542 - Set receive address register
+ *  @hw: pointer to the HW structure
+ *  @addr: pointer to the receive address
+ *  @index: receive address array register
+ *
+ *  Sets the receive address array register at index to the address passed
+ *  in by addr.
+ **/
+STATIC int igc_rar_set_82542(struct igc_hw *hw, u8 *addr, u32 index)
+{
+	u32 rar_low, rar_high;
+
+	DEBUGFUNC("igc_rar_set_82542");
+
+	/*
+	 * HW expects these in little endian so we reverse the byte order
+	 * from network order (big endian) to little endian
+	 */
+	rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
+		   ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+
+	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+	/* If MAC address zero, no need to set the AV bit */
+	if (rar_low || rar_high)
+		rar_high |= IGC_RAH_AV;
+
+	IGC_WRITE_REG_ARRAY(hw, IGC_RA, (index << 1), rar_low);
+	IGC_WRITE_REG_ARRAY(hw, IGC_RA, ((index << 1) + 1), rar_high);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_translate_register_82542 - Translate the proper register offset
+ *  @reg: e1000 register to be read
+ *
+ *  Registers in 82542 are located in different offsets than other adapters
+ *  even though they function in the same manner.  This function takes in
+ *  the name of the register to read and returns the correct offset for
+ *  82542 silicon.
+ **/
+u32 igc_translate_register_82542(u32 reg)
+{
+	/*
+	 * Some of the 82542 registers are located at different
+	 * offsets than they are in newer adapters.
+	 * Despite the difference in location, the registers
+	 * function in the same manner.
+	 */
+	switch (reg) {
+	case IGC_RA:
+		reg = 0x00040;
+		break;
+	case IGC_RDTR:
+		reg = 0x00108;
+		break;
+	case IGC_RDBAL(0):
+		reg = 0x00110;
+		break;
+	case IGC_RDBAH(0):
+		reg = 0x00114;
+		break;
+	case IGC_RDLEN(0):
+		reg = 0x00118;
+		break;
+	case IGC_RDH(0):
+		reg = 0x00120;
+		break;
+	case IGC_RDT(0):
+		reg = 0x00128;
+		break;
+	case IGC_RDBAL(1):
+		reg = 0x00138;
+		break;
+	case IGC_RDBAH(1):
+		reg = 0x0013C;
+		break;
+	case IGC_RDLEN(1):
+		reg = 0x00140;
+		break;
+	case IGC_RDH(1):
+		reg = 0x00148;
+		break;
+	case IGC_RDT(1):
+		reg = 0x00150;
+		break;
+	case IGC_FCRTH:
+		reg = 0x00160;
+		break;
+	case IGC_FCRTL:
+		reg = 0x00168;
+		break;
+	case IGC_MTA:
+		reg = 0x00200;
+		break;
+	case IGC_TDBAL(0):
+		reg = 0x00420;
+		break;
+	case IGC_TDBAH(0):
+		reg = 0x00424;
+		break;
+	case IGC_TDLEN(0):
+		reg = 0x00428;
+		break;
+	case IGC_TDH(0):
+		reg = 0x00430;
+		break;
+	case IGC_TDT(0):
+		reg = 0x00438;
+		break;
+	case IGC_TIDV:
+		reg = 0x00440;
+		break;
+	case IGC_VFTA:
+		reg = 0x00600;
+		break;
+	case IGC_TDFH:
+		reg = 0x08010;
+		break;
+	case IGC_TDFT:
+		reg = 0x08018;
+		break;
+	default:
+		break;
+	}
+
+	return reg;
+}
+
+/**
+ *  igc_clear_hw_cntrs_82542 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+STATIC void igc_clear_hw_cntrs_82542(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_clear_hw_cntrs_82542");
+
+	igc_clear_hw_cntrs_base_generic(hw);
+
+	IGC_READ_REG(hw, IGC_PRC64);
+	IGC_READ_REG(hw, IGC_PRC127);
+	IGC_READ_REG(hw, IGC_PRC255);
+	IGC_READ_REG(hw, IGC_PRC511);
+	IGC_READ_REG(hw, IGC_PRC1023);
+	IGC_READ_REG(hw, IGC_PRC1522);
+	IGC_READ_REG(hw, IGC_PTC64);
+	IGC_READ_REG(hw, IGC_PTC127);
+	IGC_READ_REG(hw, IGC_PTC255);
+	IGC_READ_REG(hw, IGC_PTC511);
+	IGC_READ_REG(hw, IGC_PTC1023);
+	IGC_READ_REG(hw, IGC_PTC1522);
+}
+
+/**
+ *  igc_read_mac_addr_82542 - Read device MAC address
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the device MAC address from the EEPROM and stores the value.
+ **/
+s32 igc_read_mac_addr_82542(struct igc_hw *hw)
+{
+	s32  ret_val = IGC_SUCCESS;
+	u16 offset, nvm_data, i;
+
+	DEBUGFUNC("igc_read_mac_addr");
+
+	for (i = 0; i < ETH_ADDR_LEN; i += 2) {
+		offset = i >> 1;
+		ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
+		if (ret_val) {
+			DEBUGOUT("NVM Read Error\n");
+			goto out;
+		}
+		hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
+		hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
+	}
+
+	for (i = 0; i < ETH_ADDR_LEN; i++)
+		hw->mac.addr[i] = hw->mac.perm_addr[i];
+
+out:
+	return ret_val;
+}
diff --git a/drivers/net/igc/base/e1000_82543.c b/drivers/net/igc/base/e1000_82543.c
new file mode 100644
index 0000000..db3c89a
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82543.c
@@ -0,0 +1,1524 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+/*
+ * 82543GC Gigabit Ethernet Controller (Fiber)
+ * 82543GC Gigabit Ethernet Controller (Copper)
+ * 82544EI Gigabit Ethernet Controller (Copper)
+ * 82544EI Gigabit Ethernet Controller (Fiber)
+ * 82544GC Gigabit Ethernet Controller (Copper)
+ * 82544GC Gigabit Ethernet Controller (LOM)
+ */
+
+#include "e1000_api.h"
+
+STATIC s32  igc_init_phy_params_82543(struct igc_hw *hw);
+STATIC s32  igc_init_nvm_params_82543(struct igc_hw *hw);
+STATIC s32  igc_init_mac_params_82543(struct igc_hw *hw);
+STATIC s32  igc_read_phy_reg_82543(struct igc_hw *hw, u32 offset,
+				     u16 *data);
+STATIC s32  igc_write_phy_reg_82543(struct igc_hw *hw, u32 offset,
+				      u16 data);
+STATIC s32  igc_phy_force_speed_duplex_82543(struct igc_hw *hw);
+STATIC s32  igc_phy_hw_reset_82543(struct igc_hw *hw);
+STATIC s32  igc_reset_hw_82543(struct igc_hw *hw);
+STATIC s32  igc_init_hw_82543(struct igc_hw *hw);
+STATIC s32  igc_setup_link_82543(struct igc_hw *hw);
+STATIC s32  igc_setup_copper_link_82543(struct igc_hw *hw);
+STATIC s32  igc_setup_fiber_link_82543(struct igc_hw *hw);
+STATIC s32  igc_check_for_copper_link_82543(struct igc_hw *hw);
+STATIC s32  igc_check_for_fiber_link_82543(struct igc_hw *hw);
+STATIC s32  igc_led_on_82543(struct igc_hw *hw);
+STATIC s32  igc_led_off_82543(struct igc_hw *hw);
+STATIC void igc_write_vfta_82543(struct igc_hw *hw, u32 offset,
+				   u32 value);
+STATIC void igc_clear_hw_cntrs_82543(struct igc_hw *hw);
+STATIC s32  igc_config_mac_to_phy_82543(struct igc_hw *hw);
+STATIC bool igc_init_phy_disabled_82543(struct igc_hw *hw);
+STATIC void igc_lower_mdi_clk_82543(struct igc_hw *hw, u32 *ctrl);
+STATIC s32  igc_polarity_reversal_workaround_82543(struct igc_hw *hw);
+STATIC void igc_raise_mdi_clk_82543(struct igc_hw *hw, u32 *ctrl);
+STATIC u16  igc_shift_in_mdi_bits_82543(struct igc_hw *hw);
+STATIC void igc_shift_out_mdi_bits_82543(struct igc_hw *hw, u32 data,
+					   u16 count);
+STATIC bool igc_tbi_compatibility_enabled_82543(struct igc_hw *hw);
+STATIC void igc_set_tbi_sbp_82543(struct igc_hw *hw, bool state);
+
+/**
+ *  igc_init_phy_params_82543 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_phy_params_82543(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_init_phy_params_82543");
+
+	if (hw->phy.media_type != igc_media_type_copper) {
+		phy->type = igc_phy_none;
+		goto out;
+	} else {
+		phy->ops.power_up = igc_power_up_phy_copper;
+		phy->ops.power_down = igc_power_down_phy_copper;
+	}
+
+	phy->addr		= 1;
+	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+	phy->reset_delay_us	= 10000;
+	phy->type		= igc_phy_m88;
+
+	/* Function Pointers */
+	phy->ops.check_polarity	= igc_check_polarity_m88;
+	phy->ops.commit		= igc_phy_sw_reset_generic;
+	phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_82543;
+	phy->ops.get_cable_length = igc_get_cable_length_m88;
+	phy->ops.get_cfg_done	= igc_get_cfg_done_generic;
+	phy->ops.read_reg	= (hw->mac.type == igc_82543)
+				  ? igc_read_phy_reg_82543
+				  : igc_read_phy_reg_m88;
+	phy->ops.reset		= (hw->mac.type == igc_82543)
+				  ? igc_phy_hw_reset_82543
+				  : igc_phy_hw_reset_generic;
+	phy->ops.write_reg	= (hw->mac.type == igc_82543)
+				  ? igc_write_phy_reg_82543
+				  : igc_write_phy_reg_m88;
+	phy->ops.get_info	= igc_get_phy_info_m88;
+
+	/*
+	 * The external PHY of the 82543 can be in a funky state.
+	 * Resetting helps us read the PHY registers for acquiring
+	 * the PHY ID.
+	 */
+	if (!igc_init_phy_disabled_82543(hw)) {
+		ret_val = phy->ops.reset(hw);
+		if (ret_val) {
+			DEBUGOUT("Resetting PHY during init failed.\n");
+			goto out;
+		}
+		msec_delay(20);
+	}
+
+	ret_val = igc_get_phy_id(hw);
+	if (ret_val)
+		goto out;
+
+	/* Verify phy id */
+	switch (hw->mac.type) {
+	case igc_82543:
+		if (phy->id != M88IGC_E_PHY_ID) {
+			ret_val = -IGC_ERR_PHY;
+			goto out;
+		}
+		break;
+	case igc_82544:
+		if (phy->id != M88IGC_I_PHY_ID) {
+			ret_val = -IGC_ERR_PHY;
+			goto out;
+		}
+		break;
+	default:
+		ret_val = -IGC_ERR_PHY;
+		goto out;
+		break;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_init_nvm_params_82543 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_nvm_params_82543(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+
+	DEBUGFUNC("igc_init_nvm_params_82543");
+
+	nvm->type		= igc_nvm_eeprom_microwire;
+	nvm->word_size		= 64;
+	nvm->delay_usec		= 50;
+	nvm->address_bits	=  6;
+	nvm->opcode_bits	=  3;
+
+	/* Function Pointers */
+	nvm->ops.read		= igc_read_nvm_microwire;
+	nvm->ops.update		= igc_update_nvm_checksum_generic;
+	nvm->ops.valid_led_default = igc_valid_led_default_generic;
+	nvm->ops.validate	= igc_validate_nvm_checksum_generic;
+	nvm->ops.write		= igc_write_nvm_microwire;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_mac_params_82543 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_mac_params_82543(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+
+	DEBUGFUNC("igc_init_mac_params_82543");
+
+	/* Set media type */
+	switch (hw->device_id) {
+	case IGC_DEV_ID_82543GC_FIBER:
+	case IGC_DEV_ID_82544EI_FIBER:
+		hw->phy.media_type = igc_media_type_fiber;
+		break;
+	default:
+		hw->phy.media_type = igc_media_type_copper;
+		break;
+	}
+
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	mac->rar_entry_count = IGC_RAR_ENTRIES;
+
+	/* Function pointers */
+
+	/* bus type/speed/width */
+	mac->ops.get_bus_info = igc_get_bus_info_pci_generic;
+	/* function id */
+	mac->ops.set_lan_id = igc_set_lan_id_multi_port_pci;
+	/* reset */
+	mac->ops.reset_hw = igc_reset_hw_82543;
+	/* hw initialization */
+	mac->ops.init_hw = igc_init_hw_82543;
+	/* link setup */
+	mac->ops.setup_link = igc_setup_link_82543;
+	/* physical interface setup */
+	mac->ops.setup_physical_interface =
+		(hw->phy.media_type == igc_media_type_copper)
+		 ? igc_setup_copper_link_82543 : igc_setup_fiber_link_82543;
+	/* check for link */
+	mac->ops.check_for_link =
+		(hw->phy.media_type == igc_media_type_copper)
+		 ? igc_check_for_copper_link_82543
+		 : igc_check_for_fiber_link_82543;
+	/* link info */
+	mac->ops.get_link_up_info =
+		(hw->phy.media_type == igc_media_type_copper)
+		 ? igc_get_speed_and_duplex_copper_generic
+		 : igc_get_speed_and_duplex_fiber_serdes_generic;
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
+	/* writing VFTA */
+	mac->ops.write_vfta = igc_write_vfta_82543;
+	/* clearing VFTA */
+	mac->ops.clear_vfta = igc_clear_vfta_generic;
+	/* turn on/off LED */
+	mac->ops.led_on = igc_led_on_82543;
+	mac->ops.led_off = igc_led_off_82543;
+	/* clear hardware counters */
+	mac->ops.clear_hw_cntrs = igc_clear_hw_cntrs_82543;
+
+	/* Set tbi compatibility */
+	if ((hw->mac.type != igc_82543) ||
+	    (hw->phy.media_type == igc_media_type_fiber))
+		igc_set_tbi_compatibility_82543(hw, false);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_function_pointers_82543 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void igc_init_function_pointers_82543(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_init_function_pointers_82543");
+
+	hw->mac.ops.init_params = igc_init_mac_params_82543;
+	hw->nvm.ops.init_params = igc_init_nvm_params_82543;
+	hw->phy.ops.init_params = igc_init_phy_params_82543;
+}
+
+/**
+ *  igc_tbi_compatibility_enabled_82543 - Returns TBI compat status
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns the current status of 10-bit Interface (TBI) compatibility
+ *  (enabled/disabled).
+ **/
+STATIC bool igc_tbi_compatibility_enabled_82543(struct igc_hw *hw)
+{
+	struct igc_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+	bool state = false;
+
+	DEBUGFUNC("igc_tbi_compatibility_enabled_82543");
+
+	if (hw->mac.type != igc_82543) {
+		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+		goto out;
+	}
+
+	state = !!(dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED);
+
+out:
+	return state;
+}
+
+/**
+ *  igc_set_tbi_compatibility_82543 - Set TBI compatibility
+ *  @hw: pointer to the HW structure
+ *  @state: enable/disable TBI compatibility
+ *
+ *  Enables or disabled 10-bit Interface (TBI) compatibility.
+ **/
+void igc_set_tbi_compatibility_82543(struct igc_hw *hw, bool state)
+{
+	struct igc_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+
+	DEBUGFUNC("igc_set_tbi_compatibility_82543");
+
+	if (hw->mac.type != igc_82543) {
+		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+		goto out;
+	}
+
+	if (state)
+		dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED;
+	else
+		dev_spec->tbi_compatibility &= ~TBI_COMPAT_ENABLED;
+
+out:
+	return;
+}
+
+/**
+ *  igc_tbi_sbp_enabled_82543 - Returns TBI SBP status
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns the current status of 10-bit Interface (TBI) store bad packet (SBP)
+ *  (enabled/disabled).
+ **/
+bool igc_tbi_sbp_enabled_82543(struct igc_hw *hw)
+{
+	struct igc_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+	bool state = false;
+
+	DEBUGFUNC("igc_tbi_sbp_enabled_82543");
+
+	if (hw->mac.type != igc_82543) {
+		DEBUGOUT("TBI compatibility workaround for 82543 only.\n");
+		goto out;
+	}
+
+	state = !!(dev_spec->tbi_compatibility & TBI_SBP_ENABLED);
+
+out:
+	return state;
+}
+
+/**
+ *  igc_set_tbi_sbp_82543 - Set TBI SBP
+ *  @hw: pointer to the HW structure
+ *  @state: enable/disable TBI store bad packet
+ *
+ *  Enables or disabled 10-bit Interface (TBI) store bad packet (SBP).
+ **/
+STATIC void igc_set_tbi_sbp_82543(struct igc_hw *hw, bool state)
+{
+	struct igc_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+
+	DEBUGFUNC("igc_set_tbi_sbp_82543");
+
+	if (state && igc_tbi_compatibility_enabled_82543(hw))
+		dev_spec->tbi_compatibility |= TBI_SBP_ENABLED;
+	else
+		dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED;
+
+	return;
+}
+
+/**
+ *  igc_init_phy_disabled_82543 - Returns init PHY status
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns the current status of whether PHY initialization is disabled.
+ *  True if PHY initialization is disabled else false.
+ **/
+STATIC bool igc_init_phy_disabled_82543(struct igc_hw *hw)
+{
+	struct igc_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+	bool ret_val;
+
+	DEBUGFUNC("igc_init_phy_disabled_82543");
+
+	if (hw->mac.type != igc_82543) {
+		ret_val = false;
+		goto out;
+	}
+
+	ret_val = dev_spec->init_phy_disabled;
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_tbi_adjust_stats_82543 - Adjust stats when TBI enabled
+ *  @hw: pointer to the HW structure
+ *  @stats: Struct containing statistic register values
+ *  @frame_len: The length of the frame in question
+ *  @mac_addr: The Ethernet destination address of the frame in question
+ *  @max_frame_size: The maximum frame size
+ *
+ *  Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
+ **/
+void igc_tbi_adjust_stats_82543(struct igc_hw *hw,
+				  struct igc_hw_stats *stats, u32 frame_len,
+				  u8 *mac_addr, u32 max_frame_size)
+{
+	if (!(igc_tbi_sbp_enabled_82543(hw)))
+		goto out;
+
+	/* First adjust the frame length. */
+	frame_len--;
+	/*
+	 * We need to adjust the statistics counters, since the hardware
+	 * counters overcount this packet as a CRC error and undercount
+	 * the packet as a good packet
+	 */
+	/* This packet should not be counted as a CRC error. */
+	stats->crcerrs--;
+	/* This packet does count as a Good Packet Received. */
+	stats->gprc++;
+
+	/* Adjust the Good Octets received counters */
+	stats->gorc += frame_len;
+
+	/*
+	 * Is this a broadcast or multicast?  Check broadcast first,
+	 * since the test for a multicast frame will test positive on
+	 * a broadcast frame.
+	 */
+	if ((mac_addr[0] == 0xff) && (mac_addr[1] == 0xff))
+		/* Broadcast packet */
+		stats->bprc++;
+	else if (*mac_addr & 0x01)
+		/* Multicast packet */
+		stats->mprc++;
+
+	/*
+	 * In this case, the hardware has over counted the number of
+	 * oversize frames.
+	 */
+	if ((frame_len == max_frame_size) && (stats->roc > 0))
+		stats->roc--;
+
+	/*
+	 * Adjust the bin counters when the extra byte put the frame in the
+	 * wrong bin. Remember that the frame_len was adjusted above.
+	 */
+	if (frame_len == 64) {
+		stats->prc64++;
+		stats->prc127--;
+	} else if (frame_len == 127) {
+		stats->prc127++;
+		stats->prc255--;
+	} else if (frame_len == 255) {
+		stats->prc255++;
+		stats->prc511--;
+	} else if (frame_len == 511) {
+		stats->prc511++;
+		stats->prc1023--;
+	} else if (frame_len == 1023) {
+		stats->prc1023++;
+		stats->prc1522--;
+	} else if (frame_len == 1522) {
+		stats->prc1522++;
+	}
+
+out:
+	return;
+}
+
+/**
+ *  igc_read_phy_reg_82543 - Read PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY at offset and stores the information read to data.
+ **/
+STATIC s32 igc_read_phy_reg_82543(struct igc_hw *hw, u32 offset, u16 *data)
+{
+	u32 mdic;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_read_phy_reg_82543");
+
+	if (offset > MAX_PHY_REG_ADDRESS) {
+		DEBUGOUT1("PHY Address %d is out of range\n", offset);
+		ret_val = -IGC_ERR_PARAM;
+		goto out;
+	}
+
+	/*
+	 * We must first send a preamble through the MDIO pin to signal the
+	 * beginning of an MII instruction.  This is done by sending 32
+	 * consecutive "1" bits.
+	 */
+	igc_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+	/*
+	 * Now combine the next few fields that are required for a read
+	 * operation.  We use this method instead of calling the
+	 * igc_shift_out_mdi_bits routine five different times.  The format
+	 * of an MII read instruction consists of a shift out of 14 bits and
+	 * is defined as follows:
+	 *         <Preamble><SOF><Op Code><Phy Addr><Offset>
+	 * followed by a shift in of 18 bits.  This first two bits shifted in
+	 * are TurnAround bits used to avoid contention on the MDIO pin when a
+	 * READ operation is performed.  These two bits are thrown away
+	 * followed by a shift in of 16 bits which contains the desired data.
+	 */
+	mdic = (offset | (hw->phy.addr << 5) |
+		(PHY_OP_READ << 10) | (PHY_SOF << 12));
+
+	igc_shift_out_mdi_bits_82543(hw, mdic, 14);
+
+	/*
+	 * Now that we've shifted out the read command to the MII, we need to
+	 * "shift in" the 16-bit value (18 total bits) of the requested PHY
+	 * register address.
+	 */
+	*data = igc_shift_in_mdi_bits_82543(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_write_phy_reg_82543 - Write PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be written
+ *  @data: pointer to the data to be written at offset
+ *
+ *  Writes data to the PHY at offset.
+ **/
+STATIC s32 igc_write_phy_reg_82543(struct igc_hw *hw, u32 offset, u16 data)
+{
+	u32 mdic;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_write_phy_reg_82543");
+
+	if (offset > MAX_PHY_REG_ADDRESS) {
+		DEBUGOUT1("PHY Address %d is out of range\n", offset);
+		ret_val = -IGC_ERR_PARAM;
+		goto out;
+	}
+
+	/*
+	 * We'll need to use the SW defined pins to shift the write command
+	 * out to the PHY. We first send a preamble to the PHY to signal the
+	 * beginning of the MII instruction.  This is done by sending 32
+	 * consecutive "1" bits.
+	 */
+	igc_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+	/*
+	 * Now combine the remaining required fields that will indicate a
+	 * write operation. We use this method instead of calling the
+	 * igc_shift_out_mdi_bits routine for each field in the command. The
+	 * format of a MII write instruction is as follows:
+	 * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
+	 */
+	mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) |
+		(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+	mdic <<= 16;
+	mdic |= (u32)data;
+
+	igc_shift_out_mdi_bits_82543(hw, mdic, 32);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_raise_mdi_clk_82543 - Raise Management Data Input clock
+ *  @hw: pointer to the HW structure
+ *  @ctrl: pointer to the control register
+ *
+ *  Raise the management data input clock by setting the MDC bit in the control
+ *  register.
+ **/
+STATIC void igc_raise_mdi_clk_82543(struct igc_hw *hw, u32 *ctrl)
+{
+	/*
+	 * Raise the clock input to the Management Data Clock (by setting the
+	 * MDC bit), and then delay a sufficient amount of time.
+	 */
+	IGC_WRITE_REG(hw, IGC_CTRL, (*ctrl | IGC_CTRL_MDC));
+	IGC_WRITE_FLUSH(hw);
+	usec_delay(10);
+}
+
+/**
+ *  igc_lower_mdi_clk_82543 - Lower Management Data Input clock
+ *  @hw: pointer to the HW structure
+ *  @ctrl: pointer to the control register
+ *
+ *  Lower the management data input clock by clearing the MDC bit in the
+ *  control register.
+ **/
+STATIC void igc_lower_mdi_clk_82543(struct igc_hw *hw, u32 *ctrl)
+{
+	/*
+	 * Lower the clock input to the Management Data Clock (by clearing the
+	 * MDC bit), and then delay a sufficient amount of time.
+	 */
+	IGC_WRITE_REG(hw, IGC_CTRL, (*ctrl & ~IGC_CTRL_MDC));
+	IGC_WRITE_FLUSH(hw);
+	usec_delay(10);
+}
+
+/**
+ *  igc_shift_out_mdi_bits_82543 - Shift data bits our to the PHY
+ *  @hw: pointer to the HW structure
+ *  @data: data to send to the PHY
+ *  @count: number of bits to shift out
+ *
+ *  We need to shift 'count' bits out to the PHY.  So, the value in the
+ *  "data" parameter will be shifted out to the PHY one bit at a time.
+ *  In order to do this, "data" must be broken down into bits.
+ **/
+STATIC void igc_shift_out_mdi_bits_82543(struct igc_hw *hw, u32 data,
+					   u16 count)
+{
+	u32 ctrl, mask;
+
+	/*
+	 * We need to shift "count" number of bits out to the PHY.  So, the
+	 * value in the "data" parameter will be shifted out to the PHY one
+	 * bit at a time.  In order to do this, "data" must be broken down
+	 * into bits.
+	 */
+	mask = 0x01;
+	mask <<= (count - 1);
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
+	ctrl |= (IGC_CTRL_MDIO_DIR | IGC_CTRL_MDC_DIR);
+
+	while (mask) {
+		/*
+		 * A "1" is shifted out to the PHY by setting the MDIO bit to
+		 * "1" and then raising and lowering the Management Data Clock.
+		 * A "0" is shifted out to the PHY by setting the MDIO bit to
+		 * "0" and then raising and lowering the clock.
+		 */
+		if (data & mask)
+			ctrl |= IGC_CTRL_MDIO;
+		else
+			ctrl &= ~IGC_CTRL_MDIO;
+
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+		IGC_WRITE_FLUSH(hw);
+
+		usec_delay(10);
+
+		igc_raise_mdi_clk_82543(hw, &ctrl);
+		igc_lower_mdi_clk_82543(hw, &ctrl);
+
+		mask >>= 1;
+	}
+}
+
+/**
+ *  igc_shift_in_mdi_bits_82543 - Shift data bits in from the PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  In order to read a register from the PHY, we need to shift 18 bits
+ *  in from the PHY.  Bits are "shifted in" by raising the clock input to
+ *  the PHY (setting the MDC bit), and then reading the value of the data out
+ *  MDIO bit.
+ **/
+STATIC u16 igc_shift_in_mdi_bits_82543(struct igc_hw *hw)
+{
+	u32 ctrl;
+	u16 data = 0;
+	u8 i;
+
+	/*
+	 * In order to read a register from the PHY, we need to shift in a
+	 * total of 18 bits from the PHY.  The first two bit (turnaround)
+	 * times are used to avoid contention on the MDIO pin when a read
+	 * operation is performed.  These two bits are ignored by us and
+	 * thrown away.  Bits are "shifted in" by raising the input to the
+	 * Management Data Clock (setting the MDC bit) and then reading the
+	 * value of the MDIO bit.
+	 */
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	/*
+	 * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
+	 * input.
+	 */
+	ctrl &= ~IGC_CTRL_MDIO_DIR;
+	ctrl &= ~IGC_CTRL_MDIO;
+
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+	IGC_WRITE_FLUSH(hw);
+
+	/*
+	 * Raise and lower the clock before reading in the data.  This accounts
+	 * for the turnaround bits.  The first clock occurred when we clocked
+	 * out the last bit of the Register Address.
+	 */
+	igc_raise_mdi_clk_82543(hw, &ctrl);
+	igc_lower_mdi_clk_82543(hw, &ctrl);
+
+	for (data = 0, i = 0; i < 16; i++) {
+		data <<= 1;
+		igc_raise_mdi_clk_82543(hw, &ctrl);
+		ctrl = IGC_READ_REG(hw, IGC_CTRL);
+		/* Check to see if we shifted in a "1". */
+		if (ctrl & IGC_CTRL_MDIO)
+			data |= 1;
+		igc_lower_mdi_clk_82543(hw, &ctrl);
+	}
+
+	igc_raise_mdi_clk_82543(hw, &ctrl);
+	igc_lower_mdi_clk_82543(hw, &ctrl);
+
+	return data;
+}
+
+/**
+ *  igc_phy_force_speed_duplex_82543 - Force speed/duplex for PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the function to force speed and duplex for the m88 PHY, and
+ *  if the PHY is not auto-negotiating and the speed is forced to 10Mbit,
+ *  then call the function for polarity reversal workaround.
+ **/
+STATIC s32 igc_phy_force_speed_duplex_82543(struct igc_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_phy_force_speed_duplex_82543");
+
+	ret_val = igc_phy_force_speed_duplex_m88(hw);
+	if (ret_val)
+		goto out;
+
+	if (!hw->mac.autoneg && (hw->mac.forced_speed_duplex &
+	    IGC_ALL_10_SPEED))
+		ret_val = igc_polarity_reversal_workaround_82543(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_polarity_reversal_workaround_82543 - Workaround polarity reversal
+ *  @hw: pointer to the HW structure
+ *
+ *  When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity
+ *  inadvertently.  To workaround the issue, we disable the transmitter on
+ *  the PHY until we have established the link partner's link parameters.
+ **/
+STATIC s32 igc_polarity_reversal_workaround_82543(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	u16 mii_status_reg;
+	u16 i;
+	bool link;
+
+	if (!(hw->phy.ops.write_reg))
+		goto out;
+
+	/* Polarity reversal workaround for forced 10F/10H links. */
+
+	/* Disable the transmitter on the PHY */
+
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_PAGE_SELECT, 0x0019);
+	if (ret_val)
+		goto out;
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_GEN_CONTROL, 0xFFFF);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_PAGE_SELECT, 0x0000);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * This loop will early-out if the NO link condition has been met.
+	 * In other words, DO NOT use igc_phy_has_link_generic() here.
+	 */
+	for (i = PHY_FORCE_TIME; i > 0; i--) {
+		/*
+		 * Read the MII Status Register and wait for Link Status bit
+		 * to be clear.
+		 */
+
+		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
+		if (ret_val)
+			goto out;
+
+		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
+		if (ret_val)
+			goto out;
+
+		if (!(mii_status_reg & ~MII_SR_LINK_STATUS))
+			break;
+		msec_delay_irq(100);
+	}
+
+	/* Recommended delay time after link has been lost */
+	msec_delay_irq(1000);
+
+	/* Now we will re-enable the transmitter on the PHY */
+
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_PAGE_SELECT, 0x0019);
+	if (ret_val)
+		goto out;
+	msec_delay_irq(50);
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_GEN_CONTROL, 0xFFF0);
+	if (ret_val)
+		goto out;
+	msec_delay_irq(50);
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_GEN_CONTROL, 0xFF00);
+	if (ret_val)
+		goto out;
+	msec_delay_irq(50);
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_GEN_CONTROL, 0x0000);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.write_reg(hw, M88IGC_PHY_PAGE_SELECT, 0x0000);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * Read the MII Status Register and wait for Link Status bit
+	 * to be set.
+	 */
+	ret_val = igc_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link);
+	if (ret_val)
+		goto out;
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_phy_hw_reset_82543 - PHY hardware reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets the PHY_RESET_DIR bit in the extended device control register
+ *  to put the PHY into a reset and waits for completion.  Once the reset
+ *  has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out
+ *  of reset.
+ **/
+STATIC s32 igc_phy_hw_reset_82543(struct igc_hw *hw)
+{
+	u32 ctrl_ext;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_phy_hw_reset_82543");
+
+	/*
+	 * Read the Extended Device Control Register, assert the PHY_RESET_DIR
+	 * bit to put the PHY into reset...
+	 */
+	ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+	ctrl_ext |= IGC_CTRL_EXT_SDP4_DIR;
+	ctrl_ext &= ~IGC_CTRL_EXT_SDP4_DATA;
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+	IGC_WRITE_FLUSH(hw);
+
+	msec_delay(10);
+
+	/* ...then take it out of reset. */
+	ctrl_ext |= IGC_CTRL_EXT_SDP4_DATA;
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+	IGC_WRITE_FLUSH(hw);
+
+	usec_delay(150);
+
+	if (!(hw->phy.ops.get_cfg_done))
+		return IGC_SUCCESS;
+
+	ret_val = hw->phy.ops.get_cfg_done(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_reset_hw_82543 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 igc_reset_hw_82543(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_reset_hw_82543");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
+	IGC_WRITE_FLUSH(hw);
+
+	igc_set_tbi_sbp_82543(hw, false);
+
+	/*
+	 * Delay to allow any outstanding PCI transactions to complete before
+	 * resetting the device
+	 */
+	msec_delay(10);
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n");
+	if (hw->mac.type == igc_82543) {
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+	} else {
+		/*
+		 * The 82544 can't ACK the 64-bit write when issuing the
+		 * reset, so use IO-mapping as a workaround.
+		 */
+		IGC_WRITE_REG_IO(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+	}
+
+	/*
+	 * After MAC reset, force reload of NVM to restore power-on
+	 * settings to device.
+	 */
+	hw->nvm.ops.reload(hw);
+	msec_delay(2);
+
+	/* Masking off and clearing any pending interrupts */
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_READ_REG(hw, IGC_ICR);
+
+	return ret_val;
+}
+
+/**
+ *  igc_init_hw_82543 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+STATIC s32 igc_init_hw_82543(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	struct igc_dev_spec_82543 *dev_spec = &hw->dev_spec._82543;
+	u32 ctrl;
+	s32 ret_val;
+	u16 i;
+
+	DEBUGFUNC("igc_init_hw_82543");
+
+	/* Disabling VLAN filtering */
+	IGC_WRITE_REG(hw, IGC_VET, 0);
+	mac->ops.clear_vfta(hw);
+
+	/* Setup the receive address. */
+	igc_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for (i = 0; i < mac->mta_reg_count; i++) {
+		IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
+		IGC_WRITE_FLUSH(hw);
+	}
+
+	/*
+	 * Set the PCI priority bit correctly in the CTRL register.  This
+	 * determines if the adapter gives priority to receives, or if it
+	 * gives equal priority to transmits and receives.
+	 */
+	if (hw->mac.type == igc_82543 && dev_spec->dma_fairness) {
+		ctrl = IGC_READ_REG(hw, IGC_CTRL);
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_PRIOR);
+	}
+
+	igc_pcix_mmrbc_workaround_generic(hw);
+
+	/* Setup link and flow control */
+	ret_val = mac->ops.setup_link(hw);
+
+	/*
+	 * Clear all of the statistics registers (clear on read).  It is
+	 * important that we do this after we have tried to establish link
+	 * because the symbol error count will increment wildly if there
+	 * is no link.
+	 */
+	igc_clear_hw_cntrs_82543(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_setup_link_82543 - Setup flow control and link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the EEPROM to determine the initial polarity value and write the
+ *  extended device control register with the information before calling
+ *  the generic setup link function, which does the following:
+ *  Determines which flow control settings to use, then configures flow
+ *  control.  Calls the appropriate media-specific link configuration
+ *  function.  Assuming the adapter has a valid link partner, a valid link
+ *  should be established.  Assumes the hardware has previously been reset
+ *  and the transmitter and receiver are not enabled.
+ **/
+STATIC s32 igc_setup_link_82543(struct igc_hw *hw)
+{
+	u32 ctrl_ext;
+	s32  ret_val;
+	u16 data;
+
+	DEBUGFUNC("igc_setup_link_82543");
+
+	/*
+	 * Take the 4 bits from NVM word 0xF that determine the initial
+	 * polarity value for the SW controlled pins, and setup the
+	 * Extended Device Control reg with that info.
+	 * This is needed because one of the SW controlled pins is used for
+	 * signal detection.  So this should be done before phy setup.
+	 */
+	if (hw->mac.type == igc_82543) {
+		ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+		if (ret_val) {
+			DEBUGOUT("NVM Read Error\n");
+			ret_val = -IGC_ERR_NVM;
+			goto out;
+		}
+		ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) <<
+			    NVM_SWDPIO_EXT_SHIFT);
+		IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+	}
+
+	ret_val = igc_setup_link_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_setup_copper_link_82543 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the link for auto-neg or forced speed and duplex.  Then we check
+ *  for link, once link is established calls to configure collision distance
+ *  and flow control are called.
+ **/
+STATIC s32 igc_setup_copper_link_82543(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+	bool link;
+
+	DEBUGFUNC("igc_setup_copper_link_82543");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL) | IGC_CTRL_SLU;
+	/*
+	 * With 82543, we need to force speed and duplex on the MAC
+	 * equal to what the PHY speed and duplex configuration is.
+	 * In addition, we need to perform a hardware reset on the
+	 * PHY to take it out of reset.
+	 */
+	if (hw->mac.type == igc_82543) {
+		ctrl |= (IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+		ret_val = hw->phy.ops.reset(hw);
+		if (ret_val)
+			goto out;
+	} else {
+		ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+	}
+
+	/* Set MDI/MDI-X, Polarity Reversal, and downshift settings */
+	ret_val = igc_copper_link_setup_m88(hw);
+	if (ret_val)
+		goto out;
+
+	if (hw->mac.autoneg) {
+		/*
+		 * Setup autoneg and flow control advertisement and perform
+		 * autonegotiation.
+		 */
+		ret_val = igc_copper_link_autoneg(hw);
+		if (ret_val)
+			goto out;
+	} else {
+		/*
+		 * PHY will be set to 10H, 10F, 100H or 100F
+		 * depending on user settings.
+		 */
+		DEBUGOUT("Forcing Speed and Duplex\n");
+		ret_val = igc_phy_force_speed_duplex_82543(hw);
+		if (ret_val) {
+			DEBUGOUT("Error Forcing Speed and Duplex\n");
+			goto out;
+		}
+	}
+
+	/*
+	 * Check link status. Wait up to 100 microseconds for link to become
+	 * valid.
+	 */
+	ret_val = igc_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
+					     &link);
+	if (ret_val)
+		goto out;
+
+
+	if (link) {
+		DEBUGOUT("Valid link established!!!\n");
+		/* Config the MAC and PHY after link is up */
+		if (hw->mac.type == igc_82544) {
+			hw->mac.ops.config_collision_dist(hw);
+		} else {
+			ret_val = igc_config_mac_to_phy_82543(hw);
+			if (ret_val)
+				goto out;
+		}
+		ret_val = igc_config_fc_after_link_up_generic(hw);
+	} else {
+		DEBUGOUT("Unable to establish link!!!\n");
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_setup_fiber_link_82543 - Setup link for fiber
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures collision distance and flow control for fiber links.  Upon
+ *  successful setup, poll for link.
+ **/
+STATIC s32 igc_setup_fiber_link_82543(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_setup_fiber_link_82543");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	/* Take the link out of reset */
+	ctrl &= ~IGC_CTRL_LRST;
+
+	hw->mac.ops.config_collision_dist(hw);
+
+	ret_val = igc_commit_fc_settings_generic(hw);
+	if (ret_val)
+		goto out;
+
+	DEBUGOUT("Auto-negotiation enabled\n");
+
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+	IGC_WRITE_FLUSH(hw);
+	msec_delay(1);
+
+	/*
+	 * For these adapters, the SW definable pin 1 is cleared when the
+	 * optics detect a signal.  If we have a signal, then poll for a
+	 * "Link-Up" indication.
+	 */
+	if (!(IGC_READ_REG(hw, IGC_CTRL) & IGC_CTRL_SWDPIN1))
+		ret_val = igc_poll_fiber_serdes_link_generic(hw);
+	else
+		DEBUGOUT("No signal detected\n");
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_check_for_copper_link_82543 - Check for link (Copper)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks the phy for link, if link exists, do the following:
+ *   - check for downshift
+ *   - do polarity workaround (if necessary)
+ *   - configure collision distance
+ *   - configure flow control after link up
+ *   - configure tbi compatibility
+ **/
+STATIC s32 igc_check_for_copper_link_82543(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	u32 icr, rctl;
+	s32 ret_val;
+	u16 speed, duplex;
+	bool link;
+
+	DEBUGFUNC("igc_check_for_copper_link_82543");
+
+	if (!mac->get_link_status) {
+		ret_val = IGC_SUCCESS;
+		goto out;
+	}
+
+	ret_val = igc_phy_has_link_generic(hw, 1, 0, &link);
+	if (ret_val)
+		goto out;
+
+	if (!link)
+		goto out; /* No link detected */
+
+	mac->get_link_status = false;
+
+	igc_check_downshift_generic(hw);
+
+	/*
+	 * If we are forcing speed/duplex, then we can return since
+	 * we have already determined whether we have link or not.
+	 */
+	if (!mac->autoneg) {
+		/*
+		 * If speed and duplex are forced to 10H or 10F, then we will
+		 * implement the polarity reversal workaround.  We disable
+		 * interrupts first, and upon returning, place the devices
+		 * interrupt state to its previous value except for the link
+		 * status change interrupt which will happened due to the
+		 * execution of this workaround.
+		 */
+		if (mac->forced_speed_duplex & IGC_ALL_10_SPEED) {
+			IGC_WRITE_REG(hw, IGC_IMC, 0xFFFFFFFF);
+			ret_val = igc_polarity_reversal_workaround_82543(hw);
+			icr = IGC_READ_REG(hw, IGC_ICR);
+			IGC_WRITE_REG(hw, IGC_ICS, (icr & ~IGC_ICS_LSC));
+			IGC_WRITE_REG(hw, IGC_IMS, IMS_ENABLE_MASK);
+		}
+
+		ret_val = -IGC_ERR_CONFIG;
+		goto out;
+	}
+
+	/*
+	 * We have a M88E1000 PHY and Auto-Neg is enabled.  If we
+	 * have Si on board that is 82544 or newer, Auto
+	 * Speed Detection takes care of MAC speed/duplex
+	 * configuration.  So we only need to configure Collision
+	 * Distance in the MAC.  Otherwise, we need to force
+	 * speed/duplex on the MAC to the current PHY speed/duplex
+	 * settings.
+	 */
+	if (mac->type == igc_82544)
+		hw->mac.ops.config_collision_dist(hw);
+	else {
+		ret_val = igc_config_mac_to_phy_82543(hw);
+		if (ret_val) {
+			DEBUGOUT("Error configuring MAC to PHY settings\n");
+			goto out;
+		}
+	}
+
+	/*
+	 * Configure Flow Control now that Auto-Neg has completed.
+	 * First, we need to restore the desired flow control
+	 * settings because we may have had to re-autoneg with a
+	 * different link partner.
+	 */
+	ret_val = igc_config_fc_after_link_up_generic(hw);
+	if (ret_val)
+		DEBUGOUT("Error configuring flow control\n");
+
+	/*
+	 * At this point we know that we are on copper and we have
+	 * auto-negotiated link.  These are conditions for checking the link
+	 * partner capability register.  We use the link speed to determine if
+	 * TBI compatibility needs to be turned on or off.  If the link is not
+	 * at gigabit speed, then TBI compatibility is not needed.  If we are
+	 * at gigabit speed, we turn on TBI compatibility.
+	 */
+	if (igc_tbi_compatibility_enabled_82543(hw)) {
+		ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
+		if (ret_val) {
+			DEBUGOUT("Error getting link speed and duplex\n");
+			return ret_val;
+		}
+		if (speed != SPEED_1000) {
+			/*
+			 * If link speed is not set to gigabit speed,
+			 * we do not need to enable TBI compatibility.
+			 */
+			if (igc_tbi_sbp_enabled_82543(hw)) {
+				/*
+				 * If we previously were in the mode,
+				 * turn it off.
+				 */
+				igc_set_tbi_sbp_82543(hw, false);
+				rctl = IGC_READ_REG(hw, IGC_RCTL);
+				rctl &= ~IGC_RCTL_SBP;
+				IGC_WRITE_REG(hw, IGC_RCTL, rctl);
+			}
+		} else {
+			/*
+			 * If TBI compatibility is was previously off,
+			 * turn it on. For compatibility with a TBI link
+			 * partner, we will store bad packets. Some
+			 * frames have an additional byte on the end and
+			 * will look like CRC errors to to the hardware.
+			 */
+			if (!igc_tbi_sbp_enabled_82543(hw)) {
+				igc_set_tbi_sbp_82543(hw, true);
+				rctl = IGC_READ_REG(hw, IGC_RCTL);
+				rctl |= IGC_RCTL_SBP;
+				IGC_WRITE_REG(hw, IGC_RCTL, rctl);
+			}
+		}
+	}
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_check_for_fiber_link_82543 - Check for link (Fiber)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks for link up on the hardware.  If link is not up and we have
+ *  a signal, then we need to force link up.
+ **/
+STATIC s32 igc_check_for_fiber_link_82543(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	u32 rxcw, ctrl, status;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_check_for_fiber_link_82543");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	status = IGC_READ_REG(hw, IGC_STATUS);
+	rxcw = IGC_READ_REG(hw, IGC_RXCW);
+
+	/*
+	 * If we don't have link (auto-negotiation failed or link partner
+	 * cannot auto-negotiate), the cable is plugged in (we have signal),
+	 * and our link partner is not trying to auto-negotiate with us (we
+	 * are receiving idles or data), we need to force link up. We also
+	 * need to give auto-negotiation time to complete, in case the cable
+	 * was just plugged in. The autoneg_failed flag does this.
+	 */
+	/* (ctrl & IGC_CTRL_SWDPIN1) == 0 == have signal */
+	if ((!(ctrl & IGC_CTRL_SWDPIN1)) &&
+	    (!(status & IGC_STATUS_LU)) &&
+	    (!(rxcw & IGC_RXCW_C))) {
+		if (!mac->autoneg_failed) {
+			mac->autoneg_failed = true;
+			ret_val = 0;
+			goto out;
+		}
+		DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+
+		/* Disable auto-negotiation in the TXCW register */
+		IGC_WRITE_REG(hw, IGC_TXCW, (mac->txcw & ~IGC_TXCW_ANE));
+
+		/* Force link-up and also force full-duplex. */
+		ctrl = IGC_READ_REG(hw, IGC_CTRL);
+		ctrl |= (IGC_CTRL_SLU | IGC_CTRL_FD);
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+		/* Configure Flow Control after forcing link up. */
+		ret_val = igc_config_fc_after_link_up_generic(hw);
+		if (ret_val) {
+			DEBUGOUT("Error configuring flow control\n");
+			goto out;
+		}
+	} else if ((ctrl & IGC_CTRL_SLU) && (rxcw & IGC_RXCW_C)) {
+		/*
+		 * If we are forcing link and we are receiving /C/ ordered
+		 * sets, re-enable auto-negotiation in the TXCW register
+		 * and disable forced link in the Device Control register
+		 * in an attempt to auto-negotiate with our link partner.
+		 */
+		DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+		IGC_WRITE_REG(hw, IGC_TXCW, mac->txcw);
+		IGC_WRITE_REG(hw, IGC_CTRL, (ctrl & ~IGC_CTRL_SLU));
+
+		mac->serdes_has_link = true;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_config_mac_to_phy_82543 - Configure MAC to PHY settings
+ *  @hw: pointer to the HW structure
+ *
+ *  For the 82543 silicon, we need to set the MAC to match the settings
+ *  of the PHY, even if the PHY is auto-negotiating.
+ **/
+STATIC s32 igc_config_mac_to_phy_82543(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val = IGC_SUCCESS;
+	u16 phy_data;
+
+	DEBUGFUNC("igc_config_mac_to_phy_82543");
+
+	if (!(hw->phy.ops.read_reg))
+		goto out;
+
+	/* Set the bits to force speed and duplex */
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	ctrl |= (IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+	ctrl &= ~(IGC_CTRL_SPD_SEL | IGC_CTRL_ILOS);
+
+	/*
+	 * Set up duplex in the Device Control and Transmit Control
+	 * registers depending on negotiated values.
+	 */
+	ret_val = hw->phy.ops.read_reg(hw, M88IGC_PHY_SPEC_STATUS, &phy_data);
+	if (ret_val)
+		goto out;
+
+	ctrl &= ~IGC_CTRL_FD;
+	if (phy_data & M88IGC_PSSR_DPLX)
+		ctrl |= IGC_CTRL_FD;
+
+	hw->mac.ops.config_collision_dist(hw);
+
+	/*
+	 * Set up speed in the Device Control register depending on
+	 * negotiated values.
+	 */
+	if ((phy_data & M88IGC_PSSR_SPEED) == M88IGC_PSSR_1000MBS)
+		ctrl |= IGC_CTRL_SPD_1000;
+	else if ((phy_data & M88IGC_PSSR_SPEED) == M88IGC_PSSR_100MBS)
+		ctrl |= IGC_CTRL_SPD_100;
+
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_write_vfta_82543 - Write value to VLAN filter table
+ *  @hw: pointer to the HW structure
+ *  @offset: the 32-bit offset in which to write the value to.
+ *  @value: the 32-bit value to write at location offset.
+ *
+ *  This writes a 32-bit value to a 32-bit offset in the VLAN filter
+ *  table.
+ **/
+STATIC void igc_write_vfta_82543(struct igc_hw *hw, u32 offset, u32 value)
+{
+	u32 temp;
+
+	DEBUGFUNC("igc_write_vfta_82543");
+
+	if ((hw->mac.type == igc_82544) && (offset & 1)) {
+		temp = IGC_READ_REG_ARRAY(hw, IGC_VFTA, offset - 1);
+		IGC_WRITE_REG_ARRAY(hw, IGC_VFTA, offset, value);
+		IGC_WRITE_FLUSH(hw);
+		IGC_WRITE_REG_ARRAY(hw, IGC_VFTA, offset - 1, temp);
+		IGC_WRITE_FLUSH(hw);
+	} else {
+		igc_write_vfta_generic(hw, offset, value);
+	}
+}
+
+/**
+ *  igc_led_on_82543 - Turn on SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED on.
+ **/
+STATIC s32 igc_led_on_82543(struct igc_hw *hw)
+{
+	u32 ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGFUNC("igc_led_on_82543");
+
+	if (hw->mac.type == igc_82544 &&
+	    hw->phy.media_type == igc_media_type_copper) {
+		/* Clear SW-definable Pin 0 to turn on the LED */
+		ctrl &= ~IGC_CTRL_SWDPIN0;
+		ctrl |= IGC_CTRL_SWDPIO0;
+	} else {
+		/* Fiber 82544 and all 82543 use this method */
+		ctrl |= IGC_CTRL_SWDPIN0;
+		ctrl |= IGC_CTRL_SWDPIO0;
+	}
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_led_off_82543 - Turn off SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED off.
+ **/
+STATIC s32 igc_led_off_82543(struct igc_hw *hw)
+{
+	u32 ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGFUNC("igc_led_off_82543");
+
+	if (hw->mac.type == igc_82544 &&
+	    hw->phy.media_type == igc_media_type_copper) {
+		/* Set SW-definable Pin 0 to turn off the LED */
+		ctrl |= IGC_CTRL_SWDPIN0;
+		ctrl |= IGC_CTRL_SWDPIO0;
+	} else {
+		ctrl &= ~IGC_CTRL_SWDPIN0;
+		ctrl |= IGC_CTRL_SWDPIO0;
+	}
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_clear_hw_cntrs_82543 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+STATIC void igc_clear_hw_cntrs_82543(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_clear_hw_cntrs_82543");
+
+	igc_clear_hw_cntrs_base_generic(hw);
+
+	IGC_READ_REG(hw, IGC_PRC64);
+	IGC_READ_REG(hw, IGC_PRC127);
+	IGC_READ_REG(hw, IGC_PRC255);
+	IGC_READ_REG(hw, IGC_PRC511);
+	IGC_READ_REG(hw, IGC_PRC1023);
+	IGC_READ_REG(hw, IGC_PRC1522);
+	IGC_READ_REG(hw, IGC_PTC64);
+	IGC_READ_REG(hw, IGC_PTC127);
+	IGC_READ_REG(hw, IGC_PTC255);
+	IGC_READ_REG(hw, IGC_PTC511);
+	IGC_READ_REG(hw, IGC_PTC1023);
+	IGC_READ_REG(hw, IGC_PTC1522);
+
+	IGC_READ_REG(hw, IGC_ALGNERRC);
+	IGC_READ_REG(hw, IGC_RXERRC);
+	IGC_READ_REG(hw, IGC_TNCRS);
+	IGC_READ_REG(hw, IGC_CEXTERR);
+	IGC_READ_REG(hw, IGC_TSCTC);
+	IGC_READ_REG(hw, IGC_TSCTFC);
+}
diff --git a/drivers/net/igc/base/e1000_82543.h b/drivers/net/igc/base/e1000_82543.h
new file mode 100644
index 0000000..537293d
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82543.h
@@ -0,0 +1,27 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_82543_H_
+#define _IGC_82543_H_
+
+#define PHY_PREAMBLE		0xFFFFFFFF
+#define PHY_PREAMBLE_SIZE	32
+#define PHY_SOF			0x1
+#define PHY_OP_READ		0x2
+#define PHY_OP_WRITE		0x1
+#define PHY_TURNAROUND		0x2
+
+#define TBI_COMPAT_ENABLED	0x1 /* Global "knob" for the workaround */
+/* If TBI_COMPAT_ENABLED, then this is the current state (on/off) */
+#define TBI_SBP_ENABLED		0x2
+
+void igc_tbi_adjust_stats_82543(struct igc_hw *hw,
+				  struct igc_hw_stats *stats,
+				  u32 frame_len, u8 *mac_addr,
+				  u32 max_frame_size);
+void igc_set_tbi_compatibility_82543(struct igc_hw *hw,
+				       bool state);
+bool igc_tbi_sbp_enabled_82543(struct igc_hw *hw);
+
+#endif
diff --git a/drivers/net/igc/base/e1000_82571.c b/drivers/net/igc/base/e1000_82571.c
new file mode 100644
index 0000000..33306d4
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82571.c
@@ -0,0 +1,2001 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+/* 82571EB Gigabit Ethernet Controller
+ * 82571EB Gigabit Ethernet Controller (Copper)
+ * 82571EB Gigabit Ethernet Controller (Fiber)
+ * 82571EB Dual Port Gigabit Mezzanine Adapter
+ * 82571EB Quad Port Gigabit Mezzanine Adapter
+ * 82571PT Gigabit PT Quad Port Server ExpressModule
+ * 82572EI Gigabit Ethernet Controller (Copper)
+ * 82572EI Gigabit Ethernet Controller (Fiber)
+ * 82572EI Gigabit Ethernet Controller
+ * 82573V Gigabit Ethernet Controller (Copper)
+ * 82573E Gigabit Ethernet Controller (Copper)
+ * 82573L Gigabit Ethernet Controller
+ * 82574L Gigabit Network Connection
+ * 82583V Gigabit Network Connection
+ */
+
+#include "e1000_api.h"
+
+STATIC s32  igc_acquire_nvm_82571(struct igc_hw *hw);
+STATIC void igc_release_nvm_82571(struct igc_hw *hw);
+STATIC s32  igc_write_nvm_82571(struct igc_hw *hw, u16 offset,
+				  u16 words, u16 *data);
+STATIC s32  igc_update_nvm_checksum_82571(struct igc_hw *hw);
+STATIC s32  igc_validate_nvm_checksum_82571(struct igc_hw *hw);
+STATIC s32  igc_get_cfg_done_82571(struct igc_hw *hw);
+STATIC s32  igc_set_d0_lplu_state_82571(struct igc_hw *hw,
+					  bool active);
+STATIC s32  igc_reset_hw_82571(struct igc_hw *hw);
+STATIC s32  igc_init_hw_82571(struct igc_hw *hw);
+STATIC void igc_clear_vfta_82571(struct igc_hw *hw);
+STATIC bool igc_check_mng_mode_82574(struct igc_hw *hw);
+STATIC s32 igc_led_on_82574(struct igc_hw *hw);
+STATIC s32  igc_setup_link_82571(struct igc_hw *hw);
+STATIC s32  igc_setup_copper_link_82571(struct igc_hw *hw);
+STATIC s32  igc_check_for_serdes_link_82571(struct igc_hw *hw);
+STATIC s32  igc_setup_fiber_serdes_link_82571(struct igc_hw *hw);
+STATIC s32  igc_valid_led_default_82571(struct igc_hw *hw, u16 *data);
+STATIC void igc_clear_hw_cntrs_82571(struct igc_hw *hw);
+STATIC s32  igc_get_hw_semaphore_82571(struct igc_hw *hw);
+STATIC s32  igc_fix_nvm_checksum_82571(struct igc_hw *hw);
+STATIC s32  igc_get_phy_id_82571(struct igc_hw *hw);
+STATIC void igc_put_hw_semaphore_82571(struct igc_hw *hw);
+STATIC void igc_put_hw_semaphore_82573(struct igc_hw *hw);
+STATIC s32  igc_get_hw_semaphore_82574(struct igc_hw *hw);
+STATIC void igc_put_hw_semaphore_82574(struct igc_hw *hw);
+STATIC s32  igc_set_d0_lplu_state_82574(struct igc_hw *hw,
+					  bool active);
+STATIC s32  igc_set_d3_lplu_state_82574(struct igc_hw *hw,
+					  bool active);
+STATIC void igc_initialize_hw_bits_82571(struct igc_hw *hw);
+STATIC s32  igc_write_nvm_eewr_82571(struct igc_hw *hw, u16 offset,
+				       u16 words, u16 *data);
+STATIC s32  igc_read_mac_addr_82571(struct igc_hw *hw);
+STATIC void igc_power_down_phy_copper_82571(struct igc_hw *hw);
+
+/**
+ *  igc_init_phy_params_82571 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_phy_params_82571(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_init_phy_params_82571");
+
+	if (hw->phy.media_type != igc_media_type_copper) {
+		phy->type = igc_phy_none;
+		return IGC_SUCCESS;
+	}
+
+	phy->addr			= 1;
+	phy->autoneg_mask		= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+	phy->reset_delay_us		= 100;
+
+	phy->ops.check_reset_block	= igc_check_reset_block_generic;
+	phy->ops.reset			= igc_phy_hw_reset_generic;
+	phy->ops.set_d0_lplu_state	= igc_set_d0_lplu_state_82571;
+	phy->ops.set_d3_lplu_state	= igc_set_d3_lplu_state_generic;
+	phy->ops.power_up		= igc_power_up_phy_copper;
+	phy->ops.power_down		= igc_power_down_phy_copper_82571;
+
+	switch (hw->mac.type) {
+	case igc_82571:
+	case igc_82572:
+		phy->type		= igc_phy_igp_2;
+		phy->ops.get_cfg_done	= igc_get_cfg_done_82571;
+		phy->ops.get_info	= igc_get_phy_info_igp;
+		phy->ops.check_polarity	= igc_check_polarity_igp;
+		phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_igp;
+		phy->ops.get_cable_length = igc_get_cable_length_igp_2;
+		phy->ops.read_reg	= igc_read_phy_reg_igp;
+		phy->ops.write_reg	= igc_write_phy_reg_igp;
+		phy->ops.acquire	= igc_get_hw_semaphore_82571;
+		phy->ops.release	= igc_put_hw_semaphore_82571;
+		break;
+	case igc_82573:
+		phy->type		= igc_phy_m88;
+		phy->ops.get_cfg_done	= igc_get_cfg_done_generic;
+		phy->ops.get_info	= igc_get_phy_info_m88;
+		phy->ops.check_polarity	= igc_check_polarity_m88;
+		phy->ops.commit		= igc_phy_sw_reset_generic;
+		phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_m88;
+		phy->ops.get_cable_length = igc_get_cable_length_m88;
+		phy->ops.read_reg	= igc_read_phy_reg_m88;
+		phy->ops.write_reg	= igc_write_phy_reg_m88;
+		phy->ops.acquire	= igc_get_hw_semaphore_82571;
+		phy->ops.release	= igc_put_hw_semaphore_82571;
+		break;
+	case igc_82574:
+	case igc_82583:
+		IGC_MUTEX_INIT(&hw->dev_spec._82571.swflag_mutex);
+
+		phy->type		= igc_phy_bm;
+		phy->ops.get_cfg_done	= igc_get_cfg_done_generic;
+		phy->ops.get_info	= igc_get_phy_info_m88;
+		phy->ops.check_polarity	= igc_check_polarity_m88;
+		phy->ops.commit		= igc_phy_sw_reset_generic;
+		phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_m88;
+		phy->ops.get_cable_length = igc_get_cable_length_m88;
+		phy->ops.read_reg	= igc_read_phy_reg_bm2;
+		phy->ops.write_reg	= igc_write_phy_reg_bm2;
+		phy->ops.acquire	= igc_get_hw_semaphore_82574;
+		phy->ops.release	= igc_put_hw_semaphore_82574;
+		phy->ops.set_d0_lplu_state = igc_set_d0_lplu_state_82574;
+		phy->ops.set_d3_lplu_state = igc_set_d3_lplu_state_82574;
+		break;
+	default:
+		return -IGC_ERR_PHY;
+		break;
+	}
+
+	/* This can only be done after all function pointers are setup. */
+	ret_val = igc_get_phy_id_82571(hw);
+	if (ret_val) {
+		DEBUGOUT("Error getting PHY ID\n");
+		return ret_val;
+	}
+
+	/* Verify phy id */
+	switch (hw->mac.type) {
+	case igc_82571:
+	case igc_82572:
+		if (phy->id != IGP01IGC_I_PHY_ID)
+			ret_val = -IGC_ERR_PHY;
+		break;
+	case igc_82573:
+		if (phy->id != M88E1111_I_PHY_ID)
+			ret_val = -IGC_ERR_PHY;
+		break;
+	case igc_82574:
+	case igc_82583:
+		if (phy->id != BMIGC_E_PHY_ID_R2)
+			ret_val = -IGC_ERR_PHY;
+		break;
+	default:
+		ret_val = -IGC_ERR_PHY;
+		break;
+	}
+
+	if (ret_val)
+		DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
+
+	return ret_val;
+}
+
+/**
+ *  igc_init_nvm_params_82571 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_nvm_params_82571(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	u32 eecd = IGC_READ_REG(hw, IGC_EECD);
+	u16 size;
+
+	DEBUGFUNC("igc_init_nvm_params_82571");
+
+	nvm->opcode_bits = 8;
+	nvm->delay_usec = 1;
+	switch (nvm->override) {
+	case igc_nvm_override_spi_large:
+		nvm->page_size = 32;
+		nvm->address_bits = 16;
+		break;
+	case igc_nvm_override_spi_small:
+		nvm->page_size = 8;
+		nvm->address_bits = 8;
+		break;
+	default:
+		nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
+		nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ? 16 : 8;
+		break;
+	}
+
+	switch (hw->mac.type) {
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		if (((eecd >> 15) & 0x3) == 0x3) {
+			nvm->type = igc_nvm_flash_hw;
+			nvm->word_size = 2048;
+			/* Autonomous Flash update bit must be cleared due
+			 * to Flash update issue.
+			 */
+			eecd &= ~IGC_EECD_AUPDEN;
+			IGC_WRITE_REG(hw, IGC_EECD, eecd);
+			break;
+		}
+		/* Fall Through */
+	default:
+		nvm->type = igc_nvm_eeprom_spi;
+		size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
+			     IGC_EECD_SIZE_EX_SHIFT);
+		/* Added to a constant, "size" becomes the left-shift value
+		 * for setting word_size.
+		 */
+		size += NVM_WORD_SIZE_BASE_SHIFT;
+
+		/* EEPROM access above 16k is unsupported */
+		if (size > 14)
+			size = 14;
+		nvm->word_size = 1 << size;
+		break;
+	}
+
+	/* Function Pointers */
+	switch (hw->mac.type) {
+	case igc_82574:
+	case igc_82583:
+		nvm->ops.acquire = igc_get_hw_semaphore_82574;
+		nvm->ops.release = igc_put_hw_semaphore_82574;
+		break;
+	default:
+		nvm->ops.acquire = igc_acquire_nvm_82571;
+		nvm->ops.release = igc_release_nvm_82571;
+		break;
+	}
+	nvm->ops.read = igc_read_nvm_eerd;
+	nvm->ops.update = igc_update_nvm_checksum_82571;
+	nvm->ops.validate = igc_validate_nvm_checksum_82571;
+	nvm->ops.valid_led_default = igc_valid_led_default_82571;
+	nvm->ops.write = igc_write_nvm_82571;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_mac_params_82571 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_mac_params_82571(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	u32 swsm = 0;
+	u32 swsm2 = 0;
+	bool force_clear_smbi = false;
+
+	DEBUGFUNC("igc_init_mac_params_82571");
+
+	/* Set media type and media-dependent function pointers */
+	switch (hw->device_id) {
+	case IGC_DEV_ID_82571EB_FIBER:
+	case IGC_DEV_ID_82572EI_FIBER:
+	case IGC_DEV_ID_82571EB_QUAD_FIBER:
+		hw->phy.media_type = igc_media_type_fiber;
+		mac->ops.setup_physical_interface =
+			igc_setup_fiber_serdes_link_82571;
+		mac->ops.check_for_link = igc_check_for_fiber_link_generic;
+		mac->ops.get_link_up_info =
+			igc_get_speed_and_duplex_fiber_serdes_generic;
+		break;
+	case IGC_DEV_ID_82571EB_SERDES:
+	case IGC_DEV_ID_82571EB_SERDES_DUAL:
+	case IGC_DEV_ID_82571EB_SERDES_QUAD:
+	case IGC_DEV_ID_82572EI_SERDES:
+		hw->phy.media_type = igc_media_type_internal_serdes;
+		mac->ops.setup_physical_interface =
+			igc_setup_fiber_serdes_link_82571;
+		mac->ops.check_for_link = igc_check_for_serdes_link_82571;
+		mac->ops.get_link_up_info =
+			igc_get_speed_and_duplex_fiber_serdes_generic;
+		break;
+	default:
+		hw->phy.media_type = igc_media_type_copper;
+		mac->ops.setup_physical_interface =
+			igc_setup_copper_link_82571;
+		mac->ops.check_for_link = igc_check_for_copper_link_generic;
+		mac->ops.get_link_up_info =
+			igc_get_speed_and_duplex_copper_generic;
+		break;
+	}
+
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	mac->rar_entry_count = IGC_RAR_ENTRIES;
+	/* Set if part includes ASF firmware */
+	mac->asf_firmware_present = true;
+	/* Adaptive IFS supported */
+	mac->adaptive_ifs = true;
+
+	/* Function pointers */
+
+	/* bus type/speed/width */
+	mac->ops.get_bus_info = igc_get_bus_info_pcie_generic;
+	/* reset */
+	mac->ops.reset_hw = igc_reset_hw_82571;
+	/* hw initialization */
+	mac->ops.init_hw = igc_init_hw_82571;
+	/* link setup */
+	mac->ops.setup_link = igc_setup_link_82571;
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
+	/* writing VFTA */
+	mac->ops.write_vfta = igc_write_vfta_generic;
+	/* clearing VFTA */
+	mac->ops.clear_vfta = igc_clear_vfta_82571;
+	/* read mac address */
+	mac->ops.read_mac_addr = igc_read_mac_addr_82571;
+	/* ID LED init */
+	mac->ops.id_led_init = igc_id_led_init_generic;
+	/* setup LED */
+	mac->ops.setup_led = igc_setup_led_generic;
+	/* cleanup LED */
+	mac->ops.cleanup_led = igc_cleanup_led_generic;
+	/* turn off LED */
+	mac->ops.led_off = igc_led_off_generic;
+	/* clear hardware counters */
+	mac->ops.clear_hw_cntrs = igc_clear_hw_cntrs_82571;
+
+	/* MAC-specific function pointers */
+	switch (hw->mac.type) {
+	case igc_82573:
+		mac->ops.set_lan_id = igc_set_lan_id_single_port;
+		mac->ops.check_mng_mode = igc_check_mng_mode_generic;
+		mac->ops.led_on = igc_led_on_generic;
+		mac->ops.blink_led = igc_blink_led_generic;
+
+		/* FWSM register */
+		mac->has_fwsm = true;
+		/* ARC supported; valid only if manageability features are
+		 * enabled.
+		 */
+		mac->arc_subsystem_valid = !!(IGC_READ_REG(hw, IGC_FWSM) &
+					      IGC_FWSM_MODE_MASK);
+		break;
+	case igc_82574:
+	case igc_82583:
+		mac->ops.set_lan_id = igc_set_lan_id_single_port;
+		mac->ops.check_mng_mode = igc_check_mng_mode_82574;
+		mac->ops.led_on = igc_led_on_82574;
+		break;
+	default:
+		mac->ops.check_mng_mode = igc_check_mng_mode_generic;
+		mac->ops.led_on = igc_led_on_generic;
+		mac->ops.blink_led = igc_blink_led_generic;
+
+		/* FWSM register */
+		mac->has_fwsm = true;
+		break;
+	}
+
+	/* Ensure that the inter-port SWSM.SMBI lock bit is clear before
+	 * first NVM or PHY acess. This should be done for single-port
+	 * devices, and for one port only on dual-port devices so that
+	 * for those devices we can still use the SMBI lock to synchronize
+	 * inter-port accesses to the PHY & NVM.
+	 */
+	switch (hw->mac.type) {
+	case igc_82571:
+	case igc_82572:
+		swsm2 = IGC_READ_REG(hw, IGC_SWSM2);
+
+		if (!(swsm2 & IGC_SWSM2_LOCK)) {
+			/* Only do this for the first interface on this card */
+			IGC_WRITE_REG(hw, IGC_SWSM2, swsm2 |
+					IGC_SWSM2_LOCK);
+			force_clear_smbi = true;
+		} else {
+			force_clear_smbi = false;
+		}
+		break;
+	default:
+		force_clear_smbi = true;
+		break;
+	}
+
+	if (force_clear_smbi) {
+		/* Make sure SWSM.SMBI is clear */
+		swsm = IGC_READ_REG(hw, IGC_SWSM);
+		if (swsm & IGC_SWSM_SMBI) {
+			/* This bit should not be set on a first interface, and
+			 * indicates that the bootagent or EFI code has
+			 * improperly left this bit enabled
+			 */
+			DEBUGOUT("Please update your 82571 Bootagent\n");
+		}
+		IGC_WRITE_REG(hw, IGC_SWSM, swsm & ~IGC_SWSM_SMBI);
+	}
+
+	/* Initialze device specific counter of SMBI acquisition timeouts. */
+	 hw->dev_spec._82571.smb_counter = 0;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_function_pointers_82571 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void igc_init_function_pointers_82571(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_init_function_pointers_82571");
+
+	hw->mac.ops.init_params = igc_init_mac_params_82571;
+	hw->nvm.ops.init_params = igc_init_nvm_params_82571;
+	hw->phy.ops.init_params = igc_init_phy_params_82571;
+}
+
+/**
+ *  igc_get_phy_id_82571 - Retrieve the PHY ID and revision
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the PHY registers and stores the PHY ID and possibly the PHY
+ *  revision in the hardware structure.
+ **/
+STATIC s32 igc_get_phy_id_82571(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_id = 0;
+
+	DEBUGFUNC("igc_get_phy_id_82571");
+
+	switch (hw->mac.type) {
+	case igc_82571:
+	case igc_82572:
+		/* The 82571 firmware may still be configuring the PHY.
+		 * In this case, we cannot access the PHY until the
+		 * configuration is done.  So we explicitly set the
+		 * PHY ID.
+		 */
+		phy->id = IGP01IGC_I_PHY_ID;
+		break;
+	case igc_82573:
+		return igc_get_phy_id(hw);
+		break;
+	case igc_82574:
+	case igc_82583:
+		ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
+		if (ret_val)
+			return ret_val;
+
+		phy->id = (u32)(phy_id << 16);
+		usec_delay(20);
+		ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
+		if (ret_val)
+			return ret_val;
+
+		phy->id |= (u32)(phy_id);
+		phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
+		break;
+	default:
+		return -IGC_ERR_PHY;
+		break;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_get_hw_semaphore_82571 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore to access the PHY or NVM
+ **/
+STATIC s32 igc_get_hw_semaphore_82571(struct igc_hw *hw)
+{
+	u32 swsm;
+	s32 sw_timeout = hw->nvm.word_size + 1;
+	s32 fw_timeout = hw->nvm.word_size + 1;
+	s32 i = 0;
+
+	DEBUGFUNC("igc_get_hw_semaphore_82571");
+
+	/* If we have timedout 3 times on trying to acquire
+	 * the inter-port SMBI semaphore, there is old code
+	 * operating on the other port, and it is not
+	 * releasing SMBI. Modify the number of times that
+	 * we try for the semaphore to interwork with this
+	 * older code.
+	 */
+	if (hw->dev_spec._82571.smb_counter > 2)
+		sw_timeout = 1;
+
+	/* Get the SW semaphore */
+	while (i < sw_timeout) {
+		swsm = IGC_READ_REG(hw, IGC_SWSM);
+		if (!(swsm & IGC_SWSM_SMBI))
+			break;
+
+		usec_delay(50);
+		i++;
+	}
+
+	if (i == sw_timeout) {
+		DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
+		hw->dev_spec._82571.smb_counter++;
+	}
+	/* Get the FW semaphore. */
+	for (i = 0; i < fw_timeout; i++) {
+		swsm = IGC_READ_REG(hw, IGC_SWSM);
+		IGC_WRITE_REG(hw, IGC_SWSM, swsm | IGC_SWSM_SWESMBI);
+
+		/* Semaphore acquired if bit latched */
+		if (IGC_READ_REG(hw, IGC_SWSM) & IGC_SWSM_SWESMBI)
+			break;
+
+		usec_delay(50);
+	}
+
+	if (i == fw_timeout) {
+		/* Release semaphores */
+		igc_put_hw_semaphore_82571(hw);
+		DEBUGOUT("Driver can't access the NVM\n");
+		return -IGC_ERR_NVM;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_put_hw_semaphore_82571 - Release hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Release hardware semaphore used to access the PHY or NVM
+ **/
+STATIC void igc_put_hw_semaphore_82571(struct igc_hw *hw)
+{
+	u32 swsm;
+
+	DEBUGFUNC("igc_put_hw_semaphore_generic");
+
+	swsm = IGC_READ_REG(hw, IGC_SWSM);
+
+	swsm &= ~(IGC_SWSM_SMBI | IGC_SWSM_SWESMBI);
+
+	IGC_WRITE_REG(hw, IGC_SWSM, swsm);
+}
+
+/**
+ *  igc_get_hw_semaphore_82573 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore during reset.
+ *
+ **/
+STATIC s32 igc_get_hw_semaphore_82573(struct igc_hw *hw)
+{
+	u32 extcnf_ctrl;
+	s32 i = 0;
+
+	DEBUGFUNC("igc_get_hw_semaphore_82573");
+
+	extcnf_ctrl = IGC_READ_REG(hw, IGC_EXTCNF_CTRL);
+	do {
+		extcnf_ctrl |= IGC_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+		IGC_WRITE_REG(hw, IGC_EXTCNF_CTRL, extcnf_ctrl);
+		extcnf_ctrl = IGC_READ_REG(hw, IGC_EXTCNF_CTRL);
+
+		if (extcnf_ctrl & IGC_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
+			break;
+
+		msec_delay(2);
+		i++;
+	} while (i < MDIO_OWNERSHIP_TIMEOUT);
+
+	if (i == MDIO_OWNERSHIP_TIMEOUT) {
+		/* Release semaphores */
+		igc_put_hw_semaphore_82573(hw);
+		DEBUGOUT("Driver can't access the PHY\n");
+		return -IGC_ERR_PHY;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_put_hw_semaphore_82573 - Release hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Release hardware semaphore used during reset.
+ *
+ **/
+STATIC void igc_put_hw_semaphore_82573(struct igc_hw *hw)
+{
+	u32 extcnf_ctrl;
+
+	DEBUGFUNC("igc_put_hw_semaphore_82573");
+
+	extcnf_ctrl = IGC_READ_REG(hw, IGC_EXTCNF_CTRL);
+	extcnf_ctrl &= ~IGC_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+	IGC_WRITE_REG(hw, IGC_EXTCNF_CTRL, extcnf_ctrl);
+}
+
+/**
+ *  igc_get_hw_semaphore_82574 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore to access the PHY or NVM.
+ *
+ **/
+STATIC s32 igc_get_hw_semaphore_82574(struct igc_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_get_hw_semaphore_82574");
+
+	IGC_MUTEX_LOCK(&hw->dev_spec._82571.swflag_mutex);
+	ret_val = igc_get_hw_semaphore_82573(hw);
+	if (ret_val)
+		IGC_MUTEX_UNLOCK(&hw->dev_spec._82571.swflag_mutex);
+	return ret_val;
+}
+
+/**
+ *  igc_put_hw_semaphore_82574 - Release hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Release hardware semaphore used to access the PHY or NVM
+ *
+ **/
+STATIC void igc_put_hw_semaphore_82574(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_put_hw_semaphore_82574");
+
+	igc_put_hw_semaphore_82573(hw);
+	IGC_MUTEX_UNLOCK(&hw->dev_spec._82571.swflag_mutex);
+}
+
+/**
+ *  igc_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: true to enable LPLU, false to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.
+ *  LPLU will not be activated unless the
+ *  device autonegotiation advertisement meets standards of
+ *  either 10 or 10/100 or 10/100/1000 at all duplexes.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+STATIC s32 igc_set_d0_lplu_state_82574(struct igc_hw *hw, bool active)
+{
+	u32 data = IGC_READ_REG(hw, IGC_POEMB);
+
+	DEBUGFUNC("igc_set_d0_lplu_state_82574");
+
+	if (active)
+		data |= IGC_PHY_CTRL_D0A_LPLU;
+	else
+		data &= ~IGC_PHY_CTRL_D0A_LPLU;
+
+	IGC_WRITE_REG(hw, IGC_POEMB, data);
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_set_d3_lplu_state_82574 - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  when active is true, else clear lplu for D3. LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.
+ **/
+STATIC s32 igc_set_d3_lplu_state_82574(struct igc_hw *hw, bool active)
+{
+	u32 data = IGC_READ_REG(hw, IGC_POEMB);
+
+	DEBUGFUNC("igc_set_d3_lplu_state_82574");
+
+	if (!active) {
+		data &= ~IGC_PHY_CTRL_NOND0A_LPLU;
+	} else if ((hw->phy.autoneg_advertised == IGC_ALL_SPEED_DUPLEX) ||
+		   (hw->phy.autoneg_advertised == IGC_ALL_NOT_GIG) ||
+		   (hw->phy.autoneg_advertised == IGC_ALL_10_SPEED)) {
+		data |= IGC_PHY_CTRL_NOND0A_LPLU;
+	}
+
+	IGC_WRITE_REG(hw, IGC_POEMB, data);
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_acquire_nvm_82571 - Request for access to the EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  To gain access to the EEPROM, first we must obtain a hardware semaphore.
+ *  Then for non-82573 hardware, set the EEPROM access request bit and wait
+ *  for EEPROM access grant bit.  If the access grant bit is not set, release
+ *  hardware semaphore.
+ **/
+STATIC s32 igc_acquire_nvm_82571(struct igc_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_acquire_nvm_82571");
+
+	ret_val = igc_get_hw_semaphore_82571(hw);
+	if (ret_val)
+		return ret_val;
+
+	switch (hw->mac.type) {
+	case igc_82573:
+		break;
+	default:
+		ret_val = igc_acquire_nvm_generic(hw);
+		break;
+	}
+
+	if (ret_val)
+		igc_put_hw_semaphore_82571(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_release_nvm_82571 - Release exclusive access to EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
+ **/
+STATIC void igc_release_nvm_82571(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_release_nvm_82571");
+
+	igc_release_nvm_generic(hw);
+	igc_put_hw_semaphore_82571(hw);
+}
+
+/**
+ *  igc_write_nvm_82571 - Write to EEPROM using appropriate interface
+ *  @hw: pointer to the HW structure
+ *  @offset: offset within the EEPROM to be written to
+ *  @words: number of words to write
+ *  @data: 16 bit word(s) to be written to the EEPROM
+ *
+ *  For non-82573 silicon, write data to EEPROM at offset using SPI interface.
+ *
+ *  If igc_update_nvm_checksum is not called after this function, the
+ *  EEPROM will most likely contain an invalid checksum.
+ **/
+STATIC s32 igc_write_nvm_82571(struct igc_hw *hw, u16 offset, u16 words,
+				 u16 *data)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_write_nvm_82571");
+
+	switch (hw->mac.type) {
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		ret_val = igc_write_nvm_eewr_82571(hw, offset, words, data);
+		break;
+	case igc_82571:
+	case igc_82572:
+		ret_val = igc_write_nvm_spi(hw, offset, words, data);
+		break;
+	default:
+		ret_val = -IGC_ERR_NVM;
+		break;
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_update_nvm_checksum_82571 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  up to the checksum.  Then calculates the EEPROM checksum and writes the
+ *  value to the EEPROM.
+ **/
+STATIC s32 igc_update_nvm_checksum_82571(struct igc_hw *hw)
+{
+	u32 eecd;
+	s32 ret_val;
+	u16 i;
+
+	DEBUGFUNC("igc_update_nvm_checksum_82571");
+
+	ret_val = igc_update_nvm_checksum_generic(hw);
+	if (ret_val)
+		return ret_val;
+
+	/* If our nvm is an EEPROM, then we're done
+	 * otherwise, commit the checksum to the flash NVM.
+	 */
+	if (hw->nvm.type != igc_nvm_flash_hw)
+		return IGC_SUCCESS;
+
+	/* Check for pending operations. */
+	for (i = 0; i < IGC_FLASH_UPDATES; i++) {
+		msec_delay(1);
+		if (!(IGC_READ_REG(hw, IGC_EECD) & IGC_EECD_FLUPD))
+			break;
+	}
+
+	if (i == IGC_FLASH_UPDATES)
+		return -IGC_ERR_NVM;
+
+	/* Reset the firmware if using STM opcode. */
+	if ((IGC_READ_REG(hw, IGC_FLOP) & 0xFF00) == IGC_STM_OPCODE) {
+		/* The enabling of and the actual reset must be done
+		 * in two write cycles.
+		 */
+		IGC_WRITE_REG(hw, IGC_HICR, IGC_HICR_FW_RESET_ENABLE);
+		IGC_WRITE_FLUSH(hw);
+		IGC_WRITE_REG(hw, IGC_HICR, IGC_HICR_FW_RESET);
+	}
+
+	/* Commit the write to flash */
+	eecd = IGC_READ_REG(hw, IGC_EECD) | IGC_EECD_FLUPD;
+	IGC_WRITE_REG(hw, IGC_EECD, eecd);
+
+	for (i = 0; i < IGC_FLASH_UPDATES; i++) {
+		msec_delay(1);
+		if (!(IGC_READ_REG(hw, IGC_EECD) & IGC_EECD_FLUPD))
+			break;
+	}
+
+	if (i == IGC_FLASH_UPDATES)
+		return -IGC_ERR_NVM;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_validate_nvm_checksum_82571 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+STATIC s32 igc_validate_nvm_checksum_82571(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_validate_nvm_checksum_82571");
+
+	if (hw->nvm.type == igc_nvm_flash_hw)
+		igc_fix_nvm_checksum_82571(hw);
+
+	return igc_validate_nvm_checksum_generic(hw);
+}
+
+/**
+ *  igc_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon
+ *  @hw: pointer to the HW structure
+ *  @offset: offset within the EEPROM to be written to
+ *  @words: number of words to write
+ *  @data: 16 bit word(s) to be written to the EEPROM
+ *
+ *  After checking for invalid values, poll the EEPROM to ensure the previous
+ *  command has completed before trying to write the next word.  After write
+ *  poll for completion.
+ *
+ *  If igc_update_nvm_checksum is not called after this function, the
+ *  EEPROM will most likely contain an invalid checksum.
+ **/
+STATIC s32 igc_write_nvm_eewr_82571(struct igc_hw *hw, u16 offset,
+				      u16 words, u16 *data)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	u32 i, eewr = 0;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_write_nvm_eewr_82571");
+
+	/* A check for invalid values:  offset too large, too many words,
+	 * and not enough words.
+	 */
+	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+	    (words == 0)) {
+		DEBUGOUT("nvm parameter(s) out of bounds\n");
+		return -IGC_ERR_NVM;
+	}
+
+	for (i = 0; i < words; i++) {
+		eewr = ((data[i] << IGC_NVM_RW_REG_DATA) |
+			((offset + i) << IGC_NVM_RW_ADDR_SHIFT) |
+			IGC_NVM_RW_REG_START);
+
+		ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_WRITE);
+		if (ret_val)
+			break;
+
+		IGC_WRITE_REG(hw, IGC_EEWR, eewr);
+
+		ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_WRITE);
+		if (ret_val)
+			break;
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_get_cfg_done_82571 - Poll for configuration done
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the management control register for the config done bit to be set.
+ **/
+STATIC s32 igc_get_cfg_done_82571(struct igc_hw *hw)
+{
+	s32 timeout = PHY_CFG_TIMEOUT;
+
+	DEBUGFUNC("igc_get_cfg_done_82571");
+
+	while (timeout) {
+		if (IGC_READ_REG(hw, IGC_EEMNGCTL) &
+		    IGC_NVM_CFG_DONE_PORT_0)
+			break;
+		msec_delay(1);
+		timeout--;
+	}
+	if (!timeout) {
+		DEBUGOUT("MNG configuration cycle has not completed.\n");
+		return -IGC_ERR_RESET;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: true to enable LPLU, false to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.  When activating LPLU
+ *  this function also disables smart speed and vice versa.  LPLU will not be
+ *  activated unless the device autonegotiation advertisement meets standards
+ *  of either 10 or 10/100 or 10/100/1000 at all duplexes.  This is a function
+ *  pointer entry point only called by PHY setup routines.
+ **/
+STATIC s32 igc_set_d0_lplu_state_82571(struct igc_hw *hw, bool active)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+
+	DEBUGFUNC("igc_set_d0_lplu_state_82571");
+
+	if (!(phy->ops.read_reg))
+		return IGC_SUCCESS;
+
+	ret_val = phy->ops.read_reg(hw, IGP02IGC_PHY_POWER_MGMT, &data);
+	if (ret_val)
+		return ret_val;
+
+	if (active) {
+		data |= IGP02IGC_PM_D0_LPLU;
+		ret_val = phy->ops.write_reg(hw, IGP02IGC_PHY_POWER_MGMT,
+					     data);
+		if (ret_val)
+			return ret_val;
+
+		/* When LPLU is enabled, we should disable SmartSpeed */
+		ret_val = phy->ops.read_reg(hw, IGP01IGC_PHY_PORT_CONFIG,
+					    &data);
+		if (ret_val)
+			return ret_val;
+		data &= ~IGP01IGC_PSCFR_SMART_SPEED;
+		ret_val = phy->ops.write_reg(hw, IGP01IGC_PHY_PORT_CONFIG,
+					     data);
+		if (ret_val)
+			return ret_val;
+	} else {
+		data &= ~IGP02IGC_PM_D0_LPLU;
+		ret_val = phy->ops.write_reg(hw, IGP02IGC_PHY_POWER_MGMT,
+					     data);
+		/* 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.
+		 */
+		if (phy->smart_speed == igc_smart_speed_on) {
+			ret_val = phy->ops.read_reg(hw,
+						    IGP01IGC_PHY_PORT_CONFIG,
+						    &data);
+			if (ret_val)
+				return ret_val;
+
+			data |= IGP01IGC_PSCFR_SMART_SPEED;
+			ret_val = phy->ops.write_reg(hw,
+						     IGP01IGC_PHY_PORT_CONFIG,
+						     data);
+			if (ret_val)
+				return ret_val;
+		} else if (phy->smart_speed == igc_smart_speed_off) {
+			ret_val = phy->ops.read_reg(hw,
+						    IGP01IGC_PHY_PORT_CONFIG,
+						    &data);
+			if (ret_val)
+				return ret_val;
+
+			data &= ~IGP01IGC_PSCFR_SMART_SPEED;
+			ret_val = phy->ops.write_reg(hw,
+						     IGP01IGC_PHY_PORT_CONFIG,
+						     data);
+			if (ret_val)
+				return ret_val;
+		}
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_reset_hw_82571 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 igc_reset_hw_82571(struct igc_hw *hw)
+{
+	u32 ctrl, ctrl_ext, eecd, tctl;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_reset_hw_82571");
+
+	/* Prevent the PCI-E bus from sticking if there is no TLP connection
+	 * on the last TLP read/write transaction when MAC is reset.
+	 */
+	ret_val = igc_disable_pcie_master_generic(hw);
+	if (ret_val)
+		DEBUGOUT("PCI-E Master disable polling has failed.\n");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	tctl = IGC_READ_REG(hw, IGC_TCTL);
+	tctl &= ~IGC_TCTL_EN;
+	IGC_WRITE_REG(hw, IGC_TCTL, tctl);
+	IGC_WRITE_FLUSH(hw);
+
+	msec_delay(10);
+
+	/* Must acquire the MDIO ownership before MAC reset.
+	 * Ownership defaults to firmware after a reset.
+	 */
+	switch (hw->mac.type) {
+	case igc_82573:
+		ret_val = igc_get_hw_semaphore_82573(hw);
+		break;
+	case igc_82574:
+	case igc_82583:
+		ret_val = igc_get_hw_semaphore_82574(hw);
+		break;
+	default:
+		break;
+	}
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGOUT("Issuing a global reset to MAC\n");
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+
+	/* Must release MDIO ownership and mutex after MAC reset. */
+	switch (hw->mac.type) {
+	case igc_82573:
+		/* Release mutex only if the hw semaphore is acquired */
+		if (!ret_val)
+			igc_put_hw_semaphore_82573(hw);
+		break;
+	case igc_82574:
+	case igc_82583:
+		/* Release mutex only if the hw semaphore is acquired */
+		if (!ret_val)
+			igc_put_hw_semaphore_82574(hw);
+		break;
+	default:
+		break;
+	}
+
+	if (hw->nvm.type == igc_nvm_flash_hw) {
+		usec_delay(10);
+		ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+		ctrl_ext |= IGC_CTRL_EXT_EE_RST;
+		IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+		IGC_WRITE_FLUSH(hw);
+	}
+
+	ret_val = igc_get_auto_rd_done_generic(hw);
+	if (ret_val)
+		/* We don't want to continue accessing MAC registers. */
+		return ret_val;
+
+	/* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
+	 * Need to wait for Phy configuration completion before accessing
+	 * NVM and Phy.
+	 */
+
+	switch (hw->mac.type) {
+	case igc_82571:
+	case igc_82572:
+		/* REQ and GNT bits need to be cleared when using AUTO_RD
+		 * to access the EEPROM.
+		 */
+		eecd = IGC_READ_REG(hw, IGC_EECD);
+		eecd &= ~(IGC_EECD_REQ | IGC_EECD_GNT);
+		IGC_WRITE_REG(hw, IGC_EECD, eecd);
+		break;
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		msec_delay(25);
+		break;
+	default:
+		break;
+	}
+
+	/* Clear any pending interrupt events. */
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_READ_REG(hw, IGC_ICR);
+
+	if (hw->mac.type == igc_82571) {
+		/* Install any alternate MAC address into RAR0 */
+		ret_val = igc_check_alt_mac_addr_generic(hw);
+		if (ret_val)
+			return ret_val;
+
+		igc_set_laa_state_82571(hw, true);
+	}
+
+	/* Reinitialize the 82571 serdes link state machine */
+	if (hw->phy.media_type == igc_media_type_internal_serdes)
+		hw->mac.serdes_link_state = igc_serdes_link_down;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_hw_82571 - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+STATIC s32 igc_init_hw_82571(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	u32 reg_data;
+	s32 ret_val;
+	u16 i, rar_count = mac->rar_entry_count;
+
+	DEBUGFUNC("igc_init_hw_82571");
+
+	igc_initialize_hw_bits_82571(hw);
+
+	/* Initialize identification LED */
+	ret_val = mac->ops.id_led_init(hw);
+	/* An error is not fatal and we should not stop init due to this */
+	if (ret_val)
+		DEBUGOUT("Error initializing identification LED\n");
+
+	/* Disabling VLAN filtering */
+	DEBUGOUT("Initializing the IEEE VLAN\n");
+	mac->ops.clear_vfta(hw);
+
+	/* Setup the receive address.
+	 * If, however, a locally administered address was assigned to the
+	 * 82571, we must reserve a RAR for it to work around an issue where
+	 * resetting one port will reload the MAC on the other port.
+	 */
+	if (igc_get_laa_state_82571(hw))
+		rar_count--;
+	igc_init_rx_addrs_generic(hw, rar_count);
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for (i = 0; i < mac->mta_reg_count; i++)
+		IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
+
+	/* Setup link and flow control */
+	ret_val = mac->ops.setup_link(hw);
+
+	/* Set the transmit descriptor write-back policy */
+	reg_data = IGC_READ_REG(hw, IGC_TXDCTL(0));
+	reg_data = ((reg_data & ~IGC_TXDCTL_WTHRESH) |
+		    IGC_TXDCTL_FULL_TX_DESC_WB | IGC_TXDCTL_COUNT_DESC);
+	IGC_WRITE_REG(hw, IGC_TXDCTL(0), reg_data);
+
+	/* ...for both queues. */
+	switch (mac->type) {
+	case igc_82573:
+		igc_enable_tx_pkt_filtering_generic(hw);
+		/* fall through */
+	case igc_82574:
+	case igc_82583:
+		reg_data = IGC_READ_REG(hw, IGC_GCR);
+		reg_data |= IGC_GCR_L1_ACT_WITHOUT_L0S_RX;
+		IGC_WRITE_REG(hw, IGC_GCR, reg_data);
+		break;
+	default:
+		reg_data = IGC_READ_REG(hw, IGC_TXDCTL(1));
+		reg_data = ((reg_data & ~IGC_TXDCTL_WTHRESH) |
+			    IGC_TXDCTL_FULL_TX_DESC_WB |
+			    IGC_TXDCTL_COUNT_DESC);
+		IGC_WRITE_REG(hw, IGC_TXDCTL(1), reg_data);
+		break;
+	}
+
+	/* Clear all of the statistics registers (clear on read).  It is
+	 * important that we do this after we have tried to establish link
+	 * because the symbol error count will increment wildly if there
+	 * is no link.
+	 */
+	igc_clear_hw_cntrs_82571(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_initialize_hw_bits_82571 - Initialize hardware-dependent bits
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes required hardware-dependent bits needed for normal operation.
+ **/
+STATIC void igc_initialize_hw_bits_82571(struct igc_hw *hw)
+{
+	u32 reg;
+
+	DEBUGFUNC("igc_initialize_hw_bits_82571");
+
+	/* Transmit Descriptor Control 0 */
+	reg = IGC_READ_REG(hw, IGC_TXDCTL(0));
+	reg |= (1 << 22);
+	IGC_WRITE_REG(hw, IGC_TXDCTL(0), reg);
+
+	/* Transmit Descriptor Control 1 */
+	reg = IGC_READ_REG(hw, IGC_TXDCTL(1));
+	reg |= (1 << 22);
+	IGC_WRITE_REG(hw, IGC_TXDCTL(1), reg);
+
+	/* Transmit Arbitration Control 0 */
+	reg = IGC_READ_REG(hw, IGC_TARC(0));
+	reg &= ~(0xF << 27); /* 30:27 */
+	switch (hw->mac.type) {
+	case igc_82571:
+	case igc_82572:
+		reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26);
+		break;
+	case igc_82574:
+	case igc_82583:
+		reg |= (1 << 26);
+		break;
+	default:
+		break;
+	}
+	IGC_WRITE_REG(hw, IGC_TARC(0), reg);
+
+	/* Transmit Arbitration Control 1 */
+	reg = IGC_READ_REG(hw, IGC_TARC(1));
+	switch (hw->mac.type) {
+	case igc_82571:
+	case igc_82572:
+		reg &= ~((1 << 29) | (1 << 30));
+		reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26);
+		if (IGC_READ_REG(hw, IGC_TCTL) & IGC_TCTL_MULR)
+			reg &= ~(1 << 28);
+		else
+			reg |= (1 << 28);
+		IGC_WRITE_REG(hw, IGC_TARC(1), reg);
+		break;
+	default:
+		break;
+	}
+
+	/* Device Control */
+	switch (hw->mac.type) {
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		reg = IGC_READ_REG(hw, IGC_CTRL);
+		reg &= ~(1 << 29);
+		IGC_WRITE_REG(hw, IGC_CTRL, reg);
+		break;
+	default:
+		break;
+	}
+
+	/* Extended Device Control */
+	switch (hw->mac.type) {
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		reg = IGC_READ_REG(hw, IGC_CTRL_EXT);
+		reg &= ~(1 << 23);
+		reg |= (1 << 22);
+		IGC_WRITE_REG(hw, IGC_CTRL_EXT, reg);
+		break;
+	default:
+		break;
+	}
+
+	if (hw->mac.type == igc_82571) {
+		reg = IGC_READ_REG(hw, IGC_PBA_ECC);
+		reg |= IGC_PBA_ECC_CORR_EN;
+		IGC_WRITE_REG(hw, IGC_PBA_ECC, reg);
+	}
+
+	/* Workaround for hardware errata.
+	 * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572
+	 */
+	if ((hw->mac.type == igc_82571) ||
+	   (hw->mac.type == igc_82572)) {
+		reg = IGC_READ_REG(hw, IGC_CTRL_EXT);
+		reg &= ~IGC_CTRL_EXT_DMA_DYN_CLK_EN;
+		IGC_WRITE_REG(hw, IGC_CTRL_EXT, reg);
+	}
+
+	/* Disable IPv6 extension header parsing because some malformed
+	 * IPv6 headers can hang the Rx.
+	 */
+	if (hw->mac.type <= igc_82573) {
+		reg = IGC_READ_REG(hw, IGC_RFCTL);
+		reg |= (IGC_RFCTL_IPV6_EX_DIS | IGC_RFCTL_NEW_IPV6_EXT_DIS);
+		IGC_WRITE_REG(hw, IGC_RFCTL, reg);
+	}
+
+	/* PCI-Ex Control Registers */
+	switch (hw->mac.type) {
+	case igc_82574:
+	case igc_82583:
+		reg = IGC_READ_REG(hw, IGC_GCR);
+		reg |= (1 << 22);
+		IGC_WRITE_REG(hw, IGC_GCR, reg);
+
+		/* Workaround for hardware errata.
+		 * apply workaround for hardware errata documented in errata
+		 * docs Fixes issue where some error prone or unreliable PCIe
+		 * completions are occurring, particularly with ASPM enabled.
+		 * Without fix, issue can cause Tx timeouts.
+		 */
+		reg = IGC_READ_REG(hw, IGC_GCR2);
+		reg |= 1;
+		IGC_WRITE_REG(hw, IGC_GCR2, reg);
+		break;
+	default:
+		break;
+	}
+
+	return;
+}
+
+/**
+ *  igc_clear_vfta_82571 - Clear VLAN filter table
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the register array which contains the VLAN filter table by
+ *  setting all the values to 0.
+ **/
+STATIC void igc_clear_vfta_82571(struct igc_hw *hw)
+{
+	u32 offset;
+	u32 vfta_value = 0;
+	u32 vfta_offset = 0;
+	u32 vfta_bit_in_reg = 0;
+
+	DEBUGFUNC("igc_clear_vfta_82571");
+
+	switch (hw->mac.type) {
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		if (hw->mng_cookie.vlan_id != 0) {
+			/* The VFTA is a 4096b bit-field, each identifying
+			 * a single VLAN ID.  The following operations
+			 * determine which 32b entry (i.e. offset) into the
+			 * array we want to set the VLAN ID (i.e. bit) of
+			 * the manageability unit.
+			 */
+			vfta_offset = (hw->mng_cookie.vlan_id >>
+				       IGC_VFTA_ENTRY_SHIFT) &
+			    IGC_VFTA_ENTRY_MASK;
+			vfta_bit_in_reg =
+			    1 << (hw->mng_cookie.vlan_id &
+				  IGC_VFTA_ENTRY_BIT_SHIFT_MASK);
+		}
+		break;
+	default:
+		break;
+	}
+	for (offset = 0; offset < IGC_VLAN_FILTER_TBL_SIZE; offset++) {
+		/* If the offset we want to clear is the same offset of the
+		 * manageability VLAN ID, then clear all bits except that of
+		 * the manageability unit.
+		 */
+		vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
+		IGC_WRITE_REG_ARRAY(hw, IGC_VFTA, offset, vfta_value);
+		IGC_WRITE_FLUSH(hw);
+	}
+}
+
+/**
+ *  igc_check_mng_mode_82574 - Check manageability is enabled
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the NVM Initialization Control Word 2 and returns true
+ *  (>0) if any manageability is enabled, else false (0).
+ **/
+STATIC bool igc_check_mng_mode_82574(struct igc_hw *hw)
+{
+	u16 data;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_check_mng_mode_82574");
+
+	ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+	if (ret_val)
+		return false;
+
+	return (data & IGC_NVM_INIT_CTRL2_MNGM) != 0;
+}
+
+/**
+ *  igc_led_on_82574 - Turn LED on
+ *  @hw: pointer to the HW structure
+ *
+ *  Turn LED on.
+ **/
+STATIC s32 igc_led_on_82574(struct igc_hw *hw)
+{
+	u32 ctrl;
+	u32 i;
+
+	DEBUGFUNC("igc_led_on_82574");
+
+	ctrl = hw->mac.ledctl_mode2;
+	if (!(IGC_STATUS_LU & IGC_READ_REG(hw, IGC_STATUS))) {
+		/* If no link, then turn LED on by setting the invert bit
+		 * for each LED that's "on" (0x0E) in ledctl_mode2.
+		 */
+		for (i = 0; i < 4; i++)
+			if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
+			    IGC_LEDCTL_MODE_LED_ON)
+				ctrl |= (IGC_LEDCTL_LED0_IVRT << (i * 8));
+	}
+	IGC_WRITE_REG(hw, IGC_LEDCTL, ctrl);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_check_phy_82574 - check 82574 phy hung state
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns whether phy is hung or not
+ **/
+bool igc_check_phy_82574(struct igc_hw *hw)
+{
+	u16 status_1kbt = 0;
+	u16 receive_errors = 0;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_check_phy_82574");
+
+	/* Read PHY Receive Error counter first, if its is max - all F's then
+	 * read the Base1000T status register If both are max then PHY is hung.
+	 */
+	ret_val = hw->phy.ops.read_reg(hw, IGC_RECEIVE_ERROR_COUNTER,
+				       &receive_errors);
+	if (ret_val)
+		return false;
+	if (receive_errors == IGC_RECEIVE_ERROR_MAX) {
+		ret_val = hw->phy.ops.read_reg(hw, IGC_BASE1000T_STATUS,
+					       &status_1kbt);
+		if (ret_val)
+			return false;
+		if ((status_1kbt & IGC_IDLE_ERROR_COUNT_MASK) ==
+		    IGC_IDLE_ERROR_COUNT_MASK)
+			return true;
+	}
+
+	return false;
+}
+
+
+/**
+ *  igc_setup_link_82571 - Setup flow control and link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines which flow control settings to use, then configures flow
+ *  control.  Calls the appropriate media-specific link configuration
+ *  function.  Assuming the adapter has a valid link partner, a valid link
+ *  should be established.  Assumes the hardware has previously been reset
+ *  and the transmitter and receiver are not enabled.
+ **/
+STATIC s32 igc_setup_link_82571(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_setup_link_82571");
+
+	/* 82573 does not have a word in the NVM to determine
+	 * the default flow control setting, so we explicitly
+	 * set it to full.
+	 */
+	switch (hw->mac.type) {
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		if (hw->fc.requested_mode == igc_fc_default)
+			hw->fc.requested_mode = igc_fc_full;
+		break;
+	default:
+		break;
+	}
+
+	return igc_setup_link_generic(hw);
+}
+
+/**
+ *  igc_setup_copper_link_82571 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the link for auto-neg or forced speed and duplex.  Then we check
+ *  for link, once link is established calls to configure collision distance
+ *  and flow control are called.
+ **/
+STATIC s32 igc_setup_copper_link_82571(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_setup_copper_link_82571");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	ctrl |= IGC_CTRL_SLU;
+	ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	switch (hw->phy.type) {
+	case igc_phy_m88:
+	case igc_phy_bm:
+		ret_val = igc_copper_link_setup_m88(hw);
+		break;
+	case igc_phy_igp_2:
+		ret_val = igc_copper_link_setup_igp(hw);
+		break;
+	default:
+		return -IGC_ERR_PHY;
+		break;
+	}
+
+	if (ret_val)
+		return ret_val;
+
+	return igc_setup_copper_link_generic(hw);
+}
+
+/**
+ *  igc_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures collision distance and flow control for fiber and serdes links.
+ *  Upon successful setup, poll for link.
+ **/
+STATIC s32 igc_setup_fiber_serdes_link_82571(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_setup_fiber_serdes_link_82571");
+
+	switch (hw->mac.type) {
+	case igc_82571:
+	case igc_82572:
+		/* If SerDes loopback mode is entered, there is no form
+		 * of reset to take the adapter out of that mode.  So we
+		 * have to explicitly take the adapter out of loopback
+		 * mode.  This prevents drivers from twiddling their thumbs
+		 * if another tool failed to take it out of loopback mode.
+		 */
+		IGC_WRITE_REG(hw, IGC_SCTL,
+				IGC_SCTL_DISABLE_SERDES_LOOPBACK);
+		break;
+	default:
+		break;
+	}
+
+	return igc_setup_fiber_serdes_link_generic(hw);
+}
+
+/**
+ *  igc_check_for_serdes_link_82571 - Check for link (Serdes)
+ *  @hw: pointer to the HW structure
+ *
+ *  Reports the link state as up or down.
+ *
+ *  If autonegotiation is supported by the link partner, the link state is
+ *  determined by the result of autonegotiation. This is the most likely case.
+ *  If autonegotiation is not supported by the link partner, and the link
+ *  has a valid signal, force the link up.
+ *
+ *  The link state is represented internally here by 4 states:
+ *
+ *  1) down
+ *  2) autoneg_progress
+ *  3) autoneg_complete (the link successfully autonegotiated)
+ *  4) forced_up (the link has been forced up, it did not autonegotiate)
+ *
+ **/
+STATIC s32 igc_check_for_serdes_link_82571(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	u32 rxcw;
+	u32 ctrl;
+	u32 status;
+	u32 txcw;
+	u32 i;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_check_for_serdes_link_82571");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	status = IGC_READ_REG(hw, IGC_STATUS);
+	IGC_READ_REG(hw, IGC_RXCW);
+	/* SYNCH bit and IV bit are sticky */
+	usec_delay(10);
+	rxcw = IGC_READ_REG(hw, IGC_RXCW);
+
+	if ((rxcw & IGC_RXCW_SYNCH) && !(rxcw & IGC_RXCW_IV)) {
+		/* Receiver is synchronized with no invalid bits.  */
+		switch (mac->serdes_link_state) {
+		case igc_serdes_link_autoneg_complete:
+			if (!(status & IGC_STATUS_LU)) {
+				/* We have lost link, retry autoneg before
+				 * reporting link failure
+				 */
+				mac->serdes_link_state =
+				    igc_serdes_link_autoneg_progress;
+				mac->serdes_has_link = false;
+				DEBUGOUT("AN_UP     -> AN_PROG\n");
+			} else {
+				mac->serdes_has_link = true;
+			}
+			break;
+
+		case igc_serdes_link_forced_up:
+			/* If we are receiving /C/ ordered sets, re-enable
+			 * auto-negotiation in the TXCW register and disable
+			 * forced link in the Device Control register in an
+			 * attempt to auto-negotiate with our link partner.
+			 */
+			if (rxcw & IGC_RXCW_C) {
+				/* Enable autoneg, and unforce link up */
+				IGC_WRITE_REG(hw, IGC_TXCW, mac->txcw);
+				IGC_WRITE_REG(hw, IGC_CTRL,
+				    (ctrl & ~IGC_CTRL_SLU));
+				mac->serdes_link_state =
+				    igc_serdes_link_autoneg_progress;
+				mac->serdes_has_link = false;
+				DEBUGOUT("FORCED_UP -> AN_PROG\n");
+			} else {
+				mac->serdes_has_link = true;
+			}
+			break;
+
+		case igc_serdes_link_autoneg_progress:
+			if (rxcw & IGC_RXCW_C) {
+				/* We received /C/ ordered sets, meaning the
+				 * link partner has autonegotiated, and we can
+				 * trust the Link Up (LU) status bit.
+				 */
+				if (status & IGC_STATUS_LU) {
+					mac->serdes_link_state =
+					    igc_serdes_link_autoneg_complete;
+					DEBUGOUT("AN_PROG   -> AN_UP\n");
+					mac->serdes_has_link = true;
+				} else {
+					/* Autoneg completed, but failed. */
+					mac->serdes_link_state =
+					    igc_serdes_link_down;
+					DEBUGOUT("AN_PROG   -> DOWN\n");
+				}
+			} else {
+				/* The link partner did not autoneg.
+				 * Force link up and full duplex, and change
+				 * state to forced.
+				 */
+				IGC_WRITE_REG(hw, IGC_TXCW,
+				(mac->txcw & ~IGC_TXCW_ANE));
+				ctrl |= (IGC_CTRL_SLU | IGC_CTRL_FD);
+				IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+				/* Configure Flow Control after link up. */
+				ret_val =
+				    igc_config_fc_after_link_up_generic(hw);
+				if (ret_val) {
+					DEBUGOUT("Error config flow control\n");
+					break;
+				}
+				mac->serdes_link_state =
+						igc_serdes_link_forced_up;
+				mac->serdes_has_link = true;
+				DEBUGOUT("AN_PROG   -> FORCED_UP\n");
+			}
+			break;
+
+		case igc_serdes_link_down:
+		default:
+			/* The link was down but the receiver has now gained
+			 * valid sync, so lets see if we can bring the link
+			 * up.
+			 */
+			IGC_WRITE_REG(hw, IGC_TXCW, mac->txcw);
+			IGC_WRITE_REG(hw, IGC_CTRL, (ctrl &
+					~IGC_CTRL_SLU));
+			mac->serdes_link_state =
+					igc_serdes_link_autoneg_progress;
+			mac->serdes_has_link = false;
+			DEBUGOUT("DOWN      -> AN_PROG\n");
+			break;
+		}
+	} else {
+		if (!(rxcw & IGC_RXCW_SYNCH)) {
+			mac->serdes_has_link = false;
+			mac->serdes_link_state = igc_serdes_link_down;
+			DEBUGOUT("ANYSTATE  -> DOWN\n");
+		} else {
+			/* Check several times, if SYNCH bit and CONFIG
+			 * bit both are consistently 1 then simply ignore
+			 * the IV bit and restart Autoneg
+			 */
+			for (i = 0; i < AN_RETRY_COUNT; i++) {
+				usec_delay(10);
+				rxcw = IGC_READ_REG(hw, IGC_RXCW);
+				if ((rxcw & IGC_RXCW_SYNCH) &&
+				    (rxcw & IGC_RXCW_C))
+					continue;
+
+				if (rxcw & IGC_RXCW_IV) {
+					mac->serdes_has_link = false;
+					mac->serdes_link_state =
+							igc_serdes_link_down;
+					DEBUGOUT("ANYSTATE  -> DOWN\n");
+					break;
+				}
+			}
+
+			if (i == AN_RETRY_COUNT) {
+				txcw = IGC_READ_REG(hw, IGC_TXCW);
+				txcw |= IGC_TXCW_ANE;
+				IGC_WRITE_REG(hw, IGC_TXCW, txcw);
+				mac->serdes_link_state =
+					igc_serdes_link_autoneg_progress;
+				mac->serdes_has_link = false;
+				DEBUGOUT("ANYSTATE  -> AN_PROG\n");
+			}
+		}
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_valid_led_default_82571 - Verify a valid default LED config
+ *  @hw: pointer to the HW structure
+ *  @data: pointer to the NVM (EEPROM)
+ *
+ *  Read the EEPROM for the current default LED configuration.  If the
+ *  LED configuration is not valid, set to a valid LED configuration.
+ **/
+STATIC s32 igc_valid_led_default_82571(struct igc_hw *hw, u16 *data)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_valid_led_default_82571");
+
+	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		return ret_val;
+	}
+
+	switch (hw->mac.type) {
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		if (*data == ID_LED_RESERVED_F746)
+			*data = ID_LED_DEFAULT_82573;
+		break;
+	default:
+		if (*data == ID_LED_RESERVED_0000 ||
+		    *data == ID_LED_RESERVED_FFFF)
+			*data = ID_LED_DEFAULT;
+		break;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_get_laa_state_82571 - Get locally administered address state
+ *  @hw: pointer to the HW structure
+ *
+ *  Retrieve and return the current locally administered address state.
+ **/
+bool igc_get_laa_state_82571(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_get_laa_state_82571");
+
+	if (hw->mac.type != igc_82571)
+		return false;
+
+	return hw->dev_spec._82571.laa_is_present;
+}
+
+/**
+ *  igc_set_laa_state_82571 - Set locally administered address state
+ *  @hw: pointer to the HW structure
+ *  @state: enable/disable locally administered address
+ *
+ *  Enable/Disable the current locally administered address state.
+ **/
+void igc_set_laa_state_82571(struct igc_hw *hw, bool state)
+{
+	DEBUGFUNC("igc_set_laa_state_82571");
+
+	if (hw->mac.type != igc_82571)
+		return;
+
+	hw->dev_spec._82571.laa_is_present = state;
+
+	/* If workaround is activated... */
+	if (state)
+		/* Hold a copy of the LAA in RAR[14] This is done so that
+		 * between the time RAR[0] gets clobbered and the time it
+		 * gets fixed, the actual LAA is in one of the RARs and no
+		 * incoming packets directed to this port are dropped.
+		 * Eventually the LAA will be in RAR[0] and RAR[14].
+		 */
+		hw->mac.ops.rar_set(hw, hw->mac.addr,
+				    hw->mac.rar_entry_count - 1);
+	return;
+}
+
+/**
+ *  igc_fix_nvm_checksum_82571 - Fix EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Verifies that the EEPROM has completed the update.  After updating the
+ *  EEPROM, we need to check bit 15 in work 0x23 for the checksum fix.  If
+ *  the checksum fix is not implemented, we need to set the bit and update
+ *  the checksum.  Otherwise, if bit 15 is set and the checksum is incorrect,
+ *  we need to return bad checksum.
+ **/
+STATIC s32 igc_fix_nvm_checksum_82571(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	s32 ret_val;
+	u16 data;
+
+	DEBUGFUNC("igc_fix_nvm_checksum_82571");
+
+	if (nvm->type != igc_nvm_flash_hw)
+		return IGC_SUCCESS;
+
+	/* Check bit 4 of word 10h.  If it is 0, firmware is done updating
+	 * 10h-12h.  Checksum may need to be fixed.
+	 */
+	ret_val = nvm->ops.read(hw, 0x10, 1, &data);
+	if (ret_val)
+		return ret_val;
+
+	if (!(data & 0x10)) {
+		/* Read 0x23 and check bit 15.  This bit is a 1
+		 * when the checksum has already been fixed.  If
+		 * the checksum is still wrong and this bit is a
+		 * 1, we need to return bad checksum.  Otherwise,
+		 * we need to set this bit to a 1 and update the
+		 * checksum.
+		 */
+		ret_val = nvm->ops.read(hw, 0x23, 1, &data);
+		if (ret_val)
+			return ret_val;
+
+		if (!(data & 0x8000)) {
+			data |= 0x8000;
+			ret_val = nvm->ops.write(hw, 0x23, 1, &data);
+			if (ret_val)
+				return ret_val;
+			ret_val = nvm->ops.update(hw);
+			if (ret_val)
+				return ret_val;
+		}
+	}
+
+	return IGC_SUCCESS;
+}
+
+
+/**
+ *  igc_read_mac_addr_82571 - Read device MAC address
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_read_mac_addr_82571(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_read_mac_addr_82571");
+
+	if (hw->mac.type == igc_82571) {
+		s32 ret_val;
+
+		/* If there's an alternate MAC address place it in RAR0
+		 * so that it will override the Si installed default perm
+		 * address.
+		 */
+		ret_val = igc_check_alt_mac_addr_generic(hw);
+		if (ret_val)
+			return ret_val;
+	}
+
+	return igc_read_mac_addr_generic(hw);
+}
+
+/**
+ * igc_power_down_phy_copper_82571 - Remove link during PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+STATIC void igc_power_down_phy_copper_82571(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	struct igc_mac_info *mac = &hw->mac;
+
+	if (!phy->ops.check_reset_block)
+		return;
+
+	/* If the management interface is not enabled, then power down */
+	if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw)))
+		igc_power_down_phy_copper(hw);
+
+	return;
+}
+
+/**
+ *  igc_clear_hw_cntrs_82571 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+STATIC void igc_clear_hw_cntrs_82571(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_clear_hw_cntrs_82571");
+
+	igc_clear_hw_cntrs_base_generic(hw);
+
+	IGC_READ_REG(hw, IGC_PRC64);
+	IGC_READ_REG(hw, IGC_PRC127);
+	IGC_READ_REG(hw, IGC_PRC255);
+	IGC_READ_REG(hw, IGC_PRC511);
+	IGC_READ_REG(hw, IGC_PRC1023);
+	IGC_READ_REG(hw, IGC_PRC1522);
+	IGC_READ_REG(hw, IGC_PTC64);
+	IGC_READ_REG(hw, IGC_PTC127);
+	IGC_READ_REG(hw, IGC_PTC255);
+	IGC_READ_REG(hw, IGC_PTC511);
+	IGC_READ_REG(hw, IGC_PTC1023);
+	IGC_READ_REG(hw, IGC_PTC1522);
+
+	IGC_READ_REG(hw, IGC_ALGNERRC);
+	IGC_READ_REG(hw, IGC_RXERRC);
+	IGC_READ_REG(hw, IGC_TNCRS);
+	IGC_READ_REG(hw, IGC_CEXTERR);
+	IGC_READ_REG(hw, IGC_TSCTC);
+	IGC_READ_REG(hw, IGC_TSCTFC);
+
+	IGC_READ_REG(hw, IGC_MGTPRC);
+	IGC_READ_REG(hw, IGC_MGTPDC);
+	IGC_READ_REG(hw, IGC_MGTPTC);
+
+	IGC_READ_REG(hw, IGC_IAC);
+	IGC_READ_REG(hw, IGC_ICRXOC);
+
+	IGC_READ_REG(hw, IGC_ICRXPTC);
+	IGC_READ_REG(hw, IGC_ICRXATC);
+	IGC_READ_REG(hw, IGC_ICTXPTC);
+	IGC_READ_REG(hw, IGC_ICTXATC);
+	IGC_READ_REG(hw, IGC_ICTXQEC);
+	IGC_READ_REG(hw, IGC_ICTXQMTC);
+	IGC_READ_REG(hw, IGC_ICRXDMTC);
+}
diff --git a/drivers/net/igc/base/e1000_82571.h b/drivers/net/igc/base/e1000_82571.h
new file mode 100644
index 0000000..6d1f8ac
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82571.h
@@ -0,0 +1,36 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_82571_H_
+#define _IGC_82571_H_
+
+#define ID_LED_RESERVED_F746	0xF746
+#define ID_LED_DEFAULT_82573	((ID_LED_DEF1_DEF2 << 12) | \
+				 (ID_LED_OFF1_ON2  <<  8) | \
+				 (ID_LED_DEF1_DEF2 <<  4) | \
+				 (ID_LED_DEF1_DEF2))
+
+#define IGC_GCR_L1_ACT_WITHOUT_L0S_RX	0x08000000
+#define AN_RETRY_COUNT		5 /* Autoneg Retry Count value */
+
+/* Intr Throttling - RW */
+#define IGC_EITR_82574(_n)	(0x000E8 + (0x4 * (_n)))
+
+#define IGC_EIAC_82574	0x000DC /* Ext. Interrupt Auto Clear - RW */
+#define IGC_EIAC_MASK_82574	0x01F00000
+
+#define IGC_IVAR_INT_ALLOC_VALID	0x8
+
+/* Manageability Operation Mode mask */
+#define IGC_NVM_INIT_CTRL2_MNGM	0x6000
+
+#define IGC_BASE1000T_STATUS		10
+#define IGC_IDLE_ERROR_COUNT_MASK	0xFF
+#define IGC_RECEIVE_ERROR_COUNTER	21
+#define IGC_RECEIVE_ERROR_MAX		0xFFFF
+bool igc_check_phy_82574(struct igc_hw *hw);
+bool igc_get_laa_state_82571(struct igc_hw *hw);
+void igc_set_laa_state_82571(struct igc_hw *hw, bool state);
+
+#endif
diff --git a/drivers/net/igc/base/e1000_82575.c b/drivers/net/igc/base/e1000_82575.c
new file mode 100644
index 0000000..c4650ff
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82575.c
@@ -0,0 +1,3586 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+/*
+ * 82575EB Gigabit Network Connection
+ * 82575EB Gigabit Backplane Connection
+ * 82575GB Gigabit Network Connection
+ * 82576 Gigabit Network Connection
+ * 82576 Quad Port Gigabit Mezzanine Adapter
+ * 82580 Gigabit Network Connection
+ * I350 Gigabit Network Connection
+ */
+
+#include "e1000_api.h"
+#include "e1000_i210.h"
+#include "e1000_i225.h"
+
+STATIC s32  igc_init_phy_params_82575(struct igc_hw *hw);
+STATIC s32  igc_init_mac_params_82575(struct igc_hw *hw);
+STATIC s32  igc_acquire_nvm_82575(struct igc_hw *hw);
+STATIC void igc_release_nvm_82575(struct igc_hw *hw);
+STATIC s32  igc_check_for_link_82575(struct igc_hw *hw);
+STATIC s32  igc_check_for_link_media_swap(struct igc_hw *hw);
+STATIC s32  igc_get_cfg_done_82575(struct igc_hw *hw);
+STATIC s32  igc_get_link_up_info_82575(struct igc_hw *hw, u16 *speed,
+					 u16 *duplex);
+STATIC s32  igc_phy_hw_reset_sgmii_82575(struct igc_hw *hw);
+STATIC s32  igc_read_phy_reg_sgmii_82575(struct igc_hw *hw, u32 offset,
+					   u16 *data);
+STATIC s32  igc_reset_hw_82575(struct igc_hw *hw);
+STATIC s32 igc_init_hw_82575(struct igc_hw *hw);
+STATIC s32  igc_reset_hw_82580(struct igc_hw *hw);
+STATIC s32  igc_read_phy_reg_82580(struct igc_hw *hw,
+				     u32 offset, u16 *data);
+STATIC s32  igc_write_phy_reg_82580(struct igc_hw *hw,
+				      u32 offset, u16 data);
+STATIC s32  igc_set_d0_lplu_state_82580(struct igc_hw *hw,
+					  bool active);
+STATIC s32  igc_set_d3_lplu_state_82580(struct igc_hw *hw,
+					  bool active);
+STATIC s32  igc_set_d0_lplu_state_82575(struct igc_hw *hw,
+					  bool active);
+STATIC s32  igc_setup_copper_link_82575(struct igc_hw *hw);
+STATIC s32  igc_setup_serdes_link_82575(struct igc_hw *hw);
+STATIC s32  igc_get_media_type_82575(struct igc_hw *hw);
+STATIC s32  igc_set_sfp_media_type_82575(struct igc_hw *hw);
+STATIC s32  igc_valid_led_default_82575(struct igc_hw *hw, u16 *data);
+STATIC s32  igc_write_phy_reg_sgmii_82575(struct igc_hw *hw,
+					    u32 offset, u16 data);
+STATIC void igc_clear_hw_cntrs_82575(struct igc_hw *hw);
+STATIC s32  igc_acquire_swfw_sync_82575(struct igc_hw *hw, u16 mask);
+STATIC s32  igc_get_pcs_speed_and_duplex_82575(struct igc_hw *hw,
+						 u16 *speed, u16 *duplex);
+STATIC s32  igc_get_phy_id_82575(struct igc_hw *hw);
+STATIC void igc_release_swfw_sync_82575(struct igc_hw *hw, u16 mask);
+STATIC bool igc_sgmii_active_82575(struct igc_hw *hw);
+STATIC s32  igc_read_mac_addr_82575(struct igc_hw *hw);
+STATIC void igc_config_collision_dist_82575(struct igc_hw *hw);
+STATIC void igc_shutdown_serdes_link_82575(struct igc_hw *hw);
+STATIC void igc_power_up_serdes_link_82575(struct igc_hw *hw);
+STATIC s32 igc_set_pcie_completion_timeout(struct igc_hw *hw);
+STATIC s32 igc_reset_mdicnfg_82580(struct igc_hw *hw);
+STATIC s32 igc_validate_nvm_checksum_82580(struct igc_hw *hw);
+STATIC s32 igc_update_nvm_checksum_82580(struct igc_hw *hw);
+STATIC s32 igc_update_nvm_checksum_with_offset(struct igc_hw *hw,
+						 u16 offset);
+STATIC s32 igc_validate_nvm_checksum_with_offset(struct igc_hw *hw,
+						   u16 offset);
+STATIC s32 igc_validate_nvm_checksum_i350(struct igc_hw *hw);
+STATIC s32 igc_update_nvm_checksum_i350(struct igc_hw *hw);
+STATIC void igc_clear_vfta_i350(struct igc_hw *hw);
+
+STATIC void igc_i2c_start(struct igc_hw *hw);
+STATIC void igc_i2c_stop(struct igc_hw *hw);
+STATIC void igc_clock_in_i2c_byte(struct igc_hw *hw, u8 *data);
+STATIC s32 igc_clock_out_i2c_byte(struct igc_hw *hw, u8 data);
+STATIC s32 igc_get_i2c_ack(struct igc_hw *hw);
+STATIC void igc_clock_in_i2c_bit(struct igc_hw *hw, bool *data);
+STATIC s32 igc_clock_out_i2c_bit(struct igc_hw *hw, bool data);
+STATIC void igc_raise_i2c_clk(struct igc_hw *hw, u32 *i2cctl);
+STATIC void igc_lower_i2c_clk(struct igc_hw *hw, u32 *i2cctl);
+STATIC s32 igc_set_i2c_data(struct igc_hw *hw, u32 *i2cctl, bool data);
+STATIC bool igc_get_i2c_data(u32 *i2cctl);
+
+STATIC const u16 igc_82580_rxpbs_table[] = {
+	36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 };
+#define IGC_82580_RXPBS_TABLE_SIZE \
+	(sizeof(igc_82580_rxpbs_table) / \
+	 sizeof(igc_82580_rxpbs_table[0]))
+
+
+/**
+ *  igc_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to determine if the I2C pins are being used for I2C or as an
+ *  external MDIO interface since the two options are mutually exclusive.
+ **/
+STATIC bool igc_sgmii_uses_mdio_82575(struct igc_hw *hw)
+{
+	u32 reg = 0;
+	bool ext_mdio = false;
+
+	DEBUGFUNC("igc_sgmii_uses_mdio_82575");
+
+	switch (hw->mac.type) {
+	case igc_82575:
+	case igc_82576:
+		reg = IGC_READ_REG(hw, IGC_MDIC);
+		ext_mdio = !!(reg & IGC_MDIC_DEST);
+		break;
+	case igc_82580:
+	case igc_i350:
+	case igc_i354:
+	case igc_i210:
+	case igc_i211:
+		reg = IGC_READ_REG(hw, IGC_MDICNFG);
+		ext_mdio = !!(reg & IGC_MDICNFG_EXT_MDIO);
+		break;
+	default:
+		break;
+	}
+	return ext_mdio;
+}
+
+/**
+ * igc_init_phy_params_82575 - Initialize PHY function ptrs
+ * @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_phy_params_82575(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+	u32 ctrl_ext;
+
+	DEBUGFUNC("igc_init_phy_params_82575");
+
+	phy->ops.read_i2c_byte = igc_read_i2c_byte_generic;
+	phy->ops.write_i2c_byte = igc_write_i2c_byte_generic;
+
+	if (hw->phy.media_type != igc_media_type_copper) {
+		phy->type = igc_phy_none;
+		goto out;
+	}
+
+	phy->ops.power_up	= igc_power_up_phy_copper;
+	phy->ops.power_down	= igc_power_down_phy_copper_base;
+
+	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+	phy->reset_delay_us	= 100;
+
+	phy->ops.acquire	= igc_acquire_phy_base;
+	phy->ops.check_reset_block = igc_check_reset_block_generic;
+	phy->ops.commit		= igc_phy_sw_reset_generic;
+	phy->ops.get_cfg_done	= igc_get_cfg_done_82575;
+	phy->ops.release	= igc_release_phy_base;
+
+	ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+
+	if (igc_sgmii_active_82575(hw)) {
+		phy->ops.reset = igc_phy_hw_reset_sgmii_82575;
+		ctrl_ext |= IGC_CTRL_I2C_ENA;
+	} else {
+		phy->ops.reset = igc_phy_hw_reset_generic;
+		ctrl_ext &= ~IGC_CTRL_I2C_ENA;
+	}
+
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+	igc_reset_mdicnfg_82580(hw);
+
+	if (igc_sgmii_active_82575(hw) && !igc_sgmii_uses_mdio_82575(hw)) {
+		phy->ops.read_reg = igc_read_phy_reg_sgmii_82575;
+		phy->ops.write_reg = igc_write_phy_reg_sgmii_82575;
+	} else {
+		switch (hw->mac.type) {
+		case igc_82580:
+		case igc_i350:
+		case igc_i354:
+			phy->ops.read_reg = igc_read_phy_reg_82580;
+			phy->ops.write_reg = igc_write_phy_reg_82580;
+			break;
+		case igc_i210:
+		case igc_i211:
+			phy->ops.read_reg = igc_read_phy_reg_gs40g;
+			phy->ops.write_reg = igc_write_phy_reg_gs40g;
+			break;
+		default:
+			phy->ops.read_reg = igc_read_phy_reg_igp;
+			phy->ops.write_reg = igc_write_phy_reg_igp;
+		}
+	}
+
+	/* Set phy->phy_addr and phy->id. */
+	ret_val = igc_get_phy_id_82575(hw);
+
+	/* Verify phy id and set remaining function pointers */
+	switch (phy->id) {
+	case M88E1543_E_PHY_ID:
+	case M88E1512_E_PHY_ID:
+	case I347AT4_E_PHY_ID:
+	case M88E1112_E_PHY_ID:
+	case M88E1340M_E_PHY_ID:
+		phy->type		= igc_phy_m88;
+		phy->ops.check_polarity	= igc_check_polarity_m88;
+		phy->ops.get_info	= igc_get_phy_info_m88;
+		phy->ops.get_cable_length = igc_get_cable_length_m88_gen2;
+		phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_m88;
+		break;
+	case M88E1111_I_PHY_ID:
+		phy->type		= igc_phy_m88;
+		phy->ops.check_polarity	= igc_check_polarity_m88;
+		phy->ops.get_info	= igc_get_phy_info_m88;
+		phy->ops.get_cable_length = igc_get_cable_length_m88;
+		phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_m88;
+		break;
+	case IGP03IGC_E_PHY_ID:
+	case IGP04IGC_E_PHY_ID:
+		phy->type		= igc_phy_igp_3;
+		phy->ops.check_polarity	= igc_check_polarity_igp;
+		phy->ops.get_info	= igc_get_phy_info_igp;
+		phy->ops.get_cable_length = igc_get_cable_length_igp_2;
+		phy->ops.set_d0_lplu_state = igc_set_d0_lplu_state_82575;
+		phy->ops.set_d3_lplu_state = igc_set_d3_lplu_state_generic;
+		phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_igp;
+		break;
+	case I82580_I_PHY_ID:
+	case I350_I_PHY_ID:
+		phy->type		= igc_phy_82580;
+		phy->ops.check_polarity	= igc_check_polarity_82577;
+		phy->ops.get_info	= igc_get_phy_info_82577;
+		phy->ops.get_cable_length = igc_get_cable_length_82577;
+		phy->ops.set_d0_lplu_state = igc_set_d0_lplu_state_82580;
+		phy->ops.set_d3_lplu_state = igc_set_d3_lplu_state_82580;
+		phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_82577;
+		break;
+	case I210_I_PHY_ID:
+		phy->type		= igc_phy_i210;
+		phy->ops.check_polarity	= igc_check_polarity_m88;
+		phy->ops.get_info	= igc_get_phy_info_m88;
+		phy->ops.get_cable_length = igc_get_cable_length_m88_gen2;
+		phy->ops.set_d0_lplu_state = igc_set_d0_lplu_state_82580;
+		phy->ops.set_d3_lplu_state = igc_set_d3_lplu_state_82580;
+		phy->ops.force_speed_duplex = igc_phy_force_speed_duplex_m88;
+		break;
+	default:
+		ret_val = -IGC_ERR_PHY;
+		goto out;
+	}
+
+	/* Check if this PHY is configured for media swap. */
+	switch (phy->id) {
+	case M88E1112_E_PHY_ID:
+	{
+		u16 data;
+
+		ret_val = phy->ops.write_reg(hw, IGC_M88E1112_PAGE_ADDR, 2);
+		if (ret_val)
+			goto out;
+		ret_val = phy->ops.read_reg(hw, IGC_M88E1112_MAC_CTRL_1,
+					    &data);
+		if (ret_val)
+			goto out;
+
+		data = (data & IGC_M88E1112_MAC_CTRL_1_MODE_MASK) >>
+			IGC_M88E1112_MAC_CTRL_1_MODE_SHIFT;
+		if (data == IGC_M88E1112_AUTO_COPPER_SGMII ||
+		    data == IGC_M88E1112_AUTO_COPPER_BASEX)
+			hw->mac.ops.check_for_link =
+						igc_check_for_link_media_swap;
+		break;
+	}
+	case M88E1512_E_PHY_ID:
+	{
+		ret_val = igc_initialize_M88E1512_phy(hw);
+		break;
+	}
+	case M88E1543_E_PHY_ID:
+	{
+		ret_val = igc_initialize_M88E1543_phy(hw);
+		break;
+	}
+	default:
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+
+/**
+ * igc_init_mac_params_82575 - Initialize MAC function ptrs
+ * @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_mac_params_82575(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	struct igc_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+
+	DEBUGFUNC("igc_init_mac_params_82575");
+
+	/* Initialize function pointer */
+	igc_init_mac_ops_generic(hw);
+
+	/* Derives media type */
+	igc_get_media_type_82575(hw);
+	/* Set MTA register count */
+	mac->mta_reg_count = 128;
+	/* Set UTA register count */
+	mac->uta_reg_count = (hw->mac.type == igc_82575) ? 0 : 128;
+	/* Set RAR entry count */
+	mac->rar_entry_count = IGC_RAR_ENTRIES_82575;
+	if (mac->type == igc_82576)
+		mac->rar_entry_count = IGC_RAR_ENTRIES_82576;
+	if (mac->type == igc_82580)
+		mac->rar_entry_count = IGC_RAR_ENTRIES_82580;
+	if (mac->type == igc_i350 || mac->type == igc_i354)
+		mac->rar_entry_count = IGC_RAR_ENTRIES_I350;
+
+	/* Enable EEE default settings for EEE supported devices */
+	if (mac->type >= igc_i350)
+		dev_spec->eee_disable = false;
+
+	/* Allow a single clear of the SW semaphore on I210 and newer */
+	if (mac->type >= igc_i210)
+		dev_spec->clear_semaphore_once = true;
+
+	/* Set if part includes ASF firmware */
+	mac->asf_firmware_present = true;
+	/* FWSM register */
+	mac->has_fwsm = true;
+	/* ARC supported; valid only if manageability features are enabled. */
+	mac->arc_subsystem_valid =
+		!!(IGC_READ_REG(hw, IGC_FWSM) & IGC_FWSM_MODE_MASK);
+
+	/* Function pointers */
+
+	/* bus type/speed/width */
+	mac->ops.get_bus_info = igc_get_bus_info_pcie_generic;
+	/* reset */
+	if (mac->type >= igc_82580)
+		mac->ops.reset_hw = igc_reset_hw_82580;
+	else
+		mac->ops.reset_hw = igc_reset_hw_82575;
+	/* HW initialization */
+	if (mac->type == igc_i210 || mac->type == igc_i211)
+		mac->ops.init_hw = igc_init_hw_i210;
+	else
+		mac->ops.init_hw = igc_init_hw_82575;
+	/* link setup */
+	mac->ops.setup_link = igc_setup_link_generic;
+	/* physical interface link setup */
+	mac->ops.setup_physical_interface =
+		(hw->phy.media_type == igc_media_type_copper)
+		? igc_setup_copper_link_82575 : igc_setup_serdes_link_82575;
+	/* physical interface shutdown */
+	mac->ops.shutdown_serdes = igc_shutdown_serdes_link_82575;
+	/* physical interface power up */
+	mac->ops.power_up_serdes = igc_power_up_serdes_link_82575;
+	/* check for link */
+	mac->ops.check_for_link = igc_check_for_link_82575;
+	/* read mac address */
+	mac->ops.read_mac_addr = igc_read_mac_addr_82575;
+	/* configure collision distance */
+	mac->ops.config_collision_dist = igc_config_collision_dist_82575;
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
+	if (hw->mac.type == igc_i350 || mac->type == igc_i354) {
+		/* writing VFTA */
+		mac->ops.write_vfta = igc_write_vfta_i350;
+		/* clearing VFTA */
+		mac->ops.clear_vfta = igc_clear_vfta_i350;
+	} else {
+		/* writing VFTA */
+		mac->ops.write_vfta = igc_write_vfta_generic;
+		/* clearing VFTA */
+		mac->ops.clear_vfta = igc_clear_vfta_generic;
+	}
+	if (hw->mac.type >= igc_82580)
+		mac->ops.validate_mdi_setting =
+			igc_validate_mdi_setting_crossover_generic;
+	/* ID LED init */
+	mac->ops.id_led_init = igc_id_led_init_generic;
+	/* blink LED */
+	mac->ops.blink_led = igc_blink_led_generic;
+	/* setup LED */
+	mac->ops.setup_led = igc_setup_led_generic;
+	/* cleanup LED */
+	mac->ops.cleanup_led = igc_cleanup_led_generic;
+	/* turn on/off LED */
+	mac->ops.led_on = igc_led_on_generic;
+	mac->ops.led_off = igc_led_off_generic;
+	/* clear hardware counters */
+	mac->ops.clear_hw_cntrs = igc_clear_hw_cntrs_82575;
+	/* link info */
+	mac->ops.get_link_up_info = igc_get_link_up_info_82575;
+	/* acquire SW_FW sync */
+	mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_82575;
+	/* release SW_FW sync */
+	mac->ops.release_swfw_sync = igc_release_swfw_sync_82575;
+	if (mac->type == igc_i210 || mac->type == igc_i211) {
+		mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i210;
+		mac->ops.release_swfw_sync = igc_release_swfw_sync_i210;
+	}
+
+	/* set lan id for port to determine which phy lock to use */
+	hw->mac.ops.set_lan_id(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ * igc_init_nvm_params_82575 - Initialize NVM function ptrs
+ * @hw: pointer to the HW structure
+ **/
+s32 igc_init_nvm_params_82575(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	u32 eecd = IGC_READ_REG(hw, IGC_EECD);
+	u16 size;
+
+	DEBUGFUNC("igc_init_nvm_params_82575");
+
+	size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
+		     IGC_EECD_SIZE_EX_SHIFT);
+	/* Added to a constant, "size" becomes the left-shift value
+	 * for setting word_size.
+	 */
+	size += NVM_WORD_SIZE_BASE_SHIFT;
+
+	/* Just in case size is out of range, cap it to the largest
+	 * EEPROM size supported
+	 */
+	if (size > 15)
+		size = 15;
+
+	nvm->word_size = 1 << size;
+	if (hw->mac.type < igc_i210) {
+		nvm->opcode_bits = 8;
+		nvm->delay_usec = 1;
+
+		switch (nvm->override) {
+		case igc_nvm_override_spi_large:
+			nvm->page_size = 32;
+			nvm->address_bits = 16;
+			break;
+		case igc_nvm_override_spi_small:
+			nvm->page_size = 8;
+			nvm->address_bits = 8;
+			break;
+		default:
+			nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
+			nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
+					    16 : 8;
+			break;
+		}
+		if (nvm->word_size == (1 << 15))
+			nvm->page_size = 128;
+
+		nvm->type = igc_nvm_eeprom_spi;
+	} else {
+		nvm->type = igc_nvm_flash_hw;
+	}
+
+	/* Function Pointers */
+	nvm->ops.acquire = igc_acquire_nvm_82575;
+	nvm->ops.release = igc_release_nvm_82575;
+	if (nvm->word_size < (1 << 15))
+		nvm->ops.read = igc_read_nvm_eerd;
+	else
+		nvm->ops.read = igc_read_nvm_spi;
+
+	nvm->ops.write = igc_write_nvm_spi;
+	nvm->ops.validate = igc_validate_nvm_checksum_generic;
+	nvm->ops.update = igc_update_nvm_checksum_generic;
+	nvm->ops.valid_led_default = igc_valid_led_default_82575;
+
+	/* override generic family function pointers for specific descendants */
+	switch (hw->mac.type) {
+	case igc_82580:
+		nvm->ops.validate = igc_validate_nvm_checksum_82580;
+		nvm->ops.update = igc_update_nvm_checksum_82580;
+		break;
+	case igc_i350:
+		nvm->ops.validate = igc_validate_nvm_checksum_i350;
+		nvm->ops.update = igc_update_nvm_checksum_i350;
+		break;
+	default:
+		break;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_function_pointers_82575 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void igc_init_function_pointers_82575(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_init_function_pointers_82575");
+
+	hw->mac.ops.init_params = igc_init_mac_params_82575;
+	hw->nvm.ops.init_params = igc_init_nvm_params_82575;
+	hw->phy.ops.init_params = igc_init_phy_params_82575;
+	hw->mbx.ops.init_params = igc_init_mbx_params_pf;
+}
+
+/**
+ *  igc_read_phy_reg_sgmii_82575 - Read PHY register using sgmii
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY register at offset using the serial gigabit media independent
+ *  interface and stores the retrieved information in data.
+ **/
+STATIC s32 igc_read_phy_reg_sgmii_82575(struct igc_hw *hw, u32 offset,
+					  u16 *data)
+{
+	s32 ret_val = -IGC_ERR_PARAM;
+
+	DEBUGFUNC("igc_read_phy_reg_sgmii_82575");
+
+	if (offset > IGC_MAX_SGMII_PHY_REG_ADDR) {
+		DEBUGOUT1("PHY Address %u is out of range\n", offset);
+		goto out;
+	}
+
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igc_read_phy_reg_i2c(hw, offset, data);
+
+	hw->phy.ops.release(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_write_phy_reg_sgmii_82575 - Write PHY register using sgmii
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes the data to PHY register at the offset using the serial gigabit
+ *  media independent interface.
+ **/
+STATIC s32 igc_write_phy_reg_sgmii_82575(struct igc_hw *hw, u32 offset,
+					   u16 data)
+{
+	s32 ret_val = -IGC_ERR_PARAM;
+
+	DEBUGFUNC("igc_write_phy_reg_sgmii_82575");
+
+	if (offset > IGC_MAX_SGMII_PHY_REG_ADDR) {
+		DEBUGOUT1("PHY Address %d is out of range\n", offset);
+		goto out;
+	}
+
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igc_write_phy_reg_i2c(hw, offset, data);
+
+	hw->phy.ops.release(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_get_phy_id_82575 - Retrieve PHY addr and id
+ *  @hw: pointer to the HW structure
+ *
+ *  Retrieves the PHY address and ID for both PHY's which do and do not use
+ *  sgmi interface.
+ **/
+STATIC s32 igc_get_phy_id_82575(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32  ret_val = IGC_SUCCESS;
+	u16 phy_id;
+	u32 ctrl_ext;
+	u32 mdic;
+
+	DEBUGFUNC("igc_get_phy_id_82575");
+
+	/* some i354 devices need an extra read for phy id */
+	if (hw->mac.type == igc_i354)
+		igc_get_phy_id(hw);
+
+	/*
+	 * For SGMII PHYs, we try the list of possible addresses until
+	 * we find one that works.  For non-SGMII PHYs
+	 * (e.g. integrated copper PHYs), an address of 1 should
+	 * work.  The result of this function should mean phy->phy_addr
+	 * and phy->id are set correctly.
+	 */
+	if (!igc_sgmii_active_82575(hw)) {
+		phy->addr = 1;
+		ret_val = igc_get_phy_id(hw);
+		goto out;
+	}
+
+	if (igc_sgmii_uses_mdio_82575(hw)) {
+		switch (hw->mac.type) {
+		case igc_82575:
+		case igc_82576:
+			mdic = IGC_READ_REG(hw, IGC_MDIC);
+			mdic &= IGC_MDIC_PHY_MASK;
+			phy->addr = mdic >> IGC_MDIC_PHY_SHIFT;
+			break;
+		case igc_82580:
+		case igc_i350:
+		case igc_i354:
+		case igc_i210:
+		case igc_i211:
+			mdic = IGC_READ_REG(hw, IGC_MDICNFG);
+			mdic &= IGC_MDICNFG_PHY_MASK;
+			phy->addr = mdic >> IGC_MDICNFG_PHY_SHIFT;
+			break;
+		default:
+			ret_val = -IGC_ERR_PHY;
+			goto out;
+			break;
+		}
+		ret_val = igc_get_phy_id(hw);
+		goto out;
+	}
+
+	/* Power on sgmii phy if it is disabled */
+	ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT,
+			ctrl_ext & ~IGC_CTRL_EXT_SDP3_DATA);
+	IGC_WRITE_FLUSH(hw);
+	msec_delay(300);
+
+	/*
+	 * The address field in the I2CCMD register is 3 bits and 0 is invalid.
+	 * Therefore, we need to test 1-7
+	 */
+	for (phy->addr = 1; phy->addr < 8; phy->addr++) {
+		ret_val = igc_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id);
+		if (ret_val == IGC_SUCCESS) {
+			DEBUGOUT2("Vendor ID 0x%08X read at address %u\n",
+				  phy_id, phy->addr);
+			/*
+			 * At the time of this writing, The M88 part is
+			 * the only supported SGMII PHY product.
+			 */
+			if (phy_id == M88_VENDOR)
+				break;
+		} else {
+			DEBUGOUT1("PHY address %u was unreadable\n",
+				  phy->addr);
+		}
+	}
+
+	/* A valid PHY type couldn't be found. */
+	if (phy->addr == 8) {
+		phy->addr = 0;
+		ret_val = -IGC_ERR_PHY;
+	} else {
+		ret_val = igc_get_phy_id(hw);
+	}
+
+	/* restore previous sfp cage power state */
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_phy_hw_reset_sgmii_82575 - Performs a PHY reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Resets the PHY using the serial gigabit media independent interface.
+ **/
+STATIC s32 igc_phy_hw_reset_sgmii_82575(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	struct igc_phy_info *phy = &hw->phy;
+
+	DEBUGFUNC("igc_phy_hw_reset_sgmii_82575");
+
+	/*
+	 * This isn't a true "hard" reset, but is the only reset
+	 * available to us at this time.
+	 */
+
+	DEBUGOUT("Soft resetting SGMII attached PHY...\n");
+
+	if (!(hw->phy.ops.write_reg))
+		goto out;
+
+	/*
+	 * SFP documentation requires the following to configure the SPF module
+	 * to work on SGMII.  No further documentation is given.
+	 */
+	ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084);
+	if (ret_val)
+		goto out;
+
+	ret_val = hw->phy.ops.commit(hw);
+	if (ret_val)
+		goto out;
+
+	if (phy->id == M88E1512_E_PHY_ID)
+		ret_val = igc_initialize_M88E1512_phy(hw);
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: true to enable LPLU, false to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.  When
+ *  activating LPLU this function also disables smart speed
+ *  and vice versa.  LPLU will not be activated unless the
+ *  device autonegotiation advertisement meets standards of
+ *  either 10 or 10/100 or 10/100/1000 at all duplexes.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+STATIC s32 igc_set_d0_lplu_state_82575(struct igc_hw *hw, bool active)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+	u16 data;
+
+	DEBUGFUNC("igc_set_d0_lplu_state_82575");
+
+	if (!(hw->phy.ops.read_reg))
+		goto out;
+
+	ret_val = phy->ops.read_reg(hw, IGP02IGC_PHY_POWER_MGMT, &data);
+	if (ret_val)
+		goto out;
+
+	if (active) {
+		data |= IGP02IGC_PM_D0_LPLU;
+		ret_val = phy->ops.write_reg(hw, IGP02IGC_PHY_POWER_MGMT,
+					     data);
+		if (ret_val)
+			goto out;
+
+		/* When LPLU is enabled, we should disable SmartSpeed */
+		ret_val = phy->ops.read_reg(hw, IGP01IGC_PHY_PORT_CONFIG,
+					    &data);
+		data &= ~IGP01IGC_PSCFR_SMART_SPEED;
+		ret_val = phy->ops.write_reg(hw, IGP01IGC_PHY_PORT_CONFIG,
+					     data);
+		if (ret_val)
+			goto out;
+	} else {
+		data &= ~IGP02IGC_PM_D0_LPLU;
+		ret_val = phy->ops.write_reg(hw, IGP02IGC_PHY_POWER_MGMT,
+					     data);
+		/*
+		 * 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.
+		 */
+		if (phy->smart_speed == igc_smart_speed_on) {
+			ret_val = phy->ops.read_reg(hw,
+						    IGP01IGC_PHY_PORT_CONFIG,
+						    &data);
+			if (ret_val)
+				goto out;
+
+			data |= IGP01IGC_PSCFR_SMART_SPEED;
+			ret_val = phy->ops.write_reg(hw,
+						     IGP01IGC_PHY_PORT_CONFIG,
+						     data);
+			if (ret_val)
+				goto out;
+		} else if (phy->smart_speed == igc_smart_speed_off) {
+			ret_val = phy->ops.read_reg(hw,
+						    IGP01IGC_PHY_PORT_CONFIG,
+						    &data);
+			if (ret_val)
+				goto out;
+
+			data &= ~IGP01IGC_PSCFR_SMART_SPEED;
+			ret_val = phy->ops.write_reg(hw,
+						     IGP01IGC_PHY_PORT_CONFIG,
+						     data);
+			if (ret_val)
+				goto out;
+		}
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: true to enable LPLU, false to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.  When
+ *  activating LPLU this function also disables smart speed
+ *  and vice versa.  LPLU will not be activated unless the
+ *  device autonegotiation advertisement meets standards of
+ *  either 10 or 10/100 or 10/100/1000 at all duplexes.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+STATIC s32 igc_set_d0_lplu_state_82580(struct igc_hw *hw, bool active)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	u32 data;
+
+	DEBUGFUNC("igc_set_d0_lplu_state_82580");
+
+	data = IGC_READ_REG(hw, IGC_82580_PHY_POWER_MGMT);
+
+	if (active) {
+		data |= IGC_82580_PM_D0_LPLU;
+
+		/* When LPLU is enabled, we should disable SmartSpeed */
+		data &= ~IGC_82580_PM_SPD;
+	} else {
+		data &= ~IGC_82580_PM_D0_LPLU;
+
+		/*
+		 * 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.
+		 */
+		if (phy->smart_speed == igc_smart_speed_on)
+			data |= IGC_82580_PM_SPD;
+		else if (phy->smart_speed == igc_smart_speed_off)
+			data &= ~IGC_82580_PM_SPD;
+	}
+
+	IGC_WRITE_REG(hw, IGC_82580_PHY_POWER_MGMT, data);
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_set_d3_lplu_state_82580 - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  Success returns 0, Failure returns 1
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  and SmartSpeed is disabled when active is true, else clear lplu for D3
+ *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.
+ **/
+s32 igc_set_d3_lplu_state_82580(struct igc_hw *hw, bool active)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	u32 data;
+
+	DEBUGFUNC("igc_set_d3_lplu_state_82580");
+
+	data = IGC_READ_REG(hw, IGC_82580_PHY_POWER_MGMT);
+
+	if (!active) {
+		data &= ~IGC_82580_PM_D3_LPLU;
+		/*
+		 * 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.
+		 */
+		if (phy->smart_speed == igc_smart_speed_on)
+			data |= IGC_82580_PM_SPD;
+		else if (phy->smart_speed == igc_smart_speed_off)
+			data &= ~IGC_82580_PM_SPD;
+	} else if ((phy->autoneg_advertised == IGC_ALL_SPEED_DUPLEX) ||
+		   (phy->autoneg_advertised == IGC_ALL_NOT_GIG) ||
+		   (phy->autoneg_advertised == IGC_ALL_10_SPEED)) {
+		data |= IGC_82580_PM_D3_LPLU;
+		/* When LPLU is enabled, we should disable SmartSpeed */
+		data &= ~IGC_82580_PM_SPD;
+	}
+
+	IGC_WRITE_REG(hw, IGC_82580_PHY_POWER_MGMT, data);
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_acquire_nvm_82575 - Request for access to EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the necessary semaphores for exclusive access to the EEPROM.
+ *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
+ *  Return successful if access grant bit set, else clear the request for
+ *  EEPROM access and return -IGC_ERR_NVM (-1).
+ **/
+STATIC s32 igc_acquire_nvm_82575(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_acquire_nvm_82575");
+
+	ret_val = igc_acquire_swfw_sync_82575(hw, IGC_SWFW_EEP_SM);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * Check if there is some access
+	 * error this access may hook on
+	 */
+	if (hw->mac.type == igc_i350) {
+		u32 eecd = IGC_READ_REG(hw, IGC_EECD);
+		if (eecd & (IGC_EECD_BLOCKED | IGC_EECD_ABORT |
+		    IGC_EECD_TIMEOUT)) {
+			/* Clear all access error flags */
+			IGC_WRITE_REG(hw, IGC_EECD, eecd |
+					IGC_EECD_ERROR_CLR);
+			DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
+		}
+	}
+
+	if (hw->mac.type == igc_82580) {
+		u32 eecd = IGC_READ_REG(hw, IGC_EECD);
+		if (eecd & IGC_EECD_BLOCKED) {
+			/* Clear access error flag */
+			IGC_WRITE_REG(hw, IGC_EECD, eecd |
+					IGC_EECD_BLOCKED);
+			DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
+		}
+	}
+
+	ret_val = igc_acquire_nvm_generic(hw);
+	if (ret_val)
+		igc_release_swfw_sync_82575(hw, IGC_SWFW_EEP_SM);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_release_nvm_82575 - Release exclusive access to EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
+ *  then release the semaphores acquired.
+ **/
+STATIC void igc_release_nvm_82575(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_release_nvm_82575");
+
+	igc_release_nvm_generic(hw);
+
+	igc_release_swfw_sync_82575(hw, IGC_SWFW_EEP_SM);
+}
+
+/**
+ *  igc_acquire_swfw_sync_82575 - Acquire SW/FW semaphore
+ *  @hw: pointer to the HW structure
+ *  @mask: specifies which semaphore to acquire
+ *
+ *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
+ *  will also specify which port we're acquiring the lock for.
+ **/
+STATIC s32 igc_acquire_swfw_sync_82575(struct igc_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+	u32 swmask = mask;
+	u32 fwmask = mask << 16;
+	s32 ret_val = IGC_SUCCESS;
+	s32 i = 0, timeout = 200;
+
+	DEBUGFUNC("igc_acquire_swfw_sync_82575");
+
+	while (i < timeout) {
+		if (igc_get_hw_semaphore_generic(hw)) {
+			ret_val = -IGC_ERR_SWFW_SYNC;
+			goto out;
+		}
+
+		swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
+		if (!(swfw_sync & (fwmask | swmask)))
+			break;
+
+		/*
+		 * Firmware currently using resource (fwmask)
+		 * or other software thread using resource (swmask)
+		 */
+		igc_put_hw_semaphore_generic(hw);
+		msec_delay_irq(5);
+		i++;
+	}
+
+	if (i == timeout) {
+		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
+		ret_val = -IGC_ERR_SWFW_SYNC;
+		goto out;
+	}
+
+	swfw_sync |= swmask;
+	IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
+
+	igc_put_hw_semaphore_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_release_swfw_sync_82575 - Release SW/FW semaphore
+ *  @hw: pointer to the HW structure
+ *  @mask: specifies which semaphore to acquire
+ *
+ *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
+ *  will also specify which port we're releasing the lock for.
+ **/
+STATIC void igc_release_swfw_sync_82575(struct igc_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+
+	DEBUGFUNC("igc_release_swfw_sync_82575");
+
+	while (igc_get_hw_semaphore_generic(hw) != IGC_SUCCESS)
+		; /* Empty */
+
+	swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
+	swfw_sync &= (u32)~mask;
+	IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
+
+	igc_put_hw_semaphore_generic(hw);
+}
+
+/**
+ *  igc_get_cfg_done_82575 - Read config done bit
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the management control register for the config done bit for
+ *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
+ *  to read the config done bit, so an error is *ONLY* logged and returns
+ *  IGC_SUCCESS.  If we were to return with error, EEPROM-less silicon
+ *  would not be able to be reset or change link.
+ **/
+STATIC s32 igc_get_cfg_done_82575(struct igc_hw *hw)
+{
+	s32 timeout = PHY_CFG_TIMEOUT;
+	u32 mask = IGC_NVM_CFG_DONE_PORT_0;
+
+	DEBUGFUNC("igc_get_cfg_done_82575");
+
+	if (hw->bus.func == IGC_FUNC_1)
+		mask = IGC_NVM_CFG_DONE_PORT_1;
+	else if (hw->bus.func == IGC_FUNC_2)
+		mask = IGC_NVM_CFG_DONE_PORT_2;
+	else if (hw->bus.func == IGC_FUNC_3)
+		mask = IGC_NVM_CFG_DONE_PORT_3;
+	while (timeout) {
+		if (IGC_READ_REG(hw, IGC_EEMNGCTL) & mask)
+			break;
+		msec_delay(1);
+		timeout--;
+	}
+	if (!timeout)
+		DEBUGOUT("MNG configuration cycle has not completed.\n");
+
+	/* If EEPROM is not marked present, init the PHY manually */
+	if (!(IGC_READ_REG(hw, IGC_EECD) & IGC_EECD_PRES) &&
+	    (hw->phy.type == igc_phy_igp_3))
+		igc_phy_init_script_igp3(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_get_link_up_info_82575 - Get link speed/duplex info
+ *  @hw: pointer to the HW structure
+ *  @speed: stores the current speed
+ *  @duplex: stores the current duplex
+ *
+ *  This is a wrapper function, if using the serial gigabit media independent
+ *  interface, use PCS to retrieve the link speed and duplex information.
+ *  Otherwise, use the generic function to get the link speed and duplex info.
+ **/
+STATIC s32 igc_get_link_up_info_82575(struct igc_hw *hw, u16 *speed,
+					u16 *duplex)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_get_link_up_info_82575");
+
+	if (hw->phy.media_type != igc_media_type_copper)
+		ret_val = igc_get_pcs_speed_and_duplex_82575(hw, speed,
+							       duplex);
+	else
+		ret_val = igc_get_speed_and_duplex_copper_generic(hw, speed,
+								    duplex);
+
+	return ret_val;
+}
+
+/**
+ *  igc_check_for_link_82575 - Check for link
+ *  @hw: pointer to the HW structure
+ *
+ *  If sgmii is enabled, then use the pcs register to determine link, otherwise
+ *  use the generic interface for determining link.
+ **/
+STATIC s32 igc_check_for_link_82575(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u16 speed, duplex;
+
+	DEBUGFUNC("igc_check_for_link_82575");
+
+	if (hw->phy.media_type != igc_media_type_copper) {
+		ret_val = igc_get_pcs_speed_and_duplex_82575(hw, &speed,
+							       &duplex);
+		/*
+		 * Use this flag to determine if link needs to be checked or
+		 * not.  If we have link clear the flag so that we do not
+		 * continue to check for link.
+		 */
+		hw->mac.get_link_status = !hw->mac.serdes_has_link;
+
+		/*
+		 * Configure Flow Control now that Auto-Neg has completed.
+		 * First, we need to restore the desired flow control
+		 * settings because we may have had to re-autoneg with a
+		 * different link partner.
+		 */
+		ret_val = igc_config_fc_after_link_up_generic(hw);
+		if (ret_val)
+			DEBUGOUT("Error configuring flow control\n");
+	} else {
+		ret_val = igc_check_for_copper_link_generic(hw);
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_check_for_link_media_swap - Check which M88E1112 interface linked
+ *  @hw: pointer to the HW structure
+ *
+ *  Poll the M88E1112 interfaces to see which interface achieved link.
+ */
+STATIC s32 igc_check_for_link_media_swap(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+	u8 port = 0;
+
+	DEBUGFUNC("igc_check_for_link_media_swap");
+
+	/* Check for copper. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1112_PAGE_ADDR, 0);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = phy->ops.read_reg(hw, IGC_M88E1112_STATUS, &data);
+	if (ret_val)
+		return ret_val;
+
+	if (data & IGC_M88E1112_STATUS_LINK)
+		port = IGC_MEDIA_PORT_COPPER;
+
+	/* Check for other. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1112_PAGE_ADDR, 1);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = phy->ops.read_reg(hw, IGC_M88E1112_STATUS, &data);
+	if (ret_val)
+		return ret_val;
+
+	if (data & IGC_M88E1112_STATUS_LINK)
+		port = IGC_MEDIA_PORT_OTHER;
+
+	/* Determine if a swap needs to happen. */
+	if (port && (hw->dev_spec._82575.media_port != port)) {
+		hw->dev_spec._82575.media_port = port;
+		hw->dev_spec._82575.media_changed = true;
+	}
+
+	if (port == IGC_MEDIA_PORT_COPPER) {
+		/* reset page to 0 */
+		ret_val = phy->ops.write_reg(hw, IGC_M88E1112_PAGE_ADDR, 0);
+		if (ret_val)
+			return ret_val;
+		igc_check_for_link_82575(hw);
+	} else {
+		igc_check_for_link_82575(hw);
+		/* reset page to 0 */
+		ret_val = phy->ops.write_reg(hw, IGC_M88E1112_PAGE_ADDR, 0);
+		if (ret_val)
+			return ret_val;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_power_up_serdes_link_82575 - Power up the serdes link after shutdown
+ *  @hw: pointer to the HW structure
+ **/
+STATIC void igc_power_up_serdes_link_82575(struct igc_hw *hw)
+{
+	u32 reg;
+
+	DEBUGFUNC("igc_power_up_serdes_link_82575");
+
+	if ((hw->phy.media_type != igc_media_type_internal_serdes) &&
+	    !igc_sgmii_active_82575(hw))
+		return;
+
+	/* Enable PCS to turn on link */
+	reg = IGC_READ_REG(hw, IGC_PCS_CFG0);
+	reg |= IGC_PCS_CFG_PCS_EN;
+	IGC_WRITE_REG(hw, IGC_PCS_CFG0, reg);
+
+	/* Power up the laser */
+	reg = IGC_READ_REG(hw, IGC_CTRL_EXT);
+	reg &= ~IGC_CTRL_EXT_SDP3_DATA;
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, reg);
+
+	/* flush the write to verify completion */
+	IGC_WRITE_FLUSH(hw);
+	msec_delay(1);
+}
+
+/**
+ *  igc_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
+ *  @hw: pointer to the HW structure
+ *  @speed: stores the current speed
+ *  @duplex: stores the current duplex
+ *
+ *  Using the physical coding sub-layer (PCS), retrieve the current speed and
+ *  duplex, then store the values in the pointers provided.
+ **/
+STATIC s32 igc_get_pcs_speed_and_duplex_82575(struct igc_hw *hw,
+						u16 *speed, u16 *duplex)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	u32 pcs;
+	u32 status;
+
+	DEBUGFUNC("igc_get_pcs_speed_and_duplex_82575");
+
+	/*
+	 * Read the PCS Status register for link state. For non-copper mode,
+	 * the status register is not accurate. The PCS status register is
+	 * used instead.
+	 */
+	pcs = IGC_READ_REG(hw, IGC_PCS_LSTAT);
+
+	/*
+	 * The link up bit determines when link is up on autoneg.
+	 */
+	if (pcs & IGC_PCS_LSTS_LINK_OK) {
+		mac->serdes_has_link = true;
+
+		/* Detect and store PCS speed */
+		if (pcs & IGC_PCS_LSTS_SPEED_1000)
+			*speed = SPEED_1000;
+		else if (pcs & IGC_PCS_LSTS_SPEED_100)
+			*speed = SPEED_100;
+		else
+			*speed = SPEED_10;
+
+		/* Detect and store PCS duplex */
+		if (pcs & IGC_PCS_LSTS_DUPLEX_FULL)
+			*duplex = FULL_DUPLEX;
+		else
+			*duplex = HALF_DUPLEX;
+
+		/* Check if it is an I354 2.5Gb backplane connection. */
+		if (mac->type == igc_i354) {
+			status = IGC_READ_REG(hw, IGC_STATUS);
+			if ((status & IGC_STATUS_2P5_SKU) &&
+			    !(status & IGC_STATUS_2P5_SKU_OVER)) {
+				*speed = SPEED_2500;
+				*duplex = FULL_DUPLEX;
+				DEBUGOUT("2500 Mbs, ");
+				DEBUGOUT("Full Duplex\n");
+			}
+		}
+
+	} else {
+		mac->serdes_has_link = false;
+		*speed = 0;
+		*duplex = 0;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_shutdown_serdes_link_82575 - Remove link during power down
+ *  @hw: pointer to the HW structure
+ *
+ *  In the case of serdes shut down sfp and PCS on driver unload
+ *  when management pass thru is not enabled.
+ **/
+void igc_shutdown_serdes_link_82575(struct igc_hw *hw)
+{
+	u32 reg;
+
+	DEBUGFUNC("igc_shutdown_serdes_link_82575");
+
+	if ((hw->phy.media_type != igc_media_type_internal_serdes) &&
+	    !igc_sgmii_active_82575(hw))
+		return;
+
+	if (!igc_enable_mng_pass_thru(hw)) {
+		/* Disable PCS to turn off link */
+		reg = IGC_READ_REG(hw, IGC_PCS_CFG0);
+		reg &= ~IGC_PCS_CFG_PCS_EN;
+		IGC_WRITE_REG(hw, IGC_PCS_CFG0, reg);
+
+		/* shutdown the laser */
+		reg = IGC_READ_REG(hw, IGC_CTRL_EXT);
+		reg |= IGC_CTRL_EXT_SDP3_DATA;
+		IGC_WRITE_REG(hw, IGC_CTRL_EXT, reg);
+
+		/* flush the write to verify completion */
+		IGC_WRITE_FLUSH(hw);
+		msec_delay(1);
+	}
+
+	return;
+}
+
+/**
+ *  igc_reset_hw_82575 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 igc_reset_hw_82575(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_reset_hw_82575");
+
+	/*
+	 * Prevent the PCI-E bus from sticking if there is no TLP connection
+	 * on the last TLP read/write transaction when MAC is reset.
+	 */
+	ret_val = igc_disable_pcie_master_generic(hw);
+	if (ret_val)
+		DEBUGOUT("PCI-E Master disable polling has failed.\n");
+
+	/* set the completion timeout for interface */
+	ret_val = igc_set_pcie_completion_timeout(hw);
+	if (ret_val)
+		DEBUGOUT("PCI-E Set completion timeout has failed.\n");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
+	IGC_WRITE_FLUSH(hw);
+
+	msec_delay(10);
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGOUT("Issuing a global reset to MAC\n");
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+
+	ret_val = igc_get_auto_rd_done_generic(hw);
+	if (ret_val) {
+		/*
+		 * When auto config read does not complete, do not
+		 * return with an error. This can happen in situations
+		 * where there is no eeprom and prevents getting link.
+		 */
+		DEBUGOUT("Auto Read Done did not complete\n");
+	}
+
+	/* If EEPROM is not present, run manual init scripts */
+	if (!(IGC_READ_REG(hw, IGC_EECD) & IGC_EECD_PRES))
+		igc_reset_init_script_82575(hw);
+
+	/* Clear any pending interrupt events. */
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_READ_REG(hw, IGC_ICR);
+
+	/* Install any alternate MAC address into RAR0 */
+	ret_val = igc_check_alt_mac_addr_generic(hw);
+
+	return ret_val;
+}
+
+/**
+ * igc_init_hw_82575 - Initialize hardware
+ * @hw: pointer to the HW structure
+ *
+ * This inits the hardware readying it for operation.
+ **/
+STATIC s32 igc_init_hw_82575(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_init_hw_82575");
+
+	/* Initialize identification LED */
+	ret_val = mac->ops.id_led_init(hw);
+	if (ret_val) {
+		DEBUGOUT("Error initializing identification LED\n");
+		/* This is not fatal and we should not stop init due to this */
+	}
+
+	/* Disabling VLAN filtering */
+	DEBUGOUT("Initializing the IEEE VLAN\n");
+	mac->ops.clear_vfta(hw);
+
+	ret_val = igc_init_hw_base(hw);
+
+	/* Set the default MTU size */
+	hw->dev_spec._82575.mtu = 1500;
+
+	/* Clear all of the statistics registers (clear on read).  It is
+	 * important that we do this after we have tried to establish link
+	 * because the symbol error count will increment wildly if there
+	 * is no link.
+	 */
+	igc_clear_hw_cntrs_82575(hw);
+
+	return ret_val;
+}
+/**
+ *  igc_setup_copper_link_82575 - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the link for auto-neg or forced speed and duplex.  Then we check
+ *  for link, once link is established calls to configure collision distance
+ *  and flow control are called.
+ **/
+STATIC s32 igc_setup_copper_link_82575(struct igc_hw *hw)
+{
+	u32 phpm_reg;
+	s32 ret_val;
+	u32 ctrl;
+
+	DEBUGFUNC("igc_setup_copper_link_82575");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	ctrl |= IGC_CTRL_SLU;
+	ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	/* Clear Go Link Disconnect bit on supported devices */
+	switch (hw->mac.type) {
+	case igc_82580:
+	case igc_i350:
+	case igc_i210:
+	case igc_i211:
+		phpm_reg = IGC_READ_REG(hw, IGC_82580_PHY_POWER_MGMT);
+		phpm_reg &= ~IGC_82580_PM_GO_LINKD;
+		IGC_WRITE_REG(hw, IGC_82580_PHY_POWER_MGMT, phpm_reg);
+		break;
+	default:
+		break;
+	}
+
+	ret_val = igc_setup_serdes_link_82575(hw);
+	if (ret_val)
+		goto out;
+
+	if (igc_sgmii_active_82575(hw)) {
+		/* allow time for SFP cage time to power up phy */
+		msec_delay(300);
+
+		ret_val = hw->phy.ops.reset(hw);
+		if (ret_val) {
+			DEBUGOUT("Error resetting the PHY.\n");
+			goto out;
+		}
+	}
+	switch (hw->phy.type) {
+	case igc_phy_i210:
+	/* fall through */
+	case igc_phy_m88:
+		switch (hw->phy.id) {
+		case I347AT4_E_PHY_ID:
+		/* fall through */
+		case M88E1112_E_PHY_ID:
+		/* fall through */
+		case M88E1340M_E_PHY_ID:
+		/* fall through */
+		case M88E1543_E_PHY_ID:
+		/* fall through */
+		case M88E1512_E_PHY_ID:
+		/* fall through */
+		case I210_I_PHY_ID:
+		/* fall through */
+			ret_val = igc_copper_link_setup_m88_gen2(hw);
+			break;
+		default:
+			ret_val = igc_copper_link_setup_m88(hw);
+			break;
+		}
+		break;
+	case igc_phy_igp_3:
+		ret_val = igc_copper_link_setup_igp(hw);
+		break;
+	case igc_phy_82580:
+		ret_val = igc_copper_link_setup_82577(hw);
+		break;
+	default:
+		ret_val = -IGC_ERR_PHY;
+		break;
+	}
+
+	if (ret_val)
+		goto out;
+
+	ret_val = igc_setup_copper_link_generic(hw);
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_setup_serdes_link_82575 - Setup link for serdes
+ *  @hw: pointer to the HW structure
+ *
+ *  Configure the physical coding sub-layer (PCS) link.  The PCS link is
+ *  used on copper connections where the serialized gigabit media independent
+ *  interface (sgmii), or serdes fiber is being used.  Configures the link
+ *  for auto-negotiation or forces speed/duplex.
+ **/
+STATIC s32 igc_setup_serdes_link_82575(struct igc_hw *hw)
+{
+	u32 ctrl_ext, ctrl_reg, reg, anadv_reg;
+	bool pcs_autoneg;
+	s32 ret_val = IGC_SUCCESS;
+	u16 data;
+
+	DEBUGFUNC("igc_setup_serdes_link_82575");
+
+	if ((hw->phy.media_type != igc_media_type_internal_serdes) &&
+	    !igc_sgmii_active_82575(hw))
+		return ret_val;
+
+	/*
+	 * On the 82575, SerDes loopback mode persists until it is
+	 * explicitly turned off or a power cycle is performed.  A read to
+	 * the register does not indicate its status.  Therefore, we ensure
+	 * loopback mode is disabled during initialization.
+	 */
+	IGC_WRITE_REG(hw, IGC_SCTL, IGC_SCTL_DISABLE_SERDES_LOOPBACK);
+
+	/* power on the sfp cage if present */
+	ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+	ctrl_ext &= ~IGC_CTRL_EXT_SDP3_DATA;
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+
+	ctrl_reg = IGC_READ_REG(hw, IGC_CTRL);
+	ctrl_reg |= IGC_CTRL_SLU;
+
+	/* set both sw defined pins on 82575/82576*/
+	if (hw->mac.type == igc_82575 || hw->mac.type == igc_82576)
+		ctrl_reg |= IGC_CTRL_SWDPIN0 | IGC_CTRL_SWDPIN1;
+
+	reg = IGC_READ_REG(hw, IGC_PCS_LCTL);
+
+	/* default pcs_autoneg to the same setting as mac autoneg */
+	pcs_autoneg = hw->mac.autoneg;
+
+	switch (ctrl_ext & IGC_CTRL_EXT_LINK_MODE_MASK) {
+	case IGC_CTRL_EXT_LINK_MODE_SGMII:
+		/* sgmii mode lets the phy handle forcing speed/duplex */
+		pcs_autoneg = true;
+		/* autoneg time out should be disabled for SGMII mode */
+		reg &= ~(IGC_PCS_LCTL_AN_TIMEOUT);
+		break;
+	case IGC_CTRL_EXT_LINK_MODE_1000BASE_KX:
+		/* disable PCS autoneg and support parallel detect only */
+		pcs_autoneg = false;
+		/* Fall through */
+	default:
+		if (hw->mac.type == igc_82575 ||
+		    hw->mac.type == igc_82576) {
+			ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data);
+			if (ret_val) {
+				DEBUGOUT("NVM Read Error\n");
+				return ret_val;
+			}
+
+			if (data & IGC_EEPROM_PCS_AUTONEG_DISABLE_BIT)
+				pcs_autoneg = false;
+		}
+
+		/*
+		 * non-SGMII modes only supports a speed of 1000/Full for the
+		 * link so it is best to just force the MAC and let the pcs
+		 * link either autoneg or be forced to 1000/Full
+		 */
+		ctrl_reg |= IGC_CTRL_SPD_1000 | IGC_CTRL_FRCSPD |
+			    IGC_CTRL_FD | IGC_CTRL_FRCDPX;
+
+		/* set speed of 1000/Full if speed/duplex is forced */
+		reg |= IGC_PCS_LCTL_FSV_1000 | IGC_PCS_LCTL_FDV_FULL;
+		break;
+	}
+
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl_reg);
+
+	/*
+	 * New SerDes mode allows for forcing speed or autonegotiating speed
+	 * at 1gb. Autoneg should be default set by most drivers. This is the
+	 * mode that will be compatible with older link partners and switches.
+	 * However, both are supported by the hardware and some drivers/tools.
+	 */
+	reg &= ~(IGC_PCS_LCTL_AN_ENABLE | IGC_PCS_LCTL_FLV_LINK_UP |
+		 IGC_PCS_LCTL_FSD | IGC_PCS_LCTL_FORCE_LINK);
+
+	if (pcs_autoneg) {
+		/* Set PCS register for autoneg */
+		reg |= IGC_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
+		       IGC_PCS_LCTL_AN_RESTART; /* Restart autoneg */
+
+		/* Disable force flow control for autoneg */
+		reg &= ~IGC_PCS_LCTL_FORCE_FCTRL;
+
+		/* Configure flow control advertisement for autoneg */
+		anadv_reg = IGC_READ_REG(hw, IGC_PCS_ANADV);
+		anadv_reg &= ~(IGC_TXCW_ASM_DIR | IGC_TXCW_PAUSE);
+
+		switch (hw->fc.requested_mode) {
+		case igc_fc_full:
+		case igc_fc_rx_pause:
+			anadv_reg |= IGC_TXCW_ASM_DIR;
+			anadv_reg |= IGC_TXCW_PAUSE;
+			break;
+		case igc_fc_tx_pause:
+			anadv_reg |= IGC_TXCW_ASM_DIR;
+			break;
+		default:
+			break;
+		}
+
+		IGC_WRITE_REG(hw, IGC_PCS_ANADV, anadv_reg);
+
+		DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
+	} else {
+		/* Set PCS register for forced link */
+		reg |= IGC_PCS_LCTL_FSD;	/* Force Speed */
+
+		/* Force flow control for forced link */
+		reg |= IGC_PCS_LCTL_FORCE_FCTRL;
+
+		DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
+	}
+
+	IGC_WRITE_REG(hw, IGC_PCS_LCTL, reg);
+
+	if (!pcs_autoneg && !igc_sgmii_active_82575(hw))
+		igc_force_mac_fc_generic(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_get_media_type_82575 - derives current media type.
+ *  @hw: pointer to the HW structure
+ *
+ *  The media type is chosen reflecting few settings.
+ *  The following are taken into account:
+ *  - link mode set in the current port Init Control Word #3
+ *  - current link mode settings in CSR register
+ *  - MDIO vs. I2C PHY control interface chosen
+ *  - SFP module media type
+ **/
+STATIC s32 igc_get_media_type_82575(struct igc_hw *hw)
+{
+	struct igc_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+	s32 ret_val = IGC_SUCCESS;
+	u32 ctrl_ext = 0;
+	u32 link_mode = 0;
+
+	/* Set internal phy as default */
+	dev_spec->sgmii_active = false;
+	dev_spec->module_plugged = false;
+
+	/* Get CSR setting */
+	ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+
+	/* extract link mode setting */
+	link_mode = ctrl_ext & IGC_CTRL_EXT_LINK_MODE_MASK;
+
+	switch (link_mode) {
+	case IGC_CTRL_EXT_LINK_MODE_1000BASE_KX:
+		hw->phy.media_type = igc_media_type_internal_serdes;
+		break;
+	case IGC_CTRL_EXT_LINK_MODE_GMII:
+		hw->phy.media_type = igc_media_type_copper;
+		break;
+	case IGC_CTRL_EXT_LINK_MODE_SGMII:
+		/* Get phy control interface type set (MDIO vs. I2C)*/
+		if (igc_sgmii_uses_mdio_82575(hw)) {
+			hw->phy.media_type = igc_media_type_copper;
+			dev_spec->sgmii_active = true;
+			break;
+		}
+		/* Fall through for I2C based SGMII */
+	case IGC_CTRL_EXT_LINK_MODE_PCIE_SERDES:
+		/* read media type from SFP EEPROM */
+		ret_val = igc_set_sfp_media_type_82575(hw);
+		if ((ret_val != IGC_SUCCESS) ||
+		    (hw->phy.media_type == igc_media_type_unknown)) {
+			/*
+			 * If media type was not identified then return media
+			 * type defined by the CTRL_EXT settings.
+			 */
+			hw->phy.media_type = igc_media_type_internal_serdes;
+
+			if (link_mode == IGC_CTRL_EXT_LINK_MODE_SGMII) {
+				hw->phy.media_type = igc_media_type_copper;
+				dev_spec->sgmii_active = true;
+			}
+
+			break;
+		}
+
+		/* do not change link mode for 100BaseFX */
+		if (dev_spec->eth_flags.e100_base_fx)
+			break;
+
+		/* change current link mode setting */
+		ctrl_ext &= ~IGC_CTRL_EXT_LINK_MODE_MASK;
+
+		if (hw->phy.media_type == igc_media_type_copper)
+			ctrl_ext |= IGC_CTRL_EXT_LINK_MODE_SGMII;
+		else
+			ctrl_ext |= IGC_CTRL_EXT_LINK_MODE_PCIE_SERDES;
+
+		IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+
+		break;
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_set_sfp_media_type_82575 - derives SFP module media type.
+ *  @hw: pointer to the HW structure
+ *
+ *  The media type is chosen based on SFP module.
+ *  compatibility flags retrieved from SFP ID EEPROM.
+ **/
+STATIC s32 igc_set_sfp_media_type_82575(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_ERR_CONFIG;
+	u32 ctrl_ext = 0;
+	struct igc_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+	struct sfp_igc_flags *eth_flags = &dev_spec->eth_flags;
+	u8 tranceiver_type = 0;
+	s32 timeout = 3;
+
+	/* Turn I2C interface ON and power on sfp cage */
+	ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+	ctrl_ext &= ~IGC_CTRL_EXT_SDP3_DATA;
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext | IGC_CTRL_I2C_ENA);
+
+	IGC_WRITE_FLUSH(hw);
+
+	/* Read SFP module data */
+	while (timeout) {
+		ret_val = igc_read_sfp_data_byte(hw,
+			IGC_I2CCMD_SFP_DATA_ADDR(IGC_SFF_IDENTIFIER_OFFSET),
+			&tranceiver_type);
+		if (ret_val == IGC_SUCCESS)
+			break;
+		msec_delay(100);
+		timeout--;
+	}
+	if (ret_val != IGC_SUCCESS)
+		goto out;
+
+	ret_val = igc_read_sfp_data_byte(hw,
+			IGC_I2CCMD_SFP_DATA_ADDR(IGC_SFF_ETH_FLAGS_OFFSET),
+			(u8 *)eth_flags);
+	if (ret_val != IGC_SUCCESS)
+		goto out;
+
+	/* Check if there is some SFP module plugged and powered */
+	if ((tranceiver_type == IGC_SFF_IDENTIFIER_SFP) ||
+	    (tranceiver_type == IGC_SFF_IDENTIFIER_SFF)) {
+		dev_spec->module_plugged = true;
+		if (eth_flags->igc_base_lx || eth_flags->igc_base_sx) {
+			hw->phy.media_type = igc_media_type_internal_serdes;
+		} else if (eth_flags->e100_base_fx) {
+			dev_spec->sgmii_active = true;
+			hw->phy.media_type = igc_media_type_internal_serdes;
+		} else if (eth_flags->igc_base_t) {
+			dev_spec->sgmii_active = true;
+			hw->phy.media_type = igc_media_type_copper;
+		} else {
+			hw->phy.media_type = igc_media_type_unknown;
+			DEBUGOUT("PHY module has not been recognized\n");
+			goto out;
+		}
+	} else {
+		hw->phy.media_type = igc_media_type_unknown;
+	}
+	ret_val = IGC_SUCCESS;
+out:
+	/* Restore I2C interface setting */
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+	return ret_val;
+}
+
+/**
+ *  igc_valid_led_default_82575 - Verify a valid default LED config
+ *  @hw: pointer to the HW structure
+ *  @data: pointer to the NVM (EEPROM)
+ *
+ *  Read the EEPROM for the current default LED configuration.  If the
+ *  LED configuration is not valid, set to a valid LED configuration.
+ **/
+STATIC s32 igc_valid_led_default_82575(struct igc_hw *hw, u16 *data)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_valid_led_default_82575");
+
+	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		goto out;
+	}
+
+	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
+		switch (hw->phy.media_type) {
+		case igc_media_type_internal_serdes:
+			*data = ID_LED_DEFAULT_82575_SERDES;
+			break;
+		case igc_media_type_copper:
+		default:
+			*data = ID_LED_DEFAULT;
+			break;
+		}
+	}
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_sgmii_active_82575 - Return sgmii state
+ *  @hw: pointer to the HW structure
+ *
+ *  82575 silicon has a serialized gigabit media independent interface (sgmii)
+ *  which can be enabled for use in the embedded applications.  Simply
+ *  return the current state of the sgmii interface.
+ **/
+STATIC bool igc_sgmii_active_82575(struct igc_hw *hw)
+{
+	struct igc_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
+	return dev_spec->sgmii_active;
+}
+
+/**
+ *  igc_reset_init_script_82575 - Inits HW defaults after reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Inits recommended HW defaults after a reset when there is no EEPROM
+ *  detected. This is only for the 82575.
+ **/
+s32 igc_reset_init_script_82575(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_reset_init_script_82575");
+
+	if (hw->mac.type == igc_82575) {
+		DEBUGOUT("Running reset init script for 82575\n");
+		/* SerDes configuration via SERDESCTRL */
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_SCTL, 0x00, 0x0C);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_SCTL, 0x01, 0x78);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_SCTL, 0x1B, 0x23);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_SCTL, 0x23, 0x15);
+
+		/* CCM configuration via CCMCTL register */
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_CCMCTL, 0x14, 0x00);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_CCMCTL, 0x10, 0x00);
+
+		/* PCIe lanes configuration */
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_GIOCTL, 0x00, 0xEC);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_GIOCTL, 0x61, 0xDF);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_GIOCTL, 0x34, 0x05);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_GIOCTL, 0x2F, 0x81);
+
+		/* PCIe PLL Configuration */
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_SCCTL, 0x02, 0x47);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_SCCTL, 0x14, 0x00);
+		igc_write_8bit_ctrl_reg_generic(hw, IGC_SCCTL, 0x10, 0x00);
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_read_mac_addr_82575 - Read device MAC address
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_read_mac_addr_82575(struct igc_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_read_mac_addr_82575");
+
+	/*
+	 * If there's an alternate MAC address place it in RAR0
+	 * so that it will override the Si installed default perm
+	 * address.
+	 */
+	ret_val = igc_check_alt_mac_addr_generic(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igc_read_mac_addr_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_config_collision_dist_82575 - Configure collision distance
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the collision distance to the default value and is used
+ *  during link setup.
+ **/
+STATIC void igc_config_collision_dist_82575(struct igc_hw *hw)
+{
+	u32 tctl_ext;
+
+	DEBUGFUNC("igc_config_collision_dist_82575");
+
+	tctl_ext = IGC_READ_REG(hw, IGC_TCTL_EXT);
+
+	tctl_ext &= ~IGC_TCTL_EXT_COLD;
+	tctl_ext |= IGC_COLLISION_DISTANCE << IGC_TCTL_EXT_COLD_SHIFT;
+
+	IGC_WRITE_REG(hw, IGC_TCTL_EXT, tctl_ext);
+	IGC_WRITE_FLUSH(hw);
+}
+
+/**
+ *  igc_clear_hw_cntrs_82575 - Clear device specific hardware counters
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the hardware counters by reading the counter registers.
+ **/
+STATIC void igc_clear_hw_cntrs_82575(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_clear_hw_cntrs_82575");
+
+	igc_clear_hw_cntrs_base_generic(hw);
+
+	IGC_READ_REG(hw, IGC_PRC64);
+	IGC_READ_REG(hw, IGC_PRC127);
+	IGC_READ_REG(hw, IGC_PRC255);
+	IGC_READ_REG(hw, IGC_PRC511);
+	IGC_READ_REG(hw, IGC_PRC1023);
+	IGC_READ_REG(hw, IGC_PRC1522);
+	IGC_READ_REG(hw, IGC_PTC64);
+	IGC_READ_REG(hw, IGC_PTC127);
+	IGC_READ_REG(hw, IGC_PTC255);
+	IGC_READ_REG(hw, IGC_PTC511);
+	IGC_READ_REG(hw, IGC_PTC1023);
+	IGC_READ_REG(hw, IGC_PTC1522);
+
+	IGC_READ_REG(hw, IGC_ALGNERRC);
+	IGC_READ_REG(hw, IGC_RXERRC);
+	IGC_READ_REG(hw, IGC_TNCRS);
+	IGC_READ_REG(hw, IGC_CEXTERR);
+	IGC_READ_REG(hw, IGC_TSCTC);
+	IGC_READ_REG(hw, IGC_TSCTFC);
+
+	IGC_READ_REG(hw, IGC_MGTPRC);
+	IGC_READ_REG(hw, IGC_MGTPDC);
+	IGC_READ_REG(hw, IGC_MGTPTC);
+
+	IGC_READ_REG(hw, IGC_IAC);
+	IGC_READ_REG(hw, IGC_ICRXOC);
+
+	IGC_READ_REG(hw, IGC_ICRXPTC);
+	IGC_READ_REG(hw, IGC_ICRXATC);
+	IGC_READ_REG(hw, IGC_ICTXPTC);
+	IGC_READ_REG(hw, IGC_ICTXATC);
+	IGC_READ_REG(hw, IGC_ICTXQEC);
+	IGC_READ_REG(hw, IGC_ICTXQMTC);
+	IGC_READ_REG(hw, IGC_ICRXDMTC);
+
+	IGC_READ_REG(hw, IGC_CBTMPC);
+	IGC_READ_REG(hw, IGC_HTDPMC);
+	IGC_READ_REG(hw, IGC_CBRMPC);
+	IGC_READ_REG(hw, IGC_RPTHC);
+	IGC_READ_REG(hw, IGC_HGPTC);
+	IGC_READ_REG(hw, IGC_HTCBDPC);
+	IGC_READ_REG(hw, IGC_HGORCL);
+	IGC_READ_REG(hw, IGC_HGORCH);
+	IGC_READ_REG(hw, IGC_HGOTCL);
+	IGC_READ_REG(hw, IGC_HGOTCH);
+	IGC_READ_REG(hw, IGC_LENERRS);
+
+	/* This register should not be read in copper configurations */
+	if ((hw->phy.media_type == igc_media_type_internal_serdes) ||
+	    igc_sgmii_active_82575(hw))
+		IGC_READ_REG(hw, IGC_SCVPC);
+}
+
+/**
+ *  igc_set_pcie_completion_timeout - set pci-e completion timeout
+ *  @hw: pointer to the HW structure
+ *
+ *  The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
+ *  however the hardware default for these parts is 500us to 1ms which is less
+ *  than the 10ms recommended by the pci-e spec.  To address this we need to
+ *  increase the value to either 10ms to 200ms for capability version 1 config,
+ *  or 16ms to 55ms for version 2.
+ **/
+STATIC s32 igc_set_pcie_completion_timeout(struct igc_hw *hw)
+{
+	u32 gcr = IGC_READ_REG(hw, IGC_GCR);
+	s32 ret_val = IGC_SUCCESS;
+	u16 pcie_devctl2;
+
+	/* only take action if timeout value is defaulted to 0 */
+	if (gcr & IGC_GCR_CMPL_TMOUT_MASK)
+		goto out;
+
+	/*
+	 * if capababilities version is type 1 we can write the
+	 * timeout of 10ms to 200ms through the GCR register
+	 */
+	if (!(gcr & IGC_GCR_CAP_VER2)) {
+		gcr |= IGC_GCR_CMPL_TMOUT_10ms;
+		goto out;
+	}
+
+	/*
+	 * for version 2 capabilities we need to write the config space
+	 * directly in order to set the completion timeout value for
+	 * 16ms to 55ms
+	 */
+	ret_val = igc_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
+					  &pcie_devctl2);
+	if (ret_val)
+		goto out;
+
+	pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
+
+	ret_val = igc_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
+					   &pcie_devctl2);
+out:
+	/* disable completion timeout resend */
+	gcr &= ~IGC_GCR_CMPL_TMOUT_RESEND;
+
+	IGC_WRITE_REG(hw, IGC_GCR, gcr);
+	return ret_val;
+}
+
+/**
+ *  igc_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
+ *  @hw: pointer to the hardware struct
+ *  @enable: state to enter, either enabled or disabled
+ *  @pf: Physical Function pool - do not set anti-spoofing for the PF
+ *
+ *  enables/disables L2 switch anti-spoofing functionality.
+ **/
+void igc_vmdq_set_anti_spoofing_pf(struct igc_hw *hw, bool enable, int pf)
+{
+	u32 reg_val, reg_offset;
+
+	switch (hw->mac.type) {
+	case igc_82576:
+		reg_offset = IGC_DTXSWC;
+		break;
+	case igc_i350:
+	case igc_i354:
+		reg_offset = IGC_TXSWC;
+		break;
+	default:
+		return;
+	}
+
+	reg_val = IGC_READ_REG(hw, reg_offset);
+	if (enable) {
+		reg_val |= (IGC_DTXSWC_MAC_SPOOF_MASK |
+			     IGC_DTXSWC_VLAN_SPOOF_MASK);
+		/* The PF can spoof - it has to in order to
+		 * support emulation mode NICs
+		 */
+		reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
+	} else {
+		reg_val &= ~(IGC_DTXSWC_MAC_SPOOF_MASK |
+			     IGC_DTXSWC_VLAN_SPOOF_MASK);
+	}
+	IGC_WRITE_REG(hw, reg_offset, reg_val);
+}
+
+/**
+ *  igc_vmdq_set_loopback_pf - enable or disable vmdq loopback
+ *  @hw: pointer to the hardware struct
+ *  @enable: state to enter, either enabled or disabled
+ *
+ *  enables/disables L2 switch loopback functionality.
+ **/
+void igc_vmdq_set_loopback_pf(struct igc_hw *hw, bool enable)
+{
+	u32 dtxswc;
+
+	switch (hw->mac.type) {
+	case igc_82576:
+		dtxswc = IGC_READ_REG(hw, IGC_DTXSWC);
+		if (enable)
+			dtxswc |= IGC_DTXSWC_VMDQ_LOOPBACK_EN;
+		else
+			dtxswc &= ~IGC_DTXSWC_VMDQ_LOOPBACK_EN;
+		IGC_WRITE_REG(hw, IGC_DTXSWC, dtxswc);
+		break;
+	case igc_i350:
+	case igc_i354:
+		dtxswc = IGC_READ_REG(hw, IGC_TXSWC);
+		if (enable)
+			dtxswc |= IGC_DTXSWC_VMDQ_LOOPBACK_EN;
+		else
+			dtxswc &= ~IGC_DTXSWC_VMDQ_LOOPBACK_EN;
+		IGC_WRITE_REG(hw, IGC_TXSWC, dtxswc);
+		break;
+	default:
+		/* Currently no other hardware supports loopback */
+		break;
+	}
+
+
+}
+
+/**
+ *  igc_vmdq_set_replication_pf - enable or disable vmdq replication
+ *  @hw: pointer to the hardware struct
+ *  @enable: state to enter, either enabled or disabled
+ *
+ *  enables/disables replication of packets across multiple pools.
+ **/
+void igc_vmdq_set_replication_pf(struct igc_hw *hw, bool enable)
+{
+	u32 vt_ctl = IGC_READ_REG(hw, IGC_VT_CTL);
+
+	if (enable)
+		vt_ctl |= IGC_VT_CTL_VM_REPL_EN;
+	else
+		vt_ctl &= ~IGC_VT_CTL_VM_REPL_EN;
+
+	IGC_WRITE_REG(hw, IGC_VT_CTL, vt_ctl);
+}
+
+/**
+ *  igc_read_phy_reg_82580 - Read 82580 MDI control register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the MDI control register in the PHY at offset and stores the
+ *  information read to data.
+ **/
+STATIC s32 igc_read_phy_reg_82580(struct igc_hw *hw, u32 offset, u16 *data)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_read_phy_reg_82580");
+
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igc_read_phy_reg_mdic(hw, offset, data);
+
+	hw->phy.ops.release(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_write_phy_reg_82580 - Write 82580 MDI control register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write to register at offset
+ *
+ *  Writes data to MDI control register in the PHY at offset.
+ **/
+STATIC s32 igc_write_phy_reg_82580(struct igc_hw *hw, u32 offset, u16 data)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_write_phy_reg_82580");
+
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igc_write_phy_reg_mdic(hw, offset, data);
+
+	hw->phy.ops.release(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on
+ *  the values found in the EEPROM.  This addresses an issue in which these
+ *  bits are not restored from EEPROM after reset.
+ **/
+STATIC s32 igc_reset_mdicnfg_82580(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	u32 mdicnfg;
+	u16 nvm_data = 0;
+
+	DEBUGFUNC("igc_reset_mdicnfg_82580");
+
+	if (hw->mac.type != igc_82580)
+		goto out;
+	if (!igc_sgmii_active_82575(hw))
+		goto out;
+
+	ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
+				   NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
+				   &nvm_data);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		goto out;
+	}
+
+	mdicnfg = IGC_READ_REG(hw, IGC_MDICNFG);
+	if (nvm_data & NVM_WORD24_EXT_MDIO)
+		mdicnfg |= IGC_MDICNFG_EXT_MDIO;
+	if (nvm_data & NVM_WORD24_COM_MDIO)
+		mdicnfg |= IGC_MDICNFG_COM_MDIO;
+	IGC_WRITE_REG(hw, IGC_MDICNFG, mdicnfg);
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_reset_hw_82580 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets function or entire device (all ports, etc.)
+ *  to a known state.
+ **/
+STATIC s32 igc_reset_hw_82580(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	/* BH SW mailbox bit in SW_FW_SYNC */
+	u16 swmbsw_mask = IGC_SW_SYNCH_MB;
+	u32 ctrl;
+	bool global_device_reset = hw->dev_spec._82575.global_device_reset;
+
+	DEBUGFUNC("igc_reset_hw_82580");
+
+	hw->dev_spec._82575.global_device_reset = false;
+
+	/* 82580 does not reliably do global_device_reset due to hw errata */
+	if (hw->mac.type == igc_82580)
+		global_device_reset = false;
+
+	/* Get current control state. */
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	/*
+	 * Prevent the PCI-E bus from sticking if there is no TLP connection
+	 * on the last TLP read/write transaction when MAC is reset.
+	 */
+	ret_val = igc_disable_pcie_master_generic(hw);
+	if (ret_val)
+		DEBUGOUT("PCI-E Master disable polling has failed.\n");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
+	IGC_WRITE_FLUSH(hw);
+
+	msec_delay(10);
+
+	/* Determine whether or not a global dev reset is requested */
+	if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw,
+	    swmbsw_mask))
+			global_device_reset = false;
+
+	if (global_device_reset && !(IGC_READ_REG(hw, IGC_STATUS) &
+	    IGC_STAT_DEV_RST_SET))
+		ctrl |= IGC_CTRL_DEV_RST;
+	else
+		ctrl |= IGC_CTRL_RST;
+
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	switch (hw->device_id) {
+	case IGC_DEV_ID_DH89XXCC_SGMII:
+		break;
+	default:
+		IGC_WRITE_FLUSH(hw);
+		break;
+	}
+
+	/* Add delay to insure DEV_RST or RST has time to complete */
+	msec_delay(5);
+
+	ret_val = igc_get_auto_rd_done_generic(hw);
+	if (ret_val) {
+		/*
+		 * When auto config read does not complete, do not
+		 * return with an error. This can happen in situations
+		 * where there is no eeprom and prevents getting link.
+		 */
+		DEBUGOUT("Auto Read Done did not complete\n");
+	}
+
+	/* clear global device reset status bit */
+	IGC_WRITE_REG(hw, IGC_STATUS, IGC_STAT_DEV_RST_SET);
+
+	/* Clear any pending interrupt events. */
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_READ_REG(hw, IGC_ICR);
+
+	ret_val = igc_reset_mdicnfg_82580(hw);
+	if (ret_val)
+		DEBUGOUT("Could not reset MDICNFG based on EEPROM\n");
+
+	/* Install any alternate MAC address into RAR0 */
+	ret_val = igc_check_alt_mac_addr_generic(hw);
+
+	/* Release semaphore */
+	if (global_device_reset)
+		hw->mac.ops.release_swfw_sync(hw, swmbsw_mask);
+
+	return ret_val;
+}
+
+/**
+ *  igc_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size
+ *  @data: data received by reading RXPBS register
+ *
+ *  The 82580 uses a table based approach for packet buffer allocation sizes.
+ *  This function converts the retrieved value into the correct table value
+ *     0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
+ *  0x0 36  72 144   1   2   4   8  16
+ *  0x8 35  70 140 rsv rsv rsv rsv rsv
+ */
+u16 igc_rxpbs_adjust_82580(u32 data)
+{
+	u16 ret_val = 0;
+
+	if (data < IGC_82580_RXPBS_TABLE_SIZE)
+		ret_val = igc_82580_rxpbs_table[data];
+
+	return ret_val;
+}
+
+/**
+ *  igc_validate_nvm_checksum_with_offset - Validate EEPROM
+ *  checksum
+ *  @hw: pointer to the HW structure
+ *  @offset: offset in words of the checksum protected region
+ *
+ *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 igc_validate_nvm_checksum_with_offset(struct igc_hw *hw, u16 offset)
+{
+	s32 ret_val = IGC_SUCCESS;
+	u16 checksum = 0;
+	u16 i, nvm_data;
+
+	DEBUGFUNC("igc_validate_nvm_checksum_with_offset");
+
+	for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
+		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+		if (ret_val) {
+			DEBUGOUT("NVM Read Error\n");
+			goto out;
+		}
+		checksum += nvm_data;
+	}
+
+	if (checksum != (u16) NVM_SUM) {
+		DEBUGOUT("NVM Checksum Invalid\n");
+		ret_val = -IGC_ERR_NVM;
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_update_nvm_checksum_with_offset - Update EEPROM
+ *  checksum
+ *  @hw: pointer to the HW structure
+ *  @offset: offset in words of the checksum protected region
+ *
+ *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  up to the checksum.  Then calculates the EEPROM checksum and writes the
+ *  value to the EEPROM.
+ **/
+s32 igc_update_nvm_checksum_with_offset(struct igc_hw *hw, u16 offset)
+{
+	s32 ret_val;
+	u16 checksum = 0;
+	u16 i, nvm_data;
+
+	DEBUGFUNC("igc_update_nvm_checksum_with_offset");
+
+	for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
+		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+		if (ret_val) {
+			DEBUGOUT("NVM Read Error while updating checksum.\n");
+			goto out;
+		}
+		checksum += nvm_data;
+	}
+	checksum = (u16) NVM_SUM - checksum;
+	ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
+				    &checksum);
+	if (ret_val)
+		DEBUGOUT("NVM Write Error while updating checksum.\n");
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_validate_nvm_checksum_82580 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM section checksum by reading/adding each word of
+ *  the EEPROM and then verifies that the sum of the EEPROM is
+ *  equal to 0xBABA.
+ **/
+STATIC s32 igc_validate_nvm_checksum_82580(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u16 eeprom_regions_count = 1;
+	u16 j, nvm_data;
+	u16 nvm_offset;
+
+	DEBUGFUNC("igc_validate_nvm_checksum_82580");
+
+	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		goto out;
+	}
+
+	if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
+		/* if chekcsums compatibility bit is set validate checksums
+		 * for all 4 ports. */
+		eeprom_regions_count = 4;
+	}
+
+	for (j = 0; j < eeprom_regions_count; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igc_validate_nvm_checksum_with_offset(hw,
+								  nvm_offset);
+		if (ret_val != IGC_SUCCESS)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_update_nvm_checksum_82580 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM section checksums for all 4 ports by reading/adding
+ *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
+ *  checksum and writes the value to the EEPROM.
+ **/
+STATIC s32 igc_update_nvm_checksum_82580(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u16 j, nvm_data;
+	u16 nvm_offset;
+
+	DEBUGFUNC("igc_update_nvm_checksum_82580");
+
+	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n");
+		goto out;
+	}
+
+	if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) {
+		/* set compatibility bit to validate checksums appropriately */
+		nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
+		ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
+					    &nvm_data);
+		if (ret_val) {
+			DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n");
+			goto out;
+		}
+	}
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igc_update_nvm_checksum_with_offset(hw, nvm_offset);
+		if (ret_val)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_validate_nvm_checksum_i350 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM section checksum by reading/adding each word of
+ *  the EEPROM and then verifies that the sum of the EEPROM is
+ *  equal to 0xBABA.
+ **/
+STATIC s32 igc_validate_nvm_checksum_i350(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	u16 j;
+	u16 nvm_offset;
+
+	DEBUGFUNC("igc_validate_nvm_checksum_i350");
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igc_validate_nvm_checksum_with_offset(hw,
+								  nvm_offset);
+		if (ret_val != IGC_SUCCESS)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_update_nvm_checksum_i350 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM section checksums for all 4 ports by reading/adding
+ *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
+ *  checksum and writes the value to the EEPROM.
+ **/
+STATIC s32 igc_update_nvm_checksum_i350(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	u16 j;
+	u16 nvm_offset;
+
+	DEBUGFUNC("igc_update_nvm_checksum_i350");
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igc_update_nvm_checksum_with_offset(hw, nvm_offset);
+		if (ret_val != IGC_SUCCESS)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  __igc_access_emi_reg - Read/write EMI register
+ *  @hw: pointer to the HW structure
+ *  @address: EMI address to program
+ *  @data: pointer to value to read/write from/to the EMI address
+ *  @read: boolean flag to indicate read or write
+ **/
+STATIC s32 __igc_access_emi_reg(struct igc_hw *hw, u16 address,
+				  u16 *data, bool read)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("__igc_access_emi_reg");
+
+	ret_val = hw->phy.ops.write_reg(hw, IGC_EMIADD, address);
+	if (ret_val)
+		return ret_val;
+
+	if (read)
+		ret_val = hw->phy.ops.read_reg(hw, IGC_EMIDATA, data);
+	else
+		ret_val = hw->phy.ops.write_reg(hw, IGC_EMIDATA, *data);
+
+	return ret_val;
+}
+
+/**
+ *  igc_read_emi_reg - Read Extended Management Interface register
+ *  @hw: pointer to the HW structure
+ *  @addr: EMI address to program
+ *  @data: value to be read from the EMI address
+ **/
+s32 igc_read_emi_reg(struct igc_hw *hw, u16 addr, u16 *data)
+{
+	DEBUGFUNC("igc_read_emi_reg");
+
+	return __igc_access_emi_reg(hw, addr, data, true);
+}
+
+/**
+ *  igc_initialize_M88E1512_phy - Initialize M88E1512 PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Initialize Marvell 1512 to work correctly with Avoton.
+ **/
+s32 igc_initialize_M88E1512_phy(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_initialize_M88E1512_phy");
+
+	/* Check if this is correct PHY. */
+	if (phy->id != M88E1512_E_PHY_ID)
+		goto out;
+
+	/* Switch to PHY page 0xFF. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0x00FF);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_2, 0x214B);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_1, 0x2144);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_2, 0x0C28);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_1, 0x2146);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_2, 0xB233);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_1, 0x214D);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_2, 0xCC0C);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_1, 0x2159);
+	if (ret_val)
+		goto out;
+
+	/* Switch to PHY page 0xFB. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0x00FB);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_3, 0x000D);
+	if (ret_val)
+		goto out;
+
+	/* Switch to PHY page 0x12. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0x12);
+	if (ret_val)
+		goto out;
+
+	/* Change mode to SGMII-to-Copper */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_MODE, 0x8001);
+	if (ret_val)
+		goto out;
+
+	/* Return the PHY to page 0. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.commit(hw);
+	if (ret_val) {
+		DEBUGOUT("Error committing the PHY changes\n");
+		return ret_val;
+	}
+
+	msec_delay(1000);
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_initialize_M88E1543_phy - Initialize M88E1543 PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Initialize Marvell 1543 to work correctly with Avoton.
+ **/
+s32 igc_initialize_M88E1543_phy(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_initialize_M88E1543_phy");
+
+	/* Check if this is correct PHY. */
+	if (phy->id != M88E1543_E_PHY_ID)
+		goto out;
+
+	/* Switch to PHY page 0xFF. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0x00FF);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_2, 0x214B);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_1, 0x2144);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_2, 0x0C28);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_1, 0x2146);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_2, 0xB233);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_1, 0x214D);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_2, 0xDC0C);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_1, 0x2159);
+	if (ret_val)
+		goto out;
+
+	/* Switch to PHY page 0xFB. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0x00FB);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_CFG_REG_3, 0xC00D);
+	if (ret_val)
+		goto out;
+
+	/* Switch to PHY page 0x12. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0x12);
+	if (ret_val)
+		goto out;
+
+	/* Change mode to SGMII-to-Copper */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1512_MODE, 0x8001);
+	if (ret_val)
+		goto out;
+
+	/* Switch to PHY page 1. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0x1);
+	if (ret_val)
+		goto out;
+
+	/* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_FIBER_CTRL, 0x9140);
+	if (ret_val)
+		goto out;
+
+	/* Return the PHY to page 0. */
+	ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.commit(hw);
+	if (ret_val) {
+		DEBUGOUT("Error committing the PHY changes\n");
+		return ret_val;
+	}
+
+	msec_delay(1000);
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_set_eee_i350 - Enable/disable EEE support
+ *  @hw: pointer to the HW structure
+ *  @adv1G: boolean flag enabling 1G EEE advertisement
+ *  @adv100M: boolean flag enabling 100M EEE advertisement
+ *
+ *  Enable/disable EEE based on setting in dev_spec structure.
+ *
+ **/
+s32 igc_set_eee_i350(struct igc_hw *hw, bool adv1G, bool adv100M)
+{
+	u32 ipcnfg, eeer;
+
+	DEBUGFUNC("igc_set_eee_i350");
+
+	if ((hw->mac.type < igc_i350) ||
+	    (hw->phy.media_type != igc_media_type_copper))
+		goto out;
+	ipcnfg = IGC_READ_REG(hw, IGC_IPCNFG);
+	eeer = IGC_READ_REG(hw, IGC_EEER);
+
+	/* enable or disable per user setting */
+	if (!(hw->dev_spec._82575.eee_disable)) {
+		u32 eee_su = IGC_READ_REG(hw, IGC_EEE_SU);
+
+		if (adv100M)
+			ipcnfg |= IGC_IPCNFG_EEE_100M_AN;
+		else
+			ipcnfg &= ~IGC_IPCNFG_EEE_100M_AN;
+
+		if (adv1G)
+			ipcnfg |= IGC_IPCNFG_EEE_1G_AN;
+		else
+			ipcnfg &= ~IGC_IPCNFG_EEE_1G_AN;
+
+		eeer |= (IGC_EEER_TX_LPI_EN | IGC_EEER_RX_LPI_EN |
+			 IGC_EEER_LPI_FC);
+
+		/* This bit should not be set in normal operation. */
+		if (eee_su & IGC_EEE_SU_LPI_CLK_STP)
+			DEBUGOUT("LPI Clock Stop Bit should not be set!\n");
+	} else {
+		ipcnfg &= ~(IGC_IPCNFG_EEE_1G_AN | IGC_IPCNFG_EEE_100M_AN);
+		eeer &= ~(IGC_EEER_TX_LPI_EN | IGC_EEER_RX_LPI_EN |
+			  IGC_EEER_LPI_FC);
+	}
+	IGC_WRITE_REG(hw, IGC_IPCNFG, ipcnfg);
+	IGC_WRITE_REG(hw, IGC_EEER, eeer);
+	IGC_READ_REG(hw, IGC_IPCNFG);
+	IGC_READ_REG(hw, IGC_EEER);
+out:
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_set_eee_i354 - Enable/disable EEE support
+ *  @hw: pointer to the HW structure
+ *  @adv1G: boolean flag enabling 1G EEE advertisement
+ *  @adv100M: boolean flag enabling 100M EEE advertisement
+ *
+ *  Enable/disable EEE legacy mode based on setting in dev_spec structure.
+ *
+ **/
+s32 igc_set_eee_i354(struct igc_hw *hw, bool adv1G, bool adv100M)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+	u16 phy_data;
+
+	DEBUGFUNC("igc_set_eee_i354");
+
+	if ((hw->phy.media_type != igc_media_type_copper) ||
+	    ((phy->id != M88E1543_E_PHY_ID) &&
+	    (phy->id != M88E1512_E_PHY_ID)))
+		goto out;
+
+	if (!hw->dev_spec._82575.eee_disable) {
+		/* Switch to PHY page 18. */
+		ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 18);
+		if (ret_val)
+			goto out;
+
+		ret_val = phy->ops.read_reg(hw, IGC_M88E1543_EEE_CTRL_1,
+					    &phy_data);
+		if (ret_val)
+			goto out;
+
+		phy_data |= IGC_M88E1543_EEE_CTRL_1_MS;
+		ret_val = phy->ops.write_reg(hw, IGC_M88E1543_EEE_CTRL_1,
+					     phy_data);
+		if (ret_val)
+			goto out;
+
+		/* Return the PHY to page 0. */
+		ret_val = phy->ops.write_reg(hw, IGC_M88E1543_PAGE_ADDR, 0);
+		if (ret_val)
+			goto out;
+
+		/* Turn on EEE advertisement. */
+		ret_val = igc_read_xmdio_reg(hw, IGC_EEE_ADV_ADDR_I354,
+					       IGC_EEE_ADV_DEV_I354,
+					       &phy_data);
+		if (ret_val)
+			goto out;
+
+		if (adv100M)
+			phy_data |= IGC_EEE_ADV_100_SUPPORTED;
+		else
+			phy_data &= ~IGC_EEE_ADV_100_SUPPORTED;
+
+		if (adv1G)
+			phy_data |= IGC_EEE_ADV_1000_SUPPORTED;
+		else
+			phy_data &= ~IGC_EEE_ADV_1000_SUPPORTED;
+
+		ret_val = igc_write_xmdio_reg(hw, IGC_EEE_ADV_ADDR_I354,
+						IGC_EEE_ADV_DEV_I354,
+						phy_data);
+	} else {
+		/* Turn off EEE advertisement. */
+		ret_val = igc_read_xmdio_reg(hw, IGC_EEE_ADV_ADDR_I354,
+					       IGC_EEE_ADV_DEV_I354,
+					       &phy_data);
+		if (ret_val)
+			goto out;
+
+		phy_data &= ~(IGC_EEE_ADV_100_SUPPORTED |
+			      IGC_EEE_ADV_1000_SUPPORTED);
+		ret_val = igc_write_xmdio_reg(hw, IGC_EEE_ADV_ADDR_I354,
+						IGC_EEE_ADV_DEV_I354,
+						phy_data);
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_get_eee_status_i354 - Get EEE status
+ *  @hw: pointer to the HW structure
+ *  @status: EEE status
+ *
+ *  Get EEE status by guessing based on whether Tx or Rx LPI indications have
+ *  been received.
+ **/
+s32 igc_get_eee_status_i354(struct igc_hw *hw, bool *status)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+	u16 phy_data;
+
+	DEBUGFUNC("igc_get_eee_status_i354");
+
+	/* Check if EEE is supported on this device. */
+	if ((hw->phy.media_type != igc_media_type_copper) ||
+	    ((phy->id != M88E1543_E_PHY_ID) &&
+	    (phy->id != M88E1512_E_PHY_ID)))
+		goto out;
+
+	ret_val = igc_read_xmdio_reg(hw, IGC_PCS_STATUS_ADDR_I354,
+				       IGC_PCS_STATUS_DEV_I354,
+				       &phy_data);
+	if (ret_val)
+		goto out;
+
+	*status = phy_data & (IGC_PCS_STATUS_TX_LPI_RCVD |
+			      IGC_PCS_STATUS_RX_LPI_RCVD) ? true : false;
+
+out:
+	return ret_val;
+}
+
+/* Due to a hw errata, if the host tries to  configure the VFTA register
+ * while performing queries from the BMC or DMA, then the VFTA in some
+ * cases won't be written.
+ */
+
+/**
+ *  igc_clear_vfta_i350 - Clear VLAN filter table
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the register array which contains the VLAN filter table by
+ *  setting all the values to 0.
+ **/
+void igc_clear_vfta_i350(struct igc_hw *hw)
+{
+	u32 offset;
+	int i;
+
+	DEBUGFUNC("igc_clear_vfta_350");
+
+	for (offset = 0; offset < IGC_VLAN_FILTER_TBL_SIZE; offset++) {
+		for (i = 0; i < 10; i++)
+			IGC_WRITE_REG_ARRAY(hw, IGC_VFTA, offset, 0);
+
+		IGC_WRITE_FLUSH(hw);
+	}
+}
+
+/**
+ *  igc_write_vfta_i350 - Write value to VLAN filter table
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset in VLAN filter table
+ *  @value: register value written to VLAN filter table
+ *
+ *  Writes value at the given offset in the register array which stores
+ *  the VLAN filter table.
+ **/
+void igc_write_vfta_i350(struct igc_hw *hw, u32 offset, u32 value)
+{
+	int i;
+
+	DEBUGFUNC("igc_write_vfta_350");
+
+	for (i = 0; i < 10; i++)
+		IGC_WRITE_REG_ARRAY(hw, IGC_VFTA, offset, value);
+
+	IGC_WRITE_FLUSH(hw);
+}
+
+
+/**
+ *  igc_set_i2c_bb - Enable I2C bit-bang
+ *  @hw: pointer to the HW structure
+ *
+ *  Enable I2C bit-bang interface
+ *
+ **/
+s32 igc_set_i2c_bb(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+	u32 ctrl_ext, i2cparams;
+
+	DEBUGFUNC("igc_set_i2c_bb");
+
+	ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+	ctrl_ext |= IGC_CTRL_I2C_ENA;
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+	IGC_WRITE_FLUSH(hw);
+
+	i2cparams = IGC_READ_REG(hw, IGC_I2CPARAMS);
+	i2cparams |= IGC_I2CBB_EN;
+	i2cparams |= IGC_I2C_DATA_OE_N;
+	i2cparams |= IGC_I2C_CLK_OE_N;
+	IGC_WRITE_REG(hw, IGC_I2CPARAMS, i2cparams);
+	IGC_WRITE_FLUSH(hw);
+
+	return ret_val;
+}
+
+/**
+ *  igc_read_i2c_byte_generic - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @dev_addr: device address
+ *  @data: value read
+ *
+ *  Performs byte read operation over I2C interface at
+ *  a specified device address.
+ **/
+s32 igc_read_i2c_byte_generic(struct igc_hw *hw, u8 byte_offset,
+				u8 dev_addr, u8 *data)
+{
+	s32 status = IGC_SUCCESS;
+	u32 max_retry = 10;
+	u32 retry = 1;
+	u16 swfw_mask = 0;
+
+	bool nack = true;
+
+	DEBUGFUNC("igc_read_i2c_byte_generic");
+
+	swfw_mask = IGC_SWFW_PHY0_SM;
+
+	do {
+		if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
+		    != IGC_SUCCESS) {
+			status = IGC_ERR_SWFW_SYNC;
+			goto read_byte_out;
+		}
+
+		igc_i2c_start(hw);
+
+		/* Device Address and write indication */
+		status = igc_clock_out_i2c_byte(hw, dev_addr);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_get_i2c_ack(hw);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_clock_out_i2c_byte(hw, byte_offset);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_get_i2c_ack(hw);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		igc_i2c_start(hw);
+
+		/* Device Address and read indication */
+		status = igc_clock_out_i2c_byte(hw, (dev_addr | 0x1));
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_get_i2c_ack(hw);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		igc_clock_in_i2c_byte(hw, data);
+
+		status = igc_clock_out_i2c_bit(hw, nack);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		igc_i2c_stop(hw);
+		break;
+
+fail:
+		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+		msec_delay(100);
+		igc_i2c_bus_clear(hw);
+		retry++;
+		if (retry < max_retry)
+			DEBUGOUT("I2C byte read error - Retrying.\n");
+		else
+			DEBUGOUT("I2C byte read error.\n");
+
+	} while (retry < max_retry);
+
+	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+read_byte_out:
+
+	return status;
+}
+
+/**
+ *  igc_write_i2c_byte_generic - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @dev_addr: device address
+ *  @data: value to write
+ *
+ *  Performs byte write operation over I2C interface at
+ *  a specified device address.
+ **/
+s32 igc_write_i2c_byte_generic(struct igc_hw *hw, u8 byte_offset,
+				 u8 dev_addr, u8 data)
+{
+	s32 status = IGC_SUCCESS;
+	u32 max_retry = 1;
+	u32 retry = 0;
+	u16 swfw_mask = 0;
+
+	DEBUGFUNC("igc_write_i2c_byte_generic");
+
+	swfw_mask = IGC_SWFW_PHY0_SM;
+
+	if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != IGC_SUCCESS) {
+		status = IGC_ERR_SWFW_SYNC;
+		goto write_byte_out;
+	}
+
+	do {
+		igc_i2c_start(hw);
+
+		status = igc_clock_out_i2c_byte(hw, dev_addr);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_get_i2c_ack(hw);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_clock_out_i2c_byte(hw, byte_offset);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_get_i2c_ack(hw);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_clock_out_i2c_byte(hw, data);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		status = igc_get_i2c_ack(hw);
+		if (status != IGC_SUCCESS)
+			goto fail;
+
+		igc_i2c_stop(hw);
+		break;
+
+fail:
+		igc_i2c_bus_clear(hw);
+		retry++;
+		if (retry < max_retry)
+			DEBUGOUT("I2C byte write error - Retrying.\n");
+		else
+			DEBUGOUT("I2C byte write error.\n");
+	} while (retry < max_retry);
+
+	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+write_byte_out:
+
+	return status;
+}
+
+/**
+ *  igc_i2c_start - Sets I2C start condition
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets I2C start condition (High -> Low on SDA while SCL is High)
+ **/
+STATIC void igc_i2c_start(struct igc_hw *hw)
+{
+	u32 i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+
+	DEBUGFUNC("igc_i2c_start");
+
+	/* Start condition must begin with data and clock high */
+	igc_set_i2c_data(hw, &i2cctl, 1);
+	igc_raise_i2c_clk(hw, &i2cctl);
+
+	/* Setup time for start condition (4.7us) */
+	usec_delay(IGC_I2C_T_SU_STA);
+
+	igc_set_i2c_data(hw, &i2cctl, 0);
+
+	/* Hold time for start condition (4us) */
+	usec_delay(IGC_I2C_T_HD_STA);
+
+	igc_lower_i2c_clk(hw, &i2cctl);
+
+	/* Minimum low period of clock is 4.7 us */
+	usec_delay(IGC_I2C_T_LOW);
+
+}
+
+/**
+ *  igc_i2c_stop - Sets I2C stop condition
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
+ **/
+STATIC void igc_i2c_stop(struct igc_hw *hw)
+{
+	u32 i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+
+	DEBUGFUNC("igc_i2c_stop");
+
+	/* Stop condition must begin with data low and clock high */
+	igc_set_i2c_data(hw, &i2cctl, 0);
+	igc_raise_i2c_clk(hw, &i2cctl);
+
+	/* Setup time for stop condition (4us) */
+	usec_delay(IGC_I2C_T_SU_STO);
+
+	igc_set_i2c_data(hw, &i2cctl, 1);
+
+	/* bus free time between stop and start (4.7us)*/
+	usec_delay(IGC_I2C_T_BUF);
+}
+
+/**
+ *  igc_clock_in_i2c_byte - Clocks in one byte via I2C
+ *  @hw: pointer to hardware structure
+ *  @data: data byte to clock in
+ *
+ *  Clocks in one byte data via I2C data/clock
+ **/
+STATIC void igc_clock_in_i2c_byte(struct igc_hw *hw, u8 *data)
+{
+	s32 i;
+	bool bit = 0;
+
+	DEBUGFUNC("igc_clock_in_i2c_byte");
+
+	*data = 0;
+	for (i = 7; i >= 0; i--) {
+		igc_clock_in_i2c_bit(hw, &bit);
+		*data |= bit << i;
+	}
+}
+
+/**
+ *  igc_clock_out_i2c_byte - Clocks out one byte via I2C
+ *  @hw: pointer to hardware structure
+ *  @data: data byte clocked out
+ *
+ *  Clocks out one byte data via I2C data/clock
+ **/
+STATIC s32 igc_clock_out_i2c_byte(struct igc_hw *hw, u8 data)
+{
+	s32 status = IGC_SUCCESS;
+	s32 i;
+	u32 i2cctl;
+	bool bit = 0;
+
+	DEBUGFUNC("igc_clock_out_i2c_byte");
+
+	for (i = 7; i >= 0; i--) {
+		bit = (data >> i) & 0x1;
+		status = igc_clock_out_i2c_bit(hw, bit);
+
+		if (status != IGC_SUCCESS)
+			break;
+	}
+
+	/* Release SDA line (set high) */
+	i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+
+	i2cctl |= IGC_I2C_DATA_OE_N;
+	IGC_WRITE_REG(hw, IGC_I2CPARAMS, i2cctl);
+	IGC_WRITE_FLUSH(hw);
+
+	return status;
+}
+
+/**
+ *  igc_get_i2c_ack - Polls for I2C ACK
+ *  @hw: pointer to hardware structure
+ *
+ *  Clocks in/out one bit via I2C data/clock
+ **/
+STATIC s32 igc_get_i2c_ack(struct igc_hw *hw)
+{
+	s32 status = IGC_SUCCESS;
+	u32 i = 0;
+	u32 i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+	u32 timeout = 10;
+	bool ack = true;
+
+	DEBUGFUNC("igc_get_i2c_ack");
+
+	igc_raise_i2c_clk(hw, &i2cctl);
+
+	/* Minimum high period of clock is 4us */
+	usec_delay(IGC_I2C_T_HIGH);
+
+	/* Wait until SCL returns high */
+	for (i = 0; i < timeout; i++) {
+		usec_delay(1);
+		i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+		if (i2cctl & IGC_I2C_CLK_IN)
+			break;
+	}
+	if (!(i2cctl & IGC_I2C_CLK_IN))
+		return IGC_ERR_I2C;
+
+	ack = igc_get_i2c_data(&i2cctl);
+	if (ack) {
+		DEBUGOUT("I2C ack was not received.\n");
+		status = IGC_ERR_I2C;
+	}
+
+	igc_lower_i2c_clk(hw, &i2cctl);
+
+	/* Minimum low period of clock is 4.7 us */
+	usec_delay(IGC_I2C_T_LOW);
+
+	return status;
+}
+
+/**
+ *  igc_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
+ *  @hw: pointer to hardware structure
+ *  @data: read data value
+ *
+ *  Clocks in one bit via I2C data/clock
+ **/
+STATIC void igc_clock_in_i2c_bit(struct igc_hw *hw, bool *data)
+{
+	u32 i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+
+	DEBUGFUNC("igc_clock_in_i2c_bit");
+
+	igc_raise_i2c_clk(hw, &i2cctl);
+
+	/* Minimum high period of clock is 4us */
+	usec_delay(IGC_I2C_T_HIGH);
+
+	i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+	*data = igc_get_i2c_data(&i2cctl);
+
+	igc_lower_i2c_clk(hw, &i2cctl);
+
+	/* Minimum low period of clock is 4.7 us */
+	usec_delay(IGC_I2C_T_LOW);
+}
+
+/**
+ *  igc_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
+ *  @hw: pointer to hardware structure
+ *  @data: data value to write
+ *
+ *  Clocks out one bit via I2C data/clock
+ **/
+STATIC s32 igc_clock_out_i2c_bit(struct igc_hw *hw, bool data)
+{
+	s32 status;
+	u32 i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+
+	DEBUGFUNC("igc_clock_out_i2c_bit");
+
+	status = igc_set_i2c_data(hw, &i2cctl, data);
+	if (status == IGC_SUCCESS) {
+		igc_raise_i2c_clk(hw, &i2cctl);
+
+		/* Minimum high period of clock is 4us */
+		usec_delay(IGC_I2C_T_HIGH);
+
+		igc_lower_i2c_clk(hw, &i2cctl);
+
+		/* Minimum low period of clock is 4.7 us.
+		 * This also takes care of the data hold time.
+		 */
+		usec_delay(IGC_I2C_T_LOW);
+	} else {
+		status = IGC_ERR_I2C;
+		DEBUGOUT1("I2C data was not set to %X\n", data);
+	}
+
+	return status;
+}
+/**
+ *  igc_raise_i2c_clk - Raises the I2C SCL clock
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Raises the I2C clock line '0'->'1'
+ **/
+STATIC void igc_raise_i2c_clk(struct igc_hw *hw, u32 *i2cctl)
+{
+	DEBUGFUNC("igc_raise_i2c_clk");
+
+	*i2cctl |= IGC_I2C_CLK_OUT;
+	*i2cctl &= ~IGC_I2C_CLK_OE_N;
+	IGC_WRITE_REG(hw, IGC_I2CPARAMS, *i2cctl);
+	IGC_WRITE_FLUSH(hw);
+
+	/* SCL rise time (1000ns) */
+	usec_delay(IGC_I2C_T_RISE);
+}
+
+/**
+ *  igc_lower_i2c_clk - Lowers the I2C SCL clock
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Lowers the I2C clock line '1'->'0'
+ **/
+STATIC void igc_lower_i2c_clk(struct igc_hw *hw, u32 *i2cctl)
+{
+
+	DEBUGFUNC("igc_lower_i2c_clk");
+
+	*i2cctl &= ~IGC_I2C_CLK_OUT;
+	*i2cctl &= ~IGC_I2C_CLK_OE_N;
+	IGC_WRITE_REG(hw, IGC_I2CPARAMS, *i2cctl);
+	IGC_WRITE_FLUSH(hw);
+
+	/* SCL fall time (300ns) */
+	usec_delay(IGC_I2C_T_FALL);
+}
+
+/**
+ *  igc_set_i2c_data - Sets the I2C data bit
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *  @data: I2C data value (0 or 1) to set
+ *
+ *  Sets the I2C data bit
+ **/
+STATIC s32 igc_set_i2c_data(struct igc_hw *hw, u32 *i2cctl, bool data)
+{
+	s32 status = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_set_i2c_data");
+
+	if (data)
+		*i2cctl |= IGC_I2C_DATA_OUT;
+	else
+		*i2cctl &= ~IGC_I2C_DATA_OUT;
+
+	*i2cctl &= ~IGC_I2C_DATA_OE_N;
+	*i2cctl |= IGC_I2C_CLK_OE_N;
+	IGC_WRITE_REG(hw, IGC_I2CPARAMS, *i2cctl);
+	IGC_WRITE_FLUSH(hw);
+
+	/* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
+	usec_delay(IGC_I2C_T_RISE + IGC_I2C_T_FALL + IGC_I2C_T_SU_DATA);
+
+	*i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+	if (data != igc_get_i2c_data(i2cctl)) {
+		status = IGC_ERR_I2C;
+		DEBUGOUT1("Error - I2C data was not set to %X.\n", data);
+	}
+
+	return status;
+}
+
+/**
+ *  igc_get_i2c_data - Reads the I2C SDA data bit
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Returns the I2C data bit value
+ **/
+STATIC bool igc_get_i2c_data(u32 *i2cctl)
+{
+	bool data;
+
+	DEBUGFUNC("igc_get_i2c_data");
+
+	if (*i2cctl & IGC_I2C_DATA_IN)
+		data = 1;
+	else
+		data = 0;
+
+	return data;
+}
+
+/**
+ *  igc_i2c_bus_clear - Clears the I2C bus
+ *  @hw: pointer to hardware structure
+ *
+ *  Clears the I2C bus by sending nine clock pulses.
+ *  Used when data line is stuck low.
+ **/
+void igc_i2c_bus_clear(struct igc_hw *hw)
+{
+	u32 i2cctl = IGC_READ_REG(hw, IGC_I2CPARAMS);
+	u32 i;
+
+	DEBUGFUNC("igc_i2c_bus_clear");
+
+	igc_i2c_start(hw);
+
+	igc_set_i2c_data(hw, &i2cctl, 1);
+
+	for (i = 0; i < 9; i++) {
+		igc_raise_i2c_clk(hw, &i2cctl);
+
+		/* Min high period of clock is 4us */
+		usec_delay(IGC_I2C_T_HIGH);
+
+		igc_lower_i2c_clk(hw, &i2cctl);
+
+		/* Min low period of clock is 4.7us*/
+		usec_delay(IGC_I2C_T_LOW);
+	}
+
+	igc_i2c_start(hw);
+
+	/* Put the i2c bus back to default state */
+	igc_i2c_stop(hw);
+}
+
diff --git a/drivers/net/igc/base/e1000_82575.h b/drivers/net/igc/base/e1000_82575.h
new file mode 100644
index 0000000..1b8ad1b
--- /dev/null
+++ b/drivers/net/igc/base/e1000_82575.h
@@ -0,0 +1,381 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_82575_H_
+#define _IGC_82575_H_
+
+#define ID_LED_DEFAULT_82575_SERDES	((ID_LED_DEF1_DEF2 << 12) | \
+					 (ID_LED_DEF1_DEF2 <<  8) | \
+					 (ID_LED_DEF1_DEF2 <<  4) | \
+					 (ID_LED_OFF1_ON2))
+/*
+ * Receive Address Register Count
+ * Number of high/low register pairs in the RAR.  The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor.
+ * These entries are also used for MAC-based filtering.
+ */
+/*
+ * For 82576, there are an additional set of RARs that begin at an offset
+ * separate from the first set of RARs.
+ */
+#define IGC_RAR_ENTRIES_82575	16
+#define IGC_RAR_ENTRIES_82576	24
+#define IGC_RAR_ENTRIES_82580	24
+#define IGC_RAR_ENTRIES_I350	32
+#define IGC_SW_SYNCH_MB	0x00000100
+#define IGC_STAT_DEV_RST_SET	0x00100000
+
+struct igc_adv_data_desc {
+	__le64 buffer_addr;    /* Address of the descriptor's data buffer */
+	union {
+		u32 data;
+		struct {
+			u32 datalen:16; /* Data buffer length */
+			u32 rsvd:4;
+			u32 dtyp:4;  /* Descriptor type */
+			u32 dcmd:8;  /* Descriptor command */
+		} config;
+	} lower;
+	union {
+		u32 data;
+		struct {
+			u32 status:4;  /* Descriptor status */
+			u32 idx:4;
+			u32 popts:6;  /* Packet Options */
+			u32 paylen:18; /* Payload length */
+		} options;
+	} upper;
+};
+
+#define IGC_TXD_DTYP_ADV_C	0x2  /* Advanced Context Descriptor */
+#define IGC_TXD_DTYP_ADV_D	0x3  /* Advanced Data Descriptor */
+#define IGC_ADV_TXD_CMD_DEXT	0x20 /* Descriptor extension (0 = legacy) */
+#define IGC_ADV_TUCMD_IPV4	0x2  /* IP Packet Type: 1=IPv4 */
+#define IGC_ADV_TUCMD_IPV6	0x0  /* IP Packet Type: 0=IPv6 */
+#define IGC_ADV_TUCMD_L4T_UDP	0x0  /* L4 Packet TYPE of UDP */
+#define IGC_ADV_TUCMD_L4T_TCP	0x4  /* L4 Packet TYPE of TCP */
+#define IGC_ADV_TUCMD_MKRREQ	0x10 /* Indicates markers are required */
+#define IGC_ADV_DCMD_EOP	0x1  /* End of Packet */
+#define IGC_ADV_DCMD_IFCS	0x2  /* Insert FCS (Ethernet CRC) */
+#define IGC_ADV_DCMD_RS	0x8  /* Report Status */
+#define IGC_ADV_DCMD_VLE	0x40 /* Add VLAN tag */
+#define IGC_ADV_DCMD_TSE	0x80 /* TCP Seg enable */
+/* Extended Device Control */
+#define IGC_CTRL_EXT_NSICR	0x00000001 /* Disable Intr Clear all on read */
+
+struct igc_adv_context_desc {
+	union {
+		u32 ip_config;
+		struct {
+			u32 iplen:9;
+			u32 maclen:7;
+			u32 vlan_tag:16;
+		} fields;
+	} ip_setup;
+	u32 seq_num;
+	union {
+		u64 l4_config;
+		struct {
+			u32 mkrloc:9;
+			u32 tucmd:11;
+			u32 dtyp:4;
+			u32 adv:8;
+			u32 rsvd:4;
+			u32 idx:4;
+			u32 l4len:8;
+			u32 mss:16;
+		} fields;
+	} l4_setup;
+};
+
+/* SRRCTL bit definitions */
+#define IGC_SRRCTL_BSIZEHDRSIZE_MASK		0x00000F00
+#define IGC_SRRCTL_DESCTYPE_LEGACY		0x00000000
+#define IGC_SRRCTL_DESCTYPE_HDR_SPLIT		0x04000000
+#define IGC_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS	0x0A000000
+#define IGC_SRRCTL_DESCTYPE_HDR_REPLICATION	0x06000000
+#define IGC_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
+#define IGC_SRRCTL_DESCTYPE_MASK		0x0E000000
+#define IGC_SRRCTL_TIMESTAMP			0x40000000
+#define IGC_SRRCTL_DROP_EN			0x80000000
+
+#define IGC_SRRCTL_BSIZEPKT_MASK		0x0000007F
+#define IGC_SRRCTL_BSIZEHDR_MASK		0x00003F00
+
+#define IGC_TX_HEAD_WB_ENABLE		0x1
+#define IGC_TX_SEQNUM_WB_ENABLE	0x2
+
+#define IGC_MRQC_ENABLE_RSS_4Q		0x00000002
+#define IGC_MRQC_ENABLE_VMDQ			0x00000003
+#define IGC_MRQC_ENABLE_VMDQ_RSS_2Q		0x00000005
+#define IGC_MRQC_RSS_FIELD_IPV4_UDP		0x00400000
+#define IGC_MRQC_RSS_FIELD_IPV6_UDP		0x00800000
+#define IGC_MRQC_RSS_FIELD_IPV6_UDP_EX	0x01000000
+#define IGC_MRQC_ENABLE_RSS_8Q		0x00000002
+
+#define IGC_VMRCTL_MIRROR_PORT_SHIFT		8
+#define IGC_VMRCTL_MIRROR_DSTPORT_MASK	(7 << \
+						 IGC_VMRCTL_MIRROR_PORT_SHIFT)
+#define IGC_VMRCTL_POOL_MIRROR_ENABLE		(1 << 0)
+#define IGC_VMRCTL_UPLINK_MIRROR_ENABLE	(1 << 1)
+#define IGC_VMRCTL_DOWNLINK_MIRROR_ENABLE	(1 << 2)
+
+#define IGC_EICR_TX_QUEUE ( \
+	IGC_EICR_TX_QUEUE0 |    \
+	IGC_EICR_TX_QUEUE1 |    \
+	IGC_EICR_TX_QUEUE2 |    \
+	IGC_EICR_TX_QUEUE3)
+
+#define IGC_EICR_RX_QUEUE ( \
+	IGC_EICR_RX_QUEUE0 |    \
+	IGC_EICR_RX_QUEUE1 |    \
+	IGC_EICR_RX_QUEUE2 |    \
+	IGC_EICR_RX_QUEUE3)
+
+#define IGC_EIMS_RX_QUEUE	IGC_EICR_RX_QUEUE
+#define IGC_EIMS_TX_QUEUE	IGC_EICR_TX_QUEUE
+
+#define EIMS_ENABLE_MASK ( \
+	IGC_EIMS_RX_QUEUE  | \
+	IGC_EIMS_TX_QUEUE  | \
+	IGC_EIMS_TCP_TIMER | \
+	IGC_EIMS_OTHER)
+
+/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
+#define IGC_IMIR_PORT_IM_EN	0x00010000  /* TCP port enable */
+#define IGC_IMIR_PORT_BP	0x00020000  /* TCP port check bypass */
+#define IGC_IMIREXT_CTRL_URG	0x00002000  /* Check URG bit in header */
+#define IGC_IMIREXT_CTRL_ACK	0x00004000  /* Check ACK bit in header */
+#define IGC_IMIREXT_CTRL_PSH	0x00008000  /* Check PSH bit in header */
+#define IGC_IMIREXT_CTRL_RST	0x00010000  /* Check RST bit in header */
+#define IGC_IMIREXT_CTRL_SYN	0x00020000  /* Check SYN bit in header */
+#define IGC_IMIREXT_CTRL_FIN	0x00040000  /* Check FIN bit in header */
+
+#define IGC_RXDADV_RSSTYPE_MASK	0x0000000F
+#define IGC_RXDADV_RSSTYPE_SHIFT	12
+#define IGC_RXDADV_HDRBUFLEN_MASK	0x7FE0
+#define IGC_RXDADV_HDRBUFLEN_SHIFT	5
+#define IGC_RXDADV_SPLITHEADER_EN	0x00001000
+#define IGC_RXDADV_SPH		0x8000
+#define IGC_RXDADV_STAT_TS		0x10000 /* Pkt was time stamped */
+#define IGC_RXDADV_ERR_HBO		0x00800000
+
+/* RSS Hash results */
+#define IGC_RXDADV_RSSTYPE_NONE	0x00000000
+#define IGC_RXDADV_RSSTYPE_IPV4_TCP	0x00000001
+#define IGC_RXDADV_RSSTYPE_IPV4	0x00000002
+#define IGC_RXDADV_RSSTYPE_IPV6_TCP	0x00000003
+#define IGC_RXDADV_RSSTYPE_IPV6_EX	0x00000004
+#define IGC_RXDADV_RSSTYPE_IPV6	0x00000005
+#define IGC_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006
+#define IGC_RXDADV_RSSTYPE_IPV4_UDP	0x00000007
+#define IGC_RXDADV_RSSTYPE_IPV6_UDP	0x00000008
+#define IGC_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009
+
+/* RSS Packet Types as indicated in the receive descriptor */
+#define IGC_RXDADV_PKTTYPE_ILMASK	0x000000F0
+#define IGC_RXDADV_PKTTYPE_TLMASK	0x00000F00
+#define IGC_RXDADV_PKTTYPE_NONE	0x00000000
+#define IGC_RXDADV_PKTTYPE_IPV4	0x00000010 /* IPV4 hdr present */
+#define IGC_RXDADV_PKTTYPE_IPV4_EX	0x00000020 /* IPV4 hdr + extensions */
+#define IGC_RXDADV_PKTTYPE_IPV6	0x00000040 /* IPV6 hdr present */
+#define IGC_RXDADV_PKTTYPE_IPV6_EX	0x00000080 /* IPV6 hdr + extensions */
+#define IGC_RXDADV_PKTTYPE_TCP	0x00000100 /* TCP hdr present */
+#define IGC_RXDADV_PKTTYPE_UDP	0x00000200 /* UDP hdr present */
+#define IGC_RXDADV_PKTTYPE_SCTP	0x00000400 /* SCTP hdr present */
+#define IGC_RXDADV_PKTTYPE_NFS	0x00000800 /* NFS hdr present */
+
+#define IGC_RXDADV_PKTTYPE_IPSEC_ESP	0x00001000 /* IPSec ESP */
+#define IGC_RXDADV_PKTTYPE_IPSEC_AH	0x00002000 /* IPSec AH */
+#define IGC_RXDADV_PKTTYPE_LINKSEC	0x00004000 /* LinkSec Encap */
+#define IGC_RXDADV_PKTTYPE_ETQF	0x00008000 /* PKTTYPE is ETQF index */
+#define IGC_RXDADV_PKTTYPE_ETQF_MASK	0x00000070 /* ETQF has 8 indices */
+#define IGC_RXDADV_PKTTYPE_ETQF_SHIFT	4 /* Right-shift 4 bits */
+
+/* LinkSec results */
+/* Security Processing bit Indication */
+#define IGC_RXDADV_LNKSEC_STATUS_SECP		0x00020000
+#define IGC_RXDADV_LNKSEC_ERROR_BIT_MASK	0x18000000
+#define IGC_RXDADV_LNKSEC_ERROR_NO_SA_MATCH	0x08000000
+#define IGC_RXDADV_LNKSEC_ERROR_REPLAY_ERROR	0x10000000
+#define IGC_RXDADV_LNKSEC_ERROR_BAD_SIG	0x18000000
+
+#define IGC_RXDADV_IPSEC_STATUS_SECP			0x00020000
+#define IGC_RXDADV_IPSEC_ERROR_BIT_MASK		0x18000000
+#define IGC_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL	0x08000000
+#define IGC_RXDADV_IPSEC_ERROR_INVALID_LENGTH		0x10000000
+#define IGC_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED	0x18000000
+
+#define IGC_TXDCTL_SWFLSH		0x04000000 /* Tx Desc. wbk flushing */
+/* Tx Queue Arbitration Priority 0=low, 1=high */
+#define IGC_TXDCTL_PRIORITY		0x08000000
+
+#define IGC_RXDCTL_SWFLSH		0x04000000 /* Rx Desc. wbk flushing */
+
+/* Direct Cache Access (DCA) definitions */
+#define IGC_DCA_CTRL_DCA_ENABLE	0x00000000 /* DCA Enable */
+#define IGC_DCA_CTRL_DCA_DISABLE	0x00000001 /* DCA Disable */
+
+#define IGC_DCA_CTRL_DCA_MODE_CB1	0x00 /* DCA Mode CB1 */
+#define IGC_DCA_CTRL_DCA_MODE_CB2	0x02 /* DCA Mode CB2 */
+
+#define IGC_DCA_RXCTRL_CPUID_MASK	0x0000001F /* Rx CPUID Mask */
+#define IGC_DCA_RXCTRL_DESC_DCA_EN	(1 << 5) /* DCA Rx Desc enable */
+#define IGC_DCA_RXCTRL_HEAD_DCA_EN	(1 << 6) /* DCA Rx Desc header ena */
+#define IGC_DCA_RXCTRL_DATA_DCA_EN	(1 << 7) /* DCA Rx Desc payload ena */
+#define IGC_DCA_RXCTRL_DESC_RRO_EN	(1 << 9) /* DCA Rx Desc Relax Order */
+
+#define IGC_DCA_TXCTRL_CPUID_MASK	0x0000001F /* Tx CPUID Mask */
+#define IGC_DCA_TXCTRL_DESC_DCA_EN	(1 << 5) /* DCA Tx Desc enable */
+#define IGC_DCA_TXCTRL_DESC_RRO_EN	(1 << 9) /* Tx rd Desc Relax Order */
+#define IGC_DCA_TXCTRL_TX_WB_RO_EN	(1 << 11) /* Tx Desc writeback RO bit */
+#define IGC_DCA_TXCTRL_DATA_RRO_EN	(1 << 13) /* Tx rd data Relax Order */
+
+#define IGC_DCA_TXCTRL_CPUID_MASK_82576	0xFF000000 /* Tx CPUID Mask */
+#define IGC_DCA_RXCTRL_CPUID_MASK_82576	0xFF000000 /* Rx CPUID Mask */
+#define IGC_DCA_TXCTRL_CPUID_SHIFT_82576	24 /* Tx CPUID */
+#define IGC_DCA_RXCTRL_CPUID_SHIFT_82576	24 /* Rx CPUID */
+
+/* Additional interrupt register bit definitions */
+#define IGC_ICR_LSECPNS	0x00000020 /* PN threshold - server */
+#define IGC_IMS_LSECPNS	IGC_ICR_LSECPNS /* PN threshold - server */
+#define IGC_ICS_LSECPNS	IGC_ICR_LSECPNS /* PN threshold - server */
+
+/* ETQF register bit definitions */
+#define IGC_ETQF_FILTER_ENABLE	(1 << 26)
+#define IGC_ETQF_IMM_INT		(1 << 29)
+#define IGC_ETQF_QUEUE_ENABLE		(1 << 31)
+/*
+ * ETQF filter list: one static filter per filter consumer. This is
+ *                   to avoid filter collisions later. Add new filters
+ *                   here!!
+ *
+ * Current filters:
+ *    EAPOL 802.1x (0x888e): Filter 0
+ */
+#define IGC_ETQF_FILTER_EAPOL		0
+
+#define IGC_FTQF_MASK_SOURCE_ADDR_BP	0x20000000
+#define IGC_FTQF_MASK_DEST_ADDR_BP	0x40000000
+#define IGC_FTQF_MASK_SOURCE_PORT_BP	0x80000000
+
+#define IGC_NVM_APME_82575		0x0400
+#define MAX_NUM_VFS			7
+
+#define IGC_DTXSWC_MAC_SPOOF_MASK	0x000000FF /* Per VF MAC spoof cntrl */
+#define IGC_DTXSWC_VLAN_SPOOF_MASK	0x0000FF00 /* Per VF VLAN spoof cntrl */
+#define IGC_DTXSWC_LLE_MASK		0x00FF0000 /* Per VF Local LB enables */
+#define IGC_DTXSWC_VLAN_SPOOF_SHIFT	8
+#define IGC_DTXSWC_LLE_SHIFT		16
+#define IGC_DTXSWC_VMDQ_LOOPBACK_EN	(1 << 31)  /* global VF LB enable */
+
+/* Easy defines for setting default pool, would normally be left a zero */
+#define IGC_VT_CTL_DEFAULT_POOL_SHIFT	7
+#define IGC_VT_CTL_DEFAULT_POOL_MASK	(0x7 << IGC_VT_CTL_DEFAULT_POOL_SHIFT)
+
+/* Other useful VMD_CTL register defines */
+#define IGC_VT_CTL_IGNORE_MAC		(1 << 28)
+#define IGC_VT_CTL_DISABLE_DEF_POOL	(1 << 29)
+#define IGC_VT_CTL_VM_REPL_EN		(1 << 30)
+
+/* Per VM Offload register setup */
+#define IGC_VMOLR_RLPML_MASK	0x00003FFF /* Long Packet Maximum Length mask */
+#define IGC_VMOLR_LPE		0x00010000 /* Accept Long packet */
+#define IGC_VMOLR_RSSE	0x00020000 /* Enable RSS */
+#define IGC_VMOLR_AUPE	0x01000000 /* Accept untagged packets */
+#define IGC_VMOLR_ROMPE	0x02000000 /* Accept overflow multicast */
+#define IGC_VMOLR_ROPE	0x04000000 /* Accept overflow unicast */
+#define IGC_VMOLR_BAM		0x08000000 /* Accept Broadcast packets */
+#define IGC_VMOLR_MPME	0x10000000 /* Multicast promiscuous mode */
+#define IGC_VMOLR_STRVLAN	0x40000000 /* Vlan stripping enable */
+#define IGC_VMOLR_STRCRC	0x80000000 /* CRC stripping enable */
+
+#define IGC_VMOLR_VPE		0x00800000 /* VLAN promiscuous enable */
+#define IGC_VMOLR_UPE		0x20000000 /* Unicast promisuous enable */
+#define IGC_DVMOLR_HIDVLAN	0x20000000 /* Vlan hiding enable */
+#define IGC_DVMOLR_STRVLAN	0x40000000 /* Vlan stripping enable */
+#define IGC_DVMOLR_STRCRC	0x80000000 /* CRC stripping enable */
+
+#define IGC_PBRWAC_WALPB	0x00000007 /* Wrap around event on LAN Rx PB */
+#define IGC_PBRWAC_PBE	0x00000008 /* Rx packet buffer empty */
+
+#define IGC_VLVF_ARRAY_SIZE		32
+#define IGC_VLVF_VLANID_MASK		0x00000FFF
+#define IGC_VLVF_POOLSEL_SHIFT	12
+#define IGC_VLVF_POOLSEL_MASK		(0xFF << IGC_VLVF_POOLSEL_SHIFT)
+#define IGC_VLVF_LVLAN		0x00100000
+#define IGC_VLVF_VLANID_ENABLE	0x80000000
+
+#define IGC_VMVIR_VLANA_DEFAULT	0x40000000 /* Always use default VLAN */
+#define IGC_VMVIR_VLANA_NEVER		0x80000000 /* Never insert VLAN tag */
+
+#define IGC_VF_INIT_TIMEOUT	200 /* Number of retries to clear RSTI */
+
+#define IGC_IOVCTL		0x05BBC
+#define IGC_IOVCTL_REUSE_VFQ	0x00000001
+
+#define IGC_RPLOLR_STRVLAN	0x40000000
+#define IGC_RPLOLR_STRCRC	0x80000000
+
+#define IGC_TCTL_EXT_COLD	0x000FFC00
+#define IGC_TCTL_EXT_COLD_SHIFT	10
+
+#define IGC_DTXCTL_8023LL	0x0004
+#define IGC_DTXCTL_VLAN_ADDED	0x0008
+#define IGC_DTXCTL_OOS_ENABLE	0x0010
+#define IGC_DTXCTL_MDP_EN	0x0020
+#define IGC_DTXCTL_SPOOF_INT	0x0040
+
+#define IGC_EEPROM_PCS_AUTONEG_DISABLE_BIT	(1 << 14)
+
+#define ALL_QUEUES		0xFFFF
+
+s32 igc_reset_init_script_82575(struct igc_hw *hw);
+s32 igc_init_nvm_params_82575(struct igc_hw *hw);
+
+/* Rx packet buffer size defines */
+#define IGC_RXPBS_SIZE_MASK_82576	0x0000007F
+void igc_vmdq_set_loopback_pf(struct igc_hw *hw, bool enable);
+void igc_vmdq_set_anti_spoofing_pf(struct igc_hw *hw, bool enable, int pf);
+void igc_vmdq_set_replication_pf(struct igc_hw *hw, bool enable);
+
+enum igc_promisc_type {
+	igc_promisc_disabled = 0,   /* all promisc modes disabled */
+	igc_promisc_unicast = 1,    /* unicast promiscuous enabled */
+	igc_promisc_multicast = 2,  /* multicast promiscuous enabled */
+	igc_promisc_enabled = 3,    /* both uni and multicast promisc */
+	igc_num_promisc_types
+};
+
+void igc_vfta_set_vf(struct igc_hw *, u16, bool);
+void igc_rlpml_set_vf(struct igc_hw *, u16);
+s32 igc_promisc_set_vf(struct igc_hw *, enum igc_promisc_type type);
+void igc_write_vfta_i350(struct igc_hw *hw, u32 offset, u32 value);
+u16 igc_rxpbs_adjust_82580(u32 data);
+s32 igc_read_emi_reg(struct igc_hw *hw, u16 addr, u16 *data);
+s32 igc_set_eee_i350(struct igc_hw *hw, bool adv1G, bool adv100M);
+s32 igc_set_eee_i354(struct igc_hw *hw, bool adv1G, bool adv100M);
+s32 igc_get_eee_status_i354(struct igc_hw *, bool *);
+s32 igc_initialize_M88E1512_phy(struct igc_hw *hw);
+s32 igc_initialize_M88E1543_phy(struct igc_hw *hw);
+
+/* I2C SDA and SCL timing parameters for standard mode */
+#define IGC_I2C_T_HD_STA	4
+#define IGC_I2C_T_LOW		5
+#define IGC_I2C_T_HIGH	4
+#define IGC_I2C_T_SU_STA	5
+#define IGC_I2C_T_HD_DATA	5
+#define IGC_I2C_T_SU_DATA	1
+#define IGC_I2C_T_RISE	1
+#define IGC_I2C_T_FALL	1
+#define IGC_I2C_T_SU_STO	4
+#define IGC_I2C_T_BUF		5
+
+s32 igc_set_i2c_bb(struct igc_hw *hw);
+s32 igc_read_i2c_byte_generic(struct igc_hw *hw, u8 byte_offset,
+				u8 dev_addr, u8 *data);
+s32 igc_write_i2c_byte_generic(struct igc_hw *hw, u8 byte_offset,
+				 u8 dev_addr, u8 data);
+void igc_i2c_bus_clear(struct igc_hw *hw);
+#endif /* _IGC_82575_H_ */
diff --git a/drivers/net/igc/base/e1000_api.c b/drivers/net/igc/base/e1000_api.c
new file mode 100644
index 0000000..63121b2
--- /dev/null
+++ b/drivers/net/igc/base/e1000_api.c
@@ -0,0 +1,1369 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#include "e1000_api.h"
+
+/**
+ *  igc_init_mac_params - Initialize MAC function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function initializes the function pointers for the MAC
+ *  set of functions.  Called by drivers or by igc_setup_init_funcs.
+ **/
+s32 igc_init_mac_params(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+
+	if (hw->mac.ops.init_params) {
+		ret_val = hw->mac.ops.init_params(hw);
+		if (ret_val) {
+			DEBUGOUT("MAC Initialization Error\n");
+			goto out;
+		}
+	} else {
+		DEBUGOUT("mac.init_mac_params was NULL\n");
+		ret_val = -IGC_ERR_CONFIG;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_init_nvm_params - Initialize NVM function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function initializes the function pointers for the NVM
+ *  set of functions.  Called by drivers or by igc_setup_init_funcs.
+ **/
+s32 igc_init_nvm_params(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+
+	if (hw->nvm.ops.init_params) {
+		ret_val = hw->nvm.ops.init_params(hw);
+		if (ret_val) {
+			DEBUGOUT("NVM Initialization Error\n");
+			goto out;
+		}
+	} else {
+		DEBUGOUT("nvm.init_nvm_params was NULL\n");
+		ret_val = -IGC_ERR_CONFIG;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_init_phy_params - Initialize PHY function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function initializes the function pointers for the PHY
+ *  set of functions.  Called by drivers or by igc_setup_init_funcs.
+ **/
+s32 igc_init_phy_params(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+
+	if (hw->phy.ops.init_params) {
+		ret_val = hw->phy.ops.init_params(hw);
+		if (ret_val) {
+			DEBUGOUT("PHY Initialization Error\n");
+			goto out;
+		}
+	} else {
+		DEBUGOUT("phy.init_phy_params was NULL\n");
+		ret_val =  -IGC_ERR_CONFIG;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_init_mbx_params - Initialize mailbox function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function initializes the function pointers for the PHY
+ *  set of functions.  Called by drivers or by igc_setup_init_funcs.
+ **/
+s32 igc_init_mbx_params(struct igc_hw *hw)
+{
+	s32 ret_val = IGC_SUCCESS;
+
+	if (hw->mbx.ops.init_params) {
+		ret_val = hw->mbx.ops.init_params(hw);
+		if (ret_val) {
+			DEBUGOUT("Mailbox Initialization Error\n");
+			goto out;
+		}
+	} else {
+		DEBUGOUT("mbx.init_mbx_params was NULL\n");
+		ret_val =  -IGC_ERR_CONFIG;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_set_mac_type - Sets MAC type
+ *  @hw: pointer to the HW structure
+ *
+ *  This function sets the mac type of the adapter based on the
+ *  device ID stored in the hw structure.
+ *  MUST BE FIRST FUNCTION CALLED (explicitly or through
+ *  igc_setup_init_funcs()).
+ **/
+s32 igc_set_mac_type(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_set_mac_type");
+
+	switch (hw->device_id) {
+	case IGC_DEV_ID_82542:
+		mac->type = igc_82542;
+		break;
+	case IGC_DEV_ID_82543GC_FIBER:
+	case IGC_DEV_ID_82543GC_COPPER:
+		mac->type = igc_82543;
+		break;
+	case IGC_DEV_ID_82544EI_COPPER:
+	case IGC_DEV_ID_82544EI_FIBER:
+	case IGC_DEV_ID_82544GC_COPPER:
+	case IGC_DEV_ID_82544GC_LOM:
+		mac->type = igc_82544;
+		break;
+	case IGC_DEV_ID_82540EM:
+	case IGC_DEV_ID_82540EM_LOM:
+	case IGC_DEV_ID_82540EP:
+	case IGC_DEV_ID_82540EP_LOM:
+	case IGC_DEV_ID_82540EP_LP:
+		mac->type = igc_82540;
+		break;
+	case IGC_DEV_ID_82545EM_COPPER:
+	case IGC_DEV_ID_82545EM_FIBER:
+		mac->type = igc_82545;
+		break;
+	case IGC_DEV_ID_82545GM_COPPER:
+	case IGC_DEV_ID_82545GM_FIBER:
+	case IGC_DEV_ID_82545GM_SERDES:
+		mac->type = igc_82545_rev_3;
+		break;
+	case IGC_DEV_ID_82546EB_COPPER:
+	case IGC_DEV_ID_82546EB_FIBER:
+	case IGC_DEV_ID_82546EB_QUAD_COPPER:
+		mac->type = igc_82546;
+		break;
+	case IGC_DEV_ID_82546GB_COPPER:
+	case IGC_DEV_ID_82546GB_FIBER:
+	case IGC_DEV_ID_82546GB_SERDES:
+	case IGC_DEV_ID_82546GB_PCIE:
+	case IGC_DEV_ID_82546GB_QUAD_COPPER:
+	case IGC_DEV_ID_82546GB_QUAD_COPPER_KSP3:
+		mac->type = igc_82546_rev_3;
+		break;
+	case IGC_DEV_ID_82541EI:
+	case IGC_DEV_ID_82541EI_MOBILE:
+	case IGC_DEV_ID_82541ER_LOM:
+		mac->type = igc_82541;
+		break;
+	case IGC_DEV_ID_82541ER:
+	case IGC_DEV_ID_82541GI:
+	case IGC_DEV_ID_82541GI_LF:
+	case IGC_DEV_ID_82541GI_MOBILE:
+		mac->type = igc_82541_rev_2;
+		break;
+	case IGC_DEV_ID_82547EI:
+	case IGC_DEV_ID_82547EI_MOBILE:
+		mac->type = igc_82547;
+		break;
+	case IGC_DEV_ID_82547GI:
+		mac->type = igc_82547_rev_2;
+		break;
+	case IGC_DEV_ID_82571EB_COPPER:
+	case IGC_DEV_ID_82571EB_FIBER:
+	case IGC_DEV_ID_82571EB_SERDES:
+	case IGC_DEV_ID_82571EB_SERDES_DUAL:
+	case IGC_DEV_ID_82571EB_SERDES_QUAD:
+	case IGC_DEV_ID_82571EB_QUAD_COPPER:
+	case IGC_DEV_ID_82571PT_QUAD_COPPER:
+	case IGC_DEV_ID_82571EB_QUAD_FIBER:
+	case IGC_DEV_ID_82571EB_QUAD_COPPER_LP:
+		mac->type = igc_82571;
+		break;
+	case IGC_DEV_ID_82572EI:
+	case IGC_DEV_ID_82572EI_COPPER:
+	case IGC_DEV_ID_82572EI_FIBER:
+	case IGC_DEV_ID_82572EI_SERDES:
+		mac->type = igc_82572;
+		break;
+	case IGC_DEV_ID_82573E:
+	case IGC_DEV_ID_82573E_IAMT:
+	case IGC_DEV_ID_82573L:
+		mac->type = igc_82573;
+		break;
+	case IGC_DEV_ID_82574L:
+	case IGC_DEV_ID_82574LA:
+		mac->type = igc_82574;
+		break;
+	case IGC_DEV_ID_82583V:
+		mac->type = igc_82583;
+		break;
+	case IGC_DEV_ID_80003ES2LAN_COPPER_DPT:
+	case IGC_DEV_ID_80003ES2LAN_SERDES_DPT:
+	case IGC_DEV_ID_80003ES2LAN_COPPER_SPT:
+	case IGC_DEV_ID_80003ES2LAN_SERDES_SPT:
+		mac->type = igc_80003es2lan;
+		break;
+	case IGC_DEV_ID_ICH8_IFE:
+	case IGC_DEV_ID_ICH8_IFE_GT:
+	case IGC_DEV_ID_ICH8_IFE_G:
+	case IGC_DEV_ID_ICH8_IGP_M:
+	case IGC_DEV_ID_ICH8_IGP_M_AMT:
+	case IGC_DEV_ID_ICH8_IGP_AMT:
+	case IGC_DEV_ID_ICH8_IGP_C:
+	case IGC_DEV_ID_ICH8_82567V_3:
+		mac->type = igc_ich8lan;
+		break;
+	case IGC_DEV_ID_ICH9_IFE:
+	case IGC_DEV_ID_ICH9_IFE_GT:
+	case IGC_DEV_ID_ICH9_IFE_G:
+	case IGC_DEV_ID_ICH9_IGP_M:
+	case IGC_DEV_ID_ICH9_IGP_M_AMT:
+	case IGC_DEV_ID_ICH9_IGP_M_V:
+	case IGC_DEV_ID_ICH9_IGP_AMT:
+	case IGC_DEV_ID_ICH9_BM:
+	case IGC_DEV_ID_ICH9_IGP_C:
+	case IGC_DEV_ID_ICH10_R_BM_LM:
+	case IGC_DEV_ID_ICH10_R_BM_LF:
+	case IGC_DEV_ID_ICH10_R_BM_V:
+		mac->type = igc_ich9lan;
+		break;
+	case IGC_DEV_ID_ICH10_D_BM_LM:
+	case IGC_DEV_ID_ICH10_D_BM_LF:
+	case IGC_DEV_ID_ICH10_D_BM_V:
+		mac->type = igc_ich10lan;
+		break;
+	case IGC_DEV_ID_PCH_D_HV_DM:
+	case IGC_DEV_ID_PCH_D_HV_DC:
+	case IGC_DEV_ID_PCH_M_HV_LM:
+	case IGC_DEV_ID_PCH_M_HV_LC:
+		mac->type = igc_pchlan;
+		break;
+	case IGC_DEV_ID_PCH2_LV_LM:
+	case IGC_DEV_ID_PCH2_LV_V:
+		mac->type = igc_pch2lan;
+		break;
+	case IGC_DEV_ID_PCH_LPT_I217_LM:
+	case IGC_DEV_ID_PCH_LPT_I217_V:
+	case IGC_DEV_ID_PCH_LPTLP_I218_LM:
+	case IGC_DEV_ID_PCH_LPTLP_I218_V:
+	case IGC_DEV_ID_PCH_I218_LM2:
+	case IGC_DEV_ID_PCH_I218_V2:
+	case IGC_DEV_ID_PCH_I218_LM3:
+	case IGC_DEV_ID_PCH_I218_V3:
+		mac->type = igc_pch_lpt;
+		break;
+	case IGC_DEV_ID_PCH_SPT_I219_LM:
+	case IGC_DEV_ID_PCH_SPT_I219_V:
+	case IGC_DEV_ID_PCH_SPT_I219_LM2:
+	case IGC_DEV_ID_PCH_SPT_I219_V2:
+	case IGC_DEV_ID_PCH_LBG_I219_LM3:
+	case IGC_DEV_ID_PCH_SPT_I219_LM4:
+	case IGC_DEV_ID_PCH_SPT_I219_V4:
+	case IGC_DEV_ID_PCH_SPT_I219_LM5:
+	case IGC_DEV_ID_PCH_SPT_I219_V5:
+		mac->type = igc_pch_spt;
+		break;
+	case IGC_DEV_ID_PCH_CNP_I219_LM6:
+	case IGC_DEV_ID_PCH_CNP_I219_V6:
+	case IGC_DEV_ID_PCH_CNP_I219_LM7:
+	case IGC_DEV_ID_PCH_CNP_I219_V7:
+	case IGC_DEV_ID_PCH_ICP_I219_LM8:
+	case IGC_DEV_ID_PCH_ICP_I219_V8:
+	case IGC_DEV_ID_PCH_ICP_I219_LM9:
+	case IGC_DEV_ID_PCH_ICP_I219_V9:
+		mac->type = igc_pch_cnp;
+		break;
+	case IGC_DEV_ID_82575EB_COPPER:
+	case IGC_DEV_ID_82575EB_FIBER_SERDES:
+	case IGC_DEV_ID_82575GB_QUAD_COPPER:
+		mac->type = igc_82575;
+		break;
+	case IGC_DEV_ID_82576:
+	case IGC_DEV_ID_82576_FIBER:
+	case IGC_DEV_ID_82576_SERDES:
+	case IGC_DEV_ID_82576_QUAD_COPPER:
+	case IGC_DEV_ID_82576_QUAD_COPPER_ET2:
+	case IGC_DEV_ID_82576_NS:
+	case IGC_DEV_ID_82576_NS_SERDES:
+	case IGC_DEV_ID_82576_SERDES_QUAD:
+		mac->type = igc_82576;
+		break;
+	case IGC_DEV_ID_82576_VF:
+	case IGC_DEV_ID_82576_VF_HV:
+		mac->type = igc_vfadapt;
+		break;
+	case IGC_DEV_ID_82580_COPPER:
+	case IGC_DEV_ID_82580_FIBER:
+	case IGC_DEV_ID_82580_SERDES:
+	case IGC_DEV_ID_82580_SGMII:
+	case IGC_DEV_ID_82580_COPPER_DUAL:
+	case IGC_DEV_ID_82580_QUAD_FIBER:
+	case IGC_DEV_ID_DH89XXCC_SGMII:
+	case IGC_DEV_ID_DH89XXCC_SERDES:
+	case IGC_DEV_ID_DH89XXCC_BACKPLANE:
+	case IGC_DEV_ID_DH89XXCC_SFP:
+		mac->type = igc_82580;
+		break;
+	case IGC_DEV_ID_I350_COPPER:
+	case IGC_DEV_ID_I350_FIBER:
+	case IGC_DEV_ID_I350_SERDES:
+	case IGC_DEV_ID_I350_SGMII:
+	case IGC_DEV_ID_I350_DA4:
+		mac->type = igc_i350;
+		break;
+	case IGC_DEV_ID_I210_COPPER_FLASHLESS:
+	case IGC_DEV_ID_I210_SERDES_FLASHLESS:
+	case IGC_DEV_ID_I210_SGMII_FLASHLESS:
+	case IGC_DEV_ID_I210_COPPER:
+	case IGC_DEV_ID_I210_COPPER_OEM1:
+	case IGC_DEV_ID_I210_COPPER_IT:
+	case IGC_DEV_ID_I210_FIBER:
+	case IGC_DEV_ID_I210_SERDES:
+	case IGC_DEV_ID_I210_SGMII:
+		mac->type = igc_i210;
+		break;
+	case IGC_DEV_ID_I211_COPPER:
+		mac->type = igc_i211;
+		break;
+	case IGC_DEV_ID_I225_LM:
+	case IGC_DEV_ID_I225_V:
+	case IGC_DEV_ID_I225_K:
+	case IGC_DEV_ID_I225_I:
+	case IGC_DEV_ID_I220_V:
+	case IGC_DEV_ID_I225_BLANK_NVM:
+		mac->type = igc_i225;
+		break;
+	case IGC_DEV_ID_I350_VF:
+	case IGC_DEV_ID_I350_VF_HV:
+		mac->type = igc_vfadapt_i350;
+		break;
+	case IGC_DEV_ID_I354_BACKPLANE_1GBPS:
+	case IGC_DEV_ID_I354_SGMII:
+	case IGC_DEV_ID_I354_BACKPLANE_2_5GBPS:
+		mac->type = igc_i354;
+		break;
+	default:
+		/* Should never have loaded on this device */
+		ret_val = -IGC_ERR_MAC_INIT;
+		break;
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_setup_init_funcs - Initializes function pointers
+ *  @hw: pointer to the HW structure
+ *  @init_device: true will initialize the rest of the function pointers
+ *		  getting the device ready for use.  false will only set
+ *		  MAC type and the function pointers for the other init
+ *		  functions.  Passing false will not generate any hardware
+ *		  reads or writes.
+ *
+ *  This function must be called by a driver in order to use the rest
+ *  of the 'shared' code files. Called by drivers only.
+ **/
+s32 igc_setup_init_funcs(struct igc_hw *hw, bool init_device)
+{
+	s32 ret_val;
+
+	/* Can't do much good without knowing the MAC type. */
+	ret_val = igc_set_mac_type(hw);
+	if (ret_val) {
+		DEBUGOUT("ERROR: MAC type could not be set properly.\n");
+		goto out;
+	}
+
+	if (!hw->hw_addr) {
+		DEBUGOUT("ERROR: Registers not mapped\n");
+		ret_val = -IGC_ERR_CONFIG;
+		goto out;
+	}
+
+	/*
+	 * Init function pointers to generic implementations. We do this first
+	 * allowing a driver module to override it afterward.
+	 */
+	igc_init_mac_ops_generic(hw);
+	igc_init_phy_ops_generic(hw);
+	igc_init_nvm_ops_generic(hw);
+	igc_init_mbx_ops_generic(hw);
+
+	/*
+	 * Set up the init function pointers. These are functions within the
+	 * adapter family file that sets up function pointers for the rest of
+	 * the functions in that family.
+	 */
+	switch (hw->mac.type) {
+	case igc_82542:
+		igc_init_function_pointers_82542(hw);
+		break;
+	case igc_82543:
+	case igc_82544:
+		igc_init_function_pointers_82543(hw);
+		break;
+	case igc_82540:
+	case igc_82545:
+	case igc_82545_rev_3:
+	case igc_82546:
+	case igc_82546_rev_3:
+		igc_init_function_pointers_82540(hw);
+		break;
+	case igc_82541:
+	case igc_82541_rev_2:
+	case igc_82547:
+	case igc_82547_rev_2:
+		igc_init_function_pointers_82541(hw);
+		break;
+	case igc_82571:
+	case igc_82572:
+	case igc_82573:
+	case igc_82574:
+	case igc_82583:
+		igc_init_function_pointers_82571(hw);
+		break;
+	case igc_80003es2lan:
+		igc_init_function_pointers_80003es2lan(hw);
+		break;
+	case igc_ich8lan:
+	case igc_ich9lan:
+	case igc_ich10lan:
+	case igc_pchlan:
+	case igc_pch2lan:
+	case igc_pch_lpt:
+	case igc_pch_spt:
+	case igc_pch_cnp:
+	/* fall-through */
+		igc_init_function_pointers_ich8lan(hw);
+		break;
+	case igc_82575:
+	case igc_82576:
+	case igc_82580:
+	case igc_i350:
+	case igc_i354:
+		igc_init_function_pointers_82575(hw);
+		break;
+	case igc_i210:
+	case igc_i211:
+		igc_init_function_pointers_i210(hw);
+		break;
+	case igc_i225:
+		igc_init_function_pointers_i225(hw);
+		break;
+	case igc_vfadapt:
+		igc_init_function_pointers_vf(hw);
+		break;
+	case igc_vfadapt_i350:
+		igc_init_function_pointers_vf(hw);
+		break;
+	default:
+		DEBUGOUT("Hardware not supported\n");
+		ret_val = -IGC_ERR_CONFIG;
+		break;
+	}
+
+	/*
+	 * Initialize the rest of the function pointers. These require some
+	 * register reads/writes in some cases.
+	 */
+	if (!(ret_val) && init_device) {
+		ret_val = igc_init_mac_params(hw);
+		if (ret_val)
+			goto out;
+
+		ret_val = igc_init_nvm_params(hw);
+		if (ret_val)
+			goto out;
+
+		ret_val = igc_init_phy_params(hw);
+		if (ret_val)
+			goto out;
+
+		ret_val = igc_init_mbx_params(hw);
+		if (ret_val)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_get_bus_info - Obtain bus information for adapter
+ *  @hw: pointer to the HW structure
+ *
+ *  This will obtain information about the HW bus for which the
+ *  adapter is attached and stores it in the hw structure. This is a
+ *  function pointer entry point called by drivers.
+ **/
+s32 igc_get_bus_info(struct igc_hw *hw)
+{
+	if (hw->mac.ops.get_bus_info)
+		return hw->mac.ops.get_bus_info(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_clear_vfta - Clear VLAN filter table
+ *  @hw: pointer to the HW structure
+ *
+ *  This clears the VLAN filter table on the adapter. This is a function
+ *  pointer entry point called by drivers.
+ **/
+void igc_clear_vfta(struct igc_hw *hw)
+{
+	if (hw->mac.ops.clear_vfta)
+		hw->mac.ops.clear_vfta(hw);
+}
+
+/**
+ *  igc_write_vfta - Write value to VLAN filter table
+ *  @hw: pointer to the HW structure
+ *  @offset: the 32-bit offset in which to write the value to.
+ *  @value: the 32-bit value to write at location offset.
+ *
+ *  This writes a 32-bit value to a 32-bit offset in the VLAN filter
+ *  table. This is a function pointer entry point called by drivers.
+ **/
+void igc_write_vfta(struct igc_hw *hw, u32 offset, u32 value)
+{
+	if (hw->mac.ops.write_vfta)
+		hw->mac.ops.write_vfta(hw, offset, value);
+}
+
+/**
+ *  igc_update_mc_addr_list - Update Multicast addresses
+ *  @hw: pointer to the HW structure
+ *  @mc_addr_list: array of multicast addresses to program
+ *  @mc_addr_count: number of multicast addresses to program
+ *
+ *  Updates the Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void igc_update_mc_addr_list(struct igc_hw *hw, u8 *mc_addr_list,
+			       u32 mc_addr_count)
+{
+	if (hw->mac.ops.update_mc_addr_list)
+		hw->mac.ops.update_mc_addr_list(hw, mc_addr_list,
+						mc_addr_count);
+}
+
+/**
+ *  igc_force_mac_fc - Force MAC flow control
+ *  @hw: pointer to the HW structure
+ *
+ *  Force the MAC's flow control settings. Currently no func pointer exists
+ *  and all implementations are handled in the generic version of this
+ *  function.
+ **/
+s32 igc_force_mac_fc(struct igc_hw *hw)
+{
+	return igc_force_mac_fc_generic(hw);
+}
+
+/**
+ *  igc_check_for_link - Check/Store link connection
+ *  @hw: pointer to the HW structure
+ *
+ *  This checks the link condition of the adapter and stores the
+ *  results in the hw->mac structure. This is a function pointer entry
+ *  point called by drivers.
+ **/
+s32 igc_check_for_link(struct igc_hw *hw)
+{
+	if (hw->mac.ops.check_for_link)
+		return hw->mac.ops.check_for_link(hw);
+
+	return -IGC_ERR_CONFIG;
+}
+
+/**
+ *  igc_check_mng_mode - Check management mode
+ *  @hw: pointer to the HW structure
+ *
+ *  This checks if the adapter has manageability enabled.
+ *  This is a function pointer entry point called by drivers.
+ **/
+bool igc_check_mng_mode(struct igc_hw *hw)
+{
+	if (hw->mac.ops.check_mng_mode)
+		return hw->mac.ops.check_mng_mode(hw);
+
+	return false;
+}
+
+/**
+ *  igc_mng_write_dhcp_info - Writes DHCP info to host interface
+ *  @hw: pointer to the HW structure
+ *  @buffer: pointer to the host interface
+ *  @length: size of the buffer
+ *
+ *  Writes the DHCP information to the host interface.
+ **/
+s32 igc_mng_write_dhcp_info(struct igc_hw *hw, u8 *buffer, u16 length)
+{
+	return igc_mng_write_dhcp_info_generic(hw, buffer, length);
+}
+
+/**
+ *  igc_reset_hw - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state. This is a function pointer
+ *  entry point called by drivers.
+ **/
+s32 igc_reset_hw(struct igc_hw *hw)
+{
+	if (hw->mac.ops.reset_hw)
+		return hw->mac.ops.reset_hw(hw);
+
+	return -IGC_ERR_CONFIG;
+}
+
+/**
+ *  igc_init_hw - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation. This is a function
+ *  pointer entry point called by drivers.
+ **/
+s32 igc_init_hw(struct igc_hw *hw)
+{
+	if (hw->mac.ops.init_hw)
+		return hw->mac.ops.init_hw(hw);
+
+	return -IGC_ERR_CONFIG;
+}
+
+/**
+ *  igc_setup_link - Configures link and flow control
+ *  @hw: pointer to the HW structure
+ *
+ *  This configures link and flow control settings for the adapter. This
+ *  is a function pointer entry point called by drivers. While modules can
+ *  also call this, they probably call their own version of this function.
+ **/
+s32 igc_setup_link(struct igc_hw *hw)
+{
+	if (hw->mac.ops.setup_link)
+		return hw->mac.ops.setup_link(hw);
+
+	return -IGC_ERR_CONFIG;
+}
+
+/**
+ *  igc_get_speed_and_duplex - Returns current speed and duplex
+ *  @hw: pointer to the HW structure
+ *  @speed: pointer to a 16-bit value to store the speed
+ *  @duplex: pointer to a 16-bit value to store the duplex.
+ *
+ *  This returns the speed and duplex of the adapter in the two 'out'
+ *  variables passed in. This is a function pointer entry point called
+ *  by drivers.
+ **/
+s32 igc_get_speed_and_duplex(struct igc_hw *hw, u16 *speed, u16 *duplex)
+{
+	if (hw->mac.ops.get_link_up_info)
+		return hw->mac.ops.get_link_up_info(hw, speed, duplex);
+
+	return -IGC_ERR_CONFIG;
+}
+
+/**
+ *  igc_setup_led - Configures SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This prepares the SW controllable LED for use and saves the current state
+ *  of the LED so it can be later restored. This is a function pointer entry
+ *  point called by drivers.
+ **/
+s32 igc_setup_led(struct igc_hw *hw)
+{
+	if (hw->mac.ops.setup_led)
+		return hw->mac.ops.setup_led(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_cleanup_led - Restores SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This restores the SW controllable LED to the value saved off by
+ *  igc_setup_led. This is a function pointer entry point called by drivers.
+ **/
+s32 igc_cleanup_led(struct igc_hw *hw)
+{
+	if (hw->mac.ops.cleanup_led)
+		return hw->mac.ops.cleanup_led(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_blink_led - Blink SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This starts the adapter LED blinking. Request the LED to be setup first
+ *  and cleaned up after. This is a function pointer entry point called by
+ *  drivers.
+ **/
+s32 igc_blink_led(struct igc_hw *hw)
+{
+	if (hw->mac.ops.blink_led)
+		return hw->mac.ops.blink_led(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_id_led_init - store LED configurations in SW
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes the LED config in SW. This is a function pointer entry point
+ *  called by drivers.
+ **/
+s32 igc_id_led_init(struct igc_hw *hw)
+{
+	if (hw->mac.ops.id_led_init)
+		return hw->mac.ops.id_led_init(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_led_on - Turn on SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED on. This is a function pointer entry point
+ *  called by drivers.
+ **/
+s32 igc_led_on(struct igc_hw *hw)
+{
+	if (hw->mac.ops.led_on)
+		return hw->mac.ops.led_on(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_led_off - Turn off SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  Turns the SW defined LED off. This is a function pointer entry point
+ *  called by drivers.
+ **/
+s32 igc_led_off(struct igc_hw *hw)
+{
+	if (hw->mac.ops.led_off)
+		return hw->mac.ops.led_off(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_reset_adaptive - Reset adaptive IFS
+ *  @hw: pointer to the HW structure
+ *
+ *  Resets the adaptive IFS. Currently no func pointer exists and all
+ *  implementations are handled in the generic version of this function.
+ **/
+void igc_reset_adaptive(struct igc_hw *hw)
+{
+	igc_reset_adaptive_generic(hw);
+}
+
+/**
+ *  igc_update_adaptive - Update adaptive IFS
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates adapter IFS. Currently no func pointer exists and all
+ *  implementations are handled in the generic version of this function.
+ **/
+void igc_update_adaptive(struct igc_hw *hw)
+{
+	igc_update_adaptive_generic(hw);
+}
+
+/**
+ *  igc_disable_pcie_master - Disable PCI-Express master access
+ *  @hw: pointer to the HW structure
+ *
+ *  Disables PCI-Express master access and verifies there are no pending
+ *  requests. Currently no func pointer exists and all implementations are
+ *  handled in the generic version of this function.
+ **/
+s32 igc_disable_pcie_master(struct igc_hw *hw)
+{
+	return igc_disable_pcie_master_generic(hw);
+}
+
+/**
+ *  igc_config_collision_dist - Configure collision distance
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the collision distance to the default value and is used
+ *  during link setup.
+ **/
+void igc_config_collision_dist(struct igc_hw *hw)
+{
+	if (hw->mac.ops.config_collision_dist)
+		hw->mac.ops.config_collision_dist(hw);
+}
+
+/**
+ *  igc_rar_set - Sets a receive address register
+ *  @hw: pointer to the HW structure
+ *  @addr: address to set the RAR to
+ *  @index: the RAR to set
+ *
+ *  Sets a Receive Address Register (RAR) to the specified address.
+ **/
+int igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index)
+{
+	if (hw->mac.ops.rar_set)
+		return hw->mac.ops.rar_set(hw, addr, index);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_validate_mdi_setting - Ensures valid MDI/MDIX SW state
+ *  @hw: pointer to the HW structure
+ *
+ *  Ensures that the MDI/MDIX SW state is valid.
+ **/
+s32 igc_validate_mdi_setting(struct igc_hw *hw)
+{
+	if (hw->mac.ops.validate_mdi_setting)
+		return hw->mac.ops.validate_mdi_setting(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_hash_mc_addr - Determines address location in multicast table
+ *  @hw: pointer to the HW structure
+ *  @mc_addr: Multicast address to hash.
+ *
+ *  This hashes an address to determine its location in the multicast
+ *  table. Currently no func pointer exists and all implementations
+ *  are handled in the generic version of this function.
+ **/
+u32 igc_hash_mc_addr(struct igc_hw *hw, u8 *mc_addr)
+{
+	return igc_hash_mc_addr_generic(hw, mc_addr);
+}
+
+/**
+ *  igc_enable_tx_pkt_filtering - Enable packet filtering on TX
+ *  @hw: pointer to the HW structure
+ *
+ *  Enables packet filtering on transmit packets if manageability is enabled
+ *  and host interface is enabled.
+ *  Currently no func pointer exists and all implementations are handled in the
+ *  generic version of this function.
+ **/
+bool igc_enable_tx_pkt_filtering(struct igc_hw *hw)
+{
+	return igc_enable_tx_pkt_filtering_generic(hw);
+}
+
+/**
+ *  igc_mng_host_if_write - Writes to the manageability host interface
+ *  @hw: pointer to the HW structure
+ *  @buffer: pointer to the host interface buffer
+ *  @length: size of the buffer
+ *  @offset: location in the buffer to write to
+ *  @sum: sum of the data (not checksum)
+ *
+ *  This function writes the buffer content at the offset given on the host if.
+ *  It also does alignment considerations to do the writes in most efficient
+ *  way.  Also fills up the sum of the buffer in *buffer parameter.
+ **/
+s32 igc_mng_host_if_write(struct igc_hw *hw, u8 *buffer, u16 length,
+			    u16 offset, u8 *sum)
+{
+	return igc_mng_host_if_write_generic(hw, buffer, length, offset, sum);
+}
+
+/**
+ *  igc_mng_write_cmd_header - Writes manageability command header
+ *  @hw: pointer to the HW structure
+ *  @hdr: pointer to the host interface command header
+ *
+ *  Writes the command header after does the checksum calculation.
+ **/
+s32 igc_mng_write_cmd_header(struct igc_hw *hw,
+			       struct igc_host_mng_command_header *hdr)
+{
+	return igc_mng_write_cmd_header_generic(hw, hdr);
+}
+
+/**
+ *  igc_mng_enable_host_if - Checks host interface is enabled
+ *  @hw: pointer to the HW structure
+ *
+ *  Returns IGC_success upon success, else IGC_ERR_HOST_INTERFACE_COMMAND
+ *
+ *  This function checks whether the HOST IF is enabled for command operation
+ *  and also checks whether the previous command is completed.  It busy waits
+ *  in case of previous command is not completed.
+ **/
+s32 igc_mng_enable_host_if(struct igc_hw *hw)
+{
+	return igc_mng_enable_host_if_generic(hw);
+}
+
+/**
+ *  igc_check_reset_block - Verifies PHY can be reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks if the PHY is in a state that can be reset or if manageability
+ *  has it tied up. This is a function pointer entry point called by drivers.
+ **/
+s32 igc_check_reset_block(struct igc_hw *hw)
+{
+	if (hw->phy.ops.check_reset_block)
+		return hw->phy.ops.check_reset_block(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_read_phy_reg - Reads PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: the register to read
+ *  @data: the buffer to store the 16-bit read.
+ *
+ *  Reads the PHY register and returns the value in data.
+ *  This is a function pointer entry point called by drivers.
+ **/
+s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
+{
+	if (hw->phy.ops.read_reg)
+		return hw->phy.ops.read_reg(hw, offset, data);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_write_phy_reg - Writes PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: the register to write
+ *  @data: the value to write.
+ *
+ *  Writes the PHY register at offset with the value in data.
+ *  This is a function pointer entry point called by drivers.
+ **/
+s32 igc_write_phy_reg(struct igc_hw *hw, u32 offset, u16 data)
+{
+	if (hw->phy.ops.write_reg)
+		return hw->phy.ops.write_reg(hw, offset, data);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_release_phy - Generic release PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Return if silicon family does not require a semaphore when accessing the
+ *  PHY.
+ **/
+void igc_release_phy(struct igc_hw *hw)
+{
+	if (hw->phy.ops.release)
+		hw->phy.ops.release(hw);
+}
+
+/**
+ *  igc_acquire_phy - Generic acquire PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Return success if silicon family does not require a semaphore when
+ *  accessing the PHY.
+ **/
+s32 igc_acquire_phy(struct igc_hw *hw)
+{
+	if (hw->phy.ops.acquire)
+		return hw->phy.ops.acquire(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_cfg_on_link_up - Configure PHY upon link up
+ *  @hw: pointer to the HW structure
+ **/
+s32 igc_cfg_on_link_up(struct igc_hw *hw)
+{
+	if (hw->phy.ops.cfg_on_link_up)
+		return hw->phy.ops.cfg_on_link_up(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_read_kmrn_reg - Reads register using Kumeran interface
+ *  @hw: pointer to the HW structure
+ *  @offset: the register to read
+ *  @data: the location to store the 16-bit value read.
+ *
+ *  Reads a register out of the Kumeran interface. Currently no func pointer
+ *  exists and all implementations are handled in the generic version of
+ *  this function.
+ **/
+s32 igc_read_kmrn_reg(struct igc_hw *hw, u32 offset, u16 *data)
+{
+	return igc_read_kmrn_reg_generic(hw, offset, data);
+}
+
+/**
+ *  igc_write_kmrn_reg - Writes register using Kumeran interface
+ *  @hw: pointer to the HW structure
+ *  @offset: the register to write
+ *  @data: the value to write.
+ *
+ *  Writes a register to the Kumeran interface. Currently no func pointer
+ *  exists and all implementations are handled in the generic version of
+ *  this function.
+ **/
+s32 igc_write_kmrn_reg(struct igc_hw *hw, u32 offset, u16 data)
+{
+	return igc_write_kmrn_reg_generic(hw, offset, data);
+}
+
+/**
+ *  igc_get_cable_length - Retrieves cable length estimation
+ *  @hw: pointer to the HW structure
+ *
+ *  This function estimates the cable length and stores them in
+ *  hw->phy.min_length and hw->phy.max_length. This is a function pointer
+ *  entry point called by drivers.
+ **/
+s32 igc_get_cable_length(struct igc_hw *hw)
+{
+	if (hw->phy.ops.get_cable_length)
+		return hw->phy.ops.get_cable_length(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_get_phy_info - Retrieves PHY information from registers
+ *  @hw: pointer to the HW structure
+ *
+ *  This function gets some information from various PHY registers and
+ *  populates hw->phy values with it. This is a function pointer entry
+ *  point called by drivers.
+ **/
+s32 igc_get_phy_info(struct igc_hw *hw)
+{
+	if (hw->phy.ops.get_info)
+		return hw->phy.ops.get_info(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_phy_hw_reset - Hard PHY reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Performs a hard PHY reset. This is a function pointer entry point called
+ *  by drivers.
+ **/
+s32 igc_phy_hw_reset(struct igc_hw *hw)
+{
+	if (hw->phy.ops.reset)
+		return hw->phy.ops.reset(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_phy_commit - Soft PHY reset
+ *  @hw: pointer to the HW structure
+ *
+ *  Performs a soft PHY reset on those that apply. This is a function pointer
+ *  entry point called by drivers.
+ **/
+s32 igc_phy_commit(struct igc_hw *hw)
+{
+	if (hw->phy.ops.commit)
+		return hw->phy.ops.commit(hw);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_set_d0_lplu_state - Sets low power link up state for D0
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  Success returns 0, Failure returns 1
+ *
+ *  The low power link up (lplu) state is set to the power management level D0
+ *  and SmartSpeed is disabled when active is true, else clear lplu for D0
+ *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.  This is a function pointer entry point called by drivers.
+ **/
+s32 igc_set_d0_lplu_state(struct igc_hw *hw, bool active)
+{
+	if (hw->phy.ops.set_d0_lplu_state)
+		return hw->phy.ops.set_d0_lplu_state(hw, active);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_set_d3_lplu_state - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  Success returns 0, Failure returns 1
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  and SmartSpeed is disabled when active is true, else clear lplu for D3
+ *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.  This is a function pointer entry point called by drivers.
+ **/
+s32 igc_set_d3_lplu_state(struct igc_hw *hw, bool active)
+{
+	if (hw->phy.ops.set_d3_lplu_state)
+		return hw->phy.ops.set_d3_lplu_state(hw, active);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_read_mac_addr - Reads MAC address
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the MAC address out of the adapter and stores it in the HW structure.
+ *  Currently no func pointer exists and all implementations are handled in the
+ *  generic version of this function.
+ **/
+s32 igc_read_mac_addr(struct igc_hw *hw)
+{
+	if (hw->mac.ops.read_mac_addr)
+		return hw->mac.ops.read_mac_addr(hw);
+
+	return igc_read_mac_addr_generic(hw);
+}
+
+/**
+ *  igc_read_pba_string - Read device part number string
+ *  @hw: pointer to the HW structure
+ *  @pba_num: pointer to device part number
+ *  @pba_num_size: size of part number buffer
+ *
+ *  Reads the product board assembly (PBA) number from the EEPROM and stores
+ *  the value in pba_num.
+ *  Currently no func pointer exists and all implementations are handled in the
+ *  generic version of this function.
+ **/
+s32 igc_read_pba_string(struct igc_hw *hw, u8 *pba_num, u32 pba_num_size)
+{
+	return igc_read_pba_string_generic(hw, pba_num, pba_num_size);
+}
+
+/**
+ *  igc_read_pba_length - Read device part number string length
+ *  @hw: pointer to the HW structure
+ *  @pba_num_size: size of part number buffer
+ *
+ *  Reads the product board assembly (PBA) number length from the EEPROM and
+ *  stores the value in pba_num.
+ *  Currently no func pointer exists and all implementations are handled in the
+ *  generic version of this function.
+ **/
+s32 igc_read_pba_length(struct igc_hw *hw, u32 *pba_num_size)
+{
+	return igc_read_pba_length_generic(hw, pba_num_size);
+}
+
+/**
+ *  igc_read_pba_num - Read device part number
+ *  @hw: pointer to the HW structure
+ *  @pba_num: pointer to device part number
+ *
+ *  Reads the product board assembly (PBA) number from the EEPROM and stores
+ *  the value in pba_num.
+ *  Currently no func pointer exists and all implementations are handled in the
+ *  generic version of this function.
+ **/
+s32 igc_read_pba_num(struct igc_hw *hw, u32 *pba_num)
+{
+	return igc_read_pba_num_generic(hw, pba_num);
+}
+
+/**
+ *  igc_validate_nvm_checksum - Verifies NVM (EEPROM) checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Validates the NVM checksum is correct. This is a function pointer entry
+ *  point called by drivers.
+ **/
+s32 igc_validate_nvm_checksum(struct igc_hw *hw)
+{
+	if (hw->nvm.ops.validate)
+		return hw->nvm.ops.validate(hw);
+
+	return -IGC_ERR_CONFIG;
+}
+
+/**
+ *  igc_update_nvm_checksum - Updates NVM (EEPROM) checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the NVM checksum. Currently no func pointer exists and all
+ *  implementations are handled in the generic version of this function.
+ **/
+s32 igc_update_nvm_checksum(struct igc_hw *hw)
+{
+	if (hw->nvm.ops.update)
+		return hw->nvm.ops.update(hw);
+
+	return -IGC_ERR_CONFIG;
+}
+
+/**
+ *  igc_reload_nvm - Reloads EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
+ *  extended control register.
+ **/
+void igc_reload_nvm(struct igc_hw *hw)
+{
+	if (hw->nvm.ops.reload)
+		hw->nvm.ops.reload(hw);
+}
+
+/**
+ *  igc_read_nvm - Reads NVM (EEPROM)
+ *  @hw: pointer to the HW structure
+ *  @offset: the word offset to read
+ *  @words: number of 16-bit words to read
+ *  @data: pointer to the properly sized buffer for the data.
+ *
+ *  Reads 16-bit chunks of data from the NVM (EEPROM). This is a function
+ *  pointer entry point called by drivers.
+ **/
+s32 igc_read_nvm(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
+{
+	if (hw->nvm.ops.read)
+		return hw->nvm.ops.read(hw, offset, words, data);
+
+	return -IGC_ERR_CONFIG;
+}
+
+/**
+ *  igc_write_nvm - Writes to NVM (EEPROM)
+ *  @hw: pointer to the HW structure
+ *  @offset: the word offset to read
+ *  @words: number of 16-bit words to write
+ *  @data: pointer to the properly sized buffer for the data.
+ *
+ *  Writes 16-bit chunks of data to the NVM (EEPROM). This is a function
+ *  pointer entry point called by drivers.
+ **/
+s32 igc_write_nvm(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
+{
+	if (hw->nvm.ops.write)
+		return hw->nvm.ops.write(hw, offset, words, data);
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_write_8bit_ctrl_reg - Writes 8bit Control register
+ *  @hw: pointer to the HW structure
+ *  @reg: 32bit register offset
+ *  @offset: the register to write
+ *  @data: the value to write.
+ *
+ *  Writes the PHY register at offset with the value in data.
+ *  This is a function pointer entry point called by drivers.
+ **/
+s32 igc_write_8bit_ctrl_reg(struct igc_hw *hw, u32 reg, u32 offset,
+			      u8 data)
+{
+	return igc_write_8bit_ctrl_reg_generic(hw, reg, offset, data);
+}
+
+/**
+ * igc_power_up_phy - Restores link in case of PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * The phy may be powered down to save power, to turn off link when the
+ * driver is unloaded, or wake on lan is not enabled (among others).
+ **/
+void igc_power_up_phy(struct igc_hw *hw)
+{
+	if (hw->phy.ops.power_up)
+		hw->phy.ops.power_up(hw);
+
+	igc_setup_link(hw);
+}
+
+/**
+ * igc_power_down_phy - Power down PHY
+ * @hw: pointer to the HW structure
+ *
+ * The phy may be powered down to save power, to turn off link when the
+ * driver is unloaded, or wake on lan is not enabled (among others).
+ **/
+void igc_power_down_phy(struct igc_hw *hw)
+{
+	if (hw->phy.ops.power_down)
+		hw->phy.ops.power_down(hw);
+}
+
+/**
+ *  igc_power_up_fiber_serdes_link - Power up serdes link
+ *  @hw: pointer to the HW structure
+ *
+ *  Power on the optics and PCS.
+ **/
+void igc_power_up_fiber_serdes_link(struct igc_hw *hw)
+{
+	if (hw->mac.ops.power_up_serdes)
+		hw->mac.ops.power_up_serdes(hw);
+}
+
+/**
+ *  igc_shutdown_fiber_serdes_link - Remove link during power down
+ *  @hw: pointer to the HW structure
+ *
+ *  Shutdown the optics and PCS on driver unload.
+ **/
+void igc_shutdown_fiber_serdes_link(struct igc_hw *hw)
+{
+	if (hw->mac.ops.shutdown_serdes)
+		hw->mac.ops.shutdown_serdes(hw);
+}
+
diff --git a/drivers/net/igc/base/e1000_api.h b/drivers/net/igc/base/e1000_api.h
new file mode 100644
index 0000000..1d95d32
--- /dev/null
+++ b/drivers/net/igc/base/e1000_api.h
@@ -0,0 +1,138 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_API_H_
+#define _IGC_API_H_
+
+#include "e1000_hw.h"
+
+extern void igc_init_function_pointers_82542(struct igc_hw *hw);
+extern void igc_init_function_pointers_82543(struct igc_hw *hw);
+extern void igc_init_function_pointers_82540(struct igc_hw *hw);
+extern void igc_init_function_pointers_82571(struct igc_hw *hw);
+extern void igc_init_function_pointers_82541(struct igc_hw *hw);
+extern void igc_init_function_pointers_80003es2lan(struct igc_hw *hw);
+extern void igc_init_function_pointers_ich8lan(struct igc_hw *hw);
+extern void igc_init_function_pointers_82575(struct igc_hw *hw);
+extern void igc_init_function_pointers_vf(struct igc_hw *hw);
+extern void igc_power_up_fiber_serdes_link(struct igc_hw *hw);
+extern void igc_shutdown_fiber_serdes_link(struct igc_hw *hw);
+extern void igc_init_function_pointers_i210(struct igc_hw *hw);
+extern void igc_init_function_pointers_i225(struct igc_hw *hw);
+
+s32 igc_set_obff_timer(struct igc_hw *hw, u32 itr);
+s32 igc_set_mac_type(struct igc_hw *hw);
+s32 igc_setup_init_funcs(struct igc_hw *hw, bool init_device);
+s32 igc_init_mac_params(struct igc_hw *hw);
+s32 igc_init_nvm_params(struct igc_hw *hw);
+s32 igc_init_phy_params(struct igc_hw *hw);
+s32 igc_init_mbx_params(struct igc_hw *hw);
+s32 igc_get_bus_info(struct igc_hw *hw);
+void igc_clear_vfta(struct igc_hw *hw);
+void igc_write_vfta(struct igc_hw *hw, u32 offset, u32 value);
+s32 igc_force_mac_fc(struct igc_hw *hw);
+s32 igc_check_for_link(struct igc_hw *hw);
+s32 igc_reset_hw(struct igc_hw *hw);
+s32 igc_init_hw(struct igc_hw *hw);
+s32 igc_setup_link(struct igc_hw *hw);
+s32 igc_get_speed_and_duplex(struct igc_hw *hw, u16 *speed, u16 *duplex);
+s32 igc_disable_pcie_master(struct igc_hw *hw);
+void igc_config_collision_dist(struct igc_hw *hw);
+int igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index);
+u32 igc_hash_mc_addr(struct igc_hw *hw, u8 *mc_addr);
+void igc_update_mc_addr_list(struct igc_hw *hw, u8 *mc_addr_list,
+			       u32 mc_addr_count);
+s32 igc_setup_led(struct igc_hw *hw);
+s32 igc_cleanup_led(struct igc_hw *hw);
+s32 igc_check_reset_block(struct igc_hw *hw);
+s32 igc_blink_led(struct igc_hw *hw);
+s32 igc_led_on(struct igc_hw *hw);
+s32 igc_led_off(struct igc_hw *hw);
+s32 igc_id_led_init(struct igc_hw *hw);
+void igc_reset_adaptive(struct igc_hw *hw);
+void igc_update_adaptive(struct igc_hw *hw);
+s32 igc_get_cable_length(struct igc_hw *hw);
+s32 igc_validate_mdi_setting(struct igc_hw *hw);
+s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data);
+s32 igc_write_phy_reg(struct igc_hw *hw, u32 offset, u16 data);
+s32 igc_write_8bit_ctrl_reg(struct igc_hw *hw, u32 reg, u32 offset,
+			      u8 data);
+s32 igc_get_phy_info(struct igc_hw *hw);
+void igc_release_phy(struct igc_hw *hw);
+s32 igc_acquire_phy(struct igc_hw *hw);
+s32 igc_cfg_on_link_up(struct igc_hw *hw);
+s32 igc_phy_hw_reset(struct igc_hw *hw);
+s32 igc_phy_commit(struct igc_hw *hw);
+void igc_power_up_phy(struct igc_hw *hw);
+void igc_power_down_phy(struct igc_hw *hw);
+s32 igc_read_mac_addr(struct igc_hw *hw);
+s32 igc_read_pba_num(struct igc_hw *hw, u32 *part_num);
+s32 igc_read_pba_string(struct igc_hw *hw, u8 *pba_num, u32 pba_num_size);
+s32 igc_read_pba_length(struct igc_hw *hw, u32 *pba_num_size);
+void igc_reload_nvm(struct igc_hw *hw);
+s32 igc_update_nvm_checksum(struct igc_hw *hw);
+s32 igc_validate_nvm_checksum(struct igc_hw *hw);
+s32 igc_read_nvm(struct igc_hw *hw, u16 offset, u16 words, u16 *data);
+s32 igc_read_kmrn_reg(struct igc_hw *hw, u32 offset, u16 *data);
+s32 igc_write_kmrn_reg(struct igc_hw *hw, u32 offset, u16 data);
+s32 igc_write_nvm(struct igc_hw *hw, u16 offset, u16 words, u16 *data);
+s32 igc_set_d3_lplu_state(struct igc_hw *hw, bool active);
+s32 igc_set_d0_lplu_state(struct igc_hw *hw, bool active);
+bool igc_check_mng_mode(struct igc_hw *hw);
+bool igc_enable_tx_pkt_filtering(struct igc_hw *hw);
+s32 igc_mng_enable_host_if(struct igc_hw *hw);
+s32 igc_mng_host_if_write(struct igc_hw *hw, u8 *buffer, u16 length,
+			    u16 offset, u8 *sum);
+s32 igc_mng_write_cmd_header(struct igc_hw *hw,
+			       struct igc_host_mng_command_header *hdr);
+s32 igc_mng_write_dhcp_info(struct igc_hw *hw, u8 *buffer, u16 length);
+u32  igc_translate_register_82542(u32 reg);
+
+
+
+/*
+ * TBI_ACCEPT macro definition:
+ *
+ * This macro requires:
+ *      a = a pointer to struct igc_hw
+ *      status = the 8 bit status field of the Rx descriptor with EOP set
+ *      errors = the 8 bit error field of the Rx descriptor with EOP set
+ *      length = the sum of all the length fields of the Rx descriptors that
+ *               make up the current frame
+ *      last_byte = the last byte of the frame DMAed by the hardware
+ *      min_frame_size = the minimum frame length we want to accept.
+ *      max_frame_size = the maximum frame length we want to accept.
+ *
+ * This macro is a conditional that should be used in the interrupt
+ * handler's Rx processing routine when RxErrors have been detected.
+ *
+ * Typical use:
+ *  ...
+ *  if (TBI_ACCEPT) {
+ *      accept_frame = true;
+ *      igc_tbi_adjust_stats(adapter, MacAddress);
+ *      frame_length--;
+ *  } else {
+ *      accept_frame = false;
+ *  }
+ *  ...
+ */
+
+/* The carrier extension symbol, as received by the NIC. */
+#define CARRIER_EXTENSION   0x0F
+
+#define TBI_ACCEPT(a, status, errors, length, last_byte, \
+		   min_frame_size, max_frame_size) \
+	(igc_tbi_sbp_enabled_82543(a) && \
+	 (((errors) & IGC_RXD_ERR_FRAME_ERR_MASK) == IGC_RXD_ERR_CE) && \
+	 ((last_byte) == CARRIER_EXTENSION) && \
+	 (((status) & IGC_RXD_STAT_VP) ? \
+	  (((length) > ((min_frame_size) - VLAN_TAG_SIZE)) && \
+	  ((length) <= ((max_frame_size) + 1))) : \
+	  (((length) > (min_frame_size)) && \
+	  ((length) <= ((max_frame_size) + VLAN_TAG_SIZE + 1)))))
+
+#define IGC_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define IGC_DIVIDE_ROUND_UP(a, b)	(((a) + (b) - 1) / (b)) /* ceil(a/b) */
+#endif /* _IGC_API_H_ */
diff --git a/drivers/net/igc/base/e1000_base.c b/drivers/net/igc/base/e1000_base.c
new file mode 100644
index 0000000..fa9981b
--- /dev/null
+++ b/drivers/net/igc/base/e1000_base.c
@@ -0,0 +1,193 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#include "e1000_hw.h"
+#include "e1000_82575.h"
+#include "e1000_i225.h"
+#include "e1000_mac.h"
+#include "e1000_base.h"
+#include "e1000_manage.h"
+
+/**
+ *  igc_acquire_phy_base - Acquire rights to access PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire access rights to the correct PHY.
+ **/
+s32 igc_acquire_phy_base(struct igc_hw *hw)
+{
+	u16 mask = IGC_SWFW_PHY0_SM;
+
+	DEBUGFUNC("igc_acquire_phy_base");
+
+	if (hw->bus.func == IGC_FUNC_1)
+		mask = IGC_SWFW_PHY1_SM;
+	else if (hw->bus.func == IGC_FUNC_2)
+		mask = IGC_SWFW_PHY2_SM;
+	else if (hw->bus.func == IGC_FUNC_3)
+		mask = IGC_SWFW_PHY3_SM;
+
+	return hw->mac.ops.acquire_swfw_sync(hw, mask);
+}
+
+/**
+ *  igc_release_phy_base - Release rights to access PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  A wrapper to release access rights to the correct PHY.
+ **/
+void igc_release_phy_base(struct igc_hw *hw)
+{
+	u16 mask = IGC_SWFW_PHY0_SM;
+
+	DEBUGFUNC("igc_release_phy_base");
+
+	if (hw->bus.func == IGC_FUNC_1)
+		mask = IGC_SWFW_PHY1_SM;
+	else if (hw->bus.func == IGC_FUNC_2)
+		mask = IGC_SWFW_PHY2_SM;
+	else if (hw->bus.func == IGC_FUNC_3)
+		mask = IGC_SWFW_PHY3_SM;
+
+	hw->mac.ops.release_swfw_sync(hw, mask);
+}
+
+/**
+ *  igc_init_hw_base - Initialize hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This inits the hardware readying it for operation.
+ **/
+s32 igc_init_hw_base(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	s32 ret_val;
+	u16 i, rar_count = mac->rar_entry_count;
+
+	DEBUGFUNC("igc_init_hw_base");
+
+	/* Setup the receive address */
+	igc_init_rx_addrs_generic(hw, rar_count);
+
+	/* Zero out the Multicast HASH table */
+	DEBUGOUT("Zeroing the MTA\n");
+	for (i = 0; i < mac->mta_reg_count; i++)
+		IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
+
+	/* Zero out the Unicast HASH table */
+	DEBUGOUT("Zeroing the UTA\n");
+	for (i = 0; i < mac->uta_reg_count; i++)
+		IGC_WRITE_REG_ARRAY(hw, IGC_UTA, i, 0);
+
+	/* Setup link and flow control */
+	ret_val = mac->ops.setup_link(hw);
+	/*
+	 * Clear all of the statistics registers (clear on read).  It is
+	 * important that we do this after we have tried to establish link
+	 * because the symbol error count will increment wildly if there
+	 * is no link.
+	 */
+	igc_clear_hw_cntrs_base_generic(hw);
+
+	return ret_val;
+}
+
+/**
+ * igc_power_down_phy_copper_base - Remove link during PHY power down
+ * @hw: pointer to the HW structure
+ *
+ * In the case of a PHY power down to save power, or to turn off link during a
+ * driver unload, or wake on lan is not enabled, remove the link.
+ **/
+void igc_power_down_phy_copper_base(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+
+	if (!(phy->ops.check_reset_block))
+		return;
+
+	/* If the management interface is not enabled, then power down */
+	if (phy->ops.check_reset_block(hw))
+		igc_power_down_phy_copper(hw);
+
+	return;
+}
+
+/**
+ *  igc_rx_fifo_flush_base - Clean Rx FIFO after Rx enable
+ *  @hw: pointer to the HW structure
+ *
+ *  After Rx enable, if manageability is enabled then there is likely some
+ *  bad data at the start of the FIFO and possibly in the DMA FIFO.  This
+ *  function clears the FIFOs and flushes any packets that came in as Rx was
+ *  being enabled.
+ **/
+void igc_rx_fifo_flush_base(struct igc_hw *hw)
+{
+	u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
+	int i, ms_wait;
+
+	DEBUGFUNC("igc_rx_fifo_flush_base");
+
+	/* disable IPv6 options as per hardware errata */
+	rfctl = IGC_READ_REG(hw, IGC_RFCTL);
+	rfctl |= IGC_RFCTL_IPV6_EX_DIS;
+	IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
+
+	if (!(IGC_READ_REG(hw, IGC_MANC) & IGC_MANC_RCV_TCO_EN))
+		return;
+
+	/* Disable all Rx queues */
+	for (i = 0; i < 4; i++) {
+		rxdctl[i] = IGC_READ_REG(hw, IGC_RXDCTL(i));
+		IGC_WRITE_REG(hw, IGC_RXDCTL(i),
+				rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE);
+	}
+	/* Poll all queues to verify they have shut down */
+	for (ms_wait = 0; ms_wait < 10; ms_wait++) {
+		msec_delay(1);
+		rx_enabled = 0;
+		for (i = 0; i < 4; i++)
+			rx_enabled |= IGC_READ_REG(hw, IGC_RXDCTL(i));
+		if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE))
+			break;
+	}
+
+	if (ms_wait == 10)
+		DEBUGOUT("Queue disable timed out after 10ms\n");
+
+	/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
+	 * incoming packets are rejected.  Set enable and wait 2ms so that
+	 * any packet that was coming in as RCTL.EN was set is flushed
+	 */
+	IGC_WRITE_REG(hw, IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF);
+
+	rlpml = IGC_READ_REG(hw, IGC_RLPML);
+	IGC_WRITE_REG(hw, IGC_RLPML, 0);
+
+	rctl = IGC_READ_REG(hw, IGC_RCTL);
+	temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP);
+	temp_rctl |= IGC_RCTL_LPE;
+
+	IGC_WRITE_REG(hw, IGC_RCTL, temp_rctl);
+	IGC_WRITE_REG(hw, IGC_RCTL, temp_rctl | IGC_RCTL_EN);
+	IGC_WRITE_FLUSH(hw);
+	msec_delay(2);
+
+	/* Enable Rx queues that were previously enabled and restore our
+	 * previous state
+	 */
+	for (i = 0; i < 4; i++)
+		IGC_WRITE_REG(hw, IGC_RXDCTL(i), rxdctl[i]);
+	IGC_WRITE_REG(hw, IGC_RCTL, rctl);
+	IGC_WRITE_FLUSH(hw);
+
+	IGC_WRITE_REG(hw, IGC_RLPML, rlpml);
+	IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
+
+	/* Flush receive errors generated by workaround */
+	IGC_READ_REG(hw, IGC_ROC);
+	IGC_READ_REG(hw, IGC_RNBC);
+	IGC_READ_REG(hw, IGC_MPC);
+}
diff --git a/drivers/net/igc/base/e1000_base.h b/drivers/net/igc/base/e1000_base.h
new file mode 100644
index 0000000..1f569cf
--- /dev/null
+++ b/drivers/net/igc/base/e1000_base.h
@@ -0,0 +1,127 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_BASE_H_
+#define _IGC_BASE_H_
+
+/* forward declaration */
+s32 igc_init_hw_base(struct igc_hw *hw);
+void igc_power_down_phy_copper_base(struct igc_hw *hw);
+extern void igc_rx_fifo_flush_base(struct igc_hw *hw);
+s32 igc_acquire_phy_base(struct igc_hw *hw);
+void igc_release_phy_base(struct igc_hw *hw);
+
+/* Transmit Descriptor - Advanced */
+union igc_adv_tx_desc {
+	struct {
+		__le64 buffer_addr;    /* Address of descriptor's data buf */
+		__le32 cmd_type_len;
+		__le32 olinfo_status;
+	} read;
+	struct {
+		__le64 rsvd;       /* Reserved */
+		__le32 nxtseq_seed;
+		__le32 status;
+	} wb;
+};
+
+/* Context descriptors */
+struct igc_adv_tx_context_desc {
+	__le32 vlan_macip_lens;
+	union {
+		__le32 launch_time;
+		__le32 seqnum_seed;
+	} u;
+	__le32 type_tucmd_mlhl;
+	__le32 mss_l4len_idx;
+};
+
+/* Adv Transmit Descriptor Config Masks */
+#define IGC_ADVTXD_DTYP_CTXT	0x00200000 /* Advanced Context Descriptor */
+#define IGC_ADVTXD_DTYP_DATA	0x00300000 /* Advanced Data Descriptor */
+#define IGC_ADVTXD_DCMD_EOP	0x01000000 /* End of Packet */
+#define IGC_ADVTXD_DCMD_IFCS	0x02000000 /* Insert FCS (Ethernet CRC) */
+#define IGC_ADVTXD_DCMD_RS	0x08000000 /* Report Status */
+#define IGC_ADVTXD_DCMD_DDTYP_ISCSI	0x10000000 /* DDP hdr type or iSCSI */
+#define IGC_ADVTXD_DCMD_DEXT	0x20000000 /* Descriptor extension (1=Adv) */
+#define IGC_ADVTXD_DCMD_VLE	0x40000000 /* VLAN pkt enable */
+#define IGC_ADVTXD_DCMD_TSE	0x80000000 /* TCP Seg enable */
+#define IGC_ADVTXD_MAC_LINKSEC	0x00040000 /* Apply LinkSec on pkt */
+#define IGC_ADVTXD_MAC_TSTAMP		0x00080000 /* IEEE1588 Timestamp pkt */
+#define IGC_ADVTXD_STAT_SN_CRC	0x00000002 /* NXTSEQ/SEED prsnt in WB */
+#define IGC_ADVTXD_IDX_SHIFT		4  /* Adv desc Index shift */
+#define IGC_ADVTXD_POPTS_ISCO_1ST	0x00000000 /* 1st TSO of iSCSI PDU */
+#define IGC_ADVTXD_POPTS_ISCO_MDL	0x00000800 /* Middle TSO of iSCSI PDU */
+#define IGC_ADVTXD_POPTS_ISCO_LAST	0x00001000 /* Last TSO of iSCSI PDU */
+/* 1st & Last TSO-full iSCSI PDU*/
+#define IGC_ADVTXD_POPTS_ISCO_FULL	0x00001800
+#define IGC_ADVTXD_POPTS_IPSEC	0x00000400 /* IPSec offload request */
+#define IGC_ADVTXD_PAYLEN_SHIFT	14 /* Adv desc PAYLEN shift */
+
+/* Advanced Transmit Context Descriptor Config */
+#define IGC_ADVTXD_MACLEN_SHIFT	9  /* Adv ctxt desc mac len shift */
+#define IGC_ADVTXD_VLAN_SHIFT		16  /* Adv ctxt vlan tag shift */
+#define IGC_ADVTXD_TUCMD_IPV4		0x00000400  /* IP Packet Type: 1=IPv4 */
+#define IGC_ADVTXD_TUCMD_IPV6		0x00000000  /* IP Packet Type: 0=IPv6 */
+#define IGC_ADVTXD_TUCMD_L4T_UDP	0x00000000  /* L4 Packet TYPE of UDP */
+#define IGC_ADVTXD_TUCMD_L4T_TCP	0x00000800  /* L4 Packet TYPE of TCP */
+#define IGC_ADVTXD_TUCMD_L4T_SCTP	0x00001000  /* L4 Packet TYPE of SCTP */
+#define IGC_ADVTXD_TUCMD_IPSEC_TYPE_ESP	0x00002000 /* IPSec Type ESP */
+/* IPSec Encrypt Enable for ESP */
+#define IGC_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN	0x00004000
+/* Req requires Markers and CRC */
+#define IGC_ADVTXD_TUCMD_MKRREQ	0x00002000
+#define IGC_ADVTXD_L4LEN_SHIFT	8  /* Adv ctxt L4LEN shift */
+#define IGC_ADVTXD_MSS_SHIFT		16  /* Adv ctxt MSS shift */
+/* Adv ctxt IPSec SA IDX mask */
+#define IGC_ADVTXD_IPSEC_SA_INDEX_MASK	0x000000FF
+/* Adv ctxt IPSec ESP len mask */
+#define IGC_ADVTXD_IPSEC_ESP_LEN_MASK		0x000000FF
+
+#define IGC_RAR_ENTRIES_BASE		16
+
+/* Receive Descriptor - Advanced */
+union igc_adv_rx_desc {
+	struct {
+		__le64 pkt_addr; /* Packet buffer address */
+		__le64 hdr_addr; /* Header buffer address */
+	} read;
+	struct {
+		struct {
+			union {
+				__le32 data;
+				struct {
+					__le16 pkt_info; /*RSS type, Pkt type*/
+					/* Split Header, header buffer len */
+					__le16 hdr_info;
+				} hs_rss;
+			} lo_dword;
+			union {
+				__le32 rss; /* RSS Hash */
+				struct {
+					__le16 ip_id; /* IP id */
+					__le16 csum; /* Packet Checksum */
+				} csum_ip;
+			} hi_dword;
+		} lower;
+		struct {
+			__le32 status_error; /* ext status/error */
+			__le16 length; /* Packet length */
+			__le16 vlan; /* VLAN tag */
+		} upper;
+	} wb;  /* writeback */
+};
+
+/* Additional Transmit Descriptor Control definitions */
+#define IGC_TXDCTL_QUEUE_ENABLE	0x02000000 /* Ena specific Tx Queue */
+
+/* Additional Receive Descriptor Control definitions */
+#define IGC_RXDCTL_QUEUE_ENABLE	0x02000000 /* Ena specific Rx Queue */
+
+/* SRRCTL bit definitions */
+#define IGC_SRRCTL_BSIZEPKT_SHIFT		10 /* Shift _right_ */
+#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT		2  /* Shift _left_ */
+#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF	0x02000000
+
+#endif /* _IGC_BASE_H_ */
diff --git a/drivers/net/igc/base/e1000_defines.h b/drivers/net/igc/base/e1000_defines.h
new file mode 100644
index 0000000..1bf6964
--- /dev/null
+++ b/drivers/net/igc/base/e1000_defines.h
@@ -0,0 +1,1644 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_DEFINES_H_
+#define _IGC_DEFINES_H_
+
+/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define REQ_TX_DESCRIPTOR_MULTIPLE  8
+#define REQ_RX_DESCRIPTOR_MULTIPLE  8
+
+/* Definitions for power management and wakeup registers */
+/* Wake Up Control */
+#define IGC_WUC_APME		0x00000001 /* APM Enable */
+#define IGC_WUC_PME_EN	0x00000002 /* PME Enable */
+#define IGC_WUC_PME_STATUS	0x00000004 /* PME Status */
+#define IGC_WUC_APMPME	0x00000008 /* Assert PME on APM Wakeup */
+#define IGC_WUC_PHY_WAKE	0x00000100 /* if PHY supports wakeup */
+
+/* Wake Up Filter Control */
+#define IGC_WUFC_LNKC	0x00000001 /* Link Status Change Wakeup Enable */
+#define IGC_WUFC_MAG	0x00000002 /* Magic Packet Wakeup Enable */
+#define IGC_WUFC_EX	0x00000004 /* Directed Exact Wakeup Enable */
+#define IGC_WUFC_MC	0x00000008 /* Directed Multicast Wakeup Enable */
+#define IGC_WUFC_BC	0x00000010 /* Broadcast Wakeup Enable */
+#define IGC_WUFC_ARP	0x00000020 /* ARP Request Packet Wakeup Enable */
+#define IGC_WUFC_IPV4	0x00000040 /* Directed IPv4 Packet Wakeup Enable */
+#define IGC_WUFC_FLX0		0x00010000 /* Flexible Filter 0 Enable */
+
+/* Wake Up Status */
+#define IGC_WUS_LNKC		IGC_WUFC_LNKC
+#define IGC_WUS_MAG		IGC_WUFC_MAG
+#define IGC_WUS_EX		IGC_WUFC_EX
+#define IGC_WUS_MC		IGC_WUFC_MC
+#define IGC_WUS_BC		IGC_WUFC_BC
+
+/* Extended Device Control */
+#define IGC_CTRL_EXT_LPCD		0x00000004 /* LCD Power Cycle Done */
+#define IGC_CTRL_EXT_SDP4_DATA	0x00000010 /* SW Definable Pin 4 data */
+#define IGC_CTRL_EXT_SDP6_DATA	0x00000040 /* SW Definable Pin 6 data */
+#define IGC_CTRL_EXT_SDP3_DATA	0x00000080 /* SW Definable Pin 3 data */
+/* SDP 4/5 (bits 8,9) are reserved in >= 82575 */
+#define IGC_CTRL_EXT_SDP4_DIR	0x00000100 /* Direction of SDP4 0=in 1=out */
+#define IGC_CTRL_EXT_SDP6_DIR	0x00000400 /* Direction of SDP6 0=in 1=out */
+#define IGC_CTRL_EXT_SDP3_DIR	0x00000800 /* Direction of SDP3 0=in 1=out */
+#define IGC_CTRL_EXT_FORCE_SMBUS	0x00000800 /* Force SMBus mode */
+#define IGC_CTRL_EXT_EE_RST	0x00002000 /* Reinitialize from EEPROM */
+/* Physical Func Reset Done Indication */
+#define IGC_CTRL_EXT_PFRSTD	0x00004000
+#define IGC_CTRL_EXT_SDLPE	0X00040000  /* SerDes Low Power Enable */
+#define IGC_CTRL_EXT_SPD_BYPS	0x00008000 /* Speed Select Bypass */
+#define IGC_CTRL_EXT_RO_DIS	0x00020000 /* Relaxed Ordering disable */
+#define IGC_CTRL_EXT_DMA_DYN_CLK_EN	0x00080000 /* DMA Dynamic Clk Gating */
+#define IGC_CTRL_EXT_LINK_MODE_MASK	0x00C00000
+/* Offset of the link mode field in Ctrl Ext register */
+#define IGC_CTRL_EXT_LINK_MODE_OFFSET	22
+#define IGC_CTRL_EXT_LINK_MODE_1000BASE_KX	0x00400000
+#define IGC_CTRL_EXT_LINK_MODE_GMII	0x00000000
+#define IGC_CTRL_EXT_LINK_MODE_PCIE_SERDES	0x00C00000
+#define IGC_CTRL_EXT_LINK_MODE_SGMII	0x00800000
+#define IGC_CTRL_EXT_EIAME		0x01000000
+#define IGC_CTRL_EXT_IRCA		0x00000001
+#define IGC_CTRL_EXT_DRV_LOAD		0x10000000 /* Drv loaded bit for FW */
+#define IGC_CTRL_EXT_IAME		0x08000000 /* Int ACK Auto-mask */
+#define IGC_CTRL_EXT_PBA_CLR		0x80000000 /* PBA Clear */
+#define IGC_CTRL_EXT_LSECCK		0x00001000
+#define IGC_CTRL_EXT_PHYPDEN		0x00100000
+#define IGC_I2CCMD_REG_ADDR_SHIFT	16
+#define IGC_I2CCMD_PHY_ADDR_SHIFT	24
+#define IGC_I2CCMD_OPCODE_READ	0x08000000
+#define IGC_I2CCMD_OPCODE_WRITE	0x00000000
+#define IGC_I2CCMD_READY		0x20000000
+#define IGC_I2CCMD_ERROR		0x80000000
+#define IGC_I2CCMD_SFP_DATA_ADDR(a)	(0x0000 + (a))
+#define IGC_I2CCMD_SFP_DIAG_ADDR(a)	(0x0100 + (a))
+#define IGC_MAX_SGMII_PHY_REG_ADDR	255
+#define IGC_I2CCMD_PHY_TIMEOUT	200
+#define IGC_IVAR_VALID	0x80
+#define IGC_GPIE_NSICR	0x00000001
+#define IGC_GPIE_MSIX_MODE	0x00000010
+#define IGC_GPIE_EIAME	0x40000000
+#define IGC_GPIE_PBA		0x80000000
+
+/* Receive Descriptor bit definitions */
+#define IGC_RXD_STAT_DD	0x01    /* Descriptor Done */
+#define IGC_RXD_STAT_EOP	0x02    /* End of Packet */
+#define IGC_RXD_STAT_IXSM	0x04    /* Ignore checksum */
+#define IGC_RXD_STAT_VP	0x08    /* IEEE VLAN Packet */
+#define IGC_RXD_STAT_UDPCS	0x10    /* UDP xsum calculated */
+#define IGC_RXD_STAT_TCPCS	0x20    /* TCP xsum calculated */
+#define IGC_RXD_STAT_IPCS	0x40    /* IP xsum calculated */
+#define IGC_RXD_STAT_PIF	0x80    /* passed in-exact filter */
+#define IGC_RXD_STAT_IPIDV	0x200   /* IP identification valid */
+#define IGC_RXD_STAT_UDPV	0x400   /* Valid UDP checksum */
+#define IGC_RXD_STAT_DYNINT	0x800   /* Pkt caused INT via DYNINT */
+#define IGC_RXD_ERR_CE	0x01    /* CRC Error */
+#define IGC_RXD_ERR_SE	0x02    /* Symbol Error */
+#define IGC_RXD_ERR_SEQ	0x04    /* Sequence Error */
+#define IGC_RXD_ERR_CXE	0x10    /* Carrier Extension Error */
+#define IGC_RXD_ERR_TCPE	0x20    /* TCP/UDP Checksum Error */
+#define IGC_RXD_ERR_IPE	0x40    /* IP Checksum Error */
+#define IGC_RXD_ERR_RXE	0x80    /* Rx Data Error */
+#define IGC_RXD_SPC_VLAN_MASK	0x0FFF  /* VLAN ID is in lower 12 bits */
+
+#define IGC_RXDEXT_STATERR_TST	0x00000100 /* Time Stamp taken */
+#define IGC_RXDEXT_STATERR_LB		0x00040000
+#define IGC_RXDEXT_STATERR_CE		0x01000000
+#define IGC_RXDEXT_STATERR_SE		0x02000000
+#define IGC_RXDEXT_STATERR_SEQ	0x04000000
+#define IGC_RXDEXT_STATERR_CXE	0x10000000
+#define IGC_RXDEXT_STATERR_TCPE	0x20000000
+#define IGC_RXDEXT_STATERR_IPE	0x40000000
+#define IGC_RXDEXT_STATERR_RXE	0x80000000
+
+/* mask to determine if packets should be dropped due to frame errors */
+#define IGC_RXD_ERR_FRAME_ERR_MASK ( \
+	IGC_RXD_ERR_CE  |		\
+	IGC_RXD_ERR_SE  |		\
+	IGC_RXD_ERR_SEQ |		\
+	IGC_RXD_ERR_CXE |		\
+	IGC_RXD_ERR_RXE)
+
+/* Same mask, but for extended and packet split descriptors */
+#define IGC_RXDEXT_ERR_FRAME_ERR_MASK ( \
+	IGC_RXDEXT_STATERR_CE  |	\
+	IGC_RXDEXT_STATERR_SE  |	\
+	IGC_RXDEXT_STATERR_SEQ |	\
+	IGC_RXDEXT_STATERR_CXE |	\
+	IGC_RXDEXT_STATERR_RXE)
+
+#define IGC_MRQC_ENABLE_RSS_2Q		0x00000001
+#define IGC_MRQC_RSS_FIELD_MASK		0xFFFF0000
+#define IGC_MRQC_RSS_FIELD_IPV4_TCP		0x00010000
+#define IGC_MRQC_RSS_FIELD_IPV4		0x00020000
+#define IGC_MRQC_RSS_FIELD_IPV6_TCP_EX	0x00040000
+#define IGC_MRQC_RSS_FIELD_IPV6		0x00100000
+#define IGC_MRQC_RSS_FIELD_IPV6_TCP		0x00200000
+
+#define IGC_RXDPS_HDRSTAT_HDRSP		0x00008000
+
+/* Management Control */
+#define IGC_MANC_SMBUS_EN	0x00000001 /* SMBus Enabled - RO */
+#define IGC_MANC_ASF_EN	0x00000002 /* ASF Enabled - RO */
+#define IGC_MANC_ARP_EN	0x00002000 /* Enable ARP Request Filtering */
+#define IGC_MANC_RCV_TCO_EN	0x00020000 /* Receive TCO Packets Enabled */
+#define IGC_MANC_BLK_PHY_RST_ON_IDE	0x00040000 /* Block phy resets */
+/* Enable MAC address filtering */
+#define IGC_MANC_EN_MAC_ADDR_FILTER	0x00100000
+/* Enable MNG packets to host memory */
+#define IGC_MANC_EN_MNG2HOST		0x00200000
+
+#define IGC_MANC2H_PORT_623		0x00000020 /* Port 0x26f */
+#define IGC_MANC2H_PORT_664		0x00000040 /* Port 0x298 */
+#define IGC_MDEF_PORT_623		0x00000800 /* Port 0x26f */
+#define IGC_MDEF_PORT_664		0x00000400 /* Port 0x298 */
+
+/* Receive Control */
+#define IGC_RCTL_RST		0x00000001 /* Software reset */
+#define IGC_RCTL_EN		0x00000002 /* enable */
+#define IGC_RCTL_SBP		0x00000004 /* store bad packet */
+#define IGC_RCTL_UPE		0x00000008 /* unicast promisc enable */
+#define IGC_RCTL_MPE		0x00000010 /* multicast promisc enable */
+#define IGC_RCTL_LPE		0x00000020 /* long packet enable */
+#define IGC_RCTL_LBM_NO	0x00000000 /* no loopback mode */
+#define IGC_RCTL_LBM_MAC	0x00000040 /* MAC loopback mode */
+#define IGC_RCTL_LBM_TCVR	0x000000C0 /* tcvr loopback mode */
+#define IGC_RCTL_DTYP_PS	0x00000400 /* Packet Split descriptor */
+#define IGC_RCTL_RDMTS_HALF	0x00000000 /* Rx desc min thresh size */
+#define IGC_RCTL_RDMTS_HEX	0x00010000
+#define IGC_RCTL_RDMTS1_HEX	IGC_RCTL_RDMTS_HEX
+#define IGC_RCTL_MO_SHIFT	12 /* multicast offset shift */
+#define IGC_RCTL_MO_3		0x00003000 /* multicast offset 15:4 */
+#define IGC_RCTL_BAM		0x00008000 /* broadcast enable */
+/* these buffer sizes are valid if IGC_RCTL_BSEX is 0 */
+#define IGC_RCTL_SZ_2048	0x00000000 /* Rx buffer size 2048 */
+#define IGC_RCTL_SZ_1024	0x00010000 /* Rx buffer size 1024 */
+#define IGC_RCTL_SZ_512	0x00020000 /* Rx buffer size 512 */
+#define IGC_RCTL_SZ_256	0x00030000 /* Rx buffer size 256 */
+/* these buffer sizes are valid if IGC_RCTL_BSEX is 1 */
+#define IGC_RCTL_SZ_16384	0x00010000 /* Rx buffer size 16384 */
+#define IGC_RCTL_SZ_8192	0x00020000 /* Rx buffer size 8192 */
+#define IGC_RCTL_SZ_4096	0x00030000 /* Rx buffer size 4096 */
+#define IGC_RCTL_VFE		0x00040000 /* vlan filter enable */
+#define IGC_RCTL_CFIEN	0x00080000 /* canonical form enable */
+#define IGC_RCTL_CFI		0x00100000 /* canonical form indicator */
+#define IGC_RCTL_DPF		0x00400000 /* discard pause frames */
+#define IGC_RCTL_PMCF		0x00800000 /* pass MAC control frames */
+#define IGC_RCTL_BSEX		0x02000000 /* Buffer size extension */
+#define IGC_RCTL_SECRC	0x04000000 /* Strip Ethernet CRC */
+
+/* Use byte values for the following shift parameters
+ * Usage:
+ *     psrctl |= (((ROUNDUP(value0, 128) >> IGC_PSRCTL_BSIZE0_SHIFT) &
+ *		  IGC_PSRCTL_BSIZE0_MASK) |
+ *		((ROUNDUP(value1, 1024) >> IGC_PSRCTL_BSIZE1_SHIFT) &
+ *		  IGC_PSRCTL_BSIZE1_MASK) |
+ *		((ROUNDUP(value2, 1024) << IGC_PSRCTL_BSIZE2_SHIFT) &
+ *		  IGC_PSRCTL_BSIZE2_MASK) |
+ *		((ROUNDUP(value3, 1024) << IGC_PSRCTL_BSIZE3_SHIFT) |;
+ *		  IGC_PSRCTL_BSIZE3_MASK))
+ * where value0 = [128..16256],  default=256
+ *       value1 = [1024..64512], default=4096
+ *       value2 = [0..64512],    default=4096
+ *       value3 = [0..64512],    default=0
+ */
+
+#define IGC_PSRCTL_BSIZE0_MASK	0x0000007F
+#define IGC_PSRCTL_BSIZE1_MASK	0x00003F00
+#define IGC_PSRCTL_BSIZE2_MASK	0x003F0000
+#define IGC_PSRCTL_BSIZE3_MASK	0x3F000000
+
+#define IGC_PSRCTL_BSIZE0_SHIFT	7    /* Shift _right_ 7 */
+#define IGC_PSRCTL_BSIZE1_SHIFT	2    /* Shift _right_ 2 */
+#define IGC_PSRCTL_BSIZE2_SHIFT	6    /* Shift _left_ 6 */
+#define IGC_PSRCTL_BSIZE3_SHIFT	14   /* Shift _left_ 14 */
+
+/* SWFW_SYNC Definitions */
+#define IGC_SWFW_EEP_SM	0x01
+#define IGC_SWFW_PHY0_SM	0x02
+#define IGC_SWFW_PHY1_SM	0x04
+#define IGC_SWFW_CSR_SM	0x08
+#define IGC_SWFW_PHY2_SM	0x20
+#define IGC_SWFW_PHY3_SM	0x40
+#define IGC_SWFW_SW_MNG_SM	0x400
+
+/* Device Control */
+#define IGC_CTRL_FD		0x00000001  /* Full duplex.0=half; 1=full */
+#define IGC_CTRL_PRIOR	0x00000004  /* Priority on PCI. 0=rx,1=fair */
+#define IGC_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master reqs */
+#define IGC_CTRL_LRST		0x00000008  /* Link reset. 0=normal,1=reset */
+#define IGC_CTRL_ASDE		0x00000020  /* Auto-speed detect enable */
+#define IGC_CTRL_SLU		0x00000040  /* Set link up (Force Link) */
+#define IGC_CTRL_ILOS		0x00000080  /* Invert Loss-Of Signal */
+#define IGC_CTRL_SPD_SEL	0x00000300  /* Speed Select Mask */
+#define IGC_CTRL_SPD_10	0x00000000  /* Force 10Mb */
+#define IGC_CTRL_SPD_100	0x00000100  /* Force 100Mb */
+#define IGC_CTRL_SPD_1000	0x00000200  /* Force 1Gb */
+#define IGC_CTRL_FRCSPD	0x00000800  /* Force Speed */
+#define IGC_CTRL_FRCDPX	0x00001000  /* Force Duplex */
+#define IGC_CTRL_LANPHYPC_OVERRIDE	0x00010000 /* SW control of LANPHYPC */
+#define IGC_CTRL_LANPHYPC_VALUE	0x00020000 /* SW value of LANPHYPC */
+#define IGC_CTRL_MEHE		0x00080000 /* Memory Error Handling Enable */
+#define IGC_CTRL_SWDPIN0	0x00040000 /* SWDPIN 0 value */
+#define IGC_CTRL_SWDPIN1	0x00080000 /* SWDPIN 1 value */
+#define IGC_CTRL_SWDPIN2	0x00100000 /* SWDPIN 2 value */
+#define IGC_CTRL_ADVD3WUC	0x00100000 /* D3 WUC */
+#define IGC_CTRL_EN_PHY_PWR_MGMT	0x00200000 /* PHY PM enable */
+#define IGC_CTRL_SWDPIN3	0x00200000 /* SWDPIN 3 value */
+#define IGC_CTRL_SWDPIO0	0x00400000 /* SWDPIN 0 Input or output */
+#define IGC_CTRL_SWDPIO2	0x01000000 /* SWDPIN 2 input or output */
+#define IGC_CTRL_SWDPIO3	0x02000000 /* SWDPIN 3 input or output */
+#define IGC_CTRL_DEV_RST	0x20000000 /* Device reset */
+#define IGC_CTRL_RST		0x04000000 /* Global reset */
+#define IGC_CTRL_RFCE		0x08000000 /* Receive Flow Control enable */
+#define IGC_CTRL_TFCE		0x10000000 /* Transmit flow control enable */
+#define IGC_CTRL_VME		0x40000000 /* IEEE VLAN mode enable */
+#define IGC_CTRL_PHY_RST	0x80000000 /* PHY Reset */
+#define IGC_CTRL_I2C_ENA	0x02000000 /* I2C enable */
+
+#define IGC_CTRL_MDIO_DIR		IGC_CTRL_SWDPIO2
+#define IGC_CTRL_MDIO			IGC_CTRL_SWDPIN2
+#define IGC_CTRL_MDC_DIR		IGC_CTRL_SWDPIO3
+#define IGC_CTRL_MDC			IGC_CTRL_SWDPIN3
+
+#define IGC_CONNSW_AUTOSENSE_EN	0x1
+#define IGC_CONNSW_ENRGSRC		0x4
+#define IGC_CONNSW_PHYSD		0x400
+#define IGC_CONNSW_PHY_PDN		0x800
+#define IGC_CONNSW_SERDESD		0x200
+#define IGC_CONNSW_AUTOSENSE_CONF	0x2
+#define IGC_PCS_CFG_PCS_EN		8
+#define IGC_PCS_LCTL_FLV_LINK_UP	1
+#define IGC_PCS_LCTL_FSV_10		0
+#define IGC_PCS_LCTL_FSV_100		2
+#define IGC_PCS_LCTL_FSV_1000		4
+#define IGC_PCS_LCTL_FDV_FULL		8
+#define IGC_PCS_LCTL_FSD		0x10
+#define IGC_PCS_LCTL_FORCE_LINK	0x20
+#define IGC_PCS_LCTL_FORCE_FCTRL	0x80
+#define IGC_PCS_LCTL_AN_ENABLE	0x10000
+#define IGC_PCS_LCTL_AN_RESTART	0x20000
+#define IGC_PCS_LCTL_AN_TIMEOUT	0x40000
+#define IGC_ENABLE_SERDES_LOOPBACK	0x0410
+
+#define IGC_PCS_LSTS_LINK_OK		1
+#define IGC_PCS_LSTS_SPEED_100	2
+#define IGC_PCS_LSTS_SPEED_1000	4
+#define IGC_PCS_LSTS_DUPLEX_FULL	8
+#define IGC_PCS_LSTS_SYNK_OK		0x10
+#define IGC_PCS_LSTS_AN_COMPLETE	0x10000
+
+/* Device Status */
+#define IGC_STATUS_FD			0x00000001 /* Duplex 0=half 1=full */
+#define IGC_STATUS_LU			0x00000002 /* Link up.0=no,1=link */
+#define IGC_STATUS_FUNC_MASK		0x0000000C /* PCI Function Mask */
+#define IGC_STATUS_FUNC_SHIFT		2
+#define IGC_STATUS_FUNC_1		0x00000004 /* Function 1 */
+#define IGC_STATUS_TXOFF		0x00000010 /* transmission paused */
+#define IGC_STATUS_SPEED_MASK	0x000000C0
+#define IGC_STATUS_SPEED_10		0x00000000 /* Speed 10Mb/s */
+#define IGC_STATUS_SPEED_100		0x00000040 /* Speed 100Mb/s */
+#define IGC_STATUS_SPEED_1000		0x00000080 /* Speed 1000Mb/s */
+#define IGC_STATUS_SPEED_2500		0x00400000 /* Speed 2.5Gb/s indication for I225 */
+#define IGC_STATUS_LAN_INIT_DONE	0x00000200 /* Lan Init Compltn by NVM */
+#define IGC_STATUS_PHYRA		0x00000400 /* PHY Reset Asserted */
+#define IGC_STATUS_GIO_MASTER_ENABLE	0x00080000 /* Master request status */
+#define IGC_STATUS_PCI66		0x00000800 /* In 66Mhz slot */
+#define IGC_STATUS_BUS64		0x00001000 /* In 64 bit slot */
+#define IGC_STATUS_2P5_SKU		0x00001000 /* Val of 2.5GBE SKU strap */
+#define IGC_STATUS_2P5_SKU_OVER	0x00002000 /* Val of 2.5GBE SKU Over */
+#define IGC_STATUS_PCIX_MODE		0x00002000 /* PCI-X mode */
+#define IGC_STATUS_PCIX_SPEED		0x0000C000 /* PCI-X bus speed */
+
+/* Constants used to interpret the masked PCI-X bus speed. */
+#define IGC_STATUS_PCIX_SPEED_66	0x00000000 /* PCI-X bus spd 50-66MHz */
+#define IGC_STATUS_PCIX_SPEED_100	0x00004000 /* PCI-X bus spd 66-100MHz */
+#define IGC_STATUS_PCIX_SPEED_133	0x00008000 /* PCI-X bus spd 100-133MHz*/
+#define IGC_STATUS_PCIM_STATE		0x40000000 /* PCIm function state */
+
+#define SPEED_10	10
+#define SPEED_100	100
+#define SPEED_1000	1000
+#define SPEED_2500	2500
+#define HALF_DUPLEX	1
+#define FULL_DUPLEX	2
+
+#define PHY_FORCE_TIME	20
+
+#define ADVERTISE_10_HALF		0x0001
+#define ADVERTISE_10_FULL		0x0002
+#define ADVERTISE_100_HALF		0x0004
+#define ADVERTISE_100_FULL		0x0008
+#define ADVERTISE_1000_HALF		0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL		0x0020
+#define ADVERTISE_2500_HALF		0x0040 /* NOT used, just FYI */
+#define ADVERTISE_2500_FULL		0x0080
+
+/* 1000/H is not supported, nor spec-compliant. */
+#define IGC_ALL_SPEED_DUPLEX	( \
+	ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
+	ADVERTISE_100_FULL | ADVERTISE_1000_FULL)
+#define IGC_ALL_SPEED_DUPLEX_2500 ( \
+	ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
+	ADVERTISE_100_FULL | ADVERTISE_1000_FULL | ADVERTISE_2500_FULL)
+#define IGC_ALL_NOT_GIG	( \
+	ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
+	ADVERTISE_100_FULL)
+#define IGC_ALL_100_SPEED	(ADVERTISE_100_HALF | ADVERTISE_100_FULL)
+#define IGC_ALL_10_SPEED	(ADVERTISE_10_HALF | ADVERTISE_10_FULL)
+#define IGC_ALL_HALF_DUPLEX	(ADVERTISE_10_HALF | ADVERTISE_100_HALF)
+
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT		IGC_ALL_SPEED_DUPLEX
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT_2500	IGC_ALL_SPEED_DUPLEX_2500
+
+/* LED Control */
+#define IGC_PHY_LED0_MODE_MASK	0x00000007
+#define IGC_PHY_LED0_IVRT		0x00000008
+#define IGC_PHY_LED0_MASK		0x0000001F
+
+#define IGC_LEDCTL_LED0_MODE_MASK	0x0000000F
+#define IGC_LEDCTL_LED0_MODE_SHIFT	0
+#define IGC_LEDCTL_LED0_IVRT		0x00000040
+#define IGC_LEDCTL_LED0_BLINK		0x00000080
+
+#define IGC_LEDCTL_MODE_LINK_UP	0x2
+#define IGC_LEDCTL_MODE_LED_ON	0xE
+#define IGC_LEDCTL_MODE_LED_OFF	0xF
+
+/* Transmit Descriptor bit definitions */
+#define IGC_TXD_DTYP_D	0x00100000 /* Data Descriptor */
+#define IGC_TXD_DTYP_C	0x00000000 /* Context Descriptor */
+#define IGC_TXD_POPTS_IXSM	0x01       /* Insert IP checksum */
+#define IGC_TXD_POPTS_TXSM	0x02       /* Insert TCP/UDP checksum */
+#define IGC_TXD_CMD_EOP	0x01000000 /* End of Packet */
+#define IGC_TXD_CMD_IFCS	0x02000000 /* Insert FCS (Ethernet CRC) */
+#define IGC_TXD_CMD_IC	0x04000000 /* Insert Checksum */
+#define IGC_TXD_CMD_RS	0x08000000 /* Report Status */
+#define IGC_TXD_CMD_RPS	0x10000000 /* Report Packet Sent */
+#define IGC_TXD_CMD_DEXT	0x20000000 /* Desc extension (0 = legacy) */
+#define IGC_TXD_CMD_VLE	0x40000000 /* Add VLAN tag */
+#define IGC_TXD_CMD_IDE	0x80000000 /* Enable Tidv register */
+#define IGC_TXD_STAT_DD	0x00000001 /* Descriptor Done */
+#define IGC_TXD_STAT_EC	0x00000002 /* Excess Collisions */
+#define IGC_TXD_STAT_LC	0x00000004 /* Late Collisions */
+#define IGC_TXD_STAT_TU	0x00000008 /* Transmit underrun */
+#define IGC_TXD_CMD_TCP	0x01000000 /* TCP packet */
+#define IGC_TXD_CMD_IP	0x02000000 /* IP packet */
+#define IGC_TXD_CMD_TSE	0x04000000 /* TCP Seg enable */
+#define IGC_TXD_STAT_TC	0x00000004 /* Tx Underrun */
+#define IGC_TXD_EXTCMD_TSTAMP	0x00000010 /* IEEE1588 Timestamp packet */
+
+/* Transmit Control */
+#define IGC_TCTL_EN		0x00000002 /* enable Tx */
+#define IGC_TCTL_PSP		0x00000008 /* pad short packets */
+#define IGC_TCTL_CT		0x00000ff0 /* collision threshold */
+#define IGC_TCTL_COLD		0x003ff000 /* collision distance */
+#define IGC_TCTL_RTLC		0x01000000 /* Re-transmit on late collision */
+#define IGC_TCTL_MULR		0x10000000 /* Multiple request support */
+
+/* Transmit Arbitration Count */
+#define IGC_TARC0_ENABLE	0x00000400 /* Enable Tx Queue 0 */
+
+/* SerDes Control */
+#define IGC_SCTL_DISABLE_SERDES_LOOPBACK	0x0400
+#define IGC_SCTL_ENABLE_SERDES_LOOPBACK	0x0410
+
+/* Receive Checksum Control */
+#define IGC_RXCSUM_IPOFL	0x00000100 /* IPv4 checksum offload */
+#define IGC_RXCSUM_TUOFL	0x00000200 /* TCP / UDP checksum offload */
+#define IGC_RXCSUM_CRCOFL	0x00000800 /* CRC32 offload enable */
+#define IGC_RXCSUM_IPPCSE	0x00001000 /* IP payload checksum enable */
+#define IGC_RXCSUM_PCSD	0x00002000 /* packet checksum disabled */
+
+/* GPY211 - I225 defines */
+#define GPY_MMD_MASK		0xFFFF0000
+#define GPY_MMD_SHIFT		16
+#define GPY_REG_MASK		0x0000FFFF
+/* Header split receive */
+#define IGC_RFCTL_NFSW_DIS		0x00000040
+#define IGC_RFCTL_NFSR_DIS		0x00000080
+#define IGC_RFCTL_ACK_DIS		0x00001000
+#define IGC_RFCTL_EXTEN		0x00008000
+#define IGC_RFCTL_IPV6_EX_DIS		0x00010000
+#define IGC_RFCTL_NEW_IPV6_EXT_DIS	0x00020000
+#define IGC_RFCTL_LEF			0x00040000
+
+/* Collision related configuration parameters */
+#define IGC_CT_SHIFT			4
+#define IGC_COLLISION_THRESHOLD	15
+#define IGC_COLLISION_DISTANCE	63
+#define IGC_COLD_SHIFT		12
+
+/* Default values for the transmit IPG register */
+#define DEFAULT_82542_TIPG_IPGT		10
+#define DEFAULT_82543_TIPG_IPGT_FIBER	9
+#define DEFAULT_82543_TIPG_IPGT_COPPER	8
+
+#define IGC_TIPG_IPGT_MASK		0x000003FF
+
+#define DEFAULT_82542_TIPG_IPGR1	2
+#define DEFAULT_82543_TIPG_IPGR1	8
+#define IGC_TIPG_IPGR1_SHIFT		10
+
+#define DEFAULT_82542_TIPG_IPGR2	10
+#define DEFAULT_82543_TIPG_IPGR2	6
+#define DEFAULT_80003ES2LAN_TIPG_IPGR2	7
+#define IGC_TIPG_IPGR2_SHIFT		20
+
+/* Ethertype field values */
+#define ETHERNET_IEEE_VLAN_TYPE		0x8100  /* 802.3ac packet */
+
+#define ETHERNET_FCS_SIZE		4
+#define MAX_JUMBO_FRAME_SIZE		0x3F00
+/* The datasheet maximum supported RX size is 9.5KB (9728 bytes) */
+#define MAX_RX_JUMBO_FRAME_SIZE		0x2600
+#define IGC_TX_PTR_GAP		0x1F
+
+/* Extended Configuration Control and Size */
+#define IGC_EXTCNF_CTRL_MDIO_SW_OWNERSHIP	0x00000020
+#define IGC_EXTCNF_CTRL_LCD_WRITE_ENABLE	0x00000001
+#define IGC_EXTCNF_CTRL_OEM_WRITE_ENABLE	0x00000008
+#define IGC_EXTCNF_CTRL_SWFLAG		0x00000020
+#define IGC_EXTCNF_CTRL_GATE_PHY_CFG		0x00000080
+#define IGC_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK	0x00FF0000
+#define IGC_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT	16
+#define IGC_EXTCNF_CTRL_EXT_CNF_POINTER_MASK	0x0FFF0000
+#define IGC_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT	16
+
+#define IGC_PHY_CTRL_D0A_LPLU			0x00000002
+#define IGC_PHY_CTRL_NOND0A_LPLU		0x00000004
+#define IGC_PHY_CTRL_NOND0A_GBE_DISABLE	0x00000008
+#define IGC_PHY_CTRL_GBE_DISABLE		0x00000040
+
+#define IGC_KABGTXD_BGSQLBIAS			0x00050000
+
+/* Low Power IDLE Control */
+#define IGC_LPIC_LPIET_SHIFT		24	/* Low Power Idle Entry Time */
+
+/* PBA constants */
+#define IGC_PBA_8K		0x0008    /* 8KB */
+#define IGC_PBA_10K		0x000A    /* 10KB */
+#define IGC_PBA_12K		0x000C    /* 12KB */
+#define IGC_PBA_14K		0x000E    /* 14KB */
+#define IGC_PBA_16K		0x0010    /* 16KB */
+#define IGC_PBA_18K		0x0012
+#define IGC_PBA_20K		0x0014
+#define IGC_PBA_22K		0x0016
+#define IGC_PBA_24K		0x0018
+#define IGC_PBA_26K		0x001A
+#define IGC_PBA_30K		0x001E
+#define IGC_PBA_32K		0x0020
+#define IGC_PBA_34K		0x0022
+#define IGC_PBA_35K		0x0023
+#define IGC_PBA_38K		0x0026
+#define IGC_PBA_40K		0x0028
+#define IGC_PBA_48K		0x0030    /* 48KB */
+#define IGC_PBA_64K		0x0040    /* 64KB */
+
+#define IGC_PBA_RXA_MASK	0xFFFF
+
+#define IGC_PBS_16K		IGC_PBA_16K
+
+/* Uncorrectable/correctable ECC Error counts and enable bits */
+#define IGC_PBECCSTS_CORR_ERR_CNT_MASK	0x000000FF
+#define IGC_PBECCSTS_UNCORR_ERR_CNT_MASK	0x0000FF00
+#define IGC_PBECCSTS_UNCORR_ERR_CNT_SHIFT	8
+#define IGC_PBECCSTS_ECC_ENABLE		0x00010000
+
+#define IFS_MAX			80
+#define IFS_MIN			40
+#define IFS_RATIO		4
+#define IFS_STEP		10
+#define MIN_NUM_XMITS		1000
+
+/* SW Semaphore Register */
+#define IGC_SWSM_SMBI		0x00000001 /* Driver Semaphore bit */
+#define IGC_SWSM_SWESMBI	0x00000002 /* FW Semaphore bit */
+#define IGC_SWSM_DRV_LOAD	0x00000008 /* Driver Loaded Bit */
+
+#define IGC_SWSM2_LOCK	0x00000002 /* Secondary driver semaphore bit */
+
+/* Interrupt Cause Read */
+#define IGC_ICR_TXDW		0x00000001 /* Transmit desc written back */
+#define IGC_ICR_TXQE		0x00000002 /* Transmit Queue empty */
+#define IGC_ICR_LSC		0x00000004 /* Link Status Change */
+#define IGC_ICR_RXSEQ		0x00000008 /* Rx sequence error */
+#define IGC_ICR_RXDMT0	0x00000010 /* Rx desc min. threshold (0) */
+#define IGC_ICR_RXO		0x00000040 /* Rx overrun */
+#define IGC_ICR_RXT0		0x00000080 /* Rx timer intr (ring 0) */
+#define IGC_ICR_VMMB		0x00000100 /* VM MB event */
+#define IGC_ICR_RXCFG		0x00000400 /* Rx /c/ ordered set */
+#define IGC_ICR_GPI_EN0	0x00000800 /* GP Int 0 */
+#define IGC_ICR_GPI_EN1	0x00001000 /* GP Int 1 */
+#define IGC_ICR_GPI_EN2	0x00002000 /* GP Int 2 */
+#define IGC_ICR_GPI_EN3	0x00004000 /* GP Int 3 */
+#define IGC_ICR_TXD_LOW	0x00008000
+#define IGC_ICR_MNG		0x00040000 /* Manageability event */
+#define IGC_ICR_ECCER		0x00400000 /* Uncorrectable ECC Error */
+#define IGC_ICR_TS		0x00080000 /* Time Sync Interrupt */
+#define IGC_ICR_DRSTA		0x40000000 /* Device Reset Asserted */
+/* If this bit asserted, the driver should claim the interrupt */
+#define IGC_ICR_INT_ASSERTED	0x80000000
+#define IGC_ICR_DOUTSYNC	0x10000000 /* NIC DMA out of sync */
+#define IGC_ICR_RXQ0		0x00100000 /* Rx Queue 0 Interrupt */
+#define IGC_ICR_RXQ1		0x00200000 /* Rx Queue 1 Interrupt */
+#define IGC_ICR_TXQ0		0x00400000 /* Tx Queue 0 Interrupt */
+#define IGC_ICR_TXQ1		0x00800000 /* Tx Queue 1 Interrupt */
+#define IGC_ICR_OTHER		0x01000000 /* Other Interrupts */
+#define IGC_ICR_FER		0x00400000 /* Fatal Error */
+
+#define IGC_ICR_THS		0x00800000 /* ICR.THS: Thermal Sensor Event*/
+#define IGC_ICR_MDDET		0x10000000 /* Malicious Driver Detect */
+
+/* PBA ECC Register */
+#define IGC_PBA_ECC_COUNTER_MASK	0xFFF00000 /* ECC counter mask */
+#define IGC_PBA_ECC_COUNTER_SHIFT	20 /* ECC counter shift value */
+#define IGC_PBA_ECC_CORR_EN	0x00000001 /* Enable ECC error correction */
+#define IGC_PBA_ECC_STAT_CLR	0x00000002 /* Clear ECC error counter */
+#define IGC_PBA_ECC_INT_EN	0x00000004 /* Enable ICR bit 5 on ECC error */
+
+/* Extended Interrupt Cause Read */
+#define IGC_EICR_RX_QUEUE0	0x00000001 /* Rx Queue 0 Interrupt */
+#define IGC_EICR_RX_QUEUE1	0x00000002 /* Rx Queue 1 Interrupt */
+#define IGC_EICR_RX_QUEUE2	0x00000004 /* Rx Queue 2 Interrupt */
+#define IGC_EICR_RX_QUEUE3	0x00000008 /* Rx Queue 3 Interrupt */
+#define IGC_EICR_TX_QUEUE0	0x00000100 /* Tx Queue 0 Interrupt */
+#define IGC_EICR_TX_QUEUE1	0x00000200 /* Tx Queue 1 Interrupt */
+#define IGC_EICR_TX_QUEUE2	0x00000400 /* Tx Queue 2 Interrupt */
+#define IGC_EICR_TX_QUEUE3	0x00000800 /* Tx Queue 3 Interrupt */
+#define IGC_EICR_TCP_TIMER	0x40000000 /* TCP Timer */
+#define IGC_EICR_OTHER	0x80000000 /* Interrupt Cause Active */
+/* TCP Timer */
+#define IGC_TCPTIMER_KS	0x00000100 /* KickStart */
+#define IGC_TCPTIMER_COUNT_ENABLE	0x00000200 /* Count Enable */
+#define IGC_TCPTIMER_COUNT_FINISH	0x00000400 /* Count finish */
+#define IGC_TCPTIMER_LOOP	0x00000800 /* Loop */
+
+/* This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register.  Each bit is documented below:
+ *   o RXT0   = Receiver Timer Interrupt (ring 0)
+ *   o TXDW   = Transmit Descriptor Written Back
+ *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ *   o RXSEQ  = Receive Sequence Error
+ *   o LSC    = Link Status Change
+ */
+#define IMS_ENABLE_MASK ( \
+	IGC_IMS_RXT0   |    \
+	IGC_IMS_TXDW   |    \
+	IGC_IMS_RXDMT0 |    \
+	IGC_IMS_RXSEQ  |    \
+	IGC_IMS_LSC)
+
+/* Interrupt Mask Set */
+#define IGC_IMS_TXDW		IGC_ICR_TXDW    /* Tx desc written back */
+#define IGC_IMS_TXQE		IGC_ICR_TXQE    /* Transmit Queue empty */
+#define IGC_IMS_LSC		IGC_ICR_LSC     /* Link Status Change */
+#define IGC_IMS_VMMB		IGC_ICR_VMMB    /* Mail box activity */
+#define IGC_IMS_RXSEQ		IGC_ICR_RXSEQ   /* Rx sequence error */
+#define IGC_IMS_RXDMT0	IGC_ICR_RXDMT0  /* Rx desc min. threshold */
+#define IGC_QVECTOR_MASK	0x7FFC		/* Q-vector mask */
+#define IGC_ITR_VAL_MASK	0x04		/* ITR value mask */
+#define IGC_IMS_RXO		IGC_ICR_RXO     /* Rx overrun */
+#define IGC_IMS_RXT0		IGC_ICR_RXT0    /* Rx timer intr */
+#define IGC_IMS_TXD_LOW	IGC_ICR_TXD_LOW
+#define IGC_IMS_ECCER		IGC_ICR_ECCER   /* Uncorrectable ECC Error */
+#define IGC_IMS_TS		IGC_ICR_TS      /* Time Sync Interrupt */
+#define IGC_IMS_DRSTA		IGC_ICR_DRSTA   /* Device Reset Asserted */
+#define IGC_IMS_DOUTSYNC	IGC_ICR_DOUTSYNC /* NIC DMA out of sync */
+#define IGC_IMS_RXQ0		IGC_ICR_RXQ0 /* Rx Queue 0 Interrupt */
+#define IGC_IMS_RXQ1		IGC_ICR_RXQ1 /* Rx Queue 1 Interrupt */
+#define IGC_IMS_TXQ0		IGC_ICR_TXQ0 /* Tx Queue 0 Interrupt */
+#define IGC_IMS_TXQ1		IGC_ICR_TXQ1 /* Tx Queue 1 Interrupt */
+#define IGC_IMS_OTHER		IGC_ICR_OTHER /* Other Interrupts */
+#define IGC_IMS_FER		IGC_ICR_FER /* Fatal Error */
+
+#define IGC_IMS_THS		IGC_ICR_THS /* ICR.TS: Thermal Sensor Event*/
+#define IGC_IMS_MDDET		IGC_ICR_MDDET /* Malicious Driver Detect */
+/* Extended Interrupt Mask Set */
+#define IGC_EIMS_RX_QUEUE0	IGC_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
+#define IGC_EIMS_RX_QUEUE1	IGC_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
+#define IGC_EIMS_RX_QUEUE2	IGC_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */
+#define IGC_EIMS_RX_QUEUE3	IGC_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */
+#define IGC_EIMS_TX_QUEUE0	IGC_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */
+#define IGC_EIMS_TX_QUEUE1	IGC_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */
+#define IGC_EIMS_TX_QUEUE2	IGC_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */
+#define IGC_EIMS_TX_QUEUE3	IGC_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */
+#define IGC_EIMS_TCP_TIMER	IGC_EICR_TCP_TIMER /* TCP Timer */
+#define IGC_EIMS_OTHER	IGC_EICR_OTHER   /* Interrupt Cause Active */
+
+/* Interrupt Cause Set */
+#define IGC_ICS_LSC		IGC_ICR_LSC       /* Link Status Change */
+#define IGC_ICS_RXSEQ		IGC_ICR_RXSEQ     /* Rx sequence error */
+#define IGC_ICS_RXDMT0	IGC_ICR_RXDMT0    /* Rx desc min. threshold */
+#define IGC_ICS_DRSTA		IGC_ICR_DRSTA     /* Device Reset Aserted */
+
+/* Extended Interrupt Cause Set */
+#define IGC_EICS_RX_QUEUE0	IGC_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
+#define IGC_EICS_RX_QUEUE1	IGC_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
+#define IGC_EICS_RX_QUEUE2	IGC_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */
+#define IGC_EICS_RX_QUEUE3	IGC_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */
+#define IGC_EICS_TX_QUEUE0	IGC_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */
+#define IGC_EICS_TX_QUEUE1	IGC_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */
+#define IGC_EICS_TX_QUEUE2	IGC_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */
+#define IGC_EICS_TX_QUEUE3	IGC_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */
+#define IGC_EICS_TCP_TIMER	IGC_EICR_TCP_TIMER /* TCP Timer */
+#define IGC_EICS_OTHER	IGC_EICR_OTHER   /* Interrupt Cause Active */
+
+#define IGC_EITR_ITR_INT_MASK	0x0000FFFF
+#define IGC_EITR_INTERVAL 0x00007FFC
+/* IGC_EITR_CNT_IGNR is only for 82576 and newer */
+#define IGC_EITR_CNT_IGNR	0x80000000 /* Don't reset counters on write */
+
+/* Transmit Descriptor Control */
+#define IGC_TXDCTL_PTHRESH	0x0000003F /* TXDCTL Prefetch Threshold */
+#define IGC_TXDCTL_HTHRESH	0x00003F00 /* TXDCTL Host Threshold */
+#define IGC_TXDCTL_WTHRESH	0x003F0000 /* TXDCTL Writeback Threshold */
+#define IGC_TXDCTL_GRAN	0x01000000 /* TXDCTL Granularity */
+#define IGC_TXDCTL_FULL_TX_DESC_WB	0x01010000 /* GRAN=1, WTHRESH=1 */
+#define IGC_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
+/* Enable the counting of descriptors still to be processed. */
+#define IGC_TXDCTL_COUNT_DESC	0x00400000
+
+/* Flow Control Constants */
+#define FLOW_CONTROL_ADDRESS_LOW	0x00C28001
+#define FLOW_CONTROL_ADDRESS_HIGH	0x00000100
+#define FLOW_CONTROL_TYPE		0x8808
+
+/* 802.1q VLAN Packet Size */
+#define VLAN_TAG_SIZE			4    /* 802.3ac tag (not DMA'd) */
+#define IGC_VLAN_FILTER_TBL_SIZE	128  /* VLAN Filter Table (4096 bits) */
+
+/* Receive Address
+ * Number of high/low register pairs in the RAR. The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor.
+ * Technically, we have 16 spots.  However, we reserve one of these spots
+ * (RAR[15]) for our directed address used by controllers with
+ * manageability enabled, allowing us room for 15 multicast addresses.
+ */
+#define IGC_RAR_ENTRIES	15
+#define IGC_RAH_AV		0x80000000 /* Receive descriptor valid */
+#define IGC_RAL_MAC_ADDR_LEN	4
+#define IGC_RAH_MAC_ADDR_LEN	2
+#define IGC_RAH_QUEUE_MASK_82575	0x000C0000
+#define IGC_RAH_POOL_1	0x00040000
+
+/* Error Codes */
+#define IGC_SUCCESS			0
+#define IGC_ERR_NVM			1
+#define IGC_ERR_PHY			2
+#define IGC_ERR_CONFIG		3
+#define IGC_ERR_PARAM			4
+#define IGC_ERR_MAC_INIT		5
+#define IGC_ERR_PHY_TYPE		6
+#define IGC_ERR_RESET			9
+#define IGC_ERR_MASTER_REQUESTS_PENDING	10
+#define IGC_ERR_HOST_INTERFACE_COMMAND	11
+#define IGC_BLK_PHY_RESET		12
+#define IGC_ERR_SWFW_SYNC		13
+#define IGC_NOT_IMPLEMENTED		14
+#define IGC_ERR_MBX			15
+#define IGC_ERR_INVALID_ARGUMENT	16
+#define IGC_ERR_NO_SPACE		17
+#define IGC_ERR_NVM_PBA_SECTION	18
+#define IGC_ERR_I2C			19
+#define IGC_ERR_INVM_VALUE_NOT_FOUND	20
+
+/* Loop limit on how long we wait for auto-negotiation to complete */
+#define FIBER_LINK_UP_LIMIT		50
+#define COPPER_LINK_UP_LIMIT		10
+#define PHY_AUTO_NEG_LIMIT		45
+#define PHY_FORCE_LIMIT			20
+/* Number of 100 microseconds we wait for PCI Express master disable */
+#define MASTER_DISABLE_TIMEOUT		800
+/* Number of milliseconds we wait for PHY configuration done after MAC reset */
+#define PHY_CFG_TIMEOUT			100
+/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */
+#define MDIO_OWNERSHIP_TIMEOUT		10
+/* Number of milliseconds for NVM auto read done after MAC reset. */
+#define AUTO_READ_DONE_TIMEOUT		10
+
+/* Flow Control */
+#define IGC_FCRTH_RTH		0x0000FFF8 /* Mask Bits[15:3] for RTH */
+#define IGC_FCRTL_RTL		0x0000FFF8 /* Mask Bits[15:3] for RTL */
+#define IGC_FCRTL_XONE	0x80000000 /* Enable XON frame transmission */
+
+/* Transmit Configuration Word */
+#define IGC_TXCW_FD		0x00000020 /* TXCW full duplex */
+#define IGC_TXCW_PAUSE	0x00000080 /* TXCW sym pause request */
+#define IGC_TXCW_ASM_DIR	0x00000100 /* TXCW astm pause direction */
+#define IGC_TXCW_PAUSE_MASK	0x00000180 /* TXCW pause request mask */
+#define IGC_TXCW_ANE		0x80000000 /* Auto-neg enable */
+
+/* Receive Configuration Word */
+#define IGC_RXCW_CW		0x0000ffff /* RxConfigWord mask */
+#define IGC_RXCW_IV		0x08000000 /* Receive config invalid */
+#define IGC_RXCW_C		0x20000000 /* Receive config */
+#define IGC_RXCW_SYNCH	0x40000000 /* Receive config synch */
+
+#define IGC_TSYNCTXCTL_VALID		0x00000001 /* Tx timestamp valid */
+#define IGC_TSYNCTXCTL_ENABLED	0x00000010 /* enable Tx timestamping */
+
+/* HH Time Sync */
+#define IGC_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK	0x0000F000 /* max delay */
+#define IGC_TSYNCTXCTL_SYNC_COMP_ERR		0x20000000 /* sync err */
+#define IGC_TSYNCTXCTL_SYNC_COMP		0x40000000 /* sync complete */
+#define IGC_TSYNCTXCTL_START_SYNC		0x80000000 /* initiate sync */
+
+#define IGC_TSYNCRXCTL_VALID		0x00000001 /* Rx timestamp valid */
+#define IGC_TSYNCRXCTL_TYPE_MASK	0x0000000E /* Rx type mask */
+#define IGC_TSYNCRXCTL_TYPE_L2_V2	0x00
+#define IGC_TSYNCRXCTL_TYPE_L4_V1	0x02
+#define IGC_TSYNCRXCTL_TYPE_L2_L4_V2	0x04
+#define IGC_TSYNCRXCTL_TYPE_ALL	0x08
+#define IGC_TSYNCRXCTL_TYPE_EVENT_V2	0x0A
+#define IGC_TSYNCRXCTL_ENABLED	0x00000010 /* enable Rx timestamping */
+#define IGC_TSYNCRXCTL_SYSCFI		0x00000020 /* Sys clock frequency */
+
+#define IGC_RXMTRL_PTP_V1_SYNC_MESSAGE	0x00000000
+#define IGC_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE	0x00010000
+
+#define IGC_RXMTRL_PTP_V2_SYNC_MESSAGE	0x00000000
+#define IGC_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE	0x01000000
+
+#define IGC_TSYNCRXCFG_PTP_V1_CTRLT_MASK		0x000000FF
+#define IGC_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE		0x00
+#define IGC_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE	0x01
+#define IGC_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE	0x02
+#define IGC_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE	0x03
+#define IGC_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE	0x04
+
+#define IGC_TSYNCRXCFG_PTP_V2_MSGID_MASK		0x00000F00
+#define IGC_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE		0x0000
+#define IGC_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE	0x0100
+#define IGC_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE	0x0200
+#define IGC_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE	0x0300
+#define IGC_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE	0x0800
+#define IGC_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE	0x0900
+#define IGC_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE 0x0A00
+#define IGC_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE	0x0B00
+#define IGC_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE	0x0C00
+#define IGC_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE	0x0D00
+
+#define IGC_TIMINCA_16NS_SHIFT	24
+#define IGC_TIMINCA_INCPERIOD_SHIFT	24
+#define IGC_TIMINCA_INCVALUE_MASK	0x00FFFFFF
+
+/* Time Sync Interrupt Cause/Mask Register Bits */
+#define TSINTR_SYS_WRAP	(1 << 0) /* SYSTIM Wrap around. */
+#define TSINTR_TXTS	(1 << 1) /* Transmit Timestamp. */
+#define TSINTR_TT0	(1 << 3) /* Target Time 0 Trigger. */
+#define TSINTR_TT1	(1 << 4) /* Target Time 1 Trigger. */
+#define TSINTR_AUTT0	(1 << 5) /* Auxiliary Timestamp 0 Taken. */
+#define TSINTR_AUTT1	(1 << 6) /* Auxiliary Timestamp 1 Taken. */
+
+#define TSYNC_INTERRUPTS	TSINTR_TXTS
+
+/* TSAUXC Configuration Bits */
+#define TSAUXC_EN_TT0	(1 << 0)  /* Enable target time 0. */
+#define TSAUXC_EN_TT1	(1 << 1)  /* Enable target time 1. */
+#define TSAUXC_EN_CLK0	(1 << 2)  /* Enable Configurable Frequency Clock 0. */
+#define TSAUXC_ST0	(1 << 4)  /* Start Clock 0 Toggle on Target Time 0. */
+#define TSAUXC_EN_CLK1	(1 << 5)  /* Enable Configurable Frequency Clock 1. */
+#define TSAUXC_ST1	(1 << 7)  /* Start Clock 1 Toggle on Target Time 1. */
+#define TSAUXC_EN_TS0	(1 << 8)  /* Enable hardware timestamp 0. */
+#define TSAUXC_EN_TS1	(1 << 10) /* Enable hardware timestamp 0. */
+
+/* SDP Configuration Bits */
+#define AUX0_SEL_SDP0	(0u << 0)  /* Assign SDP0 to auxiliary time stamp 0. */
+#define AUX0_SEL_SDP1	(1u << 0)  /* Assign SDP1 to auxiliary time stamp 0. */
+#define AUX0_SEL_SDP2	(2u << 0)  /* Assign SDP2 to auxiliary time stamp 0. */
+#define AUX0_SEL_SDP3	(3u << 0)  /* Assign SDP3 to auxiliary time stamp 0. */
+#define AUX0_TS_SDP_EN	(1u << 2)  /* Enable auxiliary time stamp trigger 0. */
+#define AUX1_SEL_SDP0	(0u << 3)  /* Assign SDP0 to auxiliary time stamp 1. */
+#define AUX1_SEL_SDP1	(1u << 3)  /* Assign SDP1 to auxiliary time stamp 1. */
+#define AUX1_SEL_SDP2	(2u << 3)  /* Assign SDP2 to auxiliary time stamp 1. */
+#define AUX1_SEL_SDP3	(3u << 3)  /* Assign SDP3 to auxiliary time stamp 1. */
+#define AUX1_TS_SDP_EN	(1u << 5)  /* Enable auxiliary time stamp trigger 1. */
+#define TS_SDP0_EN	(1u << 8)  /* SDP0 is assigned to Tsync. */
+#define TS_SDP1_EN	(1u << 11) /* SDP1 is assigned to Tsync. */
+#define TS_SDP2_EN	(1u << 14) /* SDP2 is assigned to Tsync. */
+#define TS_SDP3_EN	(1u << 17) /* SDP3 is assigned to Tsync. */
+#define TS_SDP0_SEL_TT0	(0u << 6)  /* Target time 0 is output on SDP0. */
+#define TS_SDP0_SEL_TT1	(1u << 6)  /* Target time 1 is output on SDP0. */
+#define TS_SDP1_SEL_TT0	(0u << 9)  /* Target time 0 is output on SDP1. */
+#define TS_SDP1_SEL_TT1	(1u << 9)  /* Target time 1 is output on SDP1. */
+#define TS_SDP0_SEL_FC0	(2u << 6)  /* Freq clock  0 is output on SDP0. */
+#define TS_SDP0_SEL_FC1	(3u << 6)  /* Freq clock  1 is output on SDP0. */
+#define TS_SDP1_SEL_FC0	(2u << 9)  /* Freq clock  0 is output on SDP1. */
+#define TS_SDP1_SEL_FC1	(3u << 9)  /* Freq clock  1 is output on SDP1. */
+#define TS_SDP2_SEL_TT0	(0u << 12) /* Target time 0 is output on SDP2. */
+#define TS_SDP2_SEL_TT1	(1u << 12) /* Target time 1 is output on SDP2. */
+#define TS_SDP2_SEL_FC0	(2u << 12) /* Freq clock  0 is output on SDP2. */
+#define TS_SDP2_SEL_FC1	(3u << 12) /* Freq clock  1 is output on SDP2. */
+#define TS_SDP3_SEL_TT0	(0u << 15) /* Target time 0 is output on SDP3. */
+#define TS_SDP3_SEL_TT1	(1u << 15) /* Target time 1 is output on SDP3. */
+#define TS_SDP3_SEL_FC0	(2u << 15) /* Freq clock  0 is output on SDP3. */
+#define TS_SDP3_SEL_FC1	(3u << 15) /* Freq clock  1 is output on SDP3. */
+
+#define IGC_CTRL_SDP0_DIR	0x00400000  /* SDP0 Data direction */
+#define IGC_CTRL_SDP1_DIR	0x00800000  /* SDP1 Data direction */
+
+/* Extended Device Control */
+#define IGC_CTRL_EXT_SDP2_DIR	0x00000400 /* SDP2 Data direction */
+
+/* ETQF register bit definitions */
+#define IGC_ETQF_1588			(1 << 30)
+#define IGC_FTQF_VF_BP		0x00008000
+#define IGC_FTQF_1588_TIME_STAMP	0x08000000
+#define IGC_FTQF_MASK			0xF0000000
+#define IGC_FTQF_MASK_PROTO_BP	0x10000000
+/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
+#define IGC_IMIREXT_CTRL_BP	0x00080000  /* Bypass check of ctrl bits */
+#define IGC_IMIREXT_SIZE_BP	0x00001000  /* Packet size bypass */
+
+#define IGC_RXDADV_STAT_TSIP		0x08000 /* timestamp in packet */
+#define IGC_TSICR_TXTS		0x00000002
+#define IGC_TSIM_TXTS			0x00000002
+/* TUPLE Filtering Configuration */
+#define IGC_TTQF_DISABLE_MASK		0xF0008000 /* TTQF Disable Mask */
+#define IGC_TTQF_QUEUE_ENABLE		0x100   /* TTQF Queue Enable Bit */
+#define IGC_TTQF_PROTOCOL_MASK	0xFF    /* TTQF Protocol Mask */
+/* TTQF TCP Bit, shift with IGC_TTQF_PROTOCOL SHIFT */
+#define IGC_TTQF_PROTOCOL_TCP		0x0
+/* TTQF UDP Bit, shift with IGC_TTQF_PROTOCOL_SHIFT */
+#define IGC_TTQF_PROTOCOL_UDP		0x1
+/* TTQF SCTP Bit, shift with IGC_TTQF_PROTOCOL_SHIFT */
+#define IGC_TTQF_PROTOCOL_SCTP	0x2
+#define IGC_TTQF_PROTOCOL_SHIFT	5       /* TTQF Protocol Shift */
+#define IGC_TTQF_QUEUE_SHIFT		16      /* TTQF Queue Shfit */
+#define IGC_TTQF_RX_QUEUE_MASK	0x70000 /* TTQF Queue Mask */
+#define IGC_TTQF_MASK_ENABLE		0x10000000 /* TTQF Mask Enable Bit */
+#define IGC_IMIR_CLEAR_MASK		0xF001FFFF /* IMIR Reg Clear Mask */
+#define IGC_IMIR_PORT_BYPASS		0x20000 /* IMIR Port Bypass Bit */
+#define IGC_IMIR_PRIORITY_SHIFT	29 /* IMIR Priority Shift */
+#define IGC_IMIREXT_CLEAR_MASK	0x7FFFF /* IMIREXT Reg Clear Mask */
+
+#define IGC_MDICNFG_EXT_MDIO		0x80000000 /* MDI ext/int destination */
+#define IGC_MDICNFG_COM_MDIO		0x40000000 /* MDI shared w/ lan 0 */
+#define IGC_MDICNFG_PHY_MASK		0x03E00000
+#define IGC_MDICNFG_PHY_SHIFT		21
+
+#define IGC_MEDIA_PORT_COPPER			1
+#define IGC_MEDIA_PORT_OTHER			2
+#define IGC_M88E1112_AUTO_COPPER_SGMII	0x2
+#define IGC_M88E1112_AUTO_COPPER_BASEX	0x3
+#define IGC_M88E1112_STATUS_LINK		0x0004 /* Interface Link Bit */
+#define IGC_M88E1112_MAC_CTRL_1		0x10
+#define IGC_M88E1112_MAC_CTRL_1_MODE_MASK	0x0380 /* Mode Select */
+#define IGC_M88E1112_MAC_CTRL_1_MODE_SHIFT	7
+#define IGC_M88E1112_PAGE_ADDR		0x16
+#define IGC_M88E1112_STATUS			0x01
+
+#define IGC_THSTAT_LOW_EVENT		0x20000000 /* Low thermal threshold */
+#define IGC_THSTAT_MID_EVENT		0x00200000 /* Mid thermal threshold */
+#define IGC_THSTAT_HIGH_EVENT		0x00002000 /* High thermal threshold */
+#define IGC_THSTAT_PWR_DOWN		0x00000001 /* Power Down Event */
+#define IGC_THSTAT_LINK_THROTTLE	0x00000002 /* Link Spd Throttle Event */
+
+/* EEE defines */
+#define IGC_IPCNFG_EEE_2_5G_AN	0x00000010 /* IPCNFG EEE Ena 2.5G AN */
+#define IGC_IPCNFG_EEE_1G_AN		0x00000008 /* IPCNFG EEE Ena 1G AN */
+#define IGC_IPCNFG_EEE_100M_AN	0x00000004 /* IPCNFG EEE Ena 100M AN */
+#define IGC_EEER_TX_LPI_EN		0x00010000 /* EEER Tx LPI Enable */
+#define IGC_EEER_RX_LPI_EN		0x00020000 /* EEER Rx LPI Enable */
+#define IGC_EEER_LPI_FC		0x00040000 /* EEER Ena on Flow Cntrl */
+/* EEE status */
+#define IGC_EEER_EEE_NEG		0x20000000 /* EEE capability nego */
+#define IGC_EEER_RX_LPI_STATUS	0x40000000 /* Rx in LPI state */
+#define IGC_EEER_TX_LPI_STATUS	0x80000000 /* Tx in LPI state */
+#define IGC_EEE_LP_ADV_ADDR_I350	0x040F     /* EEE LP Advertisement */
+#define IGC_M88E1543_PAGE_ADDR	0x16       /* Page Offset Register */
+#define IGC_M88E1543_EEE_CTRL_1	0x0
+#define IGC_M88E1543_EEE_CTRL_1_MS	0x0001     /* EEE Master/Slave */
+#define IGC_M88E1543_FIBER_CTRL	0x0        /* Fiber Control Register */
+#define IGC_EEE_ADV_DEV_I354		7
+#define IGC_EEE_ADV_ADDR_I354		60
+#define IGC_EEE_ADV_100_SUPPORTED	(1 << 1)   /* 100BaseTx EEE Supported */
+#define IGC_EEE_ADV_1000_SUPPORTED	(1 << 2)   /* 1000BaseT EEE Supported */
+#define IGC_PCS_STATUS_DEV_I354	3
+#define IGC_PCS_STATUS_ADDR_I354	1
+#define IGC_PCS_STATUS_RX_LPI_RCVD	0x0400
+#define IGC_PCS_STATUS_TX_LPI_RCVD	0x0800
+#define IGC_M88E1512_CFG_REG_1	0x0010
+#define IGC_M88E1512_CFG_REG_2	0x0011
+#define IGC_M88E1512_CFG_REG_3	0x0007
+#define IGC_M88E1512_MODE		0x0014
+#define IGC_EEE_SU_LPI_CLK_STP	0x00800000 /* EEE LPI Clock Stop */
+#define IGC_EEE_LP_ADV_DEV_I210	7          /* EEE LP Adv Device */
+#define IGC_EEE_LP_ADV_ADDR_I210	61         /* EEE LP Adv Register */
+#define IGC_EEE_SU_LPI_CLK_STP	0x00800000 /* EEE LPI Clock Stop */
+#define IGC_EEE_LP_ADV_DEV_I225	7          /* EEE LP Adv Device */
+#define IGC_EEE_LP_ADV_ADDR_I225	61         /* EEE LP Adv Register */
+
+/* PCI Express Control */
+#define IGC_GCR_RXD_NO_SNOOP		0x00000001
+#define IGC_GCR_RXDSCW_NO_SNOOP	0x00000002
+#define IGC_GCR_RXDSCR_NO_SNOOP	0x00000004
+#define IGC_GCR_TXD_NO_SNOOP		0x00000008
+#define IGC_GCR_TXDSCW_NO_SNOOP	0x00000010
+#define IGC_GCR_TXDSCR_NO_SNOOP	0x00000020
+#define IGC_GCR_CMPL_TMOUT_MASK	0x0000F000
+#define IGC_GCR_CMPL_TMOUT_10ms	0x00001000
+#define IGC_GCR_CMPL_TMOUT_RESEND	0x00010000
+#define IGC_GCR_CAP_VER2		0x00040000
+
+#define PCIE_NO_SNOOP_ALL	(IGC_GCR_RXD_NO_SNOOP | \
+				 IGC_GCR_RXDSCW_NO_SNOOP | \
+				 IGC_GCR_RXDSCR_NO_SNOOP | \
+				 IGC_GCR_TXD_NO_SNOOP    | \
+				 IGC_GCR_TXDSCW_NO_SNOOP | \
+				 IGC_GCR_TXDSCR_NO_SNOOP)
+
+#define IGC_MMDAC_FUNC_DATA	0x4000 /* Data, no post increment */
+
+/* mPHY address control and data registers */
+#define IGC_MPHY_ADDR_CTL		0x0024 /* Address Control Reg */
+#define IGC_MPHY_ADDR_CTL_OFFSET_MASK	0xFFFF0000
+#define IGC_MPHY_DATA			0x0E10 /* Data Register */
+
+/* AFE CSR Offset for PCS CLK */
+#define IGC_MPHY_PCS_CLK_REG_OFFSET	0x0004
+/* Override for near end digital loopback. */
+#define IGC_MPHY_PCS_CLK_REG_DIGINELBEN	0x10
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB	0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE	0x0080  /* Collision test enable */
+#define MII_CR_FULL_DUPLEX	0x0100  /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG	0x0200  /* Restart auto negotiation */
+#define MII_CR_ISOLATE		0x0400  /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN	0x0800  /* Power down */
+#define MII_CR_AUTO_NEG_EN	0x1000  /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB	0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK		0x4000  /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET		0x8000  /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_1000	0x0040
+#define MII_CR_SPEED_100	0x2000
+#define MII_CR_SPEED_10		0x0000
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS	0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT	0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS	0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS	0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT	0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE	0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS	0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS	0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS	0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS	0x0800 /* 10T   Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS	0x1000 /* 10T   Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS	0x2000 /* 100X  Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS	0x4000 /* 100X  Full Duplex Capable */
+#define MII_SR_100T4_CAPS	0x8000 /* 100T4 Capable */
+
+/* Autoneg Advertisement Register */
+#define NWAY_AR_SELECTOR_FIELD	0x0001   /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS	0x0020   /* 10T   Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS	0x0040   /* 10T   Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS	0x0080   /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS	0x0100   /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS	0x0200   /* 100T4 Capable */
+#define NWAY_AR_PAUSE		0x0400   /* Pause operation desired */
+#define NWAY_AR_ASM_DIR		0x0800   /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT	0x2000   /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE	0x8000   /* Next Page ability supported */
+
+/* Link Partner Ability Register (Base Page) */
+#define NWAY_LPAR_SELECTOR_FIELD	0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS		0x0020 /* LP 10T Half Dplx Capable */
+#define NWAY_LPAR_10T_FD_CAPS		0x0040 /* LP 10T Full Dplx Capable */
+#define NWAY_LPAR_100TX_HD_CAPS		0x0080 /* LP 100TX Half Dplx Capable */
+#define NWAY_LPAR_100TX_FD_CAPS		0x0100 /* LP 100TX Full Dplx Capable */
+#define NWAY_LPAR_100T4_CAPS		0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE			0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR		0x0800 /* LP Asym Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT		0x2000 /* LP detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE		0x4000 /* LP rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE		0x8000 /* Next Page ability supported */
+
+/* Autoneg Expansion Register */
+#define NWAY_ER_LP_NWAY_CAPS		0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD		0x0002 /* LP 10T Half Dplx Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS		0x0004 /* LP 10T Full Dplx Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS	0x0008 /* LP 100TX Half Dplx Capable */
+#define NWAY_ER_PAR_DETECT_FAULT	0x0010 /* LP 100TX Full Dplx Capable */
+
+/* 1000BASE-T Control Register */
+#define CR_1000T_ASYM_PAUSE	0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS	0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS	0x0200 /* Advertise 1000T FD capability  */
+/* 1=Repeater/switch device port 0=DTE device */
+#define CR_1000T_REPEATER_DTE	0x0400
+/* 1=Configure PHY as Master 0=Configure PHY as Slave */
+#define CR_1000T_MS_VALUE	0x0800
+/* 1=Master/Slave manual config value 0=Automatic Master/Slave config */
+#define CR_1000T_MS_ENABLE	0x1000
+#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define CR_1000T_TEST_MODE_1	0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2	0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3	0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4	0x8000 /* Transmitter Distortion test */
+
+/* 1000BASE-T Status Register */
+#define SR_1000T_IDLE_ERROR_CNT		0x00FF /* Num idle err since last rd */
+#define SR_1000T_ASYM_PAUSE_DIR		0x0100 /* LP asym pause direction bit */
+#define SR_1000T_LP_HD_CAPS		0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS		0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS	0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS	0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES		0x4000 /* 1=Local Tx Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT	0x8000 /* Master/Slave config fault */
+
+#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT	5
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+#define PHY_CONTROL		0x00 /* Control Register */
+#define PHY_STATUS		0x01 /* Status Register */
+#define PHY_ID1			0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2			0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV		0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY		0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP		0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX	0x07 /* Next Page Tx */
+#define PHY_LP_NEXT_PAGE	0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL		0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS	0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS		0x0F /* Extended Status Reg */
+
+/* PHY GPY 211 registers */
+#define STANDARD_AN_REG_MASK	0x0007 /* MMD */
+#define ANEG_MULTIGBT_AN_CTRL	0x0020 /* MULTI GBT AN Control Register */
+#define MMD_DEVADDR_SHIFT	16     /* Shift MMD to higher bits */
+#define CR_2500T_FD_CAPS	0x0080 /* Advertise 2500T FD capability */
+
+#define PHY_CONTROL_LB		0x4000 /* PHY Loopback bit */
+
+/* NVM Control */
+#define IGC_EECD_SK		0x00000001 /* NVM Clock */
+#define IGC_EECD_CS		0x00000002 /* NVM Chip Select */
+#define IGC_EECD_DI		0x00000004 /* NVM Data In */
+#define IGC_EECD_DO		0x00000008 /* NVM Data Out */
+#define IGC_EECD_REQ		0x00000040 /* NVM Access Request */
+#define IGC_EECD_GNT		0x00000080 /* NVM Access Grant */
+#define IGC_EECD_PRES		0x00000100 /* NVM Present */
+#define IGC_EECD_SIZE		0x00000200 /* NVM Size (0=64 word 1=256 word) */
+#define IGC_EECD_BLOCKED	0x00008000 /* Bit banging access blocked flag */
+#define IGC_EECD_ABORT	0x00010000 /* NVM operation aborted flag */
+#define IGC_EECD_TIMEOUT	0x00020000 /* NVM read operation timeout flag */
+#define IGC_EECD_ERROR_CLR	0x00040000 /* NVM error status clear bit */
+/* NVM Addressing bits based on type 0=small, 1=large */
+#define IGC_EECD_ADDR_BITS	0x00000400
+#define IGC_EECD_TYPE		0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
+#define IGC_NVM_GRANT_ATTEMPTS	1000 /* NVM # attempts to gain grant */
+#define IGC_EECD_AUTO_RD		0x00000200  /* NVM Auto Read done */
+#define IGC_EECD_SIZE_EX_MASK		0x00007800  /* NVM Size */
+#define IGC_EECD_SIZE_EX_SHIFT	11
+#define IGC_EECD_FLUPD		0x00080000 /* Update FLASH */
+#define IGC_EECD_AUPDEN		0x00100000 /* Ena Auto FLASH update */
+#define IGC_EECD_SEC1VAL		0x00400000 /* Sector One Valid */
+#define IGC_EECD_SEC1VAL_VALID_MASK	(IGC_EECD_AUTO_RD | IGC_EECD_PRES)
+#define IGC_EECD_FLUPD_I210		0x00800000 /* Update FLASH */
+#define IGC_EECD_FLUDONE_I210		0x04000000 /* Update FLASH done */
+#define IGC_EECD_FLASH_DETECTED_I210	0x00080000 /* FLASH detected */
+#define IGC_EECD_SEC1VAL_I210		0x02000000 /* Sector One Valid */
+#define IGC_FLUDONE_ATTEMPTS		20000
+#define IGC_EERD_EEWR_MAX_COUNT	512 /* buffered EEPROM words rw */
+#define IGC_I210_FIFO_SEL_RX		0x00
+#define IGC_I210_FIFO_SEL_TX_QAV(_i)	(0x02 + (_i))
+#define IGC_I210_FIFO_SEL_TX_LEGACY	IGC_I210_FIFO_SEL_TX_QAV(0)
+#define IGC_I210_FIFO_SEL_BMC2OS_TX	0x06
+#define IGC_I210_FIFO_SEL_BMC2OS_RX	0x01
+
+#define IGC_I210_FLASH_SECTOR_SIZE	0x1000 /* 4KB FLASH sector unit size */
+/* Secure FLASH mode requires removing MSb */
+#define IGC_I210_FW_PTR_MASK		0x7FFF
+/* Firmware code revision field word offset*/
+#define IGC_I210_FW_VER_OFFSET	328
+
+#define IGC_EECD_FLUPD_I225		0x00800000 /* Update FLASH */
+#define IGC_EECD_FLUDONE_I225		0x04000000 /* Update FLASH done */
+#define IGC_EECD_FLASH_DETECTED_I225	0x00080000 /* FLASH detected */
+#define IGC_FLUDONE_ATTEMPTS		20000
+#define IGC_EERD_EEWR_MAX_COUNT	512 /* buffered EEPROM words rw */
+#define IGC_EECD_SEC1VAL_I225		0x02000000 /* Sector One Valid */
+#define IGC_FLSECU_BLK_SW_ACCESS_I225	0x00000004 /* Block SW access */
+#define IGC_FWSM_FW_VALID_I225	0x8000 /* FW valid bit */
+
+#define IGC_NVM_RW_REG_DATA	16  /* Offset to data in NVM read/write regs */
+#define IGC_NVM_RW_REG_DONE	2   /* Offset to READ/WRITE done bit */
+#define IGC_NVM_RW_REG_START	1   /* Start operation */
+#define IGC_NVM_RW_ADDR_SHIFT	2   /* Shift to the address bits */
+#define IGC_NVM_POLL_WRITE	1   /* Flag for polling for write complete */
+#define IGC_NVM_POLL_READ	0   /* Flag for polling for read complete */
+#define IGC_FLASH_UPDATES	2000
+
+/* NVM Word Offsets */
+#define NVM_COMPAT			0x0003
+#define NVM_ID_LED_SETTINGS		0x0004
+#define NVM_VERSION			0x0005
+#define NVM_SERDES_AMPLITUDE		0x0006 /* SERDES output amplitude */
+#define NVM_PHY_CLASS_WORD		0x0007
+#define IGC_I210_NVM_FW_MODULE_PTR	0x0010
+#define IGC_I350_NVM_FW_MODULE_PTR	0x0051
+#define NVM_FUTURE_INIT_WORD1		0x0019
+#define NVM_ETRACK_WORD			0x0042
+#define NVM_ETRACK_HIWORD		0x0043
+#define NVM_COMB_VER_OFF		0x0083
+#define NVM_COMB_VER_PTR		0x003d
+
+/* NVM version defines */
+#define NVM_MAJOR_MASK			0xF000
+#define NVM_MINOR_MASK			0x0FF0
+#define NVM_IMAGE_ID_MASK		0x000F
+#define NVM_COMB_VER_MASK		0x00FF
+#define NVM_MAJOR_SHIFT			12
+#define NVM_MINOR_SHIFT			4
+#define NVM_COMB_VER_SHFT		8
+#define NVM_VER_INVALID			0xFFFF
+#define NVM_ETRACK_SHIFT		16
+#define NVM_ETRACK_VALID		0x8000
+#define NVM_NEW_DEC_MASK		0x0F00
+#define NVM_HEX_CONV			16
+#define NVM_HEX_TENS			10
+
+/* FW version defines */
+/* Offset of "Loader patch ptr" in Firmware Header */
+#define IGC_I350_NVM_FW_LOADER_PATCH_PTR_OFFSET	0x01
+/* Patch generation hour & minutes */
+#define IGC_I350_NVM_FW_VER_WORD1_OFFSET		0x04
+/* Patch generation month & day */
+#define IGC_I350_NVM_FW_VER_WORD2_OFFSET		0x05
+/* Patch generation year */
+#define IGC_I350_NVM_FW_VER_WORD3_OFFSET		0x06
+/* Patch major & minor numbers */
+#define IGC_I350_NVM_FW_VER_WORD4_OFFSET		0x07
+
+#define NVM_MAC_ADDR			0x0000
+#define NVM_SUB_DEV_ID			0x000B
+#define NVM_SUB_VEN_ID			0x000C
+#define NVM_DEV_ID			0x000D
+#define NVM_VEN_ID			0x000E
+#define NVM_INIT_CTRL_2			0x000F
+#define NVM_INIT_CTRL_4			0x0013
+#define NVM_LED_1_CFG			0x001C
+#define NVM_LED_0_2_CFG			0x001F
+
+#define NVM_COMPAT_VALID_CSUM		0x0001
+#define NVM_FUTURE_INIT_WORD1_VALID_CSUM	0x0040
+
+#define NVM_INIT_CONTROL2_REG		0x000F
+#define NVM_INIT_CONTROL3_PORT_B	0x0014
+#define NVM_INIT_3GIO_3			0x001A
+#define NVM_SWDEF_PINS_CTRL_PORT_0	0x0020
+#define NVM_INIT_CONTROL3_PORT_A	0x0024
+#define NVM_CFG				0x0012
+#define NVM_ALT_MAC_ADDR_PTR		0x0037
+#define NVM_CHECKSUM_REG		0x003F
+#define NVM_COMPATIBILITY_REG_3		0x0003
+#define NVM_COMPATIBILITY_BIT_MASK	0x8000
+
+#define IGC_NVM_CFG_DONE_PORT_0	0x040000 /* MNG config cycle done */
+#define IGC_NVM_CFG_DONE_PORT_1	0x080000 /* ...for second port */
+#define IGC_NVM_CFG_DONE_PORT_2	0x100000 /* ...for third port */
+#define IGC_NVM_CFG_DONE_PORT_3	0x200000 /* ...for fourth port */
+
+#define NVM_82580_LAN_FUNC_OFFSET(a)	((a) ? (0x40 + (0x40 * (a))) : 0)
+
+/* Mask bits for fields in Word 0x24 of the NVM */
+#define NVM_WORD24_COM_MDIO		0x0008 /* MDIO interface shared */
+#define NVM_WORD24_EXT_MDIO		0x0004 /* MDIO accesses routed extrnl */
+/* Offset of Link Mode bits for 82575/82576 */
+#define NVM_WORD24_LNK_MODE_OFFSET	8
+/* Offset of Link Mode bits for 82580 up */
+#define NVM_WORD24_82580_LNK_MODE_OFFSET	4
+
+
+/* Mask bits for fields in Word 0x0f of the NVM */
+#define NVM_WORD0F_PAUSE_MASK		0x3000
+#define NVM_WORD0F_PAUSE		0x1000
+#define NVM_WORD0F_ASM_DIR		0x2000
+#define NVM_WORD0F_SWPDIO_EXT_MASK	0x00F0
+
+/* Mask bits for fields in Word 0x1a of the NVM */
+#define NVM_WORD1A_ASPM_MASK		0x000C
+
+/* Mask bits for fields in Word 0x03 of the EEPROM */
+#define NVM_COMPAT_LOM			0x0800
+
+/* length of string needed to store PBA number */
+#define IGC_PBANUM_LENGTH		11
+
+/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
+#define NVM_SUM				0xBABA
+
+/* PBA (printed board assembly) number words */
+#define NVM_PBA_OFFSET_0		8
+#define NVM_PBA_OFFSET_1		9
+#define NVM_PBA_PTR_GUARD		0xFAFA
+#define NVM_RESERVED_WORD		0xFFFF
+#define NVM_PHY_CLASS_A			0x8000
+#define NVM_SERDES_AMPLITUDE_MASK	0x000F
+#define NVM_SIZE_MASK			0x1C00
+#define NVM_SIZE_SHIFT			10
+#define NVM_WORD_SIZE_BASE_SHIFT	6
+#define NVM_SWDPIO_EXT_SHIFT		4
+
+/* NVM Commands - Microwire */
+#define NVM_READ_OPCODE_MICROWIRE	0x6  /* NVM read opcode */
+#define NVM_WRITE_OPCODE_MICROWIRE	0x5  /* NVM write opcode */
+#define NVM_ERASE_OPCODE_MICROWIRE	0x7  /* NVM erase opcode */
+#define NVM_EWEN_OPCODE_MICROWIRE	0x13 /* NVM erase/write enable */
+#define NVM_EWDS_OPCODE_MICROWIRE	0x10 /* NVM erase/write disable */
+
+/* NVM Commands - SPI */
+#define NVM_MAX_RETRY_SPI	5000 /* Max wait of 5ms, for RDY signal */
+#define NVM_READ_OPCODE_SPI	0x03 /* NVM read opcode */
+#define NVM_WRITE_OPCODE_SPI	0x02 /* NVM write opcode */
+#define NVM_A8_OPCODE_SPI	0x08 /* opcode bit-3 = address bit-8 */
+#define NVM_WREN_OPCODE_SPI	0x06 /* NVM set Write Enable latch */
+#define NVM_RDSR_OPCODE_SPI	0x05 /* NVM read Status register */
+
+/* SPI NVM Status Register */
+#define NVM_STATUS_RDY_SPI	0x01
+
+/* Word definitions for ID LED Settings */
+#define ID_LED_RESERVED_0000	0x0000
+#define ID_LED_RESERVED_FFFF	0xFFFF
+#define ID_LED_DEFAULT		((ID_LED_OFF1_ON2  << 12) | \
+				 (ID_LED_OFF1_OFF2 <<  8) | \
+				 (ID_LED_DEF1_DEF2 <<  4) | \
+				 (ID_LED_DEF1_DEF2))
+#define ID_LED_DEF1_DEF2	0x1
+#define ID_LED_DEF1_ON2		0x2
+#define ID_LED_DEF1_OFF2	0x3
+#define ID_LED_ON1_DEF2		0x4
+#define ID_LED_ON1_ON2		0x5
+#define ID_LED_ON1_OFF2		0x6
+#define ID_LED_OFF1_DEF2	0x7
+#define ID_LED_OFF1_ON2		0x8
+#define ID_LED_OFF1_OFF2	0x9
+
+#define IGP_ACTIVITY_LED_MASK	0xFFFFF0FF
+#define IGP_ACTIVITY_LED_ENABLE	0x0300
+#define IGP_LED3_MODE		0x07000000
+
+/* PCI/PCI-X/PCI-EX Config space */
+#define PCIX_COMMAND_REGISTER		0xE6
+#define PCIX_STATUS_REGISTER_LO		0xE8
+#define PCIX_STATUS_REGISTER_HI		0xEA
+#define PCI_HEADER_TYPE_REGISTER	0x0E
+#define PCIE_LINK_STATUS		0x12
+#define PCIE_DEVICE_CONTROL2		0x28
+
+#define PCIX_COMMAND_MMRBC_MASK		0x000C
+#define PCIX_COMMAND_MMRBC_SHIFT	0x2
+#define PCIX_STATUS_HI_MMRBC_MASK	0x0060
+#define PCIX_STATUS_HI_MMRBC_SHIFT	0x5
+#define PCIX_STATUS_HI_MMRBC_4K		0x3
+#define PCIX_STATUS_HI_MMRBC_2K		0x2
+#define PCIX_STATUS_LO_FUNC_MASK	0x7
+#define PCI_HEADER_TYPE_MULTIFUNC	0x80
+#define PCIE_LINK_WIDTH_MASK		0x3F0
+#define PCIE_LINK_WIDTH_SHIFT		4
+#define PCIE_LINK_SPEED_MASK		0x0F
+#define PCIE_LINK_SPEED_2500		0x01
+#define PCIE_LINK_SPEED_5000		0x02
+#define PCIE_DEVICE_CONTROL2_16ms	0x0005
+
+#define ETH_ADDR_LEN			6
+
+#define PHY_REVISION_MASK		0xFFFFFFF0
+#define MAX_PHY_REG_ADDRESS		0x1F  /* 5 bit address bus (0-0x1F) */
+#define MAX_PHY_MULTI_PAGE_REG		0xF
+
+/* Bit definitions for valid PHY IDs.
+ * I = Integrated
+ * E = External
+ */
+#define M88IGC_E_PHY_ID	0x01410C50
+#define M88IGC_I_PHY_ID	0x01410C30
+#define M88E1011_I_PHY_ID	0x01410C20
+#define IGP01IGC_I_PHY_ID	0x02A80380
+#define M88E1111_I_PHY_ID	0x01410CC0
+#define M88E1543_E_PHY_ID	0x01410EA0
+#define M88E1512_E_PHY_ID	0x01410DD0
+#define M88E1112_E_PHY_ID	0x01410C90
+#define I347AT4_E_PHY_ID	0x01410DC0
+#define M88E1340M_E_PHY_ID	0x01410DF0
+#define GG82563_E_PHY_ID	0x01410CA0
+#define IGP03IGC_E_PHY_ID	0x02A80390
+#define IFE_E_PHY_ID		0x02A80330
+#define IFE_PLUS_E_PHY_ID	0x02A80320
+#define IFE_C_E_PHY_ID		0x02A80310
+#define BMIGC_E_PHY_ID	0x01410CB0
+#define BMIGC_E_PHY_ID_R2	0x01410CB1
+#define I82577_E_PHY_ID		0x01540050
+#define I82578_E_PHY_ID		0x004DD040
+#define I82579_E_PHY_ID		0x01540090
+#define I217_E_PHY_ID		0x015400A0
+#define I82580_I_PHY_ID		0x015403A0
+#define I350_I_PHY_ID		0x015403B0
+#define I210_I_PHY_ID		0x01410C00
+#define IGP04IGC_E_PHY_ID	0x02A80391
+#define M88_VENDOR		0x0141
+#define I225_I_PHY_ID		0x67C9DC00
+
+/* M88E1000 Specific Registers */
+#define M88IGC_PHY_SPEC_CTRL		0x10  /* PHY Specific Control Reg */
+#define M88IGC_PHY_SPEC_STATUS	0x11  /* PHY Specific Status Reg */
+#define M88IGC_EXT_PHY_SPEC_CTRL	0x14  /* Extended PHY Specific Cntrl */
+#define M88IGC_RX_ERR_CNTR		0x15  /* Receive Error Counter */
+
+#define M88IGC_PHY_EXT_CTRL		0x1A  /* PHY extend control register */
+#define M88IGC_PHY_PAGE_SELECT	0x1D  /* Reg 29 for pg number setting */
+#define M88IGC_PHY_GEN_CONTROL	0x1E  /* meaning depends on reg 29 */
+#define M88IGC_PHY_VCO_REG_BIT8	0x100 /* Bits 8 & 11 are adjusted for */
+#define M88IGC_PHY_VCO_REG_BIT11	0x800 /* improved BER performance */
+
+/* M88E1000 PHY Specific Control Register */
+#define M88IGC_PSCR_POLARITY_REVERSAL	0x0002 /* 1=Polarity Reverse enabled */
+/* MDI Crossover Mode bits 6:5 Manual MDI configuration */
+#define M88IGC_PSCR_MDI_MANUAL_MODE	0x0000
+#define M88IGC_PSCR_MDIX_MANUAL_MODE	0x0020  /* Manual MDIX configuration */
+/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
+#define M88IGC_PSCR_AUTO_X_1000T	0x0040
+/* Auto crossover enabled all speeds */
+#define M88IGC_PSCR_AUTO_X_MODE	0x0060
+#define M88IGC_PSCR_ASSERT_CRS_ON_TX	0x0800 /* 1=Assert CRS on Tx */
+
+/* M88E1000 PHY Specific Status Register */
+#define M88IGC_PSSR_REV_POLARITY	0x0002 /* 1=Polarity reversed */
+#define M88IGC_PSSR_DOWNSHIFT		0x0020 /* 1=Downshifted */
+#define M88IGC_PSSR_MDIX		0x0040 /* 1=MDIX; 0=MDI */
+/* 0 = <50M
+ * 1 = 50-80M
+ * 2 = 80-110M
+ * 3 = 110-140M
+ * 4 = >140M
+ */
+#define M88IGC_PSSR_CABLE_LENGTH	0x0380
+#define M88IGC_PSSR_LINK		0x0400 /* 1=Link up, 0=Link down */
+#define M88IGC_PSSR_SPD_DPLX_RESOLVED	0x0800 /* 1=Speed & Duplex resolved */
+#define M88IGC_PSSR_DPLX		0x2000 /* 1=Duplex 0=Half Duplex */
+#define M88IGC_PSSR_SPEED		0xC000 /* Speed, bits 14:15 */
+#define M88IGC_PSSR_100MBS		0x4000 /* 01=100Mbs */
+#define M88IGC_PSSR_1000MBS		0x8000 /* 10=1000Mbs */
+
+#define M88IGC_PSSR_CABLE_LENGTH_SHIFT	7
+
+/* Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
+#define M88IGC_EPSCR_MASTER_DOWNSHIFT_MASK	0x0C00
+#define M88IGC_EPSCR_MASTER_DOWNSHIFT_1X	0x0000
+/* Number of times we will attempt to autonegotiate before downshifting if we
+ * are the slave
+ */
+#define M88IGC_EPSCR_SLAVE_DOWNSHIFT_MASK	0x0300
+#define M88IGC_EPSCR_SLAVE_DOWNSHIFT_1X	0x0100
+#define M88IGC_EPSCR_TX_CLK_25	0x0070 /* 25  MHz TX_CLK */
+
+/* Intel I347AT4 Registers */
+#define I347AT4_PCDL		0x10 /* PHY Cable Diagnostics Length */
+#define I347AT4_PCDC		0x15 /* PHY Cable Diagnostics Control */
+#define I347AT4_PAGE_SELECT	0x16
+
+/* I347AT4 Extended PHY Specific Control Register */
+
+/* Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
+#define I347AT4_PSCR_DOWNSHIFT_ENABLE	0x0800
+#define I347AT4_PSCR_DOWNSHIFT_MASK	0x7000
+#define I347AT4_PSCR_DOWNSHIFT_1X	0x0000
+#define I347AT4_PSCR_DOWNSHIFT_2X	0x1000
+#define I347AT4_PSCR_DOWNSHIFT_3X	0x2000
+#define I347AT4_PSCR_DOWNSHIFT_4X	0x3000
+#define I347AT4_PSCR_DOWNSHIFT_5X	0x4000
+#define I347AT4_PSCR_DOWNSHIFT_6X	0x5000
+#define I347AT4_PSCR_DOWNSHIFT_7X	0x6000
+#define I347AT4_PSCR_DOWNSHIFT_8X	0x7000
+
+/* I347AT4 PHY Cable Diagnostics Control */
+#define I347AT4_PCDC_CABLE_LENGTH_UNIT	0x0400 /* 0=cm 1=meters */
+
+/* M88E1112 only registers */
+#define M88E1112_VCT_DSP_DISTANCE	0x001A
+
+/* M88EC018 Rev 2 specific DownShift settings */
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK	0x0E00
+#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X	0x0800
+
+#define I82578_EPSCR_DOWNSHIFT_ENABLE		0x0020
+#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK	0x001C
+
+/* BME1000 PHY Specific Control Register */
+#define BMIGC_PSCR_ENABLE_DOWNSHIFT	0x0800 /* 1 = enable downshift */
+
+/* Bits...
+ * 15-5: page
+ * 4-0: register offset
+ */
+#define GG82563_PAGE_SHIFT	5
+#define GG82563_REG(page, reg)	\
+	(((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+#define GG82563_MIN_ALT_REG	30
+
+/* GG82563 Specific Registers */
+#define GG82563_PHY_SPEC_CTRL		GG82563_REG(0, 16) /* PHY Spec Cntrl */
+#define GG82563_PHY_PAGE_SELECT		GG82563_REG(0, 22) /* Page Select */
+#define GG82563_PHY_SPEC_CTRL_2		GG82563_REG(0, 26) /* PHY Spec Cntrl2 */
+#define GG82563_PHY_PAGE_SELECT_ALT	GG82563_REG(0, 29) /* Alt Page Select */
+
+/* MAC Specific Control Register */
+#define GG82563_PHY_MAC_SPEC_CTRL	GG82563_REG(2, 21)
+
+#define GG82563_PHY_DSP_DISTANCE	GG82563_REG(5, 26) /* DSP Distance */
+
+/* Page 193 - Port Control Registers */
+/* Kumeran Mode Control */
+#define GG82563_PHY_KMRN_MODE_CTRL	GG82563_REG(193, 16)
+#define GG82563_PHY_PWR_MGMT_CTRL	GG82563_REG(193, 20) /* Pwr Mgt Ctrl */
+
+/* Page 194 - KMRN Registers */
+#define GG82563_PHY_INBAND_CTRL		GG82563_REG(194, 18) /* Inband Ctrl */
+
+/* MDI Control */
+#define IGC_MDIC_DATA_MASK	0x0000FFFF
+#define IGC_MDIC_INT_EN		0x20000000
+#define IGC_MDIC_REG_MASK	0x001F0000
+#define IGC_MDIC_REG_SHIFT	16
+#define IGC_MDIC_PHY_MASK	0x03E00000
+#define IGC_MDIC_PHY_SHIFT	21
+#define IGC_MDIC_OP_WRITE	0x04000000
+#define IGC_MDIC_OP_READ	0x08000000
+#define IGC_MDIC_READY	0x10000000
+#define IGC_MDIC_ERROR	0x40000000
+#define IGC_MDIC_DEST		0x80000000
+
+#define IGC_N0_QUEUE -1
+
+#define IGC_MAX_MAC_HDR_LEN	127
+#define IGC_MAX_NETWORK_HDR_LEN	511
+
+#define IGC_VLAPQF_QUEUE_SEL(_n, q_idx) ((q_idx) << ((_n) * 4))
+#define IGC_VLAPQF_P_VALID(_n)	(0x1 << (3 + (_n) * 4))
+#define IGC_VLAPQF_QUEUE_MASK	0x03
+#define IGC_VFTA_BLOCK_SIZE	8
+/* SerDes Control */
+#define IGC_GEN_CTL_READY		0x80000000
+#define IGC_GEN_CTL_ADDRESS_SHIFT	8
+#define IGC_GEN_POLL_TIMEOUT		640
+
+/* LinkSec register fields */
+#define IGC_LSECTXCAP_SUM_MASK	0x00FF0000
+#define IGC_LSECTXCAP_SUM_SHIFT	16
+#define IGC_LSECRXCAP_SUM_MASK	0x00FF0000
+#define IGC_LSECRXCAP_SUM_SHIFT	16
+
+#define IGC_LSECTXCTRL_EN_MASK	0x00000003
+#define IGC_LSECTXCTRL_DISABLE	0x0
+#define IGC_LSECTXCTRL_AUTH		0x1
+#define IGC_LSECTXCTRL_AUTH_ENCRYPT	0x2
+#define IGC_LSECTXCTRL_AISCI		0x00000020
+#define IGC_LSECTXCTRL_PNTHRSH_MASK	0xFFFFFF00
+#define IGC_LSECTXCTRL_RSV_MASK	0x000000D8
+
+#define IGC_LSECRXCTRL_EN_MASK	0x0000000C
+#define IGC_LSECRXCTRL_EN_SHIFT	2
+#define IGC_LSECRXCTRL_DISABLE	0x0
+#define IGC_LSECRXCTRL_CHECK		0x1
+#define IGC_LSECRXCTRL_STRICT		0x2
+#define IGC_LSECRXCTRL_DROP		0x3
+#define IGC_LSECRXCTRL_PLSH		0x00000040
+#define IGC_LSECRXCTRL_RP		0x00000080
+#define IGC_LSECRXCTRL_RSV_MASK	0xFFFFFF33
+
+/* Tx Rate-Scheduler Config fields */
+#define IGC_RTTBCNRC_RS_ENA		0x80000000
+#define IGC_RTTBCNRC_RF_DEC_MASK	0x00003FFF
+#define IGC_RTTBCNRC_RF_INT_SHIFT	14
+#define IGC_RTTBCNRC_RF_INT_MASK	\
+	(IGC_RTTBCNRC_RF_DEC_MASK << IGC_RTTBCNRC_RF_INT_SHIFT)
+
+/* DMA Coalescing register fields */
+/* DMA Coalescing Watchdog Timer */
+#define IGC_DMACR_DMACWT_MASK		0x00003FFF
+/* DMA Coalescing Rx Threshold */
+#define IGC_DMACR_DMACTHR_MASK	0x00FF0000
+#define IGC_DMACR_DMACTHR_SHIFT	16
+/* Lx when no PCIe transactions */
+#define IGC_DMACR_DMAC_LX_MASK	0x30000000
+#define IGC_DMACR_DMAC_LX_SHIFT	28
+#define IGC_DMACR_DMAC_EN		0x80000000 /* Enable DMA Coalescing */
+/* DMA Coalescing BMC-to-OS Watchdog Enable */
+#define IGC_DMACR_DC_BMC2OSW_EN	0x00008000
+
+/* DMA Coalescing Transmit Threshold */
+#define IGC_DMCTXTH_DMCTTHR_MASK	0x00000FFF
+
+#define IGC_DMCTLX_TTLX_MASK		0x00000FFF /* Time to LX request */
+
+/* Rx Traffic Rate Threshold */
+#define IGC_DMCRTRH_UTRESH_MASK	0x0007FFFF
+/* Rx packet rate in current window */
+#define IGC_DMCRTRH_LRPRCW		0x80000000
+
+/* DMA Coal Rx Traffic Current Count */
+#define IGC_DMCCNT_CCOUNT_MASK	0x01FFFFFF
+
+/* Flow ctrl Rx Threshold High val */
+#define IGC_FCRTC_RTH_COAL_MASK	0x0003FFF0
+#define IGC_FCRTC_RTH_COAL_SHIFT	4
+/* Lx power decision based on DMA coal */
+#define IGC_PCIEMISC_LX_DECISION	0x00000080
+
+#define IGC_RXPBS_CFG_TS_EN		0x80000000 /* Timestamp in Rx buffer */
+#define IGC_RXPBS_SIZE_I210_MASK	0x0000003F /* Rx packet buffer size */
+#define IGC_TXPB0S_SIZE_I210_MASK	0x0000003F /* Tx packet buffer 0 size */
+#define I210_RXPBSIZE_DEFAULT		0x000000A2 /* RXPBSIZE default */
+#define I210_TXPBSIZE_DEFAULT		0x04000014 /* TXPBSIZE default */
+
+
+#define I225_RXPBSIZE_DEFAULT		0x000000A2 /* RXPBSIZE default */
+#define I225_TXPBSIZE_DEFAULT		0x04000014 /* TXPBSIZE default */
+#define IGC_RXPBS_SIZE_I225_MASK	0x0000003F /* Rx packet buffer size */
+#define IGC_TXPB0S_SIZE_I225_MASK	0x0000003F /* Tx packet buffer 0 size */
+#define IGC_STM_OPCODE		0xDB00
+#define IGC_EEPROM_FLASH_SIZE_WORD	0x11
+#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \
+	(u8)((invm_dword) & 0x7)
+#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \
+	(u8)(((invm_dword) & 0x0000FE00) >> 9)
+#define INVM_DWORD_TO_WORD_DATA(invm_dword) \
+	(u16)(((invm_dword) & 0xFFFF0000) >> 16)
+#define IGC_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS	8
+#define IGC_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS	1
+#define IGC_INVM_ULT_BYTES_SIZE		8
+#define IGC_INVM_RECORD_SIZE_IN_BYTES	4
+#define IGC_INVM_VER_FIELD_ONE		0x1FF8
+#define IGC_INVM_VER_FIELD_TWO		0x7FE000
+#define IGC_INVM_IMGTYPE_FIELD		0x1F800000
+
+#define IGC_INVM_MAJOR_MASK	0x3F0
+#define IGC_INVM_MINOR_MASK	0xF
+#define IGC_INVM_MAJOR_SHIFT	4
+
+/* PLL Defines */
+#define IGC_PCI_PMCSR		0x44
+#define IGC_PCI_PMCSR_D3		0x03
+#define IGC_MAX_PLL_TRIES		5
+#define IGC_PHY_PLL_UNCONF		0xFF
+#define IGC_PHY_PLL_FREQ_PAGE	0xFC0000
+#define IGC_PHY_PLL_FREQ_REG		0x000E
+#define IGC_INVM_DEFAULT_AL		0x202F
+#define IGC_INVM_AUTOLOAD		0x0A
+#define IGC_INVM_PLL_WO_VAL		0x0010
+
+/* Proxy Filter Control Extended */
+#define IGC_PROXYFCEX_MDNS		0x00000001 /* mDNS */
+#define IGC_PROXYFCEX_MDNS_M		0x00000002 /* mDNS Multicast */
+#define IGC_PROXYFCEX_MDNS_U		0x00000004 /* mDNS Unicast */
+#define IGC_PROXYFCEX_IPV4_M		0x00000008 /* IPv4 Multicast */
+#define IGC_PROXYFCEX_IPV6_M		0x00000010 /* IPv6 Multicast */
+#define IGC_PROXYFCEX_IGMP		0x00000020 /* IGMP */
+#define IGC_PROXYFCEX_IGMP_M		0x00000040 /* IGMP Multicast */
+#define IGC_PROXYFCEX_ARPRES		0x00000080 /* ARP Response */
+#define IGC_PROXYFCEX_ARPRES_D	0x00000100 /* ARP Response Directed */
+#define IGC_PROXYFCEX_ICMPV4		0x00000200 /* ICMPv4 */
+#define IGC_PROXYFCEX_ICMPV4_D	0x00000400 /* ICMPv4 Directed */
+#define IGC_PROXYFCEX_ICMPV6		0x00000800 /* ICMPv6 */
+#define IGC_PROXYFCEX_ICMPV6_D	0x00001000 /* ICMPv6 Directed */
+#define IGC_PROXYFCEX_DNS		0x00002000 /* DNS */
+
+/* Proxy Filter Control */
+#define IGC_PROXYFC_D0		0x00000001 /* Enable offload in D0 */
+#define IGC_PROXYFC_EX		0x00000004 /* Directed exact proxy */
+#define IGC_PROXYFC_MC		0x00000008 /* Directed MC Proxy */
+#define IGC_PROXYFC_BC		0x00000010 /* Broadcast Proxy Enable */
+#define IGC_PROXYFC_ARP_DIRECTED	0x00000020 /* Directed ARP Proxy Ena */
+#define IGC_PROXYFC_IPV4		0x00000040 /* Directed IPv4 Enable */
+#define IGC_PROXYFC_IPV6		0x00000080 /* Directed IPv6 Enable */
+#define IGC_PROXYFC_NS		0x00000200 /* IPv6 Neighbor Solicitation */
+#define IGC_PROXYFC_NS_DIRECTED	0x00000400 /* Directed NS Proxy Ena */
+#define IGC_PROXYFC_ARP		0x00000800 /* ARP Request Proxy Ena */
+/* Proxy Status */
+#define IGC_PROXYS_CLEAR		0xFFFFFFFF /* Clear */
+
+/* Firmware Status */
+#define IGC_FWSTS_FWRI		0x80000000 /* FW Reset Indication */
+/* VF Control */
+#define IGC_VTCTRL_RST		0x04000000 /* Reset VF */
+
+#define IGC_STATUS_LAN_ID_MASK	0x00000000C /* Mask for Lan ID field */
+/* Lan ID bit field offset in status register */
+#define IGC_STATUS_LAN_ID_OFFSET	2
+#define IGC_VFTA_ENTRIES		128
+
+#define IGC_UNUSEDARG
+#define ERROR_REPORT(fmt)	do { } while (0)
+#endif /* _IGC_DEFINES_H_ */
diff --git a/drivers/net/igc/base/e1000_hw.h b/drivers/net/igc/base/e1000_hw.h
new file mode 100644
index 0000000..fd07f93
--- /dev/null
+++ b/drivers/net/igc/base/e1000_hw.h
@@ -0,0 +1,1060 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_HW_H_
+#define _IGC_HW_H_
+
+#include "e1000_osdep.h"
+#include "e1000_regs.h"
+#include "e1000_defines.h"
+
+struct igc_hw;
+
+#define IGC_DEV_ID_82542			0x1000
+#define IGC_DEV_ID_82543GC_FIBER		0x1001
+#define IGC_DEV_ID_82543GC_COPPER		0x1004
+#define IGC_DEV_ID_82544EI_COPPER		0x1008
+#define IGC_DEV_ID_82544EI_FIBER		0x1009
+#define IGC_DEV_ID_82544GC_COPPER		0x100C
+#define IGC_DEV_ID_82544GC_LOM		0x100D
+#define IGC_DEV_ID_82540EM			0x100E
+#define IGC_DEV_ID_82540EM_LOM		0x1015
+#define IGC_DEV_ID_82540EP_LOM		0x1016
+#define IGC_DEV_ID_82540EP			0x1017
+#define IGC_DEV_ID_82540EP_LP			0x101E
+#define IGC_DEV_ID_82545EM_COPPER		0x100F
+#define IGC_DEV_ID_82545EM_FIBER		0x1011
+#define IGC_DEV_ID_82545GM_COPPER		0x1026
+#define IGC_DEV_ID_82545GM_FIBER		0x1027
+#define IGC_DEV_ID_82545GM_SERDES		0x1028
+#define IGC_DEV_ID_82546EB_COPPER		0x1010
+#define IGC_DEV_ID_82546EB_FIBER		0x1012
+#define IGC_DEV_ID_82546EB_QUAD_COPPER	0x101D
+#define IGC_DEV_ID_82546GB_COPPER		0x1079
+#define IGC_DEV_ID_82546GB_FIBER		0x107A
+#define IGC_DEV_ID_82546GB_SERDES		0x107B
+#define IGC_DEV_ID_82546GB_PCIE		0x108A
+#define IGC_DEV_ID_82546GB_QUAD_COPPER	0x1099
+#define IGC_DEV_ID_82546GB_QUAD_COPPER_KSP3	0x10B5
+#define IGC_DEV_ID_82541EI			0x1013
+#define IGC_DEV_ID_82541EI_MOBILE		0x1018
+#define IGC_DEV_ID_82541ER_LOM		0x1014
+#define IGC_DEV_ID_82541ER			0x1078
+#define IGC_DEV_ID_82541GI			0x1076
+#define IGC_DEV_ID_82541GI_LF			0x107C
+#define IGC_DEV_ID_82541GI_MOBILE		0x1077
+#define IGC_DEV_ID_82547EI			0x1019
+#define IGC_DEV_ID_82547EI_MOBILE		0x101A
+#define IGC_DEV_ID_82547GI			0x1075
+#define IGC_DEV_ID_82571EB_COPPER		0x105E
+#define IGC_DEV_ID_82571EB_FIBER		0x105F
+#define IGC_DEV_ID_82571EB_SERDES		0x1060
+#define IGC_DEV_ID_82571EB_SERDES_DUAL	0x10D9
+#define IGC_DEV_ID_82571EB_SERDES_QUAD	0x10DA
+#define IGC_DEV_ID_82571EB_QUAD_COPPER	0x10A4
+#define IGC_DEV_ID_82571PT_QUAD_COPPER	0x10D5
+#define IGC_DEV_ID_82571EB_QUAD_FIBER		0x10A5
+#define IGC_DEV_ID_82571EB_QUAD_COPPER_LP	0x10BC
+#define IGC_DEV_ID_82572EI_COPPER		0x107D
+#define IGC_DEV_ID_82572EI_FIBER		0x107E
+#define IGC_DEV_ID_82572EI_SERDES		0x107F
+#define IGC_DEV_ID_82572EI			0x10B9
+#define IGC_DEV_ID_82573E			0x108B
+#define IGC_DEV_ID_82573E_IAMT		0x108C
+#define IGC_DEV_ID_82573L			0x109A
+#define IGC_DEV_ID_82574L			0x10D3
+#define IGC_DEV_ID_82574LA			0x10F6
+#define IGC_DEV_ID_82583V			0x150C
+#define IGC_DEV_ID_80003ES2LAN_COPPER_DPT	0x1096
+#define IGC_DEV_ID_80003ES2LAN_SERDES_DPT	0x1098
+#define IGC_DEV_ID_80003ES2LAN_COPPER_SPT	0x10BA
+#define IGC_DEV_ID_80003ES2LAN_SERDES_SPT	0x10BB
+#define IGC_DEV_ID_ICH8_82567V_3		0x1501
+#define IGC_DEV_ID_ICH8_IGP_M_AMT		0x1049
+#define IGC_DEV_ID_ICH8_IGP_AMT		0x104A
+#define IGC_DEV_ID_ICH8_IGP_C			0x104B
+#define IGC_DEV_ID_ICH8_IFE			0x104C
+#define IGC_DEV_ID_ICH8_IFE_GT		0x10C4
+#define IGC_DEV_ID_ICH8_IFE_G			0x10C5
+#define IGC_DEV_ID_ICH8_IGP_M			0x104D
+#define IGC_DEV_ID_ICH9_IGP_M			0x10BF
+#define IGC_DEV_ID_ICH9_IGP_M_AMT		0x10F5
+#define IGC_DEV_ID_ICH9_IGP_M_V		0x10CB
+#define IGC_DEV_ID_ICH9_IGP_AMT		0x10BD
+#define IGC_DEV_ID_ICH9_BM			0x10E5
+#define IGC_DEV_ID_ICH9_IGP_C			0x294C
+#define IGC_DEV_ID_ICH9_IFE			0x10C0
+#define IGC_DEV_ID_ICH9_IFE_GT		0x10C3
+#define IGC_DEV_ID_ICH9_IFE_G			0x10C2
+#define IGC_DEV_ID_ICH10_R_BM_LM		0x10CC
+#define IGC_DEV_ID_ICH10_R_BM_LF		0x10CD
+#define IGC_DEV_ID_ICH10_R_BM_V		0x10CE
+#define IGC_DEV_ID_ICH10_D_BM_LM		0x10DE
+#define IGC_DEV_ID_ICH10_D_BM_LF		0x10DF
+#define IGC_DEV_ID_ICH10_D_BM_V		0x1525
+#define IGC_DEV_ID_PCH_M_HV_LM		0x10EA
+#define IGC_DEV_ID_PCH_M_HV_LC		0x10EB
+#define IGC_DEV_ID_PCH_D_HV_DM		0x10EF
+#define IGC_DEV_ID_PCH_D_HV_DC		0x10F0
+#define IGC_DEV_ID_PCH2_LV_LM			0x1502
+#define IGC_DEV_ID_PCH2_LV_V			0x1503
+#define IGC_DEV_ID_PCH_LPT_I217_LM		0x153A
+#define IGC_DEV_ID_PCH_LPT_I217_V		0x153B
+#define IGC_DEV_ID_PCH_LPTLP_I218_LM		0x155A
+#define IGC_DEV_ID_PCH_LPTLP_I218_V		0x1559
+#define IGC_DEV_ID_PCH_I218_LM2		0x15A0
+#define IGC_DEV_ID_PCH_I218_V2		0x15A1
+#define IGC_DEV_ID_PCH_I218_LM3		0x15A2 /* Wildcat Point PCH */
+#define IGC_DEV_ID_PCH_I218_V3		0x15A3 /* Wildcat Point PCH */
+#define IGC_DEV_ID_PCH_SPT_I219_LM		0x156F /* Sunrise Point PCH */
+#define IGC_DEV_ID_PCH_SPT_I219_V		0x1570 /* Sunrise Point PCH */
+#define IGC_DEV_ID_PCH_SPT_I219_LM2		0x15B7 /* Sunrise Point-H PCH */
+#define IGC_DEV_ID_PCH_SPT_I219_V2		0x15B8 /* Sunrise Point-H PCH */
+#define IGC_DEV_ID_PCH_LBG_I219_LM3		0x15B9 /* LEWISBURG PCH */
+#define IGC_DEV_ID_PCH_SPT_I219_LM4		0x15D7
+#define IGC_DEV_ID_PCH_SPT_I219_V4		0x15D8
+#define IGC_DEV_ID_PCH_SPT_I219_LM5		0x15E3
+#define IGC_DEV_ID_PCH_SPT_I219_V5		0x15D6
+#define IGC_DEV_ID_PCH_CNP_I219_LM6		0x15BD
+#define IGC_DEV_ID_PCH_CNP_I219_V6		0x15BE
+#define IGC_DEV_ID_PCH_CNP_I219_LM7		0x15BB
+#define IGC_DEV_ID_PCH_CNP_I219_V7		0x15BC
+#define IGC_DEV_ID_PCH_ICP_I219_LM8		0x15DF
+#define IGC_DEV_ID_PCH_ICP_I219_V8		0x15E0
+#define IGC_DEV_ID_PCH_ICP_I219_LM9		0x15E1
+#define IGC_DEV_ID_PCH_ICP_I219_V9		0x15E2
+#define IGC_DEV_ID_82576			0x10C9
+#define IGC_DEV_ID_82576_FIBER		0x10E6
+#define IGC_DEV_ID_82576_SERDES		0x10E7
+#define IGC_DEV_ID_82576_QUAD_COPPER		0x10E8
+#define IGC_DEV_ID_82576_QUAD_COPPER_ET2	0x1526
+#define IGC_DEV_ID_82576_NS			0x150A
+#define IGC_DEV_ID_82576_NS_SERDES		0x1518
+#define IGC_DEV_ID_82576_SERDES_QUAD		0x150D
+#define IGC_DEV_ID_82576_VF			0x10CA
+#define IGC_DEV_ID_82576_VF_HV		0x152D
+#define IGC_DEV_ID_I350_VF			0x1520
+#define IGC_DEV_ID_I350_VF_HV			0x152F
+#define IGC_DEV_ID_82575EB_COPPER		0x10A7
+#define IGC_DEV_ID_82575EB_FIBER_SERDES	0x10A9
+#define IGC_DEV_ID_82575GB_QUAD_COPPER	0x10D6
+#define IGC_DEV_ID_82580_COPPER		0x150E
+#define IGC_DEV_ID_82580_FIBER		0x150F
+#define IGC_DEV_ID_82580_SERDES		0x1510
+#define IGC_DEV_ID_82580_SGMII		0x1511
+#define IGC_DEV_ID_82580_COPPER_DUAL		0x1516
+#define IGC_DEV_ID_82580_QUAD_FIBER		0x1527
+#define IGC_DEV_ID_I350_COPPER		0x1521
+#define IGC_DEV_ID_I350_FIBER			0x1522
+#define IGC_DEV_ID_I350_SERDES		0x1523
+#define IGC_DEV_ID_I350_SGMII			0x1524
+#define IGC_DEV_ID_I350_DA4			0x1546
+#define IGC_DEV_ID_I210_COPPER		0x1533
+#define IGC_DEV_ID_I210_COPPER_OEM1		0x1534
+#define IGC_DEV_ID_I210_COPPER_IT		0x1535
+#define IGC_DEV_ID_I210_FIBER			0x1536
+#define IGC_DEV_ID_I210_SERDES		0x1537
+#define IGC_DEV_ID_I210_SGMII			0x1538
+#define IGC_DEV_ID_I210_COPPER_FLASHLESS	0x157B
+#define IGC_DEV_ID_I210_SERDES_FLASHLESS	0x157C
+#define IGC_DEV_ID_I210_SGMII_FLASHLESS	0x15F6
+#define IGC_DEV_ID_I211_COPPER		0x1539
+#define IGC_DEV_ID_I225_LM			0x15F2
+#define IGC_DEV_ID_I225_V			0x15F3
+#define IGC_DEV_ID_I225_K			0x3100
+#define IGC_DEV_ID_I225_I			0x15F8
+#define IGC_DEV_ID_I220_V			0x15F7
+#define IGC_DEV_ID_I225_BLANK_NVM		0x15FD
+#define IGC_DEV_ID_I354_BACKPLANE_1GBPS	0x1F40
+#define IGC_DEV_ID_I354_SGMII			0x1F41
+#define IGC_DEV_ID_I354_BACKPLANE_2_5GBPS	0x1F45
+#define IGC_DEV_ID_DH89XXCC_SGMII		0x0438
+#define IGC_DEV_ID_DH89XXCC_SERDES		0x043A
+#define IGC_DEV_ID_DH89XXCC_BACKPLANE		0x043C
+#define IGC_DEV_ID_DH89XXCC_SFP		0x0440
+
+#define IGC_REVISION_0	0
+#define IGC_REVISION_1	1
+#define IGC_REVISION_2	2
+#define IGC_REVISION_3	3
+#define IGC_REVISION_4	4
+
+#define IGC_FUNC_0		0
+#define IGC_FUNC_1		1
+#define IGC_FUNC_2		2
+#define IGC_FUNC_3		3
+
+#define IGC_ALT_MAC_ADDRESS_OFFSET_LAN0	0
+#define IGC_ALT_MAC_ADDRESS_OFFSET_LAN1	3
+#define IGC_ALT_MAC_ADDRESS_OFFSET_LAN2	6
+#define IGC_ALT_MAC_ADDRESS_OFFSET_LAN3	9
+
+enum igc_mac_type {
+	igc_undefined = 0,
+	igc_82542,
+	igc_82543,
+	igc_82544,
+	igc_82540,
+	igc_82545,
+	igc_82545_rev_3,
+	igc_82546,
+	igc_82546_rev_3,
+	igc_82541,
+	igc_82541_rev_2,
+	igc_82547,
+	igc_82547_rev_2,
+	igc_82571,
+	igc_82572,
+	igc_82573,
+	igc_82574,
+	igc_82583,
+	igc_80003es2lan,
+	igc_ich8lan,
+	igc_ich9lan,
+	igc_ich10lan,
+	igc_pchlan,
+	igc_pch2lan,
+	igc_pch_lpt,
+	igc_pch_spt,
+	igc_pch_cnp,
+	igc_82575,
+	igc_82576,
+	igc_82580,
+	igc_i350,
+	igc_i354,
+	igc_i210,
+	igc_i211,
+	igc_i225,
+	igc_vfadapt,
+	igc_vfadapt_i350,
+	igc_num_macs  /* List is 1-based, so subtract 1 for true count. */
+};
+
+enum igc_media_type {
+	igc_media_type_unknown = 0,
+	igc_media_type_copper = 1,
+	igc_media_type_fiber = 2,
+	igc_media_type_internal_serdes = 3,
+	igc_num_media_types
+};
+
+enum igc_nvm_type {
+	igc_nvm_unknown = 0,
+	igc_nvm_none,
+	igc_nvm_eeprom_spi,
+	igc_nvm_eeprom_microwire,
+	igc_nvm_flash_hw,
+	igc_nvm_invm,
+	igc_nvm_flash_sw
+};
+
+enum igc_nvm_override {
+	igc_nvm_override_none = 0,
+	igc_nvm_override_spi_small,
+	igc_nvm_override_spi_large,
+	igc_nvm_override_microwire_small,
+	igc_nvm_override_microwire_large
+};
+
+enum igc_phy_type {
+	igc_phy_unknown = 0,
+	igc_phy_none,
+	igc_phy_m88,
+	igc_phy_igp,
+	igc_phy_igp_2,
+	igc_phy_gg82563,
+	igc_phy_igp_3,
+	igc_phy_ife,
+	igc_phy_bm,
+	igc_phy_82578,
+	igc_phy_82577,
+	igc_phy_82579,
+	igc_phy_i217,
+	igc_phy_82580,
+	igc_phy_vf,
+	igc_phy_i210,
+	igc_phy_i225,
+};
+
+enum igc_bus_type {
+	igc_bus_type_unknown = 0,
+	igc_bus_type_pci,
+	igc_bus_type_pcix,
+	igc_bus_type_pci_express,
+	igc_bus_type_reserved
+};
+
+enum igc_bus_speed {
+	igc_bus_speed_unknown = 0,
+	igc_bus_speed_33,
+	igc_bus_speed_66,
+	igc_bus_speed_100,
+	igc_bus_speed_120,
+	igc_bus_speed_133,
+	igc_bus_speed_2500,
+	igc_bus_speed_5000,
+	igc_bus_speed_reserved
+};
+
+enum igc_bus_width {
+	igc_bus_width_unknown = 0,
+	igc_bus_width_pcie_x1,
+	igc_bus_width_pcie_x2,
+	igc_bus_width_pcie_x4 = 4,
+	igc_bus_width_pcie_x8 = 8,
+	igc_bus_width_32,
+	igc_bus_width_64,
+	igc_bus_width_reserved
+};
+
+enum igc_1000t_rx_status {
+	igc_1000t_rx_status_not_ok = 0,
+	igc_1000t_rx_status_ok,
+	igc_1000t_rx_status_undefined = 0xFF
+};
+
+enum igc_rev_polarity {
+	igc_rev_polarity_normal = 0,
+	igc_rev_polarity_reversed,
+	igc_rev_polarity_undefined = 0xFF
+};
+
+enum igc_fc_mode {
+	igc_fc_none = 0,
+	igc_fc_rx_pause,
+	igc_fc_tx_pause,
+	igc_fc_full,
+	igc_fc_default = 0xFF
+};
+
+enum igc_ffe_config {
+	igc_ffe_config_enabled = 0,
+	igc_ffe_config_active,
+	igc_ffe_config_blocked
+};
+
+enum igc_dsp_config {
+	igc_dsp_config_disabled = 0,
+	igc_dsp_config_enabled,
+	igc_dsp_config_activated,
+	igc_dsp_config_undefined = 0xFF
+};
+
+enum igc_ms_type {
+	igc_ms_hw_default = 0,
+	igc_ms_force_master,
+	igc_ms_force_slave,
+	igc_ms_auto
+};
+
+enum igc_smart_speed {
+	igc_smart_speed_default = 0,
+	igc_smart_speed_on,
+	igc_smart_speed_off
+};
+
+enum igc_serdes_link_state {
+	igc_serdes_link_down = 0,
+	igc_serdes_link_autoneg_progress,
+	igc_serdes_link_autoneg_complete,
+	igc_serdes_link_forced_up
+};
+
+enum igc_invm_structure_type {
+	igc_invm_unitialized_structure		= 0x00,
+	igc_invm_word_autoload_structure		= 0x01,
+	igc_invm_csr_autoload_structure		= 0x02,
+	igc_invm_phy_register_autoload_structure	= 0x03,
+	igc_invm_rsa_key_sha256_structure		= 0x04,
+	igc_invm_invalidated_structure		= 0x0f,
+};
+
+#define __le16 u16
+#define __le32 u32
+#define __le64 u64
+/* Receive Descriptor */
+struct igc_rx_desc {
+	__le64 buffer_addr; /* Address of the descriptor's data buffer */
+	__le16 length;      /* Length of data DMAed into data buffer */
+	__le16 csum; /* Packet checksum */
+	u8  status;  /* Descriptor status */
+	u8  errors;  /* Descriptor Errors */
+	__le16 special;
+};
+
+/* Receive Descriptor - Extended */
+union igc_rx_desc_extended {
+	struct {
+		__le64 buffer_addr;
+		__le64 reserved;
+	} read;
+	struct {
+		struct {
+			__le32 mrq; /* Multiple Rx Queues */
+			union {
+				__le32 rss; /* RSS Hash */
+				struct {
+					__le16 ip_id;  /* IP id */
+					__le16 csum;   /* Packet Checksum */
+				} csum_ip;
+			} hi_dword;
+		} lower;
+		struct {
+			__le32 status_error;  /* ext status/error */
+			__le16 length;
+			__le16 vlan; /* VLAN tag */
+		} upper;
+	} wb;  /* writeback */
+};
+
+#define MAX_PS_BUFFERS 4
+
+/* Number of packet split data buffers (not including the header buffer) */
+#define PS_PAGE_BUFFERS	(MAX_PS_BUFFERS - 1)
+
+/* Receive Descriptor - Packet Split */
+union igc_rx_desc_packet_split {
+	struct {
+		/* one buffer for protocol header(s), three data buffers */
+		__le64 buffer_addr[MAX_PS_BUFFERS];
+	} read;
+	struct {
+		struct {
+			__le32 mrq;  /* Multiple Rx Queues */
+			union {
+				__le32 rss; /* RSS Hash */
+				struct {
+					__le16 ip_id;    /* IP id */
+					__le16 csum;     /* Packet Checksum */
+				} csum_ip;
+			} hi_dword;
+		} lower;
+		struct {
+			__le32 status_error;  /* ext status/error */
+			__le16 length0;  /* length of buffer 0 */
+			__le16 vlan;  /* VLAN tag */
+		} middle;
+		struct {
+			__le16 header_status;
+			/* length of buffers 1-3 */
+			__le16 length[PS_PAGE_BUFFERS];
+		} upper;
+		__le64 reserved;
+	} wb; /* writeback */
+};
+
+/* Transmit Descriptor */
+struct igc_tx_desc {
+	__le64 buffer_addr;   /* Address of the descriptor's data buffer */
+	union {
+		__le32 data;
+		struct {
+			__le16 length;  /* Data buffer length */
+			u8 cso;  /* Checksum offset */
+			u8 cmd;  /* Descriptor control */
+		} flags;
+	} lower;
+	union {
+		__le32 data;
+		struct {
+			u8 status; /* Descriptor status */
+			u8 css;  /* Checksum start */
+			__le16 special;
+		} fields;
+	} upper;
+};
+
+/* Offload Context Descriptor */
+struct igc_context_desc {
+	union {
+		__le32 ip_config;
+		struct {
+			u8 ipcss;  /* IP checksum start */
+			u8 ipcso;  /* IP checksum offset */
+			__le16 ipcse;  /* IP checksum end */
+		} ip_fields;
+	} lower_setup;
+	union {
+		__le32 tcp_config;
+		struct {
+			u8 tucss;  /* TCP checksum start */
+			u8 tucso;  /* TCP checksum offset */
+			__le16 tucse;  /* TCP checksum end */
+		} tcp_fields;
+	} upper_setup;
+	__le32 cmd_and_length;
+	union {
+		__le32 data;
+		struct {
+			u8 status;  /* Descriptor status */
+			u8 hdr_len;  /* Header length */
+			__le16 mss;  /* Maximum segment size */
+		} fields;
+	} tcp_seg_setup;
+};
+
+/* Offload data descriptor */
+struct igc_data_desc {
+	__le64 buffer_addr;  /* Address of the descriptor's buffer address */
+	union {
+		__le32 data;
+		struct {
+			__le16 length;  /* Data buffer length */
+			u8 typ_len_ext;
+			u8 cmd;
+		} flags;
+	} lower;
+	union {
+		__le32 data;
+		struct {
+			u8 status;  /* Descriptor status */
+			u8 popts;  /* Packet Options */
+			__le16 special;
+		} fields;
+	} upper;
+};
+
+/* Statistics counters collected by the MAC */
+struct igc_hw_stats {
+	u64 crcerrs;
+	u64 algnerrc;
+	u64 symerrs;
+	u64 rxerrc;
+	u64 mpc;
+	u64 scc;
+	u64 ecol;
+	u64 mcc;
+	u64 latecol;
+	u64 colc;
+	u64 dc;
+	u64 tncrs;
+	u64 sec;
+	u64 cexterr;
+	u64 rlec;
+	u64 xonrxc;
+	u64 xontxc;
+	u64 xoffrxc;
+	u64 xofftxc;
+	u64 fcruc;
+	u64 prc64;
+	u64 prc127;
+	u64 prc255;
+	u64 prc511;
+	u64 prc1023;
+	u64 prc1522;
+	u64 gprc;
+	u64 bprc;
+	u64 mprc;
+	u64 gptc;
+	u64 gorc;
+	u64 gotc;
+	u64 rnbc;
+	u64 ruc;
+	u64 rfc;
+	u64 roc;
+	u64 rjc;
+	u64 mgprc;
+	u64 mgpdc;
+	u64 mgptc;
+	u64 tor;
+	u64 tot;
+	u64 tpr;
+	u64 tpt;
+	u64 ptc64;
+	u64 ptc127;
+	u64 ptc255;
+	u64 ptc511;
+	u64 ptc1023;
+	u64 ptc1522;
+	u64 mptc;
+	u64 bptc;
+	u64 tsctc;
+	u64 tsctfc;
+	u64 iac;
+	u64 icrxptc;
+	u64 icrxatc;
+	u64 ictxptc;
+	u64 ictxatc;
+	u64 ictxqec;
+	u64 ictxqmtc;
+	u64 icrxdmtc;
+	u64 icrxoc;
+	u64 cbtmpc;
+	u64 htdpmc;
+	u64 cbrdpc;
+	u64 cbrmpc;
+	u64 rpthc;
+	u64 hgptc;
+	u64 htcbdpc;
+	u64 hgorc;
+	u64 hgotc;
+	u64 lenerrs;
+	u64 scvpc;
+	u64 hrmpc;
+	u64 doosync;
+	u64 o2bgptc;
+	u64 o2bspc;
+	u64 b2ospc;
+	u64 b2ogprc;
+};
+
+struct igc_vf_stats {
+	u64 base_gprc;
+	u64 base_gptc;
+	u64 base_gorc;
+	u64 base_gotc;
+	u64 base_mprc;
+	u64 base_gotlbc;
+	u64 base_gptlbc;
+	u64 base_gorlbc;
+	u64 base_gprlbc;
+
+	u32 last_gprc;
+	u32 last_gptc;
+	u32 last_gorc;
+	u32 last_gotc;
+	u32 last_mprc;
+	u32 last_gotlbc;
+	u32 last_gptlbc;
+	u32 last_gorlbc;
+	u32 last_gprlbc;
+
+	u64 gprc;
+	u64 gptc;
+	u64 gorc;
+	u64 gotc;
+	u64 mprc;
+	u64 gotlbc;
+	u64 gptlbc;
+	u64 gorlbc;
+	u64 gprlbc;
+};
+
+struct igc_phy_stats {
+	u32 idle_errors;
+	u32 receive_errors;
+};
+
+struct igc_host_mng_dhcp_cookie {
+	u32 signature;
+	u8  status;
+	u8  reserved0;
+	u16 vlan_id;
+	u32 reserved1;
+	u16 reserved2;
+	u8  reserved3;
+	u8  checksum;
+};
+
+/* Host Interface "Rev 1" */
+struct igc_host_command_header {
+	u8 command_id;
+	u8 command_length;
+	u8 command_options;
+	u8 checksum;
+};
+
+#define IGC_HI_MAX_DATA_LENGTH	252
+struct igc_host_command_info {
+	struct igc_host_command_header command_header;
+	u8 command_data[IGC_HI_MAX_DATA_LENGTH];
+};
+
+/* Host Interface "Rev 2" */
+struct igc_host_mng_command_header {
+	u8  command_id;
+	u8  checksum;
+	u16 reserved1;
+	u16 reserved2;
+	u16 command_length;
+};
+
+#define IGC_HI_MAX_MNG_DATA_LENGTH	0x6F8
+struct igc_host_mng_command_info {
+	struct igc_host_mng_command_header command_header;
+	u8 command_data[IGC_HI_MAX_MNG_DATA_LENGTH];
+};
+
+#include "e1000_mac.h"
+#include "e1000_phy.h"
+#include "e1000_nvm.h"
+#include "e1000_manage.h"
+#include "e1000_mbx.h"
+
+/* Function pointers for the MAC. */
+struct igc_mac_operations {
+	s32  (*init_params)(struct igc_hw *);
+	s32  (*id_led_init)(struct igc_hw *);
+	s32  (*blink_led)(struct igc_hw *);
+	bool (*check_mng_mode)(struct igc_hw *);
+	s32  (*check_for_link)(struct igc_hw *);
+	s32  (*cleanup_led)(struct igc_hw *);
+	void (*clear_hw_cntrs)(struct igc_hw *);
+	void (*clear_vfta)(struct igc_hw *);
+	s32  (*get_bus_info)(struct igc_hw *);
+	void (*set_lan_id)(struct igc_hw *);
+	s32  (*get_link_up_info)(struct igc_hw *, u16 *, u16 *);
+	s32  (*led_on)(struct igc_hw *);
+	s32  (*led_off)(struct igc_hw *);
+	void (*update_mc_addr_list)(struct igc_hw *, u8 *, u32);
+	s32  (*reset_hw)(struct igc_hw *);
+	s32  (*init_hw)(struct igc_hw *);
+	void (*shutdown_serdes)(struct igc_hw *);
+	void (*power_up_serdes)(struct igc_hw *);
+	s32  (*setup_link)(struct igc_hw *);
+	s32  (*setup_physical_interface)(struct igc_hw *);
+	s32  (*setup_led)(struct igc_hw *);
+	void (*write_vfta)(struct igc_hw *, u32, u32);
+	void (*config_collision_dist)(struct igc_hw *);
+	int  (*rar_set)(struct igc_hw *, u8*, u32);
+	s32  (*read_mac_addr)(struct igc_hw *);
+	s32  (*validate_mdi_setting)(struct igc_hw *);
+	s32  (*acquire_swfw_sync)(struct igc_hw *, u16);
+	void (*release_swfw_sync)(struct igc_hw *, u16);
+};
+
+/* When to use various PHY register access functions:
+ *
+ *                 Func   Caller
+ *   Function      Does   Does    When to use
+ *   ~~~~~~~~~~~~  ~~~~~  ~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *   X_reg         L,P,A  n/a     for simple PHY reg accesses
+ *   X_reg_locked  P,A    L       for multiple accesses of different regs
+ *                                on different pages
+ *   X_reg_page    A      L,P     for multiple accesses of different regs
+ *                                on the same page
+ *
+ * Where X=[read|write], L=locking, P=sets page, A=register access
+ *
+ */
+struct igc_phy_operations {
+	s32  (*init_params)(struct igc_hw *);
+	s32  (*acquire)(struct igc_hw *);
+	s32  (*cfg_on_link_up)(struct igc_hw *);
+	s32  (*check_polarity)(struct igc_hw *);
+	s32  (*check_reset_block)(struct igc_hw *);
+	s32  (*commit)(struct igc_hw *);
+	s32  (*force_speed_duplex)(struct igc_hw *);
+	s32  (*get_cfg_done)(struct igc_hw *hw);
+	s32  (*get_cable_length)(struct igc_hw *);
+	s32  (*get_info)(struct igc_hw *);
+	s32  (*set_page)(struct igc_hw *, u16);
+	s32  (*read_reg)(struct igc_hw *, u32, u16 *);
+	s32  (*read_reg_locked)(struct igc_hw *, u32, u16 *);
+	s32  (*read_reg_page)(struct igc_hw *, u32, u16 *);
+	void (*release)(struct igc_hw *);
+	s32  (*reset)(struct igc_hw *);
+	s32  (*set_d0_lplu_state)(struct igc_hw *, bool);
+	s32  (*set_d3_lplu_state)(struct igc_hw *, bool);
+	s32  (*write_reg)(struct igc_hw *, u32, u16);
+	s32  (*write_reg_locked)(struct igc_hw *, u32, u16);
+	s32  (*write_reg_page)(struct igc_hw *, u32, u16);
+	void (*power_up)(struct igc_hw *);
+	void (*power_down)(struct igc_hw *);
+	s32 (*read_i2c_byte)(struct igc_hw *, u8, u8, u8 *);
+	s32 (*write_i2c_byte)(struct igc_hw *, u8, u8, u8);
+};
+
+/* Function pointers for the NVM. */
+struct igc_nvm_operations {
+	s32  (*init_params)(struct igc_hw *);
+	s32  (*acquire)(struct igc_hw *);
+	s32  (*read)(struct igc_hw *, u16, u16, u16 *);
+	void (*release)(struct igc_hw *);
+	void (*reload)(struct igc_hw *);
+	s32  (*update)(struct igc_hw *);
+	s32  (*valid_led_default)(struct igc_hw *, u16 *);
+	s32  (*validate)(struct igc_hw *);
+	s32  (*write)(struct igc_hw *, u16, u16, u16 *);
+};
+
+struct igc_info {
+	s32 (*get_invariants)(struct igc_hw *hw);
+	struct igc_mac_operations *mac_ops;
+	const struct igc_phy_operations *phy_ops;
+	struct igc_nvm_operations *nvm_ops;
+};
+
+extern const struct igc_info igc_i225_info;
+
+struct igc_mac_info {
+	struct igc_mac_operations ops;
+	u8 addr[ETH_ADDR_LEN];
+	u8 perm_addr[ETH_ADDR_LEN];
+
+	enum igc_mac_type type;
+
+	u32 collision_delta;
+	u32 ledctl_default;
+	u32 ledctl_mode1;
+	u32 ledctl_mode2;
+	u32 mc_filter_type;
+	u32 tx_packet_delta;
+	u32 txcw;
+
+	u16 current_ifs_val;
+	u16 ifs_max_val;
+	u16 ifs_min_val;
+	u16 ifs_ratio;
+	u16 ifs_step_size;
+	u16 mta_reg_count;
+	u16 uta_reg_count;
+
+	/* Maximum size of the MTA register table in all supported adapters */
+#define MAX_MTA_REG 128
+	u32 mta_shadow[MAX_MTA_REG];
+	u16 rar_entry_count;
+
+	u8  forced_speed_duplex;
+
+	bool adaptive_ifs;
+	bool has_fwsm;
+	bool arc_subsystem_valid;
+	bool asf_firmware_present;
+	bool autoneg;
+	bool autoneg_failed;
+	bool get_link_status;
+	bool in_ifs_mode;
+	bool report_tx_early;
+	enum igc_serdes_link_state serdes_link_state;
+	bool serdes_has_link;
+	bool tx_pkt_filtering;
+};
+
+struct igc_phy_info {
+	struct igc_phy_operations ops;
+	enum igc_phy_type type;
+
+	enum igc_1000t_rx_status local_rx;
+	enum igc_1000t_rx_status remote_rx;
+	enum igc_ms_type ms_type;
+	enum igc_ms_type original_ms_type;
+	enum igc_rev_polarity cable_polarity;
+	enum igc_smart_speed smart_speed;
+
+	u32 addr;
+	u32 id;
+	u32 reset_delay_us; /* in usec */
+	u32 revision;
+
+	enum igc_media_type media_type;
+
+	u16 autoneg_advertised;
+	u16 autoneg_mask;
+	u16 cable_length;
+	u16 max_cable_length;
+	u16 min_cable_length;
+
+	u8 mdix;
+
+	bool disable_polarity_correction;
+	bool is_mdix;
+	bool polarity_correction;
+	bool speed_downgraded;
+	bool autoneg_wait_to_complete;
+};
+
+struct igc_nvm_info {
+	struct igc_nvm_operations ops;
+	enum igc_nvm_type type;
+	enum igc_nvm_override override;
+
+	u32 flash_bank_size;
+	u32 flash_base_addr;
+
+	u16 word_size;
+	u16 delay_usec;
+	u16 address_bits;
+	u16 opcode_bits;
+	u16 page_size;
+};
+
+struct igc_bus_info {
+	enum igc_bus_type type;
+	enum igc_bus_speed speed;
+	enum igc_bus_width width;
+
+	u16 func;
+	u16 pci_cmd_word;
+};
+
+struct igc_fc_info {
+	u32 high_water;  /* Flow control high-water mark */
+	u32 low_water;  /* Flow control low-water mark */
+	u16 pause_time;  /* Flow control pause timer */
+	u16 refresh_time;  /* Flow control refresh timer */
+	bool send_xon;  /* Flow control send XON */
+	bool strict_ieee;  /* Strict IEEE mode */
+	enum igc_fc_mode current_mode;  /* FC mode in effect */
+	enum igc_fc_mode requested_mode;  /* FC mode requested by caller */
+};
+
+struct igc_mbx_operations {
+	s32 (*init_params)(struct igc_hw *hw);
+	s32 (*read)(struct igc_hw *, u32 *, u16,  u16);
+	s32 (*write)(struct igc_hw *, u32 *, u16, u16);
+	s32 (*read_posted)(struct igc_hw *, u32 *, u16,  u16);
+	s32 (*write_posted)(struct igc_hw *, u32 *, u16, u16);
+	s32 (*check_for_msg)(struct igc_hw *, u16);
+	s32 (*check_for_ack)(struct igc_hw *, u16);
+	s32 (*check_for_rst)(struct igc_hw *, u16);
+};
+
+struct igc_mbx_stats {
+	u32 msgs_tx;
+	u32 msgs_rx;
+
+	u32 acks;
+	u32 reqs;
+	u32 rsts;
+};
+
+struct igc_mbx_info {
+	struct igc_mbx_operations ops;
+	struct igc_mbx_stats stats;
+	u32 timeout;
+	u32 usec_delay;
+	u16 size;
+};
+
+struct igc_dev_spec_82541 {
+	enum igc_dsp_config dsp_config;
+	enum igc_ffe_config ffe_config;
+	u16 spd_default;
+	bool phy_init_script;
+};
+
+struct igc_dev_spec_82542 {
+	bool dma_fairness;
+};
+
+struct igc_dev_spec_82543 {
+	u32  tbi_compatibility;
+	bool dma_fairness;
+	bool init_phy_disabled;
+};
+
+struct igc_dev_spec_82571 {
+	bool laa_is_present;
+	u32 smb_counter;
+	IGC_MUTEX swflag_mutex;
+};
+
+struct igc_dev_spec_80003es2lan {
+	bool  mdic_wa_enable;
+};
+
+struct igc_shadow_ram {
+	u16  value;
+	bool modified;
+};
+
+#define IGC_SHADOW_RAM_WORDS		2048
+
+/* I218 PHY Ultra Low Power (ULP) states */
+enum igc_ulp_state {
+	igc_ulp_state_unknown,
+	igc_ulp_state_off,
+	igc_ulp_state_on,
+};
+
+struct igc_dev_spec_ich8lan {
+	bool kmrn_lock_loss_workaround_enabled;
+	struct igc_shadow_ram shadow_ram[IGC_SHADOW_RAM_WORDS];
+	IGC_MUTEX nvm_mutex;
+	IGC_MUTEX swflag_mutex;
+	bool nvm_k1_enabled;
+	bool disable_k1_off;
+	bool eee_disable;
+	u16 eee_lp_ability;
+	enum igc_ulp_state ulp_state;
+	bool ulp_capability_disabled;
+	bool during_suspend_flow;
+	bool during_dpg_exit;
+	u16 lat_enc;
+	u16 max_ltr_enc;
+	bool smbus_disable;
+};
+
+struct igc_dev_spec_82575 {
+	bool sgmii_active;
+	bool global_device_reset;
+	bool eee_disable;
+	bool module_plugged;
+	bool clear_semaphore_once;
+	u32 mtu;
+	struct sfp_igc_flags eth_flags;
+	u8 media_port;
+	bool media_changed;
+};
+
+struct igc_dev_spec_vf {
+	u32 vf_number;
+	u32 v2p_mailbox;
+};
+
+struct igc_dev_spec_i225 {
+	bool global_device_reset;
+	bool eee_disable;
+	bool clear_semaphore_once;
+	bool module_plugged;
+	u8 media_port;
+	bool mas_capable;
+	u32 mtu;
+};
+
+struct igc_hw {
+	void *back;
+
+	u8 *hw_addr;
+	u8 *flash_address;
+	unsigned long io_base;
+
+	struct igc_mac_info  mac;
+	struct igc_fc_info   fc;
+	struct igc_phy_info  phy;
+	struct igc_nvm_info  nvm;
+	struct igc_bus_info  bus;
+	struct igc_mbx_info mbx;
+	struct igc_host_mng_dhcp_cookie mng_cookie;
+
+	union {
+		struct igc_dev_spec_82541 _82541;
+		struct igc_dev_spec_82542 _82542;
+		struct igc_dev_spec_82543 _82543;
+		struct igc_dev_spec_82571 _82571;
+		struct igc_dev_spec_80003es2lan _80003es2lan;
+		struct igc_dev_spec_ich8lan ich8lan;
+		struct igc_dev_spec_82575 _82575;
+		struct igc_dev_spec_vf vf;
+		struct igc_dev_spec_i225 _i225;
+	} dev_spec;
+
+	u16 device_id;
+	u16 subsystem_vendor_id;
+	u16 subsystem_device_id;
+	u16 vendor_id;
+
+	u8  revision_id;
+};
+
+#include "e1000_82541.h"
+#include "e1000_82543.h"
+#include "e1000_82571.h"
+#include "e1000_80003es2lan.h"
+#include "e1000_ich8lan.h"
+#include "e1000_82575.h"
+#include "e1000_i210.h"
+#include "e1000_i225.h"
+#include "e1000_base.h"
+
+/* These functions must be implemented by drivers */
+void igc_pci_clear_mwi(struct igc_hw *hw);
+void igc_pci_set_mwi(struct igc_hw *hw);
+s32  igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
+s32  igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
+void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
+void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
+
+#endif
diff --git a/drivers/net/igc/base/e1000_i210.c b/drivers/net/igc/base/e1000_i210.c
new file mode 100644
index 0000000..6998514
--- /dev/null
+++ b/drivers/net/igc/base/e1000_i210.c
@@ -0,0 +1,943 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#include "e1000_api.h"
+
+
+STATIC s32 igc_acquire_nvm_i210(struct igc_hw *hw);
+STATIC void igc_release_nvm_i210(struct igc_hw *hw);
+STATIC s32 igc_get_hw_semaphore_i210(struct igc_hw *hw);
+STATIC s32 igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words,
+				u16 *data);
+STATIC s32 igc_pool_flash_update_done_i210(struct igc_hw *hw);
+STATIC s32 igc_valid_led_default_i210(struct igc_hw *hw, u16 *data);
+
+/**
+ *  igc_acquire_nvm_i210 - Request for access to EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the necessary semaphores for exclusive access to the EEPROM.
+ *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
+ *  Return successful if access grant bit set, else clear the request for
+ *  EEPROM access and return -IGC_ERR_NVM (-1).
+ **/
+STATIC s32 igc_acquire_nvm_i210(struct igc_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_acquire_nvm_i210");
+
+	ret_val = igc_acquire_swfw_sync_i210(hw, IGC_SWFW_EEP_SM);
+
+	return ret_val;
+}
+
+/**
+ *  igc_release_nvm_i210 - Release exclusive access to EEPROM
+ *  @hw: pointer to the HW structure
+ *
+ *  Stop any current commands to the EEPROM and clear the EEPROM request bit,
+ *  then release the semaphores acquired.
+ **/
+STATIC void igc_release_nvm_i210(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_release_nvm_i210");
+
+	igc_release_swfw_sync_i210(hw, IGC_SWFW_EEP_SM);
+}
+
+/**
+ *  igc_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
+ *  @hw: pointer to the HW structure
+ *  @mask: specifies which semaphore to acquire
+ *
+ *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
+ *  will also specify which port we're acquiring the lock for.
+ **/
+s32 igc_acquire_swfw_sync_i210(struct igc_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+	u32 swmask = mask;
+	u32 fwmask = mask << 16;
+	s32 ret_val = IGC_SUCCESS;
+	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
+
+	DEBUGFUNC("igc_acquire_swfw_sync_i210");
+
+	while (i < timeout) {
+		if (igc_get_hw_semaphore_i210(hw)) {
+			ret_val = -IGC_ERR_SWFW_SYNC;
+			goto out;
+		}
+
+		swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
+		if (!(swfw_sync & (fwmask | swmask)))
+			break;
+
+		/*
+		 * Firmware currently using resource (fwmask)
+		 * or other software thread using resource (swmask)
+		 */
+		igc_put_hw_semaphore_generic(hw);
+		msec_delay_irq(5);
+		i++;
+	}
+
+	if (i == timeout) {
+		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
+		ret_val = -IGC_ERR_SWFW_SYNC;
+		goto out;
+	}
+
+	swfw_sync |= swmask;
+	IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
+
+	igc_put_hw_semaphore_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_release_swfw_sync_i210 - Release SW/FW semaphore
+ *  @hw: pointer to the HW structure
+ *  @mask: specifies which semaphore to acquire
+ *
+ *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask
+ *  will also specify which port we're releasing the lock for.
+ **/
+void igc_release_swfw_sync_i210(struct igc_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+
+	DEBUGFUNC("igc_release_swfw_sync_i210");
+
+	while (igc_get_hw_semaphore_i210(hw) != IGC_SUCCESS)
+		; /* Empty */
+
+	swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
+	swfw_sync &= (u32)~mask;
+	IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
+
+	igc_put_hw_semaphore_generic(hw);
+}
+
+/**
+ *  igc_get_hw_semaphore_i210 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore to access the PHY or NVM
+ **/
+STATIC s32 igc_get_hw_semaphore_i210(struct igc_hw *hw)
+{
+	u32 swsm;
+	s32 timeout = hw->nvm.word_size + 1;
+	s32 i = 0;
+
+	DEBUGFUNC("igc_get_hw_semaphore_i210");
+
+	/* Get the SW semaphore */
+	while (i < timeout) {
+		swsm = IGC_READ_REG(hw, IGC_SWSM);
+		if (!(swsm & IGC_SWSM_SMBI))
+			break;
+
+		usec_delay(50);
+		i++;
+	}
+
+	if (i == timeout) {
+		/* In rare circumstances, the SW semaphore may already be held
+		 * unintentionally. Clear the semaphore once before giving up.
+		 */
+		if (hw->dev_spec._82575.clear_semaphore_once) {
+			hw->dev_spec._82575.clear_semaphore_once = false;
+			igc_put_hw_semaphore_generic(hw);
+			for (i = 0; i < timeout; i++) {
+				swsm = IGC_READ_REG(hw, IGC_SWSM);
+				if (!(swsm & IGC_SWSM_SMBI))
+					break;
+
+				usec_delay(50);
+			}
+		}
+
+		/* If we do not have the semaphore here, we have to give up. */
+		if (i == timeout) {
+			DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
+			return -IGC_ERR_NVM;
+		}
+	}
+
+	/* Get the FW semaphore. */
+	for (i = 0; i < timeout; i++) {
+		swsm = IGC_READ_REG(hw, IGC_SWSM);
+		IGC_WRITE_REG(hw, IGC_SWSM, swsm | IGC_SWSM_SWESMBI);
+
+		/* Semaphore acquired if bit latched */
+		if (IGC_READ_REG(hw, IGC_SWSM) & IGC_SWSM_SWESMBI)
+			break;
+
+		usec_delay(50);
+	}
+
+	if (i == timeout) {
+		/* Release semaphores */
+		igc_put_hw_semaphore_generic(hw);
+		DEBUGOUT("Driver can't access the NVM\n");
+		return -IGC_ERR_NVM;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
+ *  @hw: pointer to the HW structure
+ *  @offset: offset of word in the Shadow Ram to read
+ *  @words: number of words to read
+ *  @data: word read from the Shadow Ram
+ *
+ *  Reads a 16 bit word from the Shadow Ram using the EERD register.
+ *  Uses necessary synchronization semaphores.
+ **/
+s32 igc_read_nvm_srrd_i210(struct igc_hw *hw, u16 offset, u16 words,
+			     u16 *data)
+{
+	s32 status = IGC_SUCCESS;
+	u16 i, count;
+
+	DEBUGFUNC("igc_read_nvm_srrd_i210");
+
+	/* We cannot hold synchronization semaphores for too long,
+	 * because of forceful takeover procedure. However it is more efficient
+	 * to read in bursts than synchronizing access for each word. */
+	for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) {
+		count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ?
+			IGC_EERD_EEWR_MAX_COUNT : (words - i);
+		if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
+			status = igc_read_nvm_eerd(hw, offset, count,
+						     data + i);
+			hw->nvm.ops.release(hw);
+		} else {
+			status = IGC_ERR_SWFW_SYNC;
+		}
+
+		if (status != IGC_SUCCESS)
+			break;
+	}
+
+	return status;
+}
+
+/**
+ *  igc_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
+ *  @hw: pointer to the HW structure
+ *  @offset: offset within the Shadow RAM to be written to
+ *  @words: number of words to write
+ *  @data: 16 bit word(s) to be written to the Shadow RAM
+ *
+ *  Writes data to Shadow RAM at offset using EEWR register.
+ *
+ *  If igc_update_nvm_checksum is not called after this function , the
+ *  data will not be committed to FLASH and also Shadow RAM will most likely
+ *  contain an invalid checksum.
+ *
+ *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
+ *  partially written.
+ **/
+s32 igc_write_nvm_srwr_i210(struct igc_hw *hw, u16 offset, u16 words,
+			      u16 *data)
+{
+	s32 status = IGC_SUCCESS;
+	u16 i, count;
+
+	DEBUGFUNC("igc_write_nvm_srwr_i210");
+
+	/* We cannot hold synchronization semaphores for too long,
+	 * because of forceful takeover procedure. However it is more efficient
+	 * to write in bursts than synchronizing access for each word. */
+	for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) {
+		count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ?
+			IGC_EERD_EEWR_MAX_COUNT : (words - i);
+		if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
+			status = igc_write_nvm_srwr(hw, offset, count,
+						      data + i);
+			hw->nvm.ops.release(hw);
+		} else {
+			status = IGC_ERR_SWFW_SYNC;
+		}
+
+		if (status != IGC_SUCCESS)
+			break;
+	}
+
+	return status;
+}
+
+/**
+ *  igc_write_nvm_srwr - Write to Shadow Ram using EEWR
+ *  @hw: pointer to the HW structure
+ *  @offset: offset within the Shadow Ram to be written to
+ *  @words: number of words to write
+ *  @data: 16 bit word(s) to be written to the Shadow Ram
+ *
+ *  Writes data to Shadow Ram at offset using EEWR register.
+ *
+ *  If igc_update_nvm_checksum is not called after this function , the
+ *  Shadow Ram will most likely contain an invalid checksum.
+ **/
+STATIC s32 igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words,
+				u16 *data)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	u32 i, k, eewr = 0;
+	u32 attempts = 100000;
+	s32 ret_val = IGC_SUCCESS;
+
+	DEBUGFUNC("igc_write_nvm_srwr");
+
+	/*
+	 * A check for invalid values:  offset too large, too many words,
+	 * too many words for the offset, and not enough words.
+	 */
+	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+	    (words == 0)) {
+		DEBUGOUT("nvm parameter(s) out of bounds\n");
+		ret_val = -IGC_ERR_NVM;
+		goto out;
+	}
+
+	for (i = 0; i < words; i++) {
+		eewr = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) |
+			(data[i] << IGC_NVM_RW_REG_DATA) |
+			IGC_NVM_RW_REG_START;
+
+		IGC_WRITE_REG(hw, IGC_SRWR, eewr);
+
+		for (k = 0; k < attempts; k++) {
+			if (IGC_NVM_RW_REG_DONE &
+			    IGC_READ_REG(hw, IGC_SRWR)) {
+				ret_val = IGC_SUCCESS;
+				break;
+			}
+			usec_delay(5);
+		}
+
+		if (ret_val != IGC_SUCCESS) {
+			DEBUGOUT("Shadow RAM write EEWR timed out\n");
+			break;
+		}
+	}
+
+out:
+	return ret_val;
+}
+
+/** igc_read_invm_word_i210 - Reads OTP
+ *  @hw: pointer to the HW structure
+ *  @address: the word address (aka eeprom offset) to read
+ *  @data: pointer to the data read
+ *
+ *  Reads 16-bit words from the OTP. Return error when the word is not
+ *  stored in OTP.
+ **/
+STATIC s32 igc_read_invm_word_i210(struct igc_hw *hw, u8 address, u16 *data)
+{
+	s32 status = -IGC_ERR_INVM_VALUE_NOT_FOUND;
+	u32 invm_dword;
+	u16 i;
+	u8 record_type, word_address;
+
+	DEBUGFUNC("igc_read_invm_word_i210");
+
+	for (i = 0; i < IGC_INVM_SIZE; i++) {
+		invm_dword = IGC_READ_REG(hw, IGC_INVM_DATA_REG(i));
+		/* Get record type */
+		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
+		if (record_type == IGC_INVM_UNINITIALIZED_STRUCTURE)
+			break;
+		if (record_type == IGC_INVM_CSR_AUTOLOAD_STRUCTURE)
+			i += IGC_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
+		if (record_type == IGC_INVM_RSA_KEY_SHA256_STRUCTURE)
+			i += IGC_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
+		if (record_type == IGC_INVM_WORD_AUTOLOAD_STRUCTURE) {
+			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
+			if (word_address == address) {
+				*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
+				DEBUGOUT2("Read INVM Word 0x%02x = %x",
+					  address, *data);
+				status = IGC_SUCCESS;
+				break;
+			}
+		}
+	}
+	if (status != IGC_SUCCESS)
+		DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address);
+	return status;
+}
+
+/** igc_read_invm_i210 - Read invm wrapper function for I210/I211
+ *  @hw: pointer to the HW structure
+ *  @address: the word address (aka eeprom offset) to read
+ *  @data: pointer to the data read
+ *
+ *  Wrapper function to return data formerly found in the NVM.
+ **/
+STATIC s32 igc_read_invm_i210(struct igc_hw *hw, u16 offset,
+				u16 IGC_UNUSEDARG words, u16 *data)
+{
+	s32 ret_val = IGC_SUCCESS;
+	UNREFERENCED_1PARAMETER(words);
+
+	DEBUGFUNC("igc_read_invm_i210");
+
+	/* Only the MAC addr is required to be present in the iNVM */
+	switch (offset) {
+	case NVM_MAC_ADDR:
+		ret_val = igc_read_invm_word_i210(hw, (u8)offset, &data[0]);
+		ret_val |= igc_read_invm_word_i210(hw, (u8)offset + 1,
+						     &data[1]);
+		ret_val |= igc_read_invm_word_i210(hw, (u8)offset + 2,
+						     &data[2]);
+		if (ret_val != IGC_SUCCESS)
+			DEBUGOUT("MAC Addr not found in iNVM\n");
+		break;
+	case NVM_INIT_CTRL_2:
+		ret_val = igc_read_invm_word_i210(hw, (u8)offset, data);
+		if (ret_val != IGC_SUCCESS) {
+			*data = NVM_INIT_CTRL_2_DEFAULT_I211;
+			ret_val = IGC_SUCCESS;
+		}
+		break;
+	case NVM_INIT_CTRL_4:
+		ret_val = igc_read_invm_word_i210(hw, (u8)offset, data);
+		if (ret_val != IGC_SUCCESS) {
+			*data = NVM_INIT_CTRL_4_DEFAULT_I211;
+			ret_val = IGC_SUCCESS;
+		}
+		break;
+	case NVM_LED_1_CFG:
+		ret_val = igc_read_invm_word_i210(hw, (u8)offset, data);
+		if (ret_val != IGC_SUCCESS) {
+			*data = NVM_LED_1_CFG_DEFAULT_I211;
+			ret_val = IGC_SUCCESS;
+		}
+		break;
+	case NVM_LED_0_2_CFG:
+		ret_val = igc_read_invm_word_i210(hw, (u8)offset, data);
+		if (ret_val != IGC_SUCCESS) {
+			*data = NVM_LED_0_2_CFG_DEFAULT_I211;
+			ret_val = IGC_SUCCESS;
+		}
+		break;
+	case NVM_ID_LED_SETTINGS:
+		ret_val = igc_read_invm_word_i210(hw, (u8)offset, data);
+		if (ret_val != IGC_SUCCESS) {
+			*data = ID_LED_RESERVED_FFFF;
+			ret_val = IGC_SUCCESS;
+		}
+		break;
+	case NVM_SUB_DEV_ID:
+		*data = hw->subsystem_device_id;
+		break;
+	case NVM_SUB_VEN_ID:
+		*data = hw->subsystem_vendor_id;
+		break;
+	case NVM_DEV_ID:
+		*data = hw->device_id;
+		break;
+	case NVM_VEN_ID:
+		*data = hw->vendor_id;
+		break;
+	default:
+		DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset);
+		*data = NVM_RESERVED_WORD;
+		break;
+	}
+	return ret_val;
+}
+
+/**
+ *  igc_read_invm_version - Reads iNVM version and image type
+ *  @hw: pointer to the HW structure
+ *  @invm_ver: version structure for the version read
+ *
+ *  Reads iNVM version and image type.
+ **/
+s32 igc_read_invm_version(struct igc_hw *hw,
+			    struct igc_fw_version *invm_ver)
+{
+	u32 *record = NULL;
+	u32 *next_record = NULL;
+	u32 i = 0;
+	u32 invm_dword = 0;
+	u32 invm_blocks = IGC_INVM_SIZE - (IGC_INVM_ULT_BYTES_SIZE /
+					     IGC_INVM_RECORD_SIZE_IN_BYTES);
+	u32 buffer[IGC_INVM_SIZE];
+	s32 status = -IGC_ERR_INVM_VALUE_NOT_FOUND;
+	u16 version = 0;
+
+	DEBUGFUNC("igc_read_invm_version");
+
+	/* Read iNVM memory */
+	for (i = 0; i < IGC_INVM_SIZE; i++) {
+		invm_dword = IGC_READ_REG(hw, IGC_INVM_DATA_REG(i));
+		buffer[i] = invm_dword;
+	}
+
+	/* Read version number */
+	for (i = 1; i < invm_blocks; i++) {
+		record = &buffer[invm_blocks - i];
+		next_record = &buffer[invm_blocks - i + 1];
+
+		/* Check if we have first version location used */
+		if ((i == 1) && ((*record & IGC_INVM_VER_FIELD_ONE) == 0)) {
+			version = 0;
+			status = IGC_SUCCESS;
+			break;
+		}
+		/* Check if we have second version location used */
+		else if ((i == 1) &&
+			 ((*record & IGC_INVM_VER_FIELD_TWO) == 0)) {
+			version = (*record & IGC_INVM_VER_FIELD_ONE) >> 3;
+			status = IGC_SUCCESS;
+			break;
+		}
+		/*
+		 * Check if we have odd version location
+		 * used and it is the last one used
+		 */
+		else if ((((*record & IGC_INVM_VER_FIELD_ONE) == 0) &&
+			 ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
+			 (i != 1))) {
+			version = (*next_record & IGC_INVM_VER_FIELD_TWO)
+				  >> 13;
+			status = IGC_SUCCESS;
+			break;
+		}
+		/*
+		 * Check if we have even version location
+		 * used and it is the last one used
+		 */
+		else if (((*record & IGC_INVM_VER_FIELD_TWO) == 0) &&
+			 ((*record & 0x3) == 0)) {
+			version = (*record & IGC_INVM_VER_FIELD_ONE) >> 3;
+			status = IGC_SUCCESS;
+			break;
+		}
+	}
+
+	if (status == IGC_SUCCESS) {
+		invm_ver->invm_major = (version & IGC_INVM_MAJOR_MASK)
+					>> IGC_INVM_MAJOR_SHIFT;
+		invm_ver->invm_minor = version & IGC_INVM_MINOR_MASK;
+	}
+	/* Read Image Type */
+	for (i = 1; i < invm_blocks; i++) {
+		record = &buffer[invm_blocks - i];
+		next_record = &buffer[invm_blocks - i + 1];
+
+		/* Check if we have image type in first location used */
+		if ((i == 1) && ((*record & IGC_INVM_IMGTYPE_FIELD) == 0)) {
+			invm_ver->invm_img_type = 0;
+			status = IGC_SUCCESS;
+			break;
+		}
+		/* Check if we have image type in first location used */
+		else if ((((*record & 0x3) == 0) &&
+			 ((*record & IGC_INVM_IMGTYPE_FIELD) == 0)) ||
+			 ((((*record & 0x3) != 0) && (i != 1)))) {
+			invm_ver->invm_img_type =
+				(*next_record & IGC_INVM_IMGTYPE_FIELD) >> 23;
+			status = IGC_SUCCESS;
+			break;
+		}
+	}
+	return status;
+}
+
+/**
+ *  igc_validate_nvm_checksum_i210 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 igc_validate_nvm_checksum_i210(struct igc_hw *hw)
+{
+	s32 status = IGC_SUCCESS;
+	s32 (*read_op_ptr)(struct igc_hw *, u16, u16, u16 *);
+
+	DEBUGFUNC("igc_validate_nvm_checksum_i210");
+
+	if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
+
+		/*
+		 * Replace the read function with semaphore grabbing with
+		 * the one that skips this for a while.
+		 * We have semaphore taken already here.
+		 */
+		read_op_ptr = hw->nvm.ops.read;
+		hw->nvm.ops.read = igc_read_nvm_eerd;
+
+		status = igc_validate_nvm_checksum_generic(hw);
+
+		/* Revert original read operation. */
+		hw->nvm.ops.read = read_op_ptr;
+
+		hw->nvm.ops.release(hw);
+	} else {
+		status = IGC_ERR_SWFW_SYNC;
+	}
+
+	return status;
+}
+
+
+/**
+ *  igc_update_nvm_checksum_i210 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  up to the checksum.  Then calculates the EEPROM checksum and writes the
+ *  value to the EEPROM. Next commit EEPROM data onto the Flash.
+ **/
+s32 igc_update_nvm_checksum_i210(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u16 checksum = 0;
+	u16 i, nvm_data;
+
+	DEBUGFUNC("igc_update_nvm_checksum_i210");
+
+	/*
+	 * Read the first word from the EEPROM. If this times out or fails, do
+	 * not continue or we could be in for a very long wait while every
+	 * EEPROM read fails
+	 */
+	ret_val = igc_read_nvm_eerd(hw, 0, 1, &nvm_data);
+	if (ret_val != IGC_SUCCESS) {
+		DEBUGOUT("EEPROM read failed\n");
+		goto out;
+	}
+
+	if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
+		/*
+		 * Do not use hw->nvm.ops.write, hw->nvm.ops.read
+		 * because we do not want to take the synchronization
+		 * semaphores twice here.
+		 */
+
+		for (i = 0; i < NVM_CHECKSUM_REG; i++) {
+			ret_val = igc_read_nvm_eerd(hw, i, 1, &nvm_data);
+			if (ret_val) {
+				hw->nvm.ops.release(hw);
+				DEBUGOUT("NVM Read Error while updating checksum.\n");
+				goto out;
+			}
+			checksum += nvm_data;
+		}
+		checksum = (u16) NVM_SUM - checksum;
+		ret_val = igc_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
+						&checksum);
+		if (ret_val != IGC_SUCCESS) {
+			hw->nvm.ops.release(hw);
+			DEBUGOUT("NVM Write Error while updating checksum.\n");
+			goto out;
+		}
+
+		hw->nvm.ops.release(hw);
+
+		ret_val = igc_update_flash_i210(hw);
+	} else {
+		ret_val = IGC_ERR_SWFW_SYNC;
+	}
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_get_flash_presence_i210 - Check if flash device is detected.
+ *  @hw: pointer to the HW structure
+ *
+ **/
+bool igc_get_flash_presence_i210(struct igc_hw *hw)
+{
+	u32 eec = 0;
+	bool ret_val = false;
+
+	DEBUGFUNC("igc_get_flash_presence_i210");
+
+	eec = IGC_READ_REG(hw, IGC_EECD);
+
+	if (eec & IGC_EECD_FLASH_DETECTED_I210)
+		ret_val = true;
+
+	return ret_val;
+}
+
+/**
+ *  igc_update_flash_i210 - Commit EEPROM to the flash
+ *  @hw: pointer to the HW structure
+ *
+ **/
+s32 igc_update_flash_i210(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u32 flup;
+
+	DEBUGFUNC("igc_update_flash_i210");
+
+	ret_val = igc_pool_flash_update_done_i210(hw);
+	if (ret_val == -IGC_ERR_NVM) {
+		DEBUGOUT("Flash update time out\n");
+		goto out;
+	}
+
+	flup = IGC_READ_REG(hw, IGC_EECD) | IGC_EECD_FLUPD_I210;
+	IGC_WRITE_REG(hw, IGC_EECD, flup);
+
+	ret_val = igc_pool_flash_update_done_i210(hw);
+	if (ret_val == IGC_SUCCESS)
+		DEBUGOUT("Flash update complete\n");
+	else
+		DEBUGOUT("Flash update time out\n");
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_pool_flash_update_done_i210 - Pool FLUDONE status.
+ *  @hw: pointer to the HW structure
+ *
+ **/
+s32 igc_pool_flash_update_done_i210(struct igc_hw *hw)
+{
+	s32 ret_val = -IGC_ERR_NVM;
+	u32 i, reg;
+
+	DEBUGFUNC("igc_pool_flash_update_done_i210");
+
+	for (i = 0; i < IGC_FLUDONE_ATTEMPTS; i++) {
+		reg = IGC_READ_REG(hw, IGC_EECD);
+		if (reg & IGC_EECD_FLUDONE_I210) {
+			ret_val = IGC_SUCCESS;
+			break;
+		}
+		usec_delay(5);
+	}
+
+	return ret_val;
+}
+
+/**
+ *  igc_init_nvm_params_i210 - Initialize i210 NVM function pointers
+ *  @hw: pointer to the HW structure
+ *
+ *  Initialize the i210/i211 NVM parameters and function pointers.
+ **/
+STATIC s32 igc_init_nvm_params_i210(struct igc_hw *hw)
+{
+	s32 ret_val;
+	struct igc_nvm_info *nvm = &hw->nvm;
+
+	DEBUGFUNC("igc_init_nvm_params_i210");
+
+	ret_val = igc_init_nvm_params_82575(hw);
+	nvm->ops.acquire = igc_acquire_nvm_i210;
+	nvm->ops.release = igc_release_nvm_i210;
+	nvm->ops.valid_led_default = igc_valid_led_default_i210;
+	if (igc_get_flash_presence_i210(hw)) {
+		hw->nvm.type = igc_nvm_flash_hw;
+		nvm->ops.read    = igc_read_nvm_srrd_i210;
+		nvm->ops.write   = igc_write_nvm_srwr_i210;
+		nvm->ops.validate = igc_validate_nvm_checksum_i210;
+		nvm->ops.update   = igc_update_nvm_checksum_i210;
+	} else {
+		hw->nvm.type = igc_nvm_invm;
+		nvm->ops.read     = igc_read_invm_i210;
+		nvm->ops.write    = igc_null_write_nvm;
+		nvm->ops.validate = igc_null_ops_generic;
+		nvm->ops.update   = igc_null_ops_generic;
+	}
+	return ret_val;
+}
+
+/**
+ *  igc_init_function_pointers_i210 - Init func ptrs.
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize all function pointers and parameters.
+ **/
+void igc_init_function_pointers_i210(struct igc_hw *hw)
+{
+	igc_init_function_pointers_82575(hw);
+	hw->nvm.ops.init_params = igc_init_nvm_params_i210;
+}
+
+/**
+ *  igc_valid_led_default_i210 - Verify a valid default LED config
+ *  @hw: pointer to the HW structure
+ *  @data: pointer to the NVM (EEPROM)
+ *
+ *  Read the EEPROM for the current default LED configuration.  If the
+ *  LED configuration is not valid, set to a valid LED configuration.
+ **/
+STATIC s32 igc_valid_led_default_i210(struct igc_hw *hw, u16 *data)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_valid_led_default_i210");
+
+	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
+	if (ret_val) {
+		DEBUGOUT("NVM Read Error\n");
+		goto out;
+	}
+
+	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
+		switch (hw->phy.media_type) {
+		case igc_media_type_internal_serdes:
+			*data = ID_LED_DEFAULT_I210_SERDES;
+			break;
+		case igc_media_type_copper:
+		default:
+			*data = ID_LED_DEFAULT_I210;
+			break;
+		}
+	}
+out:
+	return ret_val;
+}
+
+/**
+ * igc_pll_workaround_i210
+ * @hw: pointer to the HW structure
+ *
+ * Works around an errata in the PLL circuit where it occasionally
+ * provides the wrong clock frequency after power up.
+ **/
+STATIC s32 igc_pll_workaround_i210(struct igc_hw *hw)
+{
+	s32 ret_val;
+	u32 wuc, mdicnfg, ctrl, ctrl_ext, reg_val;
+	u16 nvm_word, phy_word, pci_word, tmp_nvm;
+	int i;
+
+	/* Get PHY semaphore */
+	hw->phy.ops.acquire(hw);
+	/* Get and set needed register values */
+	wuc = IGC_READ_REG(hw, IGC_WUC);
+	mdicnfg = IGC_READ_REG(hw, IGC_MDICNFG);
+	reg_val = mdicnfg & ~IGC_MDICNFG_EXT_MDIO;
+	IGC_WRITE_REG(hw, IGC_MDICNFG, reg_val);
+
+	/* Get data from NVM, or set default */
+	ret_val = igc_read_invm_word_i210(hw, IGC_INVM_AUTOLOAD,
+					    &nvm_word);
+	if (ret_val != IGC_SUCCESS)
+		nvm_word = IGC_INVM_DEFAULT_AL;
+	tmp_nvm = nvm_word | IGC_INVM_PLL_WO_VAL;
+	for (i = 0; i < IGC_MAX_PLL_TRIES; i++) {
+		/* check current state directly from internal PHY */
+		igc_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, 0xFC);
+		usec_delay(20);
+		igc_read_phy_reg_mdic(hw, IGC_PHY_PLL_FREQ_REG, &phy_word);
+		usec_delay(20);
+		igc_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, 0);
+		if ((phy_word & IGC_PHY_PLL_UNCONF)
+		    != IGC_PHY_PLL_UNCONF) {
+			ret_val = IGC_SUCCESS;
+			break;
+		} else {
+			ret_val = -IGC_ERR_PHY;
+		}
+		/* directly reset the internal PHY */
+		ctrl = IGC_READ_REG(hw, IGC_CTRL);
+		IGC_WRITE_REG(hw, IGC_CTRL, ctrl|IGC_CTRL_PHY_RST);
+
+		ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+		ctrl_ext |= (IGC_CTRL_EXT_PHYPDEN | IGC_CTRL_EXT_SDLPE);
+		IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+
+		IGC_WRITE_REG(hw, IGC_WUC, 0);
+		reg_val = (IGC_INVM_AUTOLOAD << 4) | (tmp_nvm << 16);
+		IGC_WRITE_REG(hw, IGC_EEARBC_I210, reg_val);
+
+		igc_read_pci_cfg(hw, IGC_PCI_PMCSR, &pci_word);
+		pci_word |= IGC_PCI_PMCSR_D3;
+		igc_write_pci_cfg(hw, IGC_PCI_PMCSR, &pci_word);
+		msec_delay(1);
+		pci_word &= ~IGC_PCI_PMCSR_D3;
+		igc_write_pci_cfg(hw, IGC_PCI_PMCSR, &pci_word);
+		reg_val = (IGC_INVM_AUTOLOAD << 4) | (nvm_word << 16);
+		IGC_WRITE_REG(hw, IGC_EEARBC_I210, reg_val);
+
+		/* restore WUC register */
+		IGC_WRITE_REG(hw, IGC_WUC, wuc);
+	}
+	/* restore MDICNFG setting */
+	IGC_WRITE_REG(hw, IGC_MDICNFG, mdicnfg);
+	/* Release PHY semaphore */
+	hw->phy.ops.release(hw);
+	return ret_val;
+}
+
+/**
+ *  igc_get_cfg_done_i210 - Read config done bit
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the management control register for the config done bit for
+ *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
+ *  to read the config done bit, so an error is *ONLY* logged and returns
+ *  IGC_SUCCESS.  If we were to return with error, EEPROM-less silicon
+ *  would not be able to be reset or change link.
+ **/
+STATIC s32 igc_get_cfg_done_i210(struct igc_hw *hw)
+{
+	s32 timeout = PHY_CFG_TIMEOUT;
+	u32 mask = IGC_NVM_CFG_DONE_PORT_0;
+
+	DEBUGFUNC("igc_get_cfg_done_i210");
+
+	while (timeout) {
+		if (IGC_READ_REG(hw, IGC_EEMNGCTL_I210) & mask)
+			break;
+		msec_delay(1);
+		timeout--;
+	}
+	if (!timeout)
+		DEBUGOUT("MNG configuration cycle has not completed.\n");
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_hw_i210 - Init hw for I210/I211
+ *  @hw: pointer to the HW structure
+ *
+ *  Called to initialize hw for i210 hw family.
+ **/
+s32 igc_init_hw_i210(struct igc_hw *hw)
+{
+	s32 ret_val;
+	struct igc_mac_info *mac = &hw->mac;
+
+	DEBUGFUNC("igc_init_hw_i210");
+	if ((hw->mac.type >= igc_i210) &&
+	    !(igc_get_flash_presence_i210(hw))) {
+		ret_val = igc_pll_workaround_i210(hw);
+		if (ret_val != IGC_SUCCESS)
+			return ret_val;
+	}
+	hw->phy.ops.get_cfg_done = igc_get_cfg_done_i210;
+
+	/* Initialize identification LED */
+	ret_val = mac->ops.id_led_init(hw);
+
+	ret_val = igc_init_hw_base(hw);
+	return ret_val;
+}
diff --git a/drivers/net/igc/base/e1000_i210.h b/drivers/net/igc/base/e1000_i210.h
new file mode 100644
index 0000000..15f8051
--- /dev/null
+++ b/drivers/net/igc/base/e1000_i210.h
@@ -0,0 +1,77 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#ifndef _IGC_I210_H_
+#define _IGC_I210_H_
+
+bool igc_get_flash_presence_i210(struct igc_hw *hw);
+s32 igc_update_flash_i210(struct igc_hw *hw);
+s32 igc_update_nvm_checksum_i210(struct igc_hw *hw);
+s32 igc_validate_nvm_checksum_i210(struct igc_hw *hw);
+s32 igc_write_nvm_srwr_i210(struct igc_hw *hw, u16 offset,
+			      u16 words, u16 *data);
+s32 igc_read_nvm_srrd_i210(struct igc_hw *hw, u16 offset,
+			     u16 words, u16 *data);
+s32 igc_read_invm_version(struct igc_hw *hw,
+			    struct igc_fw_version *invm_ver);
+s32 igc_acquire_swfw_sync_i210(struct igc_hw *hw, u16 mask);
+void igc_release_swfw_sync_i210(struct igc_hw *hw, u16 mask);
+s32 igc_init_hw_i210(struct igc_hw *hw);
+
+#define IGC_STM_OPCODE		0xDB00
+#define IGC_EEPROM_FLASH_SIZE_WORD	0x11
+
+#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \
+	(u8)((invm_dword) & 0x7)
+#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \
+	(u8)(((invm_dword) & 0x0000FE00) >> 9)
+#define INVM_DWORD_TO_WORD_DATA(invm_dword) \
+	(u16)(((invm_dword) & 0xFFFF0000) >> 16)
+
+enum IGC_INVM_STRUCTURE_TYPE {
+	IGC_INVM_UNINITIALIZED_STRUCTURE		= 0x00,
+	IGC_INVM_WORD_AUTOLOAD_STRUCTURE		= 0x01,
+	IGC_INVM_CSR_AUTOLOAD_STRUCTURE		= 0x02,
+	IGC_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE	= 0x03,
+	IGC_INVM_RSA_KEY_SHA256_STRUCTURE		= 0x04,
+	IGC_INVM_INVALIDATED_STRUCTURE		= 0x0F,
+};
+
+#define IGC_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS	8
+#define IGC_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS	1
+#define IGC_INVM_ULT_BYTES_SIZE	8
+#define IGC_INVM_RECORD_SIZE_IN_BYTES	4
+#define IGC_INVM_VER_FIELD_ONE	0x1FF8
+#define IGC_INVM_VER_FIELD_TWO	0x7FE000
+#define IGC_INVM_IMGTYPE_FIELD	0x1F800000
+
+#define IGC_INVM_MAJOR_MASK	0x3F0
+#define IGC_INVM_MINOR_MASK	0xF
+#define IGC_INVM_MAJOR_SHIFT	4
+
+#define ID_LED_DEFAULT_I210		((ID_LED_OFF1_ON2  << 8) | \
+					 (ID_LED_DEF1_DEF2 <<  4) | \
+					 (ID_LED_OFF1_OFF2))
+#define ID_LED_DEFAULT_I210_SERDES	((ID_LED_DEF1_DEF2 << 8) | \
+					 (ID_LED_DEF1_DEF2 <<  4) | \
+					 (ID_LED_OFF1_ON2))
+
+/* NVM offset defaults for I211 devices */
+#define NVM_INIT_CTRL_2_DEFAULT_I211	0X7243
+#define NVM_INIT_CTRL_4_DEFAULT_I211	0x00C1
+#define NVM_LED_1_CFG_DEFAULT_I211	0x0184
+#define NVM_LED_0_2_CFG_DEFAULT_I211	0x200C
+
+/* PLL Defines */
+#define IGC_PCI_PMCSR			0x44
+#define IGC_PCI_PMCSR_D3		0x03
+#define IGC_MAX_PLL_TRIES		5
+#define IGC_PHY_PLL_UNCONF		0xFF
+#define IGC_PHY_PLL_FREQ_PAGE		0xFC0000
+#define IGC_PHY_PLL_FREQ_REG		0x000E
+#define IGC_INVM_DEFAULT_AL		0x202F
+#define IGC_INVM_AUTOLOAD		0x0A
+#define IGC_INVM_PLL_WO_VAL		0x0010
+
+#endif
diff --git a/drivers/net/igc/base/e1000_i225.c b/drivers/net/igc/base/e1000_i225.c
new file mode 100644
index 0000000..3f34df7
--- /dev/null
+++ b/drivers/net/igc/base/e1000_i225.c
@@ -0,0 +1,1390 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2001-2019
+ */
+
+#include "e1000_api.h"
+
+STATIC s32 igc_init_nvm_params_i225(struct igc_hw *hw);
+STATIC s32 igc_init_mac_params_i225(struct igc_hw *hw);
+STATIC s32 igc_init_phy_params_i225(struct igc_hw *hw);
+STATIC s32 igc_reset_hw_i225(struct igc_hw *hw);
+STATIC s32 igc_acquire_nvm_i225(struct igc_hw *hw);
+STATIC void igc_release_nvm_i225(struct igc_hw *hw);
+STATIC s32 igc_get_hw_semaphore_i225(struct igc_hw *hw);
+STATIC s32 __igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words,
+				  u16 *data);
+STATIC s32 igc_pool_flash_update_done_i225(struct igc_hw *hw);
+STATIC s32 igc_valid_led_default_i225(struct igc_hw *hw, u16 *data);
+
+/**
+ *  igc_init_nvm_params_i225 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_nvm_params_i225(struct igc_hw *hw)
+{
+	struct igc_nvm_info *nvm = &hw->nvm;
+	u32 eecd = IGC_READ_REG(hw, IGC_EECD);
+	u16 size;
+
+	DEBUGFUNC("igc_init_nvm_params_i225");
+
+	size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
+		     IGC_EECD_SIZE_EX_SHIFT);
+	/*
+	 * Added to a constant, "size" becomes the left-shift value
+	 * for setting word_size.
+	 */
+	size += NVM_WORD_SIZE_BASE_SHIFT;
+
+	/* Just in case size is out of range, cap it to the largest
+	 * EEPROM size supported
+	 */
+	if (size > 15)
+		size = 15;
+
+	nvm->word_size = 1 << size;
+	nvm->opcode_bits = 8;
+	nvm->delay_usec = 1;
+	nvm->type = igc_nvm_eeprom_spi;
+
+
+	nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
+	nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
+			    16 : 8;
+
+	if (nvm->word_size == (1 << 15))
+		nvm->page_size = 128;
+
+	nvm->ops.acquire = igc_acquire_nvm_i225;
+	nvm->ops.release = igc_release_nvm_i225;
+	nvm->ops.valid_led_default = igc_valid_led_default_i225;
+	if (igc_get_flash_presence_i225(hw)) {
+		hw->nvm.type = igc_nvm_flash_hw;
+		nvm->ops.read    = igc_read_nvm_srrd_i225;
+		nvm->ops.write   = igc_write_nvm_srwr_i225;
+		nvm->ops.validate = igc_validate_nvm_checksum_i225;
+		nvm->ops.update   = igc_update_nvm_checksum_i225;
+	} else {
+		hw->nvm.type = igc_nvm_invm;
+		nvm->ops.write    = igc_null_write_nvm;
+		nvm->ops.validate = igc_null_ops_generic;
+		nvm->ops.update   = igc_null_ops_generic;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_mac_params_i225 - Init MAC func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_mac_params_i225(struct igc_hw *hw)
+{
+	struct igc_mac_info *mac = &hw->mac;
+	struct igc_dev_spec_i225 *dev_spec = &hw->dev_spec._i225;
+
+	DEBUGFUNC("igc_init_mac_params_i225");
+
+	/* Initialize function pointer */
+	igc_init_mac_ops_generic(hw);
+
+	/* Set media type */
+	hw->phy.media_type = igc_media_type_copper;
+	/* Set mta register count */
+	mac->mta_reg_count = 128;
+	/* Set rar entry count */
+	mac->rar_entry_count = IGC_RAR_ENTRIES_BASE;
+
+	/* reset */
+	mac->ops.reset_hw = igc_reset_hw_i225;
+	/* hw initialization */
+	mac->ops.init_hw = igc_init_hw_i225;
+	/* link setup */
+	mac->ops.setup_link = igc_setup_link_generic;
+	/* check for link */
+	mac->ops.check_for_link = igc_check_for_link_i225;
+	/* link info */
+	mac->ops.get_link_up_info = igc_get_speed_and_duplex_copper_generic;
+	/* acquire SW_FW sync */
+	mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
+	/* release SW_FW sync */
+	mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
+
+	/* Allow a single clear of the SW semaphore on I225 */
+	dev_spec->clear_semaphore_once = true;
+	mac->ops.setup_physical_interface = igc_setup_copper_link_i225;
+
+	/* Set if part includes ASF firmware */
+	mac->asf_firmware_present = true;
+
+	/* multicast address update */
+	mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
+
+	mac->ops.write_vfta = igc_write_vfta_generic;
+
+	return IGC_SUCCESS;
+}
+
+/**
+ *  igc_init_phy_params_i225 - Init PHY func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 igc_init_phy_params_i225(struct igc_hw *hw)
+{
+	struct igc_phy_info *phy = &hw->phy;
+	s32 ret_val = IGC_SUCCESS;
+	u32 ctrl_ext;
+
+	DEBUGFUNC("igc_init_phy_params_i225");
+
+	phy->ops.read_i2c_byte = igc_read_i2c_byte_generic;
+	phy->ops.write_i2c_byte = igc_write_i2c_byte_generic;
+
+	if (hw->phy.media_type != igc_media_type_copper) {
+		phy->type = igc_phy_none;
+		goto out;
+	}
+
+	phy->ops.power_up   = igc_power_up_phy_copper;
+	phy->ops.power_down = igc_power_down_phy_copper_base;
+
+	phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500;
+
+	phy->reset_delay_us	= 100;
+
+	phy->ops.acquire	= igc_acquire_phy_base;
+	phy->ops.check_reset_block = igc_check_reset_block_generic;
+	phy->ops.commit		= igc_phy_sw_reset_generic;
+	phy->ops.release	= igc_release_phy_base;
+
+	ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
+
+	/* Make sure the PHY is in a good state. Several people have reported
+	 * firmware leaving the PHY's page select register set to something
+	 * other than the default of zero, which causes the PHY ID read to
+	 * access something other than the intended register.
+	 */
+	ret_val = hw->phy.ops.reset(hw);
+	if (ret_val)
+		goto out;
+
+	IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
+	phy->ops.read_reg = igc_read_phy_reg_gpy;
+	phy->ops.write_reg = igc_write_phy_reg_gpy;
+
+	ret_val = igc_get_phy_id(hw);
+	/* Verify phy id and set remaining function pointers */
+	switch (phy->id) {
+	case I225_I_PHY_ID:
+		phy->type		= igc_phy_i225;
+		phy->ops.set_d0_lplu_state = igc_set_d0_lplu_state_i225;
+		phy->ops.set_d3_lplu_state = igc_set_d3_lplu_state_i225;
+		/* TODO - complete with GPY PHY information */
+		break;
+	default:
+		ret_val = -IGC_ERR_PHY;
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_reset_hw_i225 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets the hardware into a known state.
+ **/
+STATIC s32 igc_reset_hw_i225(struct igc_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val;
+
+	DEBUGFUNC("igc_reset_hw_i225");
+
+	/*
+	 * Prevent the PCI-E bus from sticking if there is no TLP connection
+	 * on the last TLP read/write transaction when MAC is reset.
+	 */
+	ret_val = igc_disable_pcie_master_generic(hw);
+	if (ret_val)
+		DEBUGOUT("PCI-E Master disable polling has failed.\n");
+
+	DEBUGOUT("Masking off all interrupts\n");
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+
+	IGC_WRITE_REG(hw, IGC_RCTL, 0);
+	IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
+	IGC_WRITE_FLUSH(hw);
+
+	msec_delay(10);
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+
+	DEBUGOUT("Issuing a global reset to MAC\n");
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
+
+	ret_val = igc_get_auto_rd_done_generic(hw);
+	if (ret_val) {
+		/*
+		 * When auto config read does not complete, do not
+		 * return with an error. This can happen in situations
+		 * where there is no eeprom and prevents getting link.
+		 */
+		DEBUGOUT("Auto Read Done did not complete\n");
+	}
+
+	/* Clear any pending interrupt events. */
+	IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
+	IGC_READ_REG(hw, IGC_ICR);
+
+	/* Install any alternate MAC address into RAR0 */
+	ret_val = igc_check_alt_mac_addr_generic(hw);
+
+	return ret_val;
+}
+
+/* igc_acquire_nvm_i225 - Request for access to EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Acquire the necessary semaphores for exclusive access to the EEPROM.
+ * Set the EEPROM access request bit and wait for EEPROM access grant bit.
+ * Return successful if access grant bit set, else clear the request for
+ * EEPROM access and return -IGC_ERR_NVM (-1).
+ */
+STATIC s32 igc_acquire_nvm_i225(struct igc_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("igc_acquire_nvm_i225");
+
+	ret_val = igc_acquire_swfw_sync_i225(hw, IGC_SWFW_EEP_SM);
+
+	return ret_val;
+}
+
+/* igc_release_nvm_i225 - Release exclusive access to EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Stop any current commands to the EEPROM and clear the EEPROM request bit,
+ * then release the semaphores acquired.
+ */
+STATIC void igc_release_nvm_i225(struct igc_hw *hw)
+{
+	DEBUGFUNC("igc_release_nvm_i225");
+
+	igc_release_swfw_sync_i225(hw, IGC_SWFW_EEP_SM);
+}
+
+/* igc_acquire_swfw_sync_i225 - Acquire SW/FW semaphore
+ * @hw: pointer to the HW structure
+ * @mask: specifies which semaphore to acquire
+ *
+ * Acquire the SW/FW semaphore to access the PHY or NVM.  The mask
+ * will also specify which port we're acquiring the lock for.
+ */
+s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+	u32 swmask = mask;
+	u32 fwmask = mask << 16;
+	s32 ret_val = IGC_SUCCESS;
+	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
+
+	DEBUGFUNC("igc_acquire_swfw_sync_i225");
+
+	while (i < timeout) {
+		if (igc_get_hw_semaphore_i225(hw)) {
+			ret_val = -IGC_ERR_SWFW_SYNC;
+			goto out;
+		}
+
+		swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
+		if (!(swfw_sync & (fwmask | swmask)))
+			break;
+
+		/* Firmware currently using resource (fwmask)
+		 * or other software thread using resource (swmask)
+		 */
+		igc_put_hw_semaphore_generic(hw);
+		msec_delay_irq(5);
+		i++;
+	}
+
+	if (i == timeout) {
+		DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
+		ret_val = -IGC_ERR_SWFW_SYNC;
+		goto out;
+	}
+
+	swfw_sync |= swmask;
+	IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
+
+	igc_put_hw_semaphore_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/* igc_release_swfw_sync_i225 - Release SW/FW semaphore
+ * @hw: pointer to the HW structure
+ * @mask: specifies which semaphore to acquire
+ *
+ * Release the SW/FW semaphore used to access the PHY or NVM.  The mask
+ * will also specify which port we're releasing the lock for.
+ */
+void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+
+	DEBUGFUNC("igc_release_swfw_sync_i225");
+
+	while (igc_get_hw_semaphore_i225(hw) != IGC_SUCCESS)
+		; /* Empty */
+
+	swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
+	swfw_sync &= ~mask;
+	IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
+
+	igc_put_hw_semaphore_generic(hw);
+}
+
+/*
+ * igc_setup_copper_link_i225 - Configure copper link settings
+ * @hw: pointer to the HW structure
+ *
+ * Configures the link for auto-neg or forced speed and duplex.  Then we check
+ * for link, once link is established calls to configure collision distance
+ * and flow control are called.
+ */
+s32 igc_setup_copper_link_i225(struct igc_hw *hw)
+{
+	u32 phpm_reg;
+	s32 ret_val;
+	u32 ctrl;
+
+	DEBUGFUNC("igc_setup_copper_link_i225");
+
+	ctrl = IGC_READ_REG(hw, IGC_CTRL);
+	ctrl |= IGC_CTRL_SLU;
+	ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
+	IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
+
+	phpm_reg = IGC_READ_REG(hw, IGC_I225_PHPM);
+	phpm_reg &= ~IGC_I225_PHPM_GO_LINKD;
+	IGC_WRITE_REG(hw, IGC_I225_PHPM, phpm_reg);
+
+	ret_val = igc_setup_copper_link_generic(hw);
+
+	return ret_val;
+}
+
+/* igc_get_hw_semaphore_i225 - Acquire hardware semaphore
+ * @hw: pointer to the HW structure
+ *
+ * Acquire the HW semaphore to access the PHY or NVM
+ */
+STATIC s32 igc_get_hw_semaphore_i225(struct igc_hw *hw)
+{
+	u32 swsm;
+	s32 timeout = hw->nvm.word_size + 1;
+	s32 i = 0;
+
+	DEBUGFUNC("igc_get_hw_semaphore_i225");
+
+	/* Get the SW semaphore */
+	while (i < timeout) {
+		swsm = IGC_READ_REG(hw, IGC_SWSM);
+		if (!(swsm & IGC_SWSM_SMBI))
+			break;
+
+		usec_delay(50);
+		i++;
+	}
+
+	if (i == timeout) {
+		/* In rare circumstances, the SW semaphore may already be held
+		 * unintentionally. Clear the semaphore once before giving up.
+		 */
+		if (hw->dev_spec._i225.clear_semaphore_once) {
+			hw->dev_spec._i225.clear_semaphore_once = false;
+			igc_put_hw_semaphore_generic(hw);
+			for (i = 0; i < timeout; i++) {
+				swsm = IGC_READ_REG(hw, IGC_SWSM);
+				if (!(swsm & IGC_SWSM_SMBI))
+					break;
+
+				usec_delay(50);
+			}
+		}
+
+		/* If we do not have the semaphore here, we have to give up. */
+		if (i == timeout) {
+			DEBUGOUT("Driver can't access device -\n");
+			DEBUGOUT("SMBI bit is set.\n");
+			return -IGC_ERR_NVM;
+		}
+	}
+
+	/* Get the FW semaphore. */
+	for (i = 0; i < timeout; i++) {
+		swsm = IGC_READ_REG(hw, IGC_SWSM);
+		IGC_WRITE_REG(hw, IGC_SWSM, swsm | IGC_SWSM_SWESMBI);
+
+		/* Semaphore acquired if bit latched */
+		if (IGC_READ_REG(hw, IGC_SWSM) & IGC_SWSM_SWESMBI)
+			break;
+
+		usec_delay(50);
+	}
+
+	if (i == timeout) {
+		/* Release semaphores */
+		igc_put_hw_semaphore_generic(hw);
+		DEBUGOUT("Driver can't access the NVM\n");
+		return -IGC_ERR_NVM;
+	}
+
+	return IGC_SUCCESS;
+}
+
+/* igc_read_nvm_srrd_i225 - Reads Shadow Ram using EERD register
+ * @hw: pointer to the HW structure
+ * @offset: offset of word in the Shadow Ram to read
+ * @words: number of words to read
+ * @data: word read from the Shadow Ram
+ *
+ * Reads a 16 bit word from the Shadow Ram using the EERD register.
+ * Uses necessary synchronization semaphores.
+ */
+s32 igc_read_nvm_srrd_i225(struct igc_hw *hw, u16 offset, u16 words,
+			     u16 *data)
+{
+	s32 status = IGC_SUCCESS;
+	u16 i, count;
+
+	DEBUGFUNC("igc_read_nvm_srrd_i225");
+
+	/* We cannot hold synchronization semaphores for too long,
+	 * because of forceful takeover procedure. However it is more efficient
+	 * to read in bursts than synchronizing access for each word.
+	 */
+	for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) {
+		count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ?
+			IGC_EERD_EEWR_MAX_COUNT : (words - i);
+		if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
+			status = igc_read_nvm_eerd(hw, offset, count,
+						     data + i);
+			hw->nvm.ops.release(hw);
+		} else {
+			status = IGC_ERR_SWFW_SYNC;
+		}
+
+		if (status != IGC_SUCCESS)
+			break;
+	}
+
+	return status;
+}
+
+/* igc_write_nvm_srwr_i225 - Write to Shadow RAM using EEWR
+ * @hw: pointer to the HW structure
+ * @offset: offset within the Shadow RAM to be written to
+ * @words: number of words to write
+ * @data: 16 bit word(s) to be written to the Shadow RAM
+ *
+ * Writes data to Shadow RAM at offset using EEWR register.
+ *
+ * If igc_update_nvm_checksum is not called after this function , the
+ * data will not be committed to FLASH and also Shadow RAM will most likely
+ * contain an invalid checksum.
+ *
+ * If error code is returned, data and Shadow RAM may be inconsistent - buffer
+ * partially written.
+ */
+s32 igc_write_nvm_srwr_i225(struct igc_hw *hw, u16 offset, u16 words,
+			      u16 *data)
+{
+	s32 status = IGC_SUCCESS;
+	u16 i, count;
+
+	DEBUGFUNC("igc_write_nvm_srwr_i225");
+
+	/* We cannot hold synchronization semaphores for too long,
+	 * because of forceful takeover procedure. However it is more efficient
+	 * to write in bursts than synchronizing access for each word.
+	 */
+	for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) {
+		count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ?
+			IGC_EERD_EEWR_MAX_COUNT : (words - i);
+		if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
+			status = __igc_write_nvm_srwr(hw, offset, count,
+							data + i);
+			hw->nvm.ops.release(hw);
+		} else {
+			status = IGC_ERR_SWFW_SYNC;