DPDK patches and discussions
 help / color / mirror / Atom feed
From: Anatoly Burakov <anatoly.burakov@intel.com>
To: dev@dpdk.org
Subject: [PATCH v1 05/42] net/e1000/base: add NVM/EEPROM support for i225
Date: Fri, 31 Jan 2025 12:58:18 +0000	[thread overview]
Message-ID: <26e5f01f2f55270f3ec04dd8f452aae0cadb1462.1738328107.git.anatoly.burakov@intel.com> (raw)
In-Reply-To: <cover.1738328106.git.anatoly.burakov@intel.com>

Add support for NVM/EEPROM operations for i225 series NICs. This is
mostly identical to IGC driver, with some minor differences due to the
way IGC driver was originally generated.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 drivers/net/intel/e1000/base/e1000_defines.h |  40 +
 drivers/net/intel/e1000/base/e1000_hw.h      |  20 +
 drivers/net/intel/e1000/base/e1000_i225.c    | 736 +++++++++++++++++++
 drivers/net/intel/e1000/base/e1000_i225.h    |  26 +
 drivers/net/intel/e1000/base/e1000_nvm.c     |   1 +
 drivers/net/intel/e1000/base/e1000_phy.c     |  63 ++
 drivers/net/intel/e1000/base/e1000_phy.h     |   6 +
 drivers/net/intel/e1000/base/e1000_regs.h    |   9 +
 8 files changed, 901 insertions(+)

diff --git a/drivers/net/intel/e1000/base/e1000_defines.h b/drivers/net/intel/e1000/base/e1000_defines.h
index 0e33f27c3f..49e4f6c7cc 100644
--- a/drivers/net/intel/e1000/base/e1000_defines.h
+++ b/drivers/net/intel/e1000/base/e1000_defines.h
@@ -1055,6 +1055,15 @@
 /* Firmware code revision field word offset*/
 #define E1000_I210_FW_VER_OFFSET	328
 
+#define E1000_EECD_FLUPD_I225		0x00800000 /* Update FLASH */
+#define E1000_EECD_FLUDONE_I225		0x04000000 /* Update FLASH done */
+#define E1000_EECD_FLASH_DETECTED_I225	0x00080000 /* FLASH detected */
+#define E1000_FLUDONE_ATTEMPTS		20000
+#define E1000_EERD_EEWR_MAX_COUNT	512 /* buffered EEPROM words rw */
+#define E1000_EECD_SEC1VAL_I225		0x02000000 /* Sector One Valid */
+#define E1000_FLSECU_BLK_SW_ACCESS_I225	0x00000004 /* Block SW access */
+#define E1000_FWSM_FW_VALID_I225	0x8000 /* FW valid bit */
+
 #define E1000_NVM_RW_REG_DATA	16  /* Offset to data in NVM read/write regs */
 #define E1000_NVM_RW_REG_DONE	2   /* Offset to READ/WRITE done bit */
 #define E1000_NVM_RW_REG_START	1   /* Start operation */
@@ -1482,6 +1491,37 @@
 #define I210_RXPBSIZE_DEFAULT		0x000000A2 /* RXPBSIZE default */
 #define I210_TXPBSIZE_DEFAULT		0x04000014 /* TXPBSIZE default */
 
+#define E1000_STM_OPCODE		0xDB00
+#define E1000_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 E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS	8
+#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS	1
+#define E1000_INVM_ULT_BYTES_SIZE		8
+#define E1000_INVM_RECORD_SIZE_IN_BYTES	4
+#define E1000_INVM_VER_FIELD_ONE		0x1FF8
+#define E1000_INVM_VER_FIELD_TWO		0x7FE000
+#define E1000_INVM_IMGTYPE_FIELD		0x1F800000
+
+#define E1000_INVM_MAJOR_MASK	0x3F0
+#define E1000_INVM_MINOR_MASK	0xF
+#define E1000_INVM_MAJOR_SHIFT	4
+
+/* PLL Defines */
+#define E1000_PCI_PMCSR		0x44
+#define E1000_PCI_PMCSR_D3		0x03
+#define E1000_MAX_PLL_TRIES		5
+#define E1000_PHY_PLL_UNCONF		0xFF
+#define E1000_PHY_PLL_FREQ_PAGE	0xFC0000
+#define E1000_PHY_PLL_FREQ_REG		0x000E
+#define E1000_INVM_DEFAULT_AL		0x202F
+#define E1000_INVM_AUTOLOAD		0x0A
+#define E1000_INVM_PLL_WO_VAL		0x0010
+
 
 /* Proxy Filter Control */
 #define E1000_PROXYFC_D0		0x00000001 /* Enable offload in D0 */
diff --git a/drivers/net/intel/e1000/base/e1000_hw.h b/drivers/net/intel/e1000/base/e1000_hw.h
index a21cb070e0..c16dd1cbf7 100644
--- a/drivers/net/intel/e1000/base/e1000_hw.h
+++ b/drivers/net/intel/e1000/base/e1000_hw.h
@@ -381,6 +381,15 @@ enum e1000_serdes_link_state {
 	e1000_serdes_link_forced_up
 };
 
