Re: [PATCH v3 3/6] i2c: at91: Send bus clear command if SDA is down
From: Wolfram Sang <hidden>
Date: 2020-02-22 11:44:39
Also in:
linux-devicetree, linux-i2c, lkml
On Wed, Jan 15, 2020 at 01:54:19PM +0200, Codrin Ciubotariu wrote:
After a transfer timeout, some faulty I2C slave devices might hold down the SDA pin. We can generate a bus clear command, hoping that the slave might release the pins. If the CLEAR command is not supported, we will use gpio recovery, if available, to reset the bus. Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
One thing to improve:
+ /*
+ * some faulty I2C slave devices might hold SDA down;
+ * we can send a bus clear command, hoping that the pins will be
+ * released
+ */
+ if (has_clear_cmd) {
+ if (!(dev->transfer_status & AT91_TWI_SDA)) {
+ dev_dbg(dev->dev,
+ "SDA is down; sending bus clear command\n");
+ if (dev->use_alt_cmd) {
+ unsigned int acr;
+
+ acr = at91_twi_read(dev, AT91_TWI_ACR);
+ acr &= ~AT91_TWI_ACR_DATAL_MASK;
+ at91_twi_write(dev, AT91_TWI_ACR, acr);
+ }
+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_CLEAR);
+ }The inner if-block should be a seperate function, then you could do in probe: if (has_clear_cmd) rinfo->recover_bus = <the above function>; else rinfo->recover_bus = i2c_generic_scl_recovery; Then, i2c_recover_bus() will always do the right thing. More readable and better maintainable IMO. If this is not possible (maybe I overlooked some logic), then maybe this will work: rinfo->recover_bus = <your custom function>; and put the if (has_clear_cmd) block there.