diff mbox

[[PATCH,7/7] keystone2: net: add keystone ethernet driver

Message ID 1391809945-10223-8-git-send-email-m-karicheri2@ti.com
State New
Headers show

Commit Message

Murali Karicheri Feb. 7, 2014, 9:52 p.m. UTC
The network driver consists of multicore navigator
driver and the ethernet sub system driver. Multicore
navigator consists of Network Coprocessor (NetCP) and
Queue Manager sub system. More details on the hardware can
be obtained from the following links:-

Network Coprocessor: http://www.ti.com/lit/pdf/sprugz6
Multicore Navigator: http://www.ti.com/lit/pdf/sprugr9

Multicore navigator driver implements APIs to configure
the Queue Manager and NetCP Pkt DMA. Ethernet driver
configures the CPSW, SGMI and Phy and uses the the Navigator
APIs. The driver supports 4 Ethernet ports and can work with
only one port at a time.

Port configurations are defined in board.c.

Signed-off-by: Vitaly Andrianov <vitalya@ti.com>
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Signed-off-by: WingMan Kwok <w-kwok2@ti.com>
---
 arch/arm/cpu/armv7/keystone/Makefile              |    1 +
 arch/arm/cpu/armv7/keystone/keystone_nav.c        |  377 +++++++++
 arch/arm/include/asm/arch-keystone/emac_defs.h    |  255 ++++++
 arch/arm/include/asm/arch-keystone/keystone_nav.h |  194 +++++
 board/ti/k2hk_evm/board.c                         |   65 ++
 drivers/net/Makefile                              |    1 +
 drivers/net/keystone_net.c                        |  857 +++++++++++++++++++++
 include/configs/k2hk_evm.h                        |   38 +
 8 files changed, 1788 insertions(+)
 create mode 100644 arch/arm/cpu/armv7/keystone/keystone_nav.c
 create mode 100644 arch/arm/include/asm/arch-keystone/emac_defs.h
 create mode 100644 arch/arm/include/asm/arch-keystone/keystone_nav.h
 create mode 100644 drivers/net/keystone_net.c
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/keystone/Makefile b/arch/arm/cpu/armv7/keystone/Makefile
index 0fd4189..e323cf6 100644
--- a/arch/arm/cpu/armv7/keystone/Makefile
+++ b/arch/arm/cpu/armv7/keystone/Makefile
@@ -11,6 +11,7 @@  obj-y   += psc.o
 obj-y   += clock.o
 obj-y   += cmd_clock.o
 obj-y   += cmd_mon.o
+obj-y   += keystone_nav.o
 obj-y   += msmc.o
 obj-y   += lowlevel_init.o
 obj-$(CONFIG_SPL_BUILD) += spl.o
diff --git a/arch/arm/cpu/armv7/keystone/keystone_nav.c b/arch/arm/cpu/armv7/keystone/keystone_nav.c
new file mode 100644
index 0000000..3579be1
--- /dev/null
+++ b/arch/arm/cpu/armv7/keystone/keystone_nav.c
@@ -0,0 +1,377 @@ 
+/*
+ * Multicore Navigator driver for TI Keystone 2 devices.
+ *
+ * (C) Copyright 2012-2014
+ *     Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/keystone_nav.h>
+
+static int soc_type =
+#ifdef CONFIG_SOC_K2HK
+	k2hk;
+#endif
+
+struct qm_config k2hk_qm_memmap = {
+	.stat_cfg	= 0x02a40000,
+	.queue		= (struct qm_reg_queue *)0x02a80000,
+	.mngr_vbusm	= 0x23a80000,
+	.i_lram		= 0x00100000,
+	.proxy		= (struct qm_reg_queue *)0x02ac0000,
+	.status_ram	= 0x02a06000,
+	.mngr_cfg	= (struct qm_cfg_reg *)0x02a02000,
+	.intd_cfg	= 0x02a0c000,
+	.desc_mem	= (struct descr_mem_setup_reg *)0x02a03000,
+	.region_num	= 64,
+	.pdsp_cmd	= 0x02a20000,
+	.pdsp_ctl	= 0x02a0f000,
+	.pdsp_iram	= 0x02a10000,
+	.qpool_num	= 4000,
+};
+
+/*
+ * We are going to use only one type of descriptors - host packet
+ * descriptors. We staticaly allocate memory for them here
+ */
+struct qm_host_desc desc_pool[HDESC_NUM] __aligned(sizeof(struct qm_host_desc));
+
+static struct qm_config *qm_cfg;
+
+inline int num_of_desc_to_reg(int num_descr)
+{
+	int j, num;
+
+	for (j = 0, num = 32; j < 15; j++, num *= 2) {
+		if (num_descr <= num)
+			return j;
+	}
+
+	return 15;
+}
+
+static int _qm_init(struct qm_config *cfg)
+{
+	u32	j;
+
+	if (cfg == NULL)
+		return QM_ERR;
+
+	qm_cfg = cfg;
+
+	qm_cfg->mngr_cfg->link_ram_base0	= qm_cfg->i_lram;
+	qm_cfg->mngr_cfg->link_ram_size0	= HDESC_NUM * 8;
+	qm_cfg->mngr_cfg->link_ram_base1	= 0;
+	qm_cfg->mngr_cfg->link_ram_size1	= 0;
+	qm_cfg->mngr_cfg->link_ram_base2	= 0;
+
+	qm_cfg->desc_mem[0].base_addr = (u32)desc_pool;
+	qm_cfg->desc_mem[0].start_idx = 0;
+	qm_cfg->desc_mem[0].desc_reg_size =
+		(((sizeof(struct qm_host_desc) >> 4) - 1) << 16) |
+		num_of_desc_to_reg(HDESC_NUM);
+
+	memset(desc_pool, 0, sizeof(desc_pool));
+	for (j = 0; j < HDESC_NUM; j++)
+		qm_push(&desc_pool[j], qm_cfg->qpool_num);
+
+	return QM_OK;
+}
+
+int qm_init(void)
+{
+	switch (soc_type) {
+	case k2hk:
+		return _qm_init(&k2hk_qm_memmap);
+	}
+
+	return QM_ERR;
+}
+
+void qm_close(void)
+{
+	u32	j;
+
+	if (qm_cfg == NULL)
+		return;
+
+	queue_close(qm_cfg->qpool_num);
+
+	qm_cfg->mngr_cfg->link_ram_base0	= 0;
+	qm_cfg->mngr_cfg->link_ram_size0	= 0;
+	qm_cfg->mngr_cfg->link_ram_base1	= 0;
+	qm_cfg->mngr_cfg->link_ram_size1	= 0;
+	qm_cfg->mngr_cfg->link_ram_base2	= 0;
+
+	for (j = 0; j < qm_cfg->region_num; j++) {
+		qm_cfg->desc_mem[j].base_addr = 0;
+		qm_cfg->desc_mem[j].start_idx = 0;
+		qm_cfg->desc_mem[j].desc_reg_size = 0;
+	}
+
+	qm_cfg = NULL;
+}
+
+void qm_push(struct qm_host_desc *hd, u32 qnum)
+{
+	u32 regd;
+
+	if (!qm_cfg)
+		return;
+
+	cpu_to_bus((u32 *)hd, sizeof(struct qm_host_desc)/4);
+	regd = (u32)hd | ((sizeof(struct qm_host_desc) >> 4) - 1);
+	writel(regd, &qm_cfg->queue[qnum].ptr_size_thresh);
+}
+
+void qm_buff_push(struct qm_host_desc *hd, u32 qnum,
+		    void *buff_ptr, u32 buff_len)
+{
+	hd->orig_buff_len = buff_len;
+	hd->buff_len = buff_len;
+	hd->orig_buff_ptr = (u32)buff_ptr;
+	hd->buff_ptr = (u32)buff_ptr;
+	qm_push(hd, qnum);
+}
+
+struct qm_host_desc *qm_pop(u32 qnum)
+{
+	u32 uhd;
+
+	if (!qm_cfg)
+		return NULL;
+
+	uhd = readl(&qm_cfg->queue[qnum].ptr_size_thresh) & ~0xf;
+	if (uhd)
+		cpu_to_bus((u32 *)uhd, sizeof(struct qm_host_desc)/4);
+
+	return (struct qm_host_desc *)uhd;
+}
+
+struct qm_host_desc *qm_pop_from_free_pool(void)
+{
+	if (!qm_cfg)
+		return NULL;
+
+	return qm_pop(qm_cfg->qpool_num);
+}
+
+void queue_close(u32 qnum)
+{
+	struct qm_host_desc *hd;
+
+	while ((hd = qm_pop(qnum)))
+		;
+}
+
+/************************************************
+ * DMA API
+ ***********************************************/
+
+struct pktdma_cfg k2hk_netcp_pktdma = {
+	.global		= (struct global_ctl_regs *)0x02004000,
+	.tx_ch		= (struct tx_chan_regs *)0x02004400,
+	.tx_ch_num	= 9,
+	.rx_ch		= (struct rx_chan_regs *)0x02004800,
+	.rx_ch_num	= 26,
+	.tx_sched	= (u32 *)0x02004c00,
+	.rx_flows	= (struct rx_flow_regs *)0x02005000,
+	.rx_flow_num	= 32,
+
+	.rx_free_q	= 4001,
+	.rx_rcv_q	= 4002,
+	.tx_snd_q	= 648,
+};
+
+struct pktdma_cfg *netcp;
+
+static int netcp_rx_disable(void)
+{
+	u32 j, v, k;
+
+	for (j = 0; j < netcp->rx_ch_num; j++) {
+		v = readl(&netcp->rx_ch[j].cfg_a);
+		if (!(v & CPDMA_CHAN_A_ENABLE))
+			continue;
+
+		writel(v | CPDMA_CHAN_A_TDOWN, &netcp->rx_ch[j].cfg_a);
+		for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) {
+			udelay(100);
+			v = readl(&netcp->rx_ch[j].cfg_a);
+			if (!(v & CPDMA_CHAN_A_ENABLE))
+				continue;
+		}
+		/* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */
+	}
+
+	/* Clear all of the flow registers */
+	for (j = 0; j < netcp->rx_flow_num; j++) {
+		writel(0, &netcp->rx_flows[j].control);
+		writel(0, &netcp->rx_flows[j].tags);
+		writel(0, &netcp->rx_flows[j].tag_sel);
+		writel(0, &netcp->rx_flows[j].fdq_sel[0]);
+		writel(0, &netcp->rx_flows[j].fdq_sel[1]);
+		writel(0, &netcp->rx_flows[j].thresh[0]);
+		writel(0, &netcp->rx_flows[j].thresh[1]);
+		writel(0, &netcp->rx_flows[j].thresh[2]);
+	}
+
+	return QM_OK;
+}
+
+static int netcp_tx_disable(void)
+{
+	u32 j, v, k;
+
+	for (j = 0; j < netcp->tx_ch_num; j++) {
+		v = readl(&netcp->tx_ch[j].cfg_a);
+		if (!(v & CPDMA_CHAN_A_ENABLE))
+			continue;
+
+		writel(v | CPDMA_CHAN_A_TDOWN, &netcp->tx_ch[j].cfg_a);
+		for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) {
+			udelay(100);
+			v = readl(&netcp->tx_ch[j].cfg_a);
+			if (!(v & CPDMA_CHAN_A_ENABLE))
+				continue;
+		}
+		/* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */
+	}
+
+	return QM_OK;
+}
+
+static int _netcp_init(struct pktdma_cfg *netcp_cfg,
+		       struct rx_buff_desc *rx_buffers)
+{
+	u32 j, v;
+	struct qm_host_desc *hd;
+	u8 *rx_ptr;
+
+	if (netcp_cfg == NULL || rx_buffers == NULL ||
+	    rx_buffers->buff_ptr == NULL || qm_cfg == NULL)
+		return QM_ERR;
+
+	netcp = netcp_cfg;
+	netcp->rx_flow = rx_buffers->rx_flow;
+
+	/* init rx queue */
+	rx_ptr = rx_buffers->buff_ptr;
+
+	for (j = 0; j < rx_buffers->num_buffs; j++) {
+		hd = qm_pop(qm_cfg->qpool_num);
+		if (hd == NULL)
+			return QM_ERR;
+
+		qm_buff_push(hd, netcp->rx_free_q,
+			     rx_ptr, rx_buffers->buff_len);
+
+		rx_ptr += rx_buffers->buff_len;
+	}
+
+	netcp_rx_disable();
+
+	/* configure rx channels */
+	v = CPDMA_REG_VAL_MAKE_RX_FLOW_A(1, 1, 0, 0, 0, 0, 0, netcp->rx_rcv_q);
+	writel(v, &netcp->rx_flows[netcp->rx_flow].control);
+	writel(0, &netcp->rx_flows[netcp->rx_flow].tags);
+	writel(0, &netcp->rx_flows[netcp->rx_flow].tag_sel);
+
+	v = CPDMA_REG_VAL_MAKE_RX_FLOW_D(0, netcp->rx_free_q, 0,
+					 netcp->rx_free_q);
+
+	writel(v, &netcp->rx_flows[netcp->rx_flow].fdq_sel[0]);
+	writel(v, &netcp->rx_flows[netcp->rx_flow].fdq_sel[1]);
+	writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[0]);
+	writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[1]);
+	writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[2]);
+
+	for (j = 0; j < netcp->rx_ch_num; j++)
+		writel(CPDMA_CHAN_A_ENABLE, &netcp->rx_ch[j].cfg_a);
+
+	/* configure tx channels */
+	/* Disable loopback in the tx direction */
+	writel(0, &netcp->global->emulation_control);
+
+/* TODO: make it dependend on a soc type variable */
+#ifdef CONFIG_SOC_K2HK
+	/* Set QM base address, only for K2x devices */
+	writel(0x23a80000, &netcp->global->qm_base_addr[0]);
+#endif
+
+	/* Enable all channels. The current state isn't important */
+	for (j = 0; j < netcp->tx_ch_num; j++)  {
+		writel(0, &netcp->tx_ch[j].cfg_b);
+		writel(CPDMA_CHAN_A_ENABLE, &netcp->tx_ch[j].cfg_a);
+	}
+
+	return QM_OK;
+}
+
+int netcp_init(struct rx_buff_desc *rx_buffers)
+{
+	switch (soc_type) {
+	case k2hk:
+		_netcp_init(&k2hk_netcp_pktdma, rx_buffers);
+		return QM_OK;
+	}
+	return QM_ERR;
+}
+
+int netcp_close(void)
+{
+	if (!netcp)
+		return QM_ERR;
+
+	netcp_tx_disable();
+	netcp_rx_disable();
+
+	queue_close(netcp->rx_free_q);
+	queue_close(netcp->rx_rcv_q);
+	queue_close(netcp->tx_snd_q);
+
+	return QM_OK;
+}
+
+int netcp_send(u32 *pkt, int num_bytes, u32 swinfo2)
+{
+	struct qm_host_desc *hd;
+
+	hd = qm_pop(qm_cfg->qpool_num);
+	if (hd == NULL)
+		return QM_ERR;
+
+	hd->desc_info	= num_bytes;
+	hd->swinfo[2]	= swinfo2;
+	hd->packet_info = qm_cfg->qpool_num;
+
+	qm_buff_push(hd, netcp->tx_snd_q, pkt, num_bytes);
+
+	return QM_OK;
+}
+
+void *netcp_recv(u32 **pkt, int *num_bytes)
+{
+	struct qm_host_desc *hd;
+
+	hd = qm_pop(netcp->rx_rcv_q);
+	if (!hd)
+		return NULL;
+
+	*pkt = (u32 *)hd->buff_ptr;
+	*num_bytes = hd->desc_info & 0x3fffff;
+
+	return hd;
+}
+
+void netcp_release_rxhd(void *hd)
+{
+	struct qm_host_desc *_hd = (struct qm_host_desc *)hd;
+
+	_hd->buff_len = _hd->orig_buff_len;
+	_hd->buff_ptr = _hd->orig_buff_ptr;
+
+	qm_push(_hd, netcp->rx_free_q);
+}
diff --git a/arch/arm/include/asm/arch-keystone/emac_defs.h b/arch/arm/include/asm/arch-keystone/emac_defs.h
new file mode 100644
index 0000000..ade5211
--- /dev/null
+++ b/arch/arm/include/asm/arch-keystone/emac_defs.h
@@ -0,0 +1,255 @@ 
+/*
+ * emac definitions for keystone2 devices
+ *
+ * (C) Copyright 2012-2014
+ *     Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _EMAC_DEFS_H_
+#define _EMAC_DEFS_H_
+
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+#define DEVICE_REG32_R(a)			readl(a)
+#define DEVICE_REG32_W(a, v)			writel(v, a)
+
+/*#define chipLmbd(x,y) _lmbd(x,y) */
+
+#define EMAC_EMACSL_BASE_ADDR		(KS2_PASS_BASE + 0x00090900)
+#define EMAC_MDIO_BASE_ADDR		(KS2_PASS_BASE + 0x00090300)
+#define EMAC_SGMII_BASE_ADDR		(KS2_PASS_BASE + 0x00090100)
+
+#define KEYSTONE2_EMAC_GIG_ENABLE
+
+#define MAC_ID_BASE_ADDR		(KS2_DEVICE_STATE_CTRL_BASE + 0x110)
+
+#ifdef CONFIG_SOC_K2HK
+/* MDIO module input frequency */
+#define EMAC_MDIO_BUS_FREQ		(clk_get_rate(pass_pll_clk))
+/* MDIO clock output frequency */
+#define EMAC_MDIO_CLOCK_FREQ		1000000		/* 1.0 MHz */
+#endif
+
+/* MII Status Register */
+#define MII_STATUS_REG			1
+#define MII_STATUS_LINK_MASK		(0x4)
+
+/* Marvell 88E1111 PHY ID */
+#define PHY_MARVELL_88E1111		(0x01410cc0)
+
+
+
+#define MDIO_CONTROL_IDLE		(0x80000000)
+#define MDIO_CONTROL_ENABLE		(0x40000000)
+#define MDIO_CONTROL_FAULT_ENABLE	(0x40000)
+#define MDIO_CONTROL_FAULT		(0x80000)
+#define MDIO_USERACCESS0_GO		(0x80000000)
+#define MDIO_USERACCESS0_WRITE_READ	(0x0)
+#define MDIO_USERACCESS0_WRITE_WRITE	(0x40000000)
+#define MDIO_USERACCESS0_ACK		(0x20000000)
+
+#define EMAC_MACCONTROL_MIIEN_ENABLE		(0x20)
+#define EMAC_MACCONTROL_FULLDUPLEX_ENABLE	(0x1)
+#define EMAC_MACCONTROL_GIGABIT_ENABLE		(1 << 7)
+#define EMAC_MACCONTROL_GIGFORCE		(1 << 17)
+#define EMAC_MACCONTROL_RMIISPEED_100		(1 << 15)
+
+#define EMAC_MIN_ETHERNET_PKT_SIZE	60
+
+struct mac_sl_cfg {
+	u_int32_t max_rx_len;	/* Maximum receive packet length. */
+	u_int32_t ctl;		/* Control bitfield */
+};
+
+/***************************************************************************
+ * Definition: Control bitfields used in the ctl field of hwGmacSlCfg_t
+ **************************************************************************/
+#define GMACSL_RX_ENABLE_RCV_CONTROL_FRAMES       (1 << 24)
+#define GMACSL_RX_ENABLE_RCV_SHORT_FRAMES         (1 << 23)
+#define GMACSL_RX_ENABLE_RCV_ERROR_FRAMES         (1 << 22)
+#define GMACSL_RX_ENABLE_EXT_CTL                  (1 << 18)
+#define GMACSL_RX_ENABLE_GIG_FORCE                (1 << 17)
+#define GMACSL_RX_ENABLE_IFCTL_B                  (1 << 16)
+#define GMACSL_RX_ENABLE_IFCTL_A                  (1 << 15)
+#define GMACSL_RX_ENABLE_CMD_IDLE                 (1 << 11)
+#define GMACSL_TX_ENABLE_SHORT_GAP                (1 << 10)
+#define GMACSL_ENABLE_GIG_MODE                    (1 <<  7)
+#define GMACSL_TX_ENABLE_PACE                     (1 <<  6)
+#define GMACSL_ENABLE                             (1 <<  5)
+#define GMACSL_TX_ENABLE_FLOW_CTL                 (1 <<  4)
+#define GMACSL_RX_ENABLE_FLOW_CTL                 (1 <<  3)
+#define GMACSL_ENABLE_LOOPBACK                    (1 <<  1)
+#define GMACSL_ENABLE_FULL_DUPLEX                 (1 <<  0)
+
+
+/***************************************************************************
+ * DEFINTITION: function return values
+ **************************************************************************/
+#define GMACSL_RET_OK                        0
+#define GMACSL_RET_INVALID_PORT             -1
+#define GMACSL_RET_WARN_RESET_INCOMPLETE    -2
+#define GMACSL_RET_WARN_MAXLEN_TOO_BIG      -3
+#define GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE -4
+
+
+/* Register offsets */
+#define CPGMACSL_REG_ID         0x00
+#define CPGMACSL_REG_CTL        0x04
+#define CPGMACSL_REG_STATUS     0x08
+#define CPGMACSL_REG_RESET      0x0c
+#define CPGMACSL_REG_MAXLEN     0x10
+#define CPGMACSL_REG_BOFF       0x14
+#define CPGMACSL_REG_RX_PAUSE   0x18
+#define CPGMACSL_REG_TX_PAURSE  0x1c
+#define CPGMACSL_REG_EM_CTL     0x20
+#define CPGMACSL_REG_PRI        0x24
+
+/* Soft reset register values */
+#define CPGMAC_REG_RESET_VAL_RESET_MASK      (1 << 0)
+#define CPGMAC_REG_RESET_VAL_RESET           (1 << 0)
+
+/* Maxlen register values */
+#define CPGMAC_REG_MAXLEN_LEN                0x3fff
+
+ /* Control bitfields */
+#define CPSW_CTL_P2_PASS_PRI_TAGGED     (1 << 5)
+#define CPSW_CTL_P1_PASS_PRI_TAGGED     (1 << 4)
+#define CPSW_CTL_P0_PASS_PRI_TAGGED     (1 << 3)
+#define CPSW_CTL_P0_ENABLE              (1 << 2)
+#define CPSW_CTL_VLAN_AWARE             (1 << 1)
+#define CPSW_CTL_FIFO_LOOPBACK          (1 << 0)
+
+#define DEVICE_CPSW_NUM_PORTS       5                    /* 5 switch ports */
+#define DEVICE_CPSW_BASE            (0x02090800)
+#define target_get_switch_ctl()        CPSW_CTL_P0_ENABLE   /* Enable port 0 */
+#define SWITCH_MAX_PKT_SIZE	9000
+
+/* Register offsets */
+#define CPSW_REG_CTL                0x004
+#define CPSW_REG_STAT_PORT_EN       0x00c
+#define CPSW_REG_MAXLEN             0x040
+#define CPSW_REG_ALE_CONTROL        0x608
+#define CPSW_REG_ALE_PORTCTL(x)     (0x640 + (x)*4)
+
+
+/* Register values */
+#define CPSW_REG_VAL_STAT_ENABLE_ALL             0xf
+#define CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE	((u_int32_t)0xc0000000)
+#define CPSW_REG_VAL_ALE_CTL_BYPASS		((u_int32_t)0x00000010)
+#define CPSW_REG_VAL_PORTCTL_FORWARD_MODE        0x3
+
+#define SGMII_REG_STATUS_LOCK		BIT(4)
+#define	SGMII_REG_STATUS_LINK		BIT(0)
+#define SGMII_REG_STATUS_AUTONEG	BIT(2)
+#define SGMII_REG_CONTROL_AUTONEG	BIT(0)
+#define SGMII_REG_CONTROL_MASTER	BIT(5)
+#define	SGMII_REG_MR_ADV_ENABLE		BIT(0)
+#define	SGMII_REG_MR_ADV_LINK		BIT(15)
+#define	SGMII_REG_MR_ADV_FULL_DUPLEX	BIT(12)
+#define SGMII_REG_MR_ADV_GIG_MODE	BIT(11)
+
+#define SGMII_LINK_MAC_MAC_AUTONEG	0
+#define SGMII_LINK_MAC_PHY		1
+#define SGMII_LINK_MAC_MAC_FORCED	2
+#define SGMII_LINK_MAC_FIBER		3
+#define SGMII_LINK_MAC_PHY_FORCED	4
+
+#define TARGET_SGMII_BASE		KS2_PASS_BASE + 0x00090100
+#define TARGET_SGMII_BASE_ADDRESSES    {KS2_PASS_BASE+0x00090100, \
+					KS2_PASS_BASE+0x00090200, \
+					KS2_PASS_BASE+0x00090400, \
+					KS2_PASS_BASE+0x00090500  }
+
+#define SGMII_OFFSET(x)	((x <= 1) ? (x * 0x100) : ((x * 0x100) + 0x100))
+
+/*
+ * SGMII registers
+ */
+#define SGMII_IDVER_REG(x)    (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x000)
+#define SGMII_SRESET_REG(x)   (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x004)
+#define SGMII_CTL_REG(x)      (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x010)
+#define SGMII_STATUS_REG(x)   (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x014)
+#define SGMII_MRADV_REG(x)    (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x018)
+#define SGMII_LPADV_REG(x)    (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x020)
+#define SGMII_TXCFG_REG(x)    (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x030)
+#define SGMII_RXCFG_REG(x)    (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x034)
+#define SGMII_AUXCFG_REG(x)   (TARGET_SGMII_BASE + SGMII_OFFSET(x) + 0x038)
+
+#define DEVICE_EMACSL_BASE(x)           (KS2_PASS_BASE + 0x00090900 + (x)*0x040)
+#define DEVICE_N_GMACSL_PORTS           4
+#define DEVICE_EMACSL_RESET_POLL_COUNT  100
+
+#define DEVICE_PSTREAM_CFG_REG_ADDR                 (KS2_PASS_BASE + 0x604)
+
+#ifdef CONFIG_SOC_K2HK
+#define DEVICE_PSTREAM_CFG_REG_VAL_ROUTE_CPPI      0x06060606
+#endif
+
+#define hw_config_streaming_switch() \
+	DEVICE_REG32_W(DEVICE_PSTREAM_CFG_REG_ADDR, \
+		       DEVICE_PSTREAM_CFG_REG_VAL_ROUTE_CPPI);
+
+/* EMAC MDIO Registers Structure */
+struct mdio_regs {
+	dv_reg		VERSION;
+	dv_reg		CONTROL;
+	dv_reg		ALIVE;
+	dv_reg		LINK;
+	dv_reg		LINKINTRAW;
+	dv_reg		LINKINTMASKED;
+	u_int8_t	RSVD0[8];
+	dv_reg		USERINTRAW;
+	dv_reg		USERINTMASKED;
+	dv_reg		USERINTMASKSET;
+	dv_reg		USERINTMASKCLEAR;
+	u_int8_t	RSVD1[80];
+	dv_reg		USERACCESS0;
+	dv_reg		USERPHYSEL0;
+	dv_reg		USERACCESS1;
+	dv_reg		USERPHYSEL1;
+};
+
+/* Ethernet MAC Registers Structure */
+struct emac_regs {
+	dv_reg		IDVER;
+	dv_reg		MACCONTROL;
+	dv_reg		MACSTATUS;
+	dv_reg		SOFT_RESET;
+	dv_reg		RX_MAXLEN;
+	u32		RSVD0;
+	dv_reg		RX_PAUSE;
+	dv_reg		TX_PAUSE;
+	dv_reg		EMCONTROL;
+	dv_reg		PRI_MAP;
+	u32		RSVD1[6];
+};
+
+struct phy_t {
+	char	name[64];
+	int	(*init)(int phy_addr);
+	int	(*is_phy_connected)(int phy_addr);
+	int	(*get_link_speed)(int phy_addr);
+	int	(*auto_negotiate)(int phy_addr);
+};
+
+#define SGMII_ACCESS(port, reg) \
+	*((volatile unsigned int *)(sgmiis[port] + reg))
+
+struct eth_priv_t {
+	char	int_name[32];
+	int	rx_flow;
+	int	phy_addr;
+	int	slave_port;
+	int	sgmii_link_type;
+};
+
+extern struct eth_priv_t eth_priv_cfg[];
+
+int keystone2_emac_initialize(struct eth_priv_t *eth_priv);
+void sgmii_serdes_setup_156p25mhz(void);
+void sgmii_serdes_shutdown(void);
+
+#endif  /* _EMAC_DEFS_H_ */
diff --git a/arch/arm/include/asm/arch-keystone/keystone_nav.h b/arch/arm/include/asm/arch-keystone/keystone_nav.h
new file mode 100644
index 0000000..12a0464
--- /dev/null
+++ b/arch/arm/include/asm/arch-keystone/keystone_nav.h
@@ -0,0 +1,194 @@ 
+/*
+ * Multicore Navigator definitions
+ *
+ * (C) Copyright 2012-2014
+ *     Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _KEYSTONE_NAV_H_
+#define _KEYSTONE_NAV_H_
+
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+enum soc_type_t {
+	k2hk
+};
+
+
+#define QM_OK			0
+#define QM_ERR			-1
+#define QM_DESC_TYPE_HOST	0
+#define QM_DESC_PSINFO_IN_DESCR	0
+#define QM_DESC_DEFAULT_DESCINFO	(QM_DESC_TYPE_HOST << 30) | \
+					(QM_DESC_PSINFO_IN_DESCR << 22)
+
+/* Packet Info */
+#define QM_DESC_PINFO_EPIB		1
+#define QM_DESC_PINFO_RETURN_OWN	1
+#define QM_DESC_DEFAULT_PINFO		(QM_DESC_PINFO_EPIB << 31) | \
+					(QM_DESC_PINFO_RETURN_OWN << 15)
+
+struct qm_cfg_reg {
+	u32	revision;
+	u32	__pad1;
+	u32	divert;
+	u32	link_ram_base0;
+	u32	link_ram_size0;
+	u32	link_ram_base1;
+	u32	link_ram_size1;
+	u32	link_ram_base2;
+	u32	starvation[0];
+};
+
+struct	descr_mem_setup_reg {
+	u32	base_addr;
+	u32	start_idx;
+	u32	desc_reg_size;
+	u32	_res0;
+};
+
+struct qm_reg_queue {
+	u32	entry_count;
+	u32	byte_count;
+	u32	packet_size;
+	u32	ptr_size_thresh;
+};
+
+struct qm_config {
+	/* QM module addresses */
+	u32	stat_cfg;	/* status and config		*/
+	struct qm_reg_queue *queue;	/* management region		*/
+	u32	mngr_vbusm;	/* management region (VBUSM)	*/
+	u32	i_lram;		/* internal linking RAM		*/
+	struct qm_reg_queue *proxy;
+	u32	status_ram;
+	struct qm_cfg_reg *mngr_cfg;
+				/* Queue manager config region	*/
+	u32	intd_cfg;	/* QMSS INTD config region	*/
+	struct	descr_mem_setup_reg *desc_mem;
+				/* descritor memory setup region*/
+	u32	region_num;
+	u32	pdsp_cmd;	/* PDSP1 command interface	*/
+	u32	pdsp_ctl;	/* PDSP1 control registers	*/
+	u32	pdsp_iram;
+	/* QM configuration parameters */
+
+	u32	qpool_num;	/* */
+};
+
+struct qm_host_desc {
+	u32 desc_info;
+	u32 tag_info;
+	u32 packet_info;
+	u32 buff_len;
+	u32 buff_ptr;
+	u32 next_bdptr;
+	u32 orig_buff_len;
+	u32 orig_buff_ptr;
+	u32 timestamp;
+	u32 swinfo[3];
+	u32 ps_data[20];
+};
+
+#define HDESC_NUM	256
+
+int	qm_init(void);
+void	qm_close(void);
+void	qm_push(struct qm_host_desc *hd, u32 qnum);
+struct qm_host_desc *qm_pop(u32 qnum);
+
+void	qm_buff_push(struct qm_host_desc *hd, u32 qnum,
+		     void *buff_ptr, u32 buff_len);
+
+struct	qm_host_desc *qm_pop_from_free_pool(void);
+void	queue_close(u32 qnum);
+
+/**********************************************
+ * DMA API
+ *********************************************/
+#define CPDMA_REG_VAL_MAKE_RX_FLOW_A(einfo, psinfo, rxerr, desc, \
+				     psloc, sopoff, qmgr, qnum) \
+	(((einfo & 1) << 30)  | \
+	 ((psinfo & 1) << 29) | \
+	 ((rxerr & 1) << 28)  | \
+	 ((desc & 3) << 26)   | \
+	 ((psloc & 1) << 25)  | \
+	 ((sopoff & 0x1ff) << 16) | \
+	 ((qmgr & 3) << 12)   | \
+	 ((qnum & 0xfff) << 0))
+
+#define CPDMA_REG_VAL_MAKE_RX_FLOW_D(fd0qm, fd0qnum, fd1qm, fd1qnum) \
+	(((fd0qm & 3) << 28)  | \
+	 ((fd0qnum & 0xfff) << 16) | \
+	 ((fd1qm & 3) << 12)  | \
+	 ((fd1qnum & 0xfff) <<  0))
+
+#define CPDMA_CHAN_A_ENABLE ((u32)1 << 31)
+#define CPDMA_CHAN_A_TDOWN  (1 << 30)
+#define TDOWN_TIMEOUT_COUNT	100
+
+struct global_ctl_regs {
+	u32	revision;
+	u32	perf_control;
+	u32	emulation_control;
+	u32	priority_control;
+	u32	qm_base_addr[4];
+};
+
+struct tx_chan_regs {
+	u32	cfg_a;
+	u32	cfg_b;
+	u32	res[6];
+};
+
+struct rx_chan_regs {
+	u32	cfg_a;
+	u32	res[7];
+};
+
+struct rx_flow_regs {
+	u32	control;
+	u32	tags;
+	u32	tag_sel;
+	u32	fdq_sel[2];
+	u32	thresh[3];
+};
+
+struct pktdma_cfg {
+	struct global_ctl_regs	*global;
+	struct tx_chan_regs	*tx_ch;
+	u32			tx_ch_num;
+	struct rx_chan_regs	*rx_ch;
+	u32			rx_ch_num;
+	u32			*tx_sched;
+	struct rx_flow_regs	*rx_flows;
+	u32			rx_flow_num;
+
+	u32			rx_free_q;
+	u32			rx_rcv_q;
+	u32			tx_snd_q;
+
+	u32			rx_flow; /* flow that is used for RX */
+};
+
+/*
+ * packet dma user allocates memory for rx buffers
+ * and describe it in the following structure
+ */
+struct rx_buff_desc {
+	u8	*buff_ptr;
+	u32	num_buffs;
+	u32	buff_len;
+	u32	rx_flow;
+};
+
+int netcp_close(void);
+int netcp_init(struct rx_buff_desc *rx_buffers);
+int netcp_send(u32 *pkt, int num_bytes, u32 swinfo2);
+void *netcp_recv(u32 **pkt, int *num_bytes);
+void netcp_release_rxhd(void *hd);
+
+#endif  /* _KEYSTONE_NAV_H_ */
diff --git a/board/ti/k2hk_evm/board.c b/board/ti/k2hk_evm/board.c
index 0ab3aef..6b2c6d8 100644
--- a/board/ti/k2hk_evm/board.c
+++ b/board/ti/k2hk_evm/board.c
@@ -17,6 +17,7 @@ 
 #include <asm/io.h>
 #include <asm/mach-types.h>
 #include <asm/arch/nand_defs.h>