+enum e1000_invm_structure_type {
+	e1000_invm_unitialized_structure		= 0x00,
+	e1000_invm_word_autoload_structure		= 0x01,
+	e1000_invm_csr_autoload_structure		= 0x02,
+	e1000_invm_phy_register_autoload_structure	= 0x03,
+	e1000_invm_rsa_key_sha256_structure		= 0x04,
+	e1000_invm_invalidated_structure		= 0x0f,
+};
+
 #define __le16 u16
 #define __le32 u32
 #define __le64 u64
@@ -996,6 +1005,16 @@ struct e1000_dev_spec_vf {
 	u32 v2p_mailbox;
 };
 
+struct e1000_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 e1000_hw {
 	void *back;
 
@@ -1020,6 +1039,7 @@ struct e1000_hw {
 		struct e1000_dev_spec_ich8lan ich8lan;
 		struct e1000_dev_spec_82575 _82575;
 		struct e1000_dev_spec_vf vf;
+		struct e1000_dev_spec_i225 _i225;
 	} dev_spec;
 
 	u16 device_id;
diff --git a/drivers/net/intel/e1000/base/e1000_i225.c b/drivers/net/intel/e1000/base/e1000_i225.c
index a7a42e2f0e..7c8cf8552d 100644
--- a/drivers/net/intel/e1000/base/e1000_i225.c
+++ b/drivers/net/intel/e1000/base/e1000_i225.c
@@ -4,9 +4,75 @@
 
 #include "e1000_api.h"
 
+STATIC s32 e1000_init_nvm_params_i225(struct e1000_hw *hw);
 STATIC s32 e1000_init_mac_params_i225(struct e1000_hw *hw);
 STATIC s32 e1000_init_phy_params_i225(struct e1000_hw *hw);
 STATIC s32 e1000_reset_hw_i225(struct e1000_hw *hw);
+STATIC s32 e1000_acquire_nvm_i225(struct e1000_hw *hw);
+STATIC void e1000_release_nvm_i225(struct e1000_hw *hw);
+STATIC s32 e1000_get_hw_semaphore_i225(struct e1000_hw *hw);
+STATIC s32 __e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data);
+STATIC s32 e1000_pool_flash_update_done_i225(struct e1000_hw *hw);
+STATIC s32 e1000_valid_led_default_i225(struct e1000_hw *hw, u16 *data);
+
+/**
+ *  e1000_init_nvm_params_i225 - Init NVM func ptrs.
+ *  @hw: pointer to the HW structure
+ **/
+STATIC s32 e1000_init_nvm_params_i225(struct e1000_hw *hw)
+{
+	struct e1000_nvm_info *nvm = &hw->nvm;
+	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
+	u16 size;
+
+	DEBUGFUNC("e1000_init_nvm_params_i225");
+
+	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+		     E1000_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 = e1000_nvm_eeprom_spi;
+
+
+	nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
+	nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ?
+			    16 : 8;
+
+	if (nvm->word_size == (1 << 15))
+		nvm->page_size = 128;
+
+	nvm->ops.acquire = e1000_acquire_nvm_i225;
+	nvm->ops.release = e1000_release_nvm_i225;
+	nvm->ops.valid_led_default = e1000_valid_led_default_i225;
+	if (e1000_get_flash_presence_i225(hw)) {
+		hw->nvm.type = e1000_nvm_flash_hw;
+		nvm->ops.read    = e1000_read_nvm_srrd_i225;
+		nvm->ops.write   = e1000_write_nvm_srwr_i225;
+		nvm->ops.validate = e1000_validate_nvm_checksum_i225;
+		nvm->ops.update   = e1000_update_nvm_checksum_i225;
+	} else {
+		hw->nvm.type = e1000_nvm_none;
+		nvm->ops.write    = e1000_null_write_nvm;
+		nvm->ops.validate = e1000_null_ops_generic;
+		nvm->ops.update   = e1000_null_ops_generic;
+	}
+
+	return E1000_SUCCESS;
+}
 
 /**
  *  e1000_init_mac_params_i225 - Init MAC func ptrs.
@@ -15,6 +81,7 @@ STATIC s32 e1000_reset_hw_i225(struct e1000_hw *hw);
 STATIC s32 e1000_init_mac_params_i225(struct e1000_hw *hw)
 {
 	struct e1000_mac_info *mac = &hw->mac;
+	struct e1000_dev_spec_i225 *dev_spec = &hw->dev_spec._i225;
 
 	DEBUGFUNC("e1000_init_mac_params_i225");
 
@@ -38,8 +105,13 @@ STATIC s32 e1000_init_mac_params_i225(struct e1000_hw *hw)
 	mac->ops.check_for_link = e1000_check_for_copper_link_generic;
 	/* link info */
 	mac->ops.get_link_up_info = e1000_get_speed_and_duplex_copper_generic;
+	/* acquire SW_FW sync */
+	mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i225;
+	/* release SW_FW sync */
+	mac->ops.release_swfw_sync = e1000_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 = e1000_setup_copper_link_i225;
 
 	/* Set if part includes ASF firmware */
@@ -103,6 +175,8 @@ STATIC s32 e1000_init_phy_params_i225(struct e1000_hw *hw)
 		goto out;
 
 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+	phy->ops.read_reg = e1000_read_phy_reg_gpy;
+	phy->ops.write_reg = e1000_write_phy_reg_gpy;
 
 	ret_val = e1000_get_phy_id(hw);
 
