linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrzej Hajda <a.hajda@samsung.com>
To: Wolfram Sang <wsa@the-dreams.de>, Andi Shyti <andi.shyti@samsung.com>
Cc: Andrzej Hajda <a.hajda@samsung.com>,
	Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	"open list:I2C SUBSYSTEM" <linux-i2c@vger.kernel.org>,
	"moderated list:ARM/SAMSUNG EXYNOS ARM ARCHITECTURES"
	<linux-samsung-soc@vger.kernel.org>
Subject: [PATCH 2/3] i2c: exynos5: implement bus recovery functionality
Date: Thu, 30 Nov 2017 15:30:06 +0100	[thread overview]
Message-ID: <20171130143007.30258-3-a.hajda@samsung.com> (raw)
In-Reply-To: <20171130143007.30258-1-a.hajda@samsung.com>

In some circumstances I2C clients can be in abnormal state, to allow
recover them from it I2C master can pulse SCL line until SDA line
goes up and then generate STOP condition. Exynos driver does not have
possibility to manipulate I2C lines directly, but it can provide similar
functionality using manual commands. Replacing I2C adapter reset with
bus recovery significantly incereases I2C bus robustness in case of timeouts.

Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
---
 drivers/i2c/busses/i2c-exynos5.c | 44 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index b02428498f6d..4ca43980e2ed 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -128,6 +128,10 @@
 #define HSI2C_TIMEOUT_EN			(1u << 31)
 #define HSI2C_TIMEOUT_MASK			0xff
 
+/* I2C_MANUAL_CMD register bits */
+#define HSI2C_CMD_READ_DATA			(1u << 4)
+#define HSI2C_CMD_SEND_STOP			(1u << 2)
+
 /* I2C_TRANS_STATUS register bits */
 #define HSI2C_MASTER_BUSY			(1u << 17)
 #define HSI2C_SLAVE_BUSY			(1u << 16)
@@ -613,6 +617,26 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
 	spin_unlock_irqrestore(&i2c->lock, flags);
 }
 
+void exynos5_i2c_recovery(struct exynos5_i2c *i2c)
+{
+	u32 val;
+
+	val = readl(i2c->regs + HSI2C_CTL) | HSI2C_RXCHON;
+	writel(val, i2c->regs + HSI2C_CTL);
+	val = readl(i2c->regs + HSI2C_CONF) & ~HSI2C_AUTO_MODE;
+	writel(val, i2c->regs + HSI2C_CONF);
+
+	writel(HSI2C_CMD_READ_DATA, i2c->regs + HSI2C_MANUAL_CMD);
+	exynos5_i2c_wait_bus_idle(i2c);
+	writel(HSI2C_CMD_SEND_STOP, i2c->regs + HSI2C_MANUAL_CMD);
+	exynos5_i2c_wait_bus_idle(i2c);
+
+	val = readl(i2c->regs + HSI2C_CTL) & ~HSI2C_RXCHON;
+	writel(val, i2c->regs + HSI2C_CTL);
+	val = readl(i2c->regs + HSI2C_CONF) | HSI2C_AUTO_MODE;
+	writel(val, i2c->regs + HSI2C_CONF);
+}
+
 static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c,
 			      struct i2c_msg *msgs, int stop)
 {
@@ -642,7 +666,7 @@ static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c,
 		ret = exynos5_i2c_wait_bus_idle(i2c);
 
 	if (ret < 0) {
-		exynos5_i2c_reset(i2c);
+		exynos5_i2c_recovery(i2c);
 		if (ret == -ETIMEDOUT)
 			dev_warn(i2c->dev, "%s timeout\n",
 				 (msgs->flags & I2C_M_RD) ? "rx" : "tx");
@@ -703,6 +727,23 @@ static const struct i2c_algorithm exynos5_i2c_algorithm = {
 	.functionality		= exynos5_i2c_func,
 };
 
+int exynos5_i2c_recover_bus(struct i2c_adapter *adap)
+{
+	struct exynos5_i2c *i2c = adap->algo_data;
+
+	i2c_lock_adapter(adap);
+	clk_enable(i2c->clk);
+	exynos5_i2c_recovery(i2c);
+	clk_disable(i2c->clk);
+	i2c_unlock_adapter(adap);
+
+	return 0;
+}
+
+static struct i2c_bus_recovery_info exynos5_i2c_recovery_info = {
+	.recover_bus = exynos5_i2c_recover_bus
+};
+
 static int exynos5_i2c_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -773,6 +814,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
 		goto err_clk;
 
 	exynos5_i2c_reset(i2c);
+	i2c->adap.bus_recovery_info = &exynos5_i2c_recovery_info;
 
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret < 0)
-- 
2.15.0

  parent reply	other threads:[~2017-11-30 14:30 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20171130143017eucas1p172b94622814eff172a27176c82f6e6fe@eucas1p1.samsung.com>
2017-11-30 14:30 ` [PATCH 0/3] i2c: exynos5: bus recovery implementation Andrzej Hajda
     [not found]   ` <CGME20171130143017eucas1p2f68094c72e4559e1a16cf334c3200950@eucas1p2.samsung.com>
2017-11-30 14:30     ` [PATCH 1/3] i2c: exynos5: change internal transmission timeout to 100ms Andrzej Hajda
2018-01-15 20:54       ` [1/3] " Wolfram Sang
     [not found]   ` <CGME20171130143018eucas1p13bd2ce9263f9ac016ab3b779920b512e@eucas1p1.samsung.com>
2017-11-30 14:30     ` Andrzej Hajda [this message]
2018-01-15 20:52       ` [2/3] i2c: exynos5: implement bus recovery functionality Wolfram Sang
2018-01-16  8:35         ` Andrzej Hajda
2018-01-17 23:30           ` Wolfram Sang
     [not found]   ` <CGME20171130143018eucas1p1eba2c4f3361e0752cc53a25d217ce616@eucas1p1.samsung.com>
2017-11-30 14:30     ` [PATCH 3/3] i2c: exynos5: do not check TRANS_STATUS in case of Exynos7 variant Andrzej Hajda
2018-01-15 20:53       ` [3/3] " Wolfram Sang
2018-01-16  9:40         ` Andrzej Hajda
2018-01-17 23:23           ` Wolfram Sang
2018-01-26  7:17             ` Andrzej Hajda
2018-01-26  9:30               ` Wolfram Sang
2017-12-07  7:36   ` [PATCH 0/3] i2c: exynos5: bus recovery implementation Andi Shyti

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=20171130143007.30258-3-a.hajda@samsung.com \
    --to=a.hajda@samsung.com \
    --cc=andi.shyti@samsung.com \
    --cc=b.zolnierkie@samsung.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=wsa@the-dreams.de \
    /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).