diff options
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 61eef47ae821..b3db4612b622 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -809,6 +809,10 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, return 0; } +/* + * Note that we currently allow DMA only if we get a channel + * for both rx and tx. Otherwise we'll do PIO for both rx and tx. + */ static int omap2_mcspi_request_dma(struct spi_device *spi) { struct spi_master *master = spi->master; @@ -827,21 +831,22 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) dma_cap_set(DMA_SLAVE, mask); sig = mcspi_dma->dma_rx_sync_dev; mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); - if (!mcspi_dma->dma_rx) { - dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n"); - return -EAGAIN; - } + if (!mcspi_dma->dma_rx) + goto no_dma; sig = mcspi_dma->dma_tx_sync_dev; mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); if (!mcspi_dma->dma_tx) { - dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n"); dma_release_channel(mcspi_dma->dma_rx); mcspi_dma->dma_rx = NULL; - return -EAGAIN; + goto no_dma; } return 0; + +no_dma: + dev_warn(&spi->dev, "not using DMA for McSPI\n"); + return -EAGAIN; } static int omap2_mcspi_setup(struct spi_device *spi) @@ -874,7 +879,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) { ret = omap2_mcspi_request_dma(spi); - if (ret < 0) + if (ret < 0 && ret != -EAGAIN) return ret; } @@ -932,6 +937,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) struct spi_device *spi; struct spi_transfer *t = NULL; struct spi_master *master; + struct omap2_mcspi_dma *mcspi_dma; int cs_active = 0; struct omap2_mcspi_cs *cs; struct omap2_mcspi_device_config *cd; @@ -941,6 +947,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) spi = m->spi; master = spi->master; + mcspi_dma = mcspi->dma_channels + spi->chip_select; cs = spi->controller_state; cd = spi->controller_data; @@ -997,7 +1004,8 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) __raw_writel(0, cs->base + OMAP2_MCSPI_TX0); - if (m->is_dma_mapped || t->len >= DMA_MIN_BYTES) + if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && + (m->is_dma_mapped || t->len >= DMA_MIN_BYTES)) count = omap2_mcspi_txrx_dma(spi, t); else count = omap2_mcspi_txrx_pio(spi, t); @@ -1044,10 +1052,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) static int omap2_mcspi_transfer_one_message(struct spi_master *master, struct spi_message *m) { + struct spi_device *spi; struct omap2_mcspi *mcspi; + struct omap2_mcspi_dma *mcspi_dma; struct spi_transfer *t; + spi = m->spi; mcspi = spi_master_get_devdata(master); + mcspi_dma = mcspi->dma_channels + spi->chip_select; m->actual_length = 0; m->status = 0; @@ -1082,7 +1094,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, if (m->is_dma_mapped || len < DMA_MIN_BYTES) continue; - if (tx_buf != NULL) { + if (mcspi_dma->dma_tx && tx_buf != NULL) { t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf, len, DMA_TO_DEVICE); if (dma_mapping_error(mcspi->dev, t->tx_dma)) { @@ -1091,7 +1103,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, return -EINVAL; } } - if (rx_buf != NULL) { + if (mcspi_dma->dma_rx && rx_buf != NULL) { t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len, DMA_FROM_DEVICE); if (dma_mapping_error(mcspi->dev, t->rx_dma)) { |