[PATCH 1/8] ARM i.MX dma: implement wrapper for dma functions

Sascha Hauer s.hauer at pengutronix.de
Mon Aug 9 05:05:36 EDT 2010


Currently there is only one i.MX DMA implementation in the tree,
the one for i.MX1/21/27. The SDMA support for i.MX25/31/35/51 can
be implemented similarly. This wrapper for the DMA is implemented
so that drivers do not have to care about the implementation
present and don't have to #ifdef DMA support

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/mach-imx/include/mach/dma-v1.h |    8 +--
 arch/arm/plat-mxc/Makefile              |    2 +-
 arch/arm/plat-mxc/dma.c                 |  112 +++++++++++++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/dma.h    |   92 +++++++++++++++++++++++++
 4 files changed, 207 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm/plat-mxc/dma.c
 create mode 100644 arch/arm/plat-mxc/include/mach/dma.h

diff --git a/arch/arm/mach-imx/include/mach/dma-v1.h b/arch/arm/mach-imx/include/mach/dma-v1.h
index 287431c..ac6fd71 100644
--- a/arch/arm/mach-imx/include/mach/dma-v1.h
+++ b/arch/arm/mach-imx/include/mach/dma-v1.h
@@ -27,6 +27,8 @@
 
 #define imx_has_dma_v1()	(cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
 
+#include <mach/dma.h>
+
 #define IMX_DMA_CHANNELS  16
 
 #define DMA_MODE_READ		0
@@ -96,12 +98,6 @@ int imx_dma_request(int channel, const char *name);
 
 void imx_dma_free(int channel);
 
-enum imx_dma_prio {
-	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 1,
-	DMA_PRIO_LOW = 2
-};
-
 int imx_dma_request_by_prio(const char *name, enum imx_dma_prio prio);
 
 #endif	/* __MACH_DMA_V1_H__ */
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 78d405e..ff9880c 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o
+obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o dma.o
 
 # MX51 uses the TZIC interrupt controller, older platforms use AVIC (irq.o)
 obj-$(CONFIG_MXC_TZIC) += tzic.o
