Surprisingly small amount of work was required in order to extend already
existing eDMA driver with the support for Kinetis SoC architecture.

Signed-off-by: Paul Osmialowski <paw...@king.net.pl>
---
 Documentation/devicetree/bindings/dma/fsl-edma.txt |  38 ++++++-
 drivers/dma/fsl-edma.c                             | 114 ++++++++++++++++-----
 2 files changed, 125 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/fsl-edma.txt 
b/Documentation/devicetree/bindings/dma/fsl-edma.txt
index 191d7bd..88c3e20 100644
--- a/Documentation/devicetree/bindings/dma/fsl-edma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-edma.txt
@@ -9,6 +9,7 @@ group, DMAMUX0 or DMAMUX1, but not both.
 Required properties:
 - compatible :
        - "fsl,vf610-edma" for eDMA used similar to that on Vybrid vf610 SoC
+       - "fsl,kinetis-edma" for eDMA used similar to that on Kinetis SoC
 - reg : Specifies base physical address(s) and size of the eDMA registers.
        The 1st region is eDMA control register's address and size.
        The 2nd and the 3rd regions are programmable channel multiplexing
@@ -16,7 +17,8 @@ Required properties:
 - interrupts : A list of interrupt-specifiers, one for each entry in
        interrupt-names.
 - interrupt-names : Should contain:
-       "edma-tx" - the transmission interrupt
+       "edma-tx" - the transmission interrupt (Vybrid)
+       "edma-tx-n,m" - interrupt for channels n (0-15) and m (16-31) (Kinetis)
        "edma-err" - the error interrupt
 - #dma-cells : Must be <2>.
        The 1st cell specifies the DMAMUX(0 for DMAMUX0 and 1 for DMAMUX1).
@@ -28,6 +30,7 @@ Required properties:
 - clock-names : A list of channel group clock names. Should contain:
        "dmamux0" - clock name of mux0 group
        "dmamux1" - clock name of mux1 group
+       "edma"    - clock gate for whole controller (Kinetis only)
 - clocks : A list of phandle and clock-specifier pairs, one for each entry in
        clock-names.
 
@@ -54,6 +57,39 @@ edma0: dma-controller@40018000 {
                <&clks VF610_CLK_DMAMUX1>;
 };
 
+edma: dma-controller@40008000 {
+       compatible = "fsl,kinetis-edma";
+       reg = <0x40008000 0x2000>, /* DMAC */
+               <0x40021000 0x1000>, /* DMAMUX0 */
+               <0x40022000 0x1000>; /* DMAMUX1 */
+       #dma-cells = <2>;
+       dma-channels = <32>;
+       interrupts =     <0>,  <1>,  <2>,  <3>,
+                        <4>,  <5>,  <6>,  <7>,
+                        <8>,  <9>, <10>, <11>,
+                       <12>, <13>, <14>, <15>,
+                       <16>;
+       interrupt-names = "edma-tx-0,16",
+                         "edma-tx-1,17",
+                         "edma-tx-2,18",
+                         "edma-tx-3,19",
+                         "edma-tx-4,20",
+                         "edma-tx-5,21",
+                         "edma-tx-6,22",
+                         "edma-tx-7,23",
+                         "edma-tx-8,24",
+                         "edma-tx-9,25",
+                         "edma-tx-10,26",
+                         "edma-tx-11,27",
+                         "edma-tx-12,28",
+                         "edma-tx-13,29",
+                         "edma-tx-14,30",
+                         "edma-tx-15,31",
+                         "edma-err";
+       clocks = <&mcg_cclk_gate 6 1>,
+                <&mcg_pclk_gate 5 1>, <&mcg_pclk_gate 5 2>;
+       clock-names = "edma", "dmamux0", "dmamux1";
+};
 
 * DMA clients
 DMA client drivers that uses the DMA function must use the format described
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 915eec3..e41a3b9 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -164,13 +164,13 @@ struct fsl_edma_desc {
 struct fsl_edma_engine {
        struct dma_device       dma_dev;
        void __iomem            *membase;
+       struct clk              *clk;
        void __iomem            *muxbase[DMAMUX_NR];
        struct clk              *muxclk[DMAMUX_NR];
        struct mutex            fsl_edma_mutex;
        u32                     n_chans;
-       int                     txirq;
-       int                     errirq;
        bool                    big_endian;
+       bool                    kinetis;
        struct fsl_edma_chan    chans[];
 };
 
@@ -788,42 +788,85 @@ static void fsl_edma_free_chan_resources(struct dma_chan 
*chan)
 }
 
 static int
-fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine 
*fsl_edma)
+fsl_edma_irq_init(struct platform_device *pdev,
+                 struct fsl_edma_engine *fsl_edma)
 {
+       struct device_node *np = pdev->dev.of_node;
+       int irq, errirq;
        int ret;
 
-       fsl_edma->txirq = platform_get_irq_byname(pdev, "edma-tx");
-       if (fsl_edma->txirq < 0) {
-               dev_err(&pdev->dev, "Can't get edma-tx irq.\n");
-               return fsl_edma->txirq;
-       }
-
-       fsl_edma->errirq = platform_get_irq_byname(pdev, "edma-err");
-       if (fsl_edma->errirq < 0) {
+       errirq = platform_get_irq_byname(pdev, "edma-err");
+       if (errirq < 0) {
                dev_err(&pdev->dev, "Can't get edma-err irq.\n");
-               return fsl_edma->errirq;
+               return irq;
        }
 
-       if (fsl_edma->txirq == fsl_edma->errirq) {
-               ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
-                               fsl_edma_irq_handler, 0, "eDMA", fsl_edma);
-               if (ret) {
-                       dev_err(&pdev->dev, "Can't register eDMA IRQ.\n");
-                        return  ret;
+       if (fsl_edma->kinetis) {
+               int i;
+               int irqs = of_irq_count(np);
+
+               if (irqs <= 1) {
+                       dev_err(&pdev->dev, "Wrong eDMA irq count %d\n", irqs);
+                       return -EINVAL;
                }
-       } else {
-               ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
+
+               for (i = 0; i < (irqs - 1); i++) {
+                       char irq_name[32];
+
+                       sprintf(irq_name, "edma-tx-%d,%d", i, 16 + i);
+                       irq = platform_get_irq_byname(pdev, irq_name);
+                       if (irq < 0) {
+                               dev_err(&pdev->dev, "Can't get %s irq.\n",
+                                                       irq_name);
+                               return irq;
+                       }
+
+                       ret = devm_request_irq(&pdev->dev, irq,
                                fsl_edma_tx_handler, 0, "eDMA tx", fsl_edma);
-               if (ret) {
-                       dev_err(&pdev->dev, "Can't register eDMA tx IRQ.\n");
-                       return  ret;
+                       if (ret) {
+                               dev_err(&pdev->dev, "Can't register %s IRQ.\n",
+                                                       irq_name);
+                               return  ret;
+                       }
                }
 
-               ret = devm_request_irq(&pdev->dev, fsl_edma->errirq,
-                               fsl_edma_err_handler, 0, "eDMA err", fsl_edma);
+               ret = devm_request_irq(&pdev->dev, errirq,
+                       fsl_edma_err_handler, 0, "eDMA err", fsl_edma);
                if (ret) {
                        dev_err(&pdev->dev, "Can't register eDMA err IRQ.\n");
-                       return  ret;
+               return  ret;
+               }
+       } else {
+               irq = platform_get_irq_byname(pdev, "edma-tx");
+               if (irq < 0) {
+                       dev_err(&pdev->dev, "Can't get edma-tx irq.\n");
+                       return irq;
+               }
+
+               if (irq == errirq) {
+                       ret = devm_request_irq(&pdev->dev, irq,
+                               fsl_edma_irq_handler, 0, "eDMA", fsl_edma);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                               "Can't register eDMA IRQ.\n");
+                               return  ret;
+                       }
+               } else {
+                       ret = devm_request_irq(&pdev->dev, irq,
+                               fsl_edma_tx_handler, 0, "eDMA tx", fsl_edma);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                           "Can't register eDMA tx IRQ.\n");
+                               return  ret;
+                       }
+
+                       ret = devm_request_irq(&pdev->dev, errirq,
+                               fsl_edma_err_handler, 0, "eDMA err", fsl_edma);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                           "Can't register eDMA err IRQ.\n");
+                               return  ret;
+                       }
                }
        }
 
@@ -851,6 +894,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        fsl_edma->n_chans = chans;
+       fsl_edma->kinetis = of_device_is_compatible(np, "fsl,kinetis-edma");
        mutex_init(&fsl_edma->fsl_edma_mutex);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -858,6 +902,20 @@ static int fsl_edma_probe(struct platform_device *pdev)
        if (IS_ERR(fsl_edma->membase))
                return PTR_ERR(fsl_edma->membase);
 
+       if (fsl_edma->kinetis) {
+               fsl_edma->clk = devm_clk_get(&pdev->dev, "edma");
+               if (IS_ERR(fsl_edma->clk)) {
+                       dev_err(&pdev->dev, "Missing EDMA clock.\n");
+                       return PTR_ERR(fsl_edma->clk);
+               }
+
+               ret = clk_prepare_enable(fsl_edma->clk);
+               if (ret) {
+                       dev_err(&pdev->dev, "EDMA clk failed.\n");
+                       return ret;
+               }
+       }
+
        for (i = 0; i < DMAMUX_NR; i++) {
                char clkname[32];
 
@@ -956,10 +1014,14 @@ static int fsl_edma_remove(struct platform_device *pdev)
        for (i = 0; i < DMAMUX_NR; i++)
                clk_disable_unprepare(fsl_edma->muxclk[i]);
 
+       if (fsl_edma->kinetis)
+               clk_disable_unprepare(fsl_edma->clk);
+
        return 0;
 }
 
 static const struct of_device_id fsl_edma_dt_ids[] = {
+       { .compatible = "fsl,kinetis-edma", },
        { .compatible = "fsl,vf610-edma", },
        { /* sentinel */ }
 };
-- 
2.3.6

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to