Merge branch 'master' of git://git.denx.de/u-boot-arm
diff --git a/README b/README
index d4eb099..423ab2c 100644
--- a/README
+++ b/README
@@ -2854,6 +2854,26 @@
 		The signing part is build into mkimage regardless of this
 		option.
 
+- bootcount support:
+		CONFIG_BOOTCOUNT_LIMIT
+
+		This enables the bootcounter support, see:
+		http://www.denx.de/wiki/DULG/UBootBootCountLimit
+
+		CONFIG_AT91SAM9XE
+		enable special bootcounter support on at91sam9xe based boards.
+		CONFIG_BLACKFIN
+		enable special bootcounter support on blackfin based boards.
+		CONFIG_SOC_DA8XX
+		enable special bootcounter support on da850 based boards.
+		CONFIG_BOOTCOUNT_RAM
+		enable support for the bootcounter in RAM
+		CONFIG_BOOTCOUNT_I2C
+		enable support for the bootcounter on an i2c (like RTC) device.
+			CONFIG_SYS_I2C_RTC_ADDR = i2c chip address
+			CONFIG_SYS_BOOTCOUNT_ADDR = i2c addr which is used for
+						    the bootcounter.
+			CONFIG_BOOTCOUNT_ALEN = address len
 
 - Show boot progress:
 		CONFIG_SHOW_BOOT_PROGRESS
diff --git a/arch/arc/include/asm/arch-arc700/hardware.h b/arch/arc/include/asm/arch-arc700/hardware.h
deleted file mode 100644
index 8ec13a8..0000000
--- a/arch/arc/include/asm/arch-arc700/hardware.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/*
- * This file is only required to allow compilation of "designware_i2c" driver.
- * Which explicitly includes <asm/arch/hardware.h>.
- */
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 2658911..e2fcca5 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -2,7 +2,6 @@
 	exynos5250-snow.dtb \
 	exynos5250-smdk5250.dtb \
 	exynos5420-smdk5420.dtb
-
 dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
 	tegra20-medcom-wide.dtb \
 	tegra20-paz00.dtb \
@@ -16,8 +15,8 @@
 	tegra30-beaver.dtb \
 	tegra30-cardhu.dtb \
 	tegra30-tec-ng.dtb \
-	tegra114-dalmore.dtb
-
+	tegra114-dalmore.dtb \
+	tegra124-venice2.dtb
 dtb-$(CONFIG_ZYNQ) += zynq-zc702.dtb \
 	zynq-zc706.dtb \
 	zynq-zed.dtb \
diff --git a/board/nvidia/dts/tegra124-venice2.dts b/arch/arm/dts/tegra124-venice2.dts
similarity index 100%
rename from board/nvidia/dts/tegra124-venice2.dts
rename to arch/arm/dts/tegra124-venice2.dts
diff --git a/arch/arm/include/asm/arch-spear/hardware.h b/arch/arm/include/asm/arch-spear/hardware.h
index f3afd4d..c6da405 100644
--- a/arch/arm/include/asm/arch-spear/hardware.h
+++ b/arch/arm/include/asm/arch-spear/hardware.h
@@ -26,7 +26,6 @@
 #define CONFIG_SYS_NAND_ALE			(1 << 17)
 
 #if defined(CONFIG_SPEAR600)
-#define CONFIG_SYS_I2C_BASE			0xD0200000
 #define CONFIG_SYS_FSMC_BASE			0xD1800000
 #define CONFIG_FSMC_NAND_BASE			0xD2000000
 
@@ -42,11 +41,9 @@
 #define CONFIG_SPEAR_MPMCREGS			100
 
 #elif defined(CONFIG_SPEAR300)
-#define CONFIG_SYS_I2C_BASE			0xD0180000
 #define CONFIG_SYS_FSMC_BASE			0x94000000
 
 #elif defined(CONFIG_SPEAR310)
-#define CONFIG_SYS_I2C_BASE			0xD0180000
 #define CONFIG_SYS_FSMC_BASE			0x44000000
 
 #undef CONFIG_SYS_NAND_CLE
@@ -63,7 +60,6 @@
 #define CONFIG_SYS_MACB3_BASE			0xB1800000
 
 #elif defined(CONFIG_SPEAR320)
-#define CONFIG_SYS_I2C_BASE			0xD0180000
 #define CONFIG_SYS_FSMC_BASE			0x4C000000
 
 #define CONFIG_SPEAR_EMIBASE			0x40000000
diff --git a/arch/blackfin/include/asm/blackfin_local.h b/arch/blackfin/include/asm/blackfin_local.h
index 4d6eeab..868c82e 100644
--- a/arch/blackfin/include/asm/blackfin_local.h
+++ b/arch/blackfin/include/asm/blackfin_local.h
@@ -42,13 +42,6 @@
 
 # include <linux/types.h>
 
-extern u_long get_vco(void);
-extern u_long get_cclk(void);
-extern u_long get_sclk(void);
-extern u_long get_sclk0(void);
-extern u_long get_sclk1(void);
-extern u_long get_dclk(void);
-
 # define bfin_revid() (bfin_read_CHIPID() >> 28)
 
 extern int bfin_os_log_check(void);
diff --git a/arch/blackfin/include/asm/clock.h b/arch/blackfin/include/asm/clock.h
index fc84fe4..59d3faa 100644
--- a/arch/blackfin/include/asm/clock.h
+++ b/arch/blackfin/include/asm/clock.h
@@ -68,10 +68,21 @@
 	return uclk;
 }
 
+extern u_long get_vco(void);
+extern u_long get_cclk(void);
+extern u_long get_sclk(void);
+
 #ifdef CGU_DIV
+extern u_long get_sclk0(void);
+extern u_long get_sclk1(void);
+extern u_long get_dclk(void);
 # define get_uart_clk get_sclk0
+# define get_i2c_clk get_sclk0
+# define get_spi_clk get_sclk0
 #else
 # define get_uart_clk get_sclk
+# define get_i2c_clk get_sclk
+# define get_spi_clk get_sclk
 #endif
 
 #endif
