]> git.baikalelectronics.ru Git - kernel.git/commitdiff
i2c: aspeed: Reset the i2c controller when timeout occurs
authorTommy Huang <tommy_huang@aspeedtech.com>
Wed, 6 Sep 2023 00:49:10 +0000 (08:49 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Sep 2023 09:11:12 +0000 (11:11 +0200)
commit fee465150b458351b6d9b9f66084f3cc3022b88b upstream.

Reset the i2c controller when an i2c transfer timeout occurs.
The remaining interrupts and device should be reset to avoid
unpredictable controller behavior.

Fixes: 2e57b7cebb98 ("i2c: aspeed: Add multi-master use case support")
Cc: <stable@vger.kernel.org> # v5.1+
Signed-off-by: Tommy Huang <tommy_huang@aspeedtech.com>
Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/i2c/busses/i2c-aspeed.c

index c64c381b69b7f8ce923b0ada0e219561b7198954..866c52afb8b0a9f37cace4956e076d5ec7e7f816 100644 (file)
@@ -698,13 +698,16 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
 
        if (time_left == 0) {
                /*
-                * If timed out and bus is still busy in a multi master
-                * environment, attempt recovery at here.
+                * In a multi-master setup, if a timeout occurs, attempt
+                * recovery. But if the bus is idle, we still need to reset the
+                * i2c controller to clear the remaining interrupts.
                 */
                if (bus->multi_master &&
                    (readl(bus->base + ASPEED_I2C_CMD_REG) &
                     ASPEED_I2CD_BUS_BUSY_STS))
                        aspeed_i2c_recover_bus(bus);
+               else
+                       aspeed_i2c_reset(bus);
 
                /*
                 * If timed out and the state is still pending, drop the pending