aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorPaul Cercueil <paul@crapouillou.net>2021-12-20 19:08:40 +0000
committerUlf Hansson <ulf.hansson@linaro.org>2021-12-21 13:38:38 +0100
commita474e52c3109870946755925ce379d730a6dcaf7 (patch)
tree1047433931431f004bfc3c68c37da34002dc2c8a /drivers/mmc
parentdt-bindings: mmc: ingenic: Support using bi-directional DMA channel (diff)
downloadlinux-dev-a474e52c3109870946755925ce379d730a6dcaf7.tar.xz
linux-dev-a474e52c3109870946755925ce379d730a6dcaf7.zip
mmc: jz4740: Support using a bi-directional DMA channel
Since the MMC/SD controller in Ingenic SoCs work in half-duplex, it is possible to use one single DMA channel for both TX and RX operations, instead of using separate channels. As some older Ingenic SoCs offer only a handful of DMA channels, supporting bi-directional channels allow more hardware to use the channels that would otherwise be used for the MMC/SD operation. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Link: https://lore.kernel.org/r/20211220190840.108061-3-paul@crapouillou.net Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/jz4740_mmc.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 80a2c270d502..a0b94f61ddcf 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -217,11 +217,23 @@ static void jz4740_mmc_release_dma_channels(struct jz4740_mmc_host *host)
return;
dma_release_channel(host->dma_tx);
- dma_release_channel(host->dma_rx);
+ if (host->dma_rx)
+ dma_release_channel(host->dma_rx);
}
static int jz4740_mmc_acquire_dma_channels(struct jz4740_mmc_host *host)
{
+ struct device *dev = mmc_dev(host->mmc);
+
+ host->dma_tx = dma_request_chan(dev, "tx-rx");
+ if (!IS_ERR(host->dma_tx))
+ return 0;
+
+ if (PTR_ERR(host->dma_tx) != -ENODEV) {
+ dev_err(dev, "Failed to get dma tx-rx channel\n");
+ return PTR_ERR(host->dma_tx);
+ }
+
host->dma_tx = dma_request_chan(mmc_dev(host->mmc), "tx");
if (IS_ERR(host->dma_tx)) {
dev_err(mmc_dev(host->mmc), "Failed to get dma_tx channel\n");
@@ -241,7 +253,10 @@ static int jz4740_mmc_acquire_dma_channels(struct jz4740_mmc_host *host)
static inline struct dma_chan *jz4740_mmc_get_dma_chan(struct jz4740_mmc_host *host,
struct mmc_data *data)
{
- return (data->flags & MMC_DATA_READ) ? host->dma_rx : host->dma_tx;
+ if ((data->flags & MMC_DATA_READ) && host->dma_rx)
+ return host->dma_rx;
+ else
+ return host->dma_tx;
}
static void jz4740_mmc_dma_unmap(struct jz4740_mmc_host *host,