Dear Maintainer, For octeon TWSI controller, I found below two cases, maybe can be improved. >From 09d9f0ce658d7f6a50d1af352dde619c29bc8bcf Mon Sep 17 00:00:00 2001 From: hgt463 <sean.c.zhang@xxxxxxxxx> Date: Thu, 23 Nov 2017 18:46:09 +0800 Subject: [PATCH] Driver updates: - In the case of I2C bus dead lock occurred during driver probing, it is better try to recovery it. so added bus recovery step in octeon_i2c_probe(); - The purpose of function octeon_i2c_start() is to send START, so after bus recovery, also need try to send START again. Signed-off-by: hgt463 <sean.c.zhang@xxxxxxxxx> --- drivers/i2c/busses/i2c-octeon-core.c | 31 ++++++++++++++++++++++++++++++- drivers/i2c/busses/i2c-octeon-platdrv.c | 15 +++++++++------ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index 1d87757..3ae1e03 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -255,6 +255,35 @@ static int octeon_i2c_recovery(struct octeon_i2c *i2c) return ret; } +/* + * octeon_i2c_start_retry - send START to the bus after bus recovery. + * @i2c: The struct octeon_i2c + * + * Returns 0 on success, otherwise a negative errno. + */ +static int octeon_i2c_start_retry(struct octeon_i2c *i2c) +{ + int ret; + u8 stat; + + ret = octeon_i2c_recovery(i2c); + if (ret) + goto error; + + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA); + ret = octeon_i2c_wait(i2c); + if (ret) + goto error; + + stat = octeon_i2c_stat_read(i2c); + if (stat == STAT_START || stat == STAT_REP_START) + /* START successful, bail out */ + return 0; + +error: + return (ret) ? ret : -EAGAIN; +} + /** * octeon_i2c_start - send START to the bus * @i2c: The struct octeon_i2c @@ -280,7 +309,7 @@ static int octeon_i2c_start(struct octeon_i2c *i2c) error: /* START failed, try to recover */ - ret = octeon_i2c_recovery(i2c); + ret = octeon_i2c_start_retry(i2c); return (ret) ? ret : -EAGAIN; } diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index 64bda83..98063af 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -228,12 +228,6 @@ static int octeon_i2c_probe(struct platform_device *pdev) if (OCTEON_IS_MODEL(OCTEON_CN38XX)) i2c->broken_irq_check = true; - result = octeon_i2c_init_lowlevel(i2c); - if (result) { - dev_err(i2c->dev, "init low level failed\n"); - goto out; - } - octeon_i2c_set_clock(i2c); i2c->adap = octeon_i2c_ops; @@ -245,6 +239,15 @@ static int octeon_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&i2c->adap, i2c); platform_set_drvdata(pdev, i2c); + stat = octeon_i2c_stat_read(i2c); + if (stat != STAT_IDLE) { + result = octeon_i2c_recovery(i2c); + if (result) { + dev_err(i2c->dev, "octeon i2c recovery failed\n"); + goto out; + } + } + result = i2c_add_adapter(&i2c->adap); if (result < 0) goto out; Attached patch for you review. Thanks in advance. BR, Sean Zhang
Attachment:
0001-Driver-updates.patch
Description: 0001-Driver-updates.patch