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