ARM: pxa: move core and drivers to dmaengine
Subsystems (16)
cover ARM: pxa: move core and drivers to dmaengine
I've been working on teaching the mmp-pdma driver more functions and porting tree-wide scattered pxa specific drivers over to dmaengine implementations. I posted the first round of patches for mmp-pdma here:
http://marc.info/?l=linux-arm-kernel&m=137587082530228
With the following patches applied, I can boot a PXA3xx board boot with all DMA runtime information determined from DT, using pxa3xx-nand, pxamci and audio components (cyclic DMA).
However, the transition is quite intrusive and spans across several subsystem, and due to the nature of the current pxa DMA implementation, it cannot be gap-less. All drivers currently request an exclusive channel via code in arch/arm/plat-pxa/dma.c and then do direct register modifications regarding their obtained channel. We can't allow this with the mmp-pdma driver of course, and I also have no idea how to provide sane stubs for the existing hooks which end up in dmaengine calls.
Hence, all drivers have to be ported over in one series, and all these changes should be merged by one pull request eventually in order to prevent both build and functional breakage. Haojian's repository seems most suitable for that, as he's the PXA maintainer.
What I currently got with respect to existing drivers is the following:
* pxa3xx-nand:
ported (with an amended and rebased patch from Zhangfei Gao) and successfully tested.
* pxamci (mmc):
ported and successfully tested
* pxa-pcm-lib (audio) and pxa-ssp:
ported and successfully tested
* spi:
Code to make this driver compatible with dmaengine was already provided by Mika Westerberg, so we can now just purge the legacy bits. I personally only compile-tested this one.
* pxa-serial:
#if0'ed legacy was removed that wouldn't even compile when enabled. This can be re-done at some point if anyone's interested.
* pata-pxa:
I ported the driver over which was simple and straight forward, but I lack hardware to actually test it. Maybe Marek Vasut, the original author can help here?
* pxaficp_ir (IRDA):
I also ported this driver, but I can't test it either. Someone with access to hardware would greatly help here with a quick test.
* smsc911x:
There are three(!) SMSC 911x driver in the tree right now, and two of them have code for PXA-DMA. I'm not sure which of these are actually actively used in DMA mode, but I blindly ported over the code and compile-tested it.
* camera driver:
I started the transition, but I'm not sure how much sense that makes without access to the hardware. I'd much appreciate if anyone could volunteer for this piece; I'll happily share what I got so far. Sascha, Sachin, Guennadi?
So, to summarize: pata-pxa, pxaficp_ir and smsc911x need testing, and the camera driver still needs to be ported.
The transition path of my patch set is as follows:
1. port over all the drivers individually, breaking them functionally because at runtime, they DMA channel allocation will fail. But they will compile.
2. remove the init calls to the dma subsystem in both mach-pxa and mach-mmp (mach-mmp was only compile-tested) and instanciate the mmp-pdma device as regular platform_device.
3. remove the old implementation including its header file that has served us so well for 12+ years. Sorry, Nicolas ;)
Regarding the procedure, my proposal is that many people give their Tested-by and Acked-by, I'll respin my series a couple of times and eventually Haojian can take it.
Prerequisities:
* Linux-3.11-rc4
* Ezequiel Garcia's pxa3xx-patches:
http://lists.infradead.org/pipermail/linux-mtd/2013-August/047862.html * My mmp-pdma patches: http://marc.info/?l=linux-arm-kernel&m=137587082530228
FWIW, the patches can also be found in this tree, but be aware that I will rebase the commits frequently:
https://github.com/zonque/linux/commits/pxa-dma
Thanks,
Daniel
Daniel Mack (19):
mtd: pxa3xx-nand: use mmp_pdma_filter_fn and
dma_request_slave_channel_compat
ARM: pxa: ssp: add shortcut for &pdev->dev
ARM: pxa: ssp: add DT bindings
ARM: pxa: ssp: use devm_ functions
tty: serial: pxa: remove old cruft
spi: spi-pxa2xx: remove legacy PXA DMA bits
mmc: host: pxamci: switch over to dmaengine use
ata: pdata_pxa: migrate over to dmaengine usage
net: irda: pxaficp_ir: switch to dmaengine
net: smc91x.c: switch to generic buf-to-buf DMA offload
net: smc911x.c: switch to dmaengine API
ASoC: pxa: pxa-ssp: add DT bindings
ASoC: pxa: use snd_dmaengine_dai_dma_data
ASoC: pxa: pxa-ssp: set dma filter data from startup hook
ASoC: pxa: add DT bindings for pxa2xx-pcm
ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
ARM: pxa: register static mmp_pdma device
ARM: mmp: register static mmp_pdma device
ARM: pxa: remove old DMA implementation
Zhangfei Gao (1):
mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
.../devicetree/bindings/serial/mrvl,pxa-ssp.txt | 43 ++ .../devicetree/bindings/sound/mrvl,pxa-ssp.txt | 7 + .../devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt | 15 + arch/arm/mach-mmp/mmp2.c | 11 +- arch/arm/mach-mmp/pxa168.c | 11 +- arch/arm/mach-mmp/pxa910.c | 11 +- arch/arm/mach-pxa/devices.c | 26 ++ arch/arm/mach-pxa/devices.h | 1 + arch/arm/mach-pxa/include/mach/dma.h | 21 - arch/arm/mach-pxa/pxa25x.c | 9 +- arch/arm/mach-pxa/pxa27x.c | 9 +- arch/arm/mach-pxa/pxa3xx.c | 11 +- arch/arm/plat-pxa/Makefile | 2 - arch/arm/plat-pxa/dma.c | 391 ---------------- arch/arm/plat-pxa/include/plat/dma.h | 85 ---- arch/arm/plat-pxa/ssp.c | 144 +++--- drivers/ata/pata_pxa.c | 172 +++----- drivers/mmc/host/pxamci.c | 188 ++++---- drivers/mtd/nand/pxa3xx_nand.c | 130 +++--- drivers/net/ethernet/smsc/smc911x.c | 80 ++-- drivers/net/ethernet/smsc/smc911x.h | 83 ++-- drivers/net/ethernet/smsc/smc91x.c | 40 +- drivers/net/ethernet/smsc/smc91x.h | 71 ++- drivers/net/irda/pxaficp_ir.c | 242 ++++++---- drivers/spi/Kconfig | 9 +- drivers/spi/Makefile | 1 - drivers/spi/spi-pxa2xx-pxadma.c | 490 --------------------- drivers/spi/spi-pxa2xx.h | 6 +- drivers/tty/serial/pxa.c | 25 -- include/linux/spi/pxa2xx_spi.h | 1 - include/sound/pxa2xx-lib.h | 8 - sound/arm/Kconfig | 1 + sound/arm/pxa2xx-ac97.c | 26 +- sound/arm/pxa2xx-pcm-lib.c | 177 ++------ sound/arm/pxa2xx-pcm.c | 15 +- sound/arm/pxa2xx-pcm.h | 9 +- sound/soc/pxa/mmp-pcm.c | 8 +- sound/soc/pxa/mmp-sspa.c | 11 +- sound/soc/pxa/pxa-ssp.c | 51 ++- sound/soc/pxa/pxa2xx-ac97.c | 67 +-- sound/soc/pxa/pxa2xx-i2s.c | 28 +- sound/soc/pxa/pxa2xx-pcm.c | 43 +- 42 files changed, 921 insertions(+), 1858 deletions(-) create mode 100644 Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt create mode 100644 Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt create mode 100644 Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt delete mode 100644 arch/arm/mach-pxa/include/mach/dma.h delete mode 100644 arch/arm/plat-pxa/dma.c delete mode 100644 arch/arm/plat-pxa/include/plat/dma.h delete mode 100644 drivers/spi/spi-pxa2xx-pxadma.c
Signature · 1 line
1.8.3.1
PATCH 1/20 mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
From: Zhangfei Gao <[email protected]>
[zonque at gmail.com: rebased in top of l2-mtd.git. The newly introduced ARCH_HAS_DMA hack was changed into a check for CONFIG_HAS_DMA]
--- drivers/mtd/nand/pxa3xx_nand.c | 115 ++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 52 deletions(-)
drivers/mtd/nand/pxa3xx_nand.c +63 -52
@@ -24,14 +24,7 @@#include <linux/slab.h> #include <linux/of.h> #include <linux/of_device.h> - -#if defined(CONFIG_ARCH_PXA ) || defined(CONFIG_ARCH_MMP ) -#define ARCH_HAS_DMA -#endif - -#ifdef ARCH_HAS_DMA -#include <mach/dma.h> -#endif +#include <linux/dmaengine.h> #include <linux/platform_data/mtd-nand-pxa3xx.h>
@@ -172,9 +165,7 @@ struct pxa3xx_nand_info {unsigned char *data_buff;unsigned char *oob_buff;dma_addr_t data_buff_phys; -int data_dma_ch; -struct pxa_dma_desc *data_desc; -dma_addr_t data_desc_addr; +struct dma_chan *data_dma_ch;struct pxa3xx_nand_host *host[NUM_CHIP_SELECT ];unsigned int state;
@@ -388,25 +379,39 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) } } -#ifdef ARCH_HAS_DMA +#ifdef CONFIG_HAS_DMA +static void dma_complete_func (void *data) +{ +struct pxa3xx_nand_info *info = data; + + info->state =STATE_DMA_DONE ; +} +static void start_data_dma (struct pxa3xx_nand_info *info) { -struct pxa_dma_desc *desc = info->data_desc; +struct dma_device *dma_dev; +struct dma_async_tx_descriptor *tx =NULL ; +dma_addr_t dma_src_addr, dma_dst_addr; +dma_cookie_t cookie;int dma_len =ALIGN (info->data_size + info->oob_size,32 ); +struct dma_slave_config conf; - desc->ddadr =DDADR_STOP ; - desc->dcmd =DCMD_ENDIRQEN |DCMD_WIDTH4 |DCMD_BURST32 | dma_len; + dma_dev = info->data_dma_ch->device;switch (info->state) {case STATE_DMA_WRITING : - desc->dsadr = info->data_buff_phys; - desc->dtadr = info->mmio_phys +NDDB ; - desc->dcmd |=DCMD_INCSRCADDR |DCMD_FLOWTRG ; + dma_src_addr = info->data_buff_phys; + dma_dst_addr = info->mmio_phys +NDDB ; + conf.direction =DMA_MEM_TO_DEV ; + conf.dst_maxburst =32 ; + conf.dst_addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES ;break ;case STATE_DMA_READING : - desc->dtadr = info->data_buff_phys; - desc->dsadr = info->mmio_phys +NDDB ; - desc->dcmd |=DCMD_INCTRGADDR |DCMD_FLOWSRC ; + dma_src_addr = info->mmio_phys +NDDB ; + dma_dst_addr = info->data_buff_phys; + conf.direction =DMA_DEV_TO_MEM ; + conf.src_maxburst =32 ; + conf.src_addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES ;break ;default : dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
@@ -414,26 +419,25 @@ static void start_data_dma(struct pxa3xx_nand_info *info) BUG(); } -DRCMR (info->drcmr_dat) =DRCMR_MAPVLD | info->data_dma_ch; -DDADR (info->data_dma_ch) = info->data_desc_addr; -DCSR (info->data_dma_ch) |=DCSR_RUN ; -} - -static void pxa3xx_nand_data_dma_irq (int channel,void *data) -{ -struct pxa3xx_nand_info *info = data; -uint32_t dcsr; + conf.slave_id = info->drcmr_dat; +dmaengine_slave_config (info->data_dma_ch, &conf); + tx = dma_dev->device_prep_dma_memcpy (info->data_dma_ch, dma_dst_addr, + dma_src_addr, dma_len,0 ); +if (!tx) { +dev_err (&info->pdev->dev,"Failed to prepare DMA memcpy\n" ); +return ; + } - dcsr =DCSR (channel); -DCSR (channel) = dcsr; + tx->callback = dma_complete_func; + tx->callback_param = info; -if (dcsr &DCSR_BUSERR ) { - info->retcode =ERR_DMABUSERR ; + cookie = tx->tx_submit (tx); +if (dma_submit_error (cookie)) { +dev_err (&info->pdev->dev,"Failed to do DMA tx_submit\n" ); +return ; } - info->state =STATE_DMA_DONE ; -enable_int (info,NDCR_INT_MASK ); -nand_writel (info,NDSR ,NDSR_WRDREQ |NDSR_RDDREQ ); +dma_async_issue_pending (info->data_dma_ch); }#else static void start_data_dma (struct pxa3xx_nand_info *info)
@@ -455,6 +459,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) } status =nand_readl (info,NDSR ); +nand_writel (info,NDSR , status);if (status &NDSR_DBERR ) info->retcode =ERR_DBERR ;
@@ -463,7 +468,6 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)if (status & (NDSR_RDDREQ |NDSR_WRDREQ )) {/* whether use dma to transfer data */ if (info->use_dma) { -disable_int (info,NDCR_INT_MASK ); info->state = (status &NDSR_RDDREQ ) ?STATE_DMA_READING :STATE_DMA_WRITING ;start_data_dma (info);
@@ -792,6 +796,9 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)struct pxa3xx_nand_info *info = host->info_data;int real_len =min_t (size_t, len, info->buf_count - info->buf_start); +if (len > mtd->oobsize) + info->use_dma = use_dma; +memcpy (buf, info->data_buff + info->buf_start, real_len); info->buf_start += real_len; }
@@ -803,6 +810,9 @@ static void pxa3xx_nand_write_buf(struct mtd_info *mtd,struct pxa3xx_nand_info *info = host->info_data;int real_len =min_t (size_t, len, info->buf_count - info->buf_start); +if (len > mtd->oobsize) + info->use_dma = use_dma; +memcpy (info->data_buff + info->buf_start, buf, real_len); info->buf_start += real_len; }
@@ -908,11 +918,11 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)*/ #define MAX_BUFF_SIZE (PAGE_SIZE*2) -#ifdef ARCH_HAS_DMA +#ifdef CONFIG_HAS_DMA static int pxa3xx_nand_init_buff (struct pxa3xx_nand_info *info) {struct platform_device *pdev = info->pdev; -int data_desc_offset =MAX_BUFF_SIZE -sizeof (struct pxa_dma_desc ); +dma_cap_mask_t mask;if (use_dma ==0 ) { info->data_buff =kmalloc (MAX_BUFF_SIZE ,GFP_KERNEL );
@@ -928,26 +938,27 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)return -ENOMEM ; } - info->data_desc = (void *)info->data_buff + data_desc_offset; - info->data_desc_addr = info->data_buff_phys + data_desc_offset; - - info->data_dma_ch =pxa_request_dma ("nand-data" ,DMA_PRIO_LOW , - pxa3xx_nand_data_dma_irq, info); -if (info->data_dma_ch <0 ) { -dev_err (&pdev->dev,"failed to request data dma\n" ); -dma_free_coherent (&pdev->dev,MAX_BUFF_SIZE , - info->data_buff, info->data_buff_phys); -return info->data_dma_ch; +dma_cap_zero (mask); +dma_cap_set (DMA_MEMCPY , mask); + info->data_dma_ch =dma_request_channel (mask,NULL ,NULL ); +if (!info->data_dma_ch) { +dev_info (&pdev->dev,"Failed to request DMA channel\n" ); + goto dma_request_fail; }return 0 ; + +dma_request_fail: +dma_free_coherent (&pdev->dev,MAX_BUFF_SIZE , + info->data_buff, info->data_buff_phys); +return -EAGAIN ; }static void pxa3xx_nand_free_buff (struct pxa3xx_nand_info *info) {struct platform_device *pdev = info->pdev;if (use_dma) { -pxa_free_dma (info->data_dma_ch); +dma_release_channel (info->data_dma_ch);dma_free_coherent (&pdev->dev,MAX_BUFF_SIZE , info->data_buff, info->data_buff_phys); }else {
@@ -1295,7 +1306,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)struct pxa3xx_nand_info *info;int ret, cs, probe_success; -#ifndef ARCH_HAS_DMA +#ifndef CONFIG_HAS_DMA if (use_dma) { use_dma =0 ; dev_warn(&pdev->dev,
Signature · 1 line
1.8.3.1
PATCH 1/20 mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
Hi Daniel,
Quoted 5 lines · Daniel Mack
From: Zhangfei Gao <[email protected]>
[zonque at gmail.com: rebased in top of l2-mtd.git. The newly introduced
ARCH_HAS_DMAhack was changed into a check forCONFIG_HAS_DMA]
Are you sure you need to introduce the CONFIG_HAS_DMA ifdef?
The reason I introduced the ARCH_HAS_DMA macro was to avoid including the "mach/dma.h" header. Now that you've removed it, I don't think this driver can be used in any platform where CONFIG_HAS_DMA=n.
Signature · 3 lines
Ezequiel Garc?a, Free Electrons Embedded Linux, Kernel and Android Engineering http://free-electrons.com
PATCH 1/20 mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
Quoted 9 lines · Ezequiel Garcia
Hi Daniel,
Quoted 5 lines · Daniel Mack
From: Zhangfei Gao <[email protected]>
[zonque at gmail.com: rebased in top of l2-mtd.git. The newly introduced
ARCH_HAS_DMAhack was changed into a check forCONFIG_HAS_DMA]
Quoted 5 lines
Are you sure you need to introduce the
CONFIG_HAS_DMAifdef?The reason I introduced the
ARCH_HAS_DMAmacro was to avoid including the "mach/dma.h" header. Now that you've removed it, I don't think this driver can be used in any platform whereCONFIG_HAS_DMA=n.
Well, yes it can, or at least you could decide to use it without DMA on PXA/MMP. The idea of CONFIG_HAS_DMA is to save binary size.
Daniel
PATCH 1/20 mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
Quoted 10 lines · Daniel Mack
Quoted 9 lines · Ezequiel Garcia
Hi Daniel,
Quoted 5 lines · Daniel Mack
From: Zhangfei Gao <[email protected]>
[zonque at gmail.com: rebased in top of l2-mtd.git. The newly introduced
ARCH_HAS_DMAhack was changed into a check forCONFIG_HAS_DMA]
Quoted 9 lines
Quoted 5 lines
Are you sure you need to introduce the
CONFIG_HAS_DMAifdef?The reason I introduced the
ARCH_HAS_DMAmacro was to avoid including the "mach/dma.h" header. Now that you've removed it, I don't think this driver can be used in any platform whereCONFIG_HAS_DMA=n.Well, yes it can, or at least you could decide to use it without DMA on PXA/MMP. The idea of
CONFIG_HAS_DMAis to save binary size.
Ok, I see.
I think maybe we will have to add something to force use_dma=0 when "armada370-nand" is used. AFAIK, the dmaengine does not support the kind of DMA operations this driver needs.
I can take care of that if this patchset hits mainline before we have something really usable for Armada 370/XP NAND.
Signature · 3 lines
Ezequiel Garc?a, Free Electrons Embedded Linux, Kernel and Android Engineering http://free-electrons.com
PATCH 1/20 mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
Quoted 21 lines · Ezequiel Garcia
Quoted 10 lines · Daniel Mack
Quoted 9 lines · Ezequiel Garcia
Hi Daniel,
Quoted 5 lines · Daniel Mack
From: Zhangfei Gao <[email protected]>
[zonque at gmail.com: rebased in top of l2-mtd.git. The newly introduced
ARCH_HAS_DMAhack was changed into a check forCONFIG_HAS_DMA]Quoted 9 lines
Quoted 5 lines
Are you sure you need to introduce the
CONFIG_HAS_DMAifdef?The reason I introduced the
ARCH_HAS_DMAmacro was to avoid including the "mach/dma.h" header. Now that you've removed it, I don't think this driver can be used in any platform whereCONFIG_HAS_DMA=n.Well, yes it can, or at least you could decide to use it without DMA on PXA/MMP. The idea of
CONFIG_HAS_DMAis to save binary size.
Quoted 5 lines
Ok, I see.
I think maybe we will have to add something to force use_dma=0 when "armada370-nand" is used. AFAIK, the dmaengine does not support the kind of DMA operations this driver needs.
What kind of operation is that?
Quoted 2 lines
I can take care of that if this patchset hits mainline before we have something really usable for Armada 370/XP NAND.
Ok :)
Daniel
PATCH 2/20 mtd: pxa3xx-nand: use mmp_pdma_filter_fn and dma_request_slave_channel_compat
In reply to Daniel Mack--- drivers/mtd/nand/pxa3xx_nand.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
drivers/mtd/nand/pxa3xx_nand.c +7 -12
@@ -25,6 +25,7 @@#include <linux/of.h> #include <linux/of_device.h> #include <linux/dmaengine.h> +#include <linux/dma/mmp-pdma.h> #include <linux/platform_data/mtd-nand-pxa3xx.h>
@@ -396,6 +397,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)int dma_len =ALIGN (info->data_size + info->oob_size,32 );struct dma_slave_config conf; +memset (&conf,0 ,sizeof (conf)); dma_dev = info->data_dma_ch->device;switch (info->state) {
@@ -419,7 +421,6 @@ static void start_data_dma(struct pxa3xx_nand_info *info)BUG (); } - conf.slave_id = info->drcmr_dat;dmaengine_slave_config (info->data_dma_ch, &conf); tx = dma_dev->device_prep_dma_memcpy (info->data_dma_ch, dma_dst_addr, dma_src_addr, dma_len,0 );
@@ -940,7 +941,10 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)dma_cap_zero (mask);dma_cap_set (DMA_MEMCPY , mask); - info->data_dma_ch =dma_request_channel (mask,NULL ,NULL ); + info->data_dma_ch = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &info->drcmr_dat, + &pdev->dev,"data" );if (!info->data_dma_ch) {dev_info (&pdev->dev,"Failed to request DMA channel\n" ); goto dma_request_fail;
@@ -1143,16 +1147,7 @@ static int alloc_nand_resource(struct platform_device *pdev)return ret;if (use_dma) { -/* -* This is a dirty hack to make this driver work from -* devicetree bindings. It can be removed once we have -* a prober DMA controller framework for DT. -*/ -if (pdev->dev.of_node && -of_machine_is_compatible ("marvell,pxa3xx" )) { - info->drcmr_dat =97 ; - info->drcmr_cmd =99 ; - }else { +if (!pdev->dev.of_node) { r =platform_get_resource (pdev,IORESOURCE_DMA ,0 );if (r ==NULL ) { dev_err(&pdev->dev,
Signature · 1 line
1.8.3.1
PATCH 3/20 ARM: pxa: ssp: add shortcut for &pdev->dev
In reply to Daniel MackNo functional change, just a cosmetic cleanup.
--- arch/arm/plat-pxa/ssp.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
arch/arm/plat-pxa/ssp.c +9 -8
@@ -77,16 +77,17 @@ static int pxa_ssp_probe(struct platform_device *pdev)const struct platform_device_id *id =platform_get_device_id (pdev);struct resource *res;struct ssp_device *ssp; +struct device *dev = &pdev->dev;int ret =0 ; ssp =kzalloc (sizeof (struct ssp_device ),GFP_KERNEL );if (ssp ==NULL ) { -dev_err (&pdev->dev,"failed to allocate memory" ); +dev_err (dev,"failed to allocate memory" );return -ENOMEM ; } ssp->pdev = pdev; - ssp->clk =clk_get (&pdev->dev,NULL ); + ssp->clk =clk_get (dev,NULL );if (IS_ERR (ssp->clk)) { ret =PTR_ERR (ssp->clk); goto err_free;
@@ -94,7 +95,7 @@ static int pxa_ssp_probe(struct platform_device *pdev) res =platform_get_resource (pdev,IORESOURCE_DMA ,0 );if (res ==NULL ) { -dev_err (&pdev->dev,"no SSP RX DRCMR defined\n" ); +dev_err (dev,"no SSP RX DRCMR defined\n" ); ret = -ENODEV ; goto err_free_clk; }
@@ -102,7 +103,7 @@ static int pxa_ssp_probe(struct platform_device *pdev) res =platform_get_resource (pdev,IORESOURCE_DMA ,1 );if (res ==NULL ) { -dev_err (&pdev->dev,"no SSP TX DRCMR defined\n" ); +dev_err (dev,"no SSP TX DRCMR defined\n" ); ret = -ENODEV ; goto err_free_clk; }
@@ -110,7 +111,7 @@ static int pxa_ssp_probe(struct platform_device *pdev) res =platform_get_resource (pdev,IORESOURCE_MEM ,0 );if (res ==NULL ) { -dev_err (&pdev->dev,"no memory resource defined\n" ); +dev_err (dev,"no memory resource defined\n" ); ret = -ENODEV ; goto err_free_clk; }
@@ -118,7 +119,7 @@ static int pxa_ssp_probe(struct platform_device *pdev) res =request_mem_region (res->start,resource_size (res), pdev->name);if (res ==NULL ) { -dev_err (&pdev->dev,"failed to request memory resource\n" ); +dev_err (dev,"failed to request memory resource\n" ); ret = -EBUSY ; goto err_free_clk; }
@@ -127,14 +128,14 @@ static int pxa_ssp_probe(struct platform_device *pdev) ssp->mmio_base =ioremap (res->start,resource_size (res));if (ssp->mmio_base ==NULL ) { -dev_err (&pdev->dev,"failed to ioremap() registers\n" ); +dev_err (dev,"failed to ioremap() registers\n" ); ret = -ENODEV ; goto err_free_mem; } ssp->irq =platform_get_irq (pdev,0 );if (ssp->irq <0 ) { -dev_err (&pdev->dev,"no IRQ resource defined\n" ); +dev_err (dev,"no IRQ resource defined\n" ); ret = -ENODEV ; goto err_free_io; }
Signature · 1 line
1.8.3.1
PATCH 3/20 ARM: pxa: ssp: add shortcut for &pdev->dev
Quoted 7 lines · Daniel Mack
No functional change, just a cosmetic cleanup.
Signed-off-by Daniel Mack <[email protected]>---
arch/arm/plat-pxa/ssp.c static int pxa_ssp_probe(struct platform_device *pdev) · line 85
Quoted 10 lines
arch/arm/plat-pxa/ssp.c +2
-1@@ -77,16 +77,17 @@ static int pxa_ssp_probe(struct platform_device *pdev)const struct platform_device_id *id =platform_get_device_id (pdev);struct resource *res;struct ssp_device *ssp; +struct device *dev = &pdev->dev;int ret =0 ; ssp =kzalloc (sizeof (struct ssp_device ),GFP_KERNEL );if (ssp ==NULL ) { -dev_err (&pdev->dev,"failed to allocate memory" ); +dev_err (dev,"failed to allocate memory" );
Two options here: either remove the message entirely (I believe kzalloc will complain loudly if the allocation fails) or at least add a newline at the end of it!
arch/arm/plat-pxa/ssp.c static int pxa_ssp_probe(struct platform_device *pdev) · line 89
Quoted 4 lines
arch/arm/plat-pxa/ssp.c +0
-0return -ENOMEM ; } ssp->pdev = pdev;
...
Brian
PATCH 3/20 ARM: pxa: ssp: add shortcut for &pdev->dev
Quoted 14 lines · Brian Norris
Quoted 13 lines · Daniel Mack
No functional change, just a cosmetic cleanup.
Signed-off-by Daniel Mack <[email protected]>---
arch/arm/plat-pxa/ssp.c +1
-0@@ -77,16 +77,17 @@ static int pxa_ssp_probe(struct platform_device *pdev)const struct platform_device_id *id =platform_get_device_id (pdev);struct resource *res;struct ssp_device *ssp; +struct device *dev = &pdev->dev;int ret =0 ;
Quoted 8 lines
arch/arm/plat-pxa/ssp.c static int pxa_ssp_probe(struct platform_device *pdev) · line 85
Quoted 4 lines
arch/arm/plat-pxa/ssp.c +1
-1ssp =kzalloc (sizeof (struct ssp_device ),GFP_KERNEL );if (ssp ==NULL ) { -dev_err (&pdev->dev,"failed to allocate memory" ); +dev_err (dev,"failed to allocate memory" );Two options here: either remove the message entirely (I believe kzalloc will complain loudly if the allocation fails) or at least add a newline at the end of it!
I think only to former is the right option.
Signature · 2 lines
Best Regards, Artem Bityutskiy
PATCH 3/20 ARM: pxa: ssp: add shortcut for &pdev->dev
Quoted 24 lines · Artem Bityutskiy
Quoted 14 lines · Brian Norris
Quoted 13 lines · Daniel Mack
No functional change, just a cosmetic cleanup.
Signed-off-by Daniel Mack <[email protected]>---
arch/arm/plat-pxa/ssp.c +1
-0@@ -77,16 +77,17 @@ static int pxa_ssp_probe(struct platform_device *pdev)const struct platform_device_id *id =platform_get_device_id (pdev);struct resource *res;struct ssp_device *ssp; +struct device *dev = &pdev->dev;int ret =0 ;Quoted 8 lines
arch/arm/plat-pxa/ssp.c static int pxa_ssp_probe(struct platform_device *pdev) · line 85
Quoted 4 lines
arch/arm/plat-pxa/ssp.c +1
-1ssp =kzalloc (sizeof (struct ssp_device ),GFP_KERNEL );if (ssp ==NULL ) { -dev_err (&pdev->dev,"failed to allocate memory" ); +dev_err (dev,"failed to allocate memory" );Two options here: either remove the message entirely (I believe kzalloc will complain loudly if the allocation fails) or at least add a newline at the end of it!
Quoted 2 lines
I think only to former is the right option.
Ok, I've added a patch for this to my series.
Thanks!
Daniel
PATCH 4/20 ARM: pxa: ssp: add DT bindings
In reply to Daniel MackThis patch adds DT bindings for the pxa ssp driver.
--- .../devicetree/bindings/serial/mrvl,pxa-ssp.txt | 43 ++++++++++ arch/arm/plat-pxa/ssp.c | 93 +++++++++++++++++----- 2 files changed, 115 insertions(+), 21 deletions(-) create mode 100644 Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt new file +43 -0
@@ -0,0 +1,43 @@ +Device tree bindings for Marvell PXA SSP ports + +Required properties: + + - compatible: Must be one of + mrvl,pxa25x-ssp + mvrl,pxa25x-nssp + mrvl,pxa27x-ssp + mrvl,pxa3xx-ssp + mvrl,pxa168-ssp + mrvl,pxa910-ssp + mrvl,ce4100-ssp + mrvl,lpss-ssp + + - reg: The memory base + + +Example for PXA3xx: + + ssp at 41000000 { + compatible = "mrvl,pxa27x-ssp"; + reg = <0x41000000 0x40>; + interrupts = <24>; + }; + + ssp at 41700000 { + compatible = "mrvl,pxa27x-ssp"; + reg = <0x41700000 0x40>; + interrupts = <16>; + }; + + ssp at 41900000 { + compatible = "mrvl,pxa27x-ssp"; + reg = <0x41900000 0x40>; + interrupts = <0>; + }; + + ssp at 41a00000 { + compatible = "mrvl,pxa27x-ssp"; + reg = <0x41a00000 0x40>; + interrupts = <13>; + }; +
arch/arm/plat-pxa/ssp.c +72 -21
134 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 4/20 ARM: pxa: ssp: add DT bindings
Quoted 7 lines · Daniel Mack
Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt new file +7
-0+Device tree bindings for Marvell PXA SSP ports + +Required properties: + + - compatible: Must be one of + mrvl,pxa25x-ssp + mvrl,pxa25x-nssp
Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt line 17
Quoted 10 lines
Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt new file +10
-0+ mrvl,pxa27x-ssp + mrvl,pxa3xx-ssp + mvrl,pxa168-ssp + mrvl,pxa910-ssp + mrvl,ce4100-ssp + mrvl,lpss-ssp + + - reg: The memory base + +
It seems you are missing the 'dmas' properties here and that two of them ("rx" and "tx") are required by the code.
Arnd
PATCH 5/20 ARM: pxa: ssp: use devm_ functions
In reply to Daniel MackUse devm_ functions to allocate memory, ioremap, clk_get etc to clean up the error unwind path.
--- arch/arm/plat-pxa/ssp.c | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-)
arch/arm/plat-pxa/ssp.c +12 -28
@@ -95,20 +95,17 @@ static int pxa_ssp_probe(struct platform_device *pdev)struct resource *res;struct ssp_device *ssp;struct device *dev = &pdev->dev; -int ret =0 ; - ssp =kzalloc (sizeof (struct ssp_device ),GFP_KERNEL ); + ssp =devm_kzalloc (dev,sizeof (struct ssp_device ),GFP_KERNEL );if (ssp ==NULL ) {dev_err (dev,"failed to allocate memory" );return -ENOMEM ; } ssp->pdev = pdev; - ssp->clk =clk_get (dev,NULL ); -if (IS_ERR (ssp->clk)) { - ret =PTR_ERR (ssp->clk); - goto err_free; - } + ssp->clk =devm_clk_get (dev,NULL ); +if (IS_ERR (ssp->clk)) +return PTR_ERR (ssp->clk);if (dev->of_node) {struct of_phandle_args dma_spec;
@@ -150,32 +147,28 @@ static int pxa_ssp_probe(struct platform_device *pdev) res =platform_get_resource (pdev,IORESOURCE_MEM ,0 );if (res ==NULL ) {dev_err (dev,"no memory resource defined\n" ); - ret = -ENODEV ; - goto err_free_clk; +return -ENODEV ; } - res =request_mem_region (res->start,resource_size (res), - pdev->name); + res =devm_request_mem_region (dev, res->start,resource_size (res), + pdev->name);if (res ==NULL ) {dev_err (dev,"failed to request memory resource\n" ); - ret = -EBUSY ; - goto err_free_clk; +return -EBUSY ; } ssp->phys_base = res->start; - ssp->mmio_base =ioremap (res->start,resource_size (res)); + ssp->mmio_base =devm_ioremap (dev, res->start,resource_size (res));if (ssp->mmio_base ==NULL ) {dev_err (dev,"failed to ioremap() registers\n" ); - ret = -ENODEV ; - goto err_free_mem; +return -ENODEV ; } ssp->irq =platform_get_irq (pdev,0 );if (ssp->irq <0 ) {dev_err (dev,"no IRQ resource defined\n" ); - ret = -ENODEV ; - goto err_free_io; +return -ENODEV ; }if (dev->of_node) {
@@ -202,17 +195,8 @@ static int pxa_ssp_probe(struct platform_device *pdev)mutex_unlock (&ssp_lock);platform_set_drvdata (pdev, ssp); -return 0 ; -err_free_io: -iounmap (ssp->mmio_base); -err_free_mem: -release_mem_region (res->start,resource_size (res)); -err_free_clk: -clk_put (ssp->clk); -err_free: -kfree (ssp); -return ret; +return 0 ; }static int pxa_ssp_remove (struct platform_device *pdev)
Signature · 1 line
1.8.3.1
PATCH 6/20 tty: serial: pxa: remove old cruft
In reply to Daniel MackThis #if-0'd block wouldn't compile, so let's dispose it.
--- drivers/tty/serial/pxa.c | 25 ------------------------- 1 file changed, 25 deletions(-)
drivers/tty/serial/pxa.c +0 -25
@@ -332,31 +332,6 @@ static void serial_pxa_break_ctl(struct uart_port *port, int break_state)spin_unlock_irqrestore (&up->port.lock, flags); } -#if 0 -static void serial_pxa_dma_init (struct pxa_uart *up) -{ - up->rxdma = -pxa_request_dma (up->name,DMA_PRIO_LOW , pxa_receive_dma, up); -if (up->rxdma <0 ) - goto out; - up->txdma = -pxa_request_dma (up->name,DMA_PRIO_LOW , pxa_transmit_dma, up); -if (up->txdma <0 ) - goto err_txdma; - up->dmadesc =kmalloc (4 *sizeof (pxa_dma_desc),GFP_KERNEL ); -if (!up->dmadesc) - goto err_alloc; - -/* ... */ -err_alloc: -pxa_free_dma (up->txdma); -err_rxdma: -pxa_free_dma (up->rxdma); -out: -return ; -} -#endif -static int serial_pxa_startup (struct uart_port *port) {struct uart_pxa_port *up = (struct uart_pxa_port *)port;
Signature · 1 line
1.8.3.1
PATCH 6/20 tty: serial: pxa: remove old cruft
Hi Greg,
This patch can be merged independently of all others. Could you queue it up for 3.12 please?
Thanks,
Daniel
Quoted 44 lines · Daniel Mack
This #if-0'd block wouldn't compile, so let's dispose it.
Signed-off-by Daniel Mack <[email protected]>--- drivers/tty/serial/pxa.c | 25 ------------------------- 1 file changed, 25 deletions(-)drivers/tty/serial/pxa.c +0
-25@@ -332,31 +332,6 @@ static void serial_pxa_break_ctl(struct uart_port *port, int break_state)spin_unlock_irqrestore (&up->port.lock, flags); } -#if 0 -static void serial_pxa_dma_init (struct pxa_uart *up) -{ - up->rxdma = -pxa_request_dma (up->name,DMA_PRIO_LOW , pxa_receive_dma, up); -if (up->rxdma <0 ) - goto out; - up->txdma = -pxa_request_dma (up->name,DMA_PRIO_LOW , pxa_transmit_dma, up); -if (up->txdma <0 ) - goto err_txdma; - up->dmadesc =kmalloc (4 *sizeof (pxa_dma_desc),GFP_KERNEL ); -if (!up->dmadesc) - goto err_alloc; - -/* ... */ -err_alloc: -pxa_free_dma (up->txdma); -err_rxdma: -pxa_free_dma (up->rxdma); -out: -return ; -} -#endif -static int serial_pxa_startup (struct uart_port *port) {struct uart_pxa_port *up = (struct uart_pxa_port *)port;
Greg KH
maintainerPATCH 6/20 tty: serial: pxa: remove old cruft
Quoted 4 lines · Daniel Mack
Hi Greg,
This patch can be merged independently of all others. Could you queue it up for 3.12 please?
Will do.
greg k-h
PATCH 7/20 spi: spi-pxa2xx: remove legacy PXA DMA bits
In reply to Daniel MackGeneric DMA support was already implemented by commit cd7bed00 ("spi/pxa2xx: break out the private DMA API usage into a separate file") which moved all the legacy PXA DMA implementation code into its own file.
With generic DMA available for PXA, we can now just trash this file.
--- drivers/spi/Kconfig | 9 +- drivers/spi/Makefile | 1 - drivers/spi/spi-pxa2xx-pxadma.c | 490 ---------------------------------------- drivers/spi/spi-pxa2xx.h | 6 +- include/linux/spi/pxa2xx_spi.h | 1 - 5 files changed, 2 insertions(+), 505 deletions(-) delete mode 100644 drivers/spi/spi-pxa2xx-pxadma.c
drivers/spi/Kconfig +1 -8
@@ -316,16 +316,9 @@ config SPI_PPC4xx help This selects a driver for the PPC4xx SPI Controller. -config SPI_PXA2XX_PXADMA - bool "PXA2xx SSP legacy PXA DMA API support" - depends on SPI_PXA2XX && ARCH_PXA - help - Enable PXA private legacy DMA API support. Note that this is - deprecated in favor of generic DMA engine API. - config SPI_PXA2XX_DMA def_bool y - depends on SPI_PXA2XX && !SPI_PXA2XX_PXADMA + depends on SPI_PXA2XX config SPI_PXA2XX tristate "PXA2xx SSP SPI master"
drivers/spi/Makefile +0 -1
@@ -50,7 +50,6 @@ obj-$(CONFIG_SPI_ORION) += spi-orion.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o spi-pxa2xx-platform-objs := spi-pxa2xx.o -spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA) += spi-pxa2xx-pxadma.o spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
drivers/spi/spi-pxa2xx-pxadma.c deleted +0 -490
490 lines not on this page · raw message
drivers/spi/spi-pxa2xx.h +1 -5
@@ -164,11 +164,7 @@ extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data);/* * Select the right DMA implementation. */ -#if defined(CONFIG_SPI_PXA2XX_PXADMA ) -#define SPI_PXA2XX_USE_DMA 1 -#define MAX_DMA_LEN 8191 -#define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE) -#elif defined(CONFIG_SPI_PXA2XX_DMA ) +#if defined(CONFIG_SPI_PXA2XX_DMA )#define SPI_PXA2XX_USE_DMA 1#define MAX_DMA_LEN SZ_64K#define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL)
include/linux/spi/pxa2xx_spi.h +0 -1
@@ -56,7 +56,6 @@ struct pxa2xx_spi_chip {#if defined(CONFIG_ARCH_PXA ) || defined(CONFIG_ARCH_MMP )#include <linux/clk.h> -#include <mach/dma.h> extern void pxa2xx_set_spi_info (unsigned id,struct pxa2xx_spi_master *info);
Signature · 1 line
1.8.3.1
Mark Brown
maintainerPATCH 7/20 spi: spi-pxa2xx: remove legacy PXA DMA bits
Quoted 4 lines · Daniel Mack
Generic DMA support was already implemented by commit
cd7bed00("spi/pxa2xx: break out the private DMA API usage into a separate file") which moved all the legacy PXA DMA implementation code into its own file.
though this will have some trivial merge issues until the merge window
they shouldn't be a problem.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/d7b7b370/attachment.sig>
PATCH 7/20 spi: spi-pxa2xx: remove legacy PXA DMA bits
Quoted 7 lines · Mark Brown
Quoted 4 lines · Daniel Mack
Generic DMA support was already implemented by commit
cd7bed00("spi/pxa2xx: break out the private DMA API usage into a separate file") which moved all the legacy PXA DMA implementation code into its own file.Acked-by Mark Brown <[email protected]>
Thanks.
Quoted 2 lines
though this will have some trivial merge issues until the merge window they shouldn't be a problem.
Given the number of patches that need testing, I doubt this will hit the 3.12 window. But let's see :)
Daniel
Mark Brown
maintainerPATCH 7/20 spi: spi-pxa2xx: remove legacy PXA DMA bits
Quoted 7 lines · Daniel Mack
Quoted 2 lines · Mark Brown
though this will have some trivial merge issues until the merge window they shouldn't be a problem.
Given the number of patches that need testing, I doubt this will hit the 3.12 window. But let's see :)
Pessimist!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/3308afef/attachment.sig>
PATCH 8/20 mmc: host: pxamci: switch over to dmaengine use
In reply to Daniel MackSuccessfully testes on a PXA3xx board.
--- drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 86 deletions(-)
drivers/mmc/host/pxamci.c +102 -86
@@ -22,7 +22,9 @@#include <linux/platform_device.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/dmaengine.h> #include <linux/dma-mapping.h> +#include <linux/dma/mmp-pdma.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/mmc/host.h>
@@ -37,7 +39,6 @@#include <asm/sizes.h> #include <mach/hardware.h> -#include <mach/dma.h> #include <linux/platform_data/mmc-pxamci.h> #include "pxamci.h"
@@ -58,7 +59,6 @@ struct pxamci_host {struct clk *clk;unsigned long clkrate;int irq; -int dma;unsigned int clkrt;unsigned int cmdat;unsigned int imask;
@@ -69,8 +69,10 @@ struct pxamci_host {struct mmc_command *cmd;struct mmc_data *data; +struct dma_chan *dma_chan_rx; +struct dma_chan *dma_chan_tx; +dma_cookie_t dma_cookie;dma_addr_t sg_dma; -struct pxa_dma_desc *sg_cpu;unsigned int dma_len;unsigned int dma_dir;
@@ -173,14 +175,18 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)spin_unlock_irqrestore (&host->lock, flags); } +static void pxamci_dma_irq (void *param); +static void pxamci_setup_data (struct pxamci_host *host,struct mmc_data *data) { +struct dma_async_tx_descriptor *tx; +enum dma_data_direction direction; +struct dma_slave_config config; +struct dma_chan *chan;unsigned int nob = data->blocks;unsigned long long clks;unsigned int timeout; -bool dalgn =0 ; -u32 dcmd; -int i; +int ret; host->data = data;
@@ -195,54 +201,46 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) timeout = (unsigned int )clks + (data->timeout_clks << host->clkrt);writel ((timeout +255 ) /256 , host->base +MMC_RDTO ); +memset (&config,0 ,sizeof (config)); + config.src_addr_width =DMA_SLAVE_BUSWIDTH_1_BYTE ; + config.dst_addr_width =DMA_SLAVE_BUSWIDTH_1_BYTE ; + config.src_addr = host->res->start +MMC_RXFIFO ; + config.dst_addr = host->res->start +MMC_TXFIFO ; + config.src_maxburst =32 ; + config.dst_maxburst =32 ; +if (data->flags &MMC_DATA_READ ) { host->dma_dir =DMA_FROM_DEVICE ; - dcmd =DCMD_INCTRGADDR |DCMD_FLOWSRC ; -DRCMR (host->dma_drcmrtx) =0 ; -DRCMR (host->dma_drcmrrx) = host->dma |DRCMR_MAPVLD ; + direction =DMA_DEV_TO_MEM ; + chan = host->dma_chan_rx; }else { host->dma_dir =DMA_TO_DEVICE ; - dcmd =DCMD_INCSRCADDR |DCMD_FLOWTRG ; -DRCMR (host->dma_drcmrrx) =0 ; -DRCMR (host->dma_drcmrtx) = host->dma |DRCMR_MAPVLD ; + direction =DMA_MEM_TO_DEV ; + chan = host->dma_chan_tx; } - dcmd |=DCMD_BURST32 |DCMD_WIDTH1 ; + config.direction = direction; + + ret =dmaengine_slave_config (chan, &config); +if (ret <0 ) { +dev_err (mmc_dev (host->mmc),"dma slave config failed\n" ); +return ; + } - host->dma_len =dma_map_sg (mmc_dev (host->mmc), data->sg, data->sg_len, + host->dma_len =dma_map_sg (chan->device->dev, data->sg, data->sg_len, host->dma_dir); -for (i =0 ; i < host->dma_len; i++) { -unsigned int length =sg_dma_len (&data->sg[i]); - host->sg_cpu[i].dcmd = dcmd | length; -if (length &31 && !(data->flags &MMC_DATA_READ )) - host->sg_cpu[i].dcmd |=DCMD_ENDIRQEN ; -/* Not aligned to 8-byte boundary? */ -if (sg_dma_address (&data->sg[i]) &0x7 ) - dalgn =1 ; -if (data->flags &MMC_DATA_READ ) { - host->sg_cpu[i].dsadr = host->res->start +MMC_RXFIFO ; - host->sg_cpu[i].dtadr =sg_dma_address (&data->sg[i]); - }else { - host->sg_cpu[i].dsadr =sg_dma_address (&data->sg[i]); - host->sg_cpu[i].dtadr = host->res->start +MMC_TXFIFO ; - } - host->sg_cpu[i].ddadr = host->sg_dma + (i +1 ) * -sizeof (struct pxa_dma_desc ); + tx =dmaengine_prep_slave_sg (chan, data->sg, host->dma_len, direction, +DMA_PREP_INTERRUPT |DMA_CTRL_ACK ); +if (!tx) { +dev_err (mmc_dev (host->mmc),"prep_slave_sg() failed\n" ); +return ; } - host->sg_cpu[host->dma_len -1 ].ddadr =DDADR_STOP ; -wmb (); -/* -* The PXA27x DMA controller encounters overhead when working with -* unaligned (to 8-byte boundaries) data, so switch on byte alignment -* mode only if we have unaligned data. -*/ -if (dalgn) -DALGN |= (1 << host->dma); -else -DALGN &= ~(1 << host->dma); -DDADR (host->dma) = host->sg_dma; + tx->callback = pxamci_dma_irq; + tx->callback_param = host; + + host->dma_cookie =dmaengine_submit (tx);/* * workaround for erratum #91:
@@ -251,7 +249,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)* before starting DMA. */ if (!cpu_is_pxa27x () || data->flags &MMC_DATA_READ ) -DCSR (host->dma) =DCSR_RUN ; +dma_async_issue_pending (chan); }static void pxamci_start_cmd (struct pxamci_host *host,struct mmc_command *cmd,unsigned int cmdat)
@@ -343,7 +341,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)* enable DMA late */ if (cpu_is_pxa27x () && host->data->flags &MMC_DATA_WRITE ) -DCSR (host->dma) =DCSR_RUN ; +dma_async_issue_pending (host->dma_chan_tx); }else {pxamci_finish_request (host, host->mrq); }
@@ -358,9 +356,8 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)if (!data)return 0 ; -DCSR (host->dma) =0 ; -dma_unmap_sg (mmc_dev (host->mmc), data->sg, data->sg_len, - host->dma_dir); +dma_unmap_sg (host->dma_chan_rx->device->dev, + data->sg, data->sg_len, host->dma_dir);if (stat &STAT_READ_TIME_OUT ) data->error = -ETIMEDOUT ;
@@ -552,17 +549,25 @@ static const struct mmc_host_ops pxamci_ops = { .enable_sdio_irq = pxamci_enable_sdio_irq, }; -static void pxamci_dma_irq (int dma,void *devid) +static void pxamci_dma_irq (void *param) { -struct pxamci_host *host = devid; -int dcsr =DCSR (dma); -DCSR (dma) = dcsr & ~DCSR_STOPIRQEN ; +struct pxamci_host *host = param; +struct dma_tx_state state; +enum dma_status status; +struct dma_chan *chan; -if (dcsr &DCSR_ENDINTR ) { +if (host->data->flags &MMC_DATA_READ ) + chan = host->dma_chan_rx; +else + chan = host->dma_chan_tx; + + status =dmaengine_tx_status (chan, host->dma_cookie, &state); + +if (likely (status ==DMA_SUCCESS )) {writel (BUF_PART_FULL , host->base +MMC_PRTBUF ); }else { -pr_err ("%s: DMA error on channel %d (DCSR=%#x)\n" , -mmc_hostname (host->mmc), dma, dcsr); +pr_err ("%s: DMA error on %s channel\n" ,mmc_hostname (host->mmc), + host->data->flags &MMC_DATA_READ ?"rx" :"tx" ); host->data->error = -EIO ;pxamci_data_done (host,0 ); }
@@ -626,6 +631,7 @@ static int pxamci_probe(struct platform_device *pdev)struct pxamci_host *host =NULL ;struct resource *r, *dmarx, *dmatx;int ret, irq, gpio_cd =-1 , gpio_ro =-1 , gpio_power =-1 ; +dma_cap_mask_t mask; ret =pxamci_of_init (pdev);if (ret)
@@ -671,7 +677,6 @@ static int pxamci_probe(struct platform_device *pdev) host =mmc_priv (mmc); host->mmc = mmc; - host->dma =-1 ; host->pdata = pdev->dev.platform_data; host->clkrt =CLKRT_OFF ;
@@ -702,12 +707,6 @@ static int pxamci_probe(struct platform_device *pdev)MMC_CAP_SD_HIGHSPEED ; } - host->sg_cpu =dma_alloc_coherent (&pdev->dev,PAGE_SIZE , &host->sg_dma,GFP_KERNEL ); -if (!host->sg_cpu) { - ret = -ENOMEM ; - goto out; - } -spin_lock_init (&host->lock); host->res = r; host->irq = irq;
@@ -728,32 +727,50 @@ static int pxamci_probe(struct platform_device *pdev)writel (64 , host->base +MMC_RESTO );writel (host->imask, host->base +MMC_I_MASK ); - host->dma =pxa_request_dma (DRIVER_NAME ,DMA_PRIO_LOW , - pxamci_dma_irq, host); -if (host->dma <0 ) { - ret = -EBUSY ; - goto out; - } - ret =request_irq (host->irq, pxamci_irq,0 ,DRIVER_NAME , host);if (ret) goto out;platform_set_drvdata (pdev, mmc); - dmarx =platform_get_resource (pdev,IORESOURCE_DMA ,0 ); -if (!dmarx) { - ret = -ENXIO ; +if (!pdev->dev.of_node) { + dmarx =platform_get_resource (pdev,IORESOURCE_DMA ,0 ); +if (!dmarx) { + ret = -ENXIO ; + goto out; + } + host->dma_drcmrrx = dmarx->start; + + dmatx =platform_get_resource (pdev,IORESOURCE_DMA ,1 ); +if (!dmatx) { + ret = -ENXIO ; + goto out; + } + host->dma_drcmrtx = dmatx->start; + } + +dma_cap_zero (mask); +dma_cap_set (DMA_SLAVE , mask); + + host->dma_chan_rx = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &host->dma_drcmrrx, + &pdev->dev,"rx" ); +if (host->dma_chan_rx ==NULL ) { +dev_err (&pdev->dev,"unable to request rx dma channel\n" ); + ret = -ENODEV ; goto out; } - host->dma_drcmrrx = dmarx->start; - dmatx =platform_get_resource (pdev,IORESOURCE_DMA ,1 ); -if (!dmatx) { - ret = -ENXIO ; + host->dma_chan_tx = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &host->dma_drcmrtx, + &pdev->dev,"tx" ); +if (host->dma_chan_tx ==NULL ) { +dev_err (&pdev->dev,"unable to request tx dma channel\n" ); + ret = -ENODEV ; goto out; } - host->dma_drcmrtx = dmatx->start;if (host->pdata) { gpio_cd = host->pdata->gpio_card_detect;
@@ -814,12 +831,12 @@ err_gpio_ro:gpio_free (gpio_power); out:if (host) { -if (host->dma >=0 ) -pxa_free_dma (host->dma); +if (host->dma_chan_rx) +dma_release_channel (host->dma_chan_rx); +if (host->dma_chan_tx) +dma_release_channel (host->dma_chan_tx);if (host->base)iounmap (host->base); -if (host->sg_cpu) -dma_free_coherent (&pdev->dev,PAGE_SIZE , host->sg_cpu, host->sg_dma);if (host->clk)clk_put (host->clk); }
@@ -863,13 +880,12 @@ static int pxamci_remove(struct platform_device *pdev)END_CMD_RES |PRG_DONE |DATA_TRAN_DONE , host->base + MMC_I_MASK); -DRCMR (host->dma_drcmrrx) =0 ; -DRCMR (host->dma_drcmrtx) =0 ; -free_irq (host->irq, host); -pxa_free_dma (host->dma); +dmaengine_terminate_all (host->dma_chan_rx); +dmaengine_terminate_all (host->dma_chan_tx); +dma_release_channel (host->dma_chan_rx); +dma_release_channel (host->dma_chan_tx);iounmap (host->base); -dma_free_coherent (&pdev->dev,PAGE_SIZE , host->sg_cpu, host->sg_dma);clk_put (host->clk);
Signature · 1 line
1.8.3.1
PATCH 8/20 mmc: host: pxamci: switch over to dmaengine use
Hi Daniel,
Quoted 1 line · Daniel Mack
Successfully testes on a PXA3xx board.
I know it could be a bit late, but I tested your pxa-dma-3.15 branch rebased against 3.17 on pxa270 device,
and unfortunatelly pxamci driver doesn't work well.
It complains like this:
[ 4.586118] mmc0: DMA error on rx channel [ 4.586471] mmc0: status: 1 [ 4.587340] mmcblk0: error -5 transferring data, sector 1586251, nr
8, cmd response 0x900, card status 0xb00
status == 1, it's DMA_IN_PROGRESS, so I guess it's mmp_pdma bug, it calls callback without calling dma_cookie_complete on appropriate cookie? Any ideas how to fix it?
Regards,
Vasily
Quoted 355 lines
Signed-off-by Daniel Mack <[email protected]>--- drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 86 deletions(-)drivers/mmc/host/pxamci.c +102
-87@@ -22,7 +22,9 @@#include <linux/platform_device.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/dmaengine.h> #include <linux/dma-mapping.h> +#include <linux/dma/mmp-pdma.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/mmc/host.h> @@ -37,7 +39,6 @@#include <asm/sizes.h> #include <mach/hardware.h> -#include <mach/dma.h> #include <linux/platform_data/mmc-pxamci.h> #include "pxamci.h" @@ -58,7 +59,6 @@ struct pxamci_host {struct clk *clk;unsigned long clkrate;int irq; -int dma;unsigned int clkrt;unsigned int cmdat;unsigned int imask;@@ -69,8 +69,10 @@ struct pxamci_host {struct mmc_command *cmd;struct mmc_data *data; +struct dma_chan *dma_chan_rx; +struct dma_chan *dma_chan_tx; +dma_cookie_t dma_cookie;dma_addr_t sg_dma; -struct pxa_dma_desc *sg_cpu;unsigned int dma_len;unsigned int dma_dir;@@ -173,14 +175,18 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)spin_unlock_irqrestore (&host->lock, flags); } +static void pxamci_dma_irq (void *param); +static void pxamci_setup_data (struct pxamci_host *host,struct mmc_data *data) { +struct dma_async_tx_descriptor *tx; +enum dma_data_direction direction; +struct dma_slave_config config; +struct dma_chan *chan;unsigned int nob = data->blocks;unsigned long long clks;unsigned int timeout; -bool dalgn =0 ; -u32 dcmd; -int i; +int ret; host->data = data;@@ -195,54 +201,46 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) timeout = (unsigned int )clks + (data->timeout_clks << host->clkrt);writel ((timeout +255 ) /256 , host->base +MMC_RDTO ); +memset (&config,0 ,sizeof (config)); + config.src_addr_width =DMA_SLAVE_BUSWIDTH_1_BYTE ; + config.dst_addr_width =DMA_SLAVE_BUSWIDTH_1_BYTE ; + config.src_addr = host->res->start +MMC_RXFIFO ; + config.dst_addr = host->res->start +MMC_TXFIFO ; + config.src_maxburst =32 ; + config.dst_maxburst =32 ; +if (data->flags &MMC_DATA_READ ) { host->dma_dir =DMA_FROM_DEVICE ; - dcmd =DCMD_INCTRGADDR |DCMD_FLOWSRC ; -DRCMR (host->dma_drcmrtx) =0 ; -DRCMR (host->dma_drcmrrx) = host->dma |DRCMR_MAPVLD ; + direction =DMA_DEV_TO_MEM ; + chan = host->dma_chan_rx; }else { host->dma_dir =DMA_TO_DEVICE ; - dcmd =DCMD_INCSRCADDR |DCMD_FLOWTRG ; -DRCMR (host->dma_drcmrrx) =0 ; -DRCMR (host->dma_drcmrtx) = host->dma |DRCMR_MAPVLD ; + direction =DMA_MEM_TO_DEV ; + chan = host->dma_chan_tx; } - dcmd |=DCMD_BURST32 |DCMD_WIDTH1 ; + config.direction = direction; + + ret =dmaengine_slave_config (chan, &config); +if (ret <0 ) { +dev_err (mmc_dev (host->mmc),"dma slave config failed\n" ); +return ; + } - host->dma_len =dma_map_sg (mmc_dev (host->mmc), data->sg, data->sg_len, + host->dma_len =dma_map_sg (chan->device->dev, data->sg, data->sg_len, host->dma_dir); -for (i =0 ; i < host->dma_len; i++) { -unsigned int length =sg_dma_len (&data->sg[i]); - host->sg_cpu[i].dcmd = dcmd | length; -if (length &31 && !(data->flags &MMC_DATA_READ )) - host->sg_cpu[i].dcmd |=DCMD_ENDIRQEN ; -/* Not aligned to 8-byte boundary? */ -if (sg_dma_address (&data->sg[i]) &0x7 ) - dalgn =1 ; -if (data->flags &MMC_DATA_READ ) { - host->sg_cpu[i].dsadr = host->res->start +MMC_RXFIFO ; - host->sg_cpu[i].dtadr =sg_dma_address (&data->sg[i]); - }else { - host->sg_cpu[i].dsadr =sg_dma_address (&data->sg[i]); - host->sg_cpu[i].dtadr = host->res->start +MMC_TXFIFO ; - } - host->sg_cpu[i].ddadr = host->sg_dma + (i +1 ) * -sizeof (struct pxa_dma_desc ); + tx =dmaengine_prep_slave_sg (chan, data->sg, host->dma_len, direction, +DMA_PREP_INTERRUPT |DMA_CTRL_ACK ); +if (!tx) { +dev_err (mmc_dev (host->mmc),"prep_slave_sg() failed\n" ); +return ; } - host->sg_cpu[host->dma_len -1 ].ddadr =DDADR_STOP ; -wmb (); -/* -* The PXA27x DMA controller encounters overhead when working with -* unaligned (to 8-byte boundaries) data, so switch on byte alignment -* mode only if we have unaligned data. -*/ -if (dalgn) -DALGN |= (1 << host->dma); -else -DALGN &= ~(1 << host->dma); -DDADR (host->dma) = host->sg_dma; + tx->callback = pxamci_dma_irq; + tx->callback_param = host; + + host->dma_cookie =dmaengine_submit (tx);/* * workaround for erratum #91: @@ -251,7 +249,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)* before starting DMA. */ if (!cpu_is_pxa27x () || data->flags &MMC_DATA_READ ) -DCSR (host->dma) =DCSR_RUN ; +dma_async_issue_pending (chan); }static void pxamci_start_cmd (struct pxamci_host *host,struct mmc_command *cmd,unsigned int cmdat)@@ -343,7 +341,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)* enable DMA late */ if (cpu_is_pxa27x () && host->data->flags &MMC_DATA_WRITE ) -DCSR (host->dma) =DCSR_RUN ; +dma_async_issue_pending (host->dma_chan_tx); }else {pxamci_finish_request (host, host->mrq); }@@ -358,9 +356,8 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)if (!data)return 0 ; -DCSR (host->dma) =0 ; -dma_unmap_sg (mmc_dev (host->mmc), data->sg, data->sg_len, - host->dma_dir); +dma_unmap_sg (host->dma_chan_rx->device->dev, + data->sg, data->sg_len, host->dma_dir);if (stat &STAT_READ_TIME_OUT ) data->error = -ETIMEDOUT ;@@ -552,17 +549,25 @@ static const struct mmc_host_ops pxamci_ops = { .enable_sdio_irq = pxamci_enable_sdio_irq, }; -static void pxamci_dma_irq (int dma,void *devid) +static void pxamci_dma_irq (void *param) { -struct pxamci_host *host = devid; -int dcsr =DCSR (dma); -DCSR (dma) = dcsr & ~DCSR_STOPIRQEN ; +struct pxamci_host *host = param; +struct dma_tx_state state; +enum dma_status status; +struct dma_chan *chan; -if (dcsr &DCSR_ENDINTR ) { +if (host->data->flags &MMC_DATA_READ ) + chan = host->dma_chan_rx; +else + chan = host->dma_chan_tx; + + status =dmaengine_tx_status (chan, host->dma_cookie, &state); + +if (likely (status ==DMA_SUCCESS )) {writel (BUF_PART_FULL , host->base +MMC_PRTBUF ); }else { -pr_err ("%s: DMA error on channel %d (DCSR=%#x)\n" , -mmc_hostname (host->mmc), dma, dcsr); +pr_err ("%s: DMA error on %s channel\n" ,mmc_hostname (host->mmc), + host->data->flags &MMC_DATA_READ ?"rx" :"tx" ); host->data->error = -EIO ;pxamci_data_done (host,0 ); }@@ -626,6 +631,7 @@ static int pxamci_probe(struct platform_device *pdev)struct pxamci_host *host =NULL ;struct resource *r, *dmarx, *dmatx;int ret, irq, gpio_cd =-1 , gpio_ro =-1 , gpio_power =-1 ; +dma_cap_mask_t mask; ret =pxamci_of_init (pdev);if (ret)@@ -671,7 +677,6 @@ static int pxamci_probe(struct platform_device *pdev) host =mmc_priv (mmc); host->mmc = mmc; - host->dma =-1 ; host->pdata = pdev->dev.platform_data; host->clkrt =CLKRT_OFF ;@@ -702,12 +707,6 @@ static int pxamci_probe(struct platform_device *pdev)MMC_CAP_SD_HIGHSPEED ; } - host->sg_cpu =dma_alloc_coherent (&pdev->dev,PAGE_SIZE , &host->sg_dma,GFP_KERNEL ); -if (!host->sg_cpu) { - ret = -ENOMEM ; - goto out; - } -spin_lock_init (&host->lock); host->res = r; host->irq = irq;@@ -728,32 +727,50 @@ static int pxamci_probe(struct platform_device *pdev)writel (64 , host->base +MMC_RESTO );writel (host->imask, host->base +MMC_I_MASK ); - host->dma =pxa_request_dma (DRIVER_NAME ,DMA_PRIO_LOW , - pxamci_dma_irq, host); -if (host->dma <0 ) { - ret = -EBUSY ; - goto out; - } - ret =request_irq (host->irq, pxamci_irq,0 ,DRIVER_NAME , host);if (ret) goto out;platform_set_drvdata (pdev, mmc); - dmarx =platform_get_resource (pdev,IORESOURCE_DMA ,0 ); -if (!dmarx) { - ret = -ENXIO ; +if (!pdev->dev.of_node) { + dmarx =platform_get_resource (pdev,IORESOURCE_DMA ,0 ); +if (!dmarx) { + ret = -ENXIO ; + goto out; + } + host->dma_drcmrrx = dmarx->start; + + dmatx =platform_get_resource (pdev,IORESOURCE_DMA ,1 ); +if (!dmatx) { + ret = -ENXIO ; + goto out; + } + host->dma_drcmrtx = dmatx->start; + } + +dma_cap_zero (mask); +dma_cap_set (DMA_SLAVE , mask); + + host->dma_chan_rx = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &host->dma_drcmrrx, + &pdev->dev,"rx" ); +if (host->dma_chan_rx ==NULL ) { +dev_err (&pdev->dev,"unable to request rx dma channel\n" ); + ret = -ENODEV ; goto out; } - host->dma_drcmrrx = dmarx->start; - dmatx =platform_get_resource (pdev,IORESOURCE_DMA ,1 ); -if (!dmatx) { - ret = -ENXIO ; + host->dma_chan_tx = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &host->dma_drcmrtx, + &pdev->dev,"tx" ); +if (host->dma_chan_tx ==NULL ) { +dev_err (&pdev->dev,"unable to request tx dma channel\n" ); + ret = -ENODEV ; goto out; } - host->dma_drcmrtx = dmatx->start;if (host->pdata) { gpio_cd = host->pdata->gpio_card_detect;@@ -814,12 +831,12 @@ err_gpio_ro:gpio_free (gpio_power); out:if (host) { -if (host->dma >=0 ) -pxa_free_dma (host->dma); +if (host->dma_chan_rx) +dma_release_channel (host->dma_chan_rx); +if (host->dma_chan_tx) +dma_release_channel (host->dma_chan_tx);if (host->base)iounmap (host->base); -if (host->sg_cpu) -dma_free_coherent (&pdev->dev,PAGE_SIZE , host->sg_cpu, host->sg_dma);if (host->clk)clk_put (host->clk); }@@ -863,13 +880,12 @@ static int pxamci_remove(struct platform_device *pdev)END_CMD_RES |PRG_DONE |DATA_TRAN_DONE , host->base + MMC_I_MASK); -DRCMR (host->dma_drcmrrx) =0 ; -DRCMR (host->dma_drcmrtx) =0 ; -free_irq (host->irq, host); -pxa_free_dma (host->dma); +dmaengine_terminate_all (host->dma_chan_rx); +dmaengine_terminate_all (host->dma_chan_tx); +dma_release_channel (host->dma_chan_rx); +dma_release_channel (host->dma_chan_tx);iounmap (host->base); -dma_free_coherent (&pdev->dev,PAGE_SIZE , host->sg_cpu, host->sg_dma);clk_put (host->clk); --1.8.3.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 8/20 mmc: host: pxamci: switch over to dmaengine use
Quoted 11 lines · Vasily Khoruzhick
Hi Daniel,
Quoted 1 line · Daniel Mack
Successfully testes on a PXA3xx board.
I know it could be a bit late, but I tested your pxa-dma-3.15 branch rebased against 3.17 on pxa270 device,
and unfortunatelly pxamci driver doesn't work well.It complains like this:
Quoted 8 lines
[ 4.586118] mmc0: DMA error on rx channel [ 4.586471] mmc0: status: 1 [ 4.587340] mmcblk0: error -5 transferring data, sector 1586251, nr8, cmd response
0x900, card status0xb00status == 1, it's
DMA_IN_PROGRESS, so I guess it'smmp_pdmabug, it calls callback without callingdma_cookie_completeon appropriate cookie? Any ideas how to fix it?
Fixed it with attached patch. Original driver didn't set ENDMAEND flag for RX DMA, but after Daniel's
conversion pxamci_dma_irq callback is called for both RX and TX.
Now struggling with oops in pxa2xx_pcm driver.
Regards
Vasily
Quoted 350 lines
Regards,
VasilyQuoted 347 lines
Signed-off-by Daniel Mack <[email protected]>--- drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 86 deletions(-)drivers/mmc/host/pxamci.c +102
-86@@ -22,7 +22,9 @@#include <linux/platform_device.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/dmaengine.h> #include <linux/dma-mapping.h> +#include <linux/dma/mmp-pdma.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/mmc/host.h> @@ -37,7 +39,6 @@#include <asm/sizes.h> #include <mach/hardware.h> -#include <mach/dma.h> #include <linux/platform_data/mmc-pxamci.h> #include "pxamci.h" @@ -58,7 +59,6 @@ struct pxamci_host {struct clk *clk;unsigned long clkrate;int irq; -int dma;unsigned int clkrt;unsigned int cmdat;unsigned int imask;@@ -69,8 +69,10 @@ struct pxamci_host {struct mmc_command *cmd;struct mmc_data *data; +struct dma_chan *dma_chan_rx; +struct dma_chan *dma_chan_tx; +dma_cookie_t dma_cookie;dma_addr_t sg_dma; -struct pxa_dma_desc *sg_cpu;unsigned int dma_len;unsigned int dma_dir;@@ -173,14 +175,18 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)spin_unlock_irqrestore (&host->lock, flags); } +static void pxamci_dma_irq (void *param); +static void pxamci_setup_data (struct pxamci_host *host,struct mmc_data *data) { +struct dma_async_tx_descriptor *tx; +enum dma_data_direction direction; +struct dma_slave_config config; +struct dma_chan *chan;unsigned int nob = data->blocks;unsigned long long clks;unsigned int timeout; -bool dalgn =0 ; -u32 dcmd; -int i; +int ret; host->data = data;@@ -195,54 +201,46 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) timeout = (unsigned int )clks + (data->timeout_clks << host->clkrt);writel ((timeout +255 ) /256 , host->base +MMC_RDTO ); +memset (&config,0 ,sizeof (config)); + config.src_addr_width =DMA_SLAVE_BUSWIDTH_1_BYTE ; + config.dst_addr_width =DMA_SLAVE_BUSWIDTH_1_BYTE ; + config.src_addr = host->res->start +MMC_RXFIFO ; + config.dst_addr = host->res->start +MMC_TXFIFO ; + config.src_maxburst =32 ; + config.dst_maxburst =32 ; +if (data->flags &MMC_DATA_READ ) { host->dma_dir =DMA_FROM_DEVICE ; - dcmd =DCMD_INCTRGADDR |DCMD_FLOWSRC ; -DRCMR (host->dma_drcmrtx) =0 ; -DRCMR (host->dma_drcmrrx) = host->dma |DRCMR_MAPVLD ; + direction =DMA_DEV_TO_MEM ; + chan = host->dma_chan_rx; }else { host->dma_dir =DMA_TO_DEVICE ; - dcmd =DCMD_INCSRCADDR |DCMD_FLOWTRG ; -DRCMR (host->dma_drcmrrx) =0 ; -DRCMR (host->dma_drcmrtx) = host->dma |DRCMR_MAPVLD ; + direction =DMA_MEM_TO_DEV ; + chan = host->dma_chan_tx; } - dcmd |=DCMD_BURST32 |DCMD_WIDTH1 ; + config.direction = direction; + + ret =dmaengine_slave_config (chan, &config); +if (ret <0 ) { +dev_err (mmc_dev (host->mmc),"dma slave config failed\n" ); +return ; + } - host->dma_len =dma_map_sg (mmc_dev (host->mmc), data->sg, data->sg_len, + host->dma_len =dma_map_sg (chan->device->dev, data->sg, data->sg_len, host->dma_dir); -for (i =0 ; i < host->dma_len; i++) { -unsigned int length =sg_dma_len (&data->sg[i]); - host->sg_cpu[i].dcmd = dcmd | length; -if (length &31 && !(data->flags &MMC_DATA_READ )) - host->sg_cpu[i].dcmd |=DCMD_ENDIRQEN ; -/* Not aligned to 8-byte boundary? */ -if (sg_dma_address (&data->sg[i]) &0x7 ) - dalgn =1 ; -if (data->flags &MMC_DATA_READ ) { - host->sg_cpu[i].dsadr = host->res->start +MMC_RXFIFO ; - host->sg_cpu[i].dtadr =sg_dma_address (&data->sg[i]); - }else { - host->sg_cpu[i].dsadr =sg_dma_address (&data->sg[i]); - host->sg_cpu[i].dtadr = host->res->start +MMC_TXFIFO ; - } - host->sg_cpu[i].ddadr = host->sg_dma + (i +1 ) * -sizeof (struct pxa_dma_desc ); + tx =dmaengine_prep_slave_sg (chan, data->sg, host->dma_len, direction, +DMA_PREP_INTERRUPT |DMA_CTRL_ACK ); +if (!tx) { +dev_err (mmc_dev (host->mmc),"prep_slave_sg() failed\n" ); +return ; } - host->sg_cpu[host->dma_len -1 ].ddadr =DDADR_STOP ; -wmb (); -/* -* The PXA27x DMA controller encounters overhead when working with -* unaligned (to 8-byte boundaries) data, so switch on byte alignment -* mode only if we have unaligned data. -*/ -if (dalgn) -DALGN |= (1 << host->dma); -else -DALGN &= ~(1 << host->dma); -DDADR (host->dma) = host->sg_dma; + tx->callback = pxamci_dma_irq; + tx->callback_param = host; + + host->dma_cookie =dmaengine_submit (tx);/* * workaround for erratum #91: @@ -251,7 +249,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)* before starting DMA. */ if (!cpu_is_pxa27x () || data->flags &MMC_DATA_READ ) -DCSR (host->dma) =DCSR_RUN ; +dma_async_issue_pending (chan); }static void pxamci_start_cmd (struct pxamci_host *host,struct mmc_command *cmd,unsigned int cmdat)@@ -343,7 +341,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)* enable DMA late */ if (cpu_is_pxa27x () && host->data->flags &MMC_DATA_WRITE ) -DCSR (host->dma) =DCSR_RUN ; +dma_async_issue_pending (host->dma_chan_tx); }else {pxamci_finish_request (host, host->mrq); }@@ -358,9 +356,8 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)if (!data)return 0 ; -DCSR (host->dma) =0 ; -dma_unmap_sg (mmc_dev (host->mmc), data->sg, data->sg_len, - host->dma_dir); +dma_unmap_sg (host->dma_chan_rx->device->dev, + data->sg, data->sg_len, host->dma_dir);if (stat &STAT_READ_TIME_OUT ) data->error = -ETIMEDOUT ;@@ -552,17 +549,25 @@ static const struct mmc_host_ops pxamci_ops = { .enable_sdio_irq = pxamci_enable_sdio_irq, }; -static void pxamci_dma_irq (int dma,void *devid) +static void pxamci_dma_irq (void *param) { -struct pxamci_host *host = devid; -int dcsr =DCSR (dma); -DCSR (dma) = dcsr & ~DCSR_STOPIRQEN ; +struct pxamci_host *host = param; +struct dma_tx_state state; +enum dma_status status; +struct dma_chan *chan; -if (dcsr &DCSR_ENDINTR ) { +if (host->data->flags &MMC_DATA_READ ) + chan = host->dma_chan_rx; +else + chan = host->dma_chan_tx; + + status =dmaengine_tx_status (chan, host->dma_cookie, &state); + +if (likely (status ==DMA_SUCCESS )) {writel (BUF_PART_FULL , host->base +MMC_PRTBUF ); }else { -pr_err ("%s: DMA error on channel %d (DCSR=%#x)\n" , -mmc_hostname (host->mmc), dma, dcsr); +pr_err ("%s: DMA error on %s channel\n" ,mmc_hostname (host->mmc), + host->data->flags &MMC_DATA_READ ?"rx" :"tx" ); host->data->error = -EIO ;pxamci_data_done (host,0 ); }@@ -626,6 +631,7 @@ static int pxamci_probe(struct platform_device *pdev)struct pxamci_host *host =NULL ;struct resource *r, *dmarx, *dmatx;int ret, irq, gpio_cd =-1 , gpio_ro =-1 , gpio_power =-1 ; +dma_cap_mask_t mask; ret =pxamci_of_init (pdev);if (ret)@@ -671,7 +677,6 @@ static int pxamci_probe(struct platform_device *pdev) host =mmc_priv (mmc); host->mmc = mmc; - host->dma =-1 ; host->pdata = pdev->dev.platform_data; host->clkrt =CLKRT_OFF ;@@ -702,12 +707,6 @@ static int pxamci_probe(struct platform_device *pdev)MMC_CAP_SD_HIGHSPEED ; } - host->sg_cpu =dma_alloc_coherent (&pdev->dev,PAGE_SIZE , &host->sg_dma,GFP_KERNEL ); -if (!host->sg_cpu) { - ret = -ENOMEM ; - goto out; - } -spin_lock_init (&host->lock); host->res = r; host->irq = irq;@@ -728,32 +727,50 @@ static int pxamci_probe(struct platform_device *pdev)writel (64 , host->base +MMC_RESTO );writel (host->imask, host->base +MMC_I_MASK ); - host->dma =pxa_request_dma (DRIVER_NAME ,DMA_PRIO_LOW , - pxamci_dma_irq, host); -if (host->dma <0 ) { - ret = -EBUSY ; - goto out; - } - ret =request_irq (host->irq, pxamci_irq,0 ,DRIVER_NAME , host);if (ret) goto out;platform_set_drvdata (pdev, mmc); - dmarx =platform_get_resource (pdev,IORESOURCE_DMA ,0 ); -if (!dmarx) { - ret = -ENXIO ; +if (!pdev->dev.of_node) { + dmarx =platform_get_resource (pdev,IORESOURCE_DMA ,0 ); +if (!dmarx) { + ret = -ENXIO ; + goto out; + } + host->dma_drcmrrx = dmarx->start; + + dmatx =platform_get_resource (pdev,IORESOURCE_DMA ,1 ); +if (!dmatx) { + ret = -ENXIO ; + goto out; + } + host->dma_drcmrtx = dmatx->start; + } + +dma_cap_zero (mask); +dma_cap_set (DMA_SLAVE , mask); + + host->dma_chan_rx = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &host->dma_drcmrrx, + &pdev->dev,"rx" ); +if (host->dma_chan_rx ==NULL ) { +dev_err (&pdev->dev,"unable to request rx dma channel\n" ); + ret = -ENODEV ; goto out; } - host->dma_drcmrrx = dmarx->start; - dmatx =platform_get_resource (pdev,IORESOURCE_DMA ,1 ); -if (!dmatx) { - ret = -ENXIO ; + host->dma_chan_tx = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &host->dma_drcmrtx, + &pdev->dev,"tx" ); +if (host->dma_chan_tx ==NULL ) { +dev_err (&pdev->dev,"unable to request tx dma channel\n" ); + ret = -ENODEV ; goto out; } - host->dma_drcmrtx = dmatx->start;if (host->pdata) { gpio_cd = host->pdata->gpio_card_detect;@@ -814,12 +831,12 @@ err_gpio_ro:gpio_free (gpio_power); out:if (host) { -if (host->dma >=0 ) -pxa_free_dma (host->dma); +if (host->dma_chan_rx) +dma_release_channel (host->dma_chan_rx); +if (host->dma_chan_tx) +dma_release_channel (host->dma_chan_tx);if (host->base)iounmap (host->base); -if (host->sg_cpu) -dma_free_coherent (&pdev->dev,PAGE_SIZE , host->sg_cpu, host->sg_dma);if (host->clk)clk_put (host->clk); }@@ -863,13 +880,12 @@ static int pxamci_remove(struct platform_device *pdev)END_CMD_RES |PRG_DONE |DATA_TRAN_DONE , host->base + MMC_I_MASK); -DRCMR (host->dma_drcmrrx) =0 ; -DRCMR (host->dma_drcmrtx) =0 ; -free_irq (host->irq, host); -pxa_free_dma (host->dma); +dmaengine_terminate_all (host->dma_chan_rx); +dmaengine_terminate_all (host->dma_chan_tx); +dma_release_channel (host->dma_chan_rx); +dma_release_channel (host->dma_chan_tx);iounmap (host->base); -dma_free_coherent (&pdev->dev,PAGE_SIZE , host->sg_cpu, host->sg_dma);clk_put (host->clk);
Quoted 8 lines
Quoted 8 lines
--
1.8.3.1_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pxamci-mmp-pdma-fix.patch
Type: text/x-patch
Size: 495 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141016/8d400f7e/attachment-0001.bin>
PATCH 9/20 ata: pdata_pxa: migrate over to dmaengine usage
In reply to Daniel MackThis patch is compile-tested only, but the migration was actually straight-forward.
--- drivers/ata/pata_pxa.c | 172 ++++++++++++++++++++----------------------------- 1 file changed, 70 insertions(+), 102 deletions(-)
drivers/ata/pata_pxa.c +70 -102
@@ -28,76 +28,43 @@#include <linux/gpio.h> #include <linux/slab.h> #include <linux/completion.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/dma/mmp-pdma.h> #include <scsi/scsi_host.h> #include <mach/pxa2xx-regs.h> #include <linux/platform_data/ata-pxa.h> -#include <mach/dma.h> #define DRV_NAME "pata_pxa"#define DRV_VERSION "0.1"struct pata_pxa_data { -uint32_t dma_channel; -struct pxa_dma_desc *dma_desc; -dma_addr_t dma_desc_addr; -uint32_t dma_desc_id; +struct dma_chan *dma_channel; +unsigned int dma_dir; +unsigned int dma_len; +dma_cookie_t dma_cookie;/* DMA IO physical address */ uint32_t dma_io_addr; -/* PXA DREQ<0:2> pin selector */ -uint32_t dma_dreq; -/* DMA DCSR register value */ -uint32_t dma_dcsr; +struct ata_port *ap;struct completion dma_done; };/* -* Setup the DMA descriptors. The size is transfer capped at 4k per descriptor, -* if the transfer is longer, it is split into multiple chained descriptors. +* DMA interrupt handler. */ -static void pxa_load_dmac (struct scatterlist *sg,struct ata_queued_cmd *qc) +static void pxa_ata_dma_irq (void *param) { +struct ata_queued_cmd *qc = param;struct pata_pxa_data *pd = qc->ap->private_data; -uint32_t cpu_len, seg_len; -dma_addr_t cpu_addr; - - cpu_addr =sg_dma_address (sg); - cpu_len =sg_dma_len (sg); - -do { - seg_len = (cpu_len >0x1000 ) ?0x1000 : cpu_len; - - pd->dma_desc[pd->dma_desc_id].ddadr = pd->dma_desc_addr + - ((pd->dma_desc_id +1 ) *sizeof (struct pxa_dma_desc )); - - pd->dma_desc[pd->dma_desc_id].dcmd =DCMD_BURST32 | -DCMD_WIDTH2 | (DCMD_LENGTH & seg_len); - -if (qc->tf.flags &ATA_TFLAG_WRITE ) { - pd->dma_desc[pd->dma_desc_id].dsadr = cpu_addr; - pd->dma_desc[pd->dma_desc_id].dtadr = pd->dma_io_addr; - pd->dma_desc[pd->dma_desc_id].dcmd |=DCMD_INCSRCADDR | -DCMD_FLOWTRG ; - }else { - pd->dma_desc[pd->dma_desc_id].dsadr = pd->dma_io_addr; - pd->dma_desc[pd->dma_desc_id].dtadr = cpu_addr; - pd->dma_desc[pd->dma_desc_id].dcmd |=DCMD_INCTRGADDR | -DCMD_FLOWSRC ; - } - - cpu_len -= seg_len; - cpu_addr += seg_len; - pd->dma_desc_id++; - - }while (cpu_len); +dma_unmap_sg (pd->dma_channel->device->dev, + qc->sg, pd->dma_len, pd->dma_dir); -/* Should not happen */ -if (seg_len &0x1f ) -DALGN |= (1 << pd->dma_dreq); +complete (&pd->dma_done); }/*
@@ -106,28 +73,51 @@ static void pxa_load_dmac(struct scatterlist *sg, struct ata_queued_cmd *qc)static void pxa_qc_prep (struct ata_queued_cmd *qc) {struct pata_pxa_data *pd = qc->ap->private_data; -int si =0 ; -struct scatterlist *sg; +struct dma_slave_config config; +struct dma_async_tx_descriptor *tx; +struct dma_chan *chan = pd->dma_channel; +int ret;if (!(qc->flags &ATA_QCFLAG_DMAMAP ))return ; - pd->dma_desc_id =0 ; - -DCSR (pd->dma_channel) =0 ; -DALGN &= ~(1 << pd->dma_dreq); +memset (&config,0 ,sizeof (config)); + +if (qc->tf.flags &ATA_TFLAG_WRITE ) { + config.dst_maxburst =32 ; + config.dst_addr = pd->dma_io_addr; + config.dst_addr_width =DMA_SLAVE_BUSWIDTH_2_BYTES ; + config.direction =DMA_MEM_TO_DEV ; + pd->dma_dir =DMA_TO_DEVICE ; + }else { + config.src_maxburst =32 ; + config.src_addr = pd->dma_io_addr; + config.src_addr_width =DMA_SLAVE_BUSWIDTH_2_BYTES ; + config.direction =DMA_DEV_TO_MEM ; + pd->dma_dir =DMA_FROM_DEVICE ; + } -for_each_sg (qc->sg, sg, qc->n_elem, si) -pxa_load_dmac (sg, qc); + ret =dmaengine_slave_config (chan, &config); +if (ret <0 ) { +pr_err ("dmaengine_slave_config() failed\n" ); +return ; + } - pd->dma_desc[pd->dma_desc_id -1 ].ddadr =DDADR_STOP ; + pd->dma_len =dma_map_sg (chan->device->dev, qc->sg, qc->n_elem, + pd->dma_dir); -/* Fire IRQ only at the end of last block */ - pd->dma_desc[pd->dma_desc_id -1 ].dcmd |=DCMD_ENDIRQEN ; + tx =dmaengine_prep_slave_sg (chan, qc->sg, pd->dma_len, + config.direction, +DMA_PREP_INTERRUPT |DMA_CTRL_ACK ); +if (tx ==NULL ) { +pr_err ("dmaengine_prep_slave_sg() failed\n" ); +return ; + } -DDADR (pd->dma_channel) = pd->dma_desc_addr; -DRCMR (pd->dma_dreq) =DRCMR_MAPVLD | pd->dma_channel; + tx->callback = pxa_ata_dma_irq; + tx->callback_param = pd->ap; + pd->dma_cookie =dmaengine_submit (tx); }/*
@@ -146,7 +136,7 @@ static void pxa_bmdma_start(struct ata_queued_cmd *qc) {struct pata_pxa_data *pd = qc->ap->private_data;init_completion (&pd->dma_done); -DCSR (pd->dma_channel) =DCSR_RUN ; +dma_async_issue_pending (pd->dma_channel); }/*
@@ -155,12 +145,7 @@ static void pxa_bmdma_start(struct ata_queued_cmd *qc)static void pxa_bmdma_stop (struct ata_queued_cmd *qc) {struct pata_pxa_data *pd = qc->ap->private_data; - -if ((DCSR (pd->dma_channel) &DCSR_RUN ) && -wait_for_completion_timeout (&pd->dma_done,HZ )) -dev_err (qc->ap->dev,"Timeout waiting for DMA completion!" ); - -DCSR (pd->dma_channel) =0 ; +dmaengine_terminate_all (pd->dma_channel); }/*
@@ -171,8 +156,12 @@ static unsigned char pxa_bmdma_status(struct ata_port *ap) {struct pata_pxa_data *pd = ap->private_data;unsigned char ret =ATA_DMA_INTR ; +struct dma_tx_state tx_state; +enum dma_status status; -if (pd->dma_dcsr &DCSR_BUSERR ) + status =dmaengine_tx_status (pd->dma_channel, pd->dma_cookie, + &tx_state); +if (status ==DMA_ERROR ) ret |=ATA_DMA_ERR ;return ret;
@@ -214,21 +203,6 @@ static struct ata_port_operations pxa_ata_port_ops = { .qc_prep = pxa_qc_prep, }; -/* -* DMA interrupt handler. -*/ -static void pxa_ata_dma_irq (int dma,void *port) -{ -struct ata_port *ap = port; -struct pata_pxa_data *pd = ap->private_data; - - pd->dma_dcsr =DCSR (dma); -DCSR (dma) = pd->dma_dcsr; - -if (pd->dma_dcsr &DCSR_STOPSTATE ) -complete (&pd->dma_done); -} -static int pxa_ata_probe (struct platform_device *pdev) {struct ata_host *host;
@@ -239,6 +213,7 @@ static int pxa_ata_probe(struct platform_device *pdev)struct resource *dma_res;struct resource *irq_res;struct pata_pxa_pdata *pdata = pdev->dev.platform_data; +dma_cap_mask_t mask;int ret =0 ;/*
@@ -333,38 +308,30 @@ static int pxa_ata_probe(struct platform_device *pdev)if (!data)return -ENOMEM ; + data->ap = ap; ap->private_data = data; - data->dma_dreq = pdata->dma_dreq; data->dma_io_addr = dma_res->start;/* -* Allocate space for the DMA descriptors -*/ - data->dma_desc =dmam_alloc_coherent (&pdev->dev,PAGE_SIZE , - &data->dma_desc_addr,GFP_KERNEL ); -if (!data->dma_desc) -return -EINVAL ; - -/* * Request the DMA channel */ - data->dma_channel =pxa_request_dma (DRV_NAME ,DMA_PRIO_LOW , - pxa_ata_dma_irq, ap); -if (data->dma_channel <0 ) +dma_cap_zero (mask); +dma_cap_set (DMA_SLAVE , mask); + + data->dma_channel = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &pdata->dma_dreq, &pdev->dev, +"data" ); +if (data->dma_channel ==NULL )return -EBUSY ;/* -* Stop and clear the DMA channel -*/ -DCSR (data->dma_channel) =0 ; - -/* * Activate the ATA host */ ret =ata_host_activate (host, irq_res->start, ata_sff_interrupt, pdata->irq_flags, &pxa_ata_sht);if (ret) -pxa_free_dma (data->dma_channel); +dma_release_channel (data->dma_channel);return ret; }
@@ -374,7 +341,8 @@ static int pxa_ata_remove(struct platform_device *pdev)struct ata_host *host =platform_get_drvdata (pdev);struct pata_pxa_data *data = host->ports[0 ]->private_data; -pxa_free_dma (data->dma_channel); +dmaengine_terminate_all (data->dma_channel); +dma_release_channel (data->dma_channel);ata_host_detach (host);
Signature · 1 line
1.8.3.1
PATCH 9/20 ata: pdata_pxa: migrate over to dmaengine usage
drivers/ata/pata_pxa.c static int pxa_ata_probe(struct platform_device *pdev) · line 326
Quoted 9 lines · Daniel Mack
drivers/ata/pata_pxa.c +8
-0+dma_cap_zero (mask); +dma_cap_set (DMA_SLAVE , mask); + + data->dma_channel = +dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &pdata->dma_dreq, &pdev->dev, +"data" ); +if (data->dma_channel ==NULL )return -EBUSY ;
Here and in other drivers, you hardwire the mmp_pdma_filter_fn pointer, which creates an explicit module dependency to the dmaengine driver, which should not be there when booting with DT.
You can avoid that by open-coding the dma_request_slave_channel_compat() function:
data->dma_channel = dma_request_slave_channel(&pdev->dev, "data"); if (IS_ENABLED(CONFIG_ATAGS) && !data->dma_channel && pdata) data->dma_channel = dma_request_channel(mask, mmp_pdma_filter_fn, &pdata->dma_dreq); Arnd
PATCH 10/20 net: irda: pxaficp_ir: switch to dmaengine
In reply to Daniel MackThis was only compile-tested.
--- drivers/net/irda/pxaficp_ir.c | 242 ++++++++++++++++++++++++++---------------- 1 file changed, 151 insertions(+), 91 deletions(-)
drivers/net/irda/pxaficp_ir.c +151 -91
@@ -21,13 +21,15 @@#include <linux/clk.h> #include <linux/gpio.h> #include <linux/slab.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/dma/mmp-pdma.h> #include <net/irda/irda.h> #include <net/irda/irmod.h> #include <net/irda/wrapper.h> #include <net/irda/irda_device.h> -#include <mach/dma.h> #include <linux/platform_data/irda-pxaficp.h> #include <mach/regs-ost.h> #include <mach/regs-uart.h>
@@ -99,6 +101,9 @@ IrSR_RCVEIR_UART_MODE | \ IrSR_XMITIR_IR_MODE) +/* FIXME */ +extern void pxa2xx_transceiver_mode (struct device *dev,int mode); +struct pxa_irda {int speed;int newspeed;
@@ -109,8 +114,10 @@ struct pxa_irda {dma_addr_t dma_rx_buff_phy;dma_addr_t dma_tx_buff_phy;unsigned int dma_tx_buff_len; -int txdma; -int rxdma; +struct dma_chan *txdma; +struct dma_chan *rxdma; +dma_cookie_t dma_rx_cookie; +dma_cookie_t dma_tx_cookie;int uart_irq;int icp_irq;
@@ -122,6 +129,7 @@ struct pxa_irda {iobuff_t rx_buff;struct device *dev; +struct net_device *net_dev;struct pxaficp_platform_data *pdata;struct clk *fir_clk;struct clk *sir_clk;
@@ -147,26 +155,121 @@ static inline void pxa_irda_enable_sirclk(struct pxa_irda *si)clk_prepare_enable (si->sir_clk); } -#define IS_FIR (si) ((si)->speed >= 4000000)#define IRDA_FRAME_SIZE_LIMIT 2047inline static void pxa_irda_fir_dma_rx_start (struct pxa_irda *si) { -DCSR (si->rxdma) =DCSR_NODESC ; -DSADR (si->rxdma) =__PREG (ICDR ); -DTADR (si->rxdma) = si->dma_rx_buff_phy; -DCMD (si->rxdma) =DCMD_INCTRGADDR |DCMD_FLOWSRC |DCMD_WIDTH1 |DCMD_BURST32 |IRDA_FRAME_SIZE_LIMIT ; -DCSR (si->rxdma) |=DCSR_RUN ; +struct dma_async_tx_descriptor *tx; +struct dma_slave_config config; +struct dma_device *dma_dev; +int ret; + + dma_dev = si->rxdma->device; + +memset (&config,0 ,sizeof (config)); + config.src_maxburst =32 ; + config.src_addr_width =DMA_SLAVE_BUSWIDTH_1_BYTE ; + config.direction =DMA_DEV_TO_MEM ; + + ret =dmaengine_slave_config (si->rxdma, &config); +if (ret <0 ) { +dev_err (si->dev,"dmaengine_slave_config() failed: %d\n" , ret); +return ; + } + + tx = dma_dev->device_prep_dma_memcpy (si->rxdma,__PREG (ICDR ), + si->dma_rx_buff_phy, +IRDA_FRAME_SIZE_LIMIT ,0 ); +if (!tx) { +dev_err (si->dev,"device_prep_dma_memcpy() failed: %d\n" , ret); +return ; + } + + si->dma_rx_cookie =dmaengine_submit (tx); +dma_async_issue_pending (si->rxdma); +} + +static int pxa_irda_set_speed (struct pxa_irda *si,int speed); + +/* FIR Transmit DMA interrupt handler */ +static void pxa_irda_fir_dma_tx_irq (void *param) +{ +struct net_device *dev = param; +struct pxa_irda *si =netdev_priv (dev); +struct dma_tx_state tx_state; +enum dma_status status; + + status =dmaengine_tx_status (si->txdma, si->dma_tx_cookie, &tx_state); +if (status ==DMA_ERROR ) { + dev->stats.tx_errors++; + }else { + dev->stats.tx_packets++; + dev->stats.tx_bytes += si->dma_tx_buff_len; + } + +while (ICSR1 &ICSR1_TBY ) +cpu_relax (); + si->last_oscr =readl_relaxed (OSCR ); + +/* +* HACK: It looks like the TBY bit is dropped too soon. +* Without this delay things break. +*/ +udelay (120 ); + +if (si->newspeed) { +pxa_irda_set_speed (si, si->newspeed); + si->newspeed =0 ; + }else { +int i =64 ; + +ICCR0 =0 ; +pxa_irda_fir_dma_rx_start (si); +while ((ICSR1 &ICSR1_RNE ) && i--) + (void )ICDR ; +ICCR0 =ICCR0_ITR |ICCR0_RXE ; + +if (i <0 ) +printk (KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n" ); + } +netif_wake_queue (dev); } +inline static void pxa_irda_fir_dma_tx_start (struct pxa_irda *si) { -DCSR (si->txdma) =DCSR_NODESC ; -DSADR (si->txdma) = si->dma_tx_buff_phy; -DTADR (si->txdma) =__PREG (ICDR ); -DCMD (si->txdma) =DCMD_INCSRCADDR |DCMD_FLOWTRG |DCMD_ENDIRQEN |DCMD_WIDTH1 |DCMD_BURST32 | si->dma_tx_buff_len; -DCSR (si->txdma) |=DCSR_RUN ; +struct dma_async_tx_descriptor *tx; +struct dma_slave_config config; +struct dma_device *dma_dev; +int ret; + + dma_dev = si->txdma->device; + +memset (&config,0 ,sizeof (config)); + config.dst_maxburst =32 ; + config.dst_addr_width =DMA_SLAVE_BUSWIDTH_1_BYTE ; + config.direction =DMA_MEM_TO_DEV ; + + ret =dmaengine_slave_config (si->txdma, &config); +if (ret <0 ) { +dev_err (si->dev,"dmaengine_slave_config() failed: %d\n" , ret); +return ; + } + + tx = dma_dev->device_prep_dma_memcpy (si->txdma,__PREG (ICDR ), + si->dma_tx_buff_phy, + si->dma_tx_buff_len,0 ); +if (!tx) { +dev_err (si->dev,"device_prep_dma_memcpy() failed: %d\n" , ret); +return ; + } + + tx->callback = pxa_irda_fir_dma_tx_irq; + tx->callback_param = si->net_dev; + + si->dma_tx_cookie =dmaengine_submit (tx); +dma_async_issue_pending (si->txdma); }/*
@@ -205,7 +308,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)if (IS_FIR (si)) {/* stop RX DMA */ -DCSR (si->rxdma) &= ~DCSR_RUN ; +dmaengine_terminate_all (si->rxdma);/* disable FICP */ ICCR0 =0 ;pxa_irda_disable_clk (si);
@@ -344,68 +447,18 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)return IRQ_HANDLED ; } -/* FIR Receive DMA interrupt handler */ -static void pxa_irda_fir_dma_rx_irq (int channel,void *data) -{ -int dcsr =DCSR (channel); - -DCSR (channel) = dcsr & ~DCSR_RUN ; - -printk (KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n" , dcsr); -} - -/* FIR Transmit DMA interrupt handler */ -static void pxa_irda_fir_dma_tx_irq (int channel,void *data) -{ -struct net_device *dev = data; -struct pxa_irda *si =netdev_priv (dev); -int dcsr; - - dcsr =DCSR (channel); -DCSR (channel) = dcsr & ~DCSR_RUN ; - -if (dcsr &DCSR_ENDINTR ) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += si->dma_tx_buff_len; - }else { - dev->stats.tx_errors++; - } - -while (ICSR1 &ICSR1_TBY ) -cpu_relax (); - si->last_oscr =readl_relaxed (OSCR ); - -/* -* HACK: It looks like the TBY bit is dropped too soon. -* Without this delay things break. -*/ -udelay (120 ); - -if (si->newspeed) { -pxa_irda_set_speed (si, si->newspeed); - si->newspeed =0 ; - }else { -int i =64 ; - -ICCR0 =0 ; -pxa_irda_fir_dma_rx_start (si); -while ((ICSR1 &ICSR1_RNE ) && i--) - (void )ICDR ; -ICCR0 =ICCR0_ITR |ICCR0_RXE ; - -if (i <0 ) -printk (KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n" ); - } -netif_wake_queue (dev); -} -/* EIF(Error in FIFO/End in Frame) handler for FIR */ static void pxa_irda_fir_irq_eif (struct pxa_irda *si,struct net_device *dev,int icsr0) {unsigned int len, stat, data; +struct dma_tx_state tx_state; +enum dma_status status; + + status =dmaengine_tx_status (si->rxdma, si->dma_rx_cookie, + &tx_state);/* Get the current data position. */ - len =DTADR (si->rxdma) - si->dma_rx_buff_phy; + len =IRDA_FRAME_SIZE_LIMIT - tx_state.residue; do { /* Read Status, and then Data. */
@@ -472,7 +525,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)int icsr0, i =64 ;/* stop RX DMA */ -DCSR (si->rxdma) &= ~DCSR_RUN ; +dmaengine_terminate_all (si->rxdma); si->last_oscr =readl_relaxed (OSCR ); icsr0 =ICSR0 ;
@@ -553,7 +606,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)cpu_relax ();/* stop RX DMA, disable FICP */ -DCSR (si->rxdma) &= ~DCSR_RUN ; +dmaengine_terminate_all (si->rxdma);ICCR0 =0 ;pxa_irda_fir_dma_tx_start (si);
@@ -626,10 +679,6 @@ static void pxa_irda_startup(struct pxa_irda *si)/* configure FICP ICCR2 */ ICCR2 =ICCR2_TXP |ICCR2_TRIG_32 ; -/* configure DMAC */ -DRCMR (17 ) = si->rxdma |DRCMR_MAPVLD ; -DRCMR (18 ) = si->txdma |DRCMR_MAPVLD ; -/* force SIR reinitialization */ si->speed =4000000 ;pxa_irda_set_speed (si,9600 );
@@ -649,17 +698,15 @@ static void pxa_irda_shutdown(struct pxa_irda *si)STISR =0 ;/* disable DMA */ -DCSR (si->txdma) &= ~DCSR_RUN ; -DCSR (si->rxdma) &= ~DCSR_RUN ; +dmaengine_terminate_all (si->rxdma); +dmaengine_terminate_all (si->txdma); +/* disable FICP */ ICCR0 =0 ;/* disable the STUART or FICP clocks */ pxa_irda_disable_clk (si); -DRCMR (17 ) =0 ; -DRCMR (18 ) =0 ; -local_irq_restore (flags);/* power off board transceiver */
@@ -671,7 +718,8 @@ static void pxa_irda_shutdown(struct pxa_irda *si)static int pxa_irda_start (struct net_device *dev) {struct pxa_irda *si =netdev_priv (dev); -int err; +dma_cap_mask_t mask; +int drcmr, err; si->speed =9600 ;
@@ -689,13 +737,21 @@ static int pxa_irda_start(struct net_device *dev)disable_irq (si->uart_irq);disable_irq (si->icp_irq); +dma_cap_zero (mask); +dma_cap_set (DMA_SLAVE , mask); + err = -EBUSY ; - si->rxdma =pxa_request_dma ("FICP_RX" ,DMA_PRIO_LOW , pxa_irda_fir_dma_rx_irq, dev); -if (si->rxdma <0 ) + + drcmr =17 ; + si->rxdma =dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &drcmr, si->dev,"rx" ); +if (si->rxdma ==NULL ) goto err_rx_dma; - si->txdma =pxa_request_dma ("FICP_TX" ,DMA_PRIO_LOW , pxa_irda_fir_dma_tx_irq, dev); -if (si->txdma <0 ) + drcmr =18 ; + si->rxdma =dma_request_slave_channel_compat (mask, mmp_pdma_filter_fn, + &drcmr, si->dev,"rx" ); +if (si->txdma ==NULL ) goto err_tx_dma; err = -ENOMEM ;
@@ -737,9 +793,9 @@ err_irlap: err_dma_tx_buff:dma_free_coherent (si->dev,IRDA_FRAME_SIZE_LIMIT , si->dma_rx_buff, si->dma_rx_buff_phy); err_dma_rx_buff: -pxa_free_dma (si->txdma); +dma_release_channel (si->txdma); err_tx_dma: -pxa_free_dma (si->rxdma); +dma_release_channel (si->rxdma); err_rx_dma:free_irq (si->icp_irq, dev); err_irq2:
@@ -766,8 +822,11 @@ static int pxa_irda_stop(struct net_device *dev)free_irq (si->uart_irq, dev);free_irq (si->icp_irq, dev); -pxa_free_dma (si->rxdma); -pxa_free_dma (si->txdma); +dmaengine_terminate_all (si->rxdma); +dmaengine_terminate_all (si->txdma); + +dma_release_channel (si->rxdma); +dma_release_channel (si->txdma);if (si->dma_rx_buff)dma_free_coherent (si->dev,IRDA_FRAME_SIZE_LIMIT , si->dma_tx_buff, si->dma_tx_buff_phy);
@@ -855,6 +914,7 @@ static int pxa_irda_probe(struct platform_device *pdev) si =netdev_priv (dev); si->dev = &pdev->dev; si->pdata = pdev->dev.platform_data; + si->net_dev = dev; si->uart_irq =platform_get_irq (pdev,0 ); si->icp_irq =platform_get_irq (pdev,1 );
Signature · 1 line
1.8.3.1
PATCH 11/20 net: smc91x.c: switch to generic buf-to-buf DMA offload
In reply to Daniel MackDrop all PXA-DMA specific implementation details and rely on dma_async_memcpy_buf_to_buf().
This patch is only compile-tested.
--- drivers/net/ethernet/smsc/smc91x.c | 40 +++++++-------------- drivers/net/ethernet/smsc/smc91x.h | 71 ++++++++++++++------------------------ 2 files changed, 38 insertions(+), 73 deletions(-)
drivers/net/ethernet/smsc/smc91x.c +12 -28
@@ -2015,17 +2015,17 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,if (retval) goto err_out; -#ifdef CONFIG_ARCH_PXA -# ifdef SMC_USE_PXA_DMA - lp->cfg.flags |=SMC91X_USE_DMA ; -# endif if (lp->cfg.flags &SMC91X_USE_DMA ) { -int dma =pxa_request_dma (dev->name,DMA_PRIO_LOW , - smc_pxa_dma_irq,NULL ); -if (dma >=0 ) - dev->dma = dma; +dma_cap_mask_t mask; + +dma_cap_zero (mask); +dma_cap_set (DMA_MEMCPY , mask); + lp->dma_channel =dma_request_channel (mask,NULL ,NULL ); + +if (!lp->dma_channel) +printk ("%s(): request of DMA channel failed\n" , + __func__); } -#endif retval =register_netdev (dev);if (retval ==0 ) {
@@ -2034,9 +2034,6 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr, dev->name, version_string, revision_register &0x0f , lp->base, dev->irq); -if (dev->dma != (unsigned char )-1 ) -printk (" DMA %d" , dev->dma); -printk ("%s%s\n" , lp->cfg.flags &SMC91X_NOWAIT ?" [nowait]" :"" ,THROTTLE_TX_PKTS ?" [throttle_tx]" :"" );
@@ -2060,10 +2057,6 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr, } err_out: -#ifdef CONFIG_ARCH_PXA -if (retval && dev->dma != (unsigned char )-1 ) -pxa_free_dma (dev->dma); -#endif return retval; }
@@ -2282,14 +2275,6 @@ static int smc_drv_probe(struct platform_device *pdev) goto out_release_attrib; } -#ifdef CONFIG_ARCH_PXA - { -struct smc_local *lp =netdev_priv (ndev); - lp->device = &pdev->dev; - lp->physaddr = res->start; - } -#endif - ret =smc_probe (ndev, addr, irq_flags);if (ret !=0 ) goto out_iounmap;
@@ -2320,12 +2305,11 @@ static int smc_drv_remove(struct platform_device *pdev)unregister_netdev (ndev); +if (lp->dma_channel) +dma_release_channel (lp->dma_channel); +free_irq (ndev->irq, ndev); -#ifdef CONFIG_ARCH_PXA -if (ndev->dma != (unsigned char )-1 ) -pxa_free_dma (ndev->dma); -#endif iounmap (lp->base);smc_release_datacs (pdev,ndev);
drivers/net/ethernet/smsc/smc91x.h +26 -45
122 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 12/20 net: smc911x.c: switch to dmaengine API
In reply to Daniel MackDrop all PXA-DMA specific implementation details and switch over to generic dmaengine usage.
This patch is only compile-tested.
--- drivers/net/ethernet/smsc/smc911x.c | 80 ++++++++++++++++++++++------------- drivers/net/ethernet/smsc/smc911x.h | 83 ++++++++++++++++++++----------------- 2 files changed, 98 insertions(+), 65 deletions(-)
drivers/net/ethernet/smsc/smc911x.c +52 -28
@@ -1178,9 +1178,9 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id)#ifdef SMC_USE_DMA static void -smc911x_tx_dma_irq (int dma,void *data) +smc911x_tx_dma_irq (void *param) { -struct net_device *dev = (struct net_device *)data; +struct net_device *dev = (struct net_device *) param;struct smc911x_local *lp =netdev_priv (dev);struct sk_buff *skb = lp->current_tx_skb;unsigned long flags;
@@ -1189,7 +1189,6 @@ smc911x_tx_dma_irq(int dma, void *data)DBG (SMC_DEBUG_TX |SMC_DEBUG_DMA ,"%s: TX DMA irq handler\n" , dev->name);/* Clear the DMA interrupt sources */ -SMC_DMA_ACK_IRQ (dev, dma);BUG_ON (skb ==NULL );dma_unmap_single (NULL , tx_dmabuf, tx_dmalen,DMA_TO_DEVICE ); dev->trans_start = jiffies;
@@ -1212,10 +1211,9 @@ smc911x_tx_dma_irq(int dma, void *data) "%s: TX DMA irq completed\n", dev->name); }static void -smc911x_rx_dma_irq (int dma,void *data) +smc911x_rx_dma_irq (void *param) { -struct net_device *dev = (struct net_device *)data; -unsigned long ioaddr = dev->base_addr; +struct net_device *dev = (struct net_device *) param;struct smc911x_local *lp =netdev_priv (dev);struct sk_buff *skb = lp->current_rx_skb;unsigned long flags;
@@ -1224,7 +1222,6 @@ smc911x_rx_dma_irq(int dma, void *data)DBG (SMC_DEBUG_FUNC ,"%s: --> %s\n" , dev->name, __func__);DBG (SMC_DEBUG_RX |SMC_DEBUG_DMA ,"%s: RX DMA irq handler\n" , dev->name);/* Clear the DMA interrupt sources */ -SMC_DMA_ACK_IRQ (dev, dma);dma_unmap_single (NULL , rx_dmabuf, rx_dmalen,DMA_FROM_DEVICE );BUG_ON (skb ==NULL ); lp->current_rx_skb =NULL ;
@@ -1754,6 +1751,37 @@ static int smc911x_findirq(struct net_device *dev)return probe_irq_off (cookie); } +#ifdef SMC_USE_DMA +static void smc_alloc_dma (struct net_device *dev, +struct smc911x_local *lp) +{ +dma_cap_mask_t mask; + +dma_cap_zero (mask); +dma_cap_set (DMA_MEMCPY , mask); + + lp->rxdma =dma_request_channel (mask,NULL ,NULL ); +if (!lp->rxdma) { +printk ("%s(): unable to allocate RX channel\n" , __func__); +return ; + } + + lp->txdma =dma_request_channel (mask,NULL ,NULL ); +if (!lp->txdma) { +printk ("%s(): unable to allocate TX channel\n" , __func__); +return ; + } + + lp->rxdma_active =0 ; + lp->txdma_active =0 ; +} +#else +static inline void smc_alloc_dma (struct net_device *dev, +struct smc911x_local *lp) +{ +} +#endif +static const struct net_device_ops smc911x_netdev_ops = { .ndo_open = smc911x_open, .ndo_stop = smc911x_close,
@@ -1969,13 +1997,7 @@ static int smc911x_probe(struct net_device *dev)if (retval) goto err_out; -#ifdef SMC_USE_DMA - lp->rxdma =SMC_DMA_REQUEST (dev, smc911x_rx_dma_irq); - lp->txdma =SMC_DMA_REQUEST (dev, smc911x_tx_dma_irq); - lp->rxdma_active =0 ; - lp->txdma_active =0 ; - dev->dma = lp->rxdma; -#endif +smc_alloc_dma (dev, lp); retval =register_netdev (dev);if (retval ==0 ) {
@@ -1985,11 +2007,11 @@ static int smc911x_probe(struct net_device *dev) dev->base_addr, dev->irq);#ifdef SMC_USE_DMA -if (lp->rxdma !=-1 ) -printk (" RXDMA %d " , lp->rxdma); +if (lp->rxdma) +printk (" RXDMA %p" , lp->rxdma); -if (lp->txdma !=-1 ) -printk ("TXDMA %d" , lp->txdma); +if (lp->txdma) +printk ("TXDMA %p" , lp->txdma);#endif printk ("\n" );if (!is_valid_ether_addr (dev->dev_addr)) {
@@ -2013,11 +2035,14 @@ static int smc911x_probe(struct net_device *dev) err_out:#ifdef SMC_USE_DMA if (retval) { -if (lp->rxdma !=-1 ) { -SMC_DMA_FREE (dev, lp->rxdma); +if (lp->rxdma) { +dmaengine_terminate_all (lp->rxdma); +dma_release_channel (lp->rxdma); } -if (lp->txdma !=-1 ) { -SMC_DMA_FREE (dev, lp->txdma); + +if (lp->txdma) { +dmaengine_terminate_all (lp->txdma); +dma_release_channel (lp->txdma); } }#endif
@@ -2119,12 +2144,11 @@ static int smc911x_drv_remove(struct platform_device *pdev)#ifdef SMC_USE_DMA { -if (lp->rxdma !=-1 ) { -SMC_DMA_FREE (dev, lp->rxdma); - } -if (lp->txdma !=-1 ) { -SMC_DMA_FREE (dev, lp->txdma); - } +if (lp->rxdma) +dma_release_channel (lp->rxdma); + +if (lp->txdma) +dma_release_channel (lp->txdma); }#endif iounmap (lp->base);
drivers/net/ethernet/smsc/smc911x.h +46 -37
133 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 13/20 ASoC: pxa: pxa-ssp: add DT bindings
In reply to Daniel MackThis patch contains a cruel hack for looking up the the DMA request number. The problem here is that the implementation as it stands will allocate the DMA channel from the user of the ssp port, and hence we cannot allocate a real channel here.
--- Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt | 7 +++++++ sound/soc/pxa/pxa-ssp.c | 12 ++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt new file +7 -0
@@ -0,0 +1,7 @@ +Marvell PXA SSP CPU DAI bindings + +Required properties: + + compatible Must be "mrvl,pxa-ssp-dai" + +
sound/soc/pxa/pxa-ssp.c +10 -2
@@ -21,6 +21,7 @@#include <linux/clk.h> #include <linux/io.h> #include <linux/pxa2xx_ssp.h> +#include <linux/of.h> #include <asm/irq.h>
@@ -798,6 +799,12 @@ static const struct snd_soc_component_driver pxa_ssp_component = { .name = "pxa-ssp", }; +#ifdef CONFIG_OF +static const struct of_device_id pxa_ssp_of_ids[] = { + { .compatible ="mrvl,pxa-ssp-dai" }, +}; +#endif +static int asoc_ssp_probe (struct platform_device *pdev) { return snd_soc_register_component(&pdev->dev, &pxa_ssp_component,
@@ -812,8 +819,9 @@ static int asoc_ssp_remove(struct platform_device *pdev)static struct platform_driver asoc_ssp_driver = { .driver = { - .name ="pxa-ssp-dai" , - .owner =THIS_MODULE , + .name ="pxa-ssp-dai" , + .owner =THIS_MODULE , + .of_match_table =of_match_ptr (pxa_ssp_of_ids), }, .probe = asoc_ssp_probe,
Signature · 1 line
1.8.3.1
Mark Brown
maintainerPATCH 13/20 ASoC: pxa: pxa-ssp: add DT bindings
Quoted 10 lines · Daniel Mack
This patch contains a cruel hack for looking up the the DMA request number. The problem here is that the implementation as it stands will allocate the DMA channel from the user of the ssp port, and hence we cannot allocate a real channel here.
Signed-off-by Daniel Mack <[email protected]>--- Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt | 7 +++++++ sound/soc/pxa/pxa-ssp.c | 12 ++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-)
So, really this should be part of a generic binding for the SSP device but obviously this is just a virtual device that binds to a generic bit of hardware that can be used for other applications like SPI. For the ASoC case we could instantiate the DAI from the machine driver but that isn't going to work for things like SPI. I'm not 100% sure what the best way to deal with that is.
One way of doing this is to have two compatible strings for the same bit
of hardware describing the application. I'm not sure that's nice but it
works...
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/452862df/attachment.sig>
PATCH 13/20 ASoC: pxa: pxa-ssp: add DT bindings
Quoted 12 lines · Mark Brown
Quoted 10 lines · Daniel Mack
This patch contains a cruel hack for looking up the the DMA request number. The problem here is that the implementation as it stands will allocate the DMA channel from the user of the ssp port, and hence we cannot allocate a real channel here.
Signed-off-by Daniel Mack <[email protected]>--- Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt | 7 +++++++ sound/soc/pxa/pxa-ssp.c | 12 ++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-)
Quoted 6 lines
So, really this should be part of a generic binding for the SSP device but obviously this is just a virtual device that binds to a generic bit of hardware that can be used for other applications like SPI. For the ASoC case we could instantiate the DAI from the machine driver but that isn't going to work for things like SPI. I'm not 100% sure what the best way to deal with that is.
Yes, I pondered over this for a while as well. I thought about having the ssp port instantiated as real device just like we have it now, and then just add a phandle reference in DT from the DAI to the upstream device.
Then, we should also allocate the DMA channel from the upstream device and pass it down to the DAI. But then again, the pxa-pcm-lib needs some rework, as it's currently in charge of obtaining and releasing the channel.
I wanted to postpone that issue until the rest of the series has settled and limit changes to the bare minimum for now. Does that sound feasible?
Daniel
Mark Brown
maintainerPATCH 13/20 ASoC: pxa: pxa-ssp: add DT bindings
Quoted 6 lines · Daniel Mack
Then, we should also allocate the DMA channel from the upstream device and pass it down to the DAI. But then again, the pxa-pcm-lib needs some rework, as it's currently in charge of obtaining and releasing the channel.
I wanted to postpone that issue until the rest of the series has settled and limit changes to the bare minimum for now. Does that sound feasible?
Yup, the big problem here is the whole DT as ABI thing - what happens in
the code isn't so important but the DT is supposed to be stable. Or we
could decide that this is one of the cases that's unstable in which case
we should probably flag it up in the DT binding document if nothing else.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130808/3b7a01cb/attachment.sig>
PATCH 13/20 ASoC: pxa: pxa-ssp: add DT bindings
Quoted 6 lines · Mark Brown
Quoted 3 lines · Daniel Mack
Then, we should also allocate the DMA channel from the upstream device and pass it down to the DAI. But then again, the pxa-pcm-lib needs some rework, as it's currently in charge of obtaining and releasing the channel.
Quoted 8 lines
Quoted 2 lines
I wanted to postpone that issue until the rest of the series has settled and limit changes to the bare minimum for now. Does that sound feasible?
Yup, the big problem here is the whole DT as ABI thing - what happens in the code isn't so important but the DT is supposed to be stable. Or we could decide that this is one of the cases that's unstable in which case we should probably flag it up in the DT binding document if nothing else.
Alright, I agreee. It's not much code that was needed to add support for what I proposed, so I added a patch for that to my queue. Thanks for the heads-up.
Daniel
PATCH 14/20 ASoC: pxa: use snd_dmaengine_dai_dma_data
In reply to Daniel MackUse snd_dmaengine_dai_dma_data for passing the dma parameters from clients to the pxa pcm lib. This does no functional change, it's just an intermedia step to migrate the pxa bits over to dmaengine.
The calculation of dcmd is a transition hack which will be removed again in a later patch. It's just there to make the transition more readable.
--- include/sound/pxa2xx-lib.h | 7 ----- sound/arm/pxa2xx-ac97.c | 26 ++++++++++-------- sound/arm/pxa2xx-pcm-lib.c | 52 +++++++++++++++++++++++++++++------ sound/arm/pxa2xx-pcm.c | 5 +++- sound/arm/pxa2xx-pcm.h | 6 ++-- sound/soc/pxa/mmp-pcm.c | 8 ++++-- sound/soc/pxa/mmp-sspa.c | 12 +++++--- sound/soc/pxa/pxa-ssp.c | 36 ++++++++---------------- sound/soc/pxa/pxa2xx-ac97.c | 67 +++++++++++++++++++++++---------------------- sound/soc/pxa/pxa2xx-i2s.c | 28 +++++++++---------- sound/soc/pxa/pxa2xx-pcm.c | 8 ++++-- 11 files changed, 142 insertions(+), 113 deletions(-)
include/sound/pxa2xx-lib.h +0 -7
@@ -6,13 +6,6 @@/* PCM */ -struct pxa2xx_pcm_dma_params { -char *name;/* stream identifier */ -u32 dcmd;/* DMA descriptor dcmd field */ -volatile u32 *drcmr;/* the DMA request channel to use */ -u32 dev_addr;/* device physical address for DMA */ -}; -extern int __pxa2xx_pcm_hw_params (struct snd_pcm_substream *substream,struct snd_pcm_hw_params *params);extern int __pxa2xx_pcm_hw_free (struct snd_pcm_substream *substream);
sound/arm/pxa2xx-ac97.c +14 -12
@@ -14,12 +14,14 @@#include <linux/io.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/dmaengine.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/ac97_codec.h> #include <sound/initval.h> #include <sound/pxa2xx-lib.h> +#include <sound/dmaengine_pcm.h> #include <mach/regs-ac97.h> #include <mach/audio.h>
@@ -41,20 +43,20 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { .reset = pxa2xx_ac97_reset, }; -static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = { - .name ="AC97 PCM out" , - .dev_addr =__PREG (PCDR ), - .drcmr = &DRCMR (12 ), - .dcmd =DCMD_INCSRCADDR |DCMD_FLOWTRG | -DCMD_BURST32 |DCMD_WIDTH4 , +static unsigned long pxa2xx_ac97_pcm_out_req =12 ; +static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_out = { + .addr =__PREG (PCDR ), + .addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES , + .maxburst =32 , + .filter_data = &pxa2xx_ac97_pcm_out_req, }; -static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = { - .name ="AC97 PCM in" , - .dev_addr =__PREG (PCDR ), - .drcmr = &DRCMR (11 ), - .dcmd =DCMD_INCTRGADDR |DCMD_FLOWSRC | -DCMD_BURST32 |DCMD_WIDTH4 , +static unsigned long pxa2xx_ac97_pcm_in_req =11 ; +static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_in = { + .addr =__PREG (PCDR ), + .addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES , + .maxburst =32 , + .filter_data = &pxa2xx_ac97_pcm_in_req, };static struct snd_pcm *pxa2xx_ac97_pcm;
sound/arm/pxa2xx-pcm-lib.c +43 -9
110 lines not on this page · raw message
sound/arm/pxa2xx-pcm.c +4 -1
@@ -11,8 +11,11 @@*/ #include <linux/module.h> +#include <linux/dmaengine.h> +#include <sound/core.h> #include <sound/pxa2xx-lib.h> +#include <sound/dmaengine_pcm.h> #include "pxa2xx-pcm.h"
@@ -40,7 +43,7 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) rtd->params = (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ) ? client->playback_params : client->capture_params; - ret =pxa_request_dma (rtd->params->name,DMA_PRIO_LOW , + ret =pxa_request_dma ("dma" ,DMA_PRIO_LOW , pxa2xx_pcm_dma_irq, substream);if (ret <0 ) goto err2;
sound/arm/pxa2xx-pcm.h +3 -3
@@ -13,14 +13,14 @@struct pxa2xx_runtime_data {int dma_ch; -struct pxa2xx_pcm_dma_params *params; +struct snd_dmaengine_dai_dma_data *params;pxa_dma_desc *dma_desc_array;dma_addr_t dma_desc_array_phys; };struct pxa2xx_pcm_client { -struct pxa2xx_pcm_dma_params *playback_params; -struct pxa2xx_pcm_dma_params *capture_params; +struct snd_dmaengine_dai_dma_data *playback_params; +struct snd_dmaengine_dai_dma_data *capture_params;int (*startup)(struct snd_pcm_substream *);void (*shutdown)(struct snd_pcm_substream *);int (*prepare)(struct snd_pcm_substream *);
sound/soc/pxa/mmp-pcm.c +5 -3
@@ -17,6 +17,8 @@#include <linux/dmaengine.h> #include <linux/platform_data/dma-mmp_tdma.h> #include <linux/platform_data/mmp_audio.h> +#include <linux/dmaengine.h> +#include <sound/pxa2xx-lib.h> #include <sound/core.h> #include <sound/pcm.h>
@@ -67,7 +69,7 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream, {struct dma_chan *chan =snd_dmaengine_pcm_get_chan (substream);struct snd_soc_pcm_runtime *rtd = substream->private_data; -struct pxa2xx_pcm_dma_params *dma_params; +struct snd_dmaengine_dai_dma_data *dma_params;struct dma_slave_config slave_config;int ret;
@@ -80,10 +82,10 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream,return ret;if (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ) { - slave_config.dst_addr = dma_params->dev_addr; + slave_config.dst_addr = dma_params->addr; slave_config.dst_maxburst =4 ; }else { - slave_config.src_addr = dma_params->dev_addr; + slave_config.src_addr = dma_params->addr; slave_config.src_maxburst =4 ; }
sound/soc/pxa/mmp-sspa.c +8 -4
@@ -27,12 +27,15 @@#include <linux/slab.h> #include <linux/pxa2xx_ssp.h> #include <linux/io.h> +#include <linux/dmaengine.h> +#include <sound/core.h> #include <sound/pcm.h> #include <sound/initval.h> #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/pxa2xx-lib.h> +#include <sound/dmaengine_pcm.h> #include "mmp-sspa.h" /*
@@ -40,7 +43,7 @@*/ struct sspa_priv {struct ssp_device *sspa; -struct pxa2xx_pcm_dma_params *dma_params; +struct snd_dmaengine_dai_dma_data *dma_params;struct clk *audio_clk;struct clk *sysclk;int dai_fmt;
@@ -266,7 +269,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,struct snd_soc_dai *cpu_dai = rtd->cpu_dai;struct sspa_priv *sspa_priv =snd_soc_dai_get_drvdata (dai);struct ssp_device *sspa = sspa_priv->sspa; -struct pxa2xx_pcm_dma_params *dma_params; +struct snd_dmaengine_dai_dma_data *dma_params;u32 sspa_ctrl;if (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK )
@@ -309,7 +312,7 @@ static int mmp_sspa_hw_params(struct snd_pcm_substream *substream, } dma_params = &sspa_priv->dma_params[substream->stream]; - dma_params->dev_addr = substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ? + dma_params->addr = substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ? (sspa->phys_base +SSPA_TXD ) : (sspa->phys_base +SSPA_RXD );snd_soc_dai_set_dma_data (cpu_dai, substream, dma_params);
@@ -425,7 +428,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev)return -ENOMEM ; priv->dma_params =devm_kzalloc (&pdev->dev, -2 *sizeof (struct pxa2xx_pcm_dma_params ),GFP_KERNEL ); +2 *sizeof (struct snd_dmaengine_dai_dma_data ), +GFP_KERNEL );if (priv->dma_params ==NULL )return -ENOMEM ;
sound/soc/pxa/pxa-ssp.c +12 -24
@@ -22,6 +22,7 @@#include <linux/io.h> #include <linux/pxa2xx_ssp.h> #include <linux/of.h> +#include <linux/dmaengine.h> #include <asm/irq.h>
@@ -31,9 +32,9 @@#include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/pxa2xx-lib.h> +#include <sound/dmaengine_pcm.h> #include <mach/hardware.h> -#include <mach/dma.h> #include "../../arm/pxa2xx-pcm.h" #include "pxa-ssp.h"
@@ -80,27 +81,14 @@ static void pxa_ssp_disable(struct ssp_device *ssp)__raw_writel (sscr0, ssp->mmio_base +SSCR0 ); } -struct pxa2xx_pcm_dma_data { -struct pxa2xx_pcm_dma_params params; -char name[20 ]; -}; -static void pxa_ssp_set_dma_params (struct ssp_device *ssp,int width4, -int out,struct pxa2xx_pcm_dma_params *dma_data) +int out,struct snd_dmaengine_dai_dma_data *dma) { -struct pxa2xx_pcm_dma_data *dma; - - dma = container_of(dma_data, struct pxa2xx_pcm_dma_data, params); - -snprintf (dma->name,20 ,"SSP%d PCM %s %s" , ssp->port_id, - width4 ?"32-bit" :"16-bit" , out ?"out" :"in" ); - - dma->params.name = dma->name; - dma->params.drcmr = &DRCMR (out ? ssp->drcmr_tx : ssp->drcmr_rx); - dma->params.dcmd = (out ? (DCMD_INCSRCADDR |DCMD_FLOWTRG ) : - (DCMD_INCTRGADDR |DCMD_FLOWSRC )) | - (width4 ?DCMD_WIDTH4 :DCMD_WIDTH2 ) |DCMD_BURST16 ; - dma->params.dev_addr = ssp->phys_base +SSDR ; + dma->filter_data = out ? &ssp->drcmr_tx : &ssp->drcmr_rx; + dma->addr_width = width4 ?DMA_SLAVE_BUSWIDTH_4_BYTES : +DMA_SLAVE_BUSWIDTH_2_BYTES ; + dma->maxburst =16 ; + dma->addr = ssp->phys_base +SSDR ; } static int pxa_ssp_startup(struct snd_pcm_substream *substream,
@@ -108,7 +96,7 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, {struct ssp_priv *priv =snd_soc_dai_get_drvdata (cpu_dai);struct ssp_device *ssp = priv->ssp; -struct pxa2xx_pcm_dma_data *dma; +struct snd_dmaengine_dai_dma_data *dma;int ret =0 ;if (!cpu_dai->active) {
@@ -116,10 +104,10 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,pxa_ssp_disable (ssp); } - dma =kzalloc (sizeof (struct pxa2xx_pcm_dma_data ),GFP_KERNEL ); + dma =kzalloc (sizeof (struct snd_dmaengine_dai_dma_data ),GFP_KERNEL );if (!dma)return -ENOMEM ; -snd_soc_dai_set_dma_data (cpu_dai, substream, &dma->params); +snd_soc_dai_set_dma_data (cpu_dai, substream, dma);return ret; }
@@ -560,7 +548,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,u32 sspsp;int width =snd_pcm_format_physical_width (params_format (params));int ttsa =pxa_ssp_read_reg (ssp,SSTSA ) &0xf ; -struct pxa2xx_pcm_dma_params *dma_data; +struct snd_dmaengine_dai_dma_data *dma_data; dma_data =snd_soc_dai_get_dma_data (cpu_dai, substream);
sound/soc/pxa/pxa2xx-ac97.c +34 -33
107 lines not on this page · raw message
sound/soc/pxa/pxa2xx-i2s.c +14 -14
@@ -23,9 +23,9 @@#include <sound/initval.h> #include <sound/soc.h> #include <sound/pxa2xx-lib.h> +#include <sound/dmaengine_pcm.h> #include <mach/hardware.h> -#include <mach/dma.h> #include <mach/audio.h> #include "pxa2xx-i2s.h"
@@ -82,20 +82,20 @@ static struct pxa_i2s_port pxa_i2s;static struct clk *clk_i2s;static int clk_ena =0 ; -static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { - .name ="I2S PCM Stereo out" , - .dev_addr =__PREG (SADR ), - .drcmr = &DRCMR (3 ), - .dcmd =DCMD_INCSRCADDR |DCMD_FLOWTRG | -DCMD_BURST32 |DCMD_WIDTH4 , +static unsigned long pxa2xx_i2s_pcm_stereo_out_req =3 ; +static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_out = { + .addr =__PREG (SADR ), + .addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES , + .maxburst =32 , + .filter_data = &pxa2xx_i2s_pcm_stereo_out_req, }; -static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { - .name ="I2S PCM Stereo in" , - .dev_addr =__PREG (SADR ), - .drcmr = &DRCMR (2 ), - .dcmd =DCMD_INCTRGADDR |DCMD_FLOWSRC | -DCMD_BURST32 |DCMD_WIDTH4 , +static unsigned long pxa2xx_i2s_pcm_stereo_in_req =2 ; +static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_in = { + .addr =__PREG (SADR ), + .addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES , + .maxburst =32 , + .filter_data = &pxa2xx_i2s_pcm_stereo_in_req, }; static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
@@ -163,7 +163,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct pxa2xx_pcm_dma_params *dma_data; + struct snd_dmaengine_dai_dma_data *dma_data;BUG_ON (IS_ERR (clk_i2s));clk_prepare_enable (clk_i2s);
sound/soc/pxa/pxa2xx-pcm.c +5 -3
@@ -12,10 +12,12 @@#include <linux/dma-mapping.h> #include <linux/module.h> +#include <linux/dmaengine.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/pxa2xx-lib.h> +#include <sound/dmaengine_pcm.h> #include "../../arm/pxa2xx-pcm.h"
@@ -25,7 +27,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_runtime *runtime = substream->runtime;struct pxa2xx_runtime_data *prtd = runtime->private_data;struct snd_soc_pcm_runtime *rtd = substream->private_data; -struct pxa2xx_pcm_dma_params *dma; +struct snd_dmaengine_dai_dma_data *dma;int ret; dma =snd_soc_dai_get_dma_data (rtd->cpu_dai, substream);
@@ -39,7 +41,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,* with different params */ if (prtd->params ==NULL ) { prtd->params = dma; - ret =pxa_request_dma (prtd->params->name,DMA_PRIO_LOW , + ret =pxa_request_dma ("name" ,DMA_PRIO_LOW , pxa2xx_pcm_dma_irq, substream);if (ret <0 )return ret;
@@ -47,7 +49,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, }else if (prtd->params != dma) {pxa_free_dma (prtd->dma_ch); prtd->params = dma; - ret =pxa_request_dma (prtd->params->name,DMA_PRIO_LOW , + ret =pxa_request_dma ("name" ,DMA_PRIO_LOW , pxa2xx_pcm_dma_irq, substream);if (ret <0 )return ret;
Signature · 1 line
1.8.3.1
Mark Brown
maintainerPATCH 14/20 ASoC: pxa: use snd_dmaengine_dai_dma_data
Quoted 6 lines · Daniel Mack
Use
snd_dmaengine_dai_dma_datafor passing the dma parameters from clients to the pxa pcm lib. This does no functional change, it's just an intermedia step to migrate the pxa bits over to dmaengine.The calculation of dcmd is a transition hack which will be removed again in a later patch. It's just there to make the transition more readable.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/623ef729/attachment.sig>
PATCH 15/20 ASoC: pxa: pxa-ssp: set dma filter data from startup hook
In reply to Daniel MackWith the new dmaengine implementation, the filter_data parameter has to be set earlier, from pxa_ssp_startup().
--- sound/soc/pxa/pxa-ssp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
sound/soc/pxa/pxa-ssp.c +4 -1
@@ -84,7 +84,6 @@ static void pxa_ssp_disable(struct ssp_device *ssp)static void pxa_ssp_set_dma_params (struct ssp_device *ssp,int width4,int out,struct snd_dmaengine_dai_dma_data *dma) { - dma->filter_data = out ? &ssp->drcmr_tx : &ssp->drcmr_rx; dma->addr_width = width4 ?DMA_SLAVE_BUSWIDTH_4_BYTES :DMA_SLAVE_BUSWIDTH_2_BYTES ; dma->maxburst =16 ;
@@ -107,6 +106,10 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, dma =kzalloc (sizeof (struct snd_dmaengine_dai_dma_data ),GFP_KERNEL );if (!dma)return -ENOMEM ; + + dma->filter_data = substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ? + &ssp->drcmr_tx : &ssp->drcmr_rx; +snd_soc_dai_set_dma_data (cpu_dai, substream, dma);return ret;
Signature · 1 line
1.8.3.1
Mark Brown
maintainerPATCH 15/20 ASoC: pxa: pxa-ssp: set dma filter data from startup hook
Quoted 2 lines · Daniel Mack
With the new dmaengine implementation, the
filter_dataparameter has to be set earlier, frompxa_ssp_startup().
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/8f30627e/attachment.sig>
PATCH 16/20 ASoC: pxa: add DT bindings for pxa2xx-pcm
In reply to Daniel MackThe bindings do not carry any resources, as the module only registers the ASoC platform driver.
--- .../devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt | 15 +++++++++++++++ sound/soc/pxa/pxa2xx-pcm.c | 13 +++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt new file +15 -0
@@ -0,0 +1,15 @@ +DT bindings for ARM PXA2xx PCM platform driver + +This is just a dummy driver that registers the PXA ASoC platform driver. +It does not have any resources assigned. + +Required properties: + + - compatible 'mrvl,pxa-pcm-audio' + +Example: + + pxa_pcm_audio: snd_soc_pxa_audio { + compatible = "mrvl,pxa-pcm-audio"; + }; +
sound/soc/pxa/pxa2xx-pcm.c +11 -2
@@ -13,6 +13,7 @@#include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/dmaengine.h> +#include <linux/of.h> #include <sound/core.h> #include <sound/soc.h>
@@ -133,10 +134,18 @@ static int pxa2xx_soc_platform_remove(struct platform_device *pdev)return 0 ; } +#ifdef CONFIG_OF +static const struct of_device_id snd_soc_pxa_audio_match[] = { + { .compatible ="mrvl,pxa-pcm-audio" }, + { } +}; +#endif +static struct platform_driver pxa_pcm_driver = { .driver = { - .name ="pxa-pcm-audio" , - .owner =THIS_MODULE , + .name ="pxa-pcm-audio" , + .owner =THIS_MODULE , + .of_match_table =of_match_ptr (snd_soc_pxa_audio_match), }, .probe = pxa2xx_soc_platform_probe,
Signature · 1 line
1.8.3.1
Mark Brown
maintainerPATCH 16/20 ASoC: pxa: add DT bindings for pxa2xx-pcm
Quoted 2 lines · Daniel Mack
The bindings do not carry any resources, as the module only registers the ASoC platform driver.
This should be done by the device for the DAI (as with other DT
platforms that have a similar thing where the DMA device is just a
wrapper around dmaengine). This is slightly funky here, I'll follow up
on the first patch about that.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/d40d5b19/attachment.sig>
PATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
In reply to Daniel MackThis patch removes the old PXA DMA API usage and switches over to generic functions provided by snd-soc-dmaengine-pcm.
More cleanups may be done on top of this, and some function stubs can now be removed completetly. However, the intention here was to keep the transition as small as possible.
--- include/sound/pxa2xx-lib.h | 1 - sound/arm/Kconfig | 1 + sound/arm/pxa2xx-pcm-lib.c | 203 ++++++++------------------------------------- sound/arm/pxa2xx-pcm.c | 12 +-- sound/arm/pxa2xx-pcm.h | 3 - sound/soc/pxa/pxa2xx-pcm.c | 26 +----- 6 files changed, 42 insertions(+), 204 deletions(-)
include/sound/pxa2xx-lib.h +0 -1
@@ -12,7 +12,6 @@ extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream);extern int pxa2xx_pcm_trigger (struct snd_pcm_substream *substream,int cmd);extern snd_pcm_uframes_t pxa2xx_pcm_pointer (struct snd_pcm_substream *substream);extern int __pxa2xx_pcm_prepare (struct snd_pcm_substream *substream); -extern void pxa2xx_pcm_dma_irq (int dma_ch,void *dev_id);extern int __pxa2xx_pcm_open (struct snd_pcm_substream *substream);extern int __pxa2xx_pcm_close (struct snd_pcm_substream *substream); extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
sound/arm/Kconfig +1 -0
@@ -24,6 +24,7 @@ config SND_PXA2XX_PCM config SND_PXA2XX_LIB tristate select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97 + select SND_SOC_DMAENGINE_PCM config SND_PXA2XX_LIB_AC97 bool
sound/arm/pxa2xx-pcm-lib.c +36 -167
285 lines not on this page · raw message
sound/arm/pxa2xx-pcm.c +3 -9
@@ -43,17 +43,13 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) rtd->params = (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ) ? client->playback_params : client->capture_params; - ret =pxa_request_dma ("dma" ,DMA_PRIO_LOW , - pxa2xx_pcm_dma_irq, substream); -if (ret <0 ) - goto err2; - rtd->dma_ch = ret; ret = client->startup (substream);if (!ret) - goto out; + goto err2; + +return 0 ; -pxa_free_dma (rtd->dma_ch); err2:__pxa2xx_pcm_close (substream); out:
@@ -63,9 +59,7 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)static int pxa2xx_pcm_close (struct snd_pcm_substream *substream) {struct pxa2xx_pcm_client *client = substream->private_data; -struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; -pxa_free_dma (rtd->dma_ch); client->shutdown (substream);return __pxa2xx_pcm_close (substream);
sound/arm/pxa2xx-pcm.h +0 -3
@@ -9,13 +9,10 @@* it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <mach/dma.h> struct pxa2xx_runtime_data {int dma_ch;struct snd_dmaengine_dai_dma_data *params; -pxa_dma_desc *dma_desc_array; -dma_addr_t dma_desc_array_phys; };struct pxa2xx_pcm_client {
sound/soc/pxa/pxa2xx-pcm.c +2 -24
@@ -29,7 +29,6 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,struct pxa2xx_runtime_data *prtd = runtime->private_data;struct snd_soc_pcm_runtime *rtd = substream->private_data;struct snd_dmaengine_dai_dma_data *dma; -int ret; dma =snd_soc_dai_get_dma_data (rtd->cpu_dai, substream);
@@ -38,24 +37,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,if (!dma)return 0 ; -/* this may get called several times by oss emulation -* with different params */ -if (prtd->params ==NULL ) { - prtd->params = dma; - ret =pxa_request_dma ("name" ,DMA_PRIO_LOW , - pxa2xx_pcm_dma_irq, substream); -if (ret <0 ) -return ret; - prtd->dma_ch = ret; - }else if (prtd->params != dma) { -pxa_free_dma (prtd->dma_ch); - prtd->params = dma; - ret =pxa_request_dma ("name" ,DMA_PRIO_LOW , - pxa2xx_pcm_dma_irq, substream); -if (ret <0 ) -return ret; - prtd->dma_ch = ret; - } + prtd->params = dma;return __pxa2xx_pcm_hw_params (substream, params); }
@@ -66,11 +48,7 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)__pxa2xx_pcm_hw_free (substream); -if (prtd->dma_ch >=0 ) { -pxa_free_dma (prtd->dma_ch); - prtd->dma_ch =-1 ; - prtd->params =NULL ; - } + prtd->params =NULL ;return 0 ; }
Signature · 1 line
1.8.3.1
Mark Brown
maintainerPATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 6 lines · Daniel Mack
This patch removes the old PXA DMA API usage and switches over to generic functions provided by snd-soc-dmaengine-pcm.
More cleanups may be done on top of this, and some function stubs can now be removed completetly. However, the intention here was to keep the transition as small as possible.
Has this been tested with the standalone non-ASoC PXA AC'97 driver?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/48f7b924/attachment-0001.sig>
PATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 9 lines · Mark Brown
Quoted 6 lines · Daniel Mack
This patch removes the old PXA DMA API usage and switches over to generic functions provided by snd-soc-dmaengine-pcm.
More cleanups may be done on top of this, and some function stubs can now be removed completetly. However, the intention here was to keep the transition as small as possible.
Has this been tested with the standalone non-ASoC PXA AC'97 driver?
Nope. I have no such device.
It's a real problem for me regarding the entire series. Many drivers are used in a variaty of runtime configurations, and I can only test a fraction of them myself of course.
I'd appreciate fix-up patches that I can squash or put on top of mine from anyone who sees breakage.
Daniel
Mark Brown
maintainerPATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 5 lines · Daniel Mack
Quoted 1 line · Mark Brown
Has this been tested with the standalone non-ASoC PXA AC'97 driver?
Nope. I have no such device.
I guess the main test there will be making sure that it builds with ASoC
disabled. I'm not sure anything later than PXA3xx ever actually used
AC'97.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130807/5584ac0c/attachment.sig>
PATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 11 lines · Mark Brown
Quoted 5 lines · Daniel Mack
Quoted 1 line · Mark Brown
Has this been tested with the standalone non-ASoC PXA AC'97 driver?
Nope. I have no such device.
I guess the main test there will be making sure that it builds with ASoC disabled. I'm not sure anything later than PXA3xx ever actually used AC'97.
Ah, I see it now.
I guess we have two options: either duplicate code from soc-dmaengine-pcm, or move soc-dmaengine-pcm out of the ASoC context. I actually see no dependecy to ASoC from there anyway.
Daniel
PATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 13 lines · Daniel Mack
Quoted 11 lines · Mark Brown
Quoted 5 lines · Daniel Mack
Quoted 1 line · Mark Brown
Has this been tested with the standalone non-ASoC PXA AC'97 driver?
Nope. I have no such device.
I guess the main test there will be making sure that it builds with ASoC disabled. I'm not sure anything later than PXA3xx ever actually used AC'97.
Quoted 5 lines
Ah, I see it now.
I guess we have two options: either duplicate code from soc-dmaengine-pcm, or move soc-dmaengine-pcm out of the ASoC context. I actually see no dependecy to ASoC from there anyway.
There is intentionally no dependency on ASoC for the soc-dmaengine-pcm code, though since I wasn't sure whether there was ever going to be a userside outside of ASoC the coded ended up in ASoC folder. It shouldn't be a problem to make it available to all of ALSA.
Not that the soc-generic-dmaengine-pcm code has a dependency on ASoC though.
- Lars
PATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 10 lines · Lars-Peter Clausen
Quoted 3 lines · Daniel Mack
I guess we have two options: either duplicate code from soc-dmaengine-pcm, or move soc-dmaengine-pcm out of the ASoC context. I actually see no dependecy to ASoC from there anyway.
There is intentionally no dependency on ASoC for the soc-dmaengine-pcm code, though since I wasn't sure whether there was ever going to be a userside outside of ASoC the coded ended up in ASoC folder. It shouldn't be a problem to make it available to all of ALSA.
Ok, great. I queued a patch for that. Will be part of my next spin, or, in case the series doesn't make it in time, I'll re-post all the patches that can be applied independently up front.
Thanks,
Daniel
Mark Brown
maintainerPATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 10 lines · Daniel Mack
Quoted 4 lines · Lars-Peter Clausen
There is intentionally no dependency on ASoC for the soc-dmaengine-pcm code, though since I wasn't sure whether there was ever going to be a userside outside of ASoC the coded ended up in ASoC folder. It shouldn't be a problem to make it available to all of ALSA.
Ok, great. I queued a patch for that. Will be part of my next spin, or, in case the series doesn't make it in time, I'll re-post all the patches that can be applied independently up front.
You probably don't need to move it, just adding a select (which should
ignore Kconfig dependencies) from the non-ASoC PXA stuff ought to do the
trick.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130808/871e2548/attachment.sig>
PATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 8 lines · Mark Brown
Quoted 6 lines · Daniel Mack
Quoted 4 lines · Lars-Peter Clausen
There is intentionally no dependency on ASoC for the soc-dmaengine-pcm code, though since I wasn't sure whether there was ever going to be a userside outside of ASoC the coded ended up in ASoC folder. It shouldn't be a problem to make it available to all of ALSA.
Quoted 7 lines
Quoted 3 lines
Ok, great. I queued a patch for that. Will be part of my next spin, or, in case the series doesn't make it in time, I'll re-post all the patches that can be applied independently up front.
You probably don't need to move it, just adding a select (which should ignore
Kconfigdependencies) from the non-ASoC PXA stuff ought to do the trick.
Hmm. We have this big "if SND_SOC" in sound/soc/Kconfig which prevent that symbol to be selected. In fact, SND_PXA2XX_LIB already selected SND_SOC_DMAENGINE_PCM, but that didn't help.
And code that is not ASoC specific should live outside of sound/soc, no?
Daniel
Mark Brown
maintainerPATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 3 lines · Daniel Mack
Hmm. We have this big "if
SND_SOC" insound/soc/Kconfigwhich prevent that symbol to be selected. In fact,SND_PXA2XX_LIBalready selectedSND_SOC_DMAENGINE_PCM, but that didn't help.
Ah, that'd cause problems.
Quoted 1 line
And code that is not ASoC specific should live outside of
sound/soc, no?
Yeah, OTOH it's pretty much entirely for ASoC and it'd be less churn.
No problem to move it though, but please leave in the files pattern for
ASoC.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130808/87bb04c1/attachment.sig>
PATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 6 lines · Mark Brown
Quoted 3 lines · Daniel Mack
Hmm. We have this big "if
SND_SOC" insound/soc/Kconfigwhich prevent that symbol to be selected. In fact,SND_PXA2XX_LIBalready selectedSND_SOC_DMAENGINE_PCM, but that didn't help.
Quoted 7 lines
Ah, that'd cause problems.
Quoted 1 line
And code that is not ASoC specific should live outside of
sound/soc, no?Yeah, OTOH it's pretty much entirely for ASoC and it'd be less churn. No problem to move it though, but please leave in the files pattern for ASoC.
So you'd be unhappy with this?
Mark Brown
maintainerPATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
Quoted 3 lines · Daniel Mack
So you'd be unhappy with this?
No, that seems fine. But please just post patches instead of sending
links.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130808/8da44ee6/attachment.sig>
PATCH 17/20 ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
In reply to Mark BrownQuoted 8 lines · Mark Brown
Quoted 6 lines · Daniel Mack
Quoted 4 lines · Lars-Peter Clausen
There is intentionally no dependency on ASoC for the soc-dmaengine-pcm code, though since I wasn't sure whether there was ever going to be a userside outside of ASoC the coded ended up in ASoC folder. It shouldn't be a problem to make it available to all of ALSA.
Quoted 7 lines
Quoted 3 lines
Ok, great. I queued a patch for that. Will be part of my next spin, or, in case the series doesn't make it in time, I'll re-post all the patches that can be applied independently up front.
You probably don't need to move it, just adding a select (which should ignore
Kconfigdependencies) from the non-ASoC PXA stuff ought to do the trick.
... which gets you a warning from modern kconfig tools.
PATCH 18/20 ARM: pxa: register static mmp_pdma device
In reply to Daniel MackDrop the init call to the properietary dma subsystem and register the mmp_pdma device.
--- arch/arm/mach-pxa/devices.c | 26 ++++++++++++++++++++++++++ arch/arm/mach-pxa/devices.h | 1 + arch/arm/mach-pxa/pxa25x.c | 9 ++++++--- arch/arm/mach-pxa/pxa27x.c | 9 ++++++--- arch/arm/mach-pxa/pxa3xx.c | 11 +++++++---- 5 files changed, 46 insertions(+), 10 deletions(-)
arch/arm/mach-pxa/devices.c +26 -0
@@ -46,6 +46,32 @@ struct platform_device pxa_device_pmu = { .num_resources = 1, }; +static struct resource pxadma_resources[] = { + [0 ] = { + .start =0x40000000 , + .end =0x40001fff , + .flags =IORESOURCE_MEM , + }, + [1 ] = { + .start =IRQ_DMA , + .end =IRQ_DMA , + .flags =IORESOURCE_IRQ , + }, +}; + +static u64 pxadma_dmamask =0xffffffffUL ; + +struct platform_device pxa_device_dma = { + .name ="mmp-pdma" , + .id =0 , + .dev = { + .dma_mask = &pxadma_dmamask, + .coherent_dma_mask =0xffffffff , + }, + .num_resources =ARRAY_SIZE (pxadma_resources), + .resource = pxadma_resources, +}; +static struct resource pxamci_resources[] = { [0 ] = { .start =0x41100000 ,
arch/arm/mach-pxa/devices.h +1 -0
@@ -1,4 +1,5 @@extern struct platform_device pxa_device_pmu; +extern struct platform_device pxa_device_dma;extern struct platform_device pxa_device_mci;extern struct platform_device pxa3xx_device_mci2;extern struct platform_device pxa3xx_device_mci3;
arch/arm/mach-pxa/pxa25x.c +6 -3
@@ -25,6 +25,7 @@#include <linux/suspend.h> #include <linux/syscore_ops.h> #include <linux/irq.h> +#include <linux/platform_data/mmp_dma.h> #include <asm/mach/map.h> #include <asm/suspend.h>
@@ -33,7 +34,6 @@#include <mach/pxa25x.h> #include <mach/reset.h> #include <mach/pm.h> -#include <mach/dma.h> #include <mach/smemc.h> #include "generic.h"
@@ -348,6 +348,10 @@ static struct pxa_gpio_platform_data pxa25x_gpio_info __initdata = { .gpio_set_wake = gpio_set_wake, }; +static struct mmp_dma_platdata pxa25x_dma_data__initdata = { + .dma_channels =16 , +}; +static struct platform_device *pxa25x_devices[]__initdata = { &pxa25x_device_udc, &pxa_device_pmu,
@@ -371,8 +375,7 @@ static int __init pxa25x_init(void)clkdev_add_table (pxa25x_clkregs,ARRAY_SIZE (pxa25x_clkregs)); -if ((ret =pxa_init_dma (IRQ_DMA ,16 ))) -return ret; +pxa_register_device (&pxa_device_dma, &pxa25x_dma_data);pxa25x_init_pm ();
arch/arm/mach-pxa/pxa27x.c +6 -3
@@ -22,6 +22,7 @@#include <linux/io.h> #include <linux/irq.h> #include <linux/i2c/pxa-i2c.h> +#include <linux/platform_data/mmp_dma.h> #include <asm/mach/map.h> #include <mach/hardware.h>
@@ -32,7 +33,6 @@#include <mach/reset.h> #include <linux/platform_data/usb-ohci-pxa27x.h> #include <mach/pm.h> -#include <mach/dma.h> #include <mach/smemc.h> #include "generic.h"
@@ -435,6 +435,10 @@ static struct pxa_gpio_platform_data pxa27x_gpio_info __initdata = { .gpio_set_wake = gpio_set_wake, }; +static struct mmp_dma_platdata pxa27x_dma_data__initdata = { + .dma_channels =32 , +}; +static struct platform_device *devices[]__initdata = { &pxa27x_device_udc, &pxa_device_pmu,
@@ -462,8 +466,7 @@ static int __init pxa27x_init(void)clkdev_add_table (pxa27x_clkregs,ARRAY_SIZE (pxa27x_clkregs)); -if ((ret =pxa_init_dma (IRQ_DMA ,32 ))) -return ret; +pxa_register_device (&pxa_device_dma, &pxa27x_dma_data);pxa27x_init_pm ();
arch/arm/mach-pxa/pxa3xx.c +7 -4
@@ -23,6 +23,7 @@#include <linux/of.h> #include <linux/syscore_ops.h> #include <linux/i2c/pxa-i2c.h> +#include <linux/platform_data/mmp_dma.h> #include <asm/mach/map.h> #include <asm/suspend.h>
@@ -31,7 +32,6 @@#include <mach/reset.h> #include <linux/platform_data/usb-ohci-pxa27x.h> #include <mach/pm.h> -#include <mach/dma.h> #include <mach/smemc.h> #include <mach/irqs.h>
@@ -441,6 +441,10 @@ static struct pxa_gpio_platform_data pxa3xx_gpio_pdata = { .irq_base = PXA_GPIO_TO_IRQ(0), }; +static struct mmp_dma_platdata pxa3xx_dma_data__initdata = { + .dma_channels =32 , +}; +static struct platform_device *devices[]__initdata = { &pxa27x_device_udc, &pxa_device_pmu,
@@ -478,9 +482,6 @@ static int __init pxa3xx_init(void)clkdev_add_table (pxa3xx_clkregs,ARRAY_SIZE (pxa3xx_clkregs)); -if ((ret =pxa_init_dma (IRQ_DMA ,32 ))) -return ret; -pxa3xx_init_pm ();register_syscore_ops (&pxa_irq_syscore_ops);
@@ -490,6 +491,8 @@ static int __init pxa3xx_init(void)if (of_have_populated_dt ())return 0 ; +pxa_register_device (&pxa_device_dma, &pxa3xx_dma_data); + ret =platform_add_devices (devices,ARRAY_SIZE (devices));if (ret)return ret;
Signature · 1 line
1.8.3.1
PATCH 19/20 ARM: mmp: register static mmp_pdma device
In reply to Daniel MackDrop the init call to the properietary dma subsystem and register the mmp_pdma device.
--- arch/arm/mach-mmp/mmp2.c | 11 +++++++++-- arch/arm/mach-mmp/pxa168.c | 11 +++++++++-- arch/arm/mach-mmp/pxa910.c | 11 +++++++++-- 3 files changed, 27 insertions(+), 6 deletions(-)
arch/arm/mach-mmp/mmp2.c +9 -2
@@ -14,6 +14,7 @@#include <linux/init.h> #include <linux/io.h> #include <linux/platform_device.h> +#include <linux/platform_data/mmp_dma.h> #include <asm/hardware/cache-tauros2.h>
@@ -22,7 +23,6 @@#include <mach/regs-apbc.h> #include <mach/cputype.h> #include <mach/irqs.h> -#include <mach/dma.h> #include <mach/mfp.h> #include <mach/devices.h> #include <mach/mmp2.h>
@@ -96,6 +96,12 @@ void __init mmp2_init_irq(void)mmp2_init_icu (); } +static struct mmp_dma_platdata mmp2_dma_data__initdata = { + .dma_channels =16 , +}; + +MMP2_DEVICE (dma,"mmp-pdma" ,0 ,DMA_RIQ ,0x40000000 ,0x2000 ); +static int __init mmp2_init (void ) {if (cpu_is_mmp2 ()) {
@@ -104,7 +110,8 @@ static int __init mmp2_init(void)#endif mfp_init_base (MFPR_VIRT_BASE );mfp_init_addr (mmp2_addr_map); -pxa_init_dma (IRQ_MMP2_DMA_RIQ ,16 ); +pxa_register_device (&mmp2_device_dma, &mmp2_dma_data, +sizeof (mmp2_dma_data));mmp2_clk_init (); }
arch/arm/mach-mmp/pxa168.c +9 -2
@@ -15,6 +15,7 @@#include <linux/clk.h> #include <linux/platform_device.h> #include <linux/platform_data/mv_usb.h> +#include <linux/platform_data/mmp_dma.h> #include <asm/mach/time.h> #include <asm/system_misc.h>
@@ -23,7 +24,6 @@#include <mach/regs-apbc.h> #include <mach/regs-apmu.h> #include <mach/irqs.h> -#include <mach/dma.h> #include <mach/devices.h> #include <mach/mfp.h> #include <linux/dma-mapping.h>
@@ -50,12 +50,19 @@ void __init pxa168_init_irq(void)icu_init_irq (); } +static struct mmp_dma_platdata pxa168_dma_data__initdata = { + .dma_channels =32 , +}; + +PXA168_DEVICE (dma,"mmp-pdma" ,0 ,DMA_INT0 ,0x40000000 ,0x2000 ); +static int __init pxa168_init (void ) {if (cpu_is_pxa168 ()) {mfp_init_base (MFPR_VIRT_BASE );mfp_init_addr (pxa168_mfp_addr_map); -pxa_init_dma (IRQ_PXA168_DMA_INT0 ,32 ); +pxa_register_device (&pxa168_device_dma, &pxa168_dma_data, +sizeof (pxa168_dma_data));pxa168_clk_init (); }
arch/arm/mach-mmp/pxa910.c +9 -2
@@ -13,6 +13,7 @@#include <linux/list.h> #include <linux/io.h> #include <linux/platform_device.h> +#include <linux/platform_data/mmp_dma.h> #include <asm/hardware/cache-tauros2.h> #include <asm/mach/time.h>
@@ -20,7 +21,6 @@#include <mach/regs-apbc.h> #include <mach/cputype.h> #include <mach/irqs.h> -#include <mach/dma.h> #include <mach/mfp.h> #include <mach/devices.h>
@@ -81,6 +81,12 @@ void __init pxa910_init_irq(void)icu_init_irq (); } +static struct mmp_dma_platdata pxa910_dma_data__initdata = { + .dma_channels =32 , +}; + +PXA910_DEVICE (dma,"mmp-pdma" ,0 ,DMA_INT0 ,0x40000000 ,0x2000 ); +static int __init pxa910_init (void ) {if (cpu_is_pxa910 ()) {
@@ -89,7 +95,8 @@ static int __init pxa910_init(void)#endif mfp_init_base (MFPR_VIRT_BASE );mfp_init_addr (pxa910_mfp_addr_map); -pxa_init_dma (IRQ_PXA910_DMA_INT0 ,32 ); +pxa_register_device (&pxa910_device_dma, &pxa910_dma_data, +sizeof (pxa910_dma_data));pxa910_clk_init (); }
Signature · 1 line
1.8.3.1
PATCH 20/20 ARM: pxa: remove old DMA implementation
In reply to Daniel Mack--- arch/arm/mach-pxa/include/mach/dma.h | 21 -- arch/arm/plat-pxa/Makefile | 2 - arch/arm/plat-pxa/dma.c | 391 ----------------------------------- arch/arm/plat-pxa/include/plat/dma.h | 85 -------- 4 files changed, 499 deletions(-) delete mode 100644 arch/arm/mach-pxa/include/mach/dma.h delete mode 100644 arch/arm/plat-pxa/dma.c delete mode 100644 arch/arm/plat-pxa/include/plat/dma.h
arch/arm/mach-pxa/include/mach/dma.h deleted +0 -21
@@ -1,21 +0,0 @@ -/* -* arch/arm/mach-pxa/include/mach/dma.h -* -* Author: Nicolas Pitre -* Created: Jun 15, 2001 -* Copyright: MontaVista Software, Inc. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -*/ -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -#include <mach/hardware.h> - -/* DMA Controller Registers Definitions */ -#define DMAC_REGS_VIRT io_p2v(0x40000000) - -#include <plat/dma.h> -#endif /* _ASM_ARCH_DMA_H */
arch/arm/plat-pxa/Makefile +0 -2
@@ -2,8 +2,6 @@ # Makefile for code common across different PXA processor families # -obj-y := dma.o - obj-$(CONFIG_PXA3xx) += mfp.o obj-$(CONFIG_ARCH_MMP) += mfp.o
arch/arm/plat-pxa/dma.c deleted +0 -391
391 lines not on this page · raw message
arch/arm/plat-pxa/include/plat/dma.h deleted +0 -85
85 lines not on this page · raw message
Signature · 1 line
1.8.3.1
cover ARM: pxa: move core and drivers to dmaengine
In reply to Daniel MackQuoted 20 lines · Daniel Mack
I've been working on teaching the mmp-pdma driver more functions and porting tree-wide scattered pxa specific drivers over to dmaengine implementations. I posted the first round of patches for mmp-pdma here:
http://marc.info/?l=linux-arm-kernel&m=137587082530228
With the following patches applied, I can boot a PXA3xx board boot with all DMA runtime information determined from DT, using pxa3xx-nand, pxamci and audio components (cyclic DMA).
However, the transition is quite intrusive and spans across several subsystem, and due to the nature of the current pxa DMA implementation, it cannot be gap-less. All drivers currently request an exclusive channel via code in
arch/arm/plat-pxa/dma.cand then do direct register modifications regarding their obtained channel. We can't allow this with the mmp-pdma driver of course, and I also have no idea how to provide sane stubs for the existing hooks which end up in dmaengine calls.
Quoted 4 lines
Hence, all drivers have to be ported over in one series, and all these changes should be merged by one pull request eventually in order to prevent both build and functional breakage. Haojian's repository seems most suitable for that, as he's the PXA maintainer.
Very nice series! I just looked over these and only found a few minor details that could be improved.
Arnd
Robert Jarzmik
maintainercover ARM: pxa: move core and drivers to dmaengine
In reply to Daniel MackQuoted 5 lines · Daniel Mack
* camera driver:
I started the transition, but I'm not sure how much sense that makes without access to the hardware. I'd much appreciate if anyone could volunteer for this piece; I'll happily share what I got so far. Sascha, Sachin, Guennadi?
Hi Daniel,
Do you mean this driver ? :drivers/media/platform/soc_camera/pxa_camera.c
In that case I might help. But before I can do that, I have to be convinced that dmaengine can deal with this driver. I'm thinking in particular of :
- "hot running DMA" queuing
- multiple DMA channel synchronization (ie. 3 channel sync)
All that is described in there :
Documentation/video4linux/pxa_camera.txt
If someone with dmaengine knowledge could have a look at pxa_camera.txt (maybe Vinod ?) and tell me that dma_engine framework fullfills the 2 requirements, then I'll be happy to help.
One minor point though is that I'm working on pxa27x. If the serie is not compatible in a way with pxa27x, I won't be able to do anything.
Another point I'd like to know, is what is the performance penalty in using dmaengine, and do you have any figures ?
Lastly, they was debug information to debug descriptors chaining, channel statuses, requestors. I didn't see where these had gone, could you point me to the right file ?
Cheers.
Signature · 1 line
Robert
cover ARM: pxa: move core and drivers to dmaengine
Hi Robert,
Quoted 11 lines · Robert Jarzmik
Quoted 5 lines · Daniel Mack
* camera driver:
I started the transition, but I'm not sure how much sense that makes without access to the hardware. I'd much appreciate if anyone could volunteer for this piece; I'll happily share what I got so far. Sascha, Sachin, Guennadi?Hi Daniel,
Do you mean this driver ? :
drivers/media/platform/soc_camera/pxa_camera.c
Yes, exactly.
Quoted 7 lines
In that case I might help. But before I can do that, I have to be convinced that dmaengine can deal with this driver. I'm thinking in particular of :
- "hot running DMA" queuing
- multiple DMA channel synchronization (ie. 3 channel sync)All that is described in there :
Documentation/video4linux/pxa_camera.txt
Yes, I've seen that, and while the documentation about all that is excellent, I lack an explanation why things are so complicated for this application, and why a simple cyclic DMA approach does not suffice here. I'm sure there's a reason though.
There might be need to teach the dmaengine core more functionality, but in order to do that, we first need to understand the exact requirements.
Quoted 3 lines
If someone with dmaengine knowledge could have a look at pxa_camera.txt (maybe Vinod ?) and tell me that
dma_engineframework fullfills the 2 requirements, then I'll be happy to help.
Yes, Vinod and and Dan are certainly the best ones to comment on that I think.
Quoted 2 lines
One minor point though is that I'm working on pxa27x. If the serie is not compatible in a way with pxa27x, I won't be able to do anything.
No, it should work just fine on pxa27x.
Quoted 2 lines
Another point I'd like to know, is what is the performance penalty in using dmaengine, and do you have any figures ?
The DMA transfers themselves certainly perform equally well, and the framework is just a thin layer. Where would you expect performance penalty?
Quoted 3 lines
Lastly, they was debug information to debug descriptors chaining, channel statuses, requestors. I didn't see where these had gone, could you point me to the right file ?
Such a debug interface is not part of the mmp-pdma implementation at this point, and the core doesn't have a generic debugfs feature either. If you need that, we'd have to add it back.
FWIW, I attached my work-in-progress patch for this driver which just does some basic dmaengine preparations. Be aware that this does not even compile, it's really just a snapshot.
Thanks,
Daniel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-drivers-media-platform-soc_camera-pxa_camera.c-DMAEN.patch
Type: text/x-patch
Size: 13827 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130810/d527dc67/attachment-0001.bin>
Robert Jarzmik
maintainercover ARM: pxa: move core and drivers to dmaengine
Quoted 1 line · Daniel Mack
Hi Robert,
We might reduce the thread broadcast, I don't think these many people care about pxa camera specifics, and its DMA constraints.
Quoted 7 lines
Quoted 2 lines
All that is described in there :
Documentation/video4linux/pxa_camera.txtYes, I've seen that, and while the documentation about all that is excellent, I lack an explanation why things are so complicated for this application, and why a simple cyclic DMA approach does not suffice here. I'm sure there's a reason though.
Well, I think there is a good one.
The current video4linux flow, for video capture, is :
1) userland prepares buffers (ie. dma transfers are prepared, one sg list for each "image" or "frame")
2) userland queues buffers (no hardware operation)
3) userland starts the capture
4) userland poll for each frame end
a) When a frame is finished, userland unqueues it
=> no overwrite of this frame is possible anymore
b) Userland treats is (might be sent to storage, or compressed, ...)
c) Userland requeues it (while other frame is being DMAed)
Moreover, it should be assumed that waiting for a "end of DMA transfer" before requeuing the next one (ie. "cold queuing" instead of "hot queueing") will imply the miss of the next frame start, and one frame will be missed.
With a cyclic DMA, if I understand dmaengine correctly, step 4a. is not posssible (ie. if userland is slow enough, the frame will be overwritten without userland knowing it, and while userland is handling it).
Quoted 2 lines
There might be need to teach the dmaengine core more functionality, but in order to do that, we first need to understand the exact requirements.
The first one that comes to my mind is :
- enable to submit a transfer to a running channel, the same one that served a previous transfer :
=> this will guarantee ordering of DMA transfers
=> this will guarantee no DMA stops if 2 or more buffers are queued => this will try to chain this transfer to the last one queued on the channel => if by bad luck the "miss window is hit", ie. the DMA finishes while the chaining was being done, restart the DMA on its stop
Quoted 4 lines
Quoted 2 lines
Another point I'd like to know, is what is the performance penalty in using dmaengine, and do you have any figures ?
The DMA transfers themselves certainly perform equally well, and the framework is just a thin layer. Where would you expect performance penalty?
Well, last time I had a look (in [1]), I think I remember having a 3% penalty on SD card transfers (pxamci driver, mioa701 board, transcend 16Go SD card).
It's been a while and my memory is a bit fuzzy about it. The loss I had at the time was in queuing/unqueuing the DMA requests IIRC.
Quoted 7 lines
Quoted 3 lines
Lastly, they was debug information to debug descriptors chaining, channel statuses, requestors. I didn't see where these had gone, could you point me to the right file ?
Such a debug interface is not part of the mmp-pdma implementation at this point, and the core doesn't have a generic debugfs feature either. If you need that, we'd have to add it back.
Well, I use that. It's not vital for DMA to work of course, but it's very nice to have when you mess with DMA transfers :)
Quoted 3 lines
FWIW, I attached my work-in-progress patch for this driver which just does some basic dmaengine preparations. Be aware that this does not even compile, it's really just a snapshot.
OK, cool. Once the dmaengine stuff is clearer in my mind, and if "hot submitting" is already possible in dmaengine, it shouldn't be that hard to convert.
Cheers.
Signature · 4 lines
Robert [1] http://archive.arm.linux.org.uk/lurker/message/20090517.194809.b18c79c8.en.html
cover ARM: pxa: move core and drivers to dmaengine
In reply to Daniel MackQuoted 33 lines · Daniel Mack
Hi Robert,
Quoted 11 lines · Robert Jarzmik
Quoted 5 lines · Daniel Mack
* camera driver:
I started the transition, but I'm not sure how much sense that makes without access to the hardware. I'd much appreciate if anyone could volunteer for this piece; I'll happily share what I got so far. Sascha, Sachin, Guennadi?Hi Daniel,
Do you mean this driver ? :
drivers/media/platform/soc_camera/pxa_camera.cYes, exactly.
Quoted 7 lines
In that case I might help. But before I can do that, I have to be convinced that dmaengine can deal with this driver. I'm thinking in particular of :
- "hot running DMA" queuing
- multiple DMA channel synchronization (ie. 3 channel sync)All that is described in there :
Documentation/video4linux/pxa_camera.txtYes, I've seen that, and while the documentation about all that is excellent, I lack an explanation why things are so complicated for this application, and why a simple cyclic DMA approach does not suffice here. I'm sure there's a reason though.
There might be need to teach the dmaengine core more functionality, but in order to do that, we first need to understand the exact requirements.
Quoted 6 lines
Quoted 3 lines
If someone with dmaengine knowledge could have a look at pxa_camera.txt (maybe Vinod ?) and tell me that
dma_engineframework fullfills the 2 requirements, then I'll be happy to help.Yes, Vinod and and Dan are certainly the best ones to comment on that I think.
I read the file esp the "DMA flow" and "DMA hot chaining timeslice issue". I can say with "properly" implemented dmaengine driver this is very much doable.
Have you guys read: Documentation/dmaengine.txt?
So for "hot chaning" it would work as follows:
Client, allocates and channel and prepares the descriptors A B & C Client (video), submits buffer A, Buffer B. Both are queued by dma driver Client calls dma_async_issue_pending
DMA driver will start Buffer A. It gets the completetion for A and then Starts B. It will invoke callbakc for A.
If you submit C, and invoke dma_async_issue_pending(), C is queued On B completetion, the DMA driver will start C and invoke callback for B.
If B completes before C is submitted, after submit and invoking dma_async_issue_pending(), the C buffer will be queued and started.
~Vinod
Robert Jarzmik
maintainercover ARM: pxa: move core and drivers to dmaengine
Quoted 4 lines · Vinod Koul
Quoted 2 lines
Yes, Vinod and and Dan are certainly the best ones to comment on that I think.
I read the file esp the "DMA flow" and "DMA hot chaining timeslice issue". I can say with "properly" implemented dmaengine driver this is very much doable.
Great.
Quoted 3 lines
Have you guys read:
Documentation/dmaengine.txt?
Yes. I had not understood the "hot chaining" was implied in it, but now I understand it is part of it, and at the discretion of the slave engine driver.
Quoted 8 lines
So for "hot chaning" it would work as follows:
Client, allocates and channel and prepares the descriptors A B & C Client (video), submits buffer A, Buffer B. Both are queued by dma driver Client calls
dma_async_issue_pending
DMA driver will start Buffer A. It gets the completetion for A and then Starts B. It will invoke callbakc for A.
Quoted 5 lines
If you submit C, and invoke
dma_async_issue_pending(), C is queued On B completetion, the DMA driver will start C and invoke callback for B.If B completes before C is submitted, after submit and invoking
dma_async_issue_pending(), the C buffer will be queued and started.
OK, that settles it then. The API allows hot chaining, and if I understand Daniel's driver properly, he already thought about it (in append_pending_queue()).
I have some homework now Daniel, I'll send you my work to include into your patch serie for the review, and my tests of your patches.
I need a bit of time (1 or 2 weeks), because of holidays, for my patch.
Cheers.
Signature · 1 line
Robert
cover ARM: pxa: move core and drivers to dmaengine
Quoted 10 lines · Robert Jarzmik
Quoted 5 lines · Vinod Koul
If you submit C, and invoke
dma_async_issue_pending(), C is queued On B completetion, the DMA driver will start C and invoke callback for B.If B completes before C is submitted, after submit and invoking
dma_async_issue_pending(), the C buffer will be queued and started.OK, that settles it then. The API allows hot chaining, and if I understand Daniel's driver properly, he already thought about it (in
append_pending_queue()).
Just for the records: it's not my driver :) I just added some functions recently to make it work in DT and audio environments.
Quoted 4 lines
I have some homework now Daniel, I'll send you my work to include into your patch serie for the review, and my tests of your patches.
I need a bit of time (1 or 2 weeks), because of holidays, for my patch.
Great, thanks a lot. I extracted some of the patches of my set to individual trees so they can be merged for 3.12. I'll rebase my series once 3.12-rc1 is released.
Many thanks for your help,
Daniel