Commit 8213dca8 authored by Tommy Huang's avatar Tommy Huang Committed by sanglipeng
Browse files

i2c: aspeed: Reset the i2c controller when timeout occurs

stable inclusion
from stable-v5.10.197
commit 993bb01d228b7cfccbade4e7e840f3d18678260b
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I96Q8P

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=993bb01d228b7cfccbade4e7e840f3d18678260b



--------------------------------

commit fee46515 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: 2e57b7ce ("i2c: aspeed: Add multi-master use case support")
Cc: <stable@vger.kernel.org> # v5.1+
Signed-off-by: default avatarTommy Huang <tommy_huang@aspeedtech.com>
Reviewed-by: default avatarAndi Shyti <andi.shyti@kernel.org>
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarsanglipeng <sanglipeng1@jd.com>
parent dbef94fb
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -693,13 +693,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