diff mbox

[U-Boot,v2,2/2] ARM:AM33XX:Added cpsw support for AM335x EVM

Message ID 1320928830-16221-3-git-send-email-chandan.nath@ti.com
State Changes Requested
Headers show

Commit Message

Chandan Nath Nov. 10, 2011, 12:40 p.m. UTC
This patch adds cpsw support on AM335X EVM.

Signed-off-by: Chandan Nath <chandan.nath@ti.com>
---
Changes since v1:
 - Added weak alias miiphy_is_1000base_x function to fix atheros phy issue

 arch/arm/cpu/armv7/am33xx/clock.c           |    9 ++-
 arch/arm/include/asm/arch-am33xx/cpu.h      |   22 ++++-
 arch/arm/include/asm/arch-am33xx/hardware.h |    5 +
 board/ti/am335x/common_def.h                |    2 +
 board/ti/am335x/evm.c                       |  149 +++++++++++++++++++++++++++
 board/ti/am335x/mux.c                       |   24 +++++
 common/miiphyutil.c                         |    5 +-
 drivers/net/cpsw.c                          |  147 ++++++++++++++++++--------
 include/configs/am335x_evm.h                |   16 +++-
 include/netdev.h                            |   19 +++-
 10 files changed, 341 insertions(+), 57 deletions(-)

Comments

Tom Rini Nov. 10, 2011, 2:46 p.m. UTC | #1
On Thu, Nov 10, 2011 at 5:40 AM, Chandan Nath <chandan.nath@ti.com> wrote:
> This patch adds cpsw support on AM335X EVM.
>
> Signed-off-by: Chandan Nath <chandan.nath@ti.com>

You aren't allowed to have hard-coded MACs anymore, iirc.  And
everyone will be able to get valid MACs from the e-fuse (or on the
other platforms, EEPROM), we need to drop that particular debug print
and just fail when ethaddr isn't set.  So you can drop the
..set_mac_addr function, and fold the rest of the changes to cpsw.c
into the original patch.  Finally, please split the miiphyutil.c
change into its own commit.  Thanks.
Chandan Nath Nov. 10, 2011, 3:05 p.m. UTC | #2
> -----Original Message-----
> From: Tom Rini [mailto:tom.rini@gmail.com]
> Sent: Thursday, November 10, 2011 8:17 PM
> To: Kumar Nath, Chandan
> Cc: u-boot@lists.denx.de
> Subject: Re: [U-Boot] [PATCH v2 2/2] ARM:AM33XX:Added cpsw support for
> AM335x EVM
> 
> On Thu, Nov 10, 2011 at 5:40 AM, Chandan Nath <chandan.nath@ti.com>
> wrote:
> > This patch adds cpsw support on AM335X EVM.
> >
> > Signed-off-by: Chandan Nath <chandan.nath@ti.com>
> 
> You aren't allowed to have hard-coded MACs anymore, iirc.  And
> everyone will be able to get valid MACs from the e-fuse (or on the
> other platforms, EEPROM), we need to drop that particular debug print
> and just fail when ethaddr isn't set.  So you can drop the
> ..set_mac_addr function, and fold the rest of the changes to cpsw.c
> into the original patch.  Finally, please split the miiphyutil.c
> change into its own commit.  Thanks.
> 

I will remove the debug print and return failure when ethaddr is not set.
I have already remove cpsw_eth_set_mac_addr function from cpsw.c and pushed
to the original patch.

I will split miiphyutil.c changes in to a separate patch.

> --
> Tom
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/am33xx/clock.c b/arch/arm/cpu/armv7/am33xx/clock.c
index 4ca6c45..73b1408 100644
--- a/arch/arm/cpu/armv7/am33xx/clock.c
+++ b/arch/arm/cpu/armv7/am33xx/clock.c
@@ -24,6 +24,7 @@ 
 
 #define PRCM_MOD_EN		0x2
 #define PRCM_FORCE_WAKEUP	0x2
