linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Gabbasov <andrew_gabbasov@mentor.com>
To: <linux-renesas-soc@vger.kernel.org>, <linux-i2c@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>,
	Wolfram Sang <wsa+renesas@sang-engineering.com>,
	Bhuvanesh Surachari <bhuvanesh_surachari@mentor.com>
Subject: [PATCH] i2c: rcar: add SMBus block read support
Date: Wed, 22 Sep 2021 11:06:49 -0500	[thread overview]
Message-ID: <20210922160649.28449-1-andrew_gabbasov@mentor.com> (raw)

The smbus block read is not currently supported for rcar i2c devices.
This patchset adds the support to rcar i2c bus so that blocks of data
can be read using SMbus block reads.(using i2c_smbus_read_block_data()
function from the i2c-core-smbus.c).

Inspired by commit 8e8782c71595 ("i2c: imx: add SMBus block read support")

This patch (adapted) was tested with v4.14, but due to lack of real
hardware with SMBus block read operations support, using "simulation",
that is manual analysis of data, read from plain I2C devices with
SMBus block read request.

Signed-off-by: Bhuvanesh Surachari <bhuvanesh_surachari@mentor.com>
Signed-off-by: Andrew Gabbasov <andrew_gabbasov@mentor.com>
---
 drivers/i2c/busses/i2c-rcar.c | 45 +++++++++++++++++++++++++++++++----
 1 file changed, 41 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index bff9913c37b8..a9fc2b3b6392 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -105,6 +105,7 @@
 #define ID_DONE		(1 << 2)
 #define ID_ARBLOST	(1 << 3)
 #define ID_NACK		(1 << 4)
+#define ID_EPROTO	(1 << 5)
 /* persistent flags */
 #define ID_P_HOST_NOTIFY	BIT(28)
 #define ID_P_REP_AFTER_RD	BIT(29)
@@ -412,6 +413,7 @@ static bool rcar_i2c_dma(struct rcar_i2c_priv *priv)
 	struct device *dev = rcar_i2c_priv_to_dev(priv);
 	struct i2c_msg *msg = priv->msg;
 	bool read = msg->flags & I2C_M_RD;
+	bool block_data = msg->flags & I2C_M_RECV_LEN;
 	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 	struct dma_chan *chan = read ? priv->dma_rx : priv->dma_tx;
 	struct dma_async_tx_descriptor *txdesc;
@@ -429,9 +431,16 @@ static bool rcar_i2c_dma(struct rcar_i2c_priv *priv)
 		/*
 		 * The last two bytes needs to be fetched using PIO in
 		 * order for the STOP phase to work.
+		 *
+		 * For SMBus block read the first byte was received using PIO.
 		 */
-		buf = priv->msg->buf;
-		len = priv->msg->len - 2;
+		if (block_data) {
+			buf = priv->msg->buf + 1;
+			len = priv->msg->len - 3;
+		} else {
+			buf = priv->msg->buf;
+			len = priv->msg->len - 2;
+		}
 	} else {
 		/*
 		 * First byte in message was sent using PIO.
@@ -530,6 +539,7 @@ static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
 static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
 {
 	struct i2c_msg *msg = priv->msg;
+	bool block_data = msg->flags & I2C_M_RECV_LEN;
 
 	/* FIXME: sometimes, unknown interrupt happened. Do nothing */
 	if (!(msr & MDR))
@@ -538,8 +548,29 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
 	if (msr & MAT) {
 		/*
 		 * Address transfer phase finished, but no data at this point.
-		 * Try to use DMA to receive data.
+		 * Try to use DMA to receive data if it is not SMBus block
+		 * data read.
 		 */
+		if (block_data)
+			goto next_txn;
+
+		rcar_i2c_dma(priv);
+	} else if (priv->pos == 0 && block_data) {
+		/*
+		 * First byte is the length of remaining packet
+		 * in the SMBus block data read. Add it to
+		 * msg->len.
+		 */
+		u8 data = rcar_i2c_read(priv, ICRXTX);
+
+		if (data == 0 || data > I2C_SMBUS_BLOCK_MAX) {
+			priv->flags |= ID_DONE | ID_EPROTO;
+			return;
+		}
+		msg->len += data;
+		msg->buf[priv->pos] = data;
+		priv->pos++;
+		/* Still try to use DMA to receive the rest of data */
 		rcar_i2c_dma(priv);
 	} else if (priv->pos < msg->len) {
 		/* get received data */
@@ -557,6 +588,7 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
 		}
 	}
 
+next_txn:
 	if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG))
 		rcar_i2c_next_msg(priv);
 	else
@@ -855,6 +887,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 		ret = -ENXIO;
 	} else if (priv->flags & ID_ARBLOST) {
 		ret = -EAGAIN;
+	} else if (priv->flags & ID_EPROTO) {
+		ret = -EPROTO;
 	} else {
 		ret = num - priv->msgs_left; /* The number of transfer */
 	}
@@ -917,6 +951,8 @@ static int rcar_i2c_master_xfer_atomic(struct i2c_adapter *adap,
 		ret = -ENXIO;
 	} else if (priv->flags & ID_ARBLOST) {
 		ret = -EAGAIN;
+	} else if (priv->flags & ID_EPROTO) {
+		ret = -EPROTO;
 	} else {
 		ret = num - priv->msgs_left; /* The number of transfer */
 	}
@@ -983,7 +1019,8 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap)
 	 * I2C_M_IGNORE_NAK (automatically sends STOP after NAK)
 	 */
 	u32 func = I2C_FUNC_I2C | I2C_FUNC_SLAVE |
-		   (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+		   (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
+		   I2C_FUNC_SMBUS_READ_BLOCK_DATA;
 
 	if (priv->flags & ID_P_HOST_NOTIFY)
 		func |= I2C_FUNC_SMBUS_HOST_NOTIFY;
-- 
2.21.0


             reply	other threads:[~2021-09-22 16:14 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-22 16:06 Andrew Gabbasov [this message]
2021-10-05 13:31 ` [PATCH] i2c: rcar: add SMBus block read support Geert Uytterhoeven
2021-10-06 18:11   ` Andrew Gabbasov
2021-10-06 18:23     ` [PATCH v2] " Andrew Gabbasov
2022-02-17 19:44       ` Wolfram Sang
2022-02-18 11:02         ` Gabbasov, Andrew
2022-03-15 10:45           ` Surachari, Bhuvanesh
2022-03-30 11:04           ` Wolfram Sang
2022-04-01 16:27             ` Wolfram Sang
2022-04-01 16:29           ` Wolfram Sang
2022-03-23 21:52         ` Eugeniu Rosca
2022-03-30 10:58           ` Wolfram Sang
2022-03-30 11:09             ` Wolfram Sang
2022-03-31 16:02               ` Eugeniu Rosca
2022-04-01 16:38                 ` Wolfram Sang
2022-04-05  9:30                   ` Eugeniu Rosca
2022-04-05  9:43                     ` Wolfram Sang
2022-04-06 17:32                       ` Eugeniu Rosca
2022-04-06 19:44                         ` Wolfram Sang
2021-11-18 10:35   ` [PATCH] " Andrew Gabbasov
2022-01-09 19:20   ` Andrew Gabbasov
2022-01-25  6:45   ` Andrew Gabbasov
2022-02-17 14:40   ` Andrew Gabbasov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210922160649.28449-1-andrew_gabbasov@mentor.com \
    --to=andrew_gabbasov@mentor.com \
    --cc=bhuvanesh_surachari@mentor.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=wsa+renesas@sang-engineering.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).