@@ -177,6 +251,118 @@ STATIC s32 e1000_reset_hw_i225(struct e1000_hw *hw)
 	return ret_val;
 }
 
+/* e1000_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 -E1000_ERR_NVM (-1).
+ */
+STATIC s32 e1000_acquire_nvm_i225(struct e1000_hw *hw)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("e1000_acquire_nvm_i225");
+
+	ret_val = e1000_acquire_swfw_sync_i225(hw, E1000_SWFW_EEP_SM);
+
+	return ret_val;
+}
+
+/* e1000_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 e1000_release_nvm_i225(struct e1000_hw *hw)
+{
+	DEBUGFUNC("e1000_release_nvm_i225");
+
+	e1000_release_swfw_sync_i225(hw, E1000_SWFW_EEP_SM);
+}
+
+/* e1000_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 e1000_acquire_swfw_sync_i225(struct e1000_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+	u32 swmask = mask;
+	u32 fwmask = mask << 16;
+	s32 ret_val = E1000_SUCCESS;
+	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
+
+	DEBUGFUNC("e1000_acquire_swfw_sync_i225");
+
+	while (i < timeout) {
+		if (e1000_get_hw_semaphore_i225(hw)) {
+			ret_val = -E1000_ERR_SWFW_SYNC;
+			goto out;
+		}
+
+		swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
+		if (!(swfw_sync & (fwmask | swmask)))
+			break;
+
+		/* Firmware currently using resource (fwmask)
+		 * or other software thread using resource (swmask)
+		 */
+		e1000_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 = -E1000_ERR_SWFW_SYNC;
+		goto out;
+	}
+
+	swfw_sync |= swmask;
+	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
+
+	e1000_put_hw_semaphore_generic(hw);
+
+out:
+	return ret_val;
+}
+
+/* e1000_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 e1000_release_swfw_sync_i225(struct e1000_hw *hw, u16 mask)
+{
+	u32 swfw_sync;
+
+	DEBUGFUNC("e1000_release_swfw_sync_i225");
+
+	/* Releasing the resource requires first getting the HW semaphore.
+	 * If we fail to get the semaphore, there is nothing we can do,
+	 * except log an error and quit. We are not allowed to hang here
+	 * indefinitely, as it may cause denial of service or system crash.
+	 */
+	if (e1000_get_hw_semaphore_i225(hw) != E1000_SUCCESS) {
+		DEBUGOUT("Failed to release SW_FW_SYNC.\n");
+		return;
+	}
+
+	swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC);
+	swfw_sync &= ~(u32)mask;
+	E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync);
+
+	e1000_put_hw_semaphore_generic(hw);
+}
+
 /*
  * e1000_setup_copper_link_i225 - Configure copper link settings
  * @hw: pointer to the HW structure
@@ -207,6 +393,520 @@ s32 e1000_setup_copper_link_i225(struct e1000_hw *hw)
 	return ret_val;
 }
 
+/* e1000_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 e1000_get_hw_semaphore_i225(struct e1000_hw *hw)
+{
+	u32 swsm;
+	s32 timeout = E1000_SWSM_TIMEOUT;
+	s32 i = 0;
+
+	DEBUGFUNC("e1000_get_hw_semaphore_i225");
+
+	/* Get the SW semaphore */
+	while (i < timeout) {
+		swsm = E1000_READ_REG(hw, E1000_SWSM);
+		if (!(swsm & E1000_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;
+			e1000_put_hw_semaphore_generic(hw);
+			for (i = 0; i < timeout; i++) {
+				swsm = E1000_READ_REG(hw, E1000_SWSM);
+				if (!(swsm & E1000_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 -E1000_ERR_NVM;
+		}
+	}
+
+	/* Get the FW semaphore. */
+	for (i = 0; i < timeout; i++) {
+		swsm = E1000_READ_REG(hw, E1000_SWSM);
+		E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
+
+		/* Semaphore acquired if bit latched */
+		if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)
+			break;
+
+		usec_delay(50);
+	}
+
+	if (i == timeout) {
+		/* Release semaphores */
+		e1000_put_hw_semaphore_generic(hw);
+		DEBUGOUT("Driver can't access the NVM\n");
+		return -E1000_ERR_NVM;
+	}
+
+	return E1000_SUCCESS;
+}
+
+/* e1000_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 e1000_read_nvm_srrd_i225(struct e1000_hw *hw, u16 offset, u16 words,
+			     u16 *data)
+{
+	s32 status = E1000_SUCCESS;
+	u16 i, count;
+
+	DEBUGFUNC("e1000_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 += E1000_EERD_EEWR_MAX_COUNT) {
+		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
+			E1000_EERD_EEWR_MAX_COUNT : (words - i);
+		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+			status = e1000_read_nvm_eerd(hw, offset, count,
+						     data + i);
+			hw->nvm.ops.release(hw);
+		} else {
+			status = E1000_ERR_SWFW_SYNC;
+		}
+
+		if (status != E1000_SUCCESS)
+			break;
+	}
+
+	return status;
+}
+
+/* e1000_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 e1000_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 e1000_write_nvm_srwr_i225(struct e1000_hw *hw, u16 offset, u16 words,
+			      u16 *data)
+{
+	s32 status = E1000_SUCCESS;
+	u16 i, count;
+
+	DEBUGFUNC("e1000_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 += E1000_EERD_EEWR_MAX_COUNT) {
+		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
+			E1000_EERD_EEWR_MAX_COUNT : (words - i);
+		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+			status = __e1000_write_nvm_srwr(hw, offset, count,
+							data + i);
+			hw->nvm.ops.release(hw);
+		} else {
+			status = E1000_ERR_SWFW_SYNC;
+		}
+
+		if (status != E1000_SUCCESS)
+			break;
+	}
+
+	return status;
+}
+
+/* __e1000_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 e1000_update_nvm_checksum is not called after this function , the
+ * Shadow Ram will most likely contain an invalid checksum.
+ */
+STATIC s32 __e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data)
+{
+	struct e1000_nvm_info *nvm = &hw->nvm;
+	u32 i, k, eewr = 0;
+	u32 attempts = 100000;
+	s32 ret_val = E1000_SUCCESS;
+
+	DEBUGFUNC("__e1000_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 = -E1000_ERR_NVM;
+		goto out;
+	}
+
+	for (i = 0; i < words; i++) {
+		ret_val = -E1000_ERR_NVM;
+		eewr = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) |
+			(data[i] << E1000_NVM_RW_REG_DATA) |
+			E1000_NVM_RW_REG_START;
+
+		E1000_WRITE_REG(hw, E1000_SRWR, eewr);
+
+		for (k = 0; k < attempts; k++) {
+			if (E1000_NVM_RW_REG_DONE &
+			    E1000_READ_REG(hw, E1000_SRWR)) {
+				ret_val = E1000_SUCCESS;
+				break;
+			}
+			usec_delay(5);
+		}
+
+		if (ret_val != E1000_SUCCESS) {
+			DEBUGOUT("Shadow RAM write EEWR timed out\n");
+			break;
+		}
+	}
+
+out:
+	return ret_val;
+}
+
+/* e1000_validate_nvm_checksum_i225 - 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 e1000_validate_nvm_checksum_i225(struct e1000_hw *hw)
+{
+	s32 status = E1000_SUCCESS;
+	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
+
+	DEBUGFUNC("e1000_validate_nvm_checksum_i225");
+
+	if (hw->nvm.ops.acquire(hw) == E1000_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 = e1000_read_nvm_eerd;
+
+		status = e1000_validate_nvm_checksum_generic(hw);
+
+		/* Revert original read operation. */
+		hw->nvm.ops.read = read_op_ptr;
+
+		hw->nvm.ops.release(hw);
+	} else {
+		status = E1000_ERR_SWFW_SYNC;
+	}
+
+	return status;
+}
+
+/* e1000_update_nvm_checksum_i225 - 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 e1000_update_nvm_checksum_i225(struct e1000_hw *hw)
+{
+	s32 ret_val;
+	u16 checksum = 0;
+	u16 i, nvm_data;
+
+	DEBUGFUNC("e1000_update_nvm_checksum_i225");
+
+	/* 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 = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data);
+	if (ret_val != E1000_SUCCESS) {
+		DEBUGOUT("EEPROM read failed\n");
+		goto out;
+	}
+
+	if (hw->nvm.ops.acquire(hw) == E1000_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 = e1000_read_nvm_eerd(hw, i, 1, &nvm_data);
+			if (ret_val) {
+				hw->nvm.ops.release(hw);
+				DEBUGOUT("NVM Read Error while updating\n");
+				DEBUGOUT("checksum.\n");
+				goto out;
+			}
+			checksum += nvm_data;
+		}
+		checksum = (u16)NVM_SUM - checksum;
+		ret_val = __e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
+						 &checksum);
+		if (ret_val != E1000_SUCCESS) {
+			hw->nvm.ops.release(hw);
+			DEBUGOUT("NVM Write Error while updating checksum.\n");
+			goto out;
+		}
+
+		hw->nvm.ops.release(hw);
+
+		ret_val = e1000_update_flash_i225(hw);
+	} else {
+		ret_val = E1000_ERR_SWFW_SYNC;
+	}
+out:
+	return ret_val;
+}
+
+/* e1000_get_flash_presence_i225 - Check if flash device is detected.
+ * @hw: pointer to the HW structure
+ */
+bool e1000_get_flash_presence_i225(struct e1000_hw *hw)
+{
+	u32 eec = 0;
+	bool ret_val = false;
+
+	DEBUGFUNC("e1000_get_flash_presence_i225");
+
+	eec = E1000_READ_REG(hw, E1000_EECD);
+
+	if (eec & E1000_EECD_FLASH_DETECTED_I225)
+		ret_val = true;
+
+	return ret_val;
+}
+
+/* e1000_set_flsw_flash_burst_counter_i225 - sets FLSW NVM Burst
+ * Counter in FLSWCNT register.
+ *
+ * @hw: pointer to the HW structure
+ * @burst_counter: size in bytes of the Flash burst to read or write
+ */
+s32 e1000_set_flsw_flash_burst_counter_i225(struct e1000_hw *hw,
+					    u32 burst_counter)
+{
+	s32 ret_val = E1000_SUCCESS;
+
+	DEBUGFUNC("e1000_set_flsw_flash_burst_counter_i225");
+
+	/* Validate input data */
+	if (burst_counter < E1000_I225_SHADOW_RAM_SIZE) {
+		/* Write FLSWCNT - burst counter */
+		E1000_WRITE_REG(hw, E1000_I225_FLSWCNT, burst_counter);
+	} else {
+		ret_val = E1000_ERR_INVALID_ARGUMENT;
+	}
+
+	return ret_val;
+}
+
+/* e1000_write_erase_flash_command_i225 - write/erase to a sector
+ * region on a given address.
+ *
+ * @hw: pointer to the HW structure
+ * @opcode: opcode to be used for the write command
+ * @address: the offset to write into the FLASH image
+ */
+s32 e1000_write_erase_flash_command_i225(struct e1000_hw *hw, u32 opcode,
+					 u32 address)
+{
+	u32 flswctl = 0;
+	s32 timeout = E1000_NVM_GRANT_ATTEMPTS;
+	s32 ret_val = E1000_SUCCESS;
+
+	DEBUGFUNC("e1000_write_erase_flash_command_i225");
+
+	flswctl = E1000_READ_REG(hw, E1000_I225_FLSWCTL);
+	/* Polling done bit on FLSWCTL register */
+	while (timeout) {
+		if (flswctl & E1000_FLSWCTL_DONE)
+			break;
+		usec_delay(5);
+		flswctl = E1000_READ_REG(hw, E1000_I225_FLSWCTL);
+		timeout--;
+	}
+
+	if (!timeout) {
+		DEBUGOUT("Flash transaction was not done\n");
+		return -E1000_ERR_NVM;
+	}
+
+	/* Build and issue command on FLSWCTL register */
+	flswctl = address | opcode;
+	E1000_WRITE_REG(hw, E1000_I225_FLSWCTL, flswctl);
+
+	/* Check if issued command is valid on FLSWCTL register */
+	flswctl = E1000_READ_REG(hw, E1000_I225_FLSWCTL);
+	if (!(flswctl & E1000_FLSWCTL_CMDV)) {
+		DEBUGOUT("Write flash command failed\n");
+		ret_val = E1000_ERR_INVALID_ARGUMENT;
+	}
+
+	return ret_val;
+}
+
+/* e1000_update_flash_i225 - Commit EEPROM to the flash
+ * if fw_valid_bit is set, FW is active. setting FLUPD bit in EEC
+ * register makes the FW load the internal shadow RAM into the flash.
+ * Otherwise, fw_valid_bit is 0. if FL_SECU.block_prtotected_sw = 0
+ * then FW is not active so the SW is responsible shadow RAM dump.
+ *
+ * @hw: pointer to the HW structure
+ */
+s32 e1000_update_flash_i225(struct e1000_hw *hw)
+{
+	u16 current_offset_data = 0;
+	u32 block_sw_protect = 1;
+	u16 base_address = 0x0;
+	u32 i, fw_valid_bit;
+	u16 current_offset;
+	s32 ret_val = 0;
+	u32 flup;
+
+	DEBUGFUNC("e1000_update_flash_i225");
+
+	block_sw_protect = E1000_READ_REG(hw, E1000_I225_FLSECU) &
+					  E1000_FLSECU_BLK_SW_ACCESS_I225;
+	fw_valid_bit = E1000_READ_REG(hw, E1000_FWSM) &
+				      E1000_FWSM_FW_VALID_I225;
+	if (fw_valid_bit) {
+		ret_val = e1000_pool_flash_update_done_i225(hw);
+		if (ret_val == -E1000_ERR_NVM) {
+			DEBUGOUT("Flash update time out\n");
+			goto out;
+		}
+
+		flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I225;
+		E1000_WRITE_REG(hw, E1000_EECD, flup);
+
+		ret_val = e1000_pool_flash_update_done_i225(hw);
+		if (ret_val == E1000_SUCCESS)
+			DEBUGOUT("Flash update complete\n");
+		else
+			DEBUGOUT("Flash update time out\n");
+	} else if (!block_sw_protect) {
+		/* FW is not active and security protection is disabled.
+		 * therefore, SW is in charge of shadow RAM dump.
+		 * Check which sector is valid. if sector 0 is valid,
+		 * base address remains 0x0. otherwise, sector 1 is
+		 * valid and it's base address is 0x1000
+		 */
+		if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL_I225)
+			base_address = 0x1000;
+
+		/* Valid sector erase */
+		ret_val = e1000_write_erase_flash_command_i225(hw,
+						  E1000_I225_ERASE_CMD_OPCODE,
+						  base_address);
+		if (!ret_val) {
+			DEBUGOUT("Sector erase failed\n");
+			goto out;
+		}
+
+		current_offset = base_address;
+
+		/* Write */
+		for (i = 0; i < E1000_I225_SHADOW_RAM_SIZE / 2; i++) {
+			/* Set burst write length */
+			ret_val = e1000_set_flsw_flash_burst_counter_i225(hw,
+									  0x2);
+			if (ret_val != E1000_SUCCESS)
+				break;
+
+			/* Set address and opcode */
+			ret_val = e1000_write_erase_flash_command_i225(hw,
+						E1000_I225_WRITE_CMD_OPCODE,
+						2 * current_offset);
+			if (ret_val != E1000_SUCCESS)
+				break;
+
+			ret_val = e1000_read_nvm_eerd(hw, current_offset,
+						      1, &current_offset_data);
+			if (ret_val) {
+				DEBUGOUT("Failed to read from EEPROM\n");
+				goto out;
+			}
+
+			/* Write CurrentOffseData to FLSWDATA register */
+			E1000_WRITE_REG(hw, E1000_I225_FLSWDATA,
+					current_offset_data);
+			current_offset++;
+
+			/* Wait till operation has finished */
+			ret_val = e1000_poll_eerd_eewr_done(hw,
+						E1000_NVM_POLL_READ);
+			if (ret_val)
+				break;
+
+			usec_delay(1000);
+		}
+	}
+out:
+	return ret_val;
+}
+
+/* e1000_pool_flash_update_done_i225 - Pool FLUDONE status.
+ * @hw: pointer to the HW structure
+ */
+s32 e1000_pool_flash_update_done_i225(struct e1000_hw *hw)
+{
+	s32 ret_val = -E1000_ERR_NVM;
+	u32 i, reg;
+
+	DEBUGFUNC("e1000_pool_flash_update_done_i225");
+
+	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
+		reg = E1000_READ_REG(hw, E1000_EECD);
+		if (reg & E1000_EECD_FLUDONE_I225) {
+			ret_val = E1000_SUCCESS;
+			break;
+		}
+		usec_delay(5);
+	}
+
+	return ret_val;
+}
+
 /* e1000_init_function_pointers_i225 - Init func ptrs.
  * @hw: pointer to the HW structure
  *
@@ -216,10 +916,46 @@ void e1000_init_function_pointers_i225(struct e1000_hw *hw)
 {
 	e1000_init_mac_ops_generic(hw);
 	e1000_init_phy_ops_generic(hw);
+	e1000_init_nvm_ops_generic(hw);
 	hw->mac.ops.init_params = e1000_init_mac_params_i225;
+	hw->nvm.ops.init_params = e1000_init_nvm_params_i225;
 	hw->phy.ops.init_params = e1000_init_phy_params_i225;
 }
 
+/* e1000_valid_led_default_i225 - 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 e1000_valid_led_default_i225(struct e1000_hw *hw, u16 *data)
+{
+	s32 ret_val;
+
+	DEBUGFUNC("e1000_valid_led_default_i225");
+
+	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 e1000_media_type_internal_serdes:
+			*data = ID_LED_DEFAULT_I225_SERDES;
+			break;
+		case e1000_media_type_copper:
+		default:
+			*data = ID_LED_DEFAULT_I225;
+			break;
+		}
+	}
+out:
+	return ret_val;
+}
+
 /* e1000_get_cfg_done_i225 - Read config done bit
  * @hw: pointer to the HW structure
  *
diff --git a/drivers/net/intel/e1000/base/e1000_i225.h b/drivers/net/intel/e1000/base/e1000_i225.h
index 03e0f4fb89..be3b1b76eb 100644
--- a/drivers/net/intel/e1000/base/e1000_i225.h
+++ b/drivers/net/intel/e1000/base/e1000_i225.h
@@ -5,8 +5,22 @@
 #ifndef _E1000_I225_H_
 #define _E1000_I225_H_
 
+bool e1000_get_flash_presence_i225(struct e1000_hw *hw);
+s32 e1000_update_flash_i225(struct e1000_hw *hw);
+s32 e1000_update_nvm_checksum_i225(struct e1000_hw *hw);
+s32 e1000_validate_nvm_checksum_i225(struct e1000_hw *hw);
+s32 e1000_write_nvm_srwr_i225(struct e1000_hw *hw, u16 offset,
+			      u16 words, u16 *data);
+s32 e1000_read_nvm_srrd_i225(struct e1000_hw *hw, u16 offset,
+			     u16 words, u16 *data);
+s32 e1000_set_flsw_flash_burst_counter_i225(struct e1000_hw *hw,
+					    u32 burst_counter);
+s32 e1000_write_erase_flash_command_i225(struct e1000_hw *hw, u32 opcode,
+					 u32 address);
 s32 e1000_id_led_init_i225(struct e1000_hw *hw);
 s32 e1000_blink_led_i225(struct e1000_hw *hw);
+s32 e1000_acquire_swfw_sync_i225(struct e1000_hw *hw, u16 mask);
+void e1000_release_swfw_sync_i225(struct e1000_hw *hw, u16 mask);
 s32 e1000_init_hw_i225(struct e1000_hw *hw);
 s32 e1000_setup_copper_link_i225(struct e1000_hw *hw);
 s32 e1000_set_d0_lplu_state_i225(struct e1000_hw *hw, bool active);
@@ -19,6 +33,18 @@ s32 e1000_set_d3_lplu_state_i225(struct e1000_hw *hw, bool active);
 					 (ID_LED_DEF1_DEF2 <<  4) | \
 					 (ID_LED_OFF1_ON2))
 
+/* NVM offset defaults for I225 devices */
+#define NVM_INIT_CTRL_2_DEFAULT_I225	0X7243
+#define NVM_INIT_CTRL_4_DEFAULT_I225	0x00C1
+#define NVM_LED_1_CFG_DEFAULT_I225	0x0184
+#define NVM_LED_0_2_CFG_DEFAULT_I225	0x200C
+
+#define E1000_I225_SHADOW_RAM_SIZE		4096
+#define E1000_I225_ERASE_CMD_OPCODE		0x02000000
+#define E1000_I225_WRITE_CMD_OPCODE		0x01000000
+#define E1000_FLSWCTL_DONE			0x40000000
+#define E1000_FLSWCTL_CMDV			0x10000000
+
 /* LED Control */
 #define E1000_GLOBAL_BLINK_MODE	0x00000020 /*Blink at 200 ms on and 200 ms off.*/
 #define E1000_LED1_MODE_MASK	0x00000F00
