SDMA support for i.MX
Subsystems (6)
Sascha Hauer
maintainerHi 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
Sascha Hauer
maintainerPATCH 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
@@ -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
@@ -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
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
Signed-off-by Sascha Hauer <[email protected]>arch/arm/plat-mxc/dma.c new file +0
-0
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
Re: [PATCH 1/8] ARM i.MX dma: implement wrapper for dma functions
In reply to Sascha Hauer2010/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
Signed-off-by Sascha Hauer <[email protected]>(...)
(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
Sascha Hauer
maintainerRe: [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
Signed-off-by Sascha Hauer <[email protected]>(...)
+structimx_dma_operations{
+ ? ? ? int (*config_channel)(int channel, structimx_dma_config*cfg);
+ ? ? ? int (*setup_single)(int channel,dma_addr_tmem, intdma_length,
+ ? ? ? ? ? ? ? unsigned int dmamode);
+ ? ? ? int (*setup_sg)(int channel, struct scatterlist *sg,
+ ? ? ? ? ? ? ? ? ? ? ? unsigned int sgcount, unsigned intdma_length,
+ ? ? ? ? ? ? ? ? ? ? ? unsigned int dmamode);
Quoted 8 lines
Quoted 6 lines
+ ? ? ? void (*enable)(int channel);
+ ? ? ? void (*disable)(int channel);
+ ? ? ? int (*request)(enumimx_dma_prio);
+ ? ? ? void (*free)(int channel);
+ ? ? ? intnum_channels;
+};This is just getting *so* close to the
drivers/dmadmaengine 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/arminstead 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 |
Sascha Hauer
maintainerPATCH 2/8 ARM i.MX dma-mx1-mx2: use wrapper
In reply to Sascha HauerThis 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
@@ -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
@@ -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
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@@ -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
Sascha Hauer
maintainerPATCH 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@@ -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()usespr_debug()whileimx_dma_disableusespr_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 |
Sascha Hauer
maintainerPATCH 3/8 mxcmmc: use new dma api
In reply to Sascha HauerThis 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
@@ -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
Sascha Hauer
maintainerPATCH 4/8 ARM i.MX: add SDMA driver
In reply to Sascha HauerThis 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
@@ -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
@@ -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
@@ -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
@@ -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
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@@ -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
...
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
Sascha Hauer
maintainerPATCH 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 |
PATCH 4/8 ARM i.MX: add SDMA driver
In reply to Sascha HauerHi 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_firmwaremechanism. 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.
Signed-off-by Sascha Hauer <[email protected]>--- 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
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/dmadmaengine 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
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/dmadmaengine 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 ___________________________________________________________
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/dmadmaengine 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.
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/dmadmaengine 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
PATCH 4/8 ARM i.MX: add SDMA driver
In reply to Sascha HauerQuoted 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_firmwaremechanism. 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.
Signed-off-by Sascha Hauer <[email protected]>--- 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.carch/arm/mach-mx3/Kconfig +2
-0@@ -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@@ -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. endifarch/arm/plat-mxc/Makefile +1
-0@@ -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.oarch/arm/plat-mxc/include/mach/sdma.h new file +0
-0
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@@ -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/ |
Sascha Hauer
maintainerPATCH 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
@@ -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
@@ -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
@@ -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
Sascha Hauer
maintainerPATCH 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
@@ -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
@@ -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
@@ -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
PATCH 6/8 ARM i.MX3: add dma request defines
Quoted 18 lines · Sascha Hauer
Signed-off-by Sascha Hauer <[email protected]>--- 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@@ -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@@ -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@@ -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 3Signature · 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/ |
Sascha Hauer
maintainerPATCH 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
@@ -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
Sascha Hauer
maintainerPATCH 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
@@ -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
@@ -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
PATCH 8/8 ASoC i.MX: switch to new DMA api
Quoted 1 line · Sascha Hauer
Signed-off-by Sascha Hauer <[email protected]>
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.
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.gitAs 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