common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / net / e1000.c
index 2d66690226763c4bd6af38752ca09a0866960882..008da4ab3e77361c644d34b192fe1cac187cbc7b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /**************************************************************************
 Intel Pro 1000 for ppcboot/das-u-boot
 Drivers are port from Intel's Linux driver e1000-4.3.15
@@ -9,7 +10,6 @@ tested on both gig copper and gig fiber boards
 
   Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
 
- * SPDX-License-Identifier:    GPL-2.0+
 
   Contact Information:
   Linux NICS <linux.nics@intel.com>
@@ -29,12 +29,29 @@ tested on both gig copper and gig fiber boards
  *  Copyright 2011 Freescale Semiconductor, Inc.
  */
 
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <net.h>
+#include <pci.h>
+#include <linux/delay.h>
 #include "e1000.h"
+#include <asm/cache.h>
 
 #define TOUT_LOOP   100000
 
+#ifdef CONFIG_DM_ETH
+#define virt_to_bus(devno, v)  dm_pci_virt_to_mem(devno, (void *) (v))
+#define bus_to_phys(devno, a)  dm_pci_mem_to_phys(devno, a)
+#else
 #define virt_to_bus(devno, v)  pci_virt_to_mem(devno, (void *) (v))
 #define bus_to_phys(devno, a)  pci_mem_to_phys(devno, a)
+#endif
 
 #define E1000_DEFAULT_PCI_PBA  0x00000030
 #define E1000_DEFAULT_PCIE_PBA 0x000a0026
@@ -44,75 +61,84 @@ tested on both gig copper and gig fiber boards
 /* Intel i210 needs the DMA descriptor rings aligned to 128b */
 #define E1000_BUFFER_ALIGN     128
 
+/*
+ * TODO(sjg@chromium.org): Even with driver model we share these buffers.
+ * Concurrent receiving on multiple active Ethernet devices will not work.
+ * Normally U-Boot does not support this anyway. To fix it in this driver,
+ * move these buffers and the tx/rx pointers to struct e1000_hw.
+ */
 DEFINE_ALIGN_BUFFER(struct e1000_tx_desc, tx_base, 16, E1000_BUFFER_ALIGN);
 DEFINE_ALIGN_BUFFER(struct e1000_rx_desc, rx_base, 16, E1000_BUFFER_ALIGN);
 DEFINE_ALIGN_BUFFER(unsigned char, packet, 4096, E1000_BUFFER_ALIGN);
 
 static int tx_tail;
 static int rx_tail, rx_last;
+#ifdef CONFIG_DM_ETH
+static int num_cards;  /* Number of E1000 devices seen so far */
+#endif
 
 static struct pci_device_id e1000_supported[] = {
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82542},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_FIBER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_FIBER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_LOM},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545GM_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_FIBER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_FIBER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546GB_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM_LOM},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541ER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541GI_LF},
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82542) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_FIBER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_FIBER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_LOM) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545GM_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_FIBER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_FIBER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546GB_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM_LOM) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541ER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541GI_LF) },
        /* E1000 PCIe card */
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_FIBER      },
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_SERDES     },
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_QUAD_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571PT_QUAD_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_QUAD_FIBER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_QUAD_COPPER_LOWPROFILE},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_SERDES_DUAL},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_SERDES_QUAD},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82572EI_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82572EI_FIBER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82572EI_SERDES},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82572EI},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82573E},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82573E_IAMT},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82573L},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82574L},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546GB_QUAD_COPPER_KSP3},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_COPPER_DPT},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_SERDES_DPT},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_COPPER_SPT},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_SERDES_SPT},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_UNPROGRAMMED},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I211_UNPROGRAMMED},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I211_COPPER},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_COPPER_FLASHLESS},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS},
-       {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_1000BASEKX},
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_FIBER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_SERDES) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_QUAD_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571PT_QUAD_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_QUAD_FIBER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_QUAD_COPPER_LOWPROFILE) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_SERDES_DUAL) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82571EB_SERDES_QUAD) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82572EI_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82572EI_FIBER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82572EI_SERDES) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82572EI) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82573E) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82573E_IAMT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82573L) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82574L) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546GB_QUAD_COPPER_KSP3) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_COPPER_DPT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_SERDES_DPT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_COPPER_SPT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80003ES2LAN_SERDES_SPT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_UNPROGRAMMED) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I211_UNPROGRAMMED) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I211_COPPER) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_COPPER_FLASHLESS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_1000BASEKX) },
 
        {}
 };
 
 /* Function forward declarations */
-static int e1000_setup_link(struct eth_device *nic);
-static int e1000_setup_fiber_link(struct eth_device *nic);
-static int e1000_setup_copper_link(struct eth_device *nic);
+static int e1000_setup_link(struct e1000_hw *hw);
+static int e1000_setup_fiber_link(struct e1000_hw *hw);
+static int e1000_setup_copper_link(struct e1000_hw *hw);
 static int e1000_phy_setup_autoneg(struct e1000_hw *hw);
 static void e1000_config_collision_dist(struct e1000_hw *hw);
 static int e1000_config_mac_to_phy(struct e1000_hw *hw);
 static int e1000_config_fc_after_link_up(struct e1000_hw *hw);
-static int e1000_check_for_link(struct eth_device *nic);
+static int e1000_check_for_link(struct e1000_hw *hw);
 static int e1000_wait_autoneg(struct e1000_hw *hw);
 static int e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed,
                                       uint16_t * duplex);
@@ -126,10 +152,12 @@ static int e1000_detect_gig_phy(struct e1000_hw *hw);
 static void e1000_set_media_type(struct e1000_hw *hw);
 
 static int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
+static void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
 static int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
 
 #ifndef CONFIG_E1000_NO_NVM
 static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
+static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
 static int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
                uint16_t words,
                uint16_t *data);
@@ -536,43 +564,6 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw)
                eeprom->use_eerd = true;
                eeprom->use_eewr = false;
                break;
-
-       /* ich8lan does not support currently. if needed, please
-        * add corresponding code and functions.
-        */
-#if 0
-       case e1000_ich8lan:
-               {
-               int32_t  i = 0;
-
-               eeprom->type = e1000_eeprom_ich8;
-               eeprom->use_eerd = false;
-               eeprom->use_eewr = false;
-               eeprom->word_size = E1000_SHADOW_RAM_WORDS;
-               uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw,
-                               ICH_FLASH_GFPREG);
-               /* Zero the shadow RAM structure. But don't load it from NVM
-                * so as to save time for driver init */
-               if (hw->eeprom_shadow_ram != NULL) {
-                       for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
-                               hw->eeprom_shadow_ram[i].modified = false;
-                               hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
-                       }
-               }
-
-               hw->flash_base_addr = (flash_size & ICH_GFPREG_BASE_MASK) *
-                               ICH_FLASH_SECTOR_SIZE;
-
-               hw->flash_bank_size = ((flash_size >> 16)
-                               & ICH_GFPREG_BASE_MASK) + 1;
-               hw->flash_bank_size -= (flash_size & ICH_GFPREG_BASE_MASK);
-
-               hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
-
-               hw->flash_bank_size /= 2 * sizeof(uint16_t);
-               break;
-               }
-#endif
        default:
                break;
        }
@@ -729,7 +720,10 @@ void e1000_release_eeprom(struct e1000_hw *hw)
                eecd &= ~E1000_EECD_REQ;
                E1000_WRITE_REG(hw, EECD, eecd);
        }
