mmc: jz4740: Support using a bi-directional DMA channel
authorPaul Cercueil <paul@crapouillou.net>
Mon, 20 Dec 2021 19:08:40 +0000 (19:08 +0000)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 21 Dec 2021 12:38:38 +0000 (13:38 +0100)
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>
drivers/mmc/host/jz4740_mmc.c

index 80a2c27..a0b94f6 100644 (file)
@@ -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,