All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-07 15:33 ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

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

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-07 15:33 ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

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

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, Zhangfei Gao, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

From: Zhangfei Gao <zhangfei.gao@marvell.com>

[zonque@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]

Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 115 ++++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 52 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index a2a54f6..736673a 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -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,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

From: Zhangfei Gao <zhangfei.gao@marvell.com>

[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]

Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 115 ++++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 52 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index a2a54f6..736673a 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -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,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 02/20] mtd: pxa3xx-nand: use mmp_pdma_filter_fn and dma_request_slave_channel_compat
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 736673a..99f56c3 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -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,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 02/20] mtd: pxa3xx-nand: use mmp_pdma_filter_fn and dma_request_slave_channel_compat
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 736673a..99f56c3 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -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,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

No functional change, just a cosmetic cleanup.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 arch/arm/plat-pxa/ssp.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index 8e11e96..a503ea0 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -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;
 	}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

No functional change, just a cosmetic cleanup.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 arch/arm/plat-pxa/ssp.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index 8e11e96..a503ea0 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -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;
 	}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 04/20] ARM: pxa: ssp: add DT bindings
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

This patch adds DT bindings for the pxa ssp driver.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 .../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

diff --git a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
new file mode 100644
index 0000000..9f642f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
@@ -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@41000000 {
+		compatible = "mrvl,pxa27x-ssp";
+		reg = <0x41000000 0x40>;
+		interrupts = <24>;
+	};
+
+	ssp@41700000 {
+		compatible = "mrvl,pxa27x-ssp";
+		reg = <0x41700000 0x40>;
+		interrupts = <16>;
+	};
+
+	ssp@41900000 {
+		compatible = "mrvl,pxa27x-ssp";
+		reg = <0x41900000 0x40>;
+		interrupts = <0>;
+	};
+
+	ssp@41a00000 {
+		compatible = "mrvl,pxa27x-ssp";
+		reg = <0x41a00000 0x40>;
+		interrupts = <13>;
+	};
+
diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index a503ea0..7628e85 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -30,12 +30,15 @@
 #include <linux/platform_device.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
 
 static DEFINE_MUTEX(ssp_lock);
 static LIST_HEAD(ssp_list);
+static unsigned int ssp_count;
 
 struct ssp_device *pxa_ssp_request(int port, const char *label)
 {
@@ -72,9 +75,23 @@ void pxa_ssp_free(struct ssp_device *ssp)
 }
 EXPORT_SYMBOL(pxa_ssp_free);
 
+#ifdef CONFIG_OF
+static const struct of_device_id pxa_ssp_of_ids[] = {
+	{ .compatible = "mrvl,pxa25x-ssp",	.data = (void *) PXA25x_SSP },
+	{ .compatible = "mvrl,pxa25x-nssp",	.data = (void *) PXA25x_NSSP },
+	{ .compatible = "mrvl,pxa27x-ssp",	.data = (void *) PXA27x_SSP },
+	{ .compatible = "mrvl,pxa3xx-ssp",	.data = (void *) PXA3xx_SSP },
+	{ .compatible = "mvrl,pxa168-ssp",	.data = (void *) PXA168_SSP },
+	{ .compatible = "mrvl,pxa910-ssp",	.data = (void *) PXA910_SSP },
+	{ .compatible = "mrvl,ce4100-ssp",	.data = (void *) CE4100_SSP },
+	{ .compatible = "mrvl,lpss-ssp",	.data = (void *) LPSS_SSP },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
+#endif
+
 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;
@@ -93,21 +110,42 @@ static int pxa_ssp_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (res == NULL) {
-		dev_err(dev, "no SSP RX DRCMR defined\n");
-		ret = -ENODEV;
-		goto err_free_clk;
-	}
-	ssp->drcmr_rx = res->start;
+	if (dev->of_node) {
+		struct of_phandle_args dma_spec;
+		struct device_node *np = dev->of_node;
+
+		/*
+		 * FIXME: we should allocate the DMA channel from this
+		 * context and pass the channel down to the ssp users.
+		 * For now, we lookup the rx and tx indices manually
+		 */
+
+		/* rx */
+		of_parse_phandle_with_args(np, "dmas", "#dma-cells",
+					   0, &dma_spec);
+		ssp->drcmr_rx = dma_spec.args[0];
+		of_node_put(dma_spec.np);
+
+		/* tx */
+		of_parse_phandle_with_args(np, "dmas", "#dma-cells",
+					   1, &dma_spec);
+		ssp->drcmr_tx = dma_spec.args[0];
+		of_node_put(dma_spec.np);
+	} else {
+		res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (res == NULL) {
+			dev_err(dev, "no SSP RX DRCMR defined\n");
+			return -ENODEV;
+		}
+		ssp->drcmr_rx = res->start;
 
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (res == NULL) {
-		dev_err(dev, "no SSP TX DRCMR defined\n");
-		ret = -ENODEV;
-		goto err_free_clk;
+		res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (res == NULL) {
+			dev_err(dev, "no SSP TX DRCMR defined\n");
+			return -ENODEV;
+		}
+		ssp->drcmr_tx = res->start;
 	}
-	ssp->drcmr_tx = res->start;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
@@ -140,12 +178,24 @@ static int pxa_ssp_probe(struct platform_device *pdev)
 		goto err_free_io;
 	}
 
-	/* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
-	 * starts from 0, do a translation here
-	 */
-	ssp->port_id = pdev->id + 1;
+	if (dev->of_node) {
+		const struct of_device_id *id =
+			of_match_device(of_match_ptr(pxa_ssp_of_ids), dev);
+		ssp->type = (int) id->data;
+		/* REVISIT: we want to pass real of_nodes eventually */
+		ssp->port_id = ++ssp_count;
+	} else {
+		const struct platform_device_id *id =
+			platform_get_device_id(pdev);
+		ssp->type = (int) id->driver_data;
+
+		/* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
+		 * starts from 0, do a translation here
+		 */
+		ssp->port_id = pdev->id + 1;
+	}
+
 	ssp->use_count = 0;
-	ssp->type = (int)id->driver_data;
 
 	mutex_lock(&ssp_lock);
 	list_add(&ssp->node, &ssp_list);
@@ -202,8 +252,9 @@ static struct platform_driver pxa_ssp_driver = {
 	.probe		= pxa_ssp_probe,
 	.remove		= pxa_ssp_remove,
 	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "pxa2xx-ssp",
+		.owner		= THIS_MODULE,
+		.name		= "pxa2xx-ssp",
+		.of_match_table	= of_match_ptr(pxa_ssp_of_ids),
 	},
 	.id_table	= ssp_id_table,
 };
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 04/20] ARM: pxa: ssp: add DT bindings
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds DT bindings for the pxa ssp driver.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 .../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

diff --git a/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
new file mode 100644
index 0000000..9f642f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/mrvl,pxa-ssp.txt
@@ -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>;
+	};
+
diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index a503ea0..7628e85 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -30,12 +30,15 @@
 #include <linux/platform_device.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
 
 static DEFINE_MUTEX(ssp_lock);
 static LIST_HEAD(ssp_list);
+static unsigned int ssp_count;
 
 struct ssp_device *pxa_ssp_request(int port, const char *label)
 {
@@ -72,9 +75,23 @@ void pxa_ssp_free(struct ssp_device *ssp)
 }
 EXPORT_SYMBOL(pxa_ssp_free);
 
+#ifdef CONFIG_OF
+static const struct of_device_id pxa_ssp_of_ids[] = {
+	{ .compatible = "mrvl,pxa25x-ssp",	.data = (void *) PXA25x_SSP },
+	{ .compatible = "mvrl,pxa25x-nssp",	.data = (void *) PXA25x_NSSP },
+	{ .compatible = "mrvl,pxa27x-ssp",	.data = (void *) PXA27x_SSP },
+	{ .compatible = "mrvl,pxa3xx-ssp",	.data = (void *) PXA3xx_SSP },
+	{ .compatible = "mvrl,pxa168-ssp",	.data = (void *) PXA168_SSP },
+	{ .compatible = "mrvl,pxa910-ssp",	.data = (void *) PXA910_SSP },
+	{ .compatible = "mrvl,ce4100-ssp",	.data = (void *) CE4100_SSP },
+	{ .compatible = "mrvl,lpss-ssp",	.data = (void *) LPSS_SSP },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
+#endif
+
 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;
@@ -93,21 +110,42 @@ static int pxa_ssp_probe(struct platform_device *pdev)
 		goto err_free;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (res == NULL) {
-		dev_err(dev, "no SSP RX DRCMR defined\n");
-		ret = -ENODEV;
-		goto err_free_clk;
-	}
-	ssp->drcmr_rx = res->start;
+	if (dev->of_node) {
+		struct of_phandle_args dma_spec;
+		struct device_node *np = dev->of_node;
+
+		/*
+		 * FIXME: we should allocate the DMA channel from this
+		 * context and pass the channel down to the ssp users.
+		 * For now, we lookup the rx and tx indices manually
+		 */
+
+		/* rx */
+		of_parse_phandle_with_args(np, "dmas", "#dma-cells",
+					   0, &dma_spec);
+		ssp->drcmr_rx = dma_spec.args[0];
+		of_node_put(dma_spec.np);
+
+		/* tx */
+		of_parse_phandle_with_args(np, "dmas", "#dma-cells",
+					   1, &dma_spec);
+		ssp->drcmr_tx = dma_spec.args[0];
+		of_node_put(dma_spec.np);
+	} else {
+		res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+		if (res == NULL) {
+			dev_err(dev, "no SSP RX DRCMR defined\n");
+			return -ENODEV;
+		}
+		ssp->drcmr_rx = res->start;
 
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (res == NULL) {
-		dev_err(dev, "no SSP TX DRCMR defined\n");
-		ret = -ENODEV;
-		goto err_free_clk;
+		res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+		if (res == NULL) {
+			dev_err(dev, "no SSP TX DRCMR defined\n");
+			return -ENODEV;
+		}
+		ssp->drcmr_tx = res->start;
 	}
-	ssp->drcmr_tx = res->start;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
@@ -140,12 +178,24 @@ static int pxa_ssp_probe(struct platform_device *pdev)
 		goto err_free_io;
 	}
 
-	/* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
-	 * starts from 0, do a translation here
-	 */
-	ssp->port_id = pdev->id + 1;
+	if (dev->of_node) {
+		const struct of_device_id *id =
+			of_match_device(of_match_ptr(pxa_ssp_of_ids), dev);
+		ssp->type = (int) id->data;
+		/* REVISIT: we want to pass real of_nodes eventually */
+		ssp->port_id = ++ssp_count;
+	} else {
+		const struct platform_device_id *id =
+			platform_get_device_id(pdev);
+		ssp->type = (int) id->driver_data;
+
+		/* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id
+		 * starts from 0, do a translation here
+		 */
+		ssp->port_id = pdev->id + 1;
+	}
+
 	ssp->use_count = 0;
-	ssp->type = (int)id->driver_data;
 
 	mutex_lock(&ssp_lock);
 	list_add(&ssp->node, &ssp_list);
@@ -202,8 +252,9 @@ static struct platform_driver pxa_ssp_driver = {
 	.probe		= pxa_ssp_probe,
 	.remove		= pxa_ssp_remove,
 	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "pxa2xx-ssp",
+		.owner		= THIS_MODULE,
+		.name		= "pxa2xx-ssp",
+		.of_match_table	= of_match_ptr(pxa_ssp_of_ids),
 	},
 	.id_table	= ssp_id_table,
 };
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 05/20] ARM: pxa: ssp: use devm_ functions
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Use devm_ functions to allocate memory, ioremap, clk_get etc to clean up
the error unwind path.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 arch/arm/plat-pxa/ssp.c | 40 ++++++++++++----------------------------
 1 file changed, 12 insertions(+), 28 deletions(-)

diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index 7628e85..29fe314 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -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)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 05/20] ARM: pxa: ssp: use devm_ functions
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Use devm_ functions to allocate memory, ioremap, clk_get etc to clean up
the error unwind path.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 arch/arm/plat-pxa/ssp.c | 40 ++++++++++++----------------------------
 1 file changed, 12 insertions(+), 28 deletions(-)

diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c
index 7628e85..29fe314 100644
--- a/arch/arm/plat-pxa/ssp.c
+++ b/arch/arm/plat-pxa/ssp.c
@@ -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)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 06/20] tty: serial: pxa: remove old cruft
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

This #if-0'd block wouldn't compile, so let's dispose it.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/tty/serial/pxa.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 05f504e..cc6d539 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -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;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 06/20] tty: serial: pxa: remove old cruft
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

This #if-0'd block wouldn't compile, so let's dispose it.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/tty/serial/pxa.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 05f504e..cc6d539 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -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;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

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.

With generic DMA available for PXA, we can now just trash this
file.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 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

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 89cbbab..219c346 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -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"
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 33f9c09..149bef4 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -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
diff --git a/drivers/spi/spi-pxa2xx-pxadma.c b/drivers/spi/spi-pxa2xx-pxadma.c
deleted file mode 100644
index 2916efc..0000000
--- a/drivers/spi/spi-pxa2xx-pxadma.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * PXA2xx SPI private DMA support.
- *
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/pxa2xx_ssp.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/pxa2xx_spi.h>
-
-#include "spi-pxa2xx.h"
-
-#define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
-#define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK)
-
-bool pxa2xx_spi_dma_is_possible(size_t len)
-{
-	/* Try to map dma buffer and do a dma transfer if successful, but
-	 * only if the length is non-zero and less than MAX_DMA_LEN.
-	 *
-	 * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
-	 * of PIO instead.  Care is needed above because the transfer may
-	 * have have been passed with buffers that are already dma mapped.
-	 * A zero-length transfer in PIO mode will not try to write/read
-	 * to/from the buffers
-	 *
-	 * REVISIT large transfers are exactly where we most want to be
-	 * using DMA.  If this happens much, split those transfers into
-	 * multiple DMA segments rather than forcing PIO.
-	 */
-	return len > 0 && len <= MAX_DMA_LEN;
-}
-
-int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
-{
-	struct spi_message *msg = drv_data->cur_msg;
-	struct device *dev = &msg->spi->dev;
-
-	if (!drv_data->cur_chip->enable_dma)
-		return 0;
-
-	if (msg->is_dma_mapped)
-		return  drv_data->rx_dma && drv_data->tx_dma;
-
-	if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
-		return 0;
-
-	/* Modify setup if rx buffer is null */
-	if (drv_data->rx == NULL) {
-		*drv_data->null_dma_buf = 0;
-		drv_data->rx = drv_data->null_dma_buf;
-		drv_data->rx_map_len = 4;
-	} else
-		drv_data->rx_map_len = drv_data->len;
-
-
-	/* Modify setup if tx buffer is null */
-	if (drv_data->tx == NULL) {
-		*drv_data->null_dma_buf = 0;
-		drv_data->tx = drv_data->null_dma_buf;
-		drv_data->tx_map_len = 4;
-	} else
-		drv_data->tx_map_len = drv_data->len;
-
-	/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
-	 * so we flush the cache *before* invalidating it, in case
-	 * the tx and rx buffers overlap.
-	 */
-	drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, drv_data->tx_dma))
-		return 0;
-
-	/* Stream map the rx buffer */
-	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
-					drv_data->rx_map_len, DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, drv_data->rx_dma)) {
-		dma_unmap_single(dev, drv_data->tx_dma,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-		return 0;
-	}
-
-	return 1;
-}
-
-static void pxa2xx_spi_unmap_dma_buffers(struct driver_data *drv_data)
-{
-	struct device *dev;
-
-	if (!drv_data->dma_mapped)
-		return;
-
-	if (!drv_data->cur_msg->is_dma_mapped) {
-		dev = &drv_data->cur_msg->spi->dev;
-		dma_unmap_single(dev, drv_data->rx_dma,
-					drv_data->rx_map_len, DMA_FROM_DEVICE);
-		dma_unmap_single(dev, drv_data->tx_dma,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-	}
-
-	drv_data->dma_mapped = 0;
-}
-
-static int wait_ssp_rx_stall(void const __iomem *ioaddr)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
-		cpu_relax();
-
-	return limit;
-}
-
-static int wait_dma_channel_stop(int channel)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
-		cpu_relax();
-
-	return limit;
-}
-
-static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data,
-				      const char *msg)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	/* Stop and reset */
-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	write_SSSR_CS(drv_data, drv_data->clear_sr);
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	if (!pxa25x_ssp_comp(drv_data))
-		write_SSTO(0, reg);
-	pxa2xx_spi_flush(drv_data);
-	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-
-	pxa2xx_spi_unmap_dma_buffers(drv_data);
-
-	dev_err(&drv_data->pdev->dev, "%s\n", msg);
-
-	drv_data->cur_msg->state = ERROR_STATE;
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-	struct spi_message *msg = drv_data->cur_msg;
-
-	/* Clear and disable interrupts on SSP and DMA channels*/
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	write_SSSR_CS(drv_data, drv_data->clear_sr);
-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-
-	if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
-		dev_err(&drv_data->pdev->dev,
-			"dma_handler: dma rx channel stop failed\n");
-
-	if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
-		dev_err(&drv_data->pdev->dev,
-			"dma_transfer: ssp rx stall failed\n");
-
-	pxa2xx_spi_unmap_dma_buffers(drv_data);
-
-	/* update the buffer pointer for the amount completed in dma */
-	drv_data->rx += drv_data->len -
-			(DCMD(drv_data->rx_channel) & DCMD_LENGTH);
-
-	/* read trailing data from fifo, it does not matter how many
-	 * bytes are in the fifo just read until buffer is full
-	 * or fifo is empty, which ever occurs first */
-	drv_data->read(drv_data);
-
-	/* return count of what was actually read */
-	msg->actual_length += drv_data->len -
-				(drv_data->rx_end - drv_data->rx);
-
-	/* Transfer delays and chip select release are
-	 * handled in pump_transfers or giveback
-	 */
-
-	/* Move to next transfer */
-	msg->state = pxa2xx_spi_next_transfer(drv_data);
-
-	/* Schedule transfer tasklet */
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-void pxa2xx_spi_dma_handler(int channel, void *data)
-{
-	struct driver_data *drv_data = data;
-	u32 irq_status = DCSR(channel) & DMA_INT_MASK;
-
-	if (irq_status & DCSR_BUSERR) {
-
-		if (channel == drv_data->tx_channel)
-			pxa2xx_spi_dma_error_stop(drv_data,
-				"dma_handler: bad bus address on tx channel");
-		else
-			pxa2xx_spi_dma_error_stop(drv_data,
-				"dma_handler: bad bus address on rx channel");
-		return;
-	}
-
-	/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
-	if ((channel == drv_data->tx_channel)
-		&& (irq_status & DCSR_ENDINTR)
-		&& (drv_data->ssp_type == PXA25x_SSP)) {
-
-		/* Wait for rx to stall */
-		if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
-			dev_err(&drv_data->pdev->dev,
-				"dma_handler: ssp rx stall failed\n");
-
-		/* finish this transfer, start the next */
-		pxa2xx_spi_dma_transfer_complete(drv_data);
-	}
-}
-
-irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
-{
-	u32 irq_status;
-	void __iomem *reg = drv_data->ioaddr;
-
-	irq_status = read_SSSR(reg) & drv_data->mask_sr;
-	if (irq_status & SSSR_ROR) {
-		pxa2xx_spi_dma_error_stop(drv_data,
-					  "dma_transfer: fifo overrun");
-		return IRQ_HANDLED;
-	}
-
-	/* Check for false positive timeout */
-	if ((irq_status & SSSR_TINT)
-		&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
-		write_SSSR(SSSR_TINT, reg);
-		return IRQ_HANDLED;
-	}
-
-	if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
-
-		/* Clear and disable timeout interrupt, do the rest in
-		 * dma_transfer_complete */
-		if (!pxa25x_ssp_comp(drv_data))
-			write_SSTO(0, reg);
-
-		/* finish this transfer, start the next */
-		pxa2xx_spi_dma_transfer_complete(drv_data);
-
-		return IRQ_HANDLED;
-	}
-
-	/* Opps problem detected */
-	return IRQ_NONE;
-}
-
-int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst)
-{
-	u32 dma_width;
-
-	switch (drv_data->n_bytes) {
-	case 1:
-		dma_width = DCMD_WIDTH1;
-		break;
-	case 2:
-		dma_width = DCMD_WIDTH2;
-		break;
-	default:
-		dma_width = DCMD_WIDTH4;
-		break;
-	}
-
-	/* Setup rx DMA Channel */
-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-	DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
-	DTADR(drv_data->rx_channel) = drv_data->rx_dma;
-	if (drv_data->rx == drv_data->null_dma_buf)
-		/* No target address increment */
-		DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
-						| dma_width
-						| dma_burst
-						| drv_data->len;
-	else
-		DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
-						| DCMD_FLOWSRC
-						| dma_width
-						| dma_burst
-						| drv_data->len;
-
-	/* Setup tx DMA Channel */
-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	DSADR(drv_data->tx_channel) = drv_data->tx_dma;
-	DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
-	if (drv_data->tx == drv_data->null_dma_buf)
-		/* No source address increment */
-		DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
-						| dma_width
-						| dma_burst
-						| drv_data->len;
-	else
-		DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
-						| DCMD_FLOWTRG
-						| dma_width
-						| dma_burst
-						| drv_data->len;
-
-	/* Enable dma end irqs on SSP to detect end of transfer */
-	if (drv_data->ssp_type == PXA25x_SSP)
-		DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
-
-	return 0;
-}
-
-void pxa2xx_spi_dma_start(struct driver_data *drv_data)
-{
-	DCSR(drv_data->rx_channel) |= DCSR_RUN;
-	DCSR(drv_data->tx_channel) |= DCSR_RUN;
-}
-
-int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
-{
-	struct device *dev = &drv_data->pdev->dev;
-	struct ssp_device *ssp = drv_data->ssp;
-
-	/* Get two DMA channels	(rx and tx) */
-	drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
-						DMA_PRIO_HIGH,
-						pxa2xx_spi_dma_handler,
-						drv_data);
-	if (drv_data->rx_channel < 0) {
-		dev_err(dev, "problem (%d) requesting rx channel\n",
-			drv_data->rx_channel);
-		return -ENODEV;
-	}
-	drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
-						DMA_PRIO_MEDIUM,
-						pxa2xx_spi_dma_handler,
-						drv_data);
-	if (drv_data->tx_channel < 0) {
-		dev_err(dev, "problem (%d) requesting tx channel\n",
-			drv_data->tx_channel);
-		pxa_free_dma(drv_data->rx_channel);
-		return -ENODEV;
-	}
-
-	DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
-	DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
-
-	return 0;
-}
-
-void pxa2xx_spi_dma_release(struct driver_data *drv_data)
-{
-	struct ssp_device *ssp = drv_data->ssp;
-
-	DRCMR(ssp->drcmr_rx) = 0;
-	DRCMR(ssp->drcmr_tx) = 0;
-
-	if (drv_data->tx_channel != 0)
-		pxa_free_dma(drv_data->tx_channel);
-	if (drv_data->rx_channel != 0)
-		pxa_free_dma(drv_data->rx_channel);
-}
-
-void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
-{
-	if (drv_data->rx_channel != -1)
-		DRCMR(drv_data->ssp->drcmr_rx) =
-			DRCMR_MAPVLD | drv_data->rx_channel;
-	if (drv_data->tx_channel != -1)
-		DRCMR(drv_data->ssp->drcmr_tx) =
-			DRCMR_MAPVLD | drv_data->tx_channel;
-}
-
-int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
-					   struct spi_device *spi,
-					   u8 bits_per_word, u32 *burst_code,
-					   u32 *threshold)
-{
-	struct pxa2xx_spi_chip *chip_info =
-			(struct pxa2xx_spi_chip *)spi->controller_data;
-	int bytes_per_word;
-	int burst_bytes;
-	int thresh_words;
-	int req_burst_size;
-	int retval = 0;
-
-	/* Set the threshold (in registers) to equal the same amount of data
-	 * as represented by burst size (in bytes).  The computation below
-	 * is (burst_size rounded up to nearest 8 byte, word or long word)
-	 * divided by (bytes/register); the tx threshold is the inverse of
-	 * the rx, so that there will always be enough data in the rx fifo
-	 * to satisfy a burst, and there will always be enough space in the
-	 * tx fifo to accept a burst (a tx burst will overwrite the fifo if
-	 * there is not enough space), there must always remain enough empty
-	 * space in the rx fifo for any data loaded to the tx fifo.
-	 * Whenever burst_size (in bytes) equals bits/word, the fifo threshold
-	 * will be 8, or half the fifo;
-	 * The threshold can only be set to 2, 4 or 8, but not 16, because
-	 * to burst 16 to the tx fifo, the fifo would have to be empty;
-	 * however, the minimum fifo trigger level is 1, and the tx will
-	 * request service when the fifo is at this level, with only 15 spaces.
-	 */
-
-	/* find bytes/word */
-	if (bits_per_word <= 8)
-		bytes_per_word = 1;
-	else if (bits_per_word <= 16)
-		bytes_per_word = 2;
-	else
-		bytes_per_word = 4;
-
-	/* use struct pxa2xx_spi_chip->dma_burst_size if available */
-	if (chip_info)
-		req_burst_size = chip_info->dma_burst_size;
-	else {
-		switch (chip->dma_burst_size) {
-		default:
-			/* if the default burst size is not set,
-			 * do it now */
-			chip->dma_burst_size = DCMD_BURST8;
-		case DCMD_BURST8:
-			req_burst_size = 8;
-			break;
-		case DCMD_BURST16:
-			req_burst_size = 16;
-			break;
-		case DCMD_BURST32:
-			req_burst_size = 32;
-			break;
-		}
-	}
-	if (req_burst_size <= 8) {
-		*burst_code = DCMD_BURST8;
-		burst_bytes = 8;
-	} else if (req_burst_size <= 16) {
-		if (bytes_per_word == 1) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST8;
-			burst_bytes = 8;
-			retval = 1;
-		} else {
-			*burst_code = DCMD_BURST16;
-			burst_bytes = 16;
-		}
-	} else {
-		if (bytes_per_word == 1) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST8;
-			burst_bytes = 8;
-			retval = 1;
-		} else if (bytes_per_word == 2) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST16;
-			burst_bytes = 16;
-			retval = 1;
-		} else {
-			*burst_code = DCMD_BURST32;
-			burst_bytes = 32;
-		}
-	}
-
-	thresh_words = burst_bytes / bytes_per_word;
-
-	/* thresh_words will be between 2 and 8 */
-	*threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
-			| (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
-
-	return retval;
-}
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 5adc2a1..c37efec 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -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)
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
index 82d5111..48a0fee 100644
--- a/include/linux/spi/pxa2xx_spi.h
+++ b/include/linux/spi/pxa2xx_spi.h
@@ -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);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

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.