diff --git a/drivers/net/intel/e1000/base/e1000_nvm.c b/drivers/net/intel/e1000/base/e1000_nvm.c
index 430fecaf6d..aec5e80986 100644
--- a/drivers/net/intel/e1000/base/e1000_nvm.c
+++ b/drivers/net/intel/e1000/base/e1000_nvm.c
@@ -1295,6 +1295,7 @@ void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
 			return;
 		}
 		/* fall through */
+	case e1000_i225:
 	case e1000_i350:
 		hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
 		/* find combo image version */
diff --git a/drivers/net/intel/e1000/base/e1000_phy.c b/drivers/net/intel/e1000/base/e1000_phy.c
index a7e73112e5..6fac341d71 100644
--- a/drivers/net/intel/e1000/base/e1000_phy.c
+++ b/drivers/net/intel/e1000/base/e1000_phy.c
@@ -4171,6 +4171,69 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
 	return ret_val;
 }
 
+/**
+ *  e1000_write_phy_reg_gpy - Write GPY PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Acquires semaphore, if necessary, then writes the data to PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_gpy(struct e1000_hw *hw, u32 offset, u16 data)
+{
+	s32 ret_val;
+	u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT;
+
+	DEBUGFUNC("e1000_write_phy_reg_gpy");
+
+	offset = offset & GPY_REG_MASK;
+
+	if (!dev_addr) {
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val)
+			return ret_val;
+		ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
+		hw->phy.ops.release(hw);
+	} else {
+		ret_val = e1000_write_xmdio_reg(hw, (u16)offset, dev_addr,
+						data);
+	}
+	return ret_val;
+}
+
+/**
+ *  e1000_read_phy_reg_gpy - Read GPY PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: lower half is register offset to read to
+ *     upper half is MMD to use.
+ *  @data: data to read at register offset
+ *
+ *  Acquires semaphore, if necessary, then reads the data in the PHY register
+ *  at the offset.  Release any acquired semaphores before exiting.
+ **/
+s32 e1000_read_phy_reg_gpy(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+	s32 ret_val;
+	u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT;
+
+	DEBUGFUNC("e1000_read_phy_reg_gpy");
+
+	offset = offset & GPY_REG_MASK;
+
+	if (!dev_addr) {
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val)
+			return ret_val;
+		ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
+		hw->phy.ops.release(hw);
+	} else {
+		ret_val = e1000_read_xmdio_reg(hw, (u16)offset, dev_addr,
+					       data);
+	}
+	return ret_val;
+}
+
 /**
  *  e1000_read_phy_reg_mphy - Read mPHY control register
  *  @hw: pointer to the HW structure
diff --git a/drivers/net/intel/e1000/base/e1000_phy.h b/drivers/net/intel/e1000/base/e1000_phy.h
index 87b4d407e5..a7834240e0 100644
--- a/drivers/net/intel/e1000/base/e1000_phy.h
+++ b/drivers/net/intel/e1000/base/e1000_phy.h
@@ -86,6 +86,8 @@ s32  e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw);
 s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 s32  e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data);
 s32  e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_write_phy_reg_gpy(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_read_phy_reg_gpy(struct e1000_hw *hw, u32 offset, u16 *data);
 s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data);
 s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data,
 			     bool line_override);
@@ -131,6 +133,10 @@ s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
 #define E1000_I225_PHPM_ULP		0x0400 /* Ultra Low-Power Mode */
 #define E1000_I225_PHPM_DIS_2500	0x0800 /* Disable 2.5G globally */
 #define E1000_I225_PHPM_DIS_2500_D3	0x1000 /* Disable 2.5G in D3 */
