Merge branch 'master' of git://git.denx.de/u-boot-i2c
diff --git a/README b/README
index 09662a4..f0eedbb 100644
--- a/README
+++ b/README
@@ -1994,15 +1994,40 @@
 		    second bus.
 
 		- drivers/i2c/tegra_i2c.c:
-		 - activate this driver with CONFIG_SYS_I2C_TEGRA
-		 - This driver adds 4 i2c buses with a fix speed from
-		   100000 and the slave addr 0!
+		  - activate this driver with CONFIG_SYS_I2C_TEGRA
+		  - This driver adds 4 i2c buses with a fix speed from
+		    100000 and the slave addr 0!
 
 		- drivers/i2c/ppc4xx_i2c.c
 		  - activate this driver with CONFIG_SYS_I2C_PPC4XX
 		  - CONFIG_SYS_I2C_PPC4XX_CH0 activate hardware channel 0
 		  - CONFIG_SYS_I2C_PPC4XX_CH1 activate hardware channel 1
 
+		- drivers/i2c/i2c_mxc.c
+		  - activate this driver with CONFIG_SYS_I2C_MXC
+		  - define speed for bus 1 with CONFIG_SYS_MXC_I2C1_SPEED
+		  - define slave for bus 1 with CONFIG_SYS_MXC_I2C1_SLAVE
+		  - define speed for bus 2 with CONFIG_SYS_MXC_I2C2_SPEED
+		  - define slave for bus 2 with CONFIG_SYS_MXC_I2C2_SLAVE
+		  - define speed for bus 3 with CONFIG_SYS_MXC_I2C3_SPEED
+		  - define slave for bus 3 with CONFIG_SYS_MXC_I2C3_SLAVE
+		If thoses defines are not set, default value is 100000
+		for speed, and 0 for slave.
+
+		- drivers/i2c/rcar_i2c.c:
+		  - activate this driver with CONFIG_SYS_I2C_RCAR
+		  - This driver adds 4 i2c buses
+
+		  - CONFIG_SYS_RCAR_I2C0_BASE for setting the register channel 0
+		  - CONFIG_SYS_RCAR_I2C0_SPEED for for the speed channel 0
+		  - CONFIG_SYS_RCAR_I2C1_BASE for setting the register channel 1
+		  - CONFIG_SYS_RCAR_I2C1_SPEED for for the speed channel 1
+		  - CONFIG_SYS_RCAR_I2C2_BASE for setting the register channel 2
+		  - CONFIG_SYS_RCAR_I2C2_SPEED for for the speed channel 2
+		  - CONFIG_SYS_RCAR_I2C3_BASE for setting the register channel 3
+		  - CONFIG_SYS_RCAR_I2C3_SPEED for for the speed channel 3
+		  - CONFIF_SYS_RCAR_I2C_NUM_CONTROLLERS for number of i2c buses
+
 		additional defines:
 
 		CONFIG_SYS_NUM_I2C_BUSES
diff --git a/arch/arm/cpu/armv7/mx5/clock.c b/arch/arm/cpu/armv7/mx5/clock.c
index 6bef254..fb3b128 100644
--- a/arch/arm/cpu/armv7/mx5/clock.c
+++ b/arch/arm/cpu/armv7/mx5/clock.c
@@ -94,7 +94,7 @@
 			MXC_CCM_CCGR2_USBOH3_60M(cg));
 }
 
-#ifdef CONFIG_I2C_MXC
+#ifdef CONFIG_SYS_I2C_MXC
 /* i2c_num can be from 0, to 1 for i.MX51 and 2 for i.MX53 */
 int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
 {
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c
index df11678..cf3a38e 100644
--- a/arch/arm/cpu/armv7/mx6/clock.c
+++ b/arch/arm/cpu/armv7/mx6/clock.c
@@ -48,7 +48,7 @@
 
 }
 