diff --git a/arch/arm/plat-mxc/dma.c b/arch/arm/plat-mxc/dma.c
new file mode 100644
index 0000000..1a241ab
--- /dev/null
+++ b/arch/arm/plat-mxc/dma.c
@@ -0,0 +1,112 @@
+
+#include <mach/dma.h>
+
+static struct imx_dma_operations *imx_dma_ops;
+
+static DEFINE_MUTEX(dma_mutex);
+
+static int imxdma_check(int channel)
+{
+	if (!imx_dma_ops)
+		return -ENOSYS;
+	if (channel < 0 || channel >= imx_dma_ops->num_channels)
+		return -EINVAL;
+	return 0;
+}
+
+int imxdma_setup_single(int channel, dma_addr_t mem, int dma_length,
+		unsigned int dmamode)
+{
+	int ret;
+
+	ret = imxdma_check(channel);
+	if (ret)
+		return ret;
+
+	return imx_dma_ops->setup_single(channel, mem, dma_length, dmamode);
+}
+
+int imxdma_setup_sg(int channel, struct scatterlist *sg, unsigned int sgcount,
+			unsigned int dma_length, unsigned int dmamode)
+{
+	int ret;
+
+	ret = imxdma_check(channel);
+	if (ret)
+		return ret;
+
+	return imx_dma_ops->setup_sg(channel, sg, sgcount, dma_length, dmamode);
+}
+
+void imxdma_enable(int channel)
+{
+	int ret;
+
+	ret = imxdma_check(channel);
+	if (ret)
+		return;
+
+	imx_dma_ops->enable(channel);
+}
+
+void imxdma_disable(int channel)
+{
+	int ret;
+
+	ret = imxdma_check(channel);
+	if (ret)
+		return;
+
+	imx_dma_ops->disable(channel);
+}
+
+int imxdma_config(int channel, struct imx_dma_config *cfg)
+{
+	int ret;
+
+	ret = imxdma_check(channel);
+	if (ret)
+		return ret;
+
+	return imx_dma_ops->config_channel(channel, cfg);
+}
+
+int imxdma_request(enum imx_dma_prio prio)
+{
+	int ret;
+
+	if (!imx_dma_ops)
+		return -ENOSYS;
+
+	mutex_lock(&dma_mutex);
+
+	ret = imx_dma_ops->request(prio);
+
+	mutex_unlock(&dma_mutex);
+
+	return ret;
+}
+
+void imxdma_free(int channel)
+{
+	int ret;
+
+	ret = imxdma_check(channel);
+	if (ret)
+		return;
+
+	mutex_lock(&dma_mutex);
+
+	imx_dma_ops->free(channel);
+
+	mutex_unlock(&dma_mutex);
+}
+
+int imx_dma_ops_register(struct imx_dma_operations *ops)
+{
+	BUG_ON(imx_dma_ops);
+
+	imx_dma_ops = ops;
+
+	return 0;
+}
diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h
new file mode 100644
index 0000000..3ee9541
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/dma.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MXC_DMA_H__
+#define __ASM_ARCH_MXC_DMA_H__
+
+#include <linux/scatterlist.h>
+
+#define DMA_MODE_READ	0
+#define DMA_MODE_WRITE	1
+
+/*
+ * This enumerates peripheral types. Used for SDMA.
+ */
+typedef enum {
+	IMX_DMATYPE_SSI,	/* MCU domain SSI */
+	IMX_DMATYPE_SSI_SP,	/* Shared SSI */
+	IMX_DMATYPE_MMC,	/* MMC */
+	IMX_DMATYPE_SDHC,	/* SDHC */
+	IMX_DMATYPE_UART,	/* MCU domain UART */
+	IMX_DMATYPE_UART_SP,	/* Shared UART */
+	IMX_DMATYPE_FIRI,	/* FIRI */
+	IMX_DMATYPE_CSPI,	/* MCU domain CSPI */
+	IMX_DMATYPE_CSPI_SP,	/* Shared CSPI */
+	IMX_DMATYPE_SIM,	/* SIM */
+	IMX_DMATYPE_ATA,	/* ATA */
+	IMX_DMATYPE_CCM,	/* CCM */
+	IMX_DMATYPE_EXT,	/* External peripheral */
+	IMX_DMATYPE_MSHC,	/* Memory Stick Host Controller */
+	IMX_DMATYPE_MSHC_SP,	/* Shared Memory Stick Host Controller */
+	IMX_DMATYPE_DSP,	/* DSP */
+	IMX_DMATYPE_MEMORY,	/* Memory */
+	IMX_DMATYPE_FIFO_MEMORY,/* FIFO type Memory */
+	IMX_DMATYPE_SPDIF,	/* SPDIF */
+	IMX_DMATYPE_IPU_MEMORY,	/* IPU Memory */
+	IMX_DMATYPE_ASRC,	/* ASRC */
+	IMX_DMATYPE_ESAI,	/* ESAI */
+} sdma_peripheral_type;
+
+struct imx_dma_config {
+	int burstlen; /* number of words (*not* bytes) to transfer during
+		       * a single burst
+		       */
+	dma_addr_t dma_address; /* the physical address of the peripheral */
+	int word_size; /* FIFO width of the peripheral in bytes */
+	int peripheral_type; /* Needed for SDMA */
+	int dma_request; /* DMA request line */
+	/* completion callback */
+	void (*completion_handler) (int channel, void *data, int error);
+	void *driver_data; /* passed to handler above */
+#define IMX_DMA_SG_LOOP		(1 << 0)
+	unsigned long flags;
+};
+
+enum imx_dma_prio {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
+};
+
+int imxdma_request(enum imx_dma_prio);
+void imxdma_free(int channel);
+int imxdma_setup_single(int channel, dma_addr_t mem, int dma_length,
+		unsigned int dmamode);
+int imxdma_setup_sg(int channel, struct scatterlist *sg, unsigned int sgcount,
+			unsigned int dma_length, unsigned int dmamode);
+void imxdma_enable(int channel);
+void imxdma_disable(int channel);
+int imxdma_config(int channel, struct imx_dma_config *cfg);
+
+struct imx_dma_operations {
+	int (*config_channel)(int channel, struct imx_dma_config *cfg);
+	int (*setup_single)(int channel, dma_addr_t mem, int dma_length,
+		unsigned int dmamode);
+	int (*setup_sg)(int channel, struct scatterlist *sg,
+			unsigned int sgcount, unsigned int dma_length,
+			unsigned int dmamode);
+	void (*enable)(int channel);
+	void (*disable)(int channel);
+	int (*request)(enum imx_dma_prio);
+	void (*free)(int channel);
+	int num_channels;
+};
+
+int imx_dma_ops_register(struct imx_dma_operations *ops);
+
+#endif
-- 
1.7.1




More information about the linux-arm-kernel mailing list