With generic DMA available for PXA, we can now just trash this
file.

Signed-off-by: Daniel Mack <zonque@gmail.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 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

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 89cbbab..219c346 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -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"
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 33f9c09..149bef4 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -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
diff --git a/drivers/spi/spi-pxa2xx-pxadma.c b/drivers/spi/spi-pxa2xx-pxadma.c
deleted file mode 100644
index 2916efc..0000000
--- a/drivers/spi/spi-pxa2xx-pxadma.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * PXA2xx SPI private DMA support.
- *
- * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/pxa2xx_ssp.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/pxa2xx_spi.h>
-
-#include "spi-pxa2xx.h"
-
-#define DMA_INT_MASK		(DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
-#define RESET_DMA_CHANNEL	(DCSR_NODESC | DMA_INT_MASK)
-
-bool pxa2xx_spi_dma_is_possible(size_t len)
-{
-	/* Try to map dma buffer and do a dma transfer if successful, but
-	 * only if the length is non-zero and less than MAX_DMA_LEN.
-	 *
-	 * Zero-length non-descriptor DMA is illegal on PXA2xx; force use
-	 * of PIO instead.  Care is needed above because the transfer may
-	 * have have been passed with buffers that are already dma mapped.
-	 * A zero-length transfer in PIO mode will not try to write/read
-	 * to/from the buffers
-	 *
-	 * REVISIT large transfers are exactly where we most want to be
-	 * using DMA.  If this happens much, split those transfers into
-	 * multiple DMA segments rather than forcing PIO.
-	 */
-	return len > 0 && len <= MAX_DMA_LEN;
-}
-
-int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
-{
-	struct spi_message *msg = drv_data->cur_msg;
-	struct device *dev = &msg->spi->dev;
-
-	if (!drv_data->cur_chip->enable_dma)
-		return 0;
-
-	if (msg->is_dma_mapped)
-		return  drv_data->rx_dma && drv_data->tx_dma;
-
-	if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
-		return 0;
-
-	/* Modify setup if rx buffer is null */
-	if (drv_data->rx == NULL) {
-		*drv_data->null_dma_buf = 0;
-		drv_data->rx = drv_data->null_dma_buf;
-		drv_data->rx_map_len = 4;
-	} else
-		drv_data->rx_map_len = drv_data->len;
-
-
-	/* Modify setup if tx buffer is null */
-	if (drv_data->tx == NULL) {
-		*drv_data->null_dma_buf = 0;
-		drv_data->tx = drv_data->null_dma_buf;
-		drv_data->tx_map_len = 4;
-	} else
-		drv_data->tx_map_len = drv_data->len;
-
-	/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
-	 * so we flush the cache *before* invalidating it, in case
-	 * the tx and rx buffers overlap.
-	 */
-	drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, drv_data->tx_dma))
-		return 0;
-
-	/* Stream map the rx buffer */
-	drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
-					drv_data->rx_map_len, DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, drv_data->rx_dma)) {
-		dma_unmap_single(dev, drv_data->tx_dma,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-		return 0;
-	}
-
-	return 1;
-}
-
-static void pxa2xx_spi_unmap_dma_buffers(struct driver_data *drv_data)
-{
-	struct device *dev;
-
-	if (!drv_data->dma_mapped)
-		return;
-
-	if (!drv_data->cur_msg->is_dma_mapped) {
-		dev = &drv_data->cur_msg->spi->dev;
-		dma_unmap_single(dev, drv_data->rx_dma,
-					drv_data->rx_map_len, DMA_FROM_DEVICE);
-		dma_unmap_single(dev, drv_data->tx_dma,
-					drv_data->tx_map_len, DMA_TO_DEVICE);
-	}
-
-	drv_data->dma_mapped = 0;
-}
-
-static int wait_ssp_rx_stall(void const __iomem *ioaddr)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
-		cpu_relax();
-
-	return limit;
-}
-
-static int wait_dma_channel_stop(int channel)
-{
-	unsigned long limit = loops_per_jiffy << 1;
-
-	while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
-		cpu_relax();
-
-	return limit;
-}
-
-static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data,
-				      const char *msg)
-{
-	void __iomem *reg = drv_data->ioaddr;
-
-	/* Stop and reset */
-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	write_SSSR_CS(drv_data, drv_data->clear_sr);
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	if (!pxa25x_ssp_comp(drv_data))
-		write_SSTO(0, reg);
-	pxa2xx_spi_flush(drv_data);
-	write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
-
-	pxa2xx_spi_unmap_dma_buffers(drv_data);
-
-	dev_err(&drv_data->pdev->dev, "%s\n", msg);
-
-	drv_data->cur_msg->state = ERROR_STATE;
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data)
-{
-	void __iomem *reg = drv_data->ioaddr;
-	struct spi_message *msg = drv_data->cur_msg;
-
-	/* Clear and disable interrupts on SSP and DMA channels*/
-	write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
-	write_SSSR_CS(drv_data, drv_data->clear_sr);
-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-
-	if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
-		dev_err(&drv_data->pdev->dev,
-			"dma_handler: dma rx channel stop failed\n");
-
-	if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
-		dev_err(&drv_data->pdev->dev,
-			"dma_transfer: ssp rx stall failed\n");
-
-	pxa2xx_spi_unmap_dma_buffers(drv_data);
-
-	/* update the buffer pointer for the amount completed in dma */
-	drv_data->rx += drv_data->len -
-			(DCMD(drv_data->rx_channel) & DCMD_LENGTH);
-
-	/* read trailing data from fifo, it does not matter how many
-	 * bytes are in the fifo just read until buffer is full
-	 * or fifo is empty, which ever occurs first */
-	drv_data->read(drv_data);
-
-	/* return count of what was actually read */
-	msg->actual_length += drv_data->len -
-				(drv_data->rx_end - drv_data->rx);
-
-	/* Transfer delays and chip select release are
-	 * handled in pump_transfers or giveback
-	 */
-
-	/* Move to next transfer */
-	msg->state = pxa2xx_spi_next_transfer(drv_data);
-
-	/* Schedule transfer tasklet */
-	tasklet_schedule(&drv_data->pump_transfers);
-}
-
-void pxa2xx_spi_dma_handler(int channel, void *data)
-{
-	struct driver_data *drv_data = data;
-	u32 irq_status = DCSR(channel) & DMA_INT_MASK;
-
-	if (irq_status & DCSR_BUSERR) {
-
-		if (channel == drv_data->tx_channel)
-			pxa2xx_spi_dma_error_stop(drv_data,
-				"dma_handler: bad bus address on tx channel");
-		else
-			pxa2xx_spi_dma_error_stop(drv_data,
-				"dma_handler: bad bus address on rx channel");
-		return;
-	}
-
-	/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
-	if ((channel == drv_data->tx_channel)
-		&& (irq_status & DCSR_ENDINTR)
-		&& (drv_data->ssp_type == PXA25x_SSP)) {
-
-		/* Wait for rx to stall */
-		if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
-			dev_err(&drv_data->pdev->dev,
-				"dma_handler: ssp rx stall failed\n");
-
-		/* finish this transfer, start the next */
-		pxa2xx_spi_dma_transfer_complete(drv_data);
-	}
-}
-
-irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
-{
-	u32 irq_status;
-	void __iomem *reg = drv_data->ioaddr;
-
-	irq_status = read_SSSR(reg) & drv_data->mask_sr;
-	if (irq_status & SSSR_ROR) {
-		pxa2xx_spi_dma_error_stop(drv_data,
-					  "dma_transfer: fifo overrun");
-		return IRQ_HANDLED;
-	}
-
-	/* Check for false positive timeout */
-	if ((irq_status & SSSR_TINT)
-		&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
-		write_SSSR(SSSR_TINT, reg);
-		return IRQ_HANDLED;
-	}
-
-	if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
-
-		/* Clear and disable timeout interrupt, do the rest in
-		 * dma_transfer_complete */
-		if (!pxa25x_ssp_comp(drv_data))
-			write_SSTO(0, reg);
-
-		/* finish this transfer, start the next */
-		pxa2xx_spi_dma_transfer_complete(drv_data);
-
-		return IRQ_HANDLED;
-	}
-
-	/* Opps problem detected */
-	return IRQ_NONE;
-}
-
-int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst)
-{
-	u32 dma_width;
-
-	switch (drv_data->n_bytes) {
-	case 1:
-		dma_width = DCMD_WIDTH1;
-		break;
-	case 2:
-		dma_width = DCMD_WIDTH2;
-		break;
-	default:
-		dma_width = DCMD_WIDTH4;
-		break;
-	}
-
-	/* Setup rx DMA Channel */
-	DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
-	DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
-	DTADR(drv_data->rx_channel) = drv_data->rx_dma;
-	if (drv_data->rx == drv_data->null_dma_buf)
-		/* No target address increment */
-		DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
-						| dma_width
-						| dma_burst
-						| drv_data->len;
-	else
-		DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
-						| DCMD_FLOWSRC
-						| dma_width
-						| dma_burst
-						| drv_data->len;
-
-	/* Setup tx DMA Channel */
-	DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
-	DSADR(drv_data->tx_channel) = drv_data->tx_dma;
-	DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
-	if (drv_data->tx == drv_data->null_dma_buf)
-		/* No source address increment */
-		DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
-						| dma_width
-						| dma_burst
-						| drv_data->len;
-	else
-		DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
-						| DCMD_FLOWTRG
-						| dma_width
-						| dma_burst
-						| drv_data->len;
-
-	/* Enable dma end irqs on SSP to detect end of transfer */
-	if (drv_data->ssp_type == PXA25x_SSP)
-		DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
-
-	return 0;
-}
-
-void pxa2xx_spi_dma_start(struct driver_data *drv_data)
-{
-	DCSR(drv_data->rx_channel) |= DCSR_RUN;
-	DCSR(drv_data->tx_channel) |= DCSR_RUN;
-}
-
-int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
-{
-	struct device *dev = &drv_data->pdev->dev;
-	struct ssp_device *ssp = drv_data->ssp;
-
-	/* Get two DMA channels	(rx and tx) */
-	drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
-						DMA_PRIO_HIGH,
-						pxa2xx_spi_dma_handler,
-						drv_data);
-	if (drv_data->rx_channel < 0) {
-		dev_err(dev, "problem (%d) requesting rx channel\n",
-			drv_data->rx_channel);
-		return -ENODEV;
-	}
-	drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
-						DMA_PRIO_MEDIUM,
-						pxa2xx_spi_dma_handler,
-						drv_data);
-	if (drv_data->tx_channel < 0) {
-		dev_err(dev, "problem (%d) requesting tx channel\n",
-			drv_data->tx_channel);
-		pxa_free_dma(drv_data->rx_channel);
-		return -ENODEV;
-	}
-
-	DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
-	DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
-
-	return 0;
-}
-
-void pxa2xx_spi_dma_release(struct driver_data *drv_data)
-{
-	struct ssp_device *ssp = drv_data->ssp;
-
-	DRCMR(ssp->drcmr_rx) = 0;
-	DRCMR(ssp->drcmr_tx) = 0;
-
-	if (drv_data->tx_channel != 0)
-		pxa_free_dma(drv_data->tx_channel);
-	if (drv_data->rx_channel != 0)
-		pxa_free_dma(drv_data->rx_channel);
-}
-
-void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
-{
-	if (drv_data->rx_channel != -1)
-		DRCMR(drv_data->ssp->drcmr_rx) =
-			DRCMR_MAPVLD | drv_data->rx_channel;
-	if (drv_data->tx_channel != -1)
-		DRCMR(drv_data->ssp->drcmr_tx) =
-			DRCMR_MAPVLD | drv_data->tx_channel;
-}
-
-int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
-					   struct spi_device *spi,
-					   u8 bits_per_word, u32 *burst_code,
-					   u32 *threshold)
-{
-	struct pxa2xx_spi_chip *chip_info =
-			(struct pxa2xx_spi_chip *)spi->controller_data;
-	int bytes_per_word;
-	int burst_bytes;
-	int thresh_words;
-	int req_burst_size;
-	int retval = 0;
-
-	/* Set the threshold (in registers) to equal the same amount of data
-	 * as represented by burst size (in bytes).  The computation below
-	 * is (burst_size rounded up to nearest 8 byte, word or long word)
-	 * divided by (bytes/register); the tx threshold is the inverse of
-	 * the rx, so that there will always be enough data in the rx fifo
-	 * to satisfy a burst, and there will always be enough space in the
-	 * tx fifo to accept a burst (a tx burst will overwrite the fifo if
-	 * there is not enough space), there must always remain enough empty
-	 * space in the rx fifo for any data loaded to the tx fifo.
-	 * Whenever burst_size (in bytes) equals bits/word, the fifo threshold
-	 * will be 8, or half the fifo;
-	 * The threshold can only be set to 2, 4 or 8, but not 16, because
-	 * to burst 16 to the tx fifo, the fifo would have to be empty;
-	 * however, the minimum fifo trigger level is 1, and the tx will
-	 * request service when the fifo is at this level, with only 15 spaces.
-	 */
-
-	/* find bytes/word */
-	if (bits_per_word <= 8)
-		bytes_per_word = 1;
-	else if (bits_per_word <= 16)
-		bytes_per_word = 2;
-	else
-		bytes_per_word = 4;
-
-	/* use struct pxa2xx_spi_chip->dma_burst_size if available */
-	if (chip_info)
-		req_burst_size = chip_info->dma_burst_size;
-	else {
-		switch (chip->dma_burst_size) {
-		default:
-			/* if the default burst size is not set,
-			 * do it now */
-			chip->dma_burst_size = DCMD_BURST8;
-		case DCMD_BURST8:
-			req_burst_size = 8;
-			break;
-		case DCMD_BURST16:
-			req_burst_size = 16;
-			break;
-		case DCMD_BURST32:
-			req_burst_size = 32;
-			break;
-		}
-	}
-	if (req_burst_size <= 8) {
-		*burst_code = DCMD_BURST8;
-		burst_bytes = 8;
-	} else if (req_burst_size <= 16) {
-		if (bytes_per_word == 1) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST8;
-			burst_bytes = 8;
-			retval = 1;
-		} else {
-			*burst_code = DCMD_BURST16;
-			burst_bytes = 16;
-		}
-	} else {
-		if (bytes_per_word == 1) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST8;
-			burst_bytes = 8;
-			retval = 1;
-		} else if (bytes_per_word == 2) {
-			/* don't burst more than 1/2 the fifo */
-			*burst_code = DCMD_BURST16;
-			burst_bytes = 16;
-			retval = 1;
-		} else {
-			*burst_code = DCMD_BURST32;
-			burst_bytes = 32;
-		}
-	}
-
-	thresh_words = burst_bytes / bytes_per_word;
-
-	/* thresh_words will be between 2 and 8 */
-	*threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
-			| (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
-
-	return retval;
-}
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 5adc2a1..c37efec 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -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)
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
index 82d5111..48a0fee 100644
--- a/include/linux/spi/pxa2xx_spi.h
+++ b/include/linux/spi/pxa2xx_spi.h
@@ -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);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Successfully testes on a PXA3xx board.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++---------------------
 1 file changed, 102 insertions(+), 86 deletions(-)

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 2c5a91b..7aa97eb 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -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

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Successfully testes on a PXA3xx board.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++---------------------
 1 file changed, 102 insertions(+), 86 deletions(-)

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 2c5a91b..7aa97eb 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -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

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 09/20] ata: pdata_pxa: migrate over to dmaengine usage
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

This patch is compile-tested only, but the migration was actually
straight-forward.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/ata/pata_pxa.c | 172 ++++++++++++++++++++-----------------------------
 1 file changed, 70 insertions(+), 102 deletions(-)

diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index 942ef94..906c0b5 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -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);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 09/20] ata: pdata_pxa: migrate over to dmaengine usage
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

This patch is compile-tested only, but the migration was actually
straight-forward.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/ata/pata_pxa.c | 172 ++++++++++++++++++++-----------------------------
 1 file changed, 70 insertions(+), 102 deletions(-)

diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index 942ef94..906c0b5 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -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);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 10/20] net: irda: pxaficp_ir: switch to dmaengine
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:33   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

This was only compile-tested.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/net/irda/pxaficp_ir.c | 242 ++++++++++++++++++++++++++----------------
 1 file changed, 151 insertions(+), 91 deletions(-)

diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 964b116..d77a342 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -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	2047
 
 inline 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);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 10/20] net: irda: pxaficp_ir: switch to dmaengine
@ 2013-08-07 15:33   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

This was only compile-tested.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/net/irda/pxaficp_ir.c | 242 ++++++++++++++++++++++++++----------------
 1 file changed, 151 insertions(+), 91 deletions(-)

diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 964b116..d77a342 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -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	2047
 
 inline 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);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 11/20] net: smc91x.c: switch to generic buf-to-buf DMA offload
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Drop all PXA-DMA specific implementation details and rely on
dma_async_memcpy_buf_to_buf().

This patch is only compile-tested.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/net/ethernet/smsc/smc91x.c | 40 +++++++--------------
 drivers/net/ethernet/smsc/smc91x.h | 71 ++++++++++++++------------------------
 2 files changed, 38 insertions(+), 73 deletions(-)

diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index cde13be..2d1e073 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -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);
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index 370e13d..cf51366 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -34,6 +34,7 @@
 #ifndef _SMC91X_H_
 #define _SMC91X_H_
 
+#include <linux/dmaengine.h>
 #include <linux/smc91x.h>
 
 /*
@@ -338,11 +339,8 @@ struct smc_local {
 
 	spinlock_t lock;
 
-#ifdef CONFIG_ARCH_PXA
-	/* DMA needs the physical address of the chip */
-	u_long physaddr;
-	struct device *device;
-#endif
+	struct dma_chan	*dma_channel;
+
 	void __iomem *base;
 	void __iomem *datacs;
 
@@ -358,13 +356,29 @@ struct smc_local {
 
 #ifdef CONFIG_ARCH_PXA
 /*
- * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
+ * Let's use the generic DMA buffer-to-buffer offload mechanism. This is
  * always happening in irq context so no need to worry about races.  TX is
  * different and probably not worth it for that reason, and not as critical
  * as RX which can overrun memory and lose packets.
  */
-#include <linux/dma-mapping.h>
-#include <mach/dma.h>
+
+static void smc_dma_copy(struct smc_local *lp, void *dest, void *src,
+			 unsigned int len)
+{
+	dma_cookie_t cookie;
+	cookie = dma_async_memcpy_buf_to_buf(lp->dma_channel, dest, src, len);
+
+	while (1) {
+		struct dma_tx_state state;
+		enum dma_status status;
+
+		status = dmaengine_tx_status(lp->dma_channel, cookie, &state);
+		if (status != DMA_IN_PROGRESS)
+			break;
+
+		cpu_relax();
+	}
+}
 
 #ifdef SMC_insl
 #undef SMC_insl
@@ -374,11 +388,8 @@ static inline void
 smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		 u_char *buf, int len)
 {
-	u_long physaddr = lp->physaddr;
-	dma_addr_t dmabuf;
-
 	/* fallback if no DMA available */
-	if (dma == (unsigned char)-1) {
+	if (lp->dma_channel == NULL) {
 		readsl(ioaddr + reg, buf, len);
 		return;
 	}
@@ -390,18 +401,7 @@ smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		len--;
 	}
 
-	len *= 4;
-	dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
-	DCSR(dma) = DCSR_NODESC;
-	DTADR(dma) = dmabuf;
-	DSADR(dma) = physaddr + reg;
-	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-		     DCMD_WIDTH4 | (DCMD_LENGTH & len));
-	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
-	while (!(DCSR(dma) & DCSR_STOPSTATE))
-		cpu_relax();
-	DCSR(dma) = 0;
-	dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+	smc_dma_copy(lp, buf, (__u32 *) ioaddr + reg, len * 4);
 }
 #endif
 
@@ -413,11 +413,8 @@ static inline void
 smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		 u_char *buf, int len)
 {
-	u_long physaddr = lp->physaddr;
-	dma_addr_t dmabuf;
-
 	/* fallback if no DMA available */
-	if (dma == (unsigned char)-1) {
+	if (lp->dma_channel == NULL) {
 		readsw(ioaddr + reg, buf, len);
 		return;
 	}
@@ -429,26 +426,10 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		len--;
 	}
 
-	len *= 2;
-	dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
-	DCSR(dma) = DCSR_NODESC;
-	DTADR(dma) = dmabuf;
-	DSADR(dma) = physaddr + reg;
-	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-		     DCMD_WIDTH2 | (DCMD_LENGTH & len));
-	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
-	while (!(DCSR(dma) & DCSR_STOPSTATE))
-		cpu_relax();
-	DCSR(dma) = 0;
-	dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+	smc_dma_copy(lp, buf, (__u32 *) ioaddr + reg, len * 2);
 }
 #endif
 
-static void
-smc_pxa_dma_irq(int dma, void *dummy)
-{
-	DCSR(dma) = 0;
-}
 #endif  /* CONFIG_ARCH_PXA */
 
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 11/20] net: smc91x.c: switch to generic buf-to-buf DMA offload
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

Drop all PXA-DMA specific implementation details and rely on
dma_async_memcpy_buf_to_buf().

This patch is only compile-tested.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/net/ethernet/smsc/smc91x.c | 40 +++++++--------------
 drivers/net/ethernet/smsc/smc91x.h | 71 ++++++++++++++------------------------
 2 files changed, 38 insertions(+), 73 deletions(-)

diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index cde13be..2d1e073 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -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);
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index 370e13d..cf51366 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -34,6 +34,7 @@
 #ifndef _SMC91X_H_
 #define _SMC91X_H_
 
+#include <linux/dmaengine.h>
 #include <linux/smc91x.h>
 
 /*
@@ -338,11 +339,8 @@ struct smc_local {
 
 	spinlock_t lock;
 
-#ifdef CONFIG_ARCH_PXA
-	/* DMA needs the physical address of the chip */
-	u_long physaddr;
-	struct device *device;
-#endif
+	struct dma_chan	*dma_channel;
+
 	void __iomem *base;
 	void __iomem *datacs;
 