-#ifdef CONFIG_I2C_MXC
+#ifdef CONFIG_SYS_I2C_MXC
 /* i2c_num can be from 0 - 2 */
 int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
 {
diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile
index 727a052..6c78dd9 100644
--- a/arch/arm/imx-common/Makefile
+++ b/arch/arm/imx-common/Makefile
@@ -16,7 +16,7 @@
 endif
 ifeq ($(SOC),$(filter $(SOC),mx5 mx6))
 COBJS-y	+= timer.o cpu.o speed.o
-COBJS-$(CONFIG_I2C_MXC) += i2c-mxv7.o
+COBJS-$(CONFIG_SYS_I2C_MXC) += i2c-mxv7.o
 endif
 ifeq ($(SOC),$(filter $(SOC),mx6 mxs))
 COBJS-y	+= misc.o
diff --git a/common/board_f.c b/common/board_f.c
index 0ada1af..f0664bc 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -249,7 +249,11 @@
 static int init_func_i2c(void)
 {
 	puts("I2C:   ");
+#ifdef CONFIG_SYS_I2C
+	i2c_init_all();
+#else
 	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+#endif
 	puts("ready\n");
 	return 0;
 }
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index df3092e..84a2754 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -14,7 +14,6 @@
 COBJS-$(CONFIG_DW_I2C) += designware_i2c.o
 COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o
 COBJS-$(CONFIG_I2C_MV) += mv_i2c.o
-COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o
 COBJS-$(CONFIG_I2C_MXS) += mxs_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o
 COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o
@@ -28,7 +27,9 @@
 COBJS-$(CONFIG_SYS_I2C) += i2c_core.o
 COBJS-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
 COBJS-$(CONFIG_SYS_I2C_FTI2C010) += fti2c010.o
+COBJS-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
 COBJS-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o
+COBJS-$(CONFIG_SYS_I2C_RCAR) += rcar_i2c.o
 COBJS-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
 COBJS-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o
 COBJS-$(CONFIG_ZYNQ_I2C) += zynq_i2c.o
diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
index d1072e8..e1767f4 100644
--- a/drivers/i2c/i2c_core.c
+++ b/drivers/i2c/i2c_core.c
@@ -53,32 +53,26 @@
 		return;
 
 	for (i = 0; i < max; i++) {
-		/* adapter itself */
-		addr = (unsigned long)i2c_adap_p;
-		addr += gd->reloc_off;
-		i2c_adap_p = (struct i2c_adapter *)addr;
 		/* i2c_init() */
 		addr = (unsigned long)i2c_adap_p->init;
 		addr += gd->reloc_off;
-		i2c_adap_p->init = (void (*)(int, int))addr;
+		i2c_adap_p->init = (void *)addr;
 		/* i2c_probe() */
 		addr = (unsigned long)i2c_adap_p->probe;
 		addr += gd->reloc_off;
-		i2c_adap_p->probe = (int (*)(uint8_t))addr;
+		i2c_adap_p->probe = (void *)addr;
 		/* i2c_read() */
 		addr = (unsigned long)i2c_adap_p->read;
 		addr += gd->reloc_off;
-		i2c_adap_p->read = (int (*)(uint8_t, uint, int, uint8_t *,
-					int))addr;
+		i2c_adap_p->read = (void *)addr;
 		/* i2c_write() */
 		addr = (unsigned long)i2c_adap_p->write;
 		addr += gd->reloc_off;
-		i2c_adap_p->write = (int (*)(uint8_t, uint, int, uint8_t *,
-					int))addr;
+		i2c_adap_p->write = (void *)addr;
 		/* i2c_set_bus_speed() */
 		addr = (unsigned long)i2c_adap_p->set_bus_speed;
 		addr += gd->reloc_off;
-		i2c_adap_p->set_bus_speed = (uint (*)(uint))addr;
+		i2c_adap_p->set_bus_speed = (void *)addr;
 		/* name */
 		addr = (unsigned long)i2c_adap_p->name;
 		addr += gd->reloc_off;
@@ -138,6 +132,11 @@
 			return -1;
 		buf = (uint8_t)((channel & 0x07) | (1 << 3));
 		break;
+	case I2C_MUX_PCA9548_ID:
+		if (channel > 7)
+			return -1;
+		buf = (uint8_t)(0x01 << channel);
+		break;
 	default:
 		printf("%s: wrong mux id: %d\n", __func__, mux_id);
 		return -1;
@@ -278,20 +277,22 @@
  */
 int i2c_set_bus_num(unsigned int bus)
 {
-	int max = ll_entry_count(struct i2c_adapter, i2c);
+	int max;
 
-	if (I2C_ADAPTER(bus) >= max) {
-		printf("Error, wrong i2c adapter %d max %d possible\n",
-		       I2C_ADAPTER(bus), max);
-		return -2;
-	}
+	if ((bus == I2C_BUS) && (I2C_ADAP->init_done > 0))
+		return 0;
+
 #ifndef CONFIG_SYS_I2C_DIRECT_BUS
 	if (bus >= CONFIG_SYS_NUM_I2C_BUSES)
 		return -1;
 #endif
 
-	if ((bus == I2C_BUS) && (I2C_ADAP->init_done > 0))
-		return 0;
+	max = ll_entry_count(struct i2c_adapter, i2c);
+	if (I2C_ADAPTER(bus) >= max) {
+		printf("Error, wrong i2c adapter %d max %d possible\n",
+		       I2C_ADAPTER(bus), max);
+		return -2;
+	}
 
 #ifndef CONFIG_SYS_I2C_DIRECT_BUS
 	i2c_mux_disconnet_all();
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 06ba4e3..595019b 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -102,6 +102,28 @@
 };
 #endif
 
+
+#ifndef CONFIG_SYS_MXC_I2C1_SPEED
+#define CONFIG_SYS_MXC_I2C1_SPEED 100000
+#endif
+#ifndef CONFIG_SYS_MXC_I2C2_SPEED
+#define CONFIG_SYS_MXC_I2C2_SPEED 100000
+#endif
+#ifndef CONFIG_SYS_MXC_I2C3_SPEED
+#define CONFIG_SYS_MXC_I2C3_SPEED 100000
+#endif
+
+#ifndef CONFIG_SYS_MXC_I2C1_SLAVE
+#define CONFIG_SYS_MXC_I2C1_SLAVE 0
+#endif
+#ifndef CONFIG_SYS_MXC_I2C2_SLAVE
+#define CONFIG_SYS_MXC_I2C2_SLAVE 0
+#endif
+#ifndef CONFIG_SYS_MXC_I2C3_SLAVE
+#define CONFIG_SYS_MXC_I2C3_SLAVE 0
+#endif
+
+
 /*
  * Calculate and set proper clock divider
  */
@@ -153,21 +175,6 @@
 	return 0;
 }
 
-/*
- * Get I2C Speed
- */
-static unsigned int bus_i2c_get_bus_speed(void *base)
-{
-	struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base;
-	u8 clk_idx = readb(&i2c_regs->ifdr);
-	u8 clk_div;
-
-	for (clk_div = 0; i2c_clk_div[clk_div][1] != clk_idx; clk_div++)
-		;
-
-	return mxc_get_clock(MXC_I2C_CLK) / i2c_clk_div[clk_div][0];
-}
-
 #define ST_BUS_IDLE (0 | (I2SR_IBB << 8))
 #define ST_BUS_BUSY (I2SR_IBB | (I2SR_IBB << 8))
 #define ST_IIF (I2SR_IIF | (I2SR_IIF << 8))
@@ -410,20 +417,30 @@
  */
 static struct sram_data __attribute__((section(".data"))) srdata;
 
-void *get_base(void)
-{
-#ifdef CONFIG_SYS_I2C_BASE
-#ifdef CONFIG_I2C_MULTI_BUS
-	void *ret = srdata.i2c_data[srdata.curr_i2c_bus].base;
-	if (ret)
-		return ret;
-#endif
-	return (void *)CONFIG_SYS_I2C_BASE;
-#elif defined(CONFIG_I2C_MULTI_BUS)
-	return srdata.i2c_data[srdata.curr_i2c_bus].base;
+static void * const i2c_bases[] = {
+#if defined(CONFIG_MX25)
+	(void *)IMX_I2C_BASE,
+	(void *)IMX_I2C2_BASE,
+	(void *)IMX_I2C3_BASE
+#elif defined(CONFIG_MX27)
+	(void *)IMX_I2C1_BASE,
+	(void *)IMX_I2C2_BASE
+#elif defined(CONFIG_MX31) || defined(CONFIG_MX35) || \
+	defined(CONFIG_MX51) || defined(CONFIG_MX53) ||	\
+	defined(CONFIG_MX6)
+	(void *)I2C1_BASE_ADDR,
+	(void *)I2C2_BASE_ADDR,
+	(void *)I2C3_BASE_ADDR
+#elif defined(CONFIG_VF610)
+	(void *)I2C0_BASE_ADDR
 #else
-	return srdata.i2c_data[0].base;
+#error "architecture not supported"
 #endif
+};
+
+void *i2c_get_base(struct i2c_adapter *adap)
+{
+	return i2c_bases[adap->hwadapnr];
 }
 
 static struct i2c_parms *i2c_get_parms(void *base)
@@ -447,40 +464,27 @@
 		return p->idle_bus_fn(p->idle_bus_data);
 	return 0;
 }
-
-#ifdef CONFIG_I2C_MULTI_BUS
-unsigned int i2c_get_bus_num(void)
-{
-	return srdata.curr_i2c_bus;
-}
-
-int i2c_set_bus_num(unsigned bus_idx)
-{
-	if (bus_idx >= ARRAY_SIZE(srdata.i2c_data))
-		return -1;
-	if (!srdata.i2c_data[bus_idx].base)
-		return -1;
-	srdata.curr_i2c_bus = bus_idx;
-	return 0;
-}
-#endif
 
-int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+static int mxc_i2c_read(struct i2c_adapter *adap, uint8_t chip,
+				uint addr, int alen, uint8_t *buffer,
+				int len)
 {
-	return bus_i2c_read(get_base(), chip, addr, alen, buf, len);
+	return bus_i2c_read(i2c_get_base(adap), chip, addr, alen, buffer, len);
 }
 
-int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+static int mxc_i2c_write(struct i2c_adapter *adap, uint8_t chip,
+				uint addr, int alen, uint8_t *buffer,
+				int len)
 {
-	return bus_i2c_write(get_base(), chip, addr, alen, buf, len);
+	return bus_i2c_write(i2c_get_base(adap), chip, addr, alen, buffer, len);
 }
 
 /*
  * Test if a chip at a given address responds (probe the chip)
  */
-int i2c_probe(uchar chip)
+static int mxc_i2c_probe(struct i2c_adapter *adap, uint8_t chip)
 {
-	return bus_i2c_write(get_base(), chip, 0, 0, NULL, 0);
+	return bus_i2c_write(i2c_get_base(adap), chip, 0, 0, NULL, 0);
 }
 
 void bus_i2c_init(void *base, int speed, int unused,
@@ -510,23 +514,38 @@
 /*
  * Init I2C Bus
  */
-void i2c_init(int speed, int unused)
+static void mxc_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
 {
-	bus_i2c_init(get_base(), speed, unused, NULL, NULL);
+	bus_i2c_init(i2c_get_base(adap), speed, slaveaddr, NULL, NULL);
 }
 
 /*
  * Set I2C Speed
  */
-int i2c_set_bus_speed(unsigned int speed)
+static uint mxc_i2c_set_bus_speed(struct i2c_adapter *adap, uint speed)
 {
-	return bus_i2c_set_bus_speed(get_base(), speed);
+	return bus_i2c_set_bus_speed(i2c_get_base(adap), speed);
 }
 
 /*
- * Get I2C Speed
+ * Register mxc i2c adapters
  */
-unsigned int i2c_get_bus_speed(void)
-{
-	return bus_i2c_get_bus_speed(get_base());
-}
+U_BOOT_I2C_ADAP_COMPLETE(mxc0, mxc_i2c_init, mxc_i2c_probe,
+			 mxc_i2c_read, mxc_i2c_write,
+			 mxc_i2c_set_bus_speed,
+			 CONFIG_SYS_MXC_I2C1_SPEED,
+			 CONFIG_SYS_MXC_I2C1_SLAVE, 0)
+U_BOOT_I2C_ADAP_COMPLETE(mxc1, mxc_i2c_init, mxc_i2c_probe,
+			 mxc_i2c_read, mxc_i2c_write,
+			 mxc_i2c_set_bus_speed,
+			 CONFIG_SYS_MXC_I2C2_SPEED,
+			 CONFIG_SYS_MXC_I2C2_SLAVE, 1)
+#if defined(CONFIG_MX31) || defined(CONFIG_MX35) ||\
+	defined(CONFIG_MX51) || defined(CONFIG_MX53) ||\
+	defined(CONFIG_MX6)
+U_BOOT_I2C_ADAP_COMPLETE(mxc2, mxc_i2c_init, mxc_i2c_probe,
+			 mxc_i2c_read, mxc_i2c_write,
+			 mxc_i2c_set_bus_speed,
+			 CONFIG_SYS_MXC_I2C3_SPEED,
+			 CONFIG_SYS_MXC_I2C3_SLAVE, 2)
+#endif
diff --git a/drivers/i2c/rcar_i2c.c b/drivers/i2c/rcar_i2c.c
new file mode 100644
index 0000000..ba2cadb
--- /dev/null
+++ b/drivers/i2c/rcar_i2c.c
@@ -0,0 +1,288 @@
+/*
+ * drivers/i2c/rcar_i2c.c
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rcar_i2c {
+	u32 icscr;
+	u32 icmcr;
+	u32 icssr;
+	u32 icmsr;
+	u32 icsier;
+	u32 icmier;
+	u32 icccr;
+	u32 icsar;
+	u32 icmar;
+	u32 icrxdtxd;
+	u32 icccr2;
+	u32 icmpr;
+	u32 ichpr;
+	u32 iclpr;
+};
+
+#define MCR_MDBS	0x80	/* non-fifo mode switch	*/
+#define MCR_FSCL	0x40	/* override SCL pin	*/
+#define MCR_FSDA	0x20	/* override SDA pin	*/
+#define MCR_OBPC	0x10	/* override pins	*/
+#define MCR_MIE		0x08	/* master if enable	*/
+#define MCR_TSBE	0x04
+#define MCR_FSB		0x02	/* force stop bit	*/
+#define MCR_ESG		0x01	/* en startbit gen.	*/
+
+#define MSR_MASK	0x7f
+#define MSR_MNR		0x40	/* nack received	*/
+#define MSR_MAL		0x20	/* arbitration lost	*/
+#define MSR_MST		0x10	/* sent a stop		*/
+#define MSR_MDE		0x08
+#define MSR_MDT		0x04
+#define MSR_MDR		0x02
+#define MSR_MAT		0x01	/* slave addr xfer done	*/
+
+static const struct rcar_i2c *i2c_dev[CONFIF_SYS_RCAR_I2C_NUM_CONTROLLERS] = {
+	(struct rcar_i2c *)CONFIG_SYS_RCAR_I2C0_BASE,
+	(struct rcar_i2c *)CONFIG_SYS_RCAR_I2C1_BASE,
+	(struct rcar_i2c *)CONFIG_SYS_RCAR_I2C2_BASE,
+	(struct rcar_i2c *)CONFIG_SYS_RCAR_I2C3_BASE,
+};
+
+static void rcar_i2c_raw_rw_common(struct rcar_i2c *dev, u8 chip, uint addr)
+{
+	/* set slave address */
+	writel(chip << 1, &dev->icmar);
+	/* set register address */
+	writel(addr, &dev->icrxdtxd);
+	/* clear status */
+	writel(0, &dev->icmsr);
+	/* start master send */
+	writel(MCR_MDBS | MCR_MIE | MCR_ESG, &dev->icmcr);
+
+	while ((readl(&dev->icmsr) & (MSR_MAT | MSR_MDE))
+		!= (MSR_MAT | MSR_MDE))
+		udelay(10);
+
+	/* clear ESG */
+	writel(MCR_MDBS | MCR_MIE, &dev->icmcr);
+	/* start SCLclk */
+	writel(~(MSR_MAT | MSR_MDE), &dev->icmsr);
+
+	while (!(readl(&dev->icmsr) & MSR_MDE))
+		udelay(10);
+}
+
+static void rcar_i2c_raw_rw_finish(struct rcar_i2c *dev)
+{
+	while (!(readl(&dev->icmsr) & MSR_MST))
+		udelay(10);
+
+	writel(0, &dev->icmcr);
+}
+
+static int
+rcar_i2c_raw_write(struct rcar_i2c *dev, u8 chip, uint addr, u8 *val, int size)
+{
+	rcar_i2c_raw_rw_common(dev, chip, addr);
+
+	/* set send date */
+	writel(*val, &dev->icrxdtxd);
+	/* start SCLclk */
+	writel(~MSR_MDE, &dev->icmsr);
+
+	while (!(readl(&dev->icmsr) & MSR_MDE))
+		udelay(10);
+
+	/* set stop condition */
+	writel(MCR_MDBS | MCR_MIE | MCR_FSB, &dev->icmcr);
+	/* start SCLclk */
+	writel(~MSR_MDE, &dev->icmsr);
+
+	rcar_i2c_raw_rw_finish(dev);
+
+	return 0;
+}
+
+static u8
+rcar_i2c_raw_read(struct rcar_i2c *dev, u8 chip, uint addr)
+{
+	u8 ret;
+
+	rcar_i2c_raw_rw_common(dev, chip, addr);
+
+	/* set slave address, receive */
+	writel((chip << 1) | 1, &dev->icmar);
+	/* start master receive */
+	writel(MCR_MDBS | MCR_MIE | MCR_ESG, &dev->icmcr);
+
+	while ((readl(&dev->icmsr) & (MSR_MAT | MSR_MDE))
+		!= (MSR_MAT | MSR_MDE))
+		udelay(10);
+
+	/* clear ESG */
+	writel(MCR_MDBS | MCR_MIE, &dev->icmcr);
+	/* prepare stop condition */
+	writel(MCR_MDBS | MCR_MIE | MCR_FSB, &dev->icmcr);
+	/* start SCLclk */
+	writel(~(MSR_MAT | MSR_MDR), &dev->icmsr);
+
+	while (!(readl(&dev->icmsr) & MSR_MDR))
+		udelay(10);
+
+	/* get receive data */
+	ret = (u8)readl(&dev->icrxdtxd);
+	/* start SCLclk */
+	writel(~MSR_MDR, &dev->icmsr);
+
+	rcar_i2c_raw_rw_finish(dev);
+
+	return ret;
+}
+
+/*
+ * SCL  = iicck / (20 + SCGD * 8 + F[(ticf + tr + intd) * iicck])
+ * iicck  : I2C internal clock < 20 MHz
+ * ticf : I2C SCL falling time: 35 ns
+ * tr   : I2C SCL rising time:  200 ns
+ * intd : LSI internal delay:   I2C0: 50 ns I2C1-3: 5
+ * F[n] : n rounded up to an integer
+ */
+static u32 rcar_clock_gen(int i2c_no, u32 bus_speed)
+{
+	u32 iicck, f, scl, scgd;
+	u32 intd = 5;
+
+	int bit = 0, cdf_width = 3;
+	for (bit = 0; bit < (1 << cdf_width); bit++) {
+		iicck = CONFIG_HP_CLK_FREQ / (1 + bit);
+		if (iicck < 20000000)
+			break;
+	}
+
+	if (bit > (1 << cdf_width)) {
+		puts("rcar-i2c: Can not get CDF\n");
+		return 0;
+	}
+
+	if (i2c_no == 0)
+		intd = 50;
+
+	f = (35 + 200 + intd) * (iicck / 1000000000);
+
+	for (scgd = 0; scgd < 0x40; scgd++) {
+		scl = iicck / (20 + (scgd * 8) + f);
+		if (scl <= bus_speed)
+			break;
+	}
+
+	if (scgd > 0x40) {
+		puts("rcar-i2c: Can not get SDGB\n");
+		return 0;
+	}
+
+	debug("%s: scl: %d\n", __func__, scl);
+	debug("%s: bit %x\n", __func__, bit);
+	debug("%s: scgd %x\n", __func__, scgd);
+	debug("%s: iccr %x\n", __func__, (scgd << (cdf_width) | bit));
+
+	return scgd << (cdf_width) | bit;
+}
+
+static void
+rcar_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
+{
+	struct rcar_i2c *dev = (struct rcar_i2c *)i2c_dev[adap->hwadapnr];
+	u32 icccr = 0;
+
+	/* No i2c support prior to relocation */
+	if (!(gd->flags & GD_FLG_RELOC))
+		return;
+
+	/*
+	 * reset slave mode.
+	 * slave mode is not used on this driver
+	 */
+	writel(0, &dev->icsier);
+	writel(0, &dev->icsar);
+	writel(0, &dev->icscr);
+	writel(0, &dev->icssr);
+
+	/* reset master mode */
+	writel(0, &dev->icmier);
+	writel(0, &dev->icmcr);
+	writel(0, &dev->icmsr);
+	writel(0, &dev->icmar);
+
+	icccr = rcar_clock_gen(adap->hwadapnr, adap->speed);
+	if (icccr == 0)
+		puts("I2C: Init failed\n");
+	else
+		writel(icccr, &dev->icccr);
+}
+
+static int rcar_i2c_read(struct i2c_adapter *adap, uint8_t chip,
+			uint addr, int alen, u8 *data, int len)
+{
+	struct rcar_i2c *dev = (struct rcar_i2c *)i2c_dev[adap->hwadapnr];
+	int i;
+
+	for (i = 0; i < len; i++)
+		data[i] = rcar_i2c_raw_read(dev, chip, addr + i);
+
+	return 0;
+}
+
+static int rcar_i2c_write(struct i2c_adapter *adap, uint8_t chip, uint addr,
+			int alen, u8 *data, int len)
+{
+	struct rcar_i2c *dev = (struct rcar_i2c *)i2c_dev[adap->hwadapnr];
+	return rcar_i2c_raw_write(dev, chip, addr, data, len);
+}
+
+static int
+rcar_i2c_probe(struct i2c_adapter *adap, u8 dev)
+{
+	return rcar_i2c_read(adap, dev, 0, 0, NULL, 0);
+}
+
+static unsigned int rcar_i2c_set_bus_speed(struct i2c_adapter *adap,
+			unsigned int speed)
+{
+	struct rcar_i2c *dev = (struct rcar_i2c *)i2c_dev[adap->hwadapnr];
+	u32 icccr;
+	int ret = 0;
+
+	rcar_i2c_raw_rw_finish(dev);
+
+	icccr = rcar_clock_gen(adap->hwadapnr, speed);
+	if (icccr == 0) {
+		puts("I2C: Init failed\n");
+		ret = -1;
+	} else {
+		writel(icccr, &dev->icccr);
+	}
+	return ret;
+}
+
+/*
+ * Register RCAR i2c adapters
+ */
+U_BOOT_I2C_ADAP_COMPLETE(rcar_0, rcar_i2c_init, rcar_i2c_probe, rcar_i2c_read,
+			 rcar_i2c_write, rcar_i2c_set_bus_speed,
+			 CONFIG_SYS_RCAR_I2C0_SPEED, 0, 0)
+U_BOOT_I2C_ADAP_COMPLETE(rcar_1, rcar_i2c_init, rcar_i2c_probe, rcar_i2c_read,
+			 rcar_i2c_write, rcar_i2c_set_bus_speed,
+			 CONFIG_SYS_RCAR_I2C1_SPEED, 0, 1)
+U_BOOT_I2C_ADAP_COMPLETE(rcar_2, rcar_i2c_init, rcar_i2c_probe, rcar_i2c_read,
+			 rcar_i2c_write, rcar_i2c_set_bus_speed,
+			 CONFIG_SYS_RCAR_I2C2_SPEED, 0, 2)
+U_BOOT_I2C_ADAP_COMPLETE(rcar_3, rcar_i2c_init, rcar_i2c_probe, rcar_i2c_read,
+			 rcar_i2c_write, rcar_i2c_set_bus_speed,
+			 CONFIG_SYS_RCAR_I2C3_SPEED, 0, 3)
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index cd09c78..f77a9d1 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -34,6 +34,76 @@
 #define I2C_NOK_LA	3	/* Lost arbitration */
 #define I2C_NOK_TOUT	4	/* time out */
 
+/* HSI2C specific register description */
+
+/* I2C_CTL Register bits */
+#define HSI2C_FUNC_MODE_I2C		(1u << 0)
+#define HSI2C_MASTER			(1u << 3)
+#define HSI2C_RXCHON			(1u << 6)	/* Write/Send */
+#define HSI2C_TXCHON			(1u << 7)	/* Read/Receive */
+#define HSI2C_SW_RST			(1u << 31)
+
+/* I2C_FIFO_CTL Register bits */
+#define HSI2C_RXFIFO_EN			(1u << 0)
+#define HSI2C_TXFIFO_EN			(1u << 1)
+#define HSI2C_TXFIFO_TRIGGER_LEVEL	(0x20 << 16)
+#define HSI2C_RXFIFO_TRIGGER_LEVEL	(0x20 << 4)
+
+/* I2C_TRAILING_CTL Register bits */
+#define HSI2C_TRAILING_COUNT		(0xff)
+
+/* I2C_INT_EN Register bits */
+#define HSI2C_TX_UNDERRUN_EN		(1u << 2)
+#define HSI2C_TX_OVERRUN_EN		(1u << 3)
+#define HSI2C_RX_UNDERRUN_EN		(1u << 4)
+#define HSI2C_RX_OVERRUN_EN		(1u << 5)
+#define HSI2C_INT_TRAILING_EN		(1u << 6)
+#define HSI2C_INT_I2C_EN		(1u << 9)
+
+#define HSI2C_INT_ERROR_MASK	(HSI2C_TX_UNDERRUN_EN |\
+				 HSI2C_TX_OVERRUN_EN  |\
+				 HSI2C_RX_UNDERRUN_EN |\
+				 HSI2C_RX_OVERRUN_EN  |\
+				 HSI2C_INT_TRAILING_EN)
+
+/* I2C_CONF Register bits */
+#define HSI2C_AUTO_MODE			(1u << 31)
+#define HSI2C_10BIT_ADDR_MODE		(1u << 30)
+#define HSI2C_HS_MODE			(1u << 29)
+
+/* I2C_AUTO_CONF Register bits */
+#define HSI2C_READ_WRITE		(1u << 16)
+#define HSI2C_STOP_AFTER_TRANS		(1u << 17)
+#define HSI2C_MASTER_RUN		(1u << 31)
+
+/* I2C_TIMEOUT Register bits */
+#define HSI2C_TIMEOUT_EN		(1u << 31)
+
+/* I2C_TRANS_STATUS register bits */
+#define HSI2C_MASTER_BUSY		(1u << 17)
+#define HSI2C_SLAVE_BUSY		(1u << 16)
+#define HSI2C_TIMEOUT_AUTO		(1u << 4)
+#define HSI2C_NO_DEV			(1u << 3)
+#define HSI2C_NO_DEV_ACK		(1u << 2)
+#define HSI2C_TRANS_ABORT		(1u << 1)
+#define HSI2C_TRANS_SUCCESS		(1u << 0)
+#define HSI2C_TRANS_ERROR_MASK	(HSI2C_TIMEOUT_AUTO |\
+				 HSI2C_NO_DEV | HSI2C_NO_DEV_ACK |\
+				 HSI2C_TRANS_ABORT)
+#define HSI2C_TRANS_FINISHED_MASK (HSI2C_TRANS_ERROR_MASK | HSI2C_TRANS_SUCCESS)
+
+
+/* I2C_FIFO_STAT Register bits */
+#define HSI2C_RX_FIFO_EMPTY		(1u << 24)
+#define HSI2C_RX_FIFO_FULL		(1u << 23)
+#define HSI2C_TX_FIFO_EMPTY		(1u << 8)
+#define HSI2C_TX_FIFO_FULL		(1u << 7)
+#define HSI2C_RX_FIFO_LEVEL(x)		(((x) >> 16) & 0x7f)
+#define HSI2C_TX_FIFO_LEVEL(x)		((x) & 0x7f)
+
+#define HSI2C_SLV_ADDR_MAS(x)		((x & 0x3ff) << 10)
+
+/* S3C I2C Controller bits */
 #define I2CSTAT_BSY	0x20	/* Busy bit */
 #define I2CSTAT_NACK	0x01	/* Nack bit */
 #define I2CCON_ACKGEN	0x80	/* Acknowledge generation */