diff --git a/arch/blackfin/include/asm/twi.h b/arch/blackfin/include/asm/twi.h
new file mode 100644
index 0000000..922cdbd
--- /dev/null
+++ b/arch/blackfin/include/asm/twi.h
@@ -0,0 +1,15 @@
+/*
+ * i2c.c - driver for Blackfin on-chip TWI/I2C
+ *
+ * Copyright (c) 2006-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ARCH_TWI_H
+#define __ARCH_TWI_H
+
+#include <asm/blackfin.h>
+#include <asm/mach-common/bits/twi.h>
+
+#endif
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index facbc7a..6234201 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -23,6 +23,7 @@
 
 #include <asm/cplb.h>
 #include <asm/mach-common/bits/mpu.h>
+#include <asm/clock.h>
 #include <kgdb.h>
 
 #ifdef CONFIG_CMD_NAND
diff --git a/board/cm-bf548/video.c b/board/cm-bf548/video.c
index a43413e..c35d285 100644
--- a/board/cm-bf548/video.c
+++ b/board/cm-bf548/video.c
@@ -11,6 +11,7 @@
 #include <config.h>
 #include <malloc.h>
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/gpio.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/dma.h>
diff --git a/common/cmd_otp.c b/common/cmd_otp.c
index 6f93335..67808aa 100644
--- a/common/cmd_otp.c
+++ b/common/cmd_otp.c
@@ -18,6 +18,7 @@
 #include <command.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/mach-common/bits/otp.h>
 
 static const char *otp_strerror(uint32_t err)
diff --git a/drivers/block/pata_bfin.c b/drivers/block/pata_bfin.c
index 27ecaf4..b7fd1cd 100644
--- a/drivers/block/pata_bfin.c
+++ b/drivers/block/pata_bfin.c
@@ -12,6 +12,7 @@
 #include <command.h>
 #include <config.h>
 #include <asm/byteorder.h>
+#include <asm/clock.h>
 #include <asm/io.h>
 #include <asm/errno.h>
 #include <asm/portmux.h>
diff --git a/drivers/bootcount/Makefile b/drivers/bootcount/Makefile
index bed6971..6f1c419 100644
--- a/drivers/bootcount/Makefile
+++ b/drivers/bootcount/Makefile
@@ -9,3 +9,4 @@
 obj-$(CONFIG_BOOTCOUNT_AM33XX)	+= bootcount_davinci.o
 obj-$(CONFIG_BOOTCOUNT_RAM)	+= bootcount_ram.o
 obj-$(CONFIG_BOOTCOUNT_ENV)	+= bootcount_env.o
+obj-$(CONFIG_BOOTCOUNT_I2C)	+= bootcount_i2c.o
diff --git a/drivers/bootcount/bootcount_i2c.c b/drivers/bootcount/bootcount_i2c.c
new file mode 100644
index 0000000..e27b168
--- /dev/null
+++ b/drivers/bootcount/bootcount_i2c.c
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 2013
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <bootcount.h>
+#include <linux/compiler.h>
+#include <i2c.h>
+
+#define BC_MAGIC	0xbc
+
+void bootcount_store(ulong a)
+{
+	unsigned char buf[3];
+	int ret;
+
+	buf[0] = BC_MAGIC;
+	buf[1] = (a & 0xff);
+	ret = i2c_write(CONFIG_SYS_I2C_RTC_ADDR, CONFIG_SYS_BOOTCOUNT_ADDR,
+		  CONFIG_BOOTCOUNT_ALEN, buf, 2);
+	if (ret != 0)
+		puts("Error writing bootcount\n");
+}
+
+ulong bootcount_load(void)
+{
+	unsigned char buf[3];
+	int ret;
+
+	ret = i2c_read(CONFIG_SYS_I2C_RTC_ADDR, CONFIG_SYS_BOOTCOUNT_ADDR,
+		       CONFIG_BOOTCOUNT_ALEN, buf, 2);
+	if (ret != 0) {
+		puts("Error loading bootcount\n");
+		return 0;
+	}
+	if (buf[0] == BC_MAGIC)
+		return buf[1];
+
+	bootcount_store(0);
+
+	return 0;
+}
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index f942758..0816f46 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -73,16 +73,12 @@
 			op == DFU_OP_READ ? "load" : "write",
 			dfu->data.mmc.dev, dfu->data.mmc.part,
 			(unsigned int) buf, dfu->name);
-		if (op == DFU_OP_WRITE)
-			sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len);
 		break;
 	case DFU_FS_EXT4:
 		sprintf(cmd_buf, "ext4%s mmc %d:%d 0x%x /%s",
 			op == DFU_OP_READ ? "load" : "write",
 			dfu->data.mmc.dev, dfu->data.mmc.part,
 			(unsigned int) buf, dfu->name);
-		if (op == DFU_OP_WRITE)
-			sprintf(cmd_buf + strlen(cmd_buf), " %ld", *len);
 		break;
 	default:
 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
@@ -90,6 +86,9 @@
 		return -1;
 	}
 
+	if (op == DFU_OP_WRITE)
+		sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len);
+
 	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
 
 	ret = run_command(cmd_buf, 0);
diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c
new file mode 100644
index 0000000..675f417
--- /dev/null
+++ b/drivers/i2c/adi_i2c.c
@@ -0,0 +1,387 @@
+/*
+ * i2c.c - driver for ADI TWI/I2C
+ *
+ * Copyright (c) 2006-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#include <asm/clock.h>
+#include <asm/twi.h>
+#include <asm/io.h>
+
+/* Every register is 32bit aligned, but only 16bits in size */
+#define ureg(name) u16 name; u16 __pad_##name;
+struct twi_regs {
+	ureg(clkdiv);
+	ureg(control);
+	ureg(slave_ctl);
+	ureg(slave_stat);
+	ureg(slave_addr);
+	ureg(master_ctl);
+	ureg(master_stat);
+	ureg(master_addr);
+	ureg(int_stat);
+	ureg(int_mask);
+	ureg(fifo_ctl);
+	ureg(fifo_stat);
+	char __pad[0x50];
+	ureg(xmt_data8);
+	ureg(xmt_data16);
+	ureg(rcv_data8);
+	ureg(rcv_data16);
+};
+#undef ureg
+
+/* U-Boot I2C framework allows only one active device at a time.  */
+#ifdef TWI_CLKDIV
+#define TWI0_CLKDIV TWI_CLKDIV
+#endif
+static struct twi_regs *twi = (void *)TWI0_CLKDIV;
+
+#ifdef DEBUG
+# define dmemset(s, c, n) memset(s, c, n)
+#else
+# define dmemset(s, c, n)
+#endif
+#define debugi(fmt, args...) \
+	debug( \
+		"MSTAT:0x%03x FSTAT:0x%x ISTAT:0x%02x\t%-20s:%-3i: " fmt "\n", \
+		twi->master_stat, twi->fifo_stat, twi->int_stat, \
+		__func__, __LINE__, ## args)
+
+#ifdef CONFIG_TWICLK_KHZ
+# error do not define CONFIG_TWICLK_KHZ ... use CONFIG_SYS_I2C_SPEED
+#endif
+
+/*
+ * The way speed is changed into duty often results in integer truncation
+ * with 50% duty, so we'll force rounding up to the next duty by adding 1
+ * to the max.  In practice this will get us a speed of something like
+ * 385 KHz.  The other limit is easy to handle as it is only 8 bits.
+ */
+#define I2C_SPEED_MAX             400000
+#define I2C_SPEED_TO_DUTY(speed)  (5000000 / (speed))
+#define I2C_DUTY_MAX              (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1)
+#define I2C_DUTY_MIN              0xff	/* 8 bit limited */
+#define SYS_I2C_DUTY              I2C_SPEED_TO_DUTY(CONFIG_SYS_I2C_SPEED)
+/* Note: duty is inverse of speed, so the comparisons below are correct */
+#if SYS_I2C_DUTY < I2C_DUTY_MAX || SYS_I2C_DUTY > I2C_DUTY_MIN
+# error "The Blackfin I2C hardware can only operate 20KHz - 400KHz"
+#endif
+
+/* All transfers are described by this data structure */
+struct i2c_msg {
+	u8 flags;
+#define I2C_M_COMBO		0x4
+#define I2C_M_STOP		0x2
+#define I2C_M_READ		0x1
+	int len;		/* msg length */
+	u8 *buf;		/* pointer to msg data */
+	int alen;		/* addr length */
+	u8 *abuf;		/* addr buffer */
+};
+
+/* Allow msec timeout per ~byte transfer */
+#define I2C_TIMEOUT 10
+
+/**
+ * wait_for_completion - manage the actual i2c transfer
+ *	@msg: the i2c msg
+ */
+static int wait_for_completion(struct i2c_msg *msg)
+{
+	u16 int_stat, ctl;
+	ulong timebase = get_timer(0);
+
+	do {
+		int_stat = readw(&twi->int_stat);
+
+		if (int_stat & XMTSERV) {
+			debugi("processing XMTSERV");
+			writew(XMTSERV, &twi->int_stat);
+			if (msg->alen) {
+				writew(*(msg->abuf++), &twi->xmt_data8);
+				--msg->alen;
+			} else if (!(msg->flags & I2C_M_COMBO) && msg->len) {
+				writew(*(msg->buf++), &twi->xmt_data8);
+				--msg->len;
+			} else {
+				ctl = readw(&twi->master_ctl);
+				if (msg->flags & I2C_M_COMBO)
+					writew(ctl | RSTART | MDIR,
+							&twi->master_ctl);
+				else
+					writew(ctl | STOP, &twi->master_ctl);
+			}
+		}
+		if (int_stat & RCVSERV) {
+			debugi("processing RCVSERV");
+			writew(RCVSERV, &twi->int_stat);
+			if (msg->len) {
+				*(msg->buf++) = readw(&twi->rcv_data8);
+				--msg->len;
+			} else if (msg->flags & I2C_M_STOP) {
+				ctl = readw(&twi->master_ctl);
+				writew(ctl | STOP, &twi->master_ctl);
+			}
+		}
+		if (int_stat & MERR) {
+			debugi("processing MERR");
+			writew(MERR, &twi->int_stat);
+			return msg->len;
+		}
+		if (int_stat & MCOMP) {
+			debugi("processing MCOMP");
+			writew(MCOMP, &twi->int_stat);
+			if (msg->flags & I2C_M_COMBO && msg->len) {
+				ctl = readw(&twi->master_ctl);
+				ctl = (ctl & ~RSTART) |
+					(min(msg->len, 0xff) << 6) | MEN | MDIR;
+				writew(ctl, &twi->master_ctl);
+			} else
+				break;
+		}
+
+		/* If we were able to do something, reset timeout */
+		if (int_stat)
+			timebase = get_timer(0);
+
+	} while (get_timer(timebase) < I2C_TIMEOUT);
+
+	return msg->len;
+}
+
+/**
+ * i2c_transfer - setup an i2c transfer
+ *	@return: 0 if things worked, non-0 if things failed
+ *
+ *	Here we just get the i2c stuff all prepped and ready, and then tail off
+ *	into wait_for_completion() for all the bits to go.
+ */
+static int i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer,
+			int len, u8 flags)
+{
+	int ret;
+	u16 ctl;
+	uchar addr_buffer[] = {
+		(addr >>  0),
+		(addr >>  8),
+		(addr >> 16),
+	};
+	struct i2c_msg msg = {
+		.flags = flags | (len >= 0xff ? I2C_M_STOP : 0),
+		.buf   = buffer,
+		.len   = len,
+		.abuf  = addr_buffer,
+		.alen  = alen,
+	};
+
+	dmemset(buffer, 0xff, len);
+	debugi("chip=0x%x addr=0x%02x alen=%i buf[0]=0x%02x len=%i ",
+		chip, addr, alen, buffer[0], len);
+	debugi("flags=0x%02x[%s] ", flags,
+		(flags & I2C_M_READ ? "rd" : "wr"));
+
+	/* wait for things to settle */
+	while (readw(&twi->master_stat) & BUSBUSY)
+		if (ctrlc())
+			return 1;
+
+	/* Set Transmit device address */
+	writew(chip, &twi->master_addr);
+
+	/* Clear the FIFO before starting things */
+	writew(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl);
+	writew(0, &twi->fifo_ctl);
+
+	/* prime the pump */
+	if (msg.alen) {
+		len = (msg.flags & I2C_M_COMBO) ? msg.alen : msg.alen + len;
+		debugi("first byte=0x%02x", *msg.abuf);
+		writew(*(msg.abuf++), &twi->xmt_data8);
+		--msg.alen;
+	} else if (!(msg.flags & I2C_M_READ) && msg.len) {
+		debugi("first byte=0x%02x", *msg.buf);
+		writew(*(msg.buf++), &twi->xmt_data8);
+		--msg.len;
+	}
+
+	/* clear int stat */
+	writew(-1, &twi->master_stat);
+	writew(-1, &twi->int_stat);
+	writew(0, &twi->int_mask);
+
+	/* Master enable */
+	ctl = readw(&twi->master_ctl);
+	ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN |
+		((msg.flags & I2C_M_READ) ? MDIR : 0);
+	writew(ctl, &twi->master_ctl);
+
+	/* process the rest */
+	ret = wait_for_completion(&msg);
+	debugi("ret=%d", ret);
+
+	if (ret) {
+		ctl = readw(&twi->master_ctl) & ~MEN;
+		writew(ctl, &twi->master_ctl);
+		ctl = readw(&twi->control) & ~TWI_ENA;
+		writew(ctl, &twi->control);
+		ctl = readw(&twi->control) | TWI_ENA;
+		writew(ctl, &twi->control);
+	}
+
+	return ret;
+}
+
+/**
+ * i2c_set_bus_speed - set i2c bus speed
+ *	@speed: bus speed (in HZ)
+ */
+int i2c_set_bus_speed(unsigned int speed)
+{
+	u16 clkdiv = I2C_SPEED_TO_DUTY(speed);
+
+	/* Set TWI interface clock */
+	if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN)
+		return -1;
+	clkdiv = (clkdiv << 8) | (clkdiv & 0xff);
+	writew(clkdiv, &twi->clkdiv);
+
+	/* Don't turn it on */
+	writew(speed > 100000 ? FAST : 0, &twi->master_ctl);
+
+	return 0;
+}
+
+/**
+ * i2c_get_bus_speed - get i2c bus speed
+ *	@speed: bus speed (in HZ)
+ */
+unsigned int i2c_get_bus_speed(void)
+{
+	u16 clkdiv = readw(&twi->clkdiv) & 0xff;
+	/* 10 MHz / (2 * CLKDIV) -> 5 MHz / CLKDIV */
+	return 5000000 / clkdiv;
+}
+
+/**
+ * i2c_init - initialize the i2c bus
+ *	@speed: bus speed (in HZ)
+ *	@slaveaddr: address of device in slave mode (0 - not slave)
+ *
+ *	Slave mode isn't actually implemented.  It'll stay that way until
+ *	we get a real request for it.
+ */
+void i2c_init(int speed, int slaveaddr)
+{
+	u16 prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F;
+
+	/* Set TWI internal clock as 10MHz */
+	writew(prescale, &twi->control);
+
+	/* Set TWI interface clock as specified */
+	i2c_set_bus_speed(speed);
+
+	/* Enable it */
+	writew(TWI_ENA | prescale, &twi->control);
+
+	debugi("CONTROL:0x%04x CLKDIV:0x%04x", readw(&twi->control),
+		readw(&twi->clkdiv));
+
+#if CONFIG_SYS_I2C_SLAVE
+# error I2C slave support not tested/supported
+#endif
+}
+
+/**
+ * i2c_probe - test if a chip exists at a given i2c address
+ *	@chip: i2c chip addr to search for
+ *	@return: 0 if found, non-0 if not found
+ */
+int i2c_probe(uchar chip)
+{
+	u8 byte;
+	return i2c_read(chip, 0, 0, &byte, 1);
+}
+
+/**
+ * i2c_read - read data from an i2c device
+ *	@chip: i2c chip addr
+ *	@addr: memory (register) address in the chip
+ *	@alen: byte size of address
+ *	@buffer: buffer to store data read from chip
+ *	@len: how many bytes to read
+ *	@return: 0 on success, non-0 on failure
+ */
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	return i2c_transfer(chip, addr, alen, buffer,
+			len, (alen ? I2C_M_COMBO : I2C_M_READ));
+}
+
+/**
+ * i2c_write - write data to an i2c device
+ *	@chip: i2c chip addr
+ *	@addr: memory (register) address in the chip
+ *	@alen: byte size of address
+ *	@buffer: buffer holding data to write to chip
+ *	@len: how many bytes to write
+ *	@return: 0 on success, non-0 on failure
+ */
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	return i2c_transfer(chip, addr, alen, buffer, len, 0);
+}
+
+/**
+ * i2c_set_bus_num - change active I2C bus
+ *	@bus: bus index, zero based
+ *	@returns: 0 on success, non-0 on failure
+ */
+int i2c_set_bus_num(unsigned int bus)
+{
+	switch (bus) {
+#if CONFIG_SYS_MAX_I2C_BUS > 0
+	case 0:
+		twi = (void *)TWI0_CLKDIV;
+		return 0;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 1
+	case 1:
+		twi = (void *)TWI1_CLKDIV;
+		return 0;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 2
+	case 2:
+		twi = (void *)TWI2_CLKDIV;
+		return 0;
+#endif
+	default: return -1;
+	}
+}
+
+/**
+ * i2c_get_bus_num - returns index of active I2C bus
+ */
+unsigned int i2c_get_bus_num(void)
+{
+	switch ((unsigned long)twi) {
+#if CONFIG_SYS_MAX_I2C_BUS > 0
+	case TWI0_CLKDIV:
+		return 0;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 1
+	case TWI1_CLKDIV:
+		return 1;
+#endif
+#if CONFIG_SYS_MAX_I2C_BUS > 2
+	case TWI2_CLKDIV:
+		return 2;
+#endif
+	default: return -1;
+	}
+}
diff --git a/drivers/i2c/bfin-twi_i2c.c b/drivers/i2c/bfin-twi_i2c.c
index b3a04d3..cfab064 100644
--- a/drivers/i2c/bfin-twi_i2c.c
+++ b/drivers/i2c/bfin-twi_i2c.c
@@ -10,6 +10,7 @@
 #include <i2c.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/mach-common/bits/twi.h>
 
 /* Every register is 32bit aligned, but only 16bits in size */