+#include <asm/arch/emac_defs.h>
 #include <asm/arch/psc_defs.h>
 
 
@@ -71,6 +72,70 @@  int dram_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_DRIVER_TI_KEYSTONE_NET
+struct eth_priv_t eth_priv_cfg[] = {
+	{
+		.int_name	= "K2HK_EMAC",
+		.rx_flow	= 22,
+		.phy_addr	= 0,
+		.slave_port	= 1,
+		.sgmii_link_type = SGMII_LINK_MAC_PHY,
+	},
+	{
+		.int_name	= "K2HK_EMAC1",
+		.rx_flow	= 23,
+		.phy_addr	= 1,
+		.slave_port	= 2,
+		.sgmii_link_type = SGMII_LINK_MAC_PHY,
+	},
+	{
+		.int_name	= "K2HK_EMAC2",
+		.rx_flow	= 24,
+		.phy_addr	= 2,
+		.slave_port	= 3,
+		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
+	},
+	{
+		.int_name	= "K2HK_EMAC3",
+		.rx_flow	= 25,
+		.phy_addr	= 3,
+		.slave_port	= 4,
+		.sgmii_link_type = SGMII_LINK_MAC_MAC_FORCED,
+	},
+};
+
+int get_eth_env_param(char *env_name)
+{
+	char *env;
+	int  res = -1;
+
+	env = getenv(env_name);
+	if (env)
+		res = simple_strtol(env, NULL, 0);
+
+	return res;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	int	j;
+	int	res;
+	char	link_type_name[32];
+
+	for (j = 0; j < (sizeof(eth_priv_cfg) / sizeof(struct eth_priv_t));
+	     j++) {
+		sprintf(link_type_name, "sgmii%d_link_type", j);
+		res = get_eth_env_param(link_type_name);
+		if (res >= 0)
+			eth_priv_cfg[j].sgmii_link_type = res;
+
+		keystone2_emac_initialize(&eth_priv_cfg[j]);
+	}
+
+	return 0;
+}
+#endif
+
 /* Byte swap the 32-bit data if the device is BE */
 int cpu_to_bus(u32 *ptr, u32 length)
 {
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 7f9ce90..6005f7e 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -30,6 +30,7 @@  obj-$(CONFIG_FTMAC110) += ftmac110.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GRETH) += greth.o
 obj-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
+obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o
 obj-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 obj-$(CONFIG_LAN91C96) += lan91c96.o
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
new file mode 100644
index 0000000..ec59005
--- /dev/null
+++ b/drivers/net/keystone_net.c
@@ -0,0 +1,857 @@ 
+/*
+ * Ethernet driver for TI K2HK EVM.
+ *
+ * (C) Copyright 2012-2014
+ *     Texas Instruments Incorporated, <www.ti.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#include <common.h>
+#include <command.h>
+
+#include <net.h>
+#include <miiphy.h>
+#include <malloc.h>
+#include <asm/arch/emac_defs.h>
+#include <asm/arch/psc_defs.h>
+#include <asm/arch/keystone_nav.h>
+
+unsigned int emac_dbg;
+#define debug_emac(fmt, args...) if (emac_dbg) printf(fmt, ##args)
+
+unsigned int emac_open;
+static unsigned int sys_has_mdio = 1;
+
+#ifdef KEYSTONE2_EMAC_GIG_ENABLE
+#define emac_gigabit_enable(x)	keystone2_eth_gigabit_enable(x)
+#else
+#define emac_gigabit_enable(x)	/* no gigabit to enable */
+#endif
+
+#define RX_BUFF_NUMS	24
+#define RX_BUFF_LEN	1520
+#define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN
+
+static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16);
+
+struct rx_buff_desc net_rx_buffs = {
+	.buff_ptr	= rx_buffs,
+	.num_buffs	= RX_BUFF_NUMS,
+	.buff_len	= RX_BUFF_LEN,
+	.rx_flow	= 22,
+};
+
+static void keystone2_eth_mdio_enable(void);
+
+static int gen_init_phy(int phy_addr);
+static int gen_is_phy_connected(int phy_addr);
+static int gen_get_link_speed(int phy_addr);
+static int gen_auto_negotiate(int phy_addr);
+
+static int marvell_88e1111_init_phy(int phy_addr);
+static int marvell_88e1111_is_phy_connected(int phy_addr);
+static int marvell_88e1111_get_link_speed(int phy_addr);
+static int marvell_88e1111_auto_negotiate(int phy_addr);
+
+/* EMAC Addresses */
+static volatile struct emac_regs	*adap_emac =
+	(struct emac_regs *)EMAC_EMACSL_BASE_ADDR;
+static volatile struct mdio_regs	*adap_mdio =
+	(struct mdio_regs *)EMAC_MDIO_BASE_ADDR;
+
+struct phy_t phy;
+
+static void chip_delay(u32 del)
+{
+	volatile unsigned int i;
+
+	for (i = 0; i < (del / 8); i++)
+		;
+}
+
+int keystone2_eth_read_mac_addr(struct eth_device *dev)
+{
+	struct eth_priv_t *eth_priv;
+	u32 maca = 0;
+	u32 macb = 0;
+
+	eth_priv = (struct eth_priv_t *)dev->priv;
+
+	/* Read the e-fuse mac address */
+	if (eth_priv->slave_port == 1) {
+		maca = __raw_readl(MAC_ID_BASE_ADDR);
+		macb = __raw_readl(MAC_ID_BASE_ADDR + 4);
+	}
+
+	dev->enetaddr[0] = (macb >>  8) & 0xff;
+	dev->enetaddr[1] = (macb >>  0) & 0xff;
+	dev->enetaddr[2] = (maca >> 24) & 0xff;
+	dev->enetaddr[3] = (maca >> 16) & 0xff;
+	dev->enetaddr[4] = (maca >>  8) & 0xff;
+	dev->enetaddr[5] = (maca >>  0) & 0xff;
+
+	return 0;
+}
+
+static void keystone2_eth_mdio_enable(void)
+{
+	u_int32_t	clkdiv;
+
+	clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+
+	writel((clkdiv & 0xffff) |
+	       MDIO_CONTROL_ENABLE |
+	       MDIO_CONTROL_FAULT |
+	       MDIO_CONTROL_FAULT_ENABLE,
+	       &adap_mdio->CONTROL);
+
+	while (readl(&adap_mdio->CONTROL) & MDIO_CONTROL_IDLE)
+		;
+}
+
+/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
+int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
+{
+	int	tmp;
+
+	while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+		;
+
+	writel(MDIO_USERACCESS0_GO |
+	       MDIO_USERACCESS0_WRITE_READ |
+	       ((reg_num & 0x1f) << 21) |
+	       ((phy_addr & 0x1f) << 16),
+	       &adap_mdio->USERACCESS0);
+
+	/* Wait for command to complete */
+	while ((tmp = readl(&adap_mdio->USERACCESS0)) & MDIO_USERACCESS0_GO)
+		;
+
+	if (tmp & MDIO_USERACCESS0_ACK) {
+		*data = tmp & 0xffff;
+		return 0;
+	}
+
+	*data = -1;
+	return -1;
+}
+
+/* Write to a PHY register via MDIO inteface.
+ * Blocks until operation is complete. */
+int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
+{
+	while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+		;
+
+	writel(MDIO_USERACCESS0_GO |
+	       MDIO_USERACCESS0_WRITE_WRITE |
+	       ((reg_num & 0x1f) << 21) |
+	       ((phy_addr & 0x1f) << 16) |
+	       (data & 0xffff),
+	       &adap_mdio->USERACCESS0);
+
+	/* Wait for command to complete */
+	while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
+		;
+
+	return 0;
+}
+
+/* PHY functions for a generic PHY */
+static int __attribute__((unused)) gen_init_phy(int phy_addr)
+{
+	int	ret = -1;
+
+	if (!gen_get_link_speed(phy_addr)) {
+		/* Try another time */
+		ret = gen_get_link_speed(phy_addr);
+	}
+
+	return ret;
+}
+
+static int __attribute__((unused)) gen_is_phy_connected(int phy_addr)
+{
+	u_int16_t	dummy;
+
+	return keystone2_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
+}
+
+static int gen_get_link_speed(int phy_addr)
+{
+	u_int16_t	tmp;
+
+	if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) &&
+	    (tmp & 0x04)) {
+		return 0;
+	}
+
+	return -1;
+}
+
+static int __attribute__((unused)) gen_auto_negotiate(int phy_addr)
+{
+	u_int16_t	tmp;
+
+	if (keystone2_eth_phy_read(phy_addr, MII_BMCR, &tmp))
+		return -1;
+
+	/* Restart Auto_negotiation  */
+	tmp |= BMCR_ANENABLE;
+	keystone2_eth_phy_write(phy_addr, MII_BMCR, tmp);
+
+	/*check AutoNegotiate complete */
+	udelay(10000);
+	if (keystone2_eth_phy_read(phy_addr, MII_BMSR, &tmp))
+		return -1;
+
+	if (!(tmp & BMSR_ANEGCOMPLETE))
+		return 0;
+
+	return gen_get_link_speed(phy_addr);
+}
+
+/* PHY functions for Marvell 88E1111 PHY */
+static int marvell_88e1111_init_phy(int phy_addr)
+{
+	int	ret = -1;
+
+	if (!marvell_88e1111_get_link_speed(phy_addr)) {
+		/* Try another time */
+		ret = marvell_88e1111_get_link_speed(phy_addr);
+	}
+
+	return ret;
+}
+
+static int marvell_88e1111_is_phy_connected(int phy_addr)
+{
+	u_int16_t	dummy;
+
+	return keystone2_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
+}
+
+static int marvell_88e1111_get_link_speed(int phy_addr)
+{
+	u_int16_t	tmp;
+
+	if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) &&
+	    (tmp & MII_STATUS_LINK_MASK)) {
+		return 0;
+	}
+
+	return -1;
+}
+
+static int marvell_88e1111_auto_negotiate(int phy_addr)
+{
+	u_int16_t	tmp;
+
+	if (keystone2_eth_phy_read(phy_addr, MII_BMCR, &tmp))
+		return -1;
+
+	/* Restart Auto_negotiation  */
+	tmp |= BMCR_ANENABLE;
+	keystone2_eth_phy_write(phy_addr, MII_BMCR, tmp);
+
+	/*check AutoNegotiate complete */
+	udelay(10000);
+	if (keystone2_eth_phy_read(phy_addr, MII_BMSR, &tmp))
+		return -1;
+
+	if (!(tmp & BMSR_ANEGCOMPLETE))
+		return 0;
+
+	return marvell_88e1111_get_link_speed(phy_addr);
+}
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+static int keystone2_mii_phy_read(const char *devname, unsigned char addr,
+				  unsigned char reg, unsigned short *value)
+{
+	return keystone2_eth_phy_read(addr, reg, value) ? -1 : 0;
+}
+
+static int keystone2_mii_phy_write(const char *devname, unsigned char addr,
+				 unsigned char reg, unsigned short value)
+{
+	return keystone2_eth_phy_write(addr, reg, value) ? -1 : 0;
+}
+#endif
+
+static void  __attribute__((unused))
+	keystone2_eth_gigabit_enable(struct eth_device *dev)
+{
+	u_int16_t data;
+	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+
+	if (sys_has_mdio) {
+		if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) ||
+		    !(data & (1 << 6))) /* speed selection MSB */
+			return;
+	}
+
+	/*
+	 * Check if link detected is giga-bit
+	 * If Gigabit mode detected, enable gigbit in MAC
+	 */
+	writel(readl(&(adap_emac[eth_priv->slave_port - 1].MACCONTROL)) |
+	       EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE,
+	       &(adap_emac[eth_priv->slave_port - 1].MACCONTROL))
+		;
+}
+
+int keystone_sgmii_link_status(int port)
+{
+	u32 status = 0;
+
+	status = __raw_readl(SGMII_STATUS_REG(port));
+
+	return status & SGMII_REG_STATUS_LINK;
+}
+
+
+int keystone_get_link_status(struct eth_device *dev)
+{
+	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+	int sgmii_link;
+	int link_state = 0;
+#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1
+	int j;
+
+	for (j = 0; (j < CONFIG_GET_LINK_STATUS_ATTEMPTS) && (link_state == 0);
+	     j++) {
+#endif
+		sgmii_link =
+			keystone_sgmii_link_status(eth_priv->slave_port - 1);
+
+		if (sgmii_link) {
+			link_state = 1;
+
+			if (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY)
+				if (phy.get_link_speed(eth_priv->phy_addr))
+					link_state = 0;
+		}
+#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1
+	}
+#endif
+	return link_state;
+}
+
+int keystone_sgmii_config(int port, int interface)
+{
+	unsigned int i, status, mask;
+	unsigned int mr_adv_ability, control;
+
+	switch (interface) {
+	case SGMII_LINK_MAC_MAC_AUTONEG:
+		mr_adv_ability	= (SGMII_REG_MR_ADV_ENABLE |
+				   SGMII_REG_MR_ADV_LINK |
+				   SGMII_REG_MR_ADV_FULL_DUPLEX |
+				   SGMII_REG_MR_ADV_GIG_MODE);
+		control		= (SGMII_REG_CONTROL_MASTER |
+				   SGMII_REG_CONTROL_AUTONEG);
+
+		break;
+	case SGMII_LINK_MAC_PHY:
+	case SGMII_LINK_MAC_PHY_FORCED:
+		mr_adv_ability	= SGMII_REG_MR_ADV_ENABLE;
+		control		= SGMII_REG_CONTROL_AUTONEG;
+
+		break;
+	case SGMII_LINK_MAC_MAC_FORCED:
+		mr_adv_ability	= (SGMII_REG_MR_ADV_ENABLE |
+				   SGMII_REG_MR_ADV_LINK |
+				   SGMII_REG_MR_ADV_FULL_DUPLEX |
+				   SGMII_REG_MR_ADV_GIG_MODE);
+		control		= SGMII_REG_CONTROL_MASTER;
+
+		break;
+	case SGMII_LINK_MAC_FIBER:
+		mr_adv_ability	= 0x20;
+		control		= SGMII_REG_CONTROL_AUTONEG;
+
+		break;
+	default:
+		mr_adv_ability	= SGMII_REG_MR_ADV_ENABLE;
+		control		= SGMII_REG_CONTROL_AUTONEG;
+	}
+
+	__raw_writel(0, SGMII_CTL_REG(port));
+
+	/*
+	 * Wait for the SerDes pll to lock,
+	 * but don't trap if lock is never read
+	 */
+	for (i = 0; i < 1000; i++)  {
+		udelay(2000);
+		status = __raw_readl(SGMII_STATUS_REG(port));
+		if ((status & SGMII_REG_STATUS_LOCK) != 0)
+			break;
+	}
+
+	__raw_writel(mr_adv_ability, SGMII_MRADV_REG(port));
+	__raw_writel(control, SGMII_CTL_REG(port));
+
+
+	mask = SGMII_REG_STATUS_LINK;
+
+	if (control & SGMII_REG_CONTROL_AUTONEG)
+		mask |= SGMII_REG_STATUS_AUTONEG;
+
+	for (i = 0; i < 1000; i++) {
+		status = __raw_readl(SGMII_STATUS_REG(port));
+		if ((status & mask) == mask)
+			break;
+	}
+
+	return 0;
+}
+
+int mac_sl_reset(u32 port)
+{
+	u32 i, v;
+
+	if (port >= DEVICE_N_GMACSL_PORTS)
+		return GMACSL_RET_INVALID_PORT;
+
+	/* Set the soft reset bit */
+	DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) +
+		       CPGMACSL_REG_RESET, CPGMAC_REG_RESET_VAL_RESET);
+
+	/* Wait for the bit to clear */
+	for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
+		v = DEVICE_REG32_R(DEVICE_EMACSL_BASE(port) +
+				   CPGMACSL_REG_RESET);
+		if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
+		    CPGMAC_REG_RESET_VAL_RESET)
+			return GMACSL_RET_OK;
+	}
+
+	/* Timeout on the reset */
+	return GMACSL_RET_WARN_RESET_INCOMPLETE;
+}
+
+int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg)
+{
+	u32 v, i;
+	int ret = GMACSL_RET_OK;
+
+	if (port >= DEVICE_N_GMACSL_PORTS)
+		return GMACSL_RET_INVALID_PORT;
+
+	if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) {
+		cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN;
+		ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG;
+	}
+
+	/* Must wait if the device is undergoing reset */
+	for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) {
+		v = DEVICE_REG32_R(DEVICE_EMACSL_BASE(port) +
+				   CPGMACSL_REG_RESET);
+		if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) !=
+		    CPGMAC_REG_RESET_VAL_RESET)
+			break;
+	}
+
+	if (i == DEVICE_EMACSL_RESET_POLL_COUNT)
+		return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE;
+
+	DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN,
+		       cfg->max_rx_len);
+
+	DEVICE_REG32_W(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL,
+		       cfg->ctl);
+
+	return ret;
+}
+
+int ethss_config(u32 ctl, u32 max_pkt_size)
+{
+	u32 i;
+
+	/* Max length register */
+	DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_MAXLEN, max_pkt_size);
+
+	/* Control register */
+	DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_CTL, ctl);
+
+	/* All statistics enabled by default */
+	DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN,
+		       CPSW_REG_VAL_STAT_ENABLE_ALL);
+
+	/* Reset and enable the ALE */
+	DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL,
+		       CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE |
+		       CPSW_REG_VAL_ALE_CTL_BYPASS);
+
+	/* All ports put into forward mode */
+	for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++)
+		DEVICE_REG32_W(DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i),
+			       CPSW_REG_VAL_PORTCTL_FORWARD_MODE);
+
+	return 0;
+}
+
+int ethss_start(void)
+{
+	int i;
+	struct mac_sl_cfg cfg;
+
+	cfg.max_rx_len	= MAX_SIZE_STREAM_BUFFER;
+	cfg.ctl		= GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL;
+
+	for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) {
+		mac_sl_reset(i);
+		mac_sl_config(i, &cfg);
+	}
+
+	return 0;
+}
+
+int ethss_stop(void)
+{
+	int i;
+
+	for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++)
+		mac_sl_reset(i);
+
+	return 0;
+}
+
+int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num)
+{
+	if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE)
+		num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE;
+
+	return netcp_send(buffer, num_bytes, (slave_port_num) << 16);
+}
+
+/* Eth device open */
+static int keystone2_eth_open(struct eth_device *dev, bd_t *bis)
+{
+	u_int32_t clkdiv;
+	int link;
+	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+
+	debug_emac("+ emac_open\n");
+
+	net_rx_buffs.rx_flow	= eth_priv->rx_flow;
+
+	sys_has_mdio =
+		(eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
+
+	psc_enable_module(KS2_LPSC_PA);
+	psc_enable_module(KS2_LPSC_CPGMAC);
+
+	sgmii_serdes_setup_156p25mhz();
+
+	if (sys_has_mdio)
+		keystone2_eth_mdio_enable();
+
+	keystone_sgmii_config(eth_priv->slave_port - 1,
+			      eth_priv->sgmii_link_type);
+
+	udelay(10000);
+
+	/* On chip switch configuration */
+	ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE);
+
+	/* TODO: add error handling code */
+	if (qm_init()) {
+		printf("ERROR: qm_init()\n");
+		return -1;
+	}
+	if (netcp_init(&net_rx_buffs)) {
+		qm_close();
+		printf("ERROR: netcp_init()\n");
+		return -1;
+	}
+
+	/*
+	 * Streaming switch configuration. If not present this
+	 * statement is defined to void in target.h.
+	 * If present this is usually defined to a series of register writes
+	 */
+	hw_config_streaming_switch();
+
+	if (sys_has_mdio) {
+		/* Init MDIO & get link state */
+		clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+		writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE |
+		       MDIO_CONTROL_FAULT, &adap_mdio->CONTROL)
+			;
+
+		/* We need to wait for MDIO to start */
+		udelay(1000);
+
+		link = keystone_get_link_status(dev);
+		if (link == 0) {
+			netcp_close();
+			qm_close();
+			return -1;
+		}
+	}
+
+	emac_gigabit_enable(dev);
+
+	ethss_start();
+
+	debug_emac("- emac_open\n");
+
+	emac_open = 1;
+
+	return 0;
+}
+
+/* Eth device close */
+void keystone2_eth_close(struct eth_device *dev)
+{
+	debug_emac("+ emac_close\n");
+
+	if (!emac_open)
+		return;
+
+	ethss_stop();
+
+	netcp_close();
+	qm_close();
+
+	emac_open = 0;
+
+	debug_emac("- emac_close\n");
+}
+
+static int tx_send_loop;
+
+/*
+ * This function sends a single packet on the network and returns
+ * positive number (number of bytes transmitted) or negative for error
+ */
+static int keystone2_eth_send_packet(struct eth_device *dev,
+					void *packet, int length)
+{
+	int ret_status = -1;
+	struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv;
+
+	tx_send_loop = 0;
+
+	if (keystone_get_link_status(dev) == 0)
+		return -1;
+
+	emac_gigabit_enable(dev);
+
+	if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0)
+		return ret_status;
+
+	if (keystone_get_link_status(dev) == 0)
+		return -1;
+
+	emac_gigabit_enable(dev);
+
+	return length;
+}
+
+/*
+ * This function handles receipt of a packet from the network
+ */
+static int keystone2_eth_rcv_packet(struct eth_device *dev)
+{
+	void *hd;
+	int  pkt_size;
+	u32  *pkt;
+
+	hd = netcp_recv(&pkt, &pkt_size);
+	if (hd == NULL)
+		return 0;
+
+	NetReceive((uchar *)pkt, pkt_size);
+
+	netcp_release_rxhd(hd);
+
+	return pkt_size;
+}
+
+/*
+ * This function initializes the EMAC hardware. It does NOT initialize
+ * EMAC modules power or pin multiplexors, that is done by board_init()
+ * much earlier in bootup process. Returns 1 on success, 0 otherwise.
+ */
+int keystone2_emac_initialize(struct eth_priv_t *eth_priv)
+{
+	struct eth_device *dev;
+	static int phy_registered;
+
+	dev = malloc(sizeof(struct eth_device));
+	if (dev == NULL)
+		return -1;
+
+	memset(dev, 0, sizeof(struct eth_device));
+
+	strcpy(dev->name, eth_priv->int_name);
+	dev->priv = eth_priv;
+
+	keystone2_eth_read_mac_addr(dev);
+
+	dev->iobase		= 0;
+	dev->init		= keystone2_eth_open;
+	dev->halt		= keystone2_eth_close;
+	dev->send		= keystone2_eth_send_packet;
+	dev->recv		= keystone2_eth_rcv_packet;
+
+	eth_register(dev);
+
+	if (sys_has_mdio && !phy_registered) {
+		phy_registered = 1;
+#ifdef CONFIG_ETH_PHY_MARVEL_88E1111
+		sprintf(phy.name, "88E1111");
+		phy.init = marvell_88e1111_init_phy;
+		phy.is_phy_connected = marvell_88e1111_is_phy_connected;
+		phy.get_link_speed = marvell_88e1111_get_link_speed;
+		phy.auto_negotiate = marvell_88e1111_auto_negotiate;
+#else
+		sprintf(phy.name, "GENERIC");
+		phy.init = gen_init_phy;
+		phy.is_phy_connected = gen_is_phy_connected;
+		phy.get_link_speed = gen_get_link_speed;
+		phy.auto_negotiate = gen_auto_negotiate;
+#endif
+		miiphy_register(phy.name, keystone2_mii_phy_read,
+				keystone2_mii_phy_write);
+	}
+
+	return 0;
+}
+
+#define reg_rmw(addr, value, mask) \
+	writel(((readl(addr) & (~(mask))) | (value)), (addr))
+
+void sgmii_serdes_setup_156p25mhz()
+{
+	unsigned int cnt;
+
+	reg_rmw(0x0232a000, 0x00800000, 0xffff0000);
+	reg_rmw(0x0232a014, 0x00008282, 0x0000ffff);
+	reg_rmw(0x0232a060, 0x00142438, 0x00ffffff);
+	reg_rmw(0x0232a064, 0x00c3c700, 0x00ffff00);
+	reg_rmw(0x0232a078, 0x0000c000, 0x0000ff00);
+
+	reg_rmw(0x0232a204, 0x38000080, 0xff0000ff);
+	reg_rmw(0x0232a208, 0x00000000, 0x000000ff);
+	reg_rmw(0x0232a20c, 0x02000000, 0xff000000);
+	reg_rmw(0x0232a210, 0x1b000000, 0xff000000);
+	reg_rmw(0x0232a214, 0x00006fb8, 0x0000ffff);
+	reg_rmw(0x0232a218, 0x758000e4, 0xffff00ff);
+	reg_rmw(0x0232a2ac, 0x00004400, 0x0000ff00);
+	reg_rmw(0x0232a22c, 0x00200800, 0x00ffff00);
+	reg_rmw(0x0232a280, 0x00820082, 0x00ff00ff);
+	reg_rmw(0x0232a284, 0x1d0f0385, 0xffffffff);
+
+	reg_rmw(0x0232a404, 0x38000080, 0xff0000ff);
+	reg_rmw(0x0232a408, 0x00000000, 0x000000ff);
+	reg_rmw(0x0232a40c, 0x02000000, 0xff000000);
+	reg_rmw(0x0232a410, 0x1b000000, 0xff000000);
+	reg_rmw(0x0232a414, 0x00006fb8, 0x0000ffff);
+	reg_rmw(0x0232a418, 0x758000e4, 0xffff00ff);
+	reg_rmw(0x0232a4ac, 0x00004400, 0x0000ff00);
+	reg_rmw(0x0232a42c, 0x00200800, 0x00ffff00);
+	reg_rmw(0x0232a480, 0x00820082, 0x00ff00ff);
+	reg_rmw(0x0232a484, 0x1d0f0385, 0xffffffff);
+
+	reg_rmw(0x0232a604, 0x38000080, 0xff0000ff);
+	reg_rmw(0x0232a608, 0x00000000, 0x000000ff);
+	reg_rmw(0x0232a60c, 0x02000000, 0xff000000);
+	reg_rmw(0x0232a610, 0x1b000000, 0xff000000);
+	reg_rmw(0x0232a614, 0x00006fb8, 0x0000ffff);
+	reg_rmw(0x0232a618, 0x758000e4, 0xffff00ff);
+	reg_rmw(0x0232a6ac, 0x00004400, 0x0000ff00);
+	reg_rmw(0x0232a62c, 0x00200800, 0x00ffff00);
+	reg_rmw(0x0232a680, 0x00820082, 0x00ff00ff);
+	reg_rmw(0x0232a684, 0x1d0f0385, 0xffffffff);
+
+	reg_rmw(0x0232a804, 0x38000080, 0xff0000ff);
+	reg_rmw(0x0232a808, 0x00000000, 0x000000ff);
+	reg_rmw(0x0232a80c, 0x02000000, 0xff000000);
+	reg_rmw(0x0232a810, 0x1b000000, 0xff000000);
+	reg_rmw(0x0232a814, 0x00006fb8, 0x0000ffff);
+	reg_rmw(0x0232a818, 0x758000e4, 0xffff00ff);
+	reg_rmw(0x0232a8ac, 0x00004400, 0x0000ff00);
+	reg_rmw(0x0232a82c, 0x00200800, 0x00ffff00);
+	reg_rmw(0x0232a880, 0x00820082, 0x00ff00ff);
+	reg_rmw(0x0232a884, 0x1d0f0385, 0xffffffff);
+
+	reg_rmw(0x0232aa00, 0x00000800, 0x0000ff00);
+	reg_rmw(0x0232aa08, 0x38a20000, 0xffff0000);
+	reg_rmw(0x0232aa30, 0x008a8a00, 0x00ffff00);
+	reg_rmw(0x0232aa84, 0x00000600, 0x0000ff00);
+	reg_rmw(0x0232aa94, 0x10000000, 0xff000000);
+	reg_rmw(0x0232aaa0, 0x81000000, 0xff000000);
+	reg_rmw(0x0232aabc, 0xff000000, 0xff000000);
+	reg_rmw(0x0232aac0, 0x0000008b, 0x000000ff);
+	reg_rmw(0x0232ab08, 0x583f0000, 0xffff0000);
+	reg_rmw(0x0232ab0c, 0x0000004e, 0x000000ff);
+	reg_rmw(0x0232a000, 0x00000003, 0x000000ff);
+	reg_rmw(0x0232aa00, 0x0000005f, 0x000000ff);
+
+	reg_rmw(0x0232aa48, 0x00fd8c00, 0x00ffff00);
+	reg_rmw(0x0232aa54, 0x002fec72, 0x00ffffff);
+	reg_rmw(0x0232aa58, 0x00f92100, 0xffffff00);
+	reg_rmw(0x0232aa5c, 0x00040060, 0xffffffff);
+	reg_rmw(0x0232aa60, 0x00008000, 0xffffffff);
+	reg_rmw(0x0232aa64, 0x0c581220, 0xffffffff);
+	reg_rmw(0x0232aa68, 0xe13b0602, 0xffffffff);
+	reg_rmw(0x0232aa6c, 0xb8074cc1, 0xffffffff);
+	reg_rmw(0x0232aa70, 0x3f02e989, 0xffffffff);
+	reg_rmw(0x0232aa74, 0x00000001, 0x000000ff);
+	reg_rmw(0x0232ab20, 0x00370000, 0x00ff0000);
+	reg_rmw(0x0232ab1c, 0x37000000, 0xff000000);
+	reg_rmw(0x0232ab20, 0x0000005d, 0x000000ff);
+
+	/*Bring SerDes out of Reset if SerDes is Shutdown & is in Reset Mode*/
+	reg_rmw(0x0232a010, 0x00000000, 1 << 28);
+
+	/* Enable TX and RX via the LANExCTL_STS 0x0000 + x*4 */
+	reg_rmw(0x0232a228, 0x00000000, 1 << 29);
+	writel(0xF800F8C0, 0x0232bfe0);
+	reg_rmw(0x0232a428, 0x00000000, 1 << 29);
+	writel(0xF800F8C0, 0x0232bfe4);
+	reg_rmw(0x0232a628, 0x00000000, 1 << 29);
+	writel(0xF800F8C0, 0x0232bfe8);
+	reg_rmw(0x0232a828, 0x00000000, 1 << 29);
+	writel(0xF800F8C0, 0x0232bfec);
+
+	/*Enable pll via the pll_ctrl 0x0014*/
+	writel(0xe0000000, 0x0232bff4)
+		;
+
+	/*Waiting for SGMII Serdes PLL lock.*/
+	for (cnt = 10000; cnt > 0 && ((readl(0x02090114) & 0x10) == 0); cnt--)
+		;
+
+	for (cnt = 10000; cnt > 0 && ((readl(0x02090214) & 0x10) == 0); cnt--)
+		;
+
+	for (cnt = 10000; cnt > 0 && ((readl(0x02090414) & 0x10) == 0); cnt--)
+		;
+
+	for (cnt = 10000; cnt > 0 && ((readl(0x02090514) & 0x10) == 0); cnt--)
+		;
+
+	chip_delay(45000);
+}
+
+void sgmii_serdes_shutdown()
+{
+	reg_rmw(0x0232bfe0, 0, 3 << 29 | 3 << 13);
+	reg_rmw(0x02320228, 1 << 29, 1 << 29);
+	reg_rmw(0x0232bfe4, 0, 3 << 29 | 3 << 13);
+	reg_rmw(0x02320428, 1 << 29, 1 << 29);
+	reg_rmw(0x0232bfe8, 0, 3 << 29 | 3 << 13);
+	reg_rmw(0x02320628, 1 << 29, 1 << 29);
+	reg_rmw(0x0232bfec, 0, 3 << 29 | 3 << 13);
+	reg_rmw(0x02320828, 1 << 29, 1 << 29);
+
+	reg_rmw(0x02320034, 0, 3 << 29);
+	reg_rmw(0x02320010, 1 << 28, 1 << 28);
+}
+
diff --git a/include/configs/k2hk_evm.h b/include/configs/k2hk_evm.h
index a43318a..d1e63fb 100644
--- a/include/configs/k2hk_evm.h
+++ b/include/configs/k2hk_evm.h
@@ -106,6 +106,23 @@ 
 #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS  20
 #define CONFIG_ENV_EEPROM_IS_ON_I2C
 
