+// 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
Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: GPL-2.0+
Contact Information:
*/
#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
#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);
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
*
DEBUGFUNC();
- if (hw->mac_type != e1000_80003es2lan)
+ if (hw->mac_type != e1000_80003es2lan && hw->mac_type != e1000_igb)
return E1000_SUCCESS;
while (timeout) {
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
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;
#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;
}
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;
/* 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 */
E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP);
E1000_WRITE_FLUSH(hw);
+ if (hw->mac_type == e1000_igb) {
+ E1000_WRITE_REG(hw, RXPBS, I210_RXPBSIZE_DEFAULT);
+ E1000_WRITE_REG(hw, TXPBS, I210_TXPBSIZE_DEFAULT);
+ }
+
/* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
hw->tbi_compatibility_on = false;
/* 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);
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 */
/* 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);
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 */
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;
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;
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,
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);
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;
#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 */
INIT - set up ethernet interface(s)
***************************************************************************/
static int
-e1000_init(struct eth_device *nic, bd_t *bis)
+e1000_init(struct eth_device *nic, struct bd_info *bis)
{
struct e1000_hw *hw = nic->priv;
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
***************************************************************************/
int
-e1000_initialize(bd_t * bis)
+e1000_initialize(struct bd_info * bis)
{
unsigned int i;
pci_dev_t devno;
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));
nic->recv = e1000_poll;
nic->send = e1000_transmit;
nic->halt = e1000_disable;
+ nic->write_hwaddr = e1000_write_hwaddr;
eth_register(nic);
}
#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 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;
}
#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);
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;
.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),
+ .priv_auto = sizeof(struct e1000_hw),
+ .plat_auto = sizeof(struct eth_pdata),
};
U_BOOT_PCI_DEVICE(eth_e1000, e1000_supported);