@@ -43,19 +113,43 @@
 #define I2C_START_STOP	0x20	/* START / STOP */
 #define I2C_TXRX_ENA	0x10	/* I2C Tx/Rx enable */
 
+#define I2C_TIMEOUT_MS 1000		/* 1 second */
+
-#define I2C_TIMEOUT 1		/* 1 second */
+#define	HSI2C_TIMEOUT_US 100000 /* 100 ms, finer granularity */
 
 
+/* To support VCMA9 boards and other who dont define max_i2c_num */
+#ifndef CONFIG_MAX_I2C_NUM
+#define CONFIG_MAX_I2C_NUM 1
+#endif
+
 /*
  * For SPL boot some boards need i2c before SDRAM is initialised so force
  * variables to live in SRAM
  */
 static unsigned int g_current_bus __attribute__((section(".data")));
-#ifdef CONFIG_OF_CONTROL
-static int i2c_busses __attribute__((section(".data")));
 static struct s3c24x0_i2c_bus i2c_bus[CONFIG_MAX_I2C_NUM]
 			__attribute__((section(".data")));
-#endif
+
+/**
+ * Get a pointer to the given bus index
+ *
+ * @bus_idx: Bus index to look up
+ * @return pointer to bus, or NULL if invalid or not available
+ */
+static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx)
+{
+	if (bus_idx < ARRAY_SIZE(i2c_bus)) {
+		struct s3c24x0_i2c_bus *bus;
+
+		bus = &i2c_bus[bus_idx];
+		if (bus->active)
+			return bus;
+	}
+
+	debug("Undefined bus: %d\n", bus_idx);
+	return NULL;
+}
 
 #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 static int GetI2CSDA(void)
