@@ -911,15 +911,39 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void dspi_enable_interrupts(struct fsl_dspi *dspi, bool on)
+{
+ u32 spi_rser = 0;
+
+ if (on) {
+ switch (dspi->devtype_data->trans_mode) {
+ case DSPI_EOQ_MODE:
+ spi_rser = SPI_RSER_EOQFE;
+ break;
+ case DSPI_XSPI_MODE:
+ spi_rser = SPI_RSER_CMDTCFE;
+ break;
+ default:
+ /* Interrupts not necessary for DMA mode */
+ return;
+ }
+ }
+
+ regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
+ regmap_write(dspi->regmap, SPI_RSER, spi_rser);
+}
+
static int dspi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *message)
{
struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
struct spi_device *spi = message->spi;
- enum dspi_trans_mode trans_mode;
struct spi_transfer *transfer;
int status = 0;
+ if (dspi->irq)
+ dspi_enable_interrupts(dspi, true);
+
message->actual_length = 0;
list_for_each_entry(transfer, &message->transfers, transfer_list) {
@@ -965,37 +989,24 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
dspi->progress, !dspi->irq);
- trans_mode = dspi->devtype_data->trans_mode;
- switch (trans_mode) {
- case DSPI_EOQ_MODE:
- regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
- dspi_fifo_write(dspi);
- break;
- case DSPI_XSPI_MODE:
- regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_CMDTCFE);
- dspi_fifo_write(dspi);
- break;
- case DSPI_DMA_MODE:
+ if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
regmap_write(dspi->regmap, SPI_RSER,
SPI_RSER_TFFFE | SPI_RSER_TFFFD |
SPI_RSER_RFDFE | SPI_RSER_RFDFD);
status = dspi_dma_xfer(dspi);
- break;
- default:
- dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n",
- trans_mode);
- status = -EINVAL;
- goto out;
- }
+ if (status)
+ goto out;
+ } else if (dspi->irq) {
+ /* Kick off the interrupt train */
+ dspi_fifo_write(dspi);
- if (!dspi->irq) {
- do {
- status = dspi_poll(dspi);
- } while (status == -EINPROGRESS);
- } else if (trans_mode != DSPI_DMA_MODE) {
status = wait_event_interruptible(dspi->waitq,
dspi->waitflags);
dspi->waitflags = 0;
+ } else {
+ do {
+ status = dspi_poll(dspi);
+ } while (status == -EINPROGRESS);
}
if (status)
dev_err(&dspi->pdev->dev,
@@ -1005,6 +1016,9 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
}
out:
+ if (dspi->irq)
+ dspi_enable_interrupts(dspi, false);
+
message->status = status;
spi_finalize_current_message(ctlr);
@@ -1208,7 +1222,6 @@ static void dspi_init(struct fsl_dspi *dspi)
mcr |= SPI_MCR_MASTER;
regmap_write(dspi->regmap, SPI_MCR, mcr);
- regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR);
}
static int dspi_slave_abort(struct spi_master *master)