Skip to contentSkip to conversation

SDMA support for i.MX

RFC In review Sascha Hauer 9 participants 25 messages Aug 9, 2010 – Aug 10, 2010

Subsystems (6)
lore
Share & tools
lore

Sascha Hauer

author maintainer
#0 lore raw

Hi all,

Ever wondered what's hidden behind the tons of SDMA/iapi stuff in the Freescale kernel? It's a nice and convenient to use DMA engine. The following patches add support for it.

First of all a wrapper for the current i.MX DMA support is implemented to allow the drivers to compile in DMA support without ifdefs. Then the SDMA support itself is implemented and users are switched to support the new DMA API.

The SDMA engine needs additional firmware support. Since fsl does not use the standard request_firmware mechanism but compiles in the firmware as static arrays, I had to invent a firmware layout. You can get the program for generating the firmware images from the static arrays here:

git://git.pengutronix.de/git/imx/sdma-firmware.git

As the layout of the firmware is not given by fsl but by me it should be part of the review.

The SDMA code has currently been tested on i.MX31/35 with sound and on i.MX31 with SD/MMC. i.MX25/51 are untested, but should work aswell.

Sascha

The following changes since commit fc1caf6eafb30ea185720e29f7f5eccca61ecd60:

Merge branch 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6 (2010-08-05 16:02:01 -0700)

are available in the git repository at:

git://git.pengutronix.de/git/imx/linux-2.6.git sdma

Sascha Hauer (8):
ARM i.MX dma: implement wrapper for dma functions ARM i.MX dma-mx1-mx2: use wrapper
mxcmmc: use new dma api
ARM i.MX: add SDMA driver
ARM i.MX3: Add sdma device
ARM i.MX3: add dma request defines
ARM i.MX3: add dma request resources to ssi/sdhc devices ASoC i.MX: switch to new DMA api

 arch/arm/mach-imx/dma-v1.c                   |  142 +++-
 arch/arm/mach-imx/include/mach/dma-mx1-mx2.h |    2 +-
 arch/arm/mach-imx/include/mach/dma-v1.h      |    8 +-
 arch/arm/mach-mx3/Kconfig                    |    2 +
 arch/arm/mach-mx3/clock-imx31.c              |    4 +-
 arch/arm/mach-mx3/clock-imx35.c              |    2 +-
 arch/arm/mach-mx3/devices.c                  |   80 ++
 arch/arm/plat-mxc/Kconfig                    |   10 +
 arch/arm/plat-mxc/Makefile                   |    3 +-
 arch/arm/plat-mxc/dma.c                      |  112 +++
 arch/arm/plat-mxc/include/mach/dma.h         |   92 ++
 arch/arm/plat-mxc/include/mach/mx31.h        |   14 +
 arch/arm/plat-mxc/include/mach/mx35.h        |   26 +
 arch/arm/plat-mxc/include/mach/mx3x.h        |   29 +
 arch/arm/plat-mxc/include/mach/sdma.h        |    8 +
 arch/arm/plat-mxc/sdma.c                     | 1181 ++++++++++++++++++++++++++
 drivers/mmc/host/mxcmmc.c                    |  129 ++--
 sound/soc/imx/Makefile                       |    2 -
 sound/soc/imx/imx-pcm-dma-mx2.c              |  177 ++---
 sound/soc/imx/imx-ssi.c                      |    8 +-
 20 files changed, 1826 insertions(+), 205 deletions(-)
 create mode 100644 arch/arm/plat-mxc/dma.c
 create mode 100644 arch/arm/plat-mxc/include/mach/dma.h
 create mode 100644 arch/arm/plat-mxc/include/mach/sdma.h
 create mode 100644 arch/arm/plat-mxc/sdma.c
author maintainer
#1 lore raw

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

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

---
 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
arch/arm/mach-imx/include/mach/dma-v1.h +2 -6
index 287431c..ac6fd71 100644
@@ -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__ */
arch/arm/plat-mxc/Makefile +1 -1
index 78d405e..ff9880c 100644
@@ -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
arch/arm/plat-mxc/dma.c new file +112 -0

112 lines not on this page · raw message

arch/arm/plat-mxc/include/mach/dma.h new file +92 -0

92 lines not on this page · raw message

Signature · 1 line
1.7.1
#2 lore raw

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

Hi Sascha,

Quoted 14 lines · Sascha Hauer

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

arch/arm/plat-mxc/dma.c new file +0 -0
new file mode 100644
index 0000000..1a241ab

arch/arm/plat-mxc/dma.c line 1

Quoted 1 line
arch/arm/plat-mxc/dma.c new file +1 -0
@@ -0,0 +1,112 @@
+

Remember to add Copyright+License information here!

arch/arm/plat-mxc/dma.c line 7

Quoted 6 lines
arch/arm/plat-mxc/dma.c new file +6 -0
+#include <mach/dma.h>
+
+static struct imx_dma_operations *imx_dma_ops;
+
+static DEFINE_MUTEX(dma_mutex);
+

Regards, Magnus

#3 lore raw

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

In reply to Sascha Hauer

2010/8/9 Sascha Hauer <[email protected]>:

Quoted 11 lines

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

(...)

(quoted diff) +3 -0
+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,

Review

Quoted 10 lines
(quoted diff) +10 -0
+ ? ? ? ? ? ? ? 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;
+};

This is just getting *so* close to the drivers/dma dmaengine API.

We decided to use the damengine for all our DMA drivers and we haven't regretted one bit.

There has been some noise about too many drivers stacking up below arch/arm instead of going to the apropriate subsystem, can't you atleast contemplate using the dmaengine and help us improve that subsystem?

I sent some patches to Dan which essentially is a single-buffer (non-sglist) API, which is all I see missing to fit this need.

Yours,
Linus Walleij

author maintainer
#4 lore raw

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

Hi Linus,

Quoted 17 lines · Linus Walleij

2010/8/9 Sascha Hauer <[email protected]>:

Quoted 15 lines

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

(...)
+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);

Quoted 8 lines
Quoted 6 lines

+ ? ? ? void (*enable)(int channel);
+ ? ? ? void (*disable)(int channel);
+ ? ? ? int (*request)(enum imx_dma_prio);
+ ? ? ? void (*free)(int channel);
+ ? ? ? int num_channels;
+};

This is just getting *so* close to the drivers/dma dmaengine API.

I was afraid somewone would say this ;)

Quoted 8 lines

We decided to use the damengine for all our DMA drivers and we haven't regretted one bit.

There has been some noise about too many drivers stacking up below arch/arm instead of going to the apropriate subsystem, can't you atleast contemplate using the dmaengine and help us improve that subsystem?

The last time I looked into dmaengine I failed to see how this API could help me. Looking at it again it seems that this is the way to go. I will definitely have a closer look. I can't promise though that this will be before the next merge window. The SDMA engine on the other hand is of great value for the i.MX community, so if anyone is willing to help here, please step forward.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author maintainer
#5 lore raw

PATCH 2/8 ARM i.MX dma-mx1-mx2: use wrapper

In reply to Sascha Hauer

This patch implements the new DMA API for i.MX1/21/27. The old APIP is kept in the tree until all users have switched to the new API.

---
 arch/arm/mach-imx/dma-v1.c                   |  142 +++++++++++++++++++++++---
 arch/arm/mach-imx/include/mach/dma-mx1-mx2.h |    2 +-
 2 files changed, 128 insertions(+), 16 deletions(-)
arch/arm/mach-imx/dma-v1.c +127 -15
index 3e8c47c..d141458 100644
@@ -35,6 +35,7 @@
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/dma-v1.h>
+#include <mach/dma.h>
 
 #define DMA_DCR     0x00		/* Control Register */
 #define DMA_DISR    0x04		/* Interrupt status Register */
