summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2013-04-12 17:25:07 -0700
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-15 17:10:59 +0100
commitddc5cdf161bce3d5191e7e8b84b7af5ad621a531 (patch)
treeaadb2b8dda6fb3d8712f8a405d79a972442275f8
parent788437273fa8b824810ea9a23f7ed4d7fdb2949a (diff)
downloadlinux-ddc5cdf161bce3d5191e7e8b84b7af5ad621a531.tar.bz2
spi: omap2-mcspi: Fix transfers if DMADEVICES is not set
Selecting CONFIG_DMADEVICES is optional, and we must be able to continue even without DMA. Otherwise things like omap4430sdp nfsroot will fail if DMA is not selected. Note that the driver already supports PIO mode, but we fail to fall back to PIO if requesting DMA channels fails. Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--drivers/spi/spi-omap2-mcspi.c32
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)) {