]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/i2c/busses/i2c-at91.c
Merge remote-tracking branch 'i2c/i2c/for-next'
[karo-tx-linux.git] / drivers / i2c / busses / i2c-at91.c
index 1c758cd1e1ba82d4acb56f1684270e5af5437c2e..10835d1f559ba99f9b0118b19f55b7187a980dea 100644 (file)
@@ -347,8 +347,14 @@ error:
 
 static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
 {
-       if (!dev->buf_len)
+       /*
+        * If we are in this case, it means there is garbage data in RHR, so
+        * delete them.
+        */
+       if (!dev->buf_len) {
+               at91_twi_read(dev, AT91_TWI_RHR);
                return;
+       }
 
        /* 8bit read works with and without FIFO */
        *dev->buf = readb_relaxed(dev->base + AT91_TWI_RHR);
@@ -465,19 +471,73 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
 
        if (!irqstatus)
                return IRQ_NONE;
-       else if (irqstatus & AT91_TWI_RXRDY)
+       /*
+        * In reception, the behavior of the twi device (before sama5d2) is
+        * weird. There is some magic about RXRDY flag! When a data has been
+        * almost received, the reception of a new one is anticipated if there
+        * is no stop command to send. That is the reason why ask for sending
+        * the stop command not on the last data but on the second last one.
+        *
+        * Unfortunately, we could still have the RXRDY flag set even if the
+        * transfer is done and we have read the last data. It might happen
+        * when the i2c slave device sends too quickly data after receiving the
+        * ack from the master. The data has been almost received before having
+        * the order to send stop. In this case, sending the stop command could
+        * cause a RXRDY interrupt with a TXCOMP one. It is better to manage
+        * the RXRDY interrupt first in order to not keep garbage data in the
+        * Receive Holding Register for the next transfer.
+        */
+       if (irqstatus & AT91_TWI_RXRDY)
                at91_twi_read_next_byte(dev);
-       else if (irqstatus & AT91_TWI_TXRDY)
-               at91_twi_write_next_byte(dev);
-
-       /* catch error flags */
-       dev->transfer_status |= status;
 
+       /*
+        * When a NACK condition is detected, the I2C controller sets the NACK,
+        * TXCOMP and TXRDY bits all together in the Status Register (SR).
+        *
+        * 1 - Handling NACK errors with CPU write transfer.
+        *
+        * In such case, we should not write the next byte into the Transmit
+        * Holding Register (THR) otherwise the I2C controller would start a new
+        * transfer and the I2C slave is likely to reply by another NACK.
+        *
+        * 2 - Handling NACK errors with DMA write transfer.
+        *
+        * By setting the TXRDY bit in the SR, the I2C controller also triggers
+        * the DMA controller to write the next data into the THR. Then the
+        * result depends on the hardware version of the I2C controller.
+        *
+        * 2a - Without support of the Alternative Command mode.
+        *
+        * This is the worst case: the DMA controller is triggered to write the
+        * next data into the THR, hence starting a new transfer: the I2C slave
+        * is likely to reply by another NACK.
+        * Concurrently, this interrupt handler is likely to be called to manage
+        * the first NACK before the I2C controller detects the second NACK and
+        * sets once again the NACK bit into the SR.
+        * When handling the first NACK, this interrupt handler disables the I2C
+        * controller interruptions, especially the NACK interrupt.
+        * Hence, the NACK bit is pending into the SR. This is why we should
+        * read the SR to clear all pending interrupts at the beginning of
+        * at91_do_twi_transfer() before actually starting a new transfer.
+        *
+        * 2b - With support of the Alternative Command mode.
+        *
+        * When a NACK condition is detected, the I2C controller also locks the
+        * THR (and sets the LOCK bit in the SR): even though the DMA controller
+        * is triggered by the TXRDY bit to write the next data into the THR,
+        * this data actually won't go on the I2C bus hence a second NACK is not
+        * generated.
+        */
        if (irqstatus & (AT91_TWI_TXCOMP | AT91_TWI_NACK)) {
                at91_disable_twi_interrupts(dev);
                complete(&dev->cmd_complete);
+       } else if (irqstatus & AT91_TWI_TXRDY) {
+               at91_twi_write_next_byte(dev);
        }
 
+       /* catch error flags */
+       dev->transfer_status |= status;
+
        return IRQ_HANDLED;
 }
 
@@ -537,6 +597,9 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
        reinit_completion(&dev->cmd_complete);
        dev->transfer_status = 0;
 
+       /* Clear pending interrupts, such as NACK. */
+       at91_twi_read(dev, AT91_TWI_SR);
+
        if (dev->fifo_size) {
                unsigned fifo_mr = at91_twi_read(dev, AT91_TWI_FMR);
 
@@ -558,11 +621,6 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
        } else if (dev->msg->flags & I2C_M_RD) {
                unsigned start_flags = AT91_TWI_START;
 
-               if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
-                       dev_err(dev->dev, "RXRDY still set!");
-                       at91_twi_read(dev, AT91_TWI_RHR);
-               }
-
                /* if only one byte is to be read, immediately stop transfer */
                if (!has_alt_cmd && dev->buf_len <= 1 &&
                    !(dev->msg->flags & I2C_M_RECV_LEN))