linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
To: w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org
Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Linux OMAP Mailing List
	<linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
	Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>,
	aaro.koskinen-X3B1VOXEql0@public.gmane.org,
	Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
Subject: [PATCH 5/6] i2c: omap: wait for transfer completion before sending STP bit
Date: Wed, 23 Jan 2013 12:23:07 +0200	[thread overview]
Message-ID: <1358936588-16375-6-git-send-email-balbi@ti.com> (raw)
In-Reply-To: <1358936588-16375-1-git-send-email-balbi-l0cyMroinI0@public.gmane.org>

Later patches will come adding support for
reporting amount of bytes transferred so that
client drivers can count how many bytes are
left to transfer.

This is useful mostly in case of NACKs when
client driver wants to know exactly which
byte got NACKed so it doesn't have to resend
all bytes again.

In order to make that work with OMAP's I2C
controller, we need to prevent sending STP
bit until message is transferred. The reason
behind that is because OMAP_I2C_CNT_REG gets
reset to original value after STP bit is
shifted through I2C_SDA line and that would
prevent us from reading the correct number of
bytes left to transfer.

The full programming model suggested by IP
owner was the following:

- start I2C transfer (without STP bit)
- upon completion or NACK, read I2C_CNT register
- write STP bit to I2C_CON register
- wait for ARDY bit

With this patch we're implementing all steps
except step #2 which will come in a later
patch series. In order to implement full NACK
reporting we need to add a new field to struct
i2c_msg, but that's still under discussion on
what's the best way to do it. For now, we can
prepare the driver to receive that piece of code.

Signed-off-by: Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
---
 drivers/i2c/busses/i2c-omap.c | 92 ++++++++++++++++++-------------------------
 1 file changed, 38 insertions(+), 54 deletions(-)

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ff88495..4e715c4 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -479,9 +479,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 	}
 
 	dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
-			OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
-			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
-				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
+			OMAP_I2C_IE_NACK | OMAP_I2C_IE_AL)  |
+			((dev->fifo_size) ? (OMAP_I2C_IE_RDR |
+				OMAP_I2C_IE_XDR) : 0);
 
 	dev->pscstate = psc;
 	dev->scllstate = scll;
@@ -511,6 +511,22 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
 	return 0;
 }
 
+static int omap_i2c_wait_for_ardy(struct omap_i2c_dev *dev)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + OMAP_I2C_TIMEOUT;
+	while (!(omap_i2c_read_irqstatus(dev) & OMAP_I2C_STAT_ARDY)) {
+		if (time_after(jiffies, timeout)) {
+			dev_warn(dev->dev, "timeout waiting for access ready\n");
+			return -ETIMEDOUT;
+		}
+		usleep_range(800, 1200);
+	}
+
+	return 0;
+}
+
 static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
 {
 	u16		buf;
@@ -558,6 +574,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
 {
 	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
 	unsigned long timeout;
+	int ret = 0;
 	u16 w;
 
 	dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
@@ -601,35 +618,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
 	if (!(msg->flags & I2C_M_RD))
 		w |= OMAP_I2C_CON_TRX;
 
-	if (!dev->b_hw && stop)
-		w |= OMAP_I2C_CON_STP;
-
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
 
 	/*
-	 * Don't write stt and stp together on some hardware.
-	 */
-	if (dev->b_hw && stop) {
-		unsigned long delay = jiffies + OMAP_I2C_TIMEOUT;
-		u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
-		while (con & OMAP_I2C_CON_STT) {
-			con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
-
-			/* Let the user know if i2c is in a bad state */
-			if (time_after(jiffies, delay)) {
-				dev_err(dev->dev, "controller timed out "
-				"waiting for start condition to finish\n");
-				return -ETIMEDOUT;
-			}
-			cpu_relax();
-		}
-
-		w |= OMAP_I2C_CON_STP;
-		w &= ~OMAP_I2C_CON_STT;
-		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
-	}
-
-	/*
 	 * REVISIT: We should abort the transfer on signals, but the bus goes
 	 * into arbitration and we're currently unable to recover from it.
 	 */
@@ -639,31 +630,37 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
 		dev_err(dev->dev, "controller timed out\n");
 		omap_i2c_reset(dev);
 		__omap_i2c_init(dev);
-		return -ETIMEDOUT;
+		ret = -ETIMEDOUT;
+		goto out;
 	}
 
-	if (likely(!dev->cmd_err))
-		return 0;
-
 	/* We have an error */
 	if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
 			    OMAP_I2C_STAT_XUDF)) {
 		omap_i2c_reset(dev);
 		__omap_i2c_init(dev);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
 	if (dev->cmd_err & OMAP_I2C_STAT_NACK) {
 		if (msg->flags & I2C_M_IGNORE_NAK)
 			return 0;
-		if (stop) {
-			w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
-			w |= OMAP_I2C_CON_STP;
-			omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
-		}
-		return -EREMOTEIO;
+
+		ret = -EREMOTEIO;
+	}
+
+out:
+
+	if (stop) {
+		w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+		w |= OMAP_I2C_CON_STP;
+		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+
+		ret = omap_i2c_wait_for_ardy(dev);
 	}
-	return -EIO;
+
+	return ret;
 }
 
 