+/* Network Configuration */
+#define CONFIG_ETH_PHY_MARVEL_88E1111
+
+#define CONFIG_DRIVER_TI_KEYSTONE_NET
+#define CONFIG_MII
+#define CONFIG_BOOTP_DEFAULT
+#define CONFIG_BOOTP_DNS
+#define CONFIG_BOOTP_DNS2
+#define CONFIG_BOOTP_SEND_HOSTNAME
+#define CONFIG_NET_RETRY_COUNT		32
+#define CONFIG_NET_MULTI
+#define CONFIG_GET_LINK_STATUS_ATTEMPTS 5
+
+#define CONFIG_SYS_SGMII_REFCLK_MHZ	312
+#define CONFIG_SYS_SGMII_LINERATE_MHZ	1250
+#define	CONFIG_SYS_SGMII_RATESCALE	2
+
 /* NAND Configuration */
 #define CONFIG_NAND_DAVINCI
 #define CONFIG_SYS_NAND_CS		2
@@ -179,24 +196,45 @@ 
 	"addr_fs=0x82000000\0"						\
 	"addr_ubi=0x82000000\0"						\
 	"fdt_high=0xffffffff\0"						\
+	"name_fdt=uImage-k2hk-evm.dtb\0"				\
+	"name_fs=arago-console-image.cpio.gz\0"				\
+	"name_kern=uImage-keystone-evm.bin\0"				\
+	"name_mon=skern-keystone-evm.bin\0"				\
+	"name_uboot=u-boot-spi-keystone-evm.gph\0"			\
+	"name_ubi=keystone-evm-ubifs.ubi\0"				\
 	"run_mon=mon_install ${addr_mon}\0"				\
 	"run_kern=bootm ${addr_kern} - ${addr_fdt}\0"			\
