How to recover from I2C bus lockup?
I've been testing an Up Board with a variety of I2C peripherals and encountering some problems with buggy I2C devices. Occasionally I will run into a situation where I2C read/writes will timeout, and the bus master loses arbitration. i2cdetect gets stuck. If I unplug the I2C devices, and replug them back in, everything usually works again, but this isn't a long term solution that works automatically. I need a system that can recover from faults like this.
I've read various articles such as AN-686 which discusses clocking out the problem.
I tried this out, and was able to sometimes recover the bus by using the GPIO pins attached to the I2C lines to toggle SCL ten times, and then SDA ten times. The bus would become available again, and i2cdetect would work again. However, I found other situations where it appears like the I2C master itself was stuck. I could unplug the I2C peripherals, and it was still stuck. Rebooting the Up Board did fix the problem, so it appears like it could be correctable in software.
I tried messing with the I2C driver but that did not fix anything.
echo -n "808622C1:00" > /sys/bus/platform/drivers/i2c_designware/unbind
echo -n "808622C1:01" > /sys/bus/platform/drivers/i2c_designware/unbind
echo -n "808622C1:00" > /sys/bus/platform/drivers/i2c_designware/bind
echo -n "808622C1:01" > /sys/bus/platform/drivers/i2c_designware/bind
Rather than doing these hacks that aren't working, is there a better way to recover?
(1) How to reset the onboard I2C master on the UpBoard without a reboot?
(2) How to clock out the bus to unlock any peripherals on the I2C bus?
I'm using Ubuntu 18.04 with the upboard kernel: 4.15.0-37-generic #40~upboard06-Ubuntu