Kernel bump from 4.1.3-rt to 4.1.7-rt.
[kvmfornfv.git] / kernel / drivers / i2c / busses / i2c-at91.c
index ff23d1b..9bd10a9 100644 (file)
@@ -65,6 +65,9 @@
 #define        AT91_TWI_UNRE           0x0080  /* Underrun Error */
 #define        AT91_TWI_NACK           0x0100  /* Not Acknowledged */
 
+#define        AT91_TWI_INT_MASK \
+       (AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY | AT91_TWI_NACK)
+
 #define        AT91_TWI_IER            0x0024  /* Interrupt Enable Register */
 #define        AT91_TWI_IDR            0x0028  /* Interrupt Disable Register */
 #define        AT91_TWI_IMR            0x002c  /* Interrupt Mask Register */
@@ -119,13 +122,12 @@ static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
 
 static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
 {
-       at91_twi_write(dev, AT91_TWI_IDR,
-                      AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
+       at91_twi_write(dev, AT91_TWI_IDR, AT91_TWI_INT_MASK);
 }
 
 static void at91_twi_irq_save(struct at91_twi_dev *dev)
 {
-       dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7;
+       dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & AT91_TWI_INT_MASK;
        at91_disable_twi_interrupts(dev);
 }
 
@@ -215,6 +217,14 @@ static void at91_twi_write_data_dma_callback(void *data)
        dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
                         dev->buf_len, DMA_TO_DEVICE);
 
+       /*
+        * When this callback is called, THR/TX FIFO is likely not to be empty
+        * yet. So we have to wait for TXCOMP or NACK bits to be set into the
+        * Status Register to be sure that the STOP bit has been sent and the
+        * transfer is completed. The NACK interrupt has already been enabled,
+        * we just have to enable TXCOMP one.
+        */
+       at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
        at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
 }
 
@@ -309,7 +319,7 @@ static void at91_twi_read_data_dma_callback(void *data)
        /* The last two bytes have to be read without using dma */
        dev->buf += dev->buf_len - 2;
        dev->buf_len = 2;
-       at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY);
+       at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY | AT91_TWI_TXCOMP);
 }
 
 static void at91_twi_read_data_dma(struct at91_twi_dev *dev)
@@ -370,7 +380,7 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
        /* catch error flags */
        dev->transfer_status |= status;
 
-       if (irqstatus & AT91_TWI_TXCOMP) {
+       if (irqstatus & (AT91_TWI_TXCOMP | AT91_TWI_NACK)) {
                at91_disable_twi_interrupts(dev);
                complete(&dev->cmd_complete);
        }
@@ -384,6 +394,34 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
        unsigned long time_left;
        bool has_unre_flag = dev->pdata->has_unre_flag;
 
+       /*
+        * WARNING: the TXCOMP bit in the Status Register is NOT a clear on
+        * read flag but shows the state of the transmission at the time the
+        * Status Register is read. According to the programmer datasheet,
+        * TXCOMP is set when both holding register and internal shifter are
+        * empty and STOP condition has been sent.
+        * Consequently, we should enable NACK interrupt rather than TXCOMP to
+        * detect transmission failure.
+        *
+        * Besides, the TXCOMP bit is already set before the i2c transaction
+        * has been started. For read transactions, this bit is cleared when
+        * writing the START bit into the Control Register. So the
+        * corresponding interrupt can safely be enabled just after.
+        * However for write transactions managed by the CPU, we first write
+        * into THR, so TXCOMP is cleared. Then we can safely enable TXCOMP
+        * interrupt. If TXCOMP interrupt were enabled before writing into THR,
+        * the interrupt handler would be called immediately and the i2c command
+        * would be reported as completed.
+        * Also when a write transaction is managed by the DMA controller,
+        * enabling the TXCOMP interrupt in this function may lead to a race
+        * condition since we don't know whether the TXCOMP interrupt is enabled
+        * before or after the DMA has started to write into THR. So the TXCOMP
+        * interrupt is enabled later by at91_twi_write_data_dma_callback().
+        * Immediately after in that DMA callback, we still need to send the
+        * STOP condition manually writing the corresponding bit into the
+        * Control Register.
+        */
+
        dev_dbg(dev->dev, "transfer: %s %d bytes.\n",
                (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len);
 
@@ -414,26 +452,24 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
                 * seems to be the best solution.
                 */
                if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) {
+                       at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK);
                        at91_twi_read_data_dma(dev);
-                       /*
-                        * It is important to enable TXCOMP irq here because
-                        * doing it only when transferring the last two bytes
-                        * will mask NACK errors since TXCOMP is set when a
-                        * NACK occurs.
-                        */
-                       at91_twi_write(dev, AT91_TWI_IER,
-                              AT91_TWI_TXCOMP);
-               } else
+               } else {
                        at91_twi_write(dev, AT91_TWI_IER,
-                              AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
+                                      AT91_TWI_TXCOMP |
+                                      AT91_TWI_NACK |
+                                      AT91_TWI_RXRDY);
+               }
        } else {
                if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) {
+                       at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK);
                        at91_twi_write_data_dma(dev);
-                       at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
                } else {
                        at91_twi_write_next_byte(dev);
                        at91_twi_write(dev, AT91_TWI_IER,
-                               AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
+                                      AT91_TWI_TXCOMP |
+                                      AT91_TWI_NACK |
+                                      AT91_TWI_TXRDY);
                }
        }