@@ -358,13 +356,29 @@ struct smc_local {
 
 #ifdef CONFIG_ARCH_PXA
 /*
- * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
+ * Let's use the generic DMA buffer-to-buffer offload mechanism. This is
  * always happening in irq context so no need to worry about races.  TX is
  * different and probably not worth it for that reason, and not as critical
  * as RX which can overrun memory and lose packets.
  */
-#include <linux/dma-mapping.h>
-#include <mach/dma.h>
+
+static void smc_dma_copy(struct smc_local *lp, void *dest, void *src,
+			 unsigned int len)
+{
+	dma_cookie_t cookie;
+	cookie = dma_async_memcpy_buf_to_buf(lp->dma_channel, dest, src, len);
+
+	while (1) {
+		struct dma_tx_state state;
+		enum dma_status status;
+
+		status = dmaengine_tx_status(lp->dma_channel, cookie, &state);
+		if (status != DMA_IN_PROGRESS)
+			break;
+
+		cpu_relax();
+	}
+}
 
 #ifdef SMC_insl
 #undef SMC_insl
@@ -374,11 +388,8 @@ static inline void
 smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		 u_char *buf, int len)
 {
-	u_long physaddr = lp->physaddr;
-	dma_addr_t dmabuf;
-
 	/* fallback if no DMA available */
-	if (dma == (unsigned char)-1) {
+	if (lp->dma_channel == NULL) {
 		readsl(ioaddr + reg, buf, len);
 		return;
 	}
@@ -390,18 +401,7 @@ smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		len--;
 	}
 
-	len *= 4;
-	dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
-	DCSR(dma) = DCSR_NODESC;
-	DTADR(dma) = dmabuf;
-	DSADR(dma) = physaddr + reg;
-	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-		     DCMD_WIDTH4 | (DCMD_LENGTH & len));
-	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
-	while (!(DCSR(dma) & DCSR_STOPSTATE))
-		cpu_relax();
-	DCSR(dma) = 0;
-	dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+	smc_dma_copy(lp, buf, (__u32 *) ioaddr + reg, len * 4);
 }
 #endif
 
@@ -413,11 +413,8 @@ static inline void
 smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		 u_char *buf, int len)
 {
-	u_long physaddr = lp->physaddr;
-	dma_addr_t dmabuf;
-
 	/* fallback if no DMA available */
-	if (dma == (unsigned char)-1) {
+	if (lp->dma_channel == NULL) {
 		readsw(ioaddr + reg, buf, len);
 		return;
 	}
@@ -429,26 +426,10 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		len--;
 	}
 
-	len *= 2;
-	dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
-	DCSR(dma) = DCSR_NODESC;
-	DTADR(dma) = dmabuf;
-	DSADR(dma) = physaddr + reg;
-	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-		     DCMD_WIDTH2 | (DCMD_LENGTH & len));
-	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
-	while (!(DCSR(dma) & DCSR_STOPSTATE))
-		cpu_relax();
-	DCSR(dma) = 0;
-	dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
+	smc_dma_copy(lp, buf, (__u32 *) ioaddr + reg, len * 2);
 }
 #endif
 
-static void
-smc_pxa_dma_irq(int dma, void *dummy)
-{
-	DCSR(dma) = 0;
-}
 #endif  /* CONFIG_ARCH_PXA */
 
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 12/20] net: smc911x.c: switch to dmaengine API
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Drop all PXA-DMA specific implementation details and switch over to
generic dmaengine usage.

This patch is only compile-tested.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/net/ethernet/smsc/smc911x.c | 80 ++++++++++++++++++++++-------------
 drivers/net/ethernet/smsc/smc911x.h | 83 ++++++++++++++++++++-----------------
 2 files changed, 98 insertions(+), 65 deletions(-)

diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 345558f..19cdf8f 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -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);
diff --git a/drivers/net/ethernet/smsc/smc911x.h b/drivers/net/ethernet/smsc/smc911x.h
index d51261b..9323f1d 100644
--- a/drivers/net/ethernet/smsc/smc911x.h
+++ b/drivers/net/ethernet/smsc/smc911x.h
@@ -29,6 +29,7 @@
 #ifndef _SMC911X_H_
 #define _SMC911X_H_
 
+#include <linux/dmaengine.h>
 #include <linux/smc911x.h>
 /*
  * Use the DMA feature on PXA chips
@@ -102,8 +103,8 @@ struct smc911x_local {
 #ifdef SMC_USE_DMA
 	/* DMA needs the physical address of the chip */
 	u_long physaddr;
-	int rxdma;
-	int txdma;
+	struct dma_chan	*rxdma;
+	struct dma_chan *txdma;
 	int rxdma_active;
 	int txdma_active;
 	struct sk_buff *current_rx_skb;
@@ -211,27 +212,6 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
 
 #ifdef SMC_USE_PXA_DMA
 
-#include <mach/dma.h>
-
-/*
- * Define the request and free functions
- * These are unfortunately architecture specific as no generic allocation
- * mechanism exits
- */
-#define SMC_DMA_REQUEST(dev, handler) \
-	 pxa_request_dma(dev->name, DMA_PRIO_LOW, handler, dev)
-
-#define SMC_DMA_FREE(dev, dma) \
-	 pxa_free_dma(dma)
-
-#define SMC_DMA_ACK_IRQ(dev, dma)					\
-{									\
-	if (DCSR(dma) & DCSR_BUSERR) {					\
-		printk("%s: DMA %d bus error!\n", dev->name, dma);	\
-	}								\
-	DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;		\
-}
-
 /*
  * Use a DMA for RX and TX packets.
  */
@@ -240,6 +220,9 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
 static dma_addr_t rx_dmabuf, tx_dmabuf;
 static int rx_dmalen, tx_dmalen;
 
+static void smc911x_tx_dma_irq(void *param);
+static void smc911x_rx_dma_irq(void *param);
+
 #ifdef SMC_insl
 #undef SMC_insl
 #define SMC_insl(lp, r, p, l) \
@@ -247,8 +230,17 @@ static int rx_dmalen, tx_dmalen;
 
 static inline void
 smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr,
-		int reg, int dma, u_char *buf, int len)
+		int reg, struct dma_chan *chan, u_char *buf, int len)
 {
+	struct dma_async_tx_descriptor *tx;
+	struct dma_slave_config conf;
+
+	memset(&conf, 0, sizeof(conf));
+
+	conf.direction = DMA_DEV_TO_MEM;
+	conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	conf.src_maxburst = 32;
+
 	/* 64 bit alignment is required for memory to memory DMA */
 	if ((long)buf & 4) {
 		*((u32 *)buf) = SMC_inl(lp, reg);
@@ -259,12 +251,16 @@ smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr,
 	len *= 4;
 	rx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_FROM_DEVICE);
 	rx_dmalen = len;
-	DCSR(dma) = DCSR_NODESC;
-	DTADR(dma) = rx_dmabuf;
-	DSADR(dma) = physaddr + reg;
-	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-		DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
-	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+
+	dmaengine_slave_config(chan, &conf);
+	tx = chan->device->device_prep_dma_memcpy(chan, rx_dmabuf,
+						  physaddr + reg, len, 0);
+
+	tx->callback = smc911x_rx_dma_irq;
+	tx->callback_param = lp->netdev;
+
+	dmaengine_submit(tx);
+	dma_async_issue_pending(chan);
 }
 #endif
 
@@ -275,8 +271,17 @@ smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr,
 
 static inline void
 smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
-		int reg, int dma, u_char *buf, int len)
+		int reg, struct dma_chan *chan, u_char *buf, int len)
 {
+	struct dma_async_tx_descriptor *tx;
+	struct dma_slave_config conf;
+
+	memset(&conf, 0, sizeof(conf));
+
+	conf.direction = DMA_MEM_TO_DEV;
+	conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	conf.dst_maxburst = 32;
+
 	/* 64 bit alignment is required for memory to memory DMA */
 	if ((long)buf & 4) {
 		SMC_outl(*((u32 *)buf), lp, reg);
@@ -287,12 +292,16 @@ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
 	len *= 4;
 	tx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_TO_DEVICE);
 	tx_dmalen = len;
-	DCSR(dma) = DCSR_NODESC;
-	DSADR(dma) = tx_dmabuf;
-	DTADR(dma) = physaddr + reg;
-	DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
-		DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
-	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+
+	dmaengine_slave_config(chan, &conf);
+	tx = chan->device->device_prep_dma_memcpy(chan, physaddr + reg,
+						  tx_dmabuf, len, 0);
+
+	tx->callback = smc911x_tx_dma_irq;
+	tx->callback_param = lp->netdev;
+
+	dmaengine_submit(tx);
+	dma_async_issue_pending(chan);
 }
 #endif
 #endif	 /* SMC_USE_PXA_DMA */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 12/20] net: smc911x.c: switch to dmaengine API
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

Drop all PXA-DMA specific implementation details and switch over to
generic dmaengine usage.

This patch is only compile-tested.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/net/ethernet/smsc/smc911x.c | 80 ++++++++++++++++++++++-------------
 drivers/net/ethernet/smsc/smc911x.h | 83 ++++++++++++++++++++-----------------
 2 files changed, 98 insertions(+), 65 deletions(-)

diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 345558f..19cdf8f 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -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);
diff --git a/drivers/net/ethernet/smsc/smc911x.h b/drivers/net/ethernet/smsc/smc911x.h
index d51261b..9323f1d 100644
--- a/drivers/net/ethernet/smsc/smc911x.h
+++ b/drivers/net/ethernet/smsc/smc911x.h
@@ -29,6 +29,7 @@
 #ifndef _SMC911X_H_
 #define _SMC911X_H_
 
+#include <linux/dmaengine.h>
 #include <linux/smc911x.h>
 /*
  * Use the DMA feature on PXA chips
@@ -102,8 +103,8 @@ struct smc911x_local {
 #ifdef SMC_USE_DMA
 	/* DMA needs the physical address of the chip */
 	u_long physaddr;
-	int rxdma;
-	int txdma;
+	struct dma_chan	*rxdma;
+	struct dma_chan *txdma;
 	int rxdma_active;
 	int txdma_active;
 	struct sk_buff *current_rx_skb;
@@ -211,27 +212,6 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
 
 #ifdef SMC_USE_PXA_DMA
 
-#include <mach/dma.h>
-
-/*
- * Define the request and free functions
- * These are unfortunately architecture specific as no generic allocation
- * mechanism exits
- */
-#define SMC_DMA_REQUEST(dev, handler) \
-	 pxa_request_dma(dev->name, DMA_PRIO_LOW, handler, dev)
-
-#define SMC_DMA_FREE(dev, dma) \
-	 pxa_free_dma(dma)
-
-#define SMC_DMA_ACK_IRQ(dev, dma)					\
-{									\
-	if (DCSR(dma) & DCSR_BUSERR) {					\
-		printk("%s: DMA %d bus error!\n", dev->name, dma);	\
-	}								\
-	DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;		\
-}
-
 /*
  * Use a DMA for RX and TX packets.
  */
@@ -240,6 +220,9 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
 static dma_addr_t rx_dmabuf, tx_dmabuf;
 static int rx_dmalen, tx_dmalen;
 
+static void smc911x_tx_dma_irq(void *param);
+static void smc911x_rx_dma_irq(void *param);
+
 #ifdef SMC_insl
 #undef SMC_insl
 #define SMC_insl(lp, r, p, l) \
@@ -247,8 +230,17 @@ static int rx_dmalen, tx_dmalen;
 
 static inline void
 smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr,
-		int reg, int dma, u_char *buf, int len)
+		int reg, struct dma_chan *chan, u_char *buf, int len)
 {
+	struct dma_async_tx_descriptor *tx;
+	struct dma_slave_config conf;
+
+	memset(&conf, 0, sizeof(conf));
+
+	conf.direction = DMA_DEV_TO_MEM;
+	conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	conf.src_maxburst = 32;
+
 	/* 64 bit alignment is required for memory to memory DMA */
 	if ((long)buf & 4) {
 		*((u32 *)buf) = SMC_inl(lp, reg);
@@ -259,12 +251,16 @@ smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr,
 	len *= 4;
 	rx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_FROM_DEVICE);
 	rx_dmalen = len;
-	DCSR(dma) = DCSR_NODESC;
-	DTADR(dma) = rx_dmabuf;
-	DSADR(dma) = physaddr + reg;
-	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
-		DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
-	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+
+	dmaengine_slave_config(chan, &conf);
+	tx = chan->device->device_prep_dma_memcpy(chan, rx_dmabuf,
+						  physaddr + reg, len, 0);
+
+	tx->callback = smc911x_rx_dma_irq;
+	tx->callback_param = lp->netdev;
+
+	dmaengine_submit(tx);
+	dma_async_issue_pending(chan);
 }
 #endif
 
@@ -275,8 +271,17 @@ smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr,
 
 static inline void
 smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
-		int reg, int dma, u_char *buf, int len)
+		int reg, struct dma_chan *chan, u_char *buf, int len)
 {
+	struct dma_async_tx_descriptor *tx;
+	struct dma_slave_config conf;
+
+	memset(&conf, 0, sizeof(conf));
+
+	conf.direction = DMA_MEM_TO_DEV;
+	conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	conf.dst_maxburst = 32;
+
 	/* 64 bit alignment is required for memory to memory DMA */
 	if ((long)buf & 4) {
 		SMC_outl(*((u32 *)buf), lp, reg);
@@ -287,12 +292,16 @@ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
 	len *= 4;
 	tx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_TO_DEVICE);
 	tx_dmalen = len;
-	DCSR(dma) = DCSR_NODESC;
-	DSADR(dma) = tx_dmabuf;
-	DTADR(dma) = physaddr + reg;
-	DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
-		DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
-	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+
+	dmaengine_slave_config(chan, &conf);
+	tx = chan->device->device_prep_dma_memcpy(chan, physaddr + reg,
+						  tx_dmabuf, len, 0);
+
+	tx->callback = smc911x_tx_dma_irq;
+	tx->callback_param = lp->netdev;
+
+	dmaengine_submit(tx);
+	dma_async_issue_pending(chan);
 }
 #endif
 #endif	 /* SMC_USE_PXA_DMA */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

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 <zonque@gmail.com>
---
 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

diff --git a/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
new file mode 100644
index 0000000..19d5488
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
@@ -0,0 +1,7 @@
+Marvell PXA SSP CPU DAI bindings
+
+Required properties:
+
+	compatible	Must be "mrvl,pxa-ssp-dai"
+
+
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 6f4dd75..82b9985 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -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,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

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 <zonque@gmail.com>
---
 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

diff --git a/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt b/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
new file mode 100644
index 0000000..19d5488
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
@@ -0,0 +1,7 @@
+Marvell PXA SSP CPU DAI bindings
+
+Required properties:
+
+	compatible	Must be "mrvl,pxa-ssp-dai"
+
+
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 6f4dd75..82b9985 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -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,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 14/20] ASoC: pxa: use snd_dmaengine_dai_dma_data
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Use 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.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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(-)

diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 2fd3d25..56e818e 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -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);
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index ce431e6..5066a37 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -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;
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index 823359e..a61d7a9 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -7,11 +7,13 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/pxa2xx-lib.h>
+#include <sound/dmaengine_pcm.h>
 
 #include <mach/dma.h>
 
@@ -43,6 +45,35 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 	size_t period = params_period_bytes(params);
 	pxa_dma_desc *dma_desc;
 	dma_addr_t dma_buff_phys, next_desc_phys;
+	u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
+
+	/* temporary transition hack */
+	switch (rtd->params->addr_width) {
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		dcmd |= DCMD_WIDTH1;
+		break;
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		dcmd |= DCMD_WIDTH2;
+		break;
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		dcmd |= DCMD_WIDTH4;
+		break;
+	default:
+		/* can't happen */
+		break;
+	}
+
+	switch (rtd->params->maxburst) {
+	case 8:
+		dcmd |= DCMD_BURST8;
+		break;
+	case 16:
+		dcmd |= DCMD_BURST16;
+		break;
+	case 32:
+		dcmd |= DCMD_BURST32;
+		break;
+	}
 
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 	runtime->dma_bytes = totsize;
@@ -55,14 +86,14 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 		dma_desc->ddadr = next_desc_phys;
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			dma_desc->dsadr = dma_buff_phys;
-			dma_desc->dtadr = rtd->params->dev_addr;
+			dma_desc->dtadr = rtd->params->addr;
 		} else {
-			dma_desc->dsadr = rtd->params->dev_addr;
+			dma_desc->dsadr = rtd->params->addr;
 			dma_desc->dtadr = dma_buff_phys;
 		}
 		if (period > totsize)
 			period = totsize;
-		dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN;
+		dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN;
 		dma_desc++;
 		dma_buff_phys += period;
 	} while (totsize -= period);
@@ -76,8 +107,10 @@ int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
 	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
 
-	if (rtd && rtd->params && rtd->params->drcmr)
-		*rtd->params->drcmr = 0;
+	if (rtd && rtd->params && rtd->params->filter_data) {
+		unsigned long req = *(unsigned long *) rtd->params->filter_data;
+		DRCMR(req) = 0;
+	}
 
 	snd_pcm_set_runtime_buffer(substream, NULL);
 	return 0;
@@ -136,6 +169,7 @@ EXPORT_SYMBOL(pxa2xx_pcm_pointer);
 int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
 {
 	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
+	unsigned long req;
 
 	if (!prtd || !prtd->params)
 		return 0;
@@ -146,7 +180,8 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
 	DCSR(prtd->dma_ch) &= ~DCSR_RUN;
 	DCSR(prtd->dma_ch) = 0;
 	DCMD(prtd->dma_ch) = 0;
-	*prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
+	req = *(unsigned long *) prtd->params->filter_data;
+	DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD;
 
 	return 0;
 }
@@ -155,7 +190,6 @@ EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
 void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
 {
 	struct snd_pcm_substream *substream = dev_id;
-	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
 	int dcsr;
 
 	dcsr = DCSR(dma_ch);
@@ -164,8 +198,8 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
 	if (dcsr & DCSR_ENDINTR) {
 		snd_pcm_period_elapsed(substream);
 	} else {
-		printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
-			rtd->params->name, dma_ch, dcsr);
+		printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
+			dma_ch, dcsr);
 		snd_pcm_stream_lock(substream);
 		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
 		snd_pcm_stream_unlock(substream);
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index 26422a3..69a2455 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -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;
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h
index 65f86b5..2a8fc08 100644
--- a/sound/arm/pxa2xx-pcm.h
+++ b/sound/arm/pxa2xx-pcm.h
@@ -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 *);
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 5d57e07..9a97843 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -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;
 	}
 
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 62142ce..84f1e9e 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -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;
 
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 82b9985..3903343 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -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);
 
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 1475515..f1059d9 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -14,15 +14,16 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/dmaengine.h>
 
 #include <sound/core.h>
 #include <sound/ac97_codec.h>
 #include <sound/soc.h>
 #include <sound/pxa2xx-lib.h>
+#include <sound/dmaengine_pcm.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-ac97.h>
-#include <mach/dma.h>
 #include <mach/audio.h>
 
 #include "pxa2xx-ac97.h"
@@ -48,44 +49,44 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
 	.reset	= pxa2xx_ac97_cold_reset,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
-	.name			= "AC97 PCM Stereo out",
-	.dev_addr		= __PREG(PCDR),
-	.drcmr			= &DRCMR(12),
-	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
-				  DCMD_BURST32 | DCMD_WIDTH4,
+static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 12;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = {
+	.addr		= __PREG(PCDR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_4_BYTES,
+	.maxburst	= 32,
+	.filter_data	= &pxa2xx_ac97_pcm_stereo_in_req,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
-	.name			= "AC97 PCM Stereo in",
-	.dev_addr		= __PREG(PCDR),
-	.drcmr			= &DRCMR(11),
-	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
-				  DCMD_BURST32 | DCMD_WIDTH4,
+static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 11;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = {
+	.addr		= __PREG(PCDR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_4_BYTES,
+	.maxburst	= 32,
+	.filter_data	= &pxa2xx_ac97_pcm_stereo_out_req,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
-	.name			= "AC97 Aux PCM (Slot 5) Mono out",
-	.dev_addr		= __PREG(MODR),
-	.drcmr			= &DRCMR(10),
-	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
-				  DCMD_BURST16 | DCMD_WIDTH2,
+static unsigned long pxa2xx_ac97_pcm_aux_mono_out_req = 10;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_out = {
+	.addr		= __PREG(MODR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_2_BYTES,
+	.maxburst	= 16,
+	.filter_data	= &pxa2xx_ac97_pcm_aux_mono_out_req,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
-	.name			= "AC97 Aux PCM (Slot 5) Mono in",
-	.dev_addr		= __PREG(MODR),
-	.drcmr			= &DRCMR(9),
-	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
-				  DCMD_BURST16 | DCMD_WIDTH2,
+static unsigned long pxa2xx_ac97_pcm_aux_mono_in_req = 9;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_in = {
+	.addr		= __PREG(MODR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_2_BYTES,
+	.maxburst	= 16,
+	.filter_data	= &pxa2xx_ac97_pcm_aux_mono_in_req,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
-	.name			= "AC97 Mic PCM (Slot 6) Mono in",
-	.dev_addr		= __PREG(MCDR),
-	.drcmr			= &DRCMR(8),
-	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
-				  DCMD_BURST16 | DCMD_WIDTH2,
+static unsigned long pxa2xx_ac97_pcm_aux_mic_mono_req = 8;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = {
+	.addr		= __PREG(MCDR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_2_BYTES,
+	.maxburst	= 16,
+	.filter_data	= &pxa2xx_ac97_pcm_aux_mic_mono_req,
 };
 
 #ifdef CONFIG_PM
@@ -119,7 +120,7 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
 				 struct snd_pcm_hw_params *params,
 				 struct snd_soc_dai *cpu_dai)
 {
-	struct pxa2xx_pcm_dma_params *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dma_data = &pxa2xx_ac97_pcm_stereo_out;
@@ -135,7 +136,7 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
 				     struct snd_pcm_hw_params *params,
 				     struct snd_soc_dai *cpu_dai)
 {
-	struct pxa2xx_pcm_dma_params *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index f7ca716..d5340a0 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -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);
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index ecff116..0aa2d69 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -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;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 14/20] ASoC: pxa: use snd_dmaengine_dai_dma_data
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

Use 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.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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(-)

diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 2fd3d25..56e818e 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -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);
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index ce431e6..5066a37 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -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;
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index 823359e..a61d7a9 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -7,11 +7,13 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/pxa2xx-lib.h>
+#include <sound/dmaengine_pcm.h>
 
 #include <mach/dma.h>
 
@@ -43,6 +45,35 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 	size_t period = params_period_bytes(params);
 	pxa_dma_desc *dma_desc;
 	dma_addr_t dma_buff_phys, next_desc_phys;
+	u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
+
+	/* temporary transition hack */
+	switch (rtd->params->addr_width) {
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		dcmd |= DCMD_WIDTH1;
+		break;
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		dcmd |= DCMD_WIDTH2;
+		break;
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		dcmd |= DCMD_WIDTH4;
+		break;
+	default:
+		/* can't happen */
+		break;
+	}
+
+	switch (rtd->params->maxburst) {
+	case 8:
+		dcmd |= DCMD_BURST8;
+		break;
+	case 16:
+		dcmd |= DCMD_BURST16;
+		break;
+	case 32:
+		dcmd |= DCMD_BURST32;
+		break;
+	}
 
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 	runtime->dma_bytes = totsize;
@@ -55,14 +86,14 @@ int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 		dma_desc->ddadr = next_desc_phys;
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			dma_desc->dsadr = dma_buff_phys;
-			dma_desc->dtadr = rtd->params->dev_addr;
+			dma_desc->dtadr = rtd->params->addr;
 		} else {
-			dma_desc->dsadr = rtd->params->dev_addr;
+			dma_desc->dsadr = rtd->params->addr;
 			dma_desc->dtadr = dma_buff_phys;
 		}
 		if (period > totsize)
 			period = totsize;
-		dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN;
+		dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN;
 		dma_desc++;
 		dma_buff_phys += period;
 	} while (totsize -= period);
@@ -76,8 +107,10 @@ int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
 	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
 
-	if (rtd && rtd->params && rtd->params->drcmr)
-		*rtd->params->drcmr = 0;
+	if (rtd && rtd->params && rtd->params->filter_data) {
+		unsigned long req = *(unsigned long *) rtd->params->filter_data;
+		DRCMR(req) = 0;
+	}
 
 	snd_pcm_set_runtime_buffer(substream, NULL);
 	return 0;
@@ -136,6 +169,7 @@ EXPORT_SYMBOL(pxa2xx_pcm_pointer);
 int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
 {
 	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
+	unsigned long req;
 
 	if (!prtd || !prtd->params)
 		return 0;
@@ -146,7 +180,8 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
 	DCSR(prtd->dma_ch) &= ~DCSR_RUN;
 	DCSR(prtd->dma_ch) = 0;
 	DCMD(prtd->dma_ch) = 0;
-	*prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
+	req = *(unsigned long *) prtd->params->filter_data;
+	DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD;
 
 	return 0;
 }
@@ -155,7 +190,6 @@ EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
 void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
 {
 	struct snd_pcm_substream *substream = dev_id;
-	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
 	int dcsr;
 
 	dcsr = DCSR(dma_ch);
@@ -164,8 +198,8 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
 	if (dcsr & DCSR_ENDINTR) {
 		snd_pcm_period_elapsed(substream);
 	} else {
-		printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
-			rtd->params->name, dma_ch, dcsr);
+		printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
+			dma_ch, dcsr);
 		snd_pcm_stream_lock(substream);
 		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
 		snd_pcm_stream_unlock(substream);
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index 26422a3..69a2455 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -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;
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h
index 65f86b5..2a8fc08 100644
--- a/sound/arm/pxa2xx-pcm.h
+++ b/sound/arm/pxa2xx-pcm.h
@@ -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 *);
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 5d57e07..9a97843 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -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;
 	}
 
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 62142ce..84f1e9e 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -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;
 
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 82b9985..3903343 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -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);
 
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 1475515..f1059d9 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -14,15 +14,16 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/dmaengine.h>
 
 #include <sound/core.h>
 #include <sound/ac97_codec.h>
 #include <sound/soc.h>
 #include <sound/pxa2xx-lib.h>
+#include <sound/dmaengine_pcm.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-ac97.h>
-#include <mach/dma.h>
 #include <mach/audio.h>
 
 #include "pxa2xx-ac97.h"
@@ -48,44 +49,44 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
 	.reset	= pxa2xx_ac97_cold_reset,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
-	.name			= "AC97 PCM Stereo out",
-	.dev_addr		= __PREG(PCDR),
-	.drcmr			= &DRCMR(12),
-	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
-				  DCMD_BURST32 | DCMD_WIDTH4,
+static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 12;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = {
+	.addr		= __PREG(PCDR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_4_BYTES,
+	.maxburst	= 32,
+	.filter_data	= &pxa2xx_ac97_pcm_stereo_in_req,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
-	.name			= "AC97 PCM Stereo in",
-	.dev_addr		= __PREG(PCDR),
-	.drcmr			= &DRCMR(11),
-	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
-				  DCMD_BURST32 | DCMD_WIDTH4,
+static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 11;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = {
+	.addr		= __PREG(PCDR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_4_BYTES,
+	.maxburst	= 32,
+	.filter_data	= &pxa2xx_ac97_pcm_stereo_out_req,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
-	.name			= "AC97 Aux PCM (Slot 5) Mono out",
-	.dev_addr		= __PREG(MODR),
-	.drcmr			= &DRCMR(10),
-	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
-				  DCMD_BURST16 | DCMD_WIDTH2,
+static unsigned long pxa2xx_ac97_pcm_aux_mono_out_req = 10;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_out = {
+	.addr		= __PREG(MODR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_2_BYTES,
+	.maxburst	= 16,
+	.filter_data	= &pxa2xx_ac97_pcm_aux_mono_out_req,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
-	.name			= "AC97 Aux PCM (Slot 5) Mono in",
-	.dev_addr		= __PREG(MODR),
-	.drcmr			= &DRCMR(9),
-	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
-				  DCMD_BURST16 | DCMD_WIDTH2,
+static unsigned long pxa2xx_ac97_pcm_aux_mono_in_req = 9;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_in = {
+	.addr		= __PREG(MODR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_2_BYTES,
+	.maxburst	= 16,
+	.filter_data	= &pxa2xx_ac97_pcm_aux_mono_in_req,
 };
 
-static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
-	.name			= "AC97 Mic PCM (Slot 6) Mono in",
-	.dev_addr		= __PREG(MCDR),
-	.drcmr			= &DRCMR(8),
-	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
-				  DCMD_BURST16 | DCMD_WIDTH2,
+static unsigned long pxa2xx_ac97_pcm_aux_mic_mono_req = 8;
+static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = {
+	.addr		= __PREG(MCDR),
+	.addr_width	= DMA_SLAVE_BUSWIDTH_2_BYTES,
+	.maxburst	= 16,
+	.filter_data	= &pxa2xx_ac97_pcm_aux_mic_mono_req,
 };
 
 #ifdef CONFIG_PM
@@ -119,7 +120,7 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
 				 struct snd_pcm_hw_params *params,
 				 struct snd_soc_dai *cpu_dai)
 {
-	struct pxa2xx_pcm_dma_params *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dma_data = &pxa2xx_ac97_pcm_stereo_out;
@@ -135,7 +136,7 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
 				     struct snd_pcm_hw_params *params,
 				     struct snd_soc_dai *cpu_dai)
 {
-	struct pxa2xx_pcm_dma_params *dma_data;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index f7ca716..d5340a0 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -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);
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index ecff116..0aa2d69 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -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;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 15/20] ASoC: pxa: pxa-ssp: set dma filter data from startup hook
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

With the new dmaengine implementation, the filter_data parameter has
to be set earlier, from pxa_ssp_startup().

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/soc/pxa/pxa-ssp.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 3903343..12491bd 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -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;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 15/20] ASoC: pxa: pxa-ssp: set dma filter data from startup hook
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

With the new dmaengine implementation, the filter_data parameter has
to be set earlier, from pxa_ssp_startup().

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/soc/pxa/pxa-ssp.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 3903343..12491bd 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -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;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 16/20] ASoC: pxa: add DT bindings for pxa2xx-pcm
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

The bindings do not carry any resources, as the module only registers
the ASoC platform driver.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 .../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

diff --git a/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt b/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
new file mode 100644
index 0000000..551fbb8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
@@ -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";
+	};
+
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 0aa2d69..806da27 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -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,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 16/20] ASoC: pxa: add DT bindings for pxa2xx-pcm
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

The bindings do not carry any resources, as the module only registers
the ASoC platform driver.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 .../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

diff --git a/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt b/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
new file mode 100644
index 0000000..551fbb8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mrvl,pxa2xx-pcm.txt
@@ -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";
+	};
+
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 0aa2d69..806da27 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -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,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

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.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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(-)

diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 56e818e..6ef629b 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -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,
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index 885683a..c7a872c 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -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
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index a61d7a9..8471e48 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/dma/mmp-pdma.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -15,8 +16,6 @@
 #include <sound/pxa2xx-lib.h>
 #include <sound/dmaengine_pcm.h>
 
-#include <mach/dma.h>
-
 #include "pxa2xx-pcm.h"
 
 static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
@@ -31,7 +30,7 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
 	.period_bytes_min	= 32,
 	.period_bytes_max	= 8192 - 32,
 	.periods_min		= 1,
-	.periods_max		= PAGE_SIZE/sizeof(pxa_dma_desc),
+	.periods_max		= 256,
 	.buffer_bytes_max	= 128 * 1024,
 	.fifo_size		= 32,
 };
