dmaengine: fsl-edma: add i.MX8ULP edma support
authorJoy Zou <joy.zou@nxp.com>
Sat, 23 Mar 2024 15:34:54 +0000 (11:34 -0400)
committerVinod Koul <vkoul@kernel.org>
Sun, 7 Apr 2024 11:50:00 +0000 (17:20 +0530)
Add support for the i.MX8ULP platform to the eDMA driver. Introduce the use
of the correct FSL_EDMA_DRV_HAS_CHCLK flag to handle per-channel clock
configurations.

Signed-off-by: Joy Zou <joy.zou@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20240323-8ulp_edma-v3-5-c0e981027c05@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/fsl-edma-common.c
drivers/dma/fsl-edma-common.h
drivers/dma/fsl-edma-main.c

index b18faa7cfedb9b60361aaebba82585767a270935..f9144b015439647b4b780c6b5cc848b4f5b84f2d 100644 (file)
@@ -3,6 +3,7 @@
 // Copyright (c) 2013-2014 Freescale Semiconductor, Inc
 // Copyright (c) 2017 Sysam, Angelo Dureghello  <angelo@sysam.it>
 
+#include <linux/clk.h>
 #include <linux/dmapool.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -810,6 +811,9 @@ int fsl_edma_alloc_chan_resources(struct dma_chan *chan)
 {
        struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
 
+       if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK)
+               clk_prepare_enable(fsl_chan->clk);
+
        fsl_chan->tcd_pool = dma_pool_create("tcd_pool", chan->device->dev,
                                fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_TCD64 ?
                                sizeof(struct fsl_edma_hw_tcd64) : sizeof(struct fsl_edma_hw_tcd),
@@ -838,6 +842,8 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
        fsl_chan->tcd_pool = NULL;
        fsl_chan->is_sw = false;
        fsl_chan->srcid = 0;
+       if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK)
+               clk_disable_unprepare(fsl_chan->clk);
 }
 
 void fsl_edma_cleanup_vchan(struct dma_device *dmadev)
index 532f647e540e7a5064d522964f5ff1556e92ea87..01157912bfd5f6f31d2beca0f2e43462f1c91ec8 100644 (file)
@@ -192,6 +192,7 @@ struct fsl_edma_desc {
 #define FSL_EDMA_DRV_WRAP_IO           BIT(3)
 #define FSL_EDMA_DRV_EDMA64            BIT(4)
 #define FSL_EDMA_DRV_HAS_PD            BIT(5)
+#define FSL_EDMA_DRV_HAS_CHCLK         BIT(6)
 #define FSL_EDMA_DRV_HAS_CHMUX         BIT(7)
 /* imx8 QM audio edma remote local swapped */
 #define FSL_EDMA_DRV_QUIRK_SWAPPED     BIT(8)
index 41c71c360ff1fb6df133811585d8bcdb9ff2d44d..755a3dc3b0a78a47875570079b015a6f792e5a08 100644 (file)
@@ -356,6 +356,16 @@ static struct fsl_edma_drvdata imx8qm_audio_data = {
        .setup_irq = fsl_edma3_irq_init,
 };
 
+static struct fsl_edma_drvdata imx8ulp_data = {
+       .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_CHCLK | FSL_EDMA_DRV_HAS_DMACLK |
+                FSL_EDMA_DRV_EDMA3,
+       .chreg_space_sz = 0x10000,
+       .chreg_off = 0x10000,
+       .mux_off = 0x10000 + offsetof(struct fsl_edma3_ch_reg, ch_mux),
+       .mux_skip = 0x10000,
+       .setup_irq = fsl_edma3_irq_init,
+};
+
 static struct fsl_edma_drvdata imx93_data3 = {
        .flags = FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3,
        .chreg_space_sz = 0x10000,
@@ -388,6 +398,7 @@ static const struct of_device_id fsl_edma_dt_ids[] = {
        { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data},
        { .compatible = "fsl,imx8qm-edma", .data = &imx8qm_data},
        { .compatible = "fsl,imx8qm-adma", .data = &imx8qm_audio_data},
+       { .compatible = "fsl,imx8ulp-edma", .data = &imx8ulp_data},
        { .compatible = "fsl,imx93-edma3", .data = &imx93_data3},
        { .compatible = "fsl,imx93-edma4", .data = &imx93_data4},
        { .compatible = "fsl,imx95-edma5", .data = &imx95_data5},
@@ -441,6 +452,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
        struct fsl_edma_engine *fsl_edma;
        const struct fsl_edma_drvdata *drvdata = NULL;
        u32 chan_mask[2] = {0, 0};
+       char clk_name[36];
        struct edma_regs *regs;
        int chans;
        int ret, i;
@@ -550,11 +562,21 @@ static int fsl_edma_probe(struct platform_device *pdev)
                                + i * drvdata->chreg_space_sz + drvdata->chreg_off + len;
                fsl_chan->mux_addr = fsl_edma->membase + drvdata->mux_off + i * drvdata->mux_skip;
 
+               if (drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK) {
+                       snprintf(clk_name, sizeof(clk_name), "ch%02d", i);
+                       fsl_chan->clk = devm_clk_get_enabled(&pdev->dev,
+                                                            (const char *)clk_name);
+
+                       if (IS_ERR(fsl_chan->clk))
+                               return PTR_ERR(fsl_chan->clk);
+               }
                fsl_chan->pdev = pdev;
                vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
 
                edma_write_tcdreg(fsl_chan, cpu_to_le32(0), csr);
                fsl_edma_chan_mux(fsl_chan, 0, false);
+               if (fsl_chan->edma->drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK)
+                       clk_disable_unprepare(fsl_chan->clk);
        }
 
        ret = fsl_edma->drvdata->setup_irq(pdev, fsl_edma);