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@xxxxxxxxxxxxx> 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.
Attachment:
signature.asc
Description: PGP signature