[RFC 2/2] i2c-intel-mid: Implement software fragment
There is a problem when xfer size > FIFO buffer size
Implement software fragment in host bus driver
So that I2C slave device driver need not to do modify
diff -ruN a/drivers/i2c/busses/i2c-intel-mid.c
b/drivers/i2c/busses/i2c-intel-mid.c
--- a/drivers/i2c/busses/i2c-intel-mid.c 2010-11-23 10:12:51.950754000
+0800
+++ b/drivers/i2c/busses/i2c-intel-mid.c 2010-11-23 10:15:11.119068000 +0800
@@ -59,6 +59,11 @@
/* Currently, pre-define it as 32-byte; it is safe for all CPU stepping */
#define I2C_FIFO_SIZE 32
+/* There is a problem when xfer size > FIFO buffer size */
+/* Implement software fragment in host bus driver */
+/* So that I2C slave device driver need not to do modify */
+#define I2C_XFER_FRAGMENT
+
/**
* struct intel_mid_i2c_private - per device I²C context
* @adap: core i2c layer adapter information
@@ -84,8 +89,12 @@
int speed;
struct completion complete;
int abort;
+#ifdef I2C_XFER_FRAGMENT
+ int xfer_buf_len; /* xfer buffer length */
+#else
u8 *rx_buf;
int rx_buf_len;
+#endif
enum mid_i2c_status status;
struct i2c_msg *msg;
enum platform_enum platform;
@@ -548,6 +557,13 @@
readl(i2c->base + IC_CLR_INTR);
writel(0x0044, i2c->base + IC_INTR_MASK);
+#ifdef I2C_XFER_FRAGMENT
+ /* set xfer_buf_len as xfer_read length */
+ i2c->xfer_buf_len = length;
+ /* set receive FIFO threshold */
+ writel((uint16_t)(length - 1), i2c->base + IC_RX_TL);
+#endif
+
i2c->status = STATUS_READ_START;
while (i--)
@@ -724,6 +740,11 @@
{
struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
int i, err = 0;
+#ifdef I2C_XFER_FRAGMENT
+ u16 len;
+ u8 *buf;
+ u16 xfer_len;
+#endif
/* if number of messages equal 0*/
if (num == 0)
@@ -764,6 +785,36 @@
for (i = 0; i < num; i++) {
i2c->msg = pmsg;
i2c->status = STATUS_IDLE;
+#ifdef I2C_XFER_FRAGMENT
+ if (pmsg->len && pmsg->buf) {
+ len = pmsg->len;
+ buf = pmsg->buf;
+ xfer_len = 0;
+
+ while (len && buf) {
+ if (len >= I2C_FIFO_SIZE)
+ xfer_len = I2C_FIFO_SIZE;
+ else
+ xfer_len = len;
+
+ 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)
+ goto err_1;
+
+ len -= xfer_len;
+ if (len)
+ buf += xfer_len;
+ else /* len == 0 */
+ break;
+ }
+ }
+#else
/* Read or Write */
if (pmsg->flags & I2C_M_RD) {
dev_dbg(&adap->dev, "I2C_M_RD\n");
@@ -774,6 +825,7 @@
}
if (err < 0)
break;
+#endif
dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i);
pmsg++; /* next message */
}
@@ -844,6 +896,14 @@
static void i2c_isr_read(struct intel_mid_i2c_private *i2c)
{
struct i2c_msg *msg = i2c->msg;
+#ifdef I2C_XFER_FRAGMENT
+ u32 len = i2c->xfer_buf_len;
+ u8 *buf = msg->buf;
+
+ while (len--)
+ *buf++ = readl(i2c->base + IC_DATA_CMD);
+ i2c->status = STATUS_READ_SUCCESS;
+#else
int rx_num;
u32 len;
u8 *buf;
@@ -870,6 +930,7 @@
i2c->rx_buf = buf;
} else
i2c->status = STATUS_READ_SUCCESS;
+#endif
return;
}
@@ -906,7 +967,10 @@
}
if (stat & TX_EMPTY) {
+#ifndef I2C_XFER_FRAGMENT
+ /* if IC_TX_TL == 0, TFE of IC_STATUS is always 1 */
if (readl(i2c->base + IC_STATUS) & 0x4)
+#endif
i2c->status = STATUS_WRITE_SUCCESS;
}
@@ -1014,7 +1078,11 @@
mrst->base = base;
mrst->speed = STANDARD;
mrst->abort = 0;
+#ifdef I2C_XFER_FRAGMENT
+ mrst->xfer_buf_len = 0;
+#else
mrst->rx_buf_len = 0;
+#endif
mrst->status = STATUS_IDLE;
pci_set_drvdata(dev, mrst);
2_Implement_software_fragment.patch
Description: 2_Implement_software_fragment.patch
_______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