@@ -112,6 +113,7 @@ struct imx_dma_channel {
 	void (*irq_handler) (int, void *);
 	void (*err_handler) (int, void *, int errcode);
 	void (*prog_handler) (int, void *, struct scatterlist *);
+	void (*completion_handler) (int channel, void *data, int error);
 	void *data;
 	unsigned int dma_mode;
 	struct scatterlist *sg;
@@ -126,6 +128,11 @@ struct imx_dma_channel {
 	struct timer_list watchdog;
 
 	int hw_chaining;
+
+	dma_addr_t dev_addr;
+
+	int sgcount;
+	int sgcur;
 };
 
 static void __iomem *imx_dmav1_baseaddr;
@@ -308,6 +315,8 @@ imx_dma_setup_sg(int channel,
 	imxdma->sg = sg;
 	imxdma->dma_mode = dmamode;
 	imxdma->resbytes = dma_length;
+	imxdma->sgcount = sgcount;
+	imxdma->sgcur = 0;
 
 	if (!sg || !sgcount) {
 		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg empty sg list\n",
@@ -341,8 +350,6 @@ imx_dma_setup_sg(int channel,
 		return -EINVAL;
 	}
 
-	imx_dma_sg_next(channel, sg);
-
 	return 0;
 }
 EXPORT_SYMBOL(imx_dma_setup_sg);
@@ -470,6 +477,9 @@ void imx_dma_enable(int channel)
 
 	local_irq_save(flags);
 
+	if (imxdma->sg)
+		imx_dma_sg_next(channel, imxdma->sg + imxdma->sgcur);
+
 	imx_dmav1_writel(1 << channel, DMA_DISR);
 	imx_dmav1_writel(imx_dmav1_readl(DMA_DIMR) & ~(1 << channel), DMA_DIMR);
 	imx_dmav1_writel(imx_dmav1_readl(DMA_CCR(channel)) | CCR_CEN |
@@ -478,10 +488,14 @@ void imx_dma_enable(int channel)
 #ifdef CONFIG_ARCH_MX2
 	if ((cpu_is_mx21() || cpu_is_mx27()) &&
 			imxdma->sg && imx_dma_hw_chain(imxdma)) {
-		imxdma->sg = sg_next(imxdma->sg);
-		if (imxdma->sg) {
+		imxdma->sgcur++;
+
+		if (imxdma->resbytes == IMX_DMA_LENGTH_LOOP)
+			imxdma->sgcur %= imxdma->sgcount;
+
+		if (imxdma->sgcur < imxdma->sgcount) {
 			u32 tmp;
-			imx_dma_sg_next(channel, imxdma->sg);
+			imx_dma_sg_next(channel, imxdma->sg + imxdma->sgcur);
 			tmp = imx_dmav1_readl(DMA_CCR(channel));
 			imx_dmav1_writel(tmp | CCR_RPT | CCR_ACRPT,
 				DMA_CCR(channel));
@@ -503,7 +517,7 @@ void imx_dma_disable(int channel)
 	struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
 	unsigned long flags;
 
-	pr_debug("imxdma%d: imx_dma_disable\n", channel);
+	pr_info("imxdma%d: imx_dma_disable\n", channel);
 
 	if (imx_dma_hw_chain(imxdma))
 		del_timer(&imxdma->watchdog);
@@ -522,13 +536,13 @@ EXPORT_SYMBOL(imx_dma_disable);
 static void imx_dma_watchdog(unsigned long chno)
 {
 	struct imx_dma_channel *imxdma = &imx_dma_channels[chno];
+	u32 tmp;
 
-	imx_dmav1_writel(0, DMA_CCR(chno));
-	imxdma->in_use = 0;
-	imxdma->sg = NULL;
+	mod_timer(&imxdma->watchdog, jiffies + msecs_to_jiffies(500));
 
-	if (imxdma->err_handler)
-		imxdma->err_handler(chno, imxdma->data, IMX_DMA_ERR_TIMEOUT);
+	tmp = imx_dmav1_readl(DMA_CCR(chno));
+	imx_dmav1_writel(0, DMA_CCR(chno));
+	imx_dmav1_writel(tmp, DMA_CCR(chno));
 }
 #endif
 
@@ -607,11 +621,14 @@ static void dma_irq_handle_channel(int chno)
 
 	if (imxdma->sg) {
 		u32 tmp;
-		struct scatterlist *current_sg = imxdma->sg;
-		imxdma->sg = sg_next(imxdma->sg);
+		struct scatterlist *current_sg = imxdma->sg + imxdma->sgcur;
 
-		if (imxdma->sg) {
-			imx_dma_sg_next(chno, imxdma->sg);
+		imxdma->sgcur++;
+		if (imxdma->resbytes == IMX_DMA_LENGTH_LOOP)
+			imxdma->sgcur %= imxdma->sgcount;
+
+		if (imxdma->sgcur < imxdma->sgcount) {
+			imx_dma_sg_next(chno, imxdma->sg + imxdma->sgcur);
 
 			tmp = imx_dmav1_readl(DMA_CCR(chno));
 
@@ -798,6 +815,99 @@ int imx_dma_request_by_prio(const char *name, enum imx_dma_prio prio)
 }
 EXPORT_SYMBOL(imx_dma_request_by_prio);
 
+static void __irq_handler(int channel, void *data)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
+
+	imxdma->completion_handler(channel, data, 0);
+}
+
+static void __prog_handler(int channel, void *data, struct scatterlist *unused)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
+
+	imxdma->completion_handler(channel, data, 0);
+}
+
+static int config_channel(int channel, struct imx_dma_config *cfg)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
+	unsigned int config_port;
+
+	imxdma->completion_handler = cfg->completion_handler;
+
+	imx_dma_config_burstlen(channel, cfg->burstlen * cfg->word_size);
+	imx_dma_setup_handlers(channel, __irq_handler,
+			NULL,
+			cfg->driver_data);
+
+	imxdma->dev_addr = cfg->dma_address;
+
+	switch (cfg->word_size) {
+	case 1:
+		config_port = IMX_DMA_MEMSIZE_8;
+		break;
+	case 2:
+		config_port = IMX_DMA_MEMSIZE_16;
+		break;
+	case 4:
+		config_port = IMX_DMA_MEMSIZE_32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	config_port |= IMX_DMA_TYPE_FIFO;
+
+	imx_dma_config_channel(channel, config_port,
+			IMX_DMA_MEMSIZE_32, cfg->dma_request, 1);
+
+	if (cfg->flags & IMX_DMA_SG_LOOP) {
+		imxdma->resbytes = IMX_DMA_LENGTH_LOOP;
+		imx_dma_setup_progression_handler(channel, __prog_handler);
+	}
+
+	return 0;
+}
+
+static int setup_single(int channel, dma_addr_t mem, int dma_length,
+		unsigned int dmamode)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
+
+	return imx_dma_setup_single(channel, mem,
+		     dma_length, imxdma->dev_addr,
+		     dmamode);
+}
+
+static int setup_sg(int channel, struct scatterlist *sg, unsigned int sgcount,
+			unsigned int dma_length, unsigned int dmamode)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
+
+	if (imxdma->resbytes == IMX_DMA_LENGTH_LOOP)
+		dma_length = IMX_DMA_LENGTH_LOOP;
+
+	return imx_dma_setup_sg(channel, sg, sgcount, dma_length,
+			imxdma->dev_addr,
+			dmamode);
+}
+
+static int request_channel(enum imx_dma_prio prio)
+{
+	return imx_dma_request_by_prio("imxdma", prio);
+}
+
+static struct imx_dma_operations imxdma_ops = {
+	.config_channel = config_channel,
+	.setup_single = setup_single,
+	.setup_sg = setup_sg,
+	.enable = imx_dma_enable,
+	.disable = imx_dma_disable,
+	.request = request_channel,
+	.free = imx_dma_free,
+};
+
 static int __init imx_dma_init(void)
 {
 	int ret = 0;
@@ -856,6 +966,8 @@ static int __init imx_dma_init(void)
 		imx_dma_channels[i].dma_num = i;
 	}
 
+	imx_dma_ops_register(&imxdma_ops);
+
 	return ret;
 }
 
arch/arm/mach-imx/include/mach/dma-mx1-mx2.h +1 -1
index df5f522..90b7971 100644
@@ -2,7 +2,7 @@
 #define __MACH_DMA_MX1_MX2_H__
 /*
  * Don't use this header in new code, it will go away when all users are
- * converted to mach/dma-v1.h
+ * converted to mach/dma.h
  */
 
 #include <mach/dma-v1.h>
Signature · 1 line
1.7.1
#6 lore raw

PATCH 2/8 ARM i.MX dma-mx1-mx2: use wrapper

Hi Sascha,

Quoted 5 lines
arch/arm/mach-imx/dma-v1.c +0 -0
index 3e8c47c..d141458 100644
@@ -35,6 +35,7 @@

...

arch/arm/mach-imx/dma-v1.c void imx_dma_disable(int channel) · line 520

Quoted 6 lines
arch/arm/mach-imx/dma-v1.c +1 -1
@@ -503,7 +517,7 @@ void imx_dma_disable(int channel)
 	struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
 	unsigned long flags;
 
-	pr_debug("imxdma%d: imx_dma_disable\n", channel);
+	pr_info("imxdma%d: imx_dma_disable\n", channel);

With this change imx_dma_enable() uses pr_debug() while imx_dma_disable uses pr_info(). Shouldn't both use the same pr_*() since the functions are paired?

Regards, Magnus

author maintainer
#7 lore raw

PATCH 2/8 ARM i.MX dma-mx1-mx2: use wrapper

Quoted 12 lines · Magnus Lilja

Hi Sascha,

Quoted 5 lines
arch/arm/mach-imx/dma-v1.c +0 -0
index 3e8c47c..d141458 100644
@@ -35,6 +35,7 @@

...

Quoted 4 lines
arch/arm/mach-imx/dma-v1.c +0 -0
@@ -503,7 +517,7 @@ void imx_dma_disable(int channel)
 	struct imx_dma_channel *imxdma = &imx_dma_channels[channel];
 	unsigned long flags;
 
Quoted 6 lines

arch/arm/mach-imx/dma-v1.c void imx_dma_disable(int channel) · line 520

Quoted 2 lines
arch/arm/mach-imx/dma-v1.c +1 -1
-	pr_debug("imxdma%d: imx_dma_disable\n", channel);
+	pr_info("imxdma%d: imx_dma_disable\n", channel);

With this change imx_dma_enable() uses pr_debug() while imx_dma_disable uses pr_info(). Shouldn't both use the same pr_*() since the functions are paired?

They should both use pr_debug. Will fix.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
author maintainer
#8 lore raw

PATCH 3/8 mxcmmc: use new dma api

In reply to Sascha Hauer

This switches the mxcmmc driver to use the new DMA API. Unlike the old one this one is always present in the tree, even if no DMA is implement, hence we can remove all the #ifdefs in from the driver.

---
 drivers/mmc/host/mxcmmc.c |  129 +++++++++++++++++++++++---------------------
 1 files changed, 67 insertions(+), 62 deletions(-)
drivers/mmc/host/mxcmmc.c +67 -62
index 350f78e..a71c2a6 100644
@@ -37,10 +37,7 @@
 #include <asm/sizes.h>
 #include <mach/mmc.h>
 
-#ifdef CONFIG_ARCH_MX2
-#include <mach/dma-mx1-mx2.h>
-#define HAS_DMA
-#endif
+#include <mach/dma.h>
 
 #define DRIVER_NAME "mxc-mmc"
 
@@ -141,6 +138,9 @@ struct mxcmci_host {
 
 	struct work_struct	datawork;
 	spinlock_t		lock;
+
+	int			burstlen;
+	int			dmareq;
 };
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
@@ -166,17 +166,17 @@ static void mxcmci_softreset(struct mxcmci_host *host)
 
 	writew(0xff, host->base + MMC_REG_RES_TO);
 }
+static int mxcmci_setup_dma(struct mmc_host *mmc);
 
 static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 {
 	unsigned int nob = data->blocks;
 	unsigned int blksz = data->blksz;
 	unsigned int datasize = nob * blksz;
-#ifdef HAS_DMA
 	struct scatterlist *sg;
 	int i;
 	int ret;
-#endif
+
 	if (data->flags & MMC_DATA_STREAM)
 		nob = 0xffff;
 
@@ -187,7 +187,9 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 	writew(blksz, host->base + MMC_REG_BLK_LEN);
 	host->datasize = datasize;
 
-#ifdef HAS_DMA
+	if (!mxcmci_use_dma(host))
+		return 0;
+
 	for_each_sg(data->sg, sg, data->sg_len, i) {
 		if (sg->offset & 3 || sg->length & 3) {
 			host->do_dma = 0;
@@ -200,19 +202,15 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
 					     data->sg_len,  host->dma_dir);
 
-		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
-				datasize,
-				host->res->start + MMC_REG_BUFFER_ACCESS,
-				DMA_MODE_READ);
+		ret = imxdma_setup_sg(host->dma, data->sg, host->dma_nents,
+			datasize, DMA_MODE_READ);
 	} else {
 		host->dma_dir = DMA_TO_DEVICE;
 		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
 					     data->sg_len,  host->dma_dir);
 
-		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
-				datasize,
-				host->res->start + MMC_REG_BUFFER_ACCESS,
-				DMA_MODE_WRITE);
+		ret = imxdma_setup_sg(host->dma, data->sg, host->dma_nents,
+			datasize, DMA_MODE_WRITE);
 	}
 
 	if (ret) {
@@ -221,8 +219,8 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 	}
 	wmb();
 