@@ -977,19 +974,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
 			break;
 		}
 
-		/*
-		 * ProDB0017052: Clear ARDY bit twice
-		 */
-		if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
-					OMAP_I2C_STAT_AL)) {
-			omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY |
-						OMAP_I2C_STAT_RDR |
-						OMAP_I2C_STAT_XRDY |
-						OMAP_I2C_STAT_XDR |
-						OMAP_I2C_STAT_ARDY));
-			break;
-		}
-
 		if (stat & OMAP_I2C_STAT_RDR) {
 			u8 num_bytes = 1;
 
-- 
1.8.1.rc1.5.g7e0651a

  parent reply	other threads:[~2013-01-23 10:23 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-14 16:34 [PATCH REBASE 0/6] i2c: omap: misc changes Felipe Balbi
2012-12-14 16:34 ` [PATCH REBASE 1/6] i2c: omap: no need to access platform_device Felipe Balbi
2012-12-14 16:34 ` [PATCH REBASE 3/6] i2c: omap: improve 'rev' a little bit Felipe Balbi
2012-12-14 16:34 ` [PATCH REBASE 6/6] i2c: omap: get rid of b_hw flag Felipe Balbi
     [not found] ` <1355502849-9289-1-git-send-email-balbi-l0cyMroinI0@public.gmane.org>
2012-12-14 16:34   ` [PATCH REBASE 2/6] i2c: omap: also complete() when stat becomes zero Felipe Balbi
2012-12-14 16:34   ` [PATCH REBASE 4/6] i2c: omap: in case of VERSION_2 read IRQSTATUS_RAW but write to IRQSTATUS Felipe Balbi
2012-12-14 16:34   ` [PATCH REBASE 5/6] i2c: omap: wait for transfer completion before sending STP bit Felipe Balbi
2013-01-14 19:16   ` [PATCH REBASE 0/6] i2c: omap: misc changes Felipe Balbi
     [not found]     ` <20130114191628.GB9402-S8G//mZuvNWo5Im9Ml3/Zg@public.gmane.org>
2013-01-23  9:58       ` Wolfram Sang
2013-01-23 10:23         ` [PATCH 0/6] i2c: deferred STP Felipe Balbi
     [not found]           ` <1358936588-16375-1-git-send-email-balbi-l0cyMroinI0@public.gmane.org>
2013-01-23 10:23             ` [PATCH 1/6] i2c: omap: no need to access platform_device Felipe Balbi
2013-01-23 10:23             ` [PATCH 4/6] i2c: omap: in case of VERSION_2 read IRQSTATUS_RAW but write to IRQSTATUS Felipe Balbi
2013-01-23 10:23             ` Felipe Balbi [this message]
2013-01-23 20:10               ` [PATCH 5/6] i2c: omap: wait for transfer completion before sending STP bit Aaro Koskinen
2013-01-24  7:35                 ` Felipe Balbi
2013-01-24  7:42                   ` [PATCH 5/6 v2] " Felipe Balbi
2013-01-23 10:23             ` [PATCH 6/6] i2c: omap: get rid of b_hw flag Felipe Balbi
2013-01-23 20:05             ` [PATCH 0/6] i2c: deferred STP Aaro Koskinen
     [not found]               ` <20130123200540.GE23057-R3WNPi76c83LsdW6vOPryG4HOFkwEHDbMR2xtNvyitY@public.gmane.org>
2013-01-24 16:11                 ` Aaro Koskinen
2013-01-23 10:23           ` [PATCH 2/6] i2c: omap: also complete() when stat becomes zero Felipe Balbi
2013-01-24  9:05             ` Aaro Koskinen
2013-01-24  9:13               ` Felipe Balbi
     [not found]                 ` <20130124091339.GF27304-S8G//mZuvNWo5Im9Ml3/Zg@public.gmane.org>
2013-01-24  9:37                   ` Felipe Balbi
2013-01-24  9:56                 ` Aaro Koskinen
2013-01-23 10:23           ` [PATCH 3/6] i2c: omap: improve 'rev' a little bit Felipe Balbi

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=1358936588-16375-6-git-send-email-balbi@ti.com \
    --to=balbi-l0cymroini0@public.gmane.org \
    --cc=aaro.koskinen-X3B1VOXEql0@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org \
    --cc=w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
    /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).