aboutsummaryrefslogtreecommitdiffstats
path: root/queue-6.15/i2c-imx-fix-emulated-smbus-block-read.patch
diff options
Diffstat (limited to 'queue-6.15/i2c-imx-fix-emulated-smbus-block-read.patch')
-rw-r--r--queue-6.15/i2c-imx-fix-emulated-smbus-block-read.patch64
1 files changed, 64 insertions, 0 deletions
diff --git a/queue-6.15/i2c-imx-fix-emulated-smbus-block-read.patch b/queue-6.15/i2c-imx-fix-emulated-smbus-block-read.patch
new file mode 100644
index 0000000000..87ecc1fdef
--- /dev/null
+++ b/queue-6.15/i2c-imx-fix-emulated-smbus-block-read.patch
@@ -0,0 +1,64 @@
+From a5d0b9e32745277644cda8d7d334e7080bd339bf Mon Sep 17 00:00:00 2001
+From: Lukasz Kucharczyk <lukasz.kucharczyk@leica-geosystems.com>
+Date: Tue, 20 May 2025 14:22:52 +0200
+Subject: i2c: imx: fix emulated smbus block read
+
+From: Lukasz Kucharczyk <lukasz.kucharczyk@leica-geosystems.com>
+
+commit a5d0b9e32745277644cda8d7d334e7080bd339bf upstream.
+
+Acknowledge the byte count submitted by the target.
+When I2C_SMBUS_BLOCK_DATA read operation is executed by
+i2c_smbus_xfer_emulated(), the length of the second (read) message is set
+to 1. Length of the block is supposed to be obtained from the target by the
+underlying bus driver.
+The i2c_imx_isr_read() function should emit the acknowledge on i2c bus
+after reading the first byte (i.e., byte count) while processing such
+message (as defined in Section 6.5.7 of System Management Bus
+Specification [1]). Without this acknowledge, the target does not submit
+subsequent bytes and the controller only reads 0xff's.
+
+In addition, store the length of block data obtained from the target in
+the buffer provided by i2c_smbus_xfer_emulated() - otherwise the first
+byte of actual data is erroneously interpreted as length of the data
+block.
+
+[1] https://smbus.org/specs/SMBus_3_3_20240512.pdf
+
+Fixes: 5f5c2d4579ca ("i2c: imx: prevent rescheduling in non dma mode")
+Signed-off-by: Lukasz Kucharczyk <lukasz.kucharczyk@leica-geosystems.com>
+Cc: <stable@vger.kernel.org> # v6.13+
+Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Reviewed-by: Stefan Eichenberger <eichest@gmail.com>
+Reviewed-by: Carlos Song <carlos.song@nxp.com>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Link: https://lore.kernel.org/r/20250520122252.1475403-1-lukasz.kucharczyk@leica-geosystems.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/busses/i2c-imx.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index e5732b0557fb..205cc132fdec 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -1008,7 +1008,7 @@ static inline int i2c_imx_isr_read(struct imx_i2c_struct *i2c_imx)
+ /* setup bus to read data */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp &= ~I2CR_MTX;
+- if (i2c_imx->msg->len - 1)
++ if ((i2c_imx->msg->len - 1) || (i2c_imx->msg->flags & I2C_M_RECV_LEN))
+ temp &= ~I2CR_TXAK;
+
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+@@ -1063,6 +1063,7 @@ static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_im
+ wake_up(&i2c_imx->queue);
+ }
+ i2c_imx->msg->len += len;
++ i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = len;
+ }
+
+ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status)
+--
+2.50.0
+