Skip to contentSkip to conversation

e1000: add i210 support

PATCH New Tim Harvey 5 participants 14 messages Aug 8, 2014 – Oct 4, 2014 Network drivers

lore
Share & tools
lore

Tim Harvey

author
#0 lore raw

cover e1000: add i210 support

Two patches to add Intel i210 support to the e1000 driver.

Marek Vasut (2):
e1000: Implement dcache support
e1000: add i210 support

 drivers/net/e1000.c | 266 ++++++++++++++++++++++++++++++++++++++++++----------
 drivers/net/e1000.h |  12 +++
 include/pci_ids.h   |   7 ++
 3 files changed, 236 insertions(+), 49 deletions(-)
Signature · 1 line
1.8.3.2
author
#1 lore raw

PATCH 1/2 e1000: Implement dcache support

From: Marek Vasut <[email protected]>

Implement proper support for cache flushing and invalidation into the Intel e1000 NIC driver.

---
 drivers/net/e1000.c | 71 ++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 49 insertions(+), 22 deletions(-)
drivers/net/e1000.c +49 -22
index 9d9b259..0441a4f 100644
@@ -41,12 +41,12 @@ tested on both gig copper and gig fiber boards
 
 /* NIC specific static variables go here */
 
-static char tx_pool[128 + 16];
-static char rx_pool[128 + 16];
-static char packet[2096];
+/* Intel i210 needs the DMA descriptor rings aligned to 128b */
+#define E1000_BUFFER_ALIGN	128
 
-static struct e1000_tx_desc *tx_base;
-static struct e1000_rx_desc *rx_base;
+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;
@@ -4803,12 +4803,25 @@ void
 fill_rx(struct e1000_hw *hw)
 {
 	struct e1000_rx_desc *rd;
+	uint32_t flush_start, flush_end;
 
 	rx_last = rx_tail;
 	rd = rx_base + rx_tail;
 	rx_tail = (rx_tail + 1) % 8;
 	memset(rd, 0, 16);
-	rd->buffer_addr = cpu_to_le64((u32) & packet);
+	rd->buffer_addr = cpu_to_le64((u32)packet);
+
+	/*
+	 * Make sure there are no stale data in WB over this area, which
+	 * might get written into the memory while the e1000 also writes
+	 * into the same memory area.
+	 */
+	invalidate_dcache_range((u32)packet, (u32)packet + 4096);
+	/* Dump the DMA descriptor into RAM. */
+	flush_start = ((u32)rd) & ~(ARCH_DMA_MINALIGN - 1);
+	flush_end = flush_start + roundup(sizeof(*rd), ARCH_DMA_MINALIGN);
+	flush_dcache_range(flush_start, flush_end);
+
 	E1000_WRITE_REG(hw, RDT, rx_tail);
 }
 
@@ -4822,17 +4835,10 @@ fill_rx(struct e1000_hw *hw)
 static void
 e1000_configure_tx(struct e1000_hw *hw)
 {
-	unsigned long ptr;
 	unsigned long tctl;
 	unsigned long tipg, tarc;
 	uint32_t ipgr1, ipgr2;
 
-	ptr = (u32) tx_pool;
-	if (ptr & 0xf)
-		ptr = (ptr + 0x10) & (~0xf);
-
-	tx_base = (typeof(tx_base)) ptr;
-
 	E1000_WRITE_REG(hw, TDBAL, (u32) tx_base);
 	E1000_WRITE_REG(hw, TDBAH, 0);
 
@@ -4941,7 +4947,6 @@ e1000_setup_rctl(struct e1000_hw *hw)
 static void
 e1000_configure_rx(struct e1000_hw *hw)
 {
-	unsigned long ptr;
 	unsigned long rctl, ctrl_ext;
 	rx_tail = 0;
 	/* make sure receives are disabled while setting up the descriptors */
@@ -4963,10 +4968,6 @@ e1000_configure_rx(struct e1000_hw *hw)
 		E1000_WRITE_FLUSH(hw);
 	}
 	/* Setup the Base and Length of the Rx Descriptor Ring */
-	ptr = (u32) rx_pool;
-	if (ptr & 0xf)
-		ptr = (ptr + 0x10) & (~0xf);
-	rx_base = (typeof(rx_base)) ptr;
 	E1000_WRITE_REG(hw, RDBAL, (u32) rx_base);
 	E1000_WRITE_REG(hw, RDBAH, 0);
 
@@ -4989,12 +4990,25 @@ e1000_poll(struct eth_device *nic)
 {
 	struct e1000_hw *hw = nic->priv;
 	struct e1000_rx_desc *rd;
+	uint32_t inval_start, inval_end;
+	uint32_t len;
+
 	/* return true if there's an ethernet packet ready to read */
 	rd = rx_base + rx_last;
+
+	/* Re-load the descriptor from RAM. */
+	inval_start = ((u32)rd) & ~(ARCH_DMA_MINALIGN - 1);
+	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)
 		return 0;
 	/*DEBUGOUT("recv: packet len=%d \n", rd->length); */
-	NetReceive((uchar *)packet, le32_to_cpu(rd->length));
+	/* Packet received, make sure the data are re-loaded from RAM. */
+	len = le32_to_cpu(rd->length);
+	invalidate_dcache_range((u32)packet,
+				(u32)packet + roundup(len, ARCH_DMA_MINALIGN));
+	NetReceive((uchar *)packet, len);
 	fill_rx(hw);
 	return 1;
 }
@@ -5002,12 +5016,13 @@ e1000_poll(struct eth_device *nic)
 /**************************************************************************
 TRANSMIT - Transmit a frame
 ***************************************************************************/
-static int e1000_transmit(struct eth_device *nic, void *packet, int length)
+static int e1000_transmit(struct eth_device *nic, void *txpacket, int length)
 {
-	void *nv_packet = (void *)packet;
+	void *nv_packet = (void *)txpacket;
 	struct e1000_hw *hw = nic->priv;
 	struct e1000_tx_desc *txp;
 	int i = 0;
+	uint32_t flush_start, flush_end;
 
 	txp = tx_base + tx_tail;
 	tx_tail = (tx_tail + 1) % 8;
@@ -5015,10 +5030,22 @@ static int e1000_transmit(struct eth_device *nic, void *packet, int length)
 	txp->buffer_addr = cpu_to_le64(virt_to_bus(hw->pdev, nv_packet));
 	txp->lower.data = cpu_to_le32(hw->txd_cmd | length);
 	txp->upper.data = 0;
+
+	/* Dump the packet into RAM so e1000 can pick them. */
+	flush_dcache_range((u32)nv_packet,
+			   (u32)nv_packet + roundup(length, ARCH_DMA_MINALIGN));
+	/* Dump the descriptor into RAM as well. */
+	flush_start = ((u32)txp) & ~(ARCH_DMA_MINALIGN - 1);
+	flush_end = flush_start + roundup(sizeof(*txp), ARCH_DMA_MINALIGN);
+	flush_dcache_range(flush_start, flush_end);
+
 	E1000_WRITE_REG(hw, TDT, tx_tail);
 
 	E1000_WRITE_FLUSH(hw);
-	while (!(le32_to_cpu(txp->upper.data) & E1000_TXD_STAT_DD)) {
+	while (1) {
+		invalidate_dcache_range(flush_start, flush_end);
+		if (le32_to_cpu(txp->upper.data) & E1000_TXD_STAT_DD)
+			break;
 		if (i++ > TOUT_LOOP) {
 			DEBUGOUT("e1000: tx timeout\n");
 			return 0;
Signature · 1 line
1.8.3.2
#2 lore raw

PATCH 1/2 e1000: Implement dcache support

Quoted 7 lines · Tim Harvey

From: Marek Vasut <[email protected]>

Implement proper support for cache flushing and invalidation into the Intel e1000 NIC driver.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140823/c77aa049/attachment.pgp>
#3 lore raw

PATCH 1/2 e1000: Implement dcache support

In reply to Tim Harvey

Hi Marek,

Quoted 11 lines · Tim Harvey

From: Marek Vasut <[email protected]>

Implement proper support for cache flushing and invalidation into the Intel e1000 NIC driver.

---
 drivers/net/e1000.c | 71
++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 49 insertions(+), 22 deletions(-)

After your patch (http://patchwork.ozlabs.org/patch/378226/) was applied to u-boot/master, the MVBC_P board fails to build with the following errors:

drivers/net/built-in.o: In function `e1000_transmit':
/home/lab/dev/u-boot/drivers/net/e1000.c:5175: undefined reference to flush_dcache_range' /home/lab/dev/u-boot/drivers/net/e1000.c:5180: undefined reference to flush_dcache_range' /home/lab/dev/u-boot/drivers/net/e1000.c:5186: undefined reference to `invalidate_dcache_range'
drivers/net/built-in.o: In function `fill_rx':
/home/lab/dev/u-boot/drivers/net/e1000.c:4935: undefined reference to invalidate_dcache_range' /home/lab/dev/u-boot/drivers/net/e1000.c:4939: undefined reference to flush_dcache_range'
drivers/net/built-in.o: In function `e1000_poll':
/home/lab/dev/u-boot/drivers/net/e1000.c:5142: undefined reference to invalidate_dcache_range' /home/lab/dev/u-boot/drivers/net/e1000.c:5149: undefined reference to invalidate_dcache_range'
make[1]: *** [u-boot] Error 1
make: *** [sub-make] Error 2

Best,
Vasili

#4 lore raw

PATCH 1/2 e1000: Implement dcache support

Quoted 14 lines · Vasili Galka

Hi Marek,

Quoted 11 lines · Tim Harvey

From: Marek Vasut <[email protected]>

Implement proper support for cache flushing and invalidation into the Intel e1000 NIC driver.

---

 drivers/net/e1000.c | 71
Quoted 7 lines
Quoted 3 lines

++++++++++++++++++++++++++++++++++++-----------------

 1 file changed, 49 insertions(+), 22 deletions(-)

After your patch (http://patchwork.ozlabs.org/patch/378226/) was applied to u-boot/master, the MVBC_P board fails to build with the following errors:

The board needs fixing then. Thank you for pointing this out!

Best regards,
Marek Vasut

#5 lore raw

PATCH 1/2 e1000: Implement dcache support

Quoted 17 lines · Marek Vasut
Quoted 16 lines · Vasili Galka

Hi Marek,

Quoted 13 lines · Tim Harvey

From: Marek Vasut <[email protected]>

Implement proper support for cache flushing and invalidation into the Intel e1000 NIC driver.

---

 drivers/net/e1000.c | 71

++++++++++++++++++++++++++++++++++++-----------------

Quoted 7 lines
Quoted 6 lines
Quoted 1 line
 1 file changed, 49 insertions(+), 22 deletions(-)

After your patch (http://patchwork.ozlabs.org/patch/378226/) was applied to u-boot/master, the MVBC_P board fails to build with

the following errors:

The board needs fixing then. Thank you for pointing this out!

The fix would be to add stubs for the cache functions for that board (or entire platform). The board/platform fails to implement part of U-Boot API, so you get this spew.

Best regards,
Marek Vasut

author
#6 lore raw

PATCH 2/2 e1000: add i210 support

In reply to Tim Harvey

From: Marek Vasut <[email protected]>

Add i210 support to the e1000 driver.

---
 drivers/net/e1000.c | 195 ++++++++++++++++++++++++++++++++++++++++++++--------
 drivers/net/e1000.h |  12 ++++
 include/pci_ids.h   |   7 ++
 3 files changed, 187 insertions(+), 27 deletions(-)
drivers/net/e1000.c +168 -27
index 0441a4f..0eba57c 100644
@@ -92,6 +92,12 @@ static struct pci_device_id e1000_supported[] = {
 	{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_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},
+
 	{}
 };
 
@@ -340,7 +346,7 @@ int32_t e1000_acquire_eeprom(struct e1000_hw *hw)
 		return -E1000_ERR_SWFW_SYNC;
 	eecd = E1000_READ_REG(hw, EECD);
 
-	if (hw->mac_type != e1000_82573 || hw->mac_type != e1000_82574) {
+	if (hw->mac_type != e1000_82573 && hw->mac_type != e1000_82574) {
 		/* Request EEPROM Access */
 		if (hw->mac_type > e1000_82544) {
 			eecd |= E1000_EECD_REQ;
@@ -391,10 +397,15 @@ int32_t e1000_acquire_eeprom(struct e1000_hw *hw)
 static int32_t e1000_init_eeprom_params(struct e1000_hw *hw)
 {
 	struct e1000_eeprom_info *eeprom = &hw->eeprom;
-	uint32_t eecd = E1000_READ_REG(hw, EECD);
+	uint32_t eecd;
 	int32_t ret_val = E1000_SUCCESS;
 	uint16_t eeprom_size;
 
+	if (hw->mac_type == e1000_igb)
+		eecd = E1000_READ_REG(hw, I210_EECD);
+	else
+		eecd = E1000_READ_REG(hw, EECD);
+
 	DEBUGFUNC();
 
 	switch (hw->mac_type) {
@@ -485,9 +496,10 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw)
 			eeprom->page_size = 8;
 			eeprom->address_bits = 8;
 		}
-		eeprom->use_eerd = true;
-		eeprom->use_eewr = true;
 		if (e1000_is_onboard_nvm_eeprom(hw) == false) {
+			eeprom->use_eerd = true;
+			eeprom->use_eewr = true;
+
 			eeprom->type = e1000_eeprom_flash;
 			eeprom->word_size = 2048;
 
@@ -511,6 +523,16 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw)
 		eeprom->use_eerd = true;
 		eeprom->use_eewr = false;
 		break;
+	case e1000_igb:
+		/* i210 has 4k of iNVM mapped as EEPROM */
+		eeprom->type = e1000_eeprom_invm;
+		eeprom->opcode_bits = 8;
+		eeprom->delay_usec = 1;
+		eeprom->page_size = 32;
+		eeprom->address_bits = 16;
+		eeprom->use_eerd = true;
+		eeprom->use_eewr = false;
+		break;
 
 	/* ich8lan does not support currently. if needed, please
 	 * add corresponding code and functions.
@@ -552,7 +574,8 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw)
 		break;
 	}
 
-	if (eeprom->type == e1000_eeprom_spi) {
+	if (eeprom->type == e1000_eeprom_spi ||
+	    eeprom->type == e1000_eeprom_invm) {
 		/* eeprom_size will be an enum [0..8] that maps
 		 * to eeprom sizes 128B to
 		 * 32KB (incremented by powers of 2).
@@ -596,10 +619,17 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
 	int32_t done = E1000_ERR_EEPROM;
 
 	for (i = 0; i < attempts; i++) {
-		if (eerd == E1000_EEPROM_POLL_READ)
-			reg = E1000_READ_REG(hw, EERD);
-		else
-			reg = E1000_READ_REG(hw, EEWR);
+		if (eerd == E1000_EEPROM_POLL_READ) {
+			if (hw->mac_type == e1000_igb)
+				reg = E1000_READ_REG(hw, I210_EERD);
+			else
+				reg = E1000_READ_REG(hw, EERD);
+		} else {
+			if (hw->mac_type == e1000_igb)
+				reg = E1000_READ_REG(hw, I210_EEWR);
+			else
+				reg = E1000_READ_REG(hw, EEWR);
+		}
 
 		if (reg & E1000_EEPROM_RW_REG_DONE) {
 			done = E1000_SUCCESS;
@@ -632,13 +662,23 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
 		eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
 			E1000_EEPROM_RW_REG_START;
 
-		E1000_WRITE_REG(hw, EERD, eerd);
+		if (hw->mac_type == e1000_igb)
+			E1000_WRITE_REG(hw, I210_EERD, eerd);
+		else
+			E1000_WRITE_REG(hw, EERD, eerd);
+
 		error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
 
 		if (error)
 			break;
-		data[i] = (E1000_READ_REG(hw, EERD) >>
+
+		if (hw->mac_type == e1000_igb) {
+			data[i] = (E1000_READ_REG(hw, I210_EERD) >>
+				E1000_EEPROM_RW_REG_DATA);
+		} else {
+			data[i] = (E1000_READ_REG(hw, EERD) >>
 				E1000_EEPROM_RW_REG_DATA);
+		}
 
 	}
 
@@ -949,6 +989,10 @@ 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)
 		return E1000_SUCCESS;
 
@@ -1069,7 +1113,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
 			return -E1000_ERR_SWFW_SYNC;
 
 		swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
-		if (!(swfw_sync & (fwmask | swmask)))
+		if ((swfw_sync & swmask) && !(swfw_sync & fwmask))
 			break;
 
 		/* firmware currently using resource (fwmask) */
@@ -1118,13 +1162,23 @@ e1000_read_mac_addr(struct eth_device *nic)
 	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 (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
+		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) {
 			DEBUGOUT("EEPROM Read Error\n");
 			return -E1000_ERR_EEPROM;
 		}
@@ -1320,6 +1374,13 @@ e1000_set_mac_type(struct e1000_hw *hw)
 	case E1000_DEV_ID_ICH8_IGP_M:
 		hw->mac_type = e1000_ich8lan;
 		break;
+	case PCI_DEVICE_ID_INTEL_I210_COPPER:
+	case PCI_DEVICE_ID_INTEL_I210_COPPER_FLASHLESS:
+	case PCI_DEVICE_ID_INTEL_I210_SERDES:
+	case PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS:
+	case PCI_DEVICE_ID_INTEL_I210_1000BASEKX:
+		hw->mac_type = e1000_igb;
+		break;
 	default:
 		/* Should never have loaded on this device */
 		return -E1000_ERR_MAC_TYPE;
@@ -1339,6 +1400,7 @@ e1000_reset_hw(struct e1000_hw *hw)
 	uint32_t ctrl_ext;
 	uint32_t manc;
 	uint32_t pba = 0;
+	uint32_t reg;
 
 	DEBUGFUNC();
 
@@ -1357,6 +1419,8 @@ e1000_reset_hw(struct e1000_hw *hw)
 
 	/* Clear interrupt mask to stop board from generating interrupts */
 	DEBUGOUT("Masking off all interrupts\n");
+	if (hw->mac_type == e1000_igb)
+		E1000_WRITE_REG(hw, I210_IAM, 0);
 	E1000_WRITE_REG(hw, IMC, 0xffffffff);
 
 	/* Disable the Transmit and Receive units.  Then delay to allow
@@ -1386,7 +1450,15 @@ e1000_reset_hw(struct e1000_hw *hw)
 	E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
 
 	/* Force a reload from the EEPROM if necessary */
-	if (hw->mac_type < e1000_82540) {
+	if (hw->mac_type == e1000_igb) {
+		mdelay(20);
+		reg = E1000_READ_REG(hw, STATUS);
+		if (reg & E1000_STATUS_PF_RST_DONE)
+			DEBUGOUT("PF OK\n");
+		reg = E1000_READ_REG(hw, I210_EECD);
+		if (reg & E1000_EECD_AUTO_RD)
+			DEBUGOUT("EEC OK\n");
+	} else if (hw->mac_type < e1000_82540) {
 		/* Wait for reset to complete */
 		udelay(10);
 		ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
@@ -1406,6 +1478,8 @@ e1000_reset_hw(struct e1000_hw *hw)
 
 	/* Clear interrupt mask to stop board from generating interrupts */
 	DEBUGOUT("Masking off all interrupts\n");
+	if (hw->mac_type == e1000_igb)
+		E1000_WRITE_REG(hw, I210_IAM, 0);
 	E1000_WRITE_REG(hw, IMC, 0xffffffff);
 
 	/* Clear any pending interrupt events. */
@@ -1415,7 +1489,8 @@ e1000_reset_hw(struct e1000_hw *hw)
 	if (hw->mac_type == e1000_82542_rev2_0) {
 		pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
 	}
-	E1000_WRITE_REG(hw, PBA, pba);
+	if (hw->mac_type != e1000_igb)
+		E1000_WRITE_REG(hw, PBA, pba);
 }
 
 /******************************************************************************
@@ -1451,6 +1526,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_82571:
 		case e1000_82572:
@@ -1641,6 +1720,7 @@ e1000_init_hw(struct eth_device *nic)
 	switch (hw->mac_type) {
 	case e1000_82545_rev_3:
 	case e1000_82546_rev_3:
+	case e1000_igb:
 		break;
 	default:
 	/* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
@@ -1670,6 +1750,8 @@ e1000_init_hw(struct eth_device *nic)
 	/* More time needed for PHY to initialize */
 	if (hw->mac_type == e1000_ich8lan)
 		mdelay(15);
+	if (hw->mac_type == e1000_igb)
+		mdelay(15);
 
 	/* Call a subroutine to configure the link and setup flow control. */
 	ret_val = e1000_setup_link(nic);
@@ -1684,7 +1766,6 @@ e1000_init_hw(struct eth_device *nic)
 	}
 
 	/* Set the receive descriptor write back policy */
-
 	if (hw->mac_type >= e1000_82571) {
 		ctrl = E1000_READ_REG(hw, RXDCTL);
 		ctrl =
@@ -1731,6 +1812,8 @@ e1000_init_hw(struct eth_device *nic)
 		reg_data = E1000_READ_REG(hw, GCR);
 		reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
 		E1000_WRITE_REG(hw, GCR, reg_data);
+	case e1000_igb:
+		break;
 	}
 
 #if 0
@@ -1807,6 +1890,7 @@ e1000_setup_link(struct eth_device *nic)
 		case e1000_ich8lan:
 		case e1000_82573:
 		case e1000_82574:
+		case e1000_igb:
 			hw->fc = e1000_fc_full;
 			break;
 		default:
@@ -2267,6 +2351,8 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
 
 	if (hw->mac_type == e1000_ich8lan) {
 		phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
+	} else if (hw->mac_type == e1000_igb) {
+		phy_ctrl = E1000_READ_REG(hw, I210_PHY_CTRL);
 	} else {
 		ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
 				&phy_data);
@@ -2278,6 +2364,9 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
 		if (hw->mac_type == e1000_ich8lan) {
 			phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
 			E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+		} else if (hw->mac_type == e1000_igb) {
+			phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
+			E1000_WRITE_REG(hw, I210_PHY_CTRL, phy_ctrl);
 		} else {
 			phy_data &= ~IGP02E1000_PM_D0_LPLU;
 			ret_val = e1000_write_phy_reg(hw,
@@ -2286,6 +2375,9 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
 				return ret_val;
 		}
 
+		if (hw->mac_type == e1000_igb)
+			return E1000_SUCCESS;
+
 	/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used during
 	 * Dx states where the power conservation is most important.  During
 	 * driver activity we should enable SmartSpeed, so performance is
@@ -2320,6 +2412,9 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
 		if (hw->mac_type == e1000_ich8lan) {
 			phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
 			E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+		} else if (hw->mac_type == e1000_igb) {
+			phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
+			E1000_WRITE_REG(hw, I210_PHY_CTRL, phy_ctrl);
 		} else {
 			phy_data |= IGP02E1000_PM_D0_LPLU;
 			ret_val = e1000_write_phy_reg(hw,
@@ -2328,6 +2423,9 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
 				return ret_val;
 		}
 
+		if (hw->mac_type == e1000_igb)
+			return E1000_SUCCESS;
+
 		/* When LPLU is enabled we should disable SmartSpeed */
 		ret_val = e1000_read_phy_reg(hw,
 				IGP01E1000_PHY_PORT_CONFIG, &phy_data);
@@ -2549,8 +2647,10 @@ e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data)
 	if (e1000_is_second_port(hw))
 		swfw = E1000_SWFW_PHY1_SM;
 
-	if (e1000_swfw_sync_acquire(hw, swfw))
+	if (e1000_swfw_sync_acquire(hw, swfw)) {
+		debug("%s[%i]\n", __func__, __LINE__);
 		return -E1000_ERR_SWFW_SYNC;
+	}
 
 	/* Write register address */
 	reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
@@ -2985,7 +3085,8 @@ e1000_setup_copper_link(struct eth_device *nic)
 		ret_val = e1000_copper_link_igp_setup(hw);
 		if (ret_val)
 			return ret_val;
-	} else if (hw->phy_type == e1000_phy_m88) {
+	} else if (hw->phy_type == e1000_phy_m88 ||
+		hw->phy_type == e1000_phy_igb) {
 		ret_val = e1000_copper_link_mgp_setup(hw);
 		if (ret_val)
 			return ret_val;
@@ -3229,7 +3330,8 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
 	 */
 	ctrl = E1000_READ_REG(hw, CTRL);
 	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
+	ctrl &= ~(E1000_CTRL_ILOS);
+	ctrl |= (E1000_CTRL_SPD_SEL);
 
 	/* Set up duplex in the Device Control and Transmit Control
 	 * registers depending on negotiated values.
@@ -4255,11 +4357,16 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
 
 	case e1000_82571:
 	case e1000_82572:
+	case e1000_igb:
 		while (timeout) {
-			if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
-				break;
-			else
-				mdelay(1);
+			if (hw->mac_type == e1000_igb) {
+				if (E1000_READ_REG(hw, I210_EEMNGCTL) & cfg_mask)
+					break;
+			} else {
+				if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+					break;
+			}
+			mdelay(1);
 			timeout--;
 		}
 		if (!timeout) {
@@ -4488,6 +4595,7 @@ e1000_phy_reset(struct e1000_hw *hw)
 	case e1000_phy_igp_2:
 	case e1000_phy_igp_3:
 	case e1000_phy_ife:
+	case e1000_phy_igb:
 		ret_val = e1000_phy_hw_reset(hw);
 		if (ret_val)
 			return ret_val;
@@ -4550,6 +4658,9 @@ static int e1000_set_phy_type (struct e1000_hw *hw)
 	case BME1000_E_PHY_ID:
 		hw->phy_type = e1000_phy_bm;
 		break;
+	case I210_I_PHY_ID:
+		hw->phy_type = e1000_phy_igb;
+		break;
 		/* Fall Through */
 	default:
 		/* Should never have loaded on this device */
@@ -4654,6 +4765,10 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
 		if (hw->phy_id == IFE_C_E_PHY_ID)
 			match = true;
 		break;
+	case e1000_igb:
+		if (hw->phy_id == I210_I_PHY_ID)
+			match = true;
+		break;
 	default:
 		DEBUGOUT("Invalid MAC type %d\n", hw->mac_type);
 		return -E1000_ERR_CONFIG;
@@ -4705,6 +4820,7 @@ e1000_set_media_type(struct e1000_hw *hw)
 		case e1000_ich8lan:
 		case e1000_82573:
 		case e1000_82574:
+		case e1000_igb:
 			/* The STATUS_TBIMODE bit is reserved or reused
 			 * for the this device.
 			 */
@@ -4773,6 +4889,7 @@ e1000_sw_init(struct eth_device *nic)
 	hw->fc_send_xon = 1;
 
 	/* Media type - copper or fiber */
+	hw->tbi_compatibility_en = true;
 	e1000_set_media_type(hw);
 
 	if (hw->mac_type >= e1000_82543) {
@@ -4789,7 +4906,6 @@ e1000_sw_init(struct eth_device *nic)
 		hw->media_type = e1000_media_type_fiber;
 	}
 
-	hw->tbi_compatibility_en = true;
 	hw->wait_autoneg_complete = true;
 	if (hw->mac_type < e1000_82543)
 		hw->report_tx_early = 0;
@@ -4907,7 +5023,22 @@ e1000_configure_tx(struct e1000_hw *hw)
 		hw->txd_cmd |= E1000_TXD_CMD_RPS;
 	else
 		hw->txd_cmd |= E1000_TXD_CMD_RS;
+
+
+	if (hw->mac_type == e1000_igb) {
+		E1000_WRITE_REG(hw, TCTL_EXT, 0x42 << 10);
+
+		uint32_t reg_txdctl = E1000_READ_REG(hw, TXDCTL);
+		reg_txdctl |= 1 << 25;
+		E1000_WRITE_REG(hw, TXDCTL, reg_txdctl);
+		mdelay(20);
+	}
+
+
+
 	E1000_WRITE_REG(hw, TCTL, tctl);
+
+
 }
 
 /**
@@ -4978,7 +5109,16 @@ e1000_configure_rx(struct e1000_hw *hw)
 	E1000_WRITE_REG(hw, RDT, 0);
 	/* Enable Receives */
 
+	if (hw->mac_type == e1000_igb) {
+
+		uint32_t reg_rxdctl = E1000_READ_REG(hw, RXDCTL);
+		reg_rxdctl |= 1 << 25;
+		E1000_WRITE_REG(hw, RXDCTL, reg_rxdctl);
+		mdelay(20);
+	}
+
 	E1000_WRITE_REG(hw, RCTL, rctl);
+
 	fill_rx(hw);
 }
 
@@ -5140,9 +5280,8 @@ void e1000_get_bus_type(struct e1000_hw *hw)
 	case e1000_82573:
 	case e1000_82574:
 	case e1000_80003es2lan:
-		hw->bus_type = e1000_bus_type_pci_express;
-		break;
 	case e1000_ich8lan:
+	case e1000_igb:
 		hw->bus_type = e1000_bus_type_pci_express;
 		break;
 	default:
@@ -5223,6 +5362,7 @@ e1000_initialize(bd_t * bis)
 		hw->autoneg_failed = 0;
 		hw->autoneg = 1;
 		hw->get_link_status = true;
+		hw->eeprom_semaphore_present = true;
 		hw->hw_addr = pci_map_bar(devno,	PCI_BASE_ADDRESS_0,
 							PCI_REGION_MEM);
 		hw->mac_type = e1000_undefined;
@@ -5246,7 +5386,8 @@ e1000_initialize(bd_t * bis)
 			E1000_ERR(nic, "EEPROM is invalid!\n");
 			continue;
 		}
-		if (e1000_validate_eeprom_checksum(hw))
+		if ((E1000_READ_REG(hw, I210_EECD) & E1000_EECD_FLUPD) &&
+		    e1000_validate_eeprom_checksum(hw))
 			continue;
 #endif
 		e1000_read_mac_addr(nic);
drivers/net/e1000.h +12 -0
index ff87af2..b025ecc 100644
@@ -100,6 +100,7 @@ typedef enum {
 	e1000_82574,
 	e1000_80003es2lan,
 	e1000_ich8lan,
+	e1000_igb,
 	e1000_num_macs
 } e1000_mac_type;
 
@@ -118,6 +119,7 @@ typedef enum {
 	e1000_eeprom_flash,
 	e1000_eeprom_ich8,
 	e1000_eeprom_none, /* No NVM support */
+	e1000_eeprom_invm,
 	e1000_num_eeprom_types
 } e1000_eeprom_type;
 
@@ -212,6 +214,7 @@ typedef enum {
 	e1000_phy_gg82563,
 	e1000_phy_igp_3,
 	e1000_phy_ife,
+	e1000_phy_igb,
 	e1000_phy_bm,
 	e1000_phy_undefined = 0xFF
 } e1000_phy_type;
@@ -686,7 +689,9 @@ struct e1000_ffvt_entry {
 #define E1000_CTRL     0x00000	/* Device Control - RW */
 #define E1000_STATUS   0x00008	/* Device Status - RO */
 #define E1000_EECD     0x00010	/* EEPROM/Flash Control - RW */
+#define E1000_I210_EECD     0x12010	/* EEPROM/Flash Control - RW */
 #define E1000_EERD     0x00014	/* EEPROM Read - RW */
+#define E1000_I210_EERD     0x12014	/* EEPROM Read - RW */
 #define E1000_CTRL_EXT 0x00018	/* Extended Device Control - RW */
 #define E1000_MDIC     0x00020	/* MDI Control - RW */
 #define E1000_FCAL     0x00028	/* Flow Control Address Low - RW */
@@ -698,6 +703,7 @@ struct e1000_ffvt_entry {
 #define E1000_ICS      0x000C8	/* Interrupt Cause Set - WO */
 #define E1000_IMS      0x000D0	/* Interrupt Mask Set - RW */
 #define E1000_IMC      0x000D8	/* Interrupt Mask Clear - WO */
+#define E1000_I210_IAM      0x000E0	/* Interrupt Ack Auto Mask - RW */
 #define E1000_RCTL     0x00100	/* RX Control - RW */
 #define E1000_FCTTV    0x00170	/* Flow Control Transmit Timer Value - RW */
 #define E1000_TXCW     0x00178	/* TX Configuration Word - RW */
@@ -711,14 +717,17 @@ struct e1000_ffvt_entry {
 #define E1000_EXTCNF_CTRL  0x00F00  /* Extended Configuration Control */
 #define E1000_EXTCNF_SIZE  0x00F08  /* Extended Configuration Size */
 #define E1000_PHY_CTRL     0x00F10  /* PHY Control Register in CSR */
+#define E1000_I210_PHY_CTRL     0x00E14  /* PHY Control Register in CSR */
 #define FEXTNVM_SW_CONFIG  0x0001
 #define E1000_PBA      0x01000	/* Packet Buffer Allocation - RW */
 #define E1000_PBS      0x01008  /* Packet Buffer Size */
 #define E1000_EEMNGCTL 0x01010  /* MNG EEprom Control */
+#define E1000_I210_EEMNGCTL 0x12030  /* MNG EEprom Control */
 #define E1000_FLASH_UPDATES 1000
 #define E1000_EEARBC   0x01024  /* EEPROM Auto Read Bus Control */
 #define E1000_FLASHT   0x01028  /* FLASH Timer Register */
 #define E1000_EEWR     0x0102C  /* EEPROM Write Register - RW */
+#define E1000_I210_EEWR     0x12018  /* EEPROM Write Register - RW */
 #define E1000_FLSWCTL  0x01030  /* FLASH control register */
 #define E1000_FLSWDATA 0x01034  /* FLASH data register */
 #define E1000_FLSWCNT  0x01038  /* FLASH Access Counter */
@@ -1222,6 +1231,7 @@ struct e1000_hw {
 #define E1000_STATUS_BUS64	0x00001000	/* In 64 bit slot */
 #define E1000_STATUS_PCIX_MODE	0x00002000	/* PCI-X mode */
 #define E1000_STATUS_PCIX_SPEED 0x0000C000	/* PCI-X bus speed */
+#define E1000_STATUS_PF_RST_DONE 0x00200000	/* PCI-X bus speed */
 
 /* Constants used to intrepret the masked PCI-X bus speed. */
 #define E1000_STATUS_PCIX_SPEED_66  0x00000000	/* PCI-X bus speed  50-66 MHz */
@@ -2438,6 +2448,8 @@ struct e1000_hw {
 
 #define BME1000_E_PHY_ID     0x01410CB0
 
+#define I210_I_PHY_ID		0x01410C00
+
 /* Miscellaneous PHY bit definitions. */
 #define PHY_PREAMBLE			0xFFFFFFFF
 #define PHY_SOF				0x01
include/pci_ids.h +7 -0
index 6bab677..f220c3a 100644
@@ -2546,6 +2546,13 @@
 #define PCI_DEVICE_ID_INTEL_82441	0x1237
 #define PCI_DEVICE_ID_INTEL_82380FB	0x124b
 #define PCI_DEVICE_ID_INTEL_82439	0x1250
+#define PCI_DEVICE_ID_INTEL_I210_UNPROGRAMMED		0x1531
+#define PCI_DEVICE_ID_INTEL_I210_COPPER			0x1533
+#define PCI_DEVICE_ID_INTEL_I210_SERDES			0x1536
+#define PCI_DEVICE_ID_INTEL_I210_1000BASEKX		0x1537
+#define PCI_DEVICE_ID_INTEL_I210_EXTPHY			0x1538
+#define PCI_DEVICE_ID_INTEL_I210_COPPER_FLASHLESS	0x157b
+#define PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS	0x157c
 #define PCI_DEVICE_ID_INTEL_80960_RP	0x1960
 #define PCI_DEVICE_ID_INTEL_82840_HB	0x1a21
 #define PCI_DEVICE_ID_INTEL_82845_HB	0x1a30
Signature · 1 line
1.8.3.2
#7 lore raw

PATCH 2/2 e1000: add i210 support

Quoted 6 lines · Tim Harvey

From: Marek Vasut <[email protected]>

Add i210 support to the e1000 driver.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140823/c07fe7fe/attachment.pgp>
#8 lore raw

cover e1000: add i210 support

In reply to Tim Harvey
Quoted 11 lines · Tim Harvey

Two patches to add Intel i210 support to the e1000 driver.

Marek Vasut (2):
e1000: Implement dcache support
e1000: add i210 support

 drivers/net/e1000.c | 266
++++++++++++++++++++++++++++++++++++++++++---------- drivers/net/e1000.h |
 12 +++
 include/pci_ids.h   |   7 ++
 3 files changed, 236 insertions(+), 49 deletions(-)

Thanks for taking care of those!

Best regards,
Marek Vasut

#9 lore raw

cover e1000: add i210 support

Quoted 7 lines · Marek Vasut
Quoted 6 lines · Tim Harvey

Two patches to add Intel i210 support to the e1000 driver.

Marek Vasut (2):
e1000: Implement dcache support
e1000: add i210 support

Quoted 8 lines
Quoted 5 lines
 drivers/net/e1000.c | 266
++++++++++++++++++++++++++++++++++++++++++---------- drivers/net/e1000.h |
 12 +++
 include/pci_ids.h   |   7 ++
 3 files changed, 236 insertions(+), 49 deletions(-)

Thanks for taking care of those!

Tim,

I am having problem with this patch/commit. We use e1000 cards on many of our boards for debugging. Recently I found it is not working on some. Using "git bisect" I narrowed down to this commit 951860634fdb557bbb58e0f99215391bc0c29779. What information I can provide to help you investigate? The vendor id is 0x8086. The device id is 0x107d.

York

#10 lore raw

cover e1000: add i210 support

Quoted 19 lines · York Sun
Quoted 9 lines · Marek Vasut
Quoted 8 lines · Tim Harvey

Two patches to add Intel i210 support to the e1000 driver.

Marek Vasut (2):
e1000: Implement dcache support
e1000: add i210 support

 drivers/net/e1000.c | 266
Quoted 8 lines
Quoted 6 lines

++++++++++++++++++++++++++++++++++++++++++---------- drivers/net/e1000.h |

12 +++

 include/pci_ids.h   |   7 ++
 3 files changed, 236 insertions(+), 49 deletions(-)

Thanks for taking care of those!

Quoted 7 lines

Tim,

I am having problem with this patch/commit. We use e1000 cards on many of our boards for debugging. Recently I found it is not working on some. Using "git bisect" I narrowed down to this commit 951860634fdb557bbb58e0f99215391bc0c29779. What information I can provide to help you investigate? The vendor id is 0x8086. The device id is 0x107d.

Hey,

can you dive into the patch and see which chunk broke your card please ? Right now, I really cannot tell, I suspect it might have to do with the EEPROM handling changes though.

Best regards,
Marek Vasut

#11 lore raw

cover e1000: add i210 support

Marek,

I can try piece by piece but I don't know much about this driver. Some guidance will be appreciated.

York

-------- Original Message --------
From: Marek Vasut
Sent: Fri, 03/10/2014 19:12
To: Sun York-R58495
CC: Tim Harvey ; u-boot at lists.denx.de
Subject: Re: [U-Boot] [PATCH 0/2] e1000: add i210 support

Quoted 19 lines · York Sun
Quoted 9 lines · Marek Vasut
Quoted 8 lines · Tim Harvey

Two patches to add Intel i210 support to the e1000 driver.

Marek Vasut (2):
e1000: Implement dcache support
e1000: add i210 support

 drivers/net/e1000.c | 266
Quoted 8 lines
Quoted 6 lines

++++++++++++++++++++++++++++++++++++++++++---------- drivers/net/e1000.h |

12 +++

 include/pci_ids.h   |   7 ++
 3 files changed, 236 insertions(+), 49 deletions(-)

Thanks for taking care of those!

Quoted 7 lines

Tim,

I am having problem with this patch/commit. We use e1000 cards on many of our boards for debugging. Recently I found it is not working on some. Using "git bisect" I narrowed down to this commit 951860634fdb557bbb58e0f99215391bc0c29779. What information I can provide to help you investigate? The vendor id is 0x8086. The device id is 0x107d.

Hey,

can you dive into the patch and see which chunk broke your card please ? Right now, I really cannot tell, I suspect it might have to do with the EEPROM handling changes though.

Best regards,
Marek Vasut

author
#12 lore raw

cover e1000: add i210 support

In reply to Tim Harvey
Quoted 6 lines · Tim Harvey

Two patches to add Intel i210 support to the e1000 driver.

Marek Vasut (2):
e1000: Implement dcache support
e1000: add i210 support

Quoted 8 lines
 drivers/net/e1000.c | 266 ++++++++++++++++++++++++++++++++++++++++++----------
 drivers/net/e1000.h |  12 +++
 include/pci_ids.h   |   7 ++
 3 files changed, 236 insertions(+), 49 deletions(-)

--
1.8.3.2

I'm not clear if there is a maintainer of drivers/net/e1000 that should be copied here. If not, anyone have any comments keeping these from being committed?

Regards,

Tim

#13 lore raw

cover e1000: add i210 support

Quoted 13 lines · Tim Harvey
Quoted 12 lines · Tim Harvey

Two patches to add Intel i210 support to the e1000 driver.

Marek Vasut (2):
e1000: Implement dcache support
e1000: add i210 support

 drivers/net/e1000.c | 266
 ++++++++++++++++++++++++++++++++++++++++++----------
 drivers/net/e1000.h |  12 +++
 include/pci_ids.h   |   7 ++
 3 files changed, 236 insertions(+), 49 deletions(-)
Quoted 6 lines
Quoted 2 lines

--
1.8.3.2

I'm not clear if there is a maintainer of drivers/net/e1000 that should be copied here. If not, anyone have any comments keeping these from being committed?

Joe should pick them up, but I am adding Tom to Cc ...

Best regards,
Marek Vasut