From afe108e638a2dd441b11cd2c7b1e0658bb47b5e8 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Tue, 26 Apr 2016 13:14:45 -0500 Subject: [PATCH 10/69] spi: qup: call io_config in mode specific function DMA transactions should only only need to call io_config only once, but block mode might call it several times to setup several transactions so it can handle reads/writes larger than the max size per transaction, so we move the call to the do_ functions. This is just refactoring, there should be no functional change Signed-off-by: Matthew McClintock --- drivers/spi/spi-qup.c | 327 +++++++++++++++++++++++++------------------------- 1 file changed, 166 insertions(+), 161 deletions(-) --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -418,13 +418,170 @@ static void spi_qup_dma_terminate(struct dmaengine_terminate_all(master->dma_rx); } -static int spi_qup_do_dma(struct spi_master *master, struct spi_transfer *xfer, +/* 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; + + reinit_completion(&controller->done); + reinit_completion(&controller->dma_tx_done); + + 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)) { + dev_err(controller->dev, "cannot set RESET state\n"); + return -EIO; + } + + switch (controller->mode) { + case QUP_IO_M_MODE_FIFO: + writel_relaxed(controller->n_words, + controller->base + QUP_MX_READ_CNT); + writel_relaxed(controller->n_words, + controller->base + QUP_MX_WRITE_CNT); + /* must be zero for FIFO */ + writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); + writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); + break; + case QUP_IO_M_MODE_BAM: + writel_relaxed(controller->n_words, + controller->base + QUP_MX_INPUT_CNT); + writel_relaxed(controller->n_words, + controller->base + QUP_MX_OUTPUT_CNT); + /* must be zero for BLOCK and BAM */ + writel_relaxed(0, controller->base + QUP_MX_READ_CNT); + writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); + if (!controller->qup_v1) { + void __iomem *input_cnt; + + input_cnt = controller->base + QUP_MX_INPUT_CNT; + /* + * for DMA transfers, both QUP_MX_INPUT_CNT and + * QUP_MX_OUTPUT_CNT must be zero to all cases + * but one. That case is a non-balanced + * transfer when there is only a rx_buf. + */ + if (xfer->tx_buf) + writel_relaxed(0, input_cnt); + else + writel_relaxed(controller->n_words, + input_cnt); + + writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); + } + break; + case QUP_IO_M_MODE_BLOCK: + writel_relaxed(controller->n_words, + controller->base + QUP_MX_INPUT_CNT); + writel_relaxed(controller->n_words, + controller->base + QUP_MX_OUTPUT_CNT); + /* must be zero for BLOCK and BAM */ + writel_relaxed(0, controller->base + QUP_MX_READ_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); + /* Set input and output transfer mode */ + iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK); + + if (!spi_qup_is_dma_xfer(controller->mode)) + iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN); + else + iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN; + + iomode |= (controller->mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); + iomode |= (controller->mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); + + writel_relaxed(iomode, controller->base + QUP_IO_M_MODES); + + control = readl_relaxed(controller->base + SPI_IO_CONTROL); + + if (spi->mode & SPI_CPOL) + control |= SPI_IO_C_CLK_IDLE_HIGH; + else + control &= ~SPI_IO_C_CLK_IDLE_HIGH; + + writel_relaxed(control, controller->base + SPI_IO_CONTROL); + + config = readl_relaxed(controller->base + SPI_CONFIG); + + if (spi->mode & SPI_LOOP) + config |= SPI_CONFIG_LOOPBACK; + else + config &= ~SPI_CONFIG_LOOPBACK; + + if (spi->mode & SPI_CPHA) + config &= ~SPI_CONFIG_INPUT_FIRST; + else + config |= SPI_CONFIG_INPUT_FIRST; + + /* + * HS_MODE improves signal stability for spi-clk high rates, + * but is invalid in loop back mode. + */ + if ((xfer->speed_hz >= SPI_HS_MIN_RATE) && !(spi->mode & SPI_LOOP)) + config |= SPI_CONFIG_HS_MODE; + else + config &= ~SPI_CONFIG_HS_MODE; + + writel_relaxed(config, controller->base + SPI_CONFIG); + + config = readl_relaxed(controller->base + QUP_CONFIG); + config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N); + config |= xfer->bits_per_word - 1; + config |= QUP_CONFIG_SPI_MODE; + + if (spi_qup_is_dma_xfer(controller->mode)) { + if (!xfer->tx_buf) + config |= QUP_CONFIG_NO_OUTPUT; + if (!xfer->rx_buf) + config |= QUP_CONFIG_NO_INPUT; + } + + writel_relaxed(config, controller->base + QUP_CONFIG); + + /* only write to OPERATIONAL_MASK when register is present */ + if (!controller->qup_v1) { + u32 mask = 0; + + /* + * mask INPUT and OUTPUT service flags to prevent IRQs on FIFO + * status change in BAM mode + */ + + if (spi_qup_is_dma_xfer(controller->mode)) + mask = QUP_OP_IN_SERVICE_FLAG | QUP_OP_OUT_SERVICE_FLAG; + + writel_relaxed(mask, controller->base + QUP_OPERATIONAL_MASK); + } + + return 0; +} + +static int spi_qup_do_dma(struct spi_device *spi, struct spi_transfer *xfer, unsigned long timeout) { + struct spi_master *master = spi->master; struct spi_qup *qup = spi_master_get_devdata(master); dma_async_tx_callback rx_done = NULL, tx_done = NULL; int ret; + ret = spi_qup_io_config(spi, xfer); + if (ret) + return ret; + /* before issuing the descriptors, set the QUP to run */ ret = spi_qup_set_state(qup, QUP_STATE_RUN); if (ret) { @@ -467,12 +624,17 @@ unsigned long timeout) return ret; } -static int spi_qup_do_pio(struct spi_master *master, struct spi_transfer *xfer, +static int spi_qup_do_pio(struct spi_device *spi, struct spi_transfer *xfer, unsigned long timeout) { + struct spi_master *master = spi->master; struct spi_qup *qup = spi_master_get_devdata(master); int ret; + ret = spi_qup_io_config(spi, xfer); + if (ret) + return ret; + ret = spi_qup_set_state(qup, QUP_STATE_RUN); if (ret) { dev_warn(qup->dev, "cannot set RUN state\n"); @@ -619,159 +781,6 @@ static int spi_qup_io_prep(struct spi_de 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; - - reinit_completion(&controller->done); - reinit_completion(&controller->dma_tx_done); - - 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)) { - dev_err(controller->dev, "cannot set RESET state\n"); - return -EIO; - } - - switch (controller->mode) { - case QUP_IO_M_MODE_FIFO: - writel_relaxed(controller->n_words, - controller->base + QUP_MX_READ_CNT); - writel_relaxed(controller->n_words, - controller->base + QUP_MX_WRITE_CNT); - /* must be zero for FIFO */ - writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); - writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); - break; - case QUP_IO_M_MODE_BAM: - writel_relaxed(controller->n_words, - controller->base + QUP_MX_INPUT_CNT); - writel_relaxed(controller->n_words, - controller->base + QUP_MX_OUTPUT_CNT); - /* must be zero for BLOCK and BAM */ - writel_relaxed(0, controller->base + QUP_MX_READ_CNT); - writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); - if (!controller->qup_v1) { - void __iomem *input_cnt; - - input_cnt = controller->base + QUP_MX_INPUT_CNT; - /* - * for DMA transfers, both QUP_MX_INPUT_CNT and - * QUP_MX_OUTPUT_CNT must be zero to all cases - * but one. That case is a non-balanced - * transfer when there is only a rx_buf. - */ - if (xfer->tx_buf) - writel_relaxed(0, input_cnt); - else - writel_relaxed(controller->n_words, - input_cnt); - - writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); - } - break; - case QUP_IO_M_MODE_BLOCK: - writel_relaxed(controller->n_words, - controller->base + QUP_MX_INPUT_CNT); - writel_relaxed(controller->n_words, - controller->base + QUP_MX_OUTPUT_CNT); - /* must be zero for BLOCK and BAM */ - writel_relaxed(0, controller->base + QUP_MX_READ_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); - /* Set input and output transfer mode */ - iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK); - - if (!spi_qup_is_dma_xfer(controller->mode)) - iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN); - else - iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN; - - iomode |= (controller->mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); - iomode |= (controller->mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); - - writel_relaxed(iomode, controller->base + QUP_IO_M_MODES); - - control = readl_relaxed(controller->base + SPI_IO_CONTROL); - - if (spi->mode & SPI_CPOL) - control |= SPI_IO_C_CLK_IDLE_HIGH; - else - control &= ~SPI_IO_C_CLK_IDLE_HIGH; - - writel_relaxed(control, controller->base + SPI_IO_CONTROL); - - config = readl_relaxed(controller->base + SPI_CONFIG); - - if (spi->mode & SPI_LOOP) - config |= SPI_CONFIG_LOOPBACK; - else - config &= ~SPI_CONFIG_LOOPBACK; - - if (spi->mode & SPI_CPHA) - config &= ~SPI_CONFIG_INPUT_FIRST; - else - config |= SPI_CONFIG_INPUT_FIRST; - - /* - * HS_MODE improves signal stability for spi-clk high rates, - * but is invalid in loop back mode. - */ - if ((xfer->speed_hz >= SPI_HS_MIN_RATE) && !(spi->mode & SPI_LOOP)) - config |= SPI_CONFIG_HS_MODE; - else - config &= ~SPI_CONFIG_HS_MODE; - - writel_relaxed(config, controller->base + SPI_CONFIG); - - config = readl_relaxed(controller->base + QUP_CONFIG); - config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N); - config |= xfer->bits_per_word - 1; - config |= QUP_CONFIG_SPI_MODE; - - if (spi_qup_is_dma_xfer(controller->mode)) { - if (!xfer->tx_buf) - config |= QUP_CONFIG_NO_OUTPUT; - if (!xfer->rx_buf) - config |= QUP_CONFIG_NO_INPUT; - } - - writel_relaxed(config, controller->base + QUP_CONFIG); - - /* only write to OPERATIONAL_MASK when register is present */ - if (!controller->qup_v1) { - u32 mask = 0; - - /* - * mask INPUT and OUTPUT service flags to prevent IRQs on FIFO - * status change in BAM mode - */ - - if (spi_qup_is_dma_xfer(controller->mode)) - mask = QUP_OP_IN_SERVICE_FLAG | QUP_OP_OUT_SERVICE_FLAG; - - writel_relaxed(mask, controller->base + QUP_OPERATIONAL_MASK); - } - - return 0; -} - static int spi_qup_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) @@ -784,18 +793,14 @@ static int spi_qup_transfer_one(struct s if (ret) return ret; - ret = spi_qup_io_config(spi, xfer); - if (ret) - return ret; - timeout = DIV_ROUND_UP(xfer->speed_hz, MSEC_PER_SEC); timeout = DIV_ROUND_UP(xfer->len * 8, timeout); timeout = 100 * msecs_to_jiffies(timeout); if (spi_qup_is_dma_xfer(controller->mode)) - ret = spi_qup_do_dma(master, xfer, timeout); + ret = spi_qup_do_dma(spi, xfer, timeout); else - ret = spi_qup_do_pio(master, xfer, timeout); + ret = spi_qup_do_pio(spi, xfer, timeout); if (ret) goto exit;