+/* GPY211 - I225 defines */
+#define GPY_MMD_MASK			0xFFFF0000
+#define GPY_MMD_SHIFT			16
+#define GPY_REG_MASK			0x0000FFFF
 /* BM/HV Specific Registers */
 #define BM_PORT_CTRL_PAGE		769
 #define BM_WUC_PAGE			800
diff --git a/drivers/net/intel/e1000/base/e1000_regs.h b/drivers/net/intel/e1000/base/e1000_regs.h
index 20abeeaa46..b9d2a4484b 100644
--- a/drivers/net/intel/e1000/base/e1000_regs.h
+++ b/drivers/net/intel/e1000/base/e1000_regs.h
@@ -10,6 +10,9 @@
 #define E1000_STATUS	0x00008  /* Device Status - RO */
 #define E1000_EECD	0x00010  /* EEPROM/Flash Control - RW */
 #define E1000_EERD	0x00014  /* EEPROM Read - RW */
+#define E1000_EEWR	0x0102C  /* EEPROM Write Register - RW */
+#define E1000_EERD_V2	0x12014  /* EEprom mode read - RW */
+#define E1000_EEWR_V2	0x12018  /* EEprom mode write - RW */
 #define E1000_CTRL_EXT	0x00018  /* Extended Device Control - RW */
 #define E1000_FLA	0x0001C  /* Flash Access - RW */
 #define E1000_MDIC	0x00020  /* MDI Control - RW */
