static irqreturn_t interrupt_transfer(struct dw_spi *dws) { u16 irq_status = dw_readl(dws, DW_SPI_ISR); /* Error handling */ if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) { dw_readl(dws, DW_SPI_ICR); int_error_stop(dws, "interrupt_transfer: fifo overrun/underrun"); return IRQ_HANDLED; } dw_reader(dws); if (dws->rx_end == dws->rx) { spi_mask_intr(dws, SPI_INT_TXEI); spi_finalize_current_transfer(dws->master); return IRQ_HANDLED; } if (irq_status & SPI_INT_TXEI) { spi_mask_intr(dws, SPI_INT_TXEI); dw_writer(dws); /* Enable TX irq always, it will be disabled when RX finished */ spi_umask_intr(dws, SPI_INT_TXEI); } return IRQ_HANDLED; }
static int reader_all(struct dw_spi *dws) { while (!(dw_readw(dws, SPIM_SR) & SR_RF_EMPT) && (dws->rx < dws->rx_end)) { dw_reader(dws); wait_till_not_busy(dws); } return dws->rx == dws->rx_end; }
/* Must be called inside pump_transfers() */ static int poll_transfer(struct dw_spi *dws) { do { dw_writer(dws); dw_reader(dws); cpu_relax(); } while (dws->rx_end > dws->rx); return 0; }