All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Glauber <jglauber@cavium.com>
To: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org,
	ddaney@caviumnetworks.com, Jan Glauber <jglauber@cavium.com>
Subject: [Resend PATCH 08/10] i2c-octeon: Add workaround for chips with broken irqs
Date: Mon, 29 Feb 2016 14:46:15 +0100	[thread overview]
Message-ID: <be4e3fc91e12bf2987999057404d36285933ad90.1456752497.git.jglauber@cavium.com> (raw)
In-Reply-To: <cover.1456752497.git.jglauber@cavium.com>
In-Reply-To: <cover.1456752497.git.jglauber@cavium.com>

From: David Daney <ddaney@caviumnetworks.com>

CN3860 does not interrupt the CPU when the i2c status changes.  If
we get a timeout, and see the status has in fact changed, we know we
have this problem, and drop back to polling.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Jan Glauber <jglauber@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 46 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index e3552e5..3c2f848 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -115,6 +115,7 @@ struct octeon_i2c {
 	int			sys_freq;
 	void __iomem		*twsi_base;
 	struct device		*dev;
+	int			broken_irq_mode;
 	bool			hlc_enabled;
 	void			(*int_en)	(struct octeon_i2c *);
 	void			(*int_dis)	(struct octeon_i2c *);
@@ -382,10 +383,33 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
 	int first = 1;
 	long result;
 
+	if (i2c->broken_irq_mode) {
+		/*
+		 * Some chip revisions seem to not assert the irq in
+		 * the interrupt controller.  So we must poll for the
+		 * IFLG change.
+		 */
+		u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+		while (!octeon_i2c_test_iflg(i2c) &&
+		       time_before64(get_jiffies_64(), end))
+			udelay(50);
+
+		return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT;
+	}
+
 	i2c->int_en(i2c);
 	result = wait_event_timeout(i2c->queue, poll_iflg(i2c, &first),
 				    i2c->adap.timeout);
 	i2c->int_dis(i2c);
+
+	if (result <= 0 && OCTEON_IS_MODEL(OCTEON_CN38XX) &&
+	    octeon_i2c_test_iflg(i2c)) {
+		dev_err(i2c->dev,
+			"broken irq connection detected, switching to polling mode.\n");
+		i2c->broken_irq_mode = 1;
+		return 0;
+	}
 	if (!result) {
 		dev_dbg(i2c->dev, "%s: timeout\n", __func__);
 		return -ETIMEDOUT;
@@ -740,6 +764,21 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 {
 	int result;
 
+	if (i2c->broken_irq_mode) {
+		/*
+		 * Some cn38xx boards did not assert the irq in
+		 * the interrupt controller.  So we must poll for the
+		 * IFLG change.
+		 */
+		u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+		while (!octeon_i2c_hlc_test_ready(i2c) &&
+		       time_before64(get_jiffies_64(), end))
+			udelay(50);
+
+		return octeon_i2c_hlc_test_ready(i2c) ? 0 : -ETIMEDOUT;
+	}
+
 	i2c->hlc_int_en(i2c);
 	result = wait_event_interruptible_timeout(i2c->queue,
 			octeon_i2c_hlc_test_ready(i2c), i2c->adap.timeout);
@@ -747,6 +786,13 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 	if (!result)
 		octeon_i2c_hlc_int_clear(i2c);
 
+	if (result <= 0 && OCTEON_IS_MODEL(OCTEON_CN38XX) &&
+	    octeon_i2c_hlc_test_ready(i2c)) {
+		dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
+			i2c->broken_irq_mode = 1;
+			return 0;
+	}
+
 	if (result < 0) {
 		dev_dbg(i2c->dev, "%s: wait interrupted\n", __func__);
 		return result;
-- 
1.9.1

  parent reply	other threads:[~2016-02-29 13:48 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-29 13:46 [Resend PATCH 00/10] i2c-octeon and i2c-thunderx drivers Jan Glauber
2016-02-29 13:46 ` [Resend PATCH 01/10] i2c-octeon: Cleanup i2c-octeon driver Jan Glauber
2016-02-29 13:46 ` [Resend PATCH 02/10] i2c-octeon: Support I2C_M_RECV_LEN Jan Glauber
2016-02-29 13:46 ` [Resend PATCH 03/10] i2c-octeon: Enable high-level controller and improve on bus contention Jan Glauber
2016-02-29 13:46 ` [Resend PATCH 04/10] dt-bindings: i2c: add Octeon cn78xx TWSI Jan Glauber
2016-02-29 13:46 ` [Resend PATCH 05/10] i2c-octeon: Add support for cn78XX chips Jan Glauber
2016-02-29 13:46 ` [Resend PATCH 06/10] i2c-octeon: Flush TWSI writes with readback Jan Glauber
2016-02-29 13:46 ` [Resend PATCH 07/10] i2c-octeon: Faster operation when IFLG signals late Jan Glauber
2016-02-29 13:46 ` Jan Glauber [this message]
2016-02-29 13:46 ` [Resend PATCH 09/10] i2c: split i2c-octeon driver and add ThunderX support Jan Glauber
2016-02-29 14:55   ` kbuild test robot
2016-02-29 14:55     ` kbuild test robot
2016-03-01 13:53   ` [PATCH] i2c-thunderx: fix compile error for x86_64 Jan Glauber
2016-03-01 17:02     ` David Daney
2016-03-01 17:02       ` David Daney
2016-02-29 13:46 ` [Resend PATCH 10/10] i2c: thunderx: add smbus support Jan Glauber

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=be4e3fc91e12bf2987999057404d36285933ad90.1456752497.git.jglauber@cavium.com \
    --to=jglauber@cavium.com \
    --cc=ddaney@caviumnetworks.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.