@@ -30,6 +33,11 @@
 #define E1000_FCAL	0x00028  /* Flow Control Address Low - RW */
 #define E1000_FCAH	0x0002C  /* Flow Control Address High -RW */
 #define E1000_FEXT	0x0002C  /* Future Extended - RW */
+#define E1000_I225_FLA		0x1201C /* FLASH access register */
+#define E1000_I225_FLSWCTL	0x12048 /* FLASH control register */
+#define E1000_I225_FLSWDATA	0x1204C /* FLASH data register */
+#define E1000_I225_FLSWCNT	0x12050 /* FLASH Access Counter */
+#define E1000_I225_FLSECU	0x12114 /* FLASH Security */
 #define E1000_FEXTNVM	0x00028  /* Future Extended NVM - RW */
 #define E1000_FEXTNVM3	0x0003C  /* Future Extended NVM 3 - RW */
 #define E1000_FEXTNVM4	0x00024  /* Future Extended NVM 4 - RW */
@@ -90,6 +98,7 @@
 #define E1000_EEMNGCTL_I225	0x01010  /* i225 MNG EEprom Mode Control */
 #define E1000_EEARBC	0x01024  /* EEPROM Auto Read Bus Control */
 #define E1000_EEARBC_I210	0x12024 /* EEPROM Auto Read Bus Control */
