diff options
Diffstat (limited to 'target/linux/ipq806x/patches-4.4/712-spi-qup-Fix-DMA-mode-to-work-correctly.patch')
-rw-r--r-- | target/linux/ipq806x/patches-4.4/712-spi-qup-Fix-DMA-mode-to-work-correctly.patch | 85 |
1 files changed, 40 insertions, 45 deletions
diff --git a/target/linux/ipq806x/patches-4.4/712-spi-qup-Fix-DMA-mode-to-work-correctly.patch b/target/linux/ipq806x/patches-4.4/712-spi-qup-Fix-DMA-mode-to-work-correctly.patch index d9abc65ce2..9c7bbeabda 100644 --- a/target/linux/ipq806x/patches-4.4/712-spi-qup-Fix-DMA-mode-to-work-correctly.patch +++ b/target/linux/ipq806x/patches-4.4/712-spi-qup-Fix-DMA-mode-to-work-correctly.patch @@ -14,29 +14,27 @@ Signed-off-by: Andy Gross <andy.gross@linaro.org> drivers/spi/spi-qup.c | 95 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 32 deletions(-) -diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c -index fe629f2..089c5e8 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -143,6 +143,7 @@ struct spi_qup { - + struct spi_transfer *xfer; struct completion done; + struct completion dma_tx_done; int error; int w_size; /* bytes per SPI word */ int n_words; -@@ -285,16 +286,16 @@ static void spi_qup_fifo_write(struct spi_qup *controller, - +@@ -285,16 +286,16 @@ static void spi_qup_fifo_write(struct sp + static void spi_qup_dma_done(void *data) { - struct spi_qup *qup = data; + struct completion *done = data; - + - complete(&qup->done); + complete(done); } - + static int spi_qup_prep_sg(struct spi_master *master, struct spi_transfer *xfer, enum dma_transfer_direction dir, - dma_async_tx_callback callback) @@ -47,25 +45,25 @@ index fe629f2..089c5e8 100644 unsigned long flags = DMA_PREP_INTERRUPT | DMA_PREP_FENCE; struct dma_async_tx_descriptor *desc; struct scatterlist *sgl; -@@ -313,11 +314,11 @@ static int spi_qup_prep_sg(struct spi_master *master, struct spi_transfer *xfer, +@@ -313,11 +314,11 @@ static int spi_qup_prep_sg(struct spi_ma } - + desc = dmaengine_prep_slave_sg(chan, sgl, nents, dir, flags); - if (!desc) - return -EINVAL; + if (IS_ERR_OR_NULL(desc)) + return desc ? PTR_ERR(desc) : -EINVAL; - + desc->callback = callback; - desc->callback_param = qup; + desc->callback_param = data; - + cookie = dmaengine_submit(desc); - -@@ -333,18 +334,29 @@ static void spi_qup_dma_terminate(struct spi_master *master, + +@@ -333,18 +334,29 @@ 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) +static int spi_qup_do_dma(struct spi_master *master, struct spi_transfer *xfer, +unsigned long timeout) @@ -73,7 +71,7 @@ index fe629f2..089c5e8 100644 + struct spi_qup *qup = spi_master_get_devdata(master); dma_async_tx_callback rx_done = NULL, tx_done = NULL; int ret; - + + /* before issuing the descriptors, set the QUP to run */ + ret = spi_qup_set_state(qup, QUP_STATE_RUN); + if (ret) { @@ -87,27 +85,27 @@ index fe629f2..089c5e8 100644 + + if (xfer->tx_buf) tx_done = spi_qup_dma_done; - + if (xfer->rx_buf) { - ret = spi_qup_prep_sg(master, xfer, DMA_DEV_TO_MEM, rx_done); + ret = spi_qup_prep_sg(master, xfer, DMA_DEV_TO_MEM, rx_done, + &qup->done); if (ret) return ret; - -@@ -352,17 +364,26 @@ static int spi_qup_do_dma(struct spi_master *master, struct spi_transfer *xfer) + +@@ -352,17 +364,26 @@ static int spi_qup_do_dma(struct spi_mas } - + if (xfer->tx_buf) { - ret = spi_qup_prep_sg(master, xfer, DMA_MEM_TO_DEV, tx_done); + ret = spi_qup_prep_sg(master, xfer, DMA_MEM_TO_DEV, tx_done, + &qup->dma_tx_done); if (ret) return ret; - + dma_async_issue_pending(master->dma_tx); } - + - return 0; + if (xfer->rx_buf && !wait_for_completion_timeout(&qup->done, timeout)) + return -ETIMEDOUT; @@ -118,17 +116,17 @@ index fe629f2..089c5e8 100644 + + return ret; } - + -static int spi_qup_do_pio(struct spi_master *master, struct spi_transfer *xfer) +static int spi_qup_do_pio(struct spi_master *master, struct spi_transfer *xfer, + unsigned long timeout) { struct spi_qup *qup = spi_master_get_devdata(master); int ret; -@@ -382,6 +403,15 @@ static int spi_qup_do_pio(struct spi_master *master, struct spi_transfer *xfer) +@@ -382,6 +403,15 @@ static int spi_qup_do_pio(struct spi_mas if (qup->mode == QUP_IO_M_MODE_FIFO) spi_qup_fifo_write(qup, xfer); - + + ret = spi_qup_set_state(qup, QUP_STATE_RUN); + if (ret) { + dev_warn(qup->dev, "cannot set RUN state\n"); @@ -140,36 +138,36 @@ index fe629f2..089c5e8 100644 + return 0; } - -@@ -430,7 +460,6 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) + +@@ -430,7 +460,6 @@ static irqreturn_t spi_qup_qup_irq(int i dev_warn(controller->dev, "CLK_OVER_RUN\n"); if (spi_err & SPI_ERROR_CLK_UNDER_RUN) dev_warn(controller->dev, "CLK_UNDER_RUN\n"); - error = -EIO; } - -@@ -619,6 +648,7 @@ static int spi_qup_transfer_one(struct spi_master *master, + +@@ -619,6 +648,7 @@ static int spi_qup_transfer_one(struct s timeout = 100 * msecs_to_jiffies(timeout); - + reinit_completion(&controller->done); + reinit_completion(&controller->dma_tx_done); - + spin_lock_irqsave(&controller->lock, flags); controller->xfer = xfer; -@@ -628,21 +658,13 @@ static int spi_qup_transfer_one(struct spi_master *master, +@@ -628,21 +658,13 @@ static int spi_qup_transfer_one(struct s spin_unlock_irqrestore(&controller->lock, flags); - + if (spi_qup_is_dma_xfer(controller->mode)) - ret = spi_qup_do_dma(master, xfer); + ret = spi_qup_do_dma(master, xfer, timeout); else - ret = spi_qup_do_pio(master, xfer); + ret = spi_qup_do_pio(master, xfer, timeout); - + if (ret) goto exit; - + - if (spi_qup_set_state(controller, QUP_STATE_RUN)) { - dev_warn(controller->dev, "cannot set EXECUTE state\n"); - goto exit; @@ -181,10 +179,10 @@ index fe629f2..089c5e8 100644 exit: spi_qup_set_state(controller, QUP_STATE_RESET); spin_lock_irqsave(&controller->lock, flags); -@@ -664,15 +686,23 @@ static bool spi_qup_can_dma(struct spi_master *master, struct spi_device *spi, +@@ -664,15 +686,23 @@ static bool spi_qup_can_dma(struct spi_m size_t dma_align = dma_get_cache_alignment(); int n_words; - + - if (xfer->rx_buf && (xfer->len % qup->in_blk_sz || - IS_ERR_OR_NULL(master->dma_rx) || - !IS_ALIGNED((size_t)xfer->rx_buf, dma_align))) @@ -193,7 +191,7 @@ index fe629f2..089c5e8 100644 + if (!IS_ALIGNED((size_t)xfer->rx_buf, dma_align) || + IS_ERR_OR_NULL(master->dma_rx)) + return false; - + - if (xfer->tx_buf && (xfer->len % qup->out_blk_sz || - IS_ERR_OR_NULL(master->dma_tx) || - !IS_ALIGNED((size_t)xfer->tx_buf, dma_align))) @@ -210,17 +208,14 @@ index fe629f2..089c5e8 100644 + if (qup->qup_v1 && (xfer->len % qup->out_blk_sz)) + return false; + } - + n_words = xfer->len / DIV_ROUND_UP(xfer->bits_per_word, 8); if (n_words <= (qup->in_fifo_sz / sizeof(u32))) -@@ -875,6 +905,7 @@ static int spi_qup_probe(struct platform_device *pdev) - +@@ -875,6 +905,7 @@ static int spi_qup_probe(struct platform + spin_lock_init(&controller->lock); init_completion(&controller->done); + init_completion(&controller->dma_tx_done); - + iomode = readl_relaxed(base + QUP_IO_M_MODES); - --- -2.7.2 - + |