devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Akhil R <akhilrajeev@nvidia.com>
To: <andy.shevchenko@gmail.com>, <christian.koenig@amd.com>,
	<digetx@gmail.com>, <dri-devel@lists.freedesktop.org>,
	<jonathanh@nvidia.com>, <ldewangan@nvidia.com>,
	<linaro-mm-sig@lists.linaro.org>, <linux-i2c@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <linux-media@vger.kernel.org>,
	<linux-tegra@vger.kernel.org>, <p.zabel@pengutronix.de>,
	<sumit.semwal@linaro.org>, <thierry.reding@gmail.com>,
	<robh+dt@kernel.org>, <devicetree@vger.kernel.org>
Cc: <akhilrajeev@nvidia.com>
Subject: [PATCH 2/2] i2c: tegra: Add SMBus block read and SMBus alert functions
Date: Thu, 9 Dec 2021 20:35:21 +0530	[thread overview]
Message-ID: <1639062321-18840-3-git-send-email-akhilrajeev@nvidia.com> (raw)
In-Reply-To: <1639062321-18840-1-git-send-email-akhilrajeev@nvidia.com>

Emulate the SMBus block read using ContinueXfer and SMBus using GPIO
interrupt.

For SMBus block read, the driver  reads the first byte with ContinueXfer
set which will help to parse the data count and read the remaining bytes
without stop condition in between.
SMBus alert is implemented using external gpio interrupt.

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
 drivers/i2c/busses/i2c-tegra.c | 54 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index a5be8f0..3b70013 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -14,6 +14,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -226,6 +227,11 @@ struct tegra_i2c_hw_feature {
 	bool has_interface_timing_reg;
 };
 
+struct tegra_i2c_smbalert {
+	struct i2c_smbus_alert_setup alert_data;
+	struct i2c_client *ara;
+};
+
 /**
  * struct tegra_i2c_dev - per device I2C context
  * @dev: device reference for power management
@@ -280,6 +286,8 @@ struct tegra_i2c_dev {
 	int msg_err;
 	u8 *msg_buf;
 
+	struct tegra_i2c_smbalert smbalert;
+
 	struct completion dma_complete;
 	struct dma_chan *tx_dma_chan;
 	struct dma_chan *rx_dma_chan;
@@ -1232,6 +1240,11 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 		return err;
 
 	i2c_dev->msg_buf = msg->buf;
+
+	/* The condition true implies smbus block read and len is already read*/
+	if (msg->flags & I2C_M_RECV_LEN && end_state != MSG_END_CONTINUE)
+		i2c_dev->msg_buf = msg->buf + 1;
+
 	i2c_dev->msg_buf_remaining = msg->len;
 	i2c_dev->msg_err = I2C_ERR_NONE;
 	i2c_dev->msg_read = !!(msg->flags & I2C_M_RD);
@@ -1388,6 +1401,15 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 			else
 				end_type = MSG_END_REPEAT_START;
 		}
+		/* If M_RECV_LEN use ContinueXfer to read the first byte */
+		if (msgs[i].flags & I2C_M_RECV_LEN) {
+			ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], MSG_END_CONTINUE);
+			if (ret)
+				break;
+			/* Set the read byte as msg len */
+			msgs[i].len = msgs[i].buf[0];
+			dev_dbg(i2c_dev->dev, "reading %d bytes\n", msgs[i].len);
+		}
 		ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], end_type);
 		if (ret)
 			break;
@@ -1415,7 +1437,8 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap)
 {
 	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
 	u32 ret = I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
-		  I2C_FUNC_10BIT_ADDR |	I2C_FUNC_PROTOCOL_MANGLING;
+		  I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_10BIT_ADDR |
+		  I2C_FUNC_PROTOCOL_MANGLING;
 
 	if (i2c_dev->hw->has_continue_xfer_support)
 		ret |= I2C_FUNC_NOSTART;
@@ -1727,6 +1750,29 @@ static int tegra_i2c_init_hardware(struct tegra_i2c_dev *i2c_dev)
 	return ret;
 }
 
+static int tegra_i2c_setup_smbalert(struct tegra_i2c_dev *i2c_dev)
+{
+	struct tegra_i2c_smbalert *smbalert = &i2c_dev->smbalert;
+	struct gpio_desc *alert_gpiod;
+	struct i2c_client *ara;
+
+	alert_gpiod = devm_gpiod_get(i2c_dev->dev, "smbalert", GPIOD_IN);
+	if (IS_ERR(alert_gpiod))
+		return PTR_ERR(alert_gpiod);
+
+	smbalert->alert_data.irq = gpiod_to_irq(alert_gpiod);
+	if (smbalert->alert_data.irq <= 0)
+		return smbalert->alert_data.irq;
+
+	ara = i2c_new_smbus_alert_device(&i2c_dev->adapter, &smbalert->alert_data);
+	if (IS_ERR(ara))
+		return PTR_ERR(ara);
+
+	smbalert->ara = ara;
+
+	return 0;
+}
+
 static int tegra_i2c_probe(struct platform_device *pdev)
 {
 	struct tegra_i2c_dev *i2c_dev;
@@ -1821,6 +1867,12 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	if (err)
 		goto release_rpm;
 
+	if (device_property_read_bool(i2c_dev->dev, "smbus-alert")) {
+		err = tegra_i2c_setup_smbalert(i2c_dev);
+		if (err)
+			dev_warn(&pdev->dev, "smbus-alert setup failed: %d\n", err);
+	}
+
 	return 0;
 
 release_rpm:
-- 
2.7.4


  parent reply	other threads:[~2021-12-09 15:06 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-09 15:05 [PATCH 0/2] Add SMBus features to Tegra I2C Akhil R
2021-12-09 15:05 ` [PATCH 1/2] dt-bindings: i2c: tegra: Add SMBus feature properties Akhil R
2021-12-09 15:30   ` Andy Shevchenko
2021-12-15 18:37   ` Rob Herring
2021-12-09 15:05 ` Akhil R [this message]
2021-12-09 15:27   ` [PATCH 2/2] i2c: tegra: Add SMBus block read and SMBus alert functions Dmitry Osipenko
2021-12-10  9:38     ` Akhil R
2021-12-11 20:07       ` Dmitry Osipenko
2021-12-11 20:12       ` Dmitry Osipenko
2021-12-09 15:30   ` Dmitry Osipenko
2021-12-09 15:33     ` Andy Shevchenko
2021-12-09 15:42       ` Dmitry Osipenko
2021-12-09 15:43   ` Dmitry Osipenko
2021-12-09 16:04 ` [PATCH 0/2] Add SMBus features to Tegra I2C Dmitry Osipenko
2021-12-10  8:56   ` Thierry Reding
2021-12-15 18:42     ` Rob Herring

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=1639062321-18840-3-git-send-email-akhilrajeev@nvidia.com \
    --to=akhilrajeev@nvidia.com \
    --cc=andy.shevchenko@gmail.com \
    --cc=christian.koenig@amd.com \
    --cc=devicetree@vger.kernel.org \
    --cc=digetx@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jonathanh@nvidia.com \
    --cc=ldewangan@nvidia.com \
    --cc=linaro-mm-sig@lists.linaro.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=robh+dt@kernel.org \
    --cc=sumit.semwal@linaro.org \
    --cc=thierry.reding@gmail.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).