]> www.infradead.org Git - users/willy/xarray.git/commitdiff
i2c: aspeed: Update the stop sw state when the bus recovery occurs
authorTommy Huang <tommy_huang@aspeedtech.com>
Wed, 11 Sep 2024 09:39:51 +0000 (17:39 +0800)
committerAndi Shyti <andi.shyti@kernel.org>
Wed, 11 Sep 2024 15:54:21 +0000 (17:54 +0200)
When the i2c bus recovery occurs, driver will send i2c stop command
in the scl low condition. In this case the sw state will still keep
original situation. Under multi-master usage, i2c bus recovery will
be called when i2c transfer timeout occurs. Update the stop command
calling with aspeed_i2c_do_stop function to update master_state.

Fixes: f327c686d3ba ("i2c: aspeed: added driver for Aspeed I2C")
Cc: stable@vger.kernel.org # v4.13+
Signed-off-by: Tommy Huang <tommy_huang@aspeedtech.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
drivers/i2c/busses/i2c-aspeed.c

index ce8c4846b7fae4548e36ccd78ce59ce1c90532f3..2a03a221e2dd57d4a22ea42201b35caabe19741c 100644 (file)
@@ -170,6 +170,13 @@ struct aspeed_i2c_bus {
 
 static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
 
+/* precondition: bus.lock has been acquired. */
+static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
+{
+       bus->master_state = ASPEED_I2C_MASTER_STOP;
+       writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
+}
+
 static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
 {
        unsigned long time_left, flags;
@@ -187,7 +194,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
                        command);
 
                reinit_completion(&bus->cmd_complete);
-               writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
+               aspeed_i2c_do_stop(bus);
                spin_unlock_irqrestore(&bus->lock, flags);
 
                time_left = wait_for_completion_timeout(
@@ -390,13 +397,6 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
        writel(command, bus->base + ASPEED_I2C_CMD_REG);
 }
 
-/* precondition: bus.lock has been acquired. */
-static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
-{
-       bus->master_state = ASPEED_I2C_MASTER_STOP;
-       writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
-}
-
 /* precondition: bus.lock has been acquired. */
 static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
 {