Merge branch 'master' of git://git.denx.de/u-boot-i2c
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index cbb443f..05436f9 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -248,6 +248,11 @@
 #ifdef CONFIG_SYS_FSL_ERRATUM_A005812
 	puts("Work-around for Erratum A-005812 enabled\n");
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+	if ((SVR_SOC_VER(svr) == SVR_8548 && IS_SVR_REV(svr, 3, 1)) ||
+	    (SVR_REV(svr) <= CONFIG_SYS_FSL_A004447_SVR_REV))
+		puts("Work-around for Erratum I2C-A004447 enabled\n");
+#endif
 	return 0;
 }
 
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index e1fc0f7..cf1bb02 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -67,6 +67,8 @@
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM	5
 #define CONFIG_SYS_FSL_RMU
 #define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM	2
+#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_A004447_SVR_REV	0x00
 
 #elif defined(CONFIG_MPC8555)
 #define CONFIG_MAX_CPUS			1
@@ -132,6 +134,8 @@
 #define CONFIG_SYS_FSL_ERRATUM_IFC_A002769
 #define CONFIG_SYS_FSL_ERRATUM_P1010_A003549
 #define CONFIG_SYS_FSL_ERRATUM_IFC_A003399
+#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_A004447_SVR_REV	0x10
 
 /* P1011 is single core version of P1020 */
 #elif defined(CONFIG_P1011)
@@ -249,6 +253,8 @@
 #define CONFIG_SYS_FM_MURAM_SIZE	0x10000
 #define CONFIG_SYS_FSL_PCIE_COMPAT	"fsl,qoriq-pcie-v2.2"
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xff600000
+#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_A004447_SVR_REV	0x11
 
 /* P1024 is lower end variant of P1020 */
 #elif defined(CONFIG_P1024)
@@ -334,6 +340,8 @@
 #define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
 #define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
 #define CONFIG_SYS_FSL_ERRATUM_A004849
+#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_A004447_SVR_REV	0x11
 
 #elif defined(CONFIG_PPC_P3041)
 #define CONFIG_SYS_FSL_QORIQ_CHASSIS1
@@ -369,6 +377,8 @@
 #define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
 #define CONFIG_SYS_FSL_ERRATUM_A004849
 #define CONFIG_SYS_FSL_ERRATUM_A005812
+#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_A004447_SVR_REV	0x20
 
 #elif defined(CONFIG_PPC_P4080) /* also supports P4040 */
 #define CONFIG_SYS_FSL_QORIQ_CHASSIS1
@@ -415,6 +425,8 @@
 #define CONFIG_SYS_FSL_ERRATUM_A004580
 #define CONFIG_SYS_P4080_ERRATUM_PCIE_A003
 #define CONFIG_SYS_FSL_ERRATUM_A005812
+#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_A004447_SVR_REV	0x20
 
 #elif defined(CONFIG_PPC_P5020) /* also supports P5010 */
 #define CONFIG_SYS_PPC64		/* 64-bit core */
@@ -446,6 +458,8 @@
 #define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV	0x10
 #define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xc0000000
 #define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_A004447_SVR_REV	0x20
 
 #elif defined(CONFIG_PPC_P5040)
 #define CONFIG_SYS_PPC64
@@ -510,6 +524,8 @@
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_SYS_FSL_ESDHC_P1010_BROKEN_SDCLK
 #define CONFIG_SYS_FSL_PCIE_COMPAT	"fsl,qoriq-pcie-v2.2"
+#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_A004447_SVR_REV	0x11
 
 #elif defined(CONFIG_PPC_T4240) || defined(CONFIG_PPC_T4160)
 #define CONFIG_E6500
diff --git a/arch/powerpc/include/asm/fsl_i2c.h b/arch/powerpc/include/asm/fsl_i2c.h
index 4f71341..d6537fd 100644
--- a/arch/powerpc/include/asm/fsl_i2c.h
+++ b/arch/powerpc/include/asm/fsl_i2c.h
@@ -54,6 +54,7 @@
 #define I2C_CR_MTX	0x10
 #define I2C_CR_TXAK	0x08
 #define I2C_CR_RSTA	0x04
+#define I2C_CR_BIT6	0x02	/* required for workaround A004447 */
 #define I2C_CR_BCST	0x01
 
 	u8 sr;		/* I2C status register */
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 64a6f9c..bcf6cfb 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -847,7 +847,7 @@
 /* System-On-Chip Version Register (SVR) field extraction */
 
 #define SVR_VER(svr)	(((svr) >> 16) & 0xFFFF) /* Version field */
-#define SVR_REV(svr)	(((svr) >>  0) & 0xFFFF) /* Revision field */
+#define SVR_REV(svr)	(((svr) >>  0) & 0xFF)	 /* Revision field */
 
 #define SVR_CID(svr)	(((svr) >> 28) & 0x0F)	 /* Company or manufacturer ID */
 #define SVR_SOCOP(svr)	(((svr) >> 22) & 0x3F)	 /* SOC integration options */