@@ -39,65 +38,29 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
 int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct pxa2xx_runtime_data *rtd = runtime->private_data;
-	size_t totsize = params_buffer_bytes(params);
-	size_t period = params_period_bytes(params);
-	pxa_dma_desc *dma_desc;
-	dma_addr_t dma_buff_phys, next_desc_phys;
-	u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
+	struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_dmaengine_dai_dma_data *dma_params;
+	struct dma_slave_config config;
+	int ret;
 
-	/* temporary transition hack */
-	switch (rtd->params->addr_width) {
-	case DMA_SLAVE_BUSWIDTH_1_BYTE:
-		dcmd |= DCMD_WIDTH1;
-		break;
-	case DMA_SLAVE_BUSWIDTH_2_BYTES:
-		dcmd |= DCMD_WIDTH2;
-		break;
-	case DMA_SLAVE_BUSWIDTH_4_BYTES:
-		dcmd |= DCMD_WIDTH4;
-		break;
-	default:
-		/* can't happen */
-		break;
-	}
+	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+	if (!dma_params)
+		return 0;
 
-	switch (rtd->params->maxburst) {
-	case 8:
-		dcmd |= DCMD_BURST8;
-		break;
-	case 16:
-		dcmd |= DCMD_BURST16;
-		break;
-	case 32:
-		dcmd |= DCMD_BURST32;
-		break;
-	}
+	ret = snd_hwparams_to_dma_slave_config(substream, params, &config);
+	if (ret)
+		return ret;
 
-	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-	runtime->dma_bytes = totsize;
+	snd_dmaengine_pcm_set_config_from_dai_data(substream,
+			snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
+			&config);
 
-	dma_desc = rtd->dma_desc_array;
-	next_desc_phys = rtd->dma_desc_array_phys;
-	dma_buff_phys = runtime->dma_addr;
-	do {
-		next_desc_phys += sizeof(pxa_dma_desc);
-		dma_desc->ddadr = next_desc_phys;
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			dma_desc->dsadr = dma_buff_phys;
-			dma_desc->dtadr = rtd->params->addr;
-		} else {
-			dma_desc->dsadr = rtd->params->addr;
-			dma_desc->dtadr = dma_buff_phys;
-		}
-		if (period > totsize)
-			period = totsize;
-		dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN;
-		dma_desc++;
-		dma_buff_phys += period;
-	} while (totsize -= period);
-	dma_desc[-1].ddadr = rtd->dma_desc_array_phys;
+	ret = dmaengine_slave_config(chan, &config);
+	if (ret)
+		return ret;
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
 	return 0;
 }
@@ -105,13 +68,6 @@ EXPORT_SYMBOL(__pxa2xx_pcm_hw_params);
 
 int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
-	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
-
-	if (rtd && rtd->params && rtd->params->filter_data) {
-		unsigned long req = *(unsigned long *) rtd->params->filter_data;
-		DRCMR(req) = 0;
-	}
-
 	snd_pcm_set_runtime_buffer(substream, NULL);
 	return 0;
 }
@@ -119,102 +75,36 @@ EXPORT_SYMBOL(__pxa2xx_pcm_hw_free);
 
 int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
-	int ret = 0;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
-		DCSR(prtd->dma_ch) = DCSR_RUN;
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		DCSR(prtd->dma_ch) &= ~DCSR_RUN;
-		break;
-
-	case SNDRV_PCM_TRIGGER_RESUME:
-		DCSR(prtd->dma_ch) |= DCSR_RUN;
-		break;
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
-		DCSR(prtd->dma_ch) |= DCSR_RUN;
-		break;
-
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
+	return snd_dmaengine_pcm_trigger(substream, cmd);
 }
 EXPORT_SYMBOL(pxa2xx_pcm_trigger);
 
 snd_pcm_uframes_t
 pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct pxa2xx_runtime_data *prtd = runtime->private_data;
-
-	dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-			 DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch);
-	snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
-
-	if (x == runtime->buffer_size)
-		x = 0;
-	return x;
+	return snd_dmaengine_pcm_pointer(substream);
 }
 EXPORT_SYMBOL(pxa2xx_pcm_pointer);
 
 int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
 {
-	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
-	unsigned long req;
-
-	if (!prtd || !prtd->params)
-		return 0;
-
-	if (prtd->dma_ch == -1)
-		return -EINVAL;
-
-	DCSR(prtd->dma_ch) &= ~DCSR_RUN;
-	DCSR(prtd->dma_ch) = 0;
-	DCMD(prtd->dma_ch) = 0;
-	req = *(unsigned long *) prtd->params->filter_data;
-	DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD;
-
 	return 0;
 }
 EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
 
-void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
-{
-	struct snd_pcm_substream *substream = dev_id;
-	int dcsr;
-
-	dcsr = DCSR(dma_ch);
-	DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
-
-	if (dcsr & DCSR_ENDINTR) {
-		snd_pcm_period_elapsed(substream);
-	} else {
-		printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
-			dma_ch, dcsr);
-		snd_pcm_stream_lock(substream);
-		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-		snd_pcm_stream_unlock(substream);
-	}
-}
-EXPORT_SYMBOL(pxa2xx_pcm_dma_irq);
-
 int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
 {
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct pxa2xx_runtime_data *rtd;
+	struct snd_dmaengine_dai_dma_data *dma_params;
 	int ret;
 
 	runtime->hw = pxa2xx_pcm_hardware;
 
+	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+	if (!dma_params)
+		return 0;
+
 	/*
 	 * For mysterious reasons (and despite what the manual says)
 	 * playback samples are lost if the DMA count is not a multiple
@@ -223,48 +113,27 @@ int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
 	ret = snd_pcm_hw_constraint_step(runtime, 0,
 		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
 	if (ret)
-		goto out;
+		return ret;
 
 	ret = snd_pcm_hw_constraint_step(runtime, 0,
 		SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
 	if (ret)
-		goto out;
+		return ret;
 
 	ret = snd_pcm_hw_constraint_integer(runtime,
 					    SNDRV_PCM_HW_PARAM_PERIODS);
 	if (ret < 0)
-		goto out;
-
-	ret = -ENOMEM;
-	rtd = kzalloc(sizeof(*rtd), GFP_KERNEL);
-	if (!rtd)
-		goto out;
-	rtd->dma_desc_array =
-		dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
-				       &rtd->dma_desc_array_phys, GFP_KERNEL);
-	if (!rtd->dma_desc_array)
-		goto err1;
+		return ret;
 
-	rtd->dma_ch = -1;
-	runtime->private_data = rtd;
-	return 0;
-
- err1:
-	kfree(rtd);
- out:
-	return ret;
+	return snd_dmaengine_pcm_open_request_chan(substream,
+					mmp_pdma_filter_fn,
+					dma_params->filter_data);
 }
 EXPORT_SYMBOL(__pxa2xx_pcm_open);
 
 int __pxa2xx_pcm_close(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct pxa2xx_runtime_data *rtd = runtime->private_data;
-
-	dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
-			      rtd->dma_desc_array, rtd->dma_desc_array_phys);
-	kfree(rtd);
-	return 0;
+	return snd_dmaengine_pcm_close_release_chan(substream);
 }
 EXPORT_SYMBOL(__pxa2xx_pcm_close);
 
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index 69a2455..51be1d4 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -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);
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h
index 2a8fc08..8fa2b7c 100644
--- a/sound/arm/pxa2xx-pcm.h
+++ b/sound/arm/pxa2xx-pcm.h
@@ -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 {
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 806da27..bb44928 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -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;
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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(-)

diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 56e818e..6ef629b 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -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,
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index 885683a..c7a872c 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -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
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index a61d7a9..8471e48 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/dma/mmp-pdma.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -15,8 +16,6 @@
 #include <sound/pxa2xx-lib.h>
 #include <sound/dmaengine_pcm.h>
 
-#include <mach/dma.h>
-
 #include "pxa2xx-pcm.h"
 
 static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
@@ -31,7 +30,7 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
 	.period_bytes_min	= 32,
 	.period_bytes_max	= 8192 - 32,
 	.periods_min		= 1,
-	.periods_max		= PAGE_SIZE/sizeof(pxa_dma_desc),
+	.periods_max		= 256,
 	.buffer_bytes_max	= 128 * 1024,
 	.fifo_size		= 32,
 };
@@ -39,65 +38,29 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
 int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct pxa2xx_runtime_data *rtd = runtime->private_data;
-	size_t totsize = params_buffer_bytes(params);
-	size_t period = params_period_bytes(params);
-	pxa_dma_desc *dma_desc;
-	dma_addr_t dma_buff_phys, next_desc_phys;
-	u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
+	struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_dmaengine_dai_dma_data *dma_params;
+	struct dma_slave_config config;
+	int ret;
 
-	/* temporary transition hack */
-	switch (rtd->params->addr_width) {
-	case DMA_SLAVE_BUSWIDTH_1_BYTE:
-		dcmd |= DCMD_WIDTH1;
-		break;
-	case DMA_SLAVE_BUSWIDTH_2_BYTES:
-		dcmd |= DCMD_WIDTH2;
-		break;
-	case DMA_SLAVE_BUSWIDTH_4_BYTES:
-		dcmd |= DCMD_WIDTH4;
-		break;
-	default:
-		/* can't happen */
-		break;
-	}
+	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+	if (!dma_params)
+		return 0;
 
-	switch (rtd->params->maxburst) {
-	case 8:
-		dcmd |= DCMD_BURST8;
-		break;
-	case 16:
-		dcmd |= DCMD_BURST16;
-		break;
-	case 32:
-		dcmd |= DCMD_BURST32;
-		break;
-	}
+	ret = snd_hwparams_to_dma_slave_config(substream, params, &config);
+	if (ret)
+		return ret;
 
-	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-	runtime->dma_bytes = totsize;
+	snd_dmaengine_pcm_set_config_from_dai_data(substream,
+			snd_soc_dai_get_dma_data(rtd->cpu_dai, substream),
+			&config);
 
-	dma_desc = rtd->dma_desc_array;
-	next_desc_phys = rtd->dma_desc_array_phys;
-	dma_buff_phys = runtime->dma_addr;
-	do {
-		next_desc_phys += sizeof(pxa_dma_desc);
-		dma_desc->ddadr = next_desc_phys;
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			dma_desc->dsadr = dma_buff_phys;
-			dma_desc->dtadr = rtd->params->addr;
-		} else {
-			dma_desc->dsadr = rtd->params->addr;
-			dma_desc->dtadr = dma_buff_phys;
-		}
-		if (period > totsize)
-			period = totsize;
-		dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN;
-		dma_desc++;
-		dma_buff_phys += period;
-	} while (totsize -= period);
-	dma_desc[-1].ddadr = rtd->dma_desc_array_phys;
+	ret = dmaengine_slave_config(chan, &config);
+	if (ret)
+		return ret;
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
 	return 0;
 }
@@ -105,13 +68,6 @@ EXPORT_SYMBOL(__pxa2xx_pcm_hw_params);
 
 int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
-	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
-
-	if (rtd && rtd->params && rtd->params->filter_data) {
-		unsigned long req = *(unsigned long *) rtd->params->filter_data;
-		DRCMR(req) = 0;
-	}
-
 	snd_pcm_set_runtime_buffer(substream, NULL);
 	return 0;
 }
@@ -119,102 +75,36 @@ EXPORT_SYMBOL(__pxa2xx_pcm_hw_free);
 
 int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
-	int ret = 0;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
-		DCSR(prtd->dma_ch) = DCSR_RUN;
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		DCSR(prtd->dma_ch) &= ~DCSR_RUN;
-		break;
-
-	case SNDRV_PCM_TRIGGER_RESUME:
-		DCSR(prtd->dma_ch) |= DCSR_RUN;
-		break;
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
-		DCSR(prtd->dma_ch) |= DCSR_RUN;
-		break;
-
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
+	return snd_dmaengine_pcm_trigger(substream, cmd);
 }
 EXPORT_SYMBOL(pxa2xx_pcm_trigger);
 
 snd_pcm_uframes_t
 pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct pxa2xx_runtime_data *prtd = runtime->private_data;
-
-	dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-			 DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch);
-	snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
-
-	if (x == runtime->buffer_size)
-		x = 0;
-	return x;
+	return snd_dmaengine_pcm_pointer(substream);
 }
 EXPORT_SYMBOL(pxa2xx_pcm_pointer);
 
 int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
 {
-	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
-	unsigned long req;
-
-	if (!prtd || !prtd->params)
-		return 0;
-
-	if (prtd->dma_ch == -1)
-		return -EINVAL;
-
-	DCSR(prtd->dma_ch) &= ~DCSR_RUN;
-	DCSR(prtd->dma_ch) = 0;
-	DCMD(prtd->dma_ch) = 0;
-	req = *(unsigned long *) prtd->params->filter_data;
-	DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD;
-
 	return 0;
 }
 EXPORT_SYMBOL(__pxa2xx_pcm_prepare);
 