+
+       e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
 }
+
 /******************************************************************************
  * Reads a 16 bit word from the EEPROM.
  *
@@ -820,14 +814,6 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
        if (eeprom->use_eerd == true)
                return e1000_read_eeprom_eerd(hw, offset, words, data);
 
-       /* ich8lan does not support currently. if needed, please
-        * add corresponding code and functions.
-        */
-#if 0
-       /* ICH EEPROM access is done via the ICH flash controller */
-       if (eeprom->type == e1000_eeprom_ich8)
-               return e1000_read_eeprom_ich8(hw, offset, words, data);
-#endif
        /* Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
         * acquired the EEPROM at this point, so any returns should relase it */
        if (eeprom->type == e1000_eeprom_spi) {
@@ -883,6 +869,174 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
        return E1000_SUCCESS;
 }
 
+#ifndef CONFIG_DM_ETH
+/******************************************************************************
+ *  e1000_write_eeprom_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_eeprom_checksum_i210 is not called after this function, the
+ *  Shadow Ram will most likely contain an invalid checksum.
+ *****************************************************************************/
+static int32_t e1000_write_eeprom_srwr(struct e1000_hw *hw, uint16_t offset,
+                                      uint16_t words, uint16_t *data)
+{
+       struct e1000_eeprom_info *eeprom = &hw->eeprom;
+       uint32_t i, k, eewr = 0;
+       uint32_t attempts = 100000;
+       int32_t ret_val = 0;
+
+       /* A check for invalid values:  offset too large, too many words,
+        * too many words for the offset, and not enough words.
+        */
+       if ((offset >= eeprom->word_size) ||
+           (words > (eeprom->word_size - offset)) || (words == 0)) {
+               DEBUGOUT("nvm parameter(s) out of bounds\n");
+               ret_val = -E1000_ERR_EEPROM;
+               goto out;
+       }
+
+       for (i = 0; i < words; i++) {
+               eewr = ((offset + i) << E1000_EEPROM_RW_ADDR_SHIFT)
+                               | (data[i] << E1000_EEPROM_RW_REG_DATA) |
+                               E1000_EEPROM_RW_REG_START;
+
+               E1000_WRITE_REG(hw, I210_EEWR, eewr);
+
+               for (k = 0; k < attempts; k++) {
+                       if (E1000_EEPROM_RW_REG_DONE &
+                           E1000_READ_REG(hw, I210_EEWR)) {
+                               ret_val = 0;
+                               break;
+                       }
+                       udelay(5);
+               }
+
+               if (ret_val) {
+                       DEBUGOUT("Shadow RAM write EEWR timed out\n");
+                       break;
+               }
+       }
+
+out:
+       return ret_val;
+}
+
+/******************************************************************************
+ *  e1000_pool_flash_update_done_i210 - Pool FLUDONE status.
+ *  @hw: pointer to the HW structure
+ *
+ *****************************************************************************/
+static int32_t e1000_pool_flash_update_done_i210(struct e1000_hw *hw)
+{
+       int32_t ret_val = -E1000_ERR_EEPROM;
+       uint32_t i, reg;
+
+       for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
+               reg = E1000_READ_REG(hw, EECD);
+               if (reg & E1000_EECD_FLUDONE_I210) {
+                       ret_val = 0;
+                       break;
+               }
+               udelay(5);
+       }
+
+       return ret_val;
+}
+
+/******************************************************************************
+ *  e1000_update_flash_i210 - Commit EEPROM to the flash
+ *  @hw: pointer to the HW structure
+ *
+ *****************************************************************************/
+static int32_t e1000_update_flash_i210(struct e1000_hw *hw)
+{
+       int32_t ret_val = 0;
+       uint32_t flup;
+
+       ret_val = e1000_pool_flash_update_done_i210(hw);
+       if (ret_val == -E1000_ERR_EEPROM) {
+               DEBUGOUT("Flash update time out\n");
+               goto out;
+       }
+
+       flup = E1000_READ_REG(hw, EECD) | E1000_EECD_FLUPD_I210;
+       E1000_WRITE_REG(hw, EECD, flup);
+
+       ret_val = e1000_pool_flash_update_done_i210(hw);
+       if (ret_val)
+               DEBUGOUT("Flash update time out\n");
+       else
+               DEBUGOUT("Flash update complete\n");
+
+out:
+       return ret_val;
+}
+
+/******************************************************************************
+ *  e1000_update_eeprom_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.
+ *****************************************************************************/
+static int32_t e1000_update_eeprom_checksum_i210(struct e1000_hw *hw)
+{
+       int32_t ret_val = 0;
+       uint16_t checksum = 0;
+       uint16_t i, nvm_data;
+
+       /* 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_eeprom_eerd(hw, 0, 1, &nvm_data);
+       if (ret_val) {
+               DEBUGOUT("EEPROM read failed\n");
+               goto out;
+       }
+
+       if (!(e1000_get_hw_eeprom_semaphore(hw))) {
+               /* 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 < EEPROM_CHECKSUM_REG; i++) {
+                       ret_val = e1000_read_eeprom_eerd(hw, i, 1, &nvm_data);
+                       if (ret_val) {
+                               e1000_put_hw_eeprom_semaphore(hw);
+                               DEBUGOUT("EEPROM Read Error while updating checksum.\n");
+                               goto out;
+                       }
+                       checksum += nvm_data;
+               }
+               checksum = (uint16_t)EEPROM_SUM - checksum;
+               ret_val = e1000_write_eeprom_srwr(hw, EEPROM_CHECKSUM_REG, 1,
+                                                 &checksum);
+               if (ret_val) {
+                       e1000_put_hw_eeprom_semaphore(hw);
+                       DEBUGOUT("EEPROM Write Error while updating checksum.\n");
+                       goto out;
+               }
+
+               e1000_put_hw_eeprom_semaphore(hw);
+
+               ret_val = e1000_update_flash_i210(hw);
+       } else {
+               ret_val = -E1000_ERR_SWFW_SYNC;
+       }
+
+out:
+       return ret_val;
+}
+#endif
+
 /******************************************************************************
  * Verifies that the EEPROM has a valid checksum
  *
@@ -901,13 +1055,13 @@ static int e1000_validate_eeprom_checksum(struct e1000_hw *hw)
        /* Allocate a temporary buffer */
        buf = malloc(sizeof(buf[0]) * (EEPROM_CHECKSUM_REG + 1));
        if (!buf) {
-               E1000_ERR(hw->nic, "Unable to allocate EEPROM buffer!\n");
+               E1000_ERR(hw, "Unable to allocate EEPROM buffer!\n");
                return -E1000_ERR_EEPROM;
        }
 
        /* Read the EEPROM */
        if (e1000_read_eeprom(hw, 0, EEPROM_CHECKSUM_REG + 1, buf) < 0) {
-               E1000_ERR(hw->nic, "Unable to read EEPROM!\n");
+               E1000_ERR(hw, "Unable to read EEPROM!\n");
                return -E1000_ERR_EEPROM;
        }
 
@@ -923,9 +1077,9 @@ static int e1000_validate_eeprom_checksum(struct e1000_hw *hw)
                return 0;
 
        /* Hrm, verification failed, print an error */
-       E1000_ERR(hw->nic, "EEPROM checksum is incorrect!\n");
-       E1000_ERR(hw->nic, "  ...register was 0x%04hx, calculated 0x%04hx\n",
-                       checksum_reg, checksum);
+       E1000_ERR(hw, "EEPROM checksum is incorrect!\n");
+       E1000_ERR(hw, "  ...register was 0x%04hx, calculated 0x%04hx\n",
+                 checksum_reg, checksum);
 
        return -E1000_ERR_EEPROM;
 }