+#define PRCM_FUNCTL		0x0
 
 #define PRCM_EMIF_CLK_ACTIVITY	BIT(2)
 #define PRCM_L3_GCLK_ACTIVITY	BIT(4)
@@ -38,7 +39,7 @@ 
 #define CLK_MODE_SEL		0x7
 #define CLK_MODE_MASK		0xfffffff8
 #define CLK_DIV_SEL		0xFFFFFFE0
-
+#define CPGMAC0_IDLE		0x30000
 
 const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
 const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
@@ -105,6 +106,12 @@  static void enable_per_clocks(void)
 	writel(PRCM_MOD_EN, &cmwkup->wkup_uart0ctrl);
 	while (readl(&cmwkup->wkup_uart0ctrl) != PRCM_MOD_EN)
 		;
+
+	/* Ethernet */
+	writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl);
+	writel(PRCM_MOD_EN, &cmper->cpswclkstctrl);
+	while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL)
+		;
 }
 
 static void mpu_pll_config(void)
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index ad9156e..e255dd9 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -108,7 +108,9 @@  struct cm_perpll {
 	unsigned int l3sclkstctrl;	/* offset 0x04 */
 	unsigned int l4fwclkstctrl;	/* offset 0x08 */
 	unsigned int l3clkstctrl;	/* offset 0x0c */
-	unsigned int resv1[6];
+	unsigned int resv0[1];
+	unsigned int cpgmac0clkctrl;	/* offset 0x14 */
+	unsigned int resv1[4];
 	unsigned int emifclkctrl;	/* offset 0x28 */
 	unsigned int ocmcramclkctrl;	/* offset 0x2c */
 	unsigned int resv2[12];
@@ -124,6 +126,8 @@  struct cm_perpll {
 	unsigned int resv6[14];
 	unsigned int l4hsclkstctrl;	/* offset 0x11C */
 	unsigned int l4hsclkctrl;	/* offset 0x120 */
+	unsigned int resv7[8];
+	unsigned int cpswclkstctrl;	/* offset 0x144 */
 };
 
 /* Encapsulating Display pll registers */
@@ -173,9 +177,9 @@  struct timer_reg {
 /* Timer 32 bit registers */
 struct gptimer {
 	unsigned int tidr;		/* offset 0x00 */
-	unsigned int res1[0xc];
+	unsigned int res1[3];
 	unsigned int tiocp_cfg;		/* offset 0x10 */
-	unsigned int res2[0xc];
+	unsigned int res2[3];
 	unsigned int tier;		/* offset 0x20 */
 	unsigned int tistatr;		/* offset 0x24 */
 	unsigned int tistat;		/* offset 0x28 */
@@ -211,6 +215,18 @@  struct ctrl_stat {
 	unsigned int statusreg;		/* ofset 0x40 */
 };
 
+/* Control Device Register */
+struct ctrl_dev {
+	unsigned int deviceid;		/* offset 0x00 */
+	unsigned int resv1[11];
+	unsigned int macid0l;		/* offset 0x30 */
+	unsigned int macid0h;		/* offset 0x34 */
+	unsigned int macid1l;		/* offset 0x38 */
+	unsigned int macid1h;		/* offset 0x3c */
+	unsigned int resv2[4];
+	unsigned int miisel;		/* offset 0x50 */
+};
+
 void init_timer(void);
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL_STRICT_NAMES */
diff --git a/arch/arm/include/asm/arch-am33xx/hardware.h b/arch/arm/include/asm/arch-am33xx/hardware.h
index 0ec22eb..4b1c725 100644
--- a/arch/arm/include/asm/arch-am33xx/hardware.h
+++ b/arch/arm/include/asm/arch-am33xx/hardware.h
@@ -46,6 +46,7 @@ 
 
 /* Control Module Base Address */
 #define CTRL_BASE			0x44E10000
+#define CTRL_DEVICE_BASE		0x44E10600
 
 /* PRCM Base Address */
 #define PRCM_BASE			0x44E00000
@@ -78,4 +79,8 @@ 
 #define DDRPHY_0_CONFIG_BASE		(CTRL_BASE + 0x1400)
 #define DDRPHY_CONFIG_BASE		DDRPHY_0_CONFIG_BASE
 
+/* CPSW Config space */
+#define AM335X_CPSW_BASE		0x4A100000
+#define AM335X_CPSW_MDIO_BASE		0x4A101000
+
 #endif /* __AM33XX_HARDWARE_H */
diff --git a/board/ti/am335x/common_def.h b/board/ti/am335x/common_def.h
index 1696d60..01cda88 100644
--- a/board/ti/am335x/common_def.h
+++ b/board/ti/am335x/common_def.h
@@ -17,8 +17,10 @@ 
 #define __COMMON_DEF_H__
 
 extern void enable_uart0_pin_mux(void);
+extern void enable_rgmii1_pin_mux(void);
 extern void configure_evm_pin_mux(unsigned char daughter_board_id,
 					unsigned short daughter_board_profile,
 					unsigned char daughter_board_flag);
+extern void cpsw_eth_set_mac_addr(const unsigned char *addr);
 
 #endif/*__COMMON_DEF_H__ */
diff --git a/board/ti/am335x/evm.c b/board/ti/am335x/evm.c
index b4eddd8..993d2a1 100644
--- a/board/ti/am335x/evm.c
+++ b/board/ti/am335x/evm.c
@@ -18,6 +18,8 @@ 
 #include <asm/arch/hardware.h>
 #include "common_def.h"
 #include <serial.h>
+#include <miiphy.h>
+#include <netdev.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -25,6 +27,12 @@  DECLARE_GLOBAL_DATA_PTR;
 #define UART_CLK_RUNNING_MASK	0x1
 #define UART_SMART_IDLE_EN	(0x1 << 0x3)
 
+/* RGMII mode define */
+#define RGMII_MODE_ENABLE	0xA
+#define ETH_ALEN		6
+
+struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
+
 /*
  * Basic board specific setup
  */
@@ -42,7 +50,148 @@  int init_basic_setup(void)
 int board_init(void)
 {
 	enable_uart0_pin_mux();
+	enable_rgmii1_pin_mux();
 	init_basic_setup();
 
 	return 0;
 }
+
+#ifdef CONFIG_DRIVER_TI_CPSW
+/* Atheros PHY report 1000baseX speed incorrectly and so this function
+ * is define to overcome this issue. The original code is kept as
+ * _miiphy_is_1000base_x as an weak alias to this function.
+ */
+int miiphy_is_1000base_x(const char *devname, unsigned char addr)
+{
+	return 0;
+}
+
+/* TODO : Check for the board specific PHY */
+static void evm_phy_init(char *name, int addr)
+{
+	unsigned short val;
+	unsigned int cntr = 0;
+
+	/* Enable Autonegotiation */
+	if (miiphy_read(name, addr, MII_BMCR, &val) != 0) {
+		printf("failed to read bmcr\n");
+		return;
+	}
+
+	val |= BMCR_FULLDPLX | BMCR_ANENABLE | BMCR_SPEED100;
+	if (miiphy_write(name, addr, MII_BMCR, val) != 0) {
+		printf("failed to write bmcr\n");
+		return;
+	}
+	miiphy_read(name, addr, MII_BMCR, &val);
+
+	/* TODO: Disable GIG advertisement for the time being */
+	miiphy_read(name, addr, MII_CTRL1000, &val);
+	val |= PHY_1000BTCR_1000FD;
+	val &= ~PHY_1000BTCR_1000HD;
+	miiphy_write(name, addr, MII_CTRL1000, val);
+	miiphy_read(name, addr, MII_CTRL1000, &val);
+
+	/* Setup general advertisement */
+	if (miiphy_read(name, addr, MII_ADVERTISE, &val) != 0) {
+		printf("failed to read anar\n");
+		return;
+	}
+	val |= (LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL);
+	if (miiphy_write(name, addr, MII_ADVERTISE, val) != 0) {
+		printf("failed to write anar\n");
+		return;
+	}
+	miiphy_read(name, addr, MII_ADVERTISE, &val);
+
+	/* Restart auto negotiation*/
+	miiphy_read(name, addr, MII_BMCR, &val);
+	val |= BMCR_ANRESTART;
+	miiphy_write(name, addr, MII_BMCR, val);
+
+	/*check AutoNegotiate complete - it can take upto 3 secs*/
+	do {
+		udelay(40000);
+		cntr++;
+		if (!miiphy_read(name, addr, MII_BMSR, &val)) {
+			if (val & BMSR_ANEGCOMPLETE)
+				break;
+		}
+	} while (cntr < 1000);
+
+	if (cntr >= 1000)
+		printf("Auto negotitation failed\n");
+
+	return;
+}
+
+static void cpsw_control(int enabled)
+{
+	/* nothing for now */
+	/* TODO : VTP was here before */
+	return;
+}
+
+static struct cpsw_slave_data cpsw_slaves[] = {
+	{
+		.slave_reg_ofs	= 0x208,
+		.sliver_reg_ofs	= 0xd80,
+		.phy_id		= 0,
+	},
+	{
+		.slave_reg_ofs	= 0x308,
+		.sliver_reg_ofs	= 0xdc0,
+		.phy_id		= 1,
+	},
+};
+
+static struct cpsw_platform_data cpsw_data = {
+	.mdio_base		= AM335X_CPSW_MDIO_BASE,
+	.cpsw_base		= AM335X_CPSW_BASE,
+	.mdio_div		= 0xff,
+	.channels		= 8,
+	.cpdma_reg_ofs		= 0x800,
+	.slaves			= 1,
+	.slave_data		= cpsw_slaves,
+	.ale_reg_ofs		= 0xd00,
+	.ale_entries		= 1024,
+	.host_port_reg_ofs	= 0x108,
+	.hw_stats_reg_ofs	= 0x900,
+	.mac_control		= (1 << 5),
+	.control		= cpsw_control,
+	.phy_init		= evm_phy_init,
+	.host_port_num		= 0,
+	.version		= CPSW_CTRL_VERSION_2,
+};
+
+int board_eth_init(bd_t *bis)
+{
+	uint8_t mac_addr[6];
+	uint32_t mac_hi, mac_lo;
+
+	if (!eth_getenv_enetaddr("ethaddr", mac_addr)) {
+		debug("<ethaddr> not set. Reading from E-fuse\n");
+		/* try reading mac address from efuse */
+		mac_lo = readl(&cdev->macid0l);
+		mac_hi = readl(&cdev->macid0h);
+		mac_addr[0] = mac_hi & 0xFF;
+		mac_addr[1] = (mac_hi & 0xFF00) >> 8;
+		mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
+		mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
+		mac_addr[4] = mac_lo & 0xFF;
+		mac_addr[5] = (mac_lo & 0xFF00) >> 8;
+
+		if (is_valid_ether_addr(mac_addr)) {
+			eth_setenv_enetaddr("ethaddr", mac_addr);
+		} else {
+			printf("Caution: Using hardcoded mac address. "
+				"Set <ethaddr> variable to overcome this.\n");
+		}
+	}
+
+	/* set mii mode to rgmii in in device configure register */
+	writel(RGMII_MODE_ENABLE, &cdev->miisel);
+
+	return cpsw_register(&cpsw_data);
+}
+#endif
diff --git a/board/ti/am335x/mux.c b/board/ti/am335x/mux.c
index 8f27409..3cda206 100644
--- a/board/ti/am335x/mux.c
+++ b/board/ti/am335x/mux.c
@@ -258,6 +258,24 @@  static struct module_pin_mux uart0_pin_mux[] = {
 	{-1},
 };
 
+static struct module_pin_mux rgmii1_pin_mux[] = {
+	{OFFSET(mii1_txen), MODE(2)},			/* RGMII1_TCTL */
+	{OFFSET(mii1_rxdv), MODE(2) | RXACTIVE},	/* RGMII1_RCTL */
+	{OFFSET(mii1_txd3), MODE(2)},			/* RGMII1_TD3 */
+	{OFFSET(mii1_txd2), MODE(2)},			/* RGMII1_TD2 */
+	{OFFSET(mii1_txd1), MODE(2)},			/* RGMII1_TD1 */
+	{OFFSET(mii1_txd0), MODE(2)},			/* RGMII1_TD0 */
+	{OFFSET(mii1_txclk), MODE(2)},			/* RGMII1_TCLK */
+	{OFFSET(mii1_rxclk), MODE(2) | RXACTIVE},	/* RGMII1_RCLK */
+	{OFFSET(mii1_rxd3), MODE(2) | RXACTIVE},	/* RGMII1_RD3 */
+	{OFFSET(mii1_rxd2), MODE(2) | RXACTIVE},	/* RGMII1_RD2 */
+	{OFFSET(mii1_rxd1), MODE(2) | RXACTIVE},	/* RGMII1_RD1 */
+	{OFFSET(mii1_rxd0), MODE(2) | RXACTIVE},	/* RGMII1_RD0 */
+	{OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN},/* MDIO_DATA */
+	{OFFSET(mdio_clk), MODE(0) | PULLUP_EN},	/* MDIO_CLK */
+	{-1},
+};
+
 /*
  * Configure the pin mux for the module
  */
@@ -276,3 +294,9 @@  void enable_uart0_pin_mux(void)
 {
 	configure_module_pin_mux(uart0_pin_mux);
 }
+
+
+void enable_rgmii1_pin_mux(void)
+{
+	configure_module_pin_mux(rgmii1_pin_mux);
+}
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
index 35ad357..dd56fda 100644
--- a/common/miiphyutil.c
+++ b/common/miiphyutil.c
@@ -548,7 +548,7 @@  miiphy_read_failed:
  * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
  * 1000BASE-T, or on error.
  */
-int miiphy_is_1000base_x(const char *devname, unsigned char addr)
+static int __miiphy_is_1000base_x(const char *devname, unsigned char addr)
 {
 #if defined(CONFIG_PHY_GIGE)
 	u16 exsr;
@@ -564,6 +564,9 @@  int miiphy_is_1000base_x(const char *devname, unsigned char addr)
 #endif
 }
 
+int miiphy_is_1000base_x(const char *devname, unsigned char addr)
+	__attribute__((weak, alias("__miiphy_is_1000base_x")));
+
 #ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
 /*****************************************************************************
  *
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index 4cef4cf..c41eeaf 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -1,22 +1,16 @@ 
 /*
  * CPSW Ethernet Switch Driver
  *
- * See file CREDITS for list of people who contributed to this
- * project.
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <common.h>
@@ -28,9 +22,7 @@ 
 #include <netdev.h>
 #include <asm/errno.h>
 #include <asm/io.h>
-#include <linux/mii.h>
 
-#define BIT(x)			(1 << (x))
 #define BITMASK(bits)		(BIT(bits) - 1)
 #define PHY_REG_MASK		0x1f
 #define PHY_ID_MASK		0x1f
@@ -43,10 +35,15 @@ 
 #define CPDMA_RXCONTROL		0x014
 #define CPDMA_SOFTRESET		0x01c
 #define CPDMA_RXFREE		0x0e0
-#define CPDMA_TXHDP		0x100
-#define CPDMA_RXHDP		0x120
-#define CPDMA_TXCP		0x140
-#define CPDMA_RXCP		0x160
+#define CPDMA_TXHDP_VER1	0x100
+#define CPDMA_TXHDP_VER2	0x200
+#define CPDMA_RXHDP_VER1	0x120
+#define CPDMA_RXHDP_VER2	0x220
+#define CPDMA_TXCP_VER1		0x140
+#define CPDMA_TXCP_VER2		0x240
+#define CPDMA_RXCP_VER1		0x160
+#define CPDMA_RXCP_VER2		0x260
+
 
 /* Descriptor mode bits */
 #define CPDMA_DESC_SOP		BIT(31)
@@ -252,12 +249,12 @@  static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value)	\
 
 DEFINE_ALE_FIELD(entry_type,		60,	2)
 DEFINE_ALE_FIELD(mcast_state,		62,	2)
-DEFINE_ALE_FIELD(port_mask,		64,	3)
-DEFINE_ALE_FIELD(ucast_type,		66,	2)
-DEFINE_ALE_FIELD(port_num,		64,	2)
-DEFINE_ALE_FIELD(blocked,		63,	1)
-DEFINE_ALE_FIELD(secure,		62,	1)
-DEFINE_ALE_FIELD(mcast,			47,	1)
+DEFINE_ALE_FIELD(port_mask,		66,	3)
+DEFINE_ALE_FIELD(ucast_type,		62,	2)
+DEFINE_ALE_FIELD(port_num,		66,	2)
+DEFINE_ALE_FIELD(blocked,		65,	1)
+DEFINE_ALE_FIELD(secure,		64,	1)
+DEFINE_ALE_FIELD(mcast,			40,	1)
 
 /* The MAC address field in the ALE entry cannot be macroized as above */
 static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
@@ -452,7 +449,7 @@  static inline void wait_for_idle(void)
 		;
 }
 
-static int cpsw_mdio_read(char *devname, unsigned char phy_id,
+static int cpsw_mdio_read(const char *devname, unsigned char phy_id,
 			  unsigned char phy_reg, unsigned short *data)
 {
 	u32 reg;
@@ -470,7 +467,7 @@  static int cpsw_mdio_read(char *devname, unsigned char phy_id,
 	return (reg & USERACCESS_ACK) ? 0 : -EIO;
 }
 
-static int cpsw_mdio_write(char *devname, unsigned char phy_id,
+static int cpsw_mdio_write(const char *devname, unsigned char phy_id,
 			   unsigned char phy_reg, unsigned short data)
 {
 	u32 reg;
@@ -502,6 +499,7 @@  static void cpsw_mdio_init(char *name, u32 mdio_base, u32 div)
 	 * silicon.  Since the effect of (b) was found to be largely
 	 * negligible, we keep things simple here.
 	 */
+
 	udelay(1000);
 
 	miiphy_register(name, cpsw_mdio_read, cpsw_mdio_write);
@@ -514,6 +512,20 @@  static inline void soft_reset(void *reg)
 		;
 }
 
+static u_int8_t cpsw_eth_mac_addr[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x66 };
+
+/*
+ * This function must be called before cpsw_init() if you want to override
+ * the default mac address.
+ */
+void cpsw_eth_set_mac_addr(const u_int8_t *addr)
+{
+	int i;
+
+	for (i = 0; i < sizeof(cpsw_eth_mac_addr); i++)
+		cpsw_eth_mac_addr[i] = addr[i];
+}
+
 #define mac_hi(mac)	(((mac)[0] << 0) | ((mac)[1] << 8) |	\
 			 ((mac)[2] << 16) | ((mac)[3] << 24))
 #define mac_lo(mac)	(((mac)[4] << 0) | ((mac)[5] << 8))
@@ -547,6 +559,8 @@  static void cpsw_slave_update_link(struct cpsw_slave *slave,
 			mac_control |= BIT(7);	/* GIGABITEN	*/
 		if (duplex == FULL)
 			mac_control |= BIT(0);	/* FULLDUPLEXEN	*/
+		if (speed == 100)
+			mac_control |= BIT(15);
 	}
 
 	if (mac_control == slave->mac_control)
@@ -571,8 +585,17 @@  static int cpsw_update_link(struct cpsw_priv *priv)
 	return link;
 }
 
+static inline u32  cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+{
+	if (priv->host_port == 0)
+		return slave_num + 1;
+	else
+		return slave_num;
+}
+
 static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
 {
+	u32     slave_port;
 	soft_reset(&slave->sliver->soft_reset);
 
 	/* setup priority mapping */
@@ -586,9 +609,10 @@  static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
 	slave->mac_control = 0;	/* no link yet */
 
 	/* enable forwarding */
-	cpsw_ale_port_state(priv, slave->slave_num, ALE_PORT_STATE_FORWARD);
+	slave_port = cpsw_get_slave_port(priv, slave->slave_num);
+	cpsw_ale_port_state(priv, slave_port, ALE_PORT_STATE_FORWARD);
 
-	cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << slave->slave_num);
+	cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << slave_port);
 
 	priv->data.phy_init(priv->dev->name, slave->data->phy_id);
 }
