{"id":2197817,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2197817/?format=json","project":{"id":35,"url":"http://patchwork.ozlabs.org/api/1.0/projects/35/?format=json","name":"Linux I2C development","link_name":"linux-i2c","list_id":"linux-i2c.vger.kernel.org","list_email":"linux-i2c@vger.kernel.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260218150940.131354-3-eichest@gmail.com>","date":"2026-02-18T15:08:50","name":"[v1,2/2] i2c: imx: ensure no clock is generated after last read","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"118d9ffc1aa0b819b6093dbb56a22d186a881f3d","submitter":{"id":70438,"url":"http://patchwork.ozlabs.org/api/1.0/people/70438/?format=json","name":"Stefan Eichenberger","email":"eichest@gmail.com"},"delegate":{"id":149066,"url":"http://patchwork.ozlabs.org/api/1.0/users/149066/?format=json","username":"cazzacarna","first_name":"Andi","last_name":"Shyti","email":"andi.shyti@kernel.org"},"mbox":"http://patchwork.ozlabs.org/project/linux-i2c/patch/20260218150940.131354-3-eichest@gmail.com/mbox/","series":[{"id":492569,"url":"http://patchwork.ozlabs.org/api/1.0/series/492569/?format=json","date":"2026-02-18T15:08:48","name":"i2c: imx: fix i2c issues when reading messages","version":1,"mbox":"http://patchwork.ozlabs.org/series/492569/mbox/"}],"check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2197817/checks/","tags":{},"headers":{"Return-Path":"\n <linux-i2c+bounces-16047-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-i2c@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=N+KMiHrg;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-i2c+bounces-16047-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=\"N+KMiHrg\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.128.41","smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gmail.com"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fGKgw3Mgyz1xpl\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 19 Feb 2026 02:10:20 +1100 (AEDT)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 5DD743020A42\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 18 Feb 2026 15:09:57 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 3F2F42FBE05;\n\tWed, 18 Feb 2026 15:09:57 +0000 (UTC)","from mail-wm1-f41.google.com (mail-wm1-f41.google.com\n [209.85.128.41])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 673CC285CB3\n\tfor <linux-i2c@vger.kernel.org>; Wed, 18 Feb 2026 15:09:55 +0000 (UTC)","by mail-wm1-f41.google.com with SMTP id\n 5b1f17b1804b1-48371119eacso51479175e9.2\n        for <linux-i2c@vger.kernel.org>; Wed, 18 Feb 2026 07:09:55 -0800 (PST)","from eichest-laptop.corp.toradex.com\n (248.201.173.83.static.wline.lns.sme.cust.swisscom.ch. [83.173.201.248])\n        by smtp.gmail.com with ESMTPSA id\n ffacd0b85a97d-43796ac7d91sm44333116f8f.26.2026.02.18.07.09.52\n        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n        Wed, 18 Feb 2026 07:09:53 -0800 (PST)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1771427396; cv=none;\n b=GwsQq0ODUgY6lItP3NmK3JhMKHmLSM25zNYVxZU9BW0Z/ADXCOgsg58BdWCVwasPVAvAlJXwRpZupvwzkx2VXNMchWWsJDoQ2zpn169cW2J6gVjdk5vS4c3vbFgHkTfPC50AWbifmkDvh1pcyt1toLLh8FkQqDdX+birLxaoAfs=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1771427396; c=relaxed/simple;\n\tbh=nD2q10ThWeIvjvO9WzEUwgKZIjJ/JreIZj5OT5fabdY=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=pET0M1acOJVvuSfejab2FwrU6tDmpBsn+2/ULPjDdm5kQKm+9jEQ49LdLr23/IHzoijpVBod2NbOpV6MZryKWFsGHPlgxSo1PFNKplJv8yMNZ/53OwGzPZAIn3/OXBG/EnA2vfo8TfUdNQdxeveRNzEDNoRHctVfgvDAd6YEXYs=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com;\n spf=pass smtp.mailfrom=gmail.com;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=N+KMiHrg; arc=none smtp.client-ip=209.85.128.41","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=gmail.com; s=20230601; t=1771427394; x=1772032194;\n darn=vger.kernel.org;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n         :message-id:reply-to;\n        bh=YiCCUrdk9XYqcbI+I7lzNNzu+GG7xW/ZdG+JQfCsf/M=;\n        b=N+KMiHrgFWHEPKSZoiDJvWVFBaBSeygtPh2iuxwN64QKECidoiB0q+fP+FGNhcJAvD\n         N3tmKKwsedRVpOj7hfyH8B2b+go6MP2cGhL/6aGBkOOpvutG88u1vuEbc5MDeVZU8oiN\n         G2CaOoR0IoRu4mqjZOL6yR/xrOVixBOZ3XyCnCR6zqkjBtDBuL9Qjv2svWcORL/w5NtE\n         7egE5nnsl9scsxbEoSrFpnSNC97KykE+u1tARGtLVTTzNpmIa+TCWzxEHGWY9iXSFU7E\n         U8ipA/ftwkRvXnvueZt8edCehJPmTowBTa1QfjoTwjJrYLQLeBQWsw14BLyZQgqS3VWm\n         1pWQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=1e100.net; s=20230601; t=1771427394; x=1772032194;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n         :to:cc:subject:date:message-id:reply-to;\n        bh=YiCCUrdk9XYqcbI+I7lzNNzu+GG7xW/ZdG+JQfCsf/M=;\n        b=tM6D1BuQuS0mjD9ve6VktCb/Ar0TAXlzJ3HHkbyKdJ8b4SX92xWAu7eDq5OivO7uCs\n         M9HCClvA1A+jnEQkbyLMKG1/rmkY0m68NRbyrswSds2eS0a88VwaKOi/AVqMAn4JG5T4\n         VbG75foeaJSnodQoHyn2kUD07Ahri35H+ETwykrO/cNJJjTwL36jYOhQYWE7pOO4ZZdO\n         c1QeorMw0PpBm47h6LEgi2HxPNR3qhjVR3cTC84TAWj8FFAyu9wBQdvN295O4a3gSpqZ\n         xfsHdLt7vAyScMsZEbg6f5AeUACy05QvhMcvY39nVS6ONu1iQ+iqYVt2F++RApNmY68Q\n         DkEQ==","X-Gm-Message-State":"AOJu0YzSEBuSotXvxjqEoijlO4zGQVq9akiufVJKXG8PhMRBWDoE1HVC\n\tva7Rho698ow92+2E6rB6hkGdY3bjjN8JHlfI70EpHpTO7ZfbFHha3f6/","X-Gm-Gg":"AZuq6aLiKzDYIpOiAInirX/AvNb2KMubmEBkMYVfakFJa8FrhoZvJG1EqFjAnAbyMP1\n\tHBeecCrDU892Un1svUT5TPNBT9K8bdJJUO6i7vqgcbWTK5CR0b3QqgSbYgwlzFUbDlCON4ks4la\n\tGssFfJblIm/J7P4KNEEMOASIDvb82xwS9/W8FVzAcAxy+rfjGFLDRoVxfgpzUWRmq+IKmoYR+jr\n\tBthJEK6n5KQKlG5G0w8tDaBw06wDqSXs37yxSTFdhJrAEKmFFrXE+TRwxGE4y3BsVnWKogHgaAl\n\tkFAyJ4+thUOE34Tpz3kNC/0dTyjlGI9CM8L0Tg/4E2QrVqUEiMaFiooeR/6dS7dH1OmC8jM/Jx6\n\t55SeWEAwN3KcXp7uobLD7OoQhmQOqB+3xjjnrrpXZwTpvaIl6g994aZzkL4AjJG+UX70Mjj475X\n\tzuwmh+j4VVrCxk0EWs4lyaYWG8uhZ0ntxx+ZIYHJDP2ieG0A56yMykqfoaoYGb5LZ9e2e+JVM4b\n\t8zg5dEnBpMgXHBRtAoVbORCeYEl8qD6bSlGjoOTOneJVzQ=","X-Received":"by 2002:a05:600d:13:b0:477:5b0a:e616 with SMTP id\n 5b1f17b1804b1-4839b4c7242mr20986195e9.5.1771427393465;\n        Wed, 18 Feb 2026 07:09:53 -0800 (PST)","From":"Stefan Eichenberger <eichest@gmail.com>","To":"o.rempel@pengutronix.de,\n\tkernel@pengutronix.de,\n\tandi.shyti@kernel.org,\n\tFrank.Li@nxp.com,\n\ts.hauer@pengutronix.de,\n\tfestevam@gmail.com,\n\tstefan.eichenberger@toradex.com,\n\tfrancesco.dolcini@toradex.com","Cc":"linux-i2c@vger.kernel.org,\n\timx@lists.linux.dev,\n\tlinux-arm-kernel@lists.infradead.org,\n\tlinux-kernel@vger.kernel.org,\n\tstable@vger.kernel.org","Subject":"[PATCH v1 2/2] i2c: imx: ensure no clock is generated after last read","Date":"Wed, 18 Feb 2026 16:08:50 +0100","Message-ID":"<20260218150940.131354-3-eichest@gmail.com>","X-Mailer":"git-send-email 2.51.0","In-Reply-To":"<20260218150940.131354-1-eichest@gmail.com>","References":"<20260218150940.131354-1-eichest@gmail.com>","Precedence":"bulk","X-Mailing-List":"linux-i2c@vger.kernel.org","List-Id":"<linux-i2c.vger.kernel.org>","List-Subscribe":"<mailto:linux-i2c+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-i2c+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit"},"content":"From: Stefan Eichenberger <stefan.eichenberger@toradex.com>\n\nWhen reading from the I2DR register, right after releasing the bus by\nclearing MSTA and MTX, the I2C controller might still generate an\nadditional clock cycle which can cause devices to misbehave. Ensure to\nonly read from I2DR after the bus is not busy anymore. Because this\nrequires polling, the read of the last byte is moved outside of the\ninterrupt handler.\n\nAn example for such a failing transfer is this:\ni2ctransfer -y -a 0 w1@0x00 0x02 r1\nError: Sending messages failed: Connection timed out\nIt does not happen with every device because not all devices react to\nthe additional clock cycle.\n\nFixes: 5f5c2d4579ca (\"i2c: imx: prevent rescheduling in non dma mode\")\nCc: <stable@vger.kernel.org> # v6.13+\nSigned-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>\n---\n drivers/i2c/busses/i2c-imx.c | 51 ++++++++++++++++++++++--------------\n 1 file changed, 32 insertions(+), 19 deletions(-)","diff":"diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c\nindex 56e2a14495a9a..452d120a210b1 100644\n--- a/drivers/i2c/busses/i2c-imx.c\n+++ b/drivers/i2c/busses/i2c-imx.c\n@@ -1018,8 +1018,9 @@ static inline int i2c_imx_isr_read(struct imx_i2c_struct *i2c_imx)\n \treturn 0;\n }\n \n-static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)\n+static inline enum imx_i2c_state i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)\n {\n+\tenum imx_i2c_state next_state = IMX_I2C_STATE_READ_CONTINUE;\n \tunsigned int temp;\n \n \tif ((i2c_imx->msg->len - 1) == i2c_imx->msg_buf_idx) {\n@@ -1033,18 +1034,20 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)\n \t\t\t\ti2c_imx->stopped =  1;\n \t\t\ttemp &= ~(I2CR_MSTA | I2CR_MTX);\n \t\t\timx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);\n-\t\t} else {\n-\t\t\t/*\n-\t\t\t * For i2c master receiver repeat restart operation like:\n-\t\t\t * read -> repeat MSTA -> read/write\n-\t\t\t * The controller must set MTX before read the last byte in\n-\t\t\t * the first read operation, otherwise the first read cost\n-\t\t\t * one extra clock cycle.\n-\t\t\t */\n-\t\t\ttemp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);\n-\t\t\ttemp |= I2CR_MTX;\n-\t\t\timx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);\n+\n+\t\t\treturn IMX_I2C_STATE_DONE;\n \t\t}\n+\t\t/*\n+\t\t * For i2c master receiver repeat restart operation like:\n+\t\t * read -> repeat MSTA -> read/write\n+\t\t * The controller must set MTX before read the last byte in\n+\t\t * the first read operation, otherwise the first read cost\n+\t\t * one extra clock cycle.\n+\t\t */\n+\t\ttemp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);\n+\t\ttemp |= I2CR_MTX;\n+\t\timx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);\n+\t\tnext_state = IMX_I2C_STATE_DONE;\n \t} else if (i2c_imx->msg_buf_idx == (i2c_imx->msg->len - 2)) {\n \t\ttemp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);\n \t\ttemp |= I2CR_TXAK;\n@@ -1052,6 +1055,7 @@ static inline void i2c_imx_isr_read_continue(struct imx_i2c_struct *i2c_imx)\n \t}\n \n \ti2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);\n+\treturn next_state;\n }\n \n static inline void i2c_imx_isr_read_block_data_len(struct imx_i2c_struct *i2c_imx)\n@@ -1088,11 +1092,9 @@ static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned i\n \t\tbreak;\n \n \tcase IMX_I2C_STATE_READ_CONTINUE:\n-\t\ti2c_imx_isr_read_continue(i2c_imx);\n-\t\tif (i2c_imx->msg_buf_idx == i2c_imx->msg->len) {\n-\t\t\ti2c_imx->state = IMX_I2C_STATE_DONE;\n+\t\ti2c_imx->state = i2c_imx_isr_read_continue(i2c_imx);\n+\t\tif (i2c_imx->state == IMX_I2C_STATE_DONE)\n \t\t\twake_up(&i2c_imx->queue);\n-\t\t}\n \t\tbreak;\n \n \tcase IMX_I2C_STATE_READ_BLOCK_DATA:\n@@ -1490,6 +1492,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,\n \t\t\tbool is_lastmsg)\n {\n \tint block_data = msgs->flags & I2C_M_RECV_LEN;\n+\tint ret = 0;\n \n \tdev_dbg(&i2c_imx->adapter.dev,\n \t\t\"<%s> write slave address: addr=0x%x\\n\",\n@@ -1522,10 +1525,20 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,\n \t\tdev_err(&i2c_imx->adapter.dev, \"<%s> read timedout\\n\", __func__);\n \t\treturn -ETIMEDOUT;\n \t}\n-\tif (i2c_imx->is_lastmsg && !i2c_imx->stopped)\n-\t\treturn i2c_imx_bus_busy(i2c_imx, 0, false);\n+\tif (i2c_imx->is_lastmsg) {\n+\t\tif (!i2c_imx->stopped)\n+\t\t\tret = i2c_imx_bus_busy(i2c_imx, 0, false);\n+\t\t/*\n+\t\t * Only read the last byte of the last message after the bus is\n+\t\t * not busy. Else the controller generates another clock which\n+\t\t * might confuse devices.\n+\t\t */\n+\t\tif (!ret)\n+\t\t\ti2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = imx_i2c_read_reg(i2c_imx,\n+\t\t\t\t\t\t\t\t\t\t     IMX_I2C_I2DR);\n+\t}\n \n-\treturn 0;\n+\treturn ret;\n }\n \n static int i2c_imx_xfer_common(struct i2c_adapter *adapter,\n","prefixes":["v1","2/2"]}