OSDN Git Service

i2c: davinci: Refactor i2c_davinci_wait_bus_not_busy()
authorAlexander Sverdlin <alexander.sverdlin@nokia.com>
Tue, 9 Jun 2015 10:58:29 +0000 (12:58 +0200)
committerWolfram Sang <wsa@the-dreams.de>
Wed, 10 Jun 2015 13:08:36 +0000 (22:08 +0900)
There are several problems in the function:
- "to_cnt" variable does nothing
- schedule_timeout() call without setting current state does nothing
- "allow_sleep" parameter is not really used

Refactor the function so that it really tries to wait. In case of timeout try
to recover the bus.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
drivers/i2c/busses/i2c-davinci.c

index 4788a32..ab341aa 100644 (file)
@@ -350,29 +350,25 @@ static struct i2c_bus_recovery_info davinci_i2c_scl_recovery_info = {
 /*
  * Waiting for bus not busy
  */
-static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
-                                        char allow_sleep)
+static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev)
 {
-       unsigned long timeout;
-       static u16 to_cnt;
-
-       timeout = jiffies + dev->adapter.timeout;
-       while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG)
-              & DAVINCI_I2C_STR_BB) {
-               if (to_cnt <= DAVINCI_I2C_MAX_TRIES) {
-                       if (time_after(jiffies, timeout)) {
-                               dev_warn(dev->dev,
-                               "timeout waiting for bus ready\n");
-                               to_cnt++;
-                               return -ETIMEDOUT;
-                       } else {
-                               to_cnt = 0;
-                               i2c_recover_bus(&dev->adapter);
-                       }
-               }
-               if (allow_sleep)
-                       schedule_timeout(1);
-       }
+       unsigned long timeout = jiffies + dev->adapter.timeout;
+
+       do {
+               if (!(davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB))
+                       return 0;
+               schedule_timeout_uninterruptible(1);
+       } while (time_before_eq(jiffies, timeout));
+
+       dev_warn(dev->dev, "timeout waiting for bus ready\n");
+       i2c_recover_bus(&dev->adapter);
+
+       /*
+        * if bus is still "busy" here, it's most probably a HW problem like
+        * short-circuit
+        */
+       if (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB)
+               return -EIO;
 
        return 0;
 }
@@ -505,7 +501,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
        dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
 
-       ret = i2c_davinci_wait_bus_not_busy(dev, 1);
+       ret = i2c_davinci_wait_bus_not_busy(dev);
        if (ret < 0) {
                dev_warn(dev->dev, "timeout waiting for bus ready\n");
                return ret;