aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebastian.rasmussen@stericsson.com>2011-04-11 11:28:19 +0200
committerSebastian RASMUSSEN <sebastian.rasmussen@stericsson.com>2011-04-11 11:35:38 +0200
commit7d92304ec4e34ea7e0af90f8a9a4f33526f8ce0d (patch)
tree15c0fce84d456228b6bc82d3df9a0e9ec8908ca5 /drivers/mmc
parent88d075c19943f111df5464fb097a99b0cd06d0f8 (diff)
Revert "mmci: dma split adaptation: setup and preparation"
This reverts commit 104f06d9e3b4f6ad7ec55d5ee13c88a5299d5c2e. Change-Id: I5008f57728a340a14e481ba7add38753a1285c20 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/20572 Reviewed-by: Sebastian RASMUSSEN <sebastian.rasmussen@stericsson.com> Tested-by: Sebastian RASMUSSEN <sebastian.rasmussen@stericsson.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/mmci.c76
1 files changed, 47 insertions, 29 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 4114c17c25b..b0c53445c84 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -373,14 +373,14 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
* no custom DMA interfaces are supported.
*/
#ifdef CONFIG_DMA_ENGINE
-static int __devinit mmci_setup_dma(struct mmci_host *host)
+static void __devinit mmci_setup_dma(struct mmci_host *host)
{
struct mmci_platform_data *plat = host->plat;
dma_cap_mask_t mask;
if (!plat || !plat->dma_filter) {
dev_err(mmc_dev(host->mmc), "no DMA platform data!\n");
- return -EINVAL;
+ return;
}
/* Try to acquire a generic DMA engine slave channel */
@@ -397,7 +397,7 @@ static int __devinit mmci_setup_dma(struct mmci_host *host)
/* E.g if no DMA hardware is present */
if (!host->dma_rx_channel) {
dev_err(mmc_dev(host->mmc), "no RX DMA channel!\n");
- return -EINVAL;
+ return;
}
if (plat->dma_tx_param) {
host->dma_tx_channel = dma_request_channel(mask,
@@ -406,7 +406,7 @@ static int __devinit mmci_setup_dma(struct mmci_host *host)
if (!host->dma_tx_channel) {
dma_release_channel(host->dma_rx_channel);
host->dma_rx_channel = NULL;
- return -EINVAL;
+ return;
}
} else {
host->dma_tx_channel = host->dma_rx_channel;
@@ -415,8 +415,19 @@ static int __devinit mmci_setup_dma(struct mmci_host *host)
dev_info(mmc_dev(host->mmc), "use DMA channels DMA RX %s, DMA TX %s\n",
dma_chan_name(host->dma_rx_channel),
dma_chan_name(host->dma_tx_channel));
+}
- return 0;
+/*
+ * This is used in __devinit or __devexit so inline it
+ * so it can be discarded.
+ */
+static inline void mmci_disable_dma(struct mmci_host *host)
+{
+ if (host->dma_rx_channel)
+ dma_release_channel(host->dma_rx_channel);
+ if (host->dma_tx_channel)
+ dma_release_channel(host->dma_tx_channel);
+ host->dma_enable = false;
}
static void mmci_dma_data_end(struct mmci_host *host)
@@ -470,37 +481,37 @@ static void mmci_dma_callback(void *arg)
spin_unlock_irqrestore(&host->lock, flags);
}
-static inline int mmci_prepare_dma(struct mmci_host *host,
- struct mmc_data *data)
+static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
{
struct variant_data *variant = host->variant;
- int burst_sz = variant->fifohalfsize >> 2; /* # of words */
struct dma_slave_config rx_conf = {
.src_addr = host->phybase + MMCIFIFO,
.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
.direction = DMA_FROM_DEVICE,
- .src_maxburst = burst_sz,
+ .src_maxburst = variant->fifohalfsize >> 2, /* # of words */
};
struct dma_slave_config tx_conf = {
.dst_addr = host->phybase + MMCIFIFO,
.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
.direction = DMA_TO_DEVICE,
- .dst_maxburst = burst_sz,
+ .dst_maxburst = variant->fifohalfsize >> 2, /* # of words */
};
+ struct mmc_data *data = host->data;
enum dma_data_direction direction;
struct dma_chan *chan;
struct dma_async_tx_descriptor *desc;
struct scatterlist *sg;
dma_cookie_t cookie;
int i;
+ unsigned int irqmask0;
int sg_len;
/* If less than or equal to the fifo size, don't bother with DMA */
if (host->size <= variant->fifosize)
return -EINVAL;
- host->mmci_datactrl |= MCI_DPSM_DMAENABLE;
- host->mmci_datactrl |= variant->dmareg_enable;
+ datactrl |= MCI_DPSM_DMAENABLE;
+ datactrl |= variant->dmareg_enable;
if (data->flags & MMC_DATA_READ) {
if (host->size <= variant->txsize_threshold)
@@ -523,8 +534,8 @@ static inline int mmci_prepare_dma(struct mmci_host *host,
/* Check for weird stuff in the sg list */
for_each_sg(data->sg, sg, data->sg_len, i) {
dev_vdbg(mmc_dev(host->mmc),
- "[%s] MMCI SGlist %d dir %d: length: %08x\n",
- __func__, i, direction, sg->length);
+ "MMCI SGlist %d dir %d: length: %08x\n",
+ i, direction, sg->length);
if (sg->offset & 3 || sg->length & 3)
return -EINVAL;
}
@@ -543,18 +554,30 @@ static inline int mmci_prepare_dma(struct mmci_host *host,
desc->callback = mmci_dma_callback;
desc->callback_param = host;
host->dma_desc = desc;
+ dev_vdbg(mmc_dev(host->mmc), "Submit MMCI DMA job, sglen %d "
+ "blksz %04x blks %04x flags %08x\n",
+ data->sg_len, data->blksz, data->blocks, data->flags);
cookie = desc->tx_submit(desc);
/* Here overloaded DMA controllers may fail */
if (dma_submit_error(cookie))
goto unmap_exit;
+ host->dma_on_current_xfer = true;
chan->device->device_issue_pending(chan);
- host->mmci_mask0 |= MCI_DATAENDMASK;
+ /*
+ * MMCI monitors both MCI_DATAEND and the DMA callback.
+ * Both events must occur before the transfer is considered
+ * to be completed. MCI_DATABLOCKEND is not used in DMA mode.
+ */
+ host->last_blockend = true;
+ irqmask0 = readl(host->base + MMCIMASK0);
+ irqmask0 &= ~MCI_DATABLOCKENDMASK;
+ writel(irqmask0, host->base + MMCIMASK0);
- dev_dbg(mmc_dev(host->mmc), "[%s] config dma transfert: len:%d\n",
- __func__, host->mmci_datalenght);
+ /* Trigger the DMA transfer */
+ writel(datactrl, host->base + MMCIDATACTRL);
return 0;
unmap_exit:
@@ -565,16 +588,14 @@ map_err:
}
#else
/* Blank functions if the DMA engine is not available */
-static inline int mmci_setup_dma(struct mmci_host *host)
+static inline void mmci_setup_dma(struct mmci_host *host)
{
- return -1;
}
-static inline int mmci_prepare_dma(struct mmci_host *host,
- struct mmc_data *data)
+static inline void mmci_disable_dma(struct mmci_host *host)
{
- return -1;
}
+
static inline void mmci_dma_data_end(struct mmci_host *host)
{
}
@@ -582,16 +603,13 @@ static inline void mmci_dma_data_end(struct mmci_host *host)
static inline void mmci_dma_terminate(struct mmci_host *host)
{
}
-#endif
-static inline void mmci_disable_dma(struct mmci_host *host)
+static inline int mmci_dma_start_data(struct mmci_host *host,
+ unsigned int datactrl)
{
- if (host->dma_rx_channel)
- dma_release_channel(host->dma_rx_channel);
- if (host->dma_tx_channel)
- dma_release_channel(host->dma_tx_channel);
- host->dma_enable = false;
+ return -ENOSYS;
}
+#endif
static void
mmci_data_irq(struct mmci_host *host, struct mmc_data *data,