+	"init_net=run args_all args_net\0"				\
 	"init_ubi=run args_all args_ubi; "				\
 		"ubi part ubifs; ubifsmount boot\0"			\
+	"get_fdt_net=dhcp ${addr_fdt} ${tftp_root}/${name_fdt}\0"	\
 	"get_fdt_ubi=ubifsload ${addr_fdt} ${name_fdt}\0"		\
+	"get_kern_net=dhcp ${addr_kern} ${tftp_root}/${name_kern}\0"	\
 	"get_kern_ubi=ubifsload ${addr_kern} ${name_kern}\0"		\
+	"get_mon_net=dhcp ${addr_mon} ${tftp_root}/${name_mon}\0"	\
 	"get_mon_ubi=ubifsload ${addr_mon} ${name_mon}\0"		\
+	"get_uboot_net=dhcp ${addr_uboot} ${tftp_root}/${name_uboot}\0"	\
 	"burn_uboot=sf probe; sf erase 0 0x100000; "			\
 		"sf write ${addr_uboot} 0 ${filesize}\0"		\
 	"args_all=setenv bootargs console=ttyS0,115200n8 rootwait=1\0"	\
 	"args_ubi=setenv bootargs ${bootargs} rootfstype=ubifs "	\
 		"root=ubi0:rootfs rootflags=sync rw ubi.mtd=2,2048\0"	\
