]> git.sur5r.net Git - u-boot/blobdiff - drivers/net/e1000.c
net: e1000: Fix e1000_igb semaphore handling
[u-boot] / drivers / net / e1000.c
index 70fc02ee5ca6bb9bb28abf9361eb359398e6089e..5cc54efe483ad6bad71434fe42f60201cf1437ca 100644 (file)
@@ -38,8 +38,13 @@ tested on both gig copper and gig fiber boards
 
 #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
@@ -145,6 +150,7 @@ 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);
@@ -856,6 +862,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
  *
@@ -965,7 +1139,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
 
        DEBUGFUNC();
 
-       if (hw->mac_type != e1000_80003es2lan)
+       if (hw->mac_type != e1000_80003es2lan && hw->mac_type != e1000_igb)
                return E1000_SUCCESS;
 
        while (timeout) {
@@ -1007,7 +1181,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
@@ -1039,7 +1213,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;
@@ -1139,33 +1313,21 @@ 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 e1000_hw *hw, unsigned char enetaddr[6])
+static int e1000_read_mac_addr_from_eeprom(struct e1000_hw *hw,
+                                          unsigned char enetaddr[6])
 {
        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;
                }
@@ -1173,6 +1335,63 @@ e1000_read_mac_addr(struct e1000_hw *hw, unsigned char enetaddr[6])
                enetaddr[i + 1] = (eeprom_data >> 8) & 0xff;
        }
 
+       return 0;
+}
+
+/******************************************************************************
+ * 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;
+
+               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;
+       }
+
+       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;
@@ -1395,8 +1614,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 */
@@ -1469,7 +1693,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);
@@ -1508,11 +1736,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 */
@@ -1655,9 +1882,15 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
        /* 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);
@@ -1673,7 +1906,11 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
                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 */
@@ -1696,10 +1933,17 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
        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;
@@ -1711,8 +1955,13 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6])
                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;
@@ -4809,6 +5058,16 @@ e1000_sw_init(struct e1000_hw *hw)
        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,
@@ -4817,6 +5076,7 @@ e1000_sw_init(struct e1000_hw *hw)
 
        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);
@@ -5232,25 +5492,46 @@ void e1000_get_bus_type(struct e1000_hw *hw)
 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;
@@ -5269,8 +5550,13 @@ static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno,
 #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 */
@@ -5363,6 +5649,45 @@ e1000_poll(struct eth_device *nic)
        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
 You should omit the last argument struct pci_device * for a non-PCI NIC
@@ -5380,7 +5705,7 @@ e1000_initialize(bd_t * bis)
        for (i = 0; (devno = pci_find_devices(e1000_supported, i)) >= 0; i++) {
                /*
                 * 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));
@@ -5412,6 +5737,7 @@ e1000_initialize(bd_t * bis)
                nic->recv = e1000_poll;
                nic->send = e1000_transmit;
                nic->halt = e1000_disable;
+               nic->write_hwaddr = e1000_write_hwaddr;
                eth_register(nic);
        }
 
@@ -5440,7 +5766,8 @@ static int do_e1000(cmd_tbl_t *cmdtp, int flag,
        struct udevice *dev;
        char name[30];
        int ret;
-#else
+#endif
+#if !defined(CONFIG_DM_ETH) || defined(CONFIG_E1000_SPI)
        struct e1000_hw *hw;
 #endif
        int cardnum;
@@ -5476,6 +5803,9 @@ static int do_e1000(cmd_tbl_t *cmdtp, int flag,
        }
 
 #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);
@@ -5554,7 +5884,7 @@ static int e1000_eth_probe(struct udevice *dev)
 
        hw->name = dev->name;
        ret = e1000_init_one(hw, trailing_strtol(dev->name),
-                            dm_pci_get_bdf(dev), plat->enetaddr);
+                            dev, plat->enetaddr);
        if (ret < 0) {
                printf(pr_fmt("failed to initialize card: %d\n"), ret);
                return ret;