+#define E1000_EEARBC_I225	0x12024 /* EEPROM Auto Read Bus Control */
 #define E1000_FLASHT	0x01028  /* FLASH Timer Register */
 #define E1000_EEWR	0x0102C  /* EEPROM Write Register - RW */
 #define E1000_FLSWCTL	0x01030  /* FLASH control register */
-- 
2.43.5


  parent reply	other threads:[~2025-01-31 12:59 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-31 12:58 [PATCH v1 00/42] Merge Intel IGC and E1000 drivers, and update E1000 base code Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 01/42] net/e1000/base: fix semaphore timeout value Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 02/42] net/e1000/base: add initial support for i225 Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 03/42] net/e1000/base: add link bringup " Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 04/42] net/e1000/base: add LED blink " Anatoly Burakov
2025-01-31 12:58 ` Anatoly Burakov [this message]
2025-01-31 12:58 ` [PATCH v1 06/42] net/e1000/base: add LTR support in i225 Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 07/42] net/e1000/base: add eee support for i225 Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 08/42] net/e1000/base: add misc definitions " Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 09/42] net/e1000: merge igc with e1000 Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 10/42] net/e1000: add missing i225 devices Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 11/42] net/e1000: add missing hardware support Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 12/42] net/e1000: add support for more I219 devices Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 13/42] net/e1000/base: correct minor formatting issues Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 14/42] net/e1000/base: correct mPHY access logic Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 15/42] net/e1000/base: skip MANC check for 82575 Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 16/42] net/e1000/base: correct disable k1 logic Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 17/42] net/e1000/base: workaround for packet loss Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 18/42] net/e1000/base: add EEE common API function Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 19/42] net/e1000/base: add queue select definitions Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 20/42] net/e1000/base: add profile information field Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 21/42] net/e1000/base: add LPI counters Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 22/42] net/e1000/base: improve code flow in ICH8LAN Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 23/42] net/e1000/base: add definition for EXFWSM register Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 24/42] net/e1000/base: use longer ULP exit timeout on more HW Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 25/42] net/e1000/base: make e1000_access_phy_wakeup_reg_bm non-static Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 26/42] net/e1000/base: make debug prints more informative Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 27/42] net/e1000/base: add WoL definitions Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 28/42] net/e1000/base: hardcode bus parameters for ICH8 Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 29/42] net/e1000/base: improve NVM checksum handling Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 30/42] net/e1000/base: remove redundant access to RO register Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 31/42] net/e1000/base: remove non-inclusive language Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 32/42] net/e1000/base: introduce PHY ID retry mechanism Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 33/42] net/e1000/base: add PHY read/write " Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 34/42] net/e1000/base: fix iterator type Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 35/42] net/e1000/base: fix static analysis warnings Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 36/42] net/e1000/base: fix reset for 82580 Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 37/42] net/e1000/base: fix mac addr hash bit_shift Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 38/42] net/e1000/base: fix uninitialized variable usage Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 39/42] net/e1000/base: fix unchecked return Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 40/42] net/e1000/base: fix data type in MAC hash Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 41/42] net/e1000/base: rename NVM version variable Anatoly Burakov
2025-01-31 12:58 ` [PATCH v1 42/42] net/e1000/base: update readme Anatoly Burakov
2025-01-31 13:11 ` [PATCH v1 00/42] Merge Intel IGC and E1000 drivers, and update E1000 base code Bruce Richardson
2025-01-31 13:13   ` David Marchand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=26e5f01f2f55270f3ec04dd8f452aae0cadb1462.1738328107.git.anatoly.burakov@intel.com \
    --to=anatoly.burakov@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).