-void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
-{
-	struct snd_pcm_substream *substream = dev_id;
-	int dcsr;
-
-	dcsr = DCSR(dma_ch);
-	DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
-
-	if (dcsr & DCSR_ENDINTR) {
-		snd_pcm_period_elapsed(substream);
-	} else {
-		printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n",
-			dma_ch, dcsr);
-		snd_pcm_stream_lock(substream);
-		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-		snd_pcm_stream_unlock(substream);
-	}
-}
-EXPORT_SYMBOL(pxa2xx_pcm_dma_irq);
-
 int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
 {
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct pxa2xx_runtime_data *rtd;
+	struct snd_dmaengine_dai_dma_data *dma_params;
 	int ret;
 
 	runtime->hw = pxa2xx_pcm_hardware;
 
+	dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+	if (!dma_params)
+		return 0;
+
 	/*
 	 * For mysterious reasons (and despite what the manual says)
 	 * playback samples are lost if the DMA count is not a multiple
@@ -223,48 +113,27 @@ int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
 	ret = snd_pcm_hw_constraint_step(runtime, 0,
 		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
 	if (ret)
-		goto out;
+		return ret;
 
 	ret = snd_pcm_hw_constraint_step(runtime, 0,
 		SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
 	if (ret)
-		goto out;
+		return ret;
 
 	ret = snd_pcm_hw_constraint_integer(runtime,
 					    SNDRV_PCM_HW_PARAM_PERIODS);
 	if (ret < 0)
-		goto out;
-
-	ret = -ENOMEM;
-	rtd = kzalloc(sizeof(*rtd), GFP_KERNEL);
-	if (!rtd)
-		goto out;
-	rtd->dma_desc_array =
-		dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
-				       &rtd->dma_desc_array_phys, GFP_KERNEL);
-	if (!rtd->dma_desc_array)
-		goto err1;
+		return ret;
 
-	rtd->dma_ch = -1;
-	runtime->private_data = rtd;
-	return 0;
-
- err1:
-	kfree(rtd);
- out:
-	return ret;
+	return snd_dmaengine_pcm_open_request_chan(substream,
+					mmp_pdma_filter_fn,
+					dma_params->filter_data);
 }
 EXPORT_SYMBOL(__pxa2xx_pcm_open);
 
 int __pxa2xx_pcm_close(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct pxa2xx_runtime_data *rtd = runtime->private_data;
-
-	dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
-			      rtd->dma_desc_array, rtd->dma_desc_array_phys);
-	kfree(rtd);
-	return 0;
+	return snd_dmaengine_pcm_close_release_chan(substream);
 }
 EXPORT_SYMBOL(__pxa2xx_pcm_close);
 
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index 69a2455..51be1d4 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -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);
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h
index 2a8fc08..8fa2b7c 100644
--- a/sound/arm/pxa2xx-pcm.h
+++ b/sound/arm/pxa2xx-pcm.h
@@ -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 {
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 806da27..bb44928 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -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;
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 18/20] ARM: pxa: register static mmp_pdma device
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Drop the init call to the properietary dma subsystem and register the
mmp_pdma device.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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(-)

diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index eb7afe6..78b7181 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -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,
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 0f3fd0d..19906c9 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -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;
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index f2c2897..f9b76f7 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -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();
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..0cb17f1 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -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();
 
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..7675a5d 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -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;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 18/20] ARM: pxa: register static mmp_pdma device
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

Drop the init call to the properietary dma subsystem and register the
mmp_pdma device.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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(-)

diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index eb7afe6..78b7181 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -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,
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 0f3fd0d..19906c9 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -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;
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index f2c2897..f9b76f7 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -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();
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a..0cb17f1 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -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();
 
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3..7675a5d 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -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;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 19/20] ARM: mmp: register static mmp_pdma device
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Drop the init call to the properietary dma subsystem and register
the mmp_pdma device.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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(-)

diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index c7592f1..b027c83 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -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();
 	}
 
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 144e997..0573697 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -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();
 	}
 
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index ce6393a..69b112f 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -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();
 	}
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 19/20] ARM: mmp: register static mmp_pdma device
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

Drop the init call to the properietary dma subsystem and register
the mmp_pdma device.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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(-)

diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index c7592f1..b027c83 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -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();
 	}
 
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 144e997..0573697 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -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();
 	}
 
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index ce6393a..69b112f 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -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();
 	}
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 20/20] ARM: pxa: remove old DMA implementation
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 15:34   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: haojian.zhuang, eric.y.miao, linux-arm-kernel
  Cc: mark.rutland, s.neumann, linux-mtd, Daniel Mack, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	thomas.petazzoni, gregkh, g.liakhovetski, sachin.kamat, kernel,
	djbw, davem

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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

diff --git a/arch/arm/mach-pxa/include/mach/dma.h b/arch/arm/mach-pxa/include/mach/dma.h
deleted file mode 100644
index 5bd5589..0000000
--- a/arch/arm/mach-pxa/include/mach/dma.h
+++ /dev/null
@@ -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 */
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 1fc9419..826ef87 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -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
 
diff --git a/arch/arm/plat-pxa/dma.c b/arch/arm/plat-pxa/dma.c
deleted file mode 100644
index 79ef102..0000000
--- a/arch/arm/plat-pxa/dma.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- *  linux/arch/arm/plat-pxa/dma.c
- *
- *  PXA DMA registration and IRQ dispatching
- *
- *  Author:	Nicolas Pitre
- *  Created:	Nov 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.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/irq.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
-
-#define DMA_DEBUG_NAME		"pxa_dma"
-#define DMA_MAX_REQUESTERS	64
-
-struct dma_channel {
-	char *name;
-	pxa_dma_prio prio;
-	void (*irq_handler)(int, void *);
-	void *data;
-	spinlock_t lock;
-};
-
-static struct dma_channel *dma_channels;
-static int num_dma_channels;
-
-/*
- * Debug fs
- */
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-#include <linux/seq_file.h>
-
-static struct dentry *dbgfs_root, *dbgfs_state, **dbgfs_chan;
-
-static int dbg_show_requester_chan(struct seq_file *s, void *p)
-{
-	int pos = 0;
-	int chan = (int)s->private;
-	int i;
-	u32 drcmr;
-
-	pos += seq_printf(s, "DMA channel %d requesters list :\n", chan);
-	for (i = 0; i < DMA_MAX_REQUESTERS; i++) {
-		drcmr = DRCMR(i);
-		if ((drcmr & DRCMR_CHLNUM) == chan)
-			pos += seq_printf(s, "\tRequester %d (MAPVLD=%d)\n", i,
-					  !!(drcmr & DRCMR_MAPVLD));
-	}
-	return pos;
-}
-
-static inline int dbg_burst_from_dcmd(u32 dcmd)
-{
-	int burst = (dcmd >> 16) & 0x3;
-
-	return burst ? 4 << burst : 0;
-}
-
-static int is_phys_valid(unsigned long addr)
-{
-	return pfn_valid(__phys_to_pfn(addr));
-}
-
-#define DCSR_STR(flag) (dcsr & DCSR_##flag ? #flag" " : "")
-#define DCMD_STR(flag) (dcmd & DCMD_##flag ? #flag" " : "")
-
-static int dbg_show_descriptors(struct seq_file *s, void *p)
-{
-	int pos = 0;
-	int chan = (int)s->private;
-	int i, max_show = 20, burst, width;
-	u32 dcmd;
-	unsigned long phys_desc;
-	struct pxa_dma_desc *desc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dma_channels[chan].lock, flags);
-	phys_desc = DDADR(chan);
-
-	pos += seq_printf(s, "DMA channel %d descriptors :\n", chan);
-	pos += seq_printf(s, "[%03d] First descriptor unknown\n", 0);
-	for (i = 1; i < max_show && is_phys_valid(phys_desc); i++) {
-		desc = phys_to_virt(phys_desc);
-		dcmd = desc->dcmd;
-		burst = dbg_burst_from_dcmd(dcmd);
-		width = (1 << ((dcmd >> 14) & 0x3)) >> 1;
-
-		pos += seq_printf(s, "[%03d] Desc at %08lx(virt %p)\n",
-				  i, phys_desc, desc);
-		pos += seq_printf(s, "\tDDADR = %08x\n", desc->ddadr);
-		pos += seq_printf(s, "\tDSADR = %08x\n", desc->dsadr);
-		pos += seq_printf(s, "\tDTADR = %08x\n", desc->dtadr);
-		pos += seq_printf(s, "\tDCMD  = %08x (%s%s%s%s%s%s%sburst=%d"
-				  " width=%d len=%d)\n",
-				  dcmd,
-				  DCMD_STR(INCSRCADDR), DCMD_STR(INCTRGADDR),
-				  DCMD_STR(FLOWSRC), DCMD_STR(FLOWTRG),
-				  DCMD_STR(STARTIRQEN), DCMD_STR(ENDIRQEN),
-				  DCMD_STR(ENDIAN), burst, width,
-				  dcmd & DCMD_LENGTH);
-		phys_desc = desc->ddadr;
-	}
-	if (i == max_show)
-		pos += seq_printf(s, "[%03d] Desc at %08lx ... max display reached\n",
-				  i, phys_desc);
-	else
-		pos += seq_printf(s, "[%03d] Desc at %08lx is %s\n",
-				  i, phys_desc, phys_desc == DDADR_STOP ?
-				  "DDADR_STOP" : "invalid");
-
-	spin_unlock_irqrestore(&dma_channels[chan].lock, flags);
-	return pos;
-}
-
-static int dbg_show_chan_state(struct seq_file *s, void *p)
-{
-	int pos = 0;
-	int chan = (int)s->private;
-	u32 dcsr, dcmd;
-	int burst, width;
-	static char *str_prio[] = { "high", "normal", "low" };
-
-	dcsr = DCSR(chan);
-	dcmd = DCMD(chan);
-	burst = dbg_burst_from_dcmd(dcmd);
-	width = (1 << ((dcmd >> 14) & 0x3)) >> 1;
-
-	pos += seq_printf(s, "DMA channel %d\n", chan);
-	pos += seq_printf(s, "\tPriority : %s\n",
-			  str_prio[dma_channels[chan].prio]);
-	pos += seq_printf(s, "\tUnaligned transfer bit: %s\n",
-			  DALGN & (1 << chan) ? "yes" : "no");
-	pos += seq_printf(s, "\tDCSR  = %08x (%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
-			  dcsr, DCSR_STR(RUN), DCSR_STR(NODESC),
-			  DCSR_STR(STOPIRQEN), DCSR_STR(EORIRQEN),
-			  DCSR_STR(EORJMPEN), DCSR_STR(EORSTOPEN),
-			  DCSR_STR(SETCMPST), DCSR_STR(CLRCMPST),
-			  DCSR_STR(CMPST), DCSR_STR(EORINTR), DCSR_STR(REQPEND),
-			  DCSR_STR(STOPSTATE), DCSR_STR(ENDINTR),
-			  DCSR_STR(STARTINTR), DCSR_STR(BUSERR));
-
-	pos += seq_printf(s, "\tDCMD  = %08x (%s%s%s%s%s%s%sburst=%d width=%d"
-			  " len=%d)\n",
-			  dcmd,
-			  DCMD_STR(INCSRCADDR), DCMD_STR(INCTRGADDR),
-			  DCMD_STR(FLOWSRC), DCMD_STR(FLOWTRG),
-			  DCMD_STR(STARTIRQEN), DCMD_STR(ENDIRQEN),
-			  DCMD_STR(ENDIAN), burst, width, dcmd & DCMD_LENGTH);
-	pos += seq_printf(s, "\tDSADR = %08x\n", DSADR(chan));
-	pos += seq_printf(s, "\tDTADR = %08x\n", DTADR(chan));
-	pos += seq_printf(s, "\tDDADR = %08x\n", DDADR(chan));
-	return pos;
-}
-
-static int dbg_show_state(struct seq_file *s, void *p)
-{
-	int pos = 0;
-
-	/* basic device status */
-	pos += seq_printf(s, "DMA engine status\n");
-	pos += seq_printf(s, "\tChannel number: %d\n", num_dma_channels);
-
-	return pos;
-}
-
-#define DBGFS_FUNC_DECL(name) \
-static int dbg_open_##name(struct inode *inode, struct file *file) \
-{ \
-	return single_open(file, dbg_show_##name, inode->i_private); \
-} \
-static const struct file_operations dbg_fops_##name = { \
-	.owner		= THIS_MODULE, \
-	.open		= dbg_open_##name, \
-	.llseek		= seq_lseek, \
-	.read		= seq_read, \
-	.release	= single_release, \
-}
-
-DBGFS_FUNC_DECL(state);
-DBGFS_FUNC_DECL(chan_state);
-DBGFS_FUNC_DECL(descriptors);
-DBGFS_FUNC_DECL(requester_chan);
-
-static struct dentry *pxa_dma_dbg_alloc_chan(int ch, struct dentry *chandir)
-{
-	char chan_name[11];
-	struct dentry *chan, *chan_state = NULL, *chan_descr = NULL;
-	struct dentry *chan_reqs = NULL;
-	void *dt;
-
-	scnprintf(chan_name, sizeof(chan_name), "%d", ch);
-	chan = debugfs_create_dir(chan_name, chandir);
-	dt = (void *)ch;
-
-	if (chan)
-		chan_state = debugfs_create_file("state", 0400, chan, dt,
-						 &dbg_fops_chan_state);
-	if (chan_state)
-		chan_descr = debugfs_create_file("descriptors", 0400, chan, dt,
-						 &dbg_fops_descriptors);
-	if (chan_descr)
-		chan_reqs = debugfs_create_file("requesters", 0400, chan, dt,
-						&dbg_fops_requester_chan);
-	if (!chan_reqs)
-		goto err_state;
-
-	return chan;
-
-err_state:
-	debugfs_remove_recursive(chan);
-	return NULL;
-}
-
-static void pxa_dma_init_debugfs(void)
-{
-	int i;
-	struct dentry *chandir;
-
-	dbgfs_root = debugfs_create_dir(DMA_DEBUG_NAME, NULL);
-	if (IS_ERR(dbgfs_root) || !dbgfs_root)
-		goto err_root;
-
-	dbgfs_state = debugfs_create_file("state", 0400, dbgfs_root, NULL,
-					  &dbg_fops_state);
-	if (!dbgfs_state)
-		goto err_state;
-
-	dbgfs_chan = kmalloc(sizeof(*dbgfs_state) * num_dma_channels,
-			     GFP_KERNEL);
-	if (!dbgfs_chan)
-		goto err_alloc;
-
-	chandir = debugfs_create_dir("channels", dbgfs_root);
-	if (!chandir)
-		goto err_chandir;
-
-	for (i = 0; i < num_dma_channels; i++) {
-		dbgfs_chan[i] = pxa_dma_dbg_alloc_chan(i, chandir);
-		if (!dbgfs_chan[i])
-			goto err_chans;
-	}
-
-	return;
-err_chans:
-err_chandir:
-	kfree(dbgfs_chan);
-err_alloc:
-err_state:
-	debugfs_remove_recursive(dbgfs_root);
-err_root:
-	pr_err("pxa_dma: debugfs is not available\n");
-}
-
-static void __exit pxa_dma_cleanup_debugfs(void)
-{
-	debugfs_remove_recursive(dbgfs_root);
-}
-#else
-static inline void pxa_dma_init_debugfs(void) {}
-static inline void pxa_dma_cleanup_debugfs(void) {}
-#endif
-
-int pxa_request_dma (char *name, pxa_dma_prio prio,
-			void (*irq_handler)(int, void *),
-			void *data)
-{
-	unsigned long flags;
-	int i, found = 0;
-
-	/* basic sanity checks */
-	if (!name || !irq_handler)
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	do {
-		/* try grabbing a DMA channel with the requested priority */
-		for (i = 0; i < num_dma_channels; i++) {
-			if ((dma_channels[i].prio == prio) &&
-			    !dma_channels[i].name) {
-				found = 1;
-				break;
-			}
-		}
-		/* if requested prio group is full, try a hier priority */
-	} while (!found && prio--);
-
-	if (found) {
-		DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-		dma_channels[i].name = name;
-		dma_channels[i].irq_handler = irq_handler;
-		dma_channels[i].data = data;
-	} else {
-		printk (KERN_WARNING "No more available DMA channels for %s\n", name);
-		i = -ENODEV;
-	}
-
-	local_irq_restore(flags);
-	return i;
-}
-EXPORT_SYMBOL(pxa_request_dma);
-
-void pxa_free_dma (int dma_ch)
-{
-	unsigned long flags;
-
-	if (!dma_channels[dma_ch].name) {
-		printk (KERN_CRIT
-			"%s: trying to free channel %d which is already freed\n",
-			__func__, dma_ch);
-		return;
-	}
-
-	local_irq_save(flags);
-	DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-	dma_channels[dma_ch].name = NULL;
-	local_irq_restore(flags);
-}
-EXPORT_SYMBOL(pxa_free_dma);
-
-static irqreturn_t dma_irq_handler(int irq, void *dev_id)
-{
-	int i, dint = DINT;
-	struct dma_channel *channel;
-
-	while (dint) {
-		i = __ffs(dint);
-		dint &= (dint - 1);
-		channel = &dma_channels[i];
-		if (channel->name && channel->irq_handler) {
-			channel->irq_handler(i, channel->data);
-		} else {
-			/*
-			 * IRQ for an unregistered DMA channel:
-			 * let's clear the interrupts and disable it.
-			 */
-			printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
-			DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-int __init pxa_init_dma(int irq, int num_ch)
-{
-	int i, ret;
-
-	dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);
-	if (dma_channels == NULL)
-		return -ENOMEM;
-
-	/* dma channel priorities on pxa2xx processors:
-	 * ch 0 - 3,  16 - 19  <--> (0) DMA_PRIO_HIGH
-	 * ch 4 - 7,  20 - 23  <--> (1) DMA_PRIO_MEDIUM
-	 * ch 8 - 15, 24 - 31  <--> (2) DMA_PRIO_LOW
-	 */
-	for (i = 0; i < num_ch; i++) {
-		DCSR(i) = 0;
-		dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
-		spin_lock_init(&dma_channels[i].lock);
-	}
-
-	ret = request_irq(irq, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
-	if (ret) {
-		printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-		kfree(dma_channels);
-		return ret;
-	}
-	num_dma_channels = num_ch;
-
-	pxa_dma_init_debugfs();
-
-	return 0;
-}
diff --git a/arch/arm/plat-pxa/include/plat/dma.h b/arch/arm/plat-pxa/include/plat/dma.h
deleted file mode 100644
index a7b91dc..0000000
--- a/arch/arm/plat-pxa/include/plat/dma.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef __PLAT_DMA_H
-#define __PLAT_DMA_H
-
-#define DMAC_REG(x)	(*((volatile u32 *)(DMAC_REGS_VIRT + (x))))
-
-#define DCSR(n)		DMAC_REG((n) << 2)
-#define DALGN		DMAC_REG(0x00a0)  /* DMA Alignment Register */
-#define DINT		DMAC_REG(0x00f0)  /* DMA Interrupt Register */
-#define DDADR(n)	DMAC_REG(0x0200 + ((n) << 4))
-#define DSADR(n)	DMAC_REG(0x0204 + ((n) << 4))
-#define DTADR(n)	DMAC_REG(0x0208 + ((n) << 4))
-#define DCMD(n)		DMAC_REG(0x020c + ((n) << 4))
-#define DRCMR(n)	DMAC_REG((((n) < 64) ? 0x0100 : 0x1100) + \
-				 (((n) & 0x3f) << 2))
-
-#define DCSR_RUN	(1 << 31)	/* Run Bit (read / write) */
-#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch (read / write) */
-#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable (read / write) */
-#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
-#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
-#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt (read / write) */
-#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt (read / write) */
-#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt (read / write) */
-
-#define DCSR_EORIRQEN	(1 << 28)       /* End of Receive Interrupt Enable (R/W) */
-#define DCSR_EORJMPEN	(1 << 27)       /* Jump to next descriptor on EOR */
-#define DCSR_EORSTOPEN	(1 << 26)       /* STOP on an EOR */
-#define DCSR_SETCMPST	(1 << 25)       /* Set Descriptor Compare Status */
-#define DCSR_CLRCMPST	(1 << 24)       /* Clear Descriptor Compare Status */
-#define DCSR_CMPST	(1 << 10)       /* The Descriptor Compare Status */
-#define DCSR_EORINTR	(1 << 9)        /* The end of Receive */
-
-#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid (read / write) */
-#define DRCMR_CHLNUM	0x1f		/* mask for Channel Number (read / write) */
-
-#define DDADR_DESCADDR	0xfffffff0	/* Address of next descriptor (mask) */
-#define DDADR_STOP	(1 << 0)	/* Stop (read / write) */
-
-#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address Increment Setting. */
-#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address Increment Setting. */
-#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source. */
-#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target. */
-#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt Enable */
-#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
-#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
-#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
-#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
-#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
-#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
-#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
-#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
-#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
-
-/*
- * Descriptor structure for PXA's DMA engine
- * Note: this structure must always be aligned to a 16-byte boundary.
- */
-
-typedef struct pxa_dma_desc {
-	volatile u32 ddadr;	/* Points to the next descriptor + flags */
-	volatile u32 dsadr;	/* DSADR value for the current transfer */
-	volatile u32 dtadr;	/* DTADR value for the current transfer */
-	volatile u32 dcmd;	/* DCMD value for the current transfer */
-} pxa_dma_desc;
-
-typedef enum {
-	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 1,
-	DMA_PRIO_LOW = 2
-} pxa_dma_prio;
-
-/*
- * DMA registration
- */
-
-int __init pxa_init_dma(int irq, int num_ch);
-
-int pxa_request_dma (char *name,
-			 pxa_dma_prio prio,
-			 void (*irq_handler)(int, void *),
-			 void *data);
-
-void pxa_free_dma (int dma_ch);
-
-#endif /* __PLAT_DMA_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 20/20] ARM: pxa: remove old DMA implementation
@ 2013-08-07 15:34   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 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

diff --git a/arch/arm/mach-pxa/include/mach/dma.h b/arch/arm/mach-pxa/include/mach/dma.h
deleted file mode 100644
index 5bd5589..0000000
--- a/arch/arm/mach-pxa/include/mach/dma.h
+++ /dev/null
@@ -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 */
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 1fc9419..826ef87 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -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
 
diff --git a/arch/arm/plat-pxa/dma.c b/arch/arm/plat-pxa/dma.c
deleted file mode 100644
index 79ef102..0000000
--- a/arch/arm/plat-pxa/dma.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- *  linux/arch/arm/plat-pxa/dma.c
- *
- *  PXA DMA registration and IRQ dispatching
- *
- *  Author:	Nicolas Pitre
- *  Created:	Nov 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.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/irq.h>
-#include <asm/memory.h>
-#include <mach/hardware.h>
-#include <mach/dma.h>
-
-#define DMA_DEBUG_NAME		"pxa_dma"
-#define DMA_MAX_REQUESTERS	64
-
-struct dma_channel {
-	char *name;
-	pxa_dma_prio prio;
-	void (*irq_handler)(int, void *);
-	void *data;
-	spinlock_t lock;
-};
-
-static struct dma_channel *dma_channels;
-static int num_dma_channels;
-
-/*
- * Debug fs
- */
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-#include <linux/seq_file.h>
-
-static struct dentry *dbgfs_root, *dbgfs_state, **dbgfs_chan;
-
-static int dbg_show_requester_chan(struct seq_file *s, void *p)
-{
-	int pos = 0;
-	int chan = (int)s->private;
-	int i;
-	u32 drcmr;
-
-	pos += seq_printf(s, "DMA channel %d requesters list :\n", chan);
-	for (i = 0; i < DMA_MAX_REQUESTERS; i++) {
-		drcmr = DRCMR(i);
-		if ((drcmr & DRCMR_CHLNUM) == chan)
-			pos += seq_printf(s, "\tRequester %d (MAPVLD=%d)\n", i,
-					  !!(drcmr & DRCMR_MAPVLD));
-	}
-	return pos;
-}
-
-static inline int dbg_burst_from_dcmd(u32 dcmd)
-{
-	int burst = (dcmd >> 16) & 0x3;
-
-	return burst ? 4 << burst : 0;
-}
-
-static int is_phys_valid(unsigned long addr)
-{
-	return pfn_valid(__phys_to_pfn(addr));
-}
-
-#define DCSR_STR(flag) (dcsr & DCSR_##flag ? #flag" " : "")
-#define DCMD_STR(flag) (dcmd & DCMD_##flag ? #flag" " : "")
-
-static int dbg_show_descriptors(struct seq_file *s, void *p)
-{
-	int pos = 0;
-	int chan = (int)s->private;
-	int i, max_show = 20, burst, width;
-	u32 dcmd;
-	unsigned long phys_desc;
-	struct pxa_dma_desc *desc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dma_channels[chan].lock, flags);
-	phys_desc = DDADR(chan);
-
-	pos += seq_printf(s, "DMA channel %d descriptors :\n", chan);
-	pos += seq_printf(s, "[%03d] First descriptor unknown\n", 0);
-	for (i = 1; i < max_show && is_phys_valid(phys_desc); i++) {
-		desc = phys_to_virt(phys_desc);
-		dcmd = desc->dcmd;
-		burst = dbg_burst_from_dcmd(dcmd);
-		width = (1 << ((dcmd >> 14) & 0x3)) >> 1;
-
-		pos += seq_printf(s, "[%03d] Desc at %08lx(virt %p)\n",
-				  i, phys_desc, desc);
-		pos += seq_printf(s, "\tDDADR = %08x\n", desc->ddadr);
-		pos += seq_printf(s, "\tDSADR = %08x\n", desc->dsadr);
-		pos += seq_printf(s, "\tDTADR = %08x\n", desc->dtadr);
-		pos += seq_printf(s, "\tDCMD  = %08x (%s%s%s%s%s%s%sburst=%d"
-				  " width=%d len=%d)\n",
-				  dcmd,
-				  DCMD_STR(INCSRCADDR), DCMD_STR(INCTRGADDR),
-				  DCMD_STR(FLOWSRC), DCMD_STR(FLOWTRG),
-				  DCMD_STR(STARTIRQEN), DCMD_STR(ENDIRQEN),
-				  DCMD_STR(ENDIAN), burst, width,
-				  dcmd & DCMD_LENGTH);
-		phys_desc = desc->ddadr;
-	}
-	if (i == max_show)
-		pos += seq_printf(s, "[%03d] Desc at %08lx ... max display reached\n",
-				  i, phys_desc);
-	else
-		pos += seq_printf(s, "[%03d] Desc at %08lx is %s\n",
-				  i, phys_desc, phys_desc == DDADR_STOP ?
-				  "DDADR_STOP" : "invalid");
-
-	spin_unlock_irqrestore(&dma_channels[chan].lock, flags);
-	return pos;
-}
-
-static int dbg_show_chan_state(struct seq_file *s, void *p)
-{
-	int pos = 0;
-	int chan = (int)s->private;
-	u32 dcsr, dcmd;
-	int burst, width;
-	static char *str_prio[] = { "high", "normal", "low" };
-
-	dcsr = DCSR(chan);
-	dcmd = DCMD(chan);
-	burst = dbg_burst_from_dcmd(dcmd);
-	width = (1 << ((dcmd >> 14) & 0x3)) >> 1;
-
-	pos += seq_printf(s, "DMA channel %d\n", chan);
-	pos += seq_printf(s, "\tPriority : %s\n",
-			  str_prio[dma_channels[chan].prio]);
-	pos += seq_printf(s, "\tUnaligned transfer bit: %s\n",
-			  DALGN & (1 << chan) ? "yes" : "no");
-	pos += seq_printf(s, "\tDCSR  = %08x (%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
-			  dcsr, DCSR_STR(RUN), DCSR_STR(NODESC),
-			  DCSR_STR(STOPIRQEN), DCSR_STR(EORIRQEN),
-			  DCSR_STR(EORJMPEN), DCSR_STR(EORSTOPEN),
-			  DCSR_STR(SETCMPST), DCSR_STR(CLRCMPST),
-			  DCSR_STR(CMPST), DCSR_STR(EORINTR), DCSR_STR(REQPEND),
-			  DCSR_STR(STOPSTATE), DCSR_STR(ENDINTR),
-			  DCSR_STR(STARTINTR), DCSR_STR(BUSERR));
-
-	pos += seq_printf(s, "\tDCMD  = %08x (%s%s%s%s%s%s%sburst=%d width=%d"
-			  " len=%d)\n",
-			  dcmd,
-			  DCMD_STR(INCSRCADDR), DCMD_STR(INCTRGADDR),
-			  DCMD_STR(FLOWSRC), DCMD_STR(FLOWTRG),
-			  DCMD_STR(STARTIRQEN), DCMD_STR(ENDIRQEN),
-			  DCMD_STR(ENDIAN), burst, width, dcmd & DCMD_LENGTH);
-	pos += seq_printf(s, "\tDSADR = %08x\n", DSADR(chan));
-	pos += seq_printf(s, "\tDTADR = %08x\n", DTADR(chan));
-	pos += seq_printf(s, "\tDDADR = %08x\n", DDADR(chan));
-	return pos;
-}
-
-static int dbg_show_state(struct seq_file *s, void *p)
-{
-	int pos = 0;
-
-	/* basic device status */
-	pos += seq_printf(s, "DMA engine status\n");
-	pos += seq_printf(s, "\tChannel number: %d\n", num_dma_channels);
-
-	return pos;
-}
-
-#define DBGFS_FUNC_DECL(name) \
-static int dbg_open_##name(struct inode *inode, struct file *file) \
-{ \
-	return single_open(file, dbg_show_##name, inode->i_private); \
-} \
-static const struct file_operations dbg_fops_##name = { \
-	.owner		= THIS_MODULE, \
-	.open		= dbg_open_##name, \
-	.llseek		= seq_lseek, \
-	.read		= seq_read, \
-	.release	= single_release, \
-}
-
-DBGFS_FUNC_DECL(state);
-DBGFS_FUNC_DECL(chan_state);
-DBGFS_FUNC_DECL(descriptors);
-DBGFS_FUNC_DECL(requester_chan);
-
-static struct dentry *pxa_dma_dbg_alloc_chan(int ch, struct dentry *chandir)
-{
-	char chan_name[11];
-	struct dentry *chan, *chan_state = NULL, *chan_descr = NULL;
-	struct dentry *chan_reqs = NULL;
-	void *dt;
-
-	scnprintf(chan_name, sizeof(chan_name), "%d", ch);
-	chan = debugfs_create_dir(chan_name, chandir);
-	dt = (void *)ch;
-
-	if (chan)
-		chan_state = debugfs_create_file("state", 0400, chan, dt,
-						 &dbg_fops_chan_state);
-	if (chan_state)
-		chan_descr = debugfs_create_file("descriptors", 0400, chan, dt,
-						 &dbg_fops_descriptors);
-	if (chan_descr)
-		chan_reqs = debugfs_create_file("requesters", 0400, chan, dt,
-						&dbg_fops_requester_chan);
-	if (!chan_reqs)
-		goto err_state;
-
-	return chan;
-
-err_state:
-	debugfs_remove_recursive(chan);
-	return NULL;
-}
-
-static void pxa_dma_init_debugfs(void)
-{
-	int i;
-	struct dentry *chandir;
-
-	dbgfs_root = debugfs_create_dir(DMA_DEBUG_NAME, NULL);
-	if (IS_ERR(dbgfs_root) || !dbgfs_root)
-		goto err_root;
-
-	dbgfs_state = debugfs_create_file("state", 0400, dbgfs_root, NULL,
-					  &dbg_fops_state);
-	if (!dbgfs_state)
-		goto err_state;
-
-	dbgfs_chan = kmalloc(sizeof(*dbgfs_state) * num_dma_channels,
-			     GFP_KERNEL);
-	if (!dbgfs_chan)
-		goto err_alloc;
-
-	chandir = debugfs_create_dir("channels", dbgfs_root);
-	if (!chandir)
-		goto err_chandir;
-
-	for (i = 0; i < num_dma_channels; i++) {
-		dbgfs_chan[i] = pxa_dma_dbg_alloc_chan(i, chandir);
-		if (!dbgfs_chan[i])
-			goto err_chans;
-	}
-
-	return;
-err_chans:
-err_chandir:
-	kfree(dbgfs_chan);
-err_alloc:
-err_state:
-	debugfs_remove_recursive(dbgfs_root);
-err_root:
-	pr_err("pxa_dma: debugfs is not available\n");
-}
-
-static void __exit pxa_dma_cleanup_debugfs(void)
-{
-	debugfs_remove_recursive(dbgfs_root);
-}
-#else
-static inline void pxa_dma_init_debugfs(void) {}
-static inline void pxa_dma_cleanup_debugfs(void) {}
-#endif
-
-int pxa_request_dma (char *name, pxa_dma_prio prio,
-			void (*irq_handler)(int, void *),
-			void *data)
-{
-	unsigned long flags;
-	int i, found = 0;
-
-	/* basic sanity checks */
-	if (!name || !irq_handler)
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	do {
-		/* try grabbing a DMA channel with the requested priority */
-		for (i = 0; i < num_dma_channels; i++) {
-			if ((dma_channels[i].prio == prio) &&
-			    !dma_channels[i].name) {
-				found = 1;
-				break;
-			}
-		}
-		/* if requested prio group is full, try a hier priority */
-	} while (!found && prio--);
-
-	if (found) {
-		DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-		dma_channels[i].name = name;
-		dma_channels[i].irq_handler = irq_handler;
-		dma_channels[i].data = data;
-	} else {
-		printk (KERN_WARNING "No more available DMA channels for %s\n", name);
-		i = -ENODEV;
-	}
-
-	local_irq_restore(flags);
-	return i;
-}
-EXPORT_SYMBOL(pxa_request_dma);
-
-void pxa_free_dma (int dma_ch)
-{
-	unsigned long flags;
-
-	if (!dma_channels[dma_ch].name) {
-		printk (KERN_CRIT
-			"%s: trying to free channel %d which is already freed\n",
-			__func__, dma_ch);
-		return;
-	}
-
-	local_irq_save(flags);
-	DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-	dma_channels[dma_ch].name = NULL;
-	local_irq_restore(flags);
-}
-EXPORT_SYMBOL(pxa_free_dma);
-
-static irqreturn_t dma_irq_handler(int irq, void *dev_id)
-{
-	int i, dint = DINT;
-	struct dma_channel *channel;
-
-	while (dint) {
-		i = __ffs(dint);
-		dint &= (dint - 1);
-		channel = &dma_channels[i];
-		if (channel->name && channel->irq_handler) {
-			channel->irq_handler(i, channel->data);
-		} else {
-			/*
-			 * IRQ for an unregistered DMA channel:
-			 * let's clear the interrupts and disable it.
-			 */
-			printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
-			DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-int __init pxa_init_dma(int irq, int num_ch)
-{
-	int i, ret;
-
-	dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);
-	if (dma_channels == NULL)
-		return -ENOMEM;
-
-	/* dma channel priorities on pxa2xx processors:
-	 * ch 0 - 3,  16 - 19  <--> (0) DMA_PRIO_HIGH
-	 * ch 4 - 7,  20 - 23  <--> (1) DMA_PRIO_MEDIUM
-	 * ch 8 - 15, 24 - 31  <--> (2) DMA_PRIO_LOW
-	 */
-	for (i = 0; i < num_ch; i++) {
-		DCSR(i) = 0;
-		dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
-		spin_lock_init(&dma_channels[i].lock);
-	}
-
-	ret = request_irq(irq, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
-	if (ret) {
-		printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-		kfree(dma_channels);
-		return ret;
-	}
-	num_dma_channels = num_ch;
-
-	pxa_dma_init_debugfs();
-
-	return 0;
-}
diff --git a/arch/arm/plat-pxa/include/plat/dma.h b/arch/arm/plat-pxa/include/plat/dma.h
deleted file mode 100644
index a7b91dc..0000000
--- a/arch/arm/plat-pxa/include/plat/dma.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef __PLAT_DMA_H
-#define __PLAT_DMA_H
-
-#define DMAC_REG(x)	(*((volatile u32 *)(DMAC_REGS_VIRT + (x))))
-
-#define DCSR(n)		DMAC_REG((n) << 2)
-#define DALGN		DMAC_REG(0x00a0)  /* DMA Alignment Register */
-#define DINT		DMAC_REG(0x00f0)  /* DMA Interrupt Register */
-#define DDADR(n)	DMAC_REG(0x0200 + ((n) << 4))
-#define DSADR(n)	DMAC_REG(0x0204 + ((n) << 4))
-#define DTADR(n)	DMAC_REG(0x0208 + ((n) << 4))
-#define DCMD(n)		DMAC_REG(0x020c + ((n) << 4))
-#define DRCMR(n)	DMAC_REG((((n) < 64) ? 0x0100 : 0x1100) + \
-				 (((n) & 0x3f) << 2))
-
-#define DCSR_RUN	(1 << 31)	/* Run Bit (read / write) */
-#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch (read / write) */
-#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable (read / write) */
-#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
-#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
-#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt (read / write) */
-#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt (read / write) */
-#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt (read / write) */
-
-#define DCSR_EORIRQEN	(1 << 28)       /* End of Receive Interrupt Enable (R/W) */
-#define DCSR_EORJMPEN	(1 << 27)       /* Jump to next descriptor on EOR */
-#define DCSR_EORSTOPEN	(1 << 26)       /* STOP on an EOR */
-#define DCSR_SETCMPST	(1 << 25)       /* Set Descriptor Compare Status */
-#define DCSR_CLRCMPST	(1 << 24)       /* Clear Descriptor Compare Status */
-#define DCSR_CMPST	(1 << 10)       /* The Descriptor Compare Status */
-#define DCSR_EORINTR	(1 << 9)        /* The end of Receive */
-
-#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid (read / write) */
-#define DRCMR_CHLNUM	0x1f		/* mask for Channel Number (read / write) */
-
-#define DDADR_DESCADDR	0xfffffff0	/* Address of next descriptor (mask) */
-#define DDADR_STOP	(1 << 0)	/* Stop (read / write) */
-
-#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address Increment Setting. */
-#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address Increment Setting. */
-#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source. */
-#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target. */
-#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt Enable */
-#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
-#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
-#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
-#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
-#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
-#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
-#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
-#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
-#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
-
-/*
- * Descriptor structure for PXA's DMA engine
- * Note: this structure must always be aligned to a 16-byte boundary.
- */
-
-typedef struct pxa_dma_desc {
-	volatile u32 ddadr;	/* Points to the next descriptor + flags */
-	volatile u32 dsadr;	/* DSADR value for the current transfer */
-	volatile u32 dtadr;	/* DTADR value for the current transfer */
-	volatile u32 dcmd;	/* DCMD value for the current transfer */
-} pxa_dma_desc;
-
-typedef enum {
-	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 1,
-	DMA_PRIO_LOW = 2
-} pxa_dma_prio;
-
-/*
- * DMA registration
- */
-
-int __init pxa_init_dma(int irq, int num_ch);
-
-int pxa_request_dma (char *name,
-			 pxa_dma_prio prio,
-			 void (*irq_handler)(int, void *),
-			 void *data);
-
-void pxa_free_dma (int dma_ch);
-
-#endif /* __PLAT_DMA_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* Re: [PATCH 04/20] ARM: pxa: ssp: add DT bindings
  2013-08-07 15:33   ` Daniel Mack
@ 2013-08-07 15:54     ` Arnd Bergmann
  -1 siblings, 0 replies; 126+ messages in thread
From: Arnd Bergmann @ 2013-08-07 15:54 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, broonie, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On Wednesday 07 August 2013, Daniel Mack wrote:
> +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
> +
> +

It seems you are missing the 'dmas' properties here and that two of them
("rx" and "tx") are required by the code.

	Arnd

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 04/20] ARM: pxa: ssp: add DT bindings
@ 2013-08-07 15:54     ` Arnd Bergmann
  0 siblings, 0 replies; 126+ messages in thread
From: Arnd Bergmann @ 2013-08-07 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 07 August 2013, Daniel Mack wrote:
> +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
> +
> +

It seems you are missing the 'dmas' properties here and that two of them
("rx" and "tx") are required by the code.

	Arnd

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits
  2013-08-07 15:33   ` Daniel Mack
@ 2013-08-07 15:55     ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 15:55 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 423 bytes --]

On Wed, Aug 07, 2013 at 05:33:56PM +0200, Daniel Mack wrote:
> 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 <broonie@linaro.org>

though this will have some trivial merge issues until the merge window
they shouldn't be a problem.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits
@ 2013-08-07 15:55     ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 15:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 05:33:56PM +0200, Daniel Mack wrote:
> 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 <broonie@linaro.org>

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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 14/20] ASoC: pxa: use snd_dmaengine_dai_dma_data
  2013-08-07 15:34   ` Daniel Mack
@ 2013-08-07 15:57     ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 15:57 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 470 bytes --]

On Wed, Aug 07, 2013 at 05:34:03PM +0200, Daniel Mack wrote:
> Use 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.

Acked-by: Mark Brown <broonie@linaro.org>

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 14/20] ASoC: pxa: use snd_dmaengine_dai_dma_data
@ 2013-08-07 15:57     ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 15:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 05:34:03PM +0200, Daniel Mack wrote:
> Use 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.

Acked-by: Mark Brown <broonie@linaro.org>
-------------- 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 15/20] ASoC: pxa: pxa-ssp: set dma filter data from startup hook
  2013-08-07 15:34   ` Daniel Mack