@@ -84,22 +178,75 @@
 }
 #endif
 
+/*
+ * Wait til the byte transfer is completed.
+ *
+ * @param i2c- pointer to the appropriate i2c register bank.
+ * @return I2C_OK, if transmission was ACKED
+ *         I2C_NACK, if transmission was NACKED
+ *         I2C_NOK_TIMEOUT, if transaction did not complete in I2C_TIMEOUT_MS
+ */
+
 static int WaitForXfer(struct s3c24x0_i2c *i2c)
 {
-	int i;
+	ulong start_time = get_timer(0);
 
-	i = I2C_TIMEOUT * 10000;
-	while (!(readl(&i2c->iiccon) & I2CCON_IRPND) && (i > 0)) {
-		udelay(100);
-		i--;
-	}
+	do {
+		if (readl(&i2c->iiccon) & I2CCON_IRPND)
+			return (readl(&i2c->iicstat) & I2CSTAT_NACK) ?
+				I2C_NACK : I2C_OK;
+	} while (get_timer(start_time) < I2C_TIMEOUT_MS);
 
-	return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
+	return I2C_NOK_TOUT;
 }
 
-static int IsACK(struct s3c24x0_i2c *i2c)
+/*
+ * Wait for transfer completion.
+ *
+ * This function reads the interrupt status register waiting for the INT_I2C
+ * bit to be set, which indicates copletion of a transaction.
+ *
+ * @param i2c: pointer to the appropriate register bank
+ *
+ * @return: I2C_OK in case of successful completion, I2C_NOK_TIMEOUT in case
+ *          the status bits do not get set in time, or an approrpiate error
+ *          value in case of transfer errors.
+ */
+static int hsi2c_wait_for_trx(struct exynos5_hsi2c *i2c)
 {
-	return !(readl(&i2c->iicstat) & I2CSTAT_NACK);
+	int i = HSI2C_TIMEOUT_US;
+
+	while (i-- > 0) {
+		u32 int_status = readl(&i2c->usi_int_stat);
+
+		if (int_status & HSI2C_INT_I2C_EN) {
+			u32 trans_status = readl(&i2c->usi_trans_status);
+
+			/* Deassert pending interrupt. */
+			writel(int_status, &i2c->usi_int_stat);
+
+			if (trans_status & HSI2C_NO_DEV_ACK) {
+				debug("%s: no ACK from device\n", __func__);
+				return I2C_NACK;
+			}
+			if (trans_status & HSI2C_NO_DEV) {
+				debug("%s: no device\n", __func__);
+				return I2C_NOK;
+			}
+			if (trans_status & HSI2C_TRANS_ABORT) {
+				debug("%s: arbitration lost\n", __func__);
+				return I2C_NOK_LA;
+			}
+			if (trans_status & HSI2C_TIMEOUT_AUTO) {
+				debug("%s: device timed out\n", __func__);
+				return I2C_NOK_TOUT;
+			}
+			return I2C_OK;
+		}
+		udelay(1);
+	}
+	debug("%s: transaction timeout!\n", __func__);
+	return I2C_NOK_TOUT;
 }
 
 static void ReadWriteByte(struct s3c24x0_i2c *i2c)
@@ -150,6 +297,109 @@
 	/* program Master Transmit (and implicit STOP) */
 	writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
 }
