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

Chandan Nath chandan.nath at ti.com
Thu Nov 10 13:40:29 CET 2011


This patch adds cpsw support on AM335X EVM.

Signed-off-by: Chandan Nath <chandan.nath at 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(-)

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);
-- 
1.7.1



More information about the U-Boot mailing list