@ 2013-08-07 15:58     ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 15:58 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 220 bytes --]

On Wed, Aug 07, 2013 at 05:34:04PM +0200, Daniel Mack wrote:
> With the new dmaengine implementation, the filter_data parameter has
> to be set earlier, from pxa_ssp_startup().

Acked-by: Mark Brown <broonie@linaro.org>

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 15/20] ASoC: pxa: pxa-ssp: set dma filter data from startup hook
@ 2013-08-07 15:58     ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 15:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 05:34:04PM +0200, Daniel Mack wrote:
> With the new dmaengine implementation, the filter_data parameter has
> to be set earlier, from pxa_ssp_startup().

Acked-by: Mark Brown <broonie@linaro.org>
-------------- 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 09/20] ata: pdata_pxa: migrate over to dmaengine usage
  2013-08-07 15:33   ` Daniel Mack
@ 2013-08-07 15:59     ` Arnd Bergmann
  -1 siblings, 0 replies; 126+ messages in thread
From: Arnd Bergmann @ 2013-08-07 15:59 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, broonie, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On Wednesday 07 August 2013, Daniel Mack wrote:
> +       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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 09/20] ata: pdata_pxa: migrate over to dmaengine usage
@ 2013-08-07 15:59     ` Arnd Bergmann
  0 siblings, 0 replies; 126+ messages in thread
From: Arnd Bergmann @ 2013-08-07 15:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 07 August 2013, Daniel Mack wrote:
> +       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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits
  2013-08-07 15:55     ` Mark Brown
@ 2013-08-07 15:59       ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:59 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 07.08.2013 17:55, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 05:33:56PM +0200, Daniel Mack wrote:
>> 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 <broonie@linaro.org>

Thanks.

> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits
@ 2013-08-07 15:59       ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 15:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 07.08.2013 17:55, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 05:33:56PM +0200, Daniel Mack wrote:
>> 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 <broonie@linaro.org>

Thanks.

> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 16/20] ASoC: pxa: add DT bindings for pxa2xx-pcm
  2013-08-07 15:34   ` Daniel Mack
@ 2013-08-07 16:06     ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:06 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 396 bytes --]

On Wed, Aug 07, 2013 at 05:34:05PM +0200, Daniel Mack wrote:
> 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.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 16/20] ASoC: pxa: add DT bindings for pxa2xx-pcm
@ 2013-08-07 16:06     ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 05:34:05PM +0200, Daniel Mack wrote:
> 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-07 15:34   ` Daniel Mack
@ 2013-08-07 16:07     ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:07 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 446 bytes --]

On Wed, Aug 07, 2013 at 05:34:06PM +0200, Daniel Mack wrote:
> 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?

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-07 16:07     ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 05:34:06PM +0200, Daniel Mack wrote:
> 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-07 16:08   ` Arnd Bergmann
  -1 siblings, 0 replies; 126+ messages in thread
From: Arnd Bergmann @ 2013-08-07 16:08 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, broonie, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On Wednesday 07 August 2013, Daniel Mack wrote:
> 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.

Very nice series! I just looked over these and only found a few minor details
that could be improved.

	Arnd

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-07 16:08   ` Arnd Bergmann
  0 siblings, 0 replies; 126+ messages in thread
From: Arnd Bergmann @ 2013-08-07 16:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 07 August 2013, Daniel Mack wrote:
> 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.

Very nice series! I just looked over these and only found a few minor details
that could be improved.

	Arnd

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-07 16:07     ` Mark Brown
@ 2013-08-07 16:10       ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 16:10 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 07.08.2013 18:07, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 05:34:06PM +0200, Daniel Mack wrote:
>> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-07 16:10       ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-07 16:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 07.08.2013 18:07, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 05:34:06PM +0200, Daniel Mack wrote:
>> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-07 16:10       ` Daniel Mack
@ 2013-08-07 16:32         ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:32 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 358 bytes --]

On Wed, Aug 07, 2013 at 06:10:55PM +0200, Daniel Mack wrote:
> On 07.08.2013 18:07, Mark Brown wrote:

> > 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.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-07 16:32         ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 06:10:55PM +0200, Daniel Mack wrote:
> On 07.08.2013 18:07, Mark Brown wrote:

> > 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
  2013-08-07 15:34   ` Daniel Mack
@ 2013-08-07 16:40     ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:40 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 1139 bytes --]

On Wed, Aug 07, 2013 at 05:34:02PM +0200, Daniel Mack wrote:
> 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 <zonque@gmail.com>
> ---
>  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...

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
@ 2013-08-07 16:40     ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 05:34:02PM +0200, Daniel Mack wrote:
> 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 <zonque@gmail.com>
> ---
>  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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits
  2013-08-07 15:59       ` Daniel Mack
@ 2013-08-07 16:41         ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:41 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 331 bytes --]

On Wed, Aug 07, 2013 at 05:59:29PM +0200, Daniel Mack wrote:
> On 07.08.2013 17:55, Mark Brown wrote:

> > 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!

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits
@ 2013-08-07 16:41         ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-07 16:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 05:59:29PM +0200, Daniel Mack wrote:
> On 07.08.2013 17:55, Mark Brown wrote:

> > 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
  2013-08-07 15:33   ` Daniel Mack
@ 2013-08-07 17:46     ` Ezequiel Garcia
  -1 siblings, 0 replies; 126+ messages in thread
From: Ezequiel Garcia @ 2013-08-07 17:46 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, rmk+kernel, devicetree, samuel,
	arnd, broonie, Zhangfei Gao, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

Hi Daniel,

On Wed, Aug 07, 2013 at 05:33:50PM +0200, Daniel Mack wrote:
> From: Zhangfei Gao <zhangfei.gao@marvell.com>
> 
> [zonque@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]
> 

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.
-- 
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
@ 2013-08-07 17:46     ` Ezequiel Garcia
  0 siblings, 0 replies; 126+ messages in thread
From: Ezequiel Garcia @ 2013-08-07 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Daniel,

On Wed, Aug 07, 2013 at 05:33:50PM +0200, Daniel Mack wrote:
> From: Zhangfei Gao <zhangfei.gao@marvell.com>
> 
> [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]
> 

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.
-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
  2013-08-07 17:46     ` Ezequiel Garcia
@ 2013-08-08  6:42       ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  6:42 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, rmk+kernel, devicetree, samuel,
	arnd, broonie, Zhangfei Gao, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 07.08.2013 19:46, Ezequiel Garcia wrote:
> Hi Daniel,
> 
> On Wed, Aug 07, 2013 at 05:33:50PM +0200, Daniel Mack wrote:
>> From: Zhangfei Gao <zhangfei.gao@marvell.com>
>>
>> [zonque@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]
>>
> 
> 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.

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
@ 2013-08-08  6:42       ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  6:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 07.08.2013 19:46, Ezequiel Garcia wrote:
> Hi Daniel,
> 
> On Wed, Aug 07, 2013 at 05:33:50PM +0200, Daniel Mack wrote:
>> From: Zhangfei Gao <zhangfei.gao@marvell.com>
>>
>> [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]
>>
> 
> 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.

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev
  2013-08-07 15:33   ` Daniel Mack
@ 2013-08-08  7:32     ` Brian Norris
  -1 siblings, 0 replies; 126+ messages in thread
From: Brian Norris @ 2013-08-08  7:32 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	linux-arm-kernel, thomas.petazzoni, eric.y.miao, gregkh, davem,
	sachin.kamat, kernel, djbw, g.liakhovetski

On Wed, Aug 07, 2013 at 05:33:52PM +0200, Daniel Mack wrote:
> No functional change, just a cosmetic cleanup.
> 
> Signed-off-by: Daniel Mack <zonque@gmail.com>
> ---
> --- a/arch/arm/plat-pxa/ssp.c
> +++ b/arch/arm/plat-pxa/ssp.c
> @@ -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!

>  		return -ENOMEM;
>  	}
>  	ssp->pdev = pdev;
>  
...

Brian

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev
@ 2013-08-08  7:32     ` Brian Norris
  0 siblings, 0 replies; 126+ messages in thread
From: Brian Norris @ 2013-08-08  7:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 07, 2013 at 05:33:52PM +0200, Daniel Mack wrote:
> No functional change, just a cosmetic cleanup.
> 
> Signed-off-by: Daniel Mack <zonque@gmail.com>
> ---
> --- a/arch/arm/plat-pxa/ssp.c
> +++ b/arch/arm/plat-pxa/ssp.c
> @@ -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!

>  		return -ENOMEM;
>  	}
>  	ssp->pdev = pdev;
>  
...

Brian

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev
  2013-08-08  7:32     ` Brian Norris
@ 2013-08-08  7:52       ` Artem Bityutskiy
  -1 siblings, 0 replies; 126+ messages in thread
From: Artem Bityutskiy @ 2013-08-08  7:52 UTC (permalink / raw)
  To: Brian Norris
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	g.liakhovetski, devicetree, samuel, arnd, broonie,
	mika.westerberg, linux-arm-kernel, thomas.petazzoni, eric.y.miao,
	gregkh, Daniel Mack, sachin.kamat, kernel, djbw, davem

On Thu, 2013-08-08 at 00:32 -0700, Brian Norris wrote:
> On Wed, Aug 07, 2013 at 05:33:52PM +0200, Daniel Mack wrote:
> > No functional change, just a cosmetic cleanup.
> > 
> > Signed-off-by: Daniel Mack <zonque@gmail.com>
> > ---
> > --- a/arch/arm/plat-pxa/ssp.c
> > +++ b/arch/arm/plat-pxa/ssp.c
> > @@ -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!

I think only to former is the right option.

-- 
Best Regards,
Artem Bityutskiy

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev
@ 2013-08-08  7:52       ` Artem Bityutskiy
  0 siblings, 0 replies; 126+ messages in thread
From: Artem Bityutskiy @ 2013-08-08  7:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2013-08-08 at 00:32 -0700, Brian Norris wrote:
> On Wed, Aug 07, 2013 at 05:33:52PM +0200, Daniel Mack wrote:
> > No functional change, just a cosmetic cleanup.
> > 
> > Signed-off-by: Daniel Mack <zonque@gmail.com>
> > ---
> > --- a/arch/arm/plat-pxa/ssp.c
> > +++ b/arch/arm/plat-pxa/ssp.c
> > @@ -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!

I think only to former is the right option.

-- 
Best Regards,
Artem Bityutskiy

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-07 16:32         ` Mark Brown
@ 2013-08-08  8:18           ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  8:18 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 07.08.2013 18:32, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 06:10:55PM +0200, Daniel Mack wrote:
>> On 07.08.2013 18:07, Mark Brown wrote:
> 
>>> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08  8:18           ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  8:18 UTC (permalink / raw)
  To: linux-arm-kernel

On 07.08.2013 18:32, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 06:10:55PM +0200, Daniel Mack wrote:
>> On 07.08.2013 18:07, Mark Brown wrote:
> 
>>> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev
  2013-08-08  7:52       ` Artem Bityutskiy
@ 2013-08-08  8:20         ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  8:20 UTC (permalink / raw)
  To: dedekind1
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	linux-arm-kernel, thomas.petazzoni, eric.y.miao, gregkh,
	g.liakhovetski, sachin.kamat, kernel, djbw, Brian Norris, davem

On 08.08.2013 09:52, Artem Bityutskiy wrote:
> On Thu, 2013-08-08 at 00:32 -0700, Brian Norris wrote:
>> On Wed, Aug 07, 2013 at 05:33:52PM +0200, Daniel Mack wrote:
>>> No functional change, just a cosmetic cleanup.
>>>
>>> Signed-off-by: Daniel Mack <zonque@gmail.com>
>>> ---
>>> --- a/arch/arm/plat-pxa/ssp.c
>>> +++ b/arch/arm/plat-pxa/ssp.c
>>> @@ -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!
> 
> I think only to former is the right option.
> 

Ok, I've added a patch for this to my series.


Thanks!

Daniel

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev
@ 2013-08-08  8:20         ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  8:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 08.08.2013 09:52, Artem Bityutskiy wrote:
> On Thu, 2013-08-08 at 00:32 -0700, Brian Norris wrote:
>> On Wed, Aug 07, 2013 at 05:33:52PM +0200, Daniel Mack wrote:
>>> No functional change, just a cosmetic cleanup.
>>>
>>> Signed-off-by: Daniel Mack <zonque@gmail.com>
>>> ---
>>> --- a/arch/arm/plat-pxa/ssp.c
>>> +++ b/arch/arm/plat-pxa/ssp.c
>>> @@ -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!
> 
> I think only to former is the right option.
> 

Ok, I've added a patch for this to my series.


Thanks!

Daniel

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-08  8:18           ` Daniel Mack
@ 2013-08-08  8:44             ` Lars-Peter Clausen
  -1 siblings, 0 replies; 126+ messages in thread
From: Lars-Peter Clausen @ 2013-08-08  8:44 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, nico,
	vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel, devicetree,
	samuel, arnd, Mark Brown, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 08/08/2013 10:18 AM, Daniel Mack wrote:
> On 07.08.2013 18:32, Mark Brown wrote:
>> On Wed, Aug 07, 2013 at 06:10:55PM +0200, Daniel Mack wrote:
>>> On 07.08.2013 18:07, Mark Brown wrote:
>>
>>>> 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.

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08  8:44             ` Lars-Peter Clausen
  0 siblings, 0 replies; 126+ messages in thread
From: Lars-Peter Clausen @ 2013-08-08  8:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 10:18 AM, Daniel Mack wrote:
> On 07.08.2013 18:32, Mark Brown wrote:
>> On Wed, Aug 07, 2013 at 06:10:55PM +0200, Daniel Mack wrote:
>>> On 07.08.2013 18:07, Mark Brown wrote:
>>
>>>> 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.

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-08  8:44             ` Lars-Peter Clausen
@ 2013-08-08  9:03               ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  9:03 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, nico,
	vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel, devicetree,
	samuel, arnd, Mark Brown, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 08.08.2013 10:44, Lars-Peter Clausen wrote:
