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 61eef47ae82..b3db4612b62 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)) {  |