i2c: exynos5: add conditional reset of hsi2c master before transfer
authorYoungmin Nam <youngmin.nam@samsung.com>
Tue, 5 Jan 2016 06:18:28 +0000 (15:18 +0900)
committermyung-su.cha <myung-su.cha@samsung.com>
Wed, 9 May 2018 12:14:45 +0000 (21:14 +0900)
This patch resets hsi2c master before transfer if related property was set.
HSI2C master can goes into master arbitration lost state if there is the
fluctuation on SCL/SDA line before starting transfer.
To getting out of this state, mater should be reset.

Change-Id: I2487152abff708f61182bbca866f51a421a0c4c9
Signed-off-by: Youngmin Nam <youngmin.nam@samsung.com>
drivers/i2c/busses/i2c-exynos5.c
drivers/i2c/busses/i2c-exynos5.h

index 4378ecdc8dc0aea51485426d4cd51708710d1439..56cd86c16a332b3ea98d40ac49c2e685555c5b5e 100644 (file)
@@ -816,6 +816,16 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
        exynos_update_ip_idle_status(i2c->idle_ip_index, 0);
        clk_prepare_enable(i2c->clk);
 #endif
+
+       /* If master is in arbitration lost state before transfer */
+       /* master should be reset */
+       if (i2c->reset_before_trans) {
+               if (unlikely((readl(i2c->regs + HSI2C_TRANS_STATUS)
+                       & HSI2C_MAST_ST_MASK) == 0xC)) {
+                       i2c->need_hw_init = 1;
+               }
+       }
+
        if (i2c->need_hw_init)
                exynos5_i2c_reset(i2c);
 
@@ -959,6 +969,11 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
        else
                i2c->stop_after_trans = 0;
 
+       if (of_get_property(np, "samsung,reset-before-trans", NULL))
+               i2c->reset_before_trans = 1;
+       else
+               i2c->reset_before_trans = 0;
+
        i2c->idle_ip_index = exynos_get_idle_ip_index(dev_name(&pdev->dev));
 
        strlcpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name));
index 70a6bcb15185144e9a2b453d4067cfc1838d0f39..cf299da1838fe7e4b1efd519b3cfa91d756856a3 100644 (file)
@@ -54,5 +54,6 @@ struct exynos5_i2c {
        unsigned int            transfer_delay;
 
        int                     idle_ip_index;
+       int                     reset_before_trans;
 };
 #endif /*__I2C_EXYNOS5_H */