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)
committerWolfram Sang <wsa@kernel.org>
Wed, 13 Sep 2023 09:04:25 +0000 (11:04 +0200)
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>
drivers/i2c/busses/i2c-aspeed.c

index 2e5acfe..5a416b3 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