i2c: npcm: Assign client address earlier for `i2c_recover_bus()`
authorTyrone Ting <kfting@nuvoton.com>
Thu, 19 Dec 2024 09:08:57 +0000 (17:08 +0800)
committerAndi Shyti <andi.shyti@kernel.org>
Tue, 7 Jan 2025 22:46:10 +0000 (23:46 +0100)
Store the client address earlier since it might get called in
the i2c_recover_bus() logic flow at the early stage of
npcm_i2c_master_xfer().

Signed-off-by: Tyrone Ting <kfting@nuvoton.com>
Reviewed-by: Tali Perry <tali.perry1@gmail.com>
Link: https://lore.kernel.org/r/20241219090859.18722-3-kfting@nuvoton.com
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
drivers/i2c/busses/i2c-npcm7xx.c

index c96a25d37c14cdf9860f2cfa642d96ef73830a29..760608fdd075a832d0cfb846fcadd39ce2d2db1b 100644 (file)
@@ -2035,7 +2035,7 @@ static irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id)
 }
 
 static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus,
-                                      u8 slave_addr, u16 nwrite, u16 nread,
+                                      u16 nwrite, u16 nread,
                                       u8 *write_data, u8 *read_data,
                                       bool use_PEC, bool use_read_block)
 {
@@ -2043,7 +2043,6 @@ static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus,
                bus->cmd_err = -EBUSY;
                return false;
        }
-       bus->dest_addr = slave_addr << 1;
        bus->wr_buf = write_data;
        bus->wr_size = nwrite;
        bus->wr_ind = 0;
@@ -2086,7 +2085,6 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
        unsigned long time_left, flags;
        u16 nwrite, nread;
        u8 *write_data, *read_data;
-       u8 slave_addr;
        unsigned long timeout;
        bool read_block = false;
        bool read_PEC = false;
@@ -2099,7 +2097,6 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
        }
 
        msg0 = &msgs[0];
-       slave_addr = msg0->addr;
        if (msg0->flags & I2C_M_RD) { /* read */
                nwrite = 0;
                write_data = NULL;
@@ -2155,6 +2152,21 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 
        } while (time_is_after_jiffies(time_left) && bus_busy);
 
+       /*
+        * Store the address early in a global position to ensure it is
+        * accessible for a potential call to i2c_recover_bus().
+        *
+        * Since the transfer might be a read operation, remove the I2C_M_RD flag
+        * from the bus->dest_addr for the i2c_recover_bus() call later.
+        *
+        * The i2c_recover_bus() uses the address in a write direction to recover
+        * the i2c bus if some error condition occurs.
+        *
+        * Remove the I2C_M_RD flag from the address since npcm_i2c_master_start_xmit()
+        * handles the read/write operation internally.
+        */
+       bus->dest_addr = i2c_8bit_addr_from_msg(msg0) & ~I2C_M_RD;
+
        /*
         * Check the BER (bus error) state, when ber_state is true, it means that the module
         * detects the bus error which is caused by some factor like that the electricity
@@ -2172,7 +2184,6 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
        }
 
        npcm_i2c_init_params(bus);
-       bus->dest_addr = slave_addr;
        bus->msgs = msgs;
        bus->msgs_num = num;
        bus->cmd_err = 0;
@@ -2182,7 +2193,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 
        npcm_i2c_int_enable(bus, true);
 
-       if (npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread,
+       if (npcm_i2c_master_start_xmit(bus, nwrite, nread,
                                       write_data, read_data, read_PEC,
                                       read_block)) {
                /*