/** * cdns_spi_irq - Interrupt service routine of the SPI controller * @irq: IRQ number * @dev_id: Pointer to the xspi structure * * This function handles TX empty and Mode Fault interrupts only. * On TX empty interrupt this function reads the received data from RX FIFO and * fills the TX FIFO if there is any data remaining to be transferred. * On Mode Fault interrupt this function indicates that transfer is completed, * the SPI subsystem will identify the error as the remaining bytes to be * transferred is non-zero. * * Return: IRQ_HANDLED when handled; IRQ_NONE otherwise. */ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) { struct spi_master *master = dev_id; struct cdns_spi *xspi = spi_master_get_devdata(master); u32 intr_status, status; status = IRQ_NONE; intr_status = cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET); cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, intr_status); if (intr_status & CDNS_SPI_IXR_MODF_MASK) { /* Indicate that transfer is completed, the SPI subsystem will * identify the error as the remaining bytes to be * transferred is non-zero */ cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, CDNS_SPI_IXR_DEFAULT_MASK); spi_finalize_current_transfer(master); status = IRQ_HANDLED; } else if (intr_status & CDNS_SPI_IXR_TXOW_MASK) { unsigned long trans_cnt; trans_cnt = xspi->rx_bytes - xspi->tx_bytes; /* Read out the data from the RX FIFO */ while (trans_cnt) { u8 data; data = cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET); if (xspi->rxbuf) *xspi->rxbuf++ = data; xspi->rx_bytes--; trans_cnt--; } if (xspi->tx_bytes) { /* There is more data to send */ cdns_spi_fill_tx_fifo(xspi); } else { /* Transfer is completed */ cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, CDNS_SPI_IXR_DEFAULT_MASK); spi_finalize_current_transfer(master); } status = IRQ_HANDLED; } return status; }
/** * cdns_transfer_one - Initiates the SPI transfer * @master: Pointer to spi_master structure * @spi: Pointer to the spi_device structure * @transfer: Pointer to the spi_transfer structure which provides * information about next transfer parameters * * This function fills the TX FIFO, starts the SPI transfer and * returns a positive transfer count so that core will wait for completion. * * Return: Number of bytes transferred in the last transfer */ static int cdns_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer) { struct cdns_spi *xspi = spi_master_get_devdata(master); xspi->txbuf = transfer->tx_buf; xspi->rxbuf = transfer->rx_buf; xspi->tx_bytes = transfer->len; xspi->rx_bytes = transfer->len; cdns_spi_setup_transfer(spi, transfer); cdns_spi_fill_tx_fifo(xspi); cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT); return transfer->len; }