@@ -274,7 +275,7 @@
  */
 void i2c_init(int speed, int slaveaddr)
 {
-	uint8_t prescale = ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F;
+	uint8_t prescale = ((get_i2c_clk() / 1000 / 1000 + 5) / 10) & 0x7F;
 
 	/* Set TWI internal clock as 10MHz */
 	twi->control = prescale;
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 9ed9295..c891ebd 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -7,7 +7,6 @@
 
 #include <common.h>
 #include <asm/io.h>
-#include <asm/arch/hardware.h>
 #include "designware_i2c.h"
 
 #ifdef CONFIG_I2C_MULTI_BUS
@@ -197,35 +196,18 @@
 	return 0;
 }
 
-/* check parameters for i2c_read and i2c_write */
-static int check_params(uint addr, int alen, uchar *buffer, int len)
-{
-	if (buffer == NULL) {
-		printf("Buffer is invalid\n");
-		return 1;
-	}
-
-	if (alen > 1) {
-		printf("addr len %d not supported\n", alen);
-		return 1;
-	}
-
-	if (addr + len > 256) {
-		printf("address out of range\n");
-		return 1;
-	}
-
-	return 0;
-}
-
-static int i2c_xfer_init(uchar chip, uint addr)
+static int i2c_xfer_init(uchar chip, uint addr, int alen)
 {
 	if (i2c_wait_for_bb())
 		return 1;
 
 	i2c_setaddress(chip);
-	writel(addr, &i2c_regs_p->ic_cmd_data);
-
+	while (alen) {
+		alen--;
+		/* high byte address going out first */
+		writel((addr >> (alen * 8)) & 0xff,
+		       &i2c_regs_p->ic_cmd_data);
+	}
 	return 0;
 }
 
