Commit a474e52c authored by Paul Cercueil's avatar Paul Cercueil Committed by Ulf Hansson

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: default avatarPaul Cercueil <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20211220190840.108061-3-paul@crapouillou.netSigned-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 34ce2930
...@@ -217,11 +217,23 @@ static void jz4740_mmc_release_dma_channels(struct jz4740_mmc_host *host) ...@@ -217,11 +217,23 @@ static void jz4740_mmc_release_dma_channels(struct jz4740_mmc_host *host)
return; return;
dma_release_channel(host->dma_tx); dma_release_channel(host->dma_tx);
if (host->dma_rx)
dma_release_channel(host->dma_rx); dma_release_channel(host->dma_rx);
} }
static int jz4740_mmc_acquire_dma_channels(struct jz4740_mmc_host *host) 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"); host->dma_tx = dma_request_chan(mmc_dev(host->mmc), "tx");
if (IS_ERR(host->dma_tx)) { if (IS_ERR(host->dma_tx)) {
dev_err(mmc_dev(host->mmc), "Failed to get dma_tx channel\n"); 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) ...@@ -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, static inline struct dma_chan *jz4740_mmc_get_dma_chan(struct jz4740_mmc_host *host,
struct mmc_data *data) 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, static void jz4740_mmc_dma_unmap(struct jz4740_mmc_host *host,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment