[U-Boot] [PATCH] Gbe Controller driver support for kirkwood SOCs

Prafulla Wadaskar prafulla at marvell.com
Sat Apr 4 00:39:28 CEST 2009


From: prafulla_wadaskar <prafulla at marvell.com>

Contributors:
Yotam Admon <yotam at marvell.com>
Michael Blostein <michaelbl at marvell.com

Signed-off-by: prafulla_wadaskar <prafulla at marvell.com>
Reviewed by: Ronen Shitrit <rshitrit at marvell.com>
---
 cpu/arm926ejs/kirkwood/Makefile     |    1 +
 cpu/arm926ejs/kirkwood/egiga.c      | 2169 +++++++++++++++++++++++++++++++++++
 cpu/arm926ejs/kirkwood/egiga.h      |  707 ++++++++++++
 cpu/arm926ejs/kirkwood/egiga_regs.h |  161 +++
 cpu/arm926ejs/kirkwood/kwcore.h     |    2 +
 net/eth.c                           |    4 +
 6 files changed, 3044 insertions(+), 0 deletions(-)
 create mode 100644 cpu/arm926ejs/kirkwood/egiga.c
 create mode 100644 cpu/arm926ejs/kirkwood/egiga.h
 create mode 100644 cpu/arm926ejs/kirkwood/egiga_regs.h

diff --git a/cpu/arm926ejs/kirkwood/Makefile b/cpu/arm926ejs/kirkwood/Makefile
index 41ac8d7..3e20898 100644
--- a/cpu/arm926ejs/kirkwood/Makefile
+++ b/cpu/arm926ejs/kirkwood/Makefile
@@ -30,6 +30,7 @@ COBJS-y	= timer.o
 COBJS-y	+= serial.o
 COBJS-y	+= kwcore.o
 COBJS-y	+= dram.o
+COBJS-y	+= egiga.o
 COBJS-$(CONFIG_KIRKWOOD_SPI)		+= spi.o
 
 SOBJS	= soc_init.o
diff --git a/cpu/arm926ejs/kirkwood/egiga.c b/cpu/arm926ejs/kirkwood/egiga.c
new file mode 100644
index 0000000..609ee0c
--- /dev/null
+++ b/cpu/arm926ejs/kirkwood/egiga.c
@@ -0,0 +1,2169 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Prafulla Wadaskar <prafulla at marvell.com>
+ *
+ * (C) Copyright 2003
+ * Ingo Assmus <ingo.assmus at keymile.com>
+ *
+ * based on - Driver for MV64360X ethernet ports
+ * Copyright (C) 2002 rabeeh at galileo.co.il
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/*
+ * mv_eth.c - header file for the polled mode GT ethernet driver
+ */
+#ifndef KWEGIGA_DEBUG
+#define KWEGIGA_DEBUG 0
+#endif
+#define DEBUG_PRINT	KWEGIGA_DEBUG
+
+#include <common.h>
+#include <net.h>
+#include <malloc.h>
+#include <debug_prints.h>
+#include <../board/Marvell/common/ppc_error_no.h>
+
+#if defined (CONFIG_KIRKWOOD_EGIGA)
+
+/* In case SRAM is cache coherent or non-cacheable */
+#define CONFIG_NOT_COHERENT_CACHE
+#define D_CACHE_FLUSH_LINE(addr, offset) ;
+#define CPU_PIPE_FLUSH	{ __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop");}
+
+#include "egiga.h"
+
+/* PHY_BASE_ADR is board specific and can be configured */
+#if defined (CONFIG_PHY_BASE_ADR)
+#define PHY_BASE_ADR		CONFIG_PHY_BASE_ADR
+#else
+#define PHY_BASE_ADR		0x08	/* default phy base addr */
+#endif
+
+/*************************************************************************
+*  The first part is the high level driver of the gigE ethernet ports.   *
+*************************************************************************/
+
+/* Definition for configuring driver */
+#undef UPDATE_STATS_BY_SOFTWARE
+
+/* Constants */
+#define MAGIC_ETH_RUNNING		8031971
+#define KW_INTERNAL_SRAM_SIZE           _256K
+#define EXTRA_BYTES 32
+#define WRAP       ETH_HLEN + 2 + 4 + 16
+#define BUFFER_MTU dev->mtu + WRAP
+#define INT_CAUSE_UNMASK_ALL		0x0007ffff
+#define INT_CAUSE_UNMASK_ALL_EXT	0x0011ffff
+#ifdef KW_RX_FILL_ON_TASK
+#define INT_CAUSE_MASK_ALL		0x00000000
+#define INT_CAUSE_CHECK_BITS		INT_CAUSE_UNMASK_ALL
+#define INT_CAUSE_CHECK_BITS_EXT	INT_CAUSE_UNMASK_ALL_EXT
+#endif
+
+/*
+ * PHY link detection and printing is not a dependency of egiga controller
+ * By default phy link is assumed to be UP
+ * if you want to detect link by querying phy then,
+ *  configure CONFIG_PHY_LINK_DETECT in board header file
+ *  and provide these functions in board specific code
+ */
+#ifndef CONFIG_PHY_LINK_DETECT
+#define eth_phy_link_status(x)		(TRUE)
+#define egiga_print_phy_status(x)
+#else
+static bool eth_phy_link_status(ETH_PORT prt_num);
+static void egiga_print_phy_status(struct eth_device *dev);
+#endif
+
+/*
+ * eth_smi_reg_read - Read from ethernet phy register.
+ *
+ * INPUT:
+ * @phy_adr - Phy address.
+ * @reg_ofs - Phy register offset.
+ *
+ * This function reads ethernet phy register.
+ * REturns 16bit phy register value, or 0xffff on error
+ */
+int eth_smi_reg_read(u32 eth_port_num, u32 phy_adr, u32 reg_ofs, u16 * data)
+{
+	u32 smi_reg;
+	volatile u32 timeout;
+
+	/* check parameters */
+	if ((phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) {
+		error_print("Illegal PHY device address %d", phy_adr);
+		return -EFAULT;
+	}
+	if ((reg_ofs << KW_ETH_SMI_REG_ADDR_OFFS) & ~KW_ETH_SMI_REG_ADDR_MASK) {
+		error_print("Illegal PHY register offset %d", reg_ofs);
+		return -EFAULT;
+	}
+
+	timeout = ETH_PHY_SMI_TIMEOUT;
+	/* wait till the SMI is not busy */
+	do {
+		/* read smi register */
+		smi_reg = KW_REG_READ(KW_ETH_SMI_REG(eth_port_num));
+		if (timeout-- == 0) {
+			error_print("SMI busy timeout");
+			return -EFAULT;
+		}
+	} while (smi_reg & ETH_PHY_SMI_BUSY_MASK);
+
+	/* fill the phy address and regiser offset and read opcode */
+	smi_reg =
+	    (phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) | (reg_ofs <<
+						      KW_ETH_SMI_REG_ADDR_OFFS)
+	    | ETH_PHY_SMI_OPCODE_READ;
+
+	/* write the smi register */
+	KW_REG_WRITE(KW_ETH_SMI_REG(eth_port_num), smi_reg);
+
+	timeout = ETH_PHY_SMI_TIMEOUT;
+
+	/*wait till readed value is ready */
+	do {
+		/* read smi register */
+		smi_reg = KW_REG_READ(KW_ETH_SMI_REG(eth_port_num));
+
+		if (timeout-- == 0) {
+			error_print("SMI read-valid timeout");
+			return -EFAULT;
+		}
+	} while (!(smi_reg & ETH_PHY_SMI_READ_VALID_MASK));
+
+	/* Wait for the data to update in the SMI register */
+	for (timeout = 0; timeout < ETH_PHY_SMI_TIMEOUT; timeout++) ;
+
+	*data =
+	    (u16) (KW_REG_READ(KW_ETH_SMI_REG(eth_port_num)) &
+		   ETH_PHY_SMI_DATA_MASK);
+
+	debug_print8("Reg(phyadr %d, off %d) Phy-value = %04x", phy_adr,
+		     reg_ofs, *data);
+
+	return 0;
+}
+
+/*
+ * eth_smi_reg_write - Write to ethernet phy register.
+ *
+ * @phy_adr - Phy address.
+ * @reg_ofs - Phy register offset.
+ * @data    - 16bit data.
+ *
+ * This function write to ethernet phy register.
+ * Returns 0 if write succeed, -EINVAL on bad parameters , MV_ERROR on error .
+ * -ETIME on timeout
+ */
+int eth_smi_reg_write(u32 eth_port_num, u32 phy_adr, u32 reg_ofs, u16 data)
+{
+	u32 smi_reg;
+	volatile u32 timeout;
+
+	/* check parameters */
+	if ((phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) & ~ETH_PHY_SMI_DEV_ADDR_MASK) {
+		error_print("Illegal phy address");
+		return -EINVAL;
+	}
+	if ((reg_ofs << KW_ETH_SMI_REG_ADDR_OFFS) & ~KW_ETH_SMI_REG_ADDR_MASK) {
+		error_print("Illegal register offset");
+		return -EINVAL;
+	}
+
+	timeout = ETH_PHY_SMI_TIMEOUT;
+
+	/* wait till the SMI is not busy */
+	do {
+		/* read smi register */
+		smi_reg = KW_REG_READ(KW_ETH_SMI_REG(eth_port_num));
+		if (timeout-- == 0) {
+			error_print("SMI busy timeout");
+			return -ETIME;
+		}
+	} while (smi_reg & ETH_PHY_SMI_BUSY_MASK);
+
+	/* fill the phy address and regiser offset and write opcode and data */
+	smi_reg = (data << ETH_PHY_SMI_DATA_OFFS);
+	smi_reg |=
+	    (phy_adr << ETH_PHY_SMI_DEV_ADDR_OFFS) | (reg_ofs <<
+						      KW_ETH_SMI_REG_ADDR_OFFS);
+	smi_reg &= ~ETH_PHY_SMI_OPCODE_READ;
+
+	/* write the smi register */
+	KW_REG_WRITE(KW_ETH_SMI_REG(eth_port_num), smi_reg);
+
+	return 0;
+
+}
+
+static int egiga_free_tx_rings(struct eth_device *dev)
+{
+	u32 queue;
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	u32 port_num;
+	volatile ETH_TX_DESC *p_tx_curr_desc;
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+
+	/* Stop Tx Queues */
+	KW_REG_WRITE(KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
+
+	/* Free TX rings */
+	debug_print("Clearing previously allocated TX queues... ");
+	for (queue = 0; queue < KW_TX_QUEUE_NUM; queue++) {
+		/* Free on TX rings */
+		for (p_tx_curr_desc =
+		     ethernet_private->p_tx_desc_area_base[queue];
+		     ((u32)p_tx_curr_desc <= (u32)
+		      ethernet_private->p_tx_desc_area_base[queue] +
+		      ethernet_private->tx_desc_area_size[queue]);
+		     p_tx_curr_desc =
+		     (ETH_TX_DESC *) ((u32)p_tx_curr_desc +
+				      TX_DESC_ALIGNED_SIZE)) {
+			/* this is inside for loop */
+			if (p_tx_curr_desc->return_info != 0) {
+				p_tx_curr_desc->return_info = 0;
+				debug_print("freed");
+			}
+		}
+		debug_print("Done");
+	}
+	return 0;
+}
+
+static int egiga_free_rx_rings(struct eth_device *dev)
+{
+	u32 queue;
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	u32 port_num;
+	volatile ETH_RX_DESC *p_rx_curr_desc;
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+
+	/* Stop RX Queues */
+	KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
+
+	/* Free RX rings */
+	debug_print("Clearing previously allocated RX queues... ");
+	for (queue = 0; queue < KW_RX_QUEUE_NUM; queue++) {
+		/* Free preallocated skb's on RX rings */
+		for (p_rx_curr_desc =
+		     ethernet_private->p_rx_desc_area_base[queue];
+		     (((u32)p_rx_curr_desc <
+		       ((u32)ethernet_private->
+			p_rx_desc_area_base[queue] +
+			ethernet_private->rx_desc_area_size[queue])));
+		     p_rx_curr_desc =
+		     (ETH_RX_DESC *) ((u32)p_rx_curr_desc +
+				      RX_DESC_ALIGNED_SIZE)) {
+			if (p_rx_curr_desc->return_info != 0) {
+				p_rx_curr_desc->return_info = 0;
+				debug_print("freed");
+			}
+		}
+		debug_print("Done");
+	}
+	return 0;
+}
+
+static void eth_phy_set_addr(ETH_PORT eth_port_num, int phy_addr)
+{
+	KW_REG_WRITE(KW_ETH_PHY_ADDR_REG(eth_port_num), phy_addr);
+}
+
+#ifdef  UPDATE_STATS_BY_SOFTWARE
+/**********************************************************************
+ * egiga_print_stat
+ *
+ * Update the statistics structure in the private data structure
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ **********************************************************************/
+
+static void egiga_print_stat(struct eth_device *dev)
+{
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	struct net_device_stats *stats;
+	u32 port_num;
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+	stats = port_private->stats;
+
+	/* These are false updates */
+	printf("\n### Network statistics: ###\n");
+	printf("--------------------------\n");
+	printf(" Packets received:		%ld\n", stats->rx_packets);
+	printf(" Packets send:			%ld\n", stats->tx_packets);
+	printf(" Received bytes:		%ld\n", stats->rx_bytes);
+	printf(" Send bytes:			%ld\n", stats->tx_bytes);
+	if (stats->rx_errors != 0)
+		printf(" Rx Errors:			%ld\n",
+		       stats->rx_errors);
+	if (stats->rx_dropped != 0)
+		printf(" Rx dropped (CRC Errors):	%ld\n",
+		       stats->rx_dropped);
+	if (stats->multicast != 0)
+		printf(" Rx mulicast frames:		%ld\n",
+		       stats->multicast);
+	if (stats->collisions != 0)
+		printf(" No. of collisions:		%ld\n",
+		       stats->collisions);
+	if (stats->rx_length_errors != 0)
+		printf(" Rx length errors:		%ld\n",
+		       stats->rx_length_errors);
+}
+#endif
+
+/* Helper function for egiga_stop */
+static int egiga_real_stop(struct eth_device *dev)
+{
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	u32 port_num;
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+
+	egiga_free_tx_rings(dev);
+	egiga_free_rx_rings(dev);
+
+	eth_port_reset(ethernet_private->port_num);
+	/* Disable ethernet port interrupts */
+	KW_REG_WRITE(KW_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+	KW_REG_WRITE(KW_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+	/* Mask RX buffer and TX end interrupt */
+	KW_REG_WRITE(KW_ETH_INTERRUPT_MASK_REG(port_num), 0);
+	/* Mask phy and link status changes interrupts */
+	KW_REG_WRITE(KW_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+	/* make sure CPU interrupts are disabled
+	   KW_REG_BITS_RESET (KW_INTERRUPT0_MASK_HIGH(port_num),
+	   BIT0 << port_num);
+	 */
+
+	/* Print Network statistics */
+#ifdef  UPDATE_STATS_BY_SOFTWARE
+	/*
+	 * Print statistics (only if ethernet is running),
+	 * then zero all the stats fields in memory
+	 */
+	if (port_private->eth_running == MAGIC_ETH_RUNNING) {
+		port_private->eth_running = 0;
+		egiga_print_stat(dev);
+	}
+	memset(port_private->stats, 0, sizeof(struct net_device_stats));
+#endif
+	debug_print("Ethernet stopped ... ");
+	return 0;
+}
+
+/**********************************************************************
+ * kw_egiga_stop
+ *
+ * This function is used when closing the network device.
+ * It updates the hardware,
+ * release all memory that holds buffers and descriptors and release the IRQ.
+ * Input : a pointer to the device structure
+ * Output : zero if success , nonzero if fails
+ *********************************************************************/
+
+int kw_egiga_stop(struct eth_device *dev)
+{
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	u32 port_num;
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+
+	debug_print_ftrace();
+	/* Disable all gigE address decoder */
+	KW_REG_WRITE(KW_ETH_BASE_ADDR_ENABLE_REG(port_num), 0x3f);
+	egiga_real_stop(dev);
+
+	return 0;
+}
+
+/*******************************************************************************
+* eth_clear_mib_counters - Clear all MIB counters
+*
+* DESCRIPTION:
+*       This function clears all MIB counters of a specific ethernet port.
+*       A read from the MIB counter will reset the counter.
+*
+* INPUT:
+*	ETH_PORT    eth_port_num   Ethernet Port number. See ETH_PORT enum.
+*
+* OUTPUT:
+*       After reading all MIB counters, the counters resets.
+*
+* RETURN:
+*       MIB counter value.
+*
+*******************************************************************************/
+static void eth_clear_mib_counters(ETH_PORT eth_port_num)
+{
+	int i;
+	u32 dummy;
+
+	/* Perform dummy reads from MIB counters */
+	for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
+	     i += 4)
+		dummy = KW_REG_READ((KW_ETH_MIB_COUNTERS_BASE
+				     (eth_port_num) + i));
+
+	return;
+}
+
+/*******************************************************************************
+* eth_read_mib_counter - Read a MIB counter
+*
+* DESCRIPTION:
+*       This function reads a MIB counter of a specific ethernet port.
+*       NOTE - If read from ETH_MIB_GOOD_OCTETS_RECEIVED_LOW, then the
+*       following read must be from ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH
+*       register. The same applies for ETH_MIB_GOOD_OCTETS_SENT_LOW and
+*       ETH_MIB_GOOD_OCTETS_SENT_HIGH
+*
+* INPUT:
+*	ETH_PORT    eth_port_num   Ethernet Port number. See ETH_PORT enum.
+*       u32 mib_offset   MIB counter offset (use ETH_MIB_... macros).
+*
+* OUTPUT:
+*       After reading the MIB counter, the counter resets.
+*
+* RETURN:
+*       MIB counter value.
+*
+*******************************************************************************/
+u32 eth_read_mib_counter(ETH_PORT eth_port_num,
+				  u32 mib_offset)
+{
+	return (KW_REG_READ((KW_ETH_MIB_COUNTERS_BASE(eth_port_num)
+			     + mib_offset)));
+}
+
+
+/**********************************************************************
+ * egiga_update_stat
+ *
+ * Update the statistics structure in the private data structure
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ **********************************************************************/
+
+static void egiga_update_stat(struct eth_device *dev)
+{
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	struct net_device_stats *stats;
+	u32 port_num;
+	volatile u32 dummy;
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+	stats = port_private->stats;
+
+	/* These are false updates */
+	stats->rx_packets += (unsigned long)
+	    eth_read_mib_counter(ethernet_private->port_num,
+				 ETH_MIB_GOOD_FRAMES_RECEIVED);
+	stats->tx_packets += (unsigned long)
+	    eth_read_mib_counter(ethernet_private->port_num,
+				 ETH_MIB_GOOD_FRAMES_SENT);
+	stats->rx_bytes += (unsigned long)
+	    eth_read_mib_counter(ethernet_private->port_num,
+				 ETH_MIB_GOOD_OCTETS_RECEIVED_LOW);
+	/*
+	 * Ideally this should be as follows -
+	 *
+	 *   stats->rx_bytes   += stats->rx_bytes +
+	 * ((unsigned long) ethReadMibCounter (ethernet_private->port_num ,
+	 * ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH) << 32);
+	 *
+	 * But the unsigned long in PowerPC and MIPS are 32bit. So the next read
+	 * is just a dummy read for proper work of the GigE port
+	 */
+	dummy = eth_read_mib_counter(ethernet_private->port_num,
+				     ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH);
+	stats->tx_bytes += (unsigned long)
+	    eth_read_mib_counter(ethernet_private->port_num,
+				 ETH_MIB_GOOD_OCTETS_SENT_LOW);
+	dummy = eth_read_mib_counter(ethernet_private->port_num,
+				     ETH_MIB_GOOD_OCTETS_SENT_HIGH);
+	stats->rx_errors += (unsigned long)
+	    eth_read_mib_counter(ethernet_private->port_num,
+				 ETH_MIB_MAC_RECEIVE_ERROR);
+
+	/* Rx dropped is for received packet with CRC error */
+	stats->rx_dropped +=
+	    (unsigned long)eth_read_mib_counter(ethernet_private->
+						port_num,
+						ETH_MIB_BAD_CRC_EVENT);
+	stats->multicast += (unsigned long)
+	    eth_read_mib_counter(ethernet_private->port_num,
+				 ETH_MIB_MULTICAST_FRAMES_RECEIVED);
+	stats->collisions +=
+	    (unsigned long)eth_read_mib_counter(ethernet_private->
+						port_num,
+						ETH_MIB_COLLISION) +
+	    (unsigned long)eth_read_mib_counter(ethernet_private->
+						port_num,
+						ETH_MIB_LATE_COLLISION);
+	/* detailed rx errors */
+	stats->rx_length_errors +=
+	    (unsigned long)eth_read_mib_counter(ethernet_private->
+						port_num,
+						ETH_MIB_UNDERSIZE_RECEIVED)
+	    +
+	    (unsigned long)eth_read_mib_counter(ethernet_private->
+						port_num,
+						ETH_MIB_OVERSIZE_RECEIVED);
+	/* detailed tx errors */
+}
+
+/**********************************************************************
+ * egiga_get_stats
+ *
+ * Returns a pointer to the interface statistics.
+ *
+ * Input : dev - a pointer to the required interface
+ *
+ * Output : a pointer to the interface's statistics
+ **********************************************************************/
+
+static struct net_device_stats *egiga_get_stats(struct eth_device *dev)
+{
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	u32 port_num;
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+
+	egiga_update_stat(dev);
+
+	return port_private->stats;
+}
+
+/*************************************************************************
+*  The second part is the low level driver of the gigE ethernet ports.   *
+*************************************************************************/
+
+/* defines */
+/* SDMA command macros */
+#define ETH_ENABLE_TX_QUEUE(tx_queue, eth_port) \
+ KW_REG_WRITE(KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), (1 << tx_queue))
+
+#define CURR_RFD_GET(p_curr_desc, queue) \
+ ((p_curr_desc) = p_eth_port_ctrl->p_rx_curr_desc_q[queue])
+
+#define CURR_RFD_SET(p_curr_desc, queue) \
+ (p_eth_port_ctrl->p_rx_curr_desc_q[queue] = (p_curr_desc))
+
+#define USED_RFD_GET(p_used_desc, queue) \
+ ((p_used_desc) = p_eth_port_ctrl->p_rx_used_desc_q[queue])
+
+#define USED_RFD_SET(p_used_desc, queue)\
+(p_eth_port_ctrl->p_rx_used_desc_q[queue] = (p_used_desc))
+
+#define CURR_TFD_GET(p_curr_desc, queue) \
+ ((p_curr_desc) = p_eth_port_ctrl->p_tx_curr_desc_q[queue])
+
+#define CURR_TFD_SET(p_curr_desc, queue) \
+ (p_eth_port_ctrl->p_tx_curr_desc_q[queue] = (p_curr_desc))
+
+#define USED_TFD_GET(p_used_desc, queue) \
+ ((p_used_desc) = p_eth_port_ctrl->p_tx_used_desc_q[queue])
+
+#define USED_TFD_SET(p_used_desc, queue) \
+ (p_eth_port_ctrl->p_tx_used_desc_q[queue] = (p_used_desc))
+
+#define FIRST_TFD_GET(p_first_desc, queue) \
+ ((p_first_desc) = p_eth_port_ctrl->p_tx_first_desc_q[queue])
+
+#define FIRST_TFD_SET(p_first_desc, queue) \
+ (p_eth_port_ctrl->p_tx_first_desc_q[queue] = (p_first_desc))
+
+/* Macros that save access to desc in order to find next desc pointer  */
+#define RX_NEXT_DESC_PTR(p_rx_desc, queue) 	( \
+	ETH_RX_DESC*)(((((u32)p_rx_desc - \
+	(u32)p_eth_port_ctrl->p_rx_desc_area_base[queue]) + \
+	RX_DESC_ALIGNED_SIZE) % p_eth_port_ctrl->rx_desc_area_size[queue]) + \
+	(u32)p_eth_port_ctrl->p_rx_desc_area_base[queue])
+
+#define TX_NEXT_DESC_PTR(p_tx_desc, queue) 	( \
+	ETH_TX_DESC*)(((((u32)p_tx_desc - \
+	(u32)p_eth_port_ctrl->p_tx_desc_area_base[queue]) + \
+	TX_DESC_ALIGNED_SIZE) % p_eth_port_ctrl->tx_desc_area_size[queue]) + \
+	(u32)p_eth_port_ctrl->p_tx_desc_area_base[queue])
+
+/*******************************************************************************
+ * eth_set_access_control - Config address decode parameters for Ethernet unit
+ *
+ * DESCRIPTION:
+ *       This function configures the address decode parameters for the Gigabit
+ *       Ethernet Controller according the given parameters struct.
+ *
+ * INPUT:
+ *	ETH_PORT   eth_port_num   Ethernet Port number. See ETH_PORT enum.
+ *       ETH_WIN_PARAM  *param   Address decode parameter struct.
+ *
+ * OUTPUT:
+ *       An access window is opened using the given access parameters.
+ *
+ * RETURN:
+ *       None.
+ *
+ *******************************************************************************/
+static void eth_set_access_control(ETH_PORT eth_port_num, ETH_WIN_PARAM * param)
+{
+	u32 access_prot_reg;
+
+	debug_print_ftrace();
+	/* Set access control register */
+	access_prot_reg = KW_REG_READ(KW_ETH_ACCESS_PROTECTION_REG
+				      (eth_port_num));
+	access_prot_reg &= (~(3 << (param->win * 2)));	/* clear window permission */
+	access_prot_reg |= (param->access_ctrl << (param->win * 2));
+	KW_REG_WRITE(KW_ETH_ACCESS_PROTECTION_REG(eth_port_num),
+		     access_prot_reg);
+
+	/* Set window Size reg (SR) */
+	KW_REG_WRITE((KW_ETH_SIZE_REG_0(eth_port_num) +
+		      (ETH_SIZE_REG_GAP * param->win)),
+		     (((param->size / 0x10000) - 1) << 16));
+
+	/* Set window Base address reg (BA) */
+	KW_REG_WRITE((KW_ETH_BAR_0(eth_port_num) + (ETH_BAR_GAP * param->win)),
+		     (param->target | param->attributes | param->base_addr));
+	/* High address remap reg (HARR) */
+	if (param->win < 4)
+		KW_REG_WRITE((KW_ETH_HIGH_ADDR_REMAP_REG_0(eth_port_num) +
+			      (ETH_HIGH_ADDR_REMAP_REG_GAP * param->win)),
+			     param->high_addr);
+
+	/* Base address enable reg (BARER) */
+	if (param->enable == 1)
+		KW_REG_BITS_RESET(KW_ETH_BASE_ADDR_ENABLE_REG(eth_port_num),
+				  (1 << param->win));
+	else
+		KW_REG_BITS_SET(KW_ETH_BASE_ADDR_ENABLE_REG(eth_port_num),
+				(1 << param->win));
+}
+
+static void eth_set_access_control_for_dram(u32 port_num)
+{
+	ETH_WIN_PARAM win_param;
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		/* Set access parameters for DRAM bank i */
+		win_param.win = i;	/* Use Ethernet window i */
+		win_param.target = ETH_TARGET_DRAM;	/* Window target - DDR  */
+		win_param.access_ctrl = EWIN_ACCESS_FULL; /* Enable full access */
+		win_param.high_addr = 0;
+		/* Get bank base */
+		win_param.base_addr = kw_get_dram_bank_base_addr(i);
+		win_param.size = kw_get_dram_bank_size(i);	/* Get bank size */
+		if (win_param.size == 0)
+			win_param.enable = 0;
+		else
+			win_param.enable = 1;	/* Enable the access */
+		switch(i) {
+		case 0:
+			/* Enable DRAM bank 0  */
+			win_param.attributes = EBAR_ATTR_DRAM_CS0;
+			break;
+		case 1:
+			/* Enable DRAM bank 1  */
+			win_param.attributes = EBAR_ATTR_DRAM_CS1;
+			break;
+		case 2:
+			/* Enable DRAM bank 2  */
+			win_param.attributes = EBAR_ATTR_DRAM_CS2;
+			break;
+		case 3:
+			/* Enable DRAM bank 3  */
+			win_param.attributes = EBAR_ATTR_DRAM_CS3;
+			break;
+		default:
+			/* invalide bank, disable access */
+			win_param.enable = 0;
+			win_param.attributes = 0;
+			break;
+		}
+#ifndef CONFIG_NOT_COHERENT_CACHE
+		win_param.attributes |= EBAR_ATTR_DRAM_CACHE_COHERENCY_WB;
+#endif
+		/* Set the access control for address window (EPAPR) READ & WRITE */
+		eth_set_access_control(port_num, &win_param);
+	}
+}
+
+/*******************************************************************************
+* eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
+*
+* DESCRIPTION:
+*       Go through all the DA filter tables (Unicast, Special Multicast & Other
+*       Multicast) and set each entry to 0.
+*
+* INPUT:
+*	ETH_PORT    eth_port_num   Ethernet Port number. See ETH_PORT enum.
+*
+* OUTPUT:
+*       Multicast and Unicast packets are rejected.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static void eth_port_init_mac_tables(ETH_PORT eth_port_num)
+{
+	int table_index;
+
+	/* Clear DA filter unicast table (Ex_dFUT) */
+	for (table_index = 0; table_index <= 0xC; table_index += 4)
+		KW_REG_WRITE((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE
+			      (eth_port_num) + table_index), 0);
+
+	for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+		/* Clear DA filter special multicast table (Ex_dFSMT) */
+		KW_REG_WRITE((KW_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+			      (eth_port_num) + table_index), 0);
+		/* Clear DA filter other multicast table (Ex_dFOMT) */
+		KW_REG_WRITE((KW_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+			      (eth_port_num) + table_index), 0);
+	}
+}
+
+/*******************************************************************************
+* eth_port_init - Initialize the Ethernet port driver
+*
+* DESCRIPTION:
+*       This function prepares the ethernet port to start its activity:
+*       1) Completes the ethernet port driver struct initialization toward port
+*           start routine.
+*       2) Resets the device to a quiescent state in case of warm reboot.
+*       3) Enable SDMA access to all four DRAM banks as well as internal SRAM.
+*       4) Clean MAC tables. The reset status of those tables is unknown.
+*       5) Set PHY address.
+*       Note: Call this routine prior to eth_port_start routine and after setting
+*       user values in the user fields of Ethernet port control struct (i.e.
+*       port_phy_addr).
+*
+* INPUT:
+*       ETH_PORT_INFO 	*p_eth_port_ctrl       Ethernet port control struct
+*
+* OUTPUT:
+*       See description.
+*
+* RETURN:
+*       None.
+*
+*******************************************************************************/
+static void eth_port_init(ETH_PORT_INFO * p_eth_port_ctrl)
+{
+	int queue;
+	u32 port_num = p_eth_port_ctrl->port_num;
+
+	p_eth_port_ctrl->port_config = PORT_CONFIG_VALUE;
+	p_eth_port_ctrl->port_config_extend = PORT_CONFIG_EXTEND_VALUE;
+	p_eth_port_ctrl->port_sdma_config = PORT_SDMA_CONFIG_VALUE;
+	p_eth_port_ctrl->port_serial_control = PORT_SERIAL_CONTROL_VALUE;
+
+	p_eth_port_ctrl->port_rx_queue_command = 0;
+	p_eth_port_ctrl->port_tx_queue_command = 0;
+
+	/* Stop RX Queues */
+	KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
+
+	/* Clear the ethernet port interrupts */
+	KW_REG_WRITE(KW_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+	KW_REG_WRITE(KW_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+
+	/* Unmask RX buffer and TX end interrupt */
+	KW_REG_WRITE(KW_ETH_INTERRUPT_MASK_REG(port_num), INT_CAUSE_UNMASK_ALL);
+
+	/* Unmask phy and link status changes interrupts */
+	KW_REG_WRITE(KW_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+		     INT_CAUSE_UNMASK_ALL_EXT);
+
+	/* Zero out SW structs */
+	for (queue = 0; queue < MAX_RX_QUEUE_NUM; queue++) {
+		CURR_RFD_SET((ETH_RX_DESC *) 0x00000000, queue);
+		USED_RFD_SET((ETH_RX_DESC *) 0x00000000, queue);
+		p_eth_port_ctrl->rx_resource_err[queue] = false;
+	}
+
+	for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) {
+		CURR_TFD_SET((ETH_TX_DESC *) 0x00000000, queue);
+		USED_TFD_SET((ETH_TX_DESC *) 0x00000000, queue);
+		FIRST_TFD_SET((ETH_TX_DESC *) 0x00000000, queue);
+		p_eth_port_ctrl->tx_resource_err[queue] = false;
+	}
+
+	eth_port_reset(port_num);
+
+	eth_set_access_control_for_dram(port_num);
+
+	eth_port_init_mac_tables(port_num);
+}
+
+
+/*******************************************************************************
+* eth_port_start - Start the Ethernet port activity.
+*
+* DESCRIPTION:
+*       This routine prepares the Ethernet port for Rx and Tx activity:
+*       1. Initialize Tx and Rx Current Descriptor Pointer for each queue that
+*           has been initialized a descriptor's ring (using kw_egiga_init_tx_desc_ring
+*           for Tx and kw_egiga_init_rx_desc_ring for Rx)
+*       2. Initialize and enable the Ethernet configuration port by writing to
+*           the port's configuration and command registers.
+*       3. Initialize and enable the SDMA by writing to the SDMA's
+*    configuration and command registers.
+*       After completing these steps, the ethernet port SDMA can starts to
+*       perform Rx and Tx activities.
+*
+*       Note: Each Rx and Tx queue descriptor's list must be initialized prior
+*       to calling this function (use kw_egiga_init_tx_desc_ring for Tx queues and
+*       kw_egiga_init_rx_desc_ring for Rx queues).
+*
+* INPUT:
+*       ETH_PORT_INFO 	*p_eth_port_ctrl       Ethernet port control struct
+*
+* OUTPUT:
+*       Ethernet port is ready to receive and transmit.
+*
+* RETURN:
+*       false if the port PHY is not up.
+*       true otherwise.
+*
+*******************************************************************************/
+static void eth_port_start(ETH_PORT_INFO * p_eth_port_ctrl)
+{
+	int queue;
+	volatile ETH_TX_DESC *p_tx_curr_desc;
+	volatile ETH_RX_DESC *p_rx_curr_desc;
+	ETH_PORT eth_port_num = p_eth_port_ctrl->port_num;
+
+	/* Assignment of Tx CTRP of given queue */
+	for (queue = 0; queue < MAX_TX_QUEUE_NUM; queue++) {
+		CURR_TFD_GET(p_tx_curr_desc, queue);
+		KW_REG_WRITE((KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num)
+			      + (4 * queue)), ((u32)p_tx_curr_desc));
+
+	}
+
+	/* Assignment of Rx CRDB of given queue */
+	for (queue = 0; queue < MAX_RX_QUEUE_NUM; queue++) {
+		CURR_RFD_GET(p_rx_curr_desc, queue);
+		KW_REG_WRITE((KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num)
+			      + (4 * queue)), ((u32)p_rx_curr_desc));
+
+		if (p_rx_curr_desc != NULL)
+			/* Add the assigned Ethernet address to the port's address table */
+			eth_port_uc_addr_set(p_eth_port_ctrl->port_num,
+					     p_eth_port_ctrl->port_mac_addr,
+					     queue);
+	}
+
+	/* Assign port configuration and command. */
+	KW_REG_WRITE(KW_ETH_PORT_CONFIG_REG(eth_port_num),
+		     p_eth_port_ctrl->port_config);
+
+	KW_REG_WRITE(KW_ETH_PORT_CONFIG_EXTEND_REG(eth_port_num),
+		     p_eth_port_ctrl->port_config_extend);
+
+	KW_REG_WRITE(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num),
+		     p_eth_port_ctrl->port_serial_control);
+
+	KW_REG_BITS_SET(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num),
+			ETH_SERIAL_PORT_ENABLE);
+
+	/* Assign port SDMA configuration */
+	KW_REG_WRITE(KW_ETH_SDMA_CONFIG_REG(eth_port_num),
+		     p_eth_port_ctrl->port_sdma_config);
+
+	KW_REG_WRITE(KW_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT
+		     (eth_port_num), 0x3fffffff);
+	KW_REG_WRITE(KW_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG
+		     (eth_port_num), 0x03fffcff);
+	/* Turn off the port/queue bandwidth limitation */
+	KW_REG_WRITE(KW_ETH_MAXIMUM_TRANSMIT_UNIT(eth_port_num), 0x0);
+
+	/* Enable port Rx. */
+	KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num),
+		     p_eth_port_ctrl->port_rx_queue_command);
+
+	/* Set maximum receive buffer to 9700 bytes */
+	KW_REG_WRITE(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num),
+		     (0x5 << 17) |
+		     (KW_REG_READ(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num))
+		      & 0xfff1ffff));
+
+	/*
+	 * Set ethernet MTU for leaky bucket mechanism to 0 - this will
+	 * disable the leaky bucket mechanism .
+	 */
+	KW_REG_WRITE(KW_ETH_MAXIMUM_TRANSMIT_UNIT(eth_port_num), 0);
+}
+
+/*******************************************************************************
+* eth_port_uc_addr - This function Set the port unicast address table
+*
+* DESCRIPTION:
+*	This function locates the proper entry in the Unicast table for the
+*	specified MAC nibble and sets its properties according to function
+*	parameters.
+*
+* INPUT:
+*	ETH_PORT 	eth_port_num      Port number.
+*	u8 uc_nibble		Unicast MAC Address last nibble.
+*	ETH_QUEUE 		 queue		Rx queue number for this MAC address.
+*	int 			option      0 = Add, 1 = remove address.
+*
+* OUTPUT:
+*	This function add/removes MAC addresses from the port unicast address
+*	table.
+*
+* RETURN:
+*	true is output succeeded.
+*	false if option parameter is invalid.
+*
+*******************************************************************************/
+static bool eth_port_uc_addr(ETH_PORT eth_port_num,
+			     u8 uc_nibble,
+			     ETH_QUEUE queue, int option)
+{
+	u32 unicast_reg;
+	u32 tbl_offset;
+	u32 reg_offset;
+
+	/* Locate the Unicast table entry */
+	uc_nibble = (0xf & uc_nibble);
+	tbl_offset = (uc_nibble / 4) * 4;	/* Register offset from unicast table base */
+	reg_offset = uc_nibble % 4;	/* Entry offset within the above register */
+
+	switch (option) {
+	case REJECT_MAC_ADDR:
+		/* Clear accepts frame bit at specified unicast DA table entry */
+		unicast_reg =
+		    KW_REG_READ((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE
+				 (eth_port_num)
+				 + tbl_offset));
+
+		unicast_reg &= (0xFF << (8 * reg_offset));
+
+		KW_REG_WRITE((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE(eth_port_num)
+			      + tbl_offset), unicast_reg);
+		break;
+
+	case ACCEPT_MAC_ADDR:
+		/* Set accepts frame bit at unicast DA filter table entry */
+		unicast_reg =
+		    KW_REG_READ((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE
+				 (eth_port_num)
+				 + tbl_offset));
+
+		unicast_reg &= (0xFF << (8 * reg_offset));
+		unicast_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset));
+
+		KW_REG_WRITE((KW_ETH_DA_FILTER_UNICAST_TABLE_BASE(eth_port_num)
+			      + tbl_offset), unicast_reg);
+
+		break;
+
+	default:
+		return false;
+	}
+	return true;
+}
+
+/*******************************************************************************
+* eth_port_uc_addr_set - This function Set the port Unicast address.
+*
+* DESCRIPTION:
+*		This function Set the port Ethernet MAC address.
+*
+* INPUT:
+*	ETH_PORT eth_port_num     Port number.
+*	char *        p_addr		Address to be set
+*	ETH_QUEUE 	  queue		Rx queue number for this MAC address.
+*
+* OUTPUT:
+*	Set MAC address low and high registers. also calls eth_port_uc_addr()
+*       To set the unicast table with the proper information.
+*
+* RETURN:
+*	N/A.
+*
+*******************************************************************************/
+static void eth_port_uc_addr_set(ETH_PORT eth_port_num,
+				 u8 *p_addr, ETH_QUEUE queue)
+{
+	u32 mac_h;
+	u32 mac_l;
+
+	mac_l = (p_addr[4] << 8) | (p_addr[5]);
+	mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) |
+	    (p_addr[2] << 8) | (p_addr[3] << 0);
+
+	KW_REG_WRITE(KW_ETH_MAC_ADDR_LOW(eth_port_num), mac_l);
+	KW_REG_WRITE(KW_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h);
+
+	/* Accept frames of this address */
+	eth_port_uc_addr(eth_port_num, p_addr[5], queue, ACCEPT_MAC_ADDR);
+
+	return;
+}
+/*******************************************************************************
+ * eth_port_reset - Reset Ethernet port
+ *
+ * DESCRIPTION:
+ * 	This routine resets the chip by aborting any SDMA engine activity and
+ *      clearing the MIB counters. The Receiver and the Transmit unit are in
+ *      idle state after this command is performed and the port is disabled.
+ *
+ * INPUT:
+ *	ETH_PORT   eth_port_num   Ethernet Port number. See ETH_PORT enum.
+ *
+ * OUTPUT:
+ *       Channel activity is halted.
+ *
+ * RETURN:
+ *       None.
+ *
+ *******************************************************************************/
+static void eth_port_reset(ETH_PORT eth_port_num)
+{
+	u32 reg_data, i;
+
+	/* Stop Tx port activity. Check port Tx activity. */
+	reg_data = KW_REG_READ(KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port_num));
+
+	if (reg_data & 0xFF) {
+		/* Issue stop command for active channels only */
+		KW_REG_WRITE(KW_ETH_TRANSMIT_QUEUE_COMMAND_REG
+			     (eth_port_num), (reg_data << 8));
+
+		/* Wait for all Tx activity to terminate. */
+		do {
+			/* Check port cause register that all Tx queues are stopped */
+			reg_data =
+			    KW_REG_READ
+			    (KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port_num));
+		}
+		while (reg_data & 0xFF);
+	}
+
+	/* Stop Rx port activity. Check port Rx activity. */
+	reg_data = KW_REG_READ(KW_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num));
+
+	if (reg_data & 0xFF) {
+		/* Issue stop command for active channels only */
+		KW_REG_WRITE(KW_ETH_RECEIVE_QUEUE_COMMAND_REG
+			     (eth_port_num), (reg_data << 8));
+
+		/* Wait for all Rx activity to terminate. */
+		do {
+			/* Check port cause register that all Rx queues are stopped */
+			reg_data =
+			    KW_REG_READ
+			    (KW_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num));
+		}
+		while (reg_data & 0xFF);
+	}
+
+	/* Clear all MIB counters */
+	eth_clear_mib_counters(eth_port_num);
+
+	/* Enable port in the Configuration Register */
+	KW_REG_BITS_RESET(KW_ETH_PORT_SERIAL_CONTROL0_REG(eth_port_num),
+			  ETH_SERIAL_PORT_ENABLE);
+	/* Set port of active in the Configuration Register */
+	KW_REG_BITS_RESET(KW_ETH_PORT_SERIAL_CONTROL1_REG(eth_port_num), BIT4);
+#ifdef CONFIG_SYS_MII_MODE
+	/* Set MMI interface up */
+	KW_REG_BITS_RESET(KW_ETH_PORT_SERIAL_CONTROL1_REG(eth_port_num), BIT3);
+#endif
+
+	for (i = 0; i < 4000; i++) ;
+	return;
+}
+
+/*******************************************************************************
+ * kw_egiga_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
+ *
+ * DESCRIPTION:
+ *       This function prepares a Rx chained list of descriptors and packet
+ *       buffers in a form of a ring. The routine must be called after port
+ *       initialization routine and before port start routine.
+ *       The Ethernet SDMA engine uses CPU bus addresses to access the various
+ *       devices in the system (i.e. DRAM). This function uses the ethernet
+ *       struct 'virtual to physical' routine (set by the user) to set the ring
+ *       with physical addresses.
+ *
+ * INPUT:
+ *	ETH_PORT_INFO   *p_eth_port_ctrl   Ethernet Port Control srtuct.
+ *	ETH_QUEUE   	rx_queue         Number of Rx queue.
+ *      int 			rx_desc_num       Number of Rx descriptors
+ *      int 			rx_buff_size      Size of Rx buffer
+ *      u32    rx_desc_base_addr  Rx descriptors memory area base addr.
+ *      u32    rx_buff_base_addr  Rx buffer memory area base addr.
+ *
+ * OUTPUT:
+ *      The routine updates the Ethernet port control struct with information
+ *      regarding the Rx descriptors and buffers.
+ *
+ * RETURN:
+ *      false if the given descriptors memory area is not aligned according to
+ *      Ethernet SDMA specifications.
+ *      true otherwise.
+ *
+ *******************************************************************************/
+static bool kw_egiga_init_rx_desc_ring(ETH_PORT_INFO * p_eth_port_ctrl,
+				    ETH_QUEUE rx_queue,
+				    int rx_desc_num,
+				    int rx_buff_size,
+				    u32 rx_desc_base_addr,
+				    u32 rx_buff_base_addr)
+{
+	ETH_RX_DESC *p_rx_desc;
+	ETH_RX_DESC *p_rx_prev_desc;	/* pointer to link with the last descriptor */
+	u32 buffer_addr;
+	int ix;			/* a counter */
+
+	p_rx_desc = (ETH_RX_DESC *) rx_desc_base_addr;
+	p_rx_prev_desc = p_rx_desc;
+	buffer_addr = rx_buff_base_addr;
+
+	/* Rx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
+	if (rx_buff_base_addr & 0xF)
+		return false;
+
+	/* Rx buffers are limited to 64K bytes and Minimum size is 8 bytes  */
+	if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE))
+		return false;
+
+	/* Rx buffers must be 64-bit aligned.       */
+	if ((rx_buff_base_addr + rx_buff_size) & 0x7)
+		return false;
+
+	/* initialize the Rx descriptors ring */
+	for (ix = 0; ix < rx_desc_num; ix++) {
+		p_rx_desc->buf_size = rx_buff_size;
+		p_rx_desc->byte_cnt = 0x0000;
+		p_rx_desc->cmd_sts =
+		    ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+		p_rx_desc->next_desc_ptr =
+		    ((u32)p_rx_desc) + RX_DESC_ALIGNED_SIZE;
+		p_rx_desc->buf_ptr = buffer_addr;
+		p_rx_desc->return_info = 0x00000000;
+		D_CACHE_FLUSH_LINE(p_rx_desc, 0);
+		buffer_addr += rx_buff_size;
+		p_rx_prev_desc = p_rx_desc;
+		p_rx_desc = (ETH_RX_DESC *)
+		    ((u32)p_rx_desc + RX_DESC_ALIGNED_SIZE);
+	}
+
+	/* Closing Rx descriptors ring */
+	p_rx_prev_desc->next_desc_ptr = (rx_desc_base_addr);
+	D_CACHE_FLUSH_LINE(p_rx_prev_desc, 0);
+
+	/* Save Rx desc pointer to driver struct. */
+	CURR_RFD_SET((ETH_RX_DESC *) rx_desc_base_addr, rx_queue);
+	USED_RFD_SET((ETH_RX_DESC *) rx_desc_base_addr, rx_queue);
+
+	p_eth_port_ctrl->p_rx_desc_area_base[rx_queue] =
+	    (ETH_RX_DESC *) rx_desc_base_addr;
+	p_eth_port_ctrl->rx_desc_area_size[rx_queue] =
+	    rx_desc_num * RX_DESC_ALIGNED_SIZE;
+
+	p_eth_port_ctrl->port_rx_queue_command |= (1 << rx_queue);
+
+	return true;
+}
+
+/*******************************************************************************
+ * kw_egiga_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory.
+ *
+ * DESCRIPTION:
+ *       This function prepares a Tx chained list of descriptors and packet
+ *       buffers in a form of a ring. The routine must be called after port
+ *       initialization routine and before port start routine.
+ *       The Ethernet SDMA engine uses CPU bus addresses to access the various
+ *       devices in the system (i.e. DRAM). This function uses the ethernet
+ *       struct 'virtual to physical' routine (set by the user) to set the ring
+ *       with physical addresses.
+ *
+ * INPUT:
+ *	ETH_PORT_INFO   *p_eth_port_ctrl   Ethernet Port Control srtuct.
+ *	ETH_QUEUE   	tx_queue         Number of Tx queue.
+ *      int 			tx_desc_num       Number of Tx descriptors
+ *      int 			tx_buff_size      Size of Tx buffer
+ *      u32    tx_desc_base_addr  Tx descriptors memory area base addr.
+ *      u32    tx_buff_base_addr  Tx buffer memory area base addr.
+ *
+ * OUTPUT:
+ *      The routine updates the Ethernet port control struct with information
+ *      regarding the Tx descriptors and buffers.
+ *
+ * RETURN:
+ *      false if the given descriptors memory area is not aligned according to
+ *      Ethernet SDMA specifications.
+ *      true otherwise.
+ *
+ *******************************************************************************/
+static bool kw_egiga_init_tx_desc_ring(ETH_PORT_INFO * p_eth_port_ctrl,
+				    ETH_QUEUE tx_queue,
+				    int tx_desc_num,
+				    int tx_buff_size,
+				    u32 tx_desc_base_addr,
+				    u32 tx_buff_base_addr)
+{
+
+	ETH_TX_DESC *p_tx_desc;
+	ETH_TX_DESC *p_tx_prev_desc;
+	u32 buffer_addr;
+	int ix;			/* a counter */
+
+	/* save the first desc pointer to link with the last descriptor */
+	p_tx_desc = (ETH_TX_DESC *) tx_desc_base_addr;
+	p_tx_prev_desc = p_tx_desc;
+	buffer_addr = tx_buff_base_addr;
+
+	/* Tx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
+	if (tx_buff_base_addr & 0xF)
+		return false;
+
+	/* Tx buffers are limited to 64K bytes and Minimum size is 8 bytes  */
+	if ((tx_buff_size > TX_BUFFER_MAX_SIZE)
+	    || (tx_buff_size < TX_BUFFER_MIN_SIZE))
+		return false;
+
+	/* Initialize the Tx descriptors ring */
+	for (ix = 0; ix < tx_desc_num; ix++) {
+		p_tx_desc->byte_cnt = 0x0000;
+		p_tx_desc->l4i_chk = 0x0000;
+		p_tx_desc->cmd_sts = 0x00000000;
+		p_tx_desc->next_desc_ptr =
+		    ((u32)p_tx_desc) + TX_DESC_ALIGNED_SIZE;
+
+		p_tx_desc->buf_ptr = buffer_addr;
+		p_tx_desc->return_info = 0x00000000;
+		D_CACHE_FLUSH_LINE(p_tx_desc, 0);
+		buffer_addr += tx_buff_size;
+		p_tx_prev_desc = p_tx_desc;
+		p_tx_desc = (ETH_TX_DESC *)
+		    ((u32)p_tx_desc + TX_DESC_ALIGNED_SIZE);
+
+	}
+	/* Closing Tx descriptors ring */
+	p_tx_prev_desc->next_desc_ptr = tx_desc_base_addr;
+	D_CACHE_FLUSH_LINE(p_tx_prev_desc, 0);
+	/* Set Tx desc pointer in driver struct. */
+	CURR_TFD_SET((ETH_TX_DESC *) tx_desc_base_addr, tx_queue);
+	USED_TFD_SET((ETH_TX_DESC *) tx_desc_base_addr, tx_queue);
+
+	/* Init Tx ring base and size parameters */
+	p_eth_port_ctrl->p_tx_desc_area_base[tx_queue] =
+	    (ETH_TX_DESC *) tx_desc_base_addr;
+	p_eth_port_ctrl->tx_desc_area_size[tx_queue] =
+	    (tx_desc_num * TX_DESC_ALIGNED_SIZE);
+
+	/* Add the queue to the list of Tx queues of this port */
+	p_eth_port_ctrl->port_tx_queue_command |= (1 << tx_queue);
+
+	return true;
+}
+
+/*******************************************************************************
+ * eth_b_copy - Copy bytes from source to destination
+ *
+ * DESCRIPTION:
+ *       This function supports the eight bytes limitation on Tx buffer size.
+ *       The routine will zero eight bytes starting from the destination address
+ *       followed by copying bytes from the source address to the destination.
+ *
+ * INPUT:
+ *       u32 src_addr    32 bit source address.
+ *       u32 dst_addr    32 bit destination address.
+ *       int        byte_count    Number of bytes to copy.
+ *
+ * OUTPUT:
+ *       See description.
+ *
+ * RETURN:
+ *       None.
+ *
+ *******************************************************************************/
+static void eth_b_copy(u32 src_addr, u32 dst_addr,
+		       int byte_count)
+{
+	/* Zero the dst_addr area */
+	*(u32 *)dst_addr = 0x0;
+
+	while (byte_count != 0) {
+		*(char *)dst_addr = *(char *)src_addr;
+		dst_addr++;
+		src_addr++;
+		byte_count--;
+	}
+}
+
+/*******************************************************************************
+ * eth_port_send - Send an Ethernet packet
+ *
+ * DESCRIPTION:
+ *	This routine send a given packet described by p_pktinfo parameter. It
+ *      supports transmitting of a packet spaned over multiple buffers. The
+ *      routine updates 'curr' and 'first' indexes according to the packet
+ *      segment passed to the routine. In case the packet segment is first,
+ *      the 'first' index is update. In any case, the 'curr' index is updated.
+ *      If the routine get into Tx resource error it assigns 'curr' index as
+ *      'first'. This way the function can abort Tx process of multiple
+ *      descriptors per packet.
+ *
+ * INPUT:
+ *	ETH_PORT_INFO   *p_eth_port_ctrl   Ethernet Port Control srtuct.
+ *	ETH_QUEUE   	tx_queue         Number of Tx queue.
+ *	PKT_INFO        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *	Tx ring 'curr' and 'first' indexes are updated.
+ *
+ * RETURN:
+ *      ETH_QUEUE_FULL in case of Tx resource error.
+ *	ETH_ERROR in case the routine can not access Tx desc ring.
+ *	ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource.
+ *      ETH_OK otherwise.
+ *
+ *******************************************************************************/
+static ETH_FUNC_RET_STATUS eth_port_send(ETH_PORT_INFO * p_eth_port_ctrl,
+					 ETH_QUEUE tx_queue,
+					 PKT_INFO * p_pkt_info)
+{
+	volatile ETH_TX_DESC *p_tx_desc_first;
+	volatile ETH_TX_DESC *p_tx_desc_curr;
+	volatile ETH_TX_DESC *p_tx_next_desc_curr;
+	volatile ETH_TX_DESC *p_tx_desc_used;
+	u32 command_status;
+
+#ifdef CONFIG_TX_PKT_DISPLAY
+	{
+		u16 pcnt = p_pkt_info->byte_cnt;
+		u8 *prndt = (char *)p_pkt_info->buf_ptr;
+		printf("cnt=%d ", pcnt);
+		while (pcnt) {
+			printf("%02x,", prndt[0]);
+			prndt++;
+			pcnt--;
+		}
+		printf(" pckend \n");
+
+	}
+#endif
+	/* Do not process Tx ring in case of Tx ring resource error */
+	if (p_eth_port_ctrl->tx_resource_err[tx_queue] == true)
+		return ETH_QUEUE_FULL;
+
+	/* Get the Tx Desc ring indexes */
+	CURR_TFD_GET(p_tx_desc_curr, tx_queue);
+	USED_TFD_GET(p_tx_desc_used, tx_queue);
+
+	if (p_tx_desc_curr == NULL)
+		return ETH_ERROR;
+
+	/* The following parameters are used to save readings from memory */
+	p_tx_next_desc_curr = TX_NEXT_DESC_PTR(p_tx_desc_curr, tx_queue);
+	command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
+
+	if (command_status & (ETH_TX_FIRST_DESC)) {
+		/* Update first desc */
+		FIRST_TFD_SET(p_tx_desc_curr, tx_queue);
+		p_tx_desc_first = p_tx_desc_curr;
+	} else {
+		FIRST_TFD_GET(p_tx_desc_first, tx_queue);
+		command_status |= ETH_BUFFER_OWNED_BY_DMA;
+	}
+
+	/* Buffers with a payload smaller than 8 bytes must be aligned to 64-bit */
+	/* boundary. We use the memory allocated for Tx descriptor. This memory  */
+	/* located in TX_BUF_OFFSET_IN_DESC offset within the Tx descriptor. */
+	if (p_pkt_info->byte_cnt <= 8) {
+		printf("You have failed in the < 8 bytes errata - fixme\n");	/* RABEEH - TBD */
+		return ETH_ERROR;
+
+		p_tx_desc_curr->buf_ptr =
+		    (u32)p_tx_desc_curr + TX_BUF_OFFSET_IN_DESC;
+		eth_b_copy(p_pkt_info->buf_ptr, p_tx_desc_curr->buf_ptr,
+			   p_pkt_info->byte_cnt);
+	} else
+		p_tx_desc_curr->buf_ptr = p_pkt_info->buf_ptr;
+
+	p_tx_desc_curr->byte_cnt = p_pkt_info->byte_cnt;
+	p_tx_desc_curr->return_info = p_pkt_info->return_info;
+
+	if (p_pkt_info->cmd_sts & (ETH_TX_LAST_DESC)) {
+		/* Set last desc with DMA ownership and interrupt enable. */
+		p_tx_desc_curr->cmd_sts = command_status |
+		    ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT;
+
+		if (p_tx_desc_curr != p_tx_desc_first)
+			p_tx_desc_first->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA;
+
+		/* Flush CPU pipe */
+
+		D_CACHE_FLUSH_LINE((u32)p_tx_desc_curr, 0);
+		D_CACHE_FLUSH_LINE((u32)p_tx_desc_first, 0);
+		CPU_PIPE_FLUSH;
+
+		/* Apply send command */
+		ETH_ENABLE_TX_QUEUE(tx_queue, p_eth_port_ctrl->port_num);
+		debug_print("packet xmitted");
+
+		/* Finish Tx packet. Update first desc in case of Tx resource error */
+		p_tx_desc_first = p_tx_next_desc_curr;
+		FIRST_TFD_SET(p_tx_desc_first, tx_queue);
+
+	} else {
+		p_tx_desc_curr->cmd_sts = command_status;
+		D_CACHE_FLUSH_LINE((u32)p_tx_desc_curr, 0);
+	}
+
+	/* Check for ring index overlap in the Tx desc ring */
+	if (p_tx_next_desc_curr == p_tx_desc_used) {
+		/* Update the current descriptor */
+		CURR_TFD_SET(p_tx_desc_first, tx_queue);
+
+		p_eth_port_ctrl->tx_resource_err[tx_queue] = true;
+		return ETH_QUEUE_LAST_RESOURCE;
+	} else {
+		/* Update the current descriptor */
+		CURR_TFD_SET(p_tx_next_desc_curr, tx_queue);
+		return ETH_OK;
+	}
+}
+
+/*******************************************************************************
+ * eth_tx_return_desc - Free all used Tx descriptors
+ *
+ * DESCRIPTION:
+ *	This routine returns the transmitted packet information to the caller.
+ *      It uses the 'first' index to support Tx desc return in case a transmit
+ *      of a packet spanned over multiple buffer still in process.
+ *      In case the Tx queue was in "resource error" condition, where there are
+ *      no available Tx resources, the function resets the resource error flag.
+ *
+ * INPUT:
+ *	ETH_PORT_INFO   *p_eth_port_ctrl   Ethernet Port Control srtuct.
+ *	ETH_QUEUE   	tx_queue         Number of Tx queue.
+ *	PKT_INFO        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *	Tx ring 'first' and 'used' indexes are updated.
+ *
+ * RETURN:
+ *	ETH_ERROR in case the routine can not access Tx desc ring.
+ *      ETH_RETRY in case there is transmission in process.
+ *	ETH_END_OF_JOB if the routine has nothing to release.
+ *      ETH_OK otherwise.
+ *
+ *******************************************************************************/
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(ETH_PORT_INFO *
+					      p_eth_port_ctrl,
+					      ETH_QUEUE tx_queue,
+					      PKT_INFO * p_pkt_info)
+{
+	volatile ETH_TX_DESC *p_tx_desc_used = NULL;
+	volatile ETH_TX_DESC *p_tx_desc_first = NULL;
+	u32 command_status;
+
+	/* Get the Tx Desc ring indexes */
+	USED_TFD_GET(p_tx_desc_used, tx_queue);
+	FIRST_TFD_GET(p_tx_desc_first, tx_queue);
+
+	/* Sanity check */
+	if (p_tx_desc_used == NULL)
+		return ETH_ERROR;
+
+	command_status = p_tx_desc_used->cmd_sts;
+
+	/* Still transmitting... */
+	if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+		D_CACHE_FLUSH_LINE((u32)p_tx_desc_used, 0);
+		return ETH_RETRY;
+	}
+
+	/* Stop release. About to overlap the current available Tx descriptor */
+	if ((p_tx_desc_used == p_tx_desc_first) &&
+	    (p_eth_port_ctrl->tx_resource_err[tx_queue] == false)) {
+		D_CACHE_FLUSH_LINE((u32)p_tx_desc_used, 0);
+		return ETH_END_OF_JOB;
+	}
+
+	/* Pass the packet information to the caller */
+	p_pkt_info->cmd_sts = command_status;
+	p_pkt_info->return_info = p_tx_desc_used->return_info;
+	p_tx_desc_used->return_info = 0;
+
+	/* Update the next descriptor to release. */
+	USED_TFD_SET(TX_NEXT_DESC_PTR(p_tx_desc_used, tx_queue), tx_queue);
+
+	/* Any Tx return cancels the Tx resource error status */
+	if (p_eth_port_ctrl->tx_resource_err[tx_queue] == true)
+		p_eth_port_ctrl->tx_resource_err[tx_queue] = false;
+
+	D_CACHE_FLUSH_LINE((u32)p_tx_desc_used, 0);
+
+	return ETH_OK;
+
+}
+
+/*******************************************************************************
+ * eth_port_receive - Get received information from Rx ring.
+ *
+ * DESCRIPTION:
+ * 	This routine returns the received data to the caller. There is no
+ *	data copying during routine operation. All information is returned
+ *	using pointer to packet information struct passed from the caller.
+ *      If the routine exhausts	Rx ring resources then the resource error flag
+ *      is set.
+ *
+ * INPUT:
+ *	ETH_PORT_INFO   *p_eth_port_ctrl   Ethernet Port Control srtuct.
+ *	ETH_QUEUE   	rx_queue         Number of Rx queue.
+ *	PKT_INFO        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *	Rx ring current and used indexes are updated.
+ *
+ * RETURN:
+ *	ETH_ERROR in case the routine can not access Rx desc ring.
+ *	ETH_QUEUE_FULL if Rx ring resources are exhausted.
+ *	ETH_END_OF_JOB if there is no received data.
+ *      ETH_OK otherwise.
+ *
+ *******************************************************************************/
+static ETH_FUNC_RET_STATUS eth_port_receive(ETH_PORT_INFO * p_eth_port_ctrl,
+					    ETH_QUEUE rx_queue,
+					    PKT_INFO * p_pkt_info)
+{
+	volatile ETH_RX_DESC *p_rx_curr_desc;
+	volatile ETH_RX_DESC *p_rx_next_curr_desc;
+	volatile ETH_RX_DESC *p_rx_used_desc;
+	u32 command_status;
+
+	/* Do not process Rx ring in case of Rx ring resource error */
+	if (p_eth_port_ctrl->rx_resource_err[rx_queue] == true) {
+		error_print("Rx Queue is full ...");
+		return ETH_QUEUE_FULL;
+	}
+
+	/* Get the Rx Desc ring 'curr and 'used' indexes */
+	CURR_RFD_GET(p_rx_curr_desc, rx_queue);
+	USED_RFD_GET(p_rx_used_desc, rx_queue);
+
+	/* Sanity check */
+	if (p_rx_curr_desc == NULL)
+		return ETH_ERROR;
+
+	/* The following parameters are used to save readings from memory */
+	p_rx_next_curr_desc = RX_NEXT_DESC_PTR(p_rx_curr_desc, rx_queue);
+	command_status = p_rx_curr_desc->cmd_sts;
+
+	/* Nothing to receive... */
+	if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+		/*debug_print("Rx: command_status: %08x", command_status); */
+		D_CACHE_FLUSH_LINE((u32)p_rx_curr_desc, 0);
+		/*debug_print("ETH_END_OF_JOB ..."); */
+		return ETH_END_OF_JOB;
+	}
+
+	p_pkt_info->byte_cnt = (p_rx_curr_desc->byte_cnt) - RX_BUF_OFFSET;
+	p_pkt_info->cmd_sts = command_status;
+	p_pkt_info->buf_ptr = (p_rx_curr_desc->buf_ptr) + RX_BUF_OFFSET;
+	p_pkt_info->return_info = p_rx_curr_desc->return_info;
+	p_pkt_info->l4i_chk = p_rx_curr_desc->buf_size;	/* IP fragment indicator */
+
+	/* Clean the return info field to indicate that the packet has been */
+	/* moved to the upper layers                                        */
+	p_rx_curr_desc->return_info = 0;
+
+	/* Update 'curr' in data structure */
+	CURR_RFD_SET(p_rx_next_curr_desc, rx_queue);
+
+	/* Rx descriptors resource exhausted. Set the Rx ring resource error flag */
+	if (p_rx_next_curr_desc == p_rx_used_desc)
+		p_eth_port_ctrl->rx_resource_err[rx_queue] = true;
+
+	D_CACHE_FLUSH_LINE((u32)p_rx_curr_desc, 0);
+	CPU_PIPE_FLUSH;
+	return ETH_OK;
+}
+
+/*******************************************************************************
+ * eth_rx_return_buff - Returns a Rx buffer back to the Rx ring.
+ *
+ * DESCRIPTION:
+ *	This routine returns a Rx buffer back to the Rx ring. It retrieves the
+ *      next 'used' descriptor and attached the returned buffer to it.
+ *      In case the Rx ring was in "resource error" condition, where there are
+ *      no available Rx resources, the function resets the resource error flag.
+ *
+ * INPUT:
+ *	ETH_PORT_INFO   *p_eth_port_ctrl   Ethernet Port Control srtuct.
+ *	ETH_QUEUE   	rx_queue         Number of Rx queue.
+ *      PKT_INFO        *p_pkt_info       Information on the returned buffer.
+ *
+ * OUTPUT:
+ *	New available Rx resource in Rx descriptor ring.
+ *
+ * RETURN:
+ *	ETH_ERROR in case the routine can not access Rx desc ring.
+ *      ETH_OK otherwise.
+ *
+ *******************************************************************************/
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(ETH_PORT_INFO *
+					      p_eth_port_ctrl,
+					      ETH_QUEUE rx_queue,
+					      PKT_INFO * p_pkt_info)
+{
+	volatile ETH_RX_DESC *p_used_rx_desc;	/* Where to return Rx resource */
+
+	/* Get 'used' Rx descriptor */
+	USED_RFD_GET(p_used_rx_desc, rx_queue);
+
+	/* Sanity check */
+	if (p_used_rx_desc == NULL)
+		return ETH_ERROR;
+
+	p_used_rx_desc->buf_ptr = p_pkt_info->buf_ptr;
+	p_used_rx_desc->return_info = p_pkt_info->return_info;
+	p_used_rx_desc->byte_cnt = p_pkt_info->byte_cnt;
+	p_used_rx_desc->buf_size = KW_RX_BUFFER_SIZE;	/* Reset Buffer size */
+
+	/* Flush the write pipe */
+	CPU_PIPE_FLUSH;
+
+	/* Return the descriptor to DMA ownership */
+	p_used_rx_desc->cmd_sts =
+	    ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+
+	/* Flush descriptor and CPU pipe */
+	D_CACHE_FLUSH_LINE((u32)p_used_rx_desc, 0);
+	CPU_PIPE_FLUSH;
+
+	/* Move the used descriptor pointer to the next descriptor */
+	USED_RFD_SET(RX_NEXT_DESC_PTR(p_used_rx_desc, rx_queue), rx_queue);
+
+	/* Any Rx return cancels the Rx resource error status */
+	if (p_eth_port_ctrl->rx_resource_err[rx_queue] == true)
+		p_eth_port_ctrl->rx_resource_err[rx_queue] = false;
+
+	return ETH_OK;
+}
+
+/*
+ * helper function used for kirkwood_egiga_initialize
+ */
+void print_globals(struct eth_device *dev)
+{
+	debug_print("Ethernet PRINT_Globals-Debug function");
+	debug_print("Base Address for ETH_PORT_INFO:	%08x",
+	       (u32)dev->priv);
+	debug_print("Base Address for egiga_priv:	%08x",
+	       (u32)&(((ETH_PORT_INFO *) dev->priv)->port_private));
+
+	debug_print
+	    ("Base Address for TX-DESCs:	%08x	Number of allocated Buffers %d",
+	     (u32)((ETH_PORT_INFO *) dev->priv)->
+	     p_tx_desc_area_base[0], KW_TX_QUEUE_SIZE);
+	debug_print
+	    ("Base Address for RX-DESCs:	%08x	Number of allocated Buffers %d",
+	     (u32)((ETH_PORT_INFO *) dev->priv)->
+	     p_rx_desc_area_base[0], KW_RX_QUEUE_SIZE);
+	debug_print("Base Address for RX-Buffer:	%08x	allocated Bytes %d",
+	       (u32)((ETH_PORT_INFO *) dev->priv)->
+	       p_rx_buffer_base[0],
+	       (KW_RX_QUEUE_SIZE * KW_RX_BUFFER_SIZE) + 32);
+	debug_print("Base Address for TX-Buffer:	%08x	allocated Bytes %d",
+	       (u32)((ETH_PORT_INFO *) dev->priv)->
+	       p_tx_buffer_base[0],
+	       (KW_TX_QUEUE_SIZE * KW_TX_BUFFER_SIZE) + 32);
+}
+
+
+/*
+ * u-boot entry functions
+ */
+static int kw_egiga_init(struct eth_device *dev)
+{
+
+	u32 queue;
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	u32 port_num;
+
+	debug_print_ftrace();
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	/* ronen - when we update the MAC env params we only update dev->enetaddr
+	   see ./net/eth.c eth_set_enetaddr() */
+	memcpy(ethernet_private->port_mac_addr, dev->enetaddr, 6);
+
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+
+	/* Activate the DMA channels etc */
+	eth_port_init(ethernet_private);
+
+	/* "Allocate" setup TX rings */
+
+	for (queue = 0; queue < KW_TX_QUEUE_NUM; queue++) {
+		u32 size;
+
+		port_private->tx_ring_size[queue] = KW_TX_QUEUE_SIZE;
+		/*size = no of DESCs times DESC-size */
+		size =
+		    (port_private->tx_ring_size[queue] * TX_DESC_ALIGNED_SIZE);
+		ethernet_private->tx_desc_area_size[queue] = size;
+
+		/* first clear desc area completely */
+		memset((void *)ethernet_private->p_tx_desc_area_base[queue],
+		       0, ethernet_private->tx_desc_area_size[queue]);
+
+		/* initialize tx desc ring with low level driver */
+		if (kw_egiga_init_tx_desc_ring
+		    (ethernet_private, ETH_Q0,
+		     port_private->tx_ring_size[queue],
+		     KW_TX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ ,
+		     (u32)ethernet_private->
+		     p_tx_desc_area_base[queue],
+		     (u32)ethernet_private->
+		     p_tx_buffer_base[queue]) == false)
+			error_print("### initializing TX Ring");
+	}
+
+	/* "Allocate" setup RX rings */
+	for (queue = 0; queue < KW_RX_QUEUE_NUM; queue++) {
+		u32 size;
+
+		/* Meantime RX Ring are fixed - but must be configurable by user */
+		port_private->rx_ring_size[queue] = KW_RX_QUEUE_SIZE;
+		size = (port_private->rx_ring_size[queue] *
+			RX_DESC_ALIGNED_SIZE);
+		ethernet_private->rx_desc_area_size[queue] = size;
+
+		/* first clear desc area completely */
+		memset((void *)ethernet_private->p_rx_desc_area_base[queue],
+		       0, ethernet_private->rx_desc_area_size[queue]);
+		if ((kw_egiga_init_rx_desc_ring
+		     (ethernet_private, ETH_Q0,
+		      port_private->rx_ring_size[queue],
+		      KW_RX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ ,
+		      (u32)ethernet_private->
+		      p_rx_desc_area_base[queue],
+		      (u32)ethernet_private->
+		      p_rx_buffer_base[queue])) == false)
+			error_print("### initializing RX Ring");
+	}
+
+	eth_port_start(ethernet_private);
+
+	if (!eth_phy_link_status(port_num)) {
+		warn_print("No link on port %d", port_num);
+		return 0;
+	} else {
+		egiga_print_phy_status(port_num);
+	}
+	port_private->eth_running = MAGIC_ETH_RUNNING;
+	return 1;
+}
+
+/**********************************************************************
+ * egiga_start_xmit
+ *
+ * This function is queues a packet in the Tx descriptor for
+ * required port.
+ *
+ * Input : skb - a pointer to socket buffer
+ *         dev - a pointer to the required port
+ *
+ * Output : zero upon success
+ **********************************************************************/
+
+int kw_egiga_xmit(struct eth_device *dev, volatile void *dataPtr, int dataSize)
+{
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	u32 port_num;
+	PKT_INFO pkt_info;
+	ETH_FUNC_RET_STATUS status;
+	struct net_device_stats *stats;
+	ETH_FUNC_RET_STATUS release_result;
+
+	debug_print_ftrace();
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+
+	stats = port_private->stats;
+
+	/* Update packet info data structure */
+	pkt_info.cmd_sts = ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;	/* first last */
+	pkt_info.cmd_sts |= ETH_BUFFER_OWNED_BY_DMA;	/* DMA owned */
+
+	pkt_info.byte_cnt = dataSize;
+	pkt_info.buf_ptr = (u32)dataPtr;
+	pkt_info.return_info = 0;
+
+	status = eth_port_send(ethernet_private, ETH_Q0, &pkt_info);
+	if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) {
+		error_print("On transmitting packet ..");
+		if (status == ETH_QUEUE_FULL)
+			error_print("ETH Queue is full.");
+		if (status == ETH_QUEUE_LAST_RESOURCE)
+			error_print("ETH Queue: using last available resource.");
+		goto error;
+	}
+
+	/* Update statistics and start of transmittion time */
+	stats->tx_bytes += dataSize;
+	stats->tx_packets++;
+
+	/* Check if packet(s) is(are) transmitted correctly (release everything) */
+	do {
+		release_result =
+		    eth_tx_return_desc(ethernet_private, ETH_Q0, &pkt_info);
+		switch (release_result) {
+		case ETH_OK:
+			debug_print("descriptor released");
+			if (pkt_info.cmd_sts & BIT0) {
+				error_print("in TX");
+				stats->tx_errors++;
+
+			}
+			break;
+		case ETH_RETRY:
+			debug_print("transmission still in process");
+			break;
+
+		case ETH_ERROR:
+			error_print("routine can not access Tx desc ring");
+			break;
+
+		case ETH_END_OF_JOB:
+			debug_print("the routine has nothing to release");
+			break;
+		default:	/* should not happen */
+			break;
+		}
+	} while (release_result == ETH_OK);
+
+	return 0;		/* success */
+      error:
+	return 1;		/* Failed - higher layers will free the skb */
+}
+
+/**********************************************************************
+ * kw_egiga_receive
+ *
+ * This function is forward packets that are received from the port's
+ * queues toward kernel core or FastRoute them to another interface.
+ *
+ * Input : dev - a pointer to the required interface
+ *         max - maximum number to receive (0 means unlimted)
+ *
+ * Output : number of served packets
+ **********************************************************************/
+
+int kw_egiga_receive(struct eth_device *dev)
+{
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	u32 port_num;
+	PKT_INFO pkt_info;
+	struct net_device_stats *stats;
+
+	ethernet_private = (ETH_PORT_INFO *) dev->priv;
+	port_private = (struct egiga_priv *)ethernet_private->port_private;
+	port_num = port_private->port_num;
+	stats = port_private->stats;
+
+	while ((eth_port_receive(ethernet_private, ETH_Q0, &pkt_info) ==
+		ETH_OK)) {
+
+		if (pkt_info.byte_cnt != 0) {
+			debug_print("%s: Received %d byte Packet @ 0x%x",
+			       __FUNCTION__, pkt_info.byte_cnt,
+			       pkt_info.buf_ptr);
+		}
+		/* Update statistics. Note byte count includes 4 byte CRC count */
+		stats->rx_packets++;
+		stats->rx_bytes += pkt_info.byte_cnt;
+
+		/*
+		 * In case received a packet without first / last bits on OR the error
+		 * summary bit is on, the packets needs to be dropeed.
+		 */
+		if (((pkt_info.
+		      cmd_sts & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
+		     (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
+		    || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
+			stats->rx_dropped++;
+
+			printf
+			    ("Received packet spread on multiple descriptors\n");
+
+			/* Is this caused by an error ? */
+			if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY) {
+				stats->rx_errors++;
+			}
+
+			/* free these descriptors again without forwarding them to the higher layers */
+			pkt_info.buf_ptr &= ~0x7;	/* realign buffer again */
+			pkt_info.byte_cnt = 0x0000;	/* Reset Byte count */
+
+			if (eth_rx_return_buff
+			    (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) {
+				printf
+				    ("Error while returning the RX Desc to Ring\n");
+			} else {
+				debug_print("RX Desc returned to Ring");
+			}
+			/* /free these descriptors again */
+		} else {
+
+			/* !!! call higher layer processing */
+			debug_print("\nNow send it to upper layer protocols (NetReceive) ...");
+
+			/* let the upper layer handle the packet */
+			NetReceive((uchar *) pkt_info.buf_ptr,
+				   (int)pkt_info.byte_cnt);
+
+			/* free descriptor  */
+			pkt_info.buf_ptr &= ~0x7;	/* realign buffer again */
+			pkt_info.byte_cnt = 0x0000;	/* Reset Byte count */
+			debug_print("RX: pkt_info.buf_ptr = %x",
+			    pkt_info.buf_ptr);
+			if (eth_rx_return_buff
+			    (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) {
+				error_print
+				    ("while returning the RX Desc to Ring");
+			} else {
+				debug_print("RX Desc returned to Ring");
+			}
+			/* free descriptor code end  */
+		}
+	}
+	egiga_get_stats(dev);	/* update statistics */
+	return 1;
+}
+
+/*
+ * Called from net/eth.c
+ */
+int kirkwood_egiga_initialize(bd_t * bis)
+{
+	struct eth_device *dev;
+	ETH_PORT_INFO *ethernet_private;
+	struct egiga_priv *port_private;
+	int devnum, x, temp;
+	char *s, *e, buf[64];
+	u8 used_ports[MAX_ETH_DEVS] = CONFIG_KIRKWOOD_EGIGA_PORTS;
+
+	debug_print_ftrace();
+	for (devnum = 0; devnum < MAX_ETH_DEVS; devnum++) {
+		/*skip if port is configured not to use */
+		if (used_ports[devnum] == FALSE)
+			continue;
+
+		dev = calloc(sizeof(*dev), 1);
+		if (!dev) {
+			printf("%s: mv_enet%d allocation failure, %s\n",
+			       __FUNCTION__, devnum, "eth_device structure");
+			return -1;
+		}
+
+		/* must be less than NAMESIZE (16) */
+		sprintf(dev->name, "egiga%d", devnum);
+
+		debug_print("Initializing %s", dev->name);
+
+		/* Extract the MAC address from the environment */
+		switch (devnum) {
+		case 0:
+			s = "ethaddr";
+			break;
+
+		case 1:
+			s = "eth1addr";
+			break;
+
+		default:	/* this should never happen */
+			printf("%s: Invalid device number %d\n",
+			       __FUNCTION__, devnum);
+			return -1;
+		}
+
+		e = getenv(s);
+		if (!e) {
+			/* Generate Ramdom MAC addresses if not set */
+			sprintf(buf, "00:50:43:%02x:%02x:%02x",
+				get_random_hex(), get_random_hex(),
+				get_random_hex());
+			setenv(s, buf);
+		}
+
+		temp = getenv_r(s, buf, sizeof(buf));
+		s = (temp > 0) ? buf : NULL;
+
+		debug_print("Setting MAC %d to %s", devnum, s);
+		/* Assume port is pre-powered up */
+		/* eth_port_power_up(devnum); */
+
+		for (x = 0; x < 6; ++x) {
+			dev->enetaddr[x] = s ? simple_strtoul(s, &e, 16) : 0;
+			if (s)
+				s = (*e) ? e + 1 : e;
+		}
+		/* set the MAC addr in the HW */
+		eth_port_uc_addr_set(devnum, dev->enetaddr, 0);
+
+		dev->init = (void *)kw_egiga_init;
+		dev->halt = (void *)kw_egiga_stop;
+		dev->send = (void *)kw_egiga_xmit;
+		dev->recv = (void *)kw_egiga_receive;
+
+		ethernet_private = calloc(sizeof(*ethernet_private), 1);
+		dev->priv = (void *)ethernet_private;
+
+		if (!ethernet_private) {
+			printf("%s: %s allocation failure, %s\n",
+			       __FUNCTION__, dev->name,
+			       "Private Device Structure");
+			free(dev);
+			return -1;
+		}
+		/* start with an zeroed ETH_PORT_INFO */
+		memset(ethernet_private, 0, sizeof(ETH_PORT_INFO));
+		memcpy(ethernet_private->port_mac_addr, dev->enetaddr, 6);
+
+		/* set pointer to memory for stats data structure etc... */
+		port_private = calloc(sizeof(*ethernet_private), 1);
+		ethernet_private->port_private = (void *)port_private;
+		if (!port_private) {
+			printf("%s: %s allocation failure, %s\n",
+			       __FUNCTION__, dev->name,
+			       "Port Private Device Structure");
+
+			free(ethernet_private);
+			free(dev);
+			return -1;
+		}
+
+		port_private->stats =
+		    calloc(sizeof(struct net_device_stats), 1);
+		if (!port_private->stats) {
+			printf("%s: %s allocation failure, %s\n",
+			       __FUNCTION__, dev->name, "Net stat Structure");
+
+			free(port_private);
+			free(ethernet_private);
+			free(dev);
+			return -1;
+		}
+		memset(ethernet_private->port_private, 0,
+		       sizeof(struct egiga_priv));
+		switch (devnum) {
+		case 0:
+			ethernet_private->port_num = ETH_0;
+			break;
+		case 1:
+			ethernet_private->port_num = ETH_1;
+			break;
+		default:
+			printf("Invalid device number %d\n", devnum);
+			break;
+		};
+
+		port_private->port_num = devnum;
+		/*
+		 * Read MIB counter on the GT in order to reset them,
+		 * then zero all the stats fields in memory
+		 */
+		egiga_update_stat(dev);
+		memset(port_private->stats, 0, sizeof(struct net_device_stats));
+
+		debug_print("Allocating descriptor and buffer rings");
+
+		ethernet_private->p_rx_desc_area_base[0] =
+		    (ETH_RX_DESC *) memalign(16,
+					     RX_DESC_ALIGNED_SIZE *
+					     KW_RX_QUEUE_SIZE + 1);
+		ethernet_private->p_tx_desc_area_base[0] =
+		    (ETH_TX_DESC *) memalign(16,
+					     TX_DESC_ALIGNED_SIZE *
+					     KW_TX_QUEUE_SIZE + 1);
+
+		ethernet_private->p_rx_buffer_base[0] =
+		    (char *)memalign(16,
+				     KW_RX_QUEUE_SIZE * KW_TX_BUFFER_SIZE + 1);
+		ethernet_private->p_tx_buffer_base[0] =
+		    (char *)memalign(16,
+				     KW_RX_QUEUE_SIZE * KW_TX_BUFFER_SIZE + 1);
+
+		/* DEBUG OUTPUT prints adresses of globals */
+		print_globals(dev);
+
+		eth_register(dev);
+
+		/* Set phy address of the port */
+		ethernet_private->port_phy_addr =
+		    PHY_BASE_ADR + ethernet_private->port_num;
+		eth_phy_set_addr(ethernet_private->port_num,
+				 ethernet_private->port_phy_addr);
+
+	}
+	return 0;
+}
+
+#endif /* CONFIG_KIRKWOOD_EGIGA */
diff --git a/cpu/arm926ejs/kirkwood/egiga.h b/cpu/arm926ejs/kirkwood/egiga.h
new file mode 100644
index 0000000..83dc4b3
--- /dev/null
+++ b/cpu/arm926ejs/kirkwood/egiga.h
@@ -0,0 +1,707 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Prafulla Wadaskar <prafulla at marvell.com>
+ *
+ * based on - Driver for MV64360X ethernet ports
+ * Copyright (C) 2002 rabeeh at galileo.co.il
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef __EGIGA_H__
+#define __EGIGA_H__
+
+#define MAX_ETH_DEVS	2	/*controller has two ports */
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <common.h>
+#include <net.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* Port attributes */
+/* Max queue number is 8 for controller but here configured 1 */
+#define MAX_RX_QUEUE_NUM	1
+#define MAX_TX_QUEUE_NUM	1
+/* Use one TX queue and one RX queue */
+#define KW_TX_QUEUE_NUM 	1
+#define KW_RX_QUEUE_NUM 	1
+
+/*
+ * Number of RX / TX descriptors on RX / TX rings.
+ * Note that allocating RX descriptors is done by allocating the RX
+ * ring AND a preallocated RX buffers (skb's) for each descriptor.
+ * The TX descriptors only allocates the TX descriptors ring,
+ * with no pre allocated TX buffers (skb's are allocated by higher layers.
+ */
+
+/* TX/RX parameters can be passed externally */
+#ifdef CONFIG_ETH_TXQUEUE_SIZE
+#define KW_TX_QUEUE_SIZE CONFIG_ETH_TXQUEUE_SIZE
+#else
+#define KW_TX_QUEUE_SIZE 4
+#endif
+
+#ifdef	CONFIG_ETH_RXQUEUE_SIZE
+#define KW_RX_QUEUE_SIZE CONFIG_ETH_RXQUEUE_SIZE
+#else
+#define KW_RX_QUEUE_SIZE 4
+#endif
+
+#ifdef CONFIG_ETH_RXBUFFER_SIZE
+#define KW_RX_BUFFER_SIZE CONFIG_ETH_RXBUFFER_SIZE
+#else
+#define KW_RX_BUFFER_SIZE 1600
+#endif
+
+#ifdef CONFIG_ETH_TXBUFFER_SIZE
+#define KW_TX_BUFFER_SIZE CONFIG_ETH_TXBUFFER_SIZE
+#else
+#define KW_TX_BUFFER_SIZE 1600
+#endif
+
+#define RX_BUFFER_MAX_SIZE  0xFFFF
+#define TX_BUFFER_MAX_SIZE  0xFFFF	/* Buffers are limited to 64k */
+#define RX_BUFFER_MIN_SIZE  0x8
+#define TX_BUFFER_MIN_SIZE  0x8
+
+/*
+ *	Network device statistics. Akin to the 2.0 ether stats but
+ *	with byte counters.
+ */
+struct net_device_stats {
+	u32 rx_packets;	/* total packets received       */
+	u32 tx_packets;	/* total packets transmitted    */
+	u32 rx_bytes;	/* total bytes received         */
+	u32 tx_bytes;	/* total bytes transmitted      */
+	u32 rx_errors;	/* bad packets received         */
+	u32 tx_errors;	/* packet transmit problems     */
+	u32 rx_dropped;	/* no space in linux buffers    */
+	u32 tx_dropped;	/* no space available in linux  */
+	u32 multicast;	/* multicast packets received   */
+	u32 collisions;
+	/* detailed rx_errors: */
+	u32 rx_length_errors;
+	u32 rx_over_errors;	/* receiver ring buff overflow  */
+	u32 rx_crc_errors;	/* recved pkt with crc error    */
+	u32 rx_frame_errors;	/* recv'd frame alignment error */
+	u32 rx_fifo_errors;	/* recv'r fifo overrun          */
+	u32 rx_missed_errors;	/* receiver missed packet       */
+	/* detailed tx_errors */
+	u32 tx_aborted_errors;
+	u32 tx_carrier_errors;
+	u32 tx_fifo_errors;
+	u32 tx_heartbeat_errors;
+	u32 tx_window_errors;
+	/* for cslip etc */
+	u32 rx_compressed;
+	u32 tx_compressed;
+};
+
+/* Private data structure used for ethernet device */
+struct egiga_priv {
+	u32 port_num;
+	struct net_device_stats *stats;
+	/* to buffer area aligned */
+	char *p_eth_tx_buffer[KW_TX_QUEUE_SIZE + 1];
+	char *p_eth_rx_buffer[KW_RX_QUEUE_SIZE + 1];
+	/* Size of Tx Ring per queue */
+	u32 tx_ring_size[MAX_TX_QUEUE_NUM];
+	/* Size of Rx Ring per queue */
+	u32 rx_ring_size[MAX_RX_QUEUE_NUM];
+	/* Magic Number for Ethernet running */
+	u32 eth_running;
+};
+
+/*
+ * The second part is the low level driver of the gigE ethernet ports.
+ */
+
+/********************************************************************************
+ * Header File for : network interface header
+ *
+ * DESCRIPTION:
+ *	 This header file contains macros typedefs and function declaration for
+ *	 the Marvell Gig Bit Ethernet Controller.
+ *
+ * DEPENDENCIES:
+ *	 None.
+ *
+ *******************************************************************************/
+
+/* defines  */
+
+/* Default port configuration value */
+#define PORT_CONFIG_VALUE			\
+	     ETH_UNICAST_NORMAL_MODE		|   \
+	     ETH_DEFAULT_RX_QUEUE_0		|   \
+	     ETH_DEFAULT_RX_ARP_QUEUE_0		|   \
+	     ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP	|   \
+	     ETH_RECEIVE_BC_IF_IP		|   \
+	     ETH_RECEIVE_BC_IF_ARP		|   \
+	     ETH_CAPTURE_TCP_FRAMES_DIS		|   \
+	     ETH_CAPTURE_UDP_FRAMES_DIS		|   \
+	     ETH_DEFAULT_RX_TCP_QUEUE_0		|   \
+	     ETH_DEFAULT_RX_UDP_QUEUE_0		|   \
+	     ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+/* Default port extend configuration value */
+#define PORT_CONFIG_EXTEND_VALUE		\
+	     ETH_SPAN_BPDU_PACKETS_AS_NORMAL	|   \
+	     ETH_PARTITION_DISABLE		| \
+		ETH_TX_CRC_GENERATION_ENABLE
+
+/* Default sdma control value */
+#ifdef CONFIG_NOT_COHERENT_CACHE
+#define PORT_SDMA_CONFIG_VALUE				\
+			 ETH_RX_BURST_SIZE_16_64BIT	|	\
+			 ETH_BLM_RX_NO_SWAP		| \
+			 ETH_BLM_TX_NO_SWAP		| \
+			 GT_ETH_IPG_INT_RX(0)			|	\
+			 ETH_TX_BURST_SIZE_16_64BIT;
+#else
+#define PORT_SDMA_CONFIG_VALUE			\
+			 ETH_RX_BURST_SIZE_4_64BIT	|	\
+			 GT_ETH_IPG_INT_RX(0)			|	\
+			 ETH_TX_BURST_SIZE_4_64BIT;
+#endif
+
+#define GT_ETH_IPG_INT_RX(value)		\
+	    ((value & 0x3fff) << 8)
+
+/* Default port serial control value */
+#define PORT_SERIAL_CONTROL_VALUE_TMP			    \
+			ETH_FORCE_LINK_PASS			|	\
+			ETH_DISABLE_AUTO_NEG_FOR_DUPLX		|	\
+			ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL	|	\
+			ETH_ADV_NO_FLOW_CTRL		|	\
+			ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX	|	\
+			ETH_FORCE_BP_MODE_NO_JAM		|	\
+			BIT9					|	\
+			ETH_DO_NOT_FORCE_LINK_FAIL		|	\
+			ETH_DISABLE_AUTO_NEG_SPEED_GMII		|	\
+			ETH_DTE_ADV_0				|	\
+			ETH_MIIPHY_MAC_MODE			|	\
+			ETH_AUTO_NEG_NO_CHANGE			|	\
+			ETH_MAX_RX_PACKET_1552BYTE		|	\
+			ETH_CLR_EXT_LOOPBACK			|	\
+			ETH_SET_FULL_DUPLEX_MODE		|	\
+			ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX | 	\
+			ETH_SET_MII_SPEED_TO_100
+
+#ifdef CONFIG_SYS_MII_MODE
+#define PORT_SERIAL_CONTROL_VALUE	\
+			PORT_SERIAL_CONTROL_VALUE_TMP |	\
+			ETH_SET_GMII_SPEED_TO_10_100
+#else
+#define PORT_SERIAL_CONTROL_VALUE	\
+			PORT_SERIAL_CONTROL_VALUE_TMP |	\
+			ETH_SET_GMII_SPEED_TO_1000
+#endif
+
+/* Tx WRR confoguration macros */
+#define PORT_MAX_TRAN_UNIT	    0x24	/* MTU register (default) 9KByte */
+#define PORT_MAX_TOKEN_BUCKET_SIZE  0x_fFFF	/* PMTBS register (default)      */
+#define PORT_TOKEN_RATE		    1023	/* PTTBRC register (default)     */
+/* MAC accepet/reject macros */
+#define ACCEPT_MAC_ADDR	    0
+#define REJECT_MAC_ADDR	    1
+/* Size of a Tx/Rx descriptor used in chain list data structure */
+#define RX_DESC_ALIGNED_SIZE		0x20
+#define TX_DESC_ALIGNED_SIZE		0x20
+/* An offest in Tx descriptors to store data for buffers less than 8 Bytes */
+#define TX_BUF_OFFSET_IN_DESC	    	0x18
+/* Buffer offset from buffer pointer */
+#define RX_BUF_OFFSET			0x2
+/* Gap define */
+#define ETH_BAR_GAP			0x8
+#define ETH_SIZE_REG_GAP		0x8
+#define ETH_HIGH_ADDR_REMAP_REG_GAP	0x4
+#define ETH_PORT_ACCESS_CTRL_GAP	0x4
+/* MIB Counters register definitions */
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW   0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH  0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED	   0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR  0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED	   0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED	   0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED  0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED  0x1c
+#define ETH_MIB_FRAMES_64_OCTETS	   0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS	   0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS   0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS   0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS  0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS  0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW	   0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH	   0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT	   0x40
+#define ETH_MIB_EXCESSIVE_COLLISION	   0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT	   0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT	   0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
+#define ETH_MIB_FC_SENT			   0x54
+#define ETH_MIB_GOOD_FC_RECEIVED	   0x58
+#define ETH_MIB_BAD_FC_RECEIVED		   0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED	   0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED	   0x64
+#define ETH_MIB_OVERSIZE_RECEIVED	   0x68
+#define ETH_MIB_JABBER_RECEIVED		   0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR	   0x70
+#define ETH_MIB_BAD_CRC_EVENT		   0x74
+#define ETH_MIB_COLLISION		   0x78
+#define ETH_MIB_LATE_COLLISION		   0x7c
+
+/* Port serial status reg (PSR) */
+#define ETH_INTERFACE_GMII_MII				0
+#define ETH_INTERFACE_PCM				BIT0
+#define ETH_LINK_IS_DOWN				0
+#define ETH_LINK_IS_UP					BIT1
+#define ETH_PORT_AT_HALF_DUPLEX				0
+#define ETH_PORT_AT_FULL_DUPLEX				BIT2
+#define ETH_RX_FLOW_CTRL_DISABLED			0
+#define ETH_RX_FLOW_CTRL_ENBALED			BIT3
+#define ETH_GMII_SPEED_100_10				0
+#define ETH_GMII_SPEED_1000				BIT4
+#define ETH_MII_SPEED_10				0
+#define ETH_MII_SPEED_100				BIT5
+#define ETH_NO_TX					0
+#define ETH_TX_IN_PROGRESS				BIT7
+#define ETH_BYPASS_NO_ACTIVE				0
+#define ETH_BYPASS_ACTIVE				BIT8
+#define ETH_PORT_NOT_AT_PARTITION_STATE			0
+#define ETH_PORT_AT_PARTITION_STATE			BIT9
+#define ETH_PORT_TX_FIFO_NOT_EMPTY			0
+#define ETH_PORT_TX_FIFO_EMPTY				BIT10
+
+/* These macros describes the Port configuration reg (Px_cR) bits */
+#define ETH_UNICAST_NORMAL_MODE				0
+#define ETH_UNICAST_PROMISCUOUS_MODE			BIT0
+#define ETH_DEFAULT_RX_QUEUE_0				0
+#define ETH_DEFAULT_RX_QUEUE_1				BIT1
+#define ETH_DEFAULT_RX_QUEUE_2				BIT2
+#define ETH_DEFAULT_RX_QUEUE_3				(BIT2 | BIT1)
+#define ETH_DEFAULT_RX_QUEUE_4				BIT3
+#define ETH_DEFAULT_RX_QUEUE_5				(BIT3 | BIT1)
+#define ETH_DEFAULT_RX_QUEUE_6				(BIT3 | BIT2)
+#define ETH_DEFAULT_RX_QUEUE_7				(BIT3 | BIT2 | BIT1)
+#define ETH_DEFAULT_RX_ARP_QUEUE_0			0
+#define ETH_DEFAULT_RX_ARP_QUEUE_1			BIT4
+#define ETH_DEFAULT_RX_ARP_QUEUE_2			BIT5
+#define ETH_DEFAULT_RX_ARP_QUEUE_3			(BIT5 | BIT4)
+#define ETH_DEFAULT_RX_ARP_QUEUE_4			BIT6
+#define ETH_DEFAULT_RX_ARP_QUEUE_5			(BIT6 | BIT4)
+#define ETH_DEFAULT_RX_ARP_QUEUE_6			(BIT6 | BIT5)
+#define ETH_DEFAULT_RX_ARP_QUEUE_7			(BIT6 | BIT5 | BIT4)
+#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP			0
+#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP			BIT7
+#define ETH_RECEIVE_BC_IF_IP				0
+#define ETH_REJECT_BC_IF_IP				BIT8
+#define ETH_RECEIVE_BC_IF_ARP				0
+#define ETH_REJECT_BC_IF_ARP				BIT9
+#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY		BIT12
+#define ETH_CAPTURE_TCP_FRAMES_DIS			0
+#define ETH_CAPTURE_TCP_FRAMES_EN			BIT14
+#define ETH_CAPTURE_UDP_FRAMES_DIS			0
+#define ETH_CAPTURE_UDP_FRAMES_EN			BIT15
+#define ETH_DEFAULT_RX_TCP_QUEUE_0			0
+#define ETH_DEFAULT_RX_TCP_QUEUE_1			BIT16
+#define ETH_DEFAULT_RX_TCP_QUEUE_2			BIT17
+#define ETH_DEFAULT_RX_TCP_QUEUE_3			(BIT17 | BIT16)
+#define ETH_DEFAULT_RX_TCP_QUEUE_4			BIT18
+#define ETH_DEFAULT_RX_TCP_QUEUE_5			(BIT18 | BIT16)
+#define ETH_DEFAULT_RX_TCP_QUEUE_6			(BIT18 | BIT17)
+#define ETH_DEFAULT_RX_TCP_QUEUE_7			(BIT18 | BIT17 | BIT16)
+#define ETH_DEFAULT_RX_UDP_QUEUE_0			0
+#define ETH_DEFAULT_RX_UDP_QUEUE_1			BIT19
+#define ETH_DEFAULT_RX_UDP_QUEUE_2			BIT20
+#define ETH_DEFAULT_RX_UDP_QUEUE_3			(BIT20 | BIT19)
+#define ETH_DEFAULT_RX_UDP_QUEUE_4			(BIT21
+#define ETH_DEFAULT_RX_UDP_QUEUE_5			(BIT21 | BIT19)
+#define ETH_DEFAULT_RX_UDP_QUEUE_6			(BIT21 | BIT20)
+#define ETH_DEFAULT_RX_UDP_QUEUE_7			(BIT21 | BIT20 | BIT19)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_0			 0
+#define ETH_DEFAULT_RX_BPDU_QUEUE_1			BIT22
+#define ETH_DEFAULT_RX_BPDU_QUEUE_2			BIT23
+#define ETH_DEFAULT_RX_BPDU_QUEUE_3			(BIT23 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_4			BIT24
+#define ETH_DEFAULT_RX_BPDU_QUEUE_5			(BIT24 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_6			(BIT24 | BIT23)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_7			(BIT24 | BIT23 | BIT22)
+#define ETH_DEFAULT_RX_TCP_CHKSUM_MODE			BIT25
+
+/* These macros describes the Port configuration extend reg (Px_cXR) bits*/
+#define ETH_CLASSIFY_EN					BIT0
+#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL			0
+#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7		BIT1
+#define ETH_PARTITION_DISABLE				0
+#define ETH_PARTITION_ENABLE				BIT2
+#define ETH_TX_CRC_GENERATION_ENABLE			0
+#define ETH_TX_CRC_GENERATION_DISABLE			BIT3
+
+/* Tx/Rx queue command reg (RQCR/TQCR)*/
+#define ETH_QUEUE_0_ENABLE				BIT0
+#define ETH_QUEUE_1_ENABLE				BIT1
+#define ETH_QUEUE_2_ENABLE				BIT2
+#define ETH_QUEUE_3_ENABLE				BIT3
+#define ETH_QUEUE_4_ENABLE				BIT4
+#define ETH_QUEUE_5_ENABLE				BIT5
+#define ETH_QUEUE_6_ENABLE				BIT6
+#define ETH_QUEUE_7_ENABLE				BIT7
+#define ETH_QUEUE_0_DISABLE				BIT8
+#define ETH_QUEUE_1_DISABLE				BIT9
+#define ETH_QUEUE_2_DISABLE				BIT10
+#define ETH_QUEUE_3_DISABLE				BIT11
+#define ETH_QUEUE_4_DISABLE				BIT12
+#define ETH_QUEUE_5_DISABLE				BIT13
+#define ETH_QUEUE_6_DISABLE				BIT14
+#define ETH_QUEUE_7_DISABLE				BIT15
+
+/* These macros describes the Port Sdma configuration reg (SDCR) bits */
+#define ETH_RIFB					BIT0
+#define ETH_RX_BURST_SIZE_1_64BIT			0
+#define ETH_RX_BURST_SIZE_2_64BIT			BIT1
+#define ETH_RX_BURST_SIZE_4_64BIT			BIT2
+#define ETH_RX_BURST_SIZE_8_64BIT			(BIT2 | BIT1)
+#define ETH_RX_BURST_SIZE_16_64BIT			BIT3
+#define ETH_BLM_RX_NO_SWAP				BIT4
+#define ETH_BLM_RX_BYTE_SWAP				0
+#define ETH_BLM_TX_NO_SWAP				BIT5
+#define ETH_BLM_TX_BYTE_SWAP				0
+#define ETH_DESCRIPTORS_BYTE_SWAP			BIT6
+#define ETH_DESCRIPTORS_NO_SWAP				0
+#define ETH_TX_BURST_SIZE_1_64BIT			0
+#define ETH_TX_BURST_SIZE_2_64BIT			BIT22
+#define ETH_TX_BURST_SIZE_4_64BIT			BIT23
+#define ETH_TX_BURST_SIZE_8_64BIT			(BIT23 | BIT22)
+#define ETH_TX_BURST_SIZE_16_64BIT			BIT24
+
+/* These macros describes the Port serial control reg (PSCR) bits */
+#define ETH_SERIAL_PORT_DISABLE				0
+#define ETH_SERIAL_PORT_ENABLE				BIT0
+#define ETH_FORCE_LINK_PASS				BIT1
+#define ETH_DO_NOT_FORCE_LINK_PASS			0
+#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX			0
+#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX			BIT2
+#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL		0
+#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL		BIT3
+#define ETH_ADV_NO_FLOW_CTRL				0
+#define ETH_ADV_SYMMETRIC_FLOW_CTRL			BIT4
+#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX		0
+#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS			BIT5
+#define ETH_FORCE_BP_MODE_NO_JAM			0
+#define ETH_FORCE_BP_MODE_JAM_TX			BIT7
+#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR		BIT8
+#define ETH_FORCE_LINK_FAIL				0
+#define ETH_DO_NOT_FORCE_LINK_FAIL			BIT10
+#define ETH_DISABLE_AUTO_NEG_SPEED_GMII			BIT13
+#define ETH_ENABLE_AUTO_NEG_SPEED_GMII			0
+#define ETH_DTE_ADV_0					0
+#define ETH_DTE_ADV_1					BIT14
+#define ETH_MIIPHY_MAC_MODE				0
+#define ETH_MIIPHY_PHY_MODE				BIT15
+#define ETH_AUTO_NEG_NO_CHANGE				0
+#define ETH_RESTART_AUTO_NEG				BIT16
+#define ETH_MAX_RX_PACKET_1518BYTE			0
+#define ETH_MAX_RX_PACKET_1522BYTE			BIT17
+#define ETH_MAX_RX_PACKET_1552BYTE			BIT18
+#define ETH_MAX_RX_PACKET_9022BYTE			(BIT18 | BIT17)
+#define ETH_MAX_RX_PACKET_9192BYTE			BIT19
+#define ETH_MAX_RX_PACKET_9700BYTE			(BIT19 | BIT17)
+#define ETH_SET_EXT_LOOPBACK				BIT20
+#define ETH_CLR_EXT_LOOPBACK				0
+#define ETH_SET_FULL_DUPLEX_MODE			BIT21
+#define ETH_SET_HALF_DUPLEX_MODE			0
+#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX	BIT22
+#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX	0
+#define ETH_SET_GMII_SPEED_TO_10_100			0
+#define ETH_SET_GMII_SPEED_TO_1000			BIT23
+#define ETH_SET_MII_SPEED_TO_10				0
+#define ETH_SET_MII_SPEED_TO_100			BIT24
+
+/* SMI register fields (KW_ETH_SMI_REG) */
+#define ETH_PHY_SMI_TIMEOUT		10000
+#define ETH_PHY_SMI_DATA_OFFS	        0	/* Data */
+#define ETH_PHY_SMI_DATA_MASK	        (0xffff << ETH_PHY_SMI_DATA_OFFS)
+#define ETH_PHY_SMI_DEV_ADDR_OFFS	16	/* PHY device address */
+#define ETH_PHY_SMI_DEV_ADDR_MASK       (0x1f << ETH_PHY_SMI_DEV_ADDR_OFFS)
+#define KW_ETH_SMI_REG_ADDR_OFFS	21	/* PHY device register address */
+#define KW_ETH_SMI_REG_ADDR_MASK	(0x1f << KW_ETH_SMI_REG_ADDR_OFFS)
+#define ETH_PHY_SMI_OPCODE_OFFS	        26	/* Write/Read opcode */
+#define ETH_PHY_SMI_OPCODE_MASK	        (3 << ETH_PHY_SMI_OPCODE_OFFS)
+#define ETH_PHY_SMI_OPCODE_WRITE        (0 << ETH_PHY_SMI_OPCODE_OFFS)
+#define ETH_PHY_SMI_OPCODE_READ         (1 << ETH_PHY_SMI_OPCODE_OFFS)
+#define ETH_PHY_SMI_READ_VALID_MASK	BIT27	/* Read Valid  */
+#define ETH_PHY_SMI_BUSY_MASK		BIT28	/* Busy */
+
+/* SDMA command status fields macros */
+/* Tx & Rx descriptors status */
+#define ETH_ERROR_SUMMARY		    (BIT0)
+
+/* Tx & Rx descriptors command */
+#define ETH_BUFFER_OWNED_BY_DMA		    (BIT31)
+
+/* Tx descriptors status */
+#define ETH_LC_ERROR			    (0	  )
+#define ETH_UR_ERROR			    (BIT1 )
+#define ETH_RL_ERROR			    (BIT2 )
+#define ETH_LLC_SNAP_FORMAT		    (BIT9 )
+
+/* Rx descriptors status */
+#define ETH_CRC_ERROR			    (0	  )
+#define ETH_OVERRUN_ERROR		    (BIT1 )
+#define ETH_MAX_FRAME_LENGTH_ERROR	    (BIT2 )
+#define ETH_RESOURCE_ERROR		    ((BIT2 | BIT1))
+#define ETH_VLAN_TAGGED			    (BIT19)
+#define ETH_BPDU_FRAME			    (BIT20)
+#define ETH_TCP_FRAME_OVER_IP_V_4	    (0	  )
+#define ETH_UDP_FRAME_OVER_IP_V_4	    (BIT21)
+#define ETH_OTHER_FRAME_TYPE		    (BIT22)
+#define ETH_LAYER_2_IS_ETH_V_2		    (BIT23)
+#define ETH_FRAME_TYPE_IP_V_4		    (BIT24)
+#define ETH_FRAME_HEADER_OK		    (BIT25)
+#define ETH_RX_LAST_DESC		    (BIT26)
+#define ETH_RX_FIRST_DESC		    (BIT27)
+#define ETH_UNKNOWN_DESTINATION_ADDR	    (BIT28)
+#define ETH_RX_ENABLE_INTERRUPT		    (BIT29)
+#define ETH_LAYER_4_CHECKSUM_OK		    (BIT30)
+
+/* Rx descriptors byte count */
+#define ETH_FRAME_FRAGMENTED		    (BIT2)
+
+/* Tx descriptors command */
+#define ETH_LAYER_4_CHECKSUM_FIRST_DESC	    (BIT10)
+#define ETH_FRAME_SET_TO_VLAN		    (BIT15)
+#define ETH_TCP_FRAME			    (0	  )
+#define ETH_UDP_FRAME			    (BIT16)
+#define ETH_GEN_TCP_UDP_CHECKSUM	    (BIT17)
+#define ETH_GEN_IP_V_4_CHECKSUM		    (BIT18)
+#define ETH_ZERO_PADDING		    (BIT19)
+#define ETH_TX_LAST_DESC		    (BIT20)
+#define ETH_TX_FIRST_DESC		    (BIT21)
+#define ETH_GEN_CRC			    (BIT22)
+#define ETH_TX_ENABLE_INTERRUPT		    (BIT23)
+#define ETH_AUTO_MODE			    (BIT30)
+
+/* Address decode parameters */
+/* Ethernet Base Address Register bits */
+#define EBAR_TARGET_DRAM			0x00000000
+#define EBAR_TARGET_DEVICE			0x00000001
+#define EBAR_TARGET_CBS				0x00000002
+#define EBAR_TARGET_PCI0			0x00000003
+#define EBAR_TARGET_PCI1			0x00000004
+#define EBAR_TARGET_CUNIT			0x00000005
+#define EBAR_TARGET_AUNIT			0x00000006
+#define EBAR_TARGET_GUNIT			0x00000007
+
+/* Window attributes */
+#define EBAR_ATTR_DRAM_CS0			0x00000E00
+#define EBAR_ATTR_DRAM_CS1			0x00000D00
+#define EBAR_ATTR_DRAM_CS2			0x00000B00
+#define EBAR_ATTR_DRAM_CS3			0x00000700
+
+/* DRAM Target interface */
+#define EBAR_ATTR_DRAM_NO_CACHE_COHERENCY	0x00000000
+#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WT	0x00001000
+#define EBAR_ATTR_DRAM_CACHE_COHERENCY_WB	0x00002000
+
+/* Device Bus Target interface */
+#define EBAR_ATTR_DEVICE_DEVCS0			0x00001E00
+#define EBAR_ATTR_DEVICE_DEVCS1			0x00001D00
+#define EBAR_ATTR_DEVICE_DEVCS2			0x00001B00
+#define EBAR_ATTR_DEVICE_DEVCS3			0x00001700
+#define EBAR_ATTR_DEVICE_BOOTCS3		0x00000F00
+
+/* PCI Target interface */
+#define EBAR_ATTR_PCI_BYTE_SWAP			0x00000000
+#define EBAR_ATTR_PCI_NO_SWAP			0x00000100
+#define EBAR_ATTR_PCI_BYTE_WORD_SWAP		0x00000200
+#define EBAR_ATTR_PCI_WORD_SWAP			0x00000300
+#define EBAR_ATTR_PCI_NO_SNOOP_NOT_ASSERT	0x00000000
+#define EBAR_ATTR_PCI_NO_SNOOP_ASSERT		0x00000400
+#define EBAR_ATTR_PCI_IO_SPACE			0x00000000
+#define EBAR_ATTR_PCI_MEMORY_SPACE		0x00000800
+#define EBAR_ATTR_PCI_REQ64_FORCE		0x00000000
+#define EBAR_ATTR_PCI_REQ64_SIZE		0x00001000
+
+/* Window access control */
+#define EWIN_ACCESS_NOT_ALLOWED 0
+#define EWIN_ACCESS_READ_ONLY	BIT0
+#define EWIN_ACCESS_FULL	(BIT1 | BIT0)
+
+/* typedefs */
+
+typedef enum _eth_func_ret_status {
+	ETH_OK,			/* Returned as expected. */
+	ETH_ERROR,		/* Fundamental error. */
+	ETH_RETRY,		/* Could not process request. Try later. */
+	ETH_END_OF_JOB,		/* Ring has nothing to process. */
+	ETH_QUEUE_FULL,		/* Ring resource error. */
+	ETH_QUEUE_LAST_RESOURCE	/* Ring resources about to exhaust. */
+} ETH_FUNC_RET_STATUS;
+
+typedef enum _eth_queue {
+	ETH_Q0 = 0,
+	ETH_Q1 = 1,
+	ETH_Q2 = 2,
+	ETH_Q3 = 3,
+	ETH_Q4 = 4,
+	ETH_Q5 = 5,
+	ETH_Q6 = 6,
+	ETH_Q7 = 7
+} ETH_QUEUE;
+
+typedef enum _addr_win {
+	ETH_WIN0,
+	ETH_WIN1,
+	ETH_WIN2,
+	ETH_WIN3,
+	ETH_WIN4,
+	ETH_WIN5
+} ETH_ADDR_WIN;
+
+typedef enum _eth_target {
+	ETH_TARGET_DRAM,
+	ETH_TARGET_DEVICE,
+	ETH_TARGET_CBS,
+	ETH_TARGET_PCI0,
+	ETH_TARGET_PCI1
+} ETH_TARGET;
+
+typedef struct _eth_rx_desc {
+	u32 cmd_sts;	/* Descriptor command status */
+	u16 buf_size;	/* Buffer size */
+	u16 byte_cnt;	/* Descriptor buffer byte count */
+	u32 buf_ptr;	/* Descriptor buffer pointer */
+	u32 next_desc_ptr;	/* Next descriptor pointer */
+	u32 return_info;	/* User resource return information */
+} ETH_RX_DESC;
+
+typedef struct _eth_tx_desc {
+	u32 cmd_sts;	/* Descriptor command status */
+	u16 l4i_chk;	/* CPU provided TCP Checksum */
+	u16 byte_cnt;	/* Descriptor buffer byte count */
+	u32 buf_ptr;	/* Descriptor buffer pointer */
+	u32 next_desc_ptr;	/* Next descriptor pointer */
+	u32 return_info;	/* User resource return information */
+} ETH_TX_DESC;
+
+/*
+ * Unified struct for Rx and Tx operations. The user is not required to
+ * be familier with neither Tx nor Rx descriptors.
+ */
+typedef struct _pkt_info {
+	u32 cmd_sts;	/* Descriptor command status */
+	u16 byte_cnt;	/* Descriptor buffer byte count */
+	u16 l4i_chk;	/* Tx CPU provided TCP Checksum */
+	u32 buf_ptr;	/* Descriptor buffer pointer */
+	u32 return_info;	/* User resource return information */
+} PKT_INFO;
+
+typedef struct _eth_win_param {
+	ETH_ADDR_WIN win;	/* Window number. See ETH_ADDR_WIN enum */
+	ETH_TARGET target;	/* System targets. See ETH_TARGET enum */
+	u16 attributes;	/* BAR attributes. See above macros */
+	u32 base_addr;	/* Window base address in u32 form */
+	u32 high_addr;	/* Window high address in u32 form */
+	u32 size;	/* Size in MBytes. Must be % 64Kbyte. */
+	bool enable;		/* Enable/disable access to the window. */
+	u16 access_ctrl;	/*Access ctrl register. see above macros */
+} ETH_WIN_PARAM;
+
+/* Ethernet port specific infomation */
+typedef struct _eth_port_ctrl {
+	ETH_PORT port_num;	/* User Ethernet port number */
+	int port_phy_addr;	/* User phy address of Ethrnet port */
+	u8 port_mac_addr[6];	/* User defined port MAC address. */
+	u32 port_config;	/* User port configuration value */
+	u32 port_config_extend;	/* User port config extend value */
+	u32 port_sdma_config;	/* User port SDMA config value */
+	u32 port_serial_control;	/* User port serial control value */
+	u32 port_tx_queue_command;	/* Port active Tx queues summary */
+	u32 port_rx_queue_command;	/* Port active Rx queues summary */
+
+	/* User function to cast virtual address to CPU bus address */
+	u32 (*port_virt_to_phys) (u32 addr);
+	/* User scratch pad for user specific data structures */
+	void *port_private;
+
+	bool rx_resource_err[MAX_RX_QUEUE_NUM];	/* Rx ring resource err flag */
+	bool tx_resource_err[MAX_TX_QUEUE_NUM];	/* Tx ring resource err flag */
+
+	/* Tx/Rx rings managment indexes fields. For driver use */
+
+	/* Next available Rx resource */
+	volatile ETH_RX_DESC *p_rx_curr_desc_q[MAX_RX_QUEUE_NUM];
+	/* Returning Rx resource */
+	volatile ETH_RX_DESC *p_rx_used_desc_q[MAX_RX_QUEUE_NUM];
+
+	/* Next available Tx resource */
+	volatile ETH_TX_DESC *p_tx_curr_desc_q[MAX_TX_QUEUE_NUM];
+	/* Returning Tx resource */
+	volatile ETH_TX_DESC *p_tx_used_desc_q[MAX_TX_QUEUE_NUM];
+	/* An extra Tx index to support txmt of multiple buffs per packet */
+	volatile ETH_TX_DESC *p_tx_first_desc_q[MAX_TX_QUEUE_NUM];
+
+	/* Tx/Rx rings size and base variables fields. For driver use */
+
+	volatile ETH_RX_DESC *p_rx_desc_area_base[MAX_RX_QUEUE_NUM];
+	u32 rx_desc_area_size[MAX_RX_QUEUE_NUM];
+	char *p_rx_buffer_base[MAX_RX_QUEUE_NUM];
+
+	volatile ETH_TX_DESC *p_tx_desc_area_base[MAX_TX_QUEUE_NUM];
+	u32 tx_desc_area_size[MAX_TX_QUEUE_NUM];
+	char *p_tx_buffer_base[MAX_TX_QUEUE_NUM];
+
+} ETH_PORT_INFO;
+
+
+/* Low level driver function calls */
+static void eth_clear_mib_counters(ETH_PORT eth_port_num);
+
+/* Port operation control routines */
+static void eth_port_init(ETH_PORT_INFO * p_eth_port_ctrl);
+static void eth_port_reset(ETH_PORT eth_port_num);
+static void eth_port_start(ETH_PORT_INFO * p_eth_port_ctrl);
+
+/* Port MAC address routines */
+static void eth_port_uc_addr_set(ETH_PORT eth_port_num,
+				 u8 *p_addr, ETH_QUEUE queue);
+
+/* Port data flow control routines */
+static ETH_FUNC_RET_STATUS eth_port_send(ETH_PORT_INFO * p_eth_port_ctrl,
+					 ETH_QUEUE tx_queue,
+					 PKT_INFO * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(ETH_PORT_INFO * p_eth_port_ctrl,
+					      ETH_QUEUE tx_queue,
+					      PKT_INFO * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_port_receive(ETH_PORT_INFO * p_eth_port_ctrl,
+					    ETH_QUEUE rx_queue,
+					    PKT_INFO * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(ETH_PORT_INFO * p_eth_port_ctrl,
+					      ETH_QUEUE rx_queue,
+					      PKT_INFO * p_pkt_info);
+#endif /* __EGIGA_H__ */
diff --git a/cpu/arm926ejs/kirkwood/egiga_regs.h b/cpu/arm926ejs/kirkwood/egiga_regs.h
new file mode 100644
index 0000000..a24fa04
--- /dev/null
+++ b/cpu/arm926ejs/kirkwood/egiga_regs.h
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Prafulla Wadaskar <prafulla at marvell.com>
+ *
+ * (C) Copyright 2003
+ * Ingo Assmus <ingo.assmus at keymile.com>
+ *
+ * based on - Driver for MV64360X ethernet ports
+ * Copyright (C) 2002 rabeeh at galileo.co.il
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#ifndef __EGIGA_REGS_H__
+#define __EGIGA_REGS_H__
+
+/*
+ *Ethernet Controller Registers
+ */
+#define KW_ETH_PHY_ADDR_REG(port)			(0x72000 + (port<<14))
+#define KW_ETH_SMI_REG(port)				(0x72004 + (port<<14))
+#define KW_ETH_UNIT_DEFAULT_ADDR_REG(port)		(0x72008 + (port<<14))
+#define KW_ETH_UNIT_DEFAULTID_REG(port)			(0x7200c + (port<<14))
+#define KW_ETH_UNIT_INTERRUPT_CAUSE_REG(port)		(0x72080 + (port<<14))
+#define KW_ETH_UNIT_INTERRUPT_MASK_REG(port)		(0x72084 + (port<<14))
+#define KW_ETH_UNIT_ERROR_ADDR_REG(port)		(0x72094 + (port<<14))
+#define KW_ETH_INTADR_ERROR_ADDR_REG(port)		(0x72098 + (port<<14))
+#define KW_ETH_UNIT_CTRL_REG(port)			(0x720b0 + (port<<14))
+#define KW_ETH_BAR_0(port)				(0x72200 + (port<<14))
+#define KW_ETH_BAR_1(port)				(0x72208 + (port<<14))
+#define KW_ETH_BAR_2(port)				(0x72210 + (port<<14))
+#define KW_ETH_BAR_3(port)				(0x72218 + (port<<14))
+#define KW_ETH_BAR_4(port)				(0x72220 + (port<<14))
+#define KW_ETH_BAR_5(port)				(0x72228 + (port<<14))
+#define KW_ETH_SIZE_REG_0(port)				(0x72204 + (port<<14))
+#define KW_ETH_SIZE_REG_1(port)				(0x7220c + (port<<14))
+#define KW_ETH_SIZE_REG_2(port)				(0x72214 + (port<<14))
+#define KW_ETH_SIZE_REG_3(port)				(0x7221c + (port<<14))
+#define KW_ETH_SIZE_REG_4(port)				(0x72224 + (port<<14))
+#define KW_ETH_SIZE_REG_5(port)				(0x7222c + (port<<14))
+#define KW_ETH_HIGH_ADDR_REMAP_REG_0(port)		(0x72280 + (port<<14))
+#define KW_ETH_HIGH_ADDR_REMAP_REG_1(port)		(0x72284 + (port<<14))
+#define KW_ETH_HIGH_ADDR_REMAP_REG_2(port)		(0x72288 + (port<<14))
+#define KW_ETH_HIGH_ADDR_REMAP_REG_3(port)		(0x7228c + (port<<14))
+#define KW_ETH_BASE_ADDR_ENABLE_REG(port)		(0x72290 + (port<<14))
+#define KW_ETH_ACCESS_PROTECTION_REG(port)		(0x72294 + (port<<14))
+#define KW_ETH_PORT_CONFIG_REG(port)			(0x72400 + (port<<14))
+#define KW_ETH_PORT_CONFIG_EXTEND_REG(port)		(0x72404 + (port<<14))
+#define KW_ETH_MII_SERIAL_PARAMETRS_REG(port)		(0x72408 + (port<<14))
+#define KW_ETH_VLAN_ETHERTYPE_REG(port)			(0x72410 + (port<<14))
+#define KW_ETH_MAC_ADDR_LOW(port)			(0x72414 + (port<<14))
+#define KW_ETH_MAC_ADDR_HIGH(port)			(0x72418 + (port<<14))
+#define KW_ETH_SDMA_CONFIG_REG(port)			(0x7241c + (port<<14))
+#define KW_ETH_DSCP_0(port)				(0x72420 + (port<<14))
+#define KW_ETH_DSCP_1(port)				(0x72424 + (port<<14))
+#define KW_ETH_DSCP_2(port)				(0x72428 + (port<<14))
+#define KW_ETH_DSCP_3(port)				(0x7242c + (port<<14))
+#define KW_ETH_DSCP_4(port)				(0x72430 + (port<<14))
+#define KW_ETH_DSCP_5(port)				(0x72434 + (port<<14))
+#define KW_ETH_DSCP_6(port)				(0x72438 + (port<<14))
+#define KW_ETH_PORT_SERIAL_CONTROL0_REG(port)		(0x7243c + (port<<14))
+#define KW_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port)	(0x72440 + (port<<14))
+#define KW_ETH_PORT_STATUS0_REG(port)			(0x72444 + (port<<14))
+#define KW_ETH_PORT_SERIAL_CONTROL1_REG(port)		(0x7244c + (port<<14))
+#define KW_ETH_PORT_STATUS1_REG(port)			(0x72450 + (port<<14))
+#define KW_ETH_MARVELL_HEADER_REG(port)			(0x72454 + (port<<14))
+#define KW_ETH_INTERRUPT_CAUSE_REG(port)		(0x72460 + (port<<14))
+#define KW_ETH_INTERRUPT_CAUSE_EXTEND_REG(port)		(0x72464 + (port<<14))
+#define KW_ETH_INTERRUPT_MASK_REG(port)			(0x72468 + (port<<14))
+#define KW_ETH_INTERRUPT_EXTEND_MASK_REG(port)		(0x7246c + (port<<14))
+#define KW_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port)	(0x72474 + (port<<14))
+#define KW_ETH_RX_MINIMAL_FRAME_SIZE_REG(port)		(0x7247c + (port<<14))
+#define KW_ETH_RX_DISCARDED_FRAMES_COUNTER(port)	(0x72484 + (port<<14))
+#define KW_ETH_PORT_OVERRUN_FRM_COUNTER_REG(port)	(0x72488 + (port<<14))
+#define KW_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port)	(0x72494 + (port<<14))
+#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port)	(0x7260c + (port<<14))
+#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port)	(0x7261c + (port<<14))
+#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port)	(0x7262c + (port<<14))
+#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port)	(0x7263c + (port<<14))
+#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port)	(0x7264c + (port<<14))
+#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port)	(0x7265c + (port<<14))
+#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port)	(0x7266c + (port<<14))
+#define KW_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port)	(0x7267c + (port<<14))
+#define KW_ETH_RECEIVE_QUEUE_COMMAND_REG(port)		(0x72680 + (port<<14))
+#define KW_ETH_CURRENT_SERVED_TX_DESC_PTR(port)		(0x72684 + (port<<14))
+#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port)	(0x726c0 + (port<<14))
+#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port)	(0x726c4 + (port<<14))
+#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port)	(0x726c8 + (port<<14))
+#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port)	(0x726cc + (port<<14))
+#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port)	(0x726d0 + (port<<14))
+#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port)	(0x726d4 + (port<<14))
+#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port)	(0x726d8 + (port<<14))
+#define KW_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port)	(0x726dc + (port<<14))
+#define KW_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port)	(0x73400 + (port<<14))
+#define KW_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port)	(0x73500 + (port<<14))
+#define KW_ETH_DA_FILTER_UNICAST_TABLE_BASE(port)		(0x73600 + (port<<14))
+#define KW_ETH_TRANSMIT_QUEUE_COMMAND_REG(port)		(0x72448 + (port<<14))
+#define KW_ETH_TX_QUEUE_FIXED_PRIORITY(port)		(0x724dc + (port<<14))
+#define KW_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port)	(0x724e0 + (port<<14))
+#define KW_ETH_MAXIMUM_TRANSMIT_UNIT(port)		(0x724e8 + (port<<14))
+#define KW_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port)	(0x724ec + (port<<14))
+#define KW_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port)	(0x72700 + (port<<14))
+#define KW_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port)	(0x72710 + (port<<14))
+#define KW_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port)	(0x72720 + (port<<14))
+#define KW_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port)	(0x72730 + (port<<14))
+#define KW_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port)	(0x72740 + (port<<14))
+#define KW_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port)	(0x72750 + (port<<14))
+#define KW_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port)	(0x72760 + (port<<14))
+#define KW_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port)	(0x72770 + (port<<14))
+#define KW_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port)	(0x72704 + (port<<14))
+#define KW_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port)	(0x72714 + (port<<14))
+#define KW_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port)	(0x72724 + (port<<14))
+#define KW_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port)	(0x72734 + (port<<14))
+#define KW_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port)	(0x72744 + (port<<14))
+#define KW_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port)	(0x72754 + (port<<14))
+#define KW_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port)	(0x72764 + (port<<14))
+#define KW_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port)	(0x72774 + (port<<14))
+#define KW_ETH_TX_QUEUE_0_ARBITER_CONFIG(port)		(0x72708 + (port<<14))
+#define KW_ETH_TX_QUEUE_1_ARBITER_CONFIG(port)		(0x72718 + (port<<14))
+#define KW_ETH_TX_QUEUE_2_ARBITER_CONFIG(port)		(0x72728 + (port<<14))
+#define KW_ETH_TX_QUEUE_3_ARBITER_CONFIG(port)		(0x72738 + (port<<14))
+#define KW_ETH_TX_QUEUE_4_ARBITER_CONFIG(port)		(0x72748 + (port<<14))
+#define KW_ETH_TX_QUEUE_5_ARBITER_CONFIG(port)		(0x72758 + (port<<14))
+#define KW_ETH_TX_QUEUE_6_ARBITER_CONFIG(port)		(0x72768 + (port<<14))
+#define KW_ETH_TX_QUEUE_7_ARBITER_CONFIG(port)		(0x72778 + (port<<14))
+#define KW_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port)		(0x72780 + (port<<14))
+
+#define KW_ETH_MIB_COUNTERS_BASE(port)			(0x73000 + (port<<14))
+
+/* Type defs */
+#ifndef __ASSEMBLY__
+typedef enum _eth_port {
+	ETH_0 = 0,
+	ETH_1 = 1,
+} ETH_PORT;			/* SOC has two Gbe Ports */
+
+/* smi register read/write function can be used by switch/phy */
+int eth_smi_reg_read(unsigned int eth_port_num, unsigned int phy_adr,
+		     unsigned int reg_ofs, unsigned short *data);
+int eth_smi_reg_write(unsigned int eth_port_num, unsigned int phy_adr,
+		      unsigned int reg_ofs, unsigned short data);
+#endif
+
+#endif /* __EGIGA_REGS_H__ */
diff --git a/cpu/arm926ejs/kirkwood/kwcore.h b/cpu/arm926ejs/kirkwood/kwcore.h
index 0ddc6a8..50043d8 100644
--- a/cpu/arm926ejs/kirkwood/kwcore.h
+++ b/cpu/arm926ejs/kirkwood/kwcore.h
@@ -87,6 +87,8 @@
 #define KW_REG_TMR_RELOAD		(0x20310)
 #define KW_REG_TMR_VAL			(0x20314)
 
+#include "egiga_regs.h"
+
 /*
  * Macros
  * CPU architecture dependent I/O read/write
diff --git a/net/eth.c b/net/eth.c
index 4bbf84b..77fa8a5 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -73,6 +73,7 @@ int board_eth_init(bd_t *bis) __attribute((weak, alias("__def_eth_init")));
 
 extern int mv6436x_eth_initialize(bd_t *);
 extern int mv6446x_eth_initialize(bd_t *);
+extern int kirkwood_egiga_initialize(bd_t*);
 
 #ifdef CONFIG_API
 extern void (*push_packet)(volatile void *, int);
@@ -205,6 +206,9 @@ int eth_initialize(bd_t *bis)
 #if defined(CONFIG_DB64460) || defined(CONFIG_P3Mx)
 	mv6446x_eth_initialize(bis);
 #endif
+#ifdef CONFIG_KIRKWOOD_EGIGA
+       kirkwood_egiga_initialize(bis);
+#endif
 	if (!eth_devices) {
 		puts ("No ethernet found.\n");
 		show_boot_progress (-64);
-- 
1.5.3.3



More information about the U-Boot mailing list