+
+#ifdef CONFIG_I2C_MULTI_BUS
+static int hsi2c_get_clk_details(struct s3c24x0_i2c_bus *i2c_bus)
+{
+	struct exynos5_hsi2c *hsregs = i2c_bus->hsregs;
+	ulong clkin;
+	unsigned int op_clk = i2c_bus->clock_frequency;
+	unsigned int i = 0, utemp0 = 0, utemp1 = 0;
+	unsigned int t_ftl_cycle;
+
+#if defined CONFIG_EXYNOS5
+	clkin = get_i2c_clk();
+#endif
+	/* FPCLK / FI2C =
+	 * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + 2 * FLT_CYCLE
+	 * uTemp0 = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2)
+	 * uTemp1 = (TSCLK_L + TSCLK_H + 2)
+	 * uTemp2 = TSCLK_L + TSCLK_H
+	 */
+	t_ftl_cycle = (readl(&hsregs->usi_conf) >> 16) & 0x7;
+	utemp0 = (clkin / op_clk) - 8 - 2 * t_ftl_cycle;
+
+	/* CLK_DIV max is 256 */
+	for (i = 0; i < 256; i++) {
+		utemp1 = utemp0 / (i + 1);
+		if ((utemp1 < 512) && (utemp1 > 4)) {
+			i2c_bus->clk_cycle = utemp1 - 2;
+			i2c_bus->clk_div = i;
+			return 0;
+		}
+	}
+	return -1;
+}
+#endif
+
+static void hsi2c_ch_init(struct s3c24x0_i2c_bus *i2c_bus)
+{
+	struct exynos5_hsi2c *hsregs = i2c_bus->hsregs;
+	unsigned int t_sr_release;
+	unsigned int n_clkdiv;
+	unsigned int t_start_su, t_start_hd;
+	unsigned int t_stop_su;
+	unsigned int t_data_su, t_data_hd;
+	unsigned int t_scl_l, t_scl_h;
+	u32 i2c_timing_s1;
+	u32 i2c_timing_s2;
+	u32 i2c_timing_s3;
+	u32 i2c_timing_sla;
+
+	n_clkdiv = i2c_bus->clk_div;
+	t_scl_l = i2c_bus->clk_cycle / 2;
+	t_scl_h = i2c_bus->clk_cycle / 2;
+	t_start_su = t_scl_l;
+	t_start_hd = t_scl_l;
+	t_stop_su = t_scl_l;
+	t_data_su = t_scl_l / 2;
+	t_data_hd = t_scl_l / 2;
+	t_sr_release = i2c_bus->clk_cycle;
+
+	i2c_timing_s1 = t_start_su << 24 | t_start_hd << 16 | t_stop_su << 8;
+	i2c_timing_s2 = t_data_su << 24 | t_scl_l << 8 | t_scl_h << 0;
+	i2c_timing_s3 = n_clkdiv << 16 | t_sr_release << 0;
+	i2c_timing_sla = t_data_hd << 0;
+
+	writel(HSI2C_TRAILING_COUNT, &hsregs->usi_trailing_ctl);
+
+	/* Clear to enable Timeout */
+	clrsetbits_le32(&hsregs->usi_timeout, HSI2C_TIMEOUT_EN, 0);
+
+	/* set AUTO mode */
+	writel(readl(&hsregs->usi_conf) | HSI2C_AUTO_MODE, &hsregs->usi_conf);
+
+	/* Enable completion conditions' reporting. */
+	writel(HSI2C_INT_I2C_EN, &hsregs->usi_int_en);
+
+	/* Enable FIFOs */
+	writel(HSI2C_RXFIFO_EN | HSI2C_TXFIFO_EN, &hsregs->usi_fifo_ctl);
+
+	/* Currently operating in Fast speed mode. */
+	writel(i2c_timing_s1, &hsregs->usi_timing_fs1);
+	writel(i2c_timing_s2, &hsregs->usi_timing_fs2);
+	writel(i2c_timing_s3, &hsregs->usi_timing_fs3);
+	writel(i2c_timing_sla, &hsregs->usi_timing_sla);
+}
+
+/* SW reset for the high speed bus */
+static void exynos5_i2c_reset(struct s3c24x0_i2c_bus *i2c_bus)
+{
+	struct exynos5_hsi2c *i2c = i2c_bus->hsregs;
+	u32 i2c_ctl;
+
+	/* Set and clear the bit for reset */
+	i2c_ctl = readl(&i2c->usi_ctl);
+	i2c_ctl |= HSI2C_SW_RST;
+	writel(i2c_ctl, &i2c->usi_ctl);
+
+	i2c_ctl = readl(&i2c->usi_ctl);
+	i2c_ctl &= ~HSI2C_SW_RST;
+	writel(i2c_ctl, &i2c->usi_ctl);
+
+	/* Initialize the configure registers */
+	hsi2c_ch_init(i2c_bus);
+}
 
 /*
  * MULTI BUS I2C support
@@ -158,16 +408,21 @@
 #ifdef CONFIG_I2C_MULTI_BUS
 int i2c_set_bus_num(unsigned int bus)
 {
-	struct s3c24x0_i2c *i2c;
+	struct s3c24x0_i2c_bus *i2c_bus;
 
-	if ((bus < 0) || (bus >= CONFIG_MAX_I2C_NUM)) {
-		debug("Bad bus: %d\n", bus);
+	i2c_bus = get_bus(bus);
+	if (!i2c_bus)
 		return -1;
-	}
-
 	g_current_bus = bus;
-	i2c = get_base_i2c();
-	i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+	if (i2c_bus->is_highspeed) {
+		if (hsi2c_get_clk_details(i2c_bus))
+			return -1;
+		hsi2c_ch_init(i2c_bus);
+	} else {
+		i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
+						CONFIG_SYS_I2C_SLAVE);
+	}
 
 	return 0;
 }
@@ -184,20 +439,27 @@
 #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
 #endif
-	int i;
+	ulong start_time = get_timer(0);
 
 	/* By default i2c channel 0 is the current bus */
 	g_current_bus = 0;
 	i2c = get_base_i2c();
 
-	/* wait for some time to give previous transfer a chance to finish */
-	i = I2C_TIMEOUT * 1000;
-	while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
-		udelay(1000);
-		i--;
+	/*
+	 * In case the previous transfer is still going, wait to give it a
+	 * chance to finish.
+	 */
+	while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
+		if (get_timer(start_time) > I2C_TIMEOUT_MS) {
+			printf("%s: I2C bus busy for %p\n", __func__,
+			       &i2c->iicstat);
+			return;
+		}
 	}
 
 #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
+	int i;
+
 	if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
 #ifdef CONFIG_S3C2410
 		ulong old_gpecon = readl(&gpio->gpecon);
