From 6d9939f651419a63e091105663821f9c7d3fec37 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 12 Sep 2012 16:28:00 +0530 Subject: [PATCH] i2c: omap: split out [XR]DR and [XR]RDY While they do pretty much the same thing, there are a few peculiarities. Specially WRT erratas, it's best to split those out and re-factor the read/write loop to another function which both cases call. This last part will be done on another patch. While at that, also avoid an unncessary register read since dev->fifo_len will always contain the correct amount of data to be transferred. Signed-off-by: Felipe Balbi Signed-off-by: Shubhrajyoti D Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-omap.c | 132 ++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 37 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index f24eae9f7f1e..815577b1c89f 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -801,36 +801,24 @@ complete: return IRQ_HANDLED; } - if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { + if (stat & OMAP_I2C_STAT_RDR) { u8 num_bytes = 1; - if (dev->errata & I2C_OMAP_ERRATA_I207) - i2c_omap_errata_i207(dev, stat); + if (dev->fifo_size) + num_bytes = dev->buf_len; - if (dev->fifo_size) { - if (stat & OMAP_I2C_STAT_RRDY) - num_bytes = dev->fifo_size; - else /* read RXSTAT on RDR interrupt */ - num_bytes = (omap_i2c_read_reg(dev, - OMAP_I2C_BUFSTAT_REG) - >> 8) & 0x3F; - } while (num_bytes--) { if (!dev->buf_len) { - if (stat & OMAP_I2C_STAT_RRDY) - dev_err(dev->dev, - "RRDY IRQ while no data" - " requested\n"); - if (stat & OMAP_I2C_STAT_RDR) - dev_err(dev->dev, + dev_err(dev->dev, "RDR IRQ while no data" - " requested\n"); + " requested\n"); break; } w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); *dev->buf++ = w; dev->buf_len--; + /* * Data reg in 2430, omap3 and * omap4 is 8 bit wide @@ -843,29 +831,58 @@ complete: } } } - omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY | - OMAP_I2C_STAT_RDR)); + + if (dev->errata & I2C_OMAP_ERRATA_I207) + i2c_omap_errata_i207(dev, stat); + + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); continue; } - if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) { + if (stat & OMAP_I2C_STAT_RRDY) { u8 num_bytes = 1; - if (dev->fifo_size) { - if (stat & OMAP_I2C_STAT_XRDY) - num_bytes = dev->fifo_size; - else /* read TXSTAT on XDR interrupt */ - num_bytes = omap_i2c_read_reg(dev, - OMAP_I2C_BUFSTAT_REG) - & 0x3F; - } + + if (dev->fifo_size) + num_bytes = dev->fifo_size; + while (num_bytes--) { if (!dev->buf_len) { - if (stat & OMAP_I2C_STAT_XRDY) - dev_err(dev->dev, - "XRDY IRQ while no " - "data to send\n"); - if (stat & OMAP_I2C_STAT_XDR) - dev_err(dev->dev, + dev_err(dev->dev, + "RRDY IRQ while no data" + " requested\n"); + break; + } + + w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); + *dev->buf++ = w; + dev->buf_len--; + + /* + * Data reg in 2430, omap3 and + * omap4 is 8 bit wide + */ + if (dev->flags & + OMAP_I2C_FLAG_16BIT_DATA_REG) { + if (dev->buf_len) { + *dev->buf++ = w >> 8; + dev->buf_len--; + } + } + } + + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY); + continue; + } + + if (stat & OMAP_I2C_STAT_XDR) { + u8 num_bytes = 1; + + if (dev->fifo_size) + num_bytes = dev->buf_len; + + while (num_bytes--) { + if (!dev->buf_len) { + dev_err(dev->dev, "XDR IRQ while no " "data to send\n"); break; @@ -873,6 +890,7 @@ complete: w = *dev->buf++; dev->buf_len--; + /* * Data reg in 2430, omap3 and * omap4 is 8 bit wide @@ -891,8 +909,48 @@ complete: omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); } - omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_XRDY | - OMAP_I2C_STAT_XDR)); + + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR); + continue; + } + + if (stat & OMAP_I2C_STAT_XRDY) { + u8 num_bytes = 1; + + if (dev->fifo_size) + num_bytes = dev->fifo_size; + + while (num_bytes--) { + if (!dev->buf_len) { + dev_err(dev->dev, + "XRDY IRQ while no " + "data to send\n"); + break; + } + + w = *dev->buf++; + dev->buf_len--; + + /* + * Data reg in 2430, omap3 and + * omap4 is 8 bit wide + */ + if (dev->flags & + OMAP_I2C_FLAG_16BIT_DATA_REG) { + if (dev->buf_len) { + w |= *dev->buf++ << 8; + dev->buf_len--; + } + } + + if ((dev->errata & I2C_OMAP_ERRATA_I462) && + errata_omap3_i462(dev, &stat, &err)) + goto complete; + + omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); + } + + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY); continue; }