From 93f99afbc534e00d72d58336061823055ee820f1 Mon Sep 17 00:00:00 2001 From: Andy Gross Date: Tue, 12 Apr 2016 09:11:47 -0500 Subject: [PATCH] spi: qup: Make sure mode is only determined once This patch calculates the mode once. All decisions on the current transaction is made using the mode instead of use_dma Signed-off-by: Andy Gross Change-Id: If3cdd924355e037d77dc8201a72895fac0461aa5 --- drivers/spi/spi-qup.c | 96 +++++++++++++++++++-------------------------------- 1 file changed, 36 insertions(+), 60 deletions(-) --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -150,13 +150,20 @@ struct spi_qup { int rx_bytes; int qup_v1; - int use_dma; + int mode; struct dma_slave_config rx_conf; struct dma_slave_config tx_conf; - int mode; }; +static inline bool spi_qup_is_dma_xfer(int mode) +{ + if (mode == QUP_IO_M_MODE_DMOV || mode == QUP_IO_M_MODE_BAM) + return true; + + return false; +} + static inline bool spi_qup_is_valid_state(struct spi_qup *controller) { u32 opstate = readl_relaxed(controller->base + QUP_STATE); @@ -427,7 +434,7 @@ static irqreturn_t spi_qup_qup_irq(int i error = -EIO; } - if (!controller->use_dma) { + if (!spi_qup_is_dma_xfer(controller->mode)) { if (opflags & QUP_OP_IN_SERVICE_FLAG) spi_qup_fifo_read(controller, xfer); @@ -446,43 +453,11 @@ static irqreturn_t spi_qup_qup_irq(int i return IRQ_HANDLED; } -static u32 -spi_qup_get_mode(struct spi_master *master, struct spi_transfer *xfer) -{ - struct spi_qup *qup = spi_master_get_devdata(master); - u32 mode; - size_t dma_align = dma_get_cache_alignment(); - - qup->w_size = 4; - - if (xfer->bits_per_word <= 8) - qup->w_size = 1; - else if (xfer->bits_per_word <= 16) - qup->w_size = 2; - - qup->n_words = xfer->len / qup->w_size; - - if (!IS_ERR_OR_NULL(master->dma_rx) && - IS_ALIGNED((size_t)xfer->tx_buf, dma_align) && - IS_ALIGNED((size_t)xfer->rx_buf, dma_align) && - !is_vmalloc_addr(xfer->tx_buf) && - !is_vmalloc_addr(xfer->rx_buf) && - (xfer->len > 3*qup->in_blk_sz)) - qup->use_dma = 1; - - if (qup->n_words <= (qup->in_fifo_sz / sizeof(u32))) - mode = QUP_IO_M_MODE_FIFO; - else - mode = QUP_IO_M_MODE_BLOCK; - - return mode; -} - /* set clock freq ... bits per word */ 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, mode, control; + u32 config, iomode, control; int ret, n_words; if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { @@ -503,24 +478,22 @@ static int spi_qup_io_config(struct spi_ return -EIO; } - controller->mode = mode = spi_qup_get_mode(spi->master, xfer); + controller->w_size = DIV_ROUND_UP(xfer->bits_per_word, 8); + controller->n_words = xfer->len / controller->w_size; n_words = controller->n_words; - if (mode == QUP_IO_M_MODE_FIFO) { + if (n_words <= (controller->in_fifo_sz / sizeof(u32))) { + 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 */ writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); controller->use_dma = 0; - } else if (!controller->use_dma) { - 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 */ - writel_relaxed(0, controller->base + QUP_MX_READ_CNT); - writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); - } else { - mode = QUP_IO_M_MODE_BAM; + } 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; writel_relaxed(0, controller->base + QUP_MX_READ_CNT); writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); @@ -541,19 +514,26 @@ static int spi_qup_io_config(struct spi_ writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); } + } else { + controller->mode = QUP_IO_M_MODE_BLOCK; + 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 */ + writel_relaxed(0, controller->base + QUP_MX_READ_CNT); + writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); } 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 (!controller->use_dma) + 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 |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); - iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); + 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); @@ -594,7 +574,7 @@ static int spi_qup_io_config(struct spi_ config |= xfer->bits_per_word - 1; config |= QUP_CONFIG_SPI_MODE; - if (controller->use_dma) { + if (spi_qup_is_dma_xfer(controller->mode)) { if (!xfer->tx_buf) config |= QUP_CONFIG_NO_OUTPUT; if (!xfer->rx_buf) @@ -612,7 +592,7 @@ static int spi_qup_io_config(struct spi_ * status change in BAM mode */ - if (mode == QUP_IO_M_MODE_BAM) + 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); @@ -646,7 +626,7 @@ static int spi_qup_transfer_one(struct s controller->tx_bytes = 0; spin_unlock_irqrestore(&controller->lock, flags); - if (controller->use_dma) + if (spi_qup_is_dma_xfer(controller->mode)) ret = spi_qup_do_dma(master, xfer); else ret = spi_qup_do_pio(master, xfer); @@ -670,7 +650,7 @@ exit: ret = controller->error; spin_unlock_irqrestore(&controller->lock, flags); - if (ret && controller->use_dma) + if (ret && spi_qup_is_dma_xfer(controller->mode)) spi_qup_dma_terminate(master, xfer); return ret; @@ -681,9 +661,7 @@ static bool spi_qup_can_dma(struct spi_m { struct spi_qup *qup = spi_master_get_devdata(master); size_t dma_align = dma_get_cache_alignment(); - u32 mode; - - qup->use_dma = 0; + int n_words; if (xfer->rx_buf && (xfer->len % qup->in_blk_sz || IS_ERR_OR_NULL(master->dma_rx) || @@ -695,12 +673,10 @@ static bool spi_qup_can_dma(struct spi_m !IS_ALIGNED((size_t)xfer->tx_buf, dma_align))) return false; - mode = spi_qup_get_mode(master, xfer); - if (mode == QUP_IO_M_MODE_FIFO) + n_words = xfer->len / DIV_ROUND_UP(xfer->bits_per_word, 8); + if (n_words <= (qup->in_fifo_sz / sizeof(u32))) return false; - qup->use_dma = 1; - return true; }