@@ -246,6 +508,227 @@
 }
 
 /*
+ * Poll the appropriate bit of the fifo status register until the interface is
+ * ready to process the next byte or timeout expires.
+ *
+ * In addition to the FIFO status register this function also polls the
+ * interrupt status register to be able to detect unexpected transaction
+ * completion.
+ *
+ * When FIFO is ready to process the next byte, this function returns I2C_OK.
+ * If in course of polling the INT_I2C assertion is detected, the function
+ * returns I2C_NOK. If timeout happens before any of the above conditions is
+ * met - the function returns I2C_NOK_TOUT;
+
+ * @param i2c: pointer to the appropriate i2c register bank.
+ * @param rx_transfer: set to True if the receive transaction is in progress.
+ * @return: as described above.
+ */
+static unsigned hsi2c_poll_fifo(struct exynos5_hsi2c *i2c, bool rx_transfer)
+{
+	u32 fifo_bit = rx_transfer ? HSI2C_RX_FIFO_EMPTY : HSI2C_TX_FIFO_FULL;
+	int i = HSI2C_TIMEOUT_US;
+
+	while (readl(&i2c->usi_fifo_stat) & fifo_bit) {
+		if (readl(&i2c->usi_int_stat) & HSI2C_INT_I2C_EN) {
+			/*
+			 * There is a chance that assertion of
+			 * HSI2C_INT_I2C_EN and deassertion of
+			 * HSI2C_RX_FIFO_EMPTY happen simultaneously. Let's
+			 * give FIFO status priority and check it one more
+			 * time before reporting interrupt. The interrupt will
+			 * be reported next time this function is called.
+			 */
+			if (rx_transfer &&
+			    !(readl(&i2c->usi_fifo_stat) & fifo_bit))
+				break;
+			return I2C_NOK;
+		}
+		if (!i--) {
+			debug("%s: FIFO polling timeout!\n", __func__);
+			return I2C_NOK_TOUT;
+		}
+		udelay(1);
+	}
+	return I2C_OK;
+}
+
+/*
+ * Preapre hsi2c transaction, either read or write.
+ *
+ * Set up transfer as described in section 27.5.1.2 'I2C Channel Auto Mode' of
+ * the 5420 UM.
+ *
+ * @param i2c: pointer to the appropriate i2c register bank.
+ * @param chip: slave address on the i2c bus (with read/write bit exlcuded)
+ * @param len: number of bytes expected to be sent or received
+ * @param rx_transfer: set to true for receive transactions
+ * @param: issue_stop: set to true if i2c stop condition should be generated
+ *         after this transaction.
+ * @return: I2C_NOK_TOUT in case the bus remained busy for HSI2C_TIMEOUT_US,
+ *          I2C_OK otherwise.
+ */
+static int hsi2c_prepare_transaction(struct exynos5_hsi2c *i2c,
+				     u8 chip,
+				     u16 len,
+				     bool rx_transfer,
+				     bool issue_stop)
+{
+	u32 conf;
+
+	conf = len | HSI2C_MASTER_RUN;
+
+	if (issue_stop)
+		conf |= HSI2C_STOP_AFTER_TRANS;
+
+	/* Clear to enable Timeout */
+	writel(readl(&i2c->usi_timeout) & ~HSI2C_TIMEOUT_EN, &i2c->usi_timeout);
+
+	/* Set slave address */
+	writel(HSI2C_SLV_ADDR_MAS(chip), &i2c->i2c_addr);
+
+	if (rx_transfer) {
+		/* i2c master, read transaction */
+		writel((HSI2C_RXCHON | HSI2C_FUNC_MODE_I2C | HSI2C_MASTER),
+		       &i2c->usi_ctl);
+
+		/* read up to len bytes, stop after transaction is finished */
+		writel(conf | HSI2C_READ_WRITE, &i2c->usi_auto_conf);
+	} else {
+		/* i2c master, write transaction */
+		writel((HSI2C_TXCHON | HSI2C_FUNC_MODE_I2C | HSI2C_MASTER),
+		       &i2c->usi_ctl);
+
+		/* write up to len bytes, stop after transaction is finished */
+		writel(conf, &i2c->usi_auto_conf);
+	}
+
+	/* Reset all pending interrupt status bits we care about, if any */
+	writel(HSI2C_INT_I2C_EN, &i2c->usi_int_stat);
+
+	return I2C_OK;
+}
+
+/*
+ * Wait while i2c bus is settling down (mostly stop gets completed).
+ */
+static int hsi2c_wait_while_busy(struct exynos5_hsi2c *i2c)
+{
+	int i = HSI2C_TIMEOUT_US;
+
+	while (readl(&i2c->usi_trans_status) & HSI2C_MASTER_BUSY) {
+		if (!i--) {
+			debug("%s: bus busy\n", __func__);
+			return I2C_NOK_TOUT;
+		}
+		udelay(1);
+	}
+	return I2C_OK;
+}
+
+static int hsi2c_write(struct exynos5_hsi2c *i2c,
+		       unsigned char chip,
+		       unsigned char addr[],
+		       unsigned char alen,
+		       unsigned char data[],
+		       unsigned short len,
+		       bool issue_stop)
+{
+	int i, rv = 0;
+
+	if (!(len + alen)) {
+		/* Writes of zero length not supported in auto mode. */
+		debug("%s: zero length writes not supported\n", __func__);
+		return I2C_NOK;
+	}
+
+	rv = hsi2c_prepare_transaction
+		(i2c, chip, len + alen, false, issue_stop);
+	if (rv != I2C_OK)
+		return rv;
+
+	/* Move address, if any, and the data, if any, into the FIFO. */
+	for (i = 0; i < alen; i++) {
+		rv = hsi2c_poll_fifo(i2c, false);
+		if (rv != I2C_OK) {
+			debug("%s: address write failed\n", __func__);
+			goto write_error;
+		}
+		writel(addr[i], &i2c->usi_txdata);
+	}
+
+	for (i = 0; i < len; i++) {
+		rv = hsi2c_poll_fifo(i2c, false);
+		if (rv != I2C_OK) {
+			debug("%s: data write failed\n", __func__);
+			goto write_error;
+		}
+		writel(data[i], &i2c->usi_txdata);
+	}
+
+	rv = hsi2c_wait_for_trx(i2c);
+
+ write_error:
+	if (issue_stop) {
+		int tmp_ret = hsi2c_wait_while_busy(i2c);
+		if (rv == I2C_OK)
+			rv = tmp_ret;
+	}
+
+	writel(HSI2C_FUNC_MODE_I2C, &i2c->usi_ctl); /* done */
+	return rv;
+}
+
+static int hsi2c_read(struct exynos5_hsi2c *i2c,
+		      unsigned char chip,
+		      unsigned char addr[],
+		      unsigned char alen,
+		      unsigned char data[],
+		      unsigned short len)
+{
+	int i, rv, tmp_ret;
+	bool drop_data = false;
+
+	if (!len) {
+		/* Reads of zero length not supported in auto mode. */
+		debug("%s: zero length read adjusted\n", __func__);
+		drop_data = true;
+		len = 1;
+	}
+
+	if (alen) {
+		/* Internal register adress needs to be written first. */
+		rv = hsi2c_write(i2c, chip, addr, alen, NULL, 0, false);
+		if (rv != I2C_OK)
+			return rv;
+	}
+
+	rv = hsi2c_prepare_transaction(i2c, chip, len, true, true);
+
+	if (rv != I2C_OK)
+		return rv;
+
+	for (i = 0; i < len; i++) {
+		rv = hsi2c_poll_fifo(i2c, true);
+		if (rv != I2C_OK)
+			goto read_err;
+		if (drop_data)
+			continue;
+		data[i] = readl(&i2c->usi_rxdata);
+	}
+
+	rv = hsi2c_wait_for_trx(i2c);
+
+ read_err:
+	tmp_ret = hsi2c_wait_while_busy(i2c);
+	if (rv == I2C_OK)
+		rv = tmp_ret;
+
+	writel(HSI2C_FUNC_MODE_I2C, &i2c->usi_ctl); /* done */
+	return rv;
+}
+
+/*
  * cmd_type is 0 for write, 1 for read.
  *
  * addr_len can take any value from 0-255, it is only limited
@@ -260,7 +743,8 @@
 			unsigned char data[],
 			unsigned short data_len)
 {
-	int i, result;
+	int i = 0, result;
+	ulong start_time = get_timer(0);
 
 	if (data == 0 || data_len == 0) {
 		/*Don't support data transfer of no length or to address 0 */
@@ -268,128 +752,78 @@
 		return I2C_NOK;
 	}
 
-	/* Check I2C bus idle */
-	i = I2C_TIMEOUT * 1000;
-	while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
-		udelay(1000);
-		i--;
+	while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
+		if (get_timer(start_time) > I2C_TIMEOUT_MS)
+			return I2C_NOK_TOUT;
 	}
 
-	if (readl(&i2c->iicstat) & I2CSTAT_BSY)
-		return I2C_NOK_TOUT;
-
 	writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
-	result = I2C_OK;
 
-	switch (cmd_type) {
-	case I2C_WRITE:
-		if (addr && addr_len) {
-			writel(chip, &i2c->iicds);
-			/* send START */
-			writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
-			       &i2c->iicstat);
-			i = 0;
-			while ((i < addr_len) && (result == I2C_OK)) {
-				result = WaitForXfer(i2c);
-				writel(addr[i], &i2c->iicds);
-				ReadWriteByte(i2c);
-				i++;
-			}
-			i = 0;
-			while ((i < data_len) && (result == I2C_OK)) {
-				result = WaitForXfer(i2c);
-				writel(data[i], &i2c->iicds);
-				ReadWriteByte(i2c);
-				i++;
-			}
-		} else {
-			writel(chip, &i2c->iicds);
-			/* send START */
-			writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
-			       &i2c->iicstat);
-			i = 0;
-			while ((i < data_len) && (result == I2C_OK)) {
-				result = WaitForXfer(i2c);
-				writel(data[i], &i2c->iicds);
-				ReadWriteByte(i2c);
-				i++;
-			}
-		}
+	/* Get the slave chip address going */
+	writel(chip, &i2c->iicds);
+	if ((cmd_type == I2C_WRITE) || (addr && addr_len))
+		writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
+		       &i2c->iicstat);
+	else
+		writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
+		       &i2c->iicstat);
+
+	/* Wait for chip address to transmit. */
+	result = WaitForXfer(i2c);
+	if (result != I2C_OK)
+		goto bailout;
 
-		if (result == I2C_OK)
+	/* If register address needs to be transmitted - do it now. */
+	if (addr && addr_len) {
+		while ((i < addr_len) && (result == I2C_OK)) {
+			writel(addr[i++], &i2c->iicds);
+			ReadWriteByte(i2c);
 			result = WaitForXfer(i2c);
+		}
+		i = 0;
+		if (result != I2C_OK)
+			goto bailout;
+	}
 
-		/* send STOP */
-		writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
-		ReadWriteByte(i2c);
+	switch (cmd_type) {
+	case I2C_WRITE:
+		while ((i < data_len) && (result == I2C_OK)) {
+			writel(data[i++], &i2c->iicds);
+			ReadWriteByte(i2c);
+			result = WaitForXfer(i2c);
+		}
 		break;
 
 	case I2C_READ:
 		if (addr && addr_len) {
+			/*
+			 * Register address has been sent, now send slave chip
+			 * address again to start the actual read transaction.
+			 */
 			writel(chip, &i2c->iicds);
-			/* send START */
-			writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
-				&i2c->iicstat);
-			result = WaitForXfer(i2c);
-			if (IsACK(i2c)) {
-				i = 0;
-				while ((i < addr_len) && (result == I2C_OK)) {
-					writel(addr[i], &i2c->iicds);
-					ReadWriteByte(i2c);
-					result = WaitForXfer(i2c);
-					i++;
-				}
-
-				writel(chip, &i2c->iicds);
-				/* resend START */
-				writel(I2C_MODE_MR | I2C_TXRX_ENA |
-				       I2C_START_STOP, &i2c->iicstat);
-			ReadWriteByte(i2c);
-			result = WaitForXfer(i2c);
-				i = 0;
-				while ((i < data_len) && (result == I2C_OK)) {
-					/* disable ACK for final READ */
-					if (i == data_len - 1)
-						writel(readl(&i2c->iiccon)
-							& ~I2CCON_ACKGEN,
-							&i2c->iiccon);
-				ReadWriteByte(i2c);
-				result = WaitForXfer(i2c);
-					data[i] = readl(&i2c->iicds);
-					i++;
-				}
-			} else {
-				result = I2C_NACK;
-			}
 
-		} else {
-			writel(chip, &i2c->iicds);
-			/* send START */
+			/* Generate a re-START. */
 			writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
 				&i2c->iicstat);
+			ReadWriteByte(i2c);
 			result = WaitForXfer(i2c);
 
-			if (IsACK(i2c)) {
-				i = 0;
-				while ((i < data_len) && (result == I2C_OK)) {
-					/* disable ACK for final READ */
-					if (i == data_len - 1)
-						writel(readl(&i2c->iiccon) &
-							~I2CCON_ACKGEN,
-							&i2c->iiccon);
-					ReadWriteByte(i2c);
-					result = WaitForXfer(i2c);
-					data[i] = readl(&i2c->iicds);
-					i++;
-				}
-			} else {
-				result = I2C_NACK;
-			}
+			if (result != I2C_OK)
+				goto bailout;
 		}
 