+	"args_net=setenv bootargs ${bootargs} rootfstype=nfs "		\
+		"root=/dev/nfs rw nfsroot=${serverip}:${nfs_root},"	\
+		"${nfs_options} ip=dhcp\0"				\
+	"nfs_options=v3,tcp,rsize=4096,wsize=4096\0"			\
+	"get_fdt_ramfs=dhcp ${addr_fdt} ${tftp_root}/${name_fdt}\0"	\
+	"get_kern_ramfs=dhcp ${addr_kern} ${tftp_root}/${name_kern}\0"	\
+	"get_mon_ramfs=dhcp ${addr_mon} ${tftp_root}/${name_mon}\0"	\
+	"get_fs_ramfs=dhcp ${addr_fs} ${tftp_root}/${name_fs}\0"	\
+	"get_ubi_net=dhcp ${addr_ubi} ${tftp_root}/${name_ubi}\0"	\
 	"burn_ubi=nand erase.part ubifs; "				\
 		"nand write ${addr_ubi} ubifs ${filesize}\0"		\
 	"init_ramfs=run args_all args_ramfs get_fs_ramfs\0"		\
 	"args_ramfs=setenv bootargs ${bootargs} earlyprintk "		\
 		"rdinit=/sbin/init rw root=/dev/ram0 "			\
 		"initrd=0x802000000,9M\0"				\
+	"no_post=1\0"							\
 	"mtdparts=mtdparts=davinci_nand.0:"				\
 		"1024k(bootloader)ro,512k(params)ro,522752k(ubifs)\0"
 #define CONFIG_BOOTCOMMAND						\