@@ -708,7 +732,7 @@  static int cpsw_init(struct eth_device *dev, bd_t *bis)
 	__raw_writel(BIT(priv->host_port), &priv->regs->stat_port_en);
 
 	cpsw_ale_port_state(priv, priv->host_port, ALE_PORT_STATE_FORWARD);
-
+	memcpy(priv->dev->enetaddr, cpsw_eth_mac_addr, 6);
 	cpsw_ale_add_ucast(priv, priv->dev->enetaddr, priv->host_port,
 			   ALE_SECURE);
 	cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << priv->host_port);
@@ -725,25 +749,58 @@  static int cpsw_init(struct eth_device *dev, bd_t *bis)
 	priv->desc_free = &priv->descs[0];
 
 	/* initialize channels */
-	memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
-	priv->rx_chan.hdp	= priv->dma_regs + CPDMA_RXHDP;
-	priv->rx_chan.cp	= priv->dma_regs + CPDMA_RXCP;
-	priv->rx_chan.rxfree	= priv->dma_regs + CPDMA_RXFREE;
-
-	memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
-	priv->tx_chan.hdp	= priv->dma_regs + CPDMA_TXHDP;
-	priv->tx_chan.cp	= priv->dma_regs + CPDMA_TXCP;
+	if (priv->data.version == CPSW_CTRL_VERSION_2) {
+		memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
+		priv->rx_chan.hdp       = priv->dma_regs + CPDMA_RXHDP_VER2;
+		priv->rx_chan.cp        = priv->dma_regs + CPDMA_RXCP_VER2;
+		priv->rx_chan.rxfree    = priv->dma_regs + CPDMA_RXFREE;
+
+		memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
+		priv->tx_chan.hdp       = priv->dma_regs + CPDMA_TXHDP_VER2;
+		priv->tx_chan.cp        = priv->dma_regs + CPDMA_TXCP_VER2;
+	} else {
+		memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
+		priv->rx_chan.hdp       = priv->dma_regs + CPDMA_RXHDP_VER1;
+		priv->rx_chan.cp        = priv->dma_regs + CPDMA_RXCP_VER1;
+		priv->rx_chan.rxfree    = priv->dma_regs + CPDMA_RXFREE;
+
+		memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
+		priv->tx_chan.hdp       = priv->dma_regs + CPDMA_TXHDP_VER1;
+		priv->tx_chan.cp        = priv->dma_regs + CPDMA_TXCP_VER1;
+	}
 
 	/* clear dma state */
 	soft_reset(priv->dma_regs + CPDMA_SOFTRESET);
 