-	imx_dma_enable(host->dma);
-#endif /* HAS_DMA */
+	imxdma_enable(host->dma);
+
 	return 0;
 }
 
@@ -297,13 +295,11 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
 	struct mmc_data *data = host->data;
 	int data_error;
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host)) {
-		imx_dma_disable(host->dma);
+		imxdma_disable(host->dma);
 		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
 				host->dma_dir);
 	}
-#endif
 
 	if (stat & STATUS_ERR_MASK) {
 		dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
@@ -505,7 +501,6 @@ static void mxcmci_datawork(struct work_struct *work)
 	}
 }
 
-#ifdef HAS_DMA
 static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
 {
 	struct mmc_data *data = host->data;
@@ -528,7 +523,6 @@ static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
 		mxcmci_finish_request(host, host->req);
 	}
 }
-#endif /* HAS_DMA */
 
 static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
 {
@@ -566,12 +560,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
 	sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio;
 	spin_unlock_irqrestore(&host->lock, flags);
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host) &&
 	    (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE)))
 		writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
 			host->base + MMC_REG_STATUS);
-#endif
 
 	if (sdio_irq) {
 		writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS);
@@ -581,14 +573,14 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
 	if (stat & STATUS_END_CMD_RESP)
 		mxcmci_cmd_done(host, stat);
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host) &&
 		  (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
 		mxcmci_data_done(host, stat);
-#endif
+
 	if (host->default_irq_mask &&
 		  (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
 		mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+
 	return IRQ_HANDLED;
 }
 
@@ -602,9 +594,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
 
 	host->req = req;
 	host->cmdat &= ~CMD_DAT_CONT_INIT;
-#ifdef HAS_DMA
-	host->do_dma = 1;
-#endif
+
 	if (req->data) {
 		error = mxcmci_setup_data(host, req->data);
 		if (error) {
@@ -658,22 +648,48 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
 			prescaler, divider, clk_in, clk_ios);
 }
 
+static int mxcmci_setup_dma(struct mmc_host *mmc)
+{
+	struct mxcmci_host *host = mmc_priv(mmc);
+	struct imx_dma_config cfg;
+
+	cfg.burstlen = host->burstlen;
+	cfg.dma_address = host->res->start + MMC_REG_BUFFER_ACCESS;
+	cfg.word_size = 4;
+	cfg.peripheral_type = IMX_DMATYPE_SDHC;
+	cfg.dma_request = host->dmareq;
+	cfg.completion_handler = NULL;
+	cfg.driver_data = NULL;
+	cfg.flags = 0;
+
+	return imxdma_config(host->dma, &cfg);
+}
+
 static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mxcmci_host *host = mmc_priv(mmc);
-#ifdef HAS_DMA
-	unsigned int blen;
+	int burstlen, ret;
+
 	/*
 	 * use burstlen of 64 in 4 bit mode (--> reg value  0)
 	 * use burstlen of 16 in 1 bit mode (--> reg value 16)
 	 */
 	if (ios->bus_width == MMC_BUS_WIDTH_4)
-		blen = 0;
+		burstlen = 64;
 	else
-		blen = 16;
+		burstlen = 16;
+
+	if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
+		host->burstlen = burstlen;
+		ret = mxcmci_setup_dma(mmc);
+		if (ret) {
+			dev_err(mmc_dev(host->mmc),
+				"failed to config DMA channel. Falling back to PIO\n");
+			imxdma_free(host->dma);
+			host->do_dma = 0;
+		}
+	}
 
-	imx_dma_config_burstlen(host->dma, blen);
-#endif
 	if (ios->bus_width == MMC_BUS_WIDTH_4)
 		host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
 	else
@@ -795,7 +811,7 @@ static int mxcmci_probe(struct platform_device *pdev)
 	mmc->max_blk_size = 2048;
 	mmc->max_blk_count = 65535;
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-	mmc->max_seg_size = mmc->max_req_size;
+	mmc->max_seg_size = 65535;
 
 	host = mmc_priv(mmc);
 	host->base = ioremap(r->start, resource_size(r));
@@ -847,29 +863,18 @@ static int mxcmci_probe(struct platform_device *pdev)
 
 	writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);
 
-#ifdef HAS_DMA
-	host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW);
-	if (host->dma < 0) {
-		dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
-		ret = -EBUSY;
-		goto out_clk_put;
+	host->dma = imxdma_request(DMA_PRIO_LOW);
+	if (host->dma >= 0) {
+		r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (r) {
+			host->dmareq = r->start;
+			host->do_dma = 1;
+		}
 	}
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r) {
-		ret = -EINVAL;
-		goto out_free_dma;
-	}
+	if (!host->do_dma)
+		dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n");
 
-	ret = imx_dma_config_channel(host->dma,
-				     IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO,
-				     IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
-				     r->start, 0);
-	if (ret) {
-		dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n");
-		goto out_free_dma;
-	}
-#endif
 	INIT_WORK(&host->datawork, mxcmci_datawork);
 
 	ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host);
@@ -892,9 +897,8 @@ static int mxcmci_probe(struct platform_device *pdev)
 out_free_irq:
 	free_irq(host->irq, host);
 out_free_dma:
-#ifdef HAS_DMA
-	imx_dma_free(host->dma);
-#endif
+	if (host->dma >= 0)
+		imxdma_free(host->dma);
 out_clk_put:
 	clk_disable(host->clk);
 	clk_put(host->clk);
@@ -921,9 +925,10 @@ static int mxcmci_remove(struct platform_device *pdev)
 
 	free_irq(host->irq, host);
 	iounmap(host->base);
-#ifdef HAS_DMA
-	imx_dma_free(host->dma);
-#endif
+
+	if (host->dma >= 0)
+		imxdma_free(host->dma);
+
 	clk_disable(host->clk);
 	clk_put(host->clk);
 
Signature · 1 line
1.7.1
author maintainer
#9 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

In reply to Sascha Hauer

This patch adds DMA support for i.MX25/31/35/51 based SoCs. The SDMA engine is a scatter/gather DMA engine which is implemented as a seperate coprocessor. SDMA needs its own firmware which is requested using the standard request_firmware mechanism. The firmware has different entry points for each peripheral type, so drivers have to pass the peripheral type to the DMA engine which in turn picks the correct firmware entry point from a table contained in the firmware image itself.
The original Freescale code also supports support for transfering data to the internal SRAM which needs different entry points to the firmware. Support for this is currently not implemented. Also, support for the ASRC (asymmetric sample rate converter) is skipped.

This code has been tested with sound on i.MX31/35 and with SD/MMC on i.MX31. It should work on i.MX25/51, but this is currently untested.

---
 arch/arm/mach-mx3/Kconfig             |    2 +
 arch/arm/plat-mxc/Kconfig             |   10 +
 arch/arm/plat-mxc/Makefile            |    1 +
 arch/arm/plat-mxc/include/mach/sdma.h |    8 +
 arch/arm/plat-mxc/sdma.c              | 1181 +++++++++++++++++++++++++++++++++
 5 files changed, 1202 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-mxc/include/mach/sdma.h
 create mode 100644 arch/arm/plat-mxc/sdma.c
arch/arm/mach-mx3/Kconfig +2 -0
index 85beece..301375c 100644
@@ -3,12 +3,14 @@ if ARCH_MX3
 config ARCH_MX31
 	select ARCH_HAS_RNGA
 	select ARCH_MXC_AUDMUX_V2
+	select IMX_HAVE_SDMA
 	bool
 
 config ARCH_MX35
 	bool
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
+	select IMX_HAVE_SDMA
 
 comment "MX3 platforms:"
 
arch/arm/plat-mxc/Kconfig +10 -0
index 0527e65..6741625 100644
@@ -109,4 +109,14 @@ config ARCH_MXC_AUDMUX_V1
 config ARCH_MXC_AUDMUX_V2
 	bool
 
+config IMX_HAVE_SDMA
+	bool
+
+config IMX_SDMA
+	depends on IMX_HAVE_SDMA
+	tristate "Enable SDMA support"
+	help
+	  Include support for the SDMA engine. The SDMA engine needs additional
+	  firmware support. SDMA can be compiled as a module to support loading
+	  the firmware when a rootfs is present.
 endif
arch/arm/plat-mxc/Makefile +1 -0
index ff9880c..378f8ca 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
+obj-$(CONFIG_IMX_SDMA) += sdma.o
 ifdef CONFIG_SND_IMX_SOC
 obj-y += ssi-fiq.o
 obj-y += ssi-fiq-ksym.o
arch/arm/plat-mxc/include/mach/sdma.h new file +8 -0
new file mode 100644
index 0000000..5d542b8
@@ -0,0 +1,8 @@
+#ifndef __MACH_MXC_SDMA_H__
+#define __MACH_MXC_SDMA_H__
+
+struct sdma_platform_data {
+	int sdma_version;
+};
+
+#endif /* __MACH_MXC_SDMA_H__ */
arch/arm/plat-mxc/sdma.c new file +1181 -0

1,181 lines not on this page · raw message

Signature · 1 line
1.7.1
#10 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

Hi Sascha,

Just some typos that I spotted.

Quoted 19 lines
arch/arm/plat-mxc/include/mach/sdma.h new file +8 -0
new file mode 100644
index 0000000..5d542b8
@@ -0,0 +1,8 @@
+#ifndef __MACH_MXC_SDMA_H__
+#define __MACH_MXC_SDMA_H__
+
+struct sdma_platform_data {
+	int sdma_version;
+};
+
+#endif /* __MACH_MXC_SDMA_H__ */
arch/arm/plat-mxc/sdma.c new file +0 -0
new file mode 100644
index 0000000..3fbc8d8

...

arch/arm/plat-mxc/sdma.c line 121

