static void at91_init_twi_bus(struct at91_twi_dev *dev) { at91_disable_twi_interrupts(dev); at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST); at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN); at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS); at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg); }
static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) { struct at91_twi_dev *dev = dev_id; const unsigned status = at91_twi_read(dev, AT91_TWI_SR); const unsigned irqstatus = status & at91_twi_read(dev, AT91_TWI_IMR); if (!irqstatus) return IRQ_NONE; else 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; if (irqstatus & AT91_TWI_TXCOMP) { at91_disable_twi_interrupts(dev); complete(&dev->cmd_complete); } return IRQ_HANDLED; }
static void at91_twi_irq_save(struct at91_twi_dev *dev) { dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7; at91_disable_twi_interrupts(dev); }
static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) { struct at91_twi_dev *dev = dev_id; const unsigned status = at91_twi_read(dev, AT91_TWI_SR); const unsigned irqstatus = status & at91_twi_read(dev, AT91_TWI_IMR); if (!irqstatus) return IRQ_NONE; /* * 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) { /* * Read all available bytes at once by polling RXRDY usable w/ * and w/o FIFO. With FIFO enabled we could also read RXFL and * avoid polling RXRDY. */ do { at91_twi_read_next_byte(dev); } while (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY); } /* * 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; }