[ARM] TI DaVinci support, hopefully final

Add support for the following DaVinci boards:
- DV_EVM
- SCHMOOGIE
- SONATA

Changes:

- Split into separate board directories
- Removed changes to MTD_DEBUG (or whatever it's called)
- New CONFIG_CMD party line followed
- Some cosmetic fixes, cleanup etc.
- Patches against the latest U-Boot tree as of now.
- Fixed CONFIG_CMD_NET in net files.
- Fixed CONFIG_CMD_EEPROM for schmoogie.
- Made sure it compiles and works (forceenv() link problem) on SCHMOOGIE and
   DV_EVM. Can't check if it works on SONATA, don't have a board any more,
   but it at least compiles.

Here is an excerpt from session log on SCHMOOGIE...

U-Boot 1.2.0-g6c33c785-dirty (Aug  7 2007 - 13:07:17)

DRAM:  128 MB
NAND:  128 MiB
In:    serial
Out:   serial
Err:   serial
ARM Clock : 297MHz
DDR Clock : 162MHz
ETH PHY   : DP83848 @ 0x01
U-Boot > iprobe
Valid chip addresses: 1B 38 3A 3D 3F 50 5D 6F
U-Boot > ping 192.168.253.10
host 192.168.253.10 is alive
U-Boot >

Signed-off-by: Sergey Kubushyn <ksi@koi8.net>
Acked-by: Dirk Behme <dirk.behme@gmail.com>
Acked-by: Zach Sadecki <Zach.Sadecki@ripcode.com>
Acked-by: Stefan Roese <sr@denx.de>
diff --git a/cpu/arm926ejs/davinci/Makefile b/cpu/arm926ejs/davinci/Makefile
new file mode 100644
index 0000000..0f77f40
--- /dev/null
+++ b/cpu/arm926ejs/davinci/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).a
+
+COBJS	= timer.o ether.o lxt972.o dp83848.o i2c.o nand.o
+SOBJS	= lowlevel_init.o reset.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/arm926ejs/davinci/dp83848.c b/cpu/arm926ejs/davinci/dp83848.c
new file mode 100644
index 0000000..5719845
--- /dev/null
+++ b/cpu/arm926ejs/davinci/dp83848.c
@@ -0,0 +1,156 @@
+/*
+ * National Semiconductor DP83848 PHY Driver for TI DaVinci
+ * (TMS320DM644x) based boards.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * --------------------------------------------------------
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <net.h>
+#include <dp83848.h>
+#include <asm/arch/emac_defs.h>
+
+#ifdef CONFIG_DRIVER_TI_EMAC
+
+#ifdef CONFIG_CMD_NET
+
+int dp83848_is_phy_connected(int phy_addr)
+{
+	u_int16_t	id1, id2;
+
+	if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID1_REG, &id1))
+		return(0);
+	if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID2_REG, &id2))
+		return(0);
+
+	if ((id1 == DP83848_PHYID1_OUI) && (id2 == DP83848_PHYID2_OUI))
+		return(1);
+
+	return(0);
+}
+
+int dp83848_get_link_speed(int phy_addr)
+{
+	u_int16_t		tmp;
+	volatile emac_regs*	emac = (emac_regs *)EMAC_BASE_ADDR;
+
+	if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
+		return(0);
+
+	if (!(tmp & DP83848_LINK_STATUS))	/* link up? */
+		return(0);
+
+	if (!dm644x_eth_phy_read(phy_addr, DP83848_PHY_STAT_REG, &tmp))
+		return(0);
+
+	/* Speed doesn't matter, there is no setting for it in EMAC... */
+	if (tmp & DP83848_SPEED) {
+		if (tmp & DP83848_DUPLEX) {
+			/* set DM644x EMAC for Full Duplex  */
+			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+		} else {
+			/*set DM644x EMAC for Half Duplex  */
+			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
+		}
+
+		return(1);
+	} else {
+		if (tmp & DP83848_DUPLEX) {
+			/* set DM644x EMAC for Full Duplex  */
+			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+		} else {
+			/*set DM644x EMAC for Half Duplex  */
+			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
+		}
+
+		return(1);
+	}
+
+	return(0);
+}
+
+
+int dp83848_init_phy(int phy_addr)
+{
+	int	ret = 1;
+
+	if (!dp83848_get_link_speed(phy_addr)) {
+		/* Try another time */
+		udelay(100000);
+		ret = dp83848_get_link_speed(phy_addr);
+	}
+
+	/* Disable PHY Interrupts */
+	dm644x_eth_phy_write(phy_addr, DP83848_PHY_INTR_CTRL_REG, 0);
+
+	return(ret);
+}
+
+
+int dp83848_auto_negotiate(int phy_addr)
+{
+	u_int16_t	tmp;
+
+
+	if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
+		return(0);
+
+	/* Restart Auto_negotiation  */
+	tmp &= ~DP83848_AUTONEG;	/* remove autonegotiation enable */
+	tmp |= DP83848_ISOLATE;		/* Electrically isolate PHY */
+	dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
+
+	/* Set the Auto_negotiation Advertisement Register
+	 * MII advertising for Next page, 100BaseTxFD and HD,
+	 * 10BaseTFD and HD, IEEE 802.3
+	 */
+	tmp = DP83848_NP | DP83848_TX_FDX | DP83848_TX_HDX |
+	 	DP83848_10_FDX | DP83848_10_HDX | DP83848_AN_IEEE_802_3;
+	dm644x_eth_phy_write(phy_addr, DP83848_ANA_REG, tmp);
+
+
+	/* Read Control Register */
+	if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp))
+		return(0);
+
+	tmp |= DP83848_SPEED_SELECT | DP83848_AUTONEG | DP83848_DUPLEX_MODE;
+	dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
+
+	/* Restart Auto_negotiation  */
+	tmp |= DP83848_RESTART_AUTONEG;
+	dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp);
+
+	/*check AutoNegotiate complete */
+	udelay(10000);
+	if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp))
+		return(0);
+
+	if (!(tmp & DP83848_AUTONEG_COMP))
+		return(0);
+
+	return (dp83848_get_link_speed(phy_addr));
+}
+
+#endif	/* CONFIG_CMD_NET */
+
+#endif	/* CONFIG_DRIVER_ETHER */
diff --git a/cpu/arm926ejs/davinci/ether.c b/cpu/arm926ejs/davinci/ether.c
new file mode 100644
index 0000000..9ec1ee7
--- /dev/null
+++ b/cpu/arm926ejs/davinci/ether.c
@@ -0,0 +1,652 @@
+/*
+ * Ethernet driver for TI TMS320DM644x (DaVinci) chips.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright
+ * follows:
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * dm644x_emac.c
+ *
+ * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM
+ *
+ * Copyright (C) 2005 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+
+ * Modifications:
+ * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot.
+ * ver  1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors
+ *
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <miiphy.h>
+#include <asm/arch/emac_defs.h>
+
+#ifdef CONFIG_DRIVER_TI_EMAC
+
+#ifdef CONFIG_CMD_NET
+
+unsigned int	emac_dbg = 0;
+#define debug_emac(fmt,args...)	if (emac_dbg) printf(fmt,##args)
+
+/* Internal static functions */
+static int dm644x_eth_hw_init (void);
+static int dm644x_eth_open (void);
+static int dm644x_eth_close (void);
+static int dm644x_eth_send_packet (volatile void *packet, int length);
+static int dm644x_eth_rcv_packet (void);
+static void dm644x_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);
+
+/* Wrappers exported to the U-Boot proper */
+int eth_hw_init(void)
+{
+	return(dm644x_eth_hw_init());
+}
+
+int eth_init(bd_t * bd)
+{
+	return(dm644x_eth_open());
+}
+
+void eth_halt(void)
+{
+	dm644x_eth_close();
+}
+
+int eth_send(volatile void *packet, int length)
+{
+	return(dm644x_eth_send_packet(packet, length));
+}
+
+int eth_rx(void)
+{
+	return(dm644x_eth_rcv_packet());
+}
+
+void eth_mdio_enable(void)
+{
+	dm644x_eth_mdio_enable();
+}
+/* End of wrappers */
+
+
+static u_int8_t dm644x_eth_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+/*
+ * This function must be called before emac_open() if you want to override
+ * the default mac address.
+ */
+void dm644x_eth_set_mac_addr(const u_int8_t *addr)
+{
+	int i;
+
+	for (i = 0; i < sizeof (dm644x_eth_mac_addr); i++) {
+		dm644x_eth_mac_addr[i] = addr[i];
+	}
+}
+
+/* EMAC Addresses */
+static volatile emac_regs	*adap_emac = (emac_regs *)EMAC_BASE_ADDR;
+static volatile ewrap_regs	*adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
+static volatile mdio_regs	*adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
+
+/* EMAC descriptors */
+static volatile emac_desc	*emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE);
+static volatile emac_desc	*emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
+static volatile emac_desc	*emac_rx_active_head = 0;
+static volatile emac_desc	*emac_rx_active_tail = 0;
+static int			emac_rx_queue_active = 0;
+
+/* Receive packet buffers */
+static unsigned char		emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
+
+/* PHY address for a discovered PHY (0xff - not found) */
+static volatile u_int8_t	active_phy_addr = 0xff;
+
+phy_t				phy;
+
+static void dm644x_eth_mdio_enable(void)
+{
+	u_int32_t	clkdiv;
+
+	clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+
+	adap_mdio->CONTROL = (clkdiv & 0xff) |
+		MDIO_CONTROL_ENABLE |
+		MDIO_CONTROL_FAULT |
+		MDIO_CONTROL_FAULT_ENABLE;
+
+	while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;}
+}
+
+/*
+ * Tries to find an active connected PHY. Returns 1 if address if found.
+ * If no active PHY (or more than one PHY) found returns 0.
+ * Sets active_phy_addr variable.
+ */
+static int dm644x_eth_phy_detect(void)
+{
+	u_int32_t	phy_act_state;
+	int		i;
+
+	active_phy_addr = 0xff;
+
+	if ((phy_act_state = adap_mdio->ALIVE) == 0)
+		return(0);				/* No active PHYs */
+
+	debug_emac("dm644x_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state);
+
+	for (i = 0; i < 32; i++) {
+		if (phy_act_state & (1 << i)) {
+			if (phy_act_state & ~(1 << i))
+				return(0);		/* More than one PHY */
+			else {
+				active_phy_addr = i;
+				return(1);
+			}
+		}
+	}
+
+	return(0);	/* Just to make GCC happy */
+}
+
+
+/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
+int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
+{
+	int	tmp;
+
+	while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
+
+	adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
+				MDIO_USERACCESS0_WRITE_READ |
+				((reg_num & 0x1f) << 21) |
+				((phy_addr & 0x1f) << 16);
+
+	/* Wait for command to complete */
+	while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;}
+
+	if (tmp & MDIO_USERACCESS0_ACK) {
+		*data = tmp & 0xffff;
+		return(1);
+	}
+
+	*data = -1;
+	return(0);
+}
+
+/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
+int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
+{
+
+	while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
+
+	adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
+				MDIO_USERACCESS0_WRITE_WRITE |
+				((reg_num & 0x1f) << 21) |
+				((phy_addr & 0x1f) << 16) |
+				(data & 0xffff);
+
+	/* Wait for command to complete */
+	while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
+
+	return(1);
+}
+
+/* PHY functions for a generic PHY */
+static int 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 gen_is_phy_connected(int phy_addr)
+{
+	u_int16_t	dummy;
+
+	return(dm644x_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy));
+}
+
+static int gen_get_link_speed(int phy_addr)
+{
+	u_int16_t	tmp;
+
+	if (dm644x_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04))
+		return(1);
+
+	return(0);
+}
+
+static int gen_auto_negotiate(int phy_addr)
+{
+	u_int16_t	tmp;
+
+
+	if (!dm644x_eth_phy_read(phy_addr, PHY_BMCR, &tmp))
+		return(0);
+
+	/* Restart Auto_negotiation  */
+	tmp |= PHY_BMCR_AUTON;
+	dm644x_eth_phy_write(phy_addr, PHY_BMCR, tmp);
+
+	/*check AutoNegotiate complete */
+	udelay (10000);
+	if (!dm644x_eth_phy_read(phy_addr, PHY_BMSR, &tmp))
+		return(0);
+
+	if (!(tmp & PHY_BMSR_AUTN_COMP))
+		return(0);
+
+	return(gen_get_link_speed(phy_addr));
+}
+/* End of generic PHY functions */
+
+
+
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+static int dm644x_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value)
+{
+	return(dm644x_eth_phy_read(addr, reg, value) ? 0 : 1);
+}
+
+static int dm644x_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value)
+{
+	return(dm644x_eth_phy_write(addr, reg, value) ? 0 : 1);
+}
+
+int dm644x_eth_miiphy_initialize(bd_t *bis)
+{
+	miiphy_register(phy.name, dm644x_mii_phy_read, dm644x_mii_phy_write);
+
+	return(1);
+}
+#endif
+
+/*
+ * 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.
+ */
+static int dm644x_eth_hw_init(void)
+{
+	u_int32_t	phy_id;
+	u_int16_t	tmp;
+	int		i;
+
+	dm644x_eth_mdio_enable();
+
+	for (i = 0; i < 256; i++) {
+		if (adap_mdio->ALIVE)
+			break;
+		udelay(10);
+	}
+
+	if (i >= 256) {
+		printf("No ETH PHY detected!!!\n");
+		return(0);
+	}
+
+	/* Find if a PHY is connected and get it's address */
+	if (!dm644x_eth_phy_detect())
+		return(0);
+
+	/* Get PHY ID and initialize phy_ops for a detected PHY */
+	if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) {
+		active_phy_addr = 0xff;
+		return(0);
+	}
+
+	phy_id = (tmp << 16) & 0xffff0000;
+
+	if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) {
+		active_phy_addr = 0xff;
+		return(0);
+	}
+
+	phy_id |= tmp & 0x0000ffff;
+
+	switch (phy_id) {
+		case PHY_LXT972:
+			sprintf(phy.name, "LXT972 @ 0x%02x", active_phy_addr);
+			phy.init = lxt972_init_phy;
+			phy.is_phy_connected = lxt972_is_phy_connected;
+			phy.get_link_speed = lxt972_get_link_speed;
+			phy.auto_negotiate = lxt972_auto_negotiate;
+			break;
+		case PHY_DP83848:
+			sprintf(phy.name, "DP83848 @ 0x%02x", active_phy_addr);
+			phy.init = dp83848_init_phy;
+			phy.is_phy_connected = dp83848_is_phy_connected;
+			phy.get_link_speed = dp83848_get_link_speed;
+			phy.auto_negotiate = dp83848_auto_negotiate;
+			break;
+		default:
+			sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr);
+			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;
+	}
+
+	return(1);
+}
+
+
+/* Eth device open */
+static int dm644x_eth_open(void)
+{
+	dv_reg_p		addr;
+	u_int32_t		clkdiv, cnt;
+	volatile emac_desc	*rx_desc;
+
+	debug_emac("+ emac_open\n");
+
+	/* Reset EMAC module and disable interrupts in wrapper */
+	adap_emac->SOFTRESET = 1;
+	while (adap_emac->SOFTRESET != 0) {;}
+	adap_ewrap->EWCTL = 0;
+	for (cnt = 0; cnt < 5; cnt++) {
+		clkdiv = adap_ewrap->EWCTL;
+	}
+
+	rx_desc = emac_rx_desc;
+
+	adap_emac->TXCONTROL = 0x01;
+	adap_emac->RXCONTROL = 0x01;
+
+	/* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */
+	/* Using channel 0 only - other channels are disabled */
+	adap_emac->MACINDEX = 0;
+	adap_emac->MACADDRHI =
+		(dm644x_eth_mac_addr[3] << 24) |
+		(dm644x_eth_mac_addr[2] << 16) |
+		(dm644x_eth_mac_addr[1] << 8)  |
+		(dm644x_eth_mac_addr[0]);
+	adap_emac->MACADDRLO =
+		(dm644x_eth_mac_addr[5] << 8) |
+		(dm644x_eth_mac_addr[4]);
+
+	adap_emac->MACHASH1 = 0;
+	adap_emac->MACHASH2 = 0;
+
+	/* Set source MAC address - REQUIRED */
+	adap_emac->MACSRCADDRHI =
+		(dm644x_eth_mac_addr[3] << 24) |
+		(dm644x_eth_mac_addr[2] << 16) |
+		(dm644x_eth_mac_addr[1] << 8)  |
+		(dm644x_eth_mac_addr[0]);
+	adap_emac->MACSRCADDRLO =
+		(dm644x_eth_mac_addr[4] << 8) |
+		(dm644x_eth_mac_addr[5]);
+
+	/* Set DMA 8 TX / 8 RX Head pointers to 0 */
+	addr = &adap_emac->TX0HDP;
+	for(cnt = 0; cnt < 16; cnt++)
+		*addr++ = 0;
+
+	addr = &adap_emac->RX0HDP;
+	for(cnt = 0; cnt < 16; cnt++)
+		*addr++ = 0;
+
+	/* Clear Statistics (do this before setting MacControl register) */
+	addr = &adap_emac->RXGOODFRAMES;
+	for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++)
+		*addr++ = 0;
+
+	/* No multicast addressing */
+	adap_emac->MACHASH1 = 0;
+	adap_emac->MACHASH2 = 0;
+
+	/* Create RX queue and set receive process in place */
+	emac_rx_active_head = emac_rx_desc;
+	for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
+		rx_desc->next = (u_int32_t)(rx_desc + 1);
+		rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
+		rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
+		rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
+		rx_desc++;
+	}
+
+	/* Set the last descriptor's "next" parameter to 0 to end the RX desc list */
+	rx_desc--;
+	rx_desc->next = 0;
+	emac_rx_active_tail = rx_desc;
+	emac_rx_queue_active = 1;
+
+	/* Enable TX/RX */
+	adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE;
+	adap_emac->RXBUFFEROFFSET = 0;
+
+	/* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */
+	adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN;
+
+	/* Enable ch 0 only */
+	adap_emac->RXUNICASTSET = 0x01;
+
+	/* Enable MII interface and Full duplex mode */
+	adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE);
+
+	/* Init MDIO & get link state */
+	clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
+	adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT);
+
+	if (!phy.get_link_speed(active_phy_addr))
+		return(0);
+
+	/* Start receive process */
+	adap_emac->RX0HDP = (u_int32_t)emac_rx_desc;
+
+	debug_emac("- emac_open\n");
+
+	return(1);
+}
+
+/* EMAC Channel Teardown */
+static void dm644x_eth_ch_teardown(int ch)
+{
+	dv_reg		dly = 0xff;
+	dv_reg		cnt;
+
+	debug_emac("+ emac_ch_teardown\n");
+
+	if (ch == EMAC_CH_TX) {
+		/* Init TX channel teardown */
+		adap_emac->TXTEARDOWN = 1;
+		for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) {
+			/* Wait here for Tx teardown completion interrupt to occur
+			 * Note: A task delay can be called here to pend rather than
+			 * occupying CPU cycles - anyway it has been found that teardown
+			 * takes very few cpu cycles and does not affect functionality */
+			 dly--;
+			 udelay(1);
+			 if (dly == 0)
+			 	break;
+		}
+		adap_emac->TX0CP = cnt;
+		adap_emac->TX0HDP = 0;
+	} else {
+		/* Init RX channel teardown */
+		adap_emac->RXTEARDOWN = 1;
+		for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) {
+			/* Wait here for Rx teardown completion interrupt to occur
+			 * Note: A task delay can be called here to pend rather than
+			 * occupying CPU cycles - anyway it has been found that teardown
+			 * takes very few cpu cycles and does not affect functionality */
+			 dly--;
+			 udelay(1);
+			 if (dly == 0)
+			 	break;
+		}
+		adap_emac->RX0CP = cnt;
+		adap_emac->RX0HDP = 0;
+	}
+
+	debug_emac("- emac_ch_teardown\n");
+}
+
+/* Eth device close */
+static int dm644x_eth_close(void)
+{
+	debug_emac("+ emac_close\n");
+
+	dm644x_eth_ch_teardown(EMAC_CH_TX);	/* TX Channel teardown */
+	dm644x_eth_ch_teardown(EMAC_CH_RX);	/* RX Channel teardown */
+
+	/* Reset EMAC module and disable interrupts in wrapper */
+	adap_emac->SOFTRESET = 1;
+	adap_ewrap->EWCTL = 0;
+
+	debug_emac("- emac_close\n");
+	return(1);
+}
+
+static int tx_send_loop = 0;
+
+/*
+ * This function sends a single packet on the network and returns
+ * positive number (number of bytes transmitted) or negative for error
+ */
+static int dm644x_eth_send_packet(volatile void *packet, int length)
+{
+	int ret_status = -1;
+	tx_send_loop = 0;
+
+	/* Return error if no link */
+	if (!phy.get_link_speed(active_phy_addr))
+	{
+		printf("WARN: emac_send_packet: No link\n");
+		return (ret_status);
+	}
+
+	/* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
+	if (length < EMAC_MIN_ETHERNET_PKT_SIZE)
+	{
+		length = EMAC_MIN_ETHERNET_PKT_SIZE;
+	}
+
+	/* Populate the TX descriptor */
+	emac_tx_desc->next         = 0;
+	emac_tx_desc->buffer       = (u_int8_t *)packet;
+	emac_tx_desc->buff_off_len = (length & 0xffff);
+	emac_tx_desc->pkt_flag_len = ((length & 0xffff) |
+			EMAC_CPPI_SOP_BIT |
+			EMAC_CPPI_OWNERSHIP_BIT |
+			EMAC_CPPI_EOP_BIT);
+	/* Send the packet */
+	adap_emac->TX0HDP = (unsigned int)emac_tx_desc;
+
+	/* Wait for packet to complete or link down */
+	while (1) {
+	        if (!phy.get_link_speed(active_phy_addr)) {
+	        	dm644x_eth_ch_teardown(EMAC_CH_TX);
+	        	return (ret_status);
+	        }
+	        if (adap_emac->TXINTSTATRAW & 0x01) {
+	        	ret_status = length;
+	        	break;
+		}
+	        tx_send_loop++;
+	}
+
+	return(ret_status);
+}
+
+/*
+ * This function handles receipt of a packet from the network
+ */
+static int dm644x_eth_rcv_packet(void)
+{
+	volatile emac_desc	*rx_curr_desc;
+	volatile emac_desc	*curr_desc;
+	volatile emac_desc	*tail_desc;
+	int			status, ret = -1;
+
+	rx_curr_desc = emac_rx_active_head;
+	status = rx_curr_desc->pkt_flag_len;
+	if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
+	        if (status & EMAC_CPPI_RX_ERROR_FRAME) {
+	        	/* Error in packet - discard it and requeue desc */
+	        	printf("WARN: emac_rcv_pkt: Error in packet\n");
+		} else {
+			NetReceive(rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff));
+			ret = rx_curr_desc->buff_off_len & 0xffff;
+	        }
+
+	        /* Ack received packet descriptor */
+	        adap_emac->RX0CP = (unsigned int)rx_curr_desc;
+	        curr_desc = rx_curr_desc;
+	        emac_rx_active_head = (volatile emac_desc *)rx_curr_desc->next;
+
+	        if (status & EMAC_CPPI_EOQ_BIT) {
+	        	if (emac_rx_active_head) {
+	        		adap_emac->RX0HDP = (unsigned int)emac_rx_active_head;
+			} else {
+				emac_rx_queue_active = 0;
+				printf("INFO:emac_rcv_packet: RX Queue not active\n");
+			}
+		}
+
+		/* Recycle RX descriptor */
+		rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
+		rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
+		rx_curr_desc->next = 0;
+
+		if (emac_rx_active_head == 0) {
+			printf("INFO: emac_rcv_pkt: active queue head = 0\n");
+			emac_rx_active_head = curr_desc;
+			emac_rx_active_tail = curr_desc;
+			if (emac_rx_queue_active != 0) {
+				adap_emac->RX0HDP = (unsigned int)emac_rx_active_head;
+				printf("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
+				emac_rx_queue_active = 1;
+			}
+		} else {
+			tail_desc = emac_rx_active_tail;
+			emac_rx_active_tail = curr_desc;
+			tail_desc->next = (unsigned int)curr_desc;
+			status = tail_desc->pkt_flag_len;
+			if (status & EMAC_CPPI_EOQ_BIT) {
+				adap_emac->RX0HDP = (unsigned int)curr_desc;
+				status &= ~EMAC_CPPI_EOQ_BIT;
+				tail_desc->pkt_flag_len = status;
+			}
+		}
+		return(ret);
+	}
+	return(0);
+}
+
+#endif /* CONFIG_CMD_NET */
+
+#endif /* CONFIG_DRIVER_TI_EMAC */
diff --git a/cpu/arm926ejs/davinci/i2c.c b/cpu/arm926ejs/davinci/i2c.c
new file mode 100644
index 0000000..af9dc03
--- /dev/null
+++ b/cpu/arm926ejs/davinci/i2c.c
@@ -0,0 +1,351 @@
+/*
+ * TI DaVinci (TMS320DM644x) I2C driver.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * --------------------------------------------------------
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DRIVER_DAVINCI_I2C
+
+#include <i2c.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/i2c_defs.h>
+
+#define CHECK_NACK() \
+	do {\
+		if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\
+			REG(I2C_CON) = 0;\
+			return(1);\
+		}\
+	} while (0)
+
+
+static int wait_for_bus(void)
+{
+	int	stat, timeout;
+
+	REG(I2C_STAT) = 0xffff;
+
+	for (timeout = 0; timeout < 10; timeout++) {
+		if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) {
+			REG(I2C_STAT) = 0xffff;
+			return(0);
+		}
+
+		REG(I2C_STAT) = stat;
+		udelay(50000);
+	}
+
+	REG(I2C_STAT) = 0xffff;
+	return(1);
+}
+
+
+static int poll_i2c_irq(int mask)
+{
+	int	stat, timeout;
+
+	for (timeout = 0; timeout < 10; timeout++) {
+		udelay(1000);
+		stat = REG(I2C_STAT);
+		if (stat & mask) {
+			return(stat);
+		}
+	}
+
+	REG(I2C_STAT) = 0xffff;
+	return(stat | I2C_TIMEOUT);
+}
+
+
+void flush_rx(void)
+{
+	int	dummy;
+
+	while (1) {
+		if (!(REG(I2C_STAT) & I2C_STAT_RRDY))
+			break;
+
+		dummy = REG(I2C_DRR);
+		REG(I2C_STAT) = I2C_STAT_RRDY;
+		udelay(1000);
+	}
+}
+
+
+void i2c_init(int speed, int slaveadd)
+{
+	u_int32_t	div, psc;
+
+	if (REG(I2C_CON) & I2C_CON_EN) {
+		REG(I2C_CON) = 0;
+		udelay (50000);
+	}
+
+	psc = 2;
+	div = (CFG_HZ_CLOCK / ((psc + 1) * speed)) - 10;	/* SCLL + SCLH */
+	REG(I2C_PSC) = psc;			/* 27MHz / (2 + 1) = 9MHz */
+	REG(I2C_SCLL) = (div * 50) / 100;	/* 50% Duty */
+	REG(I2C_SCLH) = div - REG(I2C_SCLL);
+
+	REG(I2C_OA) = slaveadd;
+	REG(I2C_CNT) = 0;
+
+	/* Interrupts must be enabled or I2C module won't work */
+	REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE |
+		I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE;
+
+	/* Now enable I2C controller (get it out of reset) */
+	REG(I2C_CON) = I2C_CON_EN;
+
+	udelay(1000);
+}
+
+
+int i2c_probe(u_int8_t chip)
+{
+	int	rc = 1;
+
+	if (chip == REG(I2C_OA)) {
+		return(rc);
+	}
+
+	REG(I2C_CON) = 0;
+	if (wait_for_bus()) {return(1);}
+
+	/* try to read one byte from current (or only) address */
+	REG(I2C_CNT) = 1;
+	REG(I2C_SA) = chip;
+	REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP);
+	udelay (50000);
+
+	if (!(REG(I2C_STAT) & I2C_STAT_NACK)) {
+		rc = 0;
+		flush_rx();
+		REG(I2C_STAT) = 0xffff;
+	} else {
+		REG(I2C_STAT) = 0xffff;
+		REG(I2C_CON) |= I2C_CON_STP;
+		udelay(20000);
+		if (wait_for_bus()) {return(1);}
+	}
+
+	flush_rx();
+	REG(I2C_STAT) = 0xffff;
+	REG(I2C_CNT) = 0;
+	return(rc);
+}
+
+
+int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
+{
+	u_int32_t	tmp;
+	int		i;
+
+	if ((alen < 0) || (alen > 2)) {
+		printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
+		return(1);
+	}
+
+	if (wait_for_bus()) {return(1);}
+
+	if (alen != 0) {
+		/* Start address phase */
+		tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX;
+		REG(I2C_CNT) = alen;
+		REG(I2C_SA) = chip;
+		REG(I2C_CON) = tmp;
+
+		tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+		CHECK_NACK();
+
+		switch (alen) {
+			case 2:
+				/* Send address MSByte */
+				if (tmp & I2C_STAT_XRDY) {
+					REG(I2C_DXR) = (addr >> 8) & 0xff;
+				} else {
+					REG(I2C_CON) = 0;
+					return(1);
+				}
+
+				tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+				CHECK_NACK();
+				/* No break, fall through */
+			case 1:
+				/* Send address LSByte */
+				if (tmp & I2C_STAT_XRDY) {
+					REG(I2C_DXR) = addr & 0xff;
+				} else {
+					REG(I2C_CON) = 0;
+					return(1);
+				}
+
+				tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY);
+
+				CHECK_NACK();
+
+				if (!(tmp & I2C_STAT_ARDY)) {
+					REG(I2C_CON) = 0;
+					return(1);
+				}
+		}
+	}
+
+	/* Address phase is over, now read 'len' bytes and stop */
+	tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP;
+	REG(I2C_CNT) = len & 0xffff;
+	REG(I2C_SA) = chip;
+	REG(I2C_CON) = tmp;
+
+	for (i = 0; i < len; i++) {
+		tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR);
+
+		CHECK_NACK();
+
+		if (tmp & I2C_STAT_RRDY) {
+			buf[i] = REG(I2C_DRR);
+		} else {
+			REG(I2C_CON) = 0;
+			return(1);
+		}
+	}
+
+	tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
+
+	CHECK_NACK();
+
+	if (!(tmp & I2C_STAT_SCD)) {
+		REG(I2C_CON) = 0;
+		return(1);
+	}
+
+	flush_rx();
+	REG(I2C_STAT) = 0xffff;
+	REG(I2C_CNT) = 0;
+	REG(I2C_CON) = 0;
+
+	return(0);
+}
+
+
+int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
+{
+	u_int32_t	tmp;
+	int		i;
+
+	if ((alen < 0) || (alen > 2)) {
+		printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
+		return(1);
+	}
+	if (len < 0) {
+		printf("%s(): bogus length %x\n", __FUNCTION__, len);
+		return(1);
+	}
+
+	if (wait_for_bus()) {return(1);}
+
+	/* Start address phase */
+	tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP;
+	REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen;
+	REG(I2C_SA) = chip;
+	REG(I2C_CON) = tmp;
+
+	switch (alen) {
+		case 2:
+			/* Send address MSByte */
+			tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+			CHECK_NACK();
+
+			if (tmp & I2C_STAT_XRDY) {
+				REG(I2C_DXR) = (addr >> 8) & 0xff;
+			} else {
+				REG(I2C_CON) = 0;
+				return(1);
+			}
+			/* No break, fall through */
+		case 1:
+			/* Send address LSByte */
+			tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+			CHECK_NACK();
+
+			if (tmp & I2C_STAT_XRDY) {
+				REG(I2C_DXR) = addr & 0xff;
+			} else {
+				REG(I2C_CON) = 0;
+				return(1);
+			}
+	}
+
+	for (i = 0; i < len; i++) {
+		tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
+
+		CHECK_NACK();
+
+		if (tmp & I2C_STAT_XRDY) {
+			REG(I2C_DXR) = buf[i];
+		} else {
+			return(1);
+		}
+	}
+
+	tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
+
+	CHECK_NACK();
+
+	if (!(tmp & I2C_STAT_SCD)) {
+		REG(I2C_CON) = 0;
+		return(1);
+	}
+
+	flush_rx();
+	REG(I2C_STAT) = 0xffff;
+	REG(I2C_CNT) = 0;
+	REG(I2C_CON) = 0;
+
+	return(0);
+}
+
+
+u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg)
+{
+	u_int8_t	tmp;
+
+	i2c_read(chip, reg, 1, &tmp, 1);
+	return(tmp);
+}
+
+
+void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val)
+{
+	u_int8_t	tmp;
+
+	i2c_write(chip, reg, 1, &tmp, 1);
+}
+
+#endif /* CONFIG_DRIVER_DAVINCI_I2C */
diff --git a/cpu/arm926ejs/davinci/lowlevel_init.S b/cpu/arm926ejs/davinci/lowlevel_init.S
new file mode 100644
index 0000000..bbc48ec
--- /dev/null
+++ b/cpu/arm926ejs/davinci/lowlevel_init.S
@@ -0,0 +1,707 @@
+/*
+ * Low-level board setup code for TI DaVinci SoC based boards.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * Partially based on TI sources, original copyrights follow:
+ */
+
+/*
+ * Board specific setup info
+ *
+ * (C) Copyright 2003
+ * Texas Instruments, <www.ti.com>
+ * Kshitij Gupta <Kshitij@ti.com>
+ *
+ * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004
+ *
+ * Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Modified for DV-EVM board by Swaminathan S, Nov 2005
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+.globl	lowlevel_init
+lowlevel_init:
+
+	/*-------------------------------------------------------*
+	 * Mask all IRQs by setting all bits in the EINT default *
+	 *-------------------------------------------------------*/
+	mov	r1, $0
+	ldr	r0, =EINT_ENABLE0
+	str	r1, [r0]
+	ldr	r0, =EINT_ENABLE1
+	str	r1, [r0]
+
+	/*------------------------------------------------------*
+	 * Put the GEM in reset					*
+	 *------------------------------------------------------*/
+
+	/* Put the GEM in reset */
+	ldr	r8, PSC_GEM_FLAG_CLEAR
+	ldr	r6, MDCTL_GEM
+	ldr	r7, [r6]
+	and	r7, r7, r8
+	str	r7, [r6]
+
+	/* Enable the Power Domain Transition Command */
+	ldr	r6, PTCMD
+	ldr	r7, [r6]
+	orr	r7, r7, $0x02
+	str	r7, [r6]
+
+	/* Check for Transition Complete(PTSTAT) */
+checkStatClkStopGem:
+	ldr	r6, PTSTAT
+	ldr	r7, [r6]
+	ands	r7, r7, $0x02
+	bne	checkStatClkStopGem
+
+	/* Check for GEM Reset Completion */
+checkGemStatClkStop:
+	ldr	r6, MDSTAT_GEM
+	ldr	r7, [r6]
+	ands	r7, r7, $0x100
+	bne	checkGemStatClkStop
+
+	/* Do this for enabling a WDT initiated reset this is a workaround
+	   for a chip bug.  Not required under normal situations */
+	ldr	r6, P1394
+	mov	r10, $0
+	str	r10, [r6]
+
+	/*------------------------------------------------------*
+	 * Enable L1 & L2 Memories in Fast mode                 *
+	 *------------------------------------------------------*/
+	ldr	r6, DFT_ENABLE
+	mov	r10, $0x01
+	str	r10, [r6]
+
+	ldr	r6, MMARG_BRF0
+	ldr	r10, MMARG_BRF0_VAL
+	str	r10, [r6]
+
+	ldr	r6, DFT_ENABLE
+	mov	r10, $0
+	str	r10, [r6]
+
+	/*------------------------------------------------------*
+	 * DDR2 PLL Initialization			    	*
+	 *------------------------------------------------------*/
+
+	/* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */
+	mov	r10, $0
+	ldr	r6, PLL2_CTL
+	ldr	r7, PLL_CLKSRC_MASK
+	ldr	r8, [r6]
+	and	r8, r8, r7
+	mov	r9, r10, lsl $8
+	orr	r8, r8, r9
+	str	r8, [r6]
+
+	/* Select the PLLEN source */
+	ldr	r7, PLL_ENSRC_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Bypass the PLL */
+	ldr	r7, PLL_BYPASS_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */
+	mov	r10, $0x20
+WaitPPL2Loop:
+	subs	r10, r10, $1
+	bne	WaitPPL2Loop
+
+	/* Reset the PLL */
+	ldr	r7, PLL_RESET_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Power up the PLL */
+	ldr	r7, PLL_PWRUP_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Enable the PLL from Disable Mode */
+	ldr	r7, PLL_DISABLE_ENABLE_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Program the PLL Multiplier */
+	ldr	r6, PLL2_PLLM
+	mov	r2, $0x17	/* 162 MHz */
+	str	r2, [r6]
+
+	/* Program the PLL2 Divisor Value */
+	ldr	r6, PLL2_DIV2
+	mov	r3, $0x01
+	str	r3, [r6]
+
+	/* Program the PLL2 Divisor Value */
+	ldr	r6, PLL2_DIV1
+	mov	r4, $0x0b	/* 54 MHz */
+	str	r4, [r6]
+
+	/* PLL2 DIV2 MMR */
+	ldr	r8, PLL2_DIV_MASK
+	ldr	r6, PLL2_DIV2
+	ldr	r9, [r6]
+	and	r8, r8, r9
+	mov	r9, $0x01
+	mov	r9, r9, lsl $15
+	orr	r8, r8, r9
+	str	r8, [r6]
+
+	/* Program the GOSET bit to take new divider values */
+	ldr	r6, PLL2_PLLCMD
+	ldr	r7, [r6]
+	orr	r7, r7, $0x01
+	str	r7, [r6]
+
+	/* Wait for Done */
+	ldr	r6, PLL2_PLLSTAT
+doneLoop_0:
+	ldr	r7, [r6]
+	ands	r7, r7, $0x01
+	bne	doneLoop_0
+
+	/* PLL2 DIV1 MMR */
+	ldr	r8, PLL2_DIV_MASK
+	ldr	r6, PLL2_DIV1
+	ldr	r9, [r6]
+	and	r8, r8, r9
+	mov	r9, $0x01
+	mov	r9, r9, lsl $15
+	orr	r8, r8, r9
+	str	r8, [r6]
+
+	/* Program the GOSET bit to take new divider values */
+	ldr	r6, PLL2_PLLCMD
+	ldr	r7, [r6]
+	orr	r7, r7, $0x01
+	str	r7, [r6]
+
+	/* Wait for Done */
+	ldr	r6, PLL2_PLLSTAT
+doneLoop:
+	ldr	r7, [r6]
+	ands	r7, r7, $0x01
+	bne	doneLoop
+
+	/* Wait for PLL to Reset Properly */
+	mov	r10, $0x218
+ResetPPL2Loop:
+	subs	r10, r10, $1
+	bne	ResetPPL2Loop
+
+	/* Bring PLL out of Reset */
+	ldr	r6, PLL2_CTL
+	ldr	r8, [r6]
+	orr	r8, r8, $0x08
+	str	r8, [r6]
+
+	/* Wait for PLL to Lock */
+	ldr	r10, PLL_LOCK_COUNT
+PLL2Lock:
+	subs	r10, r10, $1
+	bne	PLL2Lock
+
+	/* Enable the PLL */
+	ldr	r6, PLL2_CTL
+	ldr	r8, [r6]
+	orr	r8, r8, $0x01
+	str	r8, [r6]
+
+	/*------------------------------------------------------*
+	 * Issue Soft Reset to DDR Module			*
+	 *------------------------------------------------------*/
+
+	/* Shut down the DDR2 LPSC Module */
+	ldr	r8, PSC_FLAG_CLEAR
+	ldr	r6, MDCTL_DDR2
+	ldr	r7, [r6]
+	and	r7, r7, r8
+	orr	r7, r7, $0x03
+	str	r7, [r6]
+
+	/* Enable the Power Domain Transition Command */
+	ldr	r6, PTCMD
+	ldr	r7, [r6]
+	orr	r7, r7, $0x01
+	str	r7, [r6]
+
+	/* Check for Transition Complete(PTSTAT) */
+checkStatClkStop:
+	ldr	r6, PTSTAT
+	ldr	r7, [r6]
+	ands	r7, r7, $0x01
+	bne	checkStatClkStop
+
+	/* Check for DDR2 Controller Enable Completion */
+checkDDRStatClkStop:
+	ldr	r6, MDSTAT_DDR2
+	ldr	r7, [r6]
+	and	r7, r7, $0x1f
+	cmp	r7, $0x03
+	bne	checkDDRStatClkStop
+
+	/*------------------------------------------------------*
+	 * Program DDR2 MMRs for 162MHz Setting			*
+	 *------------------------------------------------------*/
+
+	/* Program PHY Control Register */
+	ldr	r6, DDRCTL
+	ldr	r7, DDRCTL_VAL
+	str	r7, [r6]
+
+	/* Program SDRAM Bank Config Register */
+	ldr	r6, SDCFG
+	ldr	r7, SDCFG_VAL
+	str	r7, [r6]
+
+	/* Program SDRAM TIM-0 Config Register */
+	ldr	r6, SDTIM0
+	ldr	r7, SDTIM0_VAL_162MHz
+	str	r7, [r6]
+
+	/* Program SDRAM TIM-1 Config Register */
+	ldr	r6, SDTIM1
+	ldr	r7, SDTIM1_VAL_162MHz
+	str	r7, [r6]
+
+	/* Program the SDRAM Bank Config Control Register */
+	ldr	r10, MASK_VAL
+	ldr	r8, SDCFG
+	ldr	r9, SDCFG_VAL
+	and	r9, r9, r10
+	str	r9, [r8]
+
+	/* Program SDRAM SDREF Config Register */
+	ldr	r6, SDREF
+	ldr	r7, SDREF_VAL
+	str	r7, [r6]
+
+	/*------------------------------------------------------*
+	 * Issue Soft Reset to DDR Module			*
+	 *------------------------------------------------------*/
+
+	/* Issue a Dummy DDR2 read/write */
+	ldr	r8, DDR2_START_ADDR
+	ldr	r7, DUMMY_VAL
+	str	r7, [r8]
+	ldr	r7, [r8]
+
+	/* Shut down the DDR2 LPSC Module */
+	ldr	r8, PSC_FLAG_CLEAR
+	ldr	r6, MDCTL_DDR2
+	ldr	r7, [r6]
+	and	r7, r7, r8
+	orr	r7, r7, $0x01
+	str	r7, [r6]
+
+	/* Enable the Power Domain Transition Command */
+	ldr	r6, PTCMD
+	ldr	r7, [r6]
+	orr	r7, r7, $0x01
+	str	r7, [r6]
+
+	/* Check for Transition Complete(PTSTAT) */
+checkStatClkStop2:
+	ldr	r6, PTSTAT
+	ldr	r7, [r6]
+	ands	r7, r7, $0x01
+	bne	checkStatClkStop2
+
+	/* Check for DDR2 Controller Enable Completion */
+checkDDRStatClkStop2:
+	ldr	r6, MDSTAT_DDR2
+	ldr	r7, [r6]
+	and	r7, r7, $0x1f
+	cmp	r7, $0x01
+	bne	checkDDRStatClkStop2
+
+	/*------------------------------------------------------*
+	 * Turn DDR2 Controller Clocks On			*
+	 *------------------------------------------------------*/
+
+	/* Enable the DDR2 LPSC Module */
+	ldr	r6, MDCTL_DDR2
+	ldr	r7, [r6]
+	orr	r7, r7, $0x03
+	str	r7, [r6]
+
+	/* Enable the Power Domain Transition Command */
+	ldr	r6, PTCMD
+	ldr	r7, [r6]
+	orr	r7, r7, $0x01
+	str	r7, [r6]
+
+	/* Check for Transition Complete(PTSTAT) */
+checkStatClkEn2:
+	ldr	r6, PTSTAT
+	ldr	r7, [r6]
+	ands	r7, r7, $0x01
+	bne	checkStatClkEn2
+
+	/* Check for DDR2 Controller Enable Completion */
+checkDDRStatClkEn2:
+	ldr	r6, MDSTAT_DDR2
+	ldr	r7, [r6]
+	and	r7, r7, $0x1f
+	cmp	r7, $0x03
+	bne	checkDDRStatClkEn2
+
+	/*  DDR Writes and Reads */
+	ldr	r6, CFGTEST
+	mov	r3, $0x01
+	str	r3, [r6]
+
+	/*------------------------------------------------------*
+	 * System PLL Initialization				*
+	 *------------------------------------------------------*/
+
+	/* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */
+	mov	r2, $0
+	ldr	r6, PLL1_CTL
+	ldr	r7, PLL_CLKSRC_MASK
+	ldr	r8, [r6]
+	and	r8, r8, r7
+	mov	r9, r2, lsl $8
+	orr	r8, r8, r9
+	str	r8, [r6]
+
+	/* Select the PLLEN source */
+	ldr	r7, PLL_ENSRC_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Bypass the PLL */
+	ldr	r7, PLL_BYPASS_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */
+	mov	r10, $0x20
+
+WaitLoop:
+	subs	r10, r10, $1
+	bne	WaitLoop
+
+	/* Reset the PLL */
+	ldr	r7, PLL_RESET_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Disable the PLL */
+	orr	r8, r8, $0x10
+	str	r8, [r6]
+
+	/* Power up the PLL */
+	ldr	r7, PLL_PWRUP_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Enable the PLL from Disable Mode */
+	ldr	r7, PLL_DISABLE_ENABLE_MASK
+	and	r8, r8, r7
+	str	r8, [r6]
+
+	/* Program the PLL Multiplier */
+	ldr	r6, PLL1_PLLM
+	mov	r3, $0x15	/* For 594MHz */
+	str	r3, [r6]
+
+	/* Wait for PLL to Reset Properly */
+	mov	r10, $0xff
+
+ResetLoop:
+	subs	r10, r10, $1
+	bne	ResetLoop
+
+	/* Bring PLL out of Reset */
+	ldr	r6, PLL1_CTL
+	orr	r8, r8, $0x08
+	str	r8, [r6]
+
+	/* Wait for PLL to Lock */
+	ldr	r10, PLL_LOCK_COUNT
+
+PLL1Lock:
+	subs	r10, r10, $1
+	bne	PLL1Lock
+
+	/* Enable the PLL */
+	orr	r8, r8, $0x01
+	str	r8, [r6]
+
+	nop
+	nop
+	nop
+	nop
+
+	/*------------------------------------------------------*
+	 * AEMIF configuration for NOR Flash (double check)     *
+	 *------------------------------------------------------*/
+	ldr	r0, _PINMUX0
+	ldr	r1, _DEV_SETTING
+	str	r1, [r0]
+
+	ldr	r0, WAITCFG
+	ldr	r1, WAITCFG_VAL
+	ldr	r2, [r0]
+	orr	r2, r2, r1
+	str	r2, [r0]
+
+	ldr	r0, ACFG3
+	ldr	r1, ACFG3_VAL
+	ldr	r2, [r0]
+	and	r1, r2, r1
+	str	r1, [r0]
+
+	ldr	r0, ACFG4
+	ldr	r1, ACFG4_VAL
+	ldr	r2, [r0]
+	and	r1, r2, r1
+	str	r1, [r0]
+
+	ldr	r0, ACFG5
+	ldr	r1, ACFG5_VAL
+	ldr	r2, [r0]
+	and	r1, r2, r1
+	str	r1, [r0]
+
+	/*--------------------------------------*
+	 * VTP manual Calibration               *
+	 *--------------------------------------*/
+	ldr	r0, VTPIOCR
+	ldr	r1, VTP_MMR0
+	str	r1, [r0]
+
+	ldr	r0, VTPIOCR
+	ldr	r1, VTP_MMR1
+	str	r1, [r0]
+
+	/* Wait for 33 VTP CLK cycles.  VRP operates at 27 MHz */
+	ldr	r10, VTP_LOCK_COUNT
+VTPLock:
+	subs	r10, r10, $1
+	bne	VTPLock
+
+	ldr	r6, DFT_ENABLE
+	mov	r10, $0x01
+	str	r10, [r6]
+
+	ldr	r6, DDRVTPR
+	ldr	r7, [r6]
+	and	r7, r7, $0x1f
+	and	r8, r7, $0x3e0
+	orr	r8, r7, r8
+	ldr	r7, VTP_RECAL
+	orr	r8, r7, r8
+	ldr	r7, VTP_EN
+	orr	r8, r7, r8
+	str	r8, [r0]
+
+
+	/* Wait for 33 VTP CLK cycles.  VRP operates at 27 MHz */
+	ldr	r10, VTP_LOCK_COUNT
+VTP1Lock:
+	subs	r10, r10, $1
+	bne	VTP1Lock
+
+	ldr	r1, [r0]
+	ldr	r2, VTP_MASK
+	and	r2, r1, r2
+	str	r2, [r0]
+
+	ldr	r6, DFT_ENABLE
+	mov	r10, $0
+	str	r10, [r6]
+
+	/* 
+	 * Call board-specific lowlevel init.
+ 	 * That MUST be present and THAT returns
+	 * back to arch calling code with "mov pc, lr."
+	 */
+	b	dv_board_init
+
+.ltorg
+
+_PINMUX0:
+	.word	0x01c40000		/* Device Configuration Registers */
+_PINMUX1:
+	.word	0x01c40004		/* Device Configuration Registers */
+
+_DEV_SETTING:
+	.word	0x00000c1f
+
+WAITCFG:
+	.word	0x01e00004
+WAITCFG_VAL:
+	.word	0
+ACFG3:
+	.word	0x01e00014
+ACFG3_VAL:
+	.word	0x3ffffffd
+ACFG4:
+	.word	0x01e00018
+ACFG4_VAL:
+	.word	0x3ffffffd
+ACFG5:
+	.word	0x01e0001c
+ACFG5_VAL:
+	.word	0x3ffffffd
+
+MDCTL_DDR2:
+	.word	0x01c41a34
+MDSTAT_DDR2:
+	.word	0x01c41834
+
+PTCMD:
+	.word	0x01c41120
+PTSTAT:
+	.word	0x01c41128
+
+EINT_ENABLE0:
+	.word	0x01c48018
+EINT_ENABLE1:
+	.word	0x01c4801c
+
+PSC_FLAG_CLEAR:
+	.word	0xffffffe0
+PSC_GEM_FLAG_CLEAR:
+	.word	0xfffffeff
+
+/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */
+DDRCTL:
+	.word	0x200000e4
+DDRCTL_VAL:
+	.word	0x50006405
+SDREF:
+	.word	0x2000000c
+SDREF_VAL:
+	.word	0x000005c3
+SDCFG:
+	.word	0x20000008
+SDCFG_VAL:
+#ifdef	DDR_4BANKS
+	.word	0x00178622
+#elif defined DDR_8BANKS
+	.word	0x00178632
+#else
+#error "Unknown DDR configuration!!!"
+#endif
+SDTIM0:
+	.word	0x20000010
+SDTIM0_VAL_162MHz:
+	.word	0x28923211
+SDTIM1:
+	.word	0x20000014
+SDTIM1_VAL_162MHz:
+	.word	0x0016c722
+VTPIOCR:
+	.word	0x200000f0	/* VTP IO Control register */
+DDRVTPR:
+	.word	0x01c42030	/* DDR VPTR MMR */
+VTP_MMR0:
+	.word	0x201f
+VTP_MMR1:
+	.word	0xa01f
+DFT_ENABLE:
+	.word	0x01c4004c
+VTP_LOCK_COUNT:
+	.word	0x5b0
+VTP_MASK:
+	.word	0xffffdfff
+VTP_RECAL:
+	.word	0x40000
+VTP_EN:
+	.word	0x02000
+CFGTEST:
+	.word	0x80010000
+MASK_VAL:
+	.word	0x00000fff
+
+/* GEM Power Up & LPSC Control Register */
+MDCTL_GEM:
+	.word	0x01c41a9c
+MDSTAT_GEM:
+	.word	0x01c4189c
+
+/* For WDT reset chip bug */
+P1394:
+	.word	0x01c41a20
+
+PLL_CLKSRC_MASK:
+	.word	0xfffffeff	/* Mask the Clock Mode bit */
+PLL_ENSRC_MASK:
+	.word	0xffffffdf	/* Select the PLLEN source */
+PLL_BYPASS_MASK:
+	.word	0xfffffffe	/* Put the PLL in BYPASS */
+PLL_RESET_MASK:
+	.word	0xfffffff7	/* Put the PLL in Reset Mode */
+PLL_PWRUP_MASK:
+	.word	0xfffffffd	/* PLL Power up Mask Bit  */
+PLL_DISABLE_ENABLE_MASK:
+	.word	0xffffffef	/* Enable the PLL from Disable */
+PLL_LOCK_COUNT:
+	.word	0x2000
+
+/* PLL1-SYSTEM PLL MMRs */
+PLL1_CTL:
+	.word	0x01c40900
+PLL1_PLLM:
+	.word	0x01c40910
+
+/* PLL2-SYSTEM PLL MMRs */
+PLL2_CTL:
+	.word	0x01c40d00
+PLL2_PLLM:
+	.word	0x01c40d10
+PLL2_DIV1:
+	.word	0x01c40d18
+PLL2_DIV2:
+	.word	0x01c40d1c
+PLL2_PLLCMD:
+	.word	0x01c40d38
+PLL2_PLLSTAT:
+	.word	0x01c40d3c
+PLL2_DIV_MASK:
+	.word	0xffff7fff
+
+MMARG_BRF0:
+	.word	0x01c42010	/* BRF margin mode 0 (R/W)*/
+MMARG_BRF0_VAL:
+	.word	0x00444400
+
+DDR2_START_ADDR:
+	.word	0x80000000
+DUMMY_VAL:
+	.word	0xa55aa55a
diff --git a/cpu/arm926ejs/davinci/lxt972.c b/cpu/arm926ejs/davinci/lxt972.c
new file mode 100644
index 0000000..6eeb6e5
--- /dev/null
+++ b/cpu/arm926ejs/davinci/lxt972.c
@@ -0,0 +1,142 @@
+/*
+ * Intel LXT971/LXT972 PHY Driver for TI DaVinci
+ * (TMS320DM644x) based boards.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * --------------------------------------------------------
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <net.h>
+#include <lxt971a.h>
+#include <asm/arch/emac_defs.h>
+
+#ifdef CONFIG_DRIVER_TI_EMAC
+
+#ifdef CONFIG_CMD_NET
+
+int lxt972_is_phy_connected(int phy_addr)
+{
+	u_int16_t	id1, id2;
+
+	if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID1, &id1))
+		return(0);
+	if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID2, &id2))
+		return(0);
+
+	if ((id1 == (0x0013)) && ((id2  & 0xfff0) == 0x78e0))
+		return(1);
+
+	return(0);
+}
+
+int lxt972_get_link_speed(int phy_addr)
+{
+	u_int16_t		stat1, tmp;
+	volatile emac_regs*	emac = (emac_regs *)EMAC_BASE_ADDR;
+
+	if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_STAT2, &stat1))
+		return(0);
+
+	if (!(stat1 & PHY_LXT971_STAT2_LINK))	/* link up? */
+		return(0);
+
+	if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
+		return(0);
+
+	tmp |= PHY_LXT971_DIG_CFG_MII_DRIVE;
+
+	dm644x_eth_phy_write(phy_addr, PHY_LXT971_DIG_CFG, tmp);
+	/* Read back */
+	if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp))
+		return(0);
+
+
+	/* Speed doesn't matter, there is no setting for it in EMAC... */
+	if (stat1 & PHY_LXT971_STAT2_100BTX) {
+		if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
+			/* set DM644x EMAC for Full Duplex  */
+			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+		} else {
+			/*set DM644x EMAC for Half Duplex  */
+			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
+		}
+
+		return(1);
+	} else {
+		if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) {
+			/* set DM644x EMAC for Full Duplex  */
+			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
+		} else {
+			/*set DM644x EMAC for Half Duplex  */
+			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE;
+		}
+
+		return(1);
+	}
+
+	return(0);
+}
+
+
+int lxt972_init_phy(int phy_addr)
+{
+	int	ret = 1;
+
+	if (!lxt972_get_link_speed(phy_addr)) {
+		/* Try another time */
+		ret = lxt972_get_link_speed(phy_addr);
+	}
+
+	/* Disable PHY Interrupts */
+	dm644x_eth_phy_write(phy_addr, PHY_LXT971_INT_ENABLE, 0);
+
+	return(ret);
+}
+
+
+int lxt972_auto_negotiate(int phy_addr)
+{
+	u_int16_t	tmp;
+
+
+	if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_CTRL, &tmp))
+		return(0);
+
+	/* Restart Auto_negotiation  */
+	tmp |= PHY_COMMON_CTRL_RES_AUTO;
+	dm644x_eth_phy_write(phy_addr, PHY_COMMON_CTRL, tmp);
+
+	/*check AutoNegotiate complete */
+	udelay (10000);
+	if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_STAT, &tmp))
+		return(0);
+
+	if (!(tmp & PHY_COMMON_STAT_AN_COMP))
+		return(0);
+
+	return (lxt972_get_link_speed(phy_addr));
+}
+
+#endif	/* CONFIG_CMD_NET */
+
+#endif	/* CONFIG_DRIVER_ETHER */
diff --git a/cpu/arm926ejs/davinci/nand.c b/cpu/arm926ejs/davinci/nand.c
new file mode 100644
index 0000000..127be9f
--- /dev/null
+++ b/cpu/arm926ejs/davinci/nand.c
@@ -0,0 +1,389 @@
+/*
+ * NAND driver for TI DaVinci based boards.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * Based on Linux DaVinci NAND driver by TI. Original copyright follows:
+ */
+
+/*
+ *
+ * linux/drivers/mtd/nand/nand_davinci.c
+ *
+ * NAND Flash Driver
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   DaVinci board which utilizes the Samsung k9k2g08 part.
+ *
+ Modifications:
+ ver. 1.0: Feb 2005, Vinod/Sudhakar
+ -
+ *
+ */
+
+#include <common.h>
+
+#ifdef CFG_USE_NAND
+#if !defined(CFG_NAND_LEGACY)
+
+#include <nand.h>
+#include <asm/arch/nand_defs.h>
+#include <asm/arch/emif_defs.h>
+
+extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
+
+static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+	struct		nand_chip *this = mtd->priv;
+	u_int32_t	IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
+
+	IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
+
+	switch (cmd) {
+		case NAND_CTL_SETCLE:
+			IO_ADDR_W |= MASK_CLE;
+			break;
+		case NAND_CTL_SETALE:
+			IO_ADDR_W |= MASK_ALE;
+			break;
+	}
+
+	this->IO_ADDR_W = (void *)IO_ADDR_W;
+}
+
+/* Set WP on deselect, write enable on select */
+static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
+{
+#define GPIO_SET_DATA01	0x01c67018
+#define GPIO_CLR_DATA01	0x01c6701c
+#define GPIO_NAND_WP	(1 << 4)
+#ifdef SONATA_BOARD_GPIOWP
+	if (chip < 0) {
+		REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP;
+	} else {
+		REG(GPIO_SET_DATA01) |= GPIO_NAND_WP;
+	}
+#endif
+}
+
+#ifdef CFG_NAND_HW_ECC
+#ifdef CFG_NAND_LARGEPAGE
+static struct nand_oobinfo davinci_nand_oobinfo = {
+	.useecc = MTD_NANDECC_AUTOPLACE,
+	.eccbytes = 12,
+	.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
+	.oobfree = { {2, 6}, {12, 12}, {28, 12}, {44, 12}, {60, 4} }
+};
+#elif defined(CFG_NAND_SMALLPAGE)
+static struct nand_oobinfo davinci_nand_oobinfo = {
+	.useecc = MTD_NANDECC_AUTOPLACE,
+	.eccbytes = 3,
+	.eccpos = {0, 1, 2},
+	.oobfree = { {6, 2}, {8, 8} }
+};
+#else
+#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
+#endif
+
+static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	emifregs	emif_addr;
+	int		dummy;
+
+	emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+
+	dummy = emif_addr->NANDF1ECC;
+	dummy = emif_addr->NANDF2ECC;
+	dummy = emif_addr->NANDF3ECC;
+	dummy = emif_addr->NANDF4ECC;
+
+	emif_addr->NANDFCR |= (1 << 8);
+}
+
+static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
+{
+	u_int32_t	ecc = 0;
+	emifregs	emif_base_addr;
+
+	emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+
+	if (region == 1)
+		ecc = emif_base_addr->NANDF1ECC;
+	else if (region == 2)
+		ecc = emif_base_addr->NANDF2ECC;
+	else if (region == 3)
+		ecc = emif_base_addr->NANDF3ECC;
+	else if (region == 4)
+		ecc = emif_base_addr->NANDF4ECC;
+
+	return(ecc);
+}
+
+static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+{
+	u_int32_t		tmp;
+	int			region, n;
+	struct nand_chip	*this = mtd->priv;
+
+	n = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
+
+	region = 1;
+	while (n--) {
+		tmp = nand_davinci_readecc(mtd, region);
+		*ecc_code++ = tmp;
+		*ecc_code++ = tmp >> 16;
+		*ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0);
+		region++;
+	}
+	return(0);
+}
+
+static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf)
+{
+	u_int32_t	tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8);
+
+	ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
+	ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
+	ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
+}
+
+static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data)
+{
+	u_int32_t	i;
+	u_int8_t	tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
+	u_int8_t	comp0_bit[8], comp1_bit[8], comp2_bit[8];
+	u_int8_t	ecc_bit[24];
+	u_int8_t	ecc_sum = 0;
+	u_int8_t	find_bit = 0;
+	u_int32_t	find_byte = 0;
+	int		is_ecc_ff;
+
+	is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff));
+
+	nand_davinci_gen_true_ecc(ecc_nand);
+	nand_davinci_gen_true_ecc(ecc_calc);
+
+	for (i = 0; i <= 2; i++) {
+		*(ecc_nand + i) = ~(*(ecc_nand + i));
+		*(ecc_calc + i) = ~(*(ecc_calc + i));
+	}
+
+	for (i = 0; i < 8; i++) {
+		tmp0_bit[i] = *ecc_nand % 2;
+		*ecc_nand = *ecc_nand / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		tmp1_bit[i] = *(ecc_nand + 1) % 2;
+		*(ecc_nand + 1) = *(ecc_nand + 1) / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		tmp2_bit[i] = *(ecc_nand + 2) % 2;
+		*(ecc_nand + 2) = *(ecc_nand + 2) / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		comp0_bit[i] = *ecc_calc % 2;
+		*ecc_calc = *ecc_calc / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		comp1_bit[i] = *(ecc_calc + 1) % 2;
+		*(ecc_calc + 1) = *(ecc_calc + 1) / 2;
+	}
+
+	for (i = 0; i < 8; i++) {
+		comp2_bit[i] = *(ecc_calc + 2) % 2;
+		*(ecc_calc + 2) = *(ecc_calc + 2) / 2;
+	}
+
+	for (i = 0; i< 6; i++)
+		ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
+
+	for (i = 0; i < 8; i++)
+		ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
+
+	for (i = 0; i < 8; i++)
+		ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
+
+	ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
+	ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
+
+	for (i = 0; i < 24; i++)
+		ecc_sum += ecc_bit[i];
+
+	switch (ecc_sum) {
+		case 0:
+			/* Not reached because this function is not called if
+			   ECC values are equal */
+			return 0;
+		case 1:
+			/* Uncorrectable error */
+			DEBUG (MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
+			return(-1);
+		case 12:
+			/* Correctable error */
+			find_byte = (ecc_bit[23] << 8) +
+				(ecc_bit[21] << 7) +
+				(ecc_bit[19] << 6) +
+				(ecc_bit[17] << 5) +
+				(ecc_bit[15] << 4) +
+				(ecc_bit[13] << 3) +
+				(ecc_bit[11] << 2) +
+				(ecc_bit[9]  << 1) +
+				ecc_bit[7];
+
+			find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
+
+			DEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at offset: %d, bit: %d\n", find_byte, find_bit);
+
+			page_data[find_byte] ^= (1 << find_bit);
+
+			return(0);
+		default:
+			if (is_ecc_ff) {
+				if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0)
+					return(0);
+			}
+			DEBUG (MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
+			return(-1);
+	}
+}
+
+static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+{
+	struct nand_chip	*this;
+	int			block_count = 0, i, rc;
+
+	this = mtd->priv;
+	block_count = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1;
+	for (i = 0; i < block_count; i++) {
+		if (memcmp(read_ecc, calc_ecc, 3) != 0) {
+			rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
+			if (rc < 0) {
+				return(rc);
+			}
+		}
+		read_ecc += 3;
+		calc_ecc += 3;
+		dat += 512;
+	}
+	return(0);
+}
+#endif
+
+static int nand_davinci_dev_ready(struct mtd_info *mtd)
+{
+	emifregs	emif_addr;
+
+	emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+
+	return(emif_addr->NANDFSR & 0x1);
+}
+
+static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
+{
+	while(!nand_davinci_dev_ready(mtd)) {;}
+	*NAND_CE0CLE = NAND_STATUS;
+	return(*NAND_CE0DATA);
+}
+
+static void nand_flash_init(void)
+{
+	u_int32_t	acfg1 = 0x3ffffffc;
+	u_int32_t	acfg2 = 0x3ffffffc;
+	u_int32_t	acfg3 = 0x3ffffffc;
+	u_int32_t	acfg4 = 0x3ffffffc;
+	emifregs	emif_regs;
+
+	/*------------------------------------------------------------------*
+	 *  NAND FLASH CHIP TIMEOUT @ 459 MHz                               *
+	 *                                                                  *
+	 *  AEMIF.CLK freq   = PLL1/6 = 459/6 = 76.5 MHz                    *
+	 *  AEMIF.CLK period = 1/76.5 MHz = 13.1 ns                         *
+	 *                                                                  *
+	 *------------------------------------------------------------------*/
+	 acfg1 = 0
+	 	| (0 << 31 )	/* selectStrobe */
+	 	| (0 << 30 )	/* extWait */
+	 	| (1 << 26 )	/* writeSetup	10 ns */
+	 	| (3 << 20 )	/* writeStrobe	40 ns */
+	 	| (1 << 17 )	/* writeHold	10 ns */
+	 	| (1 << 13 )	/* readSetup	10 ns */
+	 	| (5 << 7 )	/* readStrobe	60 ns */
+	 	| (1 << 4 )	/* readHold	10 ns */
+	 	| (3 << 2 )	/* turnAround	?? ns */
+	 	| (0 << 0 )	/* asyncSize	8-bit bus */
+	 	;
+
+	emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
+
+	emif_regs->AWCCR |= 0x10000000;
+	emif_regs->AB1CR = acfg1;	/* 0x08244128 */;
+	emif_regs->AB2CR = acfg2;
+	emif_regs->AB3CR = acfg3;
+	emif_regs->AB4CR = acfg4;
+	emif_regs->NANDFCR = 0x00000101;
+}
+
+int board_nand_init(struct nand_chip *nand)
+{
+	nand->IO_ADDR_R   = (void  __iomem *)NAND_CE0DATA;
+	nand->IO_ADDR_W   = (void  __iomem *)NAND_CE0DATA;
+	nand->chip_delay  = 0;
+	nand->select_chip = nand_davinci_select_chip;
+#ifdef CFG_NAND_USE_FLASH_BBT
+	nand->options	  = NAND_USE_FLASH_BBT;
+#endif
+#ifdef CFG_NAND_HW_ECC
+#ifdef CFG_NAND_LARGEPAGE
+	nand->eccmode     = NAND_ECC_HW12_2048;
+#elif defined(CFG_NAND_SMALLPAGE)
+	nand->eccmode     = NAND_ECC_HW3_512;
+#else
+#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!"
+#endif
+	nand->autooob	  = &davinci_nand_oobinfo;
+	nand->calculate_ecc = nand_davinci_calculate_ecc;
+	nand->correct_data  = nand_davinci_correct_data;
+	nand->enable_hwecc  = nand_davinci_enable_hwecc;
+#else
+	nand->eccmode     = NAND_ECC_SOFT;
+#endif
+
+	/* Set address of hardware control function */
+	nand->hwcontrol = nand_davinci_hwcontrol;
+
+	nand->dev_ready = nand_davinci_dev_ready;
+	nand->waitfunc = nand_davinci_waitfunc;
+
+	nand_flash_init();
+
+	return(0);
+}
+
+#else
+#error "U-Boot legacy NAND support not available for DaVinci chips"
+#endif
+#endif	/* CFG_USE_NAND */
diff --git a/cpu/arm926ejs/davinci/reset.S b/cpu/arm926ejs/davinci/reset.S
new file mode 100644
index 0000000..a687d44
--- /dev/null
+++ b/cpu/arm926ejs/davinci/reset.S
@@ -0,0 +1,77 @@
+/*
+ * Processor reset using WDT for TI TMS320DM644x SoC.
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * -----------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+.globl reset_cpu
+reset_cpu:
+	ldr	r0, WDT_TGCR
+	mov	r1, $0x08
+	str	r1, [r0]
+	ldr	r1, [r0]
+	orr	r1, r1, $0x03
+	str	r1, [r0]
+	mov	r1, $0
+	ldr	r0, WDT_TIM12
+	str	r1, [r0]
+	ldr	r0, WDT_TIM34
+	str	r1, [r0]
+	ldr	r0, WDT_PRD12
+	str	r1, [r0]
+	ldr	r0, WDT_PRD34
+	str	r1, [r0]
+	ldr	r0, WDT_TCR
+	ldr	r1, [r0]
+	orr	r1, r1, $0x40
+	str	r1, [r0]
+	ldr	r0, WDT_WDTCR
+	ldr	r1, [r0]
+	orr	r1, r1, $0x4000
+	str	r1, [r0]
+	ldr	r1, WDTCR_VAL1
+	str	r1, [r0]
+	ldr	r1, WDTCR_VAL2
+	str	r1, [r0]
+	nop
+	nop
+	nop
+	nop
+reset_cpu_loop:
+	b	reset_cpu_loop
+
+WDT_TGCR:
+	.word	0x01c21c24
+WDT_TIM12:
+	.word	0x01c21c10
+WDT_TIM34:
+	.word	0x01c21c14
+WDT_PRD12:
+	.word	0x01c21c18
+WDT_PRD34:
+	.word	0x01c21c1c
+WDT_TCR:
+	.word	0x01c21c20
+WDT_WDTCR:
+	.word	0x01c21c28
+WDTCR_VAL1:
+	.word	0xa5c64000
+WDTCR_VAL2:
+	.word	0xda7e4000
diff --git a/cpu/arm926ejs/davinci/timer.c b/cpu/arm926ejs/davinci/timer.c
new file mode 100644
index 0000000..c6b1dda
--- /dev/null
+++ b/cpu/arm926ejs/davinci/timer.c
@@ -0,0 +1,165 @@
+/*
+ * (C) Copyright 2003
+ * Texas Instruments <www.ti.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002-2004
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * (C) Copyright 2004
+ * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
+ *
+ * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <arm926ejs.h>
+
+typedef volatile struct {
+	u_int32_t	pid12;
+	u_int32_t	emumgt_clksped;
+	u_int32_t	gpint_en;
+	u_int32_t	gpdir_dat;
+	u_int32_t	tim12;
+	u_int32_t	tim34;
+	u_int32_t	prd12;
+	u_int32_t	prd34;
+	u_int32_t	tcr;
+	u_int32_t	tgcr;
+	u_int32_t	wdtcr;
+	u_int32_t	tlgc;
+	u_int32_t	tlmr;
+} davinci_timer;
+
+davinci_timer		*timer = (davinci_timer *)CFG_TIMERBASE;
+
+#define TIMER_LOAD_VAL	(CFG_HZ_CLOCK / CFG_HZ)
+#define READ_TIMER	timer->tim34
+
+static ulong timestamp;
+static ulong lastinc;
+
+int timer_init(void)
+{
+	/* We are using timer34 in unchained 32-bit mode, full speed */
+	timer->tcr = 0x0;
+	timer->tgcr = 0x0;
+	timer->tgcr = 0x06;
+	timer->tim34 = 0x0;
+	timer->prd34 = TIMER_LOAD_VAL;
+	lastinc = 0;
+	timer->tcr = 0x80 << 16;
+	timestamp = 0;
+
+	return(0);
+}
+
+void reset_timer(void)
+{
+	reset_timer_masked();
+}
+
+ulong get_timer(ulong base)
+{
+	return(get_timer_masked() - base);
+}
+
+void set_timer(ulong t)
+{
+	timestamp = t;
+}
+
+void udelay(unsigned long usec)
+{
+	udelay_masked(usec);
+}
+
+void reset_timer_masked(void)
+{
+	lastinc = READ_TIMER;
+	timestamp = 0;
+}
+
+ulong get_timer_raw(void)
+{
+	ulong now = READ_TIMER;
+
+	if (now >= lastinc) {
+		/* normal mode */
+		timestamp += now - lastinc;
+	} else {
+		/* overflow ... */
+		timestamp += now + TIMER_LOAD_VAL - lastinc;
+	}
+	lastinc = now;
+	return timestamp;
+}
+
+ulong get_timer_masked(void)
+{
+	return(get_timer_raw() / TIMER_LOAD_VAL);
+}
+
+void udelay_masked(unsigned long usec)
+{
+	ulong tmo;
+	ulong endtime;
+	signed long diff;
+
+	tmo = CFG_HZ_CLOCK / 1000;
+	tmo *= usec;
+	tmo /= 1000;
+
+	endtime = get_timer_raw() + tmo;
+
+	do {
+		ulong now = get_timer_raw();
+		diff = endtime - now;
+	} while (diff >= 0);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return(get_timer(0));
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	ulong tbclk;
+
+	tbclk = CFG_HZ;
+	return(tbclk);
+}