-	for (i = 0; i < priv->data.channels; i++) {
-		__raw_writel(0, priv->dma_regs + CPDMA_RXHDP + 4 * i);
-		__raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4 * i);
-		__raw_writel(0, priv->dma_regs + CPDMA_RXCP + 4 * i);
-		__raw_writel(0, priv->dma_regs + CPDMA_TXHDP + 4 * i);
-		__raw_writel(0, priv->dma_regs + CPDMA_TXCP + 4 * i);
+	if (priv->data.version == CPSW_CTRL_VERSION_2) {
+		for (i = 0; i < priv->data.channels; i++) {
+			__raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER2 + 4
+					* i);
+			__raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
+					* i);
+			__raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER2 + 4
+					* i);
+			__raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER2 + 4
+					* i);
+			__raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER2 + 4
+					* i);
+		}
+	} else {
+		for (i = 0; i < priv->data.channels; i++) {
+			__raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER1 + 4
+					* i);
+			__raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
+					* i);
+			__raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER1 + 4
+					* i);
+			__raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER1 + 4
+					* i);
+			__raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER1 + 4
+					* i);
+
+		}
 	}
+
 	__raw_writel(1, priv->dma_regs + CPDMA_TXCONTROL);
 	__raw_writel(1, priv->dma_regs + CPDMA_RXCONTROL);
 
