OSDN Git Service

i2c: omap: split out [XR]DR and [XR]RDY
authorFelipe Balbi <balbi@ti.com>
Wed, 12 Sep 2012 10:58:00 +0000 (16:28 +0530)
committerWolfram Sang <w.sang@pengutronix.de>
Wed, 12 Sep 2012 13:02:21 +0000 (15:02 +0200)
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 <balbi@ti.com>
Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
drivers/i2c/busses/i2c-omap.c

index f24eae9..815577b 100644 (file)
@@ -801,36 +801,62 @@ 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->fifo_size)
+                               num_bytes = dev->buf_len;
+
+                       while (num_bytes--) {
+                               if (!dev->buf_len) {
+                                       dev_err(dev->dev,
+                                                       "RDR 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--;
+                                       }
+                               }
+                       }
+
                        if (dev->errata & I2C_OMAP_ERRATA_I207)
                                i2c_omap_errata_i207(dev, stat);
 
-                       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;
-                       }
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
+                       continue;
+               }
+
+               if (stat & OMAP_I2C_STAT_RRDY) {
+                       u8 num_bytes = 1;
+
+                       if (dev->fifo_size)
+                               num_bytes = dev->fifo_size;
+
                        while (num_bytes--) {
                                if (!dev->buf_len) {
-                                       if (stat & OMAP_I2C_STAT_RRDY)
-                                               dev_err(dev->dev,
+                                       dev_err(dev->dev,
                                                        "RRDY IRQ while no data"
-                                                               " requested\n");
-                                       if (stat & OMAP_I2C_STAT_RDR)
-                                               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,36 +869,68 @@ complete:
                                        }
                                }
                        }
-                       omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY |
-                                               OMAP_I2C_STAT_RDR));
+
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
                        continue;
                }
 
-               if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+               if (stat & OMAP_I2C_STAT_XDR) {
                        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->buf_len;
+
+                       while (num_bytes--) {
+                               if (!dev->buf_len) {
+                                       dev_err(dev->dev,
+                                                       "XDR 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_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) {
-                                       if (stat & OMAP_I2C_STAT_XRDY)
-                                               dev_err(dev->dev,
+                                       dev_err(dev->dev,
                                                        "XRDY IRQ while no "
                                                        "data to send\n");
-                                       if (stat & OMAP_I2C_STAT_XDR)
-                                               dev_err(dev->dev,
-                                                       "XDR 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
@@ -891,8 +949,8 @@ 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_XRDY);
                        continue;
                }