i2c: designware: Add error checking on init
authorSimon Glass <sjg@chromium.org>
Sun, 17 Feb 2019 03:24:39 +0000 (20:24 -0700)
committerBin Meng <bmeng.cn@gmail.com>
Wed, 20 Feb 2019 07:21:44 +0000 (15:21 +0800)
At present this driver does not check whether it is able to actually
communicate with the I2C controller. It prints a timeout message but still
considers the probe to be successful.

To fix this, add some checking that the init succeeds.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
drivers/i2c/designware_i2c.c

index dbc3326b5a9923c78550465ec31a55e7511161a4..63e40823f121f680b2d0b214c0e45b16f8f18db9 100644 (file)
@@ -38,14 +38,16 @@ struct dw_i2c {
 };
 
 #ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
-static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
+static int  dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
 {
        u32 ena = enable ? IC_ENABLE_0B : 0;
 
        writel(ena, &i2c_base->ic_enable);
+
+       return 0;
 }
 #else
-static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
+static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
 {
        u32 ena = enable ? IC_ENABLE_0B : 0;
        int timeout = 100;
@@ -53,7 +55,7 @@ static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
        do {
                writel(ena, &i2c_base->ic_enable);
                if ((readl(&i2c_base->ic_enable_status) & IC_ENABLE_0B) == ena)
-                       return;
+                       return 0;
 
                /*
                 * Wait 10 times the signaling period of the highest I2C
@@ -62,8 +64,9 @@ static void dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
                 */
                udelay(25);
        } while (timeout--);
-
        printf("timeout in %sabling I2C adapter\n", enable ? "en" : "dis");
+
+       return -ETIMEDOUT;
 }
 #endif
 
@@ -370,10 +373,14 @@ static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr,
  *
  * Initialization function.
  */
-static void __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
+static int __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
 {
+       int ret;
+
        /* Disable i2c */
-       dw_i2c_enable(i2c_base, false);
+       ret = dw_i2c_enable(i2c_base, false);
+       if (ret)
+               return ret;
 
        writel(IC_CON_SD | IC_CON_RE | IC_CON_SPD_FS | IC_CON_MM,
               &i2c_base->ic_con);
@@ -386,7 +393,11 @@ static void __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
 #endif
 
        /* Enable i2c */
-       dw_i2c_enable(i2c_base, true);
+       ret = dw_i2c_enable(i2c_base, true);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
 #ifndef CONFIG_DM_I2C
@@ -558,9 +569,7 @@ static int designware_i2c_probe(struct udevice *bus)
        if (&priv->reset_ctl)
                reset_deassert(&priv->reset_ctl);
 
-       __dw_i2c_init(priv->regs, 0, 0);
-
-       return 0;
+       return __dw_i2c_init(priv->regs, 0, 0);
 }
 
 static int designware_i2c_bind(struct udevice *dev)