Added basic clock support. The clocks are requested at probe
and released at remove.

Signed-off-by: Kedareswara rao Appana <appa...@xilinx.com>
---
 drivers/dma/xilinx/xilinx_vdma.c | 56 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index 70caea6..d526029 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -44,6 +44,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include "../dmaengine.h"
 
@@ -352,6 +353,8 @@ struct xilinx_dma_chan {
  * @flush_on_fsync: Flush on frame sync
  * @ext_addr: Indicates 64 bit addressing is supported by dma device
  * @dmatype: DMA ip type
+ * @clks:      pointer to array of clocks
+ * @numclks:   number of clocks available
  */
 struct xilinx_dma_device {
        void __iomem *regs;
@@ -362,6 +365,8 @@ struct xilinx_dma_device {
        u32 flush_on_fsync;
        bool ext_addr;
        enum xdma_ip_type dmatype;
+       struct clk **clks;
+       int numclks;
 };
 
 /* Macros */
@@ -1731,6 +1736,26 @@ int xilinx_vdma_channel_set_config(struct dma_chan 
*dchan,
 }
 EXPORT_SYMBOL(xilinx_vdma_channel_set_config);
 
+static int xdma_clk_init(struct xilinx_dma_device *xdev, bool enable)
+{
+       int i = 0, ret;
+
+       for (i = 0; i < xdev->numclks; i++) {
+               if (enable) {
+                       ret = clk_prepare_enable(xdev->clks[i]);
+                       if (ret) {
+                               dev_err(xdev->dev,
+                                       "failed to enable the axidma clock\n");
+                               return ret;
+                       }
+               } else {
+                       clk_disable_unprepare(xdev->clks[i]);
+               }
+       }
+
+       return 0;
+}
+
 /* 
-----------------------------------------------------------------------------
  * Probe and remove
  */
@@ -1919,6 +1944,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
        struct resource *io;
        u32 num_frames, addr_width;
        int i, err;
+       const char *str;
 
        /* Allocate and initialize the DMA engine structure */
        xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
@@ -1965,6 +1991,32 @@ static int xilinx_dma_probe(struct platform_device *pdev)
        /* Set the dma mask bits */
        dma_set_mask(xdev->dev, DMA_BIT_MASK(addr_width));
 
+       xdev->numclks = of_property_count_strings(pdev->dev.of_node,
+                                                 "clock-names");
+       if (xdev->numclks > 0) {
+               xdev->clks = devm_kmalloc_array(&pdev->dev, xdev->numclks,
+                                               sizeof(struct clk *),
+                                               GFP_KERNEL);
+               if (!xdev->clks)
+                       return -ENOMEM;
+
+               for (i = 0; i < xdev->numclks; i++) {
+                       of_property_read_string_index(pdev->dev.of_node,
+                                                     "clock-names", i, &str);
+                       xdev->clks[i] = devm_clk_get(xdev->dev, str);
+                       if (IS_ERR(xdev->clks[i])) {
+                               if (PTR_ERR(xdev->clks[i]) == -ENOENT)
+                                       xdev->clks[i] = NULL;
+                               else
+                                       return PTR_ERR(xdev->clks[i]);
+                       }
+               }
+
+               err = xdma_clk_init(xdev, true);
+               if (err)
+                       return err;
+       }
+
        /* Initialize the DMA engine */
        xdev->common.dev = &pdev->dev;
 
@@ -2025,6 +2077,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
        return 0;
 
 error:
+       if (xdev->numclks > 0)
+               xdma_clk_init(xdev, false);
        for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
                if (xdev->chan[i])
                        xilinx_dma_chan_remove(xdev->chan[i]);
@@ -2050,6 +2104,8 @@ static int xilinx_dma_remove(struct platform_device *pdev)
        for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
                if (xdev->chan[i])
                        xilinx_dma_chan_remove(xdev->chan[i]);
+       if (xdev->numclks > 0)
+               xdma_clk_init(xdev, false);
 
        return 0;
 }
-- 
2.1.2

Reply via email to