Quoted 3 lines
arch/arm/plat-mxc/sdma.c new file +3 -0
+#ifdef __BIG_ENDIAN
+struct sdma_mode_count {
+	u32 command :  8; /* command mostlky used for channel 0 */
                                        ^^^ typo

arch/arm/plat-mxc/sdma.c line 129

Quoted 8 lines
arch/arm/plat-mxc/sdma.c new file +8 -0
+	u32 status  :  8; /* E,R,I,C,W,D status bits stored here */
+	u32 count   : 16; /* size of the buffer pointed by this BD */
+};
+#else
+struct sdma_mode_count {
+	u32 count   : 16; /* size of the buffer pointed by this BD */
+	u32 status  :  8; /* E,R,I,C,W,D status bits stored here */
+	u32 command :  8; /* command mostlky used for channel 0 */
                                        ^^^ typo
Quoted 18 lines
arch/arm/plat-mxc/sdma.c new file +18 -0
+};
+#endif
+
+/*
+ * Buffer descriptor
+ */
+struct sdma_buffer_descriptor {
+	struct sdma_mode_count  mode;
+	void *buffer_addr;    /* address of the buffer described */
+	void *ext_buffer_addr; /* extended buffer address */
+};
+
+/*
+ * Channel control Block
+ */
+struct sdma_channel_control {
+	struct sdma_buffer_descriptor *currentBDptr; /* current buffer descriptor processed */
+	struct sdma_buffer_descriptor *baseBDptr;    /* first element of buffer descriptor array */

arch/arm/plat-mxc/sdma.c line 157

Quoted 10 lines
arch/arm/plat-mxc/sdma.c new file +10 -0
+	void *unused;
+	void *unused1;
+};
+
+/**
+ * Context structure.
+ */
+#ifdef __BIG_ENDIAN
+struct sdma_state_registers {
+	u32 sf     : 1; /* source falut while loading data */
                                  ^^^^^ typo?

arch/arm/plat-mxc/sdma.c line 165

Quoted 8 lines
arch/arm/plat-mxc/sdma.c new file +8 -0
+	u32 unused0: 1;
+	u32 rpc    :14; /* return program counter */
+	u32 t      : 1; /* test bit:status of arithmetic & test instruction*/
+	u32 unused1: 1;
+	u32 pc     :14; /* program counter */
+	u32 lm     : 2; /* loop mode */
+	u32 epc    :14; /* loop end program counter */
+	u32 df     : 1; /* destiantion falut while storing data */
                           ^^^^^^^^^^^^^^^^^ typos

arch/arm/plat-mxc/sdma.c line 176

Quoted 11 lines
arch/arm/plat-mxc/sdma.c new file +11 -0
+	u32 unused2: 1;
+	u32 spc    :14; /* loop start program counter */
+};
+#else
+struct sdma_state_registers {
+	u32 pc     :14; /* program counter */
+	u32 unused1: 1;
+	u32 t      : 1; /* test bit: status of arithmetic & test instruction*/
+	u32 rpc    :14; /* return program counter */
+	u32 unused0: 1;
+	u32 sf     : 1; /* source falut while loading data */
                                    ^^^ typo?

Regards, Magnus Lilja

author maintainer
#11 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

Quoted 18 lines · Magnus Lilja

Hi Sascha,

Just some typos that I spotted.

Review

Quoted 2 lines
(quoted diff) +2 -0
+struct sdma_state_registers {
+	u32 sf     : 1; /* source falut while loading data */
                                  ^^^^^ typo?

arch/arm/plat-mxc/sdma.c line 165

Quoted 8 lines
arch/arm/plat-mxc/sdma.c new file +8 -0
+	u32 unused0: 1;
+	u32 rpc    :14; /* return program counter */
+	u32 t      : 1; /* test bit:status of arithmetic & test instruction*/
+	u32 unused1: 1;
+	u32 pc     :14; /* program counter */
+	u32 lm     : 2; /* loop mode */
+	u32 epc    :14; /* loop end program counter */
+	u32 df     : 1; /* destiantion falut while storing data */
                           ^^^^^^^^^^^^^^^^^ typos
Quoted 12 lines

arch/arm/plat-mxc/sdma.c line 176

Quoted 11 lines
arch/arm/plat-mxc/sdma.c new file +11 -0
+	u32 unused2: 1;
+	u32 spc    :14; /* loop start program counter */
+};
+#else
+struct sdma_state_registers {
+	u32 pc     :14; /* program counter */
+	u32 unused1: 1;
+	u32 t      : 1; /* test bit: status of arithmetic & test instruction*/
+	u32 rpc    :14; /* return program counter */
+	u32 unused0: 1;
+	u32 sf     : 1; /* source falut while loading data */
                                    ^^^ typo?

I'm glad I copied these typos from the fsl kernel and haven't invented them myself. What the heck is a falut? fault?

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#12 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

In reply to Sascha Hauer

Hi Sascha,

Quoted 26 lines

This patch adds DMA support for i.MX25/31/35/51 based SoCs. The SDMA engine is a scatter/gather DMA engine which is implemented as a seperate coprocessor. SDMA needs its own firmware which is requested using the standard request_firmware mechanism. The firmware has different entry points for each peripheral type, so drivers have to pass the peripheral type to the DMA engine which in turn picks the correct firmware entry point from a table contained in the firmware image itself.
The original Freescale code also supports support for transfering data to the internal SRAM which needs different entry points to the firmware. Support for this is currently not implemented. Also, support for the ASRC (asymmetric sample rate converter) is skipped.

This code has been tested with sound on i.MX31/35 and with SD/MMC on i.MX31. It should work on i.MX25/51, but this is currently untested.

---
 arch/arm/mach-mx3/Kconfig             |    2 +
 arch/arm/plat-mxc/Kconfig             |   10 +
 arch/arm/plat-mxc/Makefile            |    1 +
 arch/arm/plat-mxc/include/mach/sdma.h |    8 +
 arch/arm/plat-mxc/sdma.c              | 1181 +++++++++++++++++++++++++++++++++
 5 files changed, 1202 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-mxc/include/mach/sdma.h
 create mode 100644 arch/arm/plat-mxc/sdma.c

[...]

arch/arm/plat-mxc/sdma.c line 1137

Quoted 8 lines
arch/arm/plat-mxc/sdma.c new file +8 -0
+	if (header->magic != SDMA_FIRMWARE_MAGIC)
+		goto err_firmware;
+	if (header->ram_code_start + header->ram_code_size > fw->size)
+		goto err_firmware;
+
+	addr = (void *)header + header->script_addrs_start;
+	ram_code = (void *)header + header->ram_code_start;
+	memcpy(&__sdma_script_addrs, addr, sizeof(*addr));

As the firmware file is an external entity, I think it makes sense to explicitely specify the endianness of 32-bit values and use endian macros i.e. (le32_to_cpu) when accessing it.

Considering that Freescale (re)uses functional blocks in ARM and Power Architecture chips, this may save efforts in the future.

Apart from this I would also welcome if the whole driver could be adapted to the drivers/dma dmaengine API as pointed out by Linus Walleij. The dma controller support for the Power Architecture chips of Freescale do implement this API, so this would also be a great step towards code unification of drivers here.

Thanks
Detlev

--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

#13 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

On Tuesday, August 10, 2010, Detlev Zundel <[email protected]>

Quoted 5 lines

Apart from this I would also welcome if the whole driver could be adapted to the drivers/dma dmaengine API as pointed out by Linus Walleij. ?The dma controller support for the Power Architecture chips of Freescale do implement this API, so this would also be a great step towards code unification of drivers here.

The Freescale PowerPC and ARM DMA controllers are completely different, so I don't see how the drivers could be unified.

Signature · 2 lines
Timur Tabi
Linux kernel developer at Freescale
#14 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

Hi,

Quoted 10 lines · Timur Tabi

On Tuesday, August 10, 2010, Detlev Zundel <[email protected]>

Quoted 5 lines

Apart from this I would also welcome if the whole driver could be adapted to the drivers/dma dmaengine API as pointed out by Linus Walleij. ?The dma controller support for the Power Architecture chips of Freescale do implement this API, so this would also be a great step towards code unification of drivers here.

The Freescale PowerPC and ARM DMA controllers are completely different, so I don't see how the drivers could be unified.

The DMA API should abstract away the differences in the hardware so that device drivers could use DMA without having to know on what hardware they are running.

Lothar Wa?mann

Signature · 9 lines
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________
#15 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

Quoted 10 lines · Lothar Wa?mann

Hi,

Quoted 7 lines · Timur Tabi

On Tuesday, August 10, 2010, Detlev Zundel <[email protected]>

Quoted 5 lines

Apart from this I would also welcome if the whole driver could be adapted to the drivers/dma dmaengine API as pointed out by Linus Walleij. The dma controller support for the Power Architecture chips of Freescale do implement this API, so this would also be a great step towards code unification of drivers here.

Quoted 6 lines
Quoted 3 lines

The Freescale PowerPC and ARM DMA controllers are completely different, so I don't see how the drivers could be unified.

The DMA API should abstract away the differences in the hardware so that device drivers could use DMA without having to know on what hardware they are running.

I thought you were talking about unifying the PowerPC DMA driver with the I.MX SDMA driver.

#16 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

Hi Timur,

Quoted 15 lines · Lothar Wa?mann
Quoted 14 lines

Hi,

Quoted 10 lines · Timur Tabi

On Tuesday, August 10, 2010, Detlev Zundel <[email protected]>

Quoted 5 lines

Apart from this I would also welcome if the whole driver could be adapted to the drivers/dma dmaengine API as pointed out by Linus Walleij. The dma controller support for the Power Architecture chips of Freescale do implement this API, so this would also be a great step towards code unification of drivers here.

The Freescale PowerPC and ARM DMA controllers are completely different, so I don't see how the drivers could be unified.

Quoted 6 lines
Quoted 3 lines

The DMA API should abstract away the differences in the hardware so that device drivers could use DMA without having to know on what hardware they are running.

I thought you were talking about unifying the PowerPC DMA driver with the I.MX SDMA driver.

No, I was talking about the device drivers using DMA as a functional block.

I dare not think about unifying the BestComm with the SDMA driver :)

Cheers
Detlev

--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

#17 lore raw

PATCH 4/8 ARM i.MX: add SDMA driver

In reply to Sascha Hauer
Quoted 83 lines · Sascha Hauer

This patch adds DMA support for i.MX25/31/35/51 based SoCs. The SDMA engine is a scatter/gather DMA engine which is implemented as a seperate coprocessor. SDMA needs its own firmware which is requested using the standard request_firmware mechanism. The firmware has different entry points for each peripheral type, so drivers have to pass the peripheral type to the DMA engine which in turn picks the correct firmware entry point from a table contained in the firmware image itself.
The original Freescale code also supports support for transfering data to the internal SRAM which needs different entry points to the firmware. Support for this is currently not implemented. Also, support for the ASRC (asymmetric sample rate converter) is skipped.

This code has been tested with sound on i.MX31/35 and with SD/MMC on i.MX31. It should work on i.MX25/51, but this is currently untested.

---
 arch/arm/mach-mx3/Kconfig             |    2 +
 arch/arm/plat-mxc/Kconfig             |   10 +
 arch/arm/plat-mxc/Makefile            |    1 +
 arch/arm/plat-mxc/include/mach/sdma.h |    8 +
 arch/arm/plat-mxc/sdma.c              | 1181 +++++++++++++++++++++++++++++++++
 5 files changed, 1202 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-mxc/include/mach/sdma.h
 create mode 100644 arch/arm/plat-mxc/sdma.c
arch/arm/mach-mx3/Kconfig +2 -0
index 85beece..301375c 100644
@@ -3,12 +3,14 @@ if ARCH_MX3
 config ARCH_MX31
 	select ARCH_HAS_RNGA
 	select ARCH_MXC_AUDMUX_V2
+	select IMX_HAVE_SDMA
 	bool
 
 config ARCH_MX35
 	bool
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MXC_AUDMUX_V2
+	select IMX_HAVE_SDMA
 
 comment "MX3 platforms:"
 
arch/arm/plat-mxc/Kconfig +10 -0
index 0527e65..6741625 100644
@@ -109,4 +109,14 @@ config ARCH_MXC_AUDMUX_V1
 config ARCH_MXC_AUDMUX_V2
 	bool
 
+config IMX_HAVE_SDMA
+	bool
+
+config IMX_SDMA
+	depends on IMX_HAVE_SDMA
+	tristate "Enable SDMA support"
+	help
+	  Include support for the SDMA engine. The SDMA engine needs additional
+	  firmware support. SDMA can be compiled as a module to support loading
+	  the firmware when a rootfs is present.
 endif
arch/arm/plat-mxc/Makefile +1 -0
index ff9880c..378f8ca 100644
@@ -16,6 +16,7 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
+obj-$(CONFIG_IMX_SDMA) += sdma.o
 ifdef CONFIG_SND_IMX_SOC
 obj-y += ssi-fiq.o
 obj-y += ssi-fiq-ksym.o
arch/arm/plat-mxc/include/mach/sdma.h new file +0 -0
new file mode 100644
index 0000000..5d542b8

arch/arm/plat-mxc/include/mach/sdma.h line 2

Quoted 2 lines
arch/arm/plat-mxc/include/mach/sdma.h new file +2 -0
@@ -0,0 +1,8 @@
+#ifndef __MACH_MXC_SDMA_H__
+#define __MACH_MXC_SDMA_H__

__MACH_SDMA_H__ please

Quoted 287 lines
arch/arm/plat-mxc/include/mach/sdma.h new file +6 -0
+
+struct sdma_platform_data {
+	int sdma_version;
+};
+
+#endif /* __MACH_MXC_SDMA_H__ */
arch/arm/plat-mxc/sdma.c new file +275 -0
new file mode 100644
index 0000000..3fbc8d8
@@ -0,0 +1,1181 @@
+/*
+ * arch/arm/plat-mxc/sdma.c
+ *
+ * This file contains a driver for the Freescale Smart DMA engine
+ *
+ * Copyright 2010 Sascha Hauer, Pengutronix <[email protected]>
+ *
+ * Based on code from Freescale:
+ *
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <mach/sdma.h>
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+/* SDMA registers */
+#define SDMA_H_C0PTR		(sdma_base + 0x000)
+#define SDMA_H_INTR		(sdma_base + 0x004)
+#define SDMA_H_STATSTOP		(sdma_base + 0x008)
+#define SDMA_H_START		(sdma_base + 0x00c)
+#define SDMA_H_EVTOVR		(sdma_base + 0x010)
+#define SDMA_H_DSPOVR		(sdma_base + 0x014)
+#define SDMA_H_HOSTOVR		(sdma_base + 0x018)
+#define SDMA_H_EVTPEND		(sdma_base + 0x01c)
+#define SDMA_H_DSPENBL		(sdma_base + 0x020)
+#define SDMA_H_RESET		(sdma_base + 0x024)
+#define SDMA_H_EVTERR		(sdma_base + 0x028)
+#define SDMA_H_INTRMSK		(sdma_base + 0x02c)
+#define SDMA_H_PSW		(sdma_base + 0x030)
+#define SDMA_H_EVTERRDBG	(sdma_base + 0x034)
+#define SDMA_H_CONFIG		(sdma_base + 0x038)
+#define SDMA_ONCE_ENB		(sdma_base + 0x040)
+#define SDMA_ONCE_DATA		(sdma_base + 0x044)
+#define SDMA_ONCE_INSTR		(sdma_base + 0x048)
+#define SDMA_ONCE_STAT		(sdma_base + 0x04c)
+#define SDMA_ONCE_CMD		(sdma_base + 0x050)
+#define SDMA_EVT_MIRROR		(sdma_base + 0x054)
+#define SDMA_ILLINSTADDR	(sdma_base + 0x058)
+#define SDMA_CHN0ADDR		(sdma_base + 0x05c)
+#define SDMA_ONCE_RTB		(sdma_base + 0x060)
+#define SDMA_XTRIG_CONF1	(sdma_base + 0x070)
+#define SDMA_XTRIG_CONF2	(sdma_base + 0x074)
+#define SDMA_CHNENBL_0		(sdma_base + (sdma_version == 2 ? 0x200 : 0x80))
+#define SDMA_CHNPRI_0		(sdma_base + 0x100)
+
+/*
+ * Buffer descriptor status values.
+ */
+#define BD_DONE  0x01
+#define BD_WRAP  0x02
+#define BD_CONT  0x04
+#define BD_INTR  0x08
+#define BD_RROR  0x10
+#define BD_LAST  0x20
+#define BD_EXTD  0x80
+
+/*
+ * Data Node descriptor status values.
+ */
+#define DND_END_OF_FRAME  0x80
+#define DND_END_OF_XFER   0x40
+#define DND_DONE          0x20
+#define DND_UNUSED        0x01
+
+/*
+ * IPCV2 descriptor status values.
+ */
+#define BD_IPCV2_END_OF_FRAME  0x40
+
+#define IPCV2_MAX_NODES        50
+/*
+ * Error bit set in the CCB status field by the SDMA,
+ * in setbd routine, in case of a transfer error
+ */
+#define DATA_ERROR  0x10000000
+
+/*
+ * Buffer descriptor commands.
+ */
+#define C0_ADDR             0x01
+#define C0_LOAD             0x02
+#define C0_DUMP             0x03
+#define C0_SETCTX           0x07
+#define C0_GETCTX           0x03
+#define C0_SETDM            0x01
+#define C0_SETPM            0x04
+#define C0_GETDM            0x02
+#define C0_GETPM            0x08
+/*
+ * Change endianness indicator in the BD command field
+ */
+#define CHANGE_ENDIANNESS   0x80
+
+/*
+ * Mode/Count of data node descriptors - IPCv2
+ */
+#ifdef __BIG_ENDIAN
+struct sdma_mode_count {
+	u32 command :  8; /* command mostlky used for channel 0 */
+	u32 status  :  8; /* E,R,I,C,W,D status bits stored here */
+	u32 count   : 16; /* size of the buffer pointed by this BD */
+};
+#else
+struct sdma_mode_count {
+	u32 count   : 16; /* size of the buffer pointed by this BD */
+	u32 status  :  8; /* E,R,I,C,W,D status bits stored here */
+	u32 command :  8; /* command mostlky used for channel 0 */
+};
+#endif
+
+/*
+ * Buffer descriptor
+ */
+struct sdma_buffer_descriptor {
+	struct sdma_mode_count  mode;
+	void *buffer_addr;    /* address of the buffer described */
+	void *ext_buffer_addr; /* extended buffer address */
+};
+
+/*
+ * Channel control Block
+ */
+struct sdma_channel_control {
+	struct sdma_buffer_descriptor *currentBDptr; /* current buffer descriptor processed */
+	struct sdma_buffer_descriptor *baseBDptr;    /* first element of buffer descriptor array */
+	void *unused;
+	void *unused1;
+};
+
+/**
+ * Context structure.
+ */
+#ifdef __BIG_ENDIAN
+struct sdma_state_registers {
+	u32 sf     : 1; /* source falut while loading data */
+	u32 unused0: 1;
+	u32 rpc    :14; /* return program counter */
+	u32 t      : 1; /* test bit:status of arithmetic & test instruction*/
+	u32 unused1: 1;
+	u32 pc     :14; /* program counter */
+	u32 lm     : 2; /* loop mode */
+	u32 epc    :14; /* loop end program counter */
+	u32 df     : 1; /* destiantion falut while storing data */
+	u32 unused2: 1;
+	u32 spc    :14; /* loop start program counter */
+};
+#else
+struct sdma_state_registers {
+	u32 pc     :14; /* program counter */
+	u32 unused1: 1;
+	u32 t      : 1; /* test bit: status of arithmetic & test instruction*/
+	u32 rpc    :14; /* return program counter */
+	u32 unused0: 1;
+	u32 sf     : 1; /* source falut while loading data */
+	u32 spc    :14; /* loop start program counter */
+	u32 unused2: 1;
+	u32 df     : 1; /* destiantion falut while storing data */
+	u32 epc    :14; /* loop end program counter */
+	u32 lm     : 2; /* loop mode */
+};
+#endif
+
+struct sdma_context_data {
+	struct sdma_state_registers  channel_state; /* channel state bits */
+	u32  gReg[8]; /* general registers */
+	u32  mda; /* burst dma destination address register */
+	u32  msa; /* burst dma source address register */
+	u32  ms;  /* burst dma status  register */
+	u32  md;  /* burst dma data    register */
+	u32  pda; /* peripheral dma destination address register */
+	u32  psa; /* peripheral dma source address register */
+	u32  ps;  /* peripheral dma  status  register */
+	u32  pd;  /* peripheral dma  data    register */
+	u32  ca;  /* CRC polynomial  register */
+	u32  cs;  /* CRC accumulator register */
+	u32  dda; /* dedicated core destination address register */
+	u32  dsa; /* dedicated core source address register */
+	u32  ds;  /* dedicated core status  register */
+	u32  dd;  /* dedicated core data    register */
+	u32  scratch0;
+	u32  scratch1;
+	u32  scratch2;
+	u32  scratch3;
+	u32  scratch4;
+	u32  scratch5;
+	u32  scratch6;
+	u32  scratch7;
+};
+
+struct sdma_channel {
+	/* Channel number */
+	int channel;
+	/* Channel usage name */
+	int in_use;
+	/* Transfer type. Needed for setting SDMA script */
+	int dmamode;
+	/* Peripheral type. Needed for setting SDMA script */
+	sdma_peripheral_type peripheral_type;
+	/* Peripheral event id */
+	int event_id;
+	/* Peripheral event id2 (for channels that use 2 events) */
+	int event_id2;
+	/* Running status */
+	int running;
+	/* SDMA data access word size */
+	unsigned long word_size;
+
+	/* ID of the buffer that was processed */
+	unsigned int buf_tail;
+
+	void (*callback)(int channel, void *arg, int error);
+	void *callback_arg;
+
+	wait_queue_head_t waitq;	/* channel completion waitqeue */
+
+	int num_bd;
+
+	struct sdma_buffer_descriptor *bd;
+	dma_addr_t	bd_phys;
+
+	int pc_from_device, pc_to_device;
+
+	unsigned long flags;
+	dma_addr_t per_address;
+
+	uint32_t event_mask1, event_mask2;
+	uint32_t watermark_level;
+	uint32_t shp_addr, per_addr;
+};
+
+#define MAX_DMA_CHANNELS 32
+#define MXC_SDMA_DEFAULT_PRIORITY 1
+#define MXC_SDMA_MIN_PRIORITY 1
+#define MXC_SDMA_MAX_PRIORITY 7
+
+/*
+ * This enumerates transfer types
+ */
+typedef enum {
+	emi_2_per = 0,		/* EMI memory to peripheral */
+	emi_2_int,		/* EMI memory to internal RAM */
+	emi_2_emi,		/* EMI memory to EMI memory */
+	emi_2_dsp,		/* EMI memory to DSP memory */
+	per_2_int,		/* Peripheral to internal RAM */
+	per_2_emi,		/* Peripheral to internal EMI memory */
+	per_2_dsp,		/* Peripheral to DSP memory */
+	per_2_per,		/* Peripheral to Peripheral */
+	int_2_per,		/* Internal RAM to peripheral */
+	int_2_int,		/* Internal RAM to Internal RAM */
+	int_2_emi,		/* Internal RAM to EMI memory */
+	int_2_dsp,		/* Internal RAM to DSP memory */
+	dsp_2_per,		/* DSP memory to peripheral */
+	dsp_2_int,		/* DSP memory to internal RAM */

arch/arm/plat-mxc/sdma.c line 285

Quoted 10 lines
arch/arm/plat-mxc/sdma.c new file +10 -0
+	dsp_2_emi,		/* DSP memory to EMI memory */
+	dsp_2_dsp,		/* DSP memory to DSP memory */
+	emi_2_dsp_loop,		/* EMI memory to DSP memory loopback */
+	dsp_2_emi_loop,		/* DSP memory to EMI memory loopback */
+	dvfs_pll,		/* DVFS script with PLL change       */
+	dvfs_pdr		/* DVFS script without PLL change    */
+} sdma_transfer_type;
+
+/*
+ * Structure containing sdma request  parameters.

s/ / /

Quoted 53 lines
arch/arm/plat-mxc/sdma.c new file +53 -0
+ */
+struct sdma_script_start_addrs {
+	int ap_2_ap_addr;
+	int ap_2_bp_addr;
+	int ap_2_ap_fixed_addr;
+	int bp_2_ap_addr;
+	int loopback_on_dsp_side_addr;
+	int mcu_interrupt_only_addr;
+
+	int firi_2_per_addr;
+	int firi_2_mcu_addr;
+	int per_2_firi_addr;
+	int mcu_2_firi_addr;
+
+	int uart_2_per_addr;
+	int uart_2_mcu_addr;
+	int per_2_app_addr;
+	int mcu_2_app_addr;
+	int per_2_per_addr;
+
+	int uartsh_2_per_addr;
+	int uartsh_2_mcu_addr;
+	int per_2_shp_addr;
+	int mcu_2_shp_addr;
+
+	int ata_2_mcu_addr;
+	int mcu_2_ata_addr;
+
+	int app_2_per_addr;
+	int app_2_mcu_addr;
+	int shp_2_per_addr;
+	int shp_2_mcu_addr;
+
+	int mshc_2_mcu_addr;
+	int mcu_2_mshc_addr;
+
+	int spdif_2_mcu_addr;
+	int mcu_2_spdif_addr;
+
+	int asrc_2_mcu_addr;
+
+	int ext_mem_2_ipu_addr;
+
+	int descrambler_addr;
+
+	int dptc_dvfs_addr;
+
+	int utra_addr;
+
+	int ram_code_start_addr;
+};
+
+#define SDMA_FIRMWARE_MAGIC 0x414d4453

arch/arm/plat-mxc/sdma.c line 348

Quoted 10 lines
arch/arm/plat-mxc/sdma.c new file +10 -0
+
+struct sdma_firmware_header {
+	uint32_t	magic; /* "SDMA" */
+	uint32_t	version_major;	/* increased whenever layout of struct sdma_script_start_addrs changes */
+	uint32_t	version_minor;	/* firmware version */
+	uint32_t	script_addrs_start; /* offset of struct sdma_script_start_addrs in this image */
+	uint32_t	num_script_addrs; /* Number of script addresses in this image */
+	uint32_t	ram_code_start; /* offset of SDMA ram image in this firmware image */
+	uint32_t	ram_code_size; /* size of SDMA ram image */
+};

I wonder if it's worth the effort to have symbolic names for the script addresses. i.e.

struct sdma_firmware_header {
	uint32_t magic;
	uint32_t version_major;
	uint32_t version_minor;
	uint32_t script_addrs_start; /* offset of struct scriptaddr[] in this image */
	uint32_t num_script_addrs; /* number of script addresses or
				alternatively just NULL-terminate the list? */
	....
};
struct scriptaddr {
	int startaddr;
	char name[0];
};

It's a bit more flexible and doesn't necessarily introduce the need for bumping the version_major when a new address is added. Maybe require alphabetic ordering then to make lookup a bit faster?

Quoted 15 lines
arch/arm/plat-mxc/sdma.c new file +15 -0
+
+static struct sdma_channel sdma_data[MAX_DMA_CHANNELS];
+static struct sdma_channel_control *channel_control;
+static void __iomem *sdma_base;
+static int sdma_version;
+static int sdma_num_events;
+static struct sdma_context_data *sdma_context;
+dma_addr_t sdma_context_phys;
+
+#define SDMA_H_CONFIG_DSPDMA	(1 << 12) /* indicates if the DSPDMA is used */
+#define SDMA_H_CONFIG_RTD_PINS	(1 << 11) /* indicates if Real-Time Debug pins are enabled */
+#define SDMA_H_CONFIG_ACR	(1 << 4)  /* indicates if AHB freq /core freq = 2 or 1 */
+#define SDMA_H_CONFIG_CSM	(3)       /* indicates which context switch mode is selected*/
+
+static int sdma_config_ownership(int channel, int event_override,

arch/arm/plat-mxc/sdma.c line 373

Quoted 10 lines
arch/arm/plat-mxc/sdma.c new file +10 -0
+		   int mcu_verride, int dsp_override)
+{
+	u32 evt, mcu, dsp;
+
+	if (event_override && mcu_verride && dsp_override)
+		return -EINVAL;
+
+	evt = readl(SDMA_H_EVTOVR);
+	mcu = readl(SDMA_H_HOSTOVR);
+	dsp = readl(SDMA_H_DSPOVR);

readl performs little endian access, so I suggest to either use __raw_readl or run unifdef -U__BIG_ENDIAN on this patch.

Best regards
Uwe

Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
author maintainer
#18 lore raw

PATCH 5/8 ARM i.MX3: Add sdma device

In reply to Sascha Hauer
---
 arch/arm/mach-mx3/clock-imx31.c |    4 ++--
 arch/arm/mach-mx3/clock-imx35.c |    2 +-
 arch/arm/mach-mx3/devices.c     |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 35 insertions(+), 3 deletions(-)
arch/arm/mach-mx3/clock-imx31.c +2 -2
index 9a9eb6d..5ad5307 100644
@@ -477,7 +477,7 @@ DEFINE_CLOCK(epit1_clk,   0, MXC_CCM_CGR0,  6, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(epit2_clk,   1, MXC_CCM_CGR0,  8, NULL, NULL, &perclk_clk);
 DEFINE_CLOCK(iim_clk,     0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(ata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk);
+DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, NULL, &ahb_clk);
 DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
 DEFINE_CLOCK(uart1_clk,   0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
@@ -564,7 +564,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "ata", ata_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "rng", rng_clk)
-	_REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk1)
 	_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
 	_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
 	_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
arch/arm/mach-mx3/clock-imx35.c +1 -1
index d3af0fd..b5f3281 100644
@@ -461,7 +461,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
 	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
 	_REGISTER_CLOCK(NULL, "scc", scc_clk)
-	_REGISTER_CLOCK(NULL, "sdma", sdma_clk)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
 	_REGISTER_CLOCK(NULL, "spba", spba_clk)
 	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
arch/arm/mach-mx3/devices.c +32 -0
index a4fd1a2..1c6578a 100644
@@ -26,6 +26,7 @@
 #include <mach/irqs.h>
 #include <mach/common.h>
 #include <mach/mx3_camera.h>
+#include <mach/sdma.h>
 
 #include "devices.h"
 
@@ -391,6 +392,33 @@ struct platform_device imx_kpp_device = {
 	.resource = imx_kpp_resources,
 };
 
+static struct resource imx_sdma_resources[] = {
+	{
+		.start	= MX3x_SDMA_BASE_ADDR,
+		.end	= MX3x_SDMA_BASE_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM
+	}, {
+		.start	= MX31_INT_SDMA,
+		.end	= MX31_INT_SDMA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct sdma_platform_data sdma_data_imx31 = {
+	.sdma_version = 1,
+};
+
+static struct sdma_platform_data sdma_data_imx35 = {
+	.sdma_version = 2,
+};
+
+struct platform_device imx_sdma_device = {
+	.name = "imx-sdma",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(imx_sdma_resources),
+	.resource = imx_sdma_resources,
+};
+
 static int __init mx3_devices_init(void)
 {
 #if defined(CONFIG_ARCH_MX31)
@@ -398,6 +426,7 @@ static int __init mx3_devices_init(void)
 		imx_wdt_resources[0].start = MX31_WDOG_BASE_ADDR;
 		imx_wdt_resources[0].end = MX31_WDOG_BASE_ADDR + 0x3fff;
 		mxc_register_device(&mxc_rnga_device, NULL);
+		mxc_register_device(&imx_sdma_device, &sdma_data_imx31);
 	}
 #endif
 #if defined(CONFIG_ARCH_MX35)
@@ -416,6 +445,9 @@ static int __init mx3_devices_init(void)
 		imx_ssi_resources1[1].end = MX35_INT_SSI2;
 		imx_wdt_resources[0].start = MX35_WDOG_BASE_ADDR;
 		imx_wdt_resources[0].end = MX35_WDOG_BASE_ADDR + 0x3fff;
+		imx_sdma_resources[1].start = MX35_INT_SDMA;
+		imx_sdma_resources[1].end = MX35_INT_SDMA;
+		mxc_register_device(&imx_sdma_device, &sdma_data_imx35);
 	}
 #endif
 
Signature · 1 line
1.7.1
author maintainer
#19 lore raw

PATCH 6/8 ARM i.MX3: add dma request defines

In reply to Sascha Hauer
---
 arch/arm/plat-mxc/include/mach/mx31.h |   14 ++++++++++++++
 arch/arm/plat-mxc/include/mach/mx35.h |   26 ++++++++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/mx3x.h |   29 +++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 0 deletions(-)
arch/arm/plat-mxc/include/mach/mx31.h +14 -0
index afee3ab..dafe9b9 100644
@@ -197,6 +197,20 @@ static inline void mx31_setup_weimcs(size_t cs,
 #define MX31_INT_EXT_WDOG	62
 #define MX31_INT_EXT_TV		63
 
+#define MX31_DMA_REQ_SDHC2	21
+#define MX31_DMA_REQ_SDHC1	20
+#define MX31_DMA_REQ_FIRI_TX	17
+#define MX31_DMA_REQ_FIRI_RX	16
+#define MX31_DMA_REQ_UART4_TX	13
+#define MX31_DMA_REQ_UART4_RX	12
+#define MX31_DMA_REQ_CSPI3_TX	11
+#define MX31_DMA_REQ_CSPI3_RX	10
+#define MX31_DMA_REQ_UART5_TX	11
+#define MX31_DMA_REQ_UART5_RX	10
+#define MX31_DMA_REQ_UART3_TX	 9
+#define MX31_DMA_REQ_UART3_RX	 8
+#define MX31_DMA_REQ_SIM	 5
+
 #define MX31_PROD_SIGNATURE		0x1	/* For MX31 */
 
 /* silicon revisions specific to i.MX31 */
arch/arm/plat-mxc/include/mach/mx35.h +26 -0
index af3038c..1835a80 100644
@@ -39,6 +39,9 @@
 #define MX35_SSI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x14000)
 #define MX35_ATA_DMA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
 #define MX35_MSHC1_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x24000)
+#define MX35_SPDIF_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x28000)
+#define MX35_ASRC_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x2c000)
+#define MX35_ESAI_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x34000)
 #define MX35_FEC_BASE_ADDR		0x50038000
 #define MX35_SPBA_CTRL_BASE_ADDR		(MX35_SPBA0_BASE_ADDR + 0x3c000)
 
@@ -173,6 +176,26 @@
 #define MX35_INT_EXT_WDOG	62
 #define MX35_INT_EXT_TV		63
 
+#define MX35_DMA_REQ_ASRC_DMA6	41
+#define MX35_DMA_REQ_ASRC_DMA5	40
+#define MX35_DMA_REQ_ASRC_DMA4	39
+#define MX35_DMA_REQ_ASRC_DMA3	38
+#define MX35_DMA_REQ_ASRC_DMA2	37
+#define MX35_DMA_REQ_ASRC_DMA1	36
+#define MX35_DMA_REQ_RSVD3	35
+#define MX35_DMA_REQ_RSVD2	34
+#define MX35_DMA_REQ_ESAI_TX	33
+#define MX35_DMA_REQ_ESAI_RX	32
+#define MX35_DMA_REQ_IPU	21
+#define MX35_DMA_REQ_RSVD1	20
+#define MX35_DMA_REQ_SPDIF_TX	13
+#define MX35_DMA_REQ_SPDIF_RX	12
+#define MX35_DMA_REQ_UART3_TX	11
+#define MX35_DMA_REQ_UART3_RX	10
+#define MX35_DMA_REQ_MSHC	 5
+#define MX35_DMA_REQ_DPTC	 1
+#define MX35_DMA_REQ_DVFS	 1
+
 #define MX35_PROD_SIGNATURE		0x1	/* For MX31 */
 
 /* silicon revisions specific to i.MX31 */
@@ -207,6 +230,9 @@
 #define MXC_INT_MLB MX35_INT_MLB
 #define MXC_INT_SPDIF MX35_INT_SPDIF
 #define MXC_INT_FEC MX35_INT_FEC
+#define SPDIF_BASE_ADDR MX35_SPDIF_BASE_ADDR
+#define ASRC_BASE_ADDR MX35_ASRC_BASE_ADDR
+#define ESAI_BASE_ADDR MX35_ESAI_BASE_ADDR
 #endif
 
 #endif /* ifndef __MACH_MX35_H__ */
arch/arm/plat-mxc/include/mach/mx3x.h +29 -0
index 7a356de..a725daf 100644
@@ -197,6 +197,35 @@
 	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
 
 /*
+ * DMA request assignments
+ */
+#define MX3x_DMA_REQ_ECT	31
+#define MX3x_DMA_REQ_NFC	30
+#define MX3x_DMA_REQ_SSI1_TX1	29
+#define MX3x_DMA_REQ_SSI1_RX1	28
+#define MX3x_DMA_REQ_SSI1_TX2	27
+#define MX3x_DMA_REQ_SSI1_RX2	26
+#define MX3x_DMA_REQ_SSI2_TX1	25
+#define MX3x_DMA_REQ_SSI2_RX1	24
+#define MX3x_DMA_REQ_SSI2_TX2	23
+#define MX3x_DMA_REQ_SSI2_RX2	22
+#define MX3x_DMA_REQ_UART1_TX	19
+#define MX3x_DMA_REQ_UART1_RX	18
+#define MX3x_DMA_REQ_UART2_TX	17
+#define MX3x_DMA_REQ_UART2_RX	16
+#define MX3x_DMA_REQ_EXTREQ1	15
+#define MX3x_DMA_REQ_EXTREQ2	14
+#define MX3x_DMA_REQ_CSPI1_TX	 9
+#define MX3x_DMA_REQ_CSPI1_RX	 8
+#define MX3x_DMA_REQ_CSPI2_TX	 7
+#define MX3x_DMA_REQ_CSPI2_RX	 6
+#define MX3x_DMA_REQ_ATA_RX	 4
+#define MX3x_DMA_REQ_ATA_TX	 3
+#define MX3x_DMA_REQ_ATA_TX_END	 2
+#define MX3x_DMA_REQ_CCM	 1
+#define MX3x_DMA_REQ_EXTREQ0	 0
+
+/*
  * Interrupt numbers
  */
 #define MX3x_INT_I2C3		3
Signature · 1 line
1.7.1
#20 lore raw

PATCH 6/8 ARM i.MX3: add dma request defines

Quoted 18 lines · Sascha Hauer
---
 arch/arm/plat-mxc/include/mach/mx31.h |   14 ++++++++++++++
 arch/arm/plat-mxc/include/mach/mx35.h |   26 ++++++++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/mx3x.h |   29 +++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 0 deletions(-)
arch/arm/plat-mxc/include/mach/mx31.h +3 -0
index afee3ab..dafe9b9 100644
@@ -197,6 +197,20 @@ static inline void mx31_setup_weimcs(size_t cs,
 #define MX31_INT_EXT_WDOG	62
 #define MX31_INT_EXT_TV		63
 
+#define MX31_DMA_REQ_SDHC2	21
+#define MX31_DMA_REQ_SDHC1	20
+#define MX31_DMA_REQ_FIRI_TX	17

arch/arm/plat-mxc/include/mach/mx31.h static inline void mx31_setup_weimcs(size_t cs, · line 212

Quoted 10 lines
arch/arm/plat-mxc/include/mach/mx31.h +10 -0
+#define MX31_DMA_REQ_FIRI_RX	16
+#define MX31_DMA_REQ_UART4_TX	13
+#define MX31_DMA_REQ_UART4_RX	12
+#define MX31_DMA_REQ_CSPI3_TX	11
+#define MX31_DMA_REQ_CSPI3_RX	10
+#define MX31_DMA_REQ_UART5_TX	11
+#define MX31_DMA_REQ_UART5_RX	10
+#define MX31_DMA_REQ_UART3_TX	 9
+#define MX31_DMA_REQ_UART3_RX	 8
+#define MX31_DMA_REQ_SIM	 5

Die w?rde ich andersherum hinschreiben, also aufsteigend nach Wert.

Quoted 31 lines
arch/arm/plat-mxc/include/mach/mx31.h +1 -0
+
 #define MX31_PROD_SIGNATURE		0x1	/* For MX31 */
 
 /* silicon revisions specific to i.MX31 */
arch/arm/plat-mxc/include/mach/mx35.h +12 -0
index af3038c..1835a80 100644
@@ -39,6 +39,9 @@
 #define MX35_SSI2_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x14000)
 #define MX35_ATA_DMA_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x20000)
 #define MX35_MSHC1_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x24000)
+#define MX35_SPDIF_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x28000)
+#define MX35_ASRC_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x2c000)
+#define MX35_ESAI_BASE_ADDR			(MX35_SPBA0_BASE_ADDR + 0x34000)
 #define MX35_FEC_BASE_ADDR		0x50038000
 #define MX35_SPBA_CTRL_BASE_ADDR		(MX35_SPBA0_BASE_ADDR + 0x3c000)
 
@@ -173,6 +176,26 @@
 #define MX35_INT_EXT_WDOG	62
 #define MX35_INT_EXT_TV		63
 
+#define MX35_DMA_REQ_ASRC_DMA6	41
+#define MX35_DMA_REQ_ASRC_DMA5	40
+#define MX35_DMA_REQ_ASRC_DMA4	39
+#define MX35_DMA_REQ_ASRC_DMA3	38
+#define MX35_DMA_REQ_ASRC_DMA2	37
+#define MX35_DMA_REQ_ASRC_DMA1	36
+#define MX35_DMA_REQ_RSVD3	35
+#define MX35_DMA_REQ_RSVD2	34
+#define MX35_DMA_REQ_ESAI_TX	33

arch/arm/plat-mxc/include/mach/mx35.h line 197

Quoted 10 lines
arch/arm/plat-mxc/include/mach/mx35.h +10 -0
+#define MX35_DMA_REQ_ESAI_RX	32
+#define MX35_DMA_REQ_IPU	21
+#define MX35_DMA_REQ_RSVD1	20
+#define MX35_DMA_REQ_SPDIF_TX	13
+#define MX35_DMA_REQ_SPDIF_RX	12
+#define MX35_DMA_REQ_UART3_TX	11
+#define MX35_DMA_REQ_UART3_RX	10
+#define MX35_DMA_REQ_MSHC	 5
+#define MX35_DMA_REQ_DPTC	 1
+#define MX35_DMA_REQ_DVFS	 1

Diese auch.

Quoted 39 lines
arch/arm/plat-mxc/include/mach/mx35.h +4 -0
+
 #define MX35_PROD_SIGNATURE		0x1	/* For MX31 */
 
 /* silicon revisions specific to i.MX31 */
@@ -207,6 +230,9 @@
 #define MXC_INT_MLB MX35_INT_MLB
 #define MXC_INT_SPDIF MX35_INT_SPDIF
 #define MXC_INT_FEC MX35_INT_FEC
+#define SPDIF_BASE_ADDR MX35_SPDIF_BASE_ADDR
+#define ASRC_BASE_ADDR MX35_ASRC_BASE_ADDR
+#define ESAI_BASE_ADDR MX35_ESAI_BASE_ADDR
 #endif
 
 #endif /* ifndef __MACH_MX35_H__ */
arch/arm/plat-mxc/include/mach/mx3x.h +17 -0
index 7a356de..a725daf 100644
@@ -197,6 +197,35 @@
 	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
 
 /*
+ * DMA request assignments
+ */
+#define MX3x_DMA_REQ_ECT	31
+#define MX3x_DMA_REQ_NFC	30
+#define MX3x_DMA_REQ_SSI1_TX1	29
+#define MX3x_DMA_REQ_SSI1_RX1	28
+#define MX3x_DMA_REQ_SSI1_TX2	27
+#define MX3x_DMA_REQ_SSI1_RX2	26
+#define MX3x_DMA_REQ_SSI2_TX1	25
+#define MX3x_DMA_REQ_SSI2_RX1	24
+#define MX3x_DMA_REQ_SSI2_TX2	23
+#define MX3x_DMA_REQ_SSI2_RX2	22
+#define MX3x_DMA_REQ_UART1_TX	19
+#define MX3x_DMA_REQ_UART1_RX	18
+#define MX3x_DMA_REQ_UART2_TX	17
+#define MX3x_DMA_REQ_UART2_RX	16
+#define MX3x_DMA_REQ_EXTREQ1	15

arch/arm/plat-mxc/include/mach/mx3x.h line 226

Quoted 10 lines
arch/arm/plat-mxc/include/mach/mx3x.h +10 -0
+#define MX3x_DMA_REQ_EXTREQ2	14
+#define MX3x_DMA_REQ_CSPI1_TX	 9
+#define MX3x_DMA_REQ_CSPI1_RX	 8
+#define MX3x_DMA_REQ_CSPI2_TX	 7
+#define MX3x_DMA_REQ_CSPI2_RX	 6
+#define MX3x_DMA_REQ_ATA_RX	 4
+#define MX3x_DMA_REQ_ATA_TX	 3
+#define MX3x_DMA_REQ_ATA_TX_END	 2
+#define MX3x_DMA_REQ_CCM	 1
+#define MX3x_DMA_REQ_EXTREQ0	 0

ditto, brauchen wir MX3x_... wirklich?

Quoted 14 lines
arch/arm/plat-mxc/include/mach/mx3x.h +2 -0
+
+/*
  * Interrupt numbers
  */
 #define MX3x_INT_I2C3		3
Signature · 7 lines
1.7.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 2 lines
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
author maintainer
#21 lore raw

PATCH 7/8 ARM i.MX3: add dma request resources to ssi/sdhc devices

In reply to Sascha Hauer
---
 arch/arm/mach-mx3/devices.c |   48 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)
arch/arm/mach-mx3/devices.c +48 -0
index 1c6578a..c0d5d98 100644
@@ -80,6 +80,10 @@ static struct resource mxcsdhc0_resources[] = {
 		.start = MXC_INT_MMC_SDHC1,
 		.end = MXC_INT_MMC_SDHC1,
 		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = MX31_DMA_REQ_SDHC1,
+		.end = MX31_DMA_REQ_SDHC1,
+		.flags = IORESOURCE_DMA,
 	},
 };
 
@@ -92,6 +96,10 @@ static struct resource mxcsdhc1_resources[] = {
 		.start = MXC_INT_MMC_SDHC2,
 		.end = MXC_INT_MMC_SDHC2,
 		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = MX31_DMA_REQ_SDHC2,
+		.end = MX31_DMA_REQ_SDHC2,
+		.flags = IORESOURCE_DMA,
 	},
 };
 
@@ -312,6 +320,26 @@ static struct resource imx_ssi_resources0[] = {
 		.start	= MX31_INT_SSI1,
 		.end	= MX31_INT_SSI1,
 		.flags	= IORESOURCE_IRQ,
+	}, {
+		.name	= "tx0",
+		.start	= MX3x_DMA_REQ_SSI1_TX1,
+		.end	= MX3x_DMA_REQ_SSI1_TX1,
+		.flags	= IORESOURCE_DMA,
+	}, {
+		.name	= "tx1",
+		.start	= MX3x_DMA_REQ_SSI1_TX2,
+		.end	= MX3x_DMA_REQ_SSI1_TX2,
+		.flags	= IORESOURCE_DMA,
+	}, {
+		.name	= "rx0",
+		.start	= MX3x_DMA_REQ_SSI1_RX1,
+		.end	= MX3x_DMA_REQ_SSI1_RX1,
+		.flags	= IORESOURCE_DMA,
+	}, {
+		.name	= "rx1",
+		.start	= MX3x_DMA_REQ_SSI1_RX2,
+		.end	= MX3x_DMA_REQ_SSI1_RX2,
+		.flags	= IORESOURCE_DMA,
 	},
 };
 
@@ -324,6 +352,26 @@ static struct resource imx_ssi_resources1[] = {
 		.start	= MX31_INT_SSI2,
 		.end	= MX31_INT_SSI2,
 		.flags	= IORESOURCE_IRQ,
+	}, {
+		.name	= "tx0",
+		.start	= MX3x_DMA_REQ_SSI2_TX1,
+		.end	= MX3x_DMA_REQ_SSI2_TX1,
+		.flags	= IORESOURCE_DMA,
+	}, {
+		.name	= "tx1",
+		.start	= MX3x_DMA_REQ_SSI2_TX2,
+		.end	= MX3x_DMA_REQ_SSI2_TX2,
+		.flags	= IORESOURCE_DMA,
+	}, {
+		.name	= "rx0",
+		.start	= MX3x_DMA_REQ_SSI2_RX1,
+		.end	= MX3x_DMA_REQ_SSI2_RX1,
+		.flags	= IORESOURCE_DMA,
+	}, {
+		.name	= "rx1",
+		.start	= MX3x_DMA_REQ_SSI2_RX2,
+		.end	= MX3x_DMA_REQ_SSI2_RX2,
+		.flags	= IORESOURCE_DMA,
 	},
 };
 
Signature · 1 line
1.7.1
author maintainer
#22 lore raw

PATCH 8/8 ASoC i.MX: switch to new DMA api

In reply to Sascha Hauer
---
 sound/soc/imx/Makefile          |    2 -
 sound/soc/imx/imx-pcm-dma-mx2.c |  177 +++++++++++++++------------------------
 sound/soc/imx/imx-ssi.c         |    8 +-
 3 files changed, 70 insertions(+), 117 deletions(-)
sound/soc/imx/Makefile +0 -2
index 2d20363..87cf03c 100644
@@ -1,9 +1,7 @@
 # i.MX Platform Support
 snd-soc-imx-objs := imx-ssi.o imx-pcm-fiq.o
 
-ifdef CONFIG_MACH_MX27
 snd-soc-imx-objs += imx-pcm-dma-mx2.o
-endif
 
 obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
 
sound/soc/imx/imx-pcm-dma-mx2.c +67 -110

304 lines not on this page · raw message

sound/soc/imx/imx-ssi.c +3 -5
index 4fd13d0..c187fe4 100644
@@ -655,12 +655,10 @@ static int imx_ssi_probe(struct platform_device *pdev)
 	dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id);
 	dai->private_data = ssi;
 
