Some drivers might need to tweak the block size and wait cycles values
to get better performances.
Create and export the sun4i_dma_set_chan_config() to do that.

Signed-off-by: Boris Brezillon <[email protected]>
---
 drivers/dma/sun4i-dma.c       | 44 ++++++++++++++++++++++++++++++-------------
 include/linux/dma/sun4i-dma.h | 38 +++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 13 deletions(-)
 create mode 100644 include/linux/dma/sun4i-dma.h

diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c
index 1661d518..e48f537 100644
--- a/drivers/dma/sun4i-dma.c
+++ b/drivers/dma/sun4i-dma.c
@@ -12,6 +12,7 @@
 #include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/dmaengine.h>
+#include <linux/dma/sun4i-dma.h>
 #include <linux/dmapool.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -138,6 +139,7 @@ struct sun4i_dma_pchan {
 struct sun4i_dma_vchan {
        struct virt_dma_chan            vc;
        struct dma_slave_config         cfg;
+       struct sun4i_dma_chan_config    scfg;
        struct sun4i_dma_pchan          *pchan;
        struct sun4i_dma_promise        *processing;
        struct sun4i_dma_contract       *contract;
@@ -779,7 +781,7 @@ sun4i_dma_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
        u8 ram_type, io_mode, linear_mode;
        struct scatterlist *sg;
        dma_addr_t srcaddr, dstaddr;
-       u32 endpoints, para;
+       u32 endpoints;
        int i;
 
        if (!sgl)
@@ -825,17 +827,6 @@ sun4i_dma_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
                        dstaddr = sg_dma_address(sg);
                }
 
-               /*
-                * These are the magic DMA engine timings that keep SPI going.
-                * I haven't seen any interface on DMAEngine to configure
-                * timings, and so far they seem to work for everything we
-                * support, so I've kept them here. I don't know if other
-                * devices need different timings because, as usual, we only
-                * have the "para" bitfield meanings, but no comment on what
-                * the values should be when doing a certain operation :|
-                */
-               para = SUN4I_DDMA_MAGIC_SPI_PARAMETERS;
-
                /* And make a suitable promise */
                if (vchan->is_dedicated)
                        promise = generate_ddma_promise(chan, srcaddr, dstaddr,
@@ -850,7 +841,7 @@ sun4i_dma_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
                        return NULL; /* TODO: should we free everything? */
 
                promise->cfg |= endpoints;
-               promise->para = para;
+               promise->para = vchan->scfg.para;
 
                /* Then add it to the contract */
                list_add_tail(&promise->list, &contract->demands);
@@ -908,6 +899,21 @@ static int sun4i_dma_config(struct dma_chan *chan,
        return 0;
 }
 
+int sun4i_dma_set_chan_config(struct dma_chan *dchan,
+                             const struct sun4i_dma_chan_config *cfg)
+{
+       struct sun4i_dma_vchan *vchan = to_sun4i_dma_vchan(dchan);
+
+       if (!vchan->is_dedicated)
+               return -ENOTSUPP;
+
+       /* TODO: control cfg value */
+       vchan->scfg = *cfg;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(sun4i_dma_set_chan_config);
+
 static struct dma_chan *sun4i_dma_of_xlate(struct of_phandle_args *dma_spec,
                                           struct of_dma *ofdma)
 {
@@ -1206,6 +1212,18 @@ static int sun4i_dma_probe(struct platform_device *pdev)
                spin_lock_init(&vchan->vc.lock);
                vchan->vc.desc_free = sun4i_dma_free_contract;
                vchan_init(&vchan->vc, &priv->slave);
+
+               /*
+                * These are the magic DMA engine timings that keep SPI going.
+                * I haven't seen any interface on DMAEngine to configure
+                * timings, and so far they seem to work for everything we
+                * support, so I've kept them here. I don't know if other
+                * devices need different timings because, as usual, we only
+                * have the "para" bitfield meanings, but no comment on what
+                * the values should be when doing a certain operation :|
+                */
+               vchan->scfg.para = SUN4I_DDMA_MAGIC_SPI_PARAMETERS;
+
        }
 
        ret = clk_prepare_enable(priv->clk);
diff --git a/include/linux/dma/sun4i-dma.h b/include/linux/dma/sun4i-dma.h
new file mode 100644
index 0000000..f643539
--- /dev/null
+++ b/include/linux/dma/sun4i-dma.h
@@ -0,0 +1,38 @@
+/*
+ * Sun4i DMA Engine drivers support header file
+ *
+ * Copyright (C) 2016 Free Electrons. All rights reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _SUN4I_DMA_H
+#define _SUN4I_DMA_H
+
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+
+/* Dedicated DMA parameter register layout */
+#define SUN4I_DDMA_PARA_DST_DATA_BLK_SIZE(n)   (((n) - 1) << 24)
+#define SUN4I_DDMA_PARA_DST_WAIT_CYCLES(n)     (((n) - 1) << 16)
+#define SUN4I_DDMA_PARA_SRC_DATA_BLK_SIZE(n)   (((n) - 1) << 8)
+#define SUN4I_DDMA_PARA_SRC_WAIT_CYCLES(n)     (((n) - 1) << 0)
+
+/**
+ * struct sun4i_dma_chan_config - DMA channel config
+ *
+ * @para: contains information about block size and time before checking
+ *       DRQ line. This is device specific and only applicable to dedicated
+ *       DMA channels
+ */
+struct sun4i_dma_chan_config {
+       u32 para;
+};
+
+int sun4i_dma_set_chan_config(struct dma_chan *dchan,
+                             const struct sun4i_dma_chan_config *cfg);
+
+#endif /* _SUN4I_DMA_H */
-- 
2.1.4

Reply via email to