diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 16:38:41 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 16:38:41 -0700 | 
| commit | 61f3d0a9883d965b498edeb673235bddc92770fd (patch) | |
| tree | fa1e394cd1d5332f4a205d12f0db88320bc83813 /drivers/spi/spi-omap2-mcspi.c | |
| parent | 8ded8d4e4facab78acf616bc34085ddd15c2c21c (diff) | |
| parent | cd8d984f0def2a8c5733a9468634ec3e0feec03d (diff) | |
| download | olio-linux-3.10-61f3d0a9883d965b498edeb673235bddc92770fd.tar.xz olio-linux-3.10-61f3d0a9883d965b498edeb673235bddc92770fd.zip  | |
Merge tag 'spi-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
 "A fairly quiet release for SPI, mainly driver work.  A few highlights:
   - Supports bits per word compatibility checking in the core.
   - Allow use of the IP used in Freescale SPI controllers outside
     Freescale SoCs.
   - DMA support for the Atmel SPI driver.
   - New drivers for the BCM2835 and Tegra114"
* tag 'spi-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (68 commits)
  spi-topcliff-pch: fix to use list_for_each_entry_safe() when delete list items
  spi-topcliff-pch: missing platform_driver_unregister() on error in pch_spi_init()
  ARM: dts: add pinctrl property for spi node for atmel SoC
  ARM: dts: add spi nodes for the atmel boards
  ARM: dts: add spi nodes for atmel SoC
  ARM: at91: add clocks for spi dt entries
  spi/spi-atmel: add dmaengine support
  spi/spi-atmel: add flag to controller data for lock operations
  spi/spi-atmel: add physical base address
  spi/sirf: fix MODULE_DEVICE_TABLE
  MAINTAINERS: Add git repository and update my address
  spi/s3c64xx: Check for errors in dmaengine prepare_transfer()
  spi/s3c64xx: Fix non-dmaengine usage
  spi: omap2-mcspi: fix error return code in omap2_mcspi_probe()
  spi/s3c64xx: let device core setup the default pin configuration
  MAINTAINERS: Update Grant's email address and maintainership
  spi: omap2-mcspi: Fix transfers if DMADEVICES is not set
  spi: s3c64xx: move to generic dmaengine API
  spi-gpio: init CS before spi_bitbang_setup()
  spi: spi-mpc512x-psc: let transmiter/receiver enabled when in xfer loop
  ...
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
| -rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 43 | 
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 893c3d78e42..86d2158946b 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -285,8 +285,12 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)  	timeout = jiffies + msecs_to_jiffies(1000);  	while (!(__raw_readl(reg) & bit)) { -		if (time_after(jiffies, timeout)) -			return -1; +		if (time_after(jiffies, timeout)) { +			if (!(__raw_readl(reg) & bit)) +				return -ETIMEDOUT; +			else +				return 0; +		}  		cpu_relax();  	}  	return 0; @@ -805,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; @@ -823,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) @@ -870,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;  	} @@ -928,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; @@ -937,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; @@ -993,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); @@ -1040,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; @@ -1078,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)) { @@ -1087,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)) { @@ -1277,7 +1293,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)  	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);  	pm_runtime_enable(&pdev->dev); -	if (status || omap2_mcspi_master_setup(mcspi) < 0) +	status = omap2_mcspi_master_setup(mcspi); +	if (status < 0)  		goto disable_pm;  	status = spi_register_master(master);  |