@@ -285,10 +267,7 @@
 	      addr);
 #endif
 
-	if (check_params(addr, alen, buffer, len))
-		return 1;
-
-	if (i2c_xfer_init(chip, addr))
+	if (i2c_xfer_init(chip, addr, alen))
 		return 1;
 
 	start_time_rx = get_timer(0);
@@ -345,10 +324,7 @@
 	      addr);
 #endif
 
-	if (check_params(addr, alen, buffer, len))
-		return 1;
-
-	if (i2c_xfer_init(chip, addr))
+	if (i2c_xfer_init(chip, addr, alen))
 		return 1;
 
 	start_time_tx = get_timer(0);
diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c
index a298c95..de3b194 100644
--- a/drivers/i2c/mxs_i2c.c
+++ b/drivers/i2c/mxs_i2c.c
@@ -64,16 +64,17 @@
 	writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
 }
 
-static void mxs_i2c_write(uchar chip, uint addr, int alen,
+static int mxs_i2c_write(uchar chip, uint addr, int alen,
 			uchar *buf, int blen, int stop)
 {
 	struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
-	uint32_t data;
+	uint32_t data, tmp;
 	int i, remain, off;
+	int timeout = MXS_I2C_MAX_TIMEOUT;
 
 	if ((alen > 4) || (alen == 0)) {
 		debug("MXS I2C: Invalid address length\n");
-		return;
+		return -EINVAL;
 	}
 
 	if (stop)
@@ -106,6 +107,19 @@
 		writel(data >> remain, &i2c_regs->hw_i2c_data);
 
 	writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
+
+	while (--timeout) {
+		tmp = readl(&i2c_regs->hw_i2c_queuestat);
+		if (tmp & I2C_QUEUESTAT_WR_QUEUE_EMPTY)
+			break;
+	}
+
+	if (!timeout) {
+		debug("MXS I2C: Failed transmitting data!\n");
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static int mxs_i2c_wait_for_ack(void)
@@ -154,7 +168,12 @@
 	int ret;
 	int i;
 
-	mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
+	ret = mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
+	if (ret) {
+		debug("MXS I2C: Failed writing address\n");
+		return ret;
+	}
+
 	ret = mxs_i2c_wait_for_ack();
 	if (ret) {
 		debug("MXS I2C: Failed writing address\n");
@@ -193,7 +212,12 @@
 int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 {
 	int ret;
-	mxs_i2c_write(chip, addr, alen, buffer, len, 1);
+	ret = mxs_i2c_write(chip, addr, alen, buffer, len, 1);
+	if (ret) {
+		debug("MXS I2C: Failed writing address\n");
+		return ret;
+	}
+
 	ret = mxs_i2c_wait_for_ack();
 	if (ret)
 		debug("MXS I2C: Failed writing address\n");
@@ -204,8 +228,9 @@
 int i2c_probe(uchar chip)
 {
 	int ret;
-	mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
-	ret = mxs_i2c_wait_for_ack();
+	ret = mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
+	if (!ret)
+		ret = mxs_i2c_wait_for_ack();
 	mxs_i2c_reset();
 	return ret;
 }
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index c784004..a39b591 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -32,6 +32,10 @@
  * - Status functions now read irqstatus_raw as per TRM guidelines
  *   (except for OMAP243X and OMAP34XX).
  * - Driver now supports up to I2C5 (OMAP5).
+ *
+ * Copyright (c) 2014 Hannes Petermaier <oe5hpm@oevsv.at>, B&R
+ * - Added support for set_speed
+ *
  */
 
 #include <common.h>
@@ -53,43 +57,66 @@
 static struct i2c *omap24_get_base(struct i2c_adapter *adap);
 static u16 wait_for_event(struct i2c_adapter *adap);
 static void flush_fifo(struct i2c_adapter *adap);
+static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
+{
+	unsigned int sampleclk, prescaler;
+	int fsscll, fssclh;
 
-static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+	speed <<= 1;
+	prescaler = 0;
+	/*
+	 * some divisors may cause a precission loss, but shouldn't
+	 * be a big thing, because i2c_clk is then allready very slow.
+	 */
+	while (prescaler <= 0xFF) {
+		sampleclk = I2C_IP_CLK / (prescaler+1);
+
+		fsscll = sampleclk / speed;
+		fssclh = fsscll;
+		fsscll -= I2C_FASTSPEED_SCLL_TRIM;
+		fssclh -= I2C_FASTSPEED_SCLH_TRIM;
+
+		if (((fsscll > 0) && (fssclh > 0)) &&
+		    ((fsscll <= (255-I2C_FASTSPEED_SCLL_TRIM)) &&
+		    (fssclh <= (255-I2C_FASTSPEED_SCLH_TRIM)))) {
+			if (pscl)
+				*pscl = fsscll;
+			if (psch)
+				*psch = fssclh;
+
+			return prescaler;
+		}
+		prescaler++;
+	}
+	return -1;
+}
+static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
 {
 	struct i2c *i2c_base = omap24_get_base(adap);
-	int psc, fsscll, fssclh;
+	int psc, fsscll = 0, fssclh = 0;
 	int hsscll = 0, hssclh = 0;
-	u32 scll, sclh;
-	int timeout = I2C_TIMEOUT;
+	u32 scll = 0, sclh = 0;
 
-	/* Only handle standard, fast and high speeds */
-	if ((speed != OMAP_I2C_STANDARD) &&
-	    (speed != OMAP_I2C_FAST_MODE) &&
-	    (speed != OMAP_I2C_HIGH_SPEED)) {
-		printf("Error : I2C unsupported speed %d\n", speed);
-		return;
-	}
-
-	psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
-	psc -= 1;
-	if (psc < I2C_PSC_MIN) {
-		printf("Error : I2C unsupported prescalar %d\n", psc);
-		return;
-	}
-
-	if (speed == OMAP_I2C_HIGH_SPEED) {
+	if (speed >= OMAP_I2C_HIGH_SPEED) {
 		/* High speed */
+		psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
+		psc -= 1;
+		if (psc < I2C_PSC_MIN) {
+			printf("Error : I2C unsupported prescaler %d\n", psc);
+			return -1;
+		}
 
 		/* For first phase of HS mode */
-		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK /
-			(2 * OMAP_I2C_FAST_MODE);
+		fsscll = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
+
+		fssclh = fsscll;
 
 		fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
 		fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
 		if (((fsscll < 0) || (fssclh < 0)) ||
 		    ((fsscll > 255) || (fssclh > 255))) {
 			puts("Error : I2C initializing first phase clock\n");
-			return;
+			return -1;
 		}
 
 		/* For second phase of HS mode */
@@ -100,7 +127,7 @@
 		if (((fsscll < 0) || (fssclh < 0)) ||
 		    ((fsscll > 255) || (fssclh > 255))) {
 			puts("Error : I2C initializing second phase clock\n");
-			return;
+			return -1;
 		}
 
 		scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll;
@@ -108,20 +135,29 @@
 
 	} else {
 		/* Standard and fast speed */
-		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
-
-		fsscll -= I2C_FASTSPEED_SCLL_TRIM;
-		fssclh -= I2C_FASTSPEED_SCLH_TRIM;
-		if (((fsscll < 0) || (fssclh < 0)) ||
-		    ((fsscll > 255) || (fssclh > 255))) {
+		psc = omap24_i2c_findpsc(&scll, &sclh, speed);
+		if (0 > psc) {
 			puts("Error : I2C initializing clock\n");
-			return;
+			return -1;
 		}
-
-		scll = (unsigned int)fsscll;
-		sclh = (unsigned int)fssclh;
 	}
 
+	adap->speed	= speed;
+	adap->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */
+	writew(0, &i2c_base->con);
+	writew(psc, &i2c_base->psc);
+	writew(scll, &i2c_base->scll);
+	writew(sclh, &i2c_base->sclh);
+	writew(I2C_CON_EN, &i2c_base->con);
+	writew(0xFFFF, &i2c_base->stat);	/* clear all pending status */
+
+	return 0;
+}
+static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+{
+	struct i2c *i2c_base = omap24_get_base(adap);
+	int timeout = I2C_TIMEOUT;
+
 	if (readw(&i2c_base->con) & I2C_CON_EN) {
 		writew(0, &i2c_base->con);
 		udelay(50000);
@@ -139,14 +175,14 @@
 		udelay(1000);
 	}
 
-	writew(0, &i2c_base->con);
-	writew(psc, &i2c_base->psc);
-	writew(scll, &i2c_base->scll);
-	writew(sclh, &i2c_base->sclh);
+	if (0 != omap24_i2c_setspeed(adap, speed)) {
+		printf("ERROR: failed to setup I2C bus-speed!\n");
+		return;
+	}
 
 	/* own address */
 	writew(slaveadd, &i2c_base->oa);
-	writew(I2C_CON_EN, &i2c_base->con);
+
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
 	/*
 	 * Have to enable interrupts for OMAP2/3, these IPs don't have
@@ -165,7 +201,8 @@
 	struct i2c *i2c_base = omap24_get_base(adap);
 	u16 stat;
 
-	/* note: if you try and read data when its not there or ready
+	/*
+	 * note: if you try and read data when its not there or ready
 	 * you get a bus error
 	 */
 	while (1) {
@@ -220,8 +257,8 @@
 
 	/* Check for ACK (!NAK) */
 	if (!(status & I2C_STAT_NACK)) {
-		res = 0;			/* Device found */
-		udelay(I2C_WAIT);		/* Required by AM335X in SPL */
+		res = 0;				/* Device found */
+		udelay(adap->waitdelay);/* Required by AM335X in SPL */
 		/* Abort transfer (force idle state) */
 		writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
 		udelay(1000);
@@ -307,7 +344,7 @@
 				       adap->hwadapnr, status);
 				goto rd_exit;
 			}
-			if (status == 0 || status & I2C_STAT_NACK) {
+			if (status == 0 || (status & I2C_STAT_NACK)) {
 				i2c_error = 1;
 				printf("i2c_read: error waiting for addr ACK (status=0x%x)\n",
 				       status);
@@ -351,7 +388,7 @@
 			       adap->hwadapnr, status);
 			goto rd_exit;
 		}
-		if (status == 0 || status & I2C_STAT_NACK) {
+		if (status == 0 || (status & I2C_STAT_NACK)) {
 			i2c_error = 1;
 			goto rd_exit;
 		}
@@ -379,6 +416,7 @@
 	int i;
 	u16 status;
 	int i2c_error = 0;
+	int timeout = I2C_TIMEOUT;
 
 	if (alen < 0) {
 		puts("I2C write: addr len < 0\n");
@@ -428,7 +466,7 @@
 			       adap->hwadapnr, status);
 			goto wr_exit;
 		}
-		if (status == 0 || status & I2C_STAT_NACK) {
+		if (status == 0 || (status & I2C_STAT_NACK)) {
 			i2c_error = 1;
 			printf("i2c_write: error waiting for addr ACK (status=0x%x)\n",
 			       status);
@@ -448,7 +486,7 @@
 	/* Address phase is over, now write data */
 	for (i = 0; i < len; i++) {
 		status = wait_for_event(adap);
-		if (status == 0 || status & I2C_STAT_NACK) {
+		if (status == 0 || (status & I2C_STAT_NACK)) {
 			i2c_error = 1;
 			printf("i2c_write: error waiting for data ACK (status=0x%x)\n",
 			       status);
@@ -464,6 +502,15 @@
 			goto wr_exit;
 		}
 	}
+	/*
+	 * poll ARDY bit for making sure that last byte really has been
+	 * transferred on the bus.
+	 */
+	do {
+		status = wait_for_event(adap);
+	} while (!(status & I2C_STAT_ARDY) && timeout--);
+	if (timeout <= 0)
+		printf("i2c_write: timed out writig last byte!\n");
 
 wr_exit:
 	flush_fifo(adap);
@@ -490,7 +537,7 @@
 		I2C_STAT_BB) && timeout--) {
 #endif
 		writew(stat, &i2c_base->stat);
-		udelay(I2C_WAIT);
+		udelay(adap->waitdelay);
 	}
 
 	if (timeout <= 0) {
@@ -513,7 +560,7 @@
 	int timeout = I2C_TIMEOUT;
 
 	do {
-		udelay(I2C_WAIT);
+		udelay(adap->waitdelay);
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
 		status = readw(&i2c_base->stat);
 #else
@@ -580,12 +627,12 @@
 #endif
 
 U_BOOT_I2C_ADAP_COMPLETE(omap24_0, omap24_i2c_init, omap24_i2c_probe,
-			 omap24_i2c_read, omap24_i2c_write, NULL,
+			 omap24_i2c_read, omap24_i2c_write, omap24_i2c_setspeed,
 			 CONFIG_SYS_OMAP24_I2C_SPEED,
 			 CONFIG_SYS_OMAP24_I2C_SLAVE,
 			 0)
 U_BOOT_I2C_ADAP_COMPLETE(omap24_1, omap24_i2c_init, omap24_i2c_probe,
-			 omap24_i2c_read, omap24_i2c_write, NULL,
+			 omap24_i2c_read, omap24_i2c_write, omap24_i2c_setspeed,
 			 CONFIG_SYS_OMAP24_I2C_SPEED1,
 			 CONFIG_SYS_OMAP24_I2C_SLAVE1,
 			 1)
diff --git a/drivers/i2c/zynq_i2c.c b/drivers/i2c/zynq_i2c.c
index 70a9aea..f1f6513 100644
--- a/drivers/i2c/zynq_i2c.c
+++ b/drivers/i2c/zynq_i2c.c
@@ -64,19 +64,21 @@
 #define ZYNQ_I2C_FIFO_DEPTH		16
 #define ZYNQ_I2C_TRANSFERT_SIZE_MAX	255 /* Controller transfer limit */
 
-#if defined(CONFIG_ZYNQ_I2C0)
-# define ZYNQ_I2C_BASE	ZYNQ_I2C_BASEADDR0
-#else
-# define ZYNQ_I2C_BASE	ZYNQ_I2C_BASEADDR1
-#endif
-
-static struct zynq_i2c_registers *zynq_i2c =
-	(struct zynq_i2c_registers *)ZYNQ_I2C_BASE;
+static struct zynq_i2c_registers *i2c_select(struct i2c_adapter *adap)
+{
+	return adap->hwadapnr ?
+		/* Zynq PS I2C1 */
+		(struct zynq_i2c_registers *)ZYNQ_I2C_BASEADDR1 :
+		/* Zynq PS I2C0 */
+		(struct zynq_i2c_registers *)ZYNQ_I2C_BASEADDR0;
+}
 
 /* I2C init called by cmd_i2c when doing 'i2c reset'. */
 static void zynq_i2c_init(struct i2c_adapter *adap, int requested_speed,
 			  int slaveadd)
 {
+	struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
+
 	/* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */
 	writel((16 << ZYNQ_I2C_CONTROL_DIV_B_SHIFT) |
 		(2 << ZYNQ_I2C_CONTROL_DIV_A_SHIFT), &zynq_i2c->control);
@@ -87,7 +89,7 @@
 }
 
 #ifdef DEBUG
-static void zynq_i2c_debug_status(void)
+static void zynq_i2c_debug_status(struct zynq_i2c_registers *zynq_i2c)
 {
 	int int_status;
 	int status;
@@ -129,7 +131,7 @@
 #endif
 
 /* Wait for an interrupt */
-static u32 zynq_i2c_wait(u32 mask)
+static u32 zynq_i2c_wait(struct zynq_i2c_registers *zynq_i2c, u32 mask)
 {
 	int timeout, int_status;
 
@@ -140,7 +142,7 @@
 			break;
 	}
 #ifdef DEBUG
-	zynq_i2c_debug_status();
+	zynq_i2c_debug_status(zynq_i2c));
 #endif
 	/* Clear interrupt status flags */
 	writel(int_status & mask, &zynq_i2c->interrupt_status);
@@ -154,6 +156,8 @@
  */
 static int zynq_i2c_probe(struct i2c_adapter *adap, u8 dev)
 {
+	struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
+
 	/* Attempt to read a byte */
 	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
 		ZYNQ_I2C_CONTROL_RW);
@@ -162,7 +166,7 @@
 	writel(dev, &zynq_i2c->address);
 	writel(1, &zynq_i2c->transfer_size);
 
-	return (zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP |
+	return (zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP |
 		ZYNQ_I2C_INTERRUPT_NACK) &
 		ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT;
 }
@@ -177,6 +181,7 @@
 	u32 status;
 	u32 i = 0;
 	u8 *cur_data = data;
+	struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
 
 	/* Check the hardware can handle the requested bytes */
 	if ((length < 0) || (length > ZYNQ_I2C_TRANSFERT_SIZE_MAX))
@@ -189,20 +194,22 @@
 	 * Temporarily disable restart (by clearing hold)
 	 * It doesn't seem to work.
 	 */
-	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW |
-		ZYNQ_I2C_CONTROL_HOLD);
+	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
 	writel(0xFF, &zynq_i2c->interrupt_status);
-	while (alen--)
-		writel(addr >> (8*alen), &zynq_i2c->data);
-	writel(dev, &zynq_i2c->address);
+	if (alen) {
+		clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW);
+		writel(dev, &zynq_i2c->address);
+		while (alen--)
+			writel(addr >> (8 * alen), &zynq_i2c->data);
 
-	/* Wait for the address to be sent */
-	if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) {
-		/* Release the bus */
-		clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
-		return -ETIMEDOUT;
+		/* Wait for the address to be sent */
+		if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
+			/* Release the bus */
+			clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
+			return -ETIMEDOUT;
+		}
+		debug("Device acked address\n");
 	}
-	debug("Device acked address\n");
 
 	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
 		ZYNQ_I2C_CONTROL_RW);
@@ -212,7 +219,7 @@
 
 	/* Wait for data */
 	do {
-		status = zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP |
+		status = zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP |
 			ZYNQ_I2C_INTERRUPT_DATA);
 		if (!status) {
 			/* Release the bus */
@@ -241,27 +248,30 @@
 			  int alen, u8 *data, int length)
 {
 	u8 *cur_data = data;
+	struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
 
 	/* Write the register address */
 	setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
 		ZYNQ_I2C_CONTROL_HOLD);
 	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW);
 	writel(0xFF, &zynq_i2c->interrupt_status);
-	while (alen--)
-		writel(addr >> (8*alen), &zynq_i2c->data);
-	/* Start the tranfer */
 	writel(dev, &zynq_i2c->address);
-	if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) {
-		/* Release the bus */
-		clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
-		return -ETIMEDOUT;
+	if (alen) {
+		while (alen--)
+			writel(addr >> (8 * alen), &zynq_i2c->data);
+		/* Start the tranfer */
+		if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
+			/* Release the bus */
+			clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
+			return -ETIMEDOUT;
+		}
+		debug("Device acked address\n");
 	}
 
-	debug("Device acked address\n");
 	while (length--) {
 		writel(*(cur_data++), &zynq_i2c->data);
 		if (readl(&zynq_i2c->transfer_size) == ZYNQ_I2C_FIFO_DEPTH) {
-			if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) {
+			if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
 				/* Release the bus */
 				clrbits_le32(&zynq_i2c->control,
 					     ZYNQ_I2C_CONTROL_HOLD);
@@ -273,7 +283,7 @@
 	/* All done... release the bus */
 	clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
 	/* Wait for the address and data to be sent */
-	if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP))
+	if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP))
 		return -ETIMEDOUT;
 	return 0;
 }
@@ -291,3 +301,7 @@
 			 zynq_i2c_write, zynq_i2c_set_bus_speed,
 			 CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE,
 			 0)
+U_BOOT_I2C_ADAP_COMPLETE(zynq_1, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read,
+			 zynq_i2c_write, zynq_i2c_set_bus_speed,
+			 CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE,
+			 1)
diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c
index 2631174..bd9b641 100644
--- a/drivers/mmc/bfin_sdh.c
+++ b/drivers/mmc/bfin_sdh.c
@@ -15,6 +15,7 @@
 #include <asm/errno.h>
 #include <asm/byteorder.h>
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/sdh.h>
 #include <asm/mach-common/bits/dma.h>
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 42e208c..0c2d2ef 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -16,6 +16,7 @@
 #include <linux/mii.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/dma.h>
 #include <asm/mach-common/bits/emac.h>
diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c
index aa89d89..71a31d0 100644
--- a/drivers/spi/bfin_spi.c
+++ b/drivers/spi/bfin_spi.c
@@ -13,6 +13,7 @@
 #include <spi.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/gpio.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/spi.h>
@@ -140,12 +141,12 @@
 void spi_set_speed(struct spi_slave *slave, uint hz)
 {
 	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
-	ulong sclk;
+	ulong clk;
 	u32 baud;
 
-	sclk = get_sclk();
+	clk = get_spi_clk();
 	/* baud should be rounded up */
-	baud = DIV_ROUND_UP(sclk, 2 * hz);
+	baud = DIV_ROUND_UP(clk, 2 * hz);
 	if (baud < 2)
 		baud = 2;
 	else if (baud > (u16)-1)
diff --git a/drivers/spi/bfin_spi6xx.c b/drivers/spi/bfin_spi6xx.c
index 07b833d..eba01d1 100644
--- a/drivers/spi/bfin_spi6xx.c
+++ b/drivers/spi/bfin_spi6xx.c
@@ -22,6 +22,7 @@
 #include <spi.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/gpio.h>
 #include <asm/portmux.h>
 #include <asm/mach-common/bits/spi6xx.h>
@@ -135,11 +136,11 @@
 void spi_set_speed(struct spi_slave *slave, uint hz)
 {
 	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
-	ulong sclk;
+	ulong clk;
 	u32 clock;
 
-	sclk = get_sclk1();
-	clock = sclk / hz;
+	clk = get_spi_clk();
+	clock = clk / hz;
 	if (clock)
 		clock--;
 	bss->clock = clock;
diff --git a/drivers/usb/musb/blackfin_usb.c b/drivers/usb/musb/blackfin_usb.c
index 35268ba..65fff88 100644
--- a/drivers/usb/musb/blackfin_usb.c
+++ b/drivers/usb/musb/blackfin_usb.c
@@ -11,6 +11,7 @@
 #include <usb.h>
 
 #include <asm/blackfin.h>
+#include <asm/clock.h>
 #include <asm/mach-common/bits/usb.h>
 
 #include "musb_core.h"
diff --git a/include/configs/spear-common.h b/include/configs/spear-common.h
index e090a37..c0eba37 100644
--- a/include/configs/spear-common.h
+++ b/include/configs/spear-common.h
@@ -39,6 +39,15 @@
 /* I2C driver configuration */
 #define CONFIG_HARD_I2C
 #define CONFIG_DW_I2C
+#if defined(CONFIG_SPEAR600)
+#define CONFIG_SYS_I2C_BASE			0xD0200000
+#elif defined(CONFIG_SPEAR300)
+#define CONFIG_SYS_I2C_BASE			0xD0180000
+#elif defined(CONFIG_SPEAR310)
+#define CONFIG_SYS_I2C_BASE			0xD0180000
+#elif defined(CONFIG_SPEAR320)
+#define CONFIG_SYS_I2C_BASE			0xD0180000
+#endif
 #define CONFIG_SYS_I2C_SPEED			400000
 #define CONFIG_SYS_I2C_SLAVE			0x02
 
diff --git a/include/configs/x600.h b/include/configs/x600.h
index d420efe..7405419 100644
--- a/include/configs/x600.h
+++ b/include/configs/x600.h
@@ -85,6 +85,7 @@
 /* I2C config options */
 #define CONFIG_HARD_I2C
 #define CONFIG_DW_I2C
+#define CONFIG_SYS_I2C_BASE			0xD0200000
 #define CONFIG_SYS_I2C_SPEED			400000
 #define CONFIG_SYS_I2C_SLAVE			0x02
 #define CONFIG_I2C_CHIPADDRESS			0x50
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index c7eee0a..14f0b90 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -89,13 +89,13 @@
 # define CONFIG_DOS_PARTITION
 #endif
 
+#define CONFIG_SYS_I2C_ZYNQ
 /* I2C */
-#if defined(CONFIG_ZYNQ_I2C0) || defined(CONFIG_ZYNQ_I2C1)
+#if defined(CONFIG_SYS_I2C_ZYNQ)
 # define CONFIG_CMD_I2C
 # define CONFIG_SYS_I2C
-# define CONFIG_SYS_I2C_ZYNQ
 # define CONFIG_SYS_I2C_ZYNQ_SPEED		100000
-# define CONFIG_SYS_I2C_ZYNQ_SLAVE		1
+# define CONFIG_SYS_I2C_ZYNQ_SLAVE		0
 #endif
 
 /* EEPROM */
diff --git a/include/i2c.h b/include/i2c.h
index f93a183..1b4078e 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -68,6 +68,7 @@
 	uint		(*set_bus_speed)(struct i2c_adapter *adap,
 				uint speed);
 	int		speed;
+	int		waitdelay;
 	int		slaveaddr;
 	int		init_done;
 	int		hwadapnr;