From 3c56fbfb4caa05ac61393b89cbba3a93f000c373 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 18 Oct 2018 18:50:32 +0800 Subject: [PATCH] i2c: rk3x: Disable i2c controller after i2c transfer finished If the slave hold the scl low for a long time, we will send the stop because the i2c transfer is timeout. Then reset the slave, the scl will be released to high by slave, the data hold low, but the controller's state is messy now, need to diable i2c controller, it is better to reset i2c controller, it will go back to normal state. The log like this: [ 117.444700] rk3x-i2c ff3d0000.i2c: timeout, ipd: 0x93, state: 2 [ 118.466410] rk3x-i2c ff3d0000.i2c: timeout, ipd: 0x00, state: 1 [ 119.486217] rk3x-i2c ff3d0000.i2c: timeout, ipd: 0x00, state: 1 or [ 91.733176] rk3x-i2c ff3d0000.i2c: timeout, ipd: 0x80, state: 1 [ 103.406776] rk3x-i2c ff3d0000.i2c: timeout, ipd: 0x00, state: 2 [ 104.426636] rk3x-i2c ff3d0000.i2c: timeout, ipd: 0x00, state: 2 Change-Id: I53e6e383c849cea22d870f9488c23720e74115df Signed-off-by: David Wu --- drivers/i2c/busses/i2c-rk3x.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 9b1db8160d1c..653e471ca9cb 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -246,6 +246,13 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c) i2c_writel(i2c, REG_INT_ALL, REG_IPD); } +static inline void rk3x_i2c_disable(struct rk3x_i2c *i2c) +{ + u32 val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK; + + i2c_writel(i2c, val, REG_CON); +} + /** * Generate a START condition, which triggers a REG_INT_START interrupt. */ @@ -1118,6 +1125,8 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, } } + rk3x_i2c_disable(i2c); + clk_disable(i2c->pclk); clk_disable(i2c->clk);