@@ -1043,9 +1043,6 @@
 
 /* System Version Register (SVR) field extraction */
 
-#define SVR_VER(svr)	(((svr) >>  16) & 0xFFFF)	/* Version field */
-#define SVR_REV(svr)	(((svr) >>   0) & 0xFFFF)	/* Revison field */
-
 #define SVR_SUBVER(svr)	(((svr) >>  8) & 0xFF)	/* Process/MFG sub-version */
 
 #define SVR_FAM(svr)	(((svr) >> 20) & 0xFFF)	/* Family field */
diff --git a/board/samsung/common/multi_i2c.c b/board/samsung/common/multi_i2c.c
index 4fce987..084858d 100644
--- a/board/samsung/common/multi_i2c.c
+++ b/board/samsung/common/multi_i2c.c
@@ -11,13 +11,12 @@
 /* Handle multiple I2C buses instances */
 int get_multi_scl_pin(void)
 {
-	unsigned int bus = I2C_GET_BUS();
+	unsigned int bus = i2c_get_bus_num();
 
 	switch (bus) {
-	case I2C_0: /* I2C_0 definition - compatibility layer */
-	case I2C_5:
+	case I2C_0:
 		return CONFIG_SOFT_I2C_I2C5_SCL;
-	case I2C_9:
+	case I2C_1:
 		return CONFIG_SOFT_I2C_I2C9_SCL;
 	default:
 		printf("I2C_%d not supported!\n", bus);
@@ -28,13 +27,12 @@
 
 int get_multi_sda_pin(void)
 {
-	unsigned int bus = I2C_GET_BUS();
+	unsigned int bus = i2c_get_bus_num();
 
 	switch (bus) {
-	case I2C_0: /* I2C_0 definition - compatibility layer */
-	case I2C_5:
+	case I2C_0:
 		return CONFIG_SOFT_I2C_I2C5_SDA;
-	case I2C_9:
+	case I2C_1:
 		return CONFIG_SOFT_I2C_I2C9_SDA;
 	default:
 		printf("I2C_%d not supported!\n", bus);
diff --git a/board/samsung/goni/goni.c b/board/samsung/goni/goni.c
index c05801d..5b3d6ef 100644
--- a/board/samsung/goni/goni.c
+++ b/board/samsung/goni/goni.c
@@ -32,7 +32,11 @@
 {
 	int ret;
 
-	ret = pmic_init(I2C_5);
+	/*
+	 * For PMIC the I2C bus is named as I2C5, but it is connected
+	 * to logical I2C adapter 0
+	 */
+	ret = pmic_init(I2C_0);
 	if (ret)
 		return ret;
 
diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
index c8698f3..7f61d17 100644
--- a/board/samsung/trats/trats.c
+++ b/board/samsung/trats/trats.c
@@ -61,10 +61,10 @@
 	struct exynos4_gpio_part2 *gpio2 =
 		(struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2();
 
-	/* I2C_5 -> PMIC */
+	/* I2C_5 -> PMIC -> Adapter 0 */
 	s5p_gpio_direction_output(&gpio1->b, 7, 1);
 	s5p_gpio_direction_output(&gpio1->b, 6, 1);
-	/* I2C_9 -> FG */
+	/* I2C_9 -> FG -> Adapter 1 */
 	s5p_gpio_direction_output(&gpio2->y4, 0, 1);
 	s5p_gpio_direction_output(&gpio2->y4, 1, 1);
 }
@@ -282,10 +282,17 @@
 	struct power_battery *pb;
 	struct pmic *p_fg, *p_chrg, *p_muic, *p_bat;
 
-	ret = pmic_init(I2C_5);
+	/*
+	 * For PMIC/MUIC the I2C bus is named as I2C5, but it is connected
+	 * to logical I2C adapter 0
+	 *
+	 * The FUEL_GAUGE is marked as I2C9 on the schematic, but connected
+	 * to logical I2C adapter 1
+	 */
+	ret = pmic_init(I2C_0);
 	ret |= pmic_init_max8997();
-	ret |= power_fg_init(I2C_9);
-	ret |= power_muic_init(I2C_5);
+	ret |= power_fg_init(I2C_1);
+	ret |= power_muic_init(I2C_0);
 	ret |= power_bat_init(0);
 	if (ret)
 		return ret;
diff --git a/board/samsung/universal_c210/universal.c b/board/samsung/universal_c210/universal.c
index 2e1dba6..54d0e1e 100644
--- a/board/samsung/universal_c210/universal.c
+++ b/board/samsung/universal_c210/universal.c
@@ -45,6 +45,10 @@
 {
 	int ret;
 
+	/*
+	 * For PMIC the I2C bus is named as I2C5, but it is connected
+	 * to logical I2C adapter 0
+	 */
 	ret = pmic_init(I2C_5);
 	if (ret)
 		return ret;
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index 38455e1..291ad94 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -206,9 +206,58 @@
 		return gd->arch.i2c1_clk;	/* I2C1 clock */
 }
 
+static int fsl_i2c_fixup(const struct fsl_i2c *dev)
+{
+	const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT);
+	unsigned long long timeval = 0;
+	int ret = -1;
+	unsigned int flags = 0;
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+	unsigned int svr = get_svr();
+	if ((SVR_SOC_VER(svr) == SVR_8548 && IS_SVR_REV(svr, 3, 1)) ||
+	    (SVR_REV(svr) <= CONFIG_SYS_FSL_A004447_SVR_REV))
+		flags = I2C_CR_BIT6;
+#endif
+
+	writeb(I2C_CR_MEN | I2C_CR_MSTA, &dev->cr);
+
+	timeval = get_ticks();
+	while (!(readb(&dev->sr) & I2C_SR_MBB)) {
+		if ((get_ticks() - timeval) > timeout)
+			goto err;
+	}
+
+	if (readb(&dev->sr) & I2C_SR_MAL) {
+		/* SDA is stuck low */
+		writeb(0, &dev->cr);
+		udelay(100);
+		writeb(I2C_CR_MSTA | flags, &dev->cr);
+		writeb(I2C_CR_MEN | I2C_CR_MSTA | flags, &dev->cr);
+	}
+
+	readb(&dev->dr);
+
+	timeval = get_ticks();
+	while (!(readb(&dev->sr) & I2C_SR_MIF)) {
+		if ((get_ticks() - timeval) > timeout)
+			goto err;
+	}
+	ret = 0;
+
+err:
+	writeb(I2C_CR_MEN | flags, &dev->cr);
+	writeb(0, &dev->sr);
+	udelay(100);
+
+	return ret;
+}
+
 static void fsl_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
 {
 	const struct fsl_i2c *dev;
+	const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT);
+	unsigned long long timeval;
 
 #ifdef CONFIG_SYS_I2C_INIT_BOARD
 	/* Call board specific i2c bus reset routine before accessing the
@@ -226,6 +275,18 @@
 	writeb(0x0, &dev->sr);		/* clear status register */
 	writeb(I2C_CR_MEN, &dev->cr);	/* start I2C controller */
 
+	timeval = get_ticks();
+	while (readb(&dev->sr) & I2C_SR_MBB) {
+		if ((get_ticks() - timeval) < timeout)
+			continue;
+
+		if (fsl_i2c_fixup(dev))
+			debug("i2c_init: BUS#%d failed to init\n",
+			      adap->hwadapnr);
+
+		break;
+	}
+
 #ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT
 	/* Call board specific i2c bus reset routine AFTER the bus has been
 	 * initialized. Use either this callpoint or i2c_init_board;
@@ -394,8 +455,10 @@
 	int i = -1; /* signal error */
 	u8 *a = (u8*)&addr;
 
-	if (i2c_wait4bus(adap) >= 0 &&
-	    i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0 &&
+	if (i2c_wait4bus(adap) < 0)
+		return -1;
+
+	if (i2c_write_addr(adap, dev, I2C_WRITE_BIT, 0) != 0 &&
 	    __i2c_write(adap, &a[4 - alen], alen) == alen) {
 		i = __i2c_write(adap, data, length);
 	}
diff --git a/drivers/power/power_i2c.c b/drivers/power/power_i2c.c
index 66b3bab..ac76870 100644
--- a/drivers/power/power_i2c.c
+++ b/drivers/power/power_i2c.c
@@ -98,7 +98,7 @@
 
 int pmic_probe(struct pmic *p)
 {
-	I2C_SET_BUS(p->bus);
+	i2c_set_bus_num(p->bus);
 	debug("Bus: %d PMIC:%s probed!\n", p->bus, p->name);
 	if (i2c_probe(pmic_i2c_addr)) {
 		printf("Can't find PMIC:%s\n", p->name);
diff --git a/include/configs/trats.h b/include/configs/trats.h
index 9b6aac9..24ea06b 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -263,6 +263,9 @@
 #define CONFIG_SYS_I2C_SOFT		/* I2C bit-banged */
 #define CONFIG_SYS_I2C_SOFT_SPEED	50000
 #define CONFIG_SYS_I2C_SOFT_SLAVE	0xFE
+#define I2C_SOFT_DECLARATIONS2
+#define CONFIG_SYS_I2C_SOFT_SPEED_2     50000
+#define CONFIG_SYS_I2C_SOFT_SLAVE_2     0x7F
 #define CONFIG_SOFT_I2C_READ_REPEATED_START
 #define CONFIG_SYS_I2C_INIT_BOARD
 #define CONFIG_I2C_MULTI_BUS
diff --git a/include/i2c.h b/include/i2c.h
index d8674ef..8fd17d1 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -390,7 +390,7 @@
 # if !defined(CONFIG_SYS_MAX_I2C_BUS)
 #  define CONFIG_SYS_MAX_I2C_BUS		2
 # endif
-# define I2C_MULTI_BUS				0
+# define I2C_MULTI_BUS				1
 #else
 # define CONFIG_SYS_MAX_I2C_BUS		1
 # define I2C_MULTI_BUS				0