Merge branch 'master' of git://git.denx.de/u-boot-i2c
authorTom Rini <trini@ti.com>
Mon, 21 Jul 2014 15:04:10 +0000 (11:04 -0400)
committerTom Rini <trini@ti.com>
Mon, 21 Jul 2014 15:04:10 +0000 (11:04 -0400)
drivers/i2c/fsl_i2c.c
drivers/i2c/omap24xx_i2c.c

index aa159f8..811033b 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static const struct fsl_i2c *i2c_dev[2] = {
+static const struct fsl_i2c *i2c_dev[4] = {
        (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C_OFFSET),
 #ifdef CONFIG_SYS_FSL_I2C2_OFFSET
-       (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C2_OFFSET)
+       (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C2_OFFSET),
+#endif
+#ifdef CONFIG_SYS_FSL_I2C3_OFFSET
+       (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C3_OFFSET),
+#endif
+#ifdef CONFIG_SYS_FSL_I2C4_OFFSET
+       (struct fsl_i2c *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C4_OFFSET)
 #endif
 };
 
@@ -539,3 +545,15 @@ U_BOOT_I2C_ADAP_COMPLETE(fsl_1, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read,
                         CONFIG_SYS_FSL_I2C2_SPEED, CONFIG_SYS_FSL_I2C2_SLAVE,
                         1)
 #endif
+#ifdef CONFIG_SYS_FSL_I2C3_OFFSET
+U_BOOT_I2C_ADAP_COMPLETE(fsl_2, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read,
+                        fsl_i2c_write, fsl_i2c_set_bus_speed,
+                        CONFIG_SYS_FSL_I2C3_SPEED, CONFIG_SYS_FSL_I2C3_SLAVE,
+                        2)
+#endif
+#ifdef CONFIG_SYS_FSL_I2C4_OFFSET
+U_BOOT_I2C_ADAP_COMPLETE(fsl_3, fsl_i2c_init, fsl_i2c_probe, fsl_i2c_read,
+                        fsl_i2c_write, fsl_i2c_set_bus_speed,
+                        CONFIG_SYS_FSL_I2C4_SPEED, CONFIG_SYS_FSL_I2C4_SLAVE,
+                        3)
+#endif
index a39b591..0f1e35c 100644 (file)
@@ -153,11 +153,60 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
 
        return 0;
 }
+
+static void omap24_i2c_deblock(struct i2c_adapter *adap)
+{
+       struct i2c *i2c_base = omap24_get_base(adap);
+       int i;
+       u16 systest;
+       u16 orgsystest;
+
+       /* set test mode ST_EN = 1 */
+       orgsystest = readw(&i2c_base->systest);
+       systest = orgsystest;
+       /* enable testmode */
+       systest |= I2C_SYSTEST_ST_EN;
+       writew(systest, &i2c_base->systest);
+       systest &= ~I2C_SYSTEST_TMODE_MASK;
+       systest |= 3 << I2C_SYSTEST_TMODE_SHIFT;
+       writew(systest, &i2c_base->systest);
+
+       /* set SCL, SDA  = 1 */
+       systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O;
+       writew(systest, &i2c_base->systest);
+       udelay(10);
+
+       /* toggle scl 9 clocks */
+       for (i = 0; i < 9; i++) {
+               /* SCL = 0 */
+               systest &= ~I2C_SYSTEST_SCL_O;
+               writew(systest, &i2c_base->systest);
+               udelay(10);
+               /* SCL = 1 */
+               systest |= I2C_SYSTEST_SCL_O;
+               writew(systest, &i2c_base->systest);
+               udelay(10);
+       }
+
+       /* send stop */
+       systest &= ~I2C_SYSTEST_SDA_O;
+       writew(systest, &i2c_base->systest);
+       udelay(10);
+       systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O;
+       writew(systest, &i2c_base->systest);
+       udelay(10);
+
+       /* restore original mode */
+       writew(orgsystest, &i2c_base->systest);
+}
+
 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;
+       int deblock = 1;
 
+retry:
        if (readw(&i2c_base->con) & I2C_CON_EN) {
                writew(0, &i2c_base->con);
                udelay(50000);
@@ -194,6 +243,14 @@ static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
        udelay(1000);
        flush_fifo(adap);
        writew(0xFFFF, &i2c_base->stat);
+
+       /* Handle possible failed I2C state */
+       if (wait_for_bb(adap))
+               if (deblock == 1) {
+                       omap24_i2c_deblock(adap);
+                       deblock = 0;
+                       goto retry;
+               }
 }
 
 static void flush_fifo(struct i2c_adapter *adap)