> On 08/08/2013 10:18 AM, Daniel Mack wrote:

>> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08  9:03               ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  9:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 08.08.2013 10:44, Lars-Peter Clausen wrote:
> On 08/08/2013 10:18 AM, Daniel Mack wrote:

>> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-08  9:03               ` Daniel Mack
@ 2013-08-08  9:36                 ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-08  9:36 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4,
	Lars-Peter Clausen, nico, vinod.koul, marek.vasut,
	ezequiel.garcia, rmk+kernel, devicetree, samuel, arnd,
	mika.westerberg, linux-arm-kernel, thomas.petazzoni, eric.y.miao,
	gregkh, g.liakhovetski, sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 757 bytes --]

On Thu, Aug 08, 2013 at 11:03:44AM +0200, Daniel Mack wrote:
> On 08.08.2013 10:44, Lars-Peter Clausen wrote:

> > 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.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08  9:36                 ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-08  9:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 08, 2013 at 11:03:44AM +0200, Daniel Mack wrote:
> On 08.08.2013 10:44, Lars-Peter Clausen wrote:

> > 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
  2013-08-07 16:40     ` Mark Brown
@ 2013-08-08  9:39       ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  9:39 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 07.08.2013 18:40, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 05:34:02PM +0200, Daniel Mack wrote:
>> 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 <zonque@gmail.com>
>> ---
>>  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.

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
@ 2013-08-08  9:39       ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  9:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 07.08.2013 18:40, Mark Brown wrote:
> On Wed, Aug 07, 2013 at 05:34:02PM +0200, Daniel Mack wrote:
>> 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 <zonque@gmail.com>
>> ---
>>  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.

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-08  9:36                 ` Mark Brown
@ 2013-08-08  9:43                   ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  9:43 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4,
	Lars-Peter Clausen, nico, vinod.koul, marek.vasut,
	ezequiel.garcia, rmk+kernel, devicetree, samuel, arnd,
	mika.westerberg, linux-arm-kernel, thomas.petazzoni, eric.y.miao,
	gregkh, g.liakhovetski, sachin.kamat, kernel, djbw, davem

On 08.08.2013 11:36, Mark Brown wrote:
> On Thu, Aug 08, 2013 at 11:03:44AM +0200, Daniel Mack wrote:
>> On 08.08.2013 10:44, Lars-Peter Clausen wrote:
> 
>>> 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.

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08  9:43                   ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08  9:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 08.08.2013 11:36, Mark Brown wrote:
> On Thu, Aug 08, 2013 at 11:03:44AM +0200, Daniel Mack wrote:
>> On 08.08.2013 10:44, Lars-Peter Clausen wrote:
> 
>>> 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.

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
  2013-08-08  6:42       ` Daniel Mack
@ 2013-08-08 10:12         ` Ezequiel Garcia
  -1 siblings, 0 replies; 126+ messages in thread
From: Ezequiel Garcia @ 2013-08-08 10:12 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, rmk+kernel, devicetree, samuel,
	arnd, broonie, Zhangfei Gao, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On Thu, Aug 08, 2013 at 08:42:41AM +0200, Daniel Mack wrote:
> On 07.08.2013 19:46, Ezequiel Garcia wrote:
> > Hi Daniel,
> > 
> > On Wed, Aug 07, 2013 at 05:33:50PM +0200, Daniel Mack wrote:
> >> From: Zhangfei Gao <zhangfei.gao@marvell.com>
> >>
> >> [zonque@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]
> >>
> > 
> > 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.
> 
> 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.
> 

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.

-- 
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
@ 2013-08-08 10:12         ` Ezequiel Garcia
  0 siblings, 0 replies; 126+ messages in thread
From: Ezequiel Garcia @ 2013-08-08 10:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 08, 2013 at 08:42:41AM +0200, Daniel Mack wrote:
> On 07.08.2013 19:46, Ezequiel Garcia wrote:
> > Hi Daniel,
> > 
> > On Wed, Aug 07, 2013 at 05:33:50PM +0200, Daniel Mack wrote:
> >> From: Zhangfei Gao <zhangfei.gao@marvell.com>
> >>
> >> [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]
> >>
> > 
> > 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.
> 
> 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.
> 

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.

-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
  2013-08-08 10:12         ` Ezequiel Garcia
@ 2013-08-08 10:14           ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08 10:14 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, rmk+kernel, devicetree, samuel,
	arnd, broonie, Zhangfei Gao, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 08.08.2013 12:12, Ezequiel Garcia wrote:
> On Thu, Aug 08, 2013 at 08:42:41AM +0200, Daniel Mack wrote:
>> On 07.08.2013 19:46, Ezequiel Garcia wrote:
>>> Hi Daniel,
>>>
>>> On Wed, Aug 07, 2013 at 05:33:50PM +0200, Daniel Mack wrote:
>>>> From: Zhangfei Gao <zhangfei.gao@marvell.com>
>>>>
>>>> [zonque@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]
>>>>
>>>
>>> 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.
>>
>> 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.
>>
> 
> 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?

> I can take care of that if this patchset hits mainline before
> we have something really usable for Armada 370/XP NAND.

Ok :)


Daniel

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine
@ 2013-08-08 10:14           ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08 10:14 UTC (permalink / raw)
  To: linux-arm-kernel

On 08.08.2013 12:12, Ezequiel Garcia wrote:
> On Thu, Aug 08, 2013 at 08:42:41AM +0200, Daniel Mack wrote:
>> On 07.08.2013 19:46, Ezequiel Garcia wrote:
>>> Hi Daniel,
>>>
>>> On Wed, Aug 07, 2013 at 05:33:50PM +0200, Daniel Mack wrote:
>>>> From: Zhangfei Gao <zhangfei.gao@marvell.com>
>>>>
>>>> [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]
>>>>
>>>
>>> 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.
>>
>> 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.
>>
> 
> 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?

> I can take care of that if this patchset hits mainline before
> we have something really usable for Armada 370/XP NAND.

Ok :)


Daniel

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-08  9:36                 ` Mark Brown
@ 2013-08-08 10:25                   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 126+ messages in thread
From: Russell King - ARM Linux @ 2013-08-08 10:25 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4,
	Lars-Peter Clausen, nico, vinod.koul, marek.vasut,
	ezequiel.garcia, g.liakhovetski, devicetree, samuel, arnd,
	mika.westerberg, linux-arm-kernel, thomas.petazzoni, eric.y.miao,
	gregkh, Daniel Mack, sachin.kamat, kernel, djbw, davem

On Thu, Aug 08, 2013 at 10:36:28AM +0100, Mark Brown wrote:
> On Thu, Aug 08, 2013 at 11:03:44AM +0200, Daniel Mack wrote:
> > On 08.08.2013 10:44, Lars-Peter Clausen wrote:
> 
> > > 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.

... which gets you a warning from modern kconfig tools.

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08 10:25                   ` Russell King - ARM Linux
  0 siblings, 0 replies; 126+ messages in thread
From: Russell King - ARM Linux @ 2013-08-08 10:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 08, 2013 at 10:36:28AM +0100, Mark Brown wrote:
> On Thu, Aug 08, 2013 at 11:03:44AM +0200, Daniel Mack wrote:
> > On 08.08.2013 10:44, Lars-Peter Clausen wrote:
> 
> > > 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.

... which gets you a warning from modern kconfig tools.

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-08  9:43                   ` Daniel Mack
@ 2013-08-08 10:35                     ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-08 10:35 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4,
	Lars-Peter Clausen, nico, vinod.koul, marek.vasut,
	ezequiel.garcia, rmk+kernel, devicetree, samuel, arnd,
	mika.westerberg, linux-arm-kernel, thomas.petazzoni, eric.y.miao,
	gregkh, g.liakhovetski, sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 505 bytes --]

On Thu, Aug 08, 2013 at 11:43:24AM +0200, Daniel Mack wrote:

> 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.

Ah, that'd cause problems.

> 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.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08 10:35                     ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-08 10:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 08, 2013 at 11:43:24AM +0200, Daniel Mack wrote:

> 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.

Ah, that'd cause problems.

> 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-08 10:35                     ` Mark Brown
@ 2013-08-08 10:39                       ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08 10:39 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4,
	Lars-Peter Clausen, nico, vinod.koul, marek.vasut,
	ezequiel.garcia, rmk+kernel, devicetree, samuel, arnd,
	mika.westerberg, linux-arm-kernel, thomas.petazzoni, eric.y.miao,
	gregkh, g.liakhovetski, sachin.kamat, kernel, djbw, davem

On 08.08.2013 12:35, Mark Brown wrote:
> On Thu, Aug 08, 2013 at 11:43:24AM +0200, Daniel Mack wrote:
> 
>> 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.
> 
> Ah, that'd cause problems.
> 
>> 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?

  https://github.com/zonque/linux/commit/77eaba6ed

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08 10:39                       ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-08 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 08.08.2013 12:35, Mark Brown wrote:
> On Thu, Aug 08, 2013 at 11:43:24AM +0200, Daniel Mack wrote:
> 
>> 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.
> 
> Ah, that'd cause problems.
> 
>> 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?

  https://github.com/zonque/linux/commit/77eaba6ed

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
  2013-08-08 10:39                       ` Daniel Mack
@ 2013-08-08 11:03                         ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-08 11:03 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4,
	Lars-Peter Clausen, nico, vinod.koul, marek.vasut,
	ezequiel.garcia, rmk+kernel, devicetree, samuel, arnd,
	mika.westerberg, linux-arm-kernel, thomas.petazzoni, eric.y.miao,
	gregkh, g.liakhovetski, sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 227 bytes --]

On Thu, Aug 08, 2013 at 12:39:35PM +0200, Daniel Mack wrote:

> So you'd be unhappy with this?

>   https://github.com/zonque/linux/commit/77eaba6ed

No, that seems fine.  But please just post patches instead of sending
links.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm
@ 2013-08-08 11:03                         ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-08 11:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 08, 2013 at 12:39:35PM +0200, Daniel Mack wrote:

> So you'd be unhappy with this?

>   https://github.com/zonque/linux/commit/77eaba6ed

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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
  2013-08-08  9:39       ` Daniel Mack
@ 2013-08-08 13:20         ` Mark Brown
  -1 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-08 13:20 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

[-- Attachment #1: Type: text/plain, Size: 731 bytes --]

On Thu, Aug 08, 2013 at 11:39:59AM +0200, Daniel Mack wrote:

> 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.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
@ 2013-08-08 13:20         ` Mark Brown
  0 siblings, 0 replies; 126+ messages in thread
From: Mark Brown @ 2013-08-08 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 08, 2013 at 11:39:59AM +0200, Daniel Mack wrote:

> 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
  2013-08-08 13:20         ` Mark Brown
@ 2013-08-09 13:03           ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-09 13:03 UTC (permalink / raw)
  To: Mark Brown
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, mika.westerberg, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, gregkh, g.liakhovetski,
	sachin.kamat, kernel, djbw, davem

On 08.08.2013 15:20, Mark Brown wrote:
> On Thu, Aug 08, 2013 at 11:39:59AM +0200, Daniel Mack wrote:
> 
>> 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.
> 

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings
@ 2013-08-09 13:03           ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-09 13:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 08.08.2013 15:20, Mark Brown wrote:
> On Thu, Aug 08, 2013 at 11:39:59AM +0200, Daniel Mack wrote:
> 
>> 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.
> 

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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
  2013-08-07 15:33 ` Daniel Mack
@ 2013-08-09 22:50   ` Robert Jarzmik
  -1 siblings, 0 replies; 126+ messages in thread
From: Robert Jarzmik @ 2013-08-09 22:50 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	linux-arm-kernel, thomas.petazzoni, eric.y.miao, gregkh, davem,
	sachin.kamat, kernel, djbw, g.liakhovetski

Daniel Mack <zonque@gmail.com> writes:

>  * 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.

-- 
Robert

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-09 22:50   ` Robert Jarzmik
  0 siblings, 0 replies; 126+ messages in thread
From: Robert Jarzmik @ 2013-08-09 22:50 UTC (permalink / raw)
  To: linux-arm-kernel

Daniel Mack <zonque@gmail.com> writes:

>  * 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.

-- 
Robert

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
  2013-08-09 22:50   ` Robert Jarzmik
@ 2013-08-10 10:56     ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-10 10:56 UTC (permalink / raw)
  To: Robert Jarzmik
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	linux-arm-kernel, thomas.petazzoni, eric.y.miao, gregkh, davem,
	sachin.kamat, kernel, djbw, g.liakhovetski

[-- Attachment #1: Type: text/plain, Size: 2501 bytes --]

Hi Robert,

On 10.08.2013 00:50, Robert Jarzmik wrote:
> Daniel Mack <zonque@gmail.com> writes:
> 
>>  * 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.

> 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.

> 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.

Yes, Vinod and and Dan are certainly the best ones to comment on that I
think.

> 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.

> 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?

> 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


[-- Attachment #2: 0001-drivers-media-platform-soc_camera-pxa_camera.c-DMAEN.patch --]
[-- Type: text/x-patch, Size: 13827 bytes --]

>From 8d7333689479640d2586358ffb8f4e1704e4b015 Mon Sep 17 00:00:00 2001
From: Daniel Mack <zonque@gmail.com>
Date: Sun, 4 Aug 2013 00:23:00 +0200
Subject: [PATCH] drivers/media/platform/soc_camera/pxa_camera.c DMAENGINE WIP

---
 drivers/media/platform/soc_camera/pxa_camera.c | 262 ++++++++++++-------------
 1 file changed, 121 insertions(+), 141 deletions(-)

diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index d4df305..4dfd97f 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -28,6 +28,9 @@
 #include <linux/clk.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/mmp-pdma.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
@@ -37,7 +40,6 @@
 
 #include <linux/videodev2.h>
 
-#include <mach/dma.h>
 #include <linux/platform_data/camera-pxa.h>
 
 #define PXA_CAM_VERSION "0.0.6"
@@ -177,8 +179,6 @@ enum pxa_camera_active_dma {
 /* descriptor needed for the PXA DMA engine */
 struct pxa_cam_dma {
 	dma_addr_t		sg_dma;
-	struct pxa_dma_desc	*sg_cpu;
-	size_t			sg_size;
 	int			sglen;
 };
 
@@ -206,7 +206,8 @@ struct pxa_camera_dev {
 	void __iomem		*base;
 
 	int			channels;
-	unsigned int		dma_chans[3];
+	struct dma_chan		*dma_chans[3];
+	unsigned int		dma_len;
 
 	struct pxacamera_platform_data *pdata;
 	struct resource		*res;
@@ -257,15 +258,18 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
 static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
 {
 	struct soc_camera_device *icd = vq->priv_data;
-	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-	int i;
 
 	BUG_ON(in_interrupt());
 
 	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
 		&buf->vb, buf->vb.baddr, buf->vb.bsize);
 
+	/* FIXME */
+	dmaengine_terminate_all(NULL);
+	dmaengine_terminate_all(NULL);
+	dmaengine_terminate_all(NULL);
+
 	/*
 	 * This waits until this buffer is out of danger, i.e., until it is no
 	 * longer in STATE_QUEUED or STATE_ACTIVE
@@ -274,15 +278,6 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
 	videobuf_dma_unmap(vq->dev, dma);
 	videobuf_dma_free(dma);
 
-	for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
-		if (buf->dmas[i].sg_cpu)
-			dma_free_coherent(ici->v4l2_dev.dev,
-					  buf->dmas[i].sg_size,
-					  buf->dmas[i].sg_cpu,
-					  buf->dmas[i].sg_dma);
-		buf->dmas[i].sg_cpu = NULL;
-	}
-
 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
 }
 
@@ -309,6 +304,27 @@ static int calculate_dma_sglen(struct scatterlist *sglist, int sglen,
 	return i + 1;
 }
 
+static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
+			       enum pxa_camera_active_dma act_dma);
+
+static void pxa_camera_dma_irq_y(int channel, void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(channel, pcdev, DMA_Y);
+}
+
+static void pxa_camera_dma_irq_u(int channel, void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(channel, pcdev, DMA_U);
+}
+
+static void pxa_camera_dma_irq_v(int channel, void *data)
+{
+	struct pxa_camera_dev *pcdev = data;
+	pxa_camera_dma_irq(channel, pcdev, DMA_V);
+}
+
 /**
  * pxa_init_dma_channel - init dma descriptors
  * @pcdev: pxa camera device
@@ -332,61 +348,61 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
 				struct scatterlist **sg_first, int *sg_first_ofs)
 {
 	struct pxa_cam_dma *pxa_dma = &buf->dmas[channel];
+	struct dma_chan *dma_chan = pcdev->dma_chans[channel];
 	struct device *dev = pcdev->soc_host.v4l2_dev.dev;
 	struct scatterlist *sg;
-	int i, offset, sglen;
+	int ret, i, offset, sglen;
 	int dma_len = 0, xfer_len = 0;
+	struct dma_slave_config config;
+	struct dma_async_tx_descriptor *tx;
 
-	if (pxa_dma->sg_cpu)
-		dma_free_coherent(dev, pxa_dma->sg_size,
-				  pxa_dma->sg_cpu, pxa_dma->sg_dma);
+	dmaengine_terminate_all(dma_chan);
 
 	sglen = calculate_dma_sglen(*sg_first, dma->sglen,
 				    *sg_first_ofs, size);
 
-	pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
-	pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size,
-					     &pxa_dma->sg_dma, GFP_KERNEL);
-	if (!pxa_dma->sg_cpu)
-		return -ENOMEM;
-
 	pxa_dma->sglen = sglen;
 	offset = *sg_first_ofs;
 
 	dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
 		*sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma);
 
+	memset(&config, 0, sizeof(config));
+	config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; /* FIXME? */
+	config.src_maxburst = 8;
+	config.src_addr = pcdev->res->start + cibr;
+	config.direction = DMA_DEV_TO_MEM;
 
-	for_each_sg(*sg_first, sg, sglen, i) {
-		dma_len = sg_dma_len(sg);
-
-		/* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */
-		xfer_len = roundup(min(dma_len - offset, size), 8);
-
-		size = max(0, size - xfer_len);
+	ret = dmaengine_slave_config(dma_chan, &config);
+	if (ret < 0) {
+		printk("%s(): dma slave config failed: %d\n", __func__, ret);
+		return ret;
+	}
 
-		pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr;
-		pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset;
-		pxa_dma->sg_cpu[i].dcmd =
-			DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len;
-#ifdef DEBUG
-		if (!i)
-			pxa_dma->sg_cpu[i].dcmd |= DCMD_STARTIRQEN;
-#endif
-		pxa_dma->sg_cpu[i].ddadr =
-			pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
+	pcdev->dma_len = dma_map_sg(dma_chan->device->dev, *sg_first, sg_len,
+				    DMA_FROM_DEVICE);
 
-		dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
-			 pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc),
-			 sg_dma_address(sg) + offset, xfer_len);
-		offset = 0;
+	tx = dmaengine_prep_slave_sg(chan, *sg_first, pcdev->dma_len,
+				     config.direction,
+				     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx) {
+		printk("%s(): prep_slave_sg() failed\n", __func__, ret);
+		return;
+	}
 
-		if (size == 0)
-			break;
+	switch (channel) {
+	case 0:
+		tx->callback = pxa_camera_dma_irq_y;
+		break;
+	case 1:
+		tx->callback = pxa_camera_dma_irq_u;
+		break;
+	case 2:
+		tx->callback = pxa_camera_dma_irq_v;
+		break;
 	}
 
-	pxa_dma->sg_cpu[sglen].ddadr = DDADR_STOP;
-	pxa_dma->sg_cpu[sglen].dcmd  = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_ENDIRQEN;
+	tx->callback_param = pcdev;
 
 	/*
 	 * Handle 1 special case :
@@ -395,14 +411,16 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
 	 *    for next plane should be the next after the last used to store the
 	 *    last scatter gather RAM page
 	 */
-	if (xfer_len >= dma_len) {
-		*sg_first_ofs = xfer_len - dma_len;
+	if (xfer_len >= pcdev->dma_len) {
+		*sg_first_ofs = xfer_len - pcdev->dma_len;
 		*sg_first = sg_next(sg);
 	} else {
 		*sg_first_ofs = xfer_len;
 		*sg_first = sg;
 	}
 
+	dmaengine_submit(tx);
+
 	return 0;
 }
 
@@ -524,11 +542,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
 	return 0;
 
 fail_v:
-	dma_free_coherent(dev, buf->dmas[1].sg_size,
-			  buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
 fail_u:
-	dma_free_coherent(dev, buf->dmas[0].sg_size,
-			  buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
 fail:
 	free_buffer(vq, buf);
 out:
@@ -552,10 +566,8 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev)
 
 	for (i = 0; i < pcdev->channels; i++) {
 		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
-			"%s (channel=%d) ddadr=%08x\n", __func__,
-			i, active->dmas[i].sg_dma);
-		DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma;
-		DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
+			"%s (channel=%d)\n", __func__, i);
+		dma_async_issue_pending(pcdev->dma_chans[i]);
 	}
 }
 
@@ -566,7 +578,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev)
 	for (i = 0; i < pcdev->channels; i++) {
 		dev_dbg(pcdev->soc_host.v4l2_dev.dev,
 			"%s (channel=%d)\n", __func__, i);
-		DCSR(pcdev->dma_chans[i]) = 0;
+		dmaengine_terminate_all(pcdev->dma_chans[i]);
 	}
 }
 
@@ -739,25 +751,13 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
 
 	spin_lock_irqsave(&pcdev->lock, flags);
 
-	status = DCSR(channel);
-	DCSR(channel) = status;
+/* FIXME: dma_unmap_sg() */
 
 	camera_status = __raw_readl(pcdev->base + CISR);
 	overrun = CISR_IFO_0;
 	if (pcdev->channels == 3)
 		overrun |= CISR_IFO_1 | CISR_IFO_2;
 
-	if (status & DCSR_BUSERR) {
-		dev_err(dev, "DMA Bus Error IRQ!\n");
-		goto out;
-	}
-
-	if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) {
-		dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n",
-			status);
-		goto out;
-	}
-
 	/*
 	 * pcdev->active should not be NULL in DMA irq handler.
 	 *
@@ -777,52 +777,28 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
 	buf = container_of(vb, struct pxa_buffer, vb);
 	WARN_ON(buf->inwork || list_empty(&vb->queue));
 
-	dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
-		__func__, channel, status & DCSR_STARTINTR ? "SOF " : "",
-		status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
-
-	if (status & DCSR_ENDINTR) {
-		/*
-		 * It's normal if the last frame creates an overrun, as there
-		 * are no more DMA descriptors to fetch from QCI fifos
-		 */
-		if (camera_status & overrun &&
-		    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
-			dev_dbg(dev, "FIFO overrun! CISR: %x\n",
-				camera_status);
-			pxa_camera_stop_capture(pcdev);
-			pxa_camera_start_capture(pcdev);
-			goto out;
-		}
-		buf->active_dma &= ~act_dma;
-		if (!buf->active_dma) {
-			pxa_camera_wakeup(pcdev, vb, buf);
-			pxa_camera_check_link_miss(pcdev);
-		}
+	/*
+	 * It's normal if the last frame creates an overrun, as there
+	 * are no more DMA descriptors to fetch from QCI fifos
+	 */
+	if (camera_status & overrun &&
+	    !list_is_last(pcdev->capture.next, &pcdev->capture)) {
+		dev_dbg(dev, "FIFO overrun! CISR: %x\n",
+			camera_status);
+		pxa_camera_stop_capture(pcdev);
+		pxa_camera_start_capture(pcdev);
+		goto out;
+	}
+	buf->active_dma &= ~act_dma;
+	if (!buf->active_dma) {
+		pxa_camera_wakeup(pcdev, vb, buf);
+		pxa_camera_check_link_miss(pcdev);
 	}
 
 out:
 	spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