@@ -838,7 +895,7 @@  int cpsw_register(struct cpsw_platform_data *data)
 		return -ENOMEM;
 	}
 
-	priv->host_port		= data->slaves;
+	priv->host_port		= data->host_port_num;
 	priv->regs		= regs;
 	priv->host_port_regs	= regs + data->host_port_reg_ofs;
 	priv->dma_regs		= regs + data->cpdma_reg_ofs;
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index b471c9b..18844db 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -21,7 +21,6 @@ 
 #undef CONFIG_GZIP
 #undef CONFIG_ZLIB
 #undef CONFIG_SYS_HUSH_PARSER
-#undef CONFIG_CMD_NET
 
 #include <asm/arch/cpu.h>
 #include <asm/arch/hardware.h>
@@ -116,6 +115,21 @@ 
 
 #define CONFIG_SYS_TEXT_BASE		0x402f0400
 
+# define CONFIG_CMD_NET
+# define CONFIG_CMD_DHCP
+# define CONFIG_CMD_PING
+# define CONFIG_DRIVER_TI_CPSW
+# define CONFIG_MII
+# define CONFIG_BOOTP_DEFAULT
+# define CONFIG_BOOTP_DNS
+# define CONFIG_BOOTP_DNS2
+# define CONFIG_BOOTP_SEND_HOSTNAME
+# define CONFIG_BOOTP_GATEWAY
+# define CONFIG_BOOTP_SUBNETMASK
+# define CONFIG_NET_RETRY_COUNT         10
+# define CONFIG_NET_MULTI
+# define CONFIG_PHY_GIGE
+
 /* Unsupported features */
 #undef CONFIG_USE_IRQ
 
