Skip to content

Commit 768776d

Browse files
eichenbergerAndi Shyti
authored andcommitted
i2c: imx: fix missing stop condition in single-master mode
A regression was introduced with the implementation of single-master mode, preventing proper stop conditions from being generated. Devices that require a valid stop condition, such as EEPROMs, fail to function correctly as a result. The issue only affects devices with the single-master property enabled. This commit resolves the issue by re-enabling I2C bus busy bit (IBB) polling for single-master mode when generating a stop condition. The fix further ensures that the i2c_imx->stopped flag is cleared at the start of each transfer, allowing the stop condition to be correctly generated in i2c_imx_stop(). According to the reference manual (IMX8MMRM, Rev. 2, 09/2019, page 5270), polling the IBB bit to determine if the bus is free is only necessary in multi-master mode. Consequently, the IBB bit is not polled for the start condition in single-master mode. Fixes: 6692694 ("i2c: imx: do not poll for bus busy in single master mode") Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Reviewed-by: Francesco Dolcini <francesco.dolcini@toradex.com> Link: https://lore.kernel.org/r/20241216151829.74056-1-eichest@gmail.com Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
1 parent 4bbf902 commit 768776d

File tree

1 file changed

+3
-5
lines changed

1 file changed

+3
-5
lines changed

drivers/i2c/busses/i2c-imx.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -532,22 +532,20 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
532532

533533
static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
534534
{
535+
bool multi_master = i2c_imx->multi_master;
535536
unsigned long orig_jiffies = jiffies;
536537
unsigned int temp;
537538

538-
if (!i2c_imx->multi_master)
539-
return 0;
540-
541539
while (1) {
542540
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
543541

544542
/* check for arbitration lost */
545-
if (temp & I2SR_IAL) {
543+
if (multi_master && (temp & I2SR_IAL)) {
546544
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
547545
return -EAGAIN;
548546
}
549547

550-
if (for_busy && (temp & I2SR_IBB)) {
548+
if (for_busy && (!multi_master || (temp & I2SR_IBB))) {
551549
i2c_imx->stopped = 0;
552550
break;
553551
}

0 commit comments

Comments
 (0)