*/
#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <memalign.h>
+#include <pci.h>
#include "e1000.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
/* Intel i210 needs the DMA descriptor rings aligned to 128b */
#define E1000_BUFFER_ALIGN 128
+/*
+ * 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);
#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);
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;
}
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) {
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
*
/* 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;
}
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;
}
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 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;
+}
+
+/******************************************************************************
+ * 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;
-#ifdef CONFIG_E1000_FALLBACK_MAC
- if (!is_valid_ethaddr(nic->enetaddr)) {
- unsigned char fb_mac[NODE_ADDRESS_SIZE] = CONFIG_E1000_FALLBACK_MAC;
+ 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;
- memcpy (nic->enetaddr, fb_mac, NODE_ADDRESS_SIZE);
+ 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
* 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;
/* 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);
/* 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 */
/* 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 */
* 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;
/* 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);
/* 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 */
* 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:
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;
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) {
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);
* 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;
/* 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;
}
* 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;
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);
*/
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;
* 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;
* 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;
**/
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,
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;
}
unsigned long tipg, tarc;
uint32_t ipgr1, ipgr2;
- E1000_WRITE_REG(hw, TDBAL, (unsigned long)tx_base & 0xffffffff);
- E1000_WRITE_REG(hw, TDBAH, (unsigned long)tx_base >> 32);
+ 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);
{
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);
E1000_WRITE_FLUSH(hw);
}
/* Setup the Base and Length of the Rx Descriptor Ring */
- E1000_WRITE_REG(hw, RDBAL, (unsigned long)rx_base & 0xffffffff);
- E1000_WRITE_REG(hw, RDBAH, (unsigned long)rx_base >> 32);
+ 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);
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;
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); */
/* 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;
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);
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;
}
/******************************************************************************
}
}
+#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
{
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));
/* 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);
+ e1000_name(nic->name, i);
+ hw->name = nic->name;
- /* Try to enable I/O accesses and bus-mastering */
- val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
- pci_write_config_dword(devno, PCI_COMMAND, val);
-
- /* 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);
}
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[])
{
+ 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);
}
/* 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);
" - 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