spi: qup: refactor spi_qup_io_config into two functions

This is in preparation for handling transactions larger than
64K-1 bytes in block mode, which is currently unsupported and
quietly fails.

We need to break these into two functions 1) prep is
called once per spi_message and 2) io_config is called
once per spi-qup bus transaction

This is just refactoring, there should be no functional
change

Signed-off-by: Matthew McClintock <mmcclint@codeaurora.org>
Signed-off-by: Varadarajan Narayanan <varada@codeaurora.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Varadarajan Narayanan 2017-07-28 12:22:55 +05:30 committed by Mark Brown
parent 7538726f9d
commit 94b9149feb

View file

@ -545,12 +545,11 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/* set clock freq ... bits per word */ /* set clock freq ... bits per word, determine mode */
static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer)
{ {
struct spi_qup *controller = spi_master_get_devdata(spi->master); struct spi_qup *controller = spi_master_get_devdata(spi->master);
u32 config, iomode, control; int ret;
int ret, n_words;
if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) {
dev_err(controller->dev, "too big size for loopback %d > %d\n", dev_err(controller->dev, "too big size for loopback %d > %d\n",
@ -565,32 +564,56 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
return -EIO; return -EIO;
} }
controller->w_size = DIV_ROUND_UP(xfer->bits_per_word, 8);
controller->n_words = xfer->len / controller->w_size;
if (controller->n_words <= (controller->in_fifo_sz / sizeof(u32)))
controller->mode = QUP_IO_M_MODE_FIFO;
else if (spi->master->can_dma &&
spi->master->can_dma(spi->master, spi, xfer) &&
spi->master->cur_msg_mapped)
controller->mode = QUP_IO_M_MODE_BAM;
else
controller->mode = QUP_IO_M_MODE_BLOCK;
return 0;
}
/* prep qup for another spi transaction of specific type */
static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
{
struct spi_qup *controller = spi_master_get_devdata(spi->master);
u32 config, iomode, control;
unsigned long flags;
spin_lock_irqsave(&controller->lock, flags);
controller->xfer = xfer;
controller->error = 0;
controller->rx_bytes = 0;
controller->tx_bytes = 0;
spin_unlock_irqrestore(&controller->lock, flags);
if (spi_qup_set_state(controller, QUP_STATE_RESET)) { if (spi_qup_set_state(controller, QUP_STATE_RESET)) {
dev_err(controller->dev, "cannot set RESET state\n"); dev_err(controller->dev, "cannot set RESET state\n");
return -EIO; return -EIO;
} }
controller->w_size = DIV_ROUND_UP(xfer->bits_per_word, 8); switch (controller->mode) {
controller->n_words = xfer->len / controller->w_size; case QUP_IO_M_MODE_FIFO:
n_words = controller->n_words; writel_relaxed(controller->n_words,
controller->base + QUP_MX_READ_CNT);
if (n_words <= (controller->in_fifo_sz / sizeof(u32))) { writel_relaxed(controller->n_words,
controller->base + QUP_MX_WRITE_CNT);
controller->mode = QUP_IO_M_MODE_FIFO;
writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
/* must be zero for FIFO */ /* must be zero for FIFO */
writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
} else if (spi->master->can_dma && break;
spi->master->can_dma(spi->master, spi, xfer) && case QUP_IO_M_MODE_BAM:
spi->master->cur_msg_mapped) { writel_relaxed(controller->n_words,
controller->base + QUP_MX_INPUT_CNT);
controller->mode = QUP_IO_M_MODE_BAM; writel_relaxed(controller->n_words,
controller->base + QUP_MX_OUTPUT_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
/* must be zero for BLOCK and BAM */ /* must be zero for BLOCK and BAM */
writel_relaxed(0, controller->base + QUP_MX_READ_CNT); writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
@ -608,19 +631,25 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
if (xfer->tx_buf) if (xfer->tx_buf)
writel_relaxed(0, input_cnt); writel_relaxed(0, input_cnt);
else else
writel_relaxed(n_words, input_cnt); writel_relaxed(controller->n_words, input_cnt);
writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
} }
} else { break;
case QUP_IO_M_MODE_BLOCK:
controller->mode = QUP_IO_M_MODE_BLOCK; reinit_completion(&controller->done);
writel_relaxed(controller->n_words,
writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT); controller->base + QUP_MX_INPUT_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT); writel_relaxed(controller->n_words,
controller->base + QUP_MX_OUTPUT_CNT);
/* must be zero for BLOCK and BAM */ /* must be zero for BLOCK and BAM */
writel_relaxed(0, controller->base + QUP_MX_READ_CNT); writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
break;
default:
dev_err(controller->dev, "unknown mode = %d\n",
controller->mode);
return -EIO;
} }
iomode = readl_relaxed(controller->base + QUP_IO_M_MODES); iomode = readl_relaxed(controller->base + QUP_IO_M_MODES);
@ -709,6 +738,10 @@ static int spi_qup_transfer_one(struct spi_master *master,
unsigned long timeout, flags; unsigned long timeout, flags;
int ret = -EIO; int ret = -EIO;
ret = spi_qup_io_prep(spi, xfer);
if (ret)
return ret;
ret = spi_qup_io_config(spi, xfer); ret = spi_qup_io_config(spi, xfer);
if (ret) if (ret)
return ret; return ret;