i2c: rk3x: xfer timeout depends on data transferred length

Change the fixed i2c timeout transmission time dynamically to reduce
the time.

Signed-off-by: David Wu <david.wu@rock-chips.com>
Change-Id: Icd87b53f95da383c205caef9d110c9401ed7a6ac
This commit is contained in:
David Wu
2022-08-17 18:15:26 +08:00
committed by Tao Huang
parent 68c04ca2db
commit 64adcb65fd

View File

@@ -1150,9 +1150,9 @@ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num)
return ret;
}
static int rk3x_i2c_wait_xfer_poll(struct rk3x_i2c *i2c)
static int rk3x_i2c_wait_xfer_poll(struct rk3x_i2c *i2c, unsigned long xfer_time)
{
ktime_t timeout = ktime_add_ms(ktime_get(), WAIT_TIMEOUT);
ktime_t timeout = ktime_add_ms(ktime_get(), xfer_time);
while (READ_ONCE(i2c->busy) &&
ktime_compare(ktime_get(), timeout) < 0) {
@@ -1187,13 +1187,27 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
* rk3x_i2c_setup()).
*/
for (i = 0; i < num; i += ret) {
ret = rk3x_i2c_setup(i2c, msgs + i, num - i);
unsigned long xfer_time = 100;
int len;
ret = rk3x_i2c_setup(i2c, msgs + i, num - i);
if (ret < 0) {
dev_err(i2c->dev, "rk3x_i2c_setup() failed\n");
break;
}
/*
* Transfer time in mSec = Total bits / transfer rate + interval time
* Total bits = 9 bits per byte (including ACK bit) + Start & stop bits
*/
if (ret == 2)
len = msgs[i + 1].len;
else
len = msgs[i].len;
xfer_time += len / 64;
xfer_time += DIV_ROUND_CLOSEST(((len * 9) + 2) * MSEC_PER_SEC,
i2c->t.bus_freq_hz);
if (i + ret >= num)
i2c->is_last_msg = true;
@@ -1203,9 +1217,9 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
if (!polling) {
timeout = wait_event_timeout(i2c->wait, !i2c->busy,
msecs_to_jiffies(WAIT_TIMEOUT));
msecs_to_jiffies(xfer_time));
} else {
timeout = rk3x_i2c_wait_xfer_poll(i2c);
timeout = rk3x_i2c_wait_xfer_poll(i2c, xfer_time);
}
spin_lock_irqsave(&i2c->lock, flags);