diff --git a/include/netdev.h b/include/netdev.h
index 740213e..b8c12ae 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -193,21 +193,28 @@  struct cpsw_slave_data {
 	int		phy_id;
 };
 
+enum {
+	CPSW_CTRL_VERSION_1 = 0, /* version1 devices */
+	CPSW_CTRL_VERSION_2      /* version2 devices */
+};
+
 struct cpsw_platform_data {
 	u32	mdio_base;
 	u32	cpsw_base;
 	int	mdio_div;
-	int	channels;       /* number of cpdma channels (symmetric)	*/
-	u32     cpdma_reg_ofs;  /* cpdma register offset		*/
-	int     slaves;         /* number of slave cpgmac ports		*/
-	u32     ale_reg_ofs;    /* address lookup engine reg offset	*/
-	int     ale_entries;	/* ale table size			*/
+	int	channels;	/* number of cpdma channels (symmetric)	*/
+	u32	cpdma_reg_ofs;	/* cpdma register offset		*/
+	int	slaves;		/* number of slave cpgmac ports		*/
+	u32	ale_reg_ofs;	/* address lookup engine reg offset	*/
+	int	ale_entries;	/* ale table size			*/
 	u32	host_port_reg_ofs;	/* cpdma host port registers	*/
 	u32	hw_stats_reg_ofs;	/* cpsw hw stats counters	*/
 	u32	mac_control;
-	struct cpsw_slave_data  *slave_data;
+	struct	cpsw_slave_data  *slave_data;
 	void	(*control)(int enabled);
 	void	(*phy_init)(char *name, int addr);
+	u32	host_port_num;
+	u8	version;
 };
 
 int cpsw_register(struct cpsw_platform_data *data);