All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] i2c-intel-mid: I2C FIFO buffer size setting and fragmentation
@ 2011-01-25 14:28 Alan Cox
       [not found] ` <20110125142728.10001.85888.stgit-Z/y2cZnRghHXmaaqVzeoHQ@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Alan Cox @ 2011-01-25 14:28 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA

From: Major Lee <major_lee-8+ZHUTgF1KZBDgjK7y7TUQ@public.gmane.org>

The FIFO buffer size is different with different CPU stepping.
Define it as 32-byte; it is safe for all CPU stepping.

There is a problem when xfer size is greater then FIFO buffer size.
Implement software fragmentation in host bus driver so that the
I²C slave device drivers need not to be modified or to know about the
limits.

Signed-off-by: Major Lee <major_lee-8+ZHUTgF1KZBDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Alan Cox <alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---

 drivers/i2c/busses/i2c-intel-mid.c |   95 +++++++++++++++++-------------------
 1 files changed, 46 insertions(+), 49 deletions(-)


diff --git a/drivers/i2c/busses/i2c-intel-mid.c b/drivers/i2c/busses/i2c-intel-mid.c
index 3975736..da4bbdd 100644
--- a/drivers/i2c/busses/i2c-intel-mid.c
+++ b/drivers/i2c/busses/i2c-intel-mid.c
@@ -54,6 +54,10 @@ enum mid_i2c_status {
 	STATUS_STANDBY
 };
 
+/* The FIFO buffer size is different with different CPU stepping */
+/* Define it as 32-byte; it is safe for all CPU stepping */
+#define I2C_FIFO_SIZE	32
+
 /**
  * struct intel_mid_i2c_private	- per device I²C context
  * @adap: core i2c layer adapter information
@@ -62,7 +66,6 @@ enum mid_i2c_status {
  * @speed: speed mode for this port
  * @complete: completion object for transaction wait
  * @abort: reason for last abort
- * @rx_buf: pointer into working receive buffer
  * @rx_buf_len: receive buffer length
  * @status: adapter state machine
  * @msg: the message we are currently processing
@@ -79,7 +82,6 @@ struct intel_mid_i2c_private {
 	int speed;
 	struct completion complete;
 	u32 abort;
-	u8 *rx_buf;
 	int rx_buf_len;
 	enum mid_i2c_status status;
 	struct i2c_msg *msg;
@@ -560,17 +562,15 @@ static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
 	int i = length;
 	int err;
 
-	if (length >= 256) {
-		dev_err(&adap->dev,
-			"I2C FIFO cannot support larger than 256 bytes\n");
-		return -EMSGSIZE;
-	}
-
 	INIT_COMPLETION(i2c->complete);
 
 	readl(i2c->base + IC_CLR_INTR);
 	writel(0x0044, i2c->base + IC_INTR_MASK);
 
+	i2c->rx_buf_len = length;
+	/* set receive FIFO threshold */
+	writel((uint16_t)(length - 1), i2c->base + IC_RX_TL);
+
 	i2c->status = STATUS_READ_START;
 
 	while (i--)
@@ -614,12 +614,6 @@ static int xfer_write(struct i2c_adapter *adap,
 	struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
 	int i, err;
 
-	if (length >= 256) {
-		dev_err(&adap->dev,
-			"I2C FIFO cannot support larger than 256 bytes\n");
-		return -EMSGSIZE;
-	}
-
 	INIT_COMPLETION(i2c->complete);
 
 	readl(i2c->base + IC_CLR_INTR);
@@ -748,6 +742,9 @@ static int intel_mid_i2c_xfer(struct i2c_adapter *adap,
 {
 	struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
 	int i, err = 0;
+	u16 len;
+	u8 *buf;
+	u16 xfer_len;
 
 	/* if number of messages equal 0*/
 	if (num == 0)
@@ -785,13 +782,35 @@ static int intel_mid_i2c_xfer(struct i2c_adapter *adap,
 	for (i = 0; i < num; i++) {
 		i2c->msg = pmsg;
 		i2c->status = STATUS_IDLE;
-		/* Read or Write */
-		if (pmsg->flags & I2C_M_RD) {
-			dev_dbg(&adap->dev, "I2C_M_RD\n");
-			err = xfer_read(adap, pmsg->buf, pmsg->len);
-		} else {
-			dev_dbg(&adap->dev, "I2C_M_WR\n");
-			err = xfer_write(adap, pmsg->buf, pmsg->len);
+
+		if (pmsg->len && pmsg->buf) {
+			len = pmsg->len;
+			buf = pmsg->buf;
+			xfer_len = 0;
+
+			while (len && buf) {
+				/* Fragment xfer data */
+				if (len >= I2C_FIFO_SIZE)
+					xfer_len = I2C_FIFO_SIZE;
+				else
+					xfer_len = len;
+				/* Read or Write */
+				if (pmsg->flags & I2C_M_RD) {
+					dev_dbg(&adap->dev, "I2C_M_RD\n");
+					err = xfer_read(adap, buf, xfer_len);
+				} else {
+					dev_dbg(&adap->dev, "I2C_M_WR\n");
+					err = xfer_write(adap, buf, xfer_len);
+				}
+				if (err < 0)
+					break;
+
+				len -= xfer_len;
+				if (len)
+					buf += xfer_len;
+				else /* len == 0 */
+					break;
+			}
 		}
 		if (err < 0)
 			break;
@@ -875,32 +894,12 @@ static int mrst_i2c_runtime_idle(struct device *dev)
 static void i2c_isr_read(struct intel_mid_i2c_private *i2c)
 {
 	struct i2c_msg *msg = i2c->msg;
-	int rx_num;
-	u32 len;
-	u8 *buf;
-
-	if (!(msg->flags & I2C_M_RD))
-		return;
+	u32 len = i2c->rx_buf_len;
+	u8 *buf = msg->buf;
 
-	if (i2c->status != STATUS_READ_IN_PROGRESS) {
-		len = msg->len;
-		buf = msg->buf;
-	} else {
-		len = i2c->rx_buf_len;
-		buf = i2c->rx_buf;
-	}
-
-	rx_num = readl(i2c->base + IC_RXFLR);
-
-	for (; len > 0 && rx_num > 0; len--, rx_num--)
+	while (len--)
 		*buf++ = readl(i2c->base + IC_DATA_CMD);
-
-	if (len > 0) {
-		i2c->status = STATUS_READ_IN_PROGRESS;
-		i2c->rx_buf_len = len;
-		i2c->rx_buf = buf;
-	} else
-		i2c->status = STATUS_READ_SUCCESS;
+	i2c->status = STATUS_READ_SUCCESS;
 
 	return;
 }
@@ -936,10 +935,8 @@ static irqreturn_t intel_mid_i2c_isr(int this_irq, void *dev)
 		goto exit;
 	}
 
-	if (stat & TX_EMPTY) {
-		if (readl(i2c->base + IC_STATUS) & 0x4)
-			i2c->status = STATUS_WRITE_SUCCESS;
-	}
+	if (stat & TX_EMPTY)
+		i2c->status = STATUS_WRITE_SUCCESS;
 
 exit:
 	if (i2c->status == STATUS_READ_SUCCESS ||

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] i2c-intel-mid: I2C FIFO buffer size setting and fragmentation
       [not found] ` <20110125142728.10001.85888.stgit-Z/y2cZnRghHXmaaqVzeoHQ@public.gmane.org>
