diff mbox

[v2,10/12] keystone2: net: add keystone ethernet driver

Message ID 1392918914-15564-11-git-send-email-m-karicheri2@ti.com
State New
Headers show

Commit Message

Murali Karicheri Feb. 20, 2014, 5:55 p.m. UTC
From: Vitaly Andrianov <vitalya@ti.com>

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>
---
 - updated based on review comments
 arch/arm/include/asm/arch-keystone/emac_defs.h |  250 +++++++
 board/ti/k2hk_evm/board.c                      |   65 ++
 drivers/net/Makefile                           |    1 +
 drivers/net/keystone_net.c                     |  859 ++++++++++++++++++++++++
 include/configs/k2hk_evm.h                     |   38 ++
 5 files changed, 1213 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-keystone/emac_defs.h
 create mode 100644 drivers/net/keystone_net.c

Comments

Murali Karicheri March 12, 2014, 7:04 p.m. UTC | #1
On 2/25/2014 5:11 PM, Rini, Tom wrote:
> On Thu, Feb 20, 2014 at 12:55:12PM -0500, Murali Karicheri wrote:
>
>> From: Vitaly Andrianov <vitalya@ti.com>
>>
>> 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.
> First, can we just use things in a "dumb" mode and use the existing CPSW
> driver?  Or are there use cases we need to worry about here with a
> bigger / more robust network driver?

First of all we believe the CPSW driver in u-boot is for  tnetv107x CPSW 
hardware and
keystone CPSW is different and more complex. We need to support 
different modes
such as MAC to PHY, MAC to MAC and MAC to MAC forced. Also we are using 
a SGMII
with up to 8 ports in the newer K2 devices. So we don't think we can 
re-use the CPSW
driver.
>> +++ b/drivers/net/keystone_net.c
> Generic problem, please use phylib.

Vitaly has done some prototyping with phy lib and  found that this adds 
tons of code and
huge time to change the active port.  It doesn't give any advantage of 
using phylib as the
driver make only very few reads from standard generic phy registers.

keystone driver has to support phy-less mode (different modes listed 
above) and using the
phylib just unnecessary complicates the driver.  So

Does phylib based drivers have similar scenario as in keystone? How does 
other platforms
that uses phylib solves the above issues? Mainly delayed tftp and 
handling multiple modes?

We have taken care of all of comments here. So can we go with the 
current version of the
driver and then switch to phylib implementation if the above issues can 
be solved on a
phylib based implementation?

>> +void sgmii_serdes_setup_156p25mhz()
>> +{
>> +	unsigned int cnt;
>> +
>> +	reg_rmw(0x0232a000, 0x00800000, 0xffff0000);
> Please comment on what we're doing here, and why we aren't using a
> struct to describe whatever is at 0x0232a000 ?
>
>> +void sgmii_serdes_shutdown()
>> +{
>> +	reg_rmw(0x0232bfe0, 0, 3 << 29 | 3 << 13);
> Same.

We will add comment here as we are using third party SERDES IP and the 
register
names are not published by the vendor.
> Thanks!
>
Tom Rini March 12, 2014, 8:01 p.m. UTC | #2
On Wed, Mar 12, 2014 at 03:04:04PM -0400, Murali Karicheri wrote:
> On 2/25/2014 5:11 PM, Rini, Tom wrote:
> >On Thu, Feb 20, 2014 at 12:55:12PM -0500, Murali Karicheri wrote:
> >
> >>From: Vitaly Andrianov <vitalya@ti.com>
> >>
> >>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.
> >First, can we just use things in a "dumb" mode and use the existing CPSW
> >driver?  Or are there use cases we need to worry about here with a
> >bigger / more robust network driver?
> 
> First of all we believe the CPSW driver in u-boot is for  tnetv107x
> CPSW hardware and

No, it's for the am335x and DRA7xx HW.

> keystone CPSW is different and more complex. We need to support
> different modes
> such as MAC to PHY, MAC to MAC and MAC to MAC forced. Also we are
> using a SGMII
> with up to 8 ports in the newer K2 devices. So we don't think we can
> re-use the CPSW
> driver.

How many of these modes do we actually need to support in U-Boot?  What
usecase(s) do you have for networking in U-Boot?  And I assume you're
having similar conversations upstreaming the kernel networking driver
(which does support am33xx/dra7xx and tnetv107x)..

> >>+++ b/drivers/net/keystone_net.c
> >Generic problem, please use phylib.
> 
> Vitaly has done some prototyping with phy lib and  found that this
> adds tons of code and
> huge time to change the active port.  It doesn't give any advantage
> of using phylib as the
> driver make only very few reads from standard generic phy registers.

OK.

> >>+void sgmii_serdes_setup_156p25mhz()
> >>+{
> >>+	unsigned int cnt;
> >>+
> >>+	reg_rmw(0x0232a000, 0x00800000, 0xffff0000);
> >Please comment on what we're doing here, and why we aren't using a
> >struct to describe whatever is at 0x0232a000 ?
> >
> >>+void sgmii_serdes_shutdown()
> >>+{
> >>+	reg_rmw(0x0232bfe0, 0, 3 << 29 | 3 << 13);
> >Same.
> 
> We will add comment here as we are using third party SERDES IP and
> the register
> names are not published by the vendor.

Please check what you are and are not allowed to say.  It's usually the
case with NDA'd docs that if you can release code based on the docs it
doesn't have to be heavily obsucred and you can say what you're doing.
diff mbox

Patch

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..9c1c5bc
--- /dev/null
+++ b/arch/arm/include/asm/arch-keystone/emac_defs.h
@@ -0,0 +1,250 @@ 
+/*
+ * 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/board/ti/k2hk_evm/board.c b/board/ti/k2hk_evm/board.c
index 14dc7e4..81f5ca4 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>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -70,6 +71,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..473a4b1
--- /dev/null
+++ b/drivers/net/keystone_net.c
@@ -0,0 +1,859 @@ 
+/*
+ * 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 985db8e..33c7551 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						\