Merge tag 'mips-pull-2019-04-12' of git://git.denx.de/u-boot-mips
[platform/kernel/u-boot.git] / drivers / i2c / mxc_i2c.c
index a17c1ec..5420afb 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * i2c driver for Freescale i.MX series
  *
@@ -10,8 +11,6 @@
  *  Copyright (C) 2007 RightHand Technologies, Inc.
  *  Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>
  *
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
@@ -355,9 +354,10 @@ int i2c_idle_bus(struct mxc_i2c_bus *i2c_bus)
 int i2c_idle_bus(struct mxc_i2c_bus *i2c_bus)
 {
        struct udevice *bus = i2c_bus->bus;
+       struct dm_i2c_bus *i2c = dev_get_uclass_priv(bus);
        struct gpio_desc *scl_gpio = &i2c_bus->scl_gpio;
        struct gpio_desc *sda_gpio = &i2c_bus->sda_gpio;
-       int sda, scl;
+       int sda, scl, idle_sclks;
        int i, ret = 0;
        ulong elapsed, start_time;
 
@@ -381,8 +381,22 @@ int i2c_idle_bus(struct mxc_i2c_bus *i2c_bus)
        if ((sda & scl) == 1)
                goto exit;              /* Bus is idle already */
 
+       /*
+        * In most cases it is just enough to generate 8 + 1 SCLK
+        * clocks to recover I2C slave device from 'stuck' state
+        * (when for example SW reset was performed, in the middle of
+        * I2C transmission).
+        *
+        * However, there are devices which send data in packets of
+        * N bytes (N > 1). In such case we do need N * 8 + 1 SCLK
+        * clocks.
+        */
+       idle_sclks = 8 + 1;
+
+       if (i2c->max_transaction_bytes > 0)
+               idle_sclks = i2c->max_transaction_bytes * 8 + 1;
        /* Send high and low on the SCL line */
-       for (i = 0; i < 9; i++) {
+       for (i = 0; i < idle_sclks; i++) {
                dm_gpio_set_dir_flags(scl_gpio, GPIOD_IS_OUT);
                dm_gpio_set_value(scl_gpio, 0);
                udelay(50);