@ 2011-01-27  0:47   ` Ben Dooks
       [not found]     ` <20110127004759.GJ15795-SMNkleLxa3Z6Wcw2j4pizdi2O/JbrIOy@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Ben Dooks @ 2011-01-27  0:47 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

On Tue, Jan 25, 2011 at 02:28:07PM +0000, Alan Cox wrote:
> From: Major Lee <major_lee-8+ZHUTgF1KZBDgjK7y7TUQ@public.gmane.org>
> 
> The FIFO buffer size is different with different CPU stepping.
> Define it as 32-byte; it is safe for all CPU stepping.
> 
> There is a problem when xfer size is greater then FIFO buffer size.
> Implement software fragmentation in host bus driver so that the
> I²C slave device drivers need not to be modified or to know about the
> limits.

This is quite a big change, does it need to go into a -rc, or can it
wait for the next kernel merge window?

-- 
Ben Dooks, ben-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org, http://www.fluff.org/ben/

Large Hadron Colada: A large Pina Colada that makes the universe disappear.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] i2c-intel-mid: I2C FIFO buffer size setting and fragmentation
       [not found]     ` <20110127004759.GJ15795-SMNkleLxa3Z6Wcw2j4pizdi2O/JbrIOy@public.gmane.org>
@ 2011-01-27 10:34       ` Alan Cox
  0 siblings, 0 replies; 3+ messages in thread
From: Alan Cox @ 2011-01-27 10:34 UTC (permalink / raw)
  To: Ben Dooks; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

On Thu, 27 Jan 2011 00:47:59 +0000
Ben Dooks <ben-i2c-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org> wrote:

> On Tue, Jan 25, 2011 at 02:28:07PM +0000, Alan Cox wrote:
> > From: Major Lee <major_lee-8+ZHUTgF1KZBDgjK7y7TUQ@public.gmane.org>
> > 
> > The FIFO buffer size is different with different CPU stepping.
> > Define it as 32-byte; it is safe for all CPU stepping.
> > 
> > There is a problem when xfer size is greater then FIFO buffer size.
> > Implement software fragmentation in host bus driver so that the
> > I²C slave device drivers need not to be modified or to know about the
> > limits.
> 
> This is quite a big change, does it need to go into a -rc, or can it
> wait for the next kernel merge window?

I was submitting it for next merge window.

Alan

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-01-27 10:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-25 14:28 [PATCH] i2c-intel-mid: I2C FIFO buffer size setting and fragmentation Alan Cox
     [not found] ` <20110125142728.10001.85888.stgit-Z/y2cZnRghHXmaaqVzeoHQ@public.gmane.org>
2011-01-27  0:47   ` Ben Dooks
     [not found]     ` <20110127004759.GJ15795-SMNkleLxa3Z6Wcw2j4pizdi2O/JbrIOy@public.gmane.org>
2011-01-27 10:34       ` Alan Cox

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.