aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-sh-msiof.c
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2014-07-09 06:26:23 -0400
committerMark Brown <broonie@linaro.org>2014-07-16 17:41:51 -0400
commit279d2378c9c4f05bbe41b55625b4003871026266 (patch)
treec07d111eb25b18e62addcd98e311013c8c0e486b /drivers/spi/spi-sh-msiof.c
parent51fd509046f71471e606f3fd76411d238c3b5d39 (diff)
spi: sh-msiof: Handle dmaengine_prep_slave_single() failures gracefully
As typically a shmobile SoC has less DMA channels than devices that can use DMA, we may want to prioritize access to the DMA channels in the future. This means that dmaengine_prep_slave_single() may start failing arbitrarily. Handle dmaengine_prep_slave_single() failures gracefully by falling back to PIO. This requires moving DMA-specific configuration of the MSIOF device after the call(s) to dmaengine_prep_slave_single(). Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi/spi-sh-msiof.c')
-rw-r--r--drivers/spi/spi-sh-msiof.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 9922ed3a4441..373de70baf08 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -636,12 +636,6 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
636 dma_cookie_t cookie; 636 dma_cookie_t cookie;
637 int ret; 637 int ret;
638 638
639 /* 1 stage FIFO watermarks for DMA */
640 sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1);
641
642 /* setup msiof transfer mode registers (32-bit words) */
643 sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4);
644
645 if (tx) { 639 if (tx) {
646 ier_bits |= IER_TDREQE | IER_TDMAE; 640 ier_bits |= IER_TDREQE | IER_TDMAE;
647 dma_sync_single_for_device(&p->pdev->dev, p->tx_dma_addr, len, 641 dma_sync_single_for_device(&p->pdev->dev, p->tx_dma_addr, len,
@@ -650,7 +644,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
650 p->tx_dma_addr, len, DMA_TO_DEVICE, 644 p->tx_dma_addr, len, DMA_TO_DEVICE,
651 DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 645 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
652 if (!desc_tx) 646 if (!desc_tx)
653 return -EIO; 647 return -EAGAIN;
654 } 648 }
655 649
656 if (rx) { 650 if (rx) {
@@ -659,8 +653,15 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
659 p->rx_dma_addr, len, DMA_FROM_DEVICE, 653 p->rx_dma_addr, len, DMA_FROM_DEVICE,
660 DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 654 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
661 if (!desc_rx) 655 if (!desc_rx)
662 return -EIO; 656 return -EAGAIN;
663 } 657 }
658
659 /* 1 stage FIFO watermarks for DMA */
660 sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1);
661
662 /* setup msiof transfer mode registers (32-bit words) */
663 sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4);
664
664 sh_msiof_write(p, IER, ier_bits); 665 sh_msiof_write(p, IER, ier_bits);
665 666
666 reinit_completion(&p->done); 667 reinit_completion(&p->done);
@@ -822,6 +823,12 @@ static int sh_msiof_transfer_one(struct spi_master *master,
822 copy32(p->tx_dma_page, tx_buf, l / 4); 823 copy32(p->tx_dma_page, tx_buf, l / 4);
823 824
824 ret = sh_msiof_dma_once(p, tx_buf, rx_buf, l); 825 ret = sh_msiof_dma_once(p, tx_buf, rx_buf, l);
826 if (ret == -EAGAIN) {
827 pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
828 dev_driver_string(&p->pdev->dev),
829 dev_name(&p->pdev->dev));
830 break;
831 }
825 if (ret) 832 if (ret)
826 return ret; 833 return ret;
827 834