-	if ((cpu_is_mx27() || cpu_is_mx21()) &&
-			!(ssi->flags & IMX_SSI_USE_AC97) &&
-			(ssi->flags & IMX_SSI_DMA)) {
-		ssi->flags |= IMX_SSI_DMA;
+	if (!(ssi->flags & IMX_SSI_USE_AC97) &&
+			(ssi->flags & IMX_SSI_DMA))
 		platform = imx_ssi_dma_mx2_init(pdev, ssi);
-	} else
+	else
 		platform = imx_ssi_fiq_init(pdev, ssi);
 
 	imx_soc_platform.pcm_ops = platform->pcm_ops;
Signature · 1 line
1.7.1
#23 lore raw

PATCH 8/8 ASoC i.MX: switch to new DMA api

Quoted 1 line · Sascha Hauer

So, this is a little hard to read but overall this looks OK. The one thing I'd expect to see added is an implementation of delay() that includes the buffer in the SDMA controller.

Please always CC maintainers on patches. Even if you don't want to CC the list for some reason CCing the maintainers is still very helpful.

#24 lore raw
In reply to Sascha Hauer

Hi Sascha,

Quoted 5 lines · Sascha Hauer

Hi all,

Ever wondered what's hidden behind the tons of SDMA/iapi stuff in the Freescale kernel? It's a nice and convenient to use DMA engine. The following patches add support for it.

Nice!

Quoted 4 lines

git://git.pengutronix.de/git/imx/sdma-firmware.git

As the layout of the firmware is not given by fsl but by me it should be part of the review.

I don't have any comments on the layout but some general comments on files in sdma-firmware.git:

Some files are missing copyright and license information.

Shouldn't the gen_one() function do a free(name) also when everything is successfull? I.e. before return 0. Also, in case of errors after line 67, fclose(f) should be called.

Regards, Magnus