[PATCH] dma: sun4i: expose block size and wait cycle configuration to DMA users

Boris Brezillon boris.brezillon at free-electrons.com
Mon Mar 7 01:59:31 PST 2016


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 <boris.brezillon at free-electrons.com>
---
 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




More information about the linux-arm-kernel mailing list