i2c: omap: split out [XR]DR and [XR]RDY
[firefly-linux-kernel-4.4.55.git] / drivers / i2c / busses / i2c-omap.c
index f24eae9f7f1eb998fb1af608364b3e1818f024d0..815577b1c89fab8c5859bb7ce7e68eed69cf8e5c 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;
                }