-static void pxa_camera_dma_irq_y(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_Y);
-}
-
-static void pxa_camera_dma_irq_u(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_U);
-}
-
-static void pxa_camera_dma_irq_v(int channel, void *data)
-{
-	struct pxa_camera_dev *pcdev = data;
-	pxa_camera_dma_irq(channel, pcdev, DMA_V);
-}
-
 static struct videobuf_queue_ops pxa_videobuf_ops = {
 	.buf_setup      = pxa_videobuf_setup,
 	.buf_prepare    = pxa_videobuf_prepare,
@@ -1655,6 +1631,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	struct pxa_camera_dev *pcdev;
 	struct resource *res;
 	void __iomem *base;
+	unsigned int drcmr;
 	int irq;
 	int err = 0;
 
@@ -1717,36 +1694,35 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	pcdev->base = base;
 
 	/* request dma */
-	err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_y, pcdev);
-	if (err < 0) {
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	drcmr = 68;
+	pcdev->dma_chans[0] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_Y");
+	if (!pcdev->dma_chans[0]) {
 		dev_err(&pdev->dev, "Can't request DMA for Y\n");
-		return err;
+		return -ENODEV;
 	}
-	pcdev->dma_chans[0] = err;
-	dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
 
-	err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_u, pcdev);
-	if (err < 0) {
-		dev_err(&pdev->dev, "Can't request DMA for U\n");
+	drcmr = 69;
+	pcdev->dma_chans[1] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_U");
+	if (!pcdev->dma_chans[1]) {
+		dev_err(&pdev->dev, "Can't request DMA for Y\n");
 		goto exit_free_dma_y;
 	}
-	pcdev->dma_chans[1] = err;
-	dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
 
-	err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
-			      pxa_camera_dma_irq_v, pcdev);
-	if (err < 0) {
+	drcmr = 70;
+	pcdev->dma_chans[2] =
+		dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+						 &drcmr, &pdev->dev, "CI_V");
+	if (!pcdev->dma_chans[2]) {
 		dev_err(&pdev->dev, "Can't request DMA for V\n");
 		goto exit_free_dma_u;
 	}
-	pcdev->dma_chans[2] = err;
-	dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
-
-	DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
-	DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
-	DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD;
 
 	/* request irq */
 	err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0,
@@ -1769,11 +1745,11 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	return 0;
 
 exit_free_dma:
-	pxa_free_dma(pcdev->dma_chans[2]);
+	dma_release_channel(dma_chans[2]);
 exit_free_dma_u:
-	pxa_free_dma(pcdev->dma_chans[1]);
+	dma_release_channel(dma_chans[1]);
 exit_free_dma_y:
-	pxa_free_dma(pcdev->dma_chans[0]);
+	dma_release_channel(dma_chans[0]);
 	return err;
 }
 
@@ -1783,9 +1759,13 @@ static int pxa_camera_remove(struct platform_device *pdev)
 	struct pxa_camera_dev *pcdev = container_of(soc_host,
 					struct pxa_camera_dev, soc_host);
 
-	pxa_free_dma(pcdev->dma_chans[0]);
-	pxa_free_dma(pcdev->dma_chans[1]);
-	pxa_free_dma(pcdev->dma_chans[2]);
+	dmaengine_terminate_all(dma_chans[0]);
+	dmaengine_terminate_all(dma_chans[1]);
+	dmaengine_terminate_all(dma_chans[2]);
+
+	dma_release_channel(dma_chans[0]);
+	dma_release_channel(dma_chans[1]);
+	dma_release_channel(dma_chans[2]);
 
 	soc_camera_host_unregister(soc_host);
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-10 10:56     ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-10 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Robert,

On 10.08.2013 00:50, Robert Jarzmik wrote:
> Daniel Mack <zonque@gmail.com> writes:
> 
>>  * 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.

> 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.

> 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.

Yes, Vinod and and Dan are certainly the best ones to comment on that I
think.

> 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.

> 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?

> 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
  2013-08-10 10:56     ` Daniel Mack
@ 2013-08-11 20:05       ` Robert Jarzmik
  -1 siblings, 0 replies; 126+ messages in thread
From: Robert Jarzmik @ 2013-08-11 20:05 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, vinod.koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, mika.westerberg,
	linux-arm-kernel, thomas.petazzoni, eric.y.miao, gregkh, davem,
	sachin.kamat, kernel, djbw, g.liakhovetski

Daniel Mack <zonque@gmail.com> writes:
> Hi Robert,

We might reduce the thread broadcast, I don't think these many people care about
pxa camera specifics, and its DMA constraints.


>> 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.
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).

> 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

>> 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.

>> 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 :)

> 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.

-- 
Robert

[1]
http://archive.arm.linux.org.uk/lurker/message/20090517.194809.b18c79c8.en.html

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-11 20:05       ` Robert Jarzmik
  0 siblings, 0 replies; 126+ messages in thread
From: Robert Jarzmik @ 2013-08-11 20:05 UTC (permalink / raw)
  To: linux-arm-kernel

Daniel Mack <zonque@gmail.com> writes:
> Hi Robert,

We might reduce the thread broadcast, I don't think these many people care about
pxa camera specifics, and its DMA constraints.


>> 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.
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).

> 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

>> 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.

>> 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 :)

> 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.

-- 
Robert

[1]
http://archive.arm.linux.org.uk/lurker/message/20090517.194809.b18c79c8.en.html

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 06/20] tty: serial: pxa: remove old cruft
  2013-08-07 15:33   ` Daniel Mack
  (?)
@ 2013-08-12  8:19   ` Daniel Mack
  2013-08-12 18:08     ` Greg KH
  -1 siblings, 1 reply; 126+ messages in thread
From: Daniel Mack @ 2013-08-12  8:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Greg,

This patch can be merged independently of all others. Could you queue it
up for 3.12 please?


Thanks,
Daniel


On 07.08.2013 17:33, Daniel Mack wrote:
> This #if-0'd block wouldn't compile, so let's dispose it.
> 
> Signed-off-by: Daniel Mack <zonque@gmail.com>
> ---
>  drivers/tty/serial/pxa.c | 25 -------------------------
>  1 file changed, 25 deletions(-)
> 
> diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
> index 05f504e..cc6d539 100644
> --- a/drivers/tty/serial/pxa.c
> +++ b/drivers/tty/serial/pxa.c
> @@ -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;
> 

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 06/20] tty: serial: pxa: remove old cruft
  2013-08-12  8:19   ` Daniel Mack
@ 2013-08-12 18:08     ` Greg KH
  0 siblings, 0 replies; 126+ messages in thread
From: Greg KH @ 2013-08-12 18:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 12, 2013 at 10:19:13AM +0200, Daniel Mack wrote:
> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
  2013-08-10 10:56     ` Daniel Mack
@ 2013-08-14 10:00       ` Vinod Koul
  -1 siblings, 0 replies; 126+ messages in thread
From: Vinod Koul @ 2013-08-14 10:00 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang,
	Robert Jarzmik, cxie4, lars, nico, sachin.kamat, marek.vasut,
	ezequiel.garcia, rmk+kernel, devicetree, samuel, arnd, broonie,
	linux-arm-kernel, thomas.petazzoni, eric.y.miao, mika.westerberg,
	gregkh, davem, kernel, djbw, g.liakhovetski

On Sat, Aug 10, 2013 at 12:56:19PM +0200, Daniel Mack wrote:
> Hi Robert,
> 
> On 10.08.2013 00:50, Robert Jarzmik wrote:
> > Daniel Mack <zonque@gmail.com> writes:
> > 
> >>  * 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.
> 
> > 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.
> 
> > 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.
> 
> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-14 10:00       ` Vinod Koul
  0 siblings, 0 replies; 126+ messages in thread
From: Vinod Koul @ 2013-08-14 10:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Aug 10, 2013 at 12:56:19PM +0200, Daniel Mack wrote:
> Hi Robert,
> 
> On 10.08.2013 00:50, Robert Jarzmik wrote:
> > Daniel Mack <zonque@gmail.com> writes:
> > 
> >>  * 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.
> 
> > 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.
> 
> > 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.
> 
> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
  2013-08-14 10:00       ` Vinod Koul
@ 2013-08-15 15:22         ` Robert Jarzmik
  -1 siblings, 0 replies; 126+ messages in thread
From: Robert Jarzmik @ 2013-08-15 15:22 UTC (permalink / raw)
  To: Vinod Koul
  Cc: mark.rutland, s.neumann, davem, linux-mtd, haojian.zhuang, cxie4,
	lars, nico, sachin.kamat, marek.vasut, ezequiel.garcia,
	rmk+kernel, devicetree, samuel, arnd, broonie, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, mika.westerberg, gregkh,
	Daniel Mack, kernel, djbw, g.liakhovetski

Vinod Koul <vinod.koul@intel.com> writes:
>> 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.
>
>
> 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.

> 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.
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.

-- 
Robert

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-15 15:22         ` Robert Jarzmik
  0 siblings, 0 replies; 126+ messages in thread
From: Robert Jarzmik @ 2013-08-15 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

Vinod Koul <vinod.koul@intel.com> writes:
>> 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.
>
>
> 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.

> 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.
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.

-- 
Robert

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
  2013-08-15 15:22         ` Robert Jarzmik
@ 2013-08-15 15:30           ` Daniel Mack
  -1 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-15 15:30 UTC (permalink / raw)
  To: Robert Jarzmik
  Cc: mark.rutland, s.neumann, linux-mtd, haojian.zhuang, cxie4, lars,
	nico, Vinod Koul, marek.vasut, ezequiel.garcia, rmk+kernel,
	devicetree, samuel, arnd, broonie, linux-arm-kernel,
	thomas.petazzoni, eric.y.miao, mika.westerberg, gregkh, davem,
	sachin.kamat, kernel, djbw, g.liakhovetski

On 15.08.2013 17:22, Robert Jarzmik wrote:
> Vinod Koul <vinod.koul@intel.com> writes:

>> 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.

> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine
@ 2013-08-15 15:30           ` Daniel Mack
  0 siblings, 0 replies; 126+ messages in thread
From: Daniel Mack @ 2013-08-15 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 15.08.2013 17:22, Robert Jarzmik wrote:
> Vinod Koul <vinod.koul@intel.com> writes:

>> 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.

> 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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use
  2013-08-07 15:33   ` Daniel Mack
  (?)
@ 2014-10-15 18:32       ` Vasily Khoruzhick
  -1 siblings, 0 replies; 126+ messages in thread
From: Vasily Khoruzhick @ 2014-10-15 18:32 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Haojian Zhuang, Eric Miao, arm-linux, mark.rutland-5wv7dgnIgG8,
	s.neumann-5g8ninUHluJWk0Htik3J/w,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	cxie4-eYqpPyKDWXRBDgjK7y7TUQ, Lars-Peter Clausen,
	nico-QSEj5FYQhm4dnm+yROfE0A, Vinod Koul, Marek Vašut,
	ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, samuel-jcdQHdrhKHMdnm+yROfE0A,
	Arnd Bergmann, Mark Brown,
	mika.westerberg-VuQAYsv1563Yd54FQh9/CA,
	thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	Greg Kroah-Hartman, g.liakhovetski-Mmb7MZpHnFY,
	sachin.kamat-QSEj5FYQhm4dnm+yROfE0A,
	kernel-bIcnvbaLZ9MEGnE8C9+IrQ, djbw-b10kYP2dOMg,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q

Hi Daniel,

On Wed, Aug 7, 2013 at 6:33 PM, Daniel Mack <zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> 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

>
> Signed-off-by: Daniel Mack <zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++---------------------
>  1 file changed, 102 insertions(+), 86 deletions(-)
>
> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
> index 2c5a91b..7aa97eb 100644
> --- a/drivers/mmc/host/pxamci.c
> +++ b/drivers/mmc/host/pxamci.c
> @@ -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-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use
@ 2014-10-15 18:32       ` Vasily Khoruzhick
  0 siblings, 0 replies; 126+ messages in thread
From: Vasily Khoruzhick @ 2014-10-15 18:32 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, Haojian Zhuang, cxie4,
	Lars-Peter Clausen, nico, Vinod Koul, Marek Vašut,
	ezequiel.garcia, rmk+kernel, devicetree, samuel, Arnd Bergmann,
	Mark Brown, mika.westerberg, arm-linux, thomas.petazzoni,
	Eric Miao, Greg Kroah-Hartman, davem, sachin.kamat, kernel, djbw,
	g.liakhovetski

Hi Daniel,

On Wed, Aug 7, 2013 at 6:33 PM, Daniel Mack <zonque@gmail.com> wrote:
> 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

>
> Signed-off-by: Daniel Mack <zonque@gmail.com>
> ---
>  drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++---------------------
>  1 file changed, 102 insertions(+), 86 deletions(-)
>
> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
> index 2c5a91b..7aa97eb 100644
> --- a/drivers/mmc/host/pxamci.c
> +++ b/drivers/mmc/host/pxamci.c
> @@ -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@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 126+ messages in thread

* [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use
@ 2014-10-15 18:32       ` Vasily Khoruzhick
  0 siblings, 0 replies; 126+ messages in thread
From: Vasily Khoruzhick @ 2014-10-15 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Daniel,

On Wed, Aug 7, 2013 at 6:33 PM, Daniel Mack <zonque@gmail.com> wrote:
> 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

>
> Signed-off-by: Daniel Mack <zonque@gmail.com>
> ---
>  drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++---------------------
>  1 file changed, 102 insertions(+), 86 deletions(-)
>
> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
> index 2c5a91b..7aa97eb 100644
> --- a/drivers/mmc/host/pxamci.c
> +++ b/drivers/mmc/host/pxamci.c
> @@ -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

^ permalink raw reply	[flat|nested] 126+ messages in thread

* Re: [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use
  2014-10-15 18:32       ` Vasily Khoruzhick
  (?)
@ 2014-10-16 17:57           ` Vasily Khoruzhick
  -1 siblings, 0 replies; 126+ messages in thread
From: Vasily Khoruzhick @ 2014-10-16 17:57 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Haojian Zhuang, Eric Miao, arm-linux, mark.rutland-5wv7dgnIgG8,
	s.neumann-5g8ninUHluJWk0Htik3J/w,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	cxie4-eYqpPyKDWXRBDgjK7y7TUQ, Lars-Peter Clausen, Nicolas Pitre,
	Vinod Koul, Marek Vašut,
	ezequiel.garcia-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, samuel-jcdQHdrhKHMdnm+yROfE0A,
	Arnd Bergmann, Mark Brown,
	mika.westerberg-VuQAYsv1563Yd54FQh9/CA, Thomas Petazzoni,
	Greg Kroah-Hartman, Guennadi Liakhovetski,
	sachin.kamat-QSEj5FYQhm4dnm+yROfE0A,
	kernel-bIcnvbaLZ9MEGnE8C9+IrQ, djbw-b10kYP2dOMg,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q

[-- Attachment #1: Type: text/plain, Size: 15499 bytes --]

On Wed, Oct 15, 2014 at 9:32 PM, Vasily Khoruzhick <anarsoul-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Hi Daniel,
>
> On Wed, Aug 7, 2013 at 6:33 PM, Daniel Mack <zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> 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?

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

> Regards,
> Vasily
>
>>
>> Signed-off-by: Daniel Mack <zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>>  drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++---------------------
>>  1 file changed, 102 insertions(+), 86 deletions(-)
>>
>> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
>> index 2c5a91b..7aa97eb 100644
>> --- a/drivers/mmc/host/pxamci.c
>> +++ b/drivers/mmc/host/pxamci.c
>> @@ -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-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

[-- Attachment #2: pxamci-mmp-pdma-fix.patch --]
[-- Type: text/x-patch, Size: 495 bytes --]

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index eb725d3..b52e06e 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -237,8 +237,10 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
 		return;
 	}
 
-	tx->callback = pxamci_dma_irq;
-	tx->callback_param = host;
+	if (!(data->flags & MMC_DATA_READ)) {
+		tx->callback = pxamci_dma_irq;
+		tx->callback_param = host;
+	}
 
 	host->dma_cookie = dmaengine_submit(tx);
 

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* Re: [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use
@ 2014-10-16 17:57           ` Vasily Khoruzhick
  0 siblings, 0 replies; 126+ messages in thread
From: Vasily Khoruzhick @ 2014-10-16 17:57 UTC (permalink / raw)
  To: Daniel Mack
  Cc: mark.rutland, s.neumann, linux-mtd, Haojian Zhuang, cxie4,
	Lars-Peter Clausen, Nicolas Pitre, Vinod Koul, Marek Vašut,
	ezequiel.garcia, rmk+kernel, devicetree, samuel, Arnd Bergmann,
	Mark Brown, mika.westerberg, arm-linux, Thomas Petazzoni,
	Eric Miao, Greg Kroah-Hartman, davem, sachin.kamat, kernel, djbw,
	Guennadi Liakhovetski

[-- Attachment #1: Type: text/plain, Size: 15379 bytes --]

On Wed, Oct 15, 2014 at 9:32 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> Hi Daniel,
>
> On Wed, Aug 7, 2013 at 6:33 PM, Daniel Mack <zonque@gmail.com> wrote:
>> 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?

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

> Regards,
> Vasily
>
>>
>> Signed-off-by: Daniel Mack <zonque@gmail.com>
>> ---
>>  drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++---------------------
>>  1 file changed, 102 insertions(+), 86 deletions(-)
>>
>> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
>> index 2c5a91b..7aa97eb 100644
>> --- a/drivers/mmc/host/pxamci.c
>> +++ b/drivers/mmc/host/pxamci.c
>> @@ -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@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

[-- Attachment #2: pxamci-mmp-pdma-fix.patch --]
[-- Type: text/x-patch, Size: 495 bytes --]

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index eb725d3..b52e06e 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -237,8 +237,10 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
 		return;
 	}
 
-	tx->callback = pxamci_dma_irq;
-	tx->callback_param = host;
+	if (!(data->flags & MMC_DATA_READ)) {
+		tx->callback = pxamci_dma_irq;
+		tx->callback_param = host;
+	}
 
 	host->dma_cookie = dmaengine_submit(tx);
 

^ permalink raw reply related	[flat|nested] 126+ messages in thread

* [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use
@ 2014-10-16 17:57           ` Vasily Khoruzhick
  0 siblings, 0 replies; 126+ messages in thread
From: Vasily Khoruzhick @ 2014-10-16 17:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 15, 2014 at 9:32 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> Hi Daniel,
>
> On Wed, Aug 7, 2013 at 6:33 PM, Daniel Mack <zonque@gmail.com> wrote:
>> 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?

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

> Regards,
> Vasily
>
>>
>> Signed-off-by: Daniel Mack <zonque@gmail.com>
>> ---
>>  drivers/mmc/host/pxamci.c | 188 +++++++++++++++++++++++++---------------------
>>  1 file changed, 102 insertions(+), 86 deletions(-)
>>
>> diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
>> index 2c5a91b..7aa97eb 100644
>> --- a/drivers/mmc/host/pxamci.c
>> +++ b/drivers/mmc/host/pxamci.c
>> @@ -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
-------------- 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>

^ permalink raw reply	[flat|nested] 126+ messages in thread

end of thread, other threads:[~2014-10-16 17:57 UTC | newest]

Thread overview: 126+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-07 15:33 [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine Daniel Mack
2013-08-07 15:33 ` Daniel Mack
2013-08-07 15:33 ` [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-07 17:46   ` Ezequiel Garcia
2013-08-07 17:46     ` Ezequiel Garcia
2013-08-08  6:42     ` Daniel Mack
2013-08-08  6:42       ` Daniel Mack
2013-08-08 10:12       ` Ezequiel Garcia
2013-08-08 10:12         ` Ezequiel Garcia
2013-08-08 10:14         ` Daniel Mack
2013-08-08 10:14           ` Daniel Mack
2013-08-07 15:33 ` [PATCH 02/20] mtd: pxa3xx-nand: use mmp_pdma_filter_fn and dma_request_slave_channel_compat Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-07 15:33 ` [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-08  7:32   ` Brian Norris
2013-08-08  7:32     ` Brian Norris
2013-08-08  7:52     ` Artem Bityutskiy
2013-08-08  7:52       ` Artem Bityutskiy
2013-08-08  8:20       ` Daniel Mack
2013-08-08  8:20         ` Daniel Mack
2013-08-07 15:33 ` [PATCH 04/20] ARM: pxa: ssp: add DT bindings Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-07 15:54   ` Arnd Bergmann
2013-08-07 15:54     ` Arnd Bergmann
2013-08-07 15:33 ` [PATCH 05/20] ARM: pxa: ssp: use devm_ functions Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-07 15:33 ` [PATCH 06/20] tty: serial: pxa: remove old cruft Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-12  8:19   ` Daniel Mack
2013-08-12 18:08     ` Greg KH
2013-08-07 15:33 ` [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-07 15:55   ` Mark Brown
2013-08-07 15:55     ` Mark Brown
2013-08-07 15:59     ` Daniel Mack
2013-08-07 15:59       ` Daniel Mack
2013-08-07 16:41       ` Mark Brown
2013-08-07 16:41         ` Mark Brown
2013-08-07 15:33 ` [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use Daniel Mack
2013-08-07 15:33   ` Daniel Mack
     [not found]   ` <1375889649-14638-9-git-send-email-zonque-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-10-15 18:32     ` Vasily Khoruzhick
2014-10-15 18:32       ` Vasily Khoruzhick
2014-10-15 18:32       ` Vasily Khoruzhick
     [not found]       ` <CA+E=qVe5zRoR8qVa_gyJu+qpuGHFmqoGvEHowcu_hXR01GBzTA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-10-16 17:57         ` Vasily Khoruzhick
2014-10-16 17:57           ` Vasily Khoruzhick
2014-10-16 17:57           ` Vasily Khoruzhick
2013-08-07 15:33 ` [PATCH 09/20] ata: pdata_pxa: migrate over to dmaengine usage Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-07 15:59   ` Arnd Bergmann
2013-08-07 15:59     ` Arnd Bergmann
2013-08-07 15:33 ` [PATCH 10/20] net: irda: pxaficp_ir: switch to dmaengine Daniel Mack
2013-08-07 15:33   ` Daniel Mack
2013-08-07 15:34 ` [PATCH 11/20] net: smc91x.c: switch to generic buf-to-buf DMA offload Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 15:34 ` [PATCH 12/20] net: smc911x.c: switch to dmaengine API Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 15:34 ` [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 16:40   ` Mark Brown
2013-08-07 16:40     ` Mark Brown
2013-08-08  9:39     ` Daniel Mack
2013-08-08  9:39       ` Daniel Mack
2013-08-08 13:20       ` Mark Brown
2013-08-08 13:20         ` Mark Brown
2013-08-09 13:03         ` Daniel Mack
2013-08-09 13:03           ` Daniel Mack
2013-08-07 15:34 ` [PATCH 14/20] ASoC: pxa: use snd_dmaengine_dai_dma_data Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 15:57   ` Mark Brown
2013-08-07 15:57     ` Mark Brown
2013-08-07 15:34 ` [PATCH 15/20] ASoC: pxa: pxa-ssp: set dma filter data from startup hook Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 15:58   ` Mark Brown
2013-08-07 15:58     ` Mark Brown
2013-08-07 15:34 ` [PATCH 16/20] ASoC: pxa: add DT bindings for pxa2xx-pcm Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 16:06   ` Mark Brown
2013-08-07 16:06     ` Mark Brown
2013-08-07 15:34 ` [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 16:07   ` Mark Brown
2013-08-07 16:07     ` Mark Brown
2013-08-07 16:10     ` Daniel Mack
2013-08-07 16:10       ` Daniel Mack
2013-08-07 16:32       ` Mark Brown
2013-08-07 16:32         ` Mark Brown
2013-08-08  8:18         ` Daniel Mack
2013-08-08  8:18           ` Daniel Mack
2013-08-08  8:44           ` Lars-Peter Clausen
2013-08-08  8:44             ` Lars-Peter Clausen
2013-08-08  9:03             ` Daniel Mack
2013-08-08  9:03               ` Daniel Mack
2013-08-08  9:36               ` Mark Brown
2013-08-08  9:36                 ` Mark Brown
2013-08-08  9:43                 ` Daniel Mack
2013-08-08  9:43                   ` Daniel Mack
2013-08-08 10:35                   ` Mark Brown
2013-08-08 10:35                     ` Mark Brown
2013-08-08 10:39                     ` Daniel Mack
2013-08-08 10:39                       ` Daniel Mack
2013-08-08 11:03                       ` Mark Brown
2013-08-08 11:03                         ` Mark Brown
2013-08-08 10:25                 ` Russell King - ARM Linux
2013-08-08 10:25                   ` Russell King - ARM Linux
2013-08-07 15:34 ` [PATCH 18/20] ARM: pxa: register static mmp_pdma device Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 15:34 ` [PATCH 19/20] ARM: mmp: " Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 15:34 ` [PATCH 20/20] ARM: pxa: remove old DMA implementation Daniel Mack
2013-08-07 15:34   ` Daniel Mack
2013-08-07 16:08 ` [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine Arnd Bergmann
2013-08-07 16:08   ` Arnd Bergmann
2013-08-09 22:50 ` Robert Jarzmik
2013-08-09 22:50   ` Robert Jarzmik
2013-08-10 10:56   ` Daniel Mack
2013-08-10 10:56     ` Daniel Mack
2013-08-11 20:05     ` Robert Jarzmik
2013-08-11 20:05       ` Robert Jarzmik
2013-08-14 10:00     ` Vinod Koul
2013-08-14 10:00       ` Vinod Koul
2013-08-15 15:22       ` Robert Jarzmik
2013-08-15 15:22         ` Robert Jarzmik
2013-08-15 15:30         ` Daniel Mack
2013-08-15 15:30           ` Daniel Mack

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.