-		/* send STOP */
-		writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
-		ReadWriteByte(i2c);
+		while ((i < data_len) && (result == I2C_OK)) {
+			/* disable ACK for final READ */
+			if (i == data_len - 1)
+				writel(readl(&i2c->iiccon)
+				       & ~I2CCON_ACKGEN,
+				       &i2c->iiccon);
+			ReadWriteByte(i2c);
+			result = WaitForXfer(i2c);
+			data[i++] = readl(&i2c->iicds);
+		}
+		if (result == I2C_NACK)
+			result = I2C_OK; /* Normal terminated read. */
 		break;
 
 	default:
@@ -398,15 +832,23 @@
 		break;
 	}
 
+bailout:
+	/* Send STOP. */
+	writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
+	ReadWriteByte(i2c);
+
 	return result;
 }
 
 int i2c_probe(uchar chip)
 {
-	struct s3c24x0_i2c *i2c;
+	struct s3c24x0_i2c_bus *i2c_bus;
 	uchar buf[1];
+	int ret;
 
-	i2c = get_base_i2c();
+	i2c_bus = get_bus(g_current_bus);
+	if (!i2c_bus)
+		return -1;
 	buf[0] = 0;
 
 	/*
@@ -414,12 +856,21 @@
 	 * address was <ACK>ed (i.e. there was a chip at that address which
 	 * drove the data line low).
 	 */
-	return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
+	if (i2c_bus->is_highspeed) {
+		ret = hsi2c_read(i2c_bus->hsregs,
+				chip, 0, 0, buf, 1);
+	} else {
+		ret = i2c_transfer(i2c_bus->regs,
+				I2C_READ, chip << 1, 0, 0, buf, 1);
+	}
+
+
+	return ret != I2C_OK;
 }
 
 int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 {
-	struct s3c24x0_i2c *i2c;
+	struct s3c24x0_i2c_bus *i2c_bus;
 	uchar xaddr[4];
 	int ret;
 
@@ -451,11 +902,21 @@
 		chip |= ((addr >> (alen * 8)) &
 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-	i2c = get_base_i2c();
-	ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen,
-			buffer, len);
-	if (ret != 0) {
-		debug("I2c read: failed %d\n", ret);
+	i2c_bus = get_bus(g_current_bus);
+	if (!i2c_bus)
+		return -1;
+
+	if (i2c_bus->is_highspeed)
+		ret = hsi2c_read(i2c_bus->hsregs, chip, &xaddr[4 - alen],
+				 alen, buffer, len);
+	else
+		ret = i2c_transfer(i2c_bus->regs, I2C_READ, chip << 1,
+				&xaddr[4 - alen], alen, buffer, len);
+
+	if (ret) {
+		if (i2c_bus->is_highspeed)
+			exynos5_i2c_reset(i2c_bus);
+		debug("I2c read failed %d\n", ret);
 		return 1;
 	}
 	return 0;
@@ -463,8 +924,9 @@
 
 int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 {
-	struct s3c24x0_i2c *i2c;
+	struct s3c24x0_i2c_bus *i2c_bus;
 	uchar xaddr[4];
+	int ret;
 
 	if (alen > 4) {
 		debug("I2C write: addr len %d not supported\n", alen);
@@ -493,53 +955,87 @@
 		chip |= ((addr >> (alen * 8)) &
 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-	i2c = get_base_i2c();
-	return (i2c_transfer
-		(i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
-		 len) != 0);
+	i2c_bus = get_bus(g_current_bus);
+	if (!i2c_bus)
+		return -1;
+
+	if (i2c_bus->is_highspeed)
+		ret = hsi2c_write(i2c_bus->hsregs, chip, &xaddr[4 - alen],
+				  alen, buffer, len, true);
+	else
+		ret = i2c_transfer(i2c_bus->regs, I2C_WRITE, chip << 1,
+				&xaddr[4 - alen], alen, buffer, len);
+
+	if (ret != 0) {
+		if (i2c_bus->is_highspeed)
+			exynos5_i2c_reset(i2c_bus);
+		return 1;
+	} else {
+		return 0;
+	}
 }
 
 #ifdef CONFIG_OF_CONTROL
-void board_i2c_init(const void *blob)
+static void process_nodes(const void *blob, int node_list[], int count,
+			 int is_highspeed)
 {
+	struct s3c24x0_i2c_bus *bus;
 	int i;
-	int node_list[CONFIG_MAX_I2C_NUM];
-	int count;
-
-	count = fdtdec_find_aliases_for_id(blob, "i2c",
-		COMPAT_SAMSUNG_S3C2440_I2C, node_list,
-		CONFIG_MAX_I2C_NUM);
 
 	for (i = 0; i < count; i++) {
-		struct s3c24x0_i2c_bus *bus;
 		int node = node_list[i];
 
 		if (node <= 0)
 			continue;
+
 		bus = &i2c_bus[i];
-		bus->regs = (struct s3c24x0_i2c *)
-			fdtdec_get_addr(blob, node, "reg");
+		bus->active = true;
+		bus->is_highspeed = is_highspeed;
+
+		if (is_highspeed)
+			bus->hsregs = (struct exynos5_hsi2c *)
+					fdtdec_get_addr(blob, node, "reg");
+		else
+			bus->regs = (struct s3c24x0_i2c *)
+					fdtdec_get_addr(blob, node, "reg");
+
 		bus->id = pinmux_decode_periph_id(blob, node);
+		bus->clock_frequency = fdtdec_get_int(blob, node,
+						      "clock-frequency",
+						      CONFIG_SYS_I2C_SPEED);
 		bus->node = node;
-		bus->bus_num = i2c_busses++;
+		bus->bus_num = i;
 		exynos_pinmux_config(bus->id, 0);
+
+		/* Mark position as used */
+		node_list[i] = -1;
 	}
 }
 
-static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx)
+void board_i2c_init(const void *blob)
 {
-	if (bus_idx < i2c_busses)
-		return &i2c_bus[bus_idx];
+	int node_list[CONFIG_MAX_I2C_NUM];
+	int count;
 
-	debug("Undefined bus: %d\n", bus_idx);
-	return NULL;
+	/* First get the normal i2c ports */
+	count = fdtdec_find_aliases_for_id(blob, "i2c",
+		COMPAT_SAMSUNG_S3C2440_I2C, node_list,
+		CONFIG_MAX_I2C_NUM);
+	process_nodes(blob, node_list, count, 0);
+
+	/* Now look for high speed i2c ports */
+	count = fdtdec_find_aliases_for_id(blob, "i2c",
+		COMPAT_SAMSUNG_EXYNOS5_I2C, node_list,
+		CONFIG_MAX_I2C_NUM);
+	process_nodes(blob, node_list, count, 1);
+
 }
 
 int i2c_get_bus_num_fdt(int node)
 {
 	int i;
 
-	for (i = 0; i < i2c_busses; i++) {
+	for (i = 0; i < ARRAY_SIZE(i2c_bus); i++) {
 		if (node == i2c_bus[i].node)
 			return i;
 	}
@@ -548,9 +1044,10 @@
 	return -1;
 }
 
+#ifdef CONFIG_I2C_MULTI_BUS
 int i2c_reset_port_fdt(const void *blob, int node)
 {
-	struct s3c24x0_i2c_bus *i2c;
+	struct s3c24x0_i2c_bus *i2c_bus;
 	int bus;
 
 	bus = i2c_get_bus_num_fdt(node);
@@ -559,16 +1056,24 @@
 		return -1;
 	}
 
-	i2c = get_bus(bus);
-	if (!i2c) {
+	i2c_bus = get_bus(bus);
+	if (!i2c_bus) {
 		debug("get_bus() failed for node node %d\n", node);
 		return -1;
 	}
 
-	i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+	if (i2c_bus->is_highspeed) {
+		if (hsi2c_get_clk_details(i2c_bus))
+			return -1;
+		hsi2c_ch_init(i2c_bus);
+	} else {
+		i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
+						CONFIG_SYS_I2C_SLAVE);
+	}
 
 	return 0;
 }
 #endif
+#endif
 
 #endif /* CONFIG_HARD_I2C */
diff --git a/drivers/i2c/s3c24x0_i2c.h b/drivers/i2c/s3c24x0_i2c.h
index b4a337a..1ae73d2 100644
--- a/drivers/i2c/s3c24x0_i2c.h
+++ b/drivers/i2c/s3c24x0_i2c.h
@@ -15,10 +15,48 @@
 	u32	iiclc;
 };
 
+struct exynos5_hsi2c {
+	u32	usi_ctl;
+	u32	usi_fifo_ctl;
+	u32	usi_trailing_ctl;
+	u32	usi_clk_ctl;
+	u32	usi_clk_slot;
+	u32	spi_ctl;
+	u32	uart_ctl;
+	u32	res1;
+	u32	usi_int_en;
+	u32	usi_int_stat;
+	u32	usi_modem_stat;
+	u32	usi_error_stat;
+	u32	usi_fifo_stat;
+	u32	usi_txdata;
+	u32	usi_rxdata;
+	u32	res2;
+	u32	usi_conf;
+	u32	usi_auto_conf;
+	u32	usi_timeout;
+	u32	usi_manual_cmd;
+	u32	usi_trans_status;
+	u32	usi_timing_hs1;
+	u32	usi_timing_hs2;
+	u32	usi_timing_hs3;
+	u32	usi_timing_fs1;
+	u32	usi_timing_fs2;
+	u32	usi_timing_fs3;
+	u32	usi_timing_sla;
+	u32	i2c_addr;
+};
+
 struct s3c24x0_i2c_bus {
+	bool active;	/* port is active and available */
 	int node;	/* device tree node */
 	int bus_num;	/* i2c bus number */
 	struct s3c24x0_i2c *regs;
+	struct exynos5_hsi2c *hsregs;
+	int is_highspeed;	/* High speed type, rather than I2C */
+	unsigned clock_frequency;
 	int id;
+	unsigned clk_cycle;
+	unsigned clk_div;
 };
 #endif /* _S3C24X0_I2C_H */
diff --git a/drivers/i2c/sh_i2c.c b/drivers/i2c/sh_i2c.c
index 58f8bf1..808202c 100644
--- a/drivers/i2c/sh_i2c.c
+++ b/drivers/i2c/sh_i2c.c
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2011 Renesas Solutions Corp.
- * Copyright (C) 2011 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2011, 2013 Renesas Solutions Corp.
+ * Copyright (C) 2011, 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -8,6 +8,8 @@
 #include <common.h>
 #include <asm/io.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Every register is 32bit aligned, but only 8bits in size */
 #define ureg(name) u8 name; u8 __pad_##name##0; u16 __pad_##name##1;
 struct sh_i2c {
@@ -240,6 +242,10 @@
 {
 	int num, denom, tmp;
 
+	/* No i2c support prior to relocation */
+	if (!(gd->flags & GD_FLG_RELOC))
+		return;
+
 #ifdef CONFIG_I2C_MULTI_BUS
 	current_bus = 0;
 #endif
diff --git a/include/configs/apf27.h b/include/configs/apf27.h
index e7e258f..1193013 100644
--- a/include/configs/apf27.h
+++ b/include/configs/apf27.h
@@ -321,11 +321,12 @@
  */
 
 #ifdef CONFIG_CMD_I2C
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		IMX_I2C1_BASE
-#define CONFIG_SYS_I2C_SPEED		100000	/* 100 kHz */
-#define CONFIG_SYS_I2C_SLAVE		0x7F
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_MXC_I2C1_SPEED	100000	/* 100 kHz */
+#define CONFIG_SYS_MXC_I2C1_SLAVE	0x7F
+#define CONFIG_SYS_MXC_I2C2_SPEED	100000	/* 100 kHz */
+#define CONFIG_SYS_MXC_I2C2_SLAVE	0x7F
 #define CONFIG_SYS_I2C_NOPROBES		{ }
 
 #ifdef CONFIG_CMD_EEPROM
diff --git a/include/configs/flea3.h b/include/configs/flea3.h
index 655df67..1781089 100644
--- a/include/configs/flea3.h
+++ b/include/configs/flea3.h
@@ -50,11 +50,10 @@
 /*
  * Hardware drivers
  */
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C3_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED		100000
-#define CONFIG_SYS_I2C_SLAVE		0xfe
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		2 /* I2C3 */
+#define CONFIG_SYS_MXC_I2C3_SLAVE	0xfe
 #define CONFIG_MXC_SPI
 #define CONFIG_MXC_GPIO
 
diff --git a/include/configs/imx31_phycore.h b/include/configs/imx31_phycore.h
index 1e2b12c..6b99d1b 100644
--- a/include/configs/imx31_phycore.h
+++ b/include/configs/imx31_phycore.h
@@ -35,11 +35,10 @@
  * Hardware drivers
  */
 
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C2_BASE_ADDR
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		1 /* I2C2 */
 #define CONFIG_SYS_I2C_CLK_OFFSET	I2C2_CLK_OFFSET
-#define CONFIG_SYS_I2C_SPEED		100000
 
 #define CONFIG_MXC_UART
 #define CONFIG_MXC_UART_BASE		UART1_BASE
diff --git a/include/configs/m53evk.h b/include/configs/m53evk.h
index 024d3a5..d7ca66b 100644
--- a/include/configs/m53evk.h
+++ b/include/configs/m53evk.h
@@ -161,10 +161,9 @@
  * I2C
  */
 #ifdef CONFIG_CMD_I2C
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C2_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED		100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		1 /* I2C2 */
 #endif
 
 /*
diff --git a/include/configs/mx25pdk.h b/include/configs/mx25pdk.h
index 543c415..256b3c1 100644
--- a/include/configs/mx25pdk.h
+++ b/include/configs/mx25pdk.h
@@ -111,10 +111,9 @@
 
 /* I2C Configs */
 #define CONFIG_CMD_I2C
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		IMX_I2C_BASE
-#define CONFIG_SYS_I2C_SPEED		100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		0 /* I2C1 */
 
 /* RTC */
 #define CONFIG_RTC_IMXDI
diff --git a/include/configs/mx35pdk.h b/include/configs/mx35pdk.h
index 2f59104..2d1b800 100644
--- a/include/configs/mx35pdk.h
+++ b/include/configs/mx35pdk.h
@@ -40,10 +40,9 @@
 /*
  * Hardware drivers
  */
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C1_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED		100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		0 /* I2C1 */
 #define CONFIG_MXC_SPI
 #define CONFIG_MXC_GPIO
 
diff --git a/include/configs/mx53ard.h b/include/configs/mx53ard.h
index 7956083..b404247 100644
--- a/include/configs/mx53ard.h
+++ b/include/configs/mx53ard.h
@@ -44,10 +44,9 @@
 
 /* I2C Configs */
 #define CONFIG_CMD_I2C
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C2_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED            100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		1 /* I2C2 */
 
 /* MMC Configs */
 #define CONFIG_FSL_ESDHC
diff --git a/include/configs/mx53evk.h b/include/configs/mx53evk.h
index fe5cf3c..d9c7df5 100644
--- a/include/configs/mx53evk.h
+++ b/include/configs/mx53evk.h
@@ -37,10 +37,9 @@
 
 /* I2C Configs */
 #define CONFIG_CMD_I2C
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C2_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED            100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		1 /* I2C2 */
 
 /* PMIC Configs */
 #define CONFIG_POWER
diff --git a/include/configs/mx53loco.h b/include/configs/mx53loco.h
index bd2fa43..5f343b1 100644
--- a/include/configs/mx53loco.h
+++ b/include/configs/mx53loco.h
@@ -71,10 +71,9 @@
 #define CONFIG_MXC_USB_FLAGS	0
 
 /* I2C Configs */
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C1_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED		100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		0 /* I2C1 */
 
 /* PMIC Controller */
 #define CONFIG_POWER
diff --git a/include/configs/mx53smd.h b/include/configs/mx53smd.h
index 12b2c0d..2f7736d 100644
--- a/include/configs/mx53smd.h
+++ b/include/configs/mx53smd.h
@@ -34,10 +34,9 @@
 
 /* I2C Configs */
 #define CONFIG_CMD_I2C
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C2_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED            100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		1 /* I2C2 */
 
 /* MMC Configs */
 #define CONFIG_FSL_ESDHC
diff --git a/include/configs/mx6qsabreauto.h b/include/configs/mx6qsabreauto.h
index 5530fc6..e0200c7 100644
--- a/include/configs/mx6qsabreauto.h
+++ b/include/configs/mx6qsabreauto.h
@@ -36,8 +36,8 @@
 
 /* I2C Configs */
 #define CONFIG_CMD_I2C
-#define CONFIG_I2C_MULTI_BUS
-#define CONFIG_I2C_MXC
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
 #define CONFIG_SYS_I2C_SPEED		100000
 
 #endif                         /* __MX6QSABREAUTO_CONFIG_H */
diff --git a/include/configs/nitrogen6x.h b/include/configs/nitrogen6x.h
index 3454b86..d515e49 100644
--- a/include/configs/nitrogen6x.h
+++ b/include/configs/nitrogen6x.h
@@ -52,8 +52,8 @@
 
 /* I2C Configs */
 #define CONFIG_CMD_I2C
-#define CONFIG_I2C_MULTI_BUS
-#define CONFIG_I2C_MXC
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
 #define CONFIG_SYS_I2C_SPEED		100000
 
 /* OCOTP Configs */
diff --git a/include/configs/titanium.h b/include/configs/titanium.h
index 077e25e..0769f07 100644
--- a/include/configs/titanium.h
+++ b/include/configs/titanium.h
@@ -41,8 +41,8 @@
 
 /* I2C Configs */
 #define CONFIG_CMD_I2C
-#define CONFIG_I2C_MULTI_BUS
-#define CONFIG_I2C_MXC
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
 #define CONFIG_SYS_I2C_SPEED		100000
 
 /* MMC Configs */
diff --git a/include/configs/vf610twr.h b/include/configs/vf610twr.h
index 5a7a066..34861f6 100644
--- a/include/configs/vf610twr.h
+++ b/include/configs/vf610twr.h
@@ -70,10 +70,9 @@
 
 /* I2C Configs */
 #define CONFIG_CMD_I2C
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C0_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED		100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		0
 
 #define CONFIG_BOOTDELAY		3
 
diff --git a/include/configs/woodburn_common.h b/include/configs/woodburn_common.h
index 5c442ad..8770e9c 100644
--- a/include/configs/woodburn_common.h
+++ b/include/configs/woodburn_common.h
@@ -45,10 +45,9 @@
 /*
  * Hardware drivers
  */
-#define CONFIG_HARD_I2C
-#define CONFIG_I2C_MXC
-#define CONFIG_SYS_I2C_BASE		I2C1_BASE_ADDR
-#define CONFIG_SYS_I2C_SPEED		100000
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		0
 #define CONFIG_MXC_SPI
 #define CONFIG_MXC_GPIO
 
diff --git a/include/i2c.h b/include/i2c.h
index 8fd17d1..c1be533 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -135,6 +135,8 @@
 #define I2C_MUX_PCA9544		{I2C_MUX_PCA9544_ID, "PCA9544A"}
 #define I2C_MUX_PCA9547_ID	4
 #define I2C_MUX_PCA9547		{I2C_MUX_PCA9547_ID, "PCA9547A"}
+#define I2C_MUX_PCA9548_ID	5
+#define I2C_MUX_PCA9548		{I2C_MUX_PCA9548_ID, "PCA9548"}
 #endif
 
 #ifndef I2C_SOFT_DECLARATIONS