@@ -992,11 +1146,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
 
        DEBUGFUNC();
 
-               swsm = E1000_READ_REG(hw, SWSM);
-               swsm &= ~E1000_SWSM_SMBI;
-               E1000_WRITE_REG(hw, SWSM, swsm);
-
-       if (hw->mac_type != e1000_80003es2lan)
+       if (hw->mac_type != e1000_80003es2lan && hw->mac_type != e1000_igb)
                return E1000_SUCCESS;
 
        while (timeout) {
@@ -1038,7 +1188,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
                return;
 
        swsm = E1000_READ_REG(hw, SWSM);
-       if (hw->mac_type == e1000_80003es2lan) {
+       if (hw->mac_type == e1000_80003es2lan || hw->mac_type == e1000_igb) {
                /* Release both semaphores. */
                swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
        } else
@@ -1070,7 +1220,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
        if (!hw->eeprom_semaphore_present)
                return E1000_SUCCESS;
 
-       if (hw->mac_type == e1000_80003es2lan) {
+       if (hw->mac_type == e1000_80003es2lan || hw->mac_type == e1000_igb) {
                /* Get the SW semaphore. */
                if (e1000_get_software_semaphore(hw) != E1000_SUCCESS)
                        return -E1000_ERR_EEPROM;
@@ -1102,6 +1252,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
        return E1000_SUCCESS;
 }
 
+/* Take ownership of the PHY */
 static int32_t
 e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
 {
@@ -1115,10 +1266,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
                if (e1000_get_hw_eeprom_semaphore(hw))
                        return -E1000_ERR_SWFW_SYNC;
 
-               if (hw->mac_type == e1000_igb)
-                       swfw_sync = E1000_READ_REG(hw, I210_SW_FW_SYNC);
-               else
-                       swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+               swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
                if (!(swfw_sync & (fwmask | swmask)))
                        break;
 
@@ -1141,6 +1289,21 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
        return E1000_SUCCESS;
 }
 
+static void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
+{
+       uint32_t swfw_sync = 0;
+
+       DEBUGFUNC();
+       while (e1000_get_hw_eeprom_semaphore(hw))
+               ; /* Empty */
+
+       swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+       swfw_sync &= ~mask;
+       E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+
+       e1000_put_hw_eeprom_semaphore(hw);
+}
+
 static bool e1000_is_second_port(struct e1000_hw *hw)
 {
        switch (hw->mac_type) {
@@ -1157,52 +1320,89 @@ static bool e1000_is_second_port(struct e1000_hw *hw)
 
 #ifndef CONFIG_E1000_NO_NVM
 /******************************************************************************
- * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
- * second function of dual function devices
+ * Reads the adapter's MAC address from the EEPROM
  *
- * nic - Struct containing variables accessed by shared code
+ * hw - Struct containing variables accessed by shared code
+ * enetaddr - buffering where the MAC address will be stored
  *****************************************************************************/
-static int
-e1000_read_mac_addr(struct eth_device *nic)
+static int e1000_read_mac_addr_from_eeprom(struct e1000_hw *hw,
+                                          unsigned char enetaddr[6])
 {
-       struct e1000_hw *hw = nic->priv;
        uint16_t offset;
        uint16_t eeprom_data;
-       uint32_t reg_data = 0;
        int i;
 
-       DEBUGFUNC();
-
        for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
                offset = i >> 1;
-               if (hw->mac_type == e1000_igb) {
-                       /* i210 preloads MAC address into RAL/RAH registers */
-                       if (offset == 0)
-                               reg_data = E1000_READ_REG_ARRAY(hw, RA, 0);
-                       else if (offset == 1)
-                               reg_data >>= 16;
-                       else if (offset == 2)
-                               reg_data = E1000_READ_REG_ARRAY(hw, RA, 1);
-                       eeprom_data = reg_data & 0xffff;
-               } else if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
+               if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
                        DEBUGOUT("EEPROM Read Error\n");
                        return -E1000_ERR_EEPROM;
                }
-               nic->enetaddr[i] = eeprom_data & 0xff;
-               nic->enetaddr[i + 1] = (eeprom_data >> 8) & 0xff;
+               enetaddr[i] = eeprom_data & 0xff;
+               enetaddr[i + 1] = (eeprom_data >> 8) & 0xff;
        }
 
-       /* Invert the last bit if this is the second device */
-       if (e1000_is_second_port(hw))
-               nic->enetaddr[5] ^= 1;
+       return 0;
+}
 
-#ifdef CONFIG_E1000_FALLBACK_MAC
-       if (!is_valid_ethaddr(nic->enetaddr)) {
-               unsigned char fb_mac[NODE_ADDRESS_SIZE] = CONFIG_E1000_FALLBACK_MAC;
+/******************************************************************************
+ * Reads the adapter's MAC address from the RAL/RAH registers
+ *
+ * hw - Struct containing variables accessed by shared code
+ * enetaddr - buffering where the MAC address will be stored
+ *****************************************************************************/
+static int e1000_read_mac_addr_from_regs(struct e1000_hw *hw,
+                                        unsigned char enetaddr[6])
+{
+       uint16_t offset, tmp;
+       uint32_t reg_data = 0;
+       int i;
+
+       if (hw->mac_type != e1000_igb)
+               return -E1000_ERR_MAC_TYPE;
+
+       for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
+               offset = i >> 1;
 
-               memcpy (nic->enetaddr, fb_mac, NODE_ADDRESS_SIZE);
+               if (offset == 0)
+                       reg_data = E1000_READ_REG_ARRAY(hw, RA, 0);
+               else if (offset == 1)
+                       reg_data >>= 16;
+               else if (offset == 2)
+                       reg_data = E1000_READ_REG_ARRAY(hw, RA, 1);
+               tmp = reg_data & 0xffff;
+
+               enetaddr[i] = tmp & 0xff;
+               enetaddr[i + 1] = (tmp >> 8) & 0xff;
        }
-#endif
+
+       return 0;
+}
+
+/******************************************************************************
+ * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
+ * second function of dual function devices
+ *
+ * hw - Struct containing variables accessed by shared code
+ * enetaddr - buffering where the MAC address will be stored
+ *****************************************************************************/
+static int e1000_read_mac_addr(struct e1000_hw *hw, unsigned char enetaddr[6])
+{
+       int ret_val;
+
+       if (hw->mac_type == e1000_igb) {
+               /* i210 preloads MAC address into RAL/RAH registers */
+               ret_val = e1000_read_mac_addr_from_regs(hw, enetaddr);
+       } else {
+               ret_val = e1000_read_mac_addr_from_eeprom(hw, enetaddr);
+       }
+       if (ret_val)
+               return ret_val;
+
+       /* Invert the last bit if this is the second device */
+       if (e1000_is_second_port(hw))
+               enetaddr[5] ^= 1;
+
        return 0;
 }
 #endif
@@ -1217,9 +1417,8 @@ e1000_read_mac_addr(struct eth_device *nic)
  * the receiver is in reset when the routine is called.
  *****************************************************************************/
 static void
-e1000_init_rx_addrs(struct eth_device *nic)
+e1000_init_rx_addrs(struct e1000_hw *hw, unsigned char enetaddr[6])
 {
-       struct e1000_hw *hw = nic->priv;
        uint32_t i;
        uint32_t addr_low;
        uint32_t addr_high;
@@ -1228,11 +1427,11 @@ e1000_init_rx_addrs(struct eth_device *nic)
 
        /* Setup the receive address. */
        DEBUGOUT("Programming MAC Address into RAR[0]\n");
-       addr_low = (nic->enetaddr[0] |
-                   (nic->enetaddr[1] << 8) |
-                   (nic->enetaddr[2] << 16) | (nic->enetaddr[3] << 24));
+       addr_low = (enetaddr[0] |
+                   (enetaddr[1] << 8) |
+                   (enetaddr[2] << 16) | (enetaddr[3] << 24));
 
-       addr_high = (nic->enetaddr[4] | (nic->enetaddr[5] << 8) | E1000_RAH_AV);
+       addr_high = (enetaddr[4] | (enetaddr[5] << 8) | E1000_RAH_AV);
 
        E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low);
        E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high);
@@ -1422,8 +1621,13 @@ e1000_reset_hw(struct e1000_hw *hw)
        /* For 82542 (rev 2.0), disable MWI before issuing a device reset */
        if (hw->mac_type == e1000_82542_rev2_0) {
                DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+#ifdef CONFIG_DM_ETH
+               dm_pci_write_config16(hw->pdev, PCI_COMMAND,
+                               hw->pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
+#else
                pci_write_config_word(hw->pdev, PCI_COMMAND,
                                hw->pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
+#endif
        }
 
        /* Clear interrupt mask to stop board from generating interrupts */
@@ -1496,7 +1700,11 @@ e1000_reset_hw(struct e1000_hw *hw)
 
        /* If MWI was previously enabled, reenable it. */
        if (hw->mac_type == e1000_82542_rev2_0) {
+#ifdef CONFIG_DM_ETH
+               dm_pci_write_config16(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
+#else
                pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
+#endif
        }
        if (hw->mac_type != e1000_igb)
                E1000_WRITE_REG(hw, PBA, pba);
@@ -1535,11 +1743,10 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
                reg_txdctl1 |= E1000_TXDCTL_COUNT_DESC;
                E1000_WRITE_REG(hw, TXDCTL1, reg_txdctl1);
 
-       /* IGB is cool */
-       if (hw->mac_type == e1000_igb)
-               return;
 
                switch (hw->mac_type) {
+               case e1000_igb:                 /* IGB is cool */
+                       return;
                case e1000_82571:
                case e1000_82572:
                        /* Clear PHY TX compatible mode bits */
@@ -1639,9 +1846,8 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
  * the transmit and receive units disabled and uninitialized.
  *****************************************************************************/
 static int
-e1000_init_hw(struct eth_device *nic)
+e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
 {
-       struct e1000_hw *hw = nic->priv;
        uint32_t ctrl;
        uint32_t i;
        int32_t ret_val;
@@ -1683,9 +1889,15 @@ e1000_init_hw(struct eth_device *nic)
        /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
        if (hw->mac_type == e1000_82542_rev2_0) {
                DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+#ifdef CONFIG_DM_ETH
+               dm_pci_write_config16(hw->pdev, PCI_COMMAND,
+                                     hw->
+                                     pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
+#else
                pci_write_config_word(hw->pdev, PCI_COMMAND,
                                      hw->
                                      pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
+#endif
                E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
                E1000_WRITE_FLUSH(hw);
                mdelay(5);
@@ -1694,14 +1906,18 @@ e1000_init_hw(struct eth_device *nic)
        /* Setup the receive address. This involves initializing all of the Receive
         * Address Registers (RARs 0 - 15).
         */
-       e1000_init_rx_addrs(nic);
+       e1000_init_rx_addrs(hw, enetaddr);
 
        /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
        if (hw->mac_type == e1000_82542_rev2_0) {
                E1000_WRITE_REG(hw, RCTL, 0);
                E1000_WRITE_FLUSH(hw);
                mdelay(1);
+#ifdef CONFIG_DM_ETH
+               dm_pci_write_config16(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
+#else
                pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
+#endif
        }
 
        /* Zero out the Multicast HASH table */
@@ -1715,17 +1931,7 @@ e1000_init_hw(struct eth_device *nic)
                 * occuring when accessing our register space */
                E1000_WRITE_FLUSH(hw);
        }
-#if 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.  Valid only on
-        * 82542 and 82543 silicon.
-        */
-       if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
-               ctrl = E1000_READ_REG(hw, CTRL);
-               E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
-       }
-#endif
+
        switch (hw->mac_type) {
        case e1000_82545_rev_3:
        case e1000_82546_rev_3:
@@ -1734,10 +1940,17 @@ e1000_init_hw(struct eth_device *nic)
        default:
        /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
        if (hw->bus_type == e1000_bus_type_pcix) {
+#ifdef CONFIG_DM_ETH
+               dm_pci_read_config16(hw->pdev, PCIX_COMMAND_REGISTER,
+                                    &pcix_cmd_word);
+               dm_pci_read_config16(hw->pdev, PCIX_STATUS_REGISTER_HI,
+                                    &pcix_stat_hi_word);
+#else
                pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER,
                                     &pcix_cmd_word);
                pci_read_config_word(hw->pdev, PCIX_STATUS_REGISTER_HI,
                                     &pcix_stat_hi_word);
+#endif
                cmd_mmrbc =
                    (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >>
                    PCIX_COMMAND_MMRBC_SHIFT;
@@ -1749,8 +1962,13 @@ e1000_init_hw(struct eth_device *nic)
                if (cmd_mmrbc > stat_mmrbc) {
                        pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK;
                        pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
+#ifdef CONFIG_DM_ETH
+                       dm_pci_write_config16(hw->pdev, PCIX_COMMAND_REGISTER,
+                                             pcix_cmd_word);
+#else
                        pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER,
                                              pcix_cmd_word);
+#endif
                }
        }
                break;
@@ -1763,7 +1981,7 @@ e1000_init_hw(struct eth_device *nic)
                mdelay(15);
 
        /* Call a subroutine to configure the link and setup flow control. */
-       ret_val = e1000_setup_link(nic);
+       ret_val = e1000_setup_link(hw);
 
        /* Set the transmit descriptor write-back policy */
        if (hw->mac_type > e1000_82544) {
@@ -1825,20 +2043,6 @@ e1000_init_hw(struct eth_device *nic)
                break;
        }
 
-#if 0
-       /* 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.
-        */
-       e1000_clear_hw_cntrs(hw);
-
-       /* ICH8 No-snoop bits are opposite polarity.
-        * Set to snoop by default after reset. */
-       if (hw->mac_type == e1000_ich8lan)
-               e1000_set_pci_ex_no_snoop(hw, PCI_EX_82566_SNOOP_ALL);
-#endif
-
        if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
                hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
                ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
@@ -1863,9 +2067,8 @@ e1000_init_hw(struct eth_device *nic)
  * transmitter and receiver are not enabled.
  *****************************************************************************/
 static int
-e1000_setup_link(struct eth_device *nic)
+e1000_setup_link(struct e1000_hw *hw)
 {
-       struct e1000_hw *hw = nic->priv;
        int32_t ret_val;
 #ifndef CONFIG_E1000_NO_NVM
        uint32_t ctrl_ext;
@@ -1953,7 +2156,7 @@ e1000_setup_link(struct eth_device *nic)
 
        /* Call the necessary subroutine to configure the link. */
        ret_val = (hw->media_type == e1000_media_type_fiber) ?
-           e1000_setup_fiber_link(nic) : e1000_setup_copper_link(nic);
+           e1000_setup_fiber_link(hw) : e1000_setup_copper_link(hw);
        if (ret_val < 0) {
                return ret_val;
        }
@@ -2010,9 +2213,8 @@ e1000_setup_link(struct eth_device *nic)
  * and receiver are not enabled.
  *****************************************************************************/
 static int
-e1000_setup_fiber_link(struct eth_device *nic)
+e1000_setup_fiber_link(struct e1000_hw *hw)
 {
-       struct e1000_hw *hw = nic->priv;
        uint32_t ctrl;
        uint32_t status;
        uint32_t txcw = 0;
@@ -2031,7 +2233,7 @@ e1000_setup_fiber_link(struct eth_device *nic)
        else
                signal = 0;
 
-       printf("signal for %s is %x (ctrl %08x)!!!!\n", nic->name, signal,
+       printf("signal for %s is %x (ctrl %08x)!!!!\n", hw->name, signal,
               ctrl);
        /* Take the link out of reset */
        ctrl &= ~(E1000_CTRL_LRST);
@@ -2119,7 +2321,7 @@ e1000_setup_fiber_link(struct eth_device *nic)
                         */
                        DEBUGOUT("Never got a valid link from auto-neg!!!\n");
                        hw->autoneg_failed = 1;
-                       ret_val = e1000_check_for_link(nic);
+                       ret_val = e1000_check_for_link(hw);
                        if (ret_val < 0) {
                                DEBUGOUT("Error while checking for link\n");
                                return ret_val;
@@ -2174,7 +2376,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
                DEBUGOUT("Error, did not detect valid phy.\n");
                return ret_val;
        }
-       DEBUGOUT("Phy ID = %x \n", hw->phy_id);
+       DEBUGOUT("Phy ID = %x\n", hw->phy_id);
 
        /* Set PHY to class A mode (if necessary) */
        ret_val = e1000_set_phy_mode(hw);
@@ -3036,9 +3238,8 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
 static int
-e1000_setup_copper_link(struct eth_device *nic)
+e1000_setup_copper_link(struct e1000_hw *hw)
 {
-       struct e1000_hw *hw = nic->priv;
        int32_t ret_val;
        uint16_t i;
        uint16_t phy_data;
@@ -3485,11 +3686,11 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                 * some "sticky" (latched) bits.
                 */
                if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
-                       DEBUGOUT("PHY Read Error \n");
+                       DEBUGOUT("PHY Read Error\n");
                        return -E1000_ERR_PHY;
                }
                if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
-                       DEBUGOUT("PHY Read Error \n");
+                       DEBUGOUT("PHY Read Error\n");
                        return -E1000_ERR_PHY;
                }
 
@@ -3661,9 +3862,8 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
  * Called by any function that needs to check the link status of the adapter.
  *****************************************************************************/
 static int
-e1000_check_for_link(struct eth_device *nic)
+e1000_check_for_link(struct e1000_hw *hw)
 {
-       struct e1000_hw *hw = nic->priv;
        uint32_t rxcw;
        uint32_t ctrl;
        uint32_t status;
@@ -4004,7 +4204,7 @@ e1000_wait_autoneg(struct e1000_hw *hw)
        DEBUGFUNC();
        DEBUGOUT("Waiting for Auto-Neg to complete.\n");
 
-       /* We will wait for autoneg to complete or 4.5 seconds to expire. */
+       /* We will wait for autoneg to complete or timeout to expire. */
        for (i = PHY_AUTO_NEG_TIME; i > 0; i--) {
                /* Read the MII Status Register and wait for Auto-Neg
                 * Complete bit to be set.
@@ -4438,6 +4638,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
 
                if (hw->mac_type >= e1000_82571)
                        mdelay(10);
+
        } else {
                /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
                 * bit to put the PHY into reset. Then, take it out of reset.
@@ -4462,6 +4663,8 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
                E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
        }
 
+       e1000_swfw_sync_release(hw, swfw);
+
        /* Wait for FW to finish PHY configuration. */
        ret_val = e1000_get_phy_cfg_done(hw);
        if (ret_val != E1000_SUCCESS)
@@ -4857,12 +5060,21 @@ e1000_set_media_type(struct e1000_hw *hw)
  **/
 
 static int
-e1000_sw_init(struct eth_device *nic)
+e1000_sw_init(struct e1000_hw *hw)
 {
-       struct e1000_hw *hw = (typeof(hw)) nic->priv;
        int result;
 
        /* PCI config space info */
+#ifdef CONFIG_DM_ETH
+       dm_pci_read_config16(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id);
+       dm_pci_read_config16(hw->pdev, PCI_DEVICE_ID, &hw->device_id);
+       dm_pci_read_config16(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID,
+                            &hw->subsystem_vendor_id);
+       dm_pci_read_config16(hw->pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id);
+
+       dm_pci_read_config8(hw->pdev, PCI_REVISION_ID, &hw->revision_id);
+       dm_pci_read_config16(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word);
+#else
        pci_read_config_word(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id);
        pci_read_config_word(hw->pdev, PCI_DEVICE_ID, &hw->device_id);
        pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID,
@@ -4871,11 +5083,12 @@ e1000_sw_init(struct eth_device *nic)
 
        pci_read_config_byte(hw->pdev, PCI_REVISION_ID, &hw->revision_id);
        pci_read_config_word(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word);
+#endif
 
        /* identify the MAC */
        result = e1000_set_mac_type(hw);
        if (result) {
-               E1000_ERR(hw->nic, "Unknown MAC Type\n");
+               E1000_ERR(hw, "Unknown MAC Type\n");
                return result;
        }
 
@@ -4964,8 +5177,8 @@ e1000_configure_tx(struct e1000_hw *hw)
        unsigned long tipg, tarc;
        uint32_t ipgr1, ipgr2;
 
-       E1000_WRITE_REG(hw, TDBAL, (unsigned long)tx_base);
-       E1000_WRITE_REG(hw, TDBAH, 0);
+       E1000_WRITE_REG(hw, TDBAL, lower_32_bits((unsigned long)tx_base));
+       E1000_WRITE_REG(hw, TDBAH, upper_32_bits((unsigned long)tx_base));
 
        E1000_WRITE_REG(hw, TDLEN, 128);
 
@@ -5089,6 +5302,7 @@ e1000_configure_rx(struct e1000_hw *hw)
 {
        unsigned long rctl, ctrl_ext;
        rx_tail = 0;
+
        /* make sure receives are disabled while setting up the descriptors */
        rctl = E1000_READ_REG(hw, RCTL);
        E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
@@ -5108,8 +5322,8 @@ e1000_configure_rx(struct e1000_hw *hw)
                E1000_WRITE_FLUSH(hw);
        }
        /* Setup the Base and Length of the Rx Descriptor Ring */
-       E1000_WRITE_REG(hw, RDBAL, (unsigned long)rx_base);
-       E1000_WRITE_REG(hw, RDBAH, 0);
+       E1000_WRITE_REG(hw, RDBAL, lower_32_bits((unsigned long)rx_base));
+       E1000_WRITE_REG(hw, RDBAH, upper_32_bits((unsigned long)rx_base));
 
        E1000_WRITE_REG(hw, RDLEN, 128);
 
@@ -5135,9 +5349,8 @@ e1000_configure_rx(struct e1000_hw *hw)
 POLL - Wait for a frame
 ***************************************************************************/
 static int
-e1000_poll(struct eth_device *nic)
+_e1000_poll(struct e1000_hw *hw)
 {
-       struct e1000_hw *hw = nic->priv;
        struct e1000_rx_desc *rd;
        unsigned long inval_start, inval_end;
        uint32_t len;
@@ -5150,26 +5363,20 @@ e1000_poll(struct eth_device *nic)
        inval_end = inval_start + roundup(sizeof(*rd), ARCH_DMA_MINALIGN);
        invalidate_dcache_range(inval_start, inval_end);
 
-       if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD)
+       if (!(rd->status & E1000_RXD_STAT_DD))
                return 0;
-       /*DEBUGOUT("recv: packet len=%d \n", rd->length); */
+       /* DEBUGOUT("recv: packet len=%d\n", rd->length); */
        /* Packet received, make sure the data are re-loaded from RAM. */
-       len = le32_to_cpu(rd->length);
+       len = le16_to_cpu(rd->length);
        invalidate_dcache_range((unsigned long)packet,
                                (unsigned long)packet +
                                roundup(len, ARCH_DMA_MINALIGN));
-       net_process_received_packet((uchar *)packet, len);
-       fill_rx(hw);
-       return 1;
+       return len;
 }
 
-/**************************************************************************
-TRANSMIT - Transmit a frame
-***************************************************************************/
-static int e1000_transmit(struct eth_device *nic, void *txpacket, int length)
+static int _e1000_transmit(struct e1000_hw *hw, void *txpacket, int length)
 {
        void *nv_packet = (void *)txpacket;
-       struct e1000_hw *hw = nic->priv;
        struct e1000_tx_desc *txp;
        int i = 0;
        unsigned long flush_start, flush_end;
@@ -5206,27 +5413,9 @@ static int e1000_transmit(struct eth_device *nic, void *txpacket, int length)
        return 1;
 }
 
-/*reset function*/
-static inline int
-e1000_reset(struct eth_device *nic)
-{
-       struct e1000_hw *hw = nic->priv;
-
-       e1000_reset_hw(hw);
-       if (hw->mac_type >= e1000_82544) {
-               E1000_WRITE_REG(hw, WUC, 0);
-       }
-       return e1000_init_hw(nic);
-}
-
-/**************************************************************************
-DISABLE - Turn off ethernet interface
-***************************************************************************/
 static void
-e1000_disable(struct eth_device *nic)
+_e1000_disable(struct e1000_hw *hw)
 {
-       struct e1000_hw *hw = nic->priv;
-
        /* Turn off the ethernet interface */
        E1000_WRITE_REG(hw, RCTL, 0);
        E1000_WRITE_REG(hw, TCTL, 0);
@@ -5239,37 +5428,39 @@ e1000_disable(struct eth_device *nic)
        E1000_WRITE_REG(hw, RDH, 0);
        E1000_WRITE_REG(hw, RDT, 0);
 
-       /* put the card in its initial state */
-#if 0
-       E1000_WRITE_REG(hw, CTRL, E1000_CTRL_RST);
-#endif
        mdelay(10);
+}
 
+/*reset function*/
+static inline int
+e1000_reset(struct e1000_hw *hw, unsigned char enetaddr[6])
+{
+       e1000_reset_hw(hw);
+       if (hw->mac_type >= e1000_82544)
+               E1000_WRITE_REG(hw, WUC, 0);
+
+       return e1000_init_hw(hw, enetaddr);
 }
 
-/**************************************************************************
-INIT - set up ethernet interface(s)
-***************************************************************************/
 static int
-e1000_init(struct eth_device *nic, bd_t * bis)
+_e1000_init(struct e1000_hw *hw, unsigned char enetaddr[6])
 {
-       struct e1000_hw *hw = nic->priv;
        int ret_val = 0;
 
-       ret_val = e1000_reset(nic);
+       ret_val = e1000_reset(hw, enetaddr);
        if (ret_val < 0) {
                if ((ret_val == -E1000_ERR_NOLINK) ||
                    (ret_val == -E1000_ERR_TIMEOUT)) {
-                       E1000_ERR(hw->nic, "Valid Link not detected\n");
+                       E1000_ERR(hw, "Valid Link not detected: %d\n", ret_val);
                } else {
-                       E1000_ERR(hw->nic, "Hardware Initialization Failed\n");
+                       E1000_ERR(hw, "Hardware Initialization Failed\n");
                }
-               return 0;
+               return ret_val;
        }
        e1000_configure_tx(hw);
        e1000_setup_rctl(hw);
        e1000_configure_rx(hw);
-       return 1;
+       return 0;
 }
 
 /******************************************************************************
@@ -5303,8 +5494,206 @@ void e1000_get_bus_type(struct e1000_hw *hw)
        }
 }
 
+#ifndef CONFIG_DM_ETH
 /* A list of all registered e1000 devices */
 static LIST_HEAD(e1000_hw_list);
+#endif
+
+#ifdef CONFIG_DM_ETH
+static int e1000_init_one(struct e1000_hw *hw, int cardnum,
+                         struct udevice *devno, unsigned char enetaddr[6])
+#else
+static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno,
+                         unsigned char enetaddr[6])
+#endif
+{
+       u32 val;
+
+       /* Assign the passed-in values */
+#ifdef CONFIG_DM_ETH
+       hw->pdev = devno;
+#else
+       hw->pdev = devno;
+#endif
+       hw->cardnum = cardnum;
+
+       /* Print a debug message with the IO base address */
+#ifdef CONFIG_DM_ETH
+       dm_pci_read_config32(devno, PCI_BASE_ADDRESS_0, &val);
+#else
+       pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &val);
+#endif
+       E1000_DBG(hw, "iobase 0x%08x\n", val & 0xfffffff0);
+
+       /* Try to enable I/O accesses and bus-mastering */
+       val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+#ifdef CONFIG_DM_ETH
+       dm_pci_write_config32(devno, PCI_COMMAND, val);
+#else
+       pci_write_config_dword(devno, PCI_COMMAND, val);
+#endif
+
+       /* Make sure it worked */
+#ifdef CONFIG_DM_ETH
+       dm_pci_read_config32(devno, PCI_COMMAND, &val);
+#else
+       pci_read_config_dword(devno, PCI_COMMAND, &val);
+#endif
+       if (!(val & PCI_COMMAND_MEMORY)) {
+               E1000_ERR(hw, "Can't enable I/O memory\n");
+               return -ENOSPC;
+       }
+       if (!(val & PCI_COMMAND_MASTER)) {
+               E1000_ERR(hw, "Can't enable bus-mastering\n");
+               return -EPERM;
+       }
+
+       /* Are these variables needed? */
+       hw->fc = e1000_fc_default;
+       hw->original_fc = e1000_fc_default;
+       hw->autoneg_failed = 0;
+       hw->autoneg = 1;
+       hw->get_link_status = true;
+#ifndef CONFIG_E1000_NO_NVM
+       hw->eeprom_semaphore_present = true;
+#endif
+#ifdef CONFIG_DM_ETH
+       hw->hw_addr = dm_pci_map_bar(devno,     PCI_BASE_ADDRESS_0,
+                                               PCI_REGION_MEM);
+#else
+       hw->hw_addr = pci_map_bar(devno,        PCI_BASE_ADDRESS_0,
+                                               PCI_REGION_MEM);
+#endif
+       hw->mac_type = e1000_undefined;
+
+       /* MAC and Phy settings */
+       if (e1000_sw_init(hw) < 0) {
+               E1000_ERR(hw, "Software init failed\n");
+               return -EIO;
+       }
+       if (e1000_check_phy_reset_block(hw))
+               E1000_ERR(hw, "PHY Reset is blocked!\n");
+
+       /* Basic init was OK, reset the hardware and allow SPI access */
+       e1000_reset_hw(hw);
+
+#ifndef CONFIG_E1000_NO_NVM
+       /* Validate the EEPROM and get chipset information */
+       if (e1000_init_eeprom_params(hw)) {
+               E1000_ERR(hw, "EEPROM is invalid!\n");
+               return -EINVAL;
+       }
+       if ((E1000_READ_REG(hw, I210_EECD) & E1000_EECD_FLUPD) &&
+           e1000_validate_eeprom_checksum(hw))
+               return -ENXIO;
+       e1000_read_mac_addr(hw, enetaddr);
+#endif
+       e1000_get_bus_type(hw);
+
+#ifndef CONFIG_E1000_NO_NVM
+       printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n       ",
+              enetaddr[0], enetaddr[1], enetaddr[2],
+              enetaddr[3], enetaddr[4], enetaddr[5]);
+#else
+       memset(enetaddr, 0, 6);
+       printf("e1000: no NVM\n");
+#endif
+
+       return 0;
+}
+
+/* Put the name of a device in a string */
+static void e1000_name(char *str, int cardnum)
+{
+       sprintf(str, "e1000#%u", cardnum);
+}
+
+#ifndef CONFIG_DM_ETH
+/**************************************************************************
+TRANSMIT - Transmit a frame
+***************************************************************************/
+static int e1000_transmit(struct eth_device *nic, void *txpacket, int length)
+{
+       struct e1000_hw *hw = nic->priv;
+
+       return _e1000_transmit(hw, txpacket, length);
+}
+
+/**************************************************************************
+DISABLE - Turn off ethernet interface
+***************************************************************************/
+static void
+e1000_disable(struct eth_device *nic)
+{
+       struct e1000_hw *hw = nic->priv;
+
+       _e1000_disable(hw);
+}
+
+/**************************************************************************
+INIT - set up ethernet interface(s)
+***************************************************************************/
+static int
+e1000_init(struct eth_device *nic, bd_t *bis)
+{
+       struct e1000_hw *hw = nic->priv;
+
+       return _e1000_init(hw, nic->enetaddr);
+}
+
+static int
+e1000_poll(struct eth_device *nic)
+{
+       struct e1000_hw *hw = nic->priv;
+       int len;
+
+       len = _e1000_poll(hw);
+       if (len) {
+               net_process_received_packet((uchar *)packet, len);
+               fill_rx(hw);
+       }
+
+       return len ? 1 : 0;
+}
+
+static int e1000_write_hwaddr(struct eth_device *dev)
+{
+#ifndef CONFIG_E1000_NO_NVM
+       unsigned char *mac = dev->enetaddr;
+       unsigned char current_mac[6];
+       struct e1000_hw *hw = dev->priv;
+       uint16_t data[3];
+       int ret_val, i;
+
+       DEBUGOUT("%s: mac=%pM\n", __func__, mac);
+
+       memset(current_mac, 0, 6);
+
+       /* Read from EEPROM, not from registers, to make sure
+        * the address is persistently configured
+        */
+       ret_val = e1000_read_mac_addr_from_eeprom(hw, current_mac);
+       DEBUGOUT("%s: current mac=%pM\n", __func__, current_mac);
+
+       /* Only write to EEPROM if the given address is different or
+        * reading the current address failed
+        */
+       if (!ret_val && memcmp(current_mac, mac, 6) == 0)
+               return 0;
+
+       for (i = 0; i < 3; ++i)
+               data[i] = mac[i * 2 + 1] << 8 | mac[i * 2];
+
+       ret_val = e1000_write_eeprom_srwr(hw, 0x0, 3, data);
+
+       if (!ret_val)
+               ret_val = e1000_update_eeprom_checksum_i210(hw);
+
+       return ret_val;
+#else
+       return 0;
+#endif
+}
 
 /**************************************************************************
 PROBE - Look for an adapter, this routine's visible to the outside
@@ -5315,16 +5704,15 @@ e1000_initialize(bd_t * bis)
 {
        unsigned int i;
        pci_dev_t devno;
+       int ret;
 
        DEBUGFUNC();
 
        /* Find and probe all the matching PCI devices */
        for (i = 0; (devno = pci_find_devices(e1000_supported, i)) >= 0; i++) {
-               u32 val;
-
                /*
                 * These will never get freed due to errors, this allows us to
-                * perform SPI EEPROM programming from U-boot, for example.
+                * perform SPI EEPROM programming from U-Boot, for example.
                 */
                struct eth_device *nic = malloc(sizeof(*nic));
                struct e1000_hw *hw = malloc(sizeof(*hw));
@@ -5338,89 +5726,25 @@ e1000_initialize(bd_t * bis)
                /* Make sure all of the fields are initially zeroed */
                memset(nic, 0, sizeof(*nic));
                memset(hw, 0, sizeof(*hw));
-
-               /* Assign the passed-in values */
-               hw->cardnum = i;
-               hw->pdev = devno;
-               hw->nic = nic;
                nic->priv = hw;
 
                /* Generate a card name */
-               sprintf(nic->name, "e1000#%u", hw->cardnum);
-
-               /* Print a debug message with the IO base address */
-               pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &val);
-               E1000_DBG(nic, "iobase 0x%08x\n", val & 0xfffffff0);
-
-               /* Try to enable I/O accesses and bus-mastering */
-               val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-               pci_write_config_dword(devno, PCI_COMMAND, val);
+               e1000_name(nic->name, i);
+               hw->name = nic->name;
 
-               /* Make sure it worked */
-               pci_read_config_dword(devno, PCI_COMMAND, &val);
-               if (!(val & PCI_COMMAND_MEMORY)) {
-                       E1000_ERR(nic, "Can't enable I/O memory\n");
+               ret = e1000_init_one(hw, i, devno, nic->enetaddr);
+               if (ret)
                        continue;
-               }
-               if (!(val & PCI_COMMAND_MASTER)) {
-                       E1000_ERR(nic, "Can't enable bus-mastering\n");
-                       continue;
-               }
-
-               /* Are these variables needed? */
-               hw->fc = e1000_fc_default;
-               hw->original_fc = e1000_fc_default;
-               hw->autoneg_failed = 0;
-               hw->autoneg = 1;
-               hw->get_link_status = true;
-#ifndef CONFIG_E1000_NO_NVM
-               hw->eeprom_semaphore_present = true;
-#endif
-               hw->hw_addr = pci_map_bar(devno,        PCI_BASE_ADDRESS_0,
-                                                       PCI_REGION_MEM);
-               hw->mac_type = e1000_undefined;
-
-               /* MAC and Phy settings */
-               if (e1000_sw_init(nic) < 0) {
-                       E1000_ERR(nic, "Software init failed\n");
-                       continue;
-               }
-               if (e1000_check_phy_reset_block(hw))
-                       E1000_ERR(nic, "PHY Reset is blocked!\n");
-
-               /* Basic init was OK, reset the hardware and allow SPI access */
-               e1000_reset_hw(hw);
                list_add_tail(&hw->list_node, &e1000_hw_list);
 
-#ifndef CONFIG_E1000_NO_NVM
-               /* Validate the EEPROM and get chipset information */
-#if !defined(CONFIG_MVBC_1G)
-               if (e1000_init_eeprom_params(hw)) {
-                       E1000_ERR(nic, "EEPROM is invalid!\n");
-                       continue;
-               }
-               if ((E1000_READ_REG(hw, I210_EECD) & E1000_EECD_FLUPD) &&
-                   e1000_validate_eeprom_checksum(hw))
-                       continue;
-#endif
-               e1000_read_mac_addr(nic);
-#endif
-               e1000_get_bus_type(hw);
-
-#ifndef CONFIG_E1000_NO_NVM
-               printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n       ",
-                      nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2],
-                      nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]);
-#else
-               memset(nic->enetaddr, 0, 6);
-               printf("e1000: no NVM\n");
-#endif
+               hw->nic = nic;
 
                /* Set up the function pointers and register the device */
                nic->init = e1000_init;
                nic->recv = e1000_poll;
                nic->send = e1000_transmit;
                nic->halt = e1000_disable;
+               nic->write_hwaddr = e1000_write_hwaddr;
                eth_register(nic);
        }
 
@@ -5437,12 +5761,23 @@ struct e1000_hw *e1000_find_card(unsigned int cardnum)
 
        return NULL;
 }
+#endif /* !CONFIG_DM_ETH */
 
 #ifdef CONFIG_CMD_E1000
-static int do_e1000(cmd_tbl_t *cmdtp, int flag,
-               int argc, char * const argv[])
+static int do_e1000(struct cmd_tbl *cmdtp, int flag, int argc,
+                   char *const argv[])
 {
+       unsigned char *mac = NULL;
+#ifdef CONFIG_DM_ETH
+       struct eth_pdata *plat;
+       struct udevice *dev;
+       char name[30];
+       int ret;
+#endif
+#if !defined(CONFIG_DM_ETH) || defined(CONFIG_E1000_SPI)
        struct e1000_hw *hw;
+#endif
+       int cardnum;
 
        if (argc < 3) {
                cmd_usage(cmdtp);
@@ -5450,20 +5785,34 @@ static int do_e1000(cmd_tbl_t *cmdtp, int flag,
        }
 
        /* Make sure we can find the requested e1000 card */
-       hw = e1000_find_card(simple_strtoul(argv[1], NULL, 10));
-       if (!hw) {
+       cardnum = simple_strtoul(argv[1], NULL, 10);
+#ifdef CONFIG_DM_ETH
+       e1000_name(name, cardnum);
+       ret = uclass_get_device_by_name(UCLASS_ETH, name, &dev);
+       if (!ret) {
+               plat = dev_get_platdata(dev);
+               mac = plat->enetaddr;
+       }
+#else
+       hw = e1000_find_card(cardnum);
+       if (hw)
+               mac = hw->nic->enetaddr;
+#endif
+       if (!mac) {
                printf("e1000: ERROR: No such device: e1000#%s\n", argv[1]);
                return 1;
        }
 
        if (!strcmp(argv[2], "print-mac-address")) {
-               unsigned char *mac = hw->nic->enetaddr;
                printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
                return 0;
        }
 
 #ifdef CONFIG_E1000_SPI
+#ifdef CONFIG_DM_ETH
+       hw = dev_get_priv(dev);
+#endif
        /* Handle the "SPI" subcommand */
        if (!strcmp(argv[2], "spi"))
                return do_e1000_spi(cmdtp, hw, argc - 3, argv + 3);
@@ -5486,3 +5835,109 @@ U_BOOT_CMD(
        "       - Manage the Intel E1000 PCI device"
 );
 #endif /* not CONFIG_CMD_E1000 */
+
+#ifdef CONFIG_DM_ETH
+static int e1000_eth_start(struct udevice *dev)
+{
+       struct eth_pdata *plat = dev_get_platdata(dev);
+       struct e1000_hw *hw = dev_get_priv(dev);
+
+       return _e1000_init(hw, plat->enetaddr);
+}
+
+static void e1000_eth_stop(struct udevice *dev)
+{
+       struct e1000_hw *hw = dev_get_priv(dev);
+
+       _e1000_disable(hw);
+}
+
+static int e1000_eth_send(struct udevice *dev, void *packet, int length)
+{
+       struct e1000_hw *hw = dev_get_priv(dev);
+       int ret;
+
+       ret = _e1000_transmit(hw, packet, length);
+
+       return ret ? 0 : -ETIMEDOUT;
+}
+
+static int e1000_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+       struct e1000_hw *hw = dev_get_priv(dev);
+       int len;
+
+       len = _e1000_poll(hw);
+       if (len)
+               *packetp = packet;
+
+       return len ? len : -EAGAIN;
+}
+
+static int e1000_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+       struct e1000_hw *hw = dev_get_priv(dev);
+
+       fill_rx(hw);
+
+       return 0;
+}
+
+static int e1000_eth_probe(struct udevice *dev)
+{
+       struct eth_pdata *plat = dev_get_platdata(dev);
+       struct e1000_hw *hw = dev_get_priv(dev);
+       int ret;
+
+       hw->name = dev->name;
+       ret = e1000_init_one(hw, trailing_strtol(dev->name),
+                            dev, plat->enetaddr);
+       if (ret < 0) {
+               printf(pr_fmt("failed to initialize card: %d\n"), ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int e1000_eth_bind(struct udevice *dev)
+{
+       char name[20];
+
+       /*
+        * A simple way to number the devices. When device tree is used this
+        * is unnecessary, but when the device is just discovered on the PCI
+        * bus we need a name. We could instead have the uclass figure out
+        * which devices are different and number them.
+        */
+       e1000_name(name, num_cards++);
+
+       return device_set_name(dev, name);
+}
+
+static const struct eth_ops e1000_eth_ops = {
+       .start  = e1000_eth_start,
+       .send   = e1000_eth_send,
+       .recv   = e1000_eth_recv,
+       .stop   = e1000_eth_stop,
+       .free_pkt = e1000_free_pkt,
+};
+
+static const struct udevice_id e1000_eth_ids[] = {
+       { .compatible = "intel,e1000" },
+       { }
+};
+
+U_BOOT_DRIVER(eth_e1000) = {
+       .name   = "eth_e1000",
+       .id     = UCLASS_ETH,
+       .of_match = e1000_eth_ids,
+       .bind   = e1000_eth_bind,
+       .probe  = e1000_eth_probe,
+       .ops    = &e1000_eth_ops,
+       .priv_auto_alloc_size = sizeof(struct e1000_hw),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+U_BOOT_PCI_DEVICE(eth_e1000, e1000_supported);
+#endif