All of lore.kernel.org
 help / color / mirror / Atom feed
* [RESEND] [PATCH V4 0/14] To use DMA generic APIs for Samsung DMA
@ 2011-07-25  1:28 ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown

This patchset adds support DMA generic APIs for Samsung DMA
and is re-sent by the request of DMA maintainer, Vinod Koul.

V4 has the changes about 3 patches from V3.
Changes from V3:
- Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset
  into two patches.
	- One is '03/14 patch' for supporting DMA_SLAVE_CONFIG command.
	- Another is '04/14 patch' for supporting DMA_CYCLIC capability.
- Code clean-up
	- Remove unnecessary vairable referance on '01/14 patch'.
	- Remove redunancy code on '06/14 patch'

[PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
[PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
[PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
[PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
[PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
[PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
[PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
[PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
[PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
[PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
[PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
[PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
[PATCH V4 13/14] ASoC: Samsung: Update DMA interface
[PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction

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

* [RESEND] [PATCH V4 0/14] To use DMA generic APIs for Samsung DMA
@ 2011-07-25  1:28 ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset adds support DMA generic APIs for Samsung DMA
and is re-sent by the request of DMA maintainer, Vinod Koul.

V4 has the changes about 3 patches from V3.
Changes from V3:
- Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset
  into two patches.
	- One is '03/14 patch' for supporting DMA_SLAVE_CONFIG command.
	- Another is '04/14 patch' for supporting DMA_CYCLIC capability.
- Code clean-up
	- Remove unnecessary vairable referance on '01/14 patch'.
	- Remove redunancy code on '06/14 patch'

[PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
[PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
[PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
[PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
[PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
[PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
[PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
[PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
[PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
[PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
[PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
[PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
[PATCH V4 13/14] ASoC: Samsung: Update DMA interface
[PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction

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

* [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/dma/pl330.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 6abe1ec..b7ecf47 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
 
 #define NR_DEFAULT_DESC	16
 
@@ -83,6 +84,8 @@ struct dma_pl330_dmac {
 
 	/* Peripheral channels connected to this DMAC */
 	struct dma_pl330_chan peripherals[0]; /* keep at end */
+
+	struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -696,6 +699,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		goto probe_err1;
 	}
 
+	pdmac->clk = clk_get(&adev->dev, "dma");
+	if (IS_ERR(pdmac->clk)) {
+		dev_err(&adev->dev, "Cannot get operation clock.\n");
+		ret = -EINVAL;
+		goto probe_err1;
+	}
+
+	amba_set_drvdata(adev, pdmac);
+
+#ifdef CONFIG_PM_RUNTIME
+	/* to use the runtime PM helper functions */
+	pm_runtime_enable(&adev->dev);
+
+	/* enable the power domain */
+	if (pm_runtime_get_sync(&adev->dev)) {
+		dev_err(&adev->dev, "failed to get runtime pm\n");
+		ret = -ENODEV;
+		goto probe_err1;
+	}
+#else
+	/* enable dma clk */
+	clk_enable(pdmac->clk);
+#endif
+
 	irq = adev->irq[0];
 	ret = request_irq(irq, pl330_irq_handler, 0,
 			dev_name(&adev->dev), pi);
@@ -763,8 +790,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		goto probe_err4;
 	}
 
-	amba_set_drvdata(adev, pdmac);
-
 	dev_info(&adev->dev,
 		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
 	dev_info(&adev->dev,
@@ -825,6 +850,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
 	res = &adev->res;
 	release_mem_region(res->start, resource_size(res));
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_put(&adev->dev);
+	pm_runtime_disable(&adev->dev);
+#else
+	clk_disable(pdmac->clk);
+#endif
+
 	kfree(pdmac);
 
 	return 0;
@@ -838,10 +870,49 @@ static struct amba_id pl330_ids[] = {
 	{ 0, 0 },
 };
 
+#ifdef CONFIG_PM_RUNTIME
+static int pl330_runtime_suspend(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_disable(pdmac->clk);
+
+	return 0;
+}
+
+static int pl330_runtime_resume(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_enable(pdmac->clk);
+
+	return 0;
+}
+#else
+#define pl330_runtime_suspend	NULL
+#define pl330_runtime_resume	NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops pl330_pm_ops = {
+	.runtime_suspend = pl330_runtime_suspend,
+	.runtime_resume = pl330_runtime_resume,
+};
+
 static struct amba_driver pl330_driver = {
 	.drv = {
 		.owner = THIS_MODULE,
 		.name = "dma-pl330",
+		.pm = &pl330_pm_ops,
 	},
 	.id_table = pl330_ids,
 	.probe = pl330_probe,
-- 
1.7.1

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

* [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/dma/pl330.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 6abe1ec..b7ecf47 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
 
 #define NR_DEFAULT_DESC	16
 
@@ -83,6 +84,8 @@ struct dma_pl330_dmac {
 
 	/* Peripheral channels connected to this DMAC */
 	struct dma_pl330_chan peripherals[0]; /* keep at end */
+
+	struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -696,6 +699,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		goto probe_err1;
 	}
 
+	pdmac->clk = clk_get(&adev->dev, "dma");
+	if (IS_ERR(pdmac->clk)) {
+		dev_err(&adev->dev, "Cannot get operation clock.\n");
+		ret = -EINVAL;
+		goto probe_err1;
+	}
+
+	amba_set_drvdata(adev, pdmac);
+
+#ifdef CONFIG_PM_RUNTIME
+	/* to use the runtime PM helper functions */
+	pm_runtime_enable(&adev->dev);
+
+	/* enable the power domain */
+	if (pm_runtime_get_sync(&adev->dev)) {
+		dev_err(&adev->dev, "failed to get runtime pm\n");
+		ret = -ENODEV;
+		goto probe_err1;
+	}
+#else
+	/* enable dma clk */
+	clk_enable(pdmac->clk);
+#endif
+
 	irq = adev->irq[0];
 	ret = request_irq(irq, pl330_irq_handler, 0,
 			dev_name(&adev->dev), pi);
@@ -763,8 +790,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		goto probe_err4;
 	}
 
-	amba_set_drvdata(adev, pdmac);
-
 	dev_info(&adev->dev,
 		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
 	dev_info(&adev->dev,
@@ -825,6 +850,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
 	res = &adev->res;
 	release_mem_region(res->start, resource_size(res));
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_put(&adev->dev);
+	pm_runtime_disable(&adev->dev);
+#else
+	clk_disable(pdmac->clk);
+#endif
+
 	kfree(pdmac);
 
 	return 0;
@@ -838,10 +870,49 @@ static struct amba_id pl330_ids[] = {
 	{ 0, 0 },
 };
 
+#ifdef CONFIG_PM_RUNTIME
+static int pl330_runtime_suspend(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_disable(pdmac->clk);
+
+	return 0;
+}
+
+static int pl330_runtime_resume(struct device *dev)
+{
+	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
+
+	if (!pdmac) {
+		dev_err(dev, "failed to get dmac\n");
+		return -ENODEV;
+	}
+
+	clk_enable(pdmac->clk);
+
+	return 0;
+}
+#else
+#define pl330_runtime_suspend	NULL
+#define pl330_runtime_resume	NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops pl330_pm_ops = {
+	.runtime_suspend = pl330_runtime_suspend,
+	.runtime_resume = pl330_runtime_resume,
+};
+
 static struct amba_driver pl330_driver = {
 	.drv = {
 		.owner = THIS_MODULE,
 		.name = "dma-pl330",
+		.pm = &pl330_pm_ops,
 	},
 	.id_table = pl330_ids,
 	.probe = pl330_probe,
-- 
1.7.1

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

* [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch updates following 3 items.
1. Removes unneccessary code.
2. Add AMBA, PL330 configuration
3. Change the meaning of 'peri_id' variable
   from PL330 event number to specific dma id by user.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 drivers/dma/Kconfig        |    3 ++-
 drivers/dma/pl330.c        |   31 ++++++++++++++++---------------
 include/linux/amba/pl330.h |    2 +-
 3 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 25cf327..569cb14 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -193,7 +193,8 @@ config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
 config PL330_DMA
 	tristate "DMA API Driver for PL330"
 	select DMA_ENGINE
-	depends on PL330
+	depends on ARM_AMBA
+	select PL330
 	help
 	  Select if your platform has one or more PL330 DMACs.
 	  You need to provide platform specific settings via
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index b7ecf47..586ab39 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 	async_tx_ack(&desc->txd);
 
 	desc->req.rqtype = peri->rqtype;
-	desc->req.peri = peri->peri_id;
+	desc->req.peri = pch->chan.chan_id;
 
 	dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
 
@@ -577,7 +577,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	struct dma_pl330_peri *peri = chan->private;
 	struct scatterlist *sg;
 	unsigned long flags;
-	int i, burst_size;
+	int i;
 	dma_addr_t addr;
 
 	if (unlikely(!pch || !sgl || !sg_len))
@@ -594,7 +594,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	}
 
 	addr = peri->fifo_addr;
-	burst_size = peri->burst_sz;
 
 	first = NULL;
 
@@ -642,7 +641,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 				sg_dma_address(sg), addr, sg_dma_len(sg));
 		}
 
-		desc->rqcfg.brst_size = burst_size;
+		desc->rqcfg.brst_size = peri->burst_sz;
 		desc->rqcfg.brst_len = 1;
 	}
 
@@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		struct dma_pl330_peri *peri = &pdat->peri[i];
 		pch = &pdmac->peripherals[i];
 
-		switch (peri->rqtype) {
-		case MEMTOMEM:
-			dma_cap_set(DMA_MEMCPY, pd->cap_mask);
-			break;
-		case MEMTODEV:
-		case DEVTOMEM:
-			dma_cap_set(DMA_SLAVE, pd->cap_mask);
-			break;
-		default:
-			dev_err(&adev->dev, "DEVTODEV Not Supported\n");
-			continue;
+		if (peri) {
+			switch (peri->rqtype) {
+			case MEMTOMEM:
+				dma_cap_set(DMA_MEMCPY, pd->cap_mask);
+				break;
+			case MEMTODEV:
+			case DEVTOMEM:
+				dma_cap_set(DMA_SLAVE, pd->cap_mask);
+				break;
+			default:
+				dev_err(&adev->dev, "DEVTODEV Not Supported\n");
+				continue;
+			}
 		}
 
 		INIT_LIST_HEAD(&pch->work_list);
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
index cbee7de..17b0ada 100644
--- a/include/linux/amba/pl330.h
+++ b/include/linux/amba/pl330.h
@@ -19,7 +19,7 @@ struct dma_pl330_peri {
 	 * Peri_Req i/f of the DMAC that is
 	 * peripheral could be reached from.
 	 */
-	u8 peri_id; /* {0, 31} */
+	u8 peri_id; /* specific dma id */
 	enum pl330_reqtype rqtype;
 
 	/* For M->D and D->M Channels */
-- 
1.7.1

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

* [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch updates following 3 items.
1. Removes unneccessary code.
2. Add AMBA, PL330 configuration
3. Change the meaning of 'peri_id' variable
   from PL330 event number to specific dma id by user.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 drivers/dma/Kconfig        |    3 ++-
 drivers/dma/pl330.c        |   31 ++++++++++++++++---------------
 include/linux/amba/pl330.h |    2 +-
 3 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 25cf327..569cb14 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -193,7 +193,8 @@ config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
 config PL330_DMA
 	tristate "DMA API Driver for PL330"
 	select DMA_ENGINE
-	depends on PL330
+	depends on ARM_AMBA
+	select PL330
 	help
 	  Select if your platform has one or more PL330 DMACs.
 	  You need to provide platform specific settings via
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index b7ecf47..586ab39 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 	async_tx_ack(&desc->txd);
 
 	desc->req.rqtype = peri->rqtype;
-	desc->req.peri = peri->peri_id;
+	desc->req.peri = pch->chan.chan_id;
 
 	dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
 
@@ -577,7 +577,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	struct dma_pl330_peri *peri = chan->private;
 	struct scatterlist *sg;
 	unsigned long flags;
-	int i, burst_size;
+	int i;
 	dma_addr_t addr;
 
 	if (unlikely(!pch || !sgl || !sg_len))
@@ -594,7 +594,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	}
 
 	addr = peri->fifo_addr;
-	burst_size = peri->burst_sz;
 
 	first = NULL;
 
@@ -642,7 +641,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 				sg_dma_address(sg), addr, sg_dma_len(sg));
 		}
 
-		desc->rqcfg.brst_size = burst_size;
+		desc->rqcfg.brst_size = peri->burst_sz;
 		desc->rqcfg.brst_len = 1;
 	}
 
@@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		struct dma_pl330_peri *peri = &pdat->peri[i];
 		pch = &pdmac->peripherals[i];
 
-		switch (peri->rqtype) {
-		case MEMTOMEM:
-			dma_cap_set(DMA_MEMCPY, pd->cap_mask);
-			break;
-		case MEMTODEV:
-		case DEVTOMEM:
-			dma_cap_set(DMA_SLAVE, pd->cap_mask);
-			break;
-		default:
-			dev_err(&adev->dev, "DEVTODEV Not Supported\n");
-			continue;
+		if (peri) {
+			switch (peri->rqtype) {
+			case MEMTOMEM:
+				dma_cap_set(DMA_MEMCPY, pd->cap_mask);
+				break;
+			case MEMTODEV:
+			case DEVTOMEM:
+				dma_cap_set(DMA_SLAVE, pd->cap_mask);
+				break;
+			default:
+				dev_err(&adev->dev, "DEVTODEV Not Supported\n");
+				continue;
+			}
 		}
 
 		INIT_LIST_HEAD(&pch->work_list);
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
index cbee7de..17b0ada 100644
--- a/include/linux/amba/pl330.h
+++ b/include/linux/amba/pl330.h
@@ -19,7 +19,7 @@ struct dma_pl330_peri {
 	 * Peri_Req i/f of the DMAC that is
 	 * peripheral could be reached from.
 	 */
-	u8 peri_id; /* {0, 31} */
+	u8 peri_id; /* specific dma id */
 	enum pl330_reqtype rqtype;
 
 	/* For M->D and D->M Channels */
-- 
1.7.1

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

* [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch adds support DMA_SLAVE_CONFIG command.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/dma/pl330.c |   53 +++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 586ab39..880f010 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
 static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
-	struct dma_pl330_desc *desc;
+	struct dma_pl330_desc *desc, *_dt;
 	unsigned long flags;
+	struct dma_pl330_dmac *pdmac = pch->dmac;
+	struct dma_slave_config *slave_config;
+	struct dma_pl330_peri *peri;
+	LIST_HEAD(list);
 
-	/* Only supports DMA_TERMINATE_ALL */
-	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
-
-	spin_lock_irqsave(&pch->lock, flags);
-
-	/* FLUSH the PL330 Channel thread */
-	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&pch->lock, flags);
 
-	/* Mark all desc done */
-	list_for_each_entry(desc, &pch->work_list, node)
-		desc->status = DONE;
+		/* FLUSH the PL330 Channel thread */
+		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
 
-	spin_unlock_irqrestore(&pch->lock, flags);
+		/* Mark all desc done */
+		list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
+			desc->status = DONE;
+			pch->completed = desc->txd.cookie;
+			list_move_tail(&desc->node, &list);
+		}
 
-	pl330_tasklet((unsigned long) pch);
+		list_splice_tail_init(&list, &pdmac->desc_pool);
+		spin_unlock_irqrestore(&pch->lock, flags);
+		break;
+	case DMA_SLAVE_CONFIG:
+		slave_config = (struct dma_slave_config *)arg;
+		peri = pch->chan.private;
+
+		if (slave_config->direction == DMA_TO_DEVICE) {
+			if (slave_config->dst_addr)
+				peri->fifo_addr = slave_config->dst_addr;
+			if (slave_config->dst_addr_width)
+				peri->burst_sz = __ffs(slave_config->dst_addr_width);
+		} else if (slave_config->direction == DMA_FROM_DEVICE) {
+			if (slave_config->src_addr)
+				peri->fifo_addr = slave_config->src_addr;
+			if (slave_config->src_addr_width)
+				peri->burst_sz = __ffs(slave_config->src_addr_width);
+		}
+		break;
+	default:
+		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
+		return -ENXIO;
+	}
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support DMA_SLAVE_CONFIG command.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/dma/pl330.c |   53 +++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 586ab39..880f010 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
 static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
-	struct dma_pl330_desc *desc;
+	struct dma_pl330_desc *desc, *_dt;
 	unsigned long flags;
+	struct dma_pl330_dmac *pdmac = pch->dmac;
+	struct dma_slave_config *slave_config;
+	struct dma_pl330_peri *peri;
+	LIST_HEAD(list);
 
-	/* Only supports DMA_TERMINATE_ALL */
-	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
-
-	spin_lock_irqsave(&pch->lock, flags);
-
-	/* FLUSH the PL330 Channel thread */
-	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&pch->lock, flags);
 
-	/* Mark all desc done */
-	list_for_each_entry(desc, &pch->work_list, node)
-		desc->status = DONE;
+		/* FLUSH the PL330 Channel thread */
+		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
 
-	spin_unlock_irqrestore(&pch->lock, flags);
+		/* Mark all desc done */
+		list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
+			desc->status = DONE;
+			pch->completed = desc->txd.cookie;
+			list_move_tail(&desc->node, &list);
+		}
 
-	pl330_tasklet((unsigned long) pch);
+		list_splice_tail_init(&list, &pdmac->desc_pool);
+		spin_unlock_irqrestore(&pch->lock, flags);
+		break;
+	case DMA_SLAVE_CONFIG:
+		slave_config = (struct dma_slave_config *)arg;
+		peri = pch->chan.private;
+
+		if (slave_config->direction == DMA_TO_DEVICE) {
+			if (slave_config->dst_addr)
+				peri->fifo_addr = slave_config->dst_addr;
+			if (slave_config->dst_addr_width)
+				peri->burst_sz = __ffs(slave_config->dst_addr_width);
+		} else if (slave_config->direction == DMA_FROM_DEVICE) {
+			if (slave_config->src_addr)
+				peri->fifo_addr = slave_config->src_addr;
+			if (slave_config->src_addr_width)
+				peri->burst_sz = __ffs(slave_config->src_addr_width);
+		}
+		break;
+	default:
+		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
+		return -ENXIO;
+	}
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch adds DMA_CYCLIC capability that is used for audio driver.
DMA driver with DMA_CYCLIC capability reuses the dma requests that
were submitted through tx_submit().

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/dma/pl330.c |  111 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 880f010..121c75a 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -69,6 +69,11 @@ struct dma_pl330_chan {
 	 * NULL if the channel is available to be acquired.
 	 */
 	void *pl330_chid;
+
+	/* taks for cyclic capability */
+	struct tasklet_struct *cyclic_task;
+
+	bool cyclic;
 };
 
 struct dma_pl330_dmac {
@@ -184,6 +189,41 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
 	}
 }
 
+static void pl330_tasklet_cyclic(unsigned long data)
+{
+	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
+	struct dma_pl330_desc *desc, *_dt;
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	spin_lock_irqsave(&pch->lock, flags);
+
+	/* Pick up ripe tomatoes */
+	list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
+		if (desc->status == DONE) {
+			dma_async_tx_callback callback;
+
+			list_move_tail(&desc->node, &pch->work_list);
+			pch->completed = desc->txd.cookie;
+
+			desc->status = PREP;
+
+			/* Try to submit a req imm.
+			next to the last completed cookie */
+			fill_queue(pch);
+
+			/* Make sure the PL330 Channel thread is active */
+			pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START);
+
+			callback = desc->txd.callback;
+			if (callback)
+				callback(desc->txd.callback_param);
+
+		}
+
+	spin_unlock_irqrestore(&pch->lock, flags);
+}
+
 static void pl330_tasklet(unsigned long data)
 {
 	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
@@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
 
 	spin_unlock_irqrestore(&pch->lock, flags);
 
+	if (pch->cyclic_task)
+		tasklet_schedule(pch->cyclic_task);
+	else
 	tasklet_schedule(&pch->task);
 }
 
@@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
 	pl330_release_channel(pch->pl330_chid);
 	pch->pl330_chid = NULL;
 
+	if (pch->cyclic) {
+		pch->cyclic = false;
+		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
+		if (pch->cyclic_task) {
+			tasklet_kill(pch->cyclic_task);
+			pch->cyclic_task = NULL;
+		}
+	}
+
 	spin_unlock_irqrestore(&pch->lock, flags);
 }
 
@@ -547,6 +599,63 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
 	return burst_len;
 }
 
+static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
+		size_t period_len, enum dma_data_direction direction)
+{
+	struct dma_pl330_desc *desc;
+	struct dma_pl330_chan *pch = to_pchan(chan);
+	struct dma_pl330_peri *peri = chan->private;
+	dma_addr_t dst;
+	dma_addr_t src;
+
+	pch = to_pchan(chan);
+	if (!pch)
+		return NULL;
+
+	desc = pl330_get_desc(pch);
+	if (!desc) {
+		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+			__func__, __LINE__);
+		return NULL;
+	}
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		desc->rqcfg.src_inc = 1;
+		desc->rqcfg.dst_inc = 0;
+		src = dma_addr;
+		dst = peri->fifo_addr;
+		break;
+	case DMA_FROM_DEVICE:
+		desc->rqcfg.src_inc = 0;
+		desc->rqcfg.dst_inc = 1;
+		src = peri->fifo_addr;
+		dst = dma_addr;
+		break;
+	default:
+		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
+		__func__, __LINE__);
+		return NULL;
+	}
+
+	desc->rqcfg.brst_size = peri->burst_sz;
+	desc->rqcfg.brst_len = 1;
+
+	if (!pch->cyclic_task) {
+		pch->cyclic_task =
+			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
+		tasklet_init(pch->cyclic_task,
+			pl330_tasklet_cyclic, (unsigned int)pch);
+	}
+
+	pch->cyclic = true;
+
+	fill_px(&desc->px, dst, src, period_len);
+
+	return &desc->txd;
+}
+
 static struct dma_async_tx_descriptor *
 pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
 		dma_addr_t src, size_t len, unsigned long flags)
@@ -780,6 +889,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 			case MEMTODEV:
 			case DEVTOMEM:
 				dma_cap_set(DMA_SLAVE, pd->cap_mask);
+				dma_cap_set(DMA_CYCLIC, pd->cap_mask);
 				break;
 			default:
 				dev_err(&adev->dev, "DEVTODEV Not Supported\n");
@@ -805,6 +915,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
 	pd->device_free_chan_resources = pl330_free_chan_resources;
 	pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
+	pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
 	pd->device_tx_status = pl330_tx_status;
 	pd->device_prep_slave_sg = pl330_prep_slave_sg;
 	pd->device_control = pl330_control;
-- 
1.7.1

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds DMA_CYCLIC capability that is used for audio driver.
DMA driver with DMA_CYCLIC capability reuses the dma requests that
were submitted through tx_submit().

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/dma/pl330.c |  111 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 880f010..121c75a 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -69,6 +69,11 @@ struct dma_pl330_chan {
 	 * NULL if the channel is available to be acquired.
 	 */
 	void *pl330_chid;
+
+	/* taks for cyclic capability */
+	struct tasklet_struct *cyclic_task;
+
+	bool cyclic;
 };
 
 struct dma_pl330_dmac {
@@ -184,6 +189,41 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
 	}
 }
 
+static void pl330_tasklet_cyclic(unsigned long data)
+{
+	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
+	struct dma_pl330_desc *desc, *_dt;
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	spin_lock_irqsave(&pch->lock, flags);
+
+	/* Pick up ripe tomatoes */
+	list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
+		if (desc->status == DONE) {
+			dma_async_tx_callback callback;
+
+			list_move_tail(&desc->node, &pch->work_list);
+			pch->completed = desc->txd.cookie;
+
+			desc->status = PREP;
+
+			/* Try to submit a req imm.
+			next to the last completed cookie */
+			fill_queue(pch);
+
+			/* Make sure the PL330 Channel thread is active */
+			pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START);
+
+			callback = desc->txd.callback;
+			if (callback)
+				callback(desc->txd.callback_param);
+
+		}
+
+	spin_unlock_irqrestore(&pch->lock, flags);
+}
+
 static void pl330_tasklet(unsigned long data)
 {
 	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
@@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
 
 	spin_unlock_irqrestore(&pch->lock, flags);
 
+	if (pch->cyclic_task)
+		tasklet_schedule(pch->cyclic_task);
+	else
 	tasklet_schedule(&pch->task);
 }
 
@@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
 	pl330_release_channel(pch->pl330_chid);
 	pch->pl330_chid = NULL;
 
+	if (pch->cyclic) {
+		pch->cyclic = false;
+		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
+		if (pch->cyclic_task) {
+			tasklet_kill(pch->cyclic_task);
+			pch->cyclic_task = NULL;
+		}
+	}
+
 	spin_unlock_irqrestore(&pch->lock, flags);
 }
 
@@ -547,6 +599,63 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
 	return burst_len;
 }
 
+static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
+		size_t period_len, enum dma_data_direction direction)
+{
+	struct dma_pl330_desc *desc;
+	struct dma_pl330_chan *pch = to_pchan(chan);
+	struct dma_pl330_peri *peri = chan->private;
+	dma_addr_t dst;
+	dma_addr_t src;
+
+	pch = to_pchan(chan);
+	if (!pch)
+		return NULL;
+
+	desc = pl330_get_desc(pch);
+	if (!desc) {
+		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+			__func__, __LINE__);
+		return NULL;
+	}
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		desc->rqcfg.src_inc = 1;
+		desc->rqcfg.dst_inc = 0;
+		src = dma_addr;
+		dst = peri->fifo_addr;
+		break;
+	case DMA_FROM_DEVICE:
+		desc->rqcfg.src_inc = 0;
+		desc->rqcfg.dst_inc = 1;
+		src = peri->fifo_addr;
+		dst = dma_addr;
+		break;
+	default:
+		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
+		__func__, __LINE__);
+		return NULL;
+	}
+
+	desc->rqcfg.brst_size = peri->burst_sz;
+	desc->rqcfg.brst_len = 1;
+
+	if (!pch->cyclic_task) {
+		pch->cyclic_task =
+			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
+		tasklet_init(pch->cyclic_task,
+			pl330_tasklet_cyclic, (unsigned int)pch);
+	}
+
+	pch->cyclic = true;
+
+	fill_px(&desc->px, dst, src, period_len);
+
+	return &desc->txd;
+}
+
 static struct dma_async_tx_descriptor *
 pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
 		dma_addr_t src, size_t len, unsigned long flags)
@@ -780,6 +889,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 			case MEMTODEV:
 			case DEVTOMEM:
 				dma_cap_set(DMA_SLAVE, pd->cap_mask);
+				dma_cap_set(DMA_CYCLIC, pd->cap_mask);
 				break;
 			default:
 				dev_err(&adev->dev, "DEVTODEV Not Supported\n");
@@ -805,6 +915,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
 	pd->device_free_chan_resources = pl330_free_chan_resources;
 	pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
+	pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
 	pd->device_tx_status = pl330_tx_status;
 	pd->device_prep_slave_sg = pl330_prep_slave_sg;
 	pd->device_control = pl330_control;
-- 
1.7.1

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

* [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch adds to support PL330-DMA driver on DMADEVICE for S5P SoCs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-exynos4/include/mach/dma.h           |    4 +-
 arch/arm/mach-s5p64x0/include/mach/dma.h           |    2 +-
 arch/arm/mach-s5pc100/include/mach/dma.h           |    2 +-
 arch/arm/mach-s5pv210/include/mach/dma.h           |    2 +-
 arch/arm/plat-samsung/Kconfig                      |    8 +++++++
 .../include/plat/{s3c-dma-pl330.h => dma-pl330.h}  |   21 +++++++++++++------
 .../plat-samsung/include/plat/s3c-pl330-pdata.h    |    2 +-
 7 files changed, 28 insertions(+), 13 deletions(-)
 rename arch/arm/plat-samsung/include/plat/{s3c-dma-pl330.h => dma-pl330.h} (84%)

diff --git a/arch/arm/mach-exynos4/include/mach/dma.h b/arch/arm/mach-exynos4/include/mach/dma.h
index 81209eb..201842a 100644
--- a/arch/arm/mach-exynos4/include/mach/dma.h
+++ b/arch/arm/mach-exynos4/include/mach/dma.h
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
index 81209eb..1beae2c 100644
--- a/arch/arm/mach-s5p64x0/include/mach/dma.h
+++ b/arch/arm/mach-s5p64x0/include/mach/dma.h
@@ -21,6 +21,6 @@
 #define __MACH_DMA_H
 
 /* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/dma.h b/arch/arm/mach-s5pc100/include/mach/dma.h
index 81209eb..1beae2c 100644
--- a/arch/arm/mach-s5pc100/include/mach/dma.h
+++ b/arch/arm/mach-s5pc100/include/mach/dma.h
@@ -21,6 +21,6 @@
 #define __MACH_DMA_H
 
 /* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/mach-s5pv210/include/mach/dma.h
index 81209eb..1beae2c 100644
--- a/arch/arm/mach-s5pv210/include/mach/dma.h
+++ b/arch/arm/mach-s5pv210/include/mach/dma.h
@@ -21,6 +21,6 @@
 #define __MACH_DMA_H
 
 /* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 4d79519..cb170a6 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -300,6 +300,14 @@ config S3C_PL330_DMA
 	help
 	  S3C DMA API Driver for PL330 DMAC.
 
+config DMADEV_PL330
+	bool
+	select DMADEVICES
+	select PL330_DMA
+	select ARM_AMBA
+	help
+	  Use DMA device engine for PL330 DMAC.
+
 comment "Power management"
 
 config SAMSUNG_PM_DEBUG
diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
similarity index 84%
rename from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
rename to arch/arm/plat-samsung/include/plat/dma-pl330.h
index 8107442..c402719 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -8,19 +8,18 @@
  * (at your option) any later version.
  */
 
-#ifndef	__S3C_DMA_PL330_H_
-#define	__S3C_DMA_PL330_H_
-
-#define S3C2410_DMAF_AUTOSTART		(1 << 0)
-#define S3C2410_DMAF_CIRCULAR		(1 << 1)
+#ifndef __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
 
+#define S3C2410_DMAF_AUTOSTART	(1 << 0)
+#define S3C2410_DMAF_CIRCULAR	(1 << 1)
 /*
  * PL330 can assign any channel to communicate with
  * any of the peripherals attched to the DMAC.
  * For the sake of consistency across client drivers,
  * We keep the channel names unchanged and only add
  * missing peripherals are added.
- * Order is not important since S3C PL330 API driver
+ * Order is not important since DMA PL330 API driver
  * use these just as IDs.
  */
 enum dma_ch {
@@ -84,6 +83,14 @@ enum dma_ch {
 	DMACH_SLIMBUS4_TX,
 	DMACH_SLIMBUS5_RX,
 	DMACH_SLIMBUS5_TX,
+	DMACH_MTOM_0,
+	DMACH_MTOM_1,
+	DMACH_MTOM_2,
+	DMACH_MTOM_3,
+	DMACH_MTOM_4,
+	DMACH_MTOM_5,
+	DMACH_MTOM_6,
+	DMACH_MTOM_7,
 	/* END Marker, also used to denote a reserved channel */
 	DMACH_MAX,
 };
@@ -95,4 +102,4 @@ static inline bool s3c_dma_has_circular(void)
 
 #include <plat/dma.h>
 
-#endif	/* __S3C_DMA_PL330_H_ */
+#endif	/* __DMA_PL330_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
index bf5e2a9..64fdf66 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
+++ b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
@@ -12,7 +12,7 @@
 #ifndef __S3C_PL330_PDATA_H
 #define __S3C_PL330_PDATA_H
 
-#include <plat/s3c-dma-pl330.h>
+#include <plat/dma-pl330.h>
 
 /*
  * Every PL330 DMAC has max 32 peripheral interfaces,
-- 
1.7.1

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

* [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds to support PL330-DMA driver on DMADEVICE for S5P SoCs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-exynos4/include/mach/dma.h           |    4 +-
 arch/arm/mach-s5p64x0/include/mach/dma.h           |    2 +-
 arch/arm/mach-s5pc100/include/mach/dma.h           |    2 +-
 arch/arm/mach-s5pv210/include/mach/dma.h           |    2 +-
 arch/arm/plat-samsung/Kconfig                      |    8 +++++++
 .../include/plat/{s3c-dma-pl330.h => dma-pl330.h}  |   21 +++++++++++++------
 .../plat-samsung/include/plat/s3c-pl330-pdata.h    |    2 +-
 7 files changed, 28 insertions(+), 13 deletions(-)
 rename arch/arm/plat-samsung/include/plat/{s3c-dma-pl330.h => dma-pl330.h} (84%)

diff --git a/arch/arm/mach-exynos4/include/mach/dma.h b/arch/arm/mach-exynos4/include/mach/dma.h
index 81209eb..201842a 100644
--- a/arch/arm/mach-exynos4/include/mach/dma.h
+++ b/arch/arm/mach-exynos4/include/mach/dma.h
@@ -20,7 +20,7 @@
 #ifndef __MACH_DMA_H
 #define __MACH_DMA_H
 
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+/* This platform uses the common DMA API driver for PL330 */
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
index 81209eb..1beae2c 100644
--- a/arch/arm/mach-s5p64x0/include/mach/dma.h
+++ b/arch/arm/mach-s5p64x0/include/mach/dma.h
@@ -21,6 +21,6 @@
 #define __MACH_DMA_H
 
 /* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/dma.h b/arch/arm/mach-s5pc100/include/mach/dma.h
index 81209eb..1beae2c 100644
--- a/arch/arm/mach-s5pc100/include/mach/dma.h
+++ b/arch/arm/mach-s5pc100/include/mach/dma.h
@@ -21,6 +21,6 @@
 #define __MACH_DMA_H
 
 /* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/mach-s5pv210/include/mach/dma.h
index 81209eb..1beae2c 100644
--- a/arch/arm/mach-s5pv210/include/mach/dma.h
+++ b/arch/arm/mach-s5pv210/include/mach/dma.h
@@ -21,6 +21,6 @@
 #define __MACH_DMA_H
 
 /* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
+#include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 4d79519..cb170a6 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -300,6 +300,14 @@ config S3C_PL330_DMA
 	help
 	  S3C DMA API Driver for PL330 DMAC.
 
+config DMADEV_PL330
+	bool
+	select DMADEVICES
+	select PL330_DMA
+	select ARM_AMBA
+	help
+	  Use DMA device engine for PL330 DMAC.
+
 comment "Power management"
 
 config SAMSUNG_PM_DEBUG
diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
similarity index 84%
rename from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
rename to arch/arm/plat-samsung/include/plat/dma-pl330.h
index 8107442..c402719 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -8,19 +8,18 @@
  * (at your option) any later version.
  */
 
-#ifndef	__S3C_DMA_PL330_H_
-#define	__S3C_DMA_PL330_H_
-
-#define S3C2410_DMAF_AUTOSTART		(1 << 0)
-#define S3C2410_DMAF_CIRCULAR		(1 << 1)
+#ifndef __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
 
+#define S3C2410_DMAF_AUTOSTART	(1 << 0)
+#define S3C2410_DMAF_CIRCULAR	(1 << 1)
 /*
  * PL330 can assign any channel to communicate with
  * any of the peripherals attched to the DMAC.
  * For the sake of consistency across client drivers,
  * We keep the channel names unchanged and only add
  * missing peripherals are added.
- * Order is not important since S3C PL330 API driver
+ * Order is not important since DMA PL330 API driver
  * use these just as IDs.
  */
 enum dma_ch {
@@ -84,6 +83,14 @@ enum dma_ch {
 	DMACH_SLIMBUS4_TX,
 	DMACH_SLIMBUS5_RX,
 	DMACH_SLIMBUS5_TX,
+	DMACH_MTOM_0,
+	DMACH_MTOM_1,
+	DMACH_MTOM_2,
+	DMACH_MTOM_3,
+	DMACH_MTOM_4,
+	DMACH_MTOM_5,
+	DMACH_MTOM_6,
+	DMACH_MTOM_7,
 	/* END Marker, also used to denote a reserved channel */
 	DMACH_MAX,
 };
@@ -95,4 +102,4 @@ static inline bool s3c_dma_has_circular(void)
 
 #include <plat/dma.h>
 
-#endif	/* __S3C_DMA_PL330_H_ */
+#endif	/* __DMA_PL330_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
index bf5e2a9..64fdf66 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
+++ b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
@@ -12,7 +12,7 @@
 #ifndef __S3C_PL330_PDATA_H
 #define __S3C_PL330_PDATA_H
 
-#include <plat/s3c-dma-pl330.h>
+#include <plat/dma-pl330.h>
 
 /*
  * Every PL330 DMAC has max 32 peripheral interfaces,
-- 
1.7.1

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch adds common DMA operations which are used for Samsung DMA
drivers. Currently there are two types of DMA driver for Samsung SoCs.
The one is S3C-DMA for S3C SoCs and the other is PL330-DMA for S5P SoCs.
This patch provides funcion pointers for common DMA operations to DMA
client driver like SPI and Audio. It makes DMA client drivers support
multi-platform.
In addition, this common DMA operations implement the shared actions
that are needed for DMA client driver. For example shared actions are
filter() function for dma_request_channel() and parameter passing for
device_prep_slave_sg().

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 arch/arm/mach-s3c2410/include/mach/dma.h       |    8 ++-
 arch/arm/mach-s3c64xx/include/mach/dma.h       |    4 +
 arch/arm/plat-samsung/Makefile                 |    6 +-
 arch/arm/plat-samsung/dma-ops.c                |  133 ++++++++++++++++++++++++
 arch/arm/plat-samsung/include/plat/dma-ops.h   |   64 +++++++++++
 arch/arm/plat-samsung/include/plat/dma-pl330.h |    4 +
 arch/arm/plat-samsung/include/plat/dma.h       |    1 +
 arch/arm/plat-samsung/s3c-dma-ops.c            |  133 ++++++++++++++++++++++++
 8 files changed, 350 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/plat-samsung/dma-ops.c
 create mode 100644 arch/arm/plat-samsung/include/plat/dma-ops.h
 create mode 100644 arch/arm/plat-samsung/s3c-dma-ops.c

diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h
index b2b2a5b..e61a91f 100644
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#include <plat/dma.h>
 #include <linux/sysdev.h>
 
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
@@ -51,6 +50,13 @@ enum dma_ch {
 	DMACH_MAX,		/* the end entry */
 };
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return false;
+}
+
+#include <plat/dma.h>
+
 #define DMACH_LOW_LEVEL	(1<<28)	/* use this to specifiy hardware ch no */
 
 /* we have 4 dma channels */
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index 0a5d926..49c3a53 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -63,6 +63,10 @@ static __inline__ bool s3c_dma_has_circular(void)
 	return true;
 }
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return false;
+}
 #define S3C2410_DMAF_CIRCULAR		(1 << 0)
 
 #include <plat/dma.h>
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 53eb15b..9ecf2aa 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -62,9 +62,11 @@ obj-$(CONFIG_SAMSUNG_DEV_PWM)	+= dev-pwm.o
 
 # DMA support
 
-obj-$(CONFIG_S3C_DMA)		+= dma.o
+obj-$(CONFIG_S3C_DMA)		+= dma.o s3c-dma-ops.o
 
-obj-$(CONFIG_S3C_PL330_DMA)	+= s3c-pl330.o
+obj-$(CONFIG_DMADEV_PL330)	+= dma-ops.o
+
+obj-$(CONFIG_S3C_PL330_DMA)	+= s3c-pl330.o s3c-dma-ops.o
 
 # PM support
 
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
new file mode 100644
index 0000000..9053433
--- /dev/null
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -0,0 +1,133 @@
+/* linux/arch/arm/plat-samsung/dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung DMA Operations
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/amba/pl330.h>
+
+#include <mach/dma.h>
+
+static bool pl330_filter(struct dma_chan *chan, void *param)
+{
+	struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private;
+	unsigned dma_ch = (unsigned)param;
+
+	if (peri->peri_id != dma_ch)
+		return false;
+
+	return true;
+}
+
+static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
+				struct samsung_dma_info *info)
+{
+	struct dma_chan *chan;
+	dma_cap_mask_t mask;
+	struct dma_slave_config slave_config;
+
+	dma_cap_zero(mask);
+	dma_cap_set(info->cap, mask);
+
+	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
+
+	if (info->direction == DMA_FROM_DEVICE) {
+		memset(&slave_config, 0, sizeof(struct dma_slave_config));
+		slave_config.direction = info->direction;
+		slave_config.src_addr = info->fifo;
+		slave_config.src_addr_width = info->width;
+		dmaengine_slave_config(chan, &slave_config);
+	} else if (info->direction == DMA_TO_DEVICE) {
+		memset(&slave_config, 0, sizeof(struct dma_slave_config));
+		slave_config.direction = info->direction;
+		slave_config.dst_addr = info->fifo;
+		slave_config.dst_addr_width = info->width;
+		dmaengine_slave_config(chan, &slave_config);
+	}
+
+	return (unsigned)chan;
+}
+
+static int samsung_dmadev_release(unsigned ch,
+			struct s3c2410_dma_client *client)
+{
+	dma_release_channel((struct dma_chan *)ch);
+
+	return 0;
+}
+
+static int samsung_dmadev_prepare(unsigned ch,
+			struct samsung_dma_prep_info *info)
+{
+	struct scatterlist sg;
+	struct dma_chan *chan = (struct dma_chan *)ch;
+	struct dma_async_tx_descriptor *desc;
+
+	switch (info->cap) {
+	case DMA_SLAVE:
+		sg_init_table(&sg, 1);
+		sg_dma_len(&sg) = info->len;
+		sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
+			    info->len, offset_in_page(info->buf));
+		sg_dma_address(&sg) = info->buf;
+
+		desc = chan->device->device_prep_slave_sg(chan,
+			&sg, 1, info->direction, DMA_PREP_INTERRUPT);
+		break;
+	case DMA_CYCLIC:
+		desc = chan->device->device_prep_dma_cyclic(chan,
+			info->buf, info->len, info->period, info->direction);
+		break;
+	default:
+		dev_err(&chan->dev->device, "unsupported format\n");
+		return -EFAULT;
+	}
+
+	if (!desc) {
+		dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
+		return -EFAULT;
+	}
+
+	desc->callback = info->fp;
+	desc->callback_param = info->fp_param;
+
+	dmaengine_submit((struct dma_async_tx_descriptor *)desc);
+
+	return 0;
+}
+
+static inline int samsung_dmadev_trigger(unsigned ch)
+{
+	dma_async_issue_pending((struct dma_chan *)ch);
+
+	return 0;
+}
+
+static inline int samsung_dmadev_flush(unsigned ch)
+{
+	return dmaengine_terminate_all((struct dma_chan *)ch);
+}
+
+struct samsung_dma_ops dmadev_ops = {
+	.request	= samsung_dmadev_request,
+	.release	= samsung_dmadev_release,
+	.prepare	= samsung_dmadev_prepare,
+	.trigger	= samsung_dmadev_trigger,
+	.started	= NULL,
+	.flush		= samsung_dmadev_flush,
+	.stop		= samsung_dmadev_flush,
+};
+
+void *samsung_dmadev_get_ops(void)
+{
+	return &dmadev_ops;
+}
+EXPORT_SYMBOL(samsung_dmadev_get_ops);
diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h
new file mode 100644
index 0000000..e5a68c0
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -0,0 +1,64 @@
+/* arch/arm/plat-samsung/include/plat/dma-ops.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung DMA support
+ *
+ * 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 __SAMSUNG_DMA_OPS_H_
+#define __SAMSUNG_DMA_OPS_H_ __FILE__
+
+#include <linux/dmaengine.h>
+
+struct samsung_dma_prep_info {
+	enum dma_transaction_type cap;
+	enum dma_data_direction direction;
+	unsigned buf;
+	unsigned long period;
+	unsigned long len;
+	void (*fp)(void *data);
+	void *fp_param;
+};
+
+struct samsung_dma_info {
+	enum dma_transaction_type cap;
+	enum dma_data_direction direction;
+	enum dma_slave_buswidth width;
+	unsigned fifo;
+	struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+	bool init;
+	unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
+	int (*release)(unsigned ch, struct s3c2410_dma_client *client);
+	int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+	int (*trigger)(unsigned ch);
+	int (*started)(unsigned ch);
+	int (*flush)(unsigned ch);
+	int (*stop)(unsigned ch);
+};
+
+extern void *samsung_dmadev_get_ops(void);
+extern void *s3c_dma_get_ops(void);
+
+static inline void *__samsung_dma_get_ops(void)
+{
+	if (samsung_dma_is_dmadev())
+		return samsung_dmadev_get_ops();
+	else
+		return s3c_dma_get_ops();
+}
+
+/*
+ * samsung_dma_get_ops
+ * get the set of samsung dma operations
+ */
+#define samsung_dma_get_ops() __samsung_dma_get_ops()
+
+#endif /* __SAMSUNG_DMA_OPS_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index c402719..687489e 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -100,6 +100,10 @@ static inline bool s3c_dma_has_circular(void)
 	return true;
 }
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return true;
+}
 #include <plat/dma.h>
 
 #endif	/* __DMA_PL330_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h
index 2e8f8c6..e87c6be 100644
--- a/arch/arm/plat-samsung/include/plat/dma.h
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -125,3 +125,4 @@ extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
 extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
 
 
+#include <plat/dma-ops.h>
diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
new file mode 100644
index 0000000..33ab324
--- /dev/null
+++ b/arch/arm/plat-samsung/s3c-dma-ops.c
@@ -0,0 +1,133 @@
+/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung S3C-DMA Operations
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <mach/dma.h>
+
+struct cb_data {
+	void (*fp) (void *);
+	void *fp_param;
+	unsigned ch;
+	struct list_head node;
+};
+
+static LIST_HEAD(dma_list);
+
+static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
+		       int size, enum s3c2410_dma_buffresult res)
+{
+	struct cb_data *data = param;
+
+	data->fp(data->fp_param);
+}
+
+static unsigned s3c_dma_request(enum dma_ch dma_ch,
+				 struct samsung_dma_info *info)
+{
+	struct cb_data *data;
+
+	if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
+		s3c2410_dma_free(dma_ch, info->client);
+		return 0;
+	}
+
+	data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
+	data->ch = dma_ch;
+	list_add_tail(&data->node, &dma_list);
+
+	if (info->direction == DMA_FROM_DEVICE)
+		s3c2410_dma_devconfig(dma_ch, S3C2410_DMASRC_HW, info->fifo);
+	else
+		s3c2410_dma_devconfig(dma_ch, S3C2410_DMASRC_MEM, info->fifo);
+
+	if (info->cap == DMA_CYCLIC)
+		s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
+	s3c2410_dma_config(dma_ch, info->width);
+
+	return (unsigned)dma_ch;
+}
+
+static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+{
+	struct cb_data *data;
+
+	list_for_each_entry(data, &dma_list, node)
+		if (data->ch == ch)
+			break;
+	list_del(&data->node);
+
+	s3c2410_dma_free(ch, client);
+	kfree(data);
+
+	return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+{
+	struct cb_data *data;
+	int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+
+	list_for_each_entry(data, &dma_list, node)
+		if (data->ch == ch)
+			break;
+
+	if (!data->fp) {
+		s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
+		data->fp = info->fp;
+		data->fp_param = info->fp_param;
+	}
+
+	s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+
+	return 0;
+}
+
+static inline int s3c_dma_trigger(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
+}
+
+static inline int s3c_dma_started(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
+}
+
+static inline int s3c_dma_flush(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
+}
+
+static inline int s3c_dma_stop(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
+}
+
+static struct samsung_dma_ops s3c_dma_ops = {
+	.request	= s3c_dma_request,
+	.release	= s3c_dma_release,
+	.prepare	= s3c_dma_prepare,
+	.trigger	= s3c_dma_trigger,
+	.started	= s3c_dma_started,
+	.flush		= s3c_dma_flush,
+	.stop		= s3c_dma_stop,
+};
+
+void *s3c_dma_get_ops(void)
+{
+	return &s3c_dma_ops;
+}
+EXPORT_SYMBOL(s3c_dma_get_ops);
-- 
1.7.1

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds common DMA operations which are used for Samsung DMA
drivers. Currently there are two types of DMA driver for Samsung SoCs.
The one is S3C-DMA for S3C SoCs and the other is PL330-DMA for S5P SoCs.
This patch provides funcion pointers for common DMA operations to DMA
client driver like SPI and Audio. It makes DMA client drivers support
multi-platform.
In addition, this common DMA operations implement the shared actions
that are needed for DMA client driver. For example shared actions are
filter() function for dma_request_channel() and parameter passing for
device_prep_slave_sg().

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 arch/arm/mach-s3c2410/include/mach/dma.h       |    8 ++-
 arch/arm/mach-s3c64xx/include/mach/dma.h       |    4 +
 arch/arm/plat-samsung/Makefile                 |    6 +-
 arch/arm/plat-samsung/dma-ops.c                |  133 ++++++++++++++++++++++++
 arch/arm/plat-samsung/include/plat/dma-ops.h   |   64 +++++++++++
 arch/arm/plat-samsung/include/plat/dma-pl330.h |    4 +
 arch/arm/plat-samsung/include/plat/dma.h       |    1 +
 arch/arm/plat-samsung/s3c-dma-ops.c            |  133 ++++++++++++++++++++++++
 8 files changed, 350 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/plat-samsung/dma-ops.c
 create mode 100644 arch/arm/plat-samsung/include/plat/dma-ops.h
 create mode 100644 arch/arm/plat-samsung/s3c-dma-ops.c

diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h
index b2b2a5b..e61a91f 100644
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#include <plat/dma.h>
 #include <linux/sysdev.h>
 
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
@@ -51,6 +50,13 @@ enum dma_ch {
 	DMACH_MAX,		/* the end entry */
 };
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return false;
+}
+
+#include <plat/dma.h>
+
 #define DMACH_LOW_LEVEL	(1<<28)	/* use this to specifiy hardware ch no */
 
 /* we have 4 dma channels */
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index 0a5d926..49c3a53 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -63,6 +63,10 @@ static __inline__ bool s3c_dma_has_circular(void)
 	return true;
 }
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return false;
+}
 #define S3C2410_DMAF_CIRCULAR		(1 << 0)
 
 #include <plat/dma.h>
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 53eb15b..9ecf2aa 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -62,9 +62,11 @@ obj-$(CONFIG_SAMSUNG_DEV_PWM)	+= dev-pwm.o
 
 # DMA support
 
-obj-$(CONFIG_S3C_DMA)		+= dma.o
+obj-$(CONFIG_S3C_DMA)		+= dma.o s3c-dma-ops.o
 
-obj-$(CONFIG_S3C_PL330_DMA)	+= s3c-pl330.o
+obj-$(CONFIG_DMADEV_PL330)	+= dma-ops.o
+
+obj-$(CONFIG_S3C_PL330_DMA)	+= s3c-pl330.o s3c-dma-ops.o
 
 # PM support
 
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
new file mode 100644
index 0000000..9053433
--- /dev/null
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -0,0 +1,133 @@
+/* linux/arch/arm/plat-samsung/dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung DMA Operations
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/amba/pl330.h>
+
+#include <mach/dma.h>
+
+static bool pl330_filter(struct dma_chan *chan, void *param)
+{
+	struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private;
+	unsigned dma_ch = (unsigned)param;
+
+	if (peri->peri_id != dma_ch)
+		return false;
+
+	return true;
+}
+
+static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
+				struct samsung_dma_info *info)
+{
+	struct dma_chan *chan;
+	dma_cap_mask_t mask;
+	struct dma_slave_config slave_config;
+
+	dma_cap_zero(mask);
+	dma_cap_set(info->cap, mask);
+
+	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
+
+	if (info->direction == DMA_FROM_DEVICE) {
+		memset(&slave_config, 0, sizeof(struct dma_slave_config));
+		slave_config.direction = info->direction;
+		slave_config.src_addr = info->fifo;
+		slave_config.src_addr_width = info->width;
+		dmaengine_slave_config(chan, &slave_config);
+	} else if (info->direction == DMA_TO_DEVICE) {
+		memset(&slave_config, 0, sizeof(struct dma_slave_config));
+		slave_config.direction = info->direction;
+		slave_config.dst_addr = info->fifo;
+		slave_config.dst_addr_width = info->width;
+		dmaengine_slave_config(chan, &slave_config);
+	}
+
+	return (unsigned)chan;
+}
+
+static int samsung_dmadev_release(unsigned ch,
+			struct s3c2410_dma_client *client)
+{
+	dma_release_channel((struct dma_chan *)ch);
+
+	return 0;
+}
+
+static int samsung_dmadev_prepare(unsigned ch,
+			struct samsung_dma_prep_info *info)
+{
+	struct scatterlist sg;
+	struct dma_chan *chan = (struct dma_chan *)ch;
+	struct dma_async_tx_descriptor *desc;
+
+	switch (info->cap) {
+	case DMA_SLAVE:
+		sg_init_table(&sg, 1);
+		sg_dma_len(&sg) = info->len;
+		sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
+			    info->len, offset_in_page(info->buf));
+		sg_dma_address(&sg) = info->buf;
+
+		desc = chan->device->device_prep_slave_sg(chan,
+			&sg, 1, info->direction, DMA_PREP_INTERRUPT);
+		break;
+	case DMA_CYCLIC:
+		desc = chan->device->device_prep_dma_cyclic(chan,
+			info->buf, info->len, info->period, info->direction);
+		break;
+	default:
+		dev_err(&chan->dev->device, "unsupported format\n");
+		return -EFAULT;
+	}
+
+	if (!desc) {
+		dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
+		return -EFAULT;
+	}
+
+	desc->callback = info->fp;
+	desc->callback_param = info->fp_param;
+
+	dmaengine_submit((struct dma_async_tx_descriptor *)desc);
+
+	return 0;
+}
+
+static inline int samsung_dmadev_trigger(unsigned ch)
+{
+	dma_async_issue_pending((struct dma_chan *)ch);
+
+	return 0;
+}
+
+static inline int samsung_dmadev_flush(unsigned ch)
+{
+	return dmaengine_terminate_all((struct dma_chan *)ch);
+}
+
+struct samsung_dma_ops dmadev_ops = {
+	.request	= samsung_dmadev_request,
+	.release	= samsung_dmadev_release,
+	.prepare	= samsung_dmadev_prepare,
+	.trigger	= samsung_dmadev_trigger,
+	.started	= NULL,
+	.flush		= samsung_dmadev_flush,
+	.stop		= samsung_dmadev_flush,
+};
+
+void *samsung_dmadev_get_ops(void)
+{
+	return &dmadev_ops;
+}
+EXPORT_SYMBOL(samsung_dmadev_get_ops);
diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h
new file mode 100644
index 0000000..e5a68c0
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -0,0 +1,64 @@
+/* arch/arm/plat-samsung/include/plat/dma-ops.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung DMA support
+ *
+ * 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 __SAMSUNG_DMA_OPS_H_
+#define __SAMSUNG_DMA_OPS_H_ __FILE__
+
+#include <linux/dmaengine.h>
+
+struct samsung_dma_prep_info {
+	enum dma_transaction_type cap;
+	enum dma_data_direction direction;
+	unsigned buf;
+	unsigned long period;
+	unsigned long len;
+	void (*fp)(void *data);
+	void *fp_param;
+};
+
+struct samsung_dma_info {
+	enum dma_transaction_type cap;
+	enum dma_data_direction direction;
+	enum dma_slave_buswidth width;
+	unsigned fifo;
+	struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+	bool init;
+	unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
+	int (*release)(unsigned ch, struct s3c2410_dma_client *client);
+	int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+	int (*trigger)(unsigned ch);
+	int (*started)(unsigned ch);
+	int (*flush)(unsigned ch);
+	int (*stop)(unsigned ch);
+};
+
+extern void *samsung_dmadev_get_ops(void);
+extern void *s3c_dma_get_ops(void);
+
+static inline void *__samsung_dma_get_ops(void)
+{
+	if (samsung_dma_is_dmadev())
+		return samsung_dmadev_get_ops();
+	else
+		return s3c_dma_get_ops();
+}
+
+/*
+ * samsung_dma_get_ops
+ * get the set of samsung dma operations
+ */
+#define samsung_dma_get_ops() __samsung_dma_get_ops()
+
+#endif /* __SAMSUNG_DMA_OPS_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index c402719..687489e 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -100,6 +100,10 @@ static inline bool s3c_dma_has_circular(void)
 	return true;
 }
 
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return true;
+}
 #include <plat/dma.h>
 
 #endif	/* __DMA_PL330_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h
index 2e8f8c6..e87c6be 100644
--- a/arch/arm/plat-samsung/include/plat/dma.h
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -125,3 +125,4 @@ extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
 extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
 
 
+#include <plat/dma-ops.h>
diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
new file mode 100644
index 0000000..33ab324
--- /dev/null
+++ b/arch/arm/plat-samsung/s3c-dma-ops.c
@@ -0,0 +1,133 @@
+/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung S3C-DMA Operations
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <mach/dma.h>
+
+struct cb_data {
+	void (*fp) (void *);
+	void *fp_param;
+	unsigned ch;
+	struct list_head node;
+};
+
+static LIST_HEAD(dma_list);
+
+static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
+		       int size, enum s3c2410_dma_buffresult res)
+{
+	struct cb_data *data = param;
+
+	data->fp(data->fp_param);
+}
+
+static unsigned s3c_dma_request(enum dma_ch dma_ch,
+				 struct samsung_dma_info *info)
+{
+	struct cb_data *data;
+
+	if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
+		s3c2410_dma_free(dma_ch, info->client);
+		return 0;
+	}
+
+	data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
+	data->ch = dma_ch;
+	list_add_tail(&data->node, &dma_list);
+
+	if (info->direction == DMA_FROM_DEVICE)
+		s3c2410_dma_devconfig(dma_ch, S3C2410_DMASRC_HW, info->fifo);
+	else
+		s3c2410_dma_devconfig(dma_ch, S3C2410_DMASRC_MEM, info->fifo);
+
+	if (info->cap == DMA_CYCLIC)
+		s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
+	s3c2410_dma_config(dma_ch, info->width);
+
+	return (unsigned)dma_ch;
+}
+
+static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+{
+	struct cb_data *data;
+
+	list_for_each_entry(data, &dma_list, node)
+		if (data->ch == ch)
+			break;
+	list_del(&data->node);
+
+	s3c2410_dma_free(ch, client);
+	kfree(data);
+
+	return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+{
+	struct cb_data *data;
+	int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+
+	list_for_each_entry(data, &dma_list, node)
+		if (data->ch == ch)
+			break;
+
+	if (!data->fp) {
+		s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
+		data->fp = info->fp;
+		data->fp_param = info->fp_param;
+	}
+
+	s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+
+	return 0;
+}
+
+static inline int s3c_dma_trigger(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
+}
+
+static inline int s3c_dma_started(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
+}
+
+static inline int s3c_dma_flush(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
+}
+
+static inline int s3c_dma_stop(unsigned ch)
+{
+	return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
+}
+
+static struct samsung_dma_ops s3c_dma_ops = {
+	.request	= s3c_dma_request,
+	.release	= s3c_dma_release,
+	.prepare	= s3c_dma_prepare,
+	.trigger	= s3c_dma_trigger,
+	.started	= s3c_dma_started,
+	.flush		= s3c_dma_flush,
+	.stop		= s3c_dma_stop,
+};
+
+void *s3c_dma_get_ops(void)
+{
+	return &s3c_dma_ops;
+}
+EXPORT_SYMBOL(s3c_dma_get_ops);
-- 
1.7.1

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

* [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch makes Samsung EXYNOS4 to use DMA PL330 driver
on DMADEVICE. The EXYNOS4 uses DMA generic APIs instead of
SAMSUNG specific S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-exynos4/Kconfig |    2 +-
 arch/arm/mach-exynos4/clock.c |   16 +-
 arch/arm/mach-exynos4/dma.c   |  323 +++++++++++++++++++++++++++--------------
 3 files changed, 221 insertions(+), 120 deletions(-)

diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc3..5cc9b7a 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -11,7 +11,7 @@ if ARCH_EXYNOS4
 
 config CPU_EXYNOS4210
 	bool
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	help
 	  Enable EXYNOS4210 CPU support
 
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 871f9d5..1b2e78c 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -47,6 +47,11 @@ static struct clk clk_sclk_usbphy1 = {
 	.id		= -1,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
@@ -485,16 +490,11 @@ static struct clk init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 10),
 	}, {
-		.name		= "pdma",
-		.id		= 0,
+		.name		= "dma",
+		.id		= -1,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
-		.name		= "pdma",
-		.id		= 1,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
 		.name		= "adc",
 		.id		= -1,
 		.enable		= exynos4_clk_ip_peril_ctrl,
@@ -1212,5 +1212,7 @@ void __init exynos4_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
index 564bb53..e1c00cf 100644
--- a/arch/arm/mach-exynos4/dma.c
+++ b/arch/arm/mach-exynos4/dma.c
@@ -21,151 +21,250 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource exynos4_pdma0_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PDMA0,
-		.end	= EXYNOS4_PA_PDMA0 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
 	},
 };
 
-static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM2_RX,
-		[3] = DMACH_PCM2_TX,
-		[4] = DMACH_MSM_REQ0,
-		[5] = DMACH_MSM_REQ2,
-		[6] = DMACH_SPI0_RX,
-		[7] = DMACH_SPI0_TX,
-		[8] = DMACH_SPI2_RX,
-		[9] = DMACH_SPI2_TX,
-		[10] = DMACH_I2S0S_TX,
-		[11] = DMACH_I2S0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S2_RX,
-		[14] = DMACH_I2S2_TX,
-		[15] = DMACH_UART0_RX,
-		[16] = DMACH_UART0_TX,
-		[17] = DMACH_UART2_RX,
-		[18] = DMACH_UART2_TX,
-		[19] = DMACH_UART4_RX,
-		[20] = DMACH_UART4_TX,
-		[21] = DMACH_SLIMBUS0_RX,
-		[22] = DMACH_SLIMBUS0_TX,
-		[23] = DMACH_SLIMBUS2_RX,
-		[24] = DMACH_SLIMBUS2_TX,
-		[25] = DMACH_SLIMBUS4_RX,
-		[26] = DMACH_SLIMBUS4_TX,
-		[27] = DMACH_AC97_MICIN,
-		[28] = DMACH_AC97_PCMIN,
-		[29] = DMACH_AC97_PCMOUT,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata exynos4_pdma0_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma0_peri,
 };
 
-static struct platform_device exynos4_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(exynos4_pdma0_resource),
-	.resource	= exynos4_pdma0_resource,
-	.dev		= {
+struct amba_device exynos4_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &exynos4_pdma0_pdata,
-	},
+		},
+	.res = {
+		.start = EXYNOS4_PA_PDMA0,
+		.end = EXYNOS4_PA_PDMA0 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct resource exynos4_pdma1_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PDMA1,
-		.end	= EXYNOS4_PA_PDMA1 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma1_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS5_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS5_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata exynos4_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM1_RX,
-		[3] = DMACH_PCM1_TX,
-		[4] = DMACH_MSM_REQ1,
-		[5] = DMACH_MSM_REQ3,
-		[6] = DMACH_SPI1_RX,
-		[7] = DMACH_SPI1_TX,
-		[8] = DMACH_I2S0S_TX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S1_RX,
-		[12] = DMACH_I2S1_TX,
-		[13] = DMACH_UART0_RX,
-		[14] = DMACH_UART0_TX,
-		[15] = DMACH_UART1_RX,
-		[16] = DMACH_UART1_TX,
-		[17] = DMACH_UART3_RX,
-		[18] = DMACH_UART3_TX,
-		[19] = DMACH_SLIMBUS1_RX,
-		[20] = DMACH_SLIMBUS1_TX,
-		[21] = DMACH_SLIMBUS3_RX,
-		[22] = DMACH_SLIMBUS3_TX,
-		[23] = DMACH_SLIMBUS5_RX,
-		[24] = DMACH_SLIMBUS5_TX,
-		[25] = DMACH_SLIMBUS0AUX_RX,
-		[26] = DMACH_SLIMBUS0AUX_TX,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata exynos4_pdma1_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma1_peri,
 };
 
-static struct platform_device exynos4_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(exynos4_pdma1_resource),
-	.resource	= exynos4_pdma1_resource,
-	.dev		= {
+struct amba_device exynos4_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &exynos4_pdma1_pdata,
 	},
-};
-
-static struct platform_device *exynos4_dmacs[] __initdata = {
-	&exynos4_device_pdma0,
-	&exynos4_device_pdma1,
+	.res = {
+		.start = EXYNOS4_PA_PDMA1,
+		.end = EXYNOS4_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init exynos4_dma_init(void)
 {
-	platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs));
+	amba_device_register(&exynos4_device_pdma0, &iomem_resource);
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch makes Samsung EXYNOS4 to use DMA PL330 driver
on DMADEVICE. The EXYNOS4 uses DMA generic APIs instead of
SAMSUNG specific S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-exynos4/Kconfig |    2 +-
 arch/arm/mach-exynos4/clock.c |   16 +-
 arch/arm/mach-exynos4/dma.c   |  323 +++++++++++++++++++++++++++--------------
 3 files changed, 221 insertions(+), 120 deletions(-)

diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc3..5cc9b7a 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -11,7 +11,7 @@ if ARCH_EXYNOS4
 
 config CPU_EXYNOS4210
 	bool
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	help
 	  Enable EXYNOS4210 CPU support
 
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index 871f9d5..1b2e78c 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -47,6 +47,11 @@ static struct clk clk_sclk_usbphy1 = {
 	.id		= -1,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
@@ -485,16 +490,11 @@ static struct clk init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 10),
 	}, {
-		.name		= "pdma",
-		.id		= 0,
+		.name		= "dma",
+		.id		= -1,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
-		.name		= "pdma",
-		.id		= 1,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
 		.name		= "adc",
 		.id		= -1,
 		.enable		= exynos4_clk_ip_peril_ctrl,
@@ -1212,5 +1212,7 @@ void __init exynos4_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
index 564bb53..e1c00cf 100644
--- a/arch/arm/mach-exynos4/dma.c
+++ b/arch/arm/mach-exynos4/dma.c
@@ -21,151 +21,250 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource exynos4_pdma0_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PDMA0,
-		.end	= EXYNOS4_PA_PDMA0 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
 	},
 };
 
-static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM2_RX,
-		[3] = DMACH_PCM2_TX,
-		[4] = DMACH_MSM_REQ0,
-		[5] = DMACH_MSM_REQ2,
-		[6] = DMACH_SPI0_RX,
-		[7] = DMACH_SPI0_TX,
-		[8] = DMACH_SPI2_RX,
-		[9] = DMACH_SPI2_TX,
-		[10] = DMACH_I2S0S_TX,
-		[11] = DMACH_I2S0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S2_RX,
-		[14] = DMACH_I2S2_TX,
-		[15] = DMACH_UART0_RX,
-		[16] = DMACH_UART0_TX,
-		[17] = DMACH_UART2_RX,
-		[18] = DMACH_UART2_TX,
-		[19] = DMACH_UART4_RX,
-		[20] = DMACH_UART4_TX,
-		[21] = DMACH_SLIMBUS0_RX,
-		[22] = DMACH_SLIMBUS0_TX,
-		[23] = DMACH_SLIMBUS2_RX,
-		[24] = DMACH_SLIMBUS2_TX,
-		[25] = DMACH_SLIMBUS4_RX,
-		[26] = DMACH_SLIMBUS4_TX,
-		[27] = DMACH_AC97_MICIN,
-		[28] = DMACH_AC97_PCMIN,
-		[29] = DMACH_AC97_PCMOUT,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata exynos4_pdma0_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma0_peri,
 };
 
-static struct platform_device exynos4_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(exynos4_pdma0_resource),
-	.resource	= exynos4_pdma0_resource,
-	.dev		= {
+struct amba_device exynos4_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &exynos4_pdma0_pdata,
-	},
+		},
+	.res = {
+		.start = EXYNOS4_PA_PDMA0,
+		.end = EXYNOS4_PA_PDMA0 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct resource exynos4_pdma1_resource[] = {
-	[0] = {
-		.start	= EXYNOS4_PA_PDMA1,
-		.end	= EXYNOS4_PA_PDMA1 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma1_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS5_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SLIMBUS5_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata exynos4_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM1_RX,
-		[3] = DMACH_PCM1_TX,
-		[4] = DMACH_MSM_REQ1,
-		[5] = DMACH_MSM_REQ3,
-		[6] = DMACH_SPI1_RX,
-		[7] = DMACH_SPI1_TX,
-		[8] = DMACH_I2S0S_TX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S1_RX,
-		[12] = DMACH_I2S1_TX,
-		[13] = DMACH_UART0_RX,
-		[14] = DMACH_UART0_TX,
-		[15] = DMACH_UART1_RX,
-		[16] = DMACH_UART1_TX,
-		[17] = DMACH_UART3_RX,
-		[18] = DMACH_UART3_TX,
-		[19] = DMACH_SLIMBUS1_RX,
-		[20] = DMACH_SLIMBUS1_TX,
-		[21] = DMACH_SLIMBUS3_RX,
-		[22] = DMACH_SLIMBUS3_TX,
-		[23] = DMACH_SLIMBUS5_RX,
-		[24] = DMACH_SLIMBUS5_TX,
-		[25] = DMACH_SLIMBUS0AUX_RX,
-		[26] = DMACH_SLIMBUS0AUX_TX,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata exynos4_pdma1_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma1_peri,
 };
 
-static struct platform_device exynos4_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(exynos4_pdma1_resource),
-	.resource	= exynos4_pdma1_resource,
-	.dev		= {
+struct amba_device exynos4_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &exynos4_pdma1_pdata,
 	},
-};
-
-static struct platform_device *exynos4_dmacs[] __initdata = {
-	&exynos4_device_pdma0,
-	&exynos4_device_pdma1,
+	.res = {
+		.start = EXYNOS4_PA_PDMA1,
+		.end = EXYNOS4_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init exynos4_dma_init(void)
 {
-	platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs));
+	amba_device_register(&exynos4_device_pdma0, &iomem_resource);
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch makes Samsung S5PV210 to use DMA PL330 driver
on DMADEVICE. The S5PV210 uses DMA generic APIs instead of
SAMSUNG specific S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv210/Kconfig |    2 +-
 arch/arm/mach-s5pv210/clock.c |   16 +-
 arch/arm/mach-s5pv210/dma.c   |  346 +++++++++++++++++++++++++++--------------
 3 files changed, 241 insertions(+), 123 deletions(-)

diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 37b5a97..fb11e38 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -11,7 +11,7 @@ if ARCH_S5PV210
 
 config CPU_S5PV210
 	bool
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	select S5P_EXT_INT
 	select S5P_HRT
 	select S5PV210_PM if PM
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index 2d59949..dbe7285 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -221,6 +221,11 @@ static struct clk clk_pcmcdclk2 = {
 	.id		= -1,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static struct clk *clkset_vpllsrc_list[] = {
 	[0] = &clk_fin_vpll,
 	[1] = &clk_sclk_hdmi27m,
@@ -311,18 +316,12 @@ static struct clk_ops clk_fout_apll_ops = {
 
 static struct clk init_clocks_off[] = {
 	{
-		.name		= "pdma",
-		.id		= 0,
+		.name		= "dma",
+		.id		= -1,
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "pdma",
-		.id		= 1,
-		.parent		= &clk_hclk_psys.clk,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
 		.name		= "rot",
 		.id		= -1,
 		.parent		= &clk_hclk_dsys.clk,
@@ -1239,5 +1238,6 @@ void __init s5pv210_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
index 497d343..910f5a7 100644
--- a/arch/arm/mach-s5pv210/dma.c
+++ b/arch/arm/mach-s5pv210/dma.c
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pv210/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
  *
@@ -17,151 +21,265 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pv210_pdma0_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA0,
-		.end    = S5PV210_PA_PDMA0 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_SPDIF,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_MAX,
-		[15] = DMACH_MAX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_MAX,
-		[21] = DMACH_MAX,
-		[22] = DMACH_AC97_MICIN,
-		[23] = DMACH_AC97_PCMIN,
-		[24] = DMACH_AC97_PCMOUT,
-		[25] = DMACH_MAX,
-		[26] = DMACH_PWM,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pv210_pdma0_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma0_peri,
 };
 
-static struct platform_device s5pv210_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pv210_pdma0_resource),
-	.resource	= s5pv210_pdma0_resource,
-	.dev		= {
+struct amba_device s5pv210_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pv210_pdma0_pdata,
-	},
+		},
+	.res = {
+		.start = S5PV210_PA_PDMA0,
+		.end = S5PV210_PA_PDMA0 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct resource s5pv210_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA1,
-		.end    = S5PV210_PA_PDMA1 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma1_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
 	},
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_MAX,
-		[21] = DMACH_MAX,
-		[22] = DMACH_PCM0_RX,
-		[23] = DMACH_PCM0_TX,
-		[24] = DMACH_PCM1_RX,
-		[25] = DMACH_PCM1_TX,
-		[26] = DMACH_MSM_REQ0,
-		[27] = DMACH_MSM_REQ1,
-		[28] = DMACH_MSM_REQ2,
-		[29] = DMACH_MSM_REQ3,
-		[30] = DMACH_PCM2_RX,
-		[31] = DMACH_PCM2_TX,
-	},
+struct dma_pl330_platdata s5pv210_pdma1_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma1_peri,
 };
 
-static struct platform_device s5pv210_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pv210_pdma1_resource),
-	.resource	= s5pv210_pdma1_resource,
-	.dev		= {
+struct amba_device s5pv210_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pv210_pdma1_pdata,
-	},
-};
-
-static struct platform_device *s5pv210_dmacs[] __initdata = {
-	&s5pv210_device_pdma0,
-	&s5pv210_device_pdma1,
+		},
+	.res = {
+		.start = S5PV210_PA_PDMA1,
+		.end = S5PV210_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5pv210_dma_init(void)
 {
-	platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs));
+	amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch makes Samsung S5PV210 to use DMA PL330 driver
on DMADEVICE. The S5PV210 uses DMA generic APIs instead of
SAMSUNG specific S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv210/Kconfig |    2 +-
 arch/arm/mach-s5pv210/clock.c |   16 +-
 arch/arm/mach-s5pv210/dma.c   |  346 +++++++++++++++++++++++++++--------------
 3 files changed, 241 insertions(+), 123 deletions(-)

diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 37b5a97..fb11e38 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -11,7 +11,7 @@ if ARCH_S5PV210
 
 config CPU_S5PV210
 	bool
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	select S5P_EXT_INT
 	select S5P_HRT
 	select S5PV210_PM if PM
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index 2d59949..dbe7285 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -221,6 +221,11 @@ static struct clk clk_pcmcdclk2 = {
 	.id		= -1,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static struct clk *clkset_vpllsrc_list[] = {
 	[0] = &clk_fin_vpll,
 	[1] = &clk_sclk_hdmi27m,
@@ -311,18 +316,12 @@ static struct clk_ops clk_fout_apll_ops = {
 
 static struct clk init_clocks_off[] = {
 	{
-		.name		= "pdma",
-		.id		= 0,
+		.name		= "dma",
+		.id		= -1,
 		.parent		= &clk_hclk_psys.clk,
 		.enable		= s5pv210_clk_ip0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "pdma",
-		.id		= 1,
-		.parent		= &clk_hclk_psys.clk,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
 		.name		= "rot",
 		.id		= -1,
 		.parent		= &clk_hclk_dsys.clk,
@@ -1239,5 +1238,6 @@ void __init s5pv210_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
index 497d343..910f5a7 100644
--- a/arch/arm/mach-s5pv210/dma.c
+++ b/arch/arm/mach-s5pv210/dma.c
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pv210/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
  *
@@ -17,151 +21,265 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pv210_pdma0_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA0,
-		.end    = S5PV210_PA_PDMA0 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_SPDIF,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_MAX,
-		[15] = DMACH_MAX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_MAX,
-		[21] = DMACH_MAX,
-		[22] = DMACH_AC97_MICIN,
-		[23] = DMACH_AC97_PCMIN,
-		[24] = DMACH_AC97_PCMOUT,
-		[25] = DMACH_MAX,
-		[26] = DMACH_PWM,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pv210_pdma0_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma0_peri,
 };
 
-static struct platform_device s5pv210_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pv210_pdma0_resource),
-	.resource	= s5pv210_pdma0_resource,
-	.dev		= {
+struct amba_device s5pv210_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pv210_pdma0_pdata,
-	},
+		},
+	.res = {
+		.start = S5PV210_PA_PDMA0,
+		.end = S5PV210_PA_PDMA0 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct resource s5pv210_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA1,
-		.end    = S5PV210_PA_PDMA1 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma1_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
 	},
 };
 
-static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_MAX,
-		[21] = DMACH_MAX,
-		[22] = DMACH_PCM0_RX,
-		[23] = DMACH_PCM0_TX,
-		[24] = DMACH_PCM1_RX,
-		[25] = DMACH_PCM1_TX,
-		[26] = DMACH_MSM_REQ0,
-		[27] = DMACH_MSM_REQ1,
-		[28] = DMACH_MSM_REQ2,
-		[29] = DMACH_MSM_REQ3,
-		[30] = DMACH_PCM2_RX,
-		[31] = DMACH_PCM2_TX,
-	},
+struct dma_pl330_platdata s5pv210_pdma1_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma1_peri,
 };
 
-static struct platform_device s5pv210_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pv210_pdma1_resource),
-	.resource	= s5pv210_pdma1_resource,
-	.dev		= {
+struct amba_device s5pv210_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pv210_pdma1_pdata,
-	},
-};
-
-static struct platform_device *s5pv210_dmacs[] __initdata = {
-	&s5pv210_device_pdma0,
-	&s5pv210_device_pdma1,
+		},
+	.res = {
+		.start = S5PV210_PA_PDMA1,
+		.end = S5PV210_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5pv210_dma_init(void)
 {
-	platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs));
+	amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch makes Samsung S5PC100 to use DMA PL330 driver
on DMADEVICE. The S5PC100 uses DMA generic APIs instead of
SAMSUNG specific S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pc100/Kconfig |    2 +-
 arch/arm/mach-s5pc100/clock.c |   23 +--
 arch/arm/mach-s5pc100/dma.c   |  357 ++++++++++++++++++++++++++++-------------
 3 files changed, 253 insertions(+), 129 deletions(-)

diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 608722f..379fadc 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -10,7 +10,7 @@ if ARCH_S5PC100
 config CPU_S5PC100
 	bool
 	select S5P_EXT_INT
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	help
 	  Enable S5PC100 CPU support
 
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index 0305e9b..891acfe 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -34,6 +34,11 @@ static struct clk s5p_clk_otgphy = {
 	.id		= -1,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static struct clk *clk_src_mout_href_list[] = {
 	[0] = &s5p_clk_27m,
 	[1] = &clk_fin_hpll,
@@ -416,12 +421,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
-		.name		= "mdma",
-		.id		= -1,
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
 		.name		= "cfcon",
 		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
@@ -488,14 +487,8 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
-		.name		= "pdma",
-		.id		= 1,
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_0_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "pdma",
-		.id		= 0,
+		.name		= "dma",
+		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 0),
@@ -1394,5 +1387,7 @@ void __init s5pc100_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c
index bf4cd0f..02fa24c 100644
--- a/arch/arm/mach-s5pc100/dma.c
+++ b/arch/arm/mach-s5pc100/dma.c
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pc100/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
  *
@@ -17,150 +21,275 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
+#include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pc100_pdma0_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA0,
-		.end    = S5PC100_PA_PDMA0 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_IRDA,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_EXTERNAL,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_SPDIF,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_HSI_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_HSI_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_IRDA,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_SPI2_RX,
-		[21] = DMACH_SPI2_TX,
-		[22] = DMACH_AC97_MICIN,
-		[23] = DMACH_AC97_PCMIN,
-		[24] = DMACH_AC97_PCMOUT,
-		[25] = DMACH_EXTERNAL,
-		[26] = DMACH_PWM,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_HSI_RX,
-		[29] = DMACH_HSI_TX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pc100_pdma0_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma0_peri,
 };
 
-static struct platform_device s5pc100_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma0_resource),
-	.resource	= s5pc100_pdma0_resource,
-	.dev		= {
+struct amba_device s5pc100_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pc100_pdma0_pdata,
-	},
+		},
+	.res = {
+		.start = S5PC100_PA_PDMA0,
+		.end = S5PC100_PA_PDMA0 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct resource s5pc100_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA1,
-		.end    = S5PC100_PA_PDMA1 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma1_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_IRDA,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
 	},
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_IRDA,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_SPI2_RX,
-		[21] = DMACH_SPI2_TX,
-		[22] = DMACH_PCM0_RX,
-		[23] = DMACH_PCM0_TX,
-		[24] = DMACH_PCM1_RX,
-		[25] = DMACH_PCM1_TX,
-		[26] = DMACH_MSM_REQ0,
-		[27] = DMACH_MSM_REQ1,
-		[28] = DMACH_MSM_REQ2,
-		[29] = DMACH_MSM_REQ3,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pc100_pdma1_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma1_peri,
 };
 
-static struct platform_device s5pc100_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma1_resource),
-	.resource	= s5pc100_pdma1_resource,
-	.dev		= {
+struct amba_device s5pc100_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pc100_pdma1_pdata,
-	},
-};
-
-static struct platform_device *s5pc100_dmacs[] __initdata = {
-	&s5pc100_device_pdma0,
-	&s5pc100_device_pdma1,
+		},
+	.res = {
+		.start = S5PC100_PA_PDMA1,
+		.end = S5PC100_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5pc100_dma_init(void)
 {
-	platform_add_devices(s5pc100_dmacs, ARRAY_SIZE(s5pc100_dmacs));
+	amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch makes Samsung S5PC100 to use DMA PL330 driver
on DMADEVICE. The S5PC100 uses DMA generic APIs instead of
SAMSUNG specific S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pc100/Kconfig |    2 +-
 arch/arm/mach-s5pc100/clock.c |   23 +--
 arch/arm/mach-s5pc100/dma.c   |  357 ++++++++++++++++++++++++++++-------------
 3 files changed, 253 insertions(+), 129 deletions(-)

diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 608722f..379fadc 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -10,7 +10,7 @@ if ARCH_S5PC100
 config CPU_S5PC100
 	bool
 	select S5P_EXT_INT
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	help
 	  Enable S5PC100 CPU support
 
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index 0305e9b..891acfe 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -34,6 +34,11 @@ static struct clk s5p_clk_otgphy = {
 	.id		= -1,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 static struct clk *clk_src_mout_href_list[] = {
 	[0] = &s5p_clk_27m,
 	[1] = &clk_fin_hpll,
@@ -416,12 +421,6 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pc100_d0_0_ctrl,
 		.ctrlbit	= (1 << 4),
 	}, {
-		.name		= "mdma",
-		.id		= -1,
-		.parent		= &clk_div_d0_bus.clk,
-		.enable		= s5pc100_d0_0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
 		.name		= "cfcon",
 		.id		= -1,
 		.parent		= &clk_div_d0_bus.clk,
@@ -488,14 +487,8 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 2),
 	}, {
-		.name		= "pdma",
-		.id		= 1,
-		.parent		= &clk_div_d1_bus.clk,
-		.enable		= s5pc100_d1_0_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "pdma",
-		.id		= 0,
+		.name		= "dma",
+		.id		= -1,
 		.parent		= &clk_div_d1_bus.clk,
 		.enable		= s5pc100_d1_0_ctrl,
 		.ctrlbit	= (1 << 0),
@@ -1394,5 +1387,7 @@ void __init s5pc100_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c
index bf4cd0f..02fa24c 100644
--- a/arch/arm/mach-s5pc100/dma.c
+++ b/arch/arm/mach-s5pc100/dma.c
@@ -1,4 +1,8 @@
-/*
+/* linux/arch/arm/mach-s5pc100/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright (C) 2010 Samsung Electronics Co. Ltd.
  *	Jaswinder Singh <jassi.brar@samsung.com>
  *
@@ -17,150 +21,275 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
 
+#include <asm/irq.h>
 #include <plat/devs.h>
+#include <plat/irqs.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
+#include <mach/dma.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5pc100_pdma0_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA0,
-		.end    = S5PC100_PA_PDMA0 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma0_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_IRDA,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_AC97_MICIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_EXTERNAL,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_SPDIF,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_HSI_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_HSI_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_IRDA,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_SPI2_RX,
-		[21] = DMACH_SPI2_TX,
-		[22] = DMACH_AC97_MICIN,
-		[23] = DMACH_AC97_PCMIN,
-		[24] = DMACH_AC97_PCMOUT,
-		[25] = DMACH_EXTERNAL,
-		[26] = DMACH_PWM,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_HSI_RX,
-		[29] = DMACH_HSI_TX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pc100_pdma0_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma0_peri,
 };
 
-static struct platform_device s5pc100_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma0_resource),
-	.resource	= s5pc100_pdma0_resource,
-	.dev		= {
+struct amba_device s5pc100_device_pdma0 = {
+	.dev = {
+		.init_name = "dma-pl330.0",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pc100_pdma0_pdata,
-	},
+		},
+	.res = {
+		.start = S5PC100_PA_PDMA0,
+		.end = S5PC100_PA_PDMA0 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-static struct resource s5pc100_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA1,
-		.end    = S5PC100_PA_PDMA1 + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri pdma1_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_IRDA,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ1,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ3,
 	},
 };
 
-static struct s3c_pl330_platdata s5pc100_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_IRDA,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S0S_TX,
-		[12] = DMACH_I2S1_RX,
-		[13] = DMACH_I2S1_TX,
-		[14] = DMACH_I2S2_RX,
-		[15] = DMACH_I2S2_TX,
-		[16] = DMACH_SPI0_RX,
-		[17] = DMACH_SPI0_TX,
-		[18] = DMACH_SPI1_RX,
-		[19] = DMACH_SPI1_TX,
-		[20] = DMACH_SPI2_RX,
-		[21] = DMACH_SPI2_TX,
-		[22] = DMACH_PCM0_RX,
-		[23] = DMACH_PCM0_TX,
-		[24] = DMACH_PCM1_RX,
-		[25] = DMACH_PCM1_TX,
-		[26] = DMACH_MSM_REQ0,
-		[27] = DMACH_MSM_REQ1,
-		[28] = DMACH_MSM_REQ2,
-		[29] = DMACH_MSM_REQ3,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5pc100_pdma1_pdata = {
+	.nr_valid_peri = 32,
+	.peri = pdma1_peri,
 };
 
-static struct platform_device s5pc100_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma1_resource),
-	.resource	= s5pc100_pdma1_resource,
-	.dev		= {
+struct amba_device s5pc100_device_pdma1 = {
+	.dev = {
+		.init_name = "dma-pl330.1",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.platform_data = &s5pc100_pdma1_pdata,
-	},
-};
-
-static struct platform_device *s5pc100_dmacs[] __initdata = {
-	&s5pc100_device_pdma0,
-	&s5pc100_device_pdma1,
+		},
+	.res = {
+		.start = S5PC100_PA_PDMA1,
+		.end = S5PC100_PA_PDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_PDMA1, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5pc100_dma_init(void)
 {
-	platform_add_devices(s5pc100_dmacs, ARRAY_SIZE(s5pc100_dmacs));
+	amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch makes Samsung S5P64X0 to use DMA PL330 driver
on DMADEVICE. The S5P64X0 uses DMA generic APIs instead of
SAMSUNG specific S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5p64x0/Kconfig         |    4 +-
 arch/arm/mach-s5p64x0/clock-s5p6440.c |    9 +-
 arch/arm/mach-s5p64x0/clock-s5p6450.c |    9 +-
 arch/arm/mach-s5p64x0/dma.c           |  317 +++++++++++++++++++++++----------
 4 files changed, 242 insertions(+), 97 deletions(-)

diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index 017af4c..7108e7e 100644
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -9,14 +9,14 @@ if ARCH_S5P64X0
 
 config CPU_S5P6440
 	bool
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	select S5P_HRT
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	select S5P_HRT
 	help
 	  Enable S5P6450 CPU support
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index 9f12c2e..5f7ad9e 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -153,7 +153,7 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
-		.name		= "pdma",
+		.name		= "dma",
 		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
@@ -533,6 +533,11 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_pclk_low,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 void __init_or_cpufreq s5p6440_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -615,5 +620,7 @@ void __init s5p6440_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index 4eec457..62d4707 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -189,7 +189,7 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "pdma",
+		.name		= "dma",
 		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
@@ -583,6 +583,11 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_sclk_audio0,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 void __init_or_cpufreq s5p6450_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -662,5 +667,7 @@ void __init s5p6450_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
index d7ad944..1499381 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -19,130 +19,261 @@
  * 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/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
 #include <mach/regs-clock.h>
+#include <mach/dma.h>
 
 #include <plat/devs.h>
-#include <plat/s3c-pl330-pdata.h>
+#include <plat/irqs.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5p64x0_pdma_resource[] = {
-	[0] = {
-		.start	= S5P64X0_PA_PDMA,
-		.end	= S5P64X0_PA_PDMA + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DMA0,
-		.end	= IRQ_DMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri s5p6440_pdma_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
 	},
 };
 
-static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_MAX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_MAX,
-		[17] = DMACH_MAX,
-		[18] = DMACH_MAX,
-		[19] = DMACH_MAX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_MAX,
-		[23] = DMACH_MAX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_MAX,
-		[26] = DMACH_MAX,
-		[27] = DMACH_MAX,
-		[28] = DMACH_MAX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5p6440_pdma_pdata = {
+	.nr_valid_peri = 32,
+	.peri = s5p6440_pdma_peri,
 };
 
-static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_UART4_RX,
-		[9] = DMACH_UART4_TX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_PCM1_TX,
-		[17] = DMACH_PCM1_RX,
-		[18] = DMACH_PCM2_TX,
-		[19] = DMACH_PCM2_RX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_USI_TX,
-		[23] = DMACH_USI_RX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_I2S1_TX,
-		[26] = DMACH_I2S1_RX,
-		[27] = DMACH_I2S2_TX,
-		[28] = DMACH_I2S2_RX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_UART5_RX,
-		[31] = DMACH_UART5_TX,
+struct dma_pl330_peri s5p6450_pdma_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_USI_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_USI_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_UART5_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART5_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct platform_device s5p64x0_device_pdma = {
-	.name		= "s3c-pl330",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p64x0_pdma_resource),
-	.resource	= s5p64x0_pdma_resource,
-	.dev		= {
+struct dma_pl330_platdata s5p6450_pdma_pdata = {
+	.nr_valid_peri = 32,
+	.peri = s5p6450_pdma_peri,
+};
+
+struct amba_device s5p64x0_device_pdma = {
+	.dev = {
+		.init_name = "dma-pl330",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
+		},
+	.res = {
+		.start = S5P64X0_PA_PDMA,
+		.end = S5P64X0_PA_PDMA + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_DMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5p64x0_dma_init(void)
 {
-	unsigned int id;
-
-	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
+	unsigned int id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
 
 	if (id == 0x50000)
 		s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
 	else
 		s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
 
-	platform_device_register(&s5p64x0_device_pdma);
+	amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch makes Samsung S5P64X0 to use DMA PL330 driver
on DMADEVICE. The S5P64X0 uses DMA generic APIs instead of
SAMSUNG specific S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5p64x0/Kconfig         |    4 +-
 arch/arm/mach-s5p64x0/clock-s5p6440.c |    9 +-
 arch/arm/mach-s5p64x0/clock-s5p6450.c |    9 +-
 arch/arm/mach-s5p64x0/dma.c           |  317 +++++++++++++++++++++++----------
 4 files changed, 242 insertions(+), 97 deletions(-)

diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index 017af4c..7108e7e 100644
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -9,14 +9,14 @@ if ARCH_S5P64X0
 
 config CPU_S5P6440
 	bool
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	select S5P_HRT
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
-	select S3C_PL330_DMA
+	select DMADEV_PL330
 	select S5P_HRT
 	help
 	  Enable S5P6450 CPU support
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index 9f12c2e..5f7ad9e 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -153,7 +153,7 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 8),
 	}, {
-		.name		= "pdma",
+		.name		= "dma",
 		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
@@ -533,6 +533,11 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_pclk_low,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 void __init_or_cpufreq s5p6440_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -615,5 +620,7 @@ void __init s5p6440_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index 4eec457..62d4707 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -189,7 +189,7 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5p64x0_hclk0_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
-		.name		= "pdma",
+		.name		= "dma",
 		.id		= -1,
 		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p64x0_hclk0_ctrl,
@@ -583,6 +583,11 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_sclk_audio0,
 };
 
+static struct clk dummy_apb_pclk = {
+	.name		= "apb_pclk",
+	.id		= -1,
+};
+
 void __init_or_cpufreq s5p6450_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -662,5 +667,7 @@ void __init s5p6450_register_clocks(void)
 	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
 
+	s3c24xx_register_clock(&dummy_apb_pclk);
+
 	s3c_pwmclk_init();
 }
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
index d7ad944..1499381 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -19,130 +19,261 @@
  * 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/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl330.h>
+
+#include <asm/irq.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
 #include <mach/regs-clock.h>
+#include <mach/dma.h>
 
 #include <plat/devs.h>
-#include <plat/s3c-pl330-pdata.h>
+#include <plat/irqs.h>
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-static struct resource s5p64x0_pdma_resource[] = {
-	[0] = {
-		.start	= S5P64X0_PA_PDMA,
-		.end	= S5P64X0_PA_PDMA + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DMA0,
-		.end	= IRQ_DMA0,
-		.flags	= IORESOURCE_IRQ,
+struct dma_pl330_peri s5p6440_pdma_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
 	},
 };
 
-static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_MAX,
-		[9] = DMACH_MAX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_MAX,
-		[17] = DMACH_MAX,
-		[18] = DMACH_MAX,
-		[19] = DMACH_MAX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_MAX,
-		[23] = DMACH_MAX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_MAX,
-		[26] = DMACH_MAX,
-		[27] = DMACH_MAX,
-		[28] = DMACH_MAX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
+struct dma_pl330_platdata s5p6440_pdma_pdata = {
+	.nr_valid_peri = 32,
+	.peri = s5p6440_pdma_peri,
 };
 
-static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
-	.peri = {
-		[0] = DMACH_UART0_RX,
-		[1] = DMACH_UART0_TX,
-		[2] = DMACH_UART1_RX,
-		[3] = DMACH_UART1_TX,
-		[4] = DMACH_UART2_RX,
-		[5] = DMACH_UART2_TX,
-		[6] = DMACH_UART3_RX,
-		[7] = DMACH_UART3_TX,
-		[8] = DMACH_UART4_RX,
-		[9] = DMACH_UART4_TX,
-		[10] = DMACH_PCM0_TX,
-		[11] = DMACH_PCM0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S0_RX,
-		[14] = DMACH_SPI0_TX,
-		[15] = DMACH_SPI0_RX,
-		[16] = DMACH_PCM1_TX,
-		[17] = DMACH_PCM1_RX,
-		[18] = DMACH_PCM2_TX,
-		[19] = DMACH_PCM2_RX,
-		[20] = DMACH_SPI1_TX,
-		[21] = DMACH_SPI1_RX,
-		[22] = DMACH_USI_TX,
-		[23] = DMACH_USI_RX,
-		[24] = DMACH_MAX,
-		[25] = DMACH_I2S1_TX,
-		[26] = DMACH_I2S1_RX,
-		[27] = DMACH_I2S2_TX,
-		[28] = DMACH_I2S2_RX,
-		[29] = DMACH_PWM,
-		[30] = DMACH_UART5_RX,
-		[31] = DMACH_UART5_TX,
+struct dma_pl330_peri s5p6450_pdma_peri[32] = {
+	{
+		.peri_id = (u8)DMACH_UART0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 1,
+	}, {
+		.peri_id = (u8)DMACH_USI_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_USI_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+		.burst_sz = 4,
+	}, {
+		.peri_id = (u8)DMACH_PWM,
+	}, {
+		.peri_id = (u8)DMACH_UART5_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART5_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-static struct platform_device s5p64x0_device_pdma = {
-	.name		= "s3c-pl330",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p64x0_pdma_resource),
-	.resource	= s5p64x0_pdma_resource,
-	.dev		= {
+struct dma_pl330_platdata s5p6450_pdma_pdata = {
+	.nr_valid_peri = 32,
+	.peri = s5p6450_pdma_peri,
+};
+
+struct amba_device s5p64x0_device_pdma = {
+	.dev = {
+		.init_name = "dma-pl330",
 		.dma_mask = &dma_dmamask,
 		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
+		},
+	.res = {
+		.start = S5P64X0_PA_PDMA,
+		.end = S5P64X0_PA_PDMA + SZ_4K,
+		.flags = IORESOURCE_MEM,
+		},
+	.irq = {IRQ_DMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
 static int __init s5p64x0_dma_init(void)
 {
-	unsigned int id;
-
-	id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
+	unsigned int id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
 
 	if (id == 0x50000)
 		s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
 	else
 		s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
 
-	platform_device_register(&s5p64x0_device_pdma);
+	amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
 
 	return 0;
 }
-- 
1.7.1

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

* [PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

Since DMA generic APIs can be used for Samsung DMA now so that
the s3c-pl330 which includes Samsung specific DMA APIs can be
removed.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Cc: Jassi Brar <jassisinghbrar@gmail.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/plat-samsung/Kconfig                      |    6 -
 arch/arm/plat-samsung/Makefile                     |    2 -
 arch/arm/plat-samsung/include/plat/dma-pl330.h     |    9 +-
 .../plat-samsung/include/plat/s3c-pl330-pdata.h    |   32 -
 arch/arm/plat-samsung/s3c-pl330.c                  | 1244 --------------------
 5 files changed, 6 insertions(+), 1287 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
 delete mode 100644 arch/arm/plat-samsung/s3c-pl330.c

diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index cb170a6..db789d7 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -294,12 +294,6 @@ config S3C_DMA
 	help
 	  Internal configuration for S3C DMA core
 
-config S3C_PL330_DMA
-	bool
-	select PL330
-	help
-	  S3C DMA API Driver for PL330 DMAC.
-
 config DMADEV_PL330
 	bool
 	select DMADEVICES
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 9ecf2aa..ea98621 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -66,8 +66,6 @@ obj-$(CONFIG_S3C_DMA)		+= dma.o s3c-dma-ops.o
 
 obj-$(CONFIG_DMADEV_PL330)	+= dma-ops.o
 
-obj-$(CONFIG_S3C_PL330_DMA)	+= s3c-pl330.o s3c-dma-ops.o
-
 # PM support
 
 obj-$(CONFIG_PM)		+= pm.o
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index 687489e..ded416c 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -11,8 +11,6 @@
 #ifndef __DMA_PL330_H_
 #define __DMA_PL330_H_ __FILE__
 
-#define S3C2410_DMAF_AUTOSTART	(1 << 0)
-#define S3C2410_DMAF_CIRCULAR	(1 << 1)
 /*
  * PL330 can assign any channel to communicate with
  * any of the peripherals attched to the DMAC.
@@ -95,6 +93,10 @@ enum dma_ch {
 	DMACH_MAX,
 };
 
+struct s3c2410_dma_client {
+	char	*name;
+};
+
 static inline bool s3c_dma_has_circular(void)
 {
 	return true;
@@ -104,6 +106,7 @@ static inline bool samsung_dma_is_dmadev(void)
 {
 	return true;
 }
-#include <plat/dma.h>
+
+#include <plat/dma-ops.h>
 
 #endif	/* __DMA_PL330_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
deleted file mode 100644
index 64fdf66..0000000
--- a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * 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.
- */
-
-#ifndef __S3C_PL330_PDATA_H
-#define __S3C_PL330_PDATA_H
-
-#include <plat/dma-pl330.h>
-
-/*
- * Every PL330 DMAC has max 32 peripheral interfaces,
- * of which some may be not be really used in your
- * DMAC's configuration.
- * Populate this array of 32 peri i/fs with relevant
- * channel IDs for used peri i/f and DMACH_MAX for
- * those unused.
- *
- * The platforms just need to provide this info
- * to the S3C DMA API driver for PL330.
- */
-struct s3c_pl330_platdata {
-	enum dma_ch peri[32];
-};
-
-#endif /* __S3C_PL330_PDATA_H */
diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c
deleted file mode 100644
index f85638c..0000000
--- a/arch/arm/plat-samsung/s3c-pl330.c
+++ /dev/null
@@ -1,1244 +0,0 @@
-/* linux/arch/arm/plat-samsung/s3c-pl330.c
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * 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.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/hardware/pl330.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-/**
- * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC.
- * @busy_chan: Number of channels currently busy.
- * @peri: List of IDs of peripherals this DMAC can work with.
- * @node: To attach to the global list of DMACs.
- * @pi: PL330 configuration info for the DMAC.
- * @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
- * @clk: Pointer of DMAC operation clock.
- */
-struct s3c_pl330_dmac {
-	unsigned		busy_chan;
-	enum dma_ch		*peri;
-	struct list_head	node;
-	struct pl330_info	*pi;
-	struct kmem_cache	*kmcache;
-	struct clk		*clk;
-};
-
-/**
- * struct s3c_pl330_xfer - A request submitted by S3C DMA clients.
- * @token: Xfer ID provided by the client.
- * @node: To attach to the list of xfers on a channel.
- * @px: Xfer for PL330 core.
- * @chan: Owner channel of this xfer.
- */
-struct s3c_pl330_xfer {
-	void			*token;
-	struct list_head	node;
-	struct pl330_xfer	px;
-	struct s3c_pl330_chan	*chan;
-};
-
-/**
- * struct s3c_pl330_chan - Logical channel to communicate with
- * 	a Physical peripheral.
- * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC.
- * 	NULL if the channel is available to be acquired.
- * @id: ID of the peripheral that this channel can communicate with.
- * @options: Options specified by the client.
- * @sdaddr: Address provided via s3c2410_dma_devconfig.
- * @node: To attach to the global list of channels.
- * @lrq: Pointer to the last submitted pl330_req to PL330 core.
- * @xfer_list: To manage list of xfers enqueued.
- * @req: Two requests to communicate with the PL330 engine.
- * @callback_fn: Callback function to the client.
- * @rqcfg: Channel configuration for the xfers.
- * @xfer_head: Pointer to the xfer to be next executed.
- * @dmac: Pointer to the DMAC that manages this channel, NULL if the
- * 	channel is available to be acquired.
- * @client: Client of this channel. NULL if the
- * 	channel is available to be acquired.
- */
-struct s3c_pl330_chan {
-	void				*pl330_chan_id;
-	enum dma_ch			id;
-	unsigned int			options;
-	unsigned long			sdaddr;
-	struct list_head		node;
-	struct pl330_req		*lrq;
-	struct list_head		xfer_list;
-	struct pl330_req		req[2];
-	s3c2410_dma_cbfn_t		callback_fn;
-	struct pl330_reqcfg		rqcfg;
-	struct s3c_pl330_xfer		*xfer_head;
-	struct s3c_pl330_dmac		*dmac;
-	struct s3c2410_dma_client	*client;
-};
-
-/* All DMACs in the platform */
-static LIST_HEAD(dmac_list);
-
-/* All channels to peripherals in the platform */
-static LIST_HEAD(chan_list);
-
-/*
- * Since we add resources(DMACs and Channels) to the global pool,
- * we need to guard access to the resources using a global lock
- */
-static DEFINE_SPINLOCK(res_lock);
-
-/* Returns the channel with ID 'id' in the chan_list */
-static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch;
-
-	list_for_each_entry(ch, &chan_list, node)
-		if (ch->id == id)
-			return ch;
-
-	return NULL;
-}
-
-/* Allocate a new channel with ID 'id' and add to chan_list */
-static void chan_add(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-
-	/* Return if the channel already exists */
-	if (ch)
-		return;
-
-	ch = kmalloc(sizeof(*ch), GFP_KERNEL);
-	/* Return silently to work with other channels */
-	if (!ch)
-		return;
-
-	ch->id = id;
-	ch->dmac = NULL;
-
-	list_add_tail(&ch->node, &chan_list);
-}
-
-/* If the channel is not yet acquired by any client */
-static bool chan_free(struct s3c_pl330_chan *ch)
-{
-	if (!ch)
-		return false;
-
-	/* Channel points to some DMAC only when it's acquired */
-	return ch->dmac ? false : true;
-}
-
-/*
- * Returns 0 is peripheral i/f is invalid or not present on the dmac.
- * Index + 1, otherwise.
- */
-static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id)
-{
-	enum dma_ch *id = dmac->peri;
-	int i;
-
-	/* Discount invalid markers */
-	if (ch_id == DMACH_MAX)
-		return 0;
-
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (id[i] == ch_id)
-			return i + 1;
-
-	return 0;
-}
-
-/* If all channel threads of the DMAC are busy */
-static inline bool dmac_busy(struct s3c_pl330_dmac *dmac)
-{
-	struct pl330_info *pi = dmac->pi;
-
-	return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true;
-}
-
-/*
- * Returns the number of free channels that
- * can be handled by this dmac only.
- */
-static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac)
-{
-	enum dma_ch *id = dmac->peri;
-	struct s3c_pl330_dmac *d;
-	struct s3c_pl330_chan *ch;
-	unsigned found, count = 0;
-	enum dma_ch p;
-	int i;
-
-	for (i = 0; i < PL330_MAX_PERI; i++) {
-		p = id[i];
-		ch = id_to_chan(p);
-
-		if (p == DMACH_MAX || !chan_free(ch))
-			continue;
-
-		found = 0;
-		list_for_each_entry(d, &dmac_list, node) {
-			if (d != dmac && iface_of_dmac(d, ch->id)) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found)
-			count++;
-	}
-
-	return count;
-}
-
-/*
- * Measure of suitability of 'dmac' handling 'ch'
- *
- * 0 indicates 'dmac' can not handle 'ch' either
- * because it is not supported by the hardware or
- * because all dmac channels are currently busy.
- *
- * >0 vlaue indicates 'dmac' has the capability.
- * The bigger the value the more suitable the dmac.
- */
-#define MAX_SUIT	UINT_MAX
-#define MIN_SUIT	0
-
-static unsigned suitablility(struct s3c_pl330_dmac *dmac,
-		struct s3c_pl330_chan *ch)
-{
-	struct pl330_info *pi = dmac->pi;
-	enum dma_ch *id = dmac->peri;
-	struct s3c_pl330_dmac *d;
-	unsigned s;
-	int i;
-
-	s = MIN_SUIT;
-	/* If all the DMAC channel threads are busy */
-	if (dmac_busy(dmac))
-		return s;
-
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (id[i] == ch->id)
-			break;
-
-	/* If the 'dmac' can't talk to 'ch' */
-	if (i == PL330_MAX_PERI)
-		return s;
-
-	s = MAX_SUIT;
-	list_for_each_entry(d, &dmac_list, node) {
-		/*
-		 * If some other dmac can talk to this
-		 * peri and has some channel free.
-		 */
-		if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) {
-			s = 0;
-			break;
-		}
-	}
-	if (s)
-		return s;
-
-	s = 100;
-
-	/* Good if free chans are more, bad otherwise */
-	s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac);
-
-	return s;
-}
-
-/* More than one DMAC may have capability to transfer data with the
- * peripheral. This function assigns most suitable DMAC to manage the
- * channel and hence communicate with the peripheral.
- */
-static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch)
-{
-	struct s3c_pl330_dmac *d, *dmac = NULL;
-	unsigned sn, sl = MIN_SUIT;
-
-	list_for_each_entry(d, &dmac_list, node) {
-		sn = suitablility(d, ch);
-
-		if (sn == MAX_SUIT)
-			return d;
-
-		if (sn > sl)
-			dmac = d;
-	}
-
-	return dmac;
-}
-
-/* Acquire the channel for peripheral 'id' */
-static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-	struct s3c_pl330_dmac *dmac;
-
-	/* If the channel doesn't exist or is already acquired */
-	if (!ch || !chan_free(ch)) {
-		ch = NULL;
-		goto acq_exit;
-	}
-
-	dmac = map_chan_to_dmac(ch);
-	/* If couldn't map */
-	if (!dmac) {
-		ch = NULL;
-		goto acq_exit;
-	}
-
-	dmac->busy_chan++;
-	ch->dmac = dmac;
-
-acq_exit:
-	return ch;
-}
-
-/* Delete xfer from the queue */
-static inline void del_from_queue(struct s3c_pl330_xfer *xfer)
-{
-	struct s3c_pl330_xfer *t;
-	struct s3c_pl330_chan *ch;
-	int found;
-
-	if (!xfer)
-		return;
-
-	ch = xfer->chan;
-
-	/* Make sure xfer is in the queue */
-	found = 0;
-	list_for_each_entry(t, &ch->xfer_list, node)
-		if (t == xfer) {
-			found = 1;
-			break;
-		}
-
-	if (!found)
-		return;
-
-	/* If xfer is last entry in the queue */
-	if (xfer->node.next == &ch->xfer_list)
-		t = list_entry(ch->xfer_list.next,
-				struct s3c_pl330_xfer, node);
-	else
-		t = list_entry(xfer->node.next,
-				struct s3c_pl330_xfer, node);
-
-	/* If there was only one node left */
-	if (t == xfer)
-		ch->xfer_head = NULL;
-	else if (ch->xfer_head == xfer)
-		ch->xfer_head = t;
-
-	list_del(&xfer->node);
-}
-
-/* Provides pointer to the next xfer in the queue.
- * If CIRCULAR option is set, the list is left intact,
- * otherwise the xfer is removed from the list.
- * Forced delete 'pluck' can be set to override the CIRCULAR option.
- */
-static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch,
-		int pluck)
-{
-	struct s3c_pl330_xfer *xfer = ch->xfer_head;
-
-	if (!xfer)
-		return NULL;
-
-	/* If xfer is last entry in the queue */
-	if (xfer->node.next == &ch->xfer_list)
-		ch->xfer_head = list_entry(ch->xfer_list.next,
-					struct s3c_pl330_xfer, node);
-	else
-		ch->xfer_head = list_entry(xfer->node.next,
-					struct s3c_pl330_xfer, node);
-
-	if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR))
-		del_from_queue(xfer);
-
-	return xfer;
-}
-
-static inline void add_to_queue(struct s3c_pl330_chan *ch,
-		struct s3c_pl330_xfer *xfer, int front)
-{
-	struct pl330_xfer *xt;
-
-	/* If queue empty */
-	if (ch->xfer_head == NULL)
-		ch->xfer_head = xfer;
-
-	xt = &ch->xfer_head->px;
-	/* If the head already submitted (CIRCULAR head) */
-	if (ch->options & S3C2410_DMAF_CIRCULAR &&
-		(xt == ch->req[0].x || xt == ch->req[1].x))
-		ch->xfer_head = xfer;
-
-	/* If this is a resubmission, it should go at the head */
-	if (front) {
-		ch->xfer_head = xfer;
-		list_add(&xfer->node, &ch->xfer_list);
-	} else {
-		list_add_tail(&xfer->node, &ch->xfer_list);
-	}
-}
-
-static inline void _finish_off(struct s3c_pl330_xfer *xfer,
-		enum s3c2410_dma_buffresult res, int ffree)
-{
-	struct s3c_pl330_chan *ch;
-
-	if (!xfer)
-		return;
-
-	ch = xfer->chan;
-
-	/* Do callback */
-	if (ch->callback_fn)
-		ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res);
-
-	/* Force Free or if buffer is not needed anymore */
-	if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR))
-		kmem_cache_free(ch->dmac->kmcache, xfer);
-}
-
-static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch,
-		struct pl330_req *r)
-{
-	struct s3c_pl330_xfer *xfer;
-	int ret = 0;
-
-	/* If already submitted */
-	if (r->x)
-		return 0;
-
-	xfer = get_from_queue(ch, 0);
-	if (xfer) {
-		r->x = &xfer->px;
-
-		/* Use max bandwidth for M<->M xfers */
-		if (r->rqtype == MEMTOMEM) {
-			struct pl330_info *pi = xfer->chan->dmac->pi;
-			int burst = 1 << ch->rqcfg.brst_size;
-			u32 bytes = r->x->bytes;
-			int bl;
-
-			bl = pi->pcfg.data_bus_width / 8;
-			bl *= pi->pcfg.data_buf_dep;
-			bl /= burst;
-
-			/* src/dst_burst_len can't be more than 16 */
-			if (bl > 16)
-				bl = 16;
-
-			while (bl > 1) {
-				if (!(bytes % (bl * burst)))
-					break;
-				bl--;
-			}
-
-			ch->rqcfg.brst_len = bl;
-		} else {
-			ch->rqcfg.brst_len = 1;
-		}
-
-		ret = pl330_submit_req(ch->pl330_chan_id, r);
-
-		/* If submission was successful */
-		if (!ret) {
-			ch->lrq = r; /* latest submitted req */
-			return 0;
-		}
-
-		r->x = NULL;
-
-		/* If both of the PL330 ping-pong buffers filled */
-		if (ret == -EAGAIN) {
-			dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-				__func__, __LINE__);
-			/* Queue back again */
-			add_to_queue(ch, xfer, 1);
-			ret = 0;
-		} else {
-			dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-				__func__, __LINE__);
-			_finish_off(xfer, S3C2410_RES_ERR, 0);
-		}
-	}
-
-	return ret;
-}
-
-static void s3c_pl330_rq(struct s3c_pl330_chan *ch,
-	struct pl330_req *r, enum pl330_op_err err)
-{
-	unsigned long flags;
-	struct s3c_pl330_xfer *xfer;
-	struct pl330_xfer *xl = r->x;
-	enum s3c2410_dma_buffresult res;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	r->x = NULL;
-
-	s3c_pl330_submit(ch, r);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	/* Map result to S3C DMA API */
-	if (err == PL330_ERR_NONE)
-		res = S3C2410_RES_OK;
-	else if (err == PL330_ERR_ABORT)
-		res = S3C2410_RES_ABORT;
-	else
-		res = S3C2410_RES_ERR;
-
-	/* If last request had some xfer */
-	if (xl) {
-		xfer = container_of(xl, struct s3c_pl330_xfer, px);
-		_finish_off(xfer, res, 0);
-	} else {
-		dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n",
-			__func__, __LINE__);
-	}
-}
-
-static void s3c_pl330_rq0(void *token, enum pl330_op_err err)
-{
-	struct pl330_req *r = token;
-	struct s3c_pl330_chan *ch = container_of(r,
-					struct s3c_pl330_chan, req[0]);
-	s3c_pl330_rq(ch, r, err);
-}
-
-static void s3c_pl330_rq1(void *token, enum pl330_op_err err)
-{
-	struct pl330_req *r = token;
-	struct s3c_pl330_chan *ch = container_of(r,
-					struct s3c_pl330_chan, req[1]);
-	s3c_pl330_rq(ch, r, err);
-}
-
-/* Release an acquired channel */
-static void chan_release(struct s3c_pl330_chan *ch)
-{
-	struct s3c_pl330_dmac *dmac;
-
-	if (chan_free(ch))
-		return;
-
-	dmac = ch->dmac;
-	ch->dmac = NULL;
-	dmac->busy_chan--;
-}
-
-int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op)
-{
-	struct s3c_pl330_xfer *xfer;
-	enum pl330_chan_op pl330op;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int idx, ret;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto ctrl_exit;
-	}
-
-	switch (op) {
-	case S3C2410_DMAOP_START:
-		/* Make sure both reqs are enqueued */
-		idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-		s3c_pl330_submit(ch, &ch->req[idx]);
-		s3c_pl330_submit(ch, &ch->req[1 - idx]);
-		pl330op = PL330_OP_START;
-		break;
-
-	case S3C2410_DMAOP_STOP:
-		pl330op = PL330_OP_ABORT;
-		break;
-
-	case S3C2410_DMAOP_FLUSH:
-		pl330op = PL330_OP_FLUSH;
-		break;
-
-	case S3C2410_DMAOP_PAUSE:
-	case S3C2410_DMAOP_RESUME:
-	case S3C2410_DMAOP_TIMEOUT:
-	case S3C2410_DMAOP_STARTED:
-		spin_unlock_irqrestore(&res_lock, flags);
-		return 0;
-
-	default:
-		spin_unlock_irqrestore(&res_lock, flags);
-		return -EINVAL;
-	}
-
-	ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op);
-
-	if (pl330op == PL330_OP_START) {
-		spin_unlock_irqrestore(&res_lock, flags);
-		return ret;
-	}
-
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	/* Abort the current xfer */
-	if (ch->req[idx].x) {
-		xfer = container_of(ch->req[idx].x,
-				struct s3c_pl330_xfer, px);
-
-		/* Drop xfer during FLUSH */
-		if (pl330op == PL330_OP_FLUSH)
-			del_from_queue(xfer);
-
-		ch->req[idx].x = NULL;
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT,
-				pl330op == PL330_OP_FLUSH ? 1 : 0);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	/* Flush the whole queue */
-	if (pl330op == PL330_OP_FLUSH) {
-
-		if (ch->req[1 - idx].x) {
-			xfer = container_of(ch->req[1 - idx].x,
-					struct s3c_pl330_xfer, px);
-
-			del_from_queue(xfer);
-
-			ch->req[1 - idx].x = NULL;
-
-			spin_unlock_irqrestore(&res_lock, flags);
-			_finish_off(xfer, S3C2410_RES_ABORT, 1);
-			spin_lock_irqsave(&res_lock, flags);
-		}
-
-		/* Finish off the remaining in the queue */
-		xfer = ch->xfer_head;
-		while (xfer) {
-
-			del_from_queue(xfer);
-
-			spin_unlock_irqrestore(&res_lock, flags);
-			_finish_off(xfer, S3C2410_RES_ABORT, 1);
-			spin_lock_irqsave(&res_lock, flags);
-
-			xfer = ch->xfer_head;
-		}
-	}
-
-ctrl_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-int s3c2410_dma_enqueue(enum dma_ch id, void *token,
-			dma_addr_t addr, int size)
-{
-	struct s3c_pl330_chan *ch;
-	struct s3c_pl330_xfer *xfer;
-	unsigned long flags;
-	int idx, ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	/* Error if invalid or free channel */
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto enq_exit;
-	}
-
-	/* Error if size is unaligned */
-	if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) {
-		ret = -EINVAL;
-		goto enq_exit;
-	}
-
-	xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC);
-	if (!xfer) {
-		ret = -ENOMEM;
-		goto enq_exit;
-	}
-
-	xfer->token = token;
-	xfer->chan = ch;
-	xfer->px.bytes = size;
-	xfer->px.next = NULL; /* Single request */
-
-	/* For S3C DMA API, direction is always fixed for all xfers */
-	if (ch->req[0].rqtype == MEMTODEV) {
-		xfer->px.src_addr = addr;
-		xfer->px.dst_addr = ch->sdaddr;
-	} else {
-		xfer->px.src_addr = ch->sdaddr;
-		xfer->px.dst_addr = addr;
-	}
-
-	add_to_queue(ch, xfer, 0);
-
-	/* Try submitting on either request */
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	if (!ch->req[idx].x)
-		s3c_pl330_submit(ch, &ch->req[idx]);
-	else
-		s3c_pl330_submit(ch, &ch->req[1 - idx]);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	if (ch->options & S3C2410_DMAF_AUTOSTART)
-		s3c2410_dma_ctrl(id, S3C2410_DMAOP_START);
-
-	return 0;
-
-enq_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-int s3c2410_dma_request(enum dma_ch id,
-			struct s3c2410_dma_client *client,
-			void *dev)
-{
-	struct s3c_pl330_dmac *dmac;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = chan_acquire(id);
-	if (!ch) {
-		ret = -EBUSY;
-		goto req_exit;
-	}
-
-	dmac = ch->dmac;
-
-	ch->pl330_chan_id = pl330_request_channel(dmac->pi);
-	if (!ch->pl330_chan_id) {
-		chan_release(ch);
-		ret = -EBUSY;
-		goto req_exit;
-	}
-
-	ch->client = client;
-	ch->options = 0; /* Clear any option */
-	ch->callback_fn = NULL; /* Clear any callback */
-	ch->lrq = NULL;
-
-	ch->rqcfg.brst_size = 2; /* Default word size */
-	ch->rqcfg.swap = SWAP_NO;
-	ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */
-	ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */
-	ch->rqcfg.privileged = 0;
-	ch->rqcfg.insnaccess = 0;
-
-	/* Set invalid direction */
-	ch->req[0].rqtype = DEVTODEV;
-	ch->req[1].rqtype = ch->req[0].rqtype;
-
-	ch->req[0].cfg = &ch->rqcfg;
-	ch->req[1].cfg = ch->req[0].cfg;
-
-	ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */
-	ch->req[1].peri = ch->req[0].peri;
-
-	ch->req[0].token = &ch->req[0];
-	ch->req[0].xfer_cb = s3c_pl330_rq0;
-	ch->req[1].token = &ch->req[1];
-	ch->req[1].xfer_cb = s3c_pl330_rq1;
-
-	ch->req[0].x = NULL;
-	ch->req[1].x = NULL;
-
-	/* Reset xfer list */
-	INIT_LIST_HEAD(&ch->xfer_list);
-	ch->xfer_head = NULL;
-
-req_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
-{
-	struct s3c_pl330_chan *ch;
-	struct s3c_pl330_xfer *xfer;
-	unsigned long flags;
-	int ret = 0;
-	unsigned idx;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch))
-		goto free_exit;
-
-	/* Refuse if someone else wanted to free the channel */
-	if (ch->client != client) {
-		ret = -EBUSY;
-		goto free_exit;
-	}
-
-	/* Stop any active xfer, Flushe the queue and do callbacks */
-	pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH);
-
-	/* Abort the submitted requests */
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	if (ch->req[idx].x) {
-		xfer = container_of(ch->req[idx].x,
-				struct s3c_pl330_xfer, px);
-
-		ch->req[idx].x = NULL;
-		del_from_queue(xfer);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	if (ch->req[1 - idx].x) {
-		xfer = container_of(ch->req[1 - idx].x,
-				struct s3c_pl330_xfer, px);
-
-		ch->req[1 - idx].x = NULL;
-		del_from_queue(xfer);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	/* Pluck and Abort the queued requests in order */
-	do {
-		xfer = get_from_queue(ch, 1);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	} while (xfer);
-
-	ch->client = NULL;
-
-	pl330_release_channel(ch->pl330_chan_id);
-
-	ch->pl330_chan_id = NULL;
-
-	chan_release(ch);
-
-free_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-int s3c2410_dma_config(enum dma_ch id, int xferunit)
-{
-	struct s3c_pl330_chan *ch;
-	struct pl330_info *pi;
-	unsigned long flags;
-	int i, dbwidth, ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto cfg_exit;
-	}
-
-	pi = ch->dmac->pi;
-	dbwidth = pi->pcfg.data_bus_width / 8;
-
-	/* Max size of xfer can be pcfg.data_bus_width */
-	if (xferunit > dbwidth) {
-		ret = -EINVAL;
-		goto cfg_exit;
-	}
-
-	i = 0;
-	while (xferunit != (1 << i))
-		i++;
-
-	/* If valid value */
-	if (xferunit == (1 << i))
-		ch->rqcfg.brst_size = i;
-	else
-		ret = -EINVAL;
-
-cfg_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-/* Options that are supported by this driver */
-#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART)
-
-int s3c2410_dma_setflags(enum dma_ch id, unsigned int options)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS))
-		ret = -EINVAL;
-	else
-		ch->options = options;
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch))
-		ret = -EINVAL;
-	else
-		ch->callback_fn = rtn;
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
-			  unsigned long address)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto devcfg_exit;
-	}
-
-	switch (source) {
-	case S3C2410_DMASRC_HW: /* P->M */
-		ch->req[0].rqtype = DEVTOMEM;
-		ch->req[1].rqtype = DEVTOMEM;
-		ch->rqcfg.src_inc = 0;
-		ch->rqcfg.dst_inc = 1;
-		break;
-	case S3C2410_DMASRC_MEM: /* M->P */
-		ch->req[0].rqtype = MEMTODEV;
-		ch->req[1].rqtype = MEMTODEV;
-		ch->rqcfg.src_inc = 1;
-		ch->rqcfg.dst_inc = 0;
-		break;
-	default:
-		ret = -EINVAL;
-		goto devcfg_exit;
-	}
-
-	ch->sdaddr = address;
-
-devcfg_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-	struct pl330_chanstatus status;
-	int ret;
-
-	if (!ch || chan_free(ch))
-		return -EINVAL;
-
-	ret = pl330_chan_status(ch->pl330_chan_id, &status);
-	if (ret < 0)
-		return ret;
-
-	*src = status.src_addr;
-	*dst = status.dst_addr;
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-static irqreturn_t pl330_irq_handler(int irq, void *data)
-{
-	if (pl330_update(data))
-		return IRQ_HANDLED;
-	else
-		return IRQ_NONE;
-}
-
-static int pl330_probe(struct platform_device *pdev)
-{
-	struct s3c_pl330_dmac *s3c_pl330_dmac;
-	struct s3c_pl330_platdata *pl330pd;
-	struct pl330_info *pl330_info;
-	struct resource *res;
-	int i, ret, irq;
-
-	pl330pd = pdev->dev.platform_data;
-
-	/* Can't do without the list of _32_ peripherals */
-	if (!pl330pd || !pl330pd->peri) {
-		dev_err(&pdev->dev, "platform data missing!\n");
-		return -ENODEV;
-	}
-
-	pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL);
-	if (!pl330_info)
-		return -ENOMEM;
-
-	pl330_info->pl330_data = NULL;
-	pl330_info->dev = &pdev->dev;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		goto probe_err1;
-	}
-
-	request_mem_region(res->start, resource_size(res), pdev->name);
-
-	pl330_info->base = ioremap(res->start, resource_size(res));
-	if (!pl330_info->base) {
-		ret = -ENXIO;
-		goto probe_err2;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		ret = irq;
-		goto probe_err3;
-	}
-
-	ret = request_irq(irq, pl330_irq_handler, 0,
-			dev_name(&pdev->dev), pl330_info);
-	if (ret)
-		goto probe_err4;
-
-	/* Allocate a new DMAC */
-	s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
-	if (!s3c_pl330_dmac) {
-		ret = -ENOMEM;
-		goto probe_err5;
-	}
-
-	/* Get operation clock and enable it */
-	s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma");
-	if (IS_ERR(s3c_pl330_dmac->clk)) {
-		dev_err(&pdev->dev, "Cannot get operation clock.\n");
-		ret = -EINVAL;
-		goto probe_err6;
-	}
-	clk_enable(s3c_pl330_dmac->clk);
-
-	ret = pl330_add(pl330_info);
-	if (ret)
-		goto probe_err7;
-
-	/* Hook the info */
-	s3c_pl330_dmac->pi = pl330_info;
-
-	/* No busy channels */
-	s3c_pl330_dmac->busy_chan = 0;
-
-	s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev),
-				sizeof(struct s3c_pl330_xfer), 0, 0, NULL);
-
-	if (!s3c_pl330_dmac->kmcache) {
-		ret = -ENOMEM;
-		goto probe_err8;
-	}
-
-	/* Get the list of peripherals */
-	s3c_pl330_dmac->peri = pl330pd->peri;
-
-	/* Attach to the list of DMACs */
-	list_add_tail(&s3c_pl330_dmac->node, &dmac_list);
-
-	/* Create a channel for each peripheral in the DMAC
-	 * that is, if it doesn't already exist
-	 */
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (s3c_pl330_dmac->peri[i] != DMACH_MAX)
-			chan_add(s3c_pl330_dmac->peri[i]);
-
-	printk(KERN_INFO
-		"Loaded driver for PL330 DMAC-%d %s\n",	pdev->id, pdev->name);
-	printk(KERN_INFO
-		"\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
-		pl330_info->pcfg.data_buf_dep,
-		pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
-		pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
-
-	return 0;
-
-probe_err8:
-	pl330_del(pl330_info);
-probe_err7:
-	clk_disable(s3c_pl330_dmac->clk);
-	clk_put(s3c_pl330_dmac->clk);
-probe_err6:
-	kfree(s3c_pl330_dmac);
-probe_err5:
-	free_irq(irq, pl330_info);
-probe_err4:
-probe_err3:
-	iounmap(pl330_info->base);
-probe_err2:
-	release_mem_region(res->start, resource_size(res));
-probe_err1:
-	kfree(pl330_info);
-
-	return ret;
-}
-
-static int pl330_remove(struct platform_device *pdev)
-{
-	struct s3c_pl330_dmac *dmac, *d;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int del, found;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	found = 0;
-	list_for_each_entry(d, &dmac_list, node)
-		if (d->pi->dev == &pdev->dev) {
-			found = 1;
-			break;
-		}
-
-	if (!found) {
-		spin_unlock_irqrestore(&res_lock, flags);
-		return 0;
-	}
-
-	dmac = d;
-
-	/* Remove all Channels that are managed only by this DMAC */
-	list_for_each_entry(ch, &chan_list, node) {
-
-		/* Only channels that are handled by this DMAC */
-		if (iface_of_dmac(dmac, ch->id))
-			del = 1;
-		else
-			continue;
-
-		/* Don't remove if some other DMAC has it too */
-		list_for_each_entry(d, &dmac_list, node)
-			if (d != dmac && iface_of_dmac(d, ch->id)) {
-				del = 0;
-				break;
-			}
-
-		if (del) {
-			spin_unlock_irqrestore(&res_lock, flags);
-			s3c2410_dma_free(ch->id, ch->client);
-			spin_lock_irqsave(&res_lock, flags);
-			list_del(&ch->node);
-			kfree(ch);
-		}
-	}
-
-	/* Disable operation clock */
-	clk_disable(dmac->clk);
-	clk_put(dmac->clk);
-
-	/* Remove the DMAC */
-	list_del(&dmac->node);
-	kfree(dmac);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return 0;
-}
-
-static struct platform_driver pl330_driver = {
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "s3c-pl330",
-	},
-	.probe		= pl330_probe,
-	.remove		= pl330_remove,
-};
-
-static int __init pl330_init(void)
-{
-	return platform_driver_register(&pl330_driver);
-}
-module_init(pl330_init);
-
-static void __exit pl330_exit(void)
-{
-	platform_driver_unregister(&pl330_driver);
-	return;
-}
-module_exit(pl330_exit);
-
-MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
-MODULE_DESCRIPTION("Driver for PL330 DMA Controller");
-MODULE_LICENSE("GPL");
-- 
1.7.1

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

* [PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

Since DMA generic APIs can be used for Samsung DMA now so that
the s3c-pl330 which includes Samsung specific DMA APIs can be
removed.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Cc: Jassi Brar <jassisinghbrar@gmail.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/plat-samsung/Kconfig                      |    6 -
 arch/arm/plat-samsung/Makefile                     |    2 -
 arch/arm/plat-samsung/include/plat/dma-pl330.h     |    9 +-
 .../plat-samsung/include/plat/s3c-pl330-pdata.h    |   32 -
 arch/arm/plat-samsung/s3c-pl330.c                  | 1244 --------------------
 5 files changed, 6 insertions(+), 1287 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
 delete mode 100644 arch/arm/plat-samsung/s3c-pl330.c

diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index cb170a6..db789d7 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -294,12 +294,6 @@ config S3C_DMA
 	help
 	  Internal configuration for S3C DMA core
 
-config S3C_PL330_DMA
-	bool
-	select PL330
-	help
-	  S3C DMA API Driver for PL330 DMAC.
-
 config DMADEV_PL330
 	bool
 	select DMADEVICES
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 9ecf2aa..ea98621 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -66,8 +66,6 @@ obj-$(CONFIG_S3C_DMA)		+= dma.o s3c-dma-ops.o
 
 obj-$(CONFIG_DMADEV_PL330)	+= dma-ops.o
 
-obj-$(CONFIG_S3C_PL330_DMA)	+= s3c-pl330.o s3c-dma-ops.o
-
 # PM support
 
 obj-$(CONFIG_PM)		+= pm.o
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index 687489e..ded416c 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -11,8 +11,6 @@
 #ifndef __DMA_PL330_H_
 #define __DMA_PL330_H_ __FILE__
 
-#define S3C2410_DMAF_AUTOSTART	(1 << 0)
-#define S3C2410_DMAF_CIRCULAR	(1 << 1)
 /*
  * PL330 can assign any channel to communicate with
  * any of the peripherals attched to the DMAC.
@@ -95,6 +93,10 @@ enum dma_ch {
 	DMACH_MAX,
 };
 
+struct s3c2410_dma_client {
+	char	*name;
+};
+
 static inline bool s3c_dma_has_circular(void)
 {
 	return true;
@@ -104,6 +106,7 @@ static inline bool samsung_dma_is_dmadev(void)
 {
 	return true;
 }
-#include <plat/dma.h>
+
+#include <plat/dma-ops.h>
 
 #endif	/* __DMA_PL330_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
deleted file mode 100644
index 64fdf66..0000000
--- a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * 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.
- */
-
-#ifndef __S3C_PL330_PDATA_H
-#define __S3C_PL330_PDATA_H
-
-#include <plat/dma-pl330.h>
-
-/*
- * Every PL330 DMAC has max 32 peripheral interfaces,
- * of which some may be not be really used in your
- * DMAC's configuration.
- * Populate this array of 32 peri i/fs with relevant
- * channel IDs for used peri i/f and DMACH_MAX for
- * those unused.
- *
- * The platforms just need to provide this info
- * to the S3C DMA API driver for PL330.
- */
-struct s3c_pl330_platdata {
-	enum dma_ch peri[32];
-};
-
-#endif /* __S3C_PL330_PDATA_H */
diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c
deleted file mode 100644
index f85638c..0000000
--- a/arch/arm/plat-samsung/s3c-pl330.c
+++ /dev/null
@@ -1,1244 +0,0 @@
-/* linux/arch/arm/plat-samsung/s3c-pl330.c
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * 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.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/hardware/pl330.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-/**
- * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC.
- * @busy_chan: Number of channels currently busy.
- * @peri: List of IDs of peripherals this DMAC can work with.
- * @node: To attach to the global list of DMACs.
- * @pi: PL330 configuration info for the DMAC.
- * @kmcache: Pool to quickly allocate xfers for all channels in the dmac.
- * @clk: Pointer of DMAC operation clock.
- */
-struct s3c_pl330_dmac {
-	unsigned		busy_chan;
-	enum dma_ch		*peri;
-	struct list_head	node;
-	struct pl330_info	*pi;
-	struct kmem_cache	*kmcache;
-	struct clk		*clk;
-};
-
-/**
- * struct s3c_pl330_xfer - A request submitted by S3C DMA clients.
- * @token: Xfer ID provided by the client.
- * @node: To attach to the list of xfers on a channel.
- * @px: Xfer for PL330 core.
- * @chan: Owner channel of this xfer.
- */
-struct s3c_pl330_xfer {
-	void			*token;
-	struct list_head	node;
-	struct pl330_xfer	px;
-	struct s3c_pl330_chan	*chan;
-};
-
-/**
- * struct s3c_pl330_chan - Logical channel to communicate with
- * 	a Physical peripheral.
- * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC.
- * 	NULL if the channel is available to be acquired.
- * @id: ID of the peripheral that this channel can communicate with.
- * @options: Options specified by the client.
- * @sdaddr: Address provided via s3c2410_dma_devconfig.
- * @node: To attach to the global list of channels.
- * @lrq: Pointer to the last submitted pl330_req to PL330 core.
- * @xfer_list: To manage list of xfers enqueued.
- * @req: Two requests to communicate with the PL330 engine.
- * @callback_fn: Callback function to the client.
- * @rqcfg: Channel configuration for the xfers.
- * @xfer_head: Pointer to the xfer to be next executed.
- * @dmac: Pointer to the DMAC that manages this channel, NULL if the
- * 	channel is available to be acquired.
- * @client: Client of this channel. NULL if the
- * 	channel is available to be acquired.
- */
-struct s3c_pl330_chan {
-	void				*pl330_chan_id;
-	enum dma_ch			id;
-	unsigned int			options;
-	unsigned long			sdaddr;
-	struct list_head		node;
-	struct pl330_req		*lrq;
-	struct list_head		xfer_list;
-	struct pl330_req		req[2];
-	s3c2410_dma_cbfn_t		callback_fn;
-	struct pl330_reqcfg		rqcfg;
-	struct s3c_pl330_xfer		*xfer_head;
-	struct s3c_pl330_dmac		*dmac;
-	struct s3c2410_dma_client	*client;
-};
-
-/* All DMACs in the platform */
-static LIST_HEAD(dmac_list);
-
-/* All channels to peripherals in the platform */
-static LIST_HEAD(chan_list);
-
-/*
- * Since we add resources(DMACs and Channels) to the global pool,
- * we need to guard access to the resources using a global lock
- */
-static DEFINE_SPINLOCK(res_lock);
-
-/* Returns the channel with ID 'id' in the chan_list */
-static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch;
-
-	list_for_each_entry(ch, &chan_list, node)
-		if (ch->id == id)
-			return ch;
-
-	return NULL;
-}
-
-/* Allocate a new channel with ID 'id' and add to chan_list */
-static void chan_add(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-
-	/* Return if the channel already exists */
-	if (ch)
-		return;
-
-	ch = kmalloc(sizeof(*ch), GFP_KERNEL);
-	/* Return silently to work with other channels */
-	if (!ch)
-		return;
-
-	ch->id = id;
-	ch->dmac = NULL;
-
-	list_add_tail(&ch->node, &chan_list);
-}
-
-/* If the channel is not yet acquired by any client */
-static bool chan_free(struct s3c_pl330_chan *ch)
-{
-	if (!ch)
-		return false;
-
-	/* Channel points to some DMAC only when it's acquired */
-	return ch->dmac ? false : true;
-}
-
-/*
- * Returns 0 is peripheral i/f is invalid or not present on the dmac.
- * Index + 1, otherwise.
- */
-static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id)
-{
-	enum dma_ch *id = dmac->peri;
-	int i;
-
-	/* Discount invalid markers */
-	if (ch_id == DMACH_MAX)
-		return 0;
-
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (id[i] == ch_id)
-			return i + 1;
-
-	return 0;
-}
-
-/* If all channel threads of the DMAC are busy */
-static inline bool dmac_busy(struct s3c_pl330_dmac *dmac)
-{
-	struct pl330_info *pi = dmac->pi;
-
-	return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true;
-}
-
-/*
- * Returns the number of free channels that
- * can be handled by this dmac only.
- */
-static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac)
-{
-	enum dma_ch *id = dmac->peri;
-	struct s3c_pl330_dmac *d;
-	struct s3c_pl330_chan *ch;
-	unsigned found, count = 0;
-	enum dma_ch p;
-	int i;
-
-	for (i = 0; i < PL330_MAX_PERI; i++) {
-		p = id[i];
-		ch = id_to_chan(p);
-
-		if (p == DMACH_MAX || !chan_free(ch))
-			continue;
-
-		found = 0;
-		list_for_each_entry(d, &dmac_list, node) {
-			if (d != dmac && iface_of_dmac(d, ch->id)) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found)
-			count++;
-	}
-
-	return count;
-}
-
-/*
- * Measure of suitability of 'dmac' handling 'ch'
- *
- * 0 indicates 'dmac' can not handle 'ch' either
- * because it is not supported by the hardware or
- * because all dmac channels are currently busy.
- *
- * >0 vlaue indicates 'dmac' has the capability.
- * The bigger the value the more suitable the dmac.
- */
-#define MAX_SUIT	UINT_MAX
-#define MIN_SUIT	0
-
-static unsigned suitablility(struct s3c_pl330_dmac *dmac,
-		struct s3c_pl330_chan *ch)
-{
-	struct pl330_info *pi = dmac->pi;
-	enum dma_ch *id = dmac->peri;
-	struct s3c_pl330_dmac *d;
-	unsigned s;
-	int i;
-
-	s = MIN_SUIT;
-	/* If all the DMAC channel threads are busy */
-	if (dmac_busy(dmac))
-		return s;
-
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (id[i] == ch->id)
-			break;
-
-	/* If the 'dmac' can't talk to 'ch' */
-	if (i == PL330_MAX_PERI)
-		return s;
-
-	s = MAX_SUIT;
-	list_for_each_entry(d, &dmac_list, node) {
-		/*
-		 * If some other dmac can talk to this
-		 * peri and has some channel free.
-		 */
-		if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) {
-			s = 0;
-			break;
-		}
-	}
-	if (s)
-		return s;
-
-	s = 100;
-
-	/* Good if free chans are more, bad otherwise */
-	s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac);
-
-	return s;
-}
-
-/* More than one DMAC may have capability to transfer data with the
- * peripheral. This function assigns most suitable DMAC to manage the
- * channel and hence communicate with the peripheral.
- */
-static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch)
-{
-	struct s3c_pl330_dmac *d, *dmac = NULL;
-	unsigned sn, sl = MIN_SUIT;
-
-	list_for_each_entry(d, &dmac_list, node) {
-		sn = suitablility(d, ch);
-
-		if (sn == MAX_SUIT)
-			return d;
-
-		if (sn > sl)
-			dmac = d;
-	}
-
-	return dmac;
-}
-
-/* Acquire the channel for peripheral 'id' */
-static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-	struct s3c_pl330_dmac *dmac;
-
-	/* If the channel doesn't exist or is already acquired */
-	if (!ch || !chan_free(ch)) {
-		ch = NULL;
-		goto acq_exit;
-	}
-
-	dmac = map_chan_to_dmac(ch);
-	/* If couldn't map */
-	if (!dmac) {
-		ch = NULL;
-		goto acq_exit;
-	}
-
-	dmac->busy_chan++;
-	ch->dmac = dmac;
-
-acq_exit:
-	return ch;
-}
-
-/* Delete xfer from the queue */
-static inline void del_from_queue(struct s3c_pl330_xfer *xfer)
-{
-	struct s3c_pl330_xfer *t;
-	struct s3c_pl330_chan *ch;
-	int found;
-
-	if (!xfer)
-		return;
-
-	ch = xfer->chan;
-
-	/* Make sure xfer is in the queue */
-	found = 0;
-	list_for_each_entry(t, &ch->xfer_list, node)
-		if (t == xfer) {
-			found = 1;
-			break;
-		}
-
-	if (!found)
-		return;
-
-	/* If xfer is last entry in the queue */
-	if (xfer->node.next == &ch->xfer_list)
-		t = list_entry(ch->xfer_list.next,
-				struct s3c_pl330_xfer, node);
-	else
-		t = list_entry(xfer->node.next,
-				struct s3c_pl330_xfer, node);
-
-	/* If there was only one node left */
-	if (t == xfer)
-		ch->xfer_head = NULL;
-	else if (ch->xfer_head == xfer)
-		ch->xfer_head = t;
-
-	list_del(&xfer->node);
-}
-
-/* Provides pointer to the next xfer in the queue.
- * If CIRCULAR option is set, the list is left intact,
- * otherwise the xfer is removed from the list.
- * Forced delete 'pluck' can be set to override the CIRCULAR option.
- */
-static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch,
-		int pluck)
-{
-	struct s3c_pl330_xfer *xfer = ch->xfer_head;
-
-	if (!xfer)
-		return NULL;
-
-	/* If xfer is last entry in the queue */
-	if (xfer->node.next == &ch->xfer_list)
-		ch->xfer_head = list_entry(ch->xfer_list.next,
-					struct s3c_pl330_xfer, node);
-	else
-		ch->xfer_head = list_entry(xfer->node.next,
-					struct s3c_pl330_xfer, node);
-
-	if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR))
-		del_from_queue(xfer);
-
-	return xfer;
-}
-
-static inline void add_to_queue(struct s3c_pl330_chan *ch,
-		struct s3c_pl330_xfer *xfer, int front)
-{
-	struct pl330_xfer *xt;
-
-	/* If queue empty */
-	if (ch->xfer_head == NULL)
-		ch->xfer_head = xfer;
-
-	xt = &ch->xfer_head->px;
-	/* If the head already submitted (CIRCULAR head) */
-	if (ch->options & S3C2410_DMAF_CIRCULAR &&
-		(xt == ch->req[0].x || xt == ch->req[1].x))
-		ch->xfer_head = xfer;
-
-	/* If this is a resubmission, it should go at the head */
-	if (front) {
-		ch->xfer_head = xfer;
-		list_add(&xfer->node, &ch->xfer_list);
-	} else {
-		list_add_tail(&xfer->node, &ch->xfer_list);
-	}
-}
-
-static inline void _finish_off(struct s3c_pl330_xfer *xfer,
-		enum s3c2410_dma_buffresult res, int ffree)
-{
-	struct s3c_pl330_chan *ch;
-
-	if (!xfer)
-		return;
-
-	ch = xfer->chan;
-
-	/* Do callback */
-	if (ch->callback_fn)
-		ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res);
-
-	/* Force Free or if buffer is not needed anymore */
-	if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR))
-		kmem_cache_free(ch->dmac->kmcache, xfer);
-}
-
-static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch,
-		struct pl330_req *r)
-{
-	struct s3c_pl330_xfer *xfer;
-	int ret = 0;
-
-	/* If already submitted */
-	if (r->x)
-		return 0;
-
-	xfer = get_from_queue(ch, 0);
-	if (xfer) {
-		r->x = &xfer->px;
-
-		/* Use max bandwidth for M<->M xfers */
-		if (r->rqtype == MEMTOMEM) {
-			struct pl330_info *pi = xfer->chan->dmac->pi;
-			int burst = 1 << ch->rqcfg.brst_size;
-			u32 bytes = r->x->bytes;
-			int bl;
-
-			bl = pi->pcfg.data_bus_width / 8;
-			bl *= pi->pcfg.data_buf_dep;
-			bl /= burst;
-
-			/* src/dst_burst_len can't be more than 16 */
-			if (bl > 16)
-				bl = 16;
-
-			while (bl > 1) {
-				if (!(bytes % (bl * burst)))
-					break;
-				bl--;
-			}
-
-			ch->rqcfg.brst_len = bl;
-		} else {
-			ch->rqcfg.brst_len = 1;
-		}
-
-		ret = pl330_submit_req(ch->pl330_chan_id, r);
-
-		/* If submission was successful */
-		if (!ret) {
-			ch->lrq = r; /* latest submitted req */
-			return 0;
-		}
-
-		r->x = NULL;
-
-		/* If both of the PL330 ping-pong buffers filled */
-		if (ret == -EAGAIN) {
-			dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-				__func__, __LINE__);
-			/* Queue back again */
-			add_to_queue(ch, xfer, 1);
-			ret = 0;
-		} else {
-			dev_err(ch->dmac->pi->dev, "%s:%d!\n",
-				__func__, __LINE__);
-			_finish_off(xfer, S3C2410_RES_ERR, 0);
-		}
-	}
-
-	return ret;
-}
-
-static void s3c_pl330_rq(struct s3c_pl330_chan *ch,
-	struct pl330_req *r, enum pl330_op_err err)
-{
-	unsigned long flags;
-	struct s3c_pl330_xfer *xfer;
-	struct pl330_xfer *xl = r->x;
-	enum s3c2410_dma_buffresult res;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	r->x = NULL;
-
-	s3c_pl330_submit(ch, r);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	/* Map result to S3C DMA API */
-	if (err == PL330_ERR_NONE)
-		res = S3C2410_RES_OK;
-	else if (err == PL330_ERR_ABORT)
-		res = S3C2410_RES_ABORT;
-	else
-		res = S3C2410_RES_ERR;
-
-	/* If last request had some xfer */
-	if (xl) {
-		xfer = container_of(xl, struct s3c_pl330_xfer, px);
-		_finish_off(xfer, res, 0);
-	} else {
-		dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n",
-			__func__, __LINE__);
-	}
-}
-
-static void s3c_pl330_rq0(void *token, enum pl330_op_err err)
-{
-	struct pl330_req *r = token;
-	struct s3c_pl330_chan *ch = container_of(r,
-					struct s3c_pl330_chan, req[0]);
-	s3c_pl330_rq(ch, r, err);
-}
-
-static void s3c_pl330_rq1(void *token, enum pl330_op_err err)
-{
-	struct pl330_req *r = token;
-	struct s3c_pl330_chan *ch = container_of(r,
-					struct s3c_pl330_chan, req[1]);
-	s3c_pl330_rq(ch, r, err);
-}
-
-/* Release an acquired channel */
-static void chan_release(struct s3c_pl330_chan *ch)
-{
-	struct s3c_pl330_dmac *dmac;
-
-	if (chan_free(ch))
-		return;
-
-	dmac = ch->dmac;
-	ch->dmac = NULL;
-	dmac->busy_chan--;
-}
-
-int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op)
-{
-	struct s3c_pl330_xfer *xfer;
-	enum pl330_chan_op pl330op;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int idx, ret;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto ctrl_exit;
-	}
-
-	switch (op) {
-	case S3C2410_DMAOP_START:
-		/* Make sure both reqs are enqueued */
-		idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-		s3c_pl330_submit(ch, &ch->req[idx]);
-		s3c_pl330_submit(ch, &ch->req[1 - idx]);
-		pl330op = PL330_OP_START;
-		break;
-
-	case S3C2410_DMAOP_STOP:
-		pl330op = PL330_OP_ABORT;
-		break;
-
-	case S3C2410_DMAOP_FLUSH:
-		pl330op = PL330_OP_FLUSH;
-		break;
-
-	case S3C2410_DMAOP_PAUSE:
-	case S3C2410_DMAOP_RESUME:
-	case S3C2410_DMAOP_TIMEOUT:
-	case S3C2410_DMAOP_STARTED:
-		spin_unlock_irqrestore(&res_lock, flags);
-		return 0;
-
-	default:
-		spin_unlock_irqrestore(&res_lock, flags);
-		return -EINVAL;
-	}
-
-	ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op);
-
-	if (pl330op == PL330_OP_START) {
-		spin_unlock_irqrestore(&res_lock, flags);
-		return ret;
-	}
-
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	/* Abort the current xfer */
-	if (ch->req[idx].x) {
-		xfer = container_of(ch->req[idx].x,
-				struct s3c_pl330_xfer, px);
-
-		/* Drop xfer during FLUSH */
-		if (pl330op == PL330_OP_FLUSH)
-			del_from_queue(xfer);
-
-		ch->req[idx].x = NULL;
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT,
-				pl330op == PL330_OP_FLUSH ? 1 : 0);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	/* Flush the whole queue */
-	if (pl330op == PL330_OP_FLUSH) {
-
-		if (ch->req[1 - idx].x) {
-			xfer = container_of(ch->req[1 - idx].x,
-					struct s3c_pl330_xfer, px);
-
-			del_from_queue(xfer);
-
-			ch->req[1 - idx].x = NULL;
-
-			spin_unlock_irqrestore(&res_lock, flags);
-			_finish_off(xfer, S3C2410_RES_ABORT, 1);
-			spin_lock_irqsave(&res_lock, flags);
-		}
-
-		/* Finish off the remaining in the queue */
-		xfer = ch->xfer_head;
-		while (xfer) {
-
-			del_from_queue(xfer);
-
-			spin_unlock_irqrestore(&res_lock, flags);
-			_finish_off(xfer, S3C2410_RES_ABORT, 1);
-			spin_lock_irqsave(&res_lock, flags);
-
-			xfer = ch->xfer_head;
-		}
-	}
-
-ctrl_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-int s3c2410_dma_enqueue(enum dma_ch id, void *token,
-			dma_addr_t addr, int size)
-{
-	struct s3c_pl330_chan *ch;
-	struct s3c_pl330_xfer *xfer;
-	unsigned long flags;
-	int idx, ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	/* Error if invalid or free channel */
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto enq_exit;
-	}
-
-	/* Error if size is unaligned */
-	if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) {
-		ret = -EINVAL;
-		goto enq_exit;
-	}
-
-	xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC);
-	if (!xfer) {
-		ret = -ENOMEM;
-		goto enq_exit;
-	}
-
-	xfer->token = token;
-	xfer->chan = ch;
-	xfer->px.bytes = size;
-	xfer->px.next = NULL; /* Single request */
-
-	/* For S3C DMA API, direction is always fixed for all xfers */
-	if (ch->req[0].rqtype == MEMTODEV) {
-		xfer->px.src_addr = addr;
-		xfer->px.dst_addr = ch->sdaddr;
-	} else {
-		xfer->px.src_addr = ch->sdaddr;
-		xfer->px.dst_addr = addr;
-	}
-
-	add_to_queue(ch, xfer, 0);
-
-	/* Try submitting on either request */
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	if (!ch->req[idx].x)
-		s3c_pl330_submit(ch, &ch->req[idx]);
-	else
-		s3c_pl330_submit(ch, &ch->req[1 - idx]);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	if (ch->options & S3C2410_DMAF_AUTOSTART)
-		s3c2410_dma_ctrl(id, S3C2410_DMAOP_START);
-
-	return 0;
-
-enq_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-int s3c2410_dma_request(enum dma_ch id,
-			struct s3c2410_dma_client *client,
-			void *dev)
-{
-	struct s3c_pl330_dmac *dmac;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = chan_acquire(id);
-	if (!ch) {
-		ret = -EBUSY;
-		goto req_exit;
-	}
-
-	dmac = ch->dmac;
-
-	ch->pl330_chan_id = pl330_request_channel(dmac->pi);
-	if (!ch->pl330_chan_id) {
-		chan_release(ch);
-		ret = -EBUSY;
-		goto req_exit;
-	}
-
-	ch->client = client;
-	ch->options = 0; /* Clear any option */
-	ch->callback_fn = NULL; /* Clear any callback */
-	ch->lrq = NULL;
-
-	ch->rqcfg.brst_size = 2; /* Default word size */
-	ch->rqcfg.swap = SWAP_NO;
-	ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */
-	ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */
-	ch->rqcfg.privileged = 0;
-	ch->rqcfg.insnaccess = 0;
-
-	/* Set invalid direction */
-	ch->req[0].rqtype = DEVTODEV;
-	ch->req[1].rqtype = ch->req[0].rqtype;
-
-	ch->req[0].cfg = &ch->rqcfg;
-	ch->req[1].cfg = ch->req[0].cfg;
-
-	ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */
-	ch->req[1].peri = ch->req[0].peri;
-
-	ch->req[0].token = &ch->req[0];
-	ch->req[0].xfer_cb = s3c_pl330_rq0;
-	ch->req[1].token = &ch->req[1];
-	ch->req[1].xfer_cb = s3c_pl330_rq1;
-
-	ch->req[0].x = NULL;
-	ch->req[1].x = NULL;
-
-	/* Reset xfer list */
-	INIT_LIST_HEAD(&ch->xfer_list);
-	ch->xfer_head = NULL;
-
-req_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
-{
-	struct s3c_pl330_chan *ch;
-	struct s3c_pl330_xfer *xfer;
-	unsigned long flags;
-	int ret = 0;
-	unsigned idx;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch))
-		goto free_exit;
-
-	/* Refuse if someone else wanted to free the channel */
-	if (ch->client != client) {
-		ret = -EBUSY;
-		goto free_exit;
-	}
-
-	/* Stop any active xfer, Flushe the queue and do callbacks */
-	pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH);
-
-	/* Abort the submitted requests */
-	idx = (ch->lrq == &ch->req[0]) ? 1 : 0;
-
-	if (ch->req[idx].x) {
-		xfer = container_of(ch->req[idx].x,
-				struct s3c_pl330_xfer, px);
-
-		ch->req[idx].x = NULL;
-		del_from_queue(xfer);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	if (ch->req[1 - idx].x) {
-		xfer = container_of(ch->req[1 - idx].x,
-				struct s3c_pl330_xfer, px);
-
-		ch->req[1 - idx].x = NULL;
-		del_from_queue(xfer);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	}
-
-	/* Pluck and Abort the queued requests in order */
-	do {
-		xfer = get_from_queue(ch, 1);
-
-		spin_unlock_irqrestore(&res_lock, flags);
-		_finish_off(xfer, S3C2410_RES_ABORT, 1);
-		spin_lock_irqsave(&res_lock, flags);
-	} while (xfer);
-
-	ch->client = NULL;
-
-	pl330_release_channel(ch->pl330_chan_id);
-
-	ch->pl330_chan_id = NULL;
-
-	chan_release(ch);
-
-free_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-int s3c2410_dma_config(enum dma_ch id, int xferunit)
-{
-	struct s3c_pl330_chan *ch;
-	struct pl330_info *pi;
-	unsigned long flags;
-	int i, dbwidth, ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto cfg_exit;
-	}
-
-	pi = ch->dmac->pi;
-	dbwidth = pi->pcfg.data_bus_width / 8;
-
-	/* Max size of xfer can be pcfg.data_bus_width */
-	if (xferunit > dbwidth) {
-		ret = -EINVAL;
-		goto cfg_exit;
-	}
-
-	i = 0;
-	while (xferunit != (1 << i))
-		i++;
-
-	/* If valid value */
-	if (xferunit == (1 << i))
-		ch->rqcfg.brst_size = i;
-	else
-		ret = -EINVAL;
-
-cfg_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-/* Options that are supported by this driver */
-#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART)
-
-int s3c2410_dma_setflags(enum dma_ch id, unsigned int options)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS))
-		ret = -EINVAL;
-	else
-		ch->options = options;
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch))
-		ret = -EINVAL;
-	else
-		ch->callback_fn = rtn;
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
-			  unsigned long address)
-{
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	ch = id_to_chan(id);
-
-	if (!ch || chan_free(ch)) {
-		ret = -EINVAL;
-		goto devcfg_exit;
-	}
-
-	switch (source) {
-	case S3C2410_DMASRC_HW: /* P->M */
-		ch->req[0].rqtype = DEVTOMEM;
-		ch->req[1].rqtype = DEVTOMEM;
-		ch->rqcfg.src_inc = 0;
-		ch->rqcfg.dst_inc = 1;
-		break;
-	case S3C2410_DMASRC_MEM: /* M->P */
-		ch->req[0].rqtype = MEMTODEV;
-		ch->req[1].rqtype = MEMTODEV;
-		ch->rqcfg.src_inc = 1;
-		ch->rqcfg.dst_inc = 0;
-		break;
-	default:
-		ret = -EINVAL;
-		goto devcfg_exit;
-	}
-
-	ch->sdaddr = address;
-
-devcfg_exit:
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst)
-{
-	struct s3c_pl330_chan *ch = id_to_chan(id);
-	struct pl330_chanstatus status;
-	int ret;
-
-	if (!ch || chan_free(ch))
-		return -EINVAL;
-
-	ret = pl330_chan_status(ch->pl330_chan_id, &status);
-	if (ret < 0)
-		return ret;
-
-	*src = status.src_addr;
-	*dst = status.dst_addr;
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-static irqreturn_t pl330_irq_handler(int irq, void *data)
-{
-	if (pl330_update(data))
-		return IRQ_HANDLED;
-	else
-		return IRQ_NONE;
-}
-
-static int pl330_probe(struct platform_device *pdev)
-{
-	struct s3c_pl330_dmac *s3c_pl330_dmac;
-	struct s3c_pl330_platdata *pl330pd;
-	struct pl330_info *pl330_info;
-	struct resource *res;
-	int i, ret, irq;
-
-	pl330pd = pdev->dev.platform_data;
-
-	/* Can't do without the list of _32_ peripherals */
-	if (!pl330pd || !pl330pd->peri) {
-		dev_err(&pdev->dev, "platform data missing!\n");
-		return -ENODEV;
-	}
-
-	pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL);
-	if (!pl330_info)
-		return -ENOMEM;
-
-	pl330_info->pl330_data = NULL;
-	pl330_info->dev = &pdev->dev;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		goto probe_err1;
-	}
-
-	request_mem_region(res->start, resource_size(res), pdev->name);
-
-	pl330_info->base = ioremap(res->start, resource_size(res));
-	if (!pl330_info->base) {
-		ret = -ENXIO;
-		goto probe_err2;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		ret = irq;
-		goto probe_err3;
-	}
-
-	ret = request_irq(irq, pl330_irq_handler, 0,
-			dev_name(&pdev->dev), pl330_info);
-	if (ret)
-		goto probe_err4;
-
-	/* Allocate a new DMAC */
-	s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL);
-	if (!s3c_pl330_dmac) {
-		ret = -ENOMEM;
-		goto probe_err5;
-	}
-
-	/* Get operation clock and enable it */
-	s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma");
-	if (IS_ERR(s3c_pl330_dmac->clk)) {
-		dev_err(&pdev->dev, "Cannot get operation clock.\n");
-		ret = -EINVAL;
-		goto probe_err6;
-	}
-	clk_enable(s3c_pl330_dmac->clk);
-
-	ret = pl330_add(pl330_info);
-	if (ret)
-		goto probe_err7;
-
-	/* Hook the info */
-	s3c_pl330_dmac->pi = pl330_info;
-
-	/* No busy channels */
-	s3c_pl330_dmac->busy_chan = 0;
-
-	s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev),
-				sizeof(struct s3c_pl330_xfer), 0, 0, NULL);
-
-	if (!s3c_pl330_dmac->kmcache) {
-		ret = -ENOMEM;
-		goto probe_err8;
-	}
-
-	/* Get the list of peripherals */
-	s3c_pl330_dmac->peri = pl330pd->peri;
-
-	/* Attach to the list of DMACs */
-	list_add_tail(&s3c_pl330_dmac->node, &dmac_list);
-
-	/* Create a channel for each peripheral in the DMAC
-	 * that is, if it doesn't already exist
-	 */
-	for (i = 0; i < PL330_MAX_PERI; i++)
-		if (s3c_pl330_dmac->peri[i] != DMACH_MAX)
-			chan_add(s3c_pl330_dmac->peri[i]);
-
-	printk(KERN_INFO
-		"Loaded driver for PL330 DMAC-%d %s\n",	pdev->id, pdev->name);
-	printk(KERN_INFO
-		"\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
-		pl330_info->pcfg.data_buf_dep,
-		pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
-		pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
-
-	return 0;
-
-probe_err8:
-	pl330_del(pl330_info);
-probe_err7:
-	clk_disable(s3c_pl330_dmac->clk);
-	clk_put(s3c_pl330_dmac->clk);
-probe_err6:
-	kfree(s3c_pl330_dmac);
-probe_err5:
-	free_irq(irq, pl330_info);
-probe_err4:
-probe_err3:
-	iounmap(pl330_info->base);
-probe_err2:
-	release_mem_region(res->start, resource_size(res));
-probe_err1:
-	kfree(pl330_info);
-
-	return ret;
-}
-
-static int pl330_remove(struct platform_device *pdev)
-{
-	struct s3c_pl330_dmac *dmac, *d;
-	struct s3c_pl330_chan *ch;
-	unsigned long flags;
-	int del, found;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	spin_lock_irqsave(&res_lock, flags);
-
-	found = 0;
-	list_for_each_entry(d, &dmac_list, node)
-		if (d->pi->dev == &pdev->dev) {
-			found = 1;
-			break;
-		}
-
-	if (!found) {
-		spin_unlock_irqrestore(&res_lock, flags);
-		return 0;
-	}
-
-	dmac = d;
-
-	/* Remove all Channels that are managed only by this DMAC */
-	list_for_each_entry(ch, &chan_list, node) {
-
-		/* Only channels that are handled by this DMAC */
-		if (iface_of_dmac(dmac, ch->id))
-			del = 1;
-		else
-			continue;
-
-		/* Don't remove if some other DMAC has it too */
-		list_for_each_entry(d, &dmac_list, node)
-			if (d != dmac && iface_of_dmac(d, ch->id)) {
-				del = 0;
-				break;
-			}
-
-		if (del) {
-			spin_unlock_irqrestore(&res_lock, flags);
-			s3c2410_dma_free(ch->id, ch->client);
-			spin_lock_irqsave(&res_lock, flags);
-			list_del(&ch->node);
-			kfree(ch);
-		}
-	}
-
-	/* Disable operation clock */
-	clk_disable(dmac->clk);
-	clk_put(dmac->clk);
-
-	/* Remove the DMAC */
-	list_del(&dmac->node);
-	kfree(dmac);
-
-	spin_unlock_irqrestore(&res_lock, flags);
-
-	return 0;
-}
-
-static struct platform_driver pl330_driver = {
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "s3c-pl330",
-	},
-	.probe		= pl330_probe,
-	.remove		= pl330_remove,
-};
-
-static int __init pl330_init(void)
-{
-	return platform_driver_register(&pl330_driver);
-}
-module_init(pl330_init);
-
-static void __exit pl330_exit(void)
-{
-	platform_driver_unregister(&pl330_driver);
-	return;
-}
-module_exit(pl330_exit);
-
-MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
-MODULE_DESCRIPTION("Driver for PL330 DMA Controller");
-MODULE_LICENSE("GPL");
-- 
1.7.1

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

* [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch adds to support DMA generic API to transfer raw
SPI data. Basiclly the spi driver uses DMA generic API if
architecture supports it. Otherwise, uses Samsung specific
S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++-----------------------
 1 files changed, 69 insertions(+), 72 deletions(-)

diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index 8945e20..a4cf76a 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
 	unsigned                        state;
 	unsigned                        cur_mode, cur_bpw;
 	unsigned                        cur_speed;
+	unsigned			rx_ch;
+	unsigned			tx_ch;
+	struct samsung_dma_ops		*ops;
 };
 
 static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -227,6 +230,38 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
 	writel(val, regs + S3C64XX_SPI_CH_CFG);
 }
 
+static void s3c64xx_spi_dma_rxcb(void *data)
+{
+	struct s3c64xx_spi_driver_data *sdd
+		= (struct s3c64xx_spi_driver_data *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	sdd->state &= ~RXBUSY;
+	/* If the other done */
+	if (!(sdd->state & TXBUSY))
+		complete(&sdd->xfer_completion);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+static void s3c64xx_spi_dma_txcb(void *data)
+{
+	struct s3c64xx_spi_driver_data *sdd
+		= (struct s3c64xx_spi_driver_data *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	sdd->state &= ~TXBUSY;
+	/* If the other done */
+	if (!(sdd->state & RXBUSY))
+		complete(&sdd->xfer_completion);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 				struct spi_device *spi,
 				struct spi_transfer *xfer, int dma_mode)
@@ -234,6 +269,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 	void __iomem *regs = sdd->regs;
 	u32 modecfg, chcfg;
+	struct samsung_dma_prep_info info;
 
 	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
 	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
@@ -259,10 +295,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
 		if (dma_mode) {
 			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
-			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
-						xfer->tx_dma, xfer->len);
-			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
+			info.cap = DMA_SLAVE;
+			info.direction = DMA_TO_DEVICE;
+			info.buf = xfer->tx_dma;
+			info.len = xfer->len;
+			info.fp = s3c64xx_spi_dma_txcb;
+			info.fp_param = sdd;
+			sdd->ops->prepare(sdd->tx_ch, &info);
+			sdd->ops->trigger(sdd->tx_ch);
 		} else {
 			switch (sdd->cur_bpw) {
 			case 32:
@@ -294,10 +334,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
 					| S3C64XX_SPI_PACKET_CNT_EN,
 					regs + S3C64XX_SPI_PACKET_CNT);
-			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
-			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
-						xfer->rx_dma, xfer->len);
-			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
+			info.cap = DMA_SLAVE;
+			info.direction = DMA_FROM_DEVICE;
+			info.buf = xfer->rx_dma;
+			info.len = xfer->len;
+			info.fp = s3c64xx_spi_dma_rxcb;
+			info.fp_param = sdd;
+			sdd->ops->prepare(sdd->rx_ch, &info);
+			sdd->ops->trigger(sdd->rx_ch);
 		}
 	}
 
@@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 	}
 }
 
-static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
-				 int size, enum s3c2410_dma_buffresult res)
-{
-	struct s3c64xx_spi_driver_data *sdd = buf_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	if (res == S3C2410_RES_OK)
-		sdd->state &= ~RXBUSY;
-	else
-		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
-
-	/* If the other done */
-	if (!(sdd->state & TXBUSY))
-		complete(&sdd->xfer_completion);
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
-static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
-				 int size, enum s3c2410_dma_buffresult res)
-{
-	struct s3c64xx_spi_driver_data *sdd = buf_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	if (res == S3C2410_RES_OK)
-		sdd->state &= ~TXBUSY;
-	else
-		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
-
-	/* If the other done */
-	if (!(sdd->state & RXBUSY))
-		complete(&sdd->xfer_completion);
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
 #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
 
 static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
@@ -697,12 +701,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
 			if (use_dma) {
 				if (xfer->tx_buf != NULL
 						&& (sdd->state & TXBUSY))
-					s3c2410_dma_ctrl(sdd->tx_dmach,
-							S3C2410_DMAOP_FLUSH);
+					sdd->ops->stop(sdd->tx_ch);
 				if (xfer->rx_buf != NULL
 						&& (sdd->state & RXBUSY))
-					s3c2410_dma_ctrl(sdd->rx_dmach,
-							S3C2410_DMAOP_FLUSH);
+					sdd->ops->stop(sdd->rx_ch);
 			}
 
 			goto out;
@@ -742,24 +744,19 @@ out:
 
 static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
 {
-	if (s3c2410_dma_request(sdd->rx_dmach,
-					&s3c64xx_spi_dma_client, NULL) < 0) {
-		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
-		return 0;
-	}
-	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
-	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
-					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
-
-	if (s3c2410_dma_request(sdd->tx_dmach,
-					&s3c64xx_spi_dma_client, NULL) < 0) {
-		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
-		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
-		return 0;
-	}
-	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
-	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
-					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
+
+	struct samsung_dma_info info;
+	sdd->ops = samsung_dma_get_ops();
+
+	info.cap = DMA_SLAVE;
+	info.client = &s3c64xx_spi_dma_client;
+	info.direction = DMA_FROM_DEVICE;
+	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
+	info.width = sdd->cur_bpw / 8;
+	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
+	info.direction = DMA_TO_DEVICE;
+	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
+	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
 
 	return 1;
 }
@@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
 	spin_unlock_irqrestore(&sdd->lock, flags);
 
 	/* Free DMA channels */
-	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
-	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+	sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client);
+	sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client);
 }
 
 static int s3c64xx_spi_transfer(struct spi_device *spi,
-- 
1.7.1

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

* [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds to support DMA generic API to transfer raw
SPI data. Basiclly the spi driver uses DMA generic API if
architecture supports it. Otherwise, uses Samsung specific
S3C-PL330 APIs.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++-----------------------
 1 files changed, 69 insertions(+), 72 deletions(-)

diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index 8945e20..a4cf76a 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
 	unsigned                        state;
 	unsigned                        cur_mode, cur_bpw;
 	unsigned                        cur_speed;
+	unsigned			rx_ch;
+	unsigned			tx_ch;
+	struct samsung_dma_ops		*ops;
 };
 
 static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -227,6 +230,38 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
 	writel(val, regs + S3C64XX_SPI_CH_CFG);
 }
 
+static void s3c64xx_spi_dma_rxcb(void *data)
+{
+	struct s3c64xx_spi_driver_data *sdd
+		= (struct s3c64xx_spi_driver_data *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	sdd->state &= ~RXBUSY;
+	/* If the other done */
+	if (!(sdd->state & TXBUSY))
+		complete(&sdd->xfer_completion);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+static void s3c64xx_spi_dma_txcb(void *data)
+{
+	struct s3c64xx_spi_driver_data *sdd
+		= (struct s3c64xx_spi_driver_data *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	sdd->state &= ~TXBUSY;
+	/* If the other done */
+	if (!(sdd->state & RXBUSY))
+		complete(&sdd->xfer_completion);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 				struct spi_device *spi,
 				struct spi_transfer *xfer, int dma_mode)
@@ -234,6 +269,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 	void __iomem *regs = sdd->regs;
 	u32 modecfg, chcfg;
+	struct samsung_dma_prep_info info;
 
 	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
 	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
@@ -259,10 +295,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
 		if (dma_mode) {
 			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
-			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
-			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
-						xfer->tx_dma, xfer->len);
-			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
+			info.cap = DMA_SLAVE;
+			info.direction = DMA_TO_DEVICE;
+			info.buf = xfer->tx_dma;
+			info.len = xfer->len;
+			info.fp = s3c64xx_spi_dma_txcb;
+			info.fp_param = sdd;
+			sdd->ops->prepare(sdd->tx_ch, &info);
+			sdd->ops->trigger(sdd->tx_ch);
 		} else {
 			switch (sdd->cur_bpw) {
 			case 32:
@@ -294,10 +334,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
 			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
 					| S3C64XX_SPI_PACKET_CNT_EN,
 					regs + S3C64XX_SPI_PACKET_CNT);
-			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
-			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
-						xfer->rx_dma, xfer->len);
-			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
+			info.cap = DMA_SLAVE;
+			info.direction = DMA_FROM_DEVICE;
+			info.buf = xfer->rx_dma;
+			info.len = xfer->len;
+			info.fp = s3c64xx_spi_dma_rxcb;
+			info.fp_param = sdd;
+			sdd->ops->prepare(sdd->rx_ch, &info);
+			sdd->ops->trigger(sdd->rx_ch);
 		}
 	}
 
@@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 	}
 }
 
-static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
-				 int size, enum s3c2410_dma_buffresult res)
-{
-	struct s3c64xx_spi_driver_data *sdd = buf_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	if (res == S3C2410_RES_OK)
-		sdd->state &= ~RXBUSY;
-	else
-		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
-
-	/* If the other done */
-	if (!(sdd->state & TXBUSY))
-		complete(&sdd->xfer_completion);
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
-static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
-				 int size, enum s3c2410_dma_buffresult res)
-{
-	struct s3c64xx_spi_driver_data *sdd = buf_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sdd->lock, flags);
-
-	if (res == S3C2410_RES_OK)
-		sdd->state &= ~TXBUSY;
-	else
-		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
-
-	/* If the other done */
-	if (!(sdd->state & RXBUSY))
-		complete(&sdd->xfer_completion);
-
-	spin_unlock_irqrestore(&sdd->lock, flags);
-}
-
 #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
 
 static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
@@ -697,12 +701,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
 			if (use_dma) {
 				if (xfer->tx_buf != NULL
 						&& (sdd->state & TXBUSY))
-					s3c2410_dma_ctrl(sdd->tx_dmach,
-							S3C2410_DMAOP_FLUSH);
+					sdd->ops->stop(sdd->tx_ch);
 				if (xfer->rx_buf != NULL
 						&& (sdd->state & RXBUSY))
-					s3c2410_dma_ctrl(sdd->rx_dmach,
-							S3C2410_DMAOP_FLUSH);
+					sdd->ops->stop(sdd->rx_ch);
 			}
 
 			goto out;
@@ -742,24 +744,19 @@ out:
 
 static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
 {
-	if (s3c2410_dma_request(sdd->rx_dmach,
-					&s3c64xx_spi_dma_client, NULL) < 0) {
-		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
-		return 0;
-	}
-	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
-	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
-					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
-
-	if (s3c2410_dma_request(sdd->tx_dmach,
-					&s3c64xx_spi_dma_client, NULL) < 0) {
-		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
-		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
-		return 0;
-	}
-	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
-	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
-					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
+
+	struct samsung_dma_info info;
+	sdd->ops = samsung_dma_get_ops();
+
+	info.cap = DMA_SLAVE;
+	info.client = &s3c64xx_spi_dma_client;
+	info.direction = DMA_FROM_DEVICE;
+	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
+	info.width = sdd->cur_bpw / 8;
+	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
+	info.direction = DMA_TO_DEVICE;
+	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
+	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
 
 	return 1;
 }
@@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
 	spin_unlock_irqrestore(&sdd->lock, flags);
 
 	/* Free DMA channels */
-	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
-	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+	sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client);
+	sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client);
 }
 
 static int s3c64xx_spi_transfer(struct spi_device *spi,
-- 
1.7.1

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

* [PATCH V4 13/14] ASoC: Samsung: Update DMA interface
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim, Liam Girdwood

This patch adds to support the DMA PL330 driver that uses
DMA generic API. Samsung sound driver uses DMA generic API
if architecture supports it. Otherwise, use samsung specific
S3C-PL330 API driver to transfer PCM data.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Cc: Jassi Brar <jassisinghbrar@gmail.com>
Cc: Liam Girdwood <lrg@ti.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s3c2410/include/mach/dma.h       |   10 +-
 arch/arm/mach-s3c64xx/include/mach/dma.h       |    2 +-
 arch/arm/plat-samsung/include/plat/dma-pl330.h |    2 +-
 sound/soc/samsung/ac97.c                       |   10 ++-
 sound/soc/samsung/dma.c                        |  144 ++++++++++--------------
 sound/soc/samsung/dma.h                        |    4 +-
 6 files changed, 78 insertions(+), 94 deletions(-)

diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h
index e61a91f..4e485ba 100644
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
@@ -50,6 +50,11 @@ enum dma_ch {
 	DMACH_MAX,		/* the end entry */
 };
 
+static inline bool samsung_dma_has_circular(void)
+{
+	return false;
+}
+
 static inline bool samsung_dma_is_dmadev(void)
 {
 	return false;
@@ -202,9 +207,4 @@ struct s3c2410_dma_chan {
 
 typedef unsigned long dma_device_t;
 
-static inline bool s3c_dma_has_circular(void)
-{
-	return false;
-}
-
 #endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index 49c3a53..74fdf25 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -58,7 +58,7 @@ enum dma_ch {
 	DMACH_MAX		/* the end */
 };
 
-static __inline__ bool s3c_dma_has_circular(void)
+static inline bool samsung_dma_has_circular(void)
 {
 	return true;
 }
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index ded416c..c64b845 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -97,7 +97,7 @@ struct s3c2410_dma_client {
 	char	*name;
 };
 
-static inline bool s3c_dma_has_circular(void)
+static inline bool samsung_dma_has_circular(void)
 {
 	return true;
 }
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index f97110e..b4f9b00 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -271,7 +271,10 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 
 	writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-	s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+	if (!dma_data->ops)
+		dma_data->ops = samsung_dma_get_ops();
+
+	dma_data->ops->started(dma_data->channel);
 
 	return 0;
 }
@@ -317,7 +320,10 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 
 	writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-	s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+	if (!dma_data->ops)
+		dma_data->ops = samsung_dma_get_ops();
+
+	dma_data->ops->started(dma_data->channel);
 
 	return 0;
 }
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 5cb3b88..ceca331 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -62,77 +62,79 @@ struct runtime_data {
 	struct s3c_dma_params *params;
 };
 
+static void audio_buffdone(void *data);
+
 /* dma_enqueue
  *
  * place a dma buffer onto the queue for the dma system
  * to handle.
-*/
+ */
 static void dma_enqueue(struct snd_pcm_substream *substream)
 {
 	struct runtime_data *prtd = substream->runtime->private_data;
 	dma_addr_t pos = prtd->dma_pos;
 	unsigned int limit;
-	int ret;
+	struct samsung_dma_prep_info dma_info;
 
 	pr_debug("Entered %s\n", __func__);
 
-	if (s3c_dma_has_circular())
-		limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
-	else
-		limit = prtd->dma_limit;
+	limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
 
 	pr_debug("%s: loaded %d, limit %d\n",
 				__func__, prtd->dma_loaded, limit);
 
-	while (prtd->dma_loaded < limit) {
-		unsigned long len = prtd->dma_period;
+	dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
+	dma_info.direction =
+		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+		? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	dma_info.fp = audio_buffdone;
+	dma_info.fp_param = substream;
+	dma_info.period = prtd->dma_period;
+	dma_info.len = prtd->dma_period*limit;
 
+	while (prtd->dma_loaded < limit) {
 		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
 
-		if ((pos + len) > prtd->dma_end) {
-			len  = prtd->dma_end - pos;
-			pr_debug("%s: corrected dma len %ld\n", __func__, len);
+		if ((pos + dma_info.period) > prtd->dma_end) {
+			dma_info.period  = prtd->dma_end - pos;
+			pr_debug("%s: corrected dma len %ld\n",
+					__func__, dma_info.period);
 		}
 
-		ret = s3c2410_dma_enqueue(prtd->params->channel,
-			substream, pos, len);
+		dma_info.buf = pos;
+		prtd->params->ops->prepare(prtd->params->ch, &dma_info);
 
-		if (ret == 0) {
-			prtd->dma_loaded++;
-			pos += prtd->dma_period;
-			if (pos >= prtd->dma_end)
-				pos = prtd->dma_start;
-		} else
-			break;
+		prtd->dma_loaded++;
+		pos += prtd->dma_period;
+		if (pos >= prtd->dma_end)
+			pos = prtd->dma_start;
 	}
 
 	prtd->dma_pos = pos;
 }
 
-static void audio_buffdone(struct s3c2410_dma_chan *channel,
-				void *dev_id, int size,
-				enum s3c2410_dma_buffresult result)
+static void audio_buffdone(void *data)
 {
-	struct snd_pcm_substream *substream = dev_id;
-	struct runtime_data *prtd;
+	struct snd_pcm_substream *substream = data;
+	struct runtime_data *prtd = substream->runtime->private_data;
 
 	pr_debug("Entered %s\n", __func__);
 
-	if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
-		return;
-
-	prtd = substream->runtime->private_data;
+	if (prtd->state & ST_RUNNING) {
+		prtd->dma_pos += prtd->dma_period;
+		if (prtd->dma_pos >= prtd->dma_end)
+			prtd->dma_pos = prtd->dma_start;
 
-	if (substream)
-		snd_pcm_period_elapsed(substream);
+		if (substream)
+			snd_pcm_period_elapsed(substream);
 
-	spin_lock(&prtd->lock);
-	if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
-		prtd->dma_loaded--;
-		dma_enqueue(substream);
+		spin_lock(&prtd->lock);
+		if (!samsung_dma_has_circular()) {
+			prtd->dma_loaded--;
+			dma_enqueue(substream);
+		}
+		spin_unlock(&prtd->lock);
 	}
-
-	spin_unlock(&prtd->lock);
 }
 
 static int dma_hw_params(struct snd_pcm_substream *substream,
@@ -144,8 +146,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
 	unsigned long totbytes = params_buffer_bytes(params);
 	struct s3c_dma_params *dma =
 		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-	int ret = 0;
-
+	struct samsung_dma_info dma_info;
 
 	pr_debug("Entered %s\n", __func__);
 
@@ -163,23 +164,20 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
 		pr_debug("params %p, client %p, channel %d\n", prtd->params,
 			prtd->params->client, prtd->params->channel);
 
-		ret = s3c2410_dma_request(prtd->params->channel,
-					  prtd->params->client, NULL);
-
-		if (ret < 0) {
-			printk(KERN_ERR "failed to get dma channel\n");
-			return ret;
-		}
-
-		/* use the circular buffering if we have it available. */
-		if (s3c_dma_has_circular())
-			s3c2410_dma_setflags(prtd->params->channel,
-					     S3C2410_DMAF_CIRCULAR);
+		prtd->params->ops = samsung_dma_get_ops();
+
+		dma_info.cap = (samsung_dma_has_circular() ?
+			DMA_CYCLIC : DMA_SLAVE);
+		dma_info.client = prtd->params->client;
+		dma_info.direction =
+			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+			? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		dma_info.width = prtd->params->dma_size;
+		dma_info.fifo = prtd->params->dma_addr;
+		prtd->params->ch = prtd->params->ops->request(
+				prtd->params->channel, &dma_info);
 	}
 
-	s3c2410_dma_set_buffdone_fn(prtd->params->channel,
-				    audio_buffdone);
-
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
 	runtime->dma_bytes = totbytes;
@@ -206,7 +204,8 @@ static int dma_hw_free(struct snd_pcm_substream *substream)
 	snd_pcm_set_runtime_buffer(substream, NULL);
 
 	if (prtd->params) {
-		s3c2410_dma_free(prtd->params->channel, prtd->params->client);
+		prtd->params->ops->release(prtd->params->ch,
+					prtd->params->client);
 		prtd->params = NULL;
 	}
 
@@ -225,23 +224,9 @@ static int dma_prepare(struct snd_pcm_substream *substream)
 	if (!prtd->params)
 		return 0;
 
-	/* channel needs configuring for mem=>device, increment memory addr,
-	 * sync to pclk, half-word transfers to the IIS-FIFO. */
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		s3c2410_dma_devconfig(prtd->params->channel,
-				      S3C2410_DMASRC_MEM,
-				      prtd->params->dma_addr);
-	} else {
-		s3c2410_dma_devconfig(prtd->params->channel,
-				      S3C2410_DMASRC_HW,
-				      prtd->params->dma_addr);
-	}
-
-	s3c2410_dma_config(prtd->params->channel,
-			   prtd->params->dma_size);
-
 	/* flush the DMA channel */
-	s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
+	prtd->params->ops->flush(prtd->params->ch);
+
 	prtd->dma_loaded = 0;
 	prtd->dma_pos = prtd->dma_start;
 
@@ -265,14 +250,14 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		prtd->state |= ST_RUNNING;
-		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
+		prtd->params->ops->trigger(prtd->params->ch);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		prtd->state &= ~ST_RUNNING;
-		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
+		prtd->params->ops->stop(prtd->params->ch);
 		break;
 
 	default:
@@ -291,21 +276,12 @@ dma_pointer(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct runtime_data *prtd = runtime->private_data;
 	unsigned long res;
-	dma_addr_t src, dst;
 
 	pr_debug("Entered %s\n", __func__);
 
-	spin_lock(&prtd->lock);
-	s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
-
-	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-		res = dst - prtd->dma_start;
-	else
-		res = src - prtd->dma_start;
-
-	spin_unlock(&prtd->lock);
+	res = prtd->dma_pos - prtd->dma_start;
 
-	pr_debug("Pointer %x %x\n", src, dst);
+	pr_debug("Pointer offset: %lu\n", res);
 
 	/* we seem to be getting the odd error from the pcm library due
 	 * to out-of-bounds pointers. this is maybe due to the dma engine
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index c506592..7d1ead7 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -6,7 +6,7 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  ALSA PCM interface for the Samsung S3C24xx CPU
+ *  ALSA PCM interface for the Samsung SoC
  */
 
 #ifndef _S3C_AUDIO_H
@@ -17,6 +17,8 @@ struct s3c_dma_params {
 	int channel;				/* Channel ID */
 	dma_addr_t dma_addr;
 	int dma_size;			/* Size of the DMA transfer */
+	unsigned ch;
+	struct samsung_dma_ops *ops;
 };
 
 #endif
-- 
1.7.1

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

* [PATCH V4 13/14] ASoC: Samsung: Update DMA interface
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds to support the DMA PL330 driver that uses
DMA generic API. Samsung sound driver uses DMA generic API
if architecture supports it. Otherwise, use samsung specific
S3C-PL330 API driver to transfer PCM data.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Cc: Jassi Brar <jassisinghbrar@gmail.com>
Cc: Liam Girdwood <lrg@ti.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s3c2410/include/mach/dma.h       |   10 +-
 arch/arm/mach-s3c64xx/include/mach/dma.h       |    2 +-
 arch/arm/plat-samsung/include/plat/dma-pl330.h |    2 +-
 sound/soc/samsung/ac97.c                       |   10 ++-
 sound/soc/samsung/dma.c                        |  144 ++++++++++--------------
 sound/soc/samsung/dma.h                        |    4 +-
 6 files changed, 78 insertions(+), 94 deletions(-)

diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h
index e61a91f..4e485ba 100644
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
@@ -50,6 +50,11 @@ enum dma_ch {
 	DMACH_MAX,		/* the end entry */
 };
 
+static inline bool samsung_dma_has_circular(void)
+{
+	return false;
+}
+
 static inline bool samsung_dma_is_dmadev(void)
 {
 	return false;
@@ -202,9 +207,4 @@ struct s3c2410_dma_chan {
 
 typedef unsigned long dma_device_t;
 
-static inline bool s3c_dma_has_circular(void)
-{
-	return false;
-}
-
 #endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index 49c3a53..74fdf25 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -58,7 +58,7 @@ enum dma_ch {
 	DMACH_MAX		/* the end */
 };
 
-static __inline__ bool s3c_dma_has_circular(void)
+static inline bool samsung_dma_has_circular(void)
 {
 	return true;
 }
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index ded416c..c64b845 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -97,7 +97,7 @@ struct s3c2410_dma_client {
 	char	*name;
 };
 
-static inline bool s3c_dma_has_circular(void)
+static inline bool samsung_dma_has_circular(void)
 {
 	return true;
 }
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index f97110e..b4f9b00 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -271,7 +271,10 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 
 	writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-	s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+	if (!dma_data->ops)
+		dma_data->ops = samsung_dma_get_ops();
+
+	dma_data->ops->started(dma_data->channel);
 
 	return 0;
 }
@@ -317,7 +320,10 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 
 	writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-	s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+	if (!dma_data->ops)
+		dma_data->ops = samsung_dma_get_ops();
+
+	dma_data->ops->started(dma_data->channel);
 
 	return 0;
 }
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 5cb3b88..ceca331 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -62,77 +62,79 @@ struct runtime_data {
 	struct s3c_dma_params *params;
 };
 
+static void audio_buffdone(void *data);
+
 /* dma_enqueue
  *
  * place a dma buffer onto the queue for the dma system
  * to handle.
-*/
+ */
 static void dma_enqueue(struct snd_pcm_substream *substream)
 {
 	struct runtime_data *prtd = substream->runtime->private_data;
 	dma_addr_t pos = prtd->dma_pos;
 	unsigned int limit;
-	int ret;
+	struct samsung_dma_prep_info dma_info;
 
 	pr_debug("Entered %s\n", __func__);
 
-	if (s3c_dma_has_circular())
-		limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
-	else
-		limit = prtd->dma_limit;
+	limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
 
 	pr_debug("%s: loaded %d, limit %d\n",
 				__func__, prtd->dma_loaded, limit);
 
-	while (prtd->dma_loaded < limit) {
-		unsigned long len = prtd->dma_period;
+	dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
+	dma_info.direction =
+		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+		? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	dma_info.fp = audio_buffdone;
+	dma_info.fp_param = substream;
+	dma_info.period = prtd->dma_period;
+	dma_info.len = prtd->dma_period*limit;
 
+	while (prtd->dma_loaded < limit) {
 		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
 
-		if ((pos + len) > prtd->dma_end) {
-			len  = prtd->dma_end - pos;
-			pr_debug("%s: corrected dma len %ld\n", __func__, len);
+		if ((pos + dma_info.period) > prtd->dma_end) {
+			dma_info.period  = prtd->dma_end - pos;
+			pr_debug("%s: corrected dma len %ld\n",
+					__func__, dma_info.period);
 		}
 
-		ret = s3c2410_dma_enqueue(prtd->params->channel,
-			substream, pos, len);
+		dma_info.buf = pos;
+		prtd->params->ops->prepare(prtd->params->ch, &dma_info);
 
-		if (ret == 0) {
-			prtd->dma_loaded++;
-			pos += prtd->dma_period;
-			if (pos >= prtd->dma_end)
-				pos = prtd->dma_start;
-		} else
-			break;
+		prtd->dma_loaded++;
+		pos += prtd->dma_period;
+		if (pos >= prtd->dma_end)
+			pos = prtd->dma_start;
 	}
 
 	prtd->dma_pos = pos;
 }
 
-static void audio_buffdone(struct s3c2410_dma_chan *channel,
-				void *dev_id, int size,
-				enum s3c2410_dma_buffresult result)
+static void audio_buffdone(void *data)
 {
-	struct snd_pcm_substream *substream = dev_id;
-	struct runtime_data *prtd;
+	struct snd_pcm_substream *substream = data;
+	struct runtime_data *prtd = substream->runtime->private_data;
 
 	pr_debug("Entered %s\n", __func__);
 
-	if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
-		return;
-
-	prtd = substream->runtime->private_data;
+	if (prtd->state & ST_RUNNING) {
+		prtd->dma_pos += prtd->dma_period;
+		if (prtd->dma_pos >= prtd->dma_end)
+			prtd->dma_pos = prtd->dma_start;
 
-	if (substream)
-		snd_pcm_period_elapsed(substream);
+		if (substream)
+			snd_pcm_period_elapsed(substream);
 
-	spin_lock(&prtd->lock);
-	if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
-		prtd->dma_loaded--;
-		dma_enqueue(substream);
+		spin_lock(&prtd->lock);
+		if (!samsung_dma_has_circular()) {
+			prtd->dma_loaded--;
+			dma_enqueue(substream);
+		}
+		spin_unlock(&prtd->lock);
 	}
-
-	spin_unlock(&prtd->lock);
 }
 
 static int dma_hw_params(struct snd_pcm_substream *substream,
@@ -144,8 +146,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
 	unsigned long totbytes = params_buffer_bytes(params);
 	struct s3c_dma_params *dma =
 		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-	int ret = 0;
-
+	struct samsung_dma_info dma_info;
 
 	pr_debug("Entered %s\n", __func__);
 
@@ -163,23 +164,20 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
 		pr_debug("params %p, client %p, channel %d\n", prtd->params,
 			prtd->params->client, prtd->params->channel);
 
-		ret = s3c2410_dma_request(prtd->params->channel,
-					  prtd->params->client, NULL);
-
-		if (ret < 0) {
-			printk(KERN_ERR "failed to get dma channel\n");
-			return ret;
-		}
-
-		/* use the circular buffering if we have it available. */
-		if (s3c_dma_has_circular())
-			s3c2410_dma_setflags(prtd->params->channel,
-					     S3C2410_DMAF_CIRCULAR);
+		prtd->params->ops = samsung_dma_get_ops();
+
+		dma_info.cap = (samsung_dma_has_circular() ?
+			DMA_CYCLIC : DMA_SLAVE);
+		dma_info.client = prtd->params->client;
+		dma_info.direction =
+			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+			? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		dma_info.width = prtd->params->dma_size;
+		dma_info.fifo = prtd->params->dma_addr;
+		prtd->params->ch = prtd->params->ops->request(
+				prtd->params->channel, &dma_info);
 	}
 
-	s3c2410_dma_set_buffdone_fn(prtd->params->channel,
-				    audio_buffdone);
-
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
 	runtime->dma_bytes = totbytes;
@@ -206,7 +204,8 @@ static int dma_hw_free(struct snd_pcm_substream *substream)
 	snd_pcm_set_runtime_buffer(substream, NULL);
 
 	if (prtd->params) {
-		s3c2410_dma_free(prtd->params->channel, prtd->params->client);
+		prtd->params->ops->release(prtd->params->ch,
+					prtd->params->client);
 		prtd->params = NULL;
 	}
 
@@ -225,23 +224,9 @@ static int dma_prepare(struct snd_pcm_substream *substream)
 	if (!prtd->params)
 		return 0;
 
-	/* channel needs configuring for mem=>device, increment memory addr,
-	 * sync to pclk, half-word transfers to the IIS-FIFO. */
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		s3c2410_dma_devconfig(prtd->params->channel,
-				      S3C2410_DMASRC_MEM,
-				      prtd->params->dma_addr);
-	} else {
-		s3c2410_dma_devconfig(prtd->params->channel,
-				      S3C2410_DMASRC_HW,
-				      prtd->params->dma_addr);
-	}
-
-	s3c2410_dma_config(prtd->params->channel,
-			   prtd->params->dma_size);
-
 	/* flush the DMA channel */
-	s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
+	prtd->params->ops->flush(prtd->params->ch);
+
 	prtd->dma_loaded = 0;
 	prtd->dma_pos = prtd->dma_start;
 
@@ -265,14 +250,14 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		prtd->state |= ST_RUNNING;
-		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
+		prtd->params->ops->trigger(prtd->params->ch);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		prtd->state &= ~ST_RUNNING;
-		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
+		prtd->params->ops->stop(prtd->params->ch);
 		break;
 
 	default:
@@ -291,21 +276,12 @@ dma_pointer(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct runtime_data *prtd = runtime->private_data;
 	unsigned long res;
-	dma_addr_t src, dst;
 
 	pr_debug("Entered %s\n", __func__);
 
-	spin_lock(&prtd->lock);
-	s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
-
-	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-		res = dst - prtd->dma_start;
-	else
-		res = src - prtd->dma_start;
-
-	spin_unlock(&prtd->lock);
+	res = prtd->dma_pos - prtd->dma_start;
 
-	pr_debug("Pointer %x %x\n", src, dst);
+	pr_debug("Pointer offset: %lu\n", res);
 
 	/* we seem to be getting the odd error from the pcm library due
 	 * to out-of-bounds pointers. this is maybe due to the dma engine
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index c506592..7d1ead7 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -6,7 +6,7 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  ALSA PCM interface for the Samsung S3C24xx CPU
+ *  ALSA PCM interface for the Samsung SoC
  */
 
 #ifndef _S3C_AUDIO_H
@@ -17,6 +17,8 @@ struct s3c_dma_params {
 	int channel;				/* Channel ID */
 	dma_addr_t dma_addr;
 	int dma_size;			/* Size of the DMA transfer */
+	unsigned ch;
+	struct samsung_dma_ops *ops;
 };
 
 #endif
-- 
1.7.1

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

* [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25  1:28   ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Grant Likely,
	Mark Brown, Boojin Kim

This patch removes the samsung specific enum type 's3c2410_dmasrc'
and uses 'dma_data_direction' instead.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s3c2410/include/mach/dma.h         |    2 +-
 arch/arm/mach-s3c2412/dma.c                      |    4 ++--
 arch/arm/mach-s3c64xx/dma.c                      |   10 +++++-----
 arch/arm/mach-s3c64xx/include/mach/dma.h         |    2 +-
 arch/arm/plat-s3c24xx/dma.c                      |   10 +++++-----
 arch/arm/plat-samsung/include/plat/dma-s3c24xx.h |    2 +-
 arch/arm/plat-samsung/include/plat/dma.h         |    9 +++------
 arch/arm/plat-samsung/s3c-dma-ops.c              |    5 +----
 drivers/mmc/host/s3cmci.c                        |    6 +++---
 9 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h
index 4e485ba..ae8e482 100644
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
@@ -174,7 +174,7 @@ struct s3c2410_dma_chan {
 	struct s3c2410_dma_client *client;
 
 	/* channel configuration */
-	enum s3c2410_dmasrc	 source;
+	enum dma_data_direction	 source;
 	enum dma_ch		 req_ch;
 	unsigned long		 dev_addr;
 	unsigned long		 load_timeout;
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index 7abecfc..b4fc3ba 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -148,11 +148,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
 
 static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
 				  struct s3c24xx_dma_map *map,
-				  enum s3c2410_dmasrc dir)
+				  enum dma_data_direction dir)
 {
 	unsigned long chsel;
 
-	if (dir == S3C2410_DMASRC_HW)
+	if (dir == DMA_FROM_DEVICE)
 		chsel = map->channels_rx[0];
 	else
 		chsel = map->channels[0];
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
index b197171..d96ed4c 100644
--- a/arch/arm/mach-s3c64xx/dma.c
+++ b/arch/arm/mach-s3c64xx/dma.c
@@ -147,14 +147,14 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
 	u32 control0, control1;
 
 	switch (chan->source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		src = chan->dev_addr;
 		dst = data;
 		control0 = PL080_CONTROL_SRC_AHB2;
 		control0 |= PL080_CONTROL_DST_INCR;
 		break;
 
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		src = data;
 		dst = chan->dev_addr;
 		control0 = PL080_CONTROL_DST_AHB2;
@@ -416,7 +416,7 @@ EXPORT_SYMBOL(s3c2410_dma_enqueue);
 
 
 int s3c2410_dma_devconfig(unsigned int channel,
-			  enum s3c2410_dmasrc source,
+			  enum dma_data_direction source,
 			  unsigned long devaddr)
 {
 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -437,11 +437,11 @@ int s3c2410_dma_devconfig(unsigned int channel,
 	pr_debug("%s: peripheral %d\n", __func__, peripheral);
 
 	switch (source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
 		break;
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
 		break;
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index 74fdf25..fe1a98c 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -99,7 +99,7 @@ struct s3c2410_dma_chan {
 	unsigned char		 peripheral;
 
 	unsigned int		 flags;
-	enum s3c2410_dmasrc	 source;
+	enum dma_data_direction	 source;
 
 
 	dma_addr_t		dev_addr;
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index a79a8cc..036ff81 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1094,14 +1094,14 @@ EXPORT_SYMBOL(s3c2410_dma_config);
  *
  * configure the dma source/destination hardware type and address
  *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
+ * source:    DMA_FROM_DEVICE: source is hardware
+ *            DMA_TO_DEVICE: source is memory
  *
  * devaddr:   physical address of the source
 */
 
 int s3c2410_dma_devconfig(unsigned int channel,
-			  enum s3c2410_dmasrc source,
+			  enum dma_data_direction source,
 			  unsigned long devaddr)
 {
 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -1131,7 +1131,7 @@ int s3c2410_dma_devconfig(unsigned int channel,
 	 hwcfg |= S3C2410_DISRCC_INC;
 
 	switch (source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROME_DEVICE:
 		/* source is hardware */
 		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
 			 __func__, devaddr, hwcfg);
@@ -1142,7 +1142,7 @@ int s3c2410_dma_devconfig(unsigned int channel,
 		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
 		break;
 
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		/* source is memory */
 		pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
 			 __func__, devaddr, hwcfg);
diff --git a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
index 336d5ac..1982829 100644
--- a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
+++ b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
@@ -47,7 +47,7 @@ struct s3c24xx_dma_selection {
 
 	void	(*direction)(struct s3c2410_dma_chan *chan,
 			     struct s3c24xx_dma_map *map,
-			     enum s3c2410_dmasrc dir);
+			     enum dma_data_direction dir);
 };
 
 extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h
index e87c6be..b395398 100644
--- a/arch/arm/plat-samsung/include/plat/dma.h
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -10,17 +10,14 @@
  * published by the Free Software Foundation.
 */
 
+#include <linux/dma-mapping.h>
+
 enum s3c2410_dma_buffresult {
 	S3C2410_RES_OK,
 	S3C2410_RES_ERR,
 	S3C2410_RES_ABORT
 };
 
-enum s3c2410_dmasrc {
-	S3C2410_DMASRC_HW,		/* source is memory */
-	S3C2410_DMASRC_MEM		/* source is hardware */
-};
-
 /* enum s3c2410_chan_op
  *
  * operation codes passed to the DMA code by the user, and also used
@@ -111,7 +108,7 @@ extern int s3c2410_dma_config(unsigned int channel, int xferunit);
 */
 
 extern int s3c2410_dma_devconfig(unsigned int channel,
-		enum s3c2410_dmasrc source, unsigned long devaddr);
+		enum dma_data_direction source, unsigned long devaddr);
 
 /* s3c2410_dma_getposition
  *
diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
index 33ab324..582333c 100644
--- a/arch/arm/plat-samsung/s3c-dma-ops.c
+++ b/arch/arm/plat-samsung/s3c-dma-ops.c
@@ -48,10 +48,7 @@ static unsigned s3c_dma_request(enum dma_ch dma_ch,
 	data->ch = dma_ch;
 	list_add_tail(&data->node, &dma_list);
 
-	if (info->direction == DMA_FROM_DEVICE)
-		s3c2410_dma_devconfig(dma_ch, S3C2410_DMASRC_HW, info->fifo);
-	else
-		s3c2410_dma_devconfig(dma_ch, S3C2410_DMASRC_MEM, info->fifo);
+	s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
 
 	if (info->cap == DMA_CYCLIC)
 		s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index a04f87d..03cfdab 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -913,9 +913,9 @@ request_done:
 }
 
 static void s3cmci_dma_setup(struct s3cmci_host *host,
-			     enum s3c2410_dmasrc source)
+			     enum dma_data_direction source)
 {
-	static enum s3c2410_dmasrc last_source = -1;
+	static enum dma_data_direction last_source = -1;
 	static int setup_ok;
 
 	if (last_source == source)
@@ -1087,7 +1087,7 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
 
 	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
-	s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
+	s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
 	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-- 
1.7.1

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

* [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
@ 2011-07-25  1:28   ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  1:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch removes the samsung specific enum type 's3c2410_dmasrc'
and uses 'dma_data_direction' instead.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s3c2410/include/mach/dma.h         |    2 +-
 arch/arm/mach-s3c2412/dma.c                      |    4 ++--
 arch/arm/mach-s3c64xx/dma.c                      |   10 +++++-----
 arch/arm/mach-s3c64xx/include/mach/dma.h         |    2 +-
 arch/arm/plat-s3c24xx/dma.c                      |   10 +++++-----
 arch/arm/plat-samsung/include/plat/dma-s3c24xx.h |    2 +-
 arch/arm/plat-samsung/include/plat/dma.h         |    9 +++------
 arch/arm/plat-samsung/s3c-dma-ops.c              |    5 +----
 drivers/mmc/host/s3cmci.c                        |    6 +++---
 9 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h
index 4e485ba..ae8e482 100644
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
@@ -174,7 +174,7 @@ struct s3c2410_dma_chan {
 	struct s3c2410_dma_client *client;
 
 	/* channel configuration */
-	enum s3c2410_dmasrc	 source;
+	enum dma_data_direction	 source;
 	enum dma_ch		 req_ch;
 	unsigned long		 dev_addr;
 	unsigned long		 load_timeout;
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index 7abecfc..b4fc3ba 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -148,11 +148,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
 
 static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
 				  struct s3c24xx_dma_map *map,
-				  enum s3c2410_dmasrc dir)
+				  enum dma_data_direction dir)
 {
 	unsigned long chsel;
 
-	if (dir == S3C2410_DMASRC_HW)
+	if (dir == DMA_FROM_DEVICE)
 		chsel = map->channels_rx[0];
 	else
 		chsel = map->channels[0];
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
index b197171..d96ed4c 100644
--- a/arch/arm/mach-s3c64xx/dma.c
+++ b/arch/arm/mach-s3c64xx/dma.c
@@ -147,14 +147,14 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
 	u32 control0, control1;
 
 	switch (chan->source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		src = chan->dev_addr;
 		dst = data;
 		control0 = PL080_CONTROL_SRC_AHB2;
 		control0 |= PL080_CONTROL_DST_INCR;
 		break;
 
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		src = data;
 		dst = chan->dev_addr;
 		control0 = PL080_CONTROL_DST_AHB2;
@@ -416,7 +416,7 @@ EXPORT_SYMBOL(s3c2410_dma_enqueue);
 
 
 int s3c2410_dma_devconfig(unsigned int channel,
-			  enum s3c2410_dmasrc source,
+			  enum dma_data_direction source,
 			  unsigned long devaddr)
 {
 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -437,11 +437,11 @@ int s3c2410_dma_devconfig(unsigned int channel,
 	pr_debug("%s: peripheral %d\n", __func__, peripheral);
 
 	switch (source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROM_DEVICE:
 		config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
 		break;
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
 		config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
 		break;
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index 74fdf25..fe1a98c 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -99,7 +99,7 @@ struct s3c2410_dma_chan {
 	unsigned char		 peripheral;
 
 	unsigned int		 flags;
-	enum s3c2410_dmasrc	 source;
+	enum dma_data_direction	 source;
 
 
 	dma_addr_t		dev_addr;
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index a79a8cc..036ff81 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1094,14 +1094,14 @@ EXPORT_SYMBOL(s3c2410_dma_config);
  *
  * configure the dma source/destination hardware type and address
  *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
+ * source:    DMA_FROM_DEVICE: source is hardware
+ *            DMA_TO_DEVICE: source is memory
  *
  * devaddr:   physical address of the source
 */
 
 int s3c2410_dma_devconfig(unsigned int channel,
-			  enum s3c2410_dmasrc source,
+			  enum dma_data_direction source,
 			  unsigned long devaddr)
 {
 	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
@@ -1131,7 +1131,7 @@ int s3c2410_dma_devconfig(unsigned int channel,
 	 hwcfg |= S3C2410_DISRCC_INC;
 
 	switch (source) {
-	case S3C2410_DMASRC_HW:
+	case DMA_FROME_DEVICE:
 		/* source is hardware */
 		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
 			 __func__, devaddr, hwcfg);
@@ -1142,7 +1142,7 @@ int s3c2410_dma_devconfig(unsigned int channel,
 		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
 		break;
 
-	case S3C2410_DMASRC_MEM:
+	case DMA_TO_DEVICE:
 		/* source is memory */
 		pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
 			 __func__, devaddr, hwcfg);
diff --git a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
index 336d5ac..1982829 100644
--- a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
+++ b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
@@ -47,7 +47,7 @@ struct s3c24xx_dma_selection {
 
 	void	(*direction)(struct s3c2410_dma_chan *chan,
 			     struct s3c24xx_dma_map *map,
-			     enum s3c2410_dmasrc dir);
+			     enum dma_data_direction dir);
 };
 
 extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h
index e87c6be..b395398 100644
--- a/arch/arm/plat-samsung/include/plat/dma.h
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -10,17 +10,14 @@
  * published by the Free Software Foundation.
 */
 
+#include <linux/dma-mapping.h>
+
 enum s3c2410_dma_buffresult {
 	S3C2410_RES_OK,
 	S3C2410_RES_ERR,
 	S3C2410_RES_ABORT
 };
 
-enum s3c2410_dmasrc {
-	S3C2410_DMASRC_HW,		/* source is memory */
-	S3C2410_DMASRC_MEM		/* source is hardware */
-};
-
 /* enum s3c2410_chan_op
  *
  * operation codes passed to the DMA code by the user, and also used
@@ -111,7 +108,7 @@ extern int s3c2410_dma_config(unsigned int channel, int xferunit);
 */
 
 extern int s3c2410_dma_devconfig(unsigned int channel,
-		enum s3c2410_dmasrc source, unsigned long devaddr);
+		enum dma_data_direction source, unsigned long devaddr);
 
 /* s3c2410_dma_getposition
  *
diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
index 33ab324..582333c 100644
--- a/arch/arm/plat-samsung/s3c-dma-ops.c
+++ b/arch/arm/plat-samsung/s3c-dma-ops.c
@@ -48,10 +48,7 @@ static unsigned s3c_dma_request(enum dma_ch dma_ch,
 	data->ch = dma_ch;
 	list_add_tail(&data->node, &dma_list);
 
-	if (info->direction == DMA_FROM_DEVICE)
-		s3c2410_dma_devconfig(dma_ch, S3C2410_DMASRC_HW, info->fifo);
-	else
-		s3c2410_dma_devconfig(dma_ch, S3C2410_DMASRC_MEM, info->fifo);
+	s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
 
 	if (info->cap == DMA_CYCLIC)
 		s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index a04f87d..03cfdab 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -913,9 +913,9 @@ request_done:
 }
 
 static void s3cmci_dma_setup(struct s3cmci_host *host,
-			     enum s3c2410_dmasrc source)
+			     enum dma_data_direction source)
 {
-	static enum s3c2410_dmasrc last_source = -1;
+	static enum dma_data_direction last_source = -1;
 	static int setup_ok;
 
 	if (last_source == source)
@@ -1087,7 +1087,7 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
 
 	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
-	s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
+	s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
 	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-- 
1.7.1

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

* Re: [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25  8:57     ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25  8:57 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Kukjin Kim, Grant Likely, Mark Brown

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index b7ecf47..586ab39 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
>        async_tx_ack(&desc->txd);
>
>        desc->req.rqtype = peri->rqtype;
> -       desc->req.peri = peri->peri_id;
> +       desc->req.peri = pch->chan.chan_id;
Btw, I plan to revert this if my patch is accepted that proposes
to free chan_id solely for use by DMAC drivers(which we should
employ to pass paltform assigned channel ID to client drivers)

> @@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
>                struct dma_pl330_peri *peri = &pdat->peri[i];
>                pch = &pdmac->peripherals[i];
>
> -               switch (peri->rqtype) {
> -               case MEMTOMEM:
> -                       dma_cap_set(DMA_MEMCPY, pd->cap_mask);
> -                       break;
> -               case MEMTODEV:
> -               case DEVTOMEM:
> -                       dma_cap_set(DMA_SLAVE, pd->cap_mask);
> -                       break;
> -               default:
> -                       dev_err(&adev->dev, "DEVTODEV Not Supported\n");
> -                       continue;
> +               if (peri) {
> +                       switch (peri->rqtype) {
> +                       case MEMTOMEM:
> +                               dma_cap_set(DMA_MEMCPY, pd->cap_mask);
> +                               break;
> +                       case MEMTODEV:
> +                       case DEVTOMEM:
> +                               dma_cap_set(DMA_SLAVE, pd->cap_mask);
> +                               break;
> +                       default:
> +                               dev_err(&adev->dev, "DEVTODEV Not Supported\n");
> +                               continue;
> +                       }
>                }
If you pass platform data correctly, you don't need to check against NULL peri.

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

* [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
@ 2011-07-25  8:57     ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25  8:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index b7ecf47..586ab39 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
> ? ? ? ?async_tx_ack(&desc->txd);
>
> ? ? ? ?desc->req.rqtype = peri->rqtype;
> - ? ? ? desc->req.peri = peri->peri_id;
> + ? ? ? desc->req.peri = pch->chan.chan_id;
Btw, I plan to revert this if my patch is accepted that proposes
to free chan_id solely for use by DMAC drivers(which we should
employ to pass paltform assigned channel ID to client drivers)

> @@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
> ? ? ? ? ? ? ? ?struct dma_pl330_peri *peri = &pdat->peri[i];
> ? ? ? ? ? ? ? ?pch = &pdmac->peripherals[i];
>
> - ? ? ? ? ? ? ? switch (peri->rqtype) {
> - ? ? ? ? ? ? ? case MEMTOMEM:
> - ? ? ? ? ? ? ? ? ? ? ? dma_cap_set(DMA_MEMCPY, pd->cap_mask);
> - ? ? ? ? ? ? ? ? ? ? ? break;
> - ? ? ? ? ? ? ? case MEMTODEV:
> - ? ? ? ? ? ? ? case DEVTOMEM:
> - ? ? ? ? ? ? ? ? ? ? ? dma_cap_set(DMA_SLAVE, pd->cap_mask);
> - ? ? ? ? ? ? ? ? ? ? ? break;
> - ? ? ? ? ? ? ? default:
> - ? ? ? ? ? ? ? ? ? ? ? dev_err(&adev->dev, "DEVTODEV Not Supported\n");
> - ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? if (peri) {
> + ? ? ? ? ? ? ? ? ? ? ? switch (peri->rqtype) {
> + ? ? ? ? ? ? ? ? ? ? ? case MEMTOMEM:
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dma_cap_set(DMA_MEMCPY, pd->cap_mask);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? ? ? ? case MEMTODEV:
> + ? ? ? ? ? ? ? ? ? ? ? case DEVTOMEM:
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dma_cap_set(DMA_SLAVE, pd->cap_mask);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? ? ? ? default:
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_err(&adev->dev, "DEVTODEV Not Supported\n");
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? ? ? ? ? }
> ? ? ? ? ? ? ? ?}
If you pass platform data correctly, you don't need to check against NULL peri.

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

* Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25  9:27     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25  9:27 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Kukjin Kim, Vinod Koul,
	Jassi Brar, Grant Likely, Mark Brown, Dan Williams

On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> +static void pl330_tasklet_cyclic(unsigned long data)
> +{
> +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> +	struct dma_pl330_desc *desc, *_dt;
> +	unsigned long flags;
> +	LIST_HEAD(list);
> +
> +	spin_lock_irqsave(&pch->lock, flags);
...
> +			callback = desc->txd.callback;
> +			if (callback)
> +				callback(desc->txd.callback_param);

On this again - what if the callback wants to terminate the DMA activity
because there's no more audio data to be sent/received from the device?

> +

Useless blank line.

> +		}
> +
> +	spin_unlock_irqrestore(&pch->lock, flags);
> +}
> +
>  static void pl330_tasklet(unsigned long data)
>  {
>  	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> @@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
>  
>  	spin_unlock_irqrestore(&pch->lock, flags);
>  
> +	if (pch->cyclic_task)
> +		tasklet_schedule(pch->cyclic_task);
> +	else
>  	tasklet_schedule(&pch->task);

Indentation error.

>  }
>  
> @@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
>  	pl330_release_channel(pch->pl330_chid);
>  	pch->pl330_chid = NULL;
>  
> +	if (pch->cyclic) {
> +		pch->cyclic = false;
> +		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
> +		if (pch->cyclic_task) {
> +			tasklet_kill(pch->cyclic_task);
> +			pch->cyclic_task = NULL;
> +		}
> +	}
> +
>  	spin_unlock_irqrestore(&pch->lock, flags);
>  }
>  
> @@ -547,6 +599,63 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
>  	return burst_len;
>  }
>  
> +static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
> +		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
> +		size_t period_len, enum dma_data_direction direction)
> +{
> +	struct dma_pl330_desc *desc;
> +	struct dma_pl330_chan *pch = to_pchan(chan);
> +	struct dma_pl330_peri *peri = chan->private;
> +	dma_addr_t dst;
> +	dma_addr_t src;
> +
> +	pch = to_pchan(chan);
> +	if (!pch)
> +		return NULL;

You've already done the to_pchan() thing when declaring pch.  You've
already dereferenced 'chan', so there's no way that pch could be NULL
here.

> +
> +	desc = pl330_get_desc(pch);
> +	if (!desc) {
> +		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
> +			__func__, __LINE__);
> +		return NULL;
> +	}
> +
> +	switch (direction) {
> +	case DMA_TO_DEVICE:
> +		desc->rqcfg.src_inc = 1;
> +		desc->rqcfg.dst_inc = 0;
> +		src = dma_addr;
> +		dst = peri->fifo_addr;
> +		break;
> +	case DMA_FROM_DEVICE:
> +		desc->rqcfg.src_inc = 0;
> +		desc->rqcfg.dst_inc = 1;
> +		src = peri->fifo_addr;
> +		dst = dma_addr;
> +		break;
> +	default:
> +		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
> +		__func__, __LINE__);
> +		return NULL;
> +	}
> +
> +	desc->rqcfg.brst_size = peri->burst_sz;
> +	desc->rqcfg.brst_len = 1;
> +
> +	if (!pch->cyclic_task) {
> +		pch->cyclic_task =
> +			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
> +		tasklet_init(pch->cyclic_task,
> +			pl330_tasklet_cyclic, (unsigned int)pch);

Here you allocate memory for the cyclic task.  Above you set this pointer
to NULL.  That sounds like a memory leak to me.  Why are you kmallocing
this memory - why can't it be part of the dma_pl330_chan structure?  It's
only 28 bytes.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25  9:27     ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25  9:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> +static void pl330_tasklet_cyclic(unsigned long data)
> +{
> +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> +	struct dma_pl330_desc *desc, *_dt;
> +	unsigned long flags;
> +	LIST_HEAD(list);
> +
> +	spin_lock_irqsave(&pch->lock, flags);
...
> +			callback = desc->txd.callback;
> +			if (callback)
> +				callback(desc->txd.callback_param);

On this again - what if the callback wants to terminate the DMA activity
because there's no more audio data to be sent/received from the device?

> +

Useless blank line.

> +		}
> +
> +	spin_unlock_irqrestore(&pch->lock, flags);
> +}
> +
>  static void pl330_tasklet(unsigned long data)
>  {
>  	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> @@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
>  
>  	spin_unlock_irqrestore(&pch->lock, flags);
>  
> +	if (pch->cyclic_task)
> +		tasklet_schedule(pch->cyclic_task);
> +	else
>  	tasklet_schedule(&pch->task);

Indentation error.

>  }
>  
> @@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
>  	pl330_release_channel(pch->pl330_chid);
>  	pch->pl330_chid = NULL;
>  
> +	if (pch->cyclic) {
> +		pch->cyclic = false;
> +		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
> +		if (pch->cyclic_task) {
> +			tasklet_kill(pch->cyclic_task);
> +			pch->cyclic_task = NULL;
> +		}
> +	}
> +
>  	spin_unlock_irqrestore(&pch->lock, flags);
>  }
>  
> @@ -547,6 +599,63 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
>  	return burst_len;
>  }
>  
> +static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
> +		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
> +		size_t period_len, enum dma_data_direction direction)
> +{
> +	struct dma_pl330_desc *desc;
> +	struct dma_pl330_chan *pch = to_pchan(chan);
> +	struct dma_pl330_peri *peri = chan->private;
> +	dma_addr_t dst;
> +	dma_addr_t src;
> +
> +	pch = to_pchan(chan);
> +	if (!pch)
> +		return NULL;

You've already done the to_pchan() thing when declaring pch.  You've
already dereferenced 'chan', so there's no way that pch could be NULL
here.

> +
> +	desc = pl330_get_desc(pch);
> +	if (!desc) {
> +		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
> +			__func__, __LINE__);
> +		return NULL;
> +	}
> +
> +	switch (direction) {
> +	case DMA_TO_DEVICE:
> +		desc->rqcfg.src_inc = 1;
> +		desc->rqcfg.dst_inc = 0;
> +		src = dma_addr;
> +		dst = peri->fifo_addr;
> +		break;
> +	case DMA_FROM_DEVICE:
> +		desc->rqcfg.src_inc = 0;
> +		desc->rqcfg.dst_inc = 1;
> +		src = peri->fifo_addr;
> +		dst = dma_addr;
> +		break;
> +	default:
> +		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
> +		__func__, __LINE__);
> +		return NULL;
> +	}
> +
> +	desc->rqcfg.brst_size = peri->burst_sz;
> +	desc->rqcfg.brst_len = 1;
> +
> +	if (!pch->cyclic_task) {
> +		pch->cyclic_task =
> +			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
> +		tasklet_init(pch->cyclic_task,
> +			pl330_tasklet_cyclic, (unsigned int)pch);

Here you allocate memory for the cyclic task.  Above you set this pointer
to NULL.  That sounds like a memory leak to me.  Why are you kmallocing
this memory - why can't it be part of the dma_pl330_chan structure?  It's
only 28 bytes.

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

* Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25  9:36     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25  9:36 UTC (permalink / raw)
  To: Boojin Kim
  Cc: Kukjin Kim, Vinod Koul, Jassi Brar, Grant Likely,
	linux-samsung-soc, Mark Brown, Dan Williams, linux-arm-kernel

On Mon, Jul 25, 2011 at 10:28:24AM +0900, Boojin Kim wrote:
> +static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
> +				struct samsung_dma_info *info)
> +{
> +	struct dma_chan *chan;
> +	dma_cap_mask_t mask;
> +	struct dma_slave_config slave_config;
> +
> +	dma_cap_zero(mask);
> +	dma_cap_set(info->cap, mask);
> +
> +	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
> +
> +	if (info->direction == DMA_FROM_DEVICE) {
> +		memset(&slave_config, 0, sizeof(struct dma_slave_config));
> +		slave_config.direction = info->direction;
> +		slave_config.src_addr = info->fifo;
> +		slave_config.src_addr_width = info->width;

This should really set slave_config.src_maxburst to something sensible too,
even if that's just '1'.

> +		dmaengine_slave_config(chan, &slave_config);
> +	} else if (info->direction == DMA_TO_DEVICE) {
> +		memset(&slave_config, 0, sizeof(struct dma_slave_config));
> +		slave_config.direction = info->direction;
> +		slave_config.dst_addr = info->fifo;
> +		slave_config.dst_addr_width = info->width;

Ditto for dst_maxburst.

> +		dmaengine_slave_config(chan, &slave_config);
> +	}
> +
> +	return (unsigned)chan;

I hope these interfaces yet cleaned away soon so that these casts can be
killed off.

> +struct samsung_dma_prep_info {
> +	enum dma_transaction_type cap;
> +	enum dma_data_direction direction;
> +	unsigned buf;

dma_addr_t ?

> +	unsigned long period;
> +	unsigned long len;
> +	void (*fp)(void *data);
> +	void *fp_param;
> +};
> +
> +struct samsung_dma_info {
> +	enum dma_transaction_type cap;
> +	enum dma_data_direction direction;
> +	enum dma_slave_buswidth width;
> +	unsigned fifo;

dma_addr_t ?

> +	struct s3c2410_dma_client *client;
> +};
> +
> +struct samsung_dma_ops {
> +	bool init;

Unused?

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-25  9:36     ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25  9:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 10:28:24AM +0900, Boojin Kim wrote:
> +static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
> +				struct samsung_dma_info *info)
> +{
> +	struct dma_chan *chan;
> +	dma_cap_mask_t mask;
> +	struct dma_slave_config slave_config;
> +
> +	dma_cap_zero(mask);
> +	dma_cap_set(info->cap, mask);
> +
> +	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
> +
> +	if (info->direction == DMA_FROM_DEVICE) {
> +		memset(&slave_config, 0, sizeof(struct dma_slave_config));
> +		slave_config.direction = info->direction;
> +		slave_config.src_addr = info->fifo;
> +		slave_config.src_addr_width = info->width;

This should really set slave_config.src_maxburst to something sensible too,
even if that's just '1'.

> +		dmaengine_slave_config(chan, &slave_config);
> +	} else if (info->direction == DMA_TO_DEVICE) {
> +		memset(&slave_config, 0, sizeof(struct dma_slave_config));
> +		slave_config.direction = info->direction;
> +		slave_config.dst_addr = info->fifo;
> +		slave_config.dst_addr_width = info->width;

Ditto for dst_maxburst.

> +		dmaengine_slave_config(chan, &slave_config);
> +	}
> +
> +	return (unsigned)chan;

I hope these interfaces yet cleaned away soon so that these casts can be
killed off.

> +struct samsung_dma_prep_info {
> +	enum dma_transaction_type cap;
> +	enum dma_data_direction direction;
> +	unsigned buf;

dma_addr_t ?

> +	unsigned long period;
> +	unsigned long len;
> +	void (*fp)(void *data);
> +	void *fp_param;
> +};
> +
> +struct samsung_dma_info {
> +	enum dma_transaction_type cap;
> +	enum dma_data_direction direction;
> +	enum dma_slave_buswidth width;
> +	unsigned fifo;

dma_addr_t ?

> +	struct s3c2410_dma_client *client;
> +};
> +
> +struct samsung_dma_ops {
> +	bool init;

Unused?

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

* Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25  9:40     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25  9:40 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Kukjin Kim, Vinod Koul,
	Jassi Brar, Grant Likely, Mark Brown, Dan Williams

On Mon, Jul 25, 2011 at 10:28:30AM +0900, Boojin Kim wrote:
> +static void s3c64xx_spi_dma_rxcb(void *data)
> +{
> +	struct s3c64xx_spi_driver_data *sdd
> +		= (struct s3c64xx_spi_driver_data *)data;

You never need explicit casts from void * or to void *.  Please remove
these.

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

* [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
@ 2011-07-25  9:40     ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 10:28:30AM +0900, Boojin Kim wrote:
> +static void s3c64xx_spi_dma_rxcb(void *data)
> +{
> +	struct s3c64xx_spi_driver_data *sdd
> +		= (struct s3c64xx_spi_driver_data *)data;

You never need explicit casts from void * or to void *.  Please remove
these.

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

* RE: [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
  2011-07-25  8:57     ` Jassi Brar
@ 2011-07-25  9:48       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  9:48 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Vinod Koul',
	'Dan Williams', 'Kukjin Kim',
	'Grant Likely', 'Mark Brown'



> -----Original Message-----
> From: Jassi Brar [mailto:jassisinghbrar@gmail.com]
> Sent: Monday, July 25, 2011 5:58 PM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-soc@vger.kernel.org;
> Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
> Subject: Re: [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
>
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
>
> > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > index b7ecf47..586ab39 100644
> > --- a/drivers/dma/pl330.c
> > +++ b/drivers/dma/pl330.c
> > @@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct
> dma_pl330_chan *pch)
> >        async_tx_ack(&desc->txd);
> >
> >        desc->req.rqtype = peri->rqtype;
> > -       desc->req.peri = peri->peri_id;
> > +       desc->req.peri = pch->chan.chan_id;
> Btw, I plan to revert this if my patch is accepted that proposes
> to free chan_id solely for use by DMAC drivers(which we should
> employ to pass paltform assigned channel ID to client drivers)
>
> > @@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct
> amba_id *id)
> >                struct dma_pl330_peri *peri = &pdat->peri[i];
> >                pch = &pdmac->peripherals[i];
> >
> > -               switch (peri->rqtype) {
> > -               case MEMTOMEM:
> > -                       dma_cap_set(DMA_MEMCPY, pd->cap_mask);
> > -                       break;
> > -               case MEMTODEV:
> > -               case DEVTOMEM:
> > -                       dma_cap_set(DMA_SLAVE, pd->cap_mask);
> > -                       break;
> > -               default:
> > -                       dev_err(&adev->dev, "DEVTODEV Not Supported\n");
> > -                       continue;
> > +               if (peri) {
> > +                       switch (peri->rqtype) {
> > +                       case MEMTOMEM:
> > +                               dma_cap_set(DMA_MEMCPY, pd->cap_mask);
> > +                               break;
> > +                       case MEMTODEV:
> > +                       case DEVTOMEM:
> > +                               dma_cap_set(DMA_SLAVE, pd->cap_mask);
> > +                               break;
> > +                       default:
> > +                               dev_err(&adev->dev, "DEVTODEV Not
> Supported\n");
> > +                               continue;
> > +                       }
> >                }
> If you pass platform data correctly, you don't need to check against NULL
> peri.

Ok, It may be excessive error check. I will remove this point.

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

* [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
@ 2011-07-25  9:48       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  9:48 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: Jassi Brar [mailto:jassisinghbrar at gmail.com]
> Sent: Monday, July 25, 2011 5:58 PM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-soc at vger.kernel.org;
> Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
> Subject: Re: [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
>
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
>
> > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > index b7ecf47..586ab39 100644
> > --- a/drivers/dma/pl330.c
> > +++ b/drivers/dma/pl330.c
> > @@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct
> dma_pl330_chan *pch)
> >        async_tx_ack(&desc->txd);
> >
> >        desc->req.rqtype = peri->rqtype;
> > -       desc->req.peri = peri->peri_id;
> > +       desc->req.peri = pch->chan.chan_id;
> Btw, I plan to revert this if my patch is accepted that proposes
> to free chan_id solely for use by DMAC drivers(which we should
> employ to pass paltform assigned channel ID to client drivers)
>
> > @@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct
> amba_id *id)
> >                struct dma_pl330_peri *peri = &pdat->peri[i];
> >                pch = &pdmac->peripherals[i];
> >
> > -               switch (peri->rqtype) {
> > -               case MEMTOMEM:
> > -                       dma_cap_set(DMA_MEMCPY, pd->cap_mask);
> > -                       break;
> > -               case MEMTODEV:
> > -               case DEVTOMEM:
> > -                       dma_cap_set(DMA_SLAVE, pd->cap_mask);
> > -                       break;
> > -               default:
> > -                       dev_err(&adev->dev, "DEVTODEV Not Supported\n");
> > -                       continue;
> > +               if (peri) {
> > +                       switch (peri->rqtype) {
> > +                       case MEMTOMEM:
> > +                               dma_cap_set(DMA_MEMCPY, pd->cap_mask);
> > +                               break;
> > +                       case MEMTODEV:
> > +                       case DEVTOMEM:
> > +                               dma_cap_set(DMA_SLAVE, pd->cap_mask);
> > +                               break;
> > +                       default:
> > +                               dev_err(&adev->dev, "DEVTODEV Not
> Supported\n");
> > +                               continue;
> > +                       }
> >                }
> If you pass platform data correctly, you don't need to check against NULL
> peri.

Ok, It may be excessive error check. I will remove this point.

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

* RE: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-25  9:36     ` Russell King - ARM Linux
@ 2011-07-25  9:57       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  9:57 UTC (permalink / raw)
  To: 'Russell King - ARM Linux'
  Cc: 'Kukjin Kim', 'Vinod Koul', 'Jassi Brar',
	'Grant Likely', linux-samsung-soc, 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

Russell King - ARM Linux Wrote:

> Sent: Monday, July 25, 2011 6:36 PM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org;
linux-samsung-soc@vger.kernel.org;
> Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>
> On Mon, Jul 25, 2011 at 10:28:24AM +0900, Boojin Kim wrote:
> > +static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
> > +				struct samsung_dma_info *info)
> > +{
> > +	struct dma_chan *chan;
> > +	dma_cap_mask_t mask;
> > +	struct dma_slave_config slave_config;
> > +
> > +	dma_cap_zero(mask);
> > +	dma_cap_set(info->cap, mask);
> > +
> > +	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
> > +
> > +	if (info->direction == DMA_FROM_DEVICE) {
> > +		memset(&slave_config, 0, sizeof(struct dma_slave_config));
> > +		slave_config.direction = info->direction;
> > +		slave_config.src_addr = info->fifo;
> > +		slave_config.src_addr_width = info->width;
>
> This should really set slave_config.src_maxburst to something sensible
too,
> even if that's just '1'.
I will address your comment.

>
> > +		dmaengine_slave_config(chan, &slave_config);
> > +	} else if (info->direction == DMA_TO_DEVICE) {
> > +		memset(&slave_config, 0, sizeof(struct dma_slave_config));
> > +		slave_config.direction = info->direction;
> > +		slave_config.dst_addr = info->fifo;
> > +		slave_config.dst_addr_width = info->width;
>
> Ditto for dst_maxburst.
>
> > +		dmaengine_slave_config(chan, &slave_config);
> > +	}
> > +
> > +	return (unsigned)chan;
>
> I hope these interfaces yet cleaned away soon so that these casts can be
> killed off.
>
> > +struct samsung_dma_prep_info {
> > +	enum dma_transaction_type cap;
> > +	enum dma_data_direction direction;
> > +	unsigned buf;
>
> dma_addr_t ?
>
> > +	unsigned long period;
> > +	unsigned long len;
> > +	void (*fp)(void *data);
> > +	void *fp_param;
> > +};
> > +
> > +struct samsung_dma_info {
> > +	enum dma_transaction_type cap;
> > +	enum dma_data_direction direction;
> > +	enum dma_slave_buswidth width;
> > +	unsigned fifo;
>
> dma_addr_t ?
>
> > +	struct s3c2410_dma_client *client;
> > +};
> > +
> > +struct samsung_dma_ops {
> > +	bool init;
>
> Unused?
Yes, It's my mistake. I will address your comment.

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-25  9:57       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25  9:57 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux Wrote:

> Sent: Monday, July 25, 2011 6:36 PM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org;
linux-samsung-soc at vger.kernel.org;
> Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>
> On Mon, Jul 25, 2011 at 10:28:24AM +0900, Boojin Kim wrote:
> > +static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
> > +				struct samsung_dma_info *info)
> > +{
> > +	struct dma_chan *chan;
> > +	dma_cap_mask_t mask;
> > +	struct dma_slave_config slave_config;
> > +
> > +	dma_cap_zero(mask);
> > +	dma_cap_set(info->cap, mask);
> > +
> > +	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
> > +
> > +	if (info->direction == DMA_FROM_DEVICE) {
> > +		memset(&slave_config, 0, sizeof(struct dma_slave_config));
> > +		slave_config.direction = info->direction;
> > +		slave_config.src_addr = info->fifo;
> > +		slave_config.src_addr_width = info->width;
>
> This should really set slave_config.src_maxburst to something sensible
too,
> even if that's just '1'.
I will address your comment.

>
> > +		dmaengine_slave_config(chan, &slave_config);
> > +	} else if (info->direction == DMA_TO_DEVICE) {
> > +		memset(&slave_config, 0, sizeof(struct dma_slave_config));
> > +		slave_config.direction = info->direction;
> > +		slave_config.dst_addr = info->fifo;
> > +		slave_config.dst_addr_width = info->width;
>
> Ditto for dst_maxburst.
>
> > +		dmaengine_slave_config(chan, &slave_config);
> > +	}
> > +
> > +	return (unsigned)chan;
>
> I hope these interfaces yet cleaned away soon so that these casts can be
> killed off.
>
> > +struct samsung_dma_prep_info {
> > +	enum dma_transaction_type cap;
> > +	enum dma_data_direction direction;
> > +	unsigned buf;
>
> dma_addr_t ?
>
> > +	unsigned long period;
> > +	unsigned long len;
> > +	void (*fp)(void *data);
> > +	void *fp_param;
> > +};
> > +
> > +struct samsung_dma_info {
> > +	enum dma_transaction_type cap;
> > +	enum dma_data_direction direction;
> > +	enum dma_slave_buswidth width;
> > +	unsigned fifo;
>
> dma_addr_t ?
>
> > +	struct s3c2410_dma_client *client;
> > +};
> > +
> > +struct samsung_dma_ops {
> > +	bool init;
>
> Unused?
Yes, It's my mistake. I will address your comment.

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

* Re: [RESEND] [PATCH V4 0/14] To use DMA generic APIs for Samsung DMA
  2011-07-25  1:28 ` Boojin Kim
@ 2011-07-25 10:17   ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 10:17 UTC (permalink / raw)
  To: Boojin Kim
  Cc: vinod.koul, linux-arm-kernel, linux-samsung-soc, Kukjin Kim,
	Jassi Brar, Grant Likely, Mark Brown, Dan Williams

On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> This patchset adds support DMA generic APIs for Samsung DMA
> and is re-sent by the request of DMA maintainer, Vinod Koul.
> 
> V4 has the changes about 3 patches from V3.
> Changes from V3:
> - Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset
>   into two patches.
> 	- One is '03/14 patch' for supporting DMA_SLAVE_CONFIG command.
> 	- Another is '04/14 patch' for supporting DMA_CYCLIC capability.
> - Code clean-up
> 	- Remove unnecessary vairable referance on '01/14 patch'.
> 	- Remove redunancy code on '06/14 patch'
> 
> [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
> [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
> [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
> [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
> [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
> [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
> [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
> [PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
> [PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
> [PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
> [PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
> [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
> [PATCH V4 13/14] ASoC: Samsung: Update DMA interface
> [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
> 
Thanks for resending I will review them now, You should use git
--cover-letter to generate this

-- 
~Vinod Koul
Intel Corp.

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

* [RESEND] [PATCH V4 0/14] To use DMA generic APIs for Samsung DMA
@ 2011-07-25 10:17   ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 10:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> This patchset adds support DMA generic APIs for Samsung DMA
> and is re-sent by the request of DMA maintainer, Vinod Koul.
> 
> V4 has the changes about 3 patches from V3.
> Changes from V3:
> - Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset
>   into two patches.
> 	- One is '03/14 patch' for supporting DMA_SLAVE_CONFIG command.
> 	- Another is '04/14 patch' for supporting DMA_CYCLIC capability.
> - Code clean-up
> 	- Remove unnecessary vairable referance on '01/14 patch'.
> 	- Remove redunancy code on '06/14 patch'
> 
> [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
> [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
> [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
> [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
> [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
> [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
> [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
> [PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
> [PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
> [PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
> [PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
> [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
> [PATCH V4 13/14] ASoC: Samsung: Update DMA interface
> [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
> 
Thanks for resending I will review them now, You should use git
--cover-letter to generate this

-- 
~Vinod Koul
Intel Corp.

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

* Re: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25 10:26     ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 10:26 UTC (permalink / raw)
  To: Boojin Kim
  Cc: vinod.koul, linux-arm-kernel, linux-samsung-soc, Kukjin Kim,
	Jassi Brar, Grant Likely, Mark Brown, Dan Williams

On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> This patch adds support DMA_SLAVE_CONFIG command.
> 
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> ---
>  drivers/dma/pl330.c |   53 +++++++++++++++++++++++++++++++++++++-------------
>  1 files changed, 39 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 586ab39..880f010 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
>  static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
>  {
>  	struct dma_pl330_chan *pch = to_pchan(chan);
> -	struct dma_pl330_desc *desc;
> +	struct dma_pl330_desc *desc, *_dt;
>  	unsigned long flags;
> +	struct dma_pl330_dmac *pdmac = pch->dmac;
> +	struct dma_slave_config *slave_config;
> +	struct dma_pl330_peri *peri;
> +	LIST_HEAD(list);
>  
> -	/* Only supports DMA_TERMINATE_ALL */
> -	if (cmd != DMA_TERMINATE_ALL)
> -		return -ENXIO;
> -
> -	spin_lock_irqsave(&pch->lock, flags);
> -
> -	/* FLUSH the PL330 Channel thread */
> -	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> +	switch (cmd) {
> +	case DMA_TERMINATE_ALL:
> +		spin_lock_irqsave(&pch->lock, flags);
>  
> -	/* Mark all desc done */
> -	list_for_each_entry(desc, &pch->work_list, node)
> -		desc->status = DONE;
> +		/* FLUSH the PL330 Channel thread */
> +		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
>  
> -	spin_unlock_irqrestore(&pch->lock, flags);
> +		/* Mark all desc done */
> +		list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
> +			desc->status = DONE;
> +			pch->completed = desc->txd.cookie;
> +			list_move_tail(&desc->node, &list);
> +		}
>  
> -	pl330_tasklet((unsigned long) pch);
> +		list_splice_tail_init(&list, &pdmac->desc_pool);
> +		spin_unlock_irqrestore(&pch->lock, flags);
> +		break;
> +	case DMA_SLAVE_CONFIG:
> +		slave_config = (struct dma_slave_config *)arg;
> +		peri = pch->chan.private;
> +
> +		if (slave_config->direction == DMA_TO_DEVICE) {
> +			if (slave_config->dst_addr)
> +				peri->fifo_addr = slave_config->dst_addr;
> +			if (slave_config->dst_addr_width)
> +				peri->burst_sz = __ffs(slave_config->dst_addr_width);
This doesn't sound right, why can't you use xxx_maxburst field instead?

> +		} else if (slave_config->direction == DMA_FROM_DEVICE) {
> +			if (slave_config->src_addr)
> +				peri->fifo_addr = slave_config->src_addr;
> +			if (slave_config->src_addr_width)
> +				peri->burst_sz = __ffs(slave_config->src_addr_width);
ditto...
> +		}
> +		break;
> +	default:
> +		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
> +		return -ENXIO;
> +	}
>  
>  	return 0;
>  }

-- 
~Vinod Koul
Intel Corp.

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

* [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
@ 2011-07-25 10:26     ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 10:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> This patch adds support DMA_SLAVE_CONFIG command.
> 
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> ---
>  drivers/dma/pl330.c |   53 +++++++++++++++++++++++++++++++++++++-------------
>  1 files changed, 39 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 586ab39..880f010 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
>  static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
>  {
>  	struct dma_pl330_chan *pch = to_pchan(chan);
> -	struct dma_pl330_desc *desc;
> +	struct dma_pl330_desc *desc, *_dt;
>  	unsigned long flags;
> +	struct dma_pl330_dmac *pdmac = pch->dmac;
> +	struct dma_slave_config *slave_config;
> +	struct dma_pl330_peri *peri;
> +	LIST_HEAD(list);
>  
> -	/* Only supports DMA_TERMINATE_ALL */
> -	if (cmd != DMA_TERMINATE_ALL)
> -		return -ENXIO;
> -
> -	spin_lock_irqsave(&pch->lock, flags);
> -
> -	/* FLUSH the PL330 Channel thread */
> -	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> +	switch (cmd) {
> +	case DMA_TERMINATE_ALL:
> +		spin_lock_irqsave(&pch->lock, flags);
>  
> -	/* Mark all desc done */
> -	list_for_each_entry(desc, &pch->work_list, node)
> -		desc->status = DONE;
> +		/* FLUSH the PL330 Channel thread */
> +		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
>  
> -	spin_unlock_irqrestore(&pch->lock, flags);
> +		/* Mark all desc done */
> +		list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
> +			desc->status = DONE;
> +			pch->completed = desc->txd.cookie;
> +			list_move_tail(&desc->node, &list);
> +		}
>  
> -	pl330_tasklet((unsigned long) pch);
> +		list_splice_tail_init(&list, &pdmac->desc_pool);
> +		spin_unlock_irqrestore(&pch->lock, flags);
> +		break;
> +	case DMA_SLAVE_CONFIG:
> +		slave_config = (struct dma_slave_config *)arg;
> +		peri = pch->chan.private;
> +
> +		if (slave_config->direction == DMA_TO_DEVICE) {
> +			if (slave_config->dst_addr)
> +				peri->fifo_addr = slave_config->dst_addr;
> +			if (slave_config->dst_addr_width)
> +				peri->burst_sz = __ffs(slave_config->dst_addr_width);
This doesn't sound right, why can't you use xxx_maxburst field instead?

> +		} else if (slave_config->direction == DMA_FROM_DEVICE) {
> +			if (slave_config->src_addr)
> +				peri->fifo_addr = slave_config->src_addr;
> +			if (slave_config->src_addr_width)
> +				peri->burst_sz = __ffs(slave_config->src_addr_width);
ditto...
> +		}
> +		break;
> +	default:
> +		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
> +		return -ENXIO;
> +	}
>  
>  	return 0;
>  }

-- 
~Vinod Koul
Intel Corp.

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

* RE: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25  9:27     ` Russell King - ARM Linux
@ 2011-07-25 10:31       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 10:31 UTC (permalink / raw)
  To: 'Russell King - ARM Linux'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Kukjin Kim',
	'Vinod Koul', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams'

Russell King - ARM Linux Wrote:

> Sent: Monday, July 25, 2011 6:28 PM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org;
linux-samsung-soc@vger.kernel.org;
> Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
>
> On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > +static void pl330_tasklet_cyclic(unsigned long data)
> > +{
> > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > +	struct dma_pl330_desc *desc, *_dt;
> > +	unsigned long flags;
> > +	LIST_HEAD(list);
> > +
> > +	spin_lock_irqsave(&pch->lock, flags);
> ...
> > +			callback = desc->txd.callback;
> > +			if (callback)
> > +				callback(desc->txd.callback_param);
>
> On this again - what if the callback wants to terminate the DMA activity
> because there's no more audio data to be sent/received from the device?

Do you mean what is happened if the callback() is called after channel is
terminated ?
Or What is happened if Callback() calls 'dma_release_channel()' to terminate
DMA?

>
> > +
>
> Useless blank line.
I will address your comment.
>
> > +		}
> > +
> > +	spin_unlock_irqrestore(&pch->lock, flags);
> > +}
> > +
> >  static void pl330_tasklet(unsigned long data)
> >  {
> >  	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > @@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum
> pl330_op_err err)
> >
> >  	spin_unlock_irqrestore(&pch->lock, flags);
> >
> > +	if (pch->cyclic_task)
> > +		tasklet_schedule(pch->cyclic_task);
> > +	else
> >  	tasklet_schedule(&pch->task);
>
> Indentation error.
Sorry again.. I will address your comment.

>
> >  }
> >
> > @@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct
dma_chan
> *chan)
> >  	pl330_release_channel(pch->pl330_chid);
> >  	pch->pl330_chid = NULL;
> >
> > +	if (pch->cyclic) {
> > +		pch->cyclic = false;
> > +		list_splice_tail_init(&pch->work_list,
&pch->dmac->desc_pool);
> > +		if (pch->cyclic_task) {
> > +			tasklet_kill(pch->cyclic_task);
> > +			pch->cyclic_task = NULL;
> > +		}
> > +	}
> > +
> >  	spin_unlock_irqrestore(&pch->lock, flags);
> >  }
> >
> > @@ -547,6 +599,63 @@ static inline int get_burst_len(struct
dma_pl330_desc
> *desc, size_t len)
> >  	return burst_len;
> >  }
> >
> > +static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
> > +		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
> > +		size_t period_len, enum dma_data_direction direction)
> > +{
> > +	struct dma_pl330_desc *desc;
> > +	struct dma_pl330_chan *pch = to_pchan(chan);
> > +	struct dma_pl330_peri *peri = chan->private;
> > +	dma_addr_t dst;
> > +	dma_addr_t src;
> > +
> > +	pch = to_pchan(chan);
> > +	if (!pch)
> > +		return NULL;
>
> You've already done the to_pchan() thing when declaring pch.  You've
> already dereferenced 'chan', so there's no way that pch could be NULL
> here.
I will address your comment.

>
> > +
> > +	desc = pl330_get_desc(pch);
> > +	if (!desc) {
> > +		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
> > +			__func__, __LINE__);
> > +		return NULL;
> > +	}
> > +
> > +	switch (direction) {
> > +	case DMA_TO_DEVICE:
> > +		desc->rqcfg.src_inc = 1;
> > +		desc->rqcfg.dst_inc = 0;
> > +		src = dma_addr;
> > +		dst = peri->fifo_addr;
> > +		break;
> > +	case DMA_FROM_DEVICE:
> > +		desc->rqcfg.src_inc = 0;
> > +		desc->rqcfg.dst_inc = 1;
> > +		src = peri->fifo_addr;
> > +		dst = dma_addr;
> > +		break;
> > +	default:
> > +		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
> > +		__func__, __LINE__);
> > +		return NULL;
> > +	}
> > +
> > +	desc->rqcfg.brst_size = peri->burst_sz;
> > +	desc->rqcfg.brst_len = 1;
> > +
> > +	if (!pch->cyclic_task) {
> > +		pch->cyclic_task =
> > +			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
> > +		tasklet_init(pch->cyclic_task,
> > +			pl330_tasklet_cyclic, (unsigned int)pch);
>
> Here you allocate memory for the cyclic task.  Above you set this pointer
> to NULL.  That sounds like a memory leak to me.  Why are you kmallocing
> this memory - why can't it be part of the dma_pl330_chan structure?  It's
> only 28 bytes.

It's my mistake. I should have been free of the memory.

And the reason why I use kmalloc for 'cyclic_task' is following.
This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of
channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This
memory size is increased according to the number of DMAC.
And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I
make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is dedicated
for Mem-to-Mem operation should hold unused data.
So, I think it's loss that all dma channels hold own 'cyclic_task'.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 10:31       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux Wrote:

> Sent: Monday, July 25, 2011 6:28 PM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org;
linux-samsung-soc at vger.kernel.org;
> Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
>
> On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > +static void pl330_tasklet_cyclic(unsigned long data)
> > +{
> > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > +	struct dma_pl330_desc *desc, *_dt;
> > +	unsigned long flags;
> > +	LIST_HEAD(list);
> > +
> > +	spin_lock_irqsave(&pch->lock, flags);
> ...
> > +			callback = desc->txd.callback;
> > +			if (callback)
> > +				callback(desc->txd.callback_param);
>
> On this again - what if the callback wants to terminate the DMA activity
> because there's no more audio data to be sent/received from the device?

Do you mean what is happened if the callback() is called after channel is
terminated ?
Or What is happened if Callback() calls 'dma_release_channel()' to terminate
DMA?

>
> > +
>
> Useless blank line.
I will address your comment.
>
> > +		}
> > +
> > +	spin_unlock_irqrestore(&pch->lock, flags);
> > +}
> > +
> >  static void pl330_tasklet(unsigned long data)
> >  {
> >  	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > @@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum
> pl330_op_err err)
> >
> >  	spin_unlock_irqrestore(&pch->lock, flags);
> >
> > +	if (pch->cyclic_task)
> > +		tasklet_schedule(pch->cyclic_task);
> > +	else
> >  	tasklet_schedule(&pch->task);
>
> Indentation error.
Sorry again.. I will address your comment.

>
> >  }
> >
> > @@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct
dma_chan
> *chan)
> >  	pl330_release_channel(pch->pl330_chid);
> >  	pch->pl330_chid = NULL;
> >
> > +	if (pch->cyclic) {
> > +		pch->cyclic = false;
> > +		list_splice_tail_init(&pch->work_list,
&pch->dmac->desc_pool);
> > +		if (pch->cyclic_task) {
> > +			tasklet_kill(pch->cyclic_task);
> > +			pch->cyclic_task = NULL;
> > +		}
> > +	}
> > +
> >  	spin_unlock_irqrestore(&pch->lock, flags);
> >  }
> >
> > @@ -547,6 +599,63 @@ static inline int get_burst_len(struct
dma_pl330_desc
> *desc, size_t len)
> >  	return burst_len;
> >  }
> >
> > +static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
> > +		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
> > +		size_t period_len, enum dma_data_direction direction)
> > +{
> > +	struct dma_pl330_desc *desc;
> > +	struct dma_pl330_chan *pch = to_pchan(chan);
> > +	struct dma_pl330_peri *peri = chan->private;
> > +	dma_addr_t dst;
> > +	dma_addr_t src;
> > +
> > +	pch = to_pchan(chan);
> > +	if (!pch)
> > +		return NULL;
>
> You've already done the to_pchan() thing when declaring pch.  You've
> already dereferenced 'chan', so there's no way that pch could be NULL
> here.
I will address your comment.

>
> > +
> > +	desc = pl330_get_desc(pch);
> > +	if (!desc) {
> > +		dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
> > +			__func__, __LINE__);
> > +		return NULL;
> > +	}
> > +
> > +	switch (direction) {
> > +	case DMA_TO_DEVICE:
> > +		desc->rqcfg.src_inc = 1;
> > +		desc->rqcfg.dst_inc = 0;
> > +		src = dma_addr;
> > +		dst = peri->fifo_addr;
> > +		break;
> > +	case DMA_FROM_DEVICE:
> > +		desc->rqcfg.src_inc = 0;
> > +		desc->rqcfg.dst_inc = 1;
> > +		src = peri->fifo_addr;
> > +		dst = dma_addr;
> > +		break;
> > +	default:
> > +		dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
> > +		__func__, __LINE__);
> > +		return NULL;
> > +	}
> > +
> > +	desc->rqcfg.brst_size = peri->burst_sz;
> > +	desc->rqcfg.brst_len = 1;
> > +
> > +	if (!pch->cyclic_task) {
> > +		pch->cyclic_task =
> > +			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
> > +		tasklet_init(pch->cyclic_task,
> > +			pl330_tasklet_cyclic, (unsigned int)pch);
>
> Here you allocate memory for the cyclic task.  Above you set this pointer
> to NULL.  That sounds like a memory leak to me.  Why are you kmallocing
> this memory - why can't it be part of the dma_pl330_chan structure?  It's
> only 28 bytes.

It's my mistake. I should have been free of the memory.

And the reason why I use kmalloc for 'cyclic_task' is following.
This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of
channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This
memory size is increased according to the number of DMAC.
And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I
make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is dedicated
for Mem-to-Mem operation should hold unused data.
So, I think it's loss that all dma channels hold own 'cyclic_task'.

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

* RE: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
  2011-07-25  9:40     ` Russell King - ARM Linux
@ 2011-07-25 10:34       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 10:34 UTC (permalink / raw)
  To: 'Russell King - ARM Linux'
  Cc: 'Kukjin Kim', 'Vinod Koul', 'Jassi Brar',
	'Grant Likely', linux-samsung-soc, 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

Russell King - ARM Linux Wrote:

> Sent: Monday, July 25, 2011 6:40 PM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org;
linux-samsung-soc@vger.kernel.org;
> Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
>
> On Mon, Jul 25, 2011 at 10:28:30AM +0900, Boojin Kim wrote:
> > +static void s3c64xx_spi_dma_rxcb(void *data)
> > +{
> > +	struct s3c64xx_spi_driver_data *sdd
> > +		= (struct s3c64xx_spi_driver_data *)data;
>
> You never need explicit casts from void * or to void *.  Please remove
> these.
I will address your comment.

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

* [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
@ 2011-07-25 10:34       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 10:34 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux Wrote:

> Sent: Monday, July 25, 2011 6:40 PM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org;
linux-samsung-soc at vger.kernel.org;
> Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
>
> On Mon, Jul 25, 2011 at 10:28:30AM +0900, Boojin Kim wrote:
> > +static void s3c64xx_spi_dma_rxcb(void *data)
> > +{
> > +	struct s3c64xx_spi_driver_data *sdd
> > +		= (struct s3c64xx_spi_driver_data *)data;
>
> You never need explicit casts from void * or to void *.  Please remove
> these.
I will address your comment.

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

* Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 10:31       ` Boojin Kim
@ 2011-07-25 10:36         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25 10:36 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, 'Kukjin Kim',
	'Vinod Koul', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams'

On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > +{
> > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > +	struct dma_pl330_desc *desc, *_dt;
> > > +	unsigned long flags;
> > > +	LIST_HEAD(list);
> > > +
> > > +	spin_lock_irqsave(&pch->lock, flags);
> > ...
> > > +			callback = desc->txd.callback;
> > > +			if (callback)
> > > +				callback(desc->txd.callback_param);
> >
> > On this again - what if the callback wants to terminate the DMA activity
> > because there's no more audio data to be sent/received from the device?
> 
> Do you mean what is happened if the callback() is called after channel is
> terminated ?
> Or What is happened if Callback() calls 'dma_release_channel()' to terminate
> DMA?

No.  I mean what if the callback wants to call dmaengine_terminate_all().

> > > +	if (!pch->cyclic_task) {
> > > +		pch->cyclic_task =
> > > +			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
> > > +		tasklet_init(pch->cyclic_task,
> > > +			pl330_tasklet_cyclic, (unsigned int)pch);
> >
> > Here you allocate memory for the cyclic task.  Above you set this pointer
> > to NULL.  That sounds like a memory leak to me.  Why are you kmallocing
> > this memory - why can't it be part of the dma_pl330_chan structure?  It's
> > only 28 bytes.
> 
> It's my mistake. I should have been free of the memory.
> 
> And the reason why I use kmalloc for 'cyclic_task' is following.
> This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of
> channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This
> memory size is increased according to the number of DMAC.
> And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I
> make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is dedicated
> for Mem-to-Mem operation should hold unused data.
> So, I think it's loss that all dma channels hold own 'cyclic_task'.

Could you re-use the tasklet that already exists?

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 10:36         ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25 10:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > +{
> > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > +	struct dma_pl330_desc *desc, *_dt;
> > > +	unsigned long flags;
> > > +	LIST_HEAD(list);
> > > +
> > > +	spin_lock_irqsave(&pch->lock, flags);
> > ...
> > > +			callback = desc->txd.callback;
> > > +			if (callback)
> > > +				callback(desc->txd.callback_param);
> >
> > On this again - what if the callback wants to terminate the DMA activity
> > because there's no more audio data to be sent/received from the device?
> 
> Do you mean what is happened if the callback() is called after channel is
> terminated ?
> Or What is happened if Callback() calls 'dma_release_channel()' to terminate
> DMA?

No.  I mean what if the callback wants to call dmaengine_terminate_all().

> > > +	if (!pch->cyclic_task) {
> > > +		pch->cyclic_task =
> > > +			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
> > > +		tasklet_init(pch->cyclic_task,
> > > +			pl330_tasklet_cyclic, (unsigned int)pch);
> >
> > Here you allocate memory for the cyclic task.  Above you set this pointer
> > to NULL.  That sounds like a memory leak to me.  Why are you kmallocing
> > this memory - why can't it be part of the dma_pl330_chan structure?  It's
> > only 28 bytes.
> 
> It's my mistake. I should have been free of the memory.
> 
> And the reason why I use kmalloc for 'cyclic_task' is following.
> This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of
> channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This
> memory size is increased according to the number of DMAC.
> And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I
> make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is dedicated
> for Mem-to-Mem operation should hold unused data.
> So, I think it's loss that all dma channels hold own 'cyclic_task'.

Could you re-use the tasklet that already exists?

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

* Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 10:36         ` Russell King - ARM Linux
@ 2011-07-25 10:48           ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 10:48 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-samsung-soc, Boojin Kim, vinod.koul, 'Jassi Brar',
	'Grant Likely', 'Kukjin Kim',
	'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Mon, 2011-07-25 at 11:36 +0100, Russell King - ARM Linux wrote:
> On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > +{
> > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > +	unsigned long flags;
> > > > +	LIST_HEAD(list);
> > > > +
> > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > ...
> > > > +			callback = desc->txd.callback;
> > > > +			if (callback)
> > > > +				callback(desc->txd.callback_param);
> > >
> > > On this again - what if the callback wants to terminate the DMA activity
> > > because there's no more audio data to be sent/received from the device?
> > 
> > Do you mean what is happened if the callback() is called after channel is
> > terminated ?
> > Or What is happened if Callback() calls 'dma_release_channel()' to terminate
> > DMA?
> 
> No.  I mean what if the callback wants to call dmaengine_terminate_all().
you are supposed to drop the lock here, that way callback can call any
DMA API, otherwise it will result in deadlock.
This make me wonder you haven't read the documentation at all, please
ensure you have read Documentation/dmaengine.txt before next posting
> 
> > > > +	if (!pch->cyclic_task) {
> > > > +		pch->cyclic_task =
> > > > +			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
> > > > +		tasklet_init(pch->cyclic_task,
> > > > +			pl330_tasklet_cyclic, (unsigned int)pch);
> > >
> > > Here you allocate memory for the cyclic task.  Above you set this pointer
> > > to NULL.  That sounds like a memory leak to me.  Why are you kmallocing
> > > this memory - why can't it be part of the dma_pl330_chan structure?  It's
> > > only 28 bytes.
> > 
> > It's my mistake. I should have been free of the memory.
> > 
> > And the reason why I use kmalloc for 'cyclic_task' is following.
> > This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of
> > channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This
> > memory size is increased according to the number of DMAC.
> > And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I
> > make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is dedicated
> > for Mem-to-Mem operation should hold unused data.
> > So, I think it's loss that all dma channels hold own 'cyclic_task'.
> 
> Could you re-use the tasklet that already exists?


-- 
~Vinod Koul
Intel Corp.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 10:48           ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 10:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 11:36 +0100, Russell King - ARM Linux wrote:
> On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > +{
> > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > +	unsigned long flags;
> > > > +	LIST_HEAD(list);
> > > > +
> > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > ...
> > > > +			callback = desc->txd.callback;
> > > > +			if (callback)
> > > > +				callback(desc->txd.callback_param);
> > >
> > > On this again - what if the callback wants to terminate the DMA activity
> > > because there's no more audio data to be sent/received from the device?
> > 
> > Do you mean what is happened if the callback() is called after channel is
> > terminated ?
> > Or What is happened if Callback() calls 'dma_release_channel()' to terminate
> > DMA?
> 
> No.  I mean what if the callback wants to call dmaengine_terminate_all().
you are supposed to drop the lock here, that way callback can call any
DMA API, otherwise it will result in deadlock.
This make me wonder you haven't read the documentation at all, please
ensure you have read Documentation/dmaengine.txt before next posting
> 
> > > > +	if (!pch->cyclic_task) {
> > > > +		pch->cyclic_task =
> > > > +			kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
> > > > +		tasklet_init(pch->cyclic_task,
> > > > +			pl330_tasklet_cyclic, (unsigned int)pch);
> > >
> > > Here you allocate memory for the cyclic task.  Above you set this pointer
> > > to NULL.  That sounds like a memory leak to me.  Why are you kmallocing
> > > this memory - why can't it be part of the dma_pl330_chan structure?  It's
> > > only 28 bytes.
> > 
> > It's my mistake. I should have been free of the memory.
> > 
> > And the reason why I use kmalloc for 'cyclic_task' is following.
> > This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of
> > channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This
> > memory size is increased according to the number of DMAC.
> > And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I
> > make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is dedicated
> > for Mem-to-Mem operation should hold unused data.
> > So, I think it's loss that all dma channels hold own 'cyclic_task'.
> 
> Could you re-use the tasklet that already exists?


-- 
~Vinod Koul
Intel Corp.

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

* Re: [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25 10:52     ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 10:52 UTC (permalink / raw)
  To: Boojin Kim
  Cc: vinod.koul, linux-arm-kernel, linux-samsung-soc, Kukjin Kim,
	Jassi Brar, Grant Likely, Mark Brown, Dan Williams

On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> This patch adds to support PL330-DMA driver on DMADEVICE for S5P SoCs.
> 
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
>  arch/arm/mach-exynos4/include/mach/dma.h           |    4 +-
>  arch/arm/mach-s5p64x0/include/mach/dma.h           |    2 +-
>  arch/arm/mach-s5pc100/include/mach/dma.h           |    2 +-
>  arch/arm/mach-s5pv210/include/mach/dma.h           |    2 +-
>  arch/arm/plat-samsung/Kconfig                      |    8 +++++++
>  .../include/plat/{s3c-dma-pl330.h => dma-pl330.h}  |   21 +++++++++++++------
>  .../plat-samsung/include/plat/s3c-pl330-pdata.h    |    2 +-
>  7 files changed, 28 insertions(+), 13 deletions(-)
>  rename arch/arm/plat-samsung/include/plat/{s3c-dma-pl330.h => dma-pl330.h} (84%)
> 
> diff --git a/arch/arm/mach-exynos4/include/mach/dma.h b/arch/arm/mach-exynos4/include/mach/dma.h
> index 81209eb..201842a 100644
> --- a/arch/arm/mach-exynos4/include/mach/dma.h
> +++ b/arch/arm/mach-exynos4/include/mach/dma.h
> @@ -20,7 +20,7 @@
>  #ifndef __MACH_DMA_H
>  #define __MACH_DMA_H
>  
> -/* This platform uses the common S3C DMA API driver for PL330 */
> -#include <plat/s3c-dma-pl330.h>
> +/* This platform uses the common DMA API driver for PL330 */
> +#include <plat/dma-pl330.h>
>  
>  #endif /* __MACH_DMA_H */
> diff --git a/arch/arm/mach-s5p64x0/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
> index 81209eb..1beae2c 100644
> --- a/arch/arm/mach-s5p64x0/include/mach/dma.h
> +++ b/arch/arm/mach-s5p64x0/include/mach/dma.h
> @@ -21,6 +21,6 @@
>  #define __MACH_DMA_H
>  
>  /* This platform uses the common S3C DMA API driver for PL330 */
> -#include <plat/s3c-dma-pl330.h>
> +#include <plat/dma-pl330.h>
>  
>  #endif /* __MACH_DMA_H */
> diff --git a/arch/arm/mach-s5pc100/include/mach/dma.h b/arch/arm/mach-s5pc100/include/mach/dma.h
> index 81209eb..1beae2c 100644
> --- a/arch/arm/mach-s5pc100/include/mach/dma.h
> +++ b/arch/arm/mach-s5pc100/include/mach/dma.h
> @@ -21,6 +21,6 @@
>  #define __MACH_DMA_H
>  
>  /* This platform uses the common S3C DMA API driver for PL330 */
> -#include <plat/s3c-dma-pl330.h>
> +#include <plat/dma-pl330.h>
>  
>  #endif /* __MACH_DMA_H */
> diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/mach-s5pv210/include/mach/dma.h
> index 81209eb..1beae2c 100644
> --- a/arch/arm/mach-s5pv210/include/mach/dma.h
> +++ b/arch/arm/mach-s5pv210/include/mach/dma.h
> @@ -21,6 +21,6 @@
>  #define __MACH_DMA_H
>  
>  /* This platform uses the common S3C DMA API driver for PL330 */
> -#include <plat/s3c-dma-pl330.h>
> +#include <plat/dma-pl330.h>
>  
>  #endif /* __MACH_DMA_H */
> diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
> index 4d79519..cb170a6 100644
> --- a/arch/arm/plat-samsung/Kconfig
> +++ b/arch/arm/plat-samsung/Kconfig
> @@ -300,6 +300,14 @@ config S3C_PL330_DMA
>  	help
>  	  S3C DMA API Driver for PL330 DMAC.
>  
> +config DMADEV_PL330
> +	bool
> +	select DMADEVICES
> +	select PL330_DMA
> +	select ARM_AMBA
> +	help
> +	  Use DMA device engine for PL330 DMAC.
> +
>  comment "Power management"
>  
>  config SAMSUNG_PM_DEBUG
> diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
> similarity index 84%
> rename from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
> rename to arch/arm/plat-samsung/include/plat/dma-pl330.h
> index 8107442..c402719 100644
> --- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
> +++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
> @@ -8,19 +8,18 @@
>   * (at your option) any later version.
>   */
>  
> -#ifndef	__S3C_DMA_PL330_H_
> -#define	__S3C_DMA_PL330_H_
> -
> -#define S3C2410_DMAF_AUTOSTART		(1 << 0)
> -#define S3C2410_DMAF_CIRCULAR		(1 << 1)
> +#ifndef __DMA_PL330_H_
> +#define __DMA_PL330_H_ __FILE__
>  
> +#define S3C2410_DMAF_AUTOSTART	(1 << 0)
> +#define S3C2410_DMAF_CIRCULAR	(1 << 1)
this looks like bogus diff and can be avoided
>  /*
>   * PL330 can assign any channel to communicate with
>   * any of the peripherals attched to the DMAC.
>   * For the sake of consistency across client drivers,
>   * We keep the channel names unchanged and only add
>   * missing peripherals are added.
> - * Order is not important since S3C PL330 API driver
> + * Order is not important since DMA PL330 API driver
>   * use these just as IDs.
>   */
>  enum dma_ch {
> @@ -84,6 +83,14 @@ enum dma_ch {
>  	DMACH_SLIMBUS4_TX,
>  	DMACH_SLIMBUS5_RX,
>  	DMACH_SLIMBUS5_TX,
> +	DMACH_MTOM_0,
> +	DMACH_MTOM_1,
> +	DMACH_MTOM_2,
> +	DMACH_MTOM_3,
> +	DMACH_MTOM_4,
> +	DMACH_MTOM_5,
> +	DMACH_MTOM_6,
> +	DMACH_MTOM_7,
>  	/* END Marker, also used to denote a reserved channel */
>  	DMACH_MAX,
>  };
> @@ -95,4 +102,4 @@ static inline bool s3c_dma_has_circular(void)
>  
>  #include <plat/dma.h>
>  
> -#endif	/* __S3C_DMA_PL330_H_ */
> +#endif	/* __DMA_PL330_H_ */
> diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
> index bf5e2a9..64fdf66 100644
> --- a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
> +++ b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
> @@ -12,7 +12,7 @@
>  #ifndef __S3C_PL330_PDATA_H
>  #define __S3C_PL330_PDATA_H
>  
> -#include <plat/s3c-dma-pl330.h>
> +#include <plat/dma-pl330.h>
>  
>  /*
>   * Every PL330 DMAC has max 32 peripheral interfaces,

-- 
~Vinod Koul
Intel Corp.

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

* [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
@ 2011-07-25 10:52     ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> This patch adds to support PL330-DMA driver on DMADEVICE for S5P SoCs.
> 
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
>  arch/arm/mach-exynos4/include/mach/dma.h           |    4 +-
>  arch/arm/mach-s5p64x0/include/mach/dma.h           |    2 +-
>  arch/arm/mach-s5pc100/include/mach/dma.h           |    2 +-
>  arch/arm/mach-s5pv210/include/mach/dma.h           |    2 +-
>  arch/arm/plat-samsung/Kconfig                      |    8 +++++++
>  .../include/plat/{s3c-dma-pl330.h => dma-pl330.h}  |   21 +++++++++++++------
>  .../plat-samsung/include/plat/s3c-pl330-pdata.h    |    2 +-
>  7 files changed, 28 insertions(+), 13 deletions(-)
>  rename arch/arm/plat-samsung/include/plat/{s3c-dma-pl330.h => dma-pl330.h} (84%)
> 
> diff --git a/arch/arm/mach-exynos4/include/mach/dma.h b/arch/arm/mach-exynos4/include/mach/dma.h
> index 81209eb..201842a 100644
> --- a/arch/arm/mach-exynos4/include/mach/dma.h
> +++ b/arch/arm/mach-exynos4/include/mach/dma.h
> @@ -20,7 +20,7 @@
>  #ifndef __MACH_DMA_H
>  #define __MACH_DMA_H
>  
> -/* This platform uses the common S3C DMA API driver for PL330 */
> -#include <plat/s3c-dma-pl330.h>
> +/* This platform uses the common DMA API driver for PL330 */
> +#include <plat/dma-pl330.h>
>  
>  #endif /* __MACH_DMA_H */
> diff --git a/arch/arm/mach-s5p64x0/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
> index 81209eb..1beae2c 100644
> --- a/arch/arm/mach-s5p64x0/include/mach/dma.h
> +++ b/arch/arm/mach-s5p64x0/include/mach/dma.h
> @@ -21,6 +21,6 @@
>  #define __MACH_DMA_H
>  
>  /* This platform uses the common S3C DMA API driver for PL330 */
> -#include <plat/s3c-dma-pl330.h>
> +#include <plat/dma-pl330.h>
>  
>  #endif /* __MACH_DMA_H */
> diff --git a/arch/arm/mach-s5pc100/include/mach/dma.h b/arch/arm/mach-s5pc100/include/mach/dma.h
> index 81209eb..1beae2c 100644
> --- a/arch/arm/mach-s5pc100/include/mach/dma.h
> +++ b/arch/arm/mach-s5pc100/include/mach/dma.h
> @@ -21,6 +21,6 @@
>  #define __MACH_DMA_H
>  
>  /* This platform uses the common S3C DMA API driver for PL330 */
> -#include <plat/s3c-dma-pl330.h>
> +#include <plat/dma-pl330.h>
>  
>  #endif /* __MACH_DMA_H */
> diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/mach-s5pv210/include/mach/dma.h
> index 81209eb..1beae2c 100644
> --- a/arch/arm/mach-s5pv210/include/mach/dma.h
> +++ b/arch/arm/mach-s5pv210/include/mach/dma.h
> @@ -21,6 +21,6 @@
>  #define __MACH_DMA_H
>  
>  /* This platform uses the common S3C DMA API driver for PL330 */
> -#include <plat/s3c-dma-pl330.h>
> +#include <plat/dma-pl330.h>
>  
>  #endif /* __MACH_DMA_H */
> diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
> index 4d79519..cb170a6 100644
> --- a/arch/arm/plat-samsung/Kconfig
> +++ b/arch/arm/plat-samsung/Kconfig
> @@ -300,6 +300,14 @@ config S3C_PL330_DMA
>  	help
>  	  S3C DMA API Driver for PL330 DMAC.
>  
> +config DMADEV_PL330
> +	bool
> +	select DMADEVICES
> +	select PL330_DMA
> +	select ARM_AMBA
> +	help
> +	  Use DMA device engine for PL330 DMAC.
> +
>  comment "Power management"
>  
>  config SAMSUNG_PM_DEBUG
> diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
> similarity index 84%
> rename from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
> rename to arch/arm/plat-samsung/include/plat/dma-pl330.h
> index 8107442..c402719 100644
> --- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
> +++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
> @@ -8,19 +8,18 @@
>   * (at your option) any later version.
>   */
>  
> -#ifndef	__S3C_DMA_PL330_H_
> -#define	__S3C_DMA_PL330_H_
> -
> -#define S3C2410_DMAF_AUTOSTART		(1 << 0)
> -#define S3C2410_DMAF_CIRCULAR		(1 << 1)
> +#ifndef __DMA_PL330_H_
> +#define __DMA_PL330_H_ __FILE__
>  
> +#define S3C2410_DMAF_AUTOSTART	(1 << 0)
> +#define S3C2410_DMAF_CIRCULAR	(1 << 1)
this looks like bogus diff and can be avoided
>  /*
>   * PL330 can assign any channel to communicate with
>   * any of the peripherals attched to the DMAC.
>   * For the sake of consistency across client drivers,
>   * We keep the channel names unchanged and only add
>   * missing peripherals are added.
> - * Order is not important since S3C PL330 API driver
> + * Order is not important since DMA PL330 API driver
>   * use these just as IDs.
>   */
>  enum dma_ch {
> @@ -84,6 +83,14 @@ enum dma_ch {
>  	DMACH_SLIMBUS4_TX,
>  	DMACH_SLIMBUS5_RX,
>  	DMACH_SLIMBUS5_TX,
> +	DMACH_MTOM_0,
> +	DMACH_MTOM_1,
> +	DMACH_MTOM_2,
> +	DMACH_MTOM_3,
> +	DMACH_MTOM_4,
> +	DMACH_MTOM_5,
> +	DMACH_MTOM_6,
> +	DMACH_MTOM_7,
>  	/* END Marker, also used to denote a reserved channel */
>  	DMACH_MAX,
>  };
> @@ -95,4 +102,4 @@ static inline bool s3c_dma_has_circular(void)
>  
>  #include <plat/dma.h>
>  
> -#endif	/* __S3C_DMA_PL330_H_ */
> +#endif	/* __DMA_PL330_H_ */
> diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
> index bf5e2a9..64fdf66 100644
> --- a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
> +++ b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
> @@ -12,7 +12,7 @@
>  #ifndef __S3C_PL330_PDATA_H
>  #define __S3C_PL330_PDATA_H
>  
> -#include <plat/s3c-dma-pl330.h>
> +#include <plat/dma-pl330.h>
>  
>  /*
>   * Every PL330 DMAC has max 32 peripheral interfaces,

-- 
~Vinod Koul
Intel Corp.

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

* Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 10:48           ` Vinod Koul
@ 2011-07-25 10:57             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25 10:57 UTC (permalink / raw)
  To: Vinod Koul
  Cc: vinod.koul, Boojin Kim, 'Kukjin Kim',
	'Jassi Brar', 'Grant Likely',
	linux-samsung-soc, 'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Mon, Jul 25, 2011 at 04:18:04PM +0530, Vinod Koul wrote:
> On Mon, 2011-07-25 at 11:36 +0100, Russell King - ARM Linux wrote:
> > On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > > +{
> > > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > > +	unsigned long flags;
> > > > > +	LIST_HEAD(list);
> > > > > +
> > > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > > ...
> > > > > +			callback = desc->txd.callback;
> > > > > +			if (callback)
> > > > > +				callback(desc->txd.callback_param);
> > > >
> > > > On this again - what if the callback wants to terminate the DMA activity
> > > > because there's no more audio data to be sent/received from the device?
> > > 
> > > Do you mean what is happened if the callback() is called after channel is
> > > terminated ?
> > > Or What is happened if Callback() calls 'dma_release_channel()' to terminate
> > > DMA?
> > 
> > No.  I mean what if the callback wants to call dmaengine_terminate_all().
> you are supposed to drop the lock here, that way callback can call any
> DMA API, otherwise it will result in deadlock.
> This make me wonder you haven't read the documentation at all, please
> ensure you have read Documentation/dmaengine.txt before next posting

I know that very well thank you.  Please look at my previous post in the
previous round of patches, and the response from Boojin Kim to see why
I used this as an *EXAMPLE* to get this fixed.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 10:57             ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 04:18:04PM +0530, Vinod Koul wrote:
> On Mon, 2011-07-25 at 11:36 +0100, Russell King - ARM Linux wrote:
> > On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > > +{
> > > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > > +	unsigned long flags;
> > > > > +	LIST_HEAD(list);
> > > > > +
> > > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > > ...
> > > > > +			callback = desc->txd.callback;
> > > > > +			if (callback)
> > > > > +				callback(desc->txd.callback_param);
> > > >
> > > > On this again - what if the callback wants to terminate the DMA activity
> > > > because there's no more audio data to be sent/received from the device?
> > > 
> > > Do you mean what is happened if the callback() is called after channel is
> > > terminated ?
> > > Or What is happened if Callback() calls 'dma_release_channel()' to terminate
> > > DMA?
> > 
> > No.  I mean what if the callback wants to call dmaengine_terminate_all().
> you are supposed to drop the lock here, that way callback can call any
> DMA API, otherwise it will result in deadlock.
> This make me wonder you haven't read the documentation at all, please
> ensure you have read Documentation/dmaengine.txt before next posting

I know that very well thank you.  Please look at my previous post in the
previous round of patches, and the response from Boojin Kim to see why
I used this as an *EXAMPLE* to get this fixed.

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

* Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 10:57             ` Russell King - ARM Linux
@ 2011-07-25 11:01               ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 11:01 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-samsung-soc, Boojin Kim, vinod.koul, 'Jassi Brar',
	'Grant Likely', 'Kukjin Kim',
	'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Mon, 2011-07-25 at 11:57 +0100, Russell King - ARM Linux wrote:
> On Mon, Jul 25, 2011 at 04:18:04PM +0530, Vinod Koul wrote:
> > On Mon, 2011-07-25 at 11:36 +0100, Russell King - ARM Linux wrote:
> > > On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > > > +{
> > > > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > > > +	unsigned long flags;
> > > > > > +	LIST_HEAD(list);
> > > > > > +
> > > > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > > > ...
> > > > > > +			callback = desc->txd.callback;
> > > > > > +			if (callback)
> > > > > > +				callback(desc->txd.callback_param);
> > > > >
> > > > > On this again - what if the callback wants to terminate the DMA activity
> > > > > because there's no more audio data to be sent/received from the device?
> > > > 
> > > > Do you mean what is happened if the callback() is called after channel is
> > > > terminated ?
> > > > Or What is happened if Callback() calls 'dma_release_channel()' to terminate
> > > > DMA?
> > > 
> > > No.  I mean what if the callback wants to call dmaengine_terminate_all().
> > you are supposed to drop the lock here, that way callback can call any
> > DMA API, otherwise it will result in deadlock.
> > This make me wonder you haven't read the documentation at all, please
> > ensure you have read Documentation/dmaengine.txt before next posting
> 
> I know that very well thank you.  Please look at my previous post in the
> previous round of patches, and the response from Boojin Kim to see why
> I used this as an *EXAMPLE* to get this fixed.
Russell,
Sorry that was not intended for you but for the author of patch Boojin
Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it
as going thru this patch made it clear that they haven't.

-- 
~Vinod Koul
Intel Corp.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 11:01               ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 11:57 +0100, Russell King - ARM Linux wrote:
> On Mon, Jul 25, 2011 at 04:18:04PM +0530, Vinod Koul wrote:
> > On Mon, 2011-07-25 at 11:36 +0100, Russell King - ARM Linux wrote:
> > > On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > > > +{
> > > > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > > > +	unsigned long flags;
> > > > > > +	LIST_HEAD(list);
> > > > > > +
> > > > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > > > ...
> > > > > > +			callback = desc->txd.callback;
> > > > > > +			if (callback)
> > > > > > +				callback(desc->txd.callback_param);
> > > > >
> > > > > On this again - what if the callback wants to terminate the DMA activity
> > > > > because there's no more audio data to be sent/received from the device?
> > > > 
> > > > Do you mean what is happened if the callback() is called after channel is
> > > > terminated ?
> > > > Or What is happened if Callback() calls 'dma_release_channel()' to terminate
> > > > DMA?
> > > 
> > > No.  I mean what if the callback wants to call dmaengine_terminate_all().
> > you are supposed to drop the lock here, that way callback can call any
> > DMA API, otherwise it will result in deadlock.
> > This make me wonder you haven't read the documentation at all, please
> > ensure you have read Documentation/dmaengine.txt before next posting
> 
> I know that very well thank you.  Please look at my previous post in the
> previous round of patches, and the response from Boojin Kim to see why
> I used this as an *EXAMPLE* to get this fixed.
Russell,
Sorry that was not intended for you but for the author of patch Boojin
Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it
as going thru this patch made it clear that they haven't.

-- 
~Vinod Koul
Intel Corp.

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

* Re: [RESEND] [PATCH V4 0/14] To use DMA generic APIs for Samsung DMA
  2011-07-25 10:17   ` Vinod Koul
@ 2011-07-25 11:09     ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 11:09 UTC (permalink / raw)
  To: Boojin Kim
  Cc: vinod.koul, Kukjin Kim, Jassi Brar, Grant Likely,
	linux-samsung-soc, Mark Brown, Dan Williams, linux-arm-kernel

On Mon, 2011-07-25 at 15:47 +0530, Vinod Koul wrote:
> On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > This patchset adds support DMA generic APIs for Samsung DMA
> > and is re-sent by the request of DMA maintainer, Vinod Koul.
> > 
> > V4 has the changes about 3 patches from V3.
> > Changes from V3:
> > - Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset
> >   into two patches.
> > 	- One is '03/14 patch' for supporting DMA_SLAVE_CONFIG command.
> > 	- Another is '04/14 patch' for supporting DMA_CYCLIC capability.
> > - Code clean-up
> > 	- Remove unnecessary vairable referance on '01/14 patch'.
> > 	- Remove redunancy code on '06/14 patch'
> > 
> > [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
> > [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
> > [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
> > [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
> > [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
> > [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
> > [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
> > [PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
> > [PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
> > [PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
> > [PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
> > [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
> > [PATCH V4 13/14] ASoC: Samsung: Update DMA interface
> > [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
> > 
> Thanks for resending I will review them now, You should use git
> --cover-letter to generate this
> 
Also I noticed the whole patch set doesn't have any acks from previous
posting. If a patch has got ack from someone and it is not changed at
all in next posting then you can carry that ack.
Makes things easier for me to track while applying

-- 
~Vinod Koul
Intel Corp.

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

* [RESEND] [PATCH V4 0/14] To use DMA generic APIs for Samsung DMA
@ 2011-07-25 11:09     ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 11:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 15:47 +0530, Vinod Koul wrote:
> On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > This patchset adds support DMA generic APIs for Samsung DMA
> > and is re-sent by the request of DMA maintainer, Vinod Koul.
> > 
> > V4 has the changes about 3 patches from V3.
> > Changes from V3:
> > - Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset
> >   into two patches.
> > 	- One is '03/14 patch' for supporting DMA_SLAVE_CONFIG command.
> > 	- Another is '04/14 patch' for supporting DMA_CYCLIC capability.
> > - Code clean-up
> > 	- Remove unnecessary vairable referance on '01/14 patch'.
> > 	- Remove redunancy code on '06/14 patch'
> > 
> > [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
> > [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
> > [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
> > [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
> > [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
> > [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
> > [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
> > [PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
> > [PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
> > [PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
> > [PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
> > [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
> > [PATCH V4 13/14] ASoC: Samsung: Update DMA interface
> > [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
> > 
> Thanks for resending I will review them now, You should use git
> --cover-letter to generate this
> 
Also I noticed the whole patch set doesn't have any acks from previous
posting. If a patch has got ack from someone and it is not changed at
all in next posting then you can carry that ack.
Makes things easier for me to track while applying

-- 
~Vinod Koul
Intel Corp.

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

* Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25 11:17     ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 11:17 UTC (permalink / raw)
  To: Boojin Kim
  Cc: vinod.koul, linux-arm-kernel, linux-samsung-soc, Kukjin Kim,
	Jassi Brar, Grant Likely, Mark Brown, Dan Williams

On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> This patch adds to support DMA generic API to transfer raw
> SPI data. Basiclly the spi driver uses DMA generic API if
> architecture supports it. Otherwise, uses Samsung specific
> S3C-PL330 APIs.
> 
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
>  drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++-----------------------
>  1 files changed, 69 insertions(+), 72 deletions(-)
> 
> diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> index 8945e20..a4cf76a 100644
> --- a/drivers/spi/spi_s3c64xx.c
> +++ b/drivers/spi/spi_s3c64xx.c
> @@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
>  	unsigned                        state;
>  	unsigned                        cur_mode, cur_bpw;
>  	unsigned                        cur_speed;
> +	unsigned			rx_ch;
> +	unsigned			tx_ch;
> +	struct samsung_dma_ops		*ops;
>  };
>  
>  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
> @@ -227,6 +230,38 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
>  	writel(val, regs + S3C64XX_SPI_CH_CFG);
>  }
>  
> +static void s3c64xx_spi_dma_rxcb(void *data)
> +{
> +	struct s3c64xx_spi_driver_data *sdd
> +		= (struct s3c64xx_spi_driver_data *)data;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&sdd->lock, flags);
> +
> +	sdd->state &= ~RXBUSY;
> +	/* If the other done */
> +	if (!(sdd->state & TXBUSY))
> +		complete(&sdd->xfer_completion);
> +
> +	spin_unlock_irqrestore(&sdd->lock, flags);
> +}
> +
> +static void s3c64xx_spi_dma_txcb(void *data)
> +{
> +	struct s3c64xx_spi_driver_data *sdd
> +		= (struct s3c64xx_spi_driver_data *)data;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&sdd->lock, flags);
> +
> +	sdd->state &= ~TXBUSY;
> +	/* If the other done */
> +	if (!(sdd->state & RXBUSY))
> +		complete(&sdd->xfer_completion);
> +
> +	spin_unlock_irqrestore(&sdd->lock, flags);
> +}
I don't see much diff in these two functions and you should be able to
use a generic one which takes care of both TX and RX, does your callback
data know if the channel is for TX or RX? If not then a helper to do
above should take care well and making code simpler

> +
>  static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
>  				struct spi_device *spi,
>  				struct spi_transfer *xfer, int dma_mode)
> @@ -234,6 +269,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
>  	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
>  	void __iomem *regs = sdd->regs;
>  	u32 modecfg, chcfg;
> +	struct samsung_dma_prep_info info;
>  
>  	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
>  	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
> @@ -259,10 +295,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
>  		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
>  		if (dma_mode) {
>  			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
> -			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
> -			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
> -						xfer->tx_dma, xfer->len);
> -			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
> +			info.cap = DMA_SLAVE;
> +			info.direction = DMA_TO_DEVICE;
> +			info.buf = xfer->tx_dma;
> +			info.len = xfer->len;
> +			info.fp = s3c64xx_spi_dma_txcb;
> +			info.fp_param = sdd;
> +			sdd->ops->prepare(sdd->tx_ch, &info);
> +			sdd->ops->trigger(sdd->tx_ch);
>  		} else {
>  			switch (sdd->cur_bpw) {
>  			case 32:
> @@ -294,10 +334,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
>  			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
>  					| S3C64XX_SPI_PACKET_CNT_EN,
>  					regs + S3C64XX_SPI_PACKET_CNT);
> -			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
> -			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
> -						xfer->rx_dma, xfer->len);
> -			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
> +			info.cap = DMA_SLAVE;
> +			info.direction = DMA_FROM_DEVICE;
> +			info.buf = xfer->rx_dma;
> +			info.len = xfer->len;
> +			info.fp = s3c64xx_spi_dma_rxcb;
> +			info.fp_param = sdd;
> +			sdd->ops->prepare(sdd->rx_ch, &info);
> +			sdd->ops->trigger(sdd->rx_ch);
>  		}
>  	}
>  
> @@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
>  	}
>  }
>  
> -static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
> -				 int size, enum s3c2410_dma_buffresult res)
> -{
> -	struct s3c64xx_spi_driver_data *sdd = buf_id;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&sdd->lock, flags);
> -
> -	if (res == S3C2410_RES_OK)
> -		sdd->state &= ~RXBUSY;
> -	else
> -		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
> -
> -	/* If the other done */
> -	if (!(sdd->state & TXBUSY))
> -		complete(&sdd->xfer_completion);
> -
> -	spin_unlock_irqrestore(&sdd->lock, flags);
> -}
> -
> -static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
> -				 int size, enum s3c2410_dma_buffresult res)
> -{
> -	struct s3c64xx_spi_driver_data *sdd = buf_id;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&sdd->lock, flags);
> -
> -	if (res == S3C2410_RES_OK)
> -		sdd->state &= ~TXBUSY;
> -	else
> -		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
> -
> -	/* If the other done */
> -	if (!(sdd->state & RXBUSY))
> -		complete(&sdd->xfer_completion);
> -
> -	spin_unlock_irqrestore(&sdd->lock, flags);
> -}
> -
>  #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
>  
>  static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
> @@ -697,12 +701,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
>  			if (use_dma) {
>  				if (xfer->tx_buf != NULL
>  						&& (sdd->state & TXBUSY))
> -					s3c2410_dma_ctrl(sdd->tx_dmach,
> -							S3C2410_DMAOP_FLUSH);
> +					sdd->ops->stop(sdd->tx_ch);
>  				if (xfer->rx_buf != NULL
>  						&& (sdd->state & RXBUSY))
> -					s3c2410_dma_ctrl(sdd->rx_dmach,
> -							S3C2410_DMAOP_FLUSH);
> +					sdd->ops->stop(sdd->rx_ch);
>  			}
>  
>  			goto out;
> @@ -742,24 +744,19 @@ out:
>  
>  static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
>  {
> -	if (s3c2410_dma_request(sdd->rx_dmach,
> -					&s3c64xx_spi_dma_client, NULL) < 0) {
> -		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
> -		return 0;
> -	}
> -	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
> -	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
> -					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
> -
> -	if (s3c2410_dma_request(sdd->tx_dmach,
> -					&s3c64xx_spi_dma_client, NULL) < 0) {
> -		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
> -		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
> -		return 0;
> -	}
> -	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
> -	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
> -					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
> +
> +	struct samsung_dma_info info;
> +	sdd->ops = samsung_dma_get_ops();
> +
> +	info.cap = DMA_SLAVE;
> +	info.client = &s3c64xx_spi_dma_client;
> +	info.direction = DMA_FROM_DEVICE;
> +	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
> +	info.width = sdd->cur_bpw / 8;
> +	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
> +	info.direction = DMA_TO_DEVICE;
> +	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
> +	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
>  
>  	return 1;
>  }
> @@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
>  	spin_unlock_irqrestore(&sdd->lock, flags);
>  
>  	/* Free DMA channels */
> -	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
> -	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
> +	sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client);
> +	sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client);
>  }
>  
>  static int s3c64xx_spi_transfer(struct spi_device *spi,

-- 
~Vinod Koul
Intel Corp.

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

* [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
@ 2011-07-25 11:17     ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> This patch adds to support DMA generic API to transfer raw
> SPI data. Basiclly the spi driver uses DMA generic API if
> architecture supports it. Otherwise, uses Samsung specific
> S3C-PL330 APIs.
> 
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
>  drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++-----------------------
>  1 files changed, 69 insertions(+), 72 deletions(-)
> 
> diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> index 8945e20..a4cf76a 100644
> --- a/drivers/spi/spi_s3c64xx.c
> +++ b/drivers/spi/spi_s3c64xx.c
> @@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
>  	unsigned                        state;
>  	unsigned                        cur_mode, cur_bpw;
>  	unsigned                        cur_speed;
> +	unsigned			rx_ch;
> +	unsigned			tx_ch;
> +	struct samsung_dma_ops		*ops;
>  };
>  
>  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
> @@ -227,6 +230,38 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
>  	writel(val, regs + S3C64XX_SPI_CH_CFG);
>  }
>  
> +static void s3c64xx_spi_dma_rxcb(void *data)
> +{
> +	struct s3c64xx_spi_driver_data *sdd
> +		= (struct s3c64xx_spi_driver_data *)data;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&sdd->lock, flags);
> +
> +	sdd->state &= ~RXBUSY;
> +	/* If the other done */
> +	if (!(sdd->state & TXBUSY))
> +		complete(&sdd->xfer_completion);
> +
> +	spin_unlock_irqrestore(&sdd->lock, flags);
> +}
> +
> +static void s3c64xx_spi_dma_txcb(void *data)
> +{
> +	struct s3c64xx_spi_driver_data *sdd
> +		= (struct s3c64xx_spi_driver_data *)data;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&sdd->lock, flags);
> +
> +	sdd->state &= ~TXBUSY;
> +	/* If the other done */
> +	if (!(sdd->state & RXBUSY))
> +		complete(&sdd->xfer_completion);
> +
> +	spin_unlock_irqrestore(&sdd->lock, flags);
> +}
I don't see much diff in these two functions and you should be able to
use a generic one which takes care of both TX and RX, does your callback
data know if the channel is for TX or RX? If not then a helper to do
above should take care well and making code simpler

> +
>  static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
>  				struct spi_device *spi,
>  				struct spi_transfer *xfer, int dma_mode)
> @@ -234,6 +269,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
>  	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
>  	void __iomem *regs = sdd->regs;
>  	u32 modecfg, chcfg;
> +	struct samsung_dma_prep_info info;
>  
>  	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
>  	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
> @@ -259,10 +295,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
>  		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
>  		if (dma_mode) {
>  			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
> -			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
> -			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
> -						xfer->tx_dma, xfer->len);
> -			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
> +			info.cap = DMA_SLAVE;
> +			info.direction = DMA_TO_DEVICE;
> +			info.buf = xfer->tx_dma;
> +			info.len = xfer->len;
> +			info.fp = s3c64xx_spi_dma_txcb;
> +			info.fp_param = sdd;
> +			sdd->ops->prepare(sdd->tx_ch, &info);
> +			sdd->ops->trigger(sdd->tx_ch);
>  		} else {
>  			switch (sdd->cur_bpw) {
>  			case 32:
> @@ -294,10 +334,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
>  			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
>  					| S3C64XX_SPI_PACKET_CNT_EN,
>  					regs + S3C64XX_SPI_PACKET_CNT);
> -			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
> -			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
> -						xfer->rx_dma, xfer->len);
> -			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
> +			info.cap = DMA_SLAVE;
> +			info.direction = DMA_FROM_DEVICE;
> +			info.buf = xfer->rx_dma;
> +			info.len = xfer->len;
> +			info.fp = s3c64xx_spi_dma_rxcb;
> +			info.fp_param = sdd;
> +			sdd->ops->prepare(sdd->rx_ch, &info);
> +			sdd->ops->trigger(sdd->rx_ch);
>  		}
>  	}
>  
> @@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
>  	}
>  }
>  
> -static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
> -				 int size, enum s3c2410_dma_buffresult res)
> -{
> -	struct s3c64xx_spi_driver_data *sdd = buf_id;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&sdd->lock, flags);
> -
> -	if (res == S3C2410_RES_OK)
> -		sdd->state &= ~RXBUSY;
> -	else
> -		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
> -
> -	/* If the other done */
> -	if (!(sdd->state & TXBUSY))
> -		complete(&sdd->xfer_completion);
> -
> -	spin_unlock_irqrestore(&sdd->lock, flags);
> -}
> -
> -static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
> -				 int size, enum s3c2410_dma_buffresult res)
> -{
> -	struct s3c64xx_spi_driver_data *sdd = buf_id;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&sdd->lock, flags);
> -
> -	if (res == S3C2410_RES_OK)
> -		sdd->state &= ~TXBUSY;
> -	else
> -		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
> -
> -	/* If the other done */
> -	if (!(sdd->state & RXBUSY))
> -		complete(&sdd->xfer_completion);
> -
> -	spin_unlock_irqrestore(&sdd->lock, flags);
> -}
> -
>  #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
>  
>  static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
> @@ -697,12 +701,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
>  			if (use_dma) {
>  				if (xfer->tx_buf != NULL
>  						&& (sdd->state & TXBUSY))
> -					s3c2410_dma_ctrl(sdd->tx_dmach,
> -							S3C2410_DMAOP_FLUSH);
> +					sdd->ops->stop(sdd->tx_ch);
>  				if (xfer->rx_buf != NULL
>  						&& (sdd->state & RXBUSY))
> -					s3c2410_dma_ctrl(sdd->rx_dmach,
> -							S3C2410_DMAOP_FLUSH);
> +					sdd->ops->stop(sdd->rx_ch);
>  			}
>  
>  			goto out;
> @@ -742,24 +744,19 @@ out:
>  
>  static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
>  {
> -	if (s3c2410_dma_request(sdd->rx_dmach,
> -					&s3c64xx_spi_dma_client, NULL) < 0) {
> -		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
> -		return 0;
> -	}
> -	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
> -	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
> -					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
> -
> -	if (s3c2410_dma_request(sdd->tx_dmach,
> -					&s3c64xx_spi_dma_client, NULL) < 0) {
> -		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
> -		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
> -		return 0;
> -	}
> -	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
> -	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
> -					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
> +
> +	struct samsung_dma_info info;
> +	sdd->ops = samsung_dma_get_ops();
> +
> +	info.cap = DMA_SLAVE;
> +	info.client = &s3c64xx_spi_dma_client;
> +	info.direction = DMA_FROM_DEVICE;
> +	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
> +	info.width = sdd->cur_bpw / 8;
> +	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
> +	info.direction = DMA_TO_DEVICE;
> +	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
> +	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
>  
>  	return 1;
>  }
> @@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
>  	spin_unlock_irqrestore(&sdd->lock, flags);
>  
>  	/* Free DMA channels */
> -	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
> -	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
> +	sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client);
> +	sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client);
>  }
>  
>  static int s3c64xx_spi_transfer(struct spi_device *spi,

-- 
~Vinod Koul
Intel Corp.

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

* Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25 11:24     ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 11:24 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Kukjin Kim, Grant Likely, Mark Brown

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> This patch adds DMA_CYCLIC capability that is used for audio driver.
> DMA driver with DMA_CYCLIC capability reuses the dma requests that
> were submitted through tx_submit().
>
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> ---
>  drivers/dma/pl330.c |  111 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 111 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 880f010..121c75a 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -69,6 +69,11 @@ struct dma_pl330_chan {
>         * NULL if the channel is available to be acquired.
>         */
>        void *pl330_chid;
> +
> +       /* taks for cyclic capability */
> +       struct tasklet_struct *cyclic_task;
> +
> +       bool cyclic;
>  };
We already have a tasklet_struct member here.
This 'cyclic' flag can indicate if we are doing cyclic or serial
transfers. So, this cyclic_task seems unnecessary.

> +static void pl330_tasklet_cyclic(unsigned long data)
> +{
> +       struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> +       struct dma_pl330_desc *desc, *_dt;
> +       unsigned long flags;
> +       LIST_HEAD(list);
> +
> +       spin_lock_irqsave(&pch->lock, flags);
> +
> +       /* Pick up ripe tomatoes */
> +       list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
> +               if (desc->status == DONE) {
> +                       dma_async_tx_callback callback;
> +
> +                       list_move_tail(&desc->node, &pch->work_list);
> +                       pch->completed = desc->txd.cookie;
> +
> +                       desc->status = PREP;
> +
> +                       /* Try to submit a req imm.
> +                       next to the last completed cookie */
> +                       fill_queue(pch);
> +
> +                       /* Make sure the PL330 Channel thread is active */
> +                       pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START);
> +
> +                       callback = desc->txd.callback;
> +                       if (callback)
> +                               callback(desc->txd.callback_param);
> +
> +               }
> +
> +       spin_unlock_irqrestore(&pch->lock, flags);
> +}
Please merge this with pl330_tasklet and use 'cyclic' flag to differentiate.

> @@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
>
>        spin_unlock_irqrestore(&pch->lock, flags);
>
> +       if (pch->cyclic_task)
> +               tasklet_schedule(pch->cyclic_task);
> +       else
>        tasklet_schedule(&pch->task);
A tab here please, and check for 'cyclic' flag.


> @@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
>        pl330_release_channel(pch->pl330_chid);
>        pch->pl330_chid = NULL;
>
> +       if (pch->cyclic) {
> +               pch->cyclic = false;
> +               list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
> +               if (pch->cyclic_task) {
> +                       tasklet_kill(pch->cyclic_task);
> +                       pch->cyclic_task = NULL;
> +               }
> +       }
> +
>        spin_unlock_irqrestore(&pch->lock, flags);
>  }
To be explicit, please initialize 'cyclic' flag to false in
pl330_alloc_chan_resources

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 11:24     ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 11:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> This patch adds DMA_CYCLIC capability that is used for audio driver.
> DMA driver with DMA_CYCLIC capability reuses the dma requests that
> were submitted through tx_submit().
>
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> ---
> ?drivers/dma/pl330.c | ?111 +++++++++++++++++++++++++++++++++++++++++++++++++++
> ?1 files changed, 111 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 880f010..121c75a 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -69,6 +69,11 @@ struct dma_pl330_chan {
> ? ? ? ? * NULL if the channel is available to be acquired.
> ? ? ? ? */
> ? ? ? ?void *pl330_chid;
> +
> + ? ? ? /* taks for cyclic capability */
> + ? ? ? struct tasklet_struct *cyclic_task;
> +
> + ? ? ? bool cyclic;
> ?};
We already have a tasklet_struct member here.
This 'cyclic' flag can indicate if we are doing cyclic or serial
transfers. So, this cyclic_task seems unnecessary.

> +static void pl330_tasklet_cyclic(unsigned long data)
> +{
> + ? ? ? struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> + ? ? ? struct dma_pl330_desc *desc, *_dt;
> + ? ? ? unsigned long flags;
> + ? ? ? LIST_HEAD(list);
> +
> + ? ? ? spin_lock_irqsave(&pch->lock, flags);
> +
> + ? ? ? /* Pick up ripe tomatoes */
> + ? ? ? list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
> + ? ? ? ? ? ? ? if (desc->status == DONE) {
> + ? ? ? ? ? ? ? ? ? ? ? dma_async_tx_callback callback;
> +
> + ? ? ? ? ? ? ? ? ? ? ? list_move_tail(&desc->node, &pch->work_list);
> + ? ? ? ? ? ? ? ? ? ? ? pch->completed = desc->txd.cookie;
> +
> + ? ? ? ? ? ? ? ? ? ? ? desc->status = PREP;
> +
> + ? ? ? ? ? ? ? ? ? ? ? /* Try to submit a req imm.
> + ? ? ? ? ? ? ? ? ? ? ? next to the last completed cookie */
> + ? ? ? ? ? ? ? ? ? ? ? fill_queue(pch);
> +
> + ? ? ? ? ? ? ? ? ? ? ? /* Make sure the PL330 Channel thread is active */
> + ? ? ? ? ? ? ? ? ? ? ? pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START);
> +
> + ? ? ? ? ? ? ? ? ? ? ? callback = desc->txd.callback;
> + ? ? ? ? ? ? ? ? ? ? ? if (callback)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? callback(desc->txd.callback_param);
> +
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? spin_unlock_irqrestore(&pch->lock, flags);
> +}
Please merge this with pl330_tasklet and use 'cyclic' flag to differentiate.

> @@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
>
> ? ? ? ?spin_unlock_irqrestore(&pch->lock, flags);
>
> + ? ? ? if (pch->cyclic_task)
> + ? ? ? ? ? ? ? tasklet_schedule(pch->cyclic_task);
> + ? ? ? else
> ? ? ? ?tasklet_schedule(&pch->task);
A tab here please, and check for 'cyclic' flag.


> @@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
> ? ? ? ?pl330_release_channel(pch->pl330_chid);
> ? ? ? ?pch->pl330_chid = NULL;
>
> + ? ? ? if (pch->cyclic) {
> + ? ? ? ? ? ? ? pch->cyclic = false;
> + ? ? ? ? ? ? ? list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
> + ? ? ? ? ? ? ? if (pch->cyclic_task) {
> + ? ? ? ? ? ? ? ? ? ? ? tasklet_kill(pch->cyclic_task);
> + ? ? ? ? ? ? ? ? ? ? ? pch->cyclic_task = NULL;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +
> ? ? ? ?spin_unlock_irqrestore(&pch->lock, flags);
> ?}
To be explicit, please initialize 'cyclic' flag to false in
pl330_alloc_chan_resources

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

* Re: [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25 11:31     ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 11:31 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Kukjin Kim, Grant Likely, Mark Brown

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
> index 4d79519..cb170a6 100644
> --- a/arch/arm/plat-samsung/Kconfig
> +++ b/arch/arm/plat-samsung/Kconfig
> @@ -300,6 +300,14 @@ config S3C_PL330_DMA
>        help
>          S3C DMA API Driver for PL330 DMAC.
>
> +config DMADEV_PL330
> +       bool
> +       select DMADEVICES
> +       select PL330_DMA
> +       select ARM_AMBA
> +       help
> +         Use DMA device engine for PL330 DMAC.
> +
If this is for the 'wrapper' dma driver, please use S3C or similar prefix.

> diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
> similarity index 84%
> rename from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
> rename to arch/arm/plat-samsung/include/plat/dma-pl330.h
> index 8107442..c402719 100644
> --- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
> +++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
> @@ -8,19 +8,18 @@
>  * (at your option) any later version.
>  */
>
> -#ifndef        __S3C_DMA_PL330_H_
> -#define        __S3C_DMA_PL330_H_
> -
> -#define S3C2410_DMAF_AUTOSTART         (1 << 0)
> -#define S3C2410_DMAF_CIRCULAR          (1 << 1)
> +#ifndef __DMA_PL330_H_
> +#define __DMA_PL330_H_ __FILE__
To respect namespaces, please preserve S3C prefix because
the file is Samsung specific.


> @@ -84,6 +83,14 @@ enum dma_ch {
>        DMACH_SLIMBUS4_TX,
>        DMACH_SLIMBUS5_RX,
>        DMACH_SLIMBUS5_TX,
> +       DMACH_MTOM_0,
> +       DMACH_MTOM_1,
> +       DMACH_MTOM_2,
> +       DMACH_MTOM_3,
> +       DMACH_MTOM_4,
> +       DMACH_MTOM_5,
> +       DMACH_MTOM_6,
> +       DMACH_MTOM_7,
>        /* END Marker, also used to denote a reserved channel */
>        DMACH_MAX,
>  };

Naming mem->mem channels should be unnecessary.
Not sure what you have in mind.

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

* [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
@ 2011-07-25 11:31     ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 11:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
> index 4d79519..cb170a6 100644
> --- a/arch/arm/plat-samsung/Kconfig
> +++ b/arch/arm/plat-samsung/Kconfig
> @@ -300,6 +300,14 @@ config S3C_PL330_DMA
> ? ? ? ?help
> ? ? ? ? ?S3C DMA API Driver for PL330 DMAC.
>
> +config DMADEV_PL330
> + ? ? ? bool
> + ? ? ? select DMADEVICES
> + ? ? ? select PL330_DMA
> + ? ? ? select ARM_AMBA
> + ? ? ? help
> + ? ? ? ? Use DMA device engine for PL330 DMAC.
> +
If this is for the 'wrapper' dma driver, please use S3C or similar prefix.

> diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
> similarity index 84%
> rename from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
> rename to arch/arm/plat-samsung/include/plat/dma-pl330.h
> index 8107442..c402719 100644
> --- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
> +++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
> @@ -8,19 +8,18 @@
> ?* (at your option) any later version.
> ?*/
>
> -#ifndef ? ? ? ?__S3C_DMA_PL330_H_
> -#define ? ? ? ?__S3C_DMA_PL330_H_
> -
> -#define S3C2410_DMAF_AUTOSTART ? ? ? ? (1 << 0)
> -#define S3C2410_DMAF_CIRCULAR ? ? ? ? ?(1 << 1)
> +#ifndef __DMA_PL330_H_
> +#define __DMA_PL330_H_ __FILE__
To respect namespaces, please preserve S3C prefix because
the file is Samsung specific.


> @@ -84,6 +83,14 @@ enum dma_ch {
> ? ? ? ?DMACH_SLIMBUS4_TX,
> ? ? ? ?DMACH_SLIMBUS5_RX,
> ? ? ? ?DMACH_SLIMBUS5_TX,
> + ? ? ? DMACH_MTOM_0,
> + ? ? ? DMACH_MTOM_1,
> + ? ? ? DMACH_MTOM_2,
> + ? ? ? DMACH_MTOM_3,
> + ? ? ? DMACH_MTOM_4,
> + ? ? ? DMACH_MTOM_5,
> + ? ? ? DMACH_MTOM_6,
> + ? ? ? DMACH_MTOM_7,
> ? ? ? ?/* END Marker, also used to denote a reserved channel */
> ? ? ? ?DMACH_MAX,
> ?};

Naming mem->mem channels should be unnecessary.
Not sure what you have in mind.

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

* Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 11:01               ` Vinod Koul
@ 2011-07-25 11:39                 ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25 11:39 UTC (permalink / raw)
  To: Vinod Koul
  Cc: vinod.koul, Boojin Kim, 'Kukjin Kim',
	'Jassi Brar', 'Grant Likely',
	linux-samsung-soc, 'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Mon, Jul 25, 2011 at 04:31:57PM +0530, Vinod Koul wrote:
> > I know that very well thank you.  Please look at my previous post in the
> > previous round of patches, and the response from Boojin Kim to see why
> > I used this as an *EXAMPLE* to get this fixed.
> Russell,
> Sorry that was not intended for you but for the author of patch Boojin
> Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it
> as going thru this patch made it clear that they haven't.

That wasn't obvious because of the To: and the use of 'you' in your reply.

In any case, let's fix up the documentation to be a little more complete
and expansive about these conditions, and improve its formatting so it's
easier to read.

A few points:

1. This really should describe the dma_slave_config structure in detail
   (or refer to the documentation in dmaengine.h) especially describing
   what is mandatory there.

2. Note the filter function thing - I think this should be mandatory
   for slave and cyclic channels.  These typically have a DMA request
   signal associated with each channel, and so 'any random channel' isn't
   really acceptable like it is for the async_tx APIs.

3. I think this should specify that dmaengine_slave_config() should be
   specified as mandatory after obtaining the DMA engine channel.

Any comments on this before I prepare this as a proper patch?

diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
index 5a0cb1e..8ba8d3c 100644
--- a/Documentation/dmaengine.txt
+++ b/Documentation/dmaengine.txt
@@ -10,87 +10,163 @@
 Below is a guide to device driver writers on how to use the Slave-DMA API of the
 DMA Engine. This is applicable only for slave DMA usage only.
 
-The slave DMA usage consists of following steps
+The slave DMA usage consists of following steps:
 1. Allocate a DMA slave channel
 2. Set slave and controller specific parameters
 3. Get a descriptor for transaction
 4. Submit the transaction and wait for callback notification
+5. Issue pending requests
 
 1. Allocate a DMA slave channel
-Channel allocation is slightly different in the slave DMA context, client
-drivers typically need a channel from a particular DMA controller only and even
-in some cases a specific channel is desired. To request a channel
-dma_request_channel() API is used.
-
-Interface:
-struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
-		dma_filter_fn filter_fn,
-		void *filter_param);
-where dma_filter_fn is defined as:
-typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
-
-When the optional 'filter_fn' parameter is set to NULL dma_request_channel
-simply returns the first channel that satisfies the capability mask.  Otherwise,
-when the mask parameter is insufficient for specifying the necessary channel,
-the filter_fn routine can be used to disposition the available channels in the
-system. The filter_fn routine is called once for each free channel in the
-system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
-that channel to be the return value from dma_request_channel.  A channel
-allocated via this interface is exclusive to the caller, until
-dma_release_channel() is called.
+
+   Channel allocation is slightly different in the slave DMA context,
+   client drivers typically need a channel from a particular DMA
+   controller only and even in some cases a specific channel is desired.
+   To request a channel dma_request_channel() API is used.
+
+   Interface:
+	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+			dma_filter_fn filter_fn,
+			void *filter_param);
+   where dma_filter_fn is defined as:
+	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
+
+   The 'filter_fn' parameter is optional, but highly recommended for
+   slave and cyclic channels as they typically need to obtain a specific
+   DMA channel.
+
+   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
+   simply returns the first channel that satisfies the capability mask.
+
+   Otherwise, the 'filter_fn' routine will be called once for each free
+   channel which has a capability in 'mask'.  'filter_fn' is expected to
+   return 'true' when the desired DMA channel is found.
+
+   A channel allocated via this interface is exclusive to the caller,
+   until dma_release_channel() is called.
 
 2. Set slave and controller specific parameters
-Next step is always to pass some specific information to the DMA driver. Most of
-the generic information which a slave DMA can use is in struct dma_slave_config.
-It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
-burst lengths etc. If some DMA controllers have more parameters to be sent then
-they should try to embed struct dma_slave_config in their controller specific
-structure. That gives flexibility to client to pass more parameters, if
-required.
-
-Interface:
-int dmaengine_slave_config(struct dma_chan *chan,
-					  struct dma_slave_config *config)
+
+   Next step is always to pass some specific information to the DMA
+   driver.  Most of the generic information which a slave DMA can use
+   is in struct dma_slave_config.  This allows the clients to specify
+   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
+   for the peripheral.
+
+   If some DMA controllers have more parameters to be sent then they
+   should try to embed struct dma_slave_config in their controller
+   specific structure. That gives flexibility to client to pass more
+   parameters, if required.
+
+   Interface:
+	int dmaengine_slave_config(struct dma_chan *chan,
+				  struct dma_slave_config *config)
 
 3. Get a descriptor for transaction
-For slave usage the various modes of slave transfers supported by the
-DMA-engine are:
-slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
-dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
+
+   For slave usage the various modes of slave transfers supported by the
+   DMA-engine are:
+
+   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
+   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
 		  operation is explicitly stopped.
-The non NULL return of this transfer API represents a "descriptor" for the given
-transaction.
 
-Interface:
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
+   A non-NULL return of this transfer API represents a "descriptor" for
+   the given transaction.
+
+   Interface:
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
 		struct dma_chan *chan,
 		struct scatterlist *dst_sg, unsigned int dst_nents,
 		struct scatterlist *src_sg, unsigned int src_nents,
 		unsigned long flags);
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_data_direction direction);
 
+   Once a descriptor has been obtained, the callback information can be
+   added and must then be submitted.  Some DMA engine drivers may hold a
+   spinlock between a successful preparation and submission so it is
+   important that these two operations are closely paired.
+
+   Note:
+	Although the async_tx API specifies that completion callback
+	routines cannot submit any new operations, this is not the
+	case for slave/cyclic DMA.
+
+	For slave DMA, the subsequent transaction may not be available
+	for submission prior to callback function being invoked, so
+	slave DMA callbacks are permitted to prepare and submit a new
+	transaction.
+
+	For cyclic DMA, a callback function may wish to terminate the
+	DMA via dmaengine_terminate_all().
+
+	Therefore, it is important that DMA engine drivers drop any
+	locks before calling the callback function which may cause a
+	deadlock.
+
+	Note that callbacks will always be invoked from the DMA
+	engines tasklet, never from interrupt context.
+
 4. Submit the transaction and wait for callback notification
-To schedule the transaction to be scheduled by dma device, the "descriptor"
-returned in above (3) needs to be submitted.
-To tell the dma driver that a transaction is ready to be serviced, the
-descriptor->submit() callback needs to be invoked. This chains the descriptor to
-the pending queue.
-The transactions in the pending queue can be activated by calling the
-issue_pending API. If channel is idle then the first transaction in queue is
-started and subsequent ones queued up.
-On completion of the DMA operation the next in queue is submitted and a tasklet
-triggered. The tasklet would then call the client driver completion callback
-routine for notification, if set.
-Interface:
-void dma_async_issue_pending(struct dma_chan *chan);
-
-==============================================================================
-
-Additional usage notes for dma driver writers
-1/ Although DMA engine specifies that completion callback routines cannot submit
-any new operations, but typically for slave DMA subsequent transaction may not
-be available for submit prior to callback routine being called. This requirement
-is not a requirement for DMA-slave devices. But they should take care to drop
-the spin-lock they might be holding before calling the callback routine
+
+   Once the descriptor has been prepared and the callback information
+   added, it must be placed on the DMA engine drivers pending queue.
+
+   Interface:
+	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
+
+   This returns a cookie can be used to check the progress of DMA engine
+   activity via other DMA engine calls not covered in this document.
+
+   dmaengine_submit() will not start the DMA operation, it merely adds
+   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
+
+5. Issue pending DMA requests
+
+   The transactions in the pending queue can be activated by calling the
+   issue_pending API. If channel is idle then the first transaction in
+   queue is started and subsequent ones queued up.
+
+   On completion of each DMA operation, the next in queue is started and
+   a tasklet triggered. The tasklet will then call the client driver
+   completion callback routine for notification, if set.
+
+   Interface:
+	void dma_async_issue_pending(struct dma_chan *chan);
+
+Further APIs:
+
+1. int dmaengine_terminate_all(struct dma_chan *chan)
+
+   This causes all activity for the DMA channel to be stopped, and may
+   discard data in the DMA FIFO which hasn't been fully transferred.
+   No callback functions will be called for any incomplete transfers.
+
+2. int dmaengine_pause(struct dma_chan *chan)
+
+   This pauses activity on the DMA channel without data loss.
+
+3. int dmaengine_resume(struct dma_chan *chan)
+
+   Resume a previously paused DMA channel.  It is invalid to resume a
+   channel which is not currently paused.
+
+4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+
+   This can be used to check the status of the channel.  Please see
+   the documentation in include/linux/dmaengine.h for a more complete
+   description of this API.
+
+   This can be used in conjunction with dma_async_is_complete() and
+   the cookie returned from 'descriptor->submit()' to check for
+   completion of a specific DMA transaction.
+
+   Note:
+	Not all DMA engine drivers can return reliable information for
+	a running DMA channel.  It is recommended that DMA engine users
+	pause or stop (via dmaengine_terminate_all) the channel before
+	using this API.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 11:39                 ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-25 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 04:31:57PM +0530, Vinod Koul wrote:
> > I know that very well thank you.  Please look at my previous post in the
> > previous round of patches, and the response from Boojin Kim to see why
> > I used this as an *EXAMPLE* to get this fixed.
> Russell,
> Sorry that was not intended for you but for the author of patch Boojin
> Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it
> as going thru this patch made it clear that they haven't.

That wasn't obvious because of the To: and the use of 'you' in your reply.

In any case, let's fix up the documentation to be a little more complete
and expansive about these conditions, and improve its formatting so it's
easier to read.

A few points:

1. This really should describe the dma_slave_config structure in detail
   (or refer to the documentation in dmaengine.h) especially describing
   what is mandatory there.

2. Note the filter function thing - I think this should be mandatory
   for slave and cyclic channels.  These typically have a DMA request
   signal associated with each channel, and so 'any random channel' isn't
   really acceptable like it is for the async_tx APIs.

3. I think this should specify that dmaengine_slave_config() should be
   specified as mandatory after obtaining the DMA engine channel.

Any comments on this before I prepare this as a proper patch?

diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
index 5a0cb1e..8ba8d3c 100644
--- a/Documentation/dmaengine.txt
+++ b/Documentation/dmaengine.txt
@@ -10,87 +10,163 @@
 Below is a guide to device driver writers on how to use the Slave-DMA API of the
 DMA Engine. This is applicable only for slave DMA usage only.
 
-The slave DMA usage consists of following steps
+The slave DMA usage consists of following steps:
 1. Allocate a DMA slave channel
 2. Set slave and controller specific parameters
 3. Get a descriptor for transaction
 4. Submit the transaction and wait for callback notification
+5. Issue pending requests
 
 1. Allocate a DMA slave channel
-Channel allocation is slightly different in the slave DMA context, client
-drivers typically need a channel from a particular DMA controller only and even
-in some cases a specific channel is desired. To request a channel
-dma_request_channel() API is used.
-
-Interface:
-struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
-		dma_filter_fn filter_fn,
-		void *filter_param);
-where dma_filter_fn is defined as:
-typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
-
-When the optional 'filter_fn' parameter is set to NULL dma_request_channel
-simply returns the first channel that satisfies the capability mask.  Otherwise,
-when the mask parameter is insufficient for specifying the necessary channel,
-the filter_fn routine can be used to disposition the available channels in the
-system. The filter_fn routine is called once for each free channel in the
-system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
-that channel to be the return value from dma_request_channel.  A channel
-allocated via this interface is exclusive to the caller, until
-dma_release_channel() is called.
+
+   Channel allocation is slightly different in the slave DMA context,
+   client drivers typically need a channel from a particular DMA
+   controller only and even in some cases a specific channel is desired.
+   To request a channel dma_request_channel() API is used.
+
+   Interface:
+	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+			dma_filter_fn filter_fn,
+			void *filter_param);
+   where dma_filter_fn is defined as:
+	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
+
+   The 'filter_fn' parameter is optional, but highly recommended for
+   slave and cyclic channels as they typically need to obtain a specific
+   DMA channel.
+
+   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
+   simply returns the first channel that satisfies the capability mask.
+
+   Otherwise, the 'filter_fn' routine will be called once for each free
+   channel which has a capability in 'mask'.  'filter_fn' is expected to
+   return 'true' when the desired DMA channel is found.
+
+   A channel allocated via this interface is exclusive to the caller,
+   until dma_release_channel() is called.
 
 2. Set slave and controller specific parameters
-Next step is always to pass some specific information to the DMA driver. Most of
-the generic information which a slave DMA can use is in struct dma_slave_config.
-It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
-burst lengths etc. If some DMA controllers have more parameters to be sent then
-they should try to embed struct dma_slave_config in their controller specific
-structure. That gives flexibility to client to pass more parameters, if
-required.
-
-Interface:
-int dmaengine_slave_config(struct dma_chan *chan,
-					  struct dma_slave_config *config)
+
+   Next step is always to pass some specific information to the DMA
+   driver.  Most of the generic information which a slave DMA can use
+   is in struct dma_slave_config.  This allows the clients to specify
+   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
+   for the peripheral.
+
+   If some DMA controllers have more parameters to be sent then they
+   should try to embed struct dma_slave_config in their controller
+   specific structure. That gives flexibility to client to pass more
+   parameters, if required.
+
+   Interface:
+	int dmaengine_slave_config(struct dma_chan *chan,
+				  struct dma_slave_config *config)
 
 3. Get a descriptor for transaction
-For slave usage the various modes of slave transfers supported by the
-DMA-engine are:
-slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
-dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
+
+   For slave usage the various modes of slave transfers supported by the
+   DMA-engine are:
+
+   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
+   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
 		  operation is explicitly stopped.
-The non NULL return of this transfer API represents a "descriptor" for the given
-transaction.
 
-Interface:
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
+   A non-NULL return of this transfer API represents a "descriptor" for
+   the given transaction.
+
+   Interface:
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
 		struct dma_chan *chan,
 		struct scatterlist *dst_sg, unsigned int dst_nents,
 		struct scatterlist *src_sg, unsigned int src_nents,
 		unsigned long flags);
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_data_direction direction);
 
+   Once a descriptor has been obtained, the callback information can be
+   added and must then be submitted.  Some DMA engine drivers may hold a
+   spinlock between a successful preparation and submission so it is
+   important that these two operations are closely paired.
+
+   Note:
+	Although the async_tx API specifies that completion callback
+	routines cannot submit any new operations, this is not the
+	case for slave/cyclic DMA.
+
+	For slave DMA, the subsequent transaction may not be available
+	for submission prior to callback function being invoked, so
+	slave DMA callbacks are permitted to prepare and submit a new
+	transaction.
+
+	For cyclic DMA, a callback function may wish to terminate the
+	DMA via dmaengine_terminate_all().
+
+	Therefore, it is important that DMA engine drivers drop any
+	locks before calling the callback function which may cause a
+	deadlock.
+
+	Note that callbacks will always be invoked from the DMA
+	engines tasklet, never from interrupt context.
+
 4. Submit the transaction and wait for callback notification
-To schedule the transaction to be scheduled by dma device, the "descriptor"
-returned in above (3) needs to be submitted.
-To tell the dma driver that a transaction is ready to be serviced, the
-descriptor->submit() callback needs to be invoked. This chains the descriptor to
-the pending queue.
-The transactions in the pending queue can be activated by calling the
-issue_pending API. If channel is idle then the first transaction in queue is
-started and subsequent ones queued up.
-On completion of the DMA operation the next in queue is submitted and a tasklet
-triggered. The tasklet would then call the client driver completion callback
-routine for notification, if set.
-Interface:
-void dma_async_issue_pending(struct dma_chan *chan);
-
-==============================================================================
-
-Additional usage notes for dma driver writers
-1/ Although DMA engine specifies that completion callback routines cannot submit
-any new operations, but typically for slave DMA subsequent transaction may not
-be available for submit prior to callback routine being called. This requirement
-is not a requirement for DMA-slave devices. But they should take care to drop
-the spin-lock they might be holding before calling the callback routine
+
+   Once the descriptor has been prepared and the callback information
+   added, it must be placed on the DMA engine drivers pending queue.
+
+   Interface:
+	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
+
+   This returns a cookie can be used to check the progress of DMA engine
+   activity via other DMA engine calls not covered in this document.
+
+   dmaengine_submit() will not start the DMA operation, it merely adds
+   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
+
+5. Issue pending DMA requests
+
+   The transactions in the pending queue can be activated by calling the
+   issue_pending API. If channel is idle then the first transaction in
+   queue is started and subsequent ones queued up.
+
+   On completion of each DMA operation, the next in queue is started and
+   a tasklet triggered. The tasklet will then call the client driver
+   completion callback routine for notification, if set.
+
+   Interface:
+	void dma_async_issue_pending(struct dma_chan *chan);
+
+Further APIs:
+
+1. int dmaengine_terminate_all(struct dma_chan *chan)
+
+   This causes all activity for the DMA channel to be stopped, and may
+   discard data in the DMA FIFO which hasn't been fully transferred.
+   No callback functions will be called for any incomplete transfers.
+
+2. int dmaengine_pause(struct dma_chan *chan)
+
+   This pauses activity on the DMA channel without data loss.
+
+3. int dmaengine_resume(struct dma_chan *chan)
+
+   Resume a previously paused DMA channel.  It is invalid to resume a
+   channel which is not currently paused.
+
+4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+
+   This can be used to check the status of the channel.  Please see
+   the documentation in include/linux/dmaengine.h for a more complete
+   description of this API.
+
+   This can be used in conjunction with dma_async_is_complete() and
+   the cookie returned from 'descriptor->submit()' to check for
+   completion of a specific DMA transaction.
+
+   Note:
+	Not all DMA engine drivers can return reliable information for
+	a running DMA channel.  It is recommended that DMA engine users
+	pause or stop (via dmaengine_terminate_all) the channel before
+	using this API.

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

* Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25 11:51     ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 11:51 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Kukjin Kim, Grant Likely, Mark Brown

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> +
> +static bool pl330_filter(struct dma_chan *chan, void *param)
> +{
> +       struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private;
> +       unsigned dma_ch = (unsigned)param;
> +
> +       if (peri->peri_id != dma_ch)
> +               return false;
> +
> +       return true;
> +}
This is what I meant... if we keep chan_id for paltform assigned IDs,
these filter functions could simply become

static bool pl330_filter(struct dma_chan *chan, void *param)
{
        return chan->chan_id == param
}

And ideally in the long run, we could just drop the filter callback
and add expected channel ID to the request_channel call.



> +
> +static inline int s3c_dma_trigger(unsigned ch)
> +{
> +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
> +}
> +
> +static inline int s3c_dma_started(unsigned ch)
> +{
> +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
> +}
> +
> +static inline int s3c_dma_flush(unsigned ch)
> +{
> +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
> +}
> +
> +static inline int s3c_dma_stop(unsigned ch)
> +{
> +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
> +}
> +
> +static struct samsung_dma_ops s3c_dma_ops = {
> +       .request        = s3c_dma_request,
> +       .release        = s3c_dma_release,
> +       .prepare        = s3c_dma_prepare,
> +       .trigger        = s3c_dma_trigger,
> +       .started        = s3c_dma_started,
> +       .flush          = s3c_dma_flush,
> +       .stop           = s3c_dma_stop,

These last 4 should be gnereallized into one callback with OP argument.

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-25 11:51     ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 11:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> +
> +static bool pl330_filter(struct dma_chan *chan, void *param)
> +{
> + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private;
> + ? ? ? unsigned dma_ch = (unsigned)param;
> +
> + ? ? ? if (peri->peri_id != dma_ch)
> + ? ? ? ? ? ? ? return false;
> +
> + ? ? ? return true;
> +}
This is what I meant... if we keep chan_id for paltform assigned IDs,
these filter functions could simply become

static bool pl330_filter(struct dma_chan *chan, void *param)
{
        return chan->chan_id == param
}

And ideally in the long run, we could just drop the filter callback
and add expected channel ID to the request_channel call.



> +
> +static inline int s3c_dma_trigger(unsigned ch)
> +{
> + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
> +}
> +
> +static inline int s3c_dma_started(unsigned ch)
> +{
> + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
> +}
> +
> +static inline int s3c_dma_flush(unsigned ch)
> +{
> + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
> +}
> +
> +static inline int s3c_dma_stop(unsigned ch)
> +{
> + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
> +}
> +
> +static struct samsung_dma_ops s3c_dma_ops = {
> + ? ? ? .request ? ? ? ?= s3c_dma_request,
> + ? ? ? .release ? ? ? ?= s3c_dma_release,
> + ? ? ? .prepare ? ? ? ?= s3c_dma_prepare,
> + ? ? ? .trigger ? ? ? ?= s3c_dma_trigger,
> + ? ? ? .started ? ? ? ?= s3c_dma_started,
> + ? ? ? .flush ? ? ? ? ?= s3c_dma_flush,
> + ? ? ? .stop ? ? ? ? ? = s3c_dma_stop,

These last 4 should be gnereallized into one callback with OP argument.

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

* Re: [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25 11:59     ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 11:59 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Kukjin Kim, Grant Likely, Mark Brown

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
> index 564bb53..e1c00cf 100644
> --- a/arch/arm/mach-exynos4/dma.c
> +++ b/arch/arm/mach-exynos4/dma.c
> @@ -21,151 +21,250 @@
>  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>  */
>
> -#include <linux/platform_device.h>
>  #include <linux/dma-mapping.h>
> +#include <linux/amba/bus.h>
> +#include <linux/amba/pl330.h>
>
> +#include <asm/irq.h>
>  #include <plat/devs.h>
>  #include <plat/irqs.h>
>
>  #include <mach/map.h>
>  #include <mach/irqs.h>
> -
> -#include <plat/s3c-pl330-pdata.h>
> +#include <mach/dma.h>
>
>  static u64 dma_dmamask = DMA_BIT_MASK(32);
>
> -static struct resource exynos4_pdma0_resource[] = {
> -       [0] = {
> -               .start  = EXYNOS4_PA_PDMA0,
> -               .end    = EXYNOS4_PA_PDMA0 + SZ_4K,
> -               .flags  = IORESOURCE_MEM,
> -       },
> -       [1] = {
> -               .start  = IRQ_PDMA0,
> -               .end    = IRQ_PDMA0,
> -               .flags  = IORESOURCE_IRQ,
> +struct dma_pl330_peri pdma0_peri[32] = {
Please remove 32 from the list (it seems you don't always pass 32 elements)
Also for completeness, please explicitly write element indices below because
it's not some array of randomly placed elements.
Same for every other such occurance.

> +       {
> +               .peri_id = (u8)DMACH_PCM0_RX,
> +               .rqtype = DEVTOMEM,
> +       }, {
> +               .peri_id = (u8)DMACH_PCM0_TX,
> +               .rqtype = MEMTODEV,
> +       }, {
> +               .peri_id = (u8)DMACH_PCM2_RX,
> +               .rqtype = DEVTOMEM,
> +       }, {
> +               .peri_id = (u8)DMACH_PCM2_TX,
> +               .rqtype = MEMTODEV,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_MSM_REQ0,
> +       }, {
> +               .peri_id = (u8)DMACH_MSM_REQ2,
> +       }, {
> +               .peri_id = (u8)DMACH_SPI0_RX,
> +               .rqtype = DEVTOMEM,
> +               .burst_sz = 1,
> +       }, {
> +               .peri_id = (u8)DMACH_SPI0_TX,
> +               .rqtype = MEMTODEV,
> +               .burst_sz = 1,
> +       }, {
> +               .peri_id = (u8)DMACH_SPI2_RX,
> +               .rqtype = DEVTOMEM,
> +               .burst_sz = 1,
> +       }, {
> +               .peri_id = (u8)DMACH_SPI2_TX,
> +               .rqtype = MEMTODEV,
> +               .burst_sz = 1,
> +       }, {
> +               .peri_id = (u8)DMACH_I2S0S_TX,
> +               .rqtype = MEMTODEV,
> +       }, {
> +               .peri_id = (u8)DMACH_I2S0_RX,
> +               .rqtype = DEVTOMEM,
> +       }, {
> +               .peri_id = (u8)DMACH_I2S0_TX,
> +               .rqtype = MEMTODEV,
> +       }, {
> +               .peri_id = (u8)DMACH_UART0_RX,
> +               .rqtype = DEVTOMEM,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_UART0_TX,
> +               .rqtype = MEMTODEV,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_UART2_RX,
> +               .rqtype = DEVTOMEM,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_UART2_TX,
> +               .rqtype = MEMTODEV,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_UART4_RX,
> +               .rqtype = DEVTOMEM,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_UART4_TX,
> +               .rqtype = MEMTODEV,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_SLIMBUS0_RX,
> +               .rqtype = DEVTOMEM,
> +       }, {
> +               .peri_id = (u8)DMACH_SLIMBUS0_TX,
> +               .rqtype = MEMTODEV,
> +       }, {
> +               .peri_id = (u8)DMACH_SLIMBUS2_RX,
> +               .rqtype = DEVTOMEM,
> +       }, {
> +               .peri_id = (u8)DMACH_SLIMBUS2_TX,
> +               .rqtype = MEMTODEV,
> +       }, {
> +               .peri_id = (u8)DMACH_SLIMBUS4_RX,
> +               .rqtype = DEVTOMEM,
> +       }, {
> +               .peri_id = (u8)DMACH_SLIMBUS4_TX,
> +               .rqtype = MEMTODEV,
> +       }, {
> +               .peri_id = (u8)DMACH_AC97_MICIN,
> +               .rqtype = DEVTOMEM,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_AC97_PCMIN,
> +               .rqtype = DEVTOMEM,
> +               .burst_sz = 4,
> +       }, {
> +               .peri_id = (u8)DMACH_AC97_PCMOUT,
> +               .rqtype = MEMTODEV,
> +               .burst_sz = 4,
>        },
>  };


>
> -static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
> -       .peri = {
> -               [0] = DMACH_PCM0_RX,
> -               [1] = DMACH_PCM0_TX,
> -               [2] = DMACH_PCM2_RX,
> -               [3] = DMACH_PCM2_TX,
> -               [4] = DMACH_MSM_REQ0,
> -               [5] = DMACH_MSM_REQ2,
> -               [6] = DMACH_SPI0_RX,
> -               [7] = DMACH_SPI0_TX,
> -               [8] = DMACH_SPI2_RX,
> -               [9] = DMACH_SPI2_TX,
> -               [10] = DMACH_I2S0S_TX,
> -               [11] = DMACH_I2S0_RX,
> -               [12] = DMACH_I2S0_TX,
> -               [13] = DMACH_I2S2_RX,
> -               [14] = DMACH_I2S2_TX,
> -               [15] = DMACH_UART0_RX,
> -               [16] = DMACH_UART0_TX,
> -               [17] = DMACH_UART2_RX,
> -               [18] = DMACH_UART2_TX,
> -               [19] = DMACH_UART4_RX,
> -               [20] = DMACH_UART4_TX,
> -               [21] = DMACH_SLIMBUS0_RX,
> -               [22] = DMACH_SLIMBUS0_TX,
> -               [23] = DMACH_SLIMBUS2_RX,
> -               [24] = DMACH_SLIMBUS2_TX,
> -               [25] = DMACH_SLIMBUS4_RX,
> -               [26] = DMACH_SLIMBUS4_TX,
> -               [27] = DMACH_AC97_MICIN,
> -               [28] = DMACH_AC97_PCMIN,
> -               [29] = DMACH_AC97_PCMOUT,
> -               [30] = DMACH_MAX,
> -               [31] = DMACH_MAX,
> -       },
> +struct dma_pl330_platdata exynos4_pdma0_pdata = {
> +       .nr_valid_peri = 32,
Perhaps, this is why you had to add the NULL peri check.
Please use ARRAY_SIZE here.
Same for every other such occurance.

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

* [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
@ 2011-07-25 11:59     ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
> index 564bb53..e1c00cf 100644
> --- a/arch/arm/mach-exynos4/dma.c
> +++ b/arch/arm/mach-exynos4/dma.c
> @@ -21,151 +21,250 @@
> ?* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> ?*/
>
> -#include <linux/platform_device.h>
> ?#include <linux/dma-mapping.h>
> +#include <linux/amba/bus.h>
> +#include <linux/amba/pl330.h>
>
> +#include <asm/irq.h>
> ?#include <plat/devs.h>
> ?#include <plat/irqs.h>
>
> ?#include <mach/map.h>
> ?#include <mach/irqs.h>
> -
> -#include <plat/s3c-pl330-pdata.h>
> +#include <mach/dma.h>
>
> ?static u64 dma_dmamask = DMA_BIT_MASK(32);
>
> -static struct resource exynos4_pdma0_resource[] = {
> - ? ? ? [0] = {
> - ? ? ? ? ? ? ? .start ?= EXYNOS4_PA_PDMA0,
> - ? ? ? ? ? ? ? .end ? ?= EXYNOS4_PA_PDMA0 + SZ_4K,
> - ? ? ? ? ? ? ? .flags ?= IORESOURCE_MEM,
> - ? ? ? },
> - ? ? ? [1] = {
> - ? ? ? ? ? ? ? .start ?= IRQ_PDMA0,
> - ? ? ? ? ? ? ? .end ? ?= IRQ_PDMA0,
> - ? ? ? ? ? ? ? .flags ?= IORESOURCE_IRQ,
> +struct dma_pl330_peri pdma0_peri[32] = {
Please remove 32 from the list (it seems you don't always pass 32 elements)
Also for completeness, please explicitly write element indices below because
it's not some array of randomly placed elements.
Same for every other such occurance.

> + ? ? ? {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM0_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM0_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM2_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM2_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_MSM_REQ0,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_MSM_REQ2,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SPI0_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? ? ? ? ? .burst_sz = 1,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SPI0_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? ? ? ? ? .burst_sz = 1,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SPI2_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? ? ? ? ? .burst_sz = 1,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SPI2_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? ? ? ? ? .burst_sz = 1,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_I2S0S_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_I2S0_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_I2S0_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART0_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART0_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART2_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART2_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART4_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART4_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS0_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS0_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS2_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS2_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS4_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS4_TX,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_AC97_MICIN,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_AC97_PCMIN,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> + ? ? ? }, {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_AC97_PCMOUT,
> + ? ? ? ? ? ? ? .rqtype = MEMTODEV,
> + ? ? ? ? ? ? ? .burst_sz = 4,
> ? ? ? ?},
> ?};


>
> -static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
> - ? ? ? .peri = {
> - ? ? ? ? ? ? ? [0] = DMACH_PCM0_RX,
> - ? ? ? ? ? ? ? [1] = DMACH_PCM0_TX,
> - ? ? ? ? ? ? ? [2] = DMACH_PCM2_RX,
> - ? ? ? ? ? ? ? [3] = DMACH_PCM2_TX,
> - ? ? ? ? ? ? ? [4] = DMACH_MSM_REQ0,
> - ? ? ? ? ? ? ? [5] = DMACH_MSM_REQ2,
> - ? ? ? ? ? ? ? [6] = DMACH_SPI0_RX,
> - ? ? ? ? ? ? ? [7] = DMACH_SPI0_TX,
> - ? ? ? ? ? ? ? [8] = DMACH_SPI2_RX,
> - ? ? ? ? ? ? ? [9] = DMACH_SPI2_TX,
> - ? ? ? ? ? ? ? [10] = DMACH_I2S0S_TX,
> - ? ? ? ? ? ? ? [11] = DMACH_I2S0_RX,
> - ? ? ? ? ? ? ? [12] = DMACH_I2S0_TX,
> - ? ? ? ? ? ? ? [13] = DMACH_I2S2_RX,
> - ? ? ? ? ? ? ? [14] = DMACH_I2S2_TX,
> - ? ? ? ? ? ? ? [15] = DMACH_UART0_RX,
> - ? ? ? ? ? ? ? [16] = DMACH_UART0_TX,
> - ? ? ? ? ? ? ? [17] = DMACH_UART2_RX,
> - ? ? ? ? ? ? ? [18] = DMACH_UART2_TX,
> - ? ? ? ? ? ? ? [19] = DMACH_UART4_RX,
> - ? ? ? ? ? ? ? [20] = DMACH_UART4_TX,
> - ? ? ? ? ? ? ? [21] = DMACH_SLIMBUS0_RX,
> - ? ? ? ? ? ? ? [22] = DMACH_SLIMBUS0_TX,
> - ? ? ? ? ? ? ? [23] = DMACH_SLIMBUS2_RX,
> - ? ? ? ? ? ? ? [24] = DMACH_SLIMBUS2_TX,
> - ? ? ? ? ? ? ? [25] = DMACH_SLIMBUS4_RX,
> - ? ? ? ? ? ? ? [26] = DMACH_SLIMBUS4_TX,
> - ? ? ? ? ? ? ? [27] = DMACH_AC97_MICIN,
> - ? ? ? ? ? ? ? [28] = DMACH_AC97_PCMIN,
> - ? ? ? ? ? ? ? [29] = DMACH_AC97_PCMOUT,
> - ? ? ? ? ? ? ? [30] = DMACH_MAX,
> - ? ? ? ? ? ? ? [31] = DMACH_MAX,
> - ? ? ? },
> +struct dma_pl330_platdata exynos4_pdma0_pdata = {
> + ? ? ? .nr_valid_peri = 32,
Perhaps, this is why you had to add the NULL peri check.
Please use ARRAY_SIZE here.
Same for every other such occurance.

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

* Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 11:39                 ` Russell King - ARM Linux
@ 2011-07-25 12:01                   ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 12:01 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-samsung-soc, Boojin Kim, vinod.koul, 'Jassi Brar',
	'Grant Likely', 'Kukjin Kim',
	'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Mon, 2011-07-25 at 12:39 +0100, Russell King - ARM Linux wrote:
> On Mon, Jul 25, 2011 at 04:31:57PM +0530, Vinod Koul wrote:
> > > I know that very well thank you.  Please look at my previous post in the
> > > previous round of patches, and the response from Boojin Kim to see why
> > > I used this as an *EXAMPLE* to get this fixed.
> > Russell,
> > Sorry that was not intended for you but for the author of patch Boojin
> > Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it
> > as going thru this patch made it clear that they haven't.
> 
> That wasn't obvious because of the To: and the use of 'you' in your reply.
Laziness on a rainy monday evening caused me to miss that

> 
> In any case, let's fix up the documentation to be a little more complete
> and expansive about these conditions, and improve its formatting so it's
> easier to read.
> 
> A few points:
> 
> 1. This really should describe the dma_slave_config structure in detail
>    (or refer to the documentation in dmaengine.h) especially describing
>    what is mandatory there.
I think you missed mandatory fields here, Pls note I am dropping the
direction field in this, as we have discussed it makes no sense

> 
> 2. Note the filter function thing - I think this should be mandatory
>    for slave and cyclic channels.  These typically have a DMA request
>    signal associated with each channel, and so 'any random channel' isn't
>    really acceptable like it is for the async_tx APIs.
> 
> 3. I think this should specify that dmaengine_slave_config() should be
>    specified as mandatory after obtaining the DMA engine channel.
> 
> Any comments on this before I prepare this as a proper patch?
> 
> diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
> index 5a0cb1e..8ba8d3c 100644
> --- a/Documentation/dmaengine.txt
> +++ b/Documentation/dmaengine.txt
> @@ -10,87 +10,163 @@
>  Below is a guide to device driver writers on how to use the Slave-DMA API of the
>  DMA Engine. This is applicable only for slave DMA usage only.
>  
> -The slave DMA usage consists of following steps
> +The slave DMA usage consists of following steps:
>  1. Allocate a DMA slave channel
>  2. Set slave and controller specific parameters
>  3. Get a descriptor for transaction
>  4. Submit the transaction and wait for callback notification
> +5. Issue pending requests
>  
>  1. Allocate a DMA slave channel
> -Channel allocation is slightly different in the slave DMA context, client
> -drivers typically need a channel from a particular DMA controller only and even
> -in some cases a specific channel is desired. To request a channel
> -dma_request_channel() API is used.
> -
> -Interface:
> -struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
> -		dma_filter_fn filter_fn,
> -		void *filter_param);
> -where dma_filter_fn is defined as:
> -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
> -
> -When the optional 'filter_fn' parameter is set to NULL dma_request_channel
> -simply returns the first channel that satisfies the capability mask.  Otherwise,
> -when the mask parameter is insufficient for specifying the necessary channel,
> -the filter_fn routine can be used to disposition the available channels in the
> -system. The filter_fn routine is called once for each free channel in the
> -system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
> -that channel to be the return value from dma_request_channel.  A channel
> -allocated via this interface is exclusive to the caller, until
> -dma_release_channel() is called.
> +
> +   Channel allocation is slightly different in the slave DMA context,
> +   client drivers typically need a channel from a particular DMA
> +   controller only and even in some cases a specific channel is desired.
> +   To request a channel dma_request_channel() API is used.
> +
> +   Interface:
> +	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
> +			dma_filter_fn filter_fn,
> +			void *filter_param);
> +   where dma_filter_fn is defined as:
> +	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
> +
> +   The 'filter_fn' parameter is optional, but highly recommended for
> +   slave and cyclic channels as they typically need to obtain a specific
> +   DMA channel.
> +
> +   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
> +   simply returns the first channel that satisfies the capability mask.
> +
> +   Otherwise, the 'filter_fn' routine will be called once for each free
> +   channel which has a capability in 'mask'.  'filter_fn' is expected to
> +   return 'true' when the desired DMA channel is found.
> +
> +   A channel allocated via this interface is exclusive to the caller,
> +   until dma_release_channel() is called.
>  
>  2. Set slave and controller specific parameters
> -Next step is always to pass some specific information to the DMA driver. Most of
> -the generic information which a slave DMA can use is in struct dma_slave_config.
> -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
> -burst lengths etc. If some DMA controllers have more parameters to be sent then
> -they should try to embed struct dma_slave_config in their controller specific
> -structure. That gives flexibility to client to pass more parameters, if
> -required.
> -
> -Interface:
> -int dmaengine_slave_config(struct dma_chan *chan,
> -					  struct dma_slave_config *config)
> +
> +   Next step is always to pass some specific information to the DMA
> +   driver.  Most of the generic information which a slave DMA can use
> +   is in struct dma_slave_config.  This allows the clients to specify
> +   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
> +   for the peripheral.
> +
> +   If some DMA controllers have more parameters to be sent then they
> +   should try to embed struct dma_slave_config in their controller
> +   specific structure. That gives flexibility to client to pass more
> +   parameters, if required.
> +
> +   Interface:
> +	int dmaengine_slave_config(struct dma_chan *chan,
> +				  struct dma_slave_config *config)
>  
>  3. Get a descriptor for transaction
> -For slave usage the various modes of slave transfers supported by the
> -DMA-engine are:
> -slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
> -dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
> +
> +   For slave usage the various modes of slave transfers supported by the
> +   DMA-engine are:
> +
> +   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
> +   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
>  		  operation is explicitly stopped.
> -The non NULL return of this transfer API represents a "descriptor" for the given
> -transaction.
>  
> -Interface:
> -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
> +   A non-NULL return of this transfer API represents a "descriptor" for
> +   the given transaction.
> +
> +   Interface:
> +	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
>  		struct dma_chan *chan,
>  		struct scatterlist *dst_sg, unsigned int dst_nents,
>  		struct scatterlist *src_sg, unsigned int src_nents,
>  		unsigned long flags);
> -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
> +
> +	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
>  		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
>  		size_t period_len, enum dma_data_direction direction);
>  
> +   Once a descriptor has been obtained, the callback information can be
> +   added and must then be submitted.  Some DMA engine drivers may hold a
> +   spinlock between a successful preparation and submission so it is
> +   important that these two operations are closely paired.
> +
> +   Note:
> +	Although the async_tx API specifies that completion callback
> +	routines cannot submit any new operations, this is not the
> +	case for slave/cyclic DMA.
> +
> +	For slave DMA, the subsequent transaction may not be available
> +	for submission prior to callback function being invoked, so
> +	slave DMA callbacks are permitted to prepare and submit a new
> +	transaction.
> +
> +	For cyclic DMA, a callback function may wish to terminate the
> +	DMA via dmaengine_terminate_all().
> +
> +	Therefore, it is important that DMA engine drivers drop any
> +	locks before calling the callback function which may cause a
> +	deadlock.
> +
> +	Note that callbacks will always be invoked from the DMA
> +	engines tasklet, never from interrupt context.
> +
>  4. Submit the transaction and wait for callback notification
As you are adding 5 for issue pending then this needs change

> -To schedule the transaction to be scheduled by dma device, the "descriptor"
> -returned in above (3) needs to be submitted.
> -To tell the dma driver that a transaction is ready to be serviced, the
> -descriptor->submit() callback needs to be invoked. This chains the descriptor to
> -the pending queue.
> -The transactions in the pending queue can be activated by calling the
> -issue_pending API. If channel is idle then the first transaction in queue is
> -started and subsequent ones queued up.
> -On completion of the DMA operation the next in queue is submitted and a tasklet
> -triggered. The tasklet would then call the client driver completion callback
> -routine for notification, if set.
> -Interface:
> -void dma_async_issue_pending(struct dma_chan *chan);
> -
> -==============================================================================
> -
> -Additional usage notes for dma driver writers
> -1/ Although DMA engine specifies that completion callback routines cannot submit
> -any new operations, but typically for slave DMA subsequent transaction may not
> -be available for submit prior to callback routine being called. This requirement
> -is not a requirement for DMA-slave devices. But they should take care to drop
> -the spin-lock they might be holding before calling the callback routine
> +
> +   Once the descriptor has been prepared and the callback information
> +   added, it must be placed on the DMA engine drivers pending queue.
> +
> +   Interface:
> +	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
> +
> +   This returns a cookie can be used to check the progress of DMA engine
> +   activity via other DMA engine calls not covered in this document.
> +
> +   dmaengine_submit() will not start the DMA operation, it merely adds
> +   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
> +
> +5. Issue pending DMA requests
and getting callback notification
> +
> +   The transactions in the pending queue can be activated by calling the
> +   issue_pending API. If channel is idle then the first transaction in
> +   queue is started and subsequent ones queued up.
> +
> +   On completion of each DMA operation, the next in queue is started and
> +   a tasklet triggered. The tasklet will then call the client driver
> +   completion callback routine for notification, if set.
> +
> +   Interface:
> +	void dma_async_issue_pending(struct dma_chan *chan);
> +
> +Further APIs:
> +
> +1. int dmaengine_terminate_all(struct dma_chan *chan)
> +
> +   This causes all activity for the DMA channel to be stopped, and may
> +   discard data in the DMA FIFO which hasn't been fully transferred.
> +   No callback functions will be called for any incomplete transfers.
> +
> +2. int dmaengine_pause(struct dma_chan *chan)
> +
> +   This pauses activity on the DMA channel without data loss.
> +
> +3. int dmaengine_resume(struct dma_chan *chan)
> +
> +   Resume a previously paused DMA channel.  It is invalid to resume a
> +   channel which is not currently paused.
> +
> +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
> +        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
> +
> +   This can be used to check the status of the channel.  Please see
> +   the documentation in include/linux/dmaengine.h for a more complete
> +   description of this API.
> +
> +   This can be used in conjunction with dma_async_is_complete() and
> +   the cookie returned from 'descriptor->submit()' to check for
> +   completion of a specific DMA transaction.
> +
> +   Note:
> +	Not all DMA engine drivers can return reliable information for
> +	a running DMA channel.  It is recommended that DMA engine users
> +	pause or stop (via dmaengine_terminate_all) the channel before
> +	using this API.
> 

-- 
~Vinod Koul
Intel Corp.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 12:01                   ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 12:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 12:39 +0100, Russell King - ARM Linux wrote:
> On Mon, Jul 25, 2011 at 04:31:57PM +0530, Vinod Koul wrote:
> > > I know that very well thank you.  Please look at my previous post in the
> > > previous round of patches, and the response from Boojin Kim to see why
> > > I used this as an *EXAMPLE* to get this fixed.
> > Russell,
> > Sorry that was not intended for you but for the author of patch Boojin
> > Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it
> > as going thru this patch made it clear that they haven't.
> 
> That wasn't obvious because of the To: and the use of 'you' in your reply.
Laziness on a rainy monday evening caused me to miss that

> 
> In any case, let's fix up the documentation to be a little more complete
> and expansive about these conditions, and improve its formatting so it's
> easier to read.
> 
> A few points:
> 
> 1. This really should describe the dma_slave_config structure in detail
>    (or refer to the documentation in dmaengine.h) especially describing
>    what is mandatory there.
I think you missed mandatory fields here, Pls note I am dropping the
direction field in this, as we have discussed it makes no sense

> 
> 2. Note the filter function thing - I think this should be mandatory
>    for slave and cyclic channels.  These typically have a DMA request
>    signal associated with each channel, and so 'any random channel' isn't
>    really acceptable like it is for the async_tx APIs.
> 
> 3. I think this should specify that dmaengine_slave_config() should be
>    specified as mandatory after obtaining the DMA engine channel.
> 
> Any comments on this before I prepare this as a proper patch?
> 
> diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
> index 5a0cb1e..8ba8d3c 100644
> --- a/Documentation/dmaengine.txt
> +++ b/Documentation/dmaengine.txt
> @@ -10,87 +10,163 @@
>  Below is a guide to device driver writers on how to use the Slave-DMA API of the
>  DMA Engine. This is applicable only for slave DMA usage only.
>  
> -The slave DMA usage consists of following steps
> +The slave DMA usage consists of following steps:
>  1. Allocate a DMA slave channel
>  2. Set slave and controller specific parameters
>  3. Get a descriptor for transaction
>  4. Submit the transaction and wait for callback notification
> +5. Issue pending requests
>  
>  1. Allocate a DMA slave channel
> -Channel allocation is slightly different in the slave DMA context, client
> -drivers typically need a channel from a particular DMA controller only and even
> -in some cases a specific channel is desired. To request a channel
> -dma_request_channel() API is used.
> -
> -Interface:
> -struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
> -		dma_filter_fn filter_fn,
> -		void *filter_param);
> -where dma_filter_fn is defined as:
> -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
> -
> -When the optional 'filter_fn' parameter is set to NULL dma_request_channel
> -simply returns the first channel that satisfies the capability mask.  Otherwise,
> -when the mask parameter is insufficient for specifying the necessary channel,
> -the filter_fn routine can be used to disposition the available channels in the
> -system. The filter_fn routine is called once for each free channel in the
> -system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
> -that channel to be the return value from dma_request_channel.  A channel
> -allocated via this interface is exclusive to the caller, until
> -dma_release_channel() is called.
> +
> +   Channel allocation is slightly different in the slave DMA context,
> +   client drivers typically need a channel from a particular DMA
> +   controller only and even in some cases a specific channel is desired.
> +   To request a channel dma_request_channel() API is used.
> +
> +   Interface:
> +	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
> +			dma_filter_fn filter_fn,
> +			void *filter_param);
> +   where dma_filter_fn is defined as:
> +	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
> +
> +   The 'filter_fn' parameter is optional, but highly recommended for
> +   slave and cyclic channels as they typically need to obtain a specific
> +   DMA channel.
> +
> +   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
> +   simply returns the first channel that satisfies the capability mask.
> +
> +   Otherwise, the 'filter_fn' routine will be called once for each free
> +   channel which has a capability in 'mask'.  'filter_fn' is expected to
> +   return 'true' when the desired DMA channel is found.
> +
> +   A channel allocated via this interface is exclusive to the caller,
> +   until dma_release_channel() is called.
>  
>  2. Set slave and controller specific parameters
> -Next step is always to pass some specific information to the DMA driver. Most of
> -the generic information which a slave DMA can use is in struct dma_slave_config.
> -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
> -burst lengths etc. If some DMA controllers have more parameters to be sent then
> -they should try to embed struct dma_slave_config in their controller specific
> -structure. That gives flexibility to client to pass more parameters, if
> -required.
> -
> -Interface:
> -int dmaengine_slave_config(struct dma_chan *chan,
> -					  struct dma_slave_config *config)
> +
> +   Next step is always to pass some specific information to the DMA
> +   driver.  Most of the generic information which a slave DMA can use
> +   is in struct dma_slave_config.  This allows the clients to specify
> +   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
> +   for the peripheral.
> +
> +   If some DMA controllers have more parameters to be sent then they
> +   should try to embed struct dma_slave_config in their controller
> +   specific structure. That gives flexibility to client to pass more
> +   parameters, if required.
> +
> +   Interface:
> +	int dmaengine_slave_config(struct dma_chan *chan,
> +				  struct dma_slave_config *config)
>  
>  3. Get a descriptor for transaction
> -For slave usage the various modes of slave transfers supported by the
> -DMA-engine are:
> -slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
> -dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
> +
> +   For slave usage the various modes of slave transfers supported by the
> +   DMA-engine are:
> +
> +   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
> +   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
>  		  operation is explicitly stopped.
> -The non NULL return of this transfer API represents a "descriptor" for the given
> -transaction.
>  
> -Interface:
> -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
> +   A non-NULL return of this transfer API represents a "descriptor" for
> +   the given transaction.
> +
> +   Interface:
> +	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
>  		struct dma_chan *chan,
>  		struct scatterlist *dst_sg, unsigned int dst_nents,
>  		struct scatterlist *src_sg, unsigned int src_nents,
>  		unsigned long flags);
> -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
> +
> +	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
>  		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
>  		size_t period_len, enum dma_data_direction direction);
>  
> +   Once a descriptor has been obtained, the callback information can be
> +   added and must then be submitted.  Some DMA engine drivers may hold a
> +   spinlock between a successful preparation and submission so it is
> +   important that these two operations are closely paired.
> +
> +   Note:
> +	Although the async_tx API specifies that completion callback
> +	routines cannot submit any new operations, this is not the
> +	case for slave/cyclic DMA.
> +
> +	For slave DMA, the subsequent transaction may not be available
> +	for submission prior to callback function being invoked, so
> +	slave DMA callbacks are permitted to prepare and submit a new
> +	transaction.
> +
> +	For cyclic DMA, a callback function may wish to terminate the
> +	DMA via dmaengine_terminate_all().
> +
> +	Therefore, it is important that DMA engine drivers drop any
> +	locks before calling the callback function which may cause a
> +	deadlock.
> +
> +	Note that callbacks will always be invoked from the DMA
> +	engines tasklet, never from interrupt context.
> +
>  4. Submit the transaction and wait for callback notification
As you are adding 5 for issue pending then this needs change

> -To schedule the transaction to be scheduled by dma device, the "descriptor"
> -returned in above (3) needs to be submitted.
> -To tell the dma driver that a transaction is ready to be serviced, the
> -descriptor->submit() callback needs to be invoked. This chains the descriptor to
> -the pending queue.
> -The transactions in the pending queue can be activated by calling the
> -issue_pending API. If channel is idle then the first transaction in queue is
> -started and subsequent ones queued up.
> -On completion of the DMA operation the next in queue is submitted and a tasklet
> -triggered. The tasklet would then call the client driver completion callback
> -routine for notification, if set.
> -Interface:
> -void dma_async_issue_pending(struct dma_chan *chan);
> -
> -==============================================================================
> -
> -Additional usage notes for dma driver writers
> -1/ Although DMA engine specifies that completion callback routines cannot submit
> -any new operations, but typically for slave DMA subsequent transaction may not
> -be available for submit prior to callback routine being called. This requirement
> -is not a requirement for DMA-slave devices. But they should take care to drop
> -the spin-lock they might be holding before calling the callback routine
> +
> +   Once the descriptor has been prepared and the callback information
> +   added, it must be placed on the DMA engine drivers pending queue.
> +
> +   Interface:
> +	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
> +
> +   This returns a cookie can be used to check the progress of DMA engine
> +   activity via other DMA engine calls not covered in this document.
> +
> +   dmaengine_submit() will not start the DMA operation, it merely adds
> +   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
> +
> +5. Issue pending DMA requests
and getting callback notification
> +
> +   The transactions in the pending queue can be activated by calling the
> +   issue_pending API. If channel is idle then the first transaction in
> +   queue is started and subsequent ones queued up.
> +
> +   On completion of each DMA operation, the next in queue is started and
> +   a tasklet triggered. The tasklet will then call the client driver
> +   completion callback routine for notification, if set.
> +
> +   Interface:
> +	void dma_async_issue_pending(struct dma_chan *chan);
> +
> +Further APIs:
> +
> +1. int dmaengine_terminate_all(struct dma_chan *chan)
> +
> +   This causes all activity for the DMA channel to be stopped, and may
> +   discard data in the DMA FIFO which hasn't been fully transferred.
> +   No callback functions will be called for any incomplete transfers.
> +
> +2. int dmaengine_pause(struct dma_chan *chan)
> +
> +   This pauses activity on the DMA channel without data loss.
> +
> +3. int dmaengine_resume(struct dma_chan *chan)
> +
> +   Resume a previously paused DMA channel.  It is invalid to resume a
> +   channel which is not currently paused.
> +
> +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
> +        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
> +
> +   This can be used to check the status of the channel.  Please see
> +   the documentation in include/linux/dmaengine.h for a more complete
> +   description of this API.
> +
> +   This can be used in conjunction with dma_async_is_complete() and
> +   the cookie returned from 'descriptor->submit()' to check for
> +   completion of a specific DMA transaction.
> +
> +   Note:
> +	Not all DMA engine drivers can return reliable information for
> +	a running DMA channel.  It is recommended that DMA engine users
> +	pause or stop (via dmaengine_terminate_all) the channel before
> +	using this API.
> 

-- 
~Vinod Koul
Intel Corp.

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

* Re: [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-25 12:08     ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 12:08 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Kukjin Kim, Grant Likely, Mark Brown

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> This patch removes the samsung specific enum type 's3c2410_dmasrc'
> and uses 'dma_data_direction' instead.
>
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>

Acked-by: Jassi Brar <jassisinghbrar@gmail.com>

If this patch was first in the patchset, probably it could have been
already merged.

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

* [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
@ 2011-07-25 12:08     ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-25 12:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> This patch removes the samsung specific enum type 's3c2410_dmasrc'
> and uses 'dma_data_direction' instead.
>
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>

Acked-by: Jassi Brar <jassisinghbrar@gmail.com>

If this patch was first in the patchset, probably it could have been
already merged.

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

* RE: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 10:36         ` Russell King - ARM Linux
@ 2011-07-25 12:34           ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 12:34 UTC (permalink / raw)
  To: 'Russell King - ARM Linux'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Kukjin Kim',
	'Vinod Koul', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams'

Russell King - ARM Linux Wrote:
> Sent: Monday, July 25, 2011 7:36 PM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org; 'Kukjin Kim'; 'Vinod Koul'; 'Jassi Brar'; 'Grant
> Likely'; 'Mark Brown'; 'Dan Williams'
> Subject: Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
>
> On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > +{
> > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > +	unsigned long flags;
> > > > +	LIST_HEAD(list);
> > > > +
> > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > ...
> > > > +			callback = desc->txd.callback;
> > > > +			if (callback)
> > > > +				callback(desc->txd.callback_param);
> > >
> > > On this again - what if the callback wants to terminate the DMA
> activity
> > > because there's no more audio data to be sent/received from the
> device?
> >
> > Do you mean what is happened if the callback() is called after
> channel is
> > terminated ?
> > Or What is happened if Callback() calls 'dma_release_channel()' to
> terminate
> > DMA?
>
> No.  I mean what if the callback wants to call
> dmaengine_terminate_all().
I found the deadlock problem that you and Vinod post. I will fix it.

>
> > > > +	if (!pch->cyclic_task) {
> > > > +		pch->cyclic_task =
> > > > +			kmalloc(sizeof(struct tasklet_struct),
> GFP_KERNEL);
> > > > +		tasklet_init(pch->cyclic_task,
> > > > +			pl330_tasklet_cyclic, (unsigned int)pch);
> > >
> > > Here you allocate memory for the cyclic task.  Above you set this
> pointer
> > > to NULL.  That sounds like a memory leak to me.  Why are you
> kmallocing
> > > this memory - why can't it be part of the dma_pl330_chan structure?
> It's
> > > only 28 bytes.
> >
> > It's my mistake. I should have been free of the memory.
> >
> > And the reason why I use kmalloc for 'cyclic_task' is following.
> > This memory size for 'cyclic_tasklet' is the 896 bytes ( = the
> number of
> > channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And
> This
> > memory size is increased according to the number of DMAC.
> > And Samsung has the DMAC that is dedicated for Mem-to-Mem operation.
> If I
> > make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is
> dedicated
> > for Mem-to-Mem operation should hold unused data.
> > So, I think it's loss that all dma channels hold own 'cyclic_task'.
>
> Could you re-use the tasklet that already exists?
Yes, It can be re-used. But, This tasklet should be initialized on each
request by using 'tasklet_init()' because it needs the own channel as its
parameter.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 12:34           ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 12:34 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux Wrote:
> Sent: Monday, July 25, 2011 7:36 PM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> soc at vger.kernel.org; 'Kukjin Kim'; 'Vinod Koul'; 'Jassi Brar'; 'Grant
> Likely'; 'Mark Brown'; 'Dan Williams'
> Subject: Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
>
> On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > +{
> > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > +	unsigned long flags;
> > > > +	LIST_HEAD(list);
> > > > +
> > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > ...
> > > > +			callback = desc->txd.callback;
> > > > +			if (callback)
> > > > +				callback(desc->txd.callback_param);
> > >
> > > On this again - what if the callback wants to terminate the DMA
> activity
> > > because there's no more audio data to be sent/received from the
> device?
> >
> > Do you mean what is happened if the callback() is called after
> channel is
> > terminated ?
> > Or What is happened if Callback() calls 'dma_release_channel()' to
> terminate
> > DMA?
>
> No.  I mean what if the callback wants to call
> dmaengine_terminate_all().
I found the deadlock problem that you and Vinod post. I will fix it.

>
> > > > +	if (!pch->cyclic_task) {
> > > > +		pch->cyclic_task =
> > > > +			kmalloc(sizeof(struct tasklet_struct),
> GFP_KERNEL);
> > > > +		tasklet_init(pch->cyclic_task,
> > > > +			pl330_tasklet_cyclic, (unsigned int)pch);
> > >
> > > Here you allocate memory for the cyclic task.  Above you set this
> pointer
> > > to NULL.  That sounds like a memory leak to me.  Why are you
> kmallocing
> > > this memory - why can't it be part of the dma_pl330_chan structure?
> It's
> > > only 28 bytes.
> >
> > It's my mistake. I should have been free of the memory.
> >
> > And the reason why I use kmalloc for 'cyclic_task' is following.
> > This memory size for 'cyclic_tasklet' is the 896 bytes ( = the
> number of
> > channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And
> This
> > memory size is increased according to the number of DMAC.
> > And Samsung has the DMAC that is dedicated for Mem-to-Mem operation.
> If I
> > make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is
> dedicated
> > for Mem-to-Mem operation should hold unused data.
> > So, I think it's loss that all dma channels hold own 'cyclic_task'.
>
> Could you re-use the tasklet that already exists?
Yes, It can be re-used. But, This tasklet should be initialized on each
request by using 'tasklet_init()' because it needs the own channel as its
parameter.

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

* RE: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 10:48           ` Vinod Koul
@ 2011-07-25 12:36             ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 12:36 UTC (permalink / raw)
  To: 'Vinod Koul', 'Russell King - ARM Linux'
  Cc: vinod.koul, 'Kukjin Kim', 'Jassi Brar',
	'Grant Likely', linux-samsung-soc, 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

Vinod Koul Wrote:
> Sent: Monday, July 25, 2011 7:48 PM
> To: Russell King - ARM Linux
> Cc: vinod.koul@intel.com; Boojin Kim; 'Kukjin Kim'; 'Jassi Brar';
> 'Grant Likely'; linux-samsung-soc@vger.kernel.org; 'Mark Brown'; 'Dan
> Williams'; linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
>
> On Mon, 2011-07-25 at 11:36 +0100, Russell King - ARM Linux wrote:
> > On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > > +{
> > > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > > +	unsigned long flags;
> > > > > +	LIST_HEAD(list);
> > > > > +
> > > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > > ...
> > > > > +			callback = desc->txd.callback;
> > > > > +			if (callback)
> > > > > +				callback(desc->txd.callback_param);
> > > >
> > > > On this again - what if the callback wants to terminate the DMA
> activity
> > > > because there's no more audio data to be sent/received from the
> device?
> > >
> > > Do you mean what is happened if the callback() is called after
> channel is
> > > terminated ?
> > > Or What is happened if Callback() calls 'dma_release_channel()' to
> terminate
> > > DMA?
> >
> > No.  I mean what if the callback wants to call
> dmaengine_terminate_all().
> you are supposed to drop the lock here, that way callback can call any
> DMA API, otherwise it will result in deadlock.
> This make me wonder you haven't read the documentation at all, please
> ensure you have read Documentation/dmaengine.txt before next posting
I found the deadlock problem that you post. I will fix it and read the 
document again.

> >
> > > > > +	if (!pch->cyclic_task) {
> > > > > +		pch->cyclic_task =
> > > > > +			kmalloc(sizeof(struct tasklet_struct),
> GFP_KERNEL);
> > > > > +		tasklet_init(pch->cyclic_task,
> > > > > +			pl330_tasklet_cyclic, (unsigned int)pch);
> > > >
> > > > Here you allocate memory for the cyclic task.  Above you set this
> pointer
> > > > to NULL.  That sounds like a memory leak to me.  Why are you
> kmallocing
> > > > this memory - why can't it be part of the dma_pl330_chan
> structure?  It's
> > > > only 28 bytes.
> > >
> > > It's my mistake. I should have been free of the memory.
> > >
> > > And the reason why I use kmalloc for 'cyclic_task' is following.
> > > This memory size for 'cyclic_tasklet' is the 896 bytes ( = the
> number of
> > > channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And
> This
> > > memory size is increased according to the number of DMAC.
> > > And Samsung has the DMAC that is dedicated for Mem-to-Mem
> operation. If I
> > > make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is
> dedicated
> > > for Mem-to-Mem operation should hold unused data.
> > > So, I think it's loss that all dma channels hold own 'cyclic_task'.
> >
> > Could you re-use the tasklet that already exists?
>
>
> --
> ~Vinod Koul
> Intel Corp.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-25 12:36             ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 12:36 UTC (permalink / raw)
  To: linux-arm-kernel

Vinod Koul Wrote:
> Sent: Monday, July 25, 2011 7:48 PM
> To: Russell King - ARM Linux
> Cc: vinod.koul at intel.com; Boojin Kim; 'Kukjin Kim'; 'Jassi Brar';
> 'Grant Likely'; linux-samsung-soc at vger.kernel.org; 'Mark Brown'; 'Dan
> Williams'; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
>
> On Mon, 2011-07-25 at 11:36 +0100, Russell King - ARM Linux wrote:
> > On Mon, Jul 25, 2011 at 07:31:45PM +0900, Boojin Kim wrote:
> > > > On Mon, Jul 25, 2011 at 10:28:22AM +0900, Boojin Kim wrote:
> > > > > +static void pl330_tasklet_cyclic(unsigned long data)
> > > > > +{
> > > > > +	struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > > > > +	struct dma_pl330_desc *desc, *_dt;
> > > > > +	unsigned long flags;
> > > > > +	LIST_HEAD(list);
> > > > > +
> > > > > +	spin_lock_irqsave(&pch->lock, flags);
> > > > ...
> > > > > +			callback = desc->txd.callback;
> > > > > +			if (callback)
> > > > > +				callback(desc->txd.callback_param);
> > > >
> > > > On this again - what if the callback wants to terminate the DMA
> activity
> > > > because there's no more audio data to be sent/received from the
> device?
> > >
> > > Do you mean what is happened if the callback() is called after
> channel is
> > > terminated ?
> > > Or What is happened if Callback() calls 'dma_release_channel()' to
> terminate
> > > DMA?
> >
> > No.  I mean what if the callback wants to call
> dmaengine_terminate_all().
> you are supposed to drop the lock here, that way callback can call any
> DMA API, otherwise it will result in deadlock.
> This make me wonder you haven't read the documentation at all, please
> ensure you have read Documentation/dmaengine.txt before next posting
I found the deadlock problem that you post. I will fix it and read the 
document again.

> >
> > > > > +	if (!pch->cyclic_task) {
> > > > > +		pch->cyclic_task =
> > > > > +			kmalloc(sizeof(struct tasklet_struct),
> GFP_KERNEL);
> > > > > +		tasklet_init(pch->cyclic_task,
> > > > > +			pl330_tasklet_cyclic, (unsigned int)pch);
> > > >
> > > > Here you allocate memory for the cyclic task.  Above you set this
> pointer
> > > > to NULL.  That sounds like a memory leak to me.  Why are you
> kmallocing
> > > > this memory - why can't it be part of the dma_pl330_chan
> structure?  It's
> > > > only 28 bytes.
> > >
> > > It's my mistake. I should have been free of the memory.
> > >
> > > And the reason why I use kmalloc for 'cyclic_task' is following.
> > > This memory size for 'cyclic_tasklet' is the 896 bytes ( = the
> number of
> > > channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And
> This
> > > memory size is increased according to the number of DMAC.
> > > And Samsung has the DMAC that is dedicated for Mem-to-Mem
> operation. If I
> > > make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is
> dedicated
> > > for Mem-to-Mem operation should hold unused data.
> > > So, I think it's loss that all dma channels hold own 'cyclic_task'.
> >
> > Could you re-use the tasklet that already exists?
>
>
> --
> ~Vinod Koul
> Intel Corp.

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

* RE: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
  2011-07-25 10:26     ` Vinod Koul
@ 2011-07-25 12:51       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 12:51 UTC (permalink / raw)
  To: 'Vinod Koul'
  Cc: vinod.koul, linux-arm-kernel, linux-samsung-soc,
	'Kukjin Kim', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams'

Vinod Koul Wrote:
> Sent: Monday, July 25, 2011 7:27 PM
> To: Boojin Kim
> Cc: vinod.koul@intel.com; linux-arm-kernel@lists.infradead.org; linux-
> samsung-soc@vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG
> command
>
> On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > This patch adds support DMA_SLAVE_CONFIG command.
> >
> > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > ---
> >  drivers/dma/pl330.c |   53 +++++++++++++++++++++++++++++++++++++----
> ---------
> >  1 files changed, 39 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > index 586ab39..880f010 100644
> > --- a/drivers/dma/pl330.c
> > +++ b/drivers/dma/pl330.c
> > @@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct
> dma_chan *chan)
> >  static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd
> cmd, unsigned long arg)
> >  {
> >  	struct dma_pl330_chan *pch = to_pchan(chan);
> > -	struct dma_pl330_desc *desc;
> > +	struct dma_pl330_desc *desc, *_dt;
> >  	unsigned long flags;
> > +	struct dma_pl330_dmac *pdmac = pch->dmac;
> > +	struct dma_slave_config *slave_config;
> > +	struct dma_pl330_peri *peri;
> > +	LIST_HEAD(list);
> >
> > -	/* Only supports DMA_TERMINATE_ALL */
> > -	if (cmd != DMA_TERMINATE_ALL)
> > -		return -ENXIO;
> > -
> > -	spin_lock_irqsave(&pch->lock, flags);
> > -
> > -	/* FLUSH the PL330 Channel thread */
> > -	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > +	switch (cmd) {
> > +	case DMA_TERMINATE_ALL:
> > +		spin_lock_irqsave(&pch->lock, flags);
> >
> > -	/* Mark all desc done */
> > -	list_for_each_entry(desc, &pch->work_list, node)
> > -		desc->status = DONE;
> > +		/* FLUSH the PL330 Channel thread */
> > +		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> >
> > -	spin_unlock_irqrestore(&pch->lock, flags);
> > +		/* Mark all desc done */
> > +		list_for_each_entry_safe(desc, _dt, &pch->work_list , node)
> {
> > +			desc->status = DONE;
> > +			pch->completed = desc->txd.cookie;
> > +			list_move_tail(&desc->node, &list);
> > +		}
> >
> > -	pl330_tasklet((unsigned long) pch);
> > +		list_splice_tail_init(&list, &pdmac->desc_pool);
> > +		spin_unlock_irqrestore(&pch->lock, flags);
> > +		break;
> > +	case DMA_SLAVE_CONFIG:
> > +		slave_config = (struct dma_slave_config *)arg;
> > +		peri = pch->chan.private;
> > +
> > +		if (slave_config->direction == DMA_TO_DEVICE) {
> > +			if (slave_config->dst_addr)
> > +				peri->fifo_addr = slave_config->dst_addr;
> > +			if (slave_config->dst_addr_width)
> > +				peri->burst_sz = __ffs(slave_config-
> >dst_addr_width);
> This doesn't sound right, why can't you use xxx_maxburst field instead?
Can you explain the problem in more detail?
Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or __ffs() 
isn't proper here?

Additionally, I will modify this code to consider '_maxburst' field.

>
> > +		} else if (slave_config->direction == DMA_FROM_DEVICE) {
> > +			if (slave_config->src_addr)
> > +				peri->fifo_addr = slave_config->src_addr;
> > +			if (slave_config->src_addr_width)
> > +				peri->burst_sz = __ffs(slave_config-
> >src_addr_width);
> ditto...
> > +		}
> > +		break;
> > +	default:
> > +		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
> > +		return -ENXIO;
> > +	}
> >
> >  	return 0;
> >  }
>
> --
> ~Vinod Koul
> Intel Corp.

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

* [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
@ 2011-07-25 12:51       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 12:51 UTC (permalink / raw)
  To: linux-arm-kernel

Vinod Koul Wrote:
> Sent: Monday, July 25, 2011 7:27 PM
> To: Boojin Kim
> Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux-
> samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG
> command
>
> On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > This patch adds support DMA_SLAVE_CONFIG command.
> >
> > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > ---
> >  drivers/dma/pl330.c |   53 +++++++++++++++++++++++++++++++++++++----
> ---------
> >  1 files changed, 39 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > index 586ab39..880f010 100644
> > --- a/drivers/dma/pl330.c
> > +++ b/drivers/dma/pl330.c
> > @@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct
> dma_chan *chan)
> >  static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd
> cmd, unsigned long arg)
> >  {
> >  	struct dma_pl330_chan *pch = to_pchan(chan);
> > -	struct dma_pl330_desc *desc;
> > +	struct dma_pl330_desc *desc, *_dt;
> >  	unsigned long flags;
> > +	struct dma_pl330_dmac *pdmac = pch->dmac;
> > +	struct dma_slave_config *slave_config;
> > +	struct dma_pl330_peri *peri;
> > +	LIST_HEAD(list);
> >
> > -	/* Only supports DMA_TERMINATE_ALL */
> > -	if (cmd != DMA_TERMINATE_ALL)
> > -		return -ENXIO;
> > -
> > -	spin_lock_irqsave(&pch->lock, flags);
> > -
> > -	/* FLUSH the PL330 Channel thread */
> > -	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > +	switch (cmd) {
> > +	case DMA_TERMINATE_ALL:
> > +		spin_lock_irqsave(&pch->lock, flags);
> >
> > -	/* Mark all desc done */
> > -	list_for_each_entry(desc, &pch->work_list, node)
> > -		desc->status = DONE;
> > +		/* FLUSH the PL330 Channel thread */
> > +		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> >
> > -	spin_unlock_irqrestore(&pch->lock, flags);
> > +		/* Mark all desc done */
> > +		list_for_each_entry_safe(desc, _dt, &pch->work_list , node)
> {
> > +			desc->status = DONE;
> > +			pch->completed = desc->txd.cookie;
> > +			list_move_tail(&desc->node, &list);
> > +		}
> >
> > -	pl330_tasklet((unsigned long) pch);
> > +		list_splice_tail_init(&list, &pdmac->desc_pool);
> > +		spin_unlock_irqrestore(&pch->lock, flags);
> > +		break;
> > +	case DMA_SLAVE_CONFIG:
> > +		slave_config = (struct dma_slave_config *)arg;
> > +		peri = pch->chan.private;
> > +
> > +		if (slave_config->direction == DMA_TO_DEVICE) {
> > +			if (slave_config->dst_addr)
> > +				peri->fifo_addr = slave_config->dst_addr;
> > +			if (slave_config->dst_addr_width)
> > +				peri->burst_sz = __ffs(slave_config-
> >dst_addr_width);
> This doesn't sound right, why can't you use xxx_maxburst field instead?
Can you explain the problem in more detail?
Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or __ffs() 
isn't proper here?

Additionally, I will modify this code to consider '_maxburst' field.

>
> > +		} else if (slave_config->direction == DMA_FROM_DEVICE) {
> > +			if (slave_config->src_addr)
> > +				peri->fifo_addr = slave_config->src_addr;
> > +			if (slave_config->src_addr_width)
> > +				peri->burst_sz = __ffs(slave_config-
> >src_addr_width);
> ditto...
> > +		}
> > +		break;
> > +	default:
> > +		dev_err(pch->dmac->pif.dev, "Not supported command.\n");
> > +		return -ENXIO;
> > +	}
> >
> >  	return 0;
> >  }
>
> --
> ~Vinod Koul
> Intel Corp.

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

* RE: [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
  2011-07-25 11:59     ` Jassi Brar
@ 2011-07-25 12:59       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 12:59 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Vinod Koul',
	'Dan Williams', 'Kukjin Kim',
	'Grant Likely', 'Mark Brown'

Jassi Brar Wrote:
> Sent: Monday, July 25, 2011 9:00 PM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> Likely; Mark Brown
> Subject: Re: [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330
> driver
>
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
>
> > diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-
> exynos4/dma.c
> > index 564bb53..e1c00cf 100644
> > --- a/arch/arm/mach-exynos4/dma.c
> > +++ b/arch/arm/mach-exynos4/dma.c
> > @@ -21,151 +21,250 @@
> >  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> >  */
> >
> > -#include <linux/platform_device.h>
> >  #include <linux/dma-mapping.h>
> > +#include <linux/amba/bus.h>
> > +#include <linux/amba/pl330.h>
> >
> > +#include <asm/irq.h>
> >  #include <plat/devs.h>
> >  #include <plat/irqs.h>
> >
> >  #include <mach/map.h>
> >  #include <mach/irqs.h>
> > -
> > -#include <plat/s3c-pl330-pdata.h>
> > +#include <mach/dma.h>
> >
> >  static u64 dma_dmamask = DMA_BIT_MASK(32);
> >
> > -static struct resource exynos4_pdma0_resource[] = {
> > -       [0] = {
> > -               .start  = EXYNOS4_PA_PDMA0,
> > -               .end    = EXYNOS4_PA_PDMA0 + SZ_4K,
> > -               .flags  = IORESOURCE_MEM,
> > -       },
> > -       [1] = {
> > -               .start  = IRQ_PDMA0,
> > -               .end    = IRQ_PDMA0,
> > -               .flags  = IORESOURCE_IRQ,
> > +struct dma_pl330_peri pdma0_peri[32] = {
> Please remove 32 from the list (it seems you don't always pass 32
> elements)
> Also for completeness, please explicitly write element indices below
> because
> it's not some array of randomly placed elements.
> Same for every other such occurance.
I will address your comment.

>
> > +       {
> > +               .peri_id = (u8)DMACH_PCM0_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_PCM0_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_PCM2_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_PCM2_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_MSM_REQ0,
> > +       }, {
> > +               .peri_id = (u8)DMACH_MSM_REQ2,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SPI0_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 1,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SPI0_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 1,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SPI2_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 1,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SPI2_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 1,
> > +       }, {
> > +               .peri_id = (u8)DMACH_I2S0S_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_I2S0_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_I2S0_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART0_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART0_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART2_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART2_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART4_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART4_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS0_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS0_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS2_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS2_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS4_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS4_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_AC97_MICIN,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_AC97_PCMIN,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_AC97_PCMOUT,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> >        },
> >  };
>
>
> >
> > -static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
> > -       .peri = {
> > -               [0] = DMACH_PCM0_RX,
> > -               [1] = DMACH_PCM0_TX,
> > -               [2] = DMACH_PCM2_RX,
> > -               [3] = DMACH_PCM2_TX,
> > -               [4] = DMACH_MSM_REQ0,
> > -               [5] = DMACH_MSM_REQ2,
> > -               [6] = DMACH_SPI0_RX,
> > -               [7] = DMACH_SPI0_TX,
> > -               [8] = DMACH_SPI2_RX,
> > -               [9] = DMACH_SPI2_TX,
> > -               [10] = DMACH_I2S0S_TX,
> > -               [11] = DMACH_I2S0_RX,
> > -               [12] = DMACH_I2S0_TX,
> > -               [13] = DMACH_I2S2_RX,
> > -               [14] = DMACH_I2S2_TX,
> > -               [15] = DMACH_UART0_RX,
> > -               [16] = DMACH_UART0_TX,
> > -               [17] = DMACH_UART2_RX,
> > -               [18] = DMACH_UART2_TX,
> > -               [19] = DMACH_UART4_RX,
> > -               [20] = DMACH_UART4_TX,
> > -               [21] = DMACH_SLIMBUS0_RX,
> > -               [22] = DMACH_SLIMBUS0_TX,
> > -               [23] = DMACH_SLIMBUS2_RX,
> > -               [24] = DMACH_SLIMBUS2_TX,
> > -               [25] = DMACH_SLIMBUS4_RX,
> > -               [26] = DMACH_SLIMBUS4_TX,
> > -               [27] = DMACH_AC97_MICIN,
> > -               [28] = DMACH_AC97_PCMIN,
> > -               [29] = DMACH_AC97_PCMOUT,
> > -               [30] = DMACH_MAX,
> > -               [31] = DMACH_MAX,
> > -       },
> > +struct dma_pl330_platdata exynos4_pdma0_pdata = {
> > +       .nr_valid_peri = 32,
> Perhaps, this is why you had to add the NULL peri check.
> Please use ARRAY_SIZE here.
> Same for every other such occurance.
I will address your comment.

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

* [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
@ 2011-07-25 12:59       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-25 12:59 UTC (permalink / raw)
  To: linux-arm-kernel

Jassi Brar Wrote:
> Sent: Monday, July 25, 2011 9:00 PM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> Likely; Mark Brown
> Subject: Re: [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330
> driver
>
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
>
> > diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-
> exynos4/dma.c
> > index 564bb53..e1c00cf 100644
> > --- a/arch/arm/mach-exynos4/dma.c
> > +++ b/arch/arm/mach-exynos4/dma.c
> > @@ -21,151 +21,250 @@
> >  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> >  */
> >
> > -#include <linux/platform_device.h>
> >  #include <linux/dma-mapping.h>
> > +#include <linux/amba/bus.h>
> > +#include <linux/amba/pl330.h>
> >
> > +#include <asm/irq.h>
> >  #include <plat/devs.h>
> >  #include <plat/irqs.h>
> >
> >  #include <mach/map.h>
> >  #include <mach/irqs.h>
> > -
> > -#include <plat/s3c-pl330-pdata.h>
> > +#include <mach/dma.h>
> >
> >  static u64 dma_dmamask = DMA_BIT_MASK(32);
> >
> > -static struct resource exynos4_pdma0_resource[] = {
> > -       [0] = {
> > -               .start  = EXYNOS4_PA_PDMA0,
> > -               .end    = EXYNOS4_PA_PDMA0 + SZ_4K,
> > -               .flags  = IORESOURCE_MEM,
> > -       },
> > -       [1] = {
> > -               .start  = IRQ_PDMA0,
> > -               .end    = IRQ_PDMA0,
> > -               .flags  = IORESOURCE_IRQ,
> > +struct dma_pl330_peri pdma0_peri[32] = {
> Please remove 32 from the list (it seems you don't always pass 32
> elements)
> Also for completeness, please explicitly write element indices below
> because
> it's not some array of randomly placed elements.
> Same for every other such occurance.
I will address your comment.

>
> > +       {
> > +               .peri_id = (u8)DMACH_PCM0_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_PCM0_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_PCM2_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_PCM2_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_MSM_REQ0,
> > +       }, {
> > +               .peri_id = (u8)DMACH_MSM_REQ2,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SPI0_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 1,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SPI0_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 1,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SPI2_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 1,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SPI2_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 1,
> > +       }, {
> > +               .peri_id = (u8)DMACH_I2S0S_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_I2S0_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_I2S0_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART0_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART0_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART2_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART2_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART4_RX,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_UART4_TX,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS0_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS0_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS2_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS2_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS4_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> > +               .peri_id = (u8)DMACH_SLIMBUS4_TX,
> > +               .rqtype = MEMTODEV,
> > +       }, {
> > +               .peri_id = (u8)DMACH_AC97_MICIN,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_AC97_PCMIN,
> > +               .rqtype = DEVTOMEM,
> > +               .burst_sz = 4,
> > +       }, {
> > +               .peri_id = (u8)DMACH_AC97_PCMOUT,
> > +               .rqtype = MEMTODEV,
> > +               .burst_sz = 4,
> >        },
> >  };
>
>
> >
> > -static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
> > -       .peri = {
> > -               [0] = DMACH_PCM0_RX,
> > -               [1] = DMACH_PCM0_TX,
> > -               [2] = DMACH_PCM2_RX,
> > -               [3] = DMACH_PCM2_TX,
> > -               [4] = DMACH_MSM_REQ0,
> > -               [5] = DMACH_MSM_REQ2,
> > -               [6] = DMACH_SPI0_RX,
> > -               [7] = DMACH_SPI0_TX,
> > -               [8] = DMACH_SPI2_RX,
> > -               [9] = DMACH_SPI2_TX,
> > -               [10] = DMACH_I2S0S_TX,
> > -               [11] = DMACH_I2S0_RX,
> > -               [12] = DMACH_I2S0_TX,
> > -               [13] = DMACH_I2S2_RX,
> > -               [14] = DMACH_I2S2_TX,
> > -               [15] = DMACH_UART0_RX,
> > -               [16] = DMACH_UART0_TX,
> > -               [17] = DMACH_UART2_RX,
> > -               [18] = DMACH_UART2_TX,
> > -               [19] = DMACH_UART4_RX,
> > -               [20] = DMACH_UART4_TX,
> > -               [21] = DMACH_SLIMBUS0_RX,
> > -               [22] = DMACH_SLIMBUS0_TX,
> > -               [23] = DMACH_SLIMBUS2_RX,
> > -               [24] = DMACH_SLIMBUS2_TX,
> > -               [25] = DMACH_SLIMBUS4_RX,
> > -               [26] = DMACH_SLIMBUS4_TX,
> > -               [27] = DMACH_AC97_MICIN,
> > -               [28] = DMACH_AC97_PCMIN,
> > -               [29] = DMACH_AC97_PCMOUT,
> > -               [30] = DMACH_MAX,
> > -               [31] = DMACH_MAX,
> > -       },
> > +struct dma_pl330_platdata exynos4_pdma0_pdata = {
> > +       .nr_valid_peri = 32,
> Perhaps, this is why you had to add the NULL peri check.
> Please use ARRAY_SIZE here.
> Same for every other such occurance.
I will address your comment.

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

* RE: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
  2011-07-25 12:51       ` Boojin Kim
@ 2011-07-25 13:48         ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 13:48 UTC (permalink / raw)
  To: Boojin Kim
  Cc: vinod.koul, linux-arm-kernel, linux-samsung-soc,
	'Kukjin Kim', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams'

On Mon, 2011-07-25 at 21:51 +0900, Boojin Kim wrote:
> Vinod Koul Wrote:
> > Sent: Monday, July 25, 2011 7:27 PM
> > To: Boojin Kim
> > Cc: vinod.koul@intel.com; linux-arm-kernel@lists.infradead.org; linux-
> > samsung-soc@vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> > Mark Brown; Dan Williams
> > Subject: Re: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG
> > command
> >
> > On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > > This patch adds support DMA_SLAVE_CONFIG command.
> > >
> > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > ---
> > >  drivers/dma/pl330.c |   53 +++++++++++++++++++++++++++++++++++++----
> > ---------
> > >  1 files changed, 39 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > > index 586ab39..880f010 100644
> > > --- a/drivers/dma/pl330.c
> > > +++ b/drivers/dma/pl330.c
> > > @@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct
> > dma_chan *chan)
> > >  static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd
> > cmd, unsigned long arg)
> > >  {
> > >  	struct dma_pl330_chan *pch = to_pchan(chan);
> > > -	struct dma_pl330_desc *desc;
> > > +	struct dma_pl330_desc *desc, *_dt;
> > >  	unsigned long flags;
> > > +	struct dma_pl330_dmac *pdmac = pch->dmac;
> > > +	struct dma_slave_config *slave_config;
> > > +	struct dma_pl330_peri *peri;
> > > +	LIST_HEAD(list);
> > >
> > > -	/* Only supports DMA_TERMINATE_ALL */
> > > -	if (cmd != DMA_TERMINATE_ALL)
> > > -		return -ENXIO;
> > > -
> > > -	spin_lock_irqsave(&pch->lock, flags);
> > > -
> > > -	/* FLUSH the PL330 Channel thread */
> > > -	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > > +	switch (cmd) {
> > > +	case DMA_TERMINATE_ALL:
> > > +		spin_lock_irqsave(&pch->lock, flags);
> > >
> > > -	/* Mark all desc done */
> > > -	list_for_each_entry(desc, &pch->work_list, node)
> > > -		desc->status = DONE;
> > > +		/* FLUSH the PL330 Channel thread */
> > > +		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > >
> > > -	spin_unlock_irqrestore(&pch->lock, flags);
> > > +		/* Mark all desc done */
> > > +		list_for_each_entry_safe(desc, _dt, &pch->work_list , node)
> > {
> > > +			desc->status = DONE;
> > > +			pch->completed = desc->txd.cookie;
> > > +			list_move_tail(&desc->node, &list);
> > > +		}
> > >
> > > -	pl330_tasklet((unsigned long) pch);
> > > +		list_splice_tail_init(&list, &pdmac->desc_pool);
> > > +		spin_unlock_irqrestore(&pch->lock, flags);
> > > +		break;
> > > +	case DMA_SLAVE_CONFIG:
> > > +		slave_config = (struct dma_slave_config *)arg;
> > > +		peri = pch->chan.private;
> > > +
> > > +		if (slave_config->direction == DMA_TO_DEVICE) {
> > > +			if (slave_config->dst_addr)
> > > +				peri->fifo_addr = slave_config->dst_addr;
> > > +			if (slave_config->dst_addr_width)
> > > +				peri->burst_sz = __ffs(slave_config-
> > >dst_addr_width);
> > This doesn't sound right, why can't you use xxx_maxburst field instead?
> Can you explain the problem in more detail?
> Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or __ffs() 
> isn't proper here?
> 
> Additionally, I will modify this code to consider '_maxburst' field.
__ffs is okay and sensible.
I meant you should use proper fields for passing info, which in this
case would be dst_maxburst for specifying destination burst sizes
-- 
~Vinod Koul
Intel Corp.

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

* [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
@ 2011-07-25 13:48         ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-25 13:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-25 at 21:51 +0900, Boojin Kim wrote:
> Vinod Koul Wrote:
> > Sent: Monday, July 25, 2011 7:27 PM
> > To: Boojin Kim
> > Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux-
> > samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> > Mark Brown; Dan Williams
> > Subject: Re: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG
> > command
> >
> > On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > > This patch adds support DMA_SLAVE_CONFIG command.
> > >
> > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > ---
> > >  drivers/dma/pl330.c |   53 +++++++++++++++++++++++++++++++++++++----
> > ---------
> > >  1 files changed, 39 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > > index 586ab39..880f010 100644
> > > --- a/drivers/dma/pl330.c
> > > +++ b/drivers/dma/pl330.c
> > > @@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct
> > dma_chan *chan)
> > >  static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd
> > cmd, unsigned long arg)
> > >  {
> > >  	struct dma_pl330_chan *pch = to_pchan(chan);
> > > -	struct dma_pl330_desc *desc;
> > > +	struct dma_pl330_desc *desc, *_dt;
> > >  	unsigned long flags;
> > > +	struct dma_pl330_dmac *pdmac = pch->dmac;
> > > +	struct dma_slave_config *slave_config;
> > > +	struct dma_pl330_peri *peri;
> > > +	LIST_HEAD(list);
> > >
> > > -	/* Only supports DMA_TERMINATE_ALL */
> > > -	if (cmd != DMA_TERMINATE_ALL)
> > > -		return -ENXIO;
> > > -
> > > -	spin_lock_irqsave(&pch->lock, flags);
> > > -
> > > -	/* FLUSH the PL330 Channel thread */
> > > -	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > > +	switch (cmd) {
> > > +	case DMA_TERMINATE_ALL:
> > > +		spin_lock_irqsave(&pch->lock, flags);
> > >
> > > -	/* Mark all desc done */
> > > -	list_for_each_entry(desc, &pch->work_list, node)
> > > -		desc->status = DONE;
> > > +		/* FLUSH the PL330 Channel thread */
> > > +		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > >
> > > -	spin_unlock_irqrestore(&pch->lock, flags);
> > > +		/* Mark all desc done */
> > > +		list_for_each_entry_safe(desc, _dt, &pch->work_list , node)
> > {
> > > +			desc->status = DONE;
> > > +			pch->completed = desc->txd.cookie;
> > > +			list_move_tail(&desc->node, &list);
> > > +		}
> > >
> > > -	pl330_tasklet((unsigned long) pch);
> > > +		list_splice_tail_init(&list, &pdmac->desc_pool);
> > > +		spin_unlock_irqrestore(&pch->lock, flags);
> > > +		break;
> > > +	case DMA_SLAVE_CONFIG:
> > > +		slave_config = (struct dma_slave_config *)arg;
> > > +		peri = pch->chan.private;
> > > +
> > > +		if (slave_config->direction == DMA_TO_DEVICE) {
> > > +			if (slave_config->dst_addr)
> > > +				peri->fifo_addr = slave_config->dst_addr;
> > > +			if (slave_config->dst_addr_width)
> > > +				peri->burst_sz = __ffs(slave_config-
> > >dst_addr_width);
> > This doesn't sound right, why can't you use xxx_maxburst field instead?
> Can you explain the problem in more detail?
> Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or __ffs() 
> isn't proper here?
> 
> Additionally, I will modify this code to consider '_maxburst' field.
__ffs is okay and sensible.
I meant you should use proper fields for passing info, which in this
case would be dst_maxburst for specifying destination burst sizes
-- 
~Vinod Koul
Intel Corp.

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

* Re: [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
  2011-07-25 12:08     ` Jassi Brar
@ 2011-07-25 21:15       ` Grant Likely
  -1 siblings, 0 replies; 146+ messages in thread
From: Grant Likely @ 2011-07-25 21:15 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Boojin Kim, linux-arm-kernel, linux-samsung-soc, Vinod Koul,
	Dan Williams, Kukjin Kim, Mark Brown

On Mon, Jul 25, 2011 at 05:38:37PM +0530, Jassi Brar wrote:
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> > This patch removes the samsung specific enum type 's3c2410_dmasrc'
> > and uses 'dma_data_direction' instead.
> >
> > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> 
> Acked-by: Jassi Brar <jassisinghbrar@gmail.com>
> 
> If this patch was first in the patchset, probably it could have been
> already merged.

Indeed.  If you move this to the front when you post the next version
then it can be merged right away.

Acked-by: Grant Likely <grant.likely@secretlab.ca>

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

* [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
@ 2011-07-25 21:15       ` Grant Likely
  0 siblings, 0 replies; 146+ messages in thread
From: Grant Likely @ 2011-07-25 21:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 05:38:37PM +0530, Jassi Brar wrote:
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> > This patch removes the samsung specific enum type 's3c2410_dmasrc'
> > and uses 'dma_data_direction' instead.
> >
> > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> 
> Acked-by: Jassi Brar <jassisinghbrar@gmail.com>
> 
> If this patch was first in the patchset, probably it could have been
> already merged.

Indeed.  If you move this to the front when you post the next version
then it can be merged right away.

Acked-by: Grant Likely <grant.likely@secretlab.ca>

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

* Re: [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
  2011-07-25  1:28   ` Boojin Kim
@ 2011-07-26  6:03     ` Chanwoo Choi
  -1 siblings, 0 replies; 146+ messages in thread
From: Chanwoo Choi @ 2011-07-26  6:03 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Kukjin Kim, Vinod Koul,
	Jassi Brar, Grant Likely, Mark Brown, Dan Williams

Boojin Kim wrote:
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> ---
>  drivers/dma/pl330.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 73 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 6abe1ec..b7ecf47 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -17,6 +17,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/amba/bus.h>
>  #include <linux/amba/pl330.h>
> +#include <linux/pm_runtime.h>
>  
>  #define NR_DEFAULT_DESC	16
>  
> @@ -83,6 +84,8 @@ struct dma_pl330_dmac {
>  
>  	/* Peripheral channels connected to this DMAC */
>  	struct dma_pl330_chan peripherals[0]; /* keep at end */
> +
> +	struct clk *clk;
>  };
>  
>  struct dma_pl330_desc {
> @@ -696,6 +699,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
>  		goto probe_err1;
>  	}
>  
> +	pdmac->clk = clk_get(&adev->dev, "dma");
> +	if (IS_ERR(pdmac->clk)) {
> +		dev_err(&adev->dev, "Cannot get operation clock.\n");
> +		ret = -EINVAL;
> +		goto probe_err1;
> +	}
> +
> +	amba_set_drvdata(adev, pdmac);
> +
> +#ifdef CONFIG_PM_RUNTIME
> +	/* to use the runtime PM helper functions */
> +	pm_runtime_enable(&adev->dev);
> +
> +	/* enable the power domain */
> +	if (pm_runtime_get_sync(&adev->dev)) {
> +		dev_err(&adev->dev, "failed to get runtime pm\n");
> +		ret = -ENODEV;
> +		goto probe_err1;
> +	}
> +#else
> +	/* enable dma clk */
> +	clk_enable(pdmac->clk);
> +#endif
> +
>  	irq = adev->irq[0];
>  	ret = request_irq(irq, pl330_irq_handler, 0,
>  			dev_name(&adev->dev), pi);
> @@ -763,8 +790,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
>  		goto probe_err4;
>  	}
>  
> -	amba_set_drvdata(adev, pdmac);
> -
>  	dev_info(&adev->dev,
>  		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
>  	dev_info(&adev->dev,
> @@ -825,6 +850,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
>  	res = &adev->res;
>  	release_mem_region(res->start, resource_size(res));
>  
> +#ifdef CONFIG_PM_RUNTIME
> +	pm_runtime_put(&adev->dev);
> +	pm_runtime_disable(&adev->dev);
> +#else
> +	clk_disable(pdmac->clk);
> +#endif
> +
>  	kfree(pdmac);
>  
>  	return 0;
> @@ -838,10 +870,49 @@ static struct amba_id pl330_ids[] = {
>  	{ 0, 0 },
>  };
>  
> +#ifdef CONFIG_PM_RUNTIME
> +static int pl330_runtime_suspend(struct device *dev)
> +{
> +	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
> +
> +	if (!pdmac) {
> +		dev_err(dev, "failed to get dmac\n");
> +		return -ENODEV;
> +	}
> +
> +	clk_disable(pdmac->clk);
> +
> +	return 0;
> +}
> +
> +static int pl330_runtime_resume(struct device *dev)
> +{
> +	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
> +
> +	if (!pdmac) {
> +		dev_err(dev, "failed to get dmac\n");
> +		return -ENODEV;
> +	}
> +
> +	clk_enable(pdmac->clk);
> +
> +	return 0;
> +}
> +#else
> +#define pl330_runtime_suspend	NULL
> +#define pl330_runtime_resume	NULL
> +#endif /* CONFIG_PM_RUNTIME */
> +
> +static const struct dev_pm_ops pl330_pm_ops = {
> +	.runtime_suspend = pl330_runtime_suspend,
> +	.runtime_resume = pl330_runtime_resume,
> +};
> +
>  static struct amba_driver pl330_driver = {
>  	.drv = {
>  		.owner = THIS_MODULE,
>  		.name = "dma-pl330",
> +		.pm = &pl330_pm_ops,
>  	},
>  	.id_table = pl330_ids,
>  	.probe = pl330_probe,

I have a question for runtime PM of PL330 DMAC

This patch support runtime PM for PL330 DMAC, but the clock of "dma" is always on.
If the clock of "dma" is always on, additional power(10mA) is consumed. I tested it.

I think that the PL330 DMAC only turn on the clock of "dma" when using DMA.


Thanks,
Chanwoo Choi

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

* [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC
@ 2011-07-26  6:03     ` Chanwoo Choi
  0 siblings, 0 replies; 146+ messages in thread
From: Chanwoo Choi @ 2011-07-26  6:03 UTC (permalink / raw)
  To: linux-arm-kernel

Boojin Kim wrote:
> Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> ---
>  drivers/dma/pl330.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 73 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 6abe1ec..b7ecf47 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -17,6 +17,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/amba/bus.h>
>  #include <linux/amba/pl330.h>
> +#include <linux/pm_runtime.h>
>  
>  #define NR_DEFAULT_DESC	16
>  
> @@ -83,6 +84,8 @@ struct dma_pl330_dmac {
>  
>  	/* Peripheral channels connected to this DMAC */
>  	struct dma_pl330_chan peripherals[0]; /* keep at end */
> +
> +	struct clk *clk;
>  };
>  
>  struct dma_pl330_desc {
> @@ -696,6 +699,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
>  		goto probe_err1;
>  	}
>  
> +	pdmac->clk = clk_get(&adev->dev, "dma");
> +	if (IS_ERR(pdmac->clk)) {
> +		dev_err(&adev->dev, "Cannot get operation clock.\n");
> +		ret = -EINVAL;
> +		goto probe_err1;
> +	}
> +
> +	amba_set_drvdata(adev, pdmac);
> +
> +#ifdef CONFIG_PM_RUNTIME
> +	/* to use the runtime PM helper functions */
> +	pm_runtime_enable(&adev->dev);
> +
> +	/* enable the power domain */
> +	if (pm_runtime_get_sync(&adev->dev)) {
> +		dev_err(&adev->dev, "failed to get runtime pm\n");
> +		ret = -ENODEV;
> +		goto probe_err1;
> +	}
> +#else
> +	/* enable dma clk */
> +	clk_enable(pdmac->clk);
> +#endif
> +
>  	irq = adev->irq[0];
>  	ret = request_irq(irq, pl330_irq_handler, 0,
>  			dev_name(&adev->dev), pi);
> @@ -763,8 +790,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
>  		goto probe_err4;
>  	}
>  
> -	amba_set_drvdata(adev, pdmac);
> -
>  	dev_info(&adev->dev,
>  		"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
>  	dev_info(&adev->dev,
> @@ -825,6 +850,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
>  	res = &adev->res;
>  	release_mem_region(res->start, resource_size(res));
>  
> +#ifdef CONFIG_PM_RUNTIME
> +	pm_runtime_put(&adev->dev);
> +	pm_runtime_disable(&adev->dev);
> +#else
> +	clk_disable(pdmac->clk);
> +#endif
> +
>  	kfree(pdmac);
>  
>  	return 0;
> @@ -838,10 +870,49 @@ static struct amba_id pl330_ids[] = {
>  	{ 0, 0 },
>  };
>  
> +#ifdef CONFIG_PM_RUNTIME
> +static int pl330_runtime_suspend(struct device *dev)
> +{
> +	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
> +
> +	if (!pdmac) {
> +		dev_err(dev, "failed to get dmac\n");
> +		return -ENODEV;
> +	}
> +
> +	clk_disable(pdmac->clk);
> +
> +	return 0;
> +}
> +
> +static int pl330_runtime_resume(struct device *dev)
> +{
> +	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
> +
> +	if (!pdmac) {
> +		dev_err(dev, "failed to get dmac\n");
> +		return -ENODEV;
> +	}
> +
> +	clk_enable(pdmac->clk);
> +
> +	return 0;
> +}
> +#else
> +#define pl330_runtime_suspend	NULL
> +#define pl330_runtime_resume	NULL
> +#endif /* CONFIG_PM_RUNTIME */
> +
> +static const struct dev_pm_ops pl330_pm_ops = {
> +	.runtime_suspend = pl330_runtime_suspend,
> +	.runtime_resume = pl330_runtime_resume,
> +};
> +
>  static struct amba_driver pl330_driver = {
>  	.drv = {
>  		.owner = THIS_MODULE,
>  		.name = "dma-pl330",
> +		.pm = &pl330_pm_ops,
>  	},
>  	.id_table = pl330_ids,
>  	.probe = pl330_probe,

I have a question for runtime PM of PL330 DMAC

This patch support runtime PM for PL330 DMAC, but the clock of "dma" is always on.
If the clock of "dma" is always on, additional power(10mA) is consumed. I tested it.

I think that the PL330 DMAC only turn on the clock of "dma" when using DMA.


Thanks,
Chanwoo Choi

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-25 12:01                   ` Vinod Koul
@ 2011-07-26  7:57                     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26  7:57 UTC (permalink / raw)
  To: Vinod Koul
  Cc: vinod.koul, Boojin Kim, 'Kukjin Kim',
	'Jassi Brar', 'Grant Likely',
	linux-samsung-soc, 'Mark Brown', 'Dan Williams',
	linux-arm-kernel

Here's an updated patch.

8<----------
From: Russell King <rmk+kernel@arm.linux.org.uk>
DMAEngine: Improve slave/cyclic documentation

Improve the documentation for the slave and cyclic DMA engine support
reformatting it for easier reading, adding further APIs, splitting it
into five steps, and including references to the documentation in
dmaengine.h.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
 1 files changed, 146 insertions(+), 65 deletions(-)

diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
index 5a0cb1e..8c2e888 100644
--- a/Documentation/dmaengine.txt
+++ b/Documentation/dmaengine.txt
@@ -10,87 +10,168 @@
 Below is a guide to device driver writers on how to use the Slave-DMA API of the
 DMA Engine. This is applicable only for slave DMA usage only.
 
-The slave DMA usage consists of following steps
+The slave DMA usage consists of following steps:
 1. Allocate a DMA slave channel
 2. Set slave and controller specific parameters
 3. Get a descriptor for transaction
 4. Submit the transaction and wait for callback notification
+5. Issue pending requests
 
 1. Allocate a DMA slave channel
-Channel allocation is slightly different in the slave DMA context, client
-drivers typically need a channel from a particular DMA controller only and even
-in some cases a specific channel is desired. To request a channel
-dma_request_channel() API is used.
-
-Interface:
-struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
-		dma_filter_fn filter_fn,
-		void *filter_param);
-where dma_filter_fn is defined as:
-typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
-
-When the optional 'filter_fn' parameter is set to NULL dma_request_channel
-simply returns the first channel that satisfies the capability mask.  Otherwise,
-when the mask parameter is insufficient for specifying the necessary channel,
-the filter_fn routine can be used to disposition the available channels in the
-system. The filter_fn routine is called once for each free channel in the
-system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
-that channel to be the return value from dma_request_channel.  A channel
-allocated via this interface is exclusive to the caller, until
-dma_release_channel() is called.
+
+   Channel allocation is slightly different in the slave DMA context,
+   client drivers typically need a channel from a particular DMA
+   controller only and even in some cases a specific channel is desired.
+   To request a channel dma_request_channel() API is used.
+
+   Interface:
+	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+			dma_filter_fn filter_fn,
+			void *filter_param);
+   where dma_filter_fn is defined as:
+	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
+
+   The 'filter_fn' parameter is optional, but highly recommended for
+   slave and cyclic channels as they typically need to obtain a specific
+   DMA channel.
+
+   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
+   simply returns the first channel that satisfies the capability mask.
+
+   Otherwise, the 'filter_fn' routine will be called once for each free
+   channel which has a capability in 'mask'.  'filter_fn' is expected to
+   return 'true' when the desired DMA channel is found.
+
+   A channel allocated via this interface is exclusive to the caller,
+   until dma_release_channel() is called.
 
 2. Set slave and controller specific parameters
-Next step is always to pass some specific information to the DMA driver. Most of
-the generic information which a slave DMA can use is in struct dma_slave_config.
-It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
-burst lengths etc. If some DMA controllers have more parameters to be sent then
-they should try to embed struct dma_slave_config in their controller specific
-structure. That gives flexibility to client to pass more parameters, if
-required.
-
-Interface:
-int dmaengine_slave_config(struct dma_chan *chan,
-					  struct dma_slave_config *config)
+
+   Next step is always to pass some specific information to the DMA
+   driver.  Most of the generic information which a slave DMA can use
+   is in struct dma_slave_config.  This allows the clients to specify
+   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
+   for the peripheral.
+
+   If some DMA controllers have more parameters to be sent then they
+   should try to embed struct dma_slave_config in their controller
+   specific structure. That gives flexibility to client to pass more
+   parameters, if required.
+
+   Interface:
+	int dmaengine_slave_config(struct dma_chan *chan,
+				  struct dma_slave_config *config)
+
+   Please see the dma_slave_config structure definition in dmaengine.h
+   for a detailed explaination of the struct members.  Please note
+   that the 'direction' member will be going away as it duplicates the
+   direction given in the prepare call.
 
 3. Get a descriptor for transaction
-For slave usage the various modes of slave transfers supported by the
-DMA-engine are:
-slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
-dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
+
+   For slave usage the various modes of slave transfers supported by the
+   DMA-engine are:
+
+   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
+   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
 		  operation is explicitly stopped.
-The non NULL return of this transfer API represents a "descriptor" for the given
-transaction.
 
-Interface:
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
+   A non-NULL return of this transfer API represents a "descriptor" for
+   the given transaction.
+
+   Interface:
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
 		struct dma_chan *chan,
 		struct scatterlist *dst_sg, unsigned int dst_nents,
 		struct scatterlist *src_sg, unsigned int src_nents,
 		unsigned long flags);
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_data_direction direction);
 
-4. Submit the transaction and wait for callback notification
-To schedule the transaction to be scheduled by dma device, the "descriptor"
-returned in above (3) needs to be submitted.
-To tell the dma driver that a transaction is ready to be serviced, the
-descriptor->submit() callback needs to be invoked. This chains the descriptor to
-the pending queue.
-The transactions in the pending queue can be activated by calling the
-issue_pending API. If channel is idle then the first transaction in queue is
-started and subsequent ones queued up.
-On completion of the DMA operation the next in queue is submitted and a tasklet
-triggered. The tasklet would then call the client driver completion callback
-routine for notification, if set.
-Interface:
-void dma_async_issue_pending(struct dma_chan *chan);
-
-==============================================================================
-
-Additional usage notes for dma driver writers
-1/ Although DMA engine specifies that completion callback routines cannot submit
-any new operations, but typically for slave DMA subsequent transaction may not
-be available for submit prior to callback routine being called. This requirement
-is not a requirement for DMA-slave devices. But they should take care to drop
-the spin-lock they might be holding before calling the callback routine
+   Once a descriptor has been obtained, the callback information can be
+   added and must then be submitted.  Some DMA engine drivers may hold a
+   spinlock between a successful preparation and submission so it is
+   important that these two operations are closely paired.
+
+   Note:
+	Although the async_tx API specifies that completion callback
+	routines cannot submit any new operations, this is not the
+	case for slave/cyclic DMA.
+
+	For slave DMA, the subsequent transaction may not be available
+	for submission prior to callback function being invoked, so
+	slave DMA callbacks are permitted to prepare and submit a new
+	transaction.
+
+	For cyclic DMA, a callback function may wish to terminate the
+	DMA via dmaengine_terminate_all().
+
+	Therefore, it is important that DMA engine drivers drop any
+	locks before calling the callback function which may cause a
+	deadlock.
+
+	Note that callbacks will always be invoked from the DMA
+	engines tasklet, never from interrupt context.
+
+4. Submit the transaction
+
+   Once the descriptor has been prepared and the callback information
+   added, it must be placed on the DMA engine drivers pending queue.
+
+   Interface:
+	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
+
+   This returns a cookie can be used to check the progress of DMA engine
+   activity via other DMA engine calls not covered in this document.
+
+   dmaengine_submit() will not start the DMA operation, it merely adds
+   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
+
+5. Issue pending DMA requests and wait for callback notification
+
+   The transactions in the pending queue can be activated by calling the
+   issue_pending API. If channel is idle then the first transaction in
+   queue is started and subsequent ones queued up.
+
+   On completion of each DMA operation, the next in queue is started and
+   a tasklet triggered. The tasklet will then call the client driver
+   completion callback routine for notification, if set.
+
+   Interface:
+	void dma_async_issue_pending(struct dma_chan *chan);
+
+Further APIs:
+
+1. int dmaengine_terminate_all(struct dma_chan *chan)
+
+   This causes all activity for the DMA channel to be stopped, and may
+   discard data in the DMA FIFO which hasn't been fully transferred.
+   No callback functions will be called for any incomplete transfers.
+
+2. int dmaengine_pause(struct dma_chan *chan)
+
+   This pauses activity on the DMA channel without data loss.
+
+3. int dmaengine_resume(struct dma_chan *chan)
+
+   Resume a previously paused DMA channel.  It is invalid to resume a
+   channel which is not currently paused.
+
+4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+
+   This can be used to check the status of the channel.  Please see
+   the documentation in include/linux/dmaengine.h for a more complete
+   description of this API.
+
+   This can be used in conjunction with dma_async_is_complete() and
+   the cookie returned from 'descriptor->submit()' to check for
+   completion of a specific DMA transaction.
+
+   Note:
+	Not all DMA engine drivers can return reliable information for
+	a running DMA channel.  It is recommended that DMA engine users
+	pause or stop (via dmaengine_terminate_all) the channel before
+	using this API.

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-26  7:57                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26  7:57 UTC (permalink / raw)
  To: linux-arm-kernel

Here's an updated patch.

8<----------
From: Russell King <rmk+kernel@arm.linux.org.uk>
DMAEngine: Improve slave/cyclic documentation

Improve the documentation for the slave and cyclic DMA engine support
reformatting it for easier reading, adding further APIs, splitting it
into five steps, and including references to the documentation in
dmaengine.h.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
 1 files changed, 146 insertions(+), 65 deletions(-)

diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
index 5a0cb1e..8c2e888 100644
--- a/Documentation/dmaengine.txt
+++ b/Documentation/dmaengine.txt
@@ -10,87 +10,168 @@
 Below is a guide to device driver writers on how to use the Slave-DMA API of the
 DMA Engine. This is applicable only for slave DMA usage only.
 
-The slave DMA usage consists of following steps
+The slave DMA usage consists of following steps:
 1. Allocate a DMA slave channel
 2. Set slave and controller specific parameters
 3. Get a descriptor for transaction
 4. Submit the transaction and wait for callback notification
+5. Issue pending requests
 
 1. Allocate a DMA slave channel
-Channel allocation is slightly different in the slave DMA context, client
-drivers typically need a channel from a particular DMA controller only and even
-in some cases a specific channel is desired. To request a channel
-dma_request_channel() API is used.
-
-Interface:
-struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
-		dma_filter_fn filter_fn,
-		void *filter_param);
-where dma_filter_fn is defined as:
-typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
-
-When the optional 'filter_fn' parameter is set to NULL dma_request_channel
-simply returns the first channel that satisfies the capability mask.  Otherwise,
-when the mask parameter is insufficient for specifying the necessary channel,
-the filter_fn routine can be used to disposition the available channels in the
-system. The filter_fn routine is called once for each free channel in the
-system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
-that channel to be the return value from dma_request_channel.  A channel
-allocated via this interface is exclusive to the caller, until
-dma_release_channel() is called.
+
+   Channel allocation is slightly different in the slave DMA context,
+   client drivers typically need a channel from a particular DMA
+   controller only and even in some cases a specific channel is desired.
+   To request a channel dma_request_channel() API is used.
+
+   Interface:
+	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+			dma_filter_fn filter_fn,
+			void *filter_param);
+   where dma_filter_fn is defined as:
+	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
+
+   The 'filter_fn' parameter is optional, but highly recommended for
+   slave and cyclic channels as they typically need to obtain a specific
+   DMA channel.
+
+   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
+   simply returns the first channel that satisfies the capability mask.
+
+   Otherwise, the 'filter_fn' routine will be called once for each free
+   channel which has a capability in 'mask'.  'filter_fn' is expected to
+   return 'true' when the desired DMA channel is found.
+
+   A channel allocated via this interface is exclusive to the caller,
+   until dma_release_channel() is called.
 
 2. Set slave and controller specific parameters
-Next step is always to pass some specific information to the DMA driver. Most of
-the generic information which a slave DMA can use is in struct dma_slave_config.
-It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
-burst lengths etc. If some DMA controllers have more parameters to be sent then
-they should try to embed struct dma_slave_config in their controller specific
-structure. That gives flexibility to client to pass more parameters, if
-required.
-
-Interface:
-int dmaengine_slave_config(struct dma_chan *chan,
-					  struct dma_slave_config *config)
+
+   Next step is always to pass some specific information to the DMA
+   driver.  Most of the generic information which a slave DMA can use
+   is in struct dma_slave_config.  This allows the clients to specify
+   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
+   for the peripheral.
+
+   If some DMA controllers have more parameters to be sent then they
+   should try to embed struct dma_slave_config in their controller
+   specific structure. That gives flexibility to client to pass more
+   parameters, if required.
+
+   Interface:
+	int dmaengine_slave_config(struct dma_chan *chan,
+				  struct dma_slave_config *config)
+
+   Please see the dma_slave_config structure definition in dmaengine.h
+   for a detailed explaination of the struct members.  Please note
+   that the 'direction' member will be going away as it duplicates the
+   direction given in the prepare call.
 
 3. Get a descriptor for transaction
-For slave usage the various modes of slave transfers supported by the
-DMA-engine are:
-slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
-dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
+
+   For slave usage the various modes of slave transfers supported by the
+   DMA-engine are:
+
+   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
+   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
 		  operation is explicitly stopped.
-The non NULL return of this transfer API represents a "descriptor" for the given
-transaction.
 
-Interface:
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
+   A non-NULL return of this transfer API represents a "descriptor" for
+   the given transaction.
+
+   Interface:
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
 		struct dma_chan *chan,
 		struct scatterlist *dst_sg, unsigned int dst_nents,
 		struct scatterlist *src_sg, unsigned int src_nents,
 		unsigned long flags);
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_data_direction direction);
 
-4. Submit the transaction and wait for callback notification
-To schedule the transaction to be scheduled by dma device, the "descriptor"
-returned in above (3) needs to be submitted.
-To tell the dma driver that a transaction is ready to be serviced, the
-descriptor->submit() callback needs to be invoked. This chains the descriptor to
-the pending queue.
-The transactions in the pending queue can be activated by calling the
-issue_pending API. If channel is idle then the first transaction in queue is
-started and subsequent ones queued up.
-On completion of the DMA operation the next in queue is submitted and a tasklet
-triggered. The tasklet would then call the client driver completion callback
-routine for notification, if set.
-Interface:
-void dma_async_issue_pending(struct dma_chan *chan);
-
-==============================================================================
-
-Additional usage notes for dma driver writers
-1/ Although DMA engine specifies that completion callback routines cannot submit
-any new operations, but typically for slave DMA subsequent transaction may not
-be available for submit prior to callback routine being called. This requirement
-is not a requirement for DMA-slave devices. But they should take care to drop
-the spin-lock they might be holding before calling the callback routine
+   Once a descriptor has been obtained, the callback information can be
+   added and must then be submitted.  Some DMA engine drivers may hold a
+   spinlock between a successful preparation and submission so it is
+   important that these two operations are closely paired.
+
+   Note:
+	Although the async_tx API specifies that completion callback
+	routines cannot submit any new operations, this is not the
+	case for slave/cyclic DMA.
+
+	For slave DMA, the subsequent transaction may not be available
+	for submission prior to callback function being invoked, so
+	slave DMA callbacks are permitted to prepare and submit a new
+	transaction.
+
+	For cyclic DMA, a callback function may wish to terminate the
+	DMA via dmaengine_terminate_all().
+
+	Therefore, it is important that DMA engine drivers drop any
+	locks before calling the callback function which may cause a
+	deadlock.
+
+	Note that callbacks will always be invoked from the DMA
+	engines tasklet, never from interrupt context.
+
+4. Submit the transaction
+
+   Once the descriptor has been prepared and the callback information
+   added, it must be placed on the DMA engine drivers pending queue.
+
+   Interface:
+	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
+
+   This returns a cookie can be used to check the progress of DMA engine
+   activity via other DMA engine calls not covered in this document.
+
+   dmaengine_submit() will not start the DMA operation, it merely adds
+   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
+
+5. Issue pending DMA requests and wait for callback notification
+
+   The transactions in the pending queue can be activated by calling the
+   issue_pending API. If channel is idle then the first transaction in
+   queue is started and subsequent ones queued up.
+
+   On completion of each DMA operation, the next in queue is started and
+   a tasklet triggered. The tasklet will then call the client driver
+   completion callback routine for notification, if set.
+
+   Interface:
+	void dma_async_issue_pending(struct dma_chan *chan);
+
+Further APIs:
+
+1. int dmaengine_terminate_all(struct dma_chan *chan)
+
+   This causes all activity for the DMA channel to be stopped, and may
+   discard data in the DMA FIFO which hasn't been fully transferred.
+   No callback functions will be called for any incomplete transfers.
+
+2. int dmaengine_pause(struct dma_chan *chan)
+
+   This pauses activity on the DMA channel without data loss.
+
+3. int dmaengine_resume(struct dma_chan *chan)
+
+   Resume a previously paused DMA channel.  It is invalid to resume a
+   channel which is not currently paused.
+
+4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+
+   This can be used to check the status of the channel.  Please see
+   the documentation in include/linux/dmaengine.h for a more complete
+   description of this API.
+
+   This can be used in conjunction with dma_async_is_complete() and
+   the cookie returned from 'descriptor->submit()' to check for
+   completion of a specific DMA transaction.
+
+   Note:
+	Not all DMA engine drivers can return reliable information for
+	a running DMA channel.  It is recommended that DMA engine users
+	pause or stop (via dmaengine_terminate_all) the channel before
+	using this API.

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

* Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-25 11:51     ` Jassi Brar
@ 2011-07-26  8:02       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26  8:02 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Boojin Kim, Kukjin Kim, Vinod Koul, Mark Brown, Grant Likely,
	linux-samsung-soc, Dan Williams, linux-arm-kernel

On Mon, Jul 25, 2011 at 05:21:44PM +0530, Jassi Brar wrote:
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> 
> > +
> > +static bool pl330_filter(struct dma_chan *chan, void *param)
> > +{
> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private;
> > +       unsigned dma_ch = (unsigned)param;
> > +
> > +       if (peri->peri_id != dma_ch)
> > +               return false;
> > +
> > +       return true;
> > +}
> This is what I meant... if we keep chan_id for paltform assigned IDs,
> these filter functions could simply become
> 
> static bool pl330_filter(struct dma_chan *chan, void *param)
> {
>         return chan->chan_id == param
> }
> 
> And ideally in the long run, we could just drop the filter callback
> and add expected channel ID to the request_channel call.

So what if you have a PL080 and PL330 drivers registered with the DMA
engine code, and you need to match a specific PL330 channel?

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-26  8:02       ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26  8:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 25, 2011 at 05:21:44PM +0530, Jassi Brar wrote:
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> 
> > +
> > +static bool pl330_filter(struct dma_chan *chan, void *param)
> > +{
> > + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private;
> > + ? ? ? unsigned dma_ch = (unsigned)param;
> > +
> > + ? ? ? if (peri->peri_id != dma_ch)
> > + ? ? ? ? ? ? ? return false;
> > +
> > + ? ? ? return true;
> > +}
> This is what I meant... if we keep chan_id for paltform assigned IDs,
> these filter functions could simply become
> 
> static bool pl330_filter(struct dma_chan *chan, void *param)
> {
>         return chan->chan_id == param
> }
> 
> And ideally in the long run, we could just drop the filter callback
> and add expected channel ID to the request_channel call.

So what if you have a PL080 and PL330 drivers registered with the DMA
engine code, and you need to match a specific PL330 channel?

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

* RE: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
  2011-07-25 11:17     ` Vinod Koul
@ 2011-07-26  9:31       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-26  9:31 UTC (permalink / raw)
  To: 'Vinod Koul'
  Cc: vinod.koul, linux-arm-kernel, linux-samsung-soc,
	'Kukjin Kim', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams'

Vinod Koul Wrote:
> Sent: Monday, July 25, 2011 8:17 PM
> To: Boojin Kim
> Cc: vinod.koul@intel.com; linux-arm-kernel@lists.infradead.org; linux-
> samsung-soc@vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
>
> On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > This patch adds to support DMA generic API to transfer raw
> > SPI data. Basiclly the spi driver uses DMA generic API if
> > architecture supports it. Otherwise, uses Samsung specific
> > S3C-PL330 APIs.
> >
> > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > Cc: Grant Likely <grant.likely@secretlab.ca>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---
> >  drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++-------------
> ----------
> >  1 files changed, 69 insertions(+), 72 deletions(-)
> >
> > diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> > index 8945e20..a4cf76a 100644
> > --- a/drivers/spi/spi_s3c64xx.c
> > +++ b/drivers/spi/spi_s3c64xx.c
> > @@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
> >  	unsigned                        state;
> >  	unsigned                        cur_mode, cur_bpw;
> >  	unsigned                        cur_speed;
> > +	unsigned			rx_ch;
> > +	unsigned			tx_ch;
> > +	struct samsung_dma_ops		*ops;
> >  };
> >
> >  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
> > @@ -227,6 +230,38 @@ static void flush_fifo(struct
> s3c64xx_spi_driver_data *sdd)
> >  	writel(val, regs + S3C64XX_SPI_CH_CFG);
> >  }
> >
> > +static void s3c64xx_spi_dma_rxcb(void *data)
> > +{
> > +	struct s3c64xx_spi_driver_data *sdd
> > +		= (struct s3c64xx_spi_driver_data *)data;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&sdd->lock, flags);
> > +
> > +	sdd->state &= ~RXBUSY;
> > +	/* If the other done */
> > +	if (!(sdd->state & TXBUSY))
> > +		complete(&sdd->xfer_completion);
> > +
> > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > +}
> > +
> > +static void s3c64xx_spi_dma_txcb(void *data)
> > +{
> > +	struct s3c64xx_spi_driver_data *sdd
> > +		= (struct s3c64xx_spi_driver_data *)data;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&sdd->lock, flags);
> > +
> > +	sdd->state &= ~TXBUSY;
> > +	/* If the other done */
> > +	if (!(sdd->state & RXBUSY))
> > +		complete(&sdd->xfer_completion);
> > +
> > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > +}
> I don't see much diff in these two functions and you should be able to
> use a generic one which takes care of both TX and RX, does your
> callback
> data know if the channel is for TX or RX? If not then a helper to do
> above should take care well and making code simpler
I'm very agree with you.
But, I think it isn't deeply related to this patch series. So, I wish to make 
and submit it after this patch series is finished.

>
> > +
> >  static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
> >  				struct spi_device *spi,
> >  				struct spi_transfer *xfer, int dma_mode)
> > @@ -234,6 +269,7 @@ static void enable_datapath(struct
> s3c64xx_spi_driver_data *sdd,
> >  	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
> >  	void __iomem *regs = sdd->regs;
> >  	u32 modecfg, chcfg;
> > +	struct samsung_dma_prep_info info;
> >
> >  	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
> >  	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON |
> S3C64XX_SPI_MODE_RXDMA_ON);
> > @@ -259,10 +295,14 @@ static void enable_datapath(struct
> s3c64xx_spi_driver_data *sdd,
> >  		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
> >  		if (dma_mode) {
> >  			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
> > -			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
> > -			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
> > -						xfer->tx_dma, xfer->len);
> > -			s3c2410_dma_ctrl(sdd->tx_dmach,
> S3C2410_DMAOP_START);
> > +			info.cap = DMA_SLAVE;
> > +			info.direction = DMA_TO_DEVICE;
> > +			info.buf = xfer->tx_dma;
> > +			info.len = xfer->len;
> > +			info.fp = s3c64xx_spi_dma_txcb;
> > +			info.fp_param = sdd;
> > +			sdd->ops->prepare(sdd->tx_ch, &info);
> > +			sdd->ops->trigger(sdd->tx_ch);
> >  		} else {
> >  			switch (sdd->cur_bpw) {
> >  			case 32:
> > @@ -294,10 +334,14 @@ static void enable_datapath(struct
> s3c64xx_spi_driver_data *sdd,
> >  			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
> >  					| S3C64XX_SPI_PACKET_CNT_EN,
> >  					regs + S3C64XX_SPI_PACKET_CNT);
> > -			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
> > -			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
> > -						xfer->rx_dma, xfer->len);
> > -			s3c2410_dma_ctrl(sdd->rx_dmach,
> S3C2410_DMAOP_START);
> > +			info.cap = DMA_SLAVE;
> > +			info.direction = DMA_FROM_DEVICE;
> > +			info.buf = xfer->rx_dma;
> > +			info.len = xfer->len;
> > +			info.fp = s3c64xx_spi_dma_rxcb;
> > +			info.fp_param = sdd;
> > +			sdd->ops->prepare(sdd->rx_ch, &info);
> > +			sdd->ops->trigger(sdd->rx_ch);
> >  		}
> >  	}
> >
> > @@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct
> s3c64xx_spi_driver_data *sdd)
> >  	}
> >  }
> >
> > -static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan,
> void *buf_id,
> > -				 int size, enum s3c2410_dma_buffresult res)
> > -{
> > -	struct s3c64xx_spi_driver_data *sdd = buf_id;
> > -	unsigned long flags;
> > -
> > -	spin_lock_irqsave(&sdd->lock, flags);
> > -
> > -	if (res == S3C2410_RES_OK)
> > -		sdd->state &= ~RXBUSY;
> > -	else
> > -		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
> > -
> > -	/* If the other done */
> > -	if (!(sdd->state & TXBUSY))
> > -		complete(&sdd->xfer_completion);
> > -
> > -	spin_unlock_irqrestore(&sdd->lock, flags);
> > -}
> > -
> > -static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan,
> void *buf_id,
> > -				 int size, enum s3c2410_dma_buffresult res)
> > -{
> > -	struct s3c64xx_spi_driver_data *sdd = buf_id;
> > -	unsigned long flags;
> > -
> > -	spin_lock_irqsave(&sdd->lock, flags);
> > -
> > -	if (res == S3C2410_RES_OK)
> > -		sdd->state &= ~TXBUSY;
> > -	else
> > -		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
> > -
> > -	/* If the other done */
> > -	if (!(sdd->state & RXBUSY))
> > -		complete(&sdd->xfer_completion);
> > -
> > -	spin_unlock_irqrestore(&sdd->lock, flags);
> > -}
> > -
> >  #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
> >
> >  static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
> > @@ -697,12 +701,10 @@ static void handle_msg(struct
> s3c64xx_spi_driver_data *sdd,
> >  			if (use_dma) {
> >  				if (xfer->tx_buf != NULL
> >  						&& (sdd->state & TXBUSY))
> > -					s3c2410_dma_ctrl(sdd->tx_dmach,
> > -							S3C2410_DMAOP_FLUSH);
> > +					sdd->ops->stop(sdd->tx_ch);
> >  				if (xfer->rx_buf != NULL
> >  						&& (sdd->state & RXBUSY))
> > -					s3c2410_dma_ctrl(sdd->rx_dmach,
> > -							S3C2410_DMAOP_FLUSH);
> > +					sdd->ops->stop(sdd->rx_ch);
> >  			}
> >
> >  			goto out;
> > @@ -742,24 +744,19 @@ out:
> >
> >  static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
> >  {
> > -	if (s3c2410_dma_request(sdd->rx_dmach,
> > -					&s3c64xx_spi_dma_client, NULL) < 0) {
> > -		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
> > -		return 0;
> > -	}
> > -	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
> > -	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
> > -					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
> > -
> > -	if (s3c2410_dma_request(sdd->tx_dmach,
> > -					&s3c64xx_spi_dma_client, NULL) < 0) {
> > -		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
> > -		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
> > -		return 0;
> > -	}
> > -	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
> > -	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
> > -					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
> > +
> > +	struct samsung_dma_info info;
> > +	sdd->ops = samsung_dma_get_ops();
> > +
> > +	info.cap = DMA_SLAVE;
> > +	info.client = &s3c64xx_spi_dma_client;
> > +	info.direction = DMA_FROM_DEVICE;
> > +	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
> > +	info.width = sdd->cur_bpw / 8;
> > +	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
> > +	info.direction = DMA_TO_DEVICE;
> > +	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
> > +	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
> >
> >  	return 1;
> >  }
> > @@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct
> *work)
> >  	spin_unlock_irqrestore(&sdd->lock, flags);
> >
> >  	/* Free DMA channels */
> > -	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
> > -	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
> > +	sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client);
> > +	sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client);
> >  }
> >
> >  static int s3c64xx_spi_transfer(struct spi_device *spi,
>
> --
> ~Vinod Koul
> Intel Corp.

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

* [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
@ 2011-07-26  9:31       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-26  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Vinod Koul Wrote:
> Sent: Monday, July 25, 2011 8:17 PM
> To: Boojin Kim
> Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux-
> samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> Mark Brown; Dan Williams
> Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
>
> On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > This patch adds to support DMA generic API to transfer raw
> > SPI data. Basiclly the spi driver uses DMA generic API if
> > architecture supports it. Otherwise, uses Samsung specific
> > S3C-PL330 APIs.
> >
> > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > Cc: Grant Likely <grant.likely@secretlab.ca>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---
> >  drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++-------------
> ----------
> >  1 files changed, 69 insertions(+), 72 deletions(-)
> >
> > diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> > index 8945e20..a4cf76a 100644
> > --- a/drivers/spi/spi_s3c64xx.c
> > +++ b/drivers/spi/spi_s3c64xx.c
> > @@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
> >  	unsigned                        state;
> >  	unsigned                        cur_mode, cur_bpw;
> >  	unsigned                        cur_speed;
> > +	unsigned			rx_ch;
> > +	unsigned			tx_ch;
> > +	struct samsung_dma_ops		*ops;
> >  };
> >
> >  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
> > @@ -227,6 +230,38 @@ static void flush_fifo(struct
> s3c64xx_spi_driver_data *sdd)
> >  	writel(val, regs + S3C64XX_SPI_CH_CFG);
> >  }
> >
> > +static void s3c64xx_spi_dma_rxcb(void *data)
> > +{
> > +	struct s3c64xx_spi_driver_data *sdd
> > +		= (struct s3c64xx_spi_driver_data *)data;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&sdd->lock, flags);
> > +
> > +	sdd->state &= ~RXBUSY;
> > +	/* If the other done */
> > +	if (!(sdd->state & TXBUSY))
> > +		complete(&sdd->xfer_completion);
> > +
> > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > +}
> > +
> > +static void s3c64xx_spi_dma_txcb(void *data)
> > +{
> > +	struct s3c64xx_spi_driver_data *sdd
> > +		= (struct s3c64xx_spi_driver_data *)data;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&sdd->lock, flags);
> > +
> > +	sdd->state &= ~TXBUSY;
> > +	/* If the other done */
> > +	if (!(sdd->state & RXBUSY))
> > +		complete(&sdd->xfer_completion);
> > +
> > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > +}
> I don't see much diff in these two functions and you should be able to
> use a generic one which takes care of both TX and RX, does your
> callback
> data know if the channel is for TX or RX? If not then a helper to do
> above should take care well and making code simpler
I'm very agree with you.
But, I think it isn't deeply related to this patch series. So, I wish to make 
and submit it after this patch series is finished.

>
> > +
> >  static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
> >  				struct spi_device *spi,
> >  				struct spi_transfer *xfer, int dma_mode)
> > @@ -234,6 +269,7 @@ static void enable_datapath(struct
> s3c64xx_spi_driver_data *sdd,
> >  	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
> >  	void __iomem *regs = sdd->regs;
> >  	u32 modecfg, chcfg;
> > +	struct samsung_dma_prep_info info;
> >
> >  	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
> >  	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON |
> S3C64XX_SPI_MODE_RXDMA_ON);
> > @@ -259,10 +295,14 @@ static void enable_datapath(struct
> s3c64xx_spi_driver_data *sdd,
> >  		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
> >  		if (dma_mode) {
> >  			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
> > -			s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
> > -			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
> > -						xfer->tx_dma, xfer->len);
> > -			s3c2410_dma_ctrl(sdd->tx_dmach,
> S3C2410_DMAOP_START);
> > +			info.cap = DMA_SLAVE;
> > +			info.direction = DMA_TO_DEVICE;
> > +			info.buf = xfer->tx_dma;
> > +			info.len = xfer->len;
> > +			info.fp = s3c64xx_spi_dma_txcb;
> > +			info.fp_param = sdd;
> > +			sdd->ops->prepare(sdd->tx_ch, &info);
> > +			sdd->ops->trigger(sdd->tx_ch);
> >  		} else {
> >  			switch (sdd->cur_bpw) {
> >  			case 32:
> > @@ -294,10 +334,14 @@ static void enable_datapath(struct
> s3c64xx_spi_driver_data *sdd,
> >  			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
> >  					| S3C64XX_SPI_PACKET_CNT_EN,
> >  					regs + S3C64XX_SPI_PACKET_CNT);
> > -			s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
> > -			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
> > -						xfer->rx_dma, xfer->len);
> > -			s3c2410_dma_ctrl(sdd->rx_dmach,
> S3C2410_DMAOP_START);
> > +			info.cap = DMA_SLAVE;
> > +			info.direction = DMA_FROM_DEVICE;
> > +			info.buf = xfer->rx_dma;
> > +			info.len = xfer->len;
> > +			info.fp = s3c64xx_spi_dma_rxcb;
> > +			info.fp_param = sdd;
> > +			sdd->ops->prepare(sdd->rx_ch, &info);
> > +			sdd->ops->trigger(sdd->rx_ch);
> >  		}
> >  	}
> >
> > @@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct
> s3c64xx_spi_driver_data *sdd)
> >  	}
> >  }
> >
> > -static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan,
> void *buf_id,
> > -				 int size, enum s3c2410_dma_buffresult res)
> > -{
> > -	struct s3c64xx_spi_driver_data *sdd = buf_id;
> > -	unsigned long flags;
> > -
> > -	spin_lock_irqsave(&sdd->lock, flags);
> > -
> > -	if (res == S3C2410_RES_OK)
> > -		sdd->state &= ~RXBUSY;
> > -	else
> > -		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
> > -
> > -	/* If the other done */
> > -	if (!(sdd->state & TXBUSY))
> > -		complete(&sdd->xfer_completion);
> > -
> > -	spin_unlock_irqrestore(&sdd->lock, flags);
> > -}
> > -
> > -static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan,
> void *buf_id,
> > -				 int size, enum s3c2410_dma_buffresult res)
> > -{
> > -	struct s3c64xx_spi_driver_data *sdd = buf_id;
> > -	unsigned long flags;
> > -
> > -	spin_lock_irqsave(&sdd->lock, flags);
> > -
> > -	if (res == S3C2410_RES_OK)
> > -		sdd->state &= ~TXBUSY;
> > -	else
> > -		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
> > -
> > -	/* If the other done */
> > -	if (!(sdd->state & RXBUSY))
> > -		complete(&sdd->xfer_completion);
> > -
> > -	spin_unlock_irqrestore(&sdd->lock, flags);
> > -}
> > -
> >  #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
> >
> >  static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
> > @@ -697,12 +701,10 @@ static void handle_msg(struct
> s3c64xx_spi_driver_data *sdd,
> >  			if (use_dma) {
> >  				if (xfer->tx_buf != NULL
> >  						&& (sdd->state & TXBUSY))
> > -					s3c2410_dma_ctrl(sdd->tx_dmach,
> > -							S3C2410_DMAOP_FLUSH);
> > +					sdd->ops->stop(sdd->tx_ch);
> >  				if (xfer->rx_buf != NULL
> >  						&& (sdd->state & RXBUSY))
> > -					s3c2410_dma_ctrl(sdd->rx_dmach,
> > -							S3C2410_DMAOP_FLUSH);
> > +					sdd->ops->stop(sdd->rx_ch);
> >  			}
> >
> >  			goto out;
> > @@ -742,24 +744,19 @@ out:
> >
> >  static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
> >  {
> > -	if (s3c2410_dma_request(sdd->rx_dmach,
> > -					&s3c64xx_spi_dma_client, NULL) < 0) {
> > -		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
> > -		return 0;
> > -	}
> > -	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
> > -	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
> > -					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
> > -
> > -	if (s3c2410_dma_request(sdd->tx_dmach,
> > -					&s3c64xx_spi_dma_client, NULL) < 0) {
> > -		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
> > -		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
> > -		return 0;
> > -	}
> > -	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
> > -	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
> > -					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
> > +
> > +	struct samsung_dma_info info;
> > +	sdd->ops = samsung_dma_get_ops();
> > +
> > +	info.cap = DMA_SLAVE;
> > +	info.client = &s3c64xx_spi_dma_client;
> > +	info.direction = DMA_FROM_DEVICE;
> > +	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
> > +	info.width = sdd->cur_bpw / 8;
> > +	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
> > +	info.direction = DMA_TO_DEVICE;
> > +	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
> > +	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
> >
> >  	return 1;
> >  }
> > @@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct
> *work)
> >  	spin_unlock_irqrestore(&sdd->lock, flags);
> >
> >  	/* Free DMA channels */
> > -	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
> > -	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
> > +	sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client);
> > +	sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client);
> >  }
> >
> >  static int s3c64xx_spi_transfer(struct spi_device *spi,
>
> --
> ~Vinod Koul
> Intel Corp.

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

* RE: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-25 11:51     ` Jassi Brar
@ 2011-07-26  9:35       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-26  9:35 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Vinod Koul',
	'Dan Williams', 'Kukjin Kim',
	'Grant Likely', 'Mark Brown'

Jassi Brar Wrote:
> Sent: Monday, July 25, 2011 8:52 PM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> Likely; Mark Brown
> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
>
> > +
> > +static bool pl330_filter(struct dma_chan *chan, void *param)
> > +{
> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan-
> >private;
> > +       unsigned dma_ch = (unsigned)param;
> > +
> > +       if (peri->peri_id != dma_ch)
> > +               return false;
> > +
> > +       return true;
> > +}
> This is what I meant... if we keep chan_id for paltform assigned IDs,
> these filter functions could simply become
>
> static bool pl330_filter(struct dma_chan *chan, void *param)
> {
>         return chan->chan_id == param
> }
>
> And ideally in the long run, we could just drop the filter callback
> and add expected channel ID to the request_channel call.
The chan_id is set by dmaengine. So, We don't use it to hold the user specific 
Id.

>
>
>
> > +
> > +static inline int s3c_dma_trigger(unsigned ch)
> > +{
> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
> > +}
> > +
> > +static inline int s3c_dma_started(unsigned ch)
> > +{
> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
> > +}
> > +
> > +static inline int s3c_dma_flush(unsigned ch)
> > +{
> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
> > +}
> > +
> > +static inline int s3c_dma_stop(unsigned ch)
> > +{
> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
> > +}
> > +
> > +static struct samsung_dma_ops s3c_dma_ops = {
> > +       .request        = s3c_dma_request,
> > +       .release        = s3c_dma_release,
> > +       .prepare        = s3c_dma_prepare,
> > +       .trigger        = s3c_dma_trigger,
> > +       .started        = s3c_dma_started,
> > +       .flush          = s3c_dma_flush,
> > +       .stop           = s3c_dma_stop,
>
> These last 4 should be gnereallized into one callback with OP argument.
I don't have any idea about it. Can you explain it in more detail?

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-26  9:35       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-26  9:35 UTC (permalink / raw)
  To: linux-arm-kernel

Jassi Brar Wrote:
> Sent: Monday, July 25, 2011 8:52 PM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> Likely; Mark Brown
> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
>
> > +
> > +static bool pl330_filter(struct dma_chan *chan, void *param)
> > +{
> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan-
> >private;
> > +       unsigned dma_ch = (unsigned)param;
> > +
> > +       if (peri->peri_id != dma_ch)
> > +               return false;
> > +
> > +       return true;
> > +}
> This is what I meant... if we keep chan_id for paltform assigned IDs,
> these filter functions could simply become
>
> static bool pl330_filter(struct dma_chan *chan, void *param)
> {
>         return chan->chan_id == param
> }
>
> And ideally in the long run, we could just drop the filter callback
> and add expected channel ID to the request_channel call.
The chan_id is set by dmaengine. So, We don't use it to hold the user specific 
Id.

>
>
>
> > +
> > +static inline int s3c_dma_trigger(unsigned ch)
> > +{
> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
> > +}
> > +
> > +static inline int s3c_dma_started(unsigned ch)
> > +{
> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
> > +}
> > +
> > +static inline int s3c_dma_flush(unsigned ch)
> > +{
> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
> > +}
> > +
> > +static inline int s3c_dma_stop(unsigned ch)
> > +{
> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
> > +}
> > +
> > +static struct samsung_dma_ops s3c_dma_ops = {
> > +       .request        = s3c_dma_request,
> > +       .release        = s3c_dma_release,
> > +       .prepare        = s3c_dma_prepare,
> > +       .trigger        = s3c_dma_trigger,
> > +       .started        = s3c_dma_started,
> > +       .flush          = s3c_dma_flush,
> > +       .stop           = s3c_dma_stop,
>
> These last 4 should be gnereallized into one callback with OP argument.
I don't have any idea about it. Can you explain it in more detail?

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26  7:57                     ` Russell King - ARM Linux
@ 2011-07-26  9:35                       ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-26  9:35 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: vinod.koul, linux-samsung-soc, Boojin Kim, 'Jassi Brar',
	'Grant Likely', 'Kukjin Kim',
	'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Tue, 2011-07-26 at 08:57 +0100, Russell King - ARM Linux wrote:
> Here's an updated patch.
> 
> 8<----------
> From: Russell King <rmk+kernel@arm.linux.org.uk>
> DMAEngine: Improve slave/cyclic documentation
> 
> Improve the documentation for the slave and cyclic DMA engine support
> reformatting it for easier reading, adding further APIs, splitting it
> into five steps, and including references to the documentation in
> dmaengine.h.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
>  1 files changed, 146 insertions(+), 65 deletions(-)
> 
> diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
> index 5a0cb1e..8c2e888 100644
> --- a/Documentation/dmaengine.txt
> +++ b/Documentation/dmaengine.txt
> @@ -10,87 +10,168 @@
>  Below is a guide to device driver writers on how to use the Slave-DMA API of the
>  DMA Engine. This is applicable only for slave DMA usage only.
>  
> -The slave DMA usage consists of following steps
> +The slave DMA usage consists of following steps:
>  1. Allocate a DMA slave channel
>  2. Set slave and controller specific parameters
>  3. Get a descriptor for transaction
>  4. Submit the transaction and wait for callback notification
> +5. Issue pending requests
Thanks Russell,

Applied with change to 4 above. Moved "and wait for callback
notification" to 5.

>  
>  1. Allocate a DMA slave channel
> -Channel allocation is slightly different in the slave DMA context, client
> -drivers typically need a channel from a particular DMA controller only and even
> -in some cases a specific channel is desired. To request a channel
> -dma_request_channel() API is used.
> -
> -Interface:
> -struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
> -		dma_filter_fn filter_fn,
> -		void *filter_param);
> -where dma_filter_fn is defined as:
> -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
> -
> -When the optional 'filter_fn' parameter is set to NULL dma_request_channel
> -simply returns the first channel that satisfies the capability mask.  Otherwise,
> -when the mask parameter is insufficient for specifying the necessary channel,
> -the filter_fn routine can be used to disposition the available channels in the
> -system. The filter_fn routine is called once for each free channel in the
> -system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
> -that channel to be the return value from dma_request_channel.  A channel
> -allocated via this interface is exclusive to the caller, until
> -dma_release_channel() is called.
> +
> +   Channel allocation is slightly different in the slave DMA context,
> +   client drivers typically need a channel from a particular DMA
> +   controller only and even in some cases a specific channel is desired.
> +   To request a channel dma_request_channel() API is used.
> +
> +   Interface:
> +	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
> +			dma_filter_fn filter_fn,
> +			void *filter_param);
> +   where dma_filter_fn is defined as:
> +	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
> +
> +   The 'filter_fn' parameter is optional, but highly recommended for
> +   slave and cyclic channels as they typically need to obtain a specific
> +   DMA channel.
> +
> +   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
> +   simply returns the first channel that satisfies the capability mask.
> +
> +   Otherwise, the 'filter_fn' routine will be called once for each free
> +   channel which has a capability in 'mask'.  'filter_fn' is expected to
> +   return 'true' when the desired DMA channel is found.
> +
> +   A channel allocated via this interface is exclusive to the caller,
> +   until dma_release_channel() is called.
>  
>  2. Set slave and controller specific parameters
> -Next step is always to pass some specific information to the DMA driver. Most of
> -the generic information which a slave DMA can use is in struct dma_slave_config.
> -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
> -burst lengths etc. If some DMA controllers have more parameters to be sent then
> -they should try to embed struct dma_slave_config in their controller specific
> -structure. That gives flexibility to client to pass more parameters, if
> -required.
> -
> -Interface:
> -int dmaengine_slave_config(struct dma_chan *chan,
> -					  struct dma_slave_config *config)
> +
> +   Next step is always to pass some specific information to the DMA
> +   driver.  Most of the generic information which a slave DMA can use
> +   is in struct dma_slave_config.  This allows the clients to specify
> +   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
> +   for the peripheral.
> +
> +   If some DMA controllers have more parameters to be sent then they
> +   should try to embed struct dma_slave_config in their controller
> +   specific structure. That gives flexibility to client to pass more
> +   parameters, if required.
> +
> +   Interface:
> +	int dmaengine_slave_config(struct dma_chan *chan,
> +				  struct dma_slave_config *config)
> +
> +   Please see the dma_slave_config structure definition in dmaengine.h
> +   for a detailed explaination of the struct members.  Please note
> +   that the 'direction' member will be going away as it duplicates the
> +   direction given in the prepare call.
>  
>  3. Get a descriptor for transaction
> -For slave usage the various modes of slave transfers supported by the
> -DMA-engine are:
> -slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
> -dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
> +
> +   For slave usage the various modes of slave transfers supported by the
> +   DMA-engine are:
> +
> +   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
> +   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
>  		  operation is explicitly stopped.
> -The non NULL return of this transfer API represents a "descriptor" for the given
> -transaction.
>  
> -Interface:
> -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
> +   A non-NULL return of this transfer API represents a "descriptor" for
> +   the given transaction.
> +
> +   Interface:
> +	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
>  		struct dma_chan *chan,
>  		struct scatterlist *dst_sg, unsigned int dst_nents,
>  		struct scatterlist *src_sg, unsigned int src_nents,
>  		unsigned long flags);
> -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
> +
> +	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
>  		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
>  		size_t period_len, enum dma_data_direction direction);
>  
> -4. Submit the transaction and wait for callback notification
> -To schedule the transaction to be scheduled by dma device, the "descriptor"
> -returned in above (3) needs to be submitted.
> -To tell the dma driver that a transaction is ready to be serviced, the
> -descriptor->submit() callback needs to be invoked. This chains the descriptor to
> -the pending queue.
> -The transactions in the pending queue can be activated by calling the
> -issue_pending API. If channel is idle then the first transaction in queue is
> -started and subsequent ones queued up.
> -On completion of the DMA operation the next in queue is submitted and a tasklet
> -triggered. The tasklet would then call the client driver completion callback
> -routine for notification, if set.
> -Interface:
> -void dma_async_issue_pending(struct dma_chan *chan);
> -
> -==============================================================================
> -
> -Additional usage notes for dma driver writers
> -1/ Although DMA engine specifies that completion callback routines cannot submit
> -any new operations, but typically for slave DMA subsequent transaction may not
> -be available for submit prior to callback routine being called. This requirement
> -is not a requirement for DMA-slave devices. But they should take care to drop
> -the spin-lock they might be holding before calling the callback routine
> +   Once a descriptor has been obtained, the callback information can be
> +   added and must then be submitted.  Some DMA engine drivers may hold a
> +   spinlock between a successful preparation and submission so it is
> +   important that these two operations are closely paired.
> +
> +   Note:
> +	Although the async_tx API specifies that completion callback
> +	routines cannot submit any new operations, this is not the
> +	case for slave/cyclic DMA.
> +
> +	For slave DMA, the subsequent transaction may not be available
> +	for submission prior to callback function being invoked, so
> +	slave DMA callbacks are permitted to prepare and submit a new
> +	transaction.
> +
> +	For cyclic DMA, a callback function may wish to terminate the
> +	DMA via dmaengine_terminate_all().
> +
> +	Therefore, it is important that DMA engine drivers drop any
> +	locks before calling the callback function which may cause a
> +	deadlock.
> +
> +	Note that callbacks will always be invoked from the DMA
> +	engines tasklet, never from interrupt context.
> +
> +4. Submit the transaction
> +
> +   Once the descriptor has been prepared and the callback information
> +   added, it must be placed on the DMA engine drivers pending queue.
> +
> +   Interface:
> +	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
> +
> +   This returns a cookie can be used to check the progress of DMA engine
> +   activity via other DMA engine calls not covered in this document.
> +
> +   dmaengine_submit() will not start the DMA operation, it merely adds
> +   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
> +
> +5. Issue pending DMA requests and wait for callback notification
> +
> +   The transactions in the pending queue can be activated by calling the
> +   issue_pending API. If channel is idle then the first transaction in
> +   queue is started and subsequent ones queued up.
> +
> +   On completion of each DMA operation, the next in queue is started and
> +   a tasklet triggered. The tasklet will then call the client driver
> +   completion callback routine for notification, if set.
> +
> +   Interface:
> +	void dma_async_issue_pending(struct dma_chan *chan);
> +
> +Further APIs:
> +
> +1. int dmaengine_terminate_all(struct dma_chan *chan)
> +
> +   This causes all activity for the DMA channel to be stopped, and may
> +   discard data in the DMA FIFO which hasn't been fully transferred.
> +   No callback functions will be called for any incomplete transfers.
> +
> +2. int dmaengine_pause(struct dma_chan *chan)
> +
> +   This pauses activity on the DMA channel without data loss.
> +
> +3. int dmaengine_resume(struct dma_chan *chan)
> +
> +   Resume a previously paused DMA channel.  It is invalid to resume a
> +   channel which is not currently paused.
> +
> +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
> +        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
> +
> +   This can be used to check the status of the channel.  Please see
> +   the documentation in include/linux/dmaengine.h for a more complete
> +   description of this API.
> +
> +   This can be used in conjunction with dma_async_is_complete() and
> +   the cookie returned from 'descriptor->submit()' to check for
> +   completion of a specific DMA transaction.
> +
> +   Note:
> +	Not all DMA engine drivers can return reliable information for
> +	a running DMA channel.  It is recommended that DMA engine users
> +	pause or stop (via dmaengine_terminate_all) the channel before
> +	using this API.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
~Vinod Koul
Intel Corp.

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-26  9:35                       ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-26  9:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2011-07-26 at 08:57 +0100, Russell King - ARM Linux wrote:
> Here's an updated patch.
> 
> 8<----------
> From: Russell King <rmk+kernel@arm.linux.org.uk>
> DMAEngine: Improve slave/cyclic documentation
> 
> Improve the documentation for the slave and cyclic DMA engine support
> reformatting it for easier reading, adding further APIs, splitting it
> into five steps, and including references to the documentation in
> dmaengine.h.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
>  1 files changed, 146 insertions(+), 65 deletions(-)
> 
> diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
> index 5a0cb1e..8c2e888 100644
> --- a/Documentation/dmaengine.txt
> +++ b/Documentation/dmaengine.txt
> @@ -10,87 +10,168 @@
>  Below is a guide to device driver writers on how to use the Slave-DMA API of the
>  DMA Engine. This is applicable only for slave DMA usage only.
>  
> -The slave DMA usage consists of following steps
> +The slave DMA usage consists of following steps:
>  1. Allocate a DMA slave channel
>  2. Set slave and controller specific parameters
>  3. Get a descriptor for transaction
>  4. Submit the transaction and wait for callback notification
> +5. Issue pending requests
Thanks Russell,

Applied with change to 4 above. Moved "and wait for callback
notification" to 5.

>  
>  1. Allocate a DMA slave channel
> -Channel allocation is slightly different in the slave DMA context, client
> -drivers typically need a channel from a particular DMA controller only and even
> -in some cases a specific channel is desired. To request a channel
> -dma_request_channel() API is used.
> -
> -Interface:
> -struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
> -		dma_filter_fn filter_fn,
> -		void *filter_param);
> -where dma_filter_fn is defined as:
> -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
> -
> -When the optional 'filter_fn' parameter is set to NULL dma_request_channel
> -simply returns the first channel that satisfies the capability mask.  Otherwise,
> -when the mask parameter is insufficient for specifying the necessary channel,
> -the filter_fn routine can be used to disposition the available channels in the
> -system. The filter_fn routine is called once for each free channel in the
> -system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
> -that channel to be the return value from dma_request_channel.  A channel
> -allocated via this interface is exclusive to the caller, until
> -dma_release_channel() is called.
> +
> +   Channel allocation is slightly different in the slave DMA context,
> +   client drivers typically need a channel from a particular DMA
> +   controller only and even in some cases a specific channel is desired.
> +   To request a channel dma_request_channel() API is used.
> +
> +   Interface:
> +	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
> +			dma_filter_fn filter_fn,
> +			void *filter_param);
> +   where dma_filter_fn is defined as:
> +	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
> +
> +   The 'filter_fn' parameter is optional, but highly recommended for
> +   slave and cyclic channels as they typically need to obtain a specific
> +   DMA channel.
> +
> +   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
> +   simply returns the first channel that satisfies the capability mask.
> +
> +   Otherwise, the 'filter_fn' routine will be called once for each free
> +   channel which has a capability in 'mask'.  'filter_fn' is expected to
> +   return 'true' when the desired DMA channel is found.
> +
> +   A channel allocated via this interface is exclusive to the caller,
> +   until dma_release_channel() is called.
>  
>  2. Set slave and controller specific parameters
> -Next step is always to pass some specific information to the DMA driver. Most of
> -the generic information which a slave DMA can use is in struct dma_slave_config.
> -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
> -burst lengths etc. If some DMA controllers have more parameters to be sent then
> -they should try to embed struct dma_slave_config in their controller specific
> -structure. That gives flexibility to client to pass more parameters, if
> -required.
> -
> -Interface:
> -int dmaengine_slave_config(struct dma_chan *chan,
> -					  struct dma_slave_config *config)
> +
> +   Next step is always to pass some specific information to the DMA
> +   driver.  Most of the generic information which a slave DMA can use
> +   is in struct dma_slave_config.  This allows the clients to specify
> +   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
> +   for the peripheral.
> +
> +   If some DMA controllers have more parameters to be sent then they
> +   should try to embed struct dma_slave_config in their controller
> +   specific structure. That gives flexibility to client to pass more
> +   parameters, if required.
> +
> +   Interface:
> +	int dmaengine_slave_config(struct dma_chan *chan,
> +				  struct dma_slave_config *config)
> +
> +   Please see the dma_slave_config structure definition in dmaengine.h
> +   for a detailed explaination of the struct members.  Please note
> +   that the 'direction' member will be going away as it duplicates the
> +   direction given in the prepare call.
>  
>  3. Get a descriptor for transaction
> -For slave usage the various modes of slave transfers supported by the
> -DMA-engine are:
> -slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
> -dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
> +
> +   For slave usage the various modes of slave transfers supported by the
> +   DMA-engine are:
> +
> +   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
> +   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
>  		  operation is explicitly stopped.
> -The non NULL return of this transfer API represents a "descriptor" for the given
> -transaction.
>  
> -Interface:
> -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
> +   A non-NULL return of this transfer API represents a "descriptor" for
> +   the given transaction.
> +
> +   Interface:
> +	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
>  		struct dma_chan *chan,
>  		struct scatterlist *dst_sg, unsigned int dst_nents,
>  		struct scatterlist *src_sg, unsigned int src_nents,
>  		unsigned long flags);
> -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
> +
> +	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
>  		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
>  		size_t period_len, enum dma_data_direction direction);
>  
> -4. Submit the transaction and wait for callback notification
> -To schedule the transaction to be scheduled by dma device, the "descriptor"
> -returned in above (3) needs to be submitted.
> -To tell the dma driver that a transaction is ready to be serviced, the
> -descriptor->submit() callback needs to be invoked. This chains the descriptor to
> -the pending queue.
> -The transactions in the pending queue can be activated by calling the
> -issue_pending API. If channel is idle then the first transaction in queue is
> -started and subsequent ones queued up.
> -On completion of the DMA operation the next in queue is submitted and a tasklet
> -triggered. The tasklet would then call the client driver completion callback
> -routine for notification, if set.
> -Interface:
> -void dma_async_issue_pending(struct dma_chan *chan);
> -
> -==============================================================================
> -
> -Additional usage notes for dma driver writers
> -1/ Although DMA engine specifies that completion callback routines cannot submit
> -any new operations, but typically for slave DMA subsequent transaction may not
> -be available for submit prior to callback routine being called. This requirement
> -is not a requirement for DMA-slave devices. But they should take care to drop
> -the spin-lock they might be holding before calling the callback routine
> +   Once a descriptor has been obtained, the callback information can be
> +   added and must then be submitted.  Some DMA engine drivers may hold a
> +   spinlock between a successful preparation and submission so it is
> +   important that these two operations are closely paired.
> +
> +   Note:
> +	Although the async_tx API specifies that completion callback
> +	routines cannot submit any new operations, this is not the
> +	case for slave/cyclic DMA.
> +
> +	For slave DMA, the subsequent transaction may not be available
> +	for submission prior to callback function being invoked, so
> +	slave DMA callbacks are permitted to prepare and submit a new
> +	transaction.
> +
> +	For cyclic DMA, a callback function may wish to terminate the
> +	DMA via dmaengine_terminate_all().
> +
> +	Therefore, it is important that DMA engine drivers drop any
> +	locks before calling the callback function which may cause a
> +	deadlock.
> +
> +	Note that callbacks will always be invoked from the DMA
> +	engines tasklet, never from interrupt context.
> +
> +4. Submit the transaction
> +
> +   Once the descriptor has been prepared and the callback information
> +   added, it must be placed on the DMA engine drivers pending queue.
> +
> +   Interface:
> +	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
> +
> +   This returns a cookie can be used to check the progress of DMA engine
> +   activity via other DMA engine calls not covered in this document.
> +
> +   dmaengine_submit() will not start the DMA operation, it merely adds
> +   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
> +
> +5. Issue pending DMA requests and wait for callback notification
> +
> +   The transactions in the pending queue can be activated by calling the
> +   issue_pending API. If channel is idle then the first transaction in
> +   queue is started and subsequent ones queued up.
> +
> +   On completion of each DMA operation, the next in queue is started and
> +   a tasklet triggered. The tasklet will then call the client driver
> +   completion callback routine for notification, if set.
> +
> +   Interface:
> +	void dma_async_issue_pending(struct dma_chan *chan);
> +
> +Further APIs:
> +
> +1. int dmaengine_terminate_all(struct dma_chan *chan)
> +
> +   This causes all activity for the DMA channel to be stopped, and may
> +   discard data in the DMA FIFO which hasn't been fully transferred.
> +   No callback functions will be called for any incomplete transfers.
> +
> +2. int dmaengine_pause(struct dma_chan *chan)
> +
> +   This pauses activity on the DMA channel without data loss.
> +
> +3. int dmaengine_resume(struct dma_chan *chan)
> +
> +   Resume a previously paused DMA channel.  It is invalid to resume a
> +   channel which is not currently paused.
> +
> +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
> +        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
> +
> +   This can be used to check the status of the channel.  Please see
> +   the documentation in include/linux/dmaengine.h for a more complete
> +   description of this API.
> +
> +   This can be used in conjunction with dma_async_is_complete() and
> +   the cookie returned from 'descriptor->submit()' to check for
> +   completion of a specific DMA transaction.
> +
> +   Note:
> +	Not all DMA engine drivers can return reliable information for
> +	a running DMA channel.  It is recommended that DMA engine users
> +	pause or stop (via dmaengine_terminate_all) the channel before
> +	using this API.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
~Vinod Koul
Intel Corp.

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

* RE: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
  2011-07-26  9:31       ` Boojin Kim
@ 2011-07-26 10:14         ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-26 10:14 UTC (permalink / raw)
  To: Boojin Kim
  Cc: vinod.koul, 'Kukjin Kim', 'Jassi Brar',
	'Grant Likely', linux-samsung-soc, 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

On Tue, 2011-07-26 at 18:31 +0900, Boojin Kim wrote:
> Vinod Koul Wrote:
> > Sent: Monday, July 25, 2011 8:17 PM
> > To: Boojin Kim
> > Cc: vinod.koul@intel.com; linux-arm-kernel@lists.infradead.org; linux-
> > samsung-soc@vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> > Mark Brown; Dan Williams
> > Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
> >
> > On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > > This patch adds to support DMA generic API to transfer raw
> > > SPI data. Basiclly the spi driver uses DMA generic API if
> > > architecture supports it. Otherwise, uses Samsung specific
> > > S3C-PL330 APIs.
> > >
> > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > Cc: Grant Likely <grant.likely@secretlab.ca>
> > > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > > ---
> > >  drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++-------------
> > ----------
> > >  1 files changed, 69 insertions(+), 72 deletions(-)
> > >
> > > diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> > > index 8945e20..a4cf76a 100644
> > > --- a/drivers/spi/spi_s3c64xx.c
> > > +++ b/drivers/spi/spi_s3c64xx.c
> > > @@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
> > >  	unsigned                        state;
> > >  	unsigned                        cur_mode, cur_bpw;
> > >  	unsigned                        cur_speed;
> > > +	unsigned			rx_ch;
> > > +	unsigned			tx_ch;
> > > +	struct samsung_dma_ops		*ops;
> > >  };
> > >
> > >  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
> > > @@ -227,6 +230,38 @@ static void flush_fifo(struct
> > s3c64xx_spi_driver_data *sdd)
> > >  	writel(val, regs + S3C64XX_SPI_CH_CFG);
> > >  }
> > >
> > > +static void s3c64xx_spi_dma_rxcb(void *data)
> > > +{
> > > +	struct s3c64xx_spi_driver_data *sdd
> > > +		= (struct s3c64xx_spi_driver_data *)data;
> > > +	unsigned long flags;
> > > +
> > > +	spin_lock_irqsave(&sdd->lock, flags);
> > > +
> > > +	sdd->state &= ~RXBUSY;
> > > +	/* If the other done */
> > > +	if (!(sdd->state & TXBUSY))
> > > +		complete(&sdd->xfer_completion);
> > > +
> > > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > > +}
> > > +
> > > +static void s3c64xx_spi_dma_txcb(void *data)
> > > +{
> > > +	struct s3c64xx_spi_driver_data *sdd
> > > +		= (struct s3c64xx_spi_driver_data *)data;
> > > +	unsigned long flags;
> > > +
> > > +	spin_lock_irqsave(&sdd->lock, flags);
> > > +
> > > +	sdd->state &= ~TXBUSY;
> > > +	/* If the other done */
> > > +	if (!(sdd->state & RXBUSY))
> > > +		complete(&sdd->xfer_completion);
> > > +
> > > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > > +}
> > I don't see much diff in these two functions and you should be able to
> > use a generic one which takes care of both TX and RX, does your
> > callback
> > data know if the channel is for TX or RX? If not then a helper to do
> > above should take care well and making code simpler
> I'm very agree with you.
> But, I think it isn't deeply related to this patch series. So, I wish to make 
> and submit it after this patch series is finished.
> 
Since you are reworking this driver would make sense to do now, it
doesn't sound to be a big change.

-- 
~Vinod Koul
Intel Corp.

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

* [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
@ 2011-07-26 10:14         ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-26 10:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2011-07-26 at 18:31 +0900, Boojin Kim wrote:
> Vinod Koul Wrote:
> > Sent: Monday, July 25, 2011 8:17 PM
> > To: Boojin Kim
> > Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux-
> > samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> > Mark Brown; Dan Williams
> > Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
> >
> > On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > > This patch adds to support DMA generic API to transfer raw
> > > SPI data. Basiclly the spi driver uses DMA generic API if
> > > architecture supports it. Otherwise, uses Samsung specific
> > > S3C-PL330 APIs.
> > >
> > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > Cc: Grant Likely <grant.likely@secretlab.ca>
> > > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > > ---
> > >  drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++-------------
> > ----------
> > >  1 files changed, 69 insertions(+), 72 deletions(-)
> > >
> > > diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> > > index 8945e20..a4cf76a 100644
> > > --- a/drivers/spi/spi_s3c64xx.c
> > > +++ b/drivers/spi/spi_s3c64xx.c
> > > @@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
> > >  	unsigned                        state;
> > >  	unsigned                        cur_mode, cur_bpw;
> > >  	unsigned                        cur_speed;
> > > +	unsigned			rx_ch;
> > > +	unsigned			tx_ch;
> > > +	struct samsung_dma_ops		*ops;
> > >  };
> > >
> > >  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
> > > @@ -227,6 +230,38 @@ static void flush_fifo(struct
> > s3c64xx_spi_driver_data *sdd)
> > >  	writel(val, regs + S3C64XX_SPI_CH_CFG);
> > >  }
> > >
> > > +static void s3c64xx_spi_dma_rxcb(void *data)
> > > +{
> > > +	struct s3c64xx_spi_driver_data *sdd
> > > +		= (struct s3c64xx_spi_driver_data *)data;
> > > +	unsigned long flags;
> > > +
> > > +	spin_lock_irqsave(&sdd->lock, flags);
> > > +
> > > +	sdd->state &= ~RXBUSY;
> > > +	/* If the other done */
> > > +	if (!(sdd->state & TXBUSY))
> > > +		complete(&sdd->xfer_completion);
> > > +
> > > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > > +}
> > > +
> > > +static void s3c64xx_spi_dma_txcb(void *data)
> > > +{
> > > +	struct s3c64xx_spi_driver_data *sdd
> > > +		= (struct s3c64xx_spi_driver_data *)data;
> > > +	unsigned long flags;
> > > +
> > > +	spin_lock_irqsave(&sdd->lock, flags);
> > > +
> > > +	sdd->state &= ~TXBUSY;
> > > +	/* If the other done */
> > > +	if (!(sdd->state & RXBUSY))
> > > +		complete(&sdd->xfer_completion);
> > > +
> > > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > > +}
> > I don't see much diff in these two functions and you should be able to
> > use a generic one which takes care of both TX and RX, does your
> > callback
> > data know if the channel is for TX or RX? If not then a helper to do
> > above should take care well and making code simpler
> I'm very agree with you.
> But, I think it isn't deeply related to this patch series. So, I wish to make 
> and submit it after this patch series is finished.
> 
Since you are reworking this driver would make sense to do now, it
doesn't sound to be a big change.

-- 
~Vinod Koul
Intel Corp.

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

* RE: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
  2011-07-25 11:24     ` Jassi Brar
@ 2011-07-26 12:28       ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-26 12:28 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: 'Kukjin Kim', 'Vinod Koul', 'Mark Brown',
	'Grant Likely', linux-samsung-soc, 'Dan Williams',
	linux-arm-kernel

Jassi Brar Wrote:
> Sent: Monday, July 25, 2011 8:24 PM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> Likely; Mark Brown
> Subject: Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
>
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > This patch adds DMA_CYCLIC capability that is used for audio driver.
> > DMA driver with DMA_CYCLIC capability reuses the dma requests that
> > were submitted through tx_submit().
> >
> > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > ---
> >  drivers/dma/pl330.c |  111
> +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 files changed, 111 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > index 880f010..121c75a 100644
> > --- a/drivers/dma/pl330.c
> > +++ b/drivers/dma/pl330.c
> > @@ -69,6 +69,11 @@ struct dma_pl330_chan {
> >         * NULL if the channel is available to be acquired.
> >         */
> >        void *pl330_chid;
> > +
> > +       /* taks for cyclic capability */
> > +       struct tasklet_struct *cyclic_task;
> > +
> > +       bool cyclic;
> >  };
> We already have a tasklet_struct member here.
> This 'cyclic' flag can indicate if we are doing cyclic or serial
> transfers. So, this cyclic_task seems unnecessary.
I will change cyclic operation base on your comment.
Cyclic_task will be removed.

>
> > +static void pl330_tasklet_cyclic(unsigned long data)
> > +{
> > +       struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > +       struct dma_pl330_desc *desc, *_dt;
> > +       unsigned long flags;
> > +       LIST_HEAD(list);
> > +
> > +       spin_lock_irqsave(&pch->lock, flags);
> > +
> > +       /* Pick up ripe tomatoes */
> > +       list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
> > +               if (desc->status == DONE) {
> > +                       dma_async_tx_callback callback;
> > +
> > +                       list_move_tail(&desc->node, &pch->work_list);
> > +                       pch->completed = desc->txd.cookie;
> > +
> > +                       desc->status = PREP;
> > +
> > +                       /* Try to submit a req imm.
> > +                       next to the last completed cookie */
> > +                       fill_queue(pch);
> > +
> > +                       /* Make sure the PL330 Channel thread is active
> */
> > +                       pl330_chan_ctrl(pch->pl330_chid,
> PL330_OP_START);
> > +
> > +                       callback = desc->txd.callback;
> > +                       if (callback)
> > +                               callback(desc->txd.callback_param);
> > +
> > +               }
> > +
> > +       spin_unlock_irqrestore(&pch->lock, flags);
> > +}
> Please merge this with pl330_tasklet and use 'cyclic' flag to
> differentiate.
>
> > @@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum
> pl330_op_err err)
> >
> >        spin_unlock_irqrestore(&pch->lock, flags);
> >
> > +       if (pch->cyclic_task)
> > +               tasklet_schedule(pch->cyclic_task);
> > +       else
> >        tasklet_schedule(&pch->task);
> A tab here please, and check for 'cyclic' flag.
>
>
> > @@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct
> dma_chan *chan)
> >        pl330_release_channel(pch->pl330_chid);
> >        pch->pl330_chid = NULL;
> >
> > +       if (pch->cyclic) {
> > +               pch->cyclic = false;
> > +               list_splice_tail_init(&pch->work_list, &pch->dmac-
> >desc_pool);
> > +               if (pch->cyclic_task) {
> > +                       tasklet_kill(pch->cyclic_task);
> > +                       pch->cyclic_task = NULL;
> > +               }
> > +       }
> > +
> >        spin_unlock_irqrestore(&pch->lock, flags);
> >  }
> To be explicit, please initialize 'cyclic' flag to false in
> pl330_alloc_chan_resources
I will address your comment.

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

* [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
@ 2011-07-26 12:28       ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-26 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

Jassi Brar Wrote:
> Sent: Monday, July 25, 2011 8:24 PM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> Likely; Mark Brown
> Subject: Re: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
>
> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > This patch adds DMA_CYCLIC capability that is used for audio driver.
> > DMA driver with DMA_CYCLIC capability reuses the dma requests that
> > were submitted through tx_submit().
> >
> > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > ---
> >  drivers/dma/pl330.c |  111
> +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 files changed, 111 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > index 880f010..121c75a 100644
> > --- a/drivers/dma/pl330.c
> > +++ b/drivers/dma/pl330.c
> > @@ -69,6 +69,11 @@ struct dma_pl330_chan {
> >         * NULL if the channel is available to be acquired.
> >         */
> >        void *pl330_chid;
> > +
> > +       /* taks for cyclic capability */
> > +       struct tasklet_struct *cyclic_task;
> > +
> > +       bool cyclic;
> >  };
> We already have a tasklet_struct member here.
> This 'cyclic' flag can indicate if we are doing cyclic or serial
> transfers. So, this cyclic_task seems unnecessary.
I will change cyclic operation base on your comment.
Cyclic_task will be removed.

>
> > +static void pl330_tasklet_cyclic(unsigned long data)
> > +{
> > +       struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> > +       struct dma_pl330_desc *desc, *_dt;
> > +       unsigned long flags;
> > +       LIST_HEAD(list);
> > +
> > +       spin_lock_irqsave(&pch->lock, flags);
> > +
> > +       /* Pick up ripe tomatoes */
> > +       list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
> > +               if (desc->status == DONE) {
> > +                       dma_async_tx_callback callback;
> > +
> > +                       list_move_tail(&desc->node, &pch->work_list);
> > +                       pch->completed = desc->txd.cookie;
> > +
> > +                       desc->status = PREP;
> > +
> > +                       /* Try to submit a req imm.
> > +                       next to the last completed cookie */
> > +                       fill_queue(pch);
> > +
> > +                       /* Make sure the PL330 Channel thread is active
> */
> > +                       pl330_chan_ctrl(pch->pl330_chid,
> PL330_OP_START);
> > +
> > +                       callback = desc->txd.callback;
> > +                       if (callback)
> > +                               callback(desc->txd.callback_param);
> > +
> > +               }
> > +
> > +       spin_unlock_irqrestore(&pch->lock, flags);
> > +}
> Please merge this with pl330_tasklet and use 'cyclic' flag to
> differentiate.
>
> > @@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum
> pl330_op_err err)
> >
> >        spin_unlock_irqrestore(&pch->lock, flags);
> >
> > +       if (pch->cyclic_task)
> > +               tasklet_schedule(pch->cyclic_task);
> > +       else
> >        tasklet_schedule(&pch->task);
> A tab here please, and check for 'cyclic' flag.
>
>
> > @@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct
> dma_chan *chan)
> >        pl330_release_channel(pch->pl330_chid);
> >        pch->pl330_chid = NULL;
> >
> > +       if (pch->cyclic) {
> > +               pch->cyclic = false;
> > +               list_splice_tail_init(&pch->work_list, &pch->dmac-
> >desc_pool);
> > +               if (pch->cyclic_task) {
> > +                       tasklet_kill(pch->cyclic_task);
> > +                       pch->cyclic_task = NULL;
> > +               }
> > +       }
> > +
> >        spin_unlock_irqrestore(&pch->lock, flags);
> >  }
> To be explicit, please initialize 'cyclic' flag to false in
> pl330_alloc_chan_resources
I will address your comment.

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

* RE: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
  2011-07-25 13:48         ` Vinod Koul
@ 2011-07-26 13:04           ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-26 13:04 UTC (permalink / raw)
  To: 'Vinod Koul'
  Cc: 'Kukjin Kim', vinod.koul, 'Jassi Brar',
	'Grant Likely', linux-samsung-soc, 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

Vinod Koul Wrote:
> Sent: Monday, July 25, 2011 10:48 PM
> To: Boojin Kim
> Cc: vinod.koul@intel.com; linux-arm-kernel@lists.infradead.org; linux-
> samsung-soc@vger.kernel.org; 'Kukjin Kim'; 'Jassi Brar'; 'Grant
> Likely'; 'Mark Brown'; 'Dan Williams'
> Subject: RE: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG
> command
>
> On Mon, 2011-07-25 at 21:51 +0900, Boojin Kim wrote:
> > Vinod Koul Wrote:
> > > Sent: Monday, July 25, 2011 7:27 PM
> > > To: Boojin Kim
> > > Cc: vinod.koul@intel.com; linux-arm-kernel@lists.infradead.org;
> linux-
> > > samsung-soc@vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> > > Mark Brown; Dan Williams
> > > Subject: Re: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG
> > > command
> > >
> > > On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > > > This patch adds support DMA_SLAVE_CONFIG command.
> > > >
> > > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > > ---
> > > >  drivers/dma/pl330.c |   53
> +++++++++++++++++++++++++++++++++++++----
> > > ---------
> > > >  1 files changed, 39 insertions(+), 14 deletions(-)
> > > >
> > > > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > > > index 586ab39..880f010 100644
> > > > --- a/drivers/dma/pl330.c
> > > > +++ b/drivers/dma/pl330.c
> > > > @@ -256,25 +256,50 @@ static int
> pl330_alloc_chan_resources(struct
> > > dma_chan *chan)
> > > >  static int pl330_control(struct dma_chan *chan, enum
> dma_ctrl_cmd
> > > cmd, unsigned long arg)
> > > >  {
> > > >  	struct dma_pl330_chan *pch = to_pchan(chan);
> > > > -	struct dma_pl330_desc *desc;
> > > > +	struct dma_pl330_desc *desc, *_dt;
> > > >  	unsigned long flags;
> > > > +	struct dma_pl330_dmac *pdmac = pch->dmac;
> > > > +	struct dma_slave_config *slave_config;
> > > > +	struct dma_pl330_peri *peri;
> > > > +	LIST_HEAD(list);
> > > >
> > > > -	/* Only supports DMA_TERMINATE_ALL */
> > > > -	if (cmd != DMA_TERMINATE_ALL)
> > > > -		return -ENXIO;
> > > > -
> > > > -	spin_lock_irqsave(&pch->lock, flags);
> > > > -
> > > > -	/* FLUSH the PL330 Channel thread */
> > > > -	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > > > +	switch (cmd) {
> > > > +	case DMA_TERMINATE_ALL:
> > > > +		spin_lock_irqsave(&pch->lock, flags);
> > > >
> > > > -	/* Mark all desc done */
> > > > -	list_for_each_entry(desc, &pch->work_list, node)
> > > > -		desc->status = DONE;
> > > > +		/* FLUSH the PL330 Channel thread */
> > > > +		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > > >
> > > > -	spin_unlock_irqrestore(&pch->lock, flags);
> > > > +		/* Mark all desc done */
> > > > +		list_for_each_entry_safe(desc, _dt, &pch-
> >work_list , node)
> > > {
> > > > +			desc->status = DONE;
> > > > +			pch->completed = desc->txd.cookie;
> > > > +			list_move_tail(&desc->node, &list);
> > > > +		}
> > > >
> > > > -	pl330_tasklet((unsigned long) pch);
> > > > +		list_splice_tail_init(&list, &pdmac->desc_pool);
> > > > +		spin_unlock_irqrestore(&pch->lock, flags);
> > > > +		break;
> > > > +	case DMA_SLAVE_CONFIG:
> > > > +		slave_config = (struct dma_slave_config *)arg;
> > > > +		peri = pch->chan.private;
> > > > +
> > > > +		if (slave_config->direction == DMA_TO_DEVICE) {
> > > > +			if (slave_config->dst_addr)
> > > > +				peri->fifo_addr = slave_config-
> >dst_addr;
> > > > +			if (slave_config->dst_addr_width)
> > > > +				peri->burst_sz = __ffs(slave_config-
> > > >dst_addr_width);
> > > This doesn't sound right, why can't you use xxx_maxburst field
> instead?
> > Can you explain the problem in more detail?
> > Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or
> __ffs()
> > isn't proper here?
> >
> > Additionally, I will modify this code to consider '_maxburst' field.
> __ffs is okay and sensible.
> I meant you should use proper fields for passing info, which in this
> case would be dst_maxburst for specifying destination burst sizes
I think the naming seems to make confusion.
'Peri->burst_sz' on this code means the width of fifo in bytes of the peri. 
It's same with the meaning 'xxx_addr_width'. So, I think it's proper usage.
'peri->burst_sz' is passed to PL330 HW. PL330 HW wants to get the power of 2 
based the fifo width for it.
For example, If fifo width is 8 bytes, PL330 HW should get '3' for it.
And I will modify code to consider xxx_maxburst.


> --
> ~Vinod Koul
> Intel Corp.

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

* [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
@ 2011-07-26 13:04           ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-26 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

Vinod Koul Wrote:
> Sent: Monday, July 25, 2011 10:48 PM
> To: Boojin Kim
> Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux-
> samsung-soc at vger.kernel.org; 'Kukjin Kim'; 'Jassi Brar'; 'Grant
> Likely'; 'Mark Brown'; 'Dan Williams'
> Subject: RE: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG
> command
>
> On Mon, 2011-07-25 at 21:51 +0900, Boojin Kim wrote:
> > Vinod Koul Wrote:
> > > Sent: Monday, July 25, 2011 7:27 PM
> > > To: Boojin Kim
> > > Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org;
> linux-
> > > samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> > > Mark Brown; Dan Williams
> > > Subject: Re: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG
> > > command
> > >
> > > On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > > > This patch adds support DMA_SLAVE_CONFIG command.
> > > >
> > > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > > ---
> > > >  drivers/dma/pl330.c |   53
> +++++++++++++++++++++++++++++++++++++----
> > > ---------
> > > >  1 files changed, 39 insertions(+), 14 deletions(-)
> > > >
> > > > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > > > index 586ab39..880f010 100644
> > > > --- a/drivers/dma/pl330.c
> > > > +++ b/drivers/dma/pl330.c
> > > > @@ -256,25 +256,50 @@ static int
> pl330_alloc_chan_resources(struct
> > > dma_chan *chan)
> > > >  static int pl330_control(struct dma_chan *chan, enum
> dma_ctrl_cmd
> > > cmd, unsigned long arg)
> > > >  {
> > > >  	struct dma_pl330_chan *pch = to_pchan(chan);
> > > > -	struct dma_pl330_desc *desc;
> > > > +	struct dma_pl330_desc *desc, *_dt;
> > > >  	unsigned long flags;
> > > > +	struct dma_pl330_dmac *pdmac = pch->dmac;
> > > > +	struct dma_slave_config *slave_config;
> > > > +	struct dma_pl330_peri *peri;
> > > > +	LIST_HEAD(list);
> > > >
> > > > -	/* Only supports DMA_TERMINATE_ALL */
> > > > -	if (cmd != DMA_TERMINATE_ALL)
> > > > -		return -ENXIO;
> > > > -
> > > > -	spin_lock_irqsave(&pch->lock, flags);
> > > > -
> > > > -	/* FLUSH the PL330 Channel thread */
> > > > -	pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > > > +	switch (cmd) {
> > > > +	case DMA_TERMINATE_ALL:
> > > > +		spin_lock_irqsave(&pch->lock, flags);
> > > >
> > > > -	/* Mark all desc done */
> > > > -	list_for_each_entry(desc, &pch->work_list, node)
> > > > -		desc->status = DONE;
> > > > +		/* FLUSH the PL330 Channel thread */
> > > > +		pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
> > > >
> > > > -	spin_unlock_irqrestore(&pch->lock, flags);
> > > > +		/* Mark all desc done */
> > > > +		list_for_each_entry_safe(desc, _dt, &pch-
> >work_list , node)
> > > {
> > > > +			desc->status = DONE;
> > > > +			pch->completed = desc->txd.cookie;
> > > > +			list_move_tail(&desc->node, &list);
> > > > +		}
> > > >
> > > > -	pl330_tasklet((unsigned long) pch);
> > > > +		list_splice_tail_init(&list, &pdmac->desc_pool);
> > > > +		spin_unlock_irqrestore(&pch->lock, flags);
> > > > +		break;
> > > > +	case DMA_SLAVE_CONFIG:
> > > > +		slave_config = (struct dma_slave_config *)arg;
> > > > +		peri = pch->chan.private;
> > > > +
> > > > +		if (slave_config->direction == DMA_TO_DEVICE) {
> > > > +			if (slave_config->dst_addr)
> > > > +				peri->fifo_addr = slave_config-
> >dst_addr;
> > > > +			if (slave_config->dst_addr_width)
> > > > +				peri->burst_sz = __ffs(slave_config-
> > > >dst_addr_width);
> > > This doesn't sound right, why can't you use xxx_maxburst field
> instead?
> > Can you explain the problem in more detail?
> > Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or
> __ffs()
> > isn't proper here?
> >
> > Additionally, I will modify this code to consider '_maxburst' field.
> __ffs is okay and sensible.
> I meant you should use proper fields for passing info, which in this
> case would be dst_maxburst for specifying destination burst sizes
I think the naming seems to make confusion.
'Peri->burst_sz' on this code means the width of fifo in bytes of the peri. 
It's same with the meaning 'xxx_addr_width'. So, I think it's proper usage.
'peri->burst_sz' is passed to PL330 HW. PL330 HW wants to get the power of 2 
based the fifo width for it.
For example, If fifo width is 8 bytes, PL330 HW should get '3' for it.
And I will modify code to consider xxx_maxburst.


> --
> ~Vinod Koul
> Intel Corp.

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

* Re: [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
  2011-07-26 13:04           ` Boojin Kim
@ 2011-07-26 13:12             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 13:12 UTC (permalink / raw)
  To: Boojin Kim
  Cc: 'Vinod Koul', 'Kukjin Kim',
	vinod.koul, 'Jassi Brar', 'Grant Likely',
	linux-samsung-soc, 'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Tue, Jul 26, 2011 at 10:04:10PM +0900, Boojin Kim wrote:
> Vinod Koul Wrote:
> > I meant you should use proper fields for passing info, which in this
> > case would be dst_maxburst for specifying destination burst sizes
> I think the naming seems to make confusion.
> 'Peri->burst_sz' on this code means the width of fifo in bytes of the peri. 
> It's same with the meaning 'xxx_addr_width'. So, I think it's proper usage.
> 'peri->burst_sz' is passed to PL330 HW. PL330 HW wants to get the power of 2 
> based the fifo width for it.
> For example, If fifo width is 8 bytes, PL330 HW should get '3' for it.
> And I will modify code to consider xxx_maxburst.

IMHO from your description above, peri->burst_sz is misnamed.  Please
add a comment at this location to say something like:

	/* peri->burst_sz is the peripheral fifo width */

to explain this.

Thanks.

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

* [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
@ 2011-07-26 13:12             ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 13:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 10:04:10PM +0900, Boojin Kim wrote:
> Vinod Koul Wrote:
> > I meant you should use proper fields for passing info, which in this
> > case would be dst_maxburst for specifying destination burst sizes
> I think the naming seems to make confusion.
> 'Peri->burst_sz' on this code means the width of fifo in bytes of the peri. 
> It's same with the meaning 'xxx_addr_width'. So, I think it's proper usage.
> 'peri->burst_sz' is passed to PL330 HW. PL330 HW wants to get the power of 2 
> based the fifo width for it.
> For example, If fifo width is 8 bytes, PL330 HW should get '3' for it.
> And I will modify code to consider xxx_maxburst.

IMHO from your description above, peri->burst_sz is misnamed.  Please
add a comment at this location to say something like:

	/* peri->burst_sz is the peripheral fifo width */

to explain this.

Thanks.

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26  7:57                     ` Russell King - ARM Linux
@ 2011-07-26 13:25                       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 13:25 UTC (permalink / raw)
  To: Vinod Koul
  Cc: linux-samsung-soc, Boojin Kim, vinod.koul, 'Jassi Brar',
	'Grant Likely', 'Kukjin Kim',
	'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Tue, Jul 26, 2011 at 08:57:20AM +0100, Russell King - ARM Linux wrote:
> Here's an updated patch.

Sorry, another one.  I've corrected the slave_sg preparation
interface, and added a paragraph on preparing the scatterlist for
the DMA operation, including mentioning which struct device should
be used for this.

8<----------
From: Russell King <rmk+kernel@arm.linux.org.uk>
DMAEngine: Improve slave/cyclic documentation

Improve the documentation for the slave and cyclic DMA engine support
reformatting it for easier reading, adding further APIs, splitting it
into five steps, and including references to the documentation in
dmaengine.h.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 Documentation/dmaengine.txt |  232 ++++++++++++++++++++++++++++++-------------
 1 files changed, 163 insertions(+), 69 deletions(-)

diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
index 5a0cb1e..c7131a8 100644
--- a/Documentation/dmaengine.txt
+++ b/Documentation/dmaengine.txt
@@ -10,87 +10,181 @@
 Below is a guide to device driver writers on how to use the Slave-DMA API of the
 DMA Engine. This is applicable only for slave DMA usage only.
 
-The slave DMA usage consists of following steps
+The slave DMA usage consists of following steps:
 1. Allocate a DMA slave channel
 2. Set slave and controller specific parameters
 3. Get a descriptor for transaction
 4. Submit the transaction and wait for callback notification
+5. Issue pending requests
 
 1. Allocate a DMA slave channel
-Channel allocation is slightly different in the slave DMA context, client
-drivers typically need a channel from a particular DMA controller only and even
-in some cases a specific channel is desired. To request a channel
-dma_request_channel() API is used.
-
-Interface:
-struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
-		dma_filter_fn filter_fn,
-		void *filter_param);
-where dma_filter_fn is defined as:
-typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
-
-When the optional 'filter_fn' parameter is set to NULL dma_request_channel
-simply returns the first channel that satisfies the capability mask.  Otherwise,
-when the mask parameter is insufficient for specifying the necessary channel,
-the filter_fn routine can be used to disposition the available channels in the
-system. The filter_fn routine is called once for each free channel in the
-system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
-that channel to be the return value from dma_request_channel.  A channel
-allocated via this interface is exclusive to the caller, until
-dma_release_channel() is called.
+
+   Channel allocation is slightly different in the slave DMA context,
+   client drivers typically need a channel from a particular DMA
+   controller only and even in some cases a specific channel is desired.
+   To request a channel dma_request_channel() API is used.
+
+   Interface:
+	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+			dma_filter_fn filter_fn,
+			void *filter_param);
+   where dma_filter_fn is defined as:
+	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
+
+   The 'filter_fn' parameter is optional, but highly recommended for
+   slave and cyclic channels as they typically need to obtain a specific
+   DMA channel.
+
+   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
+   simply returns the first channel that satisfies the capability mask.
+
+   Otherwise, the 'filter_fn' routine will be called once for each free
+   channel which has a capability in 'mask'.  'filter_fn' is expected to
+   return 'true' when the desired DMA channel is found.
+
+   A channel allocated via this interface is exclusive to the caller,
+   until dma_release_channel() is called.
 
 2. Set slave and controller specific parameters
-Next step is always to pass some specific information to the DMA driver. Most of
-the generic information which a slave DMA can use is in struct dma_slave_config.
-It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
-burst lengths etc. If some DMA controllers have more parameters to be sent then
-they should try to embed struct dma_slave_config in their controller specific
-structure. That gives flexibility to client to pass more parameters, if
-required.
-
-Interface:
-int dmaengine_slave_config(struct dma_chan *chan,
-					  struct dma_slave_config *config)
+
+   Next step is always to pass some specific information to the DMA
+   driver.  Most of the generic information which a slave DMA can use
+   is in struct dma_slave_config.  This allows the clients to specify
+   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
+   for the peripheral.
+
+   If some DMA controllers have more parameters to be sent then they
+   should try to embed struct dma_slave_config in their controller
+   specific structure. That gives flexibility to client to pass more
+   parameters, if required.
+
+   Interface:
+	int dmaengine_slave_config(struct dma_chan *chan,
+				  struct dma_slave_config *config)
+
+   Please see the dma_slave_config structure definition in dmaengine.h
+   for a detailed explaination of the struct members.  Please note
+   that the 'direction' member will be going away as it duplicates the
+   direction given in the prepare call.
 
 3. Get a descriptor for transaction
-For slave usage the various modes of slave transfers supported by the
-DMA-engine are:
-slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
-dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
+
+   For slave usage the various modes of slave transfers supported by the
+   DMA-engine are:
+
+   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
+   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
 		  operation is explicitly stopped.
-The non NULL return of this transfer API represents a "descriptor" for the given
-transaction.
-
-Interface:
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
-		struct dma_chan *chan,
-		struct scatterlist *dst_sg, unsigned int dst_nents,
-		struct scatterlist *src_sg, unsigned int src_nents,
+
+   A non-NULL return of this transfer API represents a "descriptor" for
+   the given transaction.
+
+   Interface:
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_slave_sg)(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
 		unsigned long flags);
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_data_direction direction);
 
-4. Submit the transaction and wait for callback notification
-To schedule the transaction to be scheduled by dma device, the "descriptor"
-returned in above (3) needs to be submitted.
-To tell the dma driver that a transaction is ready to be serviced, the
-descriptor->submit() callback needs to be invoked. This chains the descriptor to
-the pending queue.
-The transactions in the pending queue can be activated by calling the
-issue_pending API. If channel is idle then the first transaction in queue is
-started and subsequent ones queued up.
-On completion of the DMA operation the next in queue is submitted and a tasklet
-triggered. The tasklet would then call the client driver completion callback
-routine for notification, if set.
-Interface:
-void dma_async_issue_pending(struct dma_chan *chan);
-
-==============================================================================
-
-Additional usage notes for dma driver writers
-1/ Although DMA engine specifies that completion callback routines cannot submit
-any new operations, but typically for slave DMA subsequent transaction may not
-be available for submit prior to callback routine being called. This requirement
-is not a requirement for DMA-slave devices. But they should take care to drop
-the spin-lock they might be holding before calling the callback routine
+   The peripheral driver is expected to have mapped the scatterlist for
+   the DMA operation prior to calling device_prep_slave_sg, and must
+   keep the scatterlist mapped until the DMA operation has completed.
+   The scatterlist must be mapped using the DMA struct device.  So,
+   normal setup should look like this:
+
+	nr_sg = dma_map_sg(chan->device->dev, sgl, sg_len);
+	if (nr_sg == 0)
+		/* error */
+
+	desc = chan->device->device_prep_slave_sg(chan, sgl, nr_sg,
+			direction, flags);
+
+   Once a descriptor has been obtained, the callback information can be
+   added and the descriptor must then be submitted.  Some DMA engine
+   drivers may hold a spinlock between a successful preparation and
+   submission so it is important that these two operations are closely
+   paired.
+
+   Note:
+	Although the async_tx API specifies that completion callback
+	routines cannot submit any new operations, this is not the
+	case for slave/cyclic DMA.
+
+	For slave DMA, the subsequent transaction may not be available
+	for submission prior to callback function being invoked, so
+	slave DMA callbacks are permitted to prepare and submit a new
+	transaction.
+
+	For cyclic DMA, a callback function may wish to terminate the
+	DMA via dmaengine_terminate_all().
+
+	Therefore, it is important that DMA engine drivers drop any
+	locks before calling the callback function which may cause a
+	deadlock.
+
+	Note that callbacks will always be invoked from the DMA
+	engines tasklet, never from interrupt context.
+
+4. Submit the transaction
+
+   Once the descriptor has been prepared and the callback information
+   added, it must be placed on the DMA engine drivers pending queue.
+
+   Interface:
+	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
+
+   This returns a cookie can be used to check the progress of DMA engine
+   activity via other DMA engine calls not covered in this document.
+
+   dmaengine_submit() will not start the DMA operation, it merely adds
+   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
+
+5. Issue pending DMA requests and wait for callback notification
+
+   The transactions in the pending queue can be activated by calling the
+   issue_pending API. If channel is idle then the first transaction in
+   queue is started and subsequent ones queued up.
+
+   On completion of each DMA operation, the next in queue is started and
+   a tasklet triggered. The tasklet will then call the client driver
+   completion callback routine for notification, if set.
+
+   Interface:
+	void dma_async_issue_pending(struct dma_chan *chan);
+
+Further APIs:
+
+1. int dmaengine_terminate_all(struct dma_chan *chan)
+
+   This causes all activity for the DMA channel to be stopped, and may
+   discard data in the DMA FIFO which hasn't been fully transferred.
+   No callback functions will be called for any incomplete transfers.
+
+2. int dmaengine_pause(struct dma_chan *chan)
+
+   This pauses activity on the DMA channel without data loss.
+
+3. int dmaengine_resume(struct dma_chan *chan)
+
+   Resume a previously paused DMA channel.  It is invalid to resume a
+   channel which is not currently paused.
+
+4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+
+   This can be used to check the status of the channel.  Please see
+   the documentation in include/linux/dmaengine.h for a more complete
+   description of this API.
+
+   This can be used in conjunction with dma_async_is_complete() and
+   the cookie returned from 'descriptor->submit()' to check for
+   completion of a specific DMA transaction.
+
+   Note:
+	Not all DMA engine drivers can return reliable information for
+	a running DMA channel.  It is recommended that DMA engine users
+	pause or stop (via dmaengine_terminate_all) the channel before
+	using this API.

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-26 13:25                       ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 13:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 08:57:20AM +0100, Russell King - ARM Linux wrote:
> Here's an updated patch.

Sorry, another one.  I've corrected the slave_sg preparation
interface, and added a paragraph on preparing the scatterlist for
the DMA operation, including mentioning which struct device should
be used for this.

8<----------
From: Russell King <rmk+kernel@arm.linux.org.uk>
DMAEngine: Improve slave/cyclic documentation

Improve the documentation for the slave and cyclic DMA engine support
reformatting it for easier reading, adding further APIs, splitting it
into five steps, and including references to the documentation in
dmaengine.h.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 Documentation/dmaengine.txt |  232 ++++++++++++++++++++++++++++++-------------
 1 files changed, 163 insertions(+), 69 deletions(-)

diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
index 5a0cb1e..c7131a8 100644
--- a/Documentation/dmaengine.txt
+++ b/Documentation/dmaengine.txt
@@ -10,87 +10,181 @@
 Below is a guide to device driver writers on how to use the Slave-DMA API of the
 DMA Engine. This is applicable only for slave DMA usage only.
 
-The slave DMA usage consists of following steps
+The slave DMA usage consists of following steps:
 1. Allocate a DMA slave channel
 2. Set slave and controller specific parameters
 3. Get a descriptor for transaction
 4. Submit the transaction and wait for callback notification
+5. Issue pending requests
 
 1. Allocate a DMA slave channel
-Channel allocation is slightly different in the slave DMA context, client
-drivers typically need a channel from a particular DMA controller only and even
-in some cases a specific channel is desired. To request a channel
-dma_request_channel() API is used.
-
-Interface:
-struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
-		dma_filter_fn filter_fn,
-		void *filter_param);
-where dma_filter_fn is defined as:
-typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
-
-When the optional 'filter_fn' parameter is set to NULL dma_request_channel
-simply returns the first channel that satisfies the capability mask.  Otherwise,
-when the mask parameter is insufficient for specifying the necessary channel,
-the filter_fn routine can be used to disposition the available channels in the
-system. The filter_fn routine is called once for each free channel in the
-system.  Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
-that channel to be the return value from dma_request_channel.  A channel
-allocated via this interface is exclusive to the caller, until
-dma_release_channel() is called.
+
+   Channel allocation is slightly different in the slave DMA context,
+   client drivers typically need a channel from a particular DMA
+   controller only and even in some cases a specific channel is desired.
+   To request a channel dma_request_channel() API is used.
+
+   Interface:
+	struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+			dma_filter_fn filter_fn,
+			void *filter_param);
+   where dma_filter_fn is defined as:
+	typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
+
+   The 'filter_fn' parameter is optional, but highly recommended for
+   slave and cyclic channels as they typically need to obtain a specific
+   DMA channel.
+
+   When the optional 'filter_fn' parameter is NULL, dma_request_channel()
+   simply returns the first channel that satisfies the capability mask.
+
+   Otherwise, the 'filter_fn' routine will be called once for each free
+   channel which has a capability in 'mask'.  'filter_fn' is expected to
+   return 'true' when the desired DMA channel is found.
+
+   A channel allocated via this interface is exclusive to the caller,
+   until dma_release_channel() is called.
 
 2. Set slave and controller specific parameters
-Next step is always to pass some specific information to the DMA driver. Most of
-the generic information which a slave DMA can use is in struct dma_slave_config.
-It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
-burst lengths etc. If some DMA controllers have more parameters to be sent then
-they should try to embed struct dma_slave_config in their controller specific
-structure. That gives flexibility to client to pass more parameters, if
-required.
-
-Interface:
-int dmaengine_slave_config(struct dma_chan *chan,
-					  struct dma_slave_config *config)
+
+   Next step is always to pass some specific information to the DMA
+   driver.  Most of the generic information which a slave DMA can use
+   is in struct dma_slave_config.  This allows the clients to specify
+   DMA direction, DMA addresses, bus widths, DMA burst lengths etc
+   for the peripheral.
+
+   If some DMA controllers have more parameters to be sent then they
+   should try to embed struct dma_slave_config in their controller
+   specific structure. That gives flexibility to client to pass more
+   parameters, if required.
+
+   Interface:
+	int dmaengine_slave_config(struct dma_chan *chan,
+				  struct dma_slave_config *config)
+
+   Please see the dma_slave_config structure definition in dmaengine.h
+   for a detailed explaination of the struct members.  Please note
+   that the 'direction' member will be going away as it duplicates the
+   direction given in the prepare call.
 
 3. Get a descriptor for transaction
-For slave usage the various modes of slave transfers supported by the
-DMA-engine are:
-slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
-dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
+
+   For slave usage the various modes of slave transfers supported by the
+   DMA-engine are:
+
+   slave_sg	- DMA a list of scatter gather buffers from/to a peripheral
+   dma_cyclic	- Perform a cyclic DMA operation from/to a peripheral till the
 		  operation is explicitly stopped.
-The non NULL return of this transfer API represents a "descriptor" for the given
-transaction.
-
-Interface:
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
-		struct dma_chan *chan,
-		struct scatterlist *dst_sg, unsigned int dst_nents,
-		struct scatterlist *src_sg, unsigned int src_nents,
+
+   A non-NULL return of this transfer API represents a "descriptor" for
+   the given transaction.
+
+   Interface:
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_slave_sg)(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
 		unsigned long flags);
-struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+
+	struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_data_direction direction);
 
-4. Submit the transaction and wait for callback notification
-To schedule the transaction to be scheduled by dma device, the "descriptor"
-returned in above (3) needs to be submitted.
-To tell the dma driver that a transaction is ready to be serviced, the
-descriptor->submit() callback needs to be invoked. This chains the descriptor to
-the pending queue.
-The transactions in the pending queue can be activated by calling the
-issue_pending API. If channel is idle then the first transaction in queue is
-started and subsequent ones queued up.
-On completion of the DMA operation the next in queue is submitted and a tasklet
-triggered. The tasklet would then call the client driver completion callback
-routine for notification, if set.
-Interface:
-void dma_async_issue_pending(struct dma_chan *chan);
-
-==============================================================================
-
-Additional usage notes for dma driver writers
-1/ Although DMA engine specifies that completion callback routines cannot submit
-any new operations, but typically for slave DMA subsequent transaction may not
-be available for submit prior to callback routine being called. This requirement
-is not a requirement for DMA-slave devices. But they should take care to drop
-the spin-lock they might be holding before calling the callback routine
+   The peripheral driver is expected to have mapped the scatterlist for
+   the DMA operation prior to calling device_prep_slave_sg, and must
+   keep the scatterlist mapped until the DMA operation has completed.
+   The scatterlist must be mapped using the DMA struct device.  So,
+   normal setup should look like this:
+
+	nr_sg = dma_map_sg(chan->device->dev, sgl, sg_len);
+	if (nr_sg == 0)
+		/* error */
+
+	desc = chan->device->device_prep_slave_sg(chan, sgl, nr_sg,
+			direction, flags);
+
+   Once a descriptor has been obtained, the callback information can be
+   added and the descriptor must then be submitted.  Some DMA engine
+   drivers may hold a spinlock between a successful preparation and
+   submission so it is important that these two operations are closely
+   paired.
+
+   Note:
+	Although the async_tx API specifies that completion callback
+	routines cannot submit any new operations, this is not the
+	case for slave/cyclic DMA.
+
+	For slave DMA, the subsequent transaction may not be available
+	for submission prior to callback function being invoked, so
+	slave DMA callbacks are permitted to prepare and submit a new
+	transaction.
+
+	For cyclic DMA, a callback function may wish to terminate the
+	DMA via dmaengine_terminate_all().
+
+	Therefore, it is important that DMA engine drivers drop any
+	locks before calling the callback function which may cause a
+	deadlock.
+
+	Note that callbacks will always be invoked from the DMA
+	engines tasklet, never from interrupt context.
+
+4. Submit the transaction
+
+   Once the descriptor has been prepared and the callback information
+   added, it must be placed on the DMA engine drivers pending queue.
+
+   Interface:
+	dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
+
+   This returns a cookie can be used to check the progress of DMA engine
+   activity via other DMA engine calls not covered in this document.
+
+   dmaengine_submit() will not start the DMA operation, it merely adds
+   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
+
+5. Issue pending DMA requests and wait for callback notification
+
+   The transactions in the pending queue can be activated by calling the
+   issue_pending API. If channel is idle then the first transaction in
+   queue is started and subsequent ones queued up.
+
+   On completion of each DMA operation, the next in queue is started and
+   a tasklet triggered. The tasklet will then call the client driver
+   completion callback routine for notification, if set.
+
+   Interface:
+	void dma_async_issue_pending(struct dma_chan *chan);
+
+Further APIs:
+
+1. int dmaengine_terminate_all(struct dma_chan *chan)
+
+   This causes all activity for the DMA channel to be stopped, and may
+   discard data in the DMA FIFO which hasn't been fully transferred.
+   No callback functions will be called for any incomplete transfers.
+
+2. int dmaengine_pause(struct dma_chan *chan)
+
+   This pauses activity on the DMA channel without data loss.
+
+3. int dmaengine_resume(struct dma_chan *chan)
+
+   Resume a previously paused DMA channel.  It is invalid to resume a
+   channel which is not currently paused.
+
+4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
+        dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+
+   This can be used to check the status of the channel.  Please see
+   the documentation in include/linux/dmaengine.h for a more complete
+   description of this API.
+
+   This can be used in conjunction with dma_async_is_complete() and
+   the cookie returned from 'descriptor->submit()' to check for
+   completion of a specific DMA transaction.
+
+   Note:
+	Not all DMA engine drivers can return reliable information for
+	a running DMA channel.  It is recommended that DMA engine users
+	pause or stop (via dmaengine_terminate_all) the channel before
+	using this API.

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26  9:35                       ` Vinod Koul
@ 2011-07-26 14:37                         ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-26 14:37 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Russell King - ARM Linux, vinod.koul, linux-samsung-soc,
	Boojin Kim, Grant Likely, Kukjin Kim, Mark Brown, Dan Williams,
	linux-arm-kernel

On Tue, Jul 26, 2011 at 3:05 PM, Vinod Koul <vkoul@infradead.org> wrote:
> On Tue, 2011-07-26 at 08:57 +0100, Russell King - ARM Linux wrote:
>> Here's an updated patch.
>>
>> 8<----------
>> From: Russell King <rmk+kernel@arm.linux.org.uk>
>> DMAEngine: Improve slave/cyclic documentation
>>
>> Improve the documentation for the slave and cyclic DMA engine support
>> reformatting it for easier reading, adding further APIs, splitting it
>> into five steps, and including references to the documentation in
>> dmaengine.h.
>>
>> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>> ---
>>  Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
>>  1 files changed, 146 insertions(+), 65 deletions(-)
>>
>> diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
>> index 5a0cb1e..8c2e888 100644
>> --- a/Documentation/dmaengine.txt
>> +++ b/Documentation/dmaengine.txt
>> @@ -10,87 +10,168 @@
>>  Below is a guide to device driver writers on how to use the Slave-DMA API of the
>>  DMA Engine. This is applicable only for slave DMA usage only.
>>
>> -The slave DMA usage consists of following steps
>> +The slave DMA usage consists of following steps:
>>  1. Allocate a DMA slave channel
>>  2. Set slave and controller specific parameters
>>  3. Get a descriptor for transaction
>>  4. Submit the transaction and wait for callback notification
>> +5. Issue pending requests
> Thanks Russell,
>
> Applied with change to 4 above. Moved "and wait for callback
> notification" to 5.
>
Dear Vinod,

 Since it came from the RMK, most probably it'll be the best.

But applying patches upon personal timeout seems very dangerous.

People not responding doesn't mean only either people agree completely
or they don't care. Some might be interested but too busy with current tasks
that they need time to check... please make some policy for such cases.

It already happened with the patch from Rob, which you probably have to
revert.

IMHO, if nobody replied, maybe you could first ack the patch and wait
for, say a week, before applying?
That way people will know they have to hurry if they care otherwise
the patch is going upstream as such.

Thanks
-Jassi

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-26 14:37                         ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-26 14:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 3:05 PM, Vinod Koul <vkoul@infradead.org> wrote:
> On Tue, 2011-07-26 at 08:57 +0100, Russell King - ARM Linux wrote:
>> Here's an updated patch.
>>
>> 8<----------
>> From: Russell King <rmk+kernel@arm.linux.org.uk>
>> DMAEngine: Improve slave/cyclic documentation
>>
>> Improve the documentation for the slave and cyclic DMA engine support
>> reformatting it for easier reading, adding further APIs, splitting it
>> into five steps, and including references to the documentation in
>> dmaengine.h.
>>
>> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>> ---
>> ?Documentation/dmaengine.txt | ?211 ++++++++++++++++++++++++++++++-------------
>> ?1 files changed, 146 insertions(+), 65 deletions(-)
>>
>> diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
>> index 5a0cb1e..8c2e888 100644
>> --- a/Documentation/dmaengine.txt
>> +++ b/Documentation/dmaengine.txt
>> @@ -10,87 +10,168 @@
>> ?Below is a guide to device driver writers on how to use the Slave-DMA API of the
>> ?DMA Engine. This is applicable only for slave DMA usage only.
>>
>> -The slave DMA usage consists of following steps
>> +The slave DMA usage consists of following steps:
>> ?1. Allocate a DMA slave channel
>> ?2. Set slave and controller specific parameters
>> ?3. Get a descriptor for transaction
>> ?4. Submit the transaction and wait for callback notification
>> +5. Issue pending requests
> Thanks Russell,
>
> Applied with change to 4 above. Moved "and wait for callback
> notification" to 5.
>
Dear Vinod,

 Since it came from the RMK, most probably it'll be the best.

But applying patches upon personal timeout seems very dangerous.

People not responding doesn't mean only either people agree completely
or they don't care. Some might be interested but too busy with current tasks
that they need time to check... please make some policy for such cases.

It already happened with the patch from Rob, which you probably have to
revert.

IMHO, if nobody replied, maybe you could first ack the patch and wait
for, say a week, before applying?
That way people will know they have to hurry if they care otherwise
the patch is going upstream as such.

Thanks
-Jassi

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26 14:37                         ` Jassi Brar
@ 2011-07-26 17:20                           ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 17:20 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Vinod Koul, vinod.koul, linux-samsung-soc, Boojin Kim,
	Grant Likely, Kukjin Kim, Mark Brown, Dan Williams,
	linux-arm-kernel

On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
> Dear Vinod,
> 
>  Since it came from the RMK, most probably it'll be the best.
> 
> But applying patches upon personal timeout seems very dangerous.

Ehh what?  Is there any contention over this documentation patch?

It's not adding anything new, it's just documenting the facts as they
stand today about the API and its use.

> People not responding doesn't mean only either people agree completely
> or they don't care. Some might be interested but too busy with current tasks
> that they need time to check... please make some policy for such cases.
> 
> It already happened with the patch from Rob, which you probably have to
> revert.
> 
> IMHO, if nobody replied, maybe you could first ack the patch and wait
> for, say a week, before applying?
> That way people will know they have to hurry if they care otherwise
> the patch is going upstream as such.

A week is far too long.  That's how patches get lost and missed.

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-26 17:20                           ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 17:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
> Dear Vinod,
> 
>  Since it came from the RMK, most probably it'll be the best.
> 
> But applying patches upon personal timeout seems very dangerous.

Ehh what?  Is there any contention over this documentation patch?

It's not adding anything new, it's just documenting the facts as they
stand today about the API and its use.

> People not responding doesn't mean only either people agree completely
> or they don't care. Some might be interested but too busy with current tasks
> that they need time to check... please make some policy for such cases.
> 
> It already happened with the patch from Rob, which you probably have to
> revert.
> 
> IMHO, if nobody replied, maybe you could first ack the patch and wait
> for, say a week, before applying?
> That way people will know they have to hurry if they care otherwise
> the patch is going upstream as such.

A week is far too long.  That's how patches get lost and missed.

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

* Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-26  8:02       ` Russell King - ARM Linux
@ 2011-07-26 17:43         ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-26 17:43 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Boojin Kim, Kukjin Kim, Vinod Koul, Mark Brown, Grant Likely,
	linux-samsung-soc, Dan Williams, linux-arm-kernel

On Tue, Jul 26, 2011 at 1:32 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Jul 25, 2011 at 05:21:44PM +0530, Jassi Brar wrote:
>> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
>>
>> > +
>> > +static bool pl330_filter(struct dma_chan *chan, void *param)
>> > +{
>> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private;
>> > +       unsigned dma_ch = (unsigned)param;
>> > +
>> > +       if (peri->peri_id != dma_ch)
>> > +               return false;
>> > +
>> > +       return true;
>> > +}
>> This is what I meant... if we keep chan_id for paltform assigned IDs,
>> these filter functions could simply become
>>
>> static bool pl330_filter(struct dma_chan *chan, void *param)
>> {
>>         return chan->chan_id == param
>> }
>>
>> And ideally in the long run, we could just drop the filter callback
>> and add expected channel ID to the request_channel call.
>
> So what if you have a PL080 and PL330 drivers registered with the DMA
> engine code, and you need to match a specific PL330 channel?
>

Before we start, let me be clear that I don't say it's all possible
today as such.
We will need changes to the API and modifications to the damc/client
drivers (which are already misusing the API as it turns out).

I hope we agree, clients (esp 'generic' ones of the future)
should not ask for channels from a particular dmac.
They should simply tell DMA API, what capabilities they expect
from the allocated channel - of whatever index on whichever dmac.
And the platform should have specified capabilities of a channel
while introducing it to the DMA API.   Yes, imho, DMA API should
only work with a pool of channels and not dmacs - it shouldn't
matter from which dmac a channel comes.

So when a client asks for a channel, the dmaengine would return
the first free channel that has just as much the requested capability.

That is, the generic filter function would look equivalent of :-

      return is_free(chan) && (cap_requested == cap_of(chan) & cap_requested)


Now it all boils down to defining the set of _practically_ possible capabilities
and a method to exchange them between the API, Client and DMAC drivers.

The above is the overall approach.

The following is my idea of implementing it as of now, I am open to suggestions.

Assuming :-
***********
There are no more than 256 types of DMA'able devices
 (MMC, USB, SPI etc) --  [8bits]

A type of device never has more than 16 instances in a platform
 (MMC-0, MMC-1, MMC-2 etc) --  [4bits]

Mem->Mem, Mem->Dev, Dev->Mem, Dev->Dev capability in [4bits]

Max_Burst_Len for any channel is less than 64KB, in power of two [4bits]
Support programmable Max_Burst_Len(tunable in geometric steps of 2)  [1bit]

Max_RW_width/fifo_width is less than 128, in power of two -- [3bits]
Support programmable Max_RW_Width(tunable in geometric steps of 2)  [1bit]

Finally, No platform has more than 128 channels with identicial
capabilities [7bits]


For a channel, when specific values of these fields are appended together,
we get a unqiue 32-bits value called 'chan_id'

Though we can use 64-bits to store the capabilities if we think number
or size of these fields need to be increased.

Thanks,
Jassi

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-26 17:43         ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-26 17:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 1:32 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Jul 25, 2011 at 05:21:44PM +0530, Jassi Brar wrote:
>> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
>>
>> > +
>> > +static bool pl330_filter(struct dma_chan *chan, void *param)
>> > +{
>> > + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private;
>> > + ? ? ? unsigned dma_ch = (unsigned)param;
>> > +
>> > + ? ? ? if (peri->peri_id != dma_ch)
>> > + ? ? ? ? ? ? ? return false;
>> > +
>> > + ? ? ? return true;
>> > +}
>> This is what I meant... if we keep chan_id for paltform assigned IDs,
>> these filter functions could simply become
>>
>> static bool pl330_filter(struct dma_chan *chan, void *param)
>> {
>> ? ? ? ? return chan->chan_id == param
>> }
>>
>> And ideally in the long run, we could just drop the filter callback
>> and add expected channel ID to the request_channel call.
>
> So what if you have a PL080 and PL330 drivers registered with the DMA
> engine code, and you need to match a specific PL330 channel?
>

Before we start, let me be clear that I don't say it's all possible
today as such.
We will need changes to the API and modifications to the damc/client
drivers (which are already misusing the API as it turns out).

I hope we agree, clients (esp 'generic' ones of the future)
should not ask for channels from a particular dmac.
They should simply tell DMA API, what capabilities they expect
from the allocated channel - of whatever index on whichever dmac.
And the platform should have specified capabilities of a channel
while introducing it to the DMA API.   Yes, imho, DMA API should
only work with a pool of channels and not dmacs - it shouldn't
matter from which dmac a channel comes.

So when a client asks for a channel, the dmaengine would return
the first free channel that has just as much the requested capability.

That is, the generic filter function would look equivalent of :-

      return is_free(chan) && (cap_requested == cap_of(chan) & cap_requested)


Now it all boils down to defining the set of _practically_ possible capabilities
and a method to exchange them between the API, Client and DMAC drivers.

The above is the overall approach.

The following is my idea of implementing it as of now, I am open to suggestions.

Assuming :-
***********
There are no more than 256 types of DMA'able devices
 (MMC, USB, SPI etc) --  [8bits]

A type of device never has more than 16 instances in a platform
 (MMC-0, MMC-1, MMC-2 etc) --  [4bits]

Mem->Mem, Mem->Dev, Dev->Mem, Dev->Dev capability in [4bits]

Max_Burst_Len for any channel is less than 64KB, in power of two [4bits]
Support programmable Max_Burst_Len(tunable in geometric steps of 2)  [1bit]

Max_RW_width/fifo_width is less than 128, in power of two -- [3bits]
Support programmable Max_RW_Width(tunable in geometric steps of 2)  [1bit]

Finally, No platform has more than 128 channels with identicial
capabilities [7bits]


For a channel, when specific values of these fields are appended together,
we get a unqiue 32-bits value called 'chan_id'

Though we can use 64-bits to store the capabilities if we think number
or size of these fields need to be increased.

Thanks,
Jassi

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26 17:20                           ` Russell King - ARM Linux
@ 2011-07-26 17:55                             ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-26 17:55 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Vinod Koul, vinod.koul, linux-samsung-soc, Boojin Kim,
	Grant Likely, Kukjin Kim, Mark Brown, Dan Williams,
	linux-arm-kernel

On Tue, Jul 26, 2011 at 10:50 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
>> Dear Vinod,
>>
>>  Since it came from the RMK, most probably it'll be the best.
>>
>> But applying patches upon personal timeout seems very dangerous.
>
> Ehh what?  Is there any contention over this documentation patch?
I haven't yet read it... even after reading I would object only if I found
your patch disturbing enough to disrupt my bowel movements. Which
I don't think would be the case.

I just observed it is second time that Vinod applied a patch without any
ack or prior alert.

>
>> People not responding doesn't mean only either people agree completely
>> or they don't care. Some might be interested but too busy with current tasks
>> that they need time to check... please make some policy for such cases.
>>
>> It already happened with the patch from Rob, which you probably have to
>> revert.
>>
>> IMHO, if nobody replied, maybe you could first ack the patch and wait
>> for, say a week, before applying?
>> That way people will know they have to hurry if they care otherwise
>> the patch is going upstream as such.
>
> A week is far too long.  That's how patches get lost and missed.
>
He may decide to wait shorter, but imho a week after the first ack
isn't that long.

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-26 17:55                             ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-26 17:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 10:50 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
>> Dear Vinod,
>>
>> ?Since it came from the RMK, most probably it'll be the best.
>>
>> But applying patches upon personal timeout seems very dangerous.
>
> Ehh what? ?Is there any contention over this documentation patch?
I haven't yet read it... even after reading I would object only if I found
your patch disturbing enough to disrupt my bowel movements. Which
I don't think would be the case.

I just observed it is second time that Vinod applied a patch without any
ack or prior alert.

>
>> People not responding doesn't mean only either people agree completely
>> or they don't care. Some might be interested but too busy with current tasks
>> that they need time to check... please make some policy for such cases.
>>
>> It already happened with the patch from Rob, which you probably have to
>> revert.
>>
>> IMHO, if nobody replied, maybe you could first ack the patch and wait
>> for, say a week, before applying?
>> That way people will know they have to hurry if they care otherwise
>> the patch is going upstream as such.
>
> A week is far too long. ?That's how patches get lost and missed.
>
He may decide to wait shorter, but imho a week after the first ack
isn't that long.

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26 17:55                             ` Jassi Brar
@ 2011-07-26 18:03                               ` Grant Likely
  -1 siblings, 0 replies; 146+ messages in thread
From: Grant Likely @ 2011-07-26 18:03 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Russell King - ARM Linux, Vinod Koul, vinod.koul,
	linux-samsung-soc, Boojin Kim, Kukjin Kim, Mark Brown,
	Dan Williams, linux-arm-kernel

On Tue, Jul 26, 2011 at 11:55 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Tue, Jul 26, 2011 at 10:50 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
>>> Dear Vinod,
>>>
>>>  Since it came from the RMK, most probably it'll be the best.
>>>
>>> But applying patches upon personal timeout seems very dangerous.
>>
>> Ehh what?  Is there any contention over this documentation patch?
> I haven't yet read it... even after reading I would object only if I found
> your patch disturbing enough to disrupt my bowel movements. Which
> I don't think would be the case.
>
> I just observed it is second time that Vinod applied a patch without any
> ack or prior alert.

Applying patches without waiting for other Acks is absolutely a
reasonable thing for a maintainer to do.  The job of maintainership is
to apply good judgement on when patches can immediately be applied
(and therefore no longer consuming limited attention) and when patches
need further acks.

g.

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-26 18:03                               ` Grant Likely
  0 siblings, 0 replies; 146+ messages in thread
From: Grant Likely @ 2011-07-26 18:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 11:55 AM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Tue, Jul 26, 2011 at 10:50 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
>>> Dear Vinod,
>>>
>>> ?Since it came from the RMK, most probably it'll be the best.
>>>
>>> But applying patches upon personal timeout seems very dangerous.
>>
>> Ehh what? ?Is there any contention over this documentation patch?
> I haven't yet read it... even after reading I would object only if I found
> your patch disturbing enough to disrupt my bowel movements. Which
> I don't think would be the case.
>
> I just observed it is second time that Vinod applied a patch without any
> ack or prior alert.

Applying patches without waiting for other Acks is absolutely a
reasonable thing for a maintainer to do.  The job of maintainership is
to apply good judgement on when patches can immediately be applied
(and therefore no longer consuming limited attention) and when patches
need further acks.

g.

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

* Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-26 17:43         ` Jassi Brar
@ 2011-07-26 18:14           ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 18:14 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Boojin Kim, Kukjin Kim, Vinod Koul, Mark Brown, Grant Likely,
	linux-samsung-soc, Dan Williams, linux-arm-kernel

On Tue, Jul 26, 2011 at 11:13:35PM +0530, Jassi Brar wrote:
> Before we start, let me be clear that I don't say it's all possible
> today as such.

It _is_ possible today.

1. Arrange for individual DMA engine drivers to provide a filter
   function - eg, pl08x_filter_id() for pl08x channels.

2. Have the filter function check chan->device->dev->driver == its
   own struct driver as the very first thing, and reject on failure.

3. Have its own matching algorithm using whatever data is appropriate
   for the DMA engine driver.

4. Platforms (or SoC code) provide the match function plus match data
   via platform data to each driver.

That is essentially (except for (2)) how we deal with differing DMA
engine drivers with AMBA peripherals, and it seems to work remarkably
well.

> I hope we agree, clients (esp 'generic' ones of the future)
> should not ask for channels from a particular dmac.
> They should simply tell DMA API, what capabilities they expect
> from the allocated channel - of whatever index on whichever dmac.
> And the platform should have specified capabilities of a channel
> while introducing it to the DMA API.   Yes, imho, DMA API should
> only work with a pool of channels and not dmacs - it shouldn't
> matter from which dmac a channel comes.

You're quite clearly confused.  "DMA API" has not very much to do with
the subject we're discussing.  The "DMA API" is the API for mapping and
unmapping buffers for DMA.  It has not much to do with the DMA engine
API.  So I'm not going to bother trying to decode what you said above
until you start using the right terminology.  I'm a stickler for that,
get used to it.

No point talking about how round bananas are when you're actually
discussing orange fruit.

> So when a client asks for a channel, the dmaengine would return
> the first free channel that has just as much the requested capability.

No.  For slave DMA, peripheral drivers normally need a specific
channel on the DMA controller.  Peripheral drivers normally do not
know which channel they need, or even which DMA controller they
require.  That information is specific to the platform and SoC.

So, returning the "first free channel that matches the capability"
is senseless - insane - for slave DMA.

> That is, the generic filter function would look equivalent of :-
> 
>       return is_free(chan) && (cap_requested == cap_of(chan) & cap_requested)
> 
> 
> Now it all boils down to defining the set of _practically_ possible capabilities
> and a method to exchange them between the API, Client and DMAC drivers.

What are these capabilities?

> The above is the overall approach.
> 
> The following is my idea of implementing it as of now, I am open to suggestions.
> 
> Assuming :-
> ***********
> There are no more than 256 types of DMA'able devices
>  (MMC, USB, SPI etc) --  [8bits]
> 
> A type of device never has more than 16 instances in a platform
>  (MMC-0, MMC-1, MMC-2 etc) --  [4bits]
> 
> Mem->Mem, Mem->Dev, Dev->Mem, Dev->Dev capability in [4bits]

No.  You're being far too specific to your own DMA controller.  Many
DMA controllers (eg, PL08x) have a number of physical channels, all of
which can be programmed for M2M, M2P, P2M and P2P.  There is nothing
in the design which restricts what a channel can do.

So to put that as the basis for a generic match algorithm is absolutely
senseless.

> Max_Burst_Len for any channel is less than 64KB, in power of two [4bits]
> Support programmable Max_Burst_Len(tunable in geometric steps of 2)  [1bit]
> 
> Max_RW_width/fifo_width is less than 128, in power of two -- [3bits]
> Support programmable Max_RW_Width(tunable in geometric steps of 2)  [1bit]
> 
> Finally, No platform has more than 128 channels with identicial
> capabilities [7bits]

There is absolutely no way that this will work in reality - are you on
a different planet?  As has already been described to you, MMCI can
use one DMA channel, and programs it according to the DMA direction,
and has in the past adjusted the burst size according to what's going
on with the driver.

With your model, it would have to claim N channels from the DMA
engine for all possible different configurations.

That's utterly unworkable and unrealistic.

So no, I don't think your idea of 'capabilities' is any solution.  It
just creates yet more problems - more than it solves.

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-26 18:14           ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 18:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 11:13:35PM +0530, Jassi Brar wrote:
> Before we start, let me be clear that I don't say it's all possible
> today as such.

It _is_ possible today.

1. Arrange for individual DMA engine drivers to provide a filter
   function - eg, pl08x_filter_id() for pl08x channels.

2. Have the filter function check chan->device->dev->driver == its
   own struct driver as the very first thing, and reject on failure.

3. Have its own matching algorithm using whatever data is appropriate
   for the DMA engine driver.

4. Platforms (or SoC code) provide the match function plus match data
   via platform data to each driver.

That is essentially (except for (2)) how we deal with differing DMA
engine drivers with AMBA peripherals, and it seems to work remarkably
well.

> I hope we agree, clients (esp 'generic' ones of the future)
> should not ask for channels from a particular dmac.
> They should simply tell DMA API, what capabilities they expect
> from the allocated channel - of whatever index on whichever dmac.
> And the platform should have specified capabilities of a channel
> while introducing it to the DMA API.   Yes, imho, DMA API should
> only work with a pool of channels and not dmacs - it shouldn't
> matter from which dmac a channel comes.

You're quite clearly confused.  "DMA API" has not very much to do with
the subject we're discussing.  The "DMA API" is the API for mapping and
unmapping buffers for DMA.  It has not much to do with the DMA engine
API.  So I'm not going to bother trying to decode what you said above
until you start using the right terminology.  I'm a stickler for that,
get used to it.

No point talking about how round bananas are when you're actually
discussing orange fruit.

> So when a client asks for a channel, the dmaengine would return
> the first free channel that has just as much the requested capability.

No.  For slave DMA, peripheral drivers normally need a specific
channel on the DMA controller.  Peripheral drivers normally do not
know which channel they need, or even which DMA controller they
require.  That information is specific to the platform and SoC.

So, returning the "first free channel that matches the capability"
is senseless - insane - for slave DMA.

> That is, the generic filter function would look equivalent of :-
> 
>       return is_free(chan) && (cap_requested == cap_of(chan) & cap_requested)
> 
> 
> Now it all boils down to defining the set of _practically_ possible capabilities
> and a method to exchange them between the API, Client and DMAC drivers.

What are these capabilities?

> The above is the overall approach.
> 
> The following is my idea of implementing it as of now, I am open to suggestions.
> 
> Assuming :-
> ***********
> There are no more than 256 types of DMA'able devices
>  (MMC, USB, SPI etc) --  [8bits]
> 
> A type of device never has more than 16 instances in a platform
>  (MMC-0, MMC-1, MMC-2 etc) --  [4bits]
> 
> Mem->Mem, Mem->Dev, Dev->Mem, Dev->Dev capability in [4bits]

No.  You're being far too specific to your own DMA controller.  Many
DMA controllers (eg, PL08x) have a number of physical channels, all of
which can be programmed for M2M, M2P, P2M and P2P.  There is nothing
in the design which restricts what a channel can do.

So to put that as the basis for a generic match algorithm is absolutely
senseless.

> Max_Burst_Len for any channel is less than 64KB, in power of two [4bits]
> Support programmable Max_Burst_Len(tunable in geometric steps of 2)  [1bit]
> 
> Max_RW_width/fifo_width is less than 128, in power of two -- [3bits]
> Support programmable Max_RW_Width(tunable in geometric steps of 2)  [1bit]
> 
> Finally, No platform has more than 128 channels with identicial
> capabilities [7bits]

There is absolutely no way that this will work in reality - are you on
a different planet?  As has already been described to you, MMCI can
use one DMA channel, and programs it according to the DMA direction,
and has in the past adjusted the burst size according to what's going
on with the driver.

With your model, it would have to claim N channels from the DMA
engine for all possible different configurations.

That's utterly unworkable and unrealistic.

So no, I don't think your idea of 'capabilities' is any solution.  It
just creates yet more problems - more than it solves.

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26 17:55                             ` Jassi Brar
@ 2011-07-26 18:16                               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 18:16 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Vinod Koul, vinod.koul, linux-samsung-soc, Boojin Kim,
	Grant Likely, Kukjin Kim, Mark Brown, Dan Williams,
	linux-arm-kernel

On Tue, Jul 26, 2011 at 11:25:13PM +0530, Jassi Brar wrote:
> On Tue, Jul 26, 2011 at 10:50 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
> >> Dear Vinod,
> >>
> >>  Since it came from the RMK, most probably it'll be the best.
> >>
> >> But applying patches upon personal timeout seems very dangerous.
> >
> > Ehh what?  Is there any contention over this documentation patch?
> I haven't yet read it... even after reading I would object only if I found
> your patch disturbing enough to disrupt my bowel movements. Which
> I don't think would be the case.
> 
> I just observed it is second time that Vinod applied a patch without any
> ack or prior alert.

That's what happens - no one says "I'm going to apply this patch" before
they apply it.  They just apply it to their tree and move on.  Vinod,
being the nominated maintainer for the slave DMA engine support has the
authority to do that for that area of code.

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-26 18:16                               ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-26 18:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 11:25:13PM +0530, Jassi Brar wrote:
> On Tue, Jul 26, 2011 at 10:50 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
> >> Dear Vinod,
> >>
> >> ?Since it came from the RMK, most probably it'll be the best.
> >>
> >> But applying patches upon personal timeout seems very dangerous.
> >
> > Ehh what? ?Is there any contention over this documentation patch?
> I haven't yet read it... even after reading I would object only if I found
> your patch disturbing enough to disrupt my bowel movements. Which
> I don't think would be the case.
> 
> I just observed it is second time that Vinod applied a patch without any
> ack or prior alert.

That's what happens - no one says "I'm going to apply this patch" before
they apply it.  They just apply it to their tree and move on.  Vinod,
being the nominated maintainer for the slave DMA engine support has the
authority to do that for that area of code.

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

* Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-26 18:14           ` Russell King - ARM Linux
@ 2011-07-26 19:54             ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-26 19:54 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Boojin Kim, Kukjin Kim, Vinod Koul, Mark Brown, Grant Likely,
	linux-samsung-soc, Dan Williams, linux-arm-kernel

On Tue, Jul 26, 2011 at 11:44 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:

>
> 1. Arrange for individual DMA engine drivers to provide a filter
>   function - eg, pl08x_filter_id() for pl08x channels.
>
> 2. Have the filter function check chan->device->dev->driver == its
>   own struct driver as the very first thing, and reject on failure.
>
> 3. Have its own matching algorithm using whatever data is appropriate
>   for the DMA engine driver.
IMHO it should be possible to have client drivers not use platform specific
details while choosing a channel. Otherwise, they are not really 'generic'
'platform-independent' client drivers.


>> I hope we agree, clients (esp 'generic' ones of the future)
>> should not ask for channels from a particular dmac.
>> They should simply tell DMA API, what capabilities they expect
>> from the allocated channel - of whatever index on whichever dmac.
>> And the platform should have specified capabilities of a channel
>> while introducing it to the DMA API.   Yes, imho, DMA API should
>> only work with a pool of channels and not dmacs - it shouldn't
>> matter from which dmac a channel comes.
>
> You're quite clearly confused.  "DMA API" has not very much to do with
> the subject we're discussing.  The "DMA API" is the API for mapping and
> unmapping buffers for DMA.  It has not much to do with the DMA engine
> API.  So I'm not going to bother trying to decode what you said above
> until you start using the right terminology.  I'm a stickler for that,
> get used to it.
>
> No point talking about how round bananas are when you're actually
> discussing orange fruit.
Sorry, my carelessness.
I should have written DMAENGINE API, instead of DMA API.

If you want I can repost with s/DMA API/DMAENGINE API/

>
>> So when a client asks for a channel, the dmaengine would return
>> the first free channel that has just as much the requested capability.
>
> No.  For slave DMA, peripheral drivers normally need a specific
> channel on the DMA controller.
Of course they do.
And It is the responsibility of platform to encode such information as a
'capability' of the channel.  Capability to reach a particular peripheral, say.

>  Peripheral drivers normally do not
> know which channel they need, or even which DMA controller they
> require.  That information is specific to the platform and SoC.
For that very reason I proposed, say, if MMC client driver is probed
for 2nd instance
of MMC controller, it should ask for the following capabilities
    (MMC << TYPE_SHFT) | (2 << INST_SHFT)    //I don't show other
fields for simplicity

It is the job of _platform_ to set TYPE and INSTANCE fields to
'MMC' and 2 resp _only_ for the channel(s) that can reach its MMC_2 controller.

That way, when the client 'generically' asks for DMA_MMC_2, it will be given
only one of those channels that can talk to second instance of MMC controller.


>> That is, the generic filter function would look equivalent of :-
>>
>>       return is_free(chan) && (cap_requested == cap_of(chan) & cap_requested)
>>
>>
>> Now it all boils down to defining the set of _practically_ possible capabilities
>> and a method to exchange them between the API, Client and DMAC drivers.
>
> What are these capabilities?
I had mentioned the list below under 'Assuming'.  We may add more.

>
>> The above is the overall approach.
>>
>> The following is my idea of implementing it as of now, I am open to suggestions.
>>
>> Assuming :-
>> ***********
>> There are no more than 256 types of DMA'able devices
>>  (MMC, USB, SPI etc) --  [8bits]
>>
>> A type of device never has more than 16 instances in a platform
>>  (MMC-0, MMC-1, MMC-2 etc) --  [4bits]
>>
>> Mem->Mem, Mem->Dev, Dev->Mem, Dev->Dev capability in [4bits]
>
> No.  You're being far too specific to your own DMA controller.  Many
> DMA controllers (eg, PL08x) have a number of physical channels, all of
> which can be programmed for M2M, M2P, P2M and P2P.  There is nothing
> in the design which restricts what a channel can do.
I am not being specific, at least not on this point. Btw, I have worked on pl080
as well and I have tried to be not specific to not only pl330 but also pl080.

If you notice I have assigned 4bits to the field. Each of the 4 bits can be set
independently.
So, a capable pl08x channel can set all 4 bits to indicate that it can
do all 4 types
 - M2M, M2P, P2M and P2P.


>> Max_Burst_Len for any channel is less than 64KB, in power of two [4bits]
>> Support programmable Max_Burst_Len(tunable in geometric steps of 2)  [1bit]
>>
>> Max_RW_width/fifo_width is less than 128, in power of two -- [3bits]
>> Support programmable Max_RW_Width(tunable in geometric steps of 2)  [1bit]
>>
>> Finally, No platform has more than 128 channels with identicial
>> capabilities [7bits]
>
> There is absolutely no way that this will work in reality - are you on
> a different planet?  As has already been described to you, MMCI can
> use one DMA channel, and programs it according to the DMA direction,
> and has in the past adjusted the burst size according to what's going
> on with the driver.
>
> With your model, it would have to claim N channels from the DMA
> engine for all possible different configurations.
I don't think so.
What I proposed is only a list of capabilities and method to _select_ a suitable
channel in a platform independent way.

For example, if MMCI driver wants to be able to change directions, it should
specify Mem->Dev and Dev->Mem capability while requesting a channel.
And use slave_config call to switch directions. (and yes we have to modify
slave_config call and maybe some other parts too)

For being able to change burst size, it could set some 'ignore' bit +
default value
to the 'fifo_width' field so that DMAENGINE ignores checking the fifo_width
capability and upon slave_config either set requested burst_size if supported
or return error if the requested burst size is not supported.
That is implementation detail.

Sincerely, I would to know other capabilities that are more flexible than I have
assumed here or missed altogether.

I have not yet written any code. I just wanted to share my belief that
it is possible
to have client drivers truly independent of the platform they run on.
And by not using platform_data of DMA channels.

Probably you don't, but if you do want, I can send rudimentary implementation
of what I propose, in a few days.

Thanks

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-26 19:54             ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-26 19:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 11:44 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:

>
> 1. Arrange for individual DMA engine drivers to provide a filter
> ? function - eg, pl08x_filter_id() for pl08x channels.
>
> 2. Have the filter function check chan->device->dev->driver == its
> ? own struct driver as the very first thing, and reject on failure.
>
> 3. Have its own matching algorithm using whatever data is appropriate
> ? for the DMA engine driver.
IMHO it should be possible to have client drivers not use platform specific
details while choosing a channel. Otherwise, they are not really 'generic'
'platform-independent' client drivers.


>> I hope we agree, clients (esp 'generic' ones of the future)
>> should not ask for channels from a particular dmac.
>> They should simply tell DMA API, what capabilities they expect
>> from the allocated channel - of whatever index on whichever dmac.
>> And the platform should have specified capabilities of a channel
>> while introducing it to the DMA API. ? Yes, imho, DMA API should
>> only work with a pool of channels and not dmacs - it shouldn't
>> matter from which dmac a channel comes.
>
> You're quite clearly confused. ?"DMA API" has not very much to do with
> the subject we're discussing. ?The "DMA API" is the API for mapping and
> unmapping buffers for DMA. ?It has not much to do with the DMA engine
> API. ?So I'm not going to bother trying to decode what you said above
> until you start using the right terminology. ?I'm a stickler for that,
> get used to it.
>
> No point talking about how round bananas are when you're actually
> discussing orange fruit.
Sorry, my carelessness.
I should have written DMAENGINE API, instead of DMA API.

If you want I can repost with s/DMA API/DMAENGINE API/

>
>> So when a client asks for a channel, the dmaengine would return
>> the first free channel that has just as much the requested capability.
>
> No. ?For slave DMA, peripheral drivers normally need a specific
> channel on the DMA controller.
Of course they do.
And It is the responsibility of platform to encode such information as a
'capability' of the channel.  Capability to reach a particular peripheral, say.

> ?Peripheral drivers normally do not
> know which channel they need, or even which DMA controller they
> require. ?That information is specific to the platform and SoC.
For that very reason I proposed, say, if MMC client driver is probed
for 2nd instance
of MMC controller, it should ask for the following capabilities
    (MMC << TYPE_SHFT) | (2 << INST_SHFT)    //I don't show other
fields for simplicity

It is the job of _platform_ to set TYPE and INSTANCE fields to
'MMC' and 2 resp _only_ for the channel(s) that can reach its MMC_2 controller.

That way, when the client 'generically' asks for DMA_MMC_2, it will be given
only one of those channels that can talk to second instance of MMC controller.


>> That is, the generic filter function would look equivalent of :-
>>
>> ? ? ? return is_free(chan) && (cap_requested == cap_of(chan) & cap_requested)
>>
>>
>> Now it all boils down to defining the set of _practically_ possible capabilities
>> and a method to exchange them between the API, Client and DMAC drivers.
>
> What are these capabilities?
I had mentioned the list below under 'Assuming'.  We may add more.

>
>> The above is the overall approach.
>>
>> The following is my idea of implementing it as of now, I am open to suggestions.
>>
>> Assuming :-
>> ***********
>> There are no more than 256 types of DMA'able devices
>> ?(MMC, USB, SPI etc) -- ?[8bits]
>>
>> A type of device never has more than 16 instances in a platform
>> ?(MMC-0, MMC-1, MMC-2 etc) -- ?[4bits]
>>
>> Mem->Mem, Mem->Dev, Dev->Mem, Dev->Dev capability in [4bits]
>
> No. ?You're being far too specific to your own DMA controller. ?Many
> DMA controllers (eg, PL08x) have a number of physical channels, all of
> which can be programmed for M2M, M2P, P2M and P2P. ?There is nothing
> in the design which restricts what a channel can do.
I am not being specific, at least not on this point. Btw, I have worked on pl080
as well and I have tried to be not specific to not only pl330 but also pl080.

If you notice I have assigned 4bits to the field. Each of the 4 bits can be set
independently.
So, a capable pl08x channel can set all 4 bits to indicate that it can
do all 4 types
 - M2M, M2P, P2M and P2P.


>> Max_Burst_Len for any channel is less than 64KB, in power of two [4bits]
>> Support programmable Max_Burst_Len(tunable in geometric steps of 2) ?[1bit]
>>
>> Max_RW_width/fifo_width is less than 128, in power of two -- [3bits]
>> Support programmable Max_RW_Width(tunable in geometric steps of 2) ?[1bit]
>>
>> Finally, No platform has more than 128 channels with identicial
>> capabilities [7bits]
>
> There is absolutely no way that this will work in reality - are you on
> a different planet? ?As has already been described to you, MMCI can
> use one DMA channel, and programs it according to the DMA direction,
> and has in the past adjusted the burst size according to what's going
> on with the driver.
>
> With your model, it would have to claim N channels from the DMA
> engine for all possible different configurations.
I don't think so.
What I proposed is only a list of capabilities and method to _select_ a suitable
channel in a platform independent way.

For example, if MMCI driver wants to be able to change directions, it should
specify Mem->Dev and Dev->Mem capability while requesting a channel.
And use slave_config call to switch directions. (and yes we have to modify
slave_config call and maybe some other parts too)

For being able to change burst size, it could set some 'ignore' bit +
default value
to the 'fifo_width' field so that DMAENGINE ignores checking the fifo_width
capability and upon slave_config either set requested burst_size if supported
or return error if the requested burst size is not supported.
That is implementation detail.

Sincerely, I would to know other capabilities that are more flexible than I have
assumed here or missed altogether.

I have not yet written any code. I just wanted to share my belief that
it is possible
to have client drivers truly independent of the platform they run on.
And by not using platform_data of DMA channels.

Probably you don't, but if you do want, I can send rudimentary implementation
of what I propose, in a few days.

Thanks

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

* Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-26  9:35       ` Boojin Kim
@ 2011-07-27  1:33         ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-27  1:33 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Kukjin Kim, Grant Likely, Mark Brown

On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim <boojin.kim@samsung.com> wrote:
> Jassi Brar Wrote:
>> Sent: Monday, July 25, 2011 8:52 PM
>> To: Boojin Kim
>> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
>> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
>> Likely; Mark Brown
>> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>>
>> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
>> wrote:
>>
>> > +
>> > +static bool pl330_filter(struct dma_chan *chan, void *param)
>> > +{
>> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan-
>> >private;
>> > +       unsigned dma_ch = (unsigned)param;
>> > +
>> > +       if (peri->peri_id != dma_ch)
>> > +               return false;
>> > +
>> > +       return true;
>> > +}
>> This is what I meant... if we keep chan_id for paltform assigned IDs,
>> these filter functions could simply become
>>
>> static bool pl330_filter(struct dma_chan *chan, void *param)
>> {
>>         return chan->chan_id == param
>> }
>>
>> And ideally in the long run, we could just drop the filter callback
>> and add expected channel ID to the request_channel call.
> The chan_id is set by dmaengine. So, We don't use it to hold the user specific
> Id.
Not for long.
See  https://lkml.org/lkml/2011/7/26/245


>> > +
>> > +static inline int s3c_dma_trigger(unsigned ch)
>> > +{
>> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
>> > +}
>> > +
>> > +static inline int s3c_dma_started(unsigned ch)
>> > +{
>> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
>> > +}
>> > +
>> > +static inline int s3c_dma_flush(unsigned ch)
>> > +{
>> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
>> > +}
>> > +
>> > +static inline int s3c_dma_stop(unsigned ch)
>> > +{
>> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
>> > +}
>> > +
>> > +static struct samsung_dma_ops s3c_dma_ops = {
>> > +       .request        = s3c_dma_request,
>> > +       .release        = s3c_dma_release,
>> > +       .prepare        = s3c_dma_prepare,
>> > +       .trigger        = s3c_dma_trigger,
>> > +       .started        = s3c_dma_started,
>> > +       .flush          = s3c_dma_flush,
>> > +       .stop           = s3c_dma_stop,
>>
>> These last 4 should be gnereallized into one callback with OP argument.
> I don't have any idea about it. Can you explain it in more detail?

static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or similar*/ op)
 {
        return s3c2410_dma_ctrl(ch, op);
 }

static struct samsung_dma_ops s3c_dma_ops = {
        .request        = s3c_dma_request,
        .release        = s3c_dma_release,
        .prepare        = s3c_dma_prepare,
        .control        = s3c_dma_control,

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-27  1:33         ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-27  1:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim <boojin.kim@samsung.com> wrote:
> Jassi Brar Wrote:
>> Sent: Monday, July 25, 2011 8:52 PM
>> To: Boojin Kim
>> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
>> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
>> Likely; Mark Brown
>> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>>
>> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
>> wrote:
>>
>> > +
>> > +static bool pl330_filter(struct dma_chan *chan, void *param)
>> > +{
>> > + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan-
>> >private;
>> > + ? ? ? unsigned dma_ch = (unsigned)param;
>> > +
>> > + ? ? ? if (peri->peri_id != dma_ch)
>> > + ? ? ? ? ? ? ? return false;
>> > +
>> > + ? ? ? return true;
>> > +}
>> This is what I meant... if we keep chan_id for paltform assigned IDs,
>> these filter functions could simply become
>>
>> static bool pl330_filter(struct dma_chan *chan, void *param)
>> {
>> ? ? ? ? return chan->chan_id == param
>> }
>>
>> And ideally in the long run, we could just drop the filter callback
>> and add expected channel ID to the request_channel call.
> The chan_id is set by dmaengine. So, We don't use it to hold the user specific
> Id.
Not for long.
See  https://lkml.org/lkml/2011/7/26/245


>> > +
>> > +static inline int s3c_dma_trigger(unsigned ch)
>> > +{
>> > + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
>> > +}
>> > +
>> > +static inline int s3c_dma_started(unsigned ch)
>> > +{
>> > + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
>> > +}
>> > +
>> > +static inline int s3c_dma_flush(unsigned ch)
>> > +{
>> > + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
>> > +}
>> > +
>> > +static inline int s3c_dma_stop(unsigned ch)
>> > +{
>> > + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
>> > +}
>> > +
>> > +static struct samsung_dma_ops s3c_dma_ops = {
>> > + ? ? ? .request ? ? ? ?= s3c_dma_request,
>> > + ? ? ? .release ? ? ? ?= s3c_dma_release,
>> > + ? ? ? .prepare ? ? ? ?= s3c_dma_prepare,
>> > + ? ? ? .trigger ? ? ? ?= s3c_dma_trigger,
>> > + ? ? ? .started ? ? ? ?= s3c_dma_started,
>> > + ? ? ? .flush ? ? ? ? ?= s3c_dma_flush,
>> > + ? ? ? .stop ? ? ? ? ? = s3c_dma_stop,
>>
>> These last 4 should be gnereallized into one callback with OP argument.
> I don't have any idea about it. Can you explain it in more detail?

static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or similar*/ op)
 {
        return s3c2410_dma_ctrl(ch, op);
 }

static struct samsung_dma_ops s3c_dma_ops = {
        .request        = s3c_dma_request,
        .release        = s3c_dma_release,
        .prepare        = s3c_dma_prepare,
        .control        = s3c_dma_control,

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26 17:55                             ` Jassi Brar
@ 2011-07-27  2:38                               ` Vinod Koul
  -1 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-27  2:38 UTC (permalink / raw)
  To: Jassi Brar
  Cc: linux-samsung-soc, Russell King - ARM Linux, Boojin Kim,
	vinod.koul, Mark Brown, Grant Likely, Kukjin Kim, Dan Williams,
	linux-arm-kernel

On Tue, 2011-07-26 at 23:25 +0530, Jassi Brar wrote:
> On Tue, Jul 26, 2011 at 10:50 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
> >> Dear Vinod,
> >>
> >>  Since it came from the RMK, most probably it'll be the best.
> >>
> >> But applying patches upon personal timeout seems very dangerous.
> >
> > Ehh what?  Is there any contention over this documentation patch?
> I haven't yet read it... even after reading I would object only if I found
> your patch disturbing enough to disrupt my bowel movements. Which
> I don't think would be the case.
Jassi,
Since this was a doc patch, I applied it soon enough, doesn't sound
dangerous to me !
If you have any updates you would like, pls feel free to send a patch.

> 
> I just observed it is second time that Vinod applied a patch without any
> ack or prior alert.
And you can't ignore the fact that you had almost _two_ weeks to ack the
patch from Rob, but....
You will get ample time to ack a patch, if you don't you can always
point out and I will do the right thing, which in this case was to
revert.
> 
> >
> >> People not responding doesn't mean only either people agree completely
> >> or they don't care. Some might be interested but too busy with current tasks
> >> that they need time to check... please make some policy for such cases.
> >>
> >> It already happened with the patch from Rob, which you probably have to
> >> revert.
> >>
> >> IMHO, if nobody replied, maybe you could first ack the patch and wait
> >> for, say a week, before applying?
> >> That way people will know they have to hurry if they care otherwise
> >> the patch is going upstream as such.
> >
> > A week is far too long.  That's how patches get lost and missed.
> >
> He may decide to wait shorter, but imho a week after the first ack
> isn't that long.
> 
> _______________________________________________
> 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] 146+ messages in thread

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-27  2:38                               ` Vinod Koul
  0 siblings, 0 replies; 146+ messages in thread
From: Vinod Koul @ 2011-07-27  2:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2011-07-26 at 23:25 +0530, Jassi Brar wrote:
> On Tue, Jul 26, 2011 at 10:50 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Tue, Jul 26, 2011 at 08:07:44PM +0530, Jassi Brar wrote:
> >> Dear Vinod,
> >>
> >>  Since it came from the RMK, most probably it'll be the best.
> >>
> >> But applying patches upon personal timeout seems very dangerous.
> >
> > Ehh what?  Is there any contention over this documentation patch?
> I haven't yet read it... even after reading I would object only if I found
> your patch disturbing enough to disrupt my bowel movements. Which
> I don't think would be the case.
Jassi,
Since this was a doc patch, I applied it soon enough, doesn't sound
dangerous to me !
If you have any updates you would like, pls feel free to send a patch.

> 
> I just observed it is second time that Vinod applied a patch without any
> ack or prior alert.
And you can't ignore the fact that you had almost _two_ weeks to ack the
patch from Rob, but....
You will get ample time to ack a patch, if you don't you can always
point out and I will do the right thing, which in this case was to
revert.
> 
> >
> >> People not responding doesn't mean only either people agree completely
> >> or they don't care. Some might be interested but too busy with current tasks
> >> that they need time to check... please make some policy for such cases.
> >>
> >> It already happened with the patch from Rob, which you probably have to
> >> revert.
> >>
> >> IMHO, if nobody replied, maybe you could first ack the patch and wait
> >> for, say a week, before applying?
> >> That way people will know they have to hurry if they care otherwise
> >> the patch is going upstream as such.
> >
> > A week is far too long.  That's how patches get lost and missed.
> >
> He may decide to wait shorter, but imho a week after the first ack
> isn't that long.
> 
> _______________________________________________
> 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] 146+ messages in thread

* RE: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
  2011-07-26 10:14         ` Vinod Koul
@ 2011-07-27  5:05           ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-27  5:05 UTC (permalink / raw)
  To: 'Vinod Koul'
  Cc: vinod.koul, 'Kukjin Kim', 'Jassi Brar',
	'Grant Likely', linux-samsung-soc, 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

Vinod Koul Wrote:
> Sent: Tuesday, July 26, 2011 7:15 PM
> To: Boojin Kim
> Cc: vinod.koul@intel.com; 'Kukjin Kim'; 'Jassi Brar'; 'Grant Likely';
> linux-samsung-soc@vger.kernel.org; 'Mark Brown'; 'Dan Williams';
> linux-arm-kernel@lists.infradead.org
> Subject: RE: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
>
> On Tue, 2011-07-26 at 18:31 +0900, Boojin Kim wrote:
> > Vinod Koul Wrote:
> > > Sent: Monday, July 25, 2011 8:17 PM
> > > To: Boojin Kim
> > > Cc: vinod.koul@intel.com; linux-arm-kernel@lists.infradead.org;
> linux-
> > > samsung-soc@vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> > > Mark Brown; Dan Williams
> > > Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine
> API
> > >
> > > On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > > > This patch adds to support DMA generic API to transfer raw
> > > > SPI data. Basiclly the spi driver uses DMA generic API if
> > > > architecture supports it. Otherwise, uses Samsung specific
> > > > S3C-PL330 APIs.
> > > >
> > > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > > Cc: Grant Likely <grant.likely@secretlab.ca>
> > > > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > > > ---
> > > >  drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++---------
> ----
> > > ----------
> > > >  1 files changed, 69 insertions(+), 72 deletions(-)
> > > >
> > > > diff --git a/drivers/spi/spi_s3c64xx.c
> b/drivers/spi/spi_s3c64xx.c
> > > > index 8945e20..a4cf76a 100644
> > > > --- a/drivers/spi/spi_s3c64xx.c
> > > > +++ b/drivers/spi/spi_s3c64xx.c
> > > > @@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
> > > >  	unsigned                        state;
> > > >  	unsigned                        cur_mode, cur_bpw;
> > > >  	unsigned                        cur_speed;
> > > > +	unsigned			rx_ch;
> > > > +	unsigned			tx_ch;
> > > > +	struct samsung_dma_ops		*ops;
> > > >  };
> > > >
> > > >  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
> > > > @@ -227,6 +230,38 @@ static void flush_fifo(struct
> > > s3c64xx_spi_driver_data *sdd)
> > > >  	writel(val, regs + S3C64XX_SPI_CH_CFG);
> > > >  }
> > > >
> > > > +static void s3c64xx_spi_dma_rxcb(void *data)
> > > > +{
> > > > +	struct s3c64xx_spi_driver_data *sdd
> > > > +		= (struct s3c64xx_spi_driver_data *)data;
> > > > +	unsigned long flags;
> > > > +
> > > > +	spin_lock_irqsave(&sdd->lock, flags);
> > > > +
> > > > +	sdd->state &= ~RXBUSY;
> > > > +	/* If the other done */
> > > > +	if (!(sdd->state & TXBUSY))
> > > > +		complete(&sdd->xfer_completion);
> > > > +
> > > > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > > > +}
> > > > +
> > > > +static void s3c64xx_spi_dma_txcb(void *data)
> > > > +{
> > > > +	struct s3c64xx_spi_driver_data *sdd
> > > > +		= (struct s3c64xx_spi_driver_data *)data;
> > > > +	unsigned long flags;
> > > > +
> > > > +	spin_lock_irqsave(&sdd->lock, flags);
> > > > +
> > > > +	sdd->state &= ~TXBUSY;
> > > > +	/* If the other done */
> > > > +	if (!(sdd->state & RXBUSY))
> > > > +		complete(&sdd->xfer_completion);
> > > > +
> > > > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > > > +}
> > > I don't see much diff in these two functions and you should be
> able to
> > > use a generic one which takes care of both TX and RX, does your
> > > callback
> > > data know if the channel is for TX or RX? If not then a helper to
> do
> > > above should take care well and making code simpler
> > I'm very agree with you.
> > But, I think it isn't deeply related to this patch series. So, I
> wish to make
> > and submit it after this patch series is finished.
> >
> Since you are reworking this driver would make sense to do now, it
> doesn't sound to be a big change.
Ok. I will follow your request.
I will make new patch for it and send it with V5 patchset.

>
> --
> ~Vinod Koul
> Intel Corp.

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

* [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
@ 2011-07-27  5:05           ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-27  5:05 UTC (permalink / raw)
  To: linux-arm-kernel

Vinod Koul Wrote:
> Sent: Tuesday, July 26, 2011 7:15 PM
> To: Boojin Kim
> Cc: vinod.koul at intel.com; 'Kukjin Kim'; 'Jassi Brar'; 'Grant Likely';
> linux-samsung-soc at vger.kernel.org; 'Mark Brown'; 'Dan Williams';
> linux-arm-kernel at lists.infradead.org
> Subject: RE: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
>
> On Tue, 2011-07-26 at 18:31 +0900, Boojin Kim wrote:
> > Vinod Koul Wrote:
> > > Sent: Monday, July 25, 2011 8:17 PM
> > > To: Boojin Kim
> > > Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org;
> linux-
> > > samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely;
> > > Mark Brown; Dan Williams
> > > Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine
> API
> > >
> > > On Mon, 2011-07-25 at 10:28 +0900, Boojin Kim wrote:
> > > > This patch adds to support DMA generic API to transfer raw
> > > > SPI data. Basiclly the spi driver uses DMA generic API if
> > > > architecture supports it. Otherwise, uses Samsung specific
> > > > S3C-PL330 APIs.
> > > >
> > > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > > Cc: Grant Likely <grant.likely@secretlab.ca>
> > > > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > > > ---
> > > >  drivers/spi/spi_s3c64xx.c |  141 ++++++++++++++++++++++---------
> ----
> > > ----------
> > > >  1 files changed, 69 insertions(+), 72 deletions(-)
> > > >
> > > > diff --git a/drivers/spi/spi_s3c64xx.c
> b/drivers/spi/spi_s3c64xx.c
> > > > index 8945e20..a4cf76a 100644
> > > > --- a/drivers/spi/spi_s3c64xx.c
> > > > +++ b/drivers/spi/spi_s3c64xx.c
> > > > @@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {
> > > >  	unsigned                        state;
> > > >  	unsigned                        cur_mode, cur_bpw;
> > > >  	unsigned                        cur_speed;
> > > > +	unsigned			rx_ch;
> > > > +	unsigned			tx_ch;
> > > > +	struct samsung_dma_ops		*ops;
> > > >  };
> > > >
> > > >  static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
> > > > @@ -227,6 +230,38 @@ static void flush_fifo(struct
> > > s3c64xx_spi_driver_data *sdd)
> > > >  	writel(val, regs + S3C64XX_SPI_CH_CFG);
> > > >  }
> > > >
> > > > +static void s3c64xx_spi_dma_rxcb(void *data)
> > > > +{
> > > > +	struct s3c64xx_spi_driver_data *sdd
> > > > +		= (struct s3c64xx_spi_driver_data *)data;
> > > > +	unsigned long flags;
> > > > +
> > > > +	spin_lock_irqsave(&sdd->lock, flags);
> > > > +
> > > > +	sdd->state &= ~RXBUSY;
> > > > +	/* If the other done */
> > > > +	if (!(sdd->state & TXBUSY))
> > > > +		complete(&sdd->xfer_completion);
> > > > +
> > > > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > > > +}
> > > > +
> > > > +static void s3c64xx_spi_dma_txcb(void *data)
> > > > +{
> > > > +	struct s3c64xx_spi_driver_data *sdd
> > > > +		= (struct s3c64xx_spi_driver_data *)data;
> > > > +	unsigned long flags;
> > > > +
> > > > +	spin_lock_irqsave(&sdd->lock, flags);
> > > > +
> > > > +	sdd->state &= ~TXBUSY;
> > > > +	/* If the other done */
> > > > +	if (!(sdd->state & RXBUSY))
> > > > +		complete(&sdd->xfer_completion);
> > > > +
> > > > +	spin_unlock_irqrestore(&sdd->lock, flags);
> > > > +}
> > > I don't see much diff in these two functions and you should be
> able to
> > > use a generic one which takes care of both TX and RX, does your
> > > callback
> > > data know if the channel is for TX or RX? If not then a helper to
> do
> > > above should take care well and making code simpler
> > I'm very agree with you.
> > But, I think it isn't deeply related to this patch series. So, I
> wish to make
> > and submit it after this patch series is finished.
> >
> Since you are reworking this driver would make sense to do now, it
> doesn't sound to be a big change.
Ok. I will follow your request.
I will make new patch for it and send it with V5 patchset.

>
> --
> ~Vinod Koul
> Intel Corp.

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

* RE: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-27  1:33         ` Jassi Brar
@ 2011-07-27  5:17           ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-27  5:17 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Vinod Koul',
	'Dan Williams', 'Kukjin Kim',
	'Grant Likely', 'Mark Brown'

Jassi Brar wrote:
> Sent: Wednesday, July 27, 2011 10:34 AM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> Likely; Mark Brown
> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>
> On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > Jassi Brar Wrote:
> >> Sent: Monday, July 25, 2011 8:52 PM
> >> To: Boojin Kim
> >> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> >> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> >> Likely; Mark Brown
> >> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA
> operations
> >>
> >> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
> <boojin.kim@samsung.com>
> >> wrote:
> >>
> >> > +
> >> > +static bool pl330_filter(struct dma_chan *chan, void *param)
> >> > +{
> >> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri
> *)chan-
> >> >private;
> >> > +       unsigned dma_ch = (unsigned)param;
> >> > +
> >> > +       if (peri->peri_id != dma_ch)
> >> > +               return false;
> >> > +
> >> > +       return true;
> >> > +}
> >> This is what I meant... if we keep chan_id for paltform assigned
> IDs,
> >> these filter functions could simply become
> >>
> >> static bool pl330_filter(struct dma_chan *chan, void *param)
> >> {
> >>         return chan->chan_id == param
> >> }
> >>
> >> And ideally in the long run, we could just drop the filter callback
> >> and add expected channel ID to the request_channel call.
> > The chan_id is set by dmaengine. So, We don't use it to hold the
> user specific
> > Id.
> Not for long.
> See  https://lkml.org/lkml/2011/7/26/245
>
>
> >> > +
> >> > +static inline int s3c_dma_trigger(unsigned ch)
> >> > +{
> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
> >> > +}
> >> > +
> >> > +static inline int s3c_dma_started(unsigned ch)
> >> > +{
> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
> >> > +}
> >> > +
> >> > +static inline int s3c_dma_flush(unsigned ch)
> >> > +{
> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
> >> > +}
> >> > +
> >> > +static inline int s3c_dma_stop(unsigned ch)
> >> > +{
> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
> >> > +}
> >> > +
> >> > +static struct samsung_dma_ops s3c_dma_ops = {
> >> > +       .request        = s3c_dma_request,
> >> > +       .release        = s3c_dma_release,
> >> > +       .prepare        = s3c_dma_prepare,
> >> > +       .trigger        = s3c_dma_trigger,
> >> > +       .started        = s3c_dma_started,
> >> > +       .flush          = s3c_dma_flush,
> >> > +       .stop           = s3c_dma_stop,
> >>
> >> These last 4 should be gnereallized into one callback with OP
> argument.
> > I don't have any idea about it. Can you explain it in more detail?
>
> static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or
> similar*/ op)
>  {
>         return s3c2410_dma_ctrl(ch, op);
>  }
>
> static struct samsung_dma_ops s3c_dma_ops = {
>         .request        = s3c_dma_request,
>         .release        = s3c_dma_release,
>         .prepare        = s3c_dma_prepare,
>         .control        = s3c_dma_control,
'Struct samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3c dma' and 
'DMA-OPS' for 'dmaengine'.
If I modify "Struct samsung_dma_ops" as your guide, It gives un-expectable 
effect to DMA-OPS.
Actually, We don't want the client with 'DMA-OPS' uses 'enum s3c2410_chan_op' 
operation anymore.

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-27  5:17           ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-27  5:17 UTC (permalink / raw)
  To: linux-arm-kernel

Jassi Brar wrote:
> Sent: Wednesday, July 27, 2011 10:34 AM
> To: Boojin Kim
> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> Likely; Mark Brown
> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>
> On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > Jassi Brar Wrote:
> >> Sent: Monday, July 25, 2011 8:52 PM
> >> To: Boojin Kim
> >> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> >> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> >> Likely; Mark Brown
> >> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA
> operations
> >>
> >> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
> <boojin.kim@samsung.com>
> >> wrote:
> >>
> >> > +
> >> > +static bool pl330_filter(struct dma_chan *chan, void *param)
> >> > +{
> >> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri
> *)chan-
> >> >private;
> >> > +       unsigned dma_ch = (unsigned)param;
> >> > +
> >> > +       if (peri->peri_id != dma_ch)
> >> > +               return false;
> >> > +
> >> > +       return true;
> >> > +}
> >> This is what I meant... if we keep chan_id for paltform assigned
> IDs,
> >> these filter functions could simply become
> >>
> >> static bool pl330_filter(struct dma_chan *chan, void *param)
> >> {
> >>         return chan->chan_id == param
> >> }
> >>
> >> And ideally in the long run, we could just drop the filter callback
> >> and add expected channel ID to the request_channel call.
> > The chan_id is set by dmaengine. So, We don't use it to hold the
> user specific
> > Id.
> Not for long.
> See  https://lkml.org/lkml/2011/7/26/245
>
>
> >> > +
> >> > +static inline int s3c_dma_trigger(unsigned ch)
> >> > +{
> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
> >> > +}
> >> > +
> >> > +static inline int s3c_dma_started(unsigned ch)
> >> > +{
> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
> >> > +}
> >> > +
> >> > +static inline int s3c_dma_flush(unsigned ch)
> >> > +{
> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
> >> > +}
> >> > +
> >> > +static inline int s3c_dma_stop(unsigned ch)
> >> > +{
> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
> >> > +}
> >> > +
> >> > +static struct samsung_dma_ops s3c_dma_ops = {
> >> > +       .request        = s3c_dma_request,
> >> > +       .release        = s3c_dma_release,
> >> > +       .prepare        = s3c_dma_prepare,
> >> > +       .trigger        = s3c_dma_trigger,
> >> > +       .started        = s3c_dma_started,
> >> > +       .flush          = s3c_dma_flush,
> >> > +       .stop           = s3c_dma_stop,
> >>
> >> These last 4 should be gnereallized into one callback with OP
> argument.
> > I don't have any idea about it. Can you explain it in more detail?
>
> static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or
> similar*/ op)
>  {
>         return s3c2410_dma_ctrl(ch, op);
>  }
>
> static struct samsung_dma_ops s3c_dma_ops = {
>         .request        = s3c_dma_request,
>         .release        = s3c_dma_release,
>         .prepare        = s3c_dma_prepare,
>         .control        = s3c_dma_control,
'Struct samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3c dma' and 
'DMA-OPS' for 'dmaengine'.
If I modify "Struct samsung_dma_ops" as your guide, It gives un-expectable 
effect to DMA-OPS.
Actually, We don't want the client with 'DMA-OPS' uses 'enum s3c2410_chan_op' 
operation anymore.

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

* Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-27  5:17           ` Boojin Kim
@ 2011-07-27  7:57             ` Jassi Brar
  -1 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-27  7:57 UTC (permalink / raw)
  To: Boojin Kim
  Cc: Kukjin Kim, Vinod Koul, Mark Brown, Grant Likely,
	linux-samsung-soc, Dan Williams, linux-arm-kernel

On Wed, Jul 27, 2011 at 10:47 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> Jassi Brar wrote:
>> Sent: Wednesday, July 27, 2011 10:34 AM
>> To: Boojin Kim
>> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
>> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
>> Likely; Mark Brown
>> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>>
>> On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim <boojin.kim@samsung.com>
>> wrote:
>> > Jassi Brar Wrote:
>> >> Sent: Monday, July 25, 2011 8:52 PM
>> >> To: Boojin Kim
>> >> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
>> >> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
>> >> Likely; Mark Brown
>> >> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA
>> operations
>> >>
>> >> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
>> <boojin.kim@samsung.com>
>> >> wrote:
>> >>
>> >> > +
>> >> > +static bool pl330_filter(struct dma_chan *chan, void *param)
>> >> > +{
>> >> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri
>> *)chan-
>> >> >private;
>> >> > +       unsigned dma_ch = (unsigned)param;
>> >> > +
>> >> > +       if (peri->peri_id != dma_ch)
>> >> > +               return false;
>> >> > +
>> >> > +       return true;
>> >> > +}
>> >> This is what I meant... if we keep chan_id for paltform assigned
>> IDs,
>> >> these filter functions could simply become
>> >>
>> >> static bool pl330_filter(struct dma_chan *chan, void *param)
>> >> {
>> >>         return chan->chan_id == param
>> >> }
>> >>
>> >> And ideally in the long run, we could just drop the filter callback
>> >> and add expected channel ID to the request_channel call.
>> > The chan_id is set by dmaengine. So, We don't use it to hold the
>> user specific
>> > Id.
>> Not for long.
>> See  https://lkml.org/lkml/2011/7/26/245
>>
>>
>> >> > +
>> >> > +static inline int s3c_dma_trigger(unsigned ch)
>> >> > +{
>> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
>> >> > +}
>> >> > +
>> >> > +static inline int s3c_dma_started(unsigned ch)
>> >> > +{
>> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
>> >> > +}
>> >> > +
>> >> > +static inline int s3c_dma_flush(unsigned ch)
>> >> > +{
>> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
>> >> > +}
>> >> > +
>> >> > +static inline int s3c_dma_stop(unsigned ch)
>> >> > +{
>> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
>> >> > +}
>> >> > +
>> >> > +static struct samsung_dma_ops s3c_dma_ops = {
>> >> > +       .request        = s3c_dma_request,
>> >> > +       .release        = s3c_dma_release,
>> >> > +       .prepare        = s3c_dma_prepare,
>> >> > +       .trigger        = s3c_dma_trigger,
>> >> > +       .started        = s3c_dma_started,
>> >> > +       .flush          = s3c_dma_flush,
>> >> > +       .stop           = s3c_dma_stop,
>> >>
>> >> These last 4 should be gnereallized into one callback with OP
>> argument.
>> > I don't have any idea about it. Can you explain it in more detail?
>>
>> static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or
>> similar*/ op)
>>  {
>>         return s3c2410_dma_ctrl(ch, op);
>>  }
>>
>> static struct samsung_dma_ops s3c_dma_ops = {
>>         .request        = s3c_dma_request,
>>         .release        = s3c_dma_release,
>>         .prepare        = s3c_dma_prepare,
>>         .control        = s3c_dma_control,
> 'Struct samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3c dma' and
> 'DMA-OPS' for 'dmaengine'.
> If I modify "Struct samsung_dma_ops" as your guide, It gives un-expectable
> effect to DMA-OPS.
> Actually, We don't want the client with 'DMA-OPS' uses 'enum s3c2410_chan_op'
> operation anymore.

" enum s3c2410_chan_op /* or similar */ "  <<<<  note 'or similar'

Defining a callback for each value of the argument doesn't make sense.

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-27  7:57             ` Jassi Brar
  0 siblings, 0 replies; 146+ messages in thread
From: Jassi Brar @ 2011-07-27  7:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 27, 2011 at 10:47 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> Jassi Brar wrote:
>> Sent: Wednesday, July 27, 2011 10:34 AM
>> To: Boojin Kim
>> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
>> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
>> Likely; Mark Brown
>> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>>
>> On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim <boojin.kim@samsung.com>
>> wrote:
>> > Jassi Brar Wrote:
>> >> Sent: Monday, July 25, 2011 8:52 PM
>> >> To: Boojin Kim
>> >> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
>> >> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
>> >> Likely; Mark Brown
>> >> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA
>> operations
>> >>
>> >> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
>> <boojin.kim@samsung.com>
>> >> wrote:
>> >>
>> >> > +
>> >> > +static bool pl330_filter(struct dma_chan *chan, void *param)
>> >> > +{
>> >> > + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri
>> *)chan-
>> >> >private;
>> >> > + ? ? ? unsigned dma_ch = (unsigned)param;
>> >> > +
>> >> > + ? ? ? if (peri->peri_id != dma_ch)
>> >> > + ? ? ? ? ? ? ? return false;
>> >> > +
>> >> > + ? ? ? return true;
>> >> > +}
>> >> This is what I meant... if we keep chan_id for paltform assigned
>> IDs,
>> >> these filter functions could simply become
>> >>
>> >> static bool pl330_filter(struct dma_chan *chan, void *param)
>> >> {
>> >> ? ? ? ? return chan->chan_id == param
>> >> }
>> >>
>> >> And ideally in the long run, we could just drop the filter callback
>> >> and add expected channel ID to the request_channel call.
>> > The chan_id is set by dmaengine. So, We don't use it to hold the
>> user specific
>> > Id.
>> Not for long.
>> See ?https://lkml.org/lkml/2011/7/26/245
>>
>>
>> >> > +
>> >> > +static inline int s3c_dma_trigger(unsigned ch)
>> >> > +{
>> >> > + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
>> >> > +}
>> >> > +
>> >> > +static inline int s3c_dma_started(unsigned ch)
>> >> > +{
>> >> > + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
>> >> > +}
>> >> > +
>> >> > +static inline int s3c_dma_flush(unsigned ch)
>> >> > +{
>> >> > + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
>> >> > +}
>> >> > +
>> >> > +static inline int s3c_dma_stop(unsigned ch)
>> >> > +{
>> >> > + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
>> >> > +}
>> >> > +
>> >> > +static struct samsung_dma_ops s3c_dma_ops = {
>> >> > + ? ? ? .request ? ? ? ?= s3c_dma_request,
>> >> > + ? ? ? .release ? ? ? ?= s3c_dma_release,
>> >> > + ? ? ? .prepare ? ? ? ?= s3c_dma_prepare,
>> >> > + ? ? ? .trigger ? ? ? ?= s3c_dma_trigger,
>> >> > + ? ? ? .started ? ? ? ?= s3c_dma_started,
>> >> > + ? ? ? .flush ? ? ? ? ?= s3c_dma_flush,
>> >> > + ? ? ? .stop ? ? ? ? ? = s3c_dma_stop,
>> >>
>> >> These last 4 should be gnereallized into one callback with OP
>> argument.
>> > I don't have any idea about it. Can you explain it in more detail?
>>
>> static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or
>> similar*/ op)
>> ?{
>> ? ? ? ? return s3c2410_dma_ctrl(ch, op);
>> ?}
>>
>> static struct samsung_dma_ops s3c_dma_ops = {
>> ? ? ? ? .request ? ? ? ?= s3c_dma_request,
>> ? ? ? ? .release ? ? ? ?= s3c_dma_release,
>> ? ? ? ? .prepare ? ? ? ?= s3c_dma_prepare,
>> ? ? ? ? .control ? ? ? ?= s3c_dma_control,
> 'Struct samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3c dma' and
> 'DMA-OPS' for 'dmaengine'.
> If I modify "Struct samsung_dma_ops" as your guide, It gives un-expectable
> effect to DMA-OPS.
> Actually, We don't want the client with 'DMA-OPS' uses 'enum s3c2410_chan_op'
> operation anymore.

" enum s3c2410_chan_op /* or similar */ "  <<<<  note 'or similar'

Defining a callback for each value of the argument doesn't make sense.

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-26  9:35                       ` Vinod Koul
@ 2011-07-27  9:01                         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-27  9:01 UTC (permalink / raw)
  To: Vinod Koul
  Cc: vinod.koul, linux-samsung-soc, Boojin Kim, 'Jassi Brar',
	'Grant Likely', 'Kukjin Kim',
	'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Tue, Jul 26, 2011 at 03:05:33PM +0530, Vinod Koul wrote:
> On Tue, 2011-07-26 at 08:57 +0100, Russell King - ARM Linux wrote:
> > Here's an updated patch.
> > 
> > 8<----------
> > From: Russell King <rmk+kernel@arm.linux.org.uk>
> > DMAEngine: Improve slave/cyclic documentation
> > 
> > Improve the documentation for the slave and cyclic DMA engine support
> > reformatting it for easier reading, adding further APIs, splitting it
> > into five steps, and including references to the documentation in
> > dmaengine.h.
> > 
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > ---
> >  Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
> >  1 files changed, 146 insertions(+), 65 deletions(-)
> > 
> > diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
> > index 5a0cb1e..8c2e888 100644
> > --- a/Documentation/dmaengine.txt
> > +++ b/Documentation/dmaengine.txt
> > @@ -10,87 +10,168 @@
> >  Below is a guide to device driver writers on how to use the Slave-DMA API of the
> >  DMA Engine. This is applicable only for slave DMA usage only.
> >  
> > -The slave DMA usage consists of following steps
> > +The slave DMA usage consists of following steps:
> >  1. Allocate a DMA slave channel
> >  2. Set slave and controller specific parameters
> >  3. Get a descriptor for transaction
> >  4. Submit the transaction and wait for callback notification
> > +5. Issue pending requests
> Thanks Russell,
> 
> Applied with change to 4 above. Moved "and wait for callback
> notification" to 5.

BTW, did you apply this one or the later one with the improved
documentation for dma mapping and fixed interface for slave
transfers etc. ?

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-27  9:01                         ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2011-07-27  9:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 03:05:33PM +0530, Vinod Koul wrote:
> On Tue, 2011-07-26 at 08:57 +0100, Russell King - ARM Linux wrote:
> > Here's an updated patch.
> > 
> > 8<----------
> > From: Russell King <rmk+kernel@arm.linux.org.uk>
> > DMAEngine: Improve slave/cyclic documentation
> > 
> > Improve the documentation for the slave and cyclic DMA engine support
> > reformatting it for easier reading, adding further APIs, splitting it
> > into five steps, and including references to the documentation in
> > dmaengine.h.
> > 
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > ---
> >  Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
> >  1 files changed, 146 insertions(+), 65 deletions(-)
> > 
> > diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
> > index 5a0cb1e..8c2e888 100644
> > --- a/Documentation/dmaengine.txt
> > +++ b/Documentation/dmaengine.txt
> > @@ -10,87 +10,168 @@
> >  Below is a guide to device driver writers on how to use the Slave-DMA API of the
> >  DMA Engine. This is applicable only for slave DMA usage only.
> >  
> > -The slave DMA usage consists of following steps
> > +The slave DMA usage consists of following steps:
> >  1. Allocate a DMA slave channel
> >  2. Set slave and controller specific parameters
> >  3. Get a descriptor for transaction
> >  4. Submit the transaction and wait for callback notification
> > +5. Issue pending requests
> Thanks Russell,
> 
> Applied with change to 4 above. Moved "and wait for callback
> notification" to 5.

BTW, did you apply this one or the later one with the improved
documentation for dma mapping and fixed interface for slave
transfers etc. ?

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

* Re: [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
  2011-07-27  9:01                         ` Russell King - ARM Linux
@ 2011-07-27  9:06                           ` Koul, Vinod
  -1 siblings, 0 replies; 146+ messages in thread
From: Koul, Vinod @ 2011-07-27  9:06 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-samsung-soc, Boojin Kim, 'Jassi Brar',
	'Grant Likely', 'Kukjin Kim',
	'Mark Brown', 'Dan Williams',
	linux-arm-kernel

On Wed, 2011-07-27 at 10:01 +0100, Russell King - ARM Linux wrote:
> On Tue, Jul 26, 2011 at 03:05:33PM +0530, Vinod Koul wrote:
> > On Tue, 2011-07-26 at 08:57 +0100, Russell King - ARM Linux wrote:
> > > Here's an updated patch.
> > > 
> > > 8<----------
> > > From: Russell King <rmk+kernel@arm.linux.org.uk>
> > > DMAEngine: Improve slave/cyclic documentation
> > > 
> > > Improve the documentation for the slave and cyclic DMA engine support
> > > reformatting it for easier reading, adding further APIs, splitting it
> > > into five steps, and including references to the documentation in
> > > dmaengine.h.
> > > 
> > > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > > ---
> > >  Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
> > >  1 files changed, 146 insertions(+), 65 deletions(-)
> > > 
> > > diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
> > > index 5a0cb1e..8c2e888 100644
> > > --- a/Documentation/dmaengine.txt
> > > +++ b/Documentation/dmaengine.txt
> > > @@ -10,87 +10,168 @@
> > >  Below is a guide to device driver writers on how to use the Slave-DMA API of the
> > >  DMA Engine. This is applicable only for slave DMA usage only.
> > >  
> > > -The slave DMA usage consists of following steps
> > > +The slave DMA usage consists of following steps:
> > >  1. Allocate a DMA slave channel
> > >  2. Set slave and controller specific parameters
> > >  3. Get a descriptor for transaction
> > >  4. Submit the transaction and wait for callback notification
> > > +5. Issue pending requests
> > Thanks Russell,
> > 
> > Applied with change to 4 above. Moved "and wait for callback
> > notification" to 5.
> 
> BTW, did you apply this one or the later one with the improved
> documentation for dma mapping and fixed interface for slave
> transfers etc. ?
I changed it to second one, not pushed yet.
I am rebasing the tree to 3.0. You should see updated version in tree
later in the evening today

-- 
~Vinod

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

* [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
@ 2011-07-27  9:06                           ` Koul, Vinod
  0 siblings, 0 replies; 146+ messages in thread
From: Koul, Vinod @ 2011-07-27  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2011-07-27 at 10:01 +0100, Russell King - ARM Linux wrote:
> On Tue, Jul 26, 2011 at 03:05:33PM +0530, Vinod Koul wrote:
> > On Tue, 2011-07-26 at 08:57 +0100, Russell King - ARM Linux wrote:
> > > Here's an updated patch.
> > > 
> > > 8<----------
> > > From: Russell King <rmk+kernel@arm.linux.org.uk>
> > > DMAEngine: Improve slave/cyclic documentation
> > > 
> > > Improve the documentation for the slave and cyclic DMA engine support
> > > reformatting it for easier reading, adding further APIs, splitting it
> > > into five steps, and including references to the documentation in
> > > dmaengine.h.
> > > 
> > > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > > ---
> > >  Documentation/dmaengine.txt |  211 ++++++++++++++++++++++++++++++-------------
> > >  1 files changed, 146 insertions(+), 65 deletions(-)
> > > 
> > > diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
> > > index 5a0cb1e..8c2e888 100644
> > > --- a/Documentation/dmaengine.txt
> > > +++ b/Documentation/dmaengine.txt
> > > @@ -10,87 +10,168 @@
> > >  Below is a guide to device driver writers on how to use the Slave-DMA API of the
> > >  DMA Engine. This is applicable only for slave DMA usage only.
> > >  
> > > -The slave DMA usage consists of following steps
> > > +The slave DMA usage consists of following steps:
> > >  1. Allocate a DMA slave channel
> > >  2. Set slave and controller specific parameters
> > >  3. Get a descriptor for transaction
> > >  4. Submit the transaction and wait for callback notification
> > > +5. Issue pending requests
> > Thanks Russell,
> > 
> > Applied with change to 4 above. Moved "and wait for callback
> > notification" to 5.
> 
> BTW, did you apply this one or the later one with the improved
> documentation for dma mapping and fixed interface for slave
> transfers etc. ?
I changed it to second one, not pushed yet.
I am rebasing the tree to 3.0. You should see updated version in tree
later in the evening today

-- 
~Vinod

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

* RE: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
  2011-07-27  7:57             ` Jassi Brar
@ 2011-07-28  0:38               ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-28  0:38 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: 'Kukjin Kim', 'Vinod Koul', 'Mark Brown',
	'Grant Likely', linux-samsung-soc, 'Dan Williams',
	linux-arm-kernel

Jassi Brar wrote:
> Sent: Wednesday, July 27, 2011 4:58 PM
> To: Boojin Kim
> Cc: Kukjin Kim; Vinod Koul; Mark Brown; Grant Likely; linux-samsung-
> soc@vger.kernel.org; Dan Williams; linux-arm-
> kernel@lists.infradead.org
> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>
> On Wed, Jul 27, 2011 at 10:47 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > Jassi Brar wrote:
> >> Sent: Wednesday, July 27, 2011 10:34 AM
> >> To: Boojin Kim
> >> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> >> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> >> Likely; Mark Brown
> >> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA
> operations
> >>
> >> On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim
> <boojin.kim@samsung.com>
> >> wrote:
> >> > Jassi Brar Wrote:
> >> >> Sent: Monday, July 25, 2011 8:52 PM
> >> >> To: Boojin Kim
> >> >> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> >> >> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> >> >> Likely; Mark Brown
> >> >> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA
> >> operations
> >> >>
> >> >> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
> >> <boojin.kim@samsung.com>
> >> >> wrote:
> >> >>
> >> >> > +
> >> >> > +static bool pl330_filter(struct dma_chan *chan, void *param)
> >> >> > +{
> >> >> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri
> >> *)chan-
> >> >> >private;
> >> >> > +       unsigned dma_ch = (unsigned)param;
> >> >> > +
> >> >> > +       if (peri->peri_id != dma_ch)
> >> >> > +               return false;
> >> >> > +
> >> >> > +       return true;
> >> >> > +}
> >> >> This is what I meant... if we keep chan_id for paltform assigned
> >> IDs,
> >> >> these filter functions could simply become
> >> >>
> >> >> static bool pl330_filter(struct dma_chan *chan, void *param)
> >> >> {
> >> >>         return chan->chan_id == param
> >> >> }
> >> >>
> >> >> And ideally in the long run, we could just drop the filter
> callback
> >> >> and add expected channel ID to the request_channel call.
> >> > The chan_id is set by dmaengine. So, We don't use it to hold the
> >> user specific
> >> > Id.
> >> Not for long.
> >> See  https://lkml.org/lkml/2011/7/26/245
> >>
> >>
> >> >> > +
> >> >> > +static inline int s3c_dma_trigger(unsigned ch)
> >> >> > +{
> >> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
> >> >> > +}
> >> >> > +
> >> >> > +static inline int s3c_dma_started(unsigned ch)
> >> >> > +{
> >> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
> >> >> > +}
> >> >> > +
> >> >> > +static inline int s3c_dma_flush(unsigned ch)
> >> >> > +{
> >> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
> >> >> > +}
> >> >> > +
> >> >> > +static inline int s3c_dma_stop(unsigned ch)
> >> >> > +{
> >> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
> >> >> > +}
> >> >> > +
> >> >> > +static struct samsung_dma_ops s3c_dma_ops = {
> >> >> > +       .request        = s3c_dma_request,
> >> >> > +       .release        = s3c_dma_release,
> >> >> > +       .prepare        = s3c_dma_prepare,
> >> >> > +       .trigger        = s3c_dma_trigger,
> >> >> > +       .started        = s3c_dma_started,
> >> >> > +       .flush          = s3c_dma_flush,
> >> >> > +       .stop           = s3c_dma_stop,
> >> >>
> >> >> These last 4 should be gnereallized into one callback with OP
> >> argument.
> >> > I don't have any idea about it. Can you explain it in more detail?
> >>
> >> static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or
> >> similar*/ op)
> >>  {
> >>         return s3c2410_dma_ctrl(ch, op);
> >>  }
> >>
> >> static struct samsung_dma_ops s3c_dma_ops = {
> >>         .request        = s3c_dma_request,
> >>         .release        = s3c_dma_release,
> >>         .prepare        = s3c_dma_prepare,
> >>         .control        = s3c_dma_control,
> > 'Struct samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3c
> dma' and
> > 'DMA-OPS' for 'dmaengine'.
> > If I modify "Struct samsung_dma_ops" as your guide, It gives un-
> expectable
> > effect to DMA-OPS.
> > Actually, We don't want the client with 'DMA-OPS' uses 'enum
> s3c2410_chan_op'
> > operation anymore.
>
> " enum s3c2410_chan_op /* or similar */ "  <<<<  note 'or similar'
>
> Defining a callback for each value of the argument doesn't make sense.
Yes, The command may not be 'enum s3c2410_chan_op'. But it's very similar with 
'enum s3c2410_chan_op'.
So, It brings same result that I sad.
Actually, I quietly agree with your comment. If the 'struct samsung_dma_ops' 
is only used for 's3c-dma-ops', I would address your comment. But, 'struct 
samsung_dma_ops' is used for all Samsung dma clients. I aim that 'struct 
samsung_dma_ops' provide the DMA clients with 'dmaengine' friendly DMA 
interface without any other command.

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

* [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-28  0:38               ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-28  0:38 UTC (permalink / raw)
  To: linux-arm-kernel

Jassi Brar wrote:
> Sent: Wednesday, July 27, 2011 4:58 PM
> To: Boojin Kim
> Cc: Kukjin Kim; Vinod Koul; Mark Brown; Grant Likely; linux-samsung-
> soc at vger.kernel.org; Dan Williams; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
>
> On Wed, Jul 27, 2011 at 10:47 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > Jassi Brar wrote:
> >> Sent: Wednesday, July 27, 2011 10:34 AM
> >> To: Boojin Kim
> >> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> >> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> >> Likely; Mark Brown
> >> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA
> operations
> >>
> >> On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim
> <boojin.kim@samsung.com>
> >> wrote:
> >> > Jassi Brar Wrote:
> >> >> Sent: Monday, July 25, 2011 8:52 PM
> >> >> To: Boojin Kim
> >> >> Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-
> >> >> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant
> >> >> Likely; Mark Brown
> >> >> Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA
> >> operations
> >> >>
> >> >> On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
> >> <boojin.kim@samsung.com>
> >> >> wrote:
> >> >>
> >> >> > +
> >> >> > +static bool pl330_filter(struct dma_chan *chan, void *param)
> >> >> > +{
> >> >> > +       struct dma_pl330_peri *peri = (struct dma_pl330_peri
> >> *)chan-
> >> >> >private;
> >> >> > +       unsigned dma_ch = (unsigned)param;
> >> >> > +
> >> >> > +       if (peri->peri_id != dma_ch)
> >> >> > +               return false;
> >> >> > +
> >> >> > +       return true;
> >> >> > +}
> >> >> This is what I meant... if we keep chan_id for paltform assigned
> >> IDs,
> >> >> these filter functions could simply become
> >> >>
> >> >> static bool pl330_filter(struct dma_chan *chan, void *param)
> >> >> {
> >> >>         return chan->chan_id == param
> >> >> }
> >> >>
> >> >> And ideally in the long run, we could just drop the filter
> callback
> >> >> and add expected channel ID to the request_channel call.
> >> > The chan_id is set by dmaengine. So, We don't use it to hold the
> >> user specific
> >> > Id.
> >> Not for long.
> >> See  https://lkml.org/lkml/2011/7/26/245
> >>
> >>
> >> >> > +
> >> >> > +static inline int s3c_dma_trigger(unsigned ch)
> >> >> > +{
> >> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
> >> >> > +}
> >> >> > +
> >> >> > +static inline int s3c_dma_started(unsigned ch)
> >> >> > +{
> >> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
> >> >> > +}
> >> >> > +
> >> >> > +static inline int s3c_dma_flush(unsigned ch)
> >> >> > +{
> >> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
> >> >> > +}
> >> >> > +
> >> >> > +static inline int s3c_dma_stop(unsigned ch)
> >> >> > +{
> >> >> > +       return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
> >> >> > +}
> >> >> > +
> >> >> > +static struct samsung_dma_ops s3c_dma_ops = {
> >> >> > +       .request        = s3c_dma_request,
> >> >> > +       .release        = s3c_dma_release,
> >> >> > +       .prepare        = s3c_dma_prepare,
> >> >> > +       .trigger        = s3c_dma_trigger,
> >> >> > +       .started        = s3c_dma_started,
> >> >> > +       .flush          = s3c_dma_flush,
> >> >> > +       .stop           = s3c_dma_stop,
> >> >>
> >> >> These last 4 should be gnereallized into one callback with OP
> >> argument.
> >> > I don't have any idea about it. Can you explain it in more detail?
> >>
> >> static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or
> >> similar*/ op)
> >>  {
> >>         return s3c2410_dma_ctrl(ch, op);
> >>  }
> >>
> >> static struct samsung_dma_ops s3c_dma_ops = {
> >>         .request        = s3c_dma_request,
> >>         .release        = s3c_dma_release,
> >>         .prepare        = s3c_dma_prepare,
> >>         .control        = s3c_dma_control,
> > 'Struct samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3c
> dma' and
> > 'DMA-OPS' for 'dmaengine'.
> > If I modify "Struct samsung_dma_ops" as your guide, It gives un-
> expectable
> > effect to DMA-OPS.
> > Actually, We don't want the client with 'DMA-OPS' uses 'enum
> s3c2410_chan_op'
> > operation anymore.
>
> " enum s3c2410_chan_op /* or similar */ "  <<<<  note 'or similar'
>
> Defining a callback for each value of the argument doesn't make sense.
Yes, The command may not be 'enum s3c2410_chan_op'. But it's very similar with 
'enum s3c2410_chan_op'.
So, It brings same result that I sad.
Actually, I quietly agree with your comment. If the 'struct samsung_dma_ops' 
is only used for 's3c-dma-ops', I would address your comment. But, 'struct 
samsung_dma_ops' is used for all Samsung dma clients. I aim that 'struct 
samsung_dma_ops' provide the DMA clients with 'dmaengine' friendly DMA 
interface without any other command.

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

* RE: [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
  2011-07-25 21:15       ` Grant Likely
@ 2011-07-28  1:23         ` Boojin Kim
  -1 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-28  1:23 UTC (permalink / raw)
  To: 'Grant Likely', 'Jassi Brar'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Vinod Koul',
	'Dan Williams', 'Kukjin Kim',
	'Mark Brown'

Grant Likely Wrote:
> Likely
> Sent: Tuesday, July 26, 2011 6:16 AM
> To: Jassi Brar
> Cc: Boojin Kim; linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Mark Brown
> Subject: Re: [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific
> enum type for dma direction
>
> On Mon, Jul 25, 2011 at 05:38:37PM +0530, Jassi Brar wrote:
> > On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > > This patch removes the samsung specific enum type 's3c2410_dmasrc'
> > > and uses 'dma_data_direction' instead.
> > >
> > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> >
> > Acked-by: Jassi Brar <jassisinghbrar@gmail.com>
> >
> > If this patch was first in the patchset, probably it could have been
> > already merged.
>
> Indeed.  If you move this to the front when you post the next version
> then it can be merged right away.
I tried to move it ahead. But It made some conflicts.
So, I pushed as it is on V5 release.
Sorry.. I would have noticed it before I release V5.

>
> Acked-by: Grant Likely <grant.likely@secretlab.ca>

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

* [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
@ 2011-07-28  1:23         ` Boojin Kim
  0 siblings, 0 replies; 146+ messages in thread
From: Boojin Kim @ 2011-07-28  1:23 UTC (permalink / raw)
  To: linux-arm-kernel

Grant Likely Wrote:
> Likely
> Sent: Tuesday, July 26, 2011 6:16 AM
> To: Jassi Brar
> Cc: Boojin Kim; linux-arm-kernel at lists.infradead.org; linux-samsung-
> soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Mark Brown
> Subject: Re: [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific
> enum type for dma direction
>
> On Mon, Jul 25, 2011 at 05:38:37PM +0530, Jassi Brar wrote:
> > On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > > This patch removes the samsung specific enum type 's3c2410_dmasrc'
> > > and uses 'dma_data_direction' instead.
> > >
> > > Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
> > > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> >
> > Acked-by: Jassi Brar <jassisinghbrar@gmail.com>
> >
> > If this patch was first in the patchset, probably it could have been
> > already merged.
>
> Indeed.  If you move this to the front when you post the next version
> then it can be merged right away.
I tried to move it ahead. But It made some conflicts.
So, I pushed as it is on V5 release.
Sorry.. I would have noticed it before I release V5.

>
> Acked-by: Grant Likely <grant.likely@secretlab.ca>

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

end of thread, other threads:[~2011-07-28  1:23 UTC | newest]

Thread overview: 146+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-25  1:28 [RESEND] [PATCH V4 0/14] To use DMA generic APIs for Samsung DMA Boojin Kim
2011-07-25  1:28 ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-26  6:03   ` Chanwoo Choi
2011-07-26  6:03     ` Chanwoo Choi
2011-07-25  1:28 ` [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  8:57   ` Jassi Brar
2011-07-25  8:57     ` Jassi Brar
2011-07-25  9:48     ` Boojin Kim
2011-07-25  9:48       ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25 10:26   ` Vinod Koul
2011-07-25 10:26     ` Vinod Koul
2011-07-25 12:51     ` Boojin Kim
2011-07-25 12:51       ` Boojin Kim
2011-07-25 13:48       ` Vinod Koul
2011-07-25 13:48         ` Vinod Koul
2011-07-26 13:04         ` Boojin Kim
2011-07-26 13:04           ` Boojin Kim
2011-07-26 13:12           ` Russell King - ARM Linux
2011-07-26 13:12             ` Russell King - ARM Linux
2011-07-25  1:28 ` [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  9:27   ` Russell King - ARM Linux
2011-07-25  9:27     ` Russell King - ARM Linux
2011-07-25 10:31     ` Boojin Kim
2011-07-25 10:31       ` Boojin Kim
2011-07-25 10:36       ` Russell King - ARM Linux
2011-07-25 10:36         ` Russell King - ARM Linux
2011-07-25 10:48         ` Vinod Koul
2011-07-25 10:48           ` Vinod Koul
2011-07-25 10:57           ` Russell King - ARM Linux
2011-07-25 10:57             ` Russell King - ARM Linux
2011-07-25 11:01             ` Vinod Koul
2011-07-25 11:01               ` Vinod Koul
2011-07-25 11:39               ` Russell King - ARM Linux
2011-07-25 11:39                 ` Russell King - ARM Linux
2011-07-25 12:01                 ` Vinod Koul
2011-07-25 12:01                   ` Vinod Koul
2011-07-26  7:57                   ` [PATCH] Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability) Russell King - ARM Linux
2011-07-26  7:57                     ` Russell King - ARM Linux
2011-07-26  9:35                     ` Vinod Koul
2011-07-26  9:35                       ` Vinod Koul
2011-07-26 14:37                       ` Jassi Brar
2011-07-26 14:37                         ` Jassi Brar
2011-07-26 17:20                         ` Russell King - ARM Linux
2011-07-26 17:20                           ` Russell King - ARM Linux
2011-07-26 17:55                           ` Jassi Brar
2011-07-26 17:55                             ` Jassi Brar
2011-07-26 18:03                             ` Grant Likely
2011-07-26 18:03                               ` Grant Likely
2011-07-26 18:16                             ` Russell King - ARM Linux
2011-07-26 18:16                               ` Russell King - ARM Linux
2011-07-27  2:38                             ` Vinod Koul
2011-07-27  2:38                               ` Vinod Koul
2011-07-27  9:01                       ` Russell King - ARM Linux
2011-07-27  9:01                         ` Russell King - ARM Linux
2011-07-27  9:06                         ` Koul, Vinod
2011-07-27  9:06                           ` Koul, Vinod
2011-07-26 13:25                     ` Russell King - ARM Linux
2011-07-26 13:25                       ` Russell King - ARM Linux
2011-07-25 12:36           ` [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability Boojin Kim
2011-07-25 12:36             ` Boojin Kim
2011-07-25 12:34         ` Boojin Kim
2011-07-25 12:34           ` Boojin Kim
2011-07-25 11:24   ` Jassi Brar
2011-07-25 11:24     ` Jassi Brar
2011-07-26 12:28     ` Boojin Kim
2011-07-26 12:28       ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25 10:52   ` Vinod Koul
2011-07-25 10:52     ` Vinod Koul
2011-07-25 11:31   ` Jassi Brar
2011-07-25 11:31     ` Jassi Brar
2011-07-25  1:28 ` [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  9:36   ` Russell King - ARM Linux
2011-07-25  9:36     ` Russell King - ARM Linux
2011-07-25  9:57     ` Boojin Kim
2011-07-25  9:57       ` Boojin Kim
2011-07-25 11:51   ` Jassi Brar
2011-07-25 11:51     ` Jassi Brar
2011-07-26  8:02     ` Russell King - ARM Linux
2011-07-26  8:02       ` Russell King - ARM Linux
2011-07-26 17:43       ` Jassi Brar
2011-07-26 17:43         ` Jassi Brar
2011-07-26 18:14         ` Russell King - ARM Linux
2011-07-26 18:14           ` Russell King - ARM Linux
2011-07-26 19:54           ` Jassi Brar
2011-07-26 19:54             ` Jassi Brar
2011-07-26  9:35     ` Boojin Kim
2011-07-26  9:35       ` Boojin Kim
2011-07-27  1:33       ` Jassi Brar
2011-07-27  1:33         ` Jassi Brar
2011-07-27  5:17         ` Boojin Kim
2011-07-27  5:17           ` Boojin Kim
2011-07-27  7:57           ` Jassi Brar
2011-07-27  7:57             ` Jassi Brar
2011-07-28  0:38             ` Boojin Kim
2011-07-28  0:38               ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25 11:59   ` Jassi Brar
2011-07-25 11:59     ` Jassi Brar
2011-07-25 12:59     ` Boojin Kim
2011-07-25 12:59       ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 08/14] ARM: S5PV210: " Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 09/14] ARM: S5PC100: " Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 10/14] ARM: S5P64X0: " Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  9:40   ` Russell King - ARM Linux
2011-07-25  9:40     ` Russell King - ARM Linux
2011-07-25 10:34     ` Boojin Kim
2011-07-25 10:34       ` Boojin Kim
2011-07-25 11:17   ` Vinod Koul
2011-07-25 11:17     ` Vinod Koul
2011-07-26  9:31     ` Boojin Kim
2011-07-26  9:31       ` Boojin Kim
2011-07-26 10:14       ` Vinod Koul
2011-07-26 10:14         ` Vinod Koul
2011-07-27  5:05         ` Boojin Kim
2011-07-27  5:05           ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 13/14] ASoC: Samsung: Update DMA interface Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25  1:28 ` [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction Boojin Kim
2011-07-25  1:28   ` Boojin Kim
2011-07-25 12:08   ` Jassi Brar
2011-07-25 12:08     ` Jassi Brar
2011-07-25 21:15     ` Grant Likely
2011-07-25 21:15       ` Grant Likely
2011-07-28  1:23       ` Boojin Kim
2011-07-28  1:23         ` Boojin Kim
2011-07-25 10:17 ` [RESEND] [PATCH V4 0/14] To use DMA generic APIs for Samsung DMA Vinod Koul
2011-07-25 10:17   ` Vinod Koul
2011-07-25 11:09   ` Vinod Koul
2011-07-25 11:09     ` Vinod Koul

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.