All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-07-27  5:31 ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King

This patchset adds support DMA generic APIs for Samsung DMA.

The changes from V4 are following:
- Change DMA cyclic capability operation on '04 patch'
	- Remove cyclic_task
	- Initialize 'cyclic' variable on channel request.
- Change pl330 data structure on '02, 07, 08, 09, 10 patches'
	- Move 'fifo_addr' and 'burst_sz' variables from 'struct dma_pl330_peri'
	  to 'struct dma_pl330_chan'
- Change some names on '02, 05 patch'
	- Change DMADEV_PL330 configuration to SAMSUNG_DMA_PL330
	- Add comment for 'burst_sz' variable
- Consider 'xxx_maxburst' on '03, 06 patch'
- Modify pl330_filter() function on '06 patch'
- Merge DMA control code on SPI driver on '13 patch'

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

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-07-27  5:31 ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset adds support DMA generic APIs for Samsung DMA.

The changes from V4 are following:
- Change DMA cyclic capability operation on '04 patch'
	- Remove cyclic_task
	- Initialize 'cyclic' variable on channel request.
- Change pl330 data structure on '02, 07, 08, 09, 10 patches'
	- Move 'fifo_addr' and 'burst_sz' variables from 'struct dma_pl330_peri'
	  to 'struct dma_pl330_chan'
- Change some names on '02, 05 patch'
	- Change DMADEV_PL330 configuration to SAMSUNG_DMA_PL330
	- Add comment for 'burst_sz' variable
- Consider 'xxx_maxburst' on '03, 06 patch'
- Modify pl330_filter() function on '06 patch'
- Merge DMA control code on SPI driver on '13 patch'

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

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

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

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/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] 88+ messages in thread

* [PATCH 01/15] DMA: PL330: Add support runtime PM for PL330 DMAC
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel

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/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] 88+ messages in thread

* [PATCH 02/15] DMA: PL330: Update PL330 DMA API driver
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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        |   13 ++++++++-----
 include/linux/amba/pl330.h |    6 +-----
 3 files changed, 11 insertions(+), 11 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..5a10df9 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -69,6 +69,10 @@ struct dma_pl330_chan {
 	 * NULL if the channel is available to be acquired.
 	 */
 	void *pl330_chid;
+
+	/* For D-to-M and M-to-D channels */
+	int burst_sz; /* the peripheral fifo width */
+	dma_addr_t fifo_addr;
 };
 
 struct dma_pl330_dmac {
@@ -455,7 +459,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 +581,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))
@@ -593,8 +597,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		return NULL;
 	}
 
-	addr = peri->fifo_addr;
-	burst_size = peri->burst_sz;
+	addr = pch->fifo_addr;
 
 	first = NULL;
 
@@ -642,7 +645,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 = pch->burst_sz;
 		desc->rqcfg.brst_len = 1;
 	}
 
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
index cbee7de..d12f077 100644
--- a/include/linux/amba/pl330.h
+++ b/include/linux/amba/pl330.h
@@ -19,12 +19,8 @@ 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 */
-	int burst_sz; /* in power of 2 */
-	dma_addr_t fifo_addr;
 };
 
 struct dma_pl330_platdata {
-- 
1.7.1

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

* [PATCH 02/15] DMA: PL330: Update PL330 DMA API driver
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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        |   13 ++++++++-----
 include/linux/amba/pl330.h |    6 +-----
 3 files changed, 11 insertions(+), 11 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..5a10df9 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -69,6 +69,10 @@ struct dma_pl330_chan {
 	 * NULL if the channel is available to be acquired.
 	 */
 	void *pl330_chid;
+
+	/* For D-to-M and M-to-D channels */
+	int burst_sz; /* the peripheral fifo width */
+	dma_addr_t fifo_addr;
 };
 
 struct dma_pl330_dmac {
@@ -455,7 +459,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 +581,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))
@@ -593,8 +597,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		return NULL;
 	}
 
-	addr = peri->fifo_addr;
-	burst_size = peri->burst_sz;
+	addr = pch->fifo_addr;
 
 	first = NULL;
 
@@ -642,7 +645,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 = pch->burst_sz;
 		desc->rqcfg.brst_len = 1;
 	}
 
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
index cbee7de..d12f077 100644
--- a/include/linux/amba/pl330.h
+++ b/include/linux/amba/pl330.h
@@ -19,12 +19,8 @@ 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 */
-	int burst_sz; /* in power of 2 */
-	dma_addr_t fifo_addr;
 };
 
 struct dma_pl330_platdata {
-- 
1.7.1

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

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

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/pl330.c |   56 ++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 5a10df9..a4c4b62 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -72,6 +72,7 @@ struct dma_pl330_chan {
 
 	/* For D-to-M and M-to-D channels */
 	int burst_sz; /* the peripheral fifo width */
+	int burst_len; /* the number of burst */
 	dma_addr_t fifo_addr;
 };
 
@@ -260,25 +261,52 @@ 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;
+	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;
+
+		if (slave_config->direction == DMA_TO_DEVICE) {
+			if (slave_config->dst_addr)
+				pch->fifo_addr = slave_config->dst_addr;
+			if (slave_config->dst_addr_width)
+				pch->burst_sz = __ffs(slave_config->dst_addr_width);
+			if (slave_config->dst_maxburst)
+				pch->burst_len = slave_config->dst_maxburst;
+		} else if (slave_config->direction == DMA_FROM_DEVICE) {
+			if (slave_config->src_addr)
+				pch->fifo_addr = slave_config->src_addr;
+			if (slave_config->src_addr_width)
+				pch->burst_sz = __ffs(slave_config->src_addr_width);
+			if (slave_config->src_maxburst)
+				pch->burst_len = slave_config->src_maxburst;
+		}
+		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] 88+ messages in thread

* [PATCH 03/15] DMA: PL330: Support DMA_SLAVE_CONFIG command
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel

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/pl330.c |   56 ++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 5a10df9..a4c4b62 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -72,6 +72,7 @@ struct dma_pl330_chan {
 
 	/* For D-to-M and M-to-D channels */
 	int burst_sz; /* the peripheral fifo width */
+	int burst_len; /* the number of burst */
 	dma_addr_t fifo_addr;
 };
 
@@ -260,25 +261,52 @@ 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;
+	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;
+
+		if (slave_config->direction == DMA_TO_DEVICE) {
+			if (slave_config->dst_addr)
+				pch->fifo_addr = slave_config->dst_addr;
+			if (slave_config->dst_addr_width)
+				pch->burst_sz = __ffs(slave_config->dst_addr_width);
+			if (slave_config->dst_maxburst)
+				pch->burst_len = slave_config->dst_maxburst;
+		} else if (slave_config->direction == DMA_FROM_DEVICE) {
+			if (slave_config->src_addr)
+				pch->fifo_addr = slave_config->src_addr;
+			if (slave_config->src_addr_width)
+				pch->burst_sz = __ffs(slave_config->src_addr_width);
+			if (slave_config->src_maxburst)
+				pch->burst_len = slave_config->src_maxburst;
+		}
+		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] 88+ messages in thread

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

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

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/pl330.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index a4c4b62..996b2e9 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -42,6 +42,12 @@ enum desc_status {
 	DONE,
 };
 
+enum cyclic_mode {
+	NO_CYCLIC,
+	CYCLIC_PREP,
+	CYCLIC_TRIGGER,
+};
+
 struct dma_pl330_chan {
 	/* Schedule desc completion */
 	struct tasklet_struct task;
@@ -74,6 +80,9 @@ struct dma_pl330_chan {
 	int burst_sz; /* the peripheral fifo width */
 	int burst_len; /* the number of burst */
 	dma_addr_t fifo_addr;
+
+	/* for cyclic capability */
+	enum cyclic_mode cyclic;
 };
 
 struct dma_pl330_dmac {
@@ -160,6 +169,31 @@ static inline void free_desc_list(struct list_head *list)
 	spin_unlock_irqrestore(&pdmac->pool_lock, flags);
 }
 
+static inline void handle_cyclic_desc_list(struct list_head *list)
+{
+	struct dma_pl330_desc *desc;
+	struct dma_pl330_chan *pch;
+	unsigned long flags;
+
+	if (list_empty(list))
+		return;
+
+	list_for_each_entry(desc, list, node) {
+		dma_async_tx_callback callback;
+
+		/* Change status to reload it */
+		desc->status = PREP;
+		pch = desc->pchan;
+		callback = desc->txd.callback;
+		if (callback)
+			callback(desc->txd.callback_param);
+	}
+
+	spin_lock_irqsave(&pch->lock, flags);
+	list_splice_tail_init(list, &pch->work_list);
+	spin_unlock_irqrestore(&pch->lock, flags);
+}
+
 static inline void fill_queue(struct dma_pl330_chan *pch)
 {
 	struct dma_pl330_desc *desc;
@@ -213,7 +247,10 @@ static void pl330_tasklet(unsigned long data)
 
 	spin_unlock_irqrestore(&pch->lock, flags);
 
-	free_desc_list(&list);
+	if (pch->cyclic == CYCLIC_TRIGGER)
+		handle_cyclic_desc_list(&list);
+	else
+		free_desc_list(&list);
 }
 
 static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
@@ -244,6 +281,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
 	spin_lock_irqsave(&pch->lock, flags);
 
 	pch->completed = chan->cookie = 1;
+	pch->cyclic = NO_CYCLIC;
 
 	pch->pl330_chid = pl330_request_channel(&pdmac->pif);
 	if (!pch->pl330_chid) {
@@ -323,6 +361,9 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
 	pl330_release_channel(pch->pl330_chid);
 	pch->pl330_chid = NULL;
 
+	if (pch->cyclic)
+		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
+
 	spin_unlock_irqrestore(&pch->lock, flags);
 }
 
@@ -346,7 +387,11 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 
 static void pl330_issue_pending(struct dma_chan *chan)
 {
-	pl330_tasklet((unsigned long) to_pchan(chan));
+	struct dma_pl330_chan *pch = to_pchan(chan);
+	pl330_tasklet((unsigned long) pch);
+
+	if (pch->cyclic == CYCLIC_PREP)
+		pch->cyclic = CYCLIC_TRIGGER;
 }
 
 /*
@@ -554,6 +599,52 @@ 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);
+	dma_addr_t dst;
+	dma_addr_t src;
+
+	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 = pch->fifo_addr;
+		break;
+	case DMA_FROM_DEVICE:
+		desc->rqcfg.src_inc = 0;
+		desc->rqcfg.dst_inc = 1;
+		src = pch->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 = pch->burst_sz;
+	desc->rqcfg.brst_len = 1;
+
+	if (!pch->cyclic)
+		pch->cyclic = CYCLIC_PREP;
+
+	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)
@@ -786,6 +877,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");
@@ -810,6 +902,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] 88+ messages in thread

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

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

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/pl330.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index a4c4b62..996b2e9 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -42,6 +42,12 @@ enum desc_status {
 	DONE,
 };
 
+enum cyclic_mode {
+	NO_CYCLIC,
+	CYCLIC_PREP,
+	CYCLIC_TRIGGER,
+};
+
 struct dma_pl330_chan {
 	/* Schedule desc completion */
 	struct tasklet_struct task;
@@ -74,6 +80,9 @@ struct dma_pl330_chan {
 	int burst_sz; /* the peripheral fifo width */
 	int burst_len; /* the number of burst */
 	dma_addr_t fifo_addr;
+
+	/* for cyclic capability */
+	enum cyclic_mode cyclic;
 };
 
 struct dma_pl330_dmac {
@@ -160,6 +169,31 @@ static inline void free_desc_list(struct list_head *list)
 	spin_unlock_irqrestore(&pdmac->pool_lock, flags);
 }
 
+static inline void handle_cyclic_desc_list(struct list_head *list)
+{
+	struct dma_pl330_desc *desc;
+	struct dma_pl330_chan *pch;
+	unsigned long flags;
+
+	if (list_empty(list))
+		return;
+
+	list_for_each_entry(desc, list, node) {
+		dma_async_tx_callback callback;
+
+		/* Change status to reload it */
+		desc->status = PREP;
+		pch = desc->pchan;
+		callback = desc->txd.callback;
+		if (callback)
+			callback(desc->txd.callback_param);
+	}
+
+	spin_lock_irqsave(&pch->lock, flags);
+	list_splice_tail_init(list, &pch->work_list);
+	spin_unlock_irqrestore(&pch->lock, flags);
+}
+
 static inline void fill_queue(struct dma_pl330_chan *pch)
 {
 	struct dma_pl330_desc *desc;
@@ -213,7 +247,10 @@ static void pl330_tasklet(unsigned long data)
 
 	spin_unlock_irqrestore(&pch->lock, flags);
 
-	free_desc_list(&list);
+	if (pch->cyclic == CYCLIC_TRIGGER)
+		handle_cyclic_desc_list(&list);
+	else
+		free_desc_list(&list);
 }
 
 static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
@@ -244,6 +281,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
 	spin_lock_irqsave(&pch->lock, flags);
 
 	pch->completed = chan->cookie = 1;
+	pch->cyclic = NO_CYCLIC;
 
 	pch->pl330_chid = pl330_request_channel(&pdmac->pif);
 	if (!pch->pl330_chid) {
@@ -323,6 +361,9 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
 	pl330_release_channel(pch->pl330_chid);
 	pch->pl330_chid = NULL;
 
+	if (pch->cyclic)
+		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
+
 	spin_unlock_irqrestore(&pch->lock, flags);
 }
 
@@ -346,7 +387,11 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 
 static void pl330_issue_pending(struct dma_chan *chan)
 {
-	pl330_tasklet((unsigned long) to_pchan(chan));
+	struct dma_pl330_chan *pch = to_pchan(chan);
+	pl330_tasklet((unsigned long) pch);
+
+	if (pch->cyclic == CYCLIC_PREP)
+		pch->cyclic = CYCLIC_TRIGGER;
 }
 
 /*
@@ -554,6 +599,52 @@ 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);
+	dma_addr_t dst;
+	dma_addr_t src;
+
+	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 = pch->fifo_addr;
+		break;
+	case DMA_FROM_DEVICE:
+		desc->rqcfg.src_inc = 0;
+		desc->rqcfg.dst_inc = 1;
+		src = pch->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 = pch->burst_sz;
+	desc->rqcfg.brst_len = 1;
+
+	if (!pch->cyclic)
+		pch->cyclic = CYCLIC_PREP;
+
+	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)
@@ -786,6 +877,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");
@@ -810,6 +902,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] 88+ messages in thread

* [PATCH 05/15] ARM: SAMSUNG: Update to use PL330-DMA driver
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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}  |    8 ++++----
 .../plat-samsung/include/plat/s3c-pl330-pdata.h    |    2 +-
 7 files changed, 18 insertions(+), 10 deletions(-)
 rename arch/arm/plat-samsung/include/plat/{s3c-dma-pl330.h => dma-pl330.h} (93%)

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..8b4e63f 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 SAMSUNG_DMA_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 93%
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..0a5dade 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -8,8 +8,8 @@
  * (at your option) any later version.
  */
 
-#ifndef	__S3C_DMA_PL330_H_
-#define	__S3C_DMA_PL330_H_
+#ifndef __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
 
 #define S3C2410_DMAF_AUTOSTART		(1 << 0)
 #define S3C2410_DMAF_CIRCULAR		(1 << 1)
@@ -20,7 +20,7 @@
  * 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 {
@@ -95,4 +95,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] 88+ messages in thread

* [PATCH 05/15] ARM: SAMSUNG: Update to use PL330-DMA driver
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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}  |    8 ++++----
 .../plat-samsung/include/plat/s3c-pl330-pdata.h    |    2 +-
 7 files changed, 18 insertions(+), 10 deletions(-)
 rename arch/arm/plat-samsung/include/plat/{s3c-dma-pl330.h => dma-pl330.h} (93%)

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..8b4e63f 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 SAMSUNG_DMA_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 93%
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..0a5dade 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -8,8 +8,8 @@
  * (at your option) any later version.
  */
 
-#ifndef	__S3C_DMA_PL330_H_
-#define	__S3C_DMA_PL330_H_
+#ifndef __DMA_PL330_H_
+#define __DMA_PL330_H_ __FILE__
 
 #define S3C2410_DMAF_AUTOSTART		(1 << 0)
 #define S3C2410_DMAF_CIRCULAR		(1 << 1)
@@ -20,7 +20,7 @@
  * 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 {
@@ -95,4 +95,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] 88+ messages in thread

* [PATCH 06/15] ARM: SAMSUNG: Add common DMA operations
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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>
Signed-off-by: Kukjin Kim <kgene.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                |  130 +++++++++++++++++++++++
 arch/arm/plat-samsung/include/plat/dma-ops.h   |   63 +++++++++++
 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, 346 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..5083797 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_SAMSUNG_DMA_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..eb81749
--- /dev/null
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -0,0 +1,130 @@
+/* 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 inline bool pl330_filter(struct dma_chan *chan, void *param)
+{
+	struct dma_pl330_peri *peri = chan->private;
+	return peri->peri_id == (unsigned)param;
+}
+
+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;
+		slave_config.src_maxburst = 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;
+		slave_config.dst_maxburst = 1;
+		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..4c1a363
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -0,0 +1,63 @@
+/* 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;
+	dma_addr_t 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;
+	dma_addr_t fifo;
+	struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+	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 0a5dade..2916920 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -93,6 +93,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] 88+ messages in thread

* [PATCH 06/15] ARM: SAMSUNG: Add common DMA operations
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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>
Signed-off-by: Kukjin Kim <kgene.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                |  130 +++++++++++++++++++++++
 arch/arm/plat-samsung/include/plat/dma-ops.h   |   63 +++++++++++
 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, 346 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..5083797 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_SAMSUNG_DMA_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..eb81749
--- /dev/null
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -0,0 +1,130 @@
+/* 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 inline bool pl330_filter(struct dma_chan *chan, void *param)
+{
+	struct dma_pl330_peri *peri = chan->private;
+	return peri->peri_id == (unsigned)param;
+}
+
+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;
+		slave_config.src_maxburst = 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;
+		slave_config.dst_maxburst = 1;
+		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..4c1a363
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -0,0 +1,63 @@
+/* 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;
+	dma_addr_t 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;
+	dma_addr_t fifo;
+	struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_ops {
+	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 0a5dade..2916920 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -93,6 +93,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] 88+ messages in thread

* [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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   |  299 ++++++++++++++++++++++++++---------------
 3 files changed, 198 insertions(+), 119 deletions(-)

diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc3..0c006c5 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 SAMSUNG_DMA_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..d57d662 100644
--- a/arch/arm/mach-exynos4/dma.c
+++ b/arch/arm/mach-exynos4/dma.c
@@ -21,151 +21,228 @@
  * 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[28] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
 	},
 };
 
-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 = ARRAY_SIZE(pdma0_peri),
+	.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[25] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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,
+	}, {
+		.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_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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 = ARRAY_SIZE(pdma1_peri),
+	.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] 88+ messages in thread

* [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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   |  299 ++++++++++++++++++++++++++---------------
 3 files changed, 198 insertions(+), 119 deletions(-)

diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index 1435fc3..0c006c5 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 SAMSUNG_DMA_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..d57d662 100644
--- a/arch/arm/mach-exynos4/dma.c
+++ b/arch/arm/mach-exynos4/dma.c
@@ -21,151 +21,228 @@
  * 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[28] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ0,
+	}, {
+		.peri_id = (u8)DMACH_MSM_REQ2,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_UART0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_UART4_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART4_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMIN,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_AC97_PCMOUT,
+		.rqtype = MEMTODEV,
 	},
 };
 
-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 = ARRAY_SIZE(pdma0_peri),
+	.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[25] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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,
+	}, {
+		.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_UART3_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_UART3_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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 = ARRAY_SIZE(pdma1_peri),
+	.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] 88+ messages in thread

* [PATCH 08/15] ARM: S5PV210: Use generic DMA PL330 driver
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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              |  316 +++++++++++++++++++-----------
 arch/arm/mach-s5pv210/include/mach/dma.h |    2 +-
 4 files changed, 214 insertions(+), 122 deletions(-)

diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 37b5a97..855d4b4 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 SAMSUNG_DMA_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..f79d0b0 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,239 @@
  * 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[28] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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 = ARRAY_SIZE(pdma0_peri),
+	.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,
 	},
-};
-
-static struct resource s5pv210_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA1,
-		.end    = S5PV210_PA_PDMA1 + SZ_4K,
+	.res = {
+		.start = S5PV210_PA_PDMA0,
+		.end = S5PV210_PA_PDMA0 + SZ_4K,
 		.flags = IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-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_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,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.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_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,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-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 dma_pl330_platdata s5pv210_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+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;
 }
diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/mach-s5pv210/include/mach/dma.h
index 1beae2c..201842a 100644
--- a/arch/arm/mach-s5pv210/include/mach/dma.h
+++ b/arch/arm/mach-s5pv210/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 */
+/* This platform uses the common DMA API driver for PL330 */
 #include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
-- 
1.7.1

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

* [PATCH 08/15] ARM: S5PV210: Use generic DMA PL330 driver
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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              |  316 +++++++++++++++++++-----------
 arch/arm/mach-s5pv210/include/mach/dma.h |    2 +-
 4 files changed, 214 insertions(+), 122 deletions(-)

diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 37b5a97..855d4b4 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 SAMSUNG_DMA_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..f79d0b0 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,239 @@
  * 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[28] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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 = ARRAY_SIZE(pdma0_peri),
+	.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,
 	},
-};
-
-static struct resource s5pv210_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PV210_PA_PDMA1,
-		.end    = S5PV210_PA_PDMA1 + SZ_4K,
+	.res = {
+		.start = S5PV210_PA_PDMA0,
+		.end = S5PV210_PA_PDMA0 + SZ_4K,
 		.flags = IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-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_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,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.peri_id = (u8)DMACH_MAX,
+	}, {
+		.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_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,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
 	},
 };
 
-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 dma_pl330_platdata s5pv210_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+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;
 }
diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/mach-s5pv210/include/mach/dma.h
index 1beae2c..201842a 100644
--- a/arch/arm/mach-s5pv210/include/mach/dma.h
+++ b/arch/arm/mach-s5pv210/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 */
+/* This platform uses the common DMA API driver for PL330 */
 #include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
-- 
1.7.1

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

* [PATCH 09/15] ARM: S5PC100: Use generic DMA PL330 driver
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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              |  323 +++++++++++++++++++----------
 arch/arm/mach-s5pc100/include/mach/dma.h |    2 +-
 4 files changed, 222 insertions(+), 128 deletions(-)

diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 608722f..1d7e2b1 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 SAMSUNG_DMA_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..ef803e9 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,245 @@
  * 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[30] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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 = ARRAY_SIZE(pdma0_peri),
+	.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,
 	},
-};
-
-static struct resource s5pc100_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA1,
-		.end    = S5PC100_PA_PDMA1 + SZ_4K,
+	.res = {
+		.start = S5PC100_PA_PDMA0,
+		.end = S5PC100_PA_PDMA0 + SZ_4K,
 		.flags = IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-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_peri pdma1_peri[30] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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 platform_device s5pc100_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma1_resource),
-	.resource	= s5pc100_pdma1_resource,
-	.dev		= {
+struct dma_pl330_platdata s5pc100_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+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;
 }
diff --git a/arch/arm/mach-s5pc100/include/mach/dma.h b/arch/arm/mach-s5pc100/include/mach/dma.h
index 1beae2c..201842a 100644
--- a/arch/arm/mach-s5pc100/include/mach/dma.h
+++ b/arch/arm/mach-s5pc100/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 */
+/* This platform uses the common DMA API driver for PL330 */
 #include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
-- 
1.7.1

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

* [PATCH 09/15] ARM: S5PC100: Use generic DMA PL330 driver
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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              |  323 +++++++++++++++++++----------
 arch/arm/mach-s5pc100/include/mach/dma.h |    2 +-
 4 files changed, 222 insertions(+), 128 deletions(-)

diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index 608722f..1d7e2b1 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 SAMSUNG_DMA_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..ef803e9 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,245 @@
  * 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[30] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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 = ARRAY_SIZE(pdma0_peri),
+	.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,
 	},
-};
-
-static struct resource s5pc100_pdma1_resource[] = {
-	[0] = {
-		.start  = S5PC100_PA_PDMA1,
-		.end    = S5PC100_PA_PDMA1 + SZ_4K,
+	.res = {
+		.start = S5PC100_PA_PDMA0,
+		.end = S5PC100_PA_PDMA0 + SZ_4K,
 		.flags = IORESOURCE_MEM,
 	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
+	.irq = {IRQ_PDMA0, NO_IRQ},
+	.periphid = 0x00041330,
 };
 
-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_peri pdma1_peri[30] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0S_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.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 platform_device s5pc100_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pc100_pdma1_resource),
-	.resource	= s5pc100_pdma1_resource,
-	.dev		= {
+struct dma_pl330_platdata s5pc100_pdma1_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
+	.peri = pdma1_peri,
+};
+
+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;
 }
diff --git a/arch/arm/mach-s5pc100/include/mach/dma.h b/arch/arm/mach-s5pc100/include/mach/dma.h
index 1beae2c..201842a 100644
--- a/arch/arm/mach-s5pc100/include/mach/dma.h
+++ b/arch/arm/mach-s5pc100/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 */
+/* This platform uses the common DMA API driver for PL330 */
 #include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
-- 
1.7.1

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

* [PATCH 10/15] ARM: S5P64X0: Use generic DMA PL330 driver
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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              |  273 ++++++++++++++++++++----------
 arch/arm/mach-s5p64x0/include/mach/dma.h |    2 +-
 5 files changed, 201 insertions(+), 96 deletions(-)

diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index 017af4c..bbf3487 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 SAMSUNG_DMA_PL330
 	select S5P_HRT
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
-	select S3C_PL330_DMA
+	select SAMSUNG_DMA_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..aebf3fc 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -21,128 +21,219 @@
  * 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[22] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
 	},
 };
 
-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 = ARRAY_SIZE(s5p6440_pdma_peri),
+	.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,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.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 = ARRAY_SIZE(s5p6450_pdma_peri),
+	.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;
 }
diff --git a/arch/arm/mach-s5p64x0/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
index 1beae2c..5a622af 100644
--- a/arch/arm/mach-s5p64x0/include/mach/dma.h
+++ b/arch/arm/mach-s5p64x0/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 */
+/* This platform uses the common common DMA API driver for PL330 */
 #include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
-- 
1.7.1

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

* [PATCH 10/15] ARM: S5P64X0: Use generic DMA PL330 driver
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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              |  273 ++++++++++++++++++++----------
 arch/arm/mach-s5p64x0/include/mach/dma.h |    2 +-
 5 files changed, 201 insertions(+), 96 deletions(-)

diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index 017af4c..bbf3487 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 SAMSUNG_DMA_PL330
 	select S5P_HRT
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
-	select S3C_PL330_DMA
+	select SAMSUNG_DMA_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..aebf3fc 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -21,128 +21,219 @@
  * 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[22] = {
+	{
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
 	},
 };
 
-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 = ARRAY_SIZE(s5p6440_pdma_peri),
+	.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,
+	}, {
+		.peri_id = (u8)DMACH_PCM0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI0_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_PCM2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_SPI1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.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,
+	}, {
+		.peri_id = (u8)DMACH_I2S1_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_TX,
+		.rqtype = MEMTODEV,
+	}, {
+		.peri_id = (u8)DMACH_I2S2_RX,
+		.rqtype = DEVTOMEM,
+	}, {
+		.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 = ARRAY_SIZE(s5p6450_pdma_peri),
+	.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;
 }
diff --git a/arch/arm/mach-s5p64x0/include/mach/dma.h b/arch/arm/mach-s5p64x0/include/mach/dma.h
index 1beae2c..5a622af 100644
--- a/arch/arm/mach-s5p64x0/include/mach/dma.h
+++ b/arch/arm/mach-s5p64x0/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 */
+/* This platform uses the common common DMA API driver for PL330 */
 #include <plat/dma-pl330.h>
 
 #endif /* __MACH_DMA_H */
-- 
1.7.1

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

* [PATCH 11/15] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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     |   10 +-
 .../plat-samsung/include/plat/s3c-pl330-pdata.h    |   32 -
 arch/arm/plat-samsung/s3c-pl330.c                  | 1244 --------------------
 5 files changed, 6 insertions(+), 1288 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 8b4e63f..a81fd80 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 SAMSUNG_DMA_PL330
 	bool
 	select DMADEVICES
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 5083797..530b546 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_SAMSUNG_DMA_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 2916920..9a1dadb 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -11,9 +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.
@@ -88,6 +85,10 @@ enum dma_ch {
 	DMACH_MAX,
 };
 
+struct s3c2410_dma_client {
+	char	*name;
+};
+
 static inline bool s3c_dma_has_circular(void)
 {
 	return true;
@@ -97,6 +98,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] 88+ messages in thread

* [PATCH 11/15] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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     |   10 +-
 .../plat-samsung/include/plat/s3c-pl330-pdata.h    |   32 -
 arch/arm/plat-samsung/s3c-pl330.c                  | 1244 --------------------
 5 files changed, 6 insertions(+), 1288 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 8b4e63f..a81fd80 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 SAMSUNG_DMA_PL330
 	bool
 	select DMADEVICES
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 5083797..530b546 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_SAMSUNG_DMA_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 2916920..9a1dadb 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -11,9 +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.
@@ -88,6 +85,10 @@ enum dma_ch {
 	DMACH_MAX,
 };
 
+struct s3c2410_dma_client {
+	char	*name;
+};
+
 static inline bool s3c_dma_has_circular(void)
 {
 	return true;
@@ -97,6 +98,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] 88+ messages in thread

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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>
Acked-by: 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] 88+ messages in thread

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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>
Acked-by: 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] 88+ messages in thread

* [PATCH 13/15] spi/s3c64xx: Merge dma control code
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, Boojin Kim

This patch modifies to merge the dma control code.
Original s3c64xx spi driver has each dma control code for rx and tx channel.
This patch merges these dma control codes into one.
With this patch, a dma setup function and callback function handle
for both rx and tx channel.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/spi/spi_s3c64xx.c |  140 ++++++++++++++++++++++++--------------------
 1 files changed, 76 insertions(+), 64 deletions(-)

diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index a4cf76a..de71f55 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -132,6 +132,12 @@
 #define RXBUSY    (1<<2)
 #define TXBUSY    (1<<3)
 
+struct s3c64xx_spi_dma_data {
+	unsigned		ch;
+	enum dma_data_direction direction;
+	enum dma_ch	dmach;
+};
+
 /**
  * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
  * @clk: Pointer to the spi clock.
@@ -165,15 +171,13 @@ struct s3c64xx_spi_driver_data {
 	struct work_struct              work;
 	struct list_head                queue;
 	spinlock_t                      lock;
-	enum dma_ch                     rx_dmach;
-	enum dma_ch                     tx_dmach;
 	unsigned long                   sfr_start;
 	struct completion               xfer_completion;
 	unsigned                        state;
 	unsigned                        cur_mode, cur_bpw;
 	unsigned                        cur_speed;
-	unsigned			rx_ch;
-	unsigned			tx_ch;
+	struct s3c64xx_spi_dma_data	rx_dma;
+	struct s3c64xx_spi_dma_data	tx_dma;
 	struct samsung_dma_ops		*ops;
 };
 
@@ -230,36 +234,76 @@ 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)
+static void s3c64xx_spi_dmacb(void *data)
 {
-	struct s3c64xx_spi_driver_data *sdd
-		= (struct s3c64xx_spi_driver_data *)data;
+	struct s3c64xx_spi_driver_data *sdd;
+	struct s3c64xx_spi_dma_data *dma = data;
 	unsigned long flags;
 
+	if (dma->direction == DMA_FROM_DEVICE)
+		sdd = container_of(data,
+			struct s3c64xx_spi_driver_data, rx_dma);
+	else
+		sdd = container_of(data,
+			struct s3c64xx_spi_driver_data, tx_dma);
+
 	spin_lock_irqsave(&sdd->lock, flags);
 
-	sdd->state &= ~RXBUSY;
-	/* If the other done */
-	if (!(sdd->state & TXBUSY))
-		complete(&sdd->xfer_completion);
+	if (dma->direction == DMA_FROM_DEVICE) {
+		sdd->state &= ~RXBUSY;
+		if (!(sdd->state & TXBUSY))
+			complete(&sdd->xfer_completion);
+	} else {
+		sdd->state &= ~TXBUSY;
+		if (!(sdd->state & RXBUSY))
+			complete(&sdd->xfer_completion);
+	}
 
 	spin_unlock_irqrestore(&sdd->lock, flags);
 }
 
-static void s3c64xx_spi_dma_txcb(void *data)
+static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
+					unsigned len, dma_addr_t buf)
 {
-	struct s3c64xx_spi_driver_data *sdd
-		= (struct s3c64xx_spi_driver_data *)data;
-	unsigned long flags;
+	struct s3c64xx_spi_driver_data *sdd;
+	struct samsung_dma_prep_info info;
 
-	spin_lock_irqsave(&sdd->lock, flags);
+	if (dma->direction == DMA_FROM_DEVICE)
+		sdd = container_of((void *)dma,
+			struct s3c64xx_spi_driver_data, rx_dma);
+	else
+		sdd = container_of((void *)dma,
+			struct s3c64xx_spi_driver_data, tx_dma);
 
-	sdd->state &= ~TXBUSY;
-	/* If the other done */
-	if (!(sdd->state & RXBUSY))
-		complete(&sdd->xfer_completion);
+	info.cap = DMA_SLAVE;
+	info.len = len;
+	info.fp = s3c64xx_spi_dmacb;
+	info.fp_param = dma;
+	info.direction = dma->direction;
+	info.buf = buf;
+
+	sdd->ops->prepare(dma->ch, &info);
+	sdd->ops->trigger(dma->ch);
+}
 
-	spin_unlock_irqrestore(&sdd->lock, flags);
+static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
+{
+	struct samsung_dma_info info;
+
+	sdd->ops = samsung_dma_get_ops();
+
+	info.cap = DMA_SLAVE;
+	info.client = &s3c64xx_spi_dma_client;
+	info.width = sdd->cur_bpw / 8;
+
+	info.direction = sdd->rx_dma.direction;
+	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
+	sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
+	info.direction =  sdd->tx_dma.direction;
+	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
+	sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
+
+	return 1;
 }
 
 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
@@ -269,7 +313,6 @@ 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);
@@ -295,14 +338,7 @@ 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;
-			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);
+			prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
 		} else {
 			switch (sdd->cur_bpw) {
 			case 32:
@@ -334,14 +370,7 @@ 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);
-			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);
+			prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
 		}
 	}
 
@@ -701,10 +730,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
 			if (use_dma) {
 				if (xfer->tx_buf != NULL
 						&& (sdd->state & TXBUSY))
-					sdd->ops->stop(sdd->tx_ch);
+					sdd->ops->stop(sdd->tx_dma.ch);
 				if (xfer->rx_buf != NULL
 						&& (sdd->state & RXBUSY))
-					sdd->ops->stop(sdd->rx_ch);
+					sdd->ops->stop(sdd->rx_dma.ch);
 			}
 
 			goto out;
@@ -742,25 +771,6 @@ out:
 		msg->complete(msg->context);
 }
 
-static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
-{
-
-	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;
-}
-
 static void s3c64xx_spi_work(struct work_struct *work)
 {
 	struct s3c64xx_spi_driver_data *sdd = container_of(work,
@@ -797,8 +807,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
 	spin_unlock_irqrestore(&sdd->lock, flags);
 
 	/* Free DMA channels */
-	sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client);
-	sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client);
+	sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
+	sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
 }
 
 static int s3c64xx_spi_transfer(struct spi_device *spi,
@@ -1015,8 +1025,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 	sdd->cntrlr_info = sci;
 	sdd->pdev = pdev;
 	sdd->sfr_start = mem_res->start;
-	sdd->tx_dmach = dmatx_res->start;
-	sdd->rx_dmach = dmarx_res->start;
+	sdd->tx_dma.dmach = dmatx_res->start;
+	sdd->tx_dma.direction = DMA_TO_DEVICE;
+	sdd->rx_dma.dmach = dmarx_res->start;
+	sdd->rx_dma.direction = DMA_FROM_DEVICE;
 
 	sdd->cur_bpw = 8;
 
@@ -1104,7 +1116,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 					pdev->id, master->num_chipselect);
 	dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
 					mem_res->end, mem_res->start,
-					sdd->rx_dmach, sdd->tx_dmach);
+					sdd->rx_dma.dmach, sdd->tx_dma.dmach);
 
 	return 0;
 
-- 
1.7.1

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

* [PATCH 13/15] spi/s3c64xx: Merge dma control code
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel

This patch modifies to merge the dma control code.
Original s3c64xx spi driver has each dma control code for rx and tx channel.
This patch merges these dma control codes into one.
With this patch, a dma setup function and callback function handle
for both rx and tx channel.

Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
---
 drivers/spi/spi_s3c64xx.c |  140 ++++++++++++++++++++++++--------------------
 1 files changed, 76 insertions(+), 64 deletions(-)

diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index a4cf76a..de71f55 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -132,6 +132,12 @@
 #define RXBUSY    (1<<2)
 #define TXBUSY    (1<<3)
 
+struct s3c64xx_spi_dma_data {
+	unsigned		ch;
+	enum dma_data_direction direction;
+	enum dma_ch	dmach;
+};
+
 /**
  * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
  * @clk: Pointer to the spi clock.
@@ -165,15 +171,13 @@ struct s3c64xx_spi_driver_data {
 	struct work_struct              work;
 	struct list_head                queue;
 	spinlock_t                      lock;
-	enum dma_ch                     rx_dmach;
-	enum dma_ch                     tx_dmach;
 	unsigned long                   sfr_start;
 	struct completion               xfer_completion;
 	unsigned                        state;
 	unsigned                        cur_mode, cur_bpw;
 	unsigned                        cur_speed;
-	unsigned			rx_ch;
-	unsigned			tx_ch;
+	struct s3c64xx_spi_dma_data	rx_dma;
+	struct s3c64xx_spi_dma_data	tx_dma;
 	struct samsung_dma_ops		*ops;
 };
 
@@ -230,36 +234,76 @@ 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)
+static void s3c64xx_spi_dmacb(void *data)
 {
-	struct s3c64xx_spi_driver_data *sdd
-		= (struct s3c64xx_spi_driver_data *)data;
+	struct s3c64xx_spi_driver_data *sdd;
+	struct s3c64xx_spi_dma_data *dma = data;
 	unsigned long flags;
 
+	if (dma->direction == DMA_FROM_DEVICE)
+		sdd = container_of(data,
+			struct s3c64xx_spi_driver_data, rx_dma);
+	else
+		sdd = container_of(data,
+			struct s3c64xx_spi_driver_data, tx_dma);
+
 	spin_lock_irqsave(&sdd->lock, flags);
 
-	sdd->state &= ~RXBUSY;
-	/* If the other done */
-	if (!(sdd->state & TXBUSY))
-		complete(&sdd->xfer_completion);
+	if (dma->direction == DMA_FROM_DEVICE) {
+		sdd->state &= ~RXBUSY;
+		if (!(sdd->state & TXBUSY))
+			complete(&sdd->xfer_completion);
+	} else {
+		sdd->state &= ~TXBUSY;
+		if (!(sdd->state & RXBUSY))
+			complete(&sdd->xfer_completion);
+	}
 
 	spin_unlock_irqrestore(&sdd->lock, flags);
 }
 
-static void s3c64xx_spi_dma_txcb(void *data)
+static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
+					unsigned len, dma_addr_t buf)
 {
-	struct s3c64xx_spi_driver_data *sdd
-		= (struct s3c64xx_spi_driver_data *)data;
-	unsigned long flags;
+	struct s3c64xx_spi_driver_data *sdd;
+	struct samsung_dma_prep_info info;
 
-	spin_lock_irqsave(&sdd->lock, flags);
+	if (dma->direction == DMA_FROM_DEVICE)
+		sdd = container_of((void *)dma,
+			struct s3c64xx_spi_driver_data, rx_dma);
+	else
+		sdd = container_of((void *)dma,
+			struct s3c64xx_spi_driver_data, tx_dma);
 
-	sdd->state &= ~TXBUSY;
-	/* If the other done */
-	if (!(sdd->state & RXBUSY))
-		complete(&sdd->xfer_completion);
+	info.cap = DMA_SLAVE;
+	info.len = len;
+	info.fp = s3c64xx_spi_dmacb;
+	info.fp_param = dma;
+	info.direction = dma->direction;
+	info.buf = buf;
+
+	sdd->ops->prepare(dma->ch, &info);
+	sdd->ops->trigger(dma->ch);
+}
 
-	spin_unlock_irqrestore(&sdd->lock, flags);
+static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
+{
+	struct samsung_dma_info info;
+
+	sdd->ops = samsung_dma_get_ops();
+
+	info.cap = DMA_SLAVE;
+	info.client = &s3c64xx_spi_dma_client;
+	info.width = sdd->cur_bpw / 8;
+
+	info.direction = sdd->rx_dma.direction;
+	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
+	sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
+	info.direction =  sdd->tx_dma.direction;
+	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
+	sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
+
+	return 1;
 }
 
 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
@@ -269,7 +313,6 @@ 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);
@@ -295,14 +338,7 @@ 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;
-			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);
+			prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
 		} else {
 			switch (sdd->cur_bpw) {
 			case 32:
@@ -334,14 +370,7 @@ 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);
-			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);
+			prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
 		}
 	}
 
@@ -701,10 +730,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
 			if (use_dma) {
 				if (xfer->tx_buf != NULL
 						&& (sdd->state & TXBUSY))
-					sdd->ops->stop(sdd->tx_ch);
+					sdd->ops->stop(sdd->tx_dma.ch);
 				if (xfer->rx_buf != NULL
 						&& (sdd->state & RXBUSY))
-					sdd->ops->stop(sdd->rx_ch);
+					sdd->ops->stop(sdd->rx_dma.ch);
 			}
 
 			goto out;
@@ -742,25 +771,6 @@ out:
 		msg->complete(msg->context);
 }
 
-static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
-{
-
-	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;
-}
-
 static void s3c64xx_spi_work(struct work_struct *work)
 {
 	struct s3c64xx_spi_driver_data *sdd = container_of(work,
@@ -797,8 +807,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
 	spin_unlock_irqrestore(&sdd->lock, flags);
 
 	/* Free DMA channels */
-	sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client);
-	sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client);
+	sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
+	sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
 }
 
 static int s3c64xx_spi_transfer(struct spi_device *spi,
@@ -1015,8 +1025,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 	sdd->cntrlr_info = sci;
 	sdd->pdev = pdev;
 	sdd->sfr_start = mem_res->start;
-	sdd->tx_dmach = dmatx_res->start;
-	sdd->rx_dmach = dmarx_res->start;
+	sdd->tx_dma.dmach = dmatx_res->start;
+	sdd->tx_dma.direction = DMA_TO_DEVICE;
+	sdd->rx_dma.dmach = dmarx_res->start;
+	sdd->rx_dma.direction = DMA_FROM_DEVICE;
 
 	sdd->cur_bpw = 8;
 
@@ -1104,7 +1116,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 					pdev->id, master->num_chipselect);
 	dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
 					mem_res->end, mem_res->start,
-					sdd->rx_dmach, sdd->tx_dmach);
+					sdd->rx_dma.dmach, sdd->tx_dma.dmach);
 
 	return 0;
 
-- 
1.7.1

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

* [PATCH 14/15] ASoC: Samsung: Update DMA interface
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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>
Acked-by: 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 9a1dadb..2e55e59 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -89,7 +89,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] 88+ messages in thread

* [PATCH 14/15] ASoC: Samsung: Update DMA interface
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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>
Acked-by: 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 9a1dadb..2e55e59 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -89,7 +89,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] 88+ messages in thread

* [PATCH 15/15] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
  2011-07-27  5:31 ` Boojin Kim
@ 2011-07-27  5:31   ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: Vinod Koul, Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown,
	Grant Likely, Russell King, 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] 88+ messages in thread

* [PATCH 15/15] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
@ 2011-07-27  5:31   ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-07-27  5:31 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] 88+ messages in thread

* [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM
  2011-07-27  5:31   ` Boojin Kim
@ 2011-07-27  6:14     ` Chanwoo Choi
  -1 siblings, 0 replies; 88+ messages in thread
From: Chanwoo Choi @ 2011-07-27  6:14 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Kukjin Kim, Russell King,
	Vinod Koul, Jassi Brar, Grant Likely, Mark Brown, Dan Williams,
	Kyungmin Park

This patch update runtime PM for PL330 DMAC to reduce power consumption.

Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
The following patch support runtime PM for PL330 DMAC, but the clock
of PL330 is always on. If the clock of PL330 is always on, additional power
(10mA) is consumed.

"[PATCH 01/15] DMA: PL330: Add support runtime PM for PL330 DMAC"
http://permalink.gmane.org/gmane.linux.kernel.samsung-soc/5931

 arch/arm/plat-samsung/dma-ops.c |   21 +++++++++++
 drivers/dma/pl330.c             |   76 +++++++++++++--------------------------
 include/linux/amba/pl330.h      |   54 +++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 51 deletions(-)

diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
index 9053433..b726e4a 100644
--- a/arch/arm/plat-samsung/dma-ops.c
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
 
 #include <mach/dma.h>
 
@@ -33,12 +34,23 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
 	struct dma_chan *chan;
 	dma_cap_mask_t mask;
 	struct dma_slave_config slave_config;
+#ifdef CONFIG_PM_RUNTIME
+	struct dma_pl330_chan *pch;
+	struct dma_pl330_dmac *pdmac;
+#endif
 
 	dma_cap_zero(mask);
 	dma_cap_set(info->cap, mask);
 
 	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
 
+#ifdef CONFIG_PM_RUNTIME
+	pch = container_of(chan, struct dma_pl330_chan, chan);
+	pdmac = pch->dmac;
+
+	pm_runtime_get_sync(pdmac->pif.dev);
+#endif
+
 	if (info->direction == DMA_FROM_DEVICE) {
 		memset(&slave_config, 0, sizeof(struct dma_slave_config));
 		slave_config.direction = info->direction;
@@ -59,8 +71,17 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
 static int samsung_dmadev_release(unsigned ch,
 			struct s3c2410_dma_client *client)
 {
+#ifdef CONFIG_PM_RUNTIME
+	struct dma_pl330_chan *pch =
+		container_of((struct dma_chan *)ch, struct dma_pl330_chan, chan);
+	struct dma_pl330_dmac *pdmac = pdmac = pch->dmac;;
+#endif
+
 	dma_release_channel((struct dma_chan *)ch);
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_put(pdmac->pif.dev);
+#endif
 	return 0;
 }
 
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 121c75a..14d0ba6 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -42,57 +42,6 @@ enum desc_status {
 	DONE,
 };
 
-struct dma_pl330_chan {
-	/* Schedule desc completion */
-	struct tasklet_struct task;
-
-	/* DMA-Engine Channel */
-	struct dma_chan chan;
-
-	/* Last completed cookie */
-	dma_cookie_t completed;
-
-	/* List of to be xfered descriptors */
-	struct list_head work_list;
-
-	/* Pointer to the DMAC that manages this channel,
-	 * NULL if the channel is available to be acquired.
-	 * As the parent, this DMAC also provides descriptors
-	 * to the channel.
-	 */
-	struct dma_pl330_dmac *dmac;
-
-	/* To protect channel manipulation */
-	spinlock_t lock;
-
-	/* Token of a hardware channel thread of PL330 DMAC
-	 * 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 {
-	struct pl330_info pif;
-
-	/* DMA-Engine Device */
-	struct dma_device ddma;
-
-	/* Pool of descriptors available for the DMAC's channels */
-	struct list_head desc_pool;
-	/* To protect desc_pool manipulation */
-	spinlock_t pool_lock;
-
-	/* Peripheral channels connected to this DMAC */
-	struct dma_pl330_chan peripherals[0]; /* keep at end */
-
-	struct clk *clk;
-};
-
 struct dma_pl330_desc {
 	/* To attach to a queue as child */
 	struct list_head node;
@@ -935,6 +884,18 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
 		pi->pcfg.num_peri, pi->pcfg.num_events);
 
+#ifdef CONFIG_PM_RUNTIME
+	/* disable the power domain */
+	ret = pm_runtime_put(&adev->dev);
+	if (ret < 0) {
+		dev_err(&adev->dev, "failed to put runtime pm\n");
+		ret = -ENODEV;
+		goto probe_err4;
+	}
+#else
+	/* disable dma clk */
+	clk_disable(pdmac->clk);
+#endif
 	return 0;
 
 probe_err4:
@@ -943,6 +904,13 @@ probe_err3:
 	free_irq(irq, pi);
 probe_err2:
 	iounmap(pi->base);
+
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_disable(&adev->dev);
+	pm_runtime_put(&adev->dev);
+#else
+	clk_disable(pdmac->clk);
+#endif
 probe_err1:
 	release_mem_region(res->start, resource_size(res));
 	kfree(pdmac);
@@ -961,6 +929,12 @@ static int __devexit pl330_remove(struct amba_device *adev)
 	if (!pdmac)
 		return 0;
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_get_sync(&adev->dev);
+#else
+	clk_enable(pdmac->clk);
+#endif
+
 	amba_set_drvdata(adev, NULL);
 
 	/* Idle the DMAC */
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
index 17b0ada..d9a63fd 100644
--- a/include/linux/amba/pl330.h
+++ b/include/linux/amba/pl330.h
@@ -12,6 +12,9 @@
 #ifndef	__AMBA_PL330_H_
 #define	__AMBA_PL330_H_
 
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+
 #include <asm/hardware/pl330.h>
 
 struct dma_pl330_peri {
@@ -42,4 +45,55 @@ struct dma_pl330_platdata {
 	unsigned mcbuf_sz;
 };
 
+struct dma_pl330_chan {
+	/* Schedule desc completion */
+	struct tasklet_struct task;
+
+	/* DMA-Engine Channel */
+	struct dma_chan chan;
+
+	/* Last completed cookie */
+	dma_cookie_t completed;
+
+	/* List of to be xfered descriptors */
+	struct list_head work_list;
+
+	/* Pointer to the DMAC that manages this channel,
+	 * NULL if the channel is available to be acquired.
+	 * As the parent, this DMAC also provides descriptors
+	 * to the channel.
+	 */
+	struct dma_pl330_dmac *dmac;
+
+	/* To protect channel manipulation */
+	spinlock_t lock;
+
+	/* Token of a hardware channel thread of PL330 DMAC
+	 * 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 {
+	struct pl330_info pif;
+
+	/* DMA-Engine Device */
+	struct dma_device ddma;
+
+	/* Pool of descriptors available for the DMAC's channels */
+	struct list_head desc_pool;
+	/* To protect desc_pool manipulation */
+	spinlock_t pool_lock;
+
+	/* Peripheral channels connected to this DMAC */
+	struct dma_pl330_chan peripherals[0]; /* keep at end */
+
+	struct clk *clk;
+};
+
 #endif	/* __AMBA_PL330_H_ */

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

* [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM
@ 2011-07-27  6:14     ` Chanwoo Choi
  0 siblings, 0 replies; 88+ messages in thread
From: Chanwoo Choi @ 2011-07-27  6:14 UTC (permalink / raw)
  To: linux-arm-kernel

This patch update runtime PM for PL330 DMAC to reduce power consumption.

Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
The following patch support runtime PM for PL330 DMAC, but the clock
of PL330 is always on. If the clock of PL330 is always on, additional power
(10mA) is consumed.

"[PATCH 01/15] DMA: PL330: Add support runtime PM for PL330 DMAC"
http://permalink.gmane.org/gmane.linux.kernel.samsung-soc/5931

 arch/arm/plat-samsung/dma-ops.c |   21 +++++++++++
 drivers/dma/pl330.c             |   76 +++++++++++++--------------------------
 include/linux/amba/pl330.h      |   54 +++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 51 deletions(-)

diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
index 9053433..b726e4a 100644
--- a/arch/arm/plat-samsung/dma-ops.c
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/amba/pl330.h>
+#include <linux/pm_runtime.h>
 
 #include <mach/dma.h>
 
@@ -33,12 +34,23 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
 	struct dma_chan *chan;
 	dma_cap_mask_t mask;
 	struct dma_slave_config slave_config;
+#ifdef CONFIG_PM_RUNTIME
+	struct dma_pl330_chan *pch;
+	struct dma_pl330_dmac *pdmac;
+#endif
 
 	dma_cap_zero(mask);
 	dma_cap_set(info->cap, mask);
 
 	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
 
+#ifdef CONFIG_PM_RUNTIME
+	pch = container_of(chan, struct dma_pl330_chan, chan);
+	pdmac = pch->dmac;
+
+	pm_runtime_get_sync(pdmac->pif.dev);
+#endif
+
 	if (info->direction == DMA_FROM_DEVICE) {
 		memset(&slave_config, 0, sizeof(struct dma_slave_config));
 		slave_config.direction = info->direction;
@@ -59,8 +71,17 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
 static int samsung_dmadev_release(unsigned ch,
 			struct s3c2410_dma_client *client)
 {
+#ifdef CONFIG_PM_RUNTIME
+	struct dma_pl330_chan *pch =
+		container_of((struct dma_chan *)ch, struct dma_pl330_chan, chan);
+	struct dma_pl330_dmac *pdmac = pdmac = pch->dmac;;
+#endif
+
 	dma_release_channel((struct dma_chan *)ch);
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_put(pdmac->pif.dev);
+#endif
 	return 0;
 }
 
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 121c75a..14d0ba6 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -42,57 +42,6 @@ enum desc_status {
 	DONE,
 };
 
-struct dma_pl330_chan {
-	/* Schedule desc completion */
-	struct tasklet_struct task;
-
-	/* DMA-Engine Channel */
-	struct dma_chan chan;
-
-	/* Last completed cookie */
-	dma_cookie_t completed;
-
-	/* List of to be xfered descriptors */
-	struct list_head work_list;
-
-	/* Pointer to the DMAC that manages this channel,
-	 * NULL if the channel is available to be acquired.
-	 * As the parent, this DMAC also provides descriptors
-	 * to the channel.
-	 */
-	struct dma_pl330_dmac *dmac;
-
-	/* To protect channel manipulation */
-	spinlock_t lock;
-
-	/* Token of a hardware channel thread of PL330 DMAC
-	 * 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 {
-	struct pl330_info pif;
-
-	/* DMA-Engine Device */
-	struct dma_device ddma;
-
-	/* Pool of descriptors available for the DMAC's channels */
-	struct list_head desc_pool;
-	/* To protect desc_pool manipulation */
-	spinlock_t pool_lock;
-
-	/* Peripheral channels connected to this DMAC */
-	struct dma_pl330_chan peripherals[0]; /* keep at end */
-
-	struct clk *clk;
-};
-
 struct dma_pl330_desc {
 	/* To attach to a queue as child */
 	struct list_head node;
@@ -935,6 +884,18 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
 		pi->pcfg.num_peri, pi->pcfg.num_events);
 
+#ifdef CONFIG_PM_RUNTIME
+	/* disable the power domain */
+	ret = pm_runtime_put(&adev->dev);
+	if (ret < 0) {
+		dev_err(&adev->dev, "failed to put runtime pm\n");
+		ret = -ENODEV;
+		goto probe_err4;
+	}
+#else
+	/* disable dma clk */
+	clk_disable(pdmac->clk);
+#endif
 	return 0;
 
 probe_err4:
@@ -943,6 +904,13 @@ probe_err3:
 	free_irq(irq, pi);
 probe_err2:
 	iounmap(pi->base);
+
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_disable(&adev->dev);
+	pm_runtime_put(&adev->dev);
+#else
+	clk_disable(pdmac->clk);
+#endif
 probe_err1:
 	release_mem_region(res->start, resource_size(res));
 	kfree(pdmac);
@@ -961,6 +929,12 @@ static int __devexit pl330_remove(struct amba_device *adev)
 	if (!pdmac)
 		return 0;
 
+#ifdef CONFIG_PM_RUNTIME
+	pm_runtime_get_sync(&adev->dev);
+#else
+	clk_enable(pdmac->clk);
+#endif
+
 	amba_set_drvdata(adev, NULL);
 
 	/* Idle the DMAC */
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
index 17b0ada..d9a63fd 100644
--- a/include/linux/amba/pl330.h
+++ b/include/linux/amba/pl330.h
@@ -12,6 +12,9 @@
 #ifndef	__AMBA_PL330_H_
 #define	__AMBA_PL330_H_
 
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+
 #include <asm/hardware/pl330.h>
 
 struct dma_pl330_peri {
@@ -42,4 +45,55 @@ struct dma_pl330_platdata {
 	unsigned mcbuf_sz;
 };
 
+struct dma_pl330_chan {
+	/* Schedule desc completion */
+	struct tasklet_struct task;
+
+	/* DMA-Engine Channel */
+	struct dma_chan chan;
+
+	/* Last completed cookie */
+	dma_cookie_t completed;
+
+	/* List of to be xfered descriptors */
+	struct list_head work_list;
+
+	/* Pointer to the DMAC that manages this channel,
+	 * NULL if the channel is available to be acquired.
+	 * As the parent, this DMAC also provides descriptors
+	 * to the channel.
+	 */
+	struct dma_pl330_dmac *dmac;
+
+	/* To protect channel manipulation */
+	spinlock_t lock;
+
+	/* Token of a hardware channel thread of PL330 DMAC
+	 * 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 {
+	struct pl330_info pif;
+
+	/* DMA-Engine Device */
+	struct dma_device ddma;
+
+	/* Pool of descriptors available for the DMAC's channels */
+	struct list_head desc_pool;
+	/* To protect desc_pool manipulation */
+	spinlock_t pool_lock;
+
+	/* Peripheral channels connected to this DMAC */
+	struct dma_pl330_chan peripherals[0]; /* keep at end */
+
+	struct clk *clk;
+};
+
 #endif	/* __AMBA_PL330_H_ */

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

* Re: [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM
  2011-07-27  6:14     ` Chanwoo Choi
@ 2011-07-27  7:31       ` Jassi Brar
  -1 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-07-27  7:31 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Boojin Kim, linux-arm-kernel, linux-samsung-soc, Kukjin Kim,
	Russell King, Vinod Koul, Grant Likely, Mark Brown, Dan Williams,
	Kyungmin Park

On Wed, Jul 27, 2011 at 11:44 AM, Chanwoo Choi <cw00.choi@samsung.com> wrote:
> This patch update runtime PM for PL330 DMAC to reduce power consumption.
>
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> The following patch support runtime PM for PL330 DMAC, but the clock
> of PL330 is always on. If the clock of PL330 is always on, additional power
> (10mA) is consumed.

Yes, we need to do this, but please do it in drivers/dma/pl330.c so that
every platform benefits.

> diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
> index 17b0ada..d9a63fd 100644
> --- a/include/linux/amba/pl330.h
> +++ b/include/linux/amba/pl330.h
> @@ -12,6 +12,9 @@
>  #ifndef        __AMBA_PL330_H_
>  #define        __AMBA_PL330_H_
>
> +#include <linux/dmaengine.h>
> +#include <linux/interrupt.h>
> +
>  #include <asm/hardware/pl330.h>
>
>  struct dma_pl330_peri {
> @@ -42,4 +45,55 @@ struct dma_pl330_platdata {
>        unsigned mcbuf_sz;
>  };
>
> +struct dma_pl330_chan {
> +       /* Schedule desc completion */
> +       struct tasklet_struct task;
> +
> +       /* DMA-Engine Channel */
> +       struct dma_chan chan;
> +
> +       /* Last completed cookie */
> +       dma_cookie_t completed;
> +
> +       /* List of to be xfered descriptors */
> +       struct list_head work_list;
> +
> +       /* Pointer to the DMAC that manages this channel,
> +        * NULL if the channel is available to be acquired.
> +        * As the parent, this DMAC also provides descriptors
> +        * to the channel.
> +        */
> +       struct dma_pl330_dmac *dmac;
> +
> +       /* To protect channel manipulation */
> +       spinlock_t lock;
> +
> +       /* Token of a hardware channel thread of PL330 DMAC
> +        * 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 {
> +       struct pl330_info pif;
> +
> +       /* DMA-Engine Device */
> +       struct dma_device ddma;
> +
> +       /* Pool of descriptors available for the DMAC's channels */
> +       struct list_head desc_pool;
> +       /* To protect desc_pool manipulation */
> +       spinlock_t pool_lock;
> +
> +       /* Peripheral channels connected to this DMAC */
> +       struct dma_pl330_chan peripherals[0]; /* keep at end */
> +
> +       struct clk *clk;
> +};
> +
>  #endif /* __AMBA_PL330_H_ */

struct dma_pl330_dmac and struct dma_pl330_chan are internal to the
pl330 dmac driver. Nobody from outside should ever need them.

Thanks,
Jassi

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

* [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM
@ 2011-07-27  7:31       ` Jassi Brar
  0 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-07-27  7:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 27, 2011 at 11:44 AM, Chanwoo Choi <cw00.choi@samsung.com> wrote:
> This patch update runtime PM for PL330 DMAC to reduce power consumption.
>
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> The following patch support runtime PM for PL330 DMAC, but the clock
> of PL330 is always on. If the clock of PL330 is always on, additional power
> (10mA) is consumed.

Yes, we need to do this, but please do it in drivers/dma/pl330.c so that
every platform benefits.

> diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
> index 17b0ada..d9a63fd 100644
> --- a/include/linux/amba/pl330.h
> +++ b/include/linux/amba/pl330.h
> @@ -12,6 +12,9 @@
> ?#ifndef ? ? ? ?__AMBA_PL330_H_
> ?#define ? ? ? ?__AMBA_PL330_H_
>
> +#include <linux/dmaengine.h>
> +#include <linux/interrupt.h>
> +
> ?#include <asm/hardware/pl330.h>
>
> ?struct dma_pl330_peri {
> @@ -42,4 +45,55 @@ struct dma_pl330_platdata {
> ? ? ? ?unsigned mcbuf_sz;
> ?};
>
> +struct dma_pl330_chan {
> + ? ? ? /* Schedule desc completion */
> + ? ? ? struct tasklet_struct task;
> +
> + ? ? ? /* DMA-Engine Channel */
> + ? ? ? struct dma_chan chan;
> +
> + ? ? ? /* Last completed cookie */
> + ? ? ? dma_cookie_t completed;
> +
> + ? ? ? /* List of to be xfered descriptors */
> + ? ? ? struct list_head work_list;
> +
> + ? ? ? /* Pointer to the DMAC that manages this channel,
> + ? ? ? ?* NULL if the channel is available to be acquired.
> + ? ? ? ?* As the parent, this DMAC also provides descriptors
> + ? ? ? ?* to the channel.
> + ? ? ? ?*/
> + ? ? ? struct dma_pl330_dmac *dmac;
> +
> + ? ? ? /* To protect channel manipulation */
> + ? ? ? spinlock_t lock;
> +
> + ? ? ? /* Token of a hardware channel thread of PL330 DMAC
> + ? ? ? ?* 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 {
> + ? ? ? struct pl330_info pif;
> +
> + ? ? ? /* DMA-Engine Device */
> + ? ? ? struct dma_device ddma;
> +
> + ? ? ? /* Pool of descriptors available for the DMAC's channels */
> + ? ? ? struct list_head desc_pool;
> + ? ? ? /* To protect desc_pool manipulation */
> + ? ? ? spinlock_t pool_lock;
> +
> + ? ? ? /* Peripheral channels connected to this DMAC */
> + ? ? ? struct dma_pl330_chan peripherals[0]; /* keep at end */
> +
> + ? ? ? struct clk *clk;
> +};
> +
> ?#endif /* __AMBA_PL330_H_ */

struct dma_pl330_dmac and struct dma_pl330_chan are internal to the
pl330 dmac driver. Nobody from outside should ever need them.

Thanks,
Jassi

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

* Re: [PATCH 01/15] DMA: PL330: Add support runtime PM for PL330 DMAC
  2011-07-27  5:31   ` Boojin Kim
@ 2011-07-27  7:43     ` Jassi Brar
  -1 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-07-27  7:43 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Kukjin Kim, Russell King,
	Vinod Koul, Grant Likely, Mark Brown, Dan Williams

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> 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>

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

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

* [PATCH 01/15] DMA: PL330: Add support runtime PM for PL330 DMAC
@ 2011-07-27  7:43     ` Jassi Brar
  0 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-07-27  7:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> 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>

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

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

* Re: [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM
  2011-07-27  6:14     ` Chanwoo Choi
@ 2011-07-27  8:53       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 88+ messages in thread
From: Russell King - ARM Linux @ 2011-07-27  8:53 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Kukjin Kim, Boojin Kim, Vinod Koul, Jassi Brar, Grant Likely,
	Kyungmin Park, linux-samsung-soc, Mark Brown, Dan Williams,
	linux-arm-kernel

On Wed, Jul 27, 2011 at 03:14:27PM +0900, Chanwoo Choi wrote:
> +#ifdef CONFIG_PM_RUNTIME
> +	struct dma_pl330_chan *pch;
> +	struct dma_pl330_dmac *pdmac;
> +#endif
>  
>  	dma_cap_zero(mask);
>  	dma_cap_set(info->cap, mask);
>  
>  	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
>  
> +#ifdef CONFIG_PM_RUNTIME
> +	pch = container_of(chan, struct dma_pl330_chan, chan);
> +	pdmac = pch->dmac;
> +
> +	pm_runtime_get_sync(pdmac->pif.dev);
> +#endif

This is not the right way to do this.  The pm runtime stuff should be
internal to the PL330 driver.  Take a moment to think about this:

You need to wake it up just before a transfer starts.  You need to
put it back to sleep just after the last transfer has finished.
That gives you a hint where the calls need to be.

That can only be done from within the PL330 driver.

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

* [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM
@ 2011-07-27  8:53       ` Russell King - ARM Linux
  0 siblings, 0 replies; 88+ messages in thread
From: Russell King - ARM Linux @ 2011-07-27  8:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 27, 2011 at 03:14:27PM +0900, Chanwoo Choi wrote:
> +#ifdef CONFIG_PM_RUNTIME
> +	struct dma_pl330_chan *pch;
> +	struct dma_pl330_dmac *pdmac;
> +#endif
>  
>  	dma_cap_zero(mask);
>  	dma_cap_set(info->cap, mask);
>  
>  	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
>  
> +#ifdef CONFIG_PM_RUNTIME
> +	pch = container_of(chan, struct dma_pl330_chan, chan);
> +	pdmac = pch->dmac;
> +
> +	pm_runtime_get_sync(pdmac->pif.dev);
> +#endif

This is not the right way to do this.  The pm runtime stuff should be
internal to the PL330 driver.  Take a moment to think about this:

You need to wake it up just before a transfer starts.  You need to
put it back to sleep just after the last transfer has finished.
That gives you a hint where the calls need to be.

That can only be done from within the PL330 driver.

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

* Re: [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM
  2011-07-27  8:53       ` Russell King - ARM Linux
@ 2011-07-27  9:43         ` Chanwoo Choi
  -1 siblings, 0 replies; 88+ messages in thread
From: Chanwoo Choi @ 2011-07-27  9:43 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Boojin Kim, linux-arm-kernel, linux-samsung-soc, Kukjin Kim,
	Vinod Koul, Jassi Brar, Grant Likely, Mark Brown, Dan Williams,
	Kyungmin Park

Russell King - ARM Linux wrote:
> On Wed, Jul 27, 2011 at 03:14:27PM +0900, Chanwoo Choi wrote:
>> +#ifdef CONFIG_PM_RUNTIME
>> +	struct dma_pl330_chan *pch;
>> +	struct dma_pl330_dmac *pdmac;
>> +#endif
>>  
>>  	dma_cap_zero(mask);
>>  	dma_cap_set(info->cap, mask);
>>  
>>  	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
>>  
>> +#ifdef CONFIG_PM_RUNTIME
>> +	pch = container_of(chan, struct dma_pl330_chan, chan);
>> +	pdmac = pch->dmac;
>> +
>> +	pm_runtime_get_sync(pdmac->pif.dev);
>> +#endif
> 
> This is not the right way to do this.  The pm runtime stuff should be
> internal to the PL330 driver.  Take a moment to think about this:
> 
> You need to wake it up just before a transfer starts.  You need to
> put it back to sleep just after the last transfer has finished.
> That gives you a hint where the calls need to be.
> 
> That can only be done from within the PL330 driver.
> 

Thanks for your comment&hint.

I will repost the patch which support runtime pm of PL330 in internal to the PL330 driver.

Regards,
Chanwoo Choi

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

* [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM
@ 2011-07-27  9:43         ` Chanwoo Choi
  0 siblings, 0 replies; 88+ messages in thread
From: Chanwoo Choi @ 2011-07-27  9:43 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux wrote:
> On Wed, Jul 27, 2011 at 03:14:27PM +0900, Chanwoo Choi wrote:
>> +#ifdef CONFIG_PM_RUNTIME
>> +	struct dma_pl330_chan *pch;
>> +	struct dma_pl330_dmac *pdmac;
>> +#endif
>>  
>>  	dma_cap_zero(mask);
>>  	dma_cap_set(info->cap, mask);
>>  
>>  	chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
>>  
>> +#ifdef CONFIG_PM_RUNTIME
>> +	pch = container_of(chan, struct dma_pl330_chan, chan);
>> +	pdmac = pch->dmac;
>> +
>> +	pm_runtime_get_sync(pdmac->pif.dev);
>> +#endif
> 
> This is not the right way to do this.  The pm runtime stuff should be
> internal to the PL330 driver.  Take a moment to think about this:
> 
> You need to wake it up just before a transfer starts.  You need to
> put it back to sleep just after the last transfer has finished.
> That gives you a hint where the calls need to be.
> 
> That can only be done from within the PL330 driver.
> 

Thanks for your comment&hint.

I will repost the patch which support runtime pm of PL330 in internal to the PL330 driver.

Regards,
Chanwoo Choi

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

* Re: [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
  2011-07-27  5:31 ` Boojin Kim
@ 2011-08-04 16:53   ` Linus Walleij
  -1 siblings, 0 replies; 88+ messages in thread
From: Linus Walleij @ 2011-08-04 16:53 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Kukjin Kim, Russell King,
	Vinod Koul, Jassi Brar, Grant Likely, Mark Brown, Dan Williams

On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> This patchset adds support DMA generic APIs for Samsung DMA.

Patches look good to me,
Acked-by: Linus Walleij <linus.walleij@linaro.org>

Are there any more users of the code in arch/arm/common/pl330.c?
Else I think next step should be to move that file to drivers/dma/
and optionally merge it with the other pl330.c file there.

Thanks!
Linus Walleij

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-08-04 16:53   ` Linus Walleij
  0 siblings, 0 replies; 88+ messages in thread
From: Linus Walleij @ 2011-08-04 16:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

> This patchset adds support DMA generic APIs for Samsung DMA.

Patches look good to me,
Acked-by: Linus Walleij <linus.walleij@linaro.org>

Are there any more users of the code in arch/arm/common/pl330.c?
Else I think next step should be to move that file to drivers/dma/
and optionally merge it with the other pl330.c file there.

Thanks!
Linus Walleij

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

* Re: [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
  2011-08-04 16:53   ` Linus Walleij
@ 2011-08-08 16:45     ` Koul, Vinod
  -1 siblings, 0 replies; 88+ messages in thread
From: Koul, Vinod @ 2011-08-08 16:45 UTC (permalink / raw)
  To: Boojin Kim
  Cc: Linus Walleij, Kukjin Kim, Russell King, Jassi Brar,
	Grant Likely, linux-samsung-soc, Mark Brown, Dan Williams,
	linux-arm-kernel

On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> 
> > This patchset adds support DMA generic APIs for Samsung DMA.
> 
> Patches look good to me,
> Acked-by: Linus Walleij <linus.walleij@linaro.org>

Acked-by: Vinod Koul <vinod.koul@intel.com>

Do you want these to go thru slave-dma tree or arm tree, I am okay with
either...

-- 
~Vinod

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-08-08 16:45     ` Koul, Vinod
  0 siblings, 0 replies; 88+ messages in thread
From: Koul, Vinod @ 2011-08-08 16:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> 
> > This patchset adds support DMA generic APIs for Samsung DMA.
> 
> Patches look good to me,
> Acked-by: Linus Walleij <linus.walleij@linaro.org>

Acked-by: Vinod Koul <vinod.koul@intel.com>

Do you want these to go thru slave-dma tree or arm tree, I am okay with
either...

-- 
~Vinod

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

* Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-07-27  5:31   ` Boojin Kim
@ 2011-08-08 17:47     ` Jassi Brar
  -1 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-08-08 17:47 UTC (permalink / raw)
  To: Boojin Kim
  Cc: Kukjin Kim, Russell King, Vinod Koul, Mark Brown, Grant Likely,
	linux-samsung-soc, Dan Williams, linux-arm-kernel

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> 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>
> Acked-by: 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;
void* doesn't need typecasting (same for all such occurances)
IIRC someone already pointed it out?


> +       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);
>  }

Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
series, both of which
have DMAENGINE drivers. May be it could be directly switched to using
those, rather than
via Samsung's wrapper driver.
Or am I overlooking something ?
_______________________________________________
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] 88+ messages in thread

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-08 17:47     ` Jassi Brar
  0 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-08-08 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> 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>
> Acked-by: 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;
void* doesn't need typecasting (same for all such occurances)
IIRC someone already pointed it out?


> + ? ? ? 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);
> ?}

Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
series, both of which
have DMAENGINE drivers. May be it could be directly switched to using
those, rather than
via Samsung's wrapper driver.
Or am I overlooking something ?

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

* Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-08-08 17:47     ` Jassi Brar
@ 2011-08-08 17:55       ` Heiko Stübner
  -1 siblings, 0 replies; 88+ messages in thread
From: Heiko Stübner @ 2011-08-08 17:55 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Boojin Kim, linux-arm-kernel, linux-samsung-soc, Vinod Koul,
	Dan Williams, Kukjin Kim, Mark Brown, Grant Likely, Russell King

Am Montag 08 August 2011, 19:47:58 schrieb Jassi Brar:
> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> 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>
> > Acked-by: 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;
> 
> void* doesn't need typecasting (same for all such occurances)
> IIRC someone already pointed it out?
> 
> > +       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);
> >  }
> 
> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
> series, both of which
> have DMAENGINE drivers. May be it could be directly switched to using
> those, rather than
> via Samsung's wrapper driver.
> Or am I overlooking something ?
yep, at least the S3C2416/2450 HSSPI which should use this driver.

Heiko

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

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-08 17:55       ` Heiko Stübner
  0 siblings, 0 replies; 88+ messages in thread
From: Heiko Stübner @ 2011-08-08 17:55 UTC (permalink / raw)
  To: linux-arm-kernel

Am Montag 08 August 2011, 19:47:58 schrieb Jassi Brar:
> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> 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>
> > Acked-by: 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;
> 
> void* doesn't need typecasting (same for all such occurances)
> IIRC someone already pointed it out?
> 
> > +       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);
> >  }
> 
> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
> series, both of which
> have DMAENGINE drivers. May be it could be directly switched to using
> those, rather than
> via Samsung's wrapper driver.
> Or am I overlooking something ?
yep, at least the S3C2416/2450 HSSPI which should use this driver.

Heiko

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

* Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-08-08 17:55       ` Heiko Stübner
@ 2011-08-08 18:16         ` Jassi Brar
  -1 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-08-08 18:16 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Boojin Kim, linux-arm-kernel, linux-samsung-soc, Vinod Koul,
	Dan Williams, Kukjin Kim, Mark Brown, Grant Likely, Russell King

On Mon, Aug 8, 2011 at 11:25 PM, Heiko Stübner <heiko@sntech.de> wrote:
> Am Montag 08 August 2011, 19:47:58 schrieb Jassi Brar:

>> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
>> series, both of which
>> have DMAENGINE drivers. May be it could be directly switched to using
>> those, rather than
>> via Samsung's wrapper driver.
>> Or am I overlooking something ?
> yep, at least the S3C2416/2450 HSSPI which should use this driver.

Seems you keep some patches private ;)  the spi driver isn't enabled
for 2416 in mainline.

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

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-08 18:16         ` Jassi Brar
  0 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-08-08 18:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 8, 2011 at 11:25 PM, Heiko St?bner <heiko@sntech.de> wrote:
> Am Montag 08 August 2011, 19:47:58 schrieb Jassi Brar:

>> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
>> series, both of which
>> have DMAENGINE drivers. May be it could be directly switched to using
>> those, rather than
>> via Samsung's wrapper driver.
>> Or am I overlooking something ?
> yep, at least the S3C2416/2450 HSSPI which should use this driver.

Seems you keep some patches private ;)  the spi driver isn't enabled
for 2416 in mainline.

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

* Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-08-08 18:16         ` Jassi Brar
@ 2011-08-08 18:26           ` Heiko Stübner
  -1 siblings, 0 replies; 88+ messages in thread
From: Heiko Stübner @ 2011-08-08 18:26 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Boojin Kim, linux-arm-kernel, linux-samsung-soc, Vinod Koul,
	Dan Williams, Kukjin Kim, Mark Brown, Grant Likely, Russell King

Am Montag 08 August 2011, 20:16:58 schrieben Sie:
> On Mon, Aug 8, 2011 at 11:25 PM, Heiko Stübner <heiko@sntech.de> wrote:
> > Am Montag 08 August 2011, 19:47:58 schrieb Jassi Brar:
> >> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
> >> series, both of which
> >> have DMAENGINE drivers. May be it could be directly switched to using
> >> those, rather than
> >> via Samsung's wrapper driver.
> >> Or am I overlooking something ?
> > 
> > yep, at least the S3C2416/2450 HSSPI which should use this driver.
> 
> Seems you keep some patches private ;)  the spi driver isn't enabled
> for 2416 in mainline.
It's not so private [1], but isn't working yet :-). I'm still new to the whole 
kernel development stuff and seem to be the only one working on this device 
family.

I know from comparing s3c2416 and s3c64xx manuals that the hsspi part is the 
same but still have some learning to do to get it to work and also need 
drivers for the other side of the spi connection.

The Asus eeeReader DR-900 uses a wlan chip supported by libertas. So having a 
"verified" driver on the other side might help me in getting the spi driver to 
work.


Heiko


[1] https://gitorious.org/oyo-hack every e-book reader with Sipix display 
seems to be made from the same model line.

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

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-08 18:26           ` Heiko Stübner
  0 siblings, 0 replies; 88+ messages in thread
From: Heiko Stübner @ 2011-08-08 18:26 UTC (permalink / raw)
  To: linux-arm-kernel

Am Montag 08 August 2011, 20:16:58 schrieben Sie:
> On Mon, Aug 8, 2011 at 11:25 PM, Heiko St?bner <heiko@sntech.de> wrote:
> > Am Montag 08 August 2011, 19:47:58 schrieb Jassi Brar:
> >> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
> >> series, both of which
> >> have DMAENGINE drivers. May be it could be directly switched to using
> >> those, rather than
> >> via Samsung's wrapper driver.
> >> Or am I overlooking something ?
> > 
> > yep, at least the S3C2416/2450 HSSPI which should use this driver.
> 
> Seems you keep some patches private ;)  the spi driver isn't enabled
> for 2416 in mainline.
It's not so private [1], but isn't working yet :-). I'm still new to the whole 
kernel development stuff and seem to be the only one working on this device 
family.

I know from comparing s3c2416 and s3c64xx manuals that the hsspi part is the 
same but still have some learning to do to get it to work and also need 
drivers for the other side of the spi connection.

The Asus eeeReader DR-900 uses a wlan chip supported by libertas. So having a 
"verified" driver on the other side might help me in getting the spi driver to 
work.


Heiko


[1] https://gitorious.org/oyo-hack every e-book reader with Sipix display 
seems to be made from the same model line.

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

* Re: [PATCH 13/15] spi/s3c64xx: Merge dma control code
  2011-07-27  5:31   ` Boojin Kim
@ 2011-08-08 18:32     ` Jassi Brar
  -1 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-08-08 18:32 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Kukjin Kim, Russell King,
	Vinod Koul, Grant Likely, Mark Brown, Dan Williams

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> This patch modifies to merge the dma control code.
> Original s3c64xx spi driver has each dma control code for rx and tx channel.
> This patch merges these dma control codes into one.
> With this patch, a dma setup function and callback function handle
> for both rx and tx channel.

This is nothing really to do with underlying DMAENGINE API.
And, apparently it actually bloats the driver ?   76 insertions(+), 64
deletions(-)
Yet, I am not very against the idea.

If you must do it, maybe It would have been better to move it early in
the patchset,
which would have resulted in a smaller and cleaner  "spi/s3c64xx: Add
support DMA engine API"

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

* [PATCH 13/15] spi/s3c64xx: Merge dma control code
@ 2011-08-08 18:32     ` Jassi Brar
  0 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-08-08 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> This patch modifies to merge the dma control code.
> Original s3c64xx spi driver has each dma control code for rx and tx channel.
> This patch merges these dma control codes into one.
> With this patch, a dma setup function and callback function handle
> for both rx and tx channel.

This is nothing really to do with underlying DMAENGINE API.
And, apparently it actually bloats the driver ?   76 insertions(+), 64
deletions(-)
Yet, I am not very against the idea.

If you must do it, maybe It would have been better to move it early in
the patchset,
which would have resulted in a smaller and cleaner  "spi/s3c64xx: Add
support DMA engine API"

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

* Re: [PATCH 14/15] ASoC: Samsung: Update DMA interface
  2011-07-27  5:31   ` Boojin Kim
@ 2011-08-08 19:27     ` Jassi Brar
  -1 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-08-08 19:27 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Kukjin Kim, Mark Brown, Grant Likely, Russell King,
	Liam Girdwood

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

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

'dma_limit' is rendered useless, so you might want to remove it from
'struct runtime_data'
as well.

>        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);
>  }

Since we set integer-constraint on number of periods, you could also
discard bothering fractional boundaries. That would make things a lot
simpler.



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

I wish you agreed and used
       prtd->params->ops->cmd(ch, enum some_cmd_options)
rather than having 4 separate callbacks
      prtd->params->ops->trigger(prtd->params->ch)
      prtd->params->ops->stop(prtd->params->ch)
     prtd->params->ops->flush(prtd->params->ch)
     prtd->params->ops->started(prtd->params->ch)


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

Isn't this a regression ?
dma_pointer() doesn't really return actual location of DMA activity anymore.
Now it simply tells the last period done.
This would affect latencies in a bad way.

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

* [PATCH 14/15] ASoC: Samsung: Update DMA interface
@ 2011-08-08 19:27     ` Jassi Brar
  0 siblings, 0 replies; 88+ messages in thread
From: Jassi Brar @ 2011-08-08 19:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> wrote:

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

'dma_limit' is rendered useless, so you might want to remove it from
'struct runtime_data'
as well.

> ? ? ? ?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);
> ?}

Since we set integer-constraint on number of periods, you could also
discard bothering fractional boundaries. That would make things a lot
simpler.



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

I wish you agreed and used
       prtd->params->ops->cmd(ch, enum some_cmd_options)
rather than having 4 separate callbacks
      prtd->params->ops->trigger(prtd->params->ch)
      prtd->params->ops->stop(prtd->params->ch)
     prtd->params->ops->flush(prtd->params->ch)
     prtd->params->ops->started(prtd->params->ch)


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

Isn't this a regression ?
dma_pointer() doesn't really return actual location of DMA activity anymore.
Now it simply tells the last period done.
This would affect latencies in a bad way.

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

* Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-08-08 17:47     ` Jassi Brar
@ 2011-08-09  4:13       ` Alim Akhtar
  -1 siblings, 0 replies; 88+ messages in thread
From: Alim Akhtar @ 2011-08-09  4:13 UTC (permalink / raw)
  To: Jassi Brar, Boojin Kim
  Cc: Kukjin Kim, Russell King, Vinod Koul, Mark Brown, Grant Likely,
	linux-samsung-soc, Dan Williams, linux-arm-kernel, Linus Walleij,
	banajit.g

On Mon, Aug 8, 2011 at 11:17 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> 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>
>> Acked-by: 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;
> void* doesn't need typecasting (same for all such occurances)
> IIRC someone already pointed it out?
>
>
>> +       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);
>>  }
>
> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
> series, both of which
> have DMAENGINE drivers. May be it could be directly switched to using
> those, rather than
> via Samsung's wrapper driver.
> Or am I overlooking something ?
Exactly, spi_s3c64xx.c (including Sound driver) can not be used with
pl080 and pl330 (DMAENGINE drivers) as it is.
Recently I was trying to use PL080 DMAENGINE driver, and i was ended
up using some #ifdef in the spi driver.
something like
#ifdef CONFIG_PL080
sdd->tx_dmac.bus_id = dmatx_res->name;
sdd->rx_dmac.bus_id = dmarx_res->name;
#else
sdd->tx_dmac.bus_id = dmatx_res->start;
sdd->tx_dmac.bus_id = dmatx_res->start;
#endif

This is because, Pl080 handle the channel as a char *(name) and pl330
expect the channel to be enum (a number).

I think the solution could be changes in the either of these drivers
to follow some symmetry or we will be ending up with
two client driver for the same device or writing up some unnecessary
warper code or finally using some #ifdef.

Please suggest if you guys have any other idea/approach to handle such
kind of situation.

Below is the git diff of spi_s3c64xx driver using with PL080 DMAENGINE driver.
This patch is against kgene's next-samsung-dma-v4
------------------------------------------------------------------------------------------------------------------
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index a4cf76a..f7b9c37 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/pl08x.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>

@@ -165,8 +166,13 @@ struct s3c64xx_spi_driver_data {
 	struct work_struct              work;
 	struct list_head                queue;
 	spinlock_t                      lock;
+#ifdef CONFIG_DMADEV_PL080
+	struct pl08x_channel_data	rx_dmach;
+	struct pl08x_channel_data	tx_dmach;
+#else
 	enum dma_ch                     rx_dmach;
 	enum dma_ch                     tx_dmach;
+#endif
 	unsigned long                   sfr_start;
 	struct completion               xfer_completion;
 	unsigned                        state;
@@ -753,10 +759,18 @@ static int acquire_dma(struct
s3c64xx_spi_driver_data *sdd)
 	info.direction = DMA_FROM_DEVICE;
 	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
 	info.width = sdd->cur_bpw / 8;
+#ifdef CONFIG_DMADEV_PL080
+	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach.bus_id, &info);
+#else
 	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
+#endif
 	info.direction = DMA_TO_DEVICE;
 	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
-	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
+#ifdef CONFIG_DMADEV_PL080
+	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach.bus_id, &info);
+#else
+		sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
+#endif

 	return 1;
 }
@@ -982,7 +996,6 @@ static int __init s3c64xx_spi_probe(struct
platform_device *pdev)
 	}

 	/* Check for availability of necessary resource */
-
 	dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (dmatx_res == NULL) {
 		dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
@@ -1015,9 +1028,13 @@ static int __init s3c64xx_spi_probe(struct
platform_device *pdev)
 	sdd->cntrlr_info = sci;
 	sdd->pdev = pdev;
 	sdd->sfr_start = mem_res->start;
+#ifdef CONFIG_DMADEV_PL080
+	sdd->tx_dmach.bus_id = dmatx_res->name;
+	sdd->rx_dmach.bus_id = dmarx_res->name;
+#else
 	sdd->tx_dmach = dmatx_res->start;
 	sdd->rx_dmach = dmarx_res->start;
-
+#endif
 	sdd->cur_bpw = 8;

 	master->bus_num = pdev->id;
@@ -1105,7 +1122,6 @@ static int __init s3c64xx_spi_probe(struct
platform_device *pdev)
 	dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
 					mem_res->end, mem_res->start,
 					sdd->rx_dmach, sdd->tx_dmach);
-
 	return 0;

 err8:
----------------------------------------------------------------------------------------------------------------------

Regards,
Alim



> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-09  4:13       ` Alim Akhtar
  0 siblings, 0 replies; 88+ messages in thread
From: Alim Akhtar @ 2011-08-09  4:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 8, 2011 at 11:17 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> 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>
>> Acked-by: 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;
> void* doesn't need typecasting (same for all such occurances)
> IIRC someone already pointed it out?
>
>
>> + ? ? ? 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);
>> ?}
>
> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
> series, both of which
> have DMAENGINE drivers. May be it could be directly switched to using
> those, rather than
> via Samsung's wrapper driver.
> Or am I overlooking something ?
Exactly, spi_s3c64xx.c (including Sound driver) can not be used with
pl080 and pl330 (DMAENGINE drivers) as it is.
Recently I was trying to use PL080 DMAENGINE driver, and i was ended
up using some #ifdef in the spi driver.
something like
#ifdef CONFIG_PL080
sdd->tx_dmac.bus_id = dmatx_res->name;
sdd->rx_dmac.bus_id = dmarx_res->name;
#else
sdd->tx_dmac.bus_id = dmatx_res->start;
sdd->tx_dmac.bus_id = dmatx_res->start;
#endif

This is because, Pl080 handle the channel as a char *(name) and pl330
expect the channel to be enum (a number).

I think the solution could be changes in the either of these drivers
to follow some symmetry or we will be ending up with
two client driver for the same device or writing up some unnecessary
warper code or finally using some #ifdef.

Please suggest if you guys have any other idea/approach to handle such
kind of situation.

Below is the git diff of spi_s3c64xx driver using with PL080 DMAENGINE driver.
This patch is against kgene's next-samsung-dma-v4
------------------------------------------------------------------------------------------------------------------
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index a4cf76a..f7b9c37 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
+#include <linux/amba/pl08x.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>

@@ -165,8 +166,13 @@ struct s3c64xx_spi_driver_data {
 	struct work_struct              work;
 	struct list_head                queue;
 	spinlock_t                      lock;
+#ifdef CONFIG_DMADEV_PL080
+	struct pl08x_channel_data	rx_dmach;
+	struct pl08x_channel_data	tx_dmach;
+#else
 	enum dma_ch                     rx_dmach;
 	enum dma_ch                     tx_dmach;
+#endif
 	unsigned long                   sfr_start;
 	struct completion               xfer_completion;
 	unsigned                        state;
@@ -753,10 +759,18 @@ static int acquire_dma(struct
s3c64xx_spi_driver_data *sdd)
 	info.direction = DMA_FROM_DEVICE;
 	info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
 	info.width = sdd->cur_bpw / 8;
+#ifdef CONFIG_DMADEV_PL080
+	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach.bus_id, &info);
+#else
 	sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
+#endif
 	info.direction = DMA_TO_DEVICE;
 	info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
-	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
+#ifdef CONFIG_DMADEV_PL080
+	sdd->tx_ch = sdd->ops->request(sdd->tx_dmach.bus_id, &info);
+#else
+		sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
+#endif

 	return 1;
 }
@@ -982,7 +996,6 @@ static int __init s3c64xx_spi_probe(struct
platform_device *pdev)
 	}

 	/* Check for availability of necessary resource */
-
 	dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (dmatx_res == NULL) {
 		dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
@@ -1015,9 +1028,13 @@ static int __init s3c64xx_spi_probe(struct
platform_device *pdev)
 	sdd->cntrlr_info = sci;
 	sdd->pdev = pdev;
 	sdd->sfr_start = mem_res->start;
+#ifdef CONFIG_DMADEV_PL080
+	sdd->tx_dmach.bus_id = dmatx_res->name;
+	sdd->rx_dmach.bus_id = dmarx_res->name;
+#else
 	sdd->tx_dmach = dmatx_res->start;
 	sdd->rx_dmach = dmarx_res->start;
-
+#endif
 	sdd->cur_bpw = 8;

 	master->bus_num = pdev->id;
@@ -1105,7 +1122,6 @@ static int __init s3c64xx_spi_probe(struct
platform_device *pdev)
 	dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
 					mem_res->end, mem_res->start,
 					sdd->rx_dmach, sdd->tx_dmach);
-
 	return 0;

 err8:
----------------------------------------------------------------------------------------------------------------------

Regards,
Alim



> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* RE: [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
  2011-08-08 16:45     ` Koul, Vinod
@ 2011-08-11  7:26       ` Kukjin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Kukjin Kim @ 2011-08-11  7:26 UTC (permalink / raw)
  To: 'Koul, Vinod', 'Boojin Kim'
  Cc: 'Linus Walleij', 'Russell King',
	'Jassi Brar', 'Grant Likely',
	linux-samsung-soc, 'Mark Brown', 'Dan Williams',
	linux-arm-kernel

Koul, Vinod wrote:
> 
> On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> >
> > > This patchset adds support DMA generic APIs for Samsung DMA.
> >
> > Patches look good to me,
> > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> 
> Acked-by: Vinod Koul <vinod.koul@intel.com>
> 
> Do you want these to go thru slave-dma tree or arm tree, I am okay with
> either...

Hi Vinod,

Thanks.

I'd like to keep its topic branch in my tree to avoid conflicts with other samsung stuff and I think, it should be merged into your slave-dma tree also for same reason.

git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git #next/topic-dma-pl330

Or if you want to make some branch for it in your tree, please let me know so that I can merge it in my tree also.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-08-11  7:26       ` Kukjin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Kukjin Kim @ 2011-08-11  7:26 UTC (permalink / raw)
  To: linux-arm-kernel

Koul, Vinod wrote:
> 
> On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> >
> > > This patchset adds support DMA generic APIs for Samsung DMA.
> >
> > Patches look good to me,
> > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> 
> Acked-by: Vinod Koul <vinod.koul@intel.com>
> 
> Do you want these to go thru slave-dma tree or arm tree, I am okay with
> either...

Hi Vinod,

Thanks.

I'd like to keep its topic branch in my tree to avoid conflicts with other samsung stuff and I think, it should be merged into your slave-dma tree also for same reason.

git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git #next/topic-dma-pl330

Or if you want to make some branch for it in your tree, please let me know so that I can merge it in my tree also.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

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

* RE: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-08-08 17:47     ` Jassi Brar
@ 2011-08-11  7:42       ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-08-11  7:42 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Vinod Koul',
	'Dan Williams', 'Kukjin Kim',
	'Mark Brown', 'Grant Likely',
	'Russell King'

Jassi Brar Wrote:
> Sent: Tuesday, August 09, 2011 2:48 AM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Mark Brown;
> Grant Likely; Russell King
> Subject: Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
>
> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com>
> 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>
> > Acked-by: 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;
> void* doesn't need typecasting (same for all such occurances)
> IIRC someone already pointed it out?
I'm sorry for late response. (I was in vacation.)
This comment was reflected on 13/15 patch.

>
>
> > +       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);
> >  }
>
> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
> series, both of which
> have DMAENGINE drivers. May be it could be directly switched to using
> those, rather than
> via Samsung's wrapper driver.
> Or am I overlooking something ?
Samsung is preparing to use PL080 with DMAENGINE. After this work is done, We 
will consider to using DMAENGINE API if required.

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

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-11  7:42       ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-08-11  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

Jassi Brar Wrote:
> Sent: Tuesday, August 09, 2011 2:48 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; Mark Brown;
> Grant Likely; Russell King
> Subject: Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
>
> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com>
> 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>
> > Acked-by: 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;
> void* doesn't need typecasting (same for all such occurances)
> IIRC someone already pointed it out?
I'm sorry for late response. (I was in vacation.)
This comment was reflected on 13/15 patch.

>
>
> > +       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);
> >  }
>
> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
> series, both of which
> have DMAENGINE drivers. May be it could be directly switched to using
> those, rather than
> via Samsung's wrapper driver.
> Or am I overlooking something ?
Samsung is preparing to use PL080 with DMAENGINE. After this work is done, We 
will consider to using DMAENGINE API if required.

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

* RE: [PATCH 14/15] ASoC: Samsung: Update DMA interface
  2011-08-08 19:27     ` Jassi Brar
@ 2011-08-11 10:04       ` Boojin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-08-11 10:04 UTC (permalink / raw)
  To: 'Jassi Brar'
  Cc: linux-arm-kernel, linux-samsung-soc, 'Vinod Koul',
	'Dan Williams', 'Kukjin Kim',
	'Mark Brown', 'Grant Likely',
	'Russell King', 'Liam Girdwood'

Jassi Brar Wrote:
> Sent: Tuesday, August 09, 2011 4:28 AM
> To: Boojin Kim
> Cc: linux-arm-kernel@lists.infradead.org; linux-samsung-
> soc@vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Mark Brown;
> Grant Likely; Russell King; Liam Girdwood
> Subject: Re: [PATCH 14/15] ASoC: Samsung: Update DMA interface
>
> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
>
> >  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;
>
> 'dma_limit' is rendered useless, so you might want to remove it from
> 'struct runtime_data'
> as well.
You're right. I will remove it in next cleanup patch

>
> >        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);
> >  }
>
> Since we set integer-constraint on number of periods, you could also
> discard bothering fractional boundaries. That would make things a lot
> simpler.
>
>
>
> > @@ -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;
>
> I wish you agreed and used
>        prtd->params->ops->cmd(ch, enum some_cmd_options)
> rather than having 4 separate callbacks
>       prtd->params->ops->trigger(prtd->params->ch)
>       prtd->params->ops->stop(prtd->params->ch)
>      prtd->params->ops->flush(prtd->params->ch)
>      prtd->params->ops->started(prtd->params->ch)
>
>
> > @@ -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
>
> Isn't this a regression ?
> dma_pointer() doesn't really return actual location of DMA activity
> anymore.
> Now it simply tells the last period done.
> This would affect latencies in a bad way.
Yes, This code makes the DMA position less accurately. But, This position is 
enough for audio DMA activity. Other drivers also use similar method to get 
the position.

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

* [PATCH 14/15] ASoC: Samsung: Update DMA interface
@ 2011-08-11 10:04       ` Boojin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Boojin Kim @ 2011-08-11 10:04 UTC (permalink / raw)
  To: linux-arm-kernel

Jassi Brar Wrote:
> Sent: Tuesday, August 09, 2011 4:28 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; Mark Brown;
> Grant Likely; Russell King; Liam Girdwood
> Subject: Re: [PATCH 14/15] ASoC: Samsung: Update DMA interface
>
> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
>
> >  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;
>
> 'dma_limit' is rendered useless, so you might want to remove it from
> 'struct runtime_data'
> as well.
You're right. I will remove it in next cleanup patch

>
> >        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);
> >  }
>
> Since we set integer-constraint on number of periods, you could also
> discard bothering fractional boundaries. That would make things a lot
> simpler.
>
>
>
> > @@ -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;
>
> I wish you agreed and used
>        prtd->params->ops->cmd(ch, enum some_cmd_options)
> rather than having 4 separate callbacks
>       prtd->params->ops->trigger(prtd->params->ch)
>       prtd->params->ops->stop(prtd->params->ch)
>      prtd->params->ops->flush(prtd->params->ch)
>      prtd->params->ops->started(prtd->params->ch)
>
>
> > @@ -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
>
> Isn't this a regression ?
> dma_pointer() doesn't really return actual location of DMA activity
> anymore.
> Now it simply tells the last period done.
> This would affect latencies in a bad way.
Yes, This code makes the DMA position less accurately. But, This position is 
enough for audio DMA activity. Other drivers also use similar method to get 
the position.

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

* RE: [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
  2011-08-11  7:26       ` Kukjin Kim
@ 2011-08-11 22:27         ` Koul, Vinod
  -1 siblings, 0 replies; 88+ messages in thread
From: Koul, Vinod @ 2011-08-11 22:27 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: 'Boojin Kim', linux-samsung-soc, 'Russell King',
	'Linus Walleij', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

On Thu, 2011-08-11 at 16:26 +0900, Kukjin Kim wrote:
> Koul, Vinod wrote:
> > 
> > On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> > >
> > > > This patchset adds support DMA generic APIs for Samsung DMA.
> > >
> > > Patches look good to me,
> > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > 
> > Acked-by: Vinod Koul <vinod.koul@intel.com>
> > 
> > Do you want these to go thru slave-dma tree or arm tree, I am okay with
> > either...
> 
> Hi Vinod,
> 
> Thanks.
> 
> I'd like to keep its topic branch in my tree to avoid conflicts with other samsung stuff and I think, it should be merged into your slave-dma tree also for same reason.
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git #next/topic-dma-pl330
> 
> Or if you want to make some branch for it in your tree, please let me know so that I can merge it in my tree also.
Okay can you update this branch with latest patchset (I think there were
few comments on last patchset). Once you add all acks let me know the
branch, I will merge it to my next

-- 
~Vinod

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-08-11 22:27         ` Koul, Vinod
  0 siblings, 0 replies; 88+ messages in thread
From: Koul, Vinod @ 2011-08-11 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-08-11 at 16:26 +0900, Kukjin Kim wrote:
> Koul, Vinod wrote:
> > 
> > On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com> wrote:
> > >
> > > > This patchset adds support DMA generic APIs for Samsung DMA.
> > >
> > > Patches look good to me,
> > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > 
> > Acked-by: Vinod Koul <vinod.koul@intel.com>
> > 
> > Do you want these to go thru slave-dma tree or arm tree, I am okay with
> > either...
> 
> Hi Vinod,
> 
> Thanks.
> 
> I'd like to keep its topic branch in my tree to avoid conflicts with other samsung stuff and I think, it should be merged into your slave-dma tree also for same reason.
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git #next/topic-dma-pl330
> 
> Or if you want to make some branch for it in your tree, please let me know so that I can merge it in my tree also.
Okay can you update this branch with latest patchset (I think there were
few comments on last patchset). Once you add all acks let me know the
branch, I will merge it to my next

-- 
~Vinod

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

* RE: [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
  2011-08-11 22:27         ` Koul, Vinod
@ 2011-08-13  4:11           ` Kukjin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Kukjin Kim @ 2011-08-13  4:11 UTC (permalink / raw)
  To: 'Koul, Vinod'
  Cc: 'Boojin Kim', linux-samsung-soc, 'Russell King',
	'Linus Walleij', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

Koul, Vinod wrote:
> 
> On Thu, 2011-08-11 at 16:26 +0900, Kukjin Kim wrote:
> > Koul, Vinod wrote:
> > >
> > > On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > > > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > > >
> > > > > This patchset adds support DMA generic APIs for Samsung DMA.
> > > >
> > > > Patches look good to me,
> > > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > >
> > > Acked-by: Vinod Koul <vinod.koul@intel.com>
> > >
> > > Do you want these to go thru slave-dma tree or arm tree, I am okay with
> > > either...
> >
> > Hi Vinod,
> >
> > Thanks.
> >
> > I'd like to keep its topic branch in my tree to avoid conflicts with other samsung
> stuff and I think, it should be merged into your slave-dma tree also for same
> reason.
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git #next/topic-
> dma-pl330
> >
> > Or if you want to make some branch for it in your tree, please let me know so
> that I can merge it in my tree also.
> Okay can you update this branch with latest patchset (I think there were
> few comments on last patchset). Once you add all acks let me know the
> branch, I will merge it to my next

Hi,

I updated it so that you can merge it to yours.
I think, if any fixing is required on that, it should be small so can be fixed easily after this merging.

If any problems, please let me know :)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-08-13  4:11           ` Kukjin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Kukjin Kim @ 2011-08-13  4:11 UTC (permalink / raw)
  To: linux-arm-kernel

Koul, Vinod wrote:
> 
> On Thu, 2011-08-11 at 16:26 +0900, Kukjin Kim wrote:
> > Koul, Vinod wrote:
> > >
> > > On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > > > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com>
> wrote:
> > > >
> > > > > This patchset adds support DMA generic APIs for Samsung DMA.
> > > >
> > > > Patches look good to me,
> > > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > >
> > > Acked-by: Vinod Koul <vinod.koul@intel.com>
> > >
> > > Do you want these to go thru slave-dma tree or arm tree, I am okay with
> > > either...
> >
> > Hi Vinod,
> >
> > Thanks.
> >
> > I'd like to keep its topic branch in my tree to avoid conflicts with other samsung
> stuff and I think, it should be merged into your slave-dma tree also for same
> reason.
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git #next/topic-
> dma-pl330
> >
> > Or if you want to make some branch for it in your tree, please let me know so
> that I can merge it in my tree also.
> Okay can you update this branch with latest patchset (I think there were
> few comments on last patchset). Once you add all acks let me know the
> branch, I will merge it to my next

Hi,

I updated it so that you can merge it to yours.
I think, if any fixing is required on that, it should be small so can be fixed easily after this merging.

If any problems, please let me know :)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

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

* Re: [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver
  2011-07-27  5:31   ` Boojin Kim
@ 2011-08-15  9:36     ` Thomas Abraham
  -1 siblings, 0 replies; 88+ messages in thread
From: Thomas Abraham @ 2011-08-15  9:36 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Jassi Brar, Kukjin Kim, Mark Brown, Grant Likely, Russell King

Hi Boojin,

On 27 July 2011 11:01, Boojin Kim <boojin.kim@samsung.com> wrote:
> 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   |  299 ++++++++++++++++++++++++++---------------
>  3 files changed, 198 insertions(+), 119 deletions(-)
>

[...]

> diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
> index 564bb53..d57d662 100644

[...]

> +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,
>  };
>

[...]

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

How would the 'exynos4_device_pdma1' instance get registered? Should
there be a amba_device_register call for 'exynos4_device_pdma1'
instance as well?

Thanks,
Thomas.

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

* [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver
@ 2011-08-15  9:36     ` Thomas Abraham
  0 siblings, 0 replies; 88+ messages in thread
From: Thomas Abraham @ 2011-08-15  9:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Boojin,

On 27 July 2011 11:01, Boojin Kim <boojin.kim@samsung.com> wrote:
> 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 ? | ?299 ++++++++++++++++++++++++++---------------
> ?3 files changed, 198 insertions(+), 119 deletions(-)
>

[...]

> diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
> index 564bb53..d57d662 100644

[...]

> +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,
> ?};
>

[...]

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

How would the 'exynos4_device_pdma1' instance get registered? Should
there be a amba_device_register call for 'exynos4_device_pdma1'
instance as well?

Thanks,
Thomas.

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

* Re: [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver
  2011-07-27  5:31   ` Boojin Kim
@ 2011-08-15 14:15     ` Thomas Abraham
  -1 siblings, 0 replies; 88+ messages in thread
From: Thomas Abraham @ 2011-08-15 14:15 UTC (permalink / raw)
  To: Boojin Kim
  Cc: linux-arm-kernel, linux-samsung-soc, Vinod Koul, Dan Williams,
	Jassi Brar, Kukjin Kim, Mark Brown, Grant Likely, Russell King

Hi Boojin,

On 27 July 2011 11:01, Boojin Kim <boojin.kim@samsung.com> wrote:
> 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   |  299 ++++++++++++++++++++++++++---------------
>  3 files changed, 198 insertions(+), 119 deletions(-)
>

[...]

> diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
> index 564bb53..d57d662 100644

[...]

> +struct dma_pl330_peri pdma0_peri[28] = {
> +       {
> +               .peri_id = (u8)DMACH_PCM0_RX,
> +               .rqtype = DEVTOMEM,
> +       }, {

The client driver specifies the direction of the transfer
(DMA_TO_DEVICE or DMA_FROM_DEVICE) when requesting for a dma channel.
So, is the rqtype parameter required in the platform data for the dma
driver?

Thanks,
Thomas.

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

* [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver
@ 2011-08-15 14:15     ` Thomas Abraham
  0 siblings, 0 replies; 88+ messages in thread
From: Thomas Abraham @ 2011-08-15 14:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Boojin,

On 27 July 2011 11:01, Boojin Kim <boojin.kim@samsung.com> wrote:
> 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 ? | ?299 ++++++++++++++++++++++++++---------------
> ?3 files changed, 198 insertions(+), 119 deletions(-)
>

[...]

> diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
> index 564bb53..d57d662 100644

[...]

> +struct dma_pl330_peri pdma0_peri[28] = {
> + ? ? ? {
> + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM0_RX,
> + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> + ? ? ? }, {

The client driver specifies the direction of the transfer
(DMA_TO_DEVICE or DMA_FROM_DEVICE) when requesting for a dma channel.
So, is the rqtype parameter required in the platform data for the dma
driver?

Thanks,
Thomas.

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

* RE: [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
  2011-08-13  4:11           ` Kukjin Kim
@ 2011-08-16 11:01             ` Koul, Vinod
  -1 siblings, 0 replies; 88+ messages in thread
From: Koul, Vinod @ 2011-08-16 11:01 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: linux-samsung-soc, 'Russell King', 'Boojin Kim',
	'Linus Walleij', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

On Sat, 2011-08-13 at 13:11 +0900, Kukjin Kim wrote:
> Koul, Vinod wrote:
> > 
> > On Thu, 2011-08-11 at 16:26 +0900, Kukjin Kim wrote:
> > > Koul, Vinod wrote:
> > > >
> > > > On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > > > > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com>
> > wrote:
> > > > >
> > > > > > This patchset adds support DMA generic APIs for Samsung DMA.
> > > > >
> > > > > Patches look good to me,
> > > > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > > >
> > > > Acked-by: Vinod Koul <vinod.koul@intel.com>
> > > >
> > > > Do you want these to go thru slave-dma tree or arm tree, I am okay with
> > > > either...
> > >
> > > Hi Vinod,
> > >
> > > Thanks.
> > >
> > > I'd like to keep its topic branch in my tree to avoid conflicts with other samsung
> > stuff and I think, it should be merged into your slave-dma tree also for same
> > reason.
> > >
> > > git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git #next/topic-
> > dma-pl330
> > >
> > > Or if you want to make some branch for it in your tree, please let me know so
> > that I can merge it in my tree also.
> > Okay can you update this branch with latest patchset (I think there were
> > few comments on last patchset). Once you add all acks let me know the
> > branch, I will merge it to my next
> 
> Hi,
> 
> I updated it so that you can merge it to yours.
> I think, if any fixing is required on that, it should be small so can be fixed easily after this merging.
> 
> If any problems, please let me know :)
> 
Well, that not how things are supposed to be done. Fixing an error
introduced is not recommended, rather original patch set should be
fixed.
Since you have already done 5 posting of your patch series, I am okay if
you split things up, send me the parts that have already been reviewed
and acked. I will host them on a branch for you. Once rest is reviewed
and acked, I will merge this entire branch to my next.


-- 
~Vinod

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-08-16 11:01             ` Koul, Vinod
  0 siblings, 0 replies; 88+ messages in thread
From: Koul, Vinod @ 2011-08-16 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 2011-08-13 at 13:11 +0900, Kukjin Kim wrote:
> Koul, Vinod wrote:
> > 
> > On Thu, 2011-08-11 at 16:26 +0900, Kukjin Kim wrote:
> > > Koul, Vinod wrote:
> > > >
> > > > On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > > > > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim <boojin.kim@samsung.com>
> > wrote:
> > > > >
> > > > > > This patchset adds support DMA generic APIs for Samsung DMA.
> > > > >
> > > > > Patches look good to me,
> > > > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > > >
> > > > Acked-by: Vinod Koul <vinod.koul@intel.com>
> > > >
> > > > Do you want these to go thru slave-dma tree or arm tree, I am okay with
> > > > either...
> > >
> > > Hi Vinod,
> > >
> > > Thanks.
> > >
> > > I'd like to keep its topic branch in my tree to avoid conflicts with other samsung
> > stuff and I think, it should be merged into your slave-dma tree also for same
> > reason.
> > >
> > > git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git #next/topic-
> > dma-pl330
> > >
> > > Or if you want to make some branch for it in your tree, please let me know so
> > that I can merge it in my tree also.
> > Okay can you update this branch with latest patchset (I think there were
> > few comments on last patchset). Once you add all acks let me know the
> > branch, I will merge it to my next
> 
> Hi,
> 
> I updated it so that you can merge it to yours.
> I think, if any fixing is required on that, it should be small so can be fixed easily after this merging.
> 
> If any problems, please let me know :)
> 
Well, that not how things are supposed to be done. Fixing an error
introduced is not recommended, rather original patch set should be
fixed.
Since you have already done 5 posting of your patch series, I am okay if
you split things up, send me the parts that have already been reviewed
and acked. I will host them on a branch for you. Once rest is reviewed
and acked, I will merge this entire branch to my next.


-- 
~Vinod

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

* RE: [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
  2011-08-16 11:01             ` Koul, Vinod
@ 2011-08-19  5:24               ` Kukjin Kim
  -1 siblings, 0 replies; 88+ messages in thread
From: Kukjin Kim @ 2011-08-19  5:24 UTC (permalink / raw)
  To: 'Koul, Vinod'
  Cc: linux-samsung-soc, 'Russell King', 'Boojin Kim',
	'Linus Walleij', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	'Dan Williams',
	linux-arm-kernel

Koul, Vinod wrote:
> 
> On Sat, 2011-08-13 at 13:11 +0900, Kukjin Kim wrote:
> > Koul, Vinod wrote:
> > >
> > > On Thu, 2011-08-11 at 16:26 +0900, Kukjin Kim wrote:
> > > > Koul, Vinod wrote:
> > > > >
> > > > > On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > > > > > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim
> <boojin.kim@samsung.com>
> > > wrote:
> > > > > >
> > > > > > > This patchset adds support DMA generic APIs for Samsung DMA.
> > > > > >
> > > > > > Patches look good to me,
> > > > > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > > > >
> > > > > Acked-by: Vinod Koul <vinod.koul@intel.com>
> > > > >
> > > > > Do you want these to go thru slave-dma tree or arm tree, I am okay with
> > > > > either...
> > > >
> > > > Hi Vinod,
> > > >
> > > > Thanks.
> > > >
> > > > I'd like to keep its topic branch in my tree to avoid conflicts with other
> samsung
> > > stuff and I think, it should be merged into your slave-dma tree also for same
> > > reason.
> > > >
> > > > git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
> #next/topic-
> > > dma-pl330
> > > >
> > > > Or if you want to make some branch for it in your tree, please let me know so
> > > that I can merge it in my tree also.
> > > Okay can you update this branch with latest patchset (I think there were
> > > few comments on last patchset). Once you add all acks let me know the
> > > branch, I will merge it to my next
> >
> > Hi,
> >
> > I updated it so that you can merge it to yours.
> > I think, if any fixing is required on that, it should be small so can be fixed easily
> after this merging.
> >
> > If any problems, please let me know :)
> >
> Well, that not how things are supposed to be done. Fixing an error
> introduced is not recommended, rather original patch set should be
> fixed.
> Since you have already done 5 posting of your patch series, I am okay if
> you split things up, send me the parts that have already been reviewed
> and acked. I will host them on a branch for you. Once rest is reviewed
> and acked, I will merge this entire branch to my next.
> 
OK, Boojin will send whole series soon.
Then if you make a branch for me, I will merge it too.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-08-19  5:24               ` Kukjin Kim
  0 siblings, 0 replies; 88+ messages in thread
From: Kukjin Kim @ 2011-08-19  5:24 UTC (permalink / raw)
  To: linux-arm-kernel

Koul, Vinod wrote:
> 
> On Sat, 2011-08-13 at 13:11 +0900, Kukjin Kim wrote:
> > Koul, Vinod wrote:
> > >
> > > On Thu, 2011-08-11 at 16:26 +0900, Kukjin Kim wrote:
> > > > Koul, Vinod wrote:
> > > > >
> > > > > On Thu, 2011-08-04 at 18:53 +0200, Linus Walleij wrote:
> > > > > > On Wed, Jul 27, 2011 at 7:31 AM, Boojin Kim
> <boojin.kim@samsung.com>
> > > wrote:
> > > > > >
> > > > > > > This patchset adds support DMA generic APIs for Samsung DMA.
> > > > > >
> > > > > > Patches look good to me,
> > > > > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > > > >
> > > > > Acked-by: Vinod Koul <vinod.koul@intel.com>
> > > > >
> > > > > Do you want these to go thru slave-dma tree or arm tree, I am okay with
> > > > > either...
> > > >
> > > > Hi Vinod,
> > > >
> > > > Thanks.
> > > >
> > > > I'd like to keep its topic branch in my tree to avoid conflicts with other
> samsung
> > > stuff and I think, it should be merged into your slave-dma tree also for same
> > > reason.
> > > >
> > > > git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
> #next/topic-
> > > dma-pl330
> > > >
> > > > Or if you want to make some branch for it in your tree, please let me know so
> > > that I can merge it in my tree also.
> > > Okay can you update this branch with latest patchset (I think there were
> > > few comments on last patchset). Once you add all acks let me know the
> > > branch, I will merge it to my next
> >
> > Hi,
> >
> > I updated it so that you can merge it to yours.
> > I think, if any fixing is required on that, it should be small so can be fixed easily
> after this merging.
> >
> > If any problems, please let me know :)
> >
> Well, that not how things are supposed to be done. Fixing an error
> introduced is not recommended, rather original patch set should be
> fixed.
> Since you have already done 5 posting of your patch series, I am okay if
> you split things up, send me the parts that have already been reviewed
> and acked. I will host them on a branch for you. Once rest is reviewed
> and acked, I will merge this entire branch to my next.
> 
OK, Boojin will send whole series soon.
Then if you make a branch for me, I will merge it too.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

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

* Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-08-09  4:13       ` Alim Akhtar
@ 2011-08-19 10:30         ` Alim Akhtar
  -1 siblings, 0 replies; 88+ messages in thread
From: Alim Akhtar @ 2011-08-19 10:30 UTC (permalink / raw)
  To: Jassi Brar, Boojin Kim
  Cc: Kukjin Kim, Russell King, Vinod Koul, Mark Brown, Grant Likely,
	linux-samsung-soc, Dan Williams, linux-arm-kernel, Linus Walleij,
	banajit.g, viresh kumar

On Tue, Aug 9, 2011 at 9:43 AM, Alim Akhtar <alim.akhtar@gmail.com> wrote:
> On Mon, Aug 8, 2011 at 11:17 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> 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>
>>> Acked-by: 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;
>> void* doesn't need typecasting (same for all such occurances)
>> IIRC someone already pointed it out?
>>
>>
>>> +       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);
>>>  }
>>
>> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
>> series, both of which
>> have DMAENGINE drivers. May be it could be directly switched to using
>> those, rather than
>> via Samsung's wrapper driver.
>> Or am I overlooking something ?
> Exactly, spi_s3c64xx.c (including Sound driver) can not be used with
> pl080 and pl330 (DMAENGINE drivers) as it is.
> Recently I was trying to use PL080 DMAENGINE driver, and i was ended
> up using some #ifdef in the spi driver.
> something like
> #ifdef CONFIG_PL080
> sdd->tx_dmac.bus_id = dmatx_res->name;
> sdd->rx_dmac.bus_id = dmarx_res->name;
> #else
> sdd->tx_dmac.bus_id = dmatx_res->start;
> sdd->tx_dmac.bus_id = dmatx_res->start;
> #endif
>
> This is because, Pl080 handle the channel as a char *(name) and pl330
> expect the channel to be enum (a number).
>
> I think the solution could be changes in the either of these drivers
> to follow some symmetry or we will be ending up with
> two client driver for the same device or writing up some unnecessary
> warper code or finally using some #ifdef.
>
> Please suggest if you guys have any other idea/approach to handle such
> kind of situation.
>
> Below is the git diff of spi_s3c64xx driver using with PL080 DMAENGINE driver.
> This patch is against kgene's next-samsung-dma-v4
> ------------------------------------------------------------------------------------------------------------------
> diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> index a4cf76a..f7b9c37 100644
> --- a/drivers/spi/spi_s3c64xx.c
> +++ b/drivers/spi/spi_s3c64xx.c
> @@ -24,6 +24,7 @@
>  #include <linux/delay.h>
>  #include <linux/clk.h>
>  #include <linux/dma-mapping.h>
> +#include <linux/amba/pl08x.h>
>  #include <linux/platform_device.h>
>  #include <linux/spi/spi.h>
>
> @@ -165,8 +166,13 @@ struct s3c64xx_spi_driver_data {
>        struct work_struct              work;
>        struct list_head                queue;
>        spinlock_t                      lock;
> +#ifdef CONFIG_DMADEV_PL080
> +       struct pl08x_channel_data       rx_dmach;
> +       struct pl08x_channel_data       tx_dmach;
> +#else
>        enum dma_ch                     rx_dmach;
>        enum dma_ch                     tx_dmach;
> +#endif
>        unsigned long                   sfr_start;
>        struct completion               xfer_completion;
>        unsigned                        state;
> @@ -753,10 +759,18 @@ static int acquire_dma(struct
> s3c64xx_spi_driver_data *sdd)
>        info.direction = DMA_FROM_DEVICE;
>        info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
>        info.width = sdd->cur_bpw / 8;
> +#ifdef CONFIG_DMADEV_PL080
> +       sdd->rx_ch = sdd->ops->request(sdd->rx_dmach.bus_id, &info);
> +#else
>        sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
> +#endif
>        info.direction = DMA_TO_DEVICE;
>        info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
> -       sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
> +#ifdef CONFIG_DMADEV_PL080
> +       sdd->tx_ch = sdd->ops->request(sdd->tx_dmach.bus_id, &info);
> +#else
> +               sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
> +#endif
>
>        return 1;
>  }
> @@ -982,7 +996,6 @@ static int __init s3c64xx_spi_probe(struct
> platform_device *pdev)
>        }
>
>        /* Check for availability of necessary resource */
> -
>        dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
>        if (dmatx_res == NULL) {
>                dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
> @@ -1015,9 +1028,13 @@ static int __init s3c64xx_spi_probe(struct
> platform_device *pdev)
>        sdd->cntrlr_info = sci;
>        sdd->pdev = pdev;
>        sdd->sfr_start = mem_res->start;
> +#ifdef CONFIG_DMADEV_PL080
> +       sdd->tx_dmach.bus_id = dmatx_res->name;
> +       sdd->rx_dmach.bus_id = dmarx_res->name;
> +#else
>        sdd->tx_dmach = dmatx_res->start;
>        sdd->rx_dmach = dmarx_res->start;
> -
> +#endif
>        sdd->cur_bpw = 8;
>
>        master->bus_num = pdev->id;
> @@ -1105,7 +1122,6 @@ static int __init s3c64xx_spi_probe(struct
> platform_device *pdev)
>        dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
>                                        mem_res->end, mem_res->start,
>                                        sdd->rx_dmach, sdd->tx_dmach);
> -
>        return 0;
>
>  err8:
> ----------------------------------------------------------------------------------------------------------------------
>
Hi All,
Any suggestions/comments on my concerns?

Thanks!
> Regards,
> Alim
>
>
>
>> _______________________________________________
>> 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] 88+ messages in thread

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-19 10:30         ` Alim Akhtar
  0 siblings, 0 replies; 88+ messages in thread
From: Alim Akhtar @ 2011-08-19 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 9, 2011 at 9:43 AM, Alim Akhtar <alim.akhtar@gmail.com> wrote:
> On Mon, Aug 8, 2011 at 11:17 PM, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>> On Wed, Jul 27, 2011 at 11:01 AM, Boojin Kim <boojin.kim@samsung.com> 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>
>>> Acked-by: 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;
>> void* doesn't need typecasting (same for all such occurances)
>> IIRC someone already pointed it out?
>>
>>
>>> + ? ? ? 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);
>>> ?}
>>
>> Btw, this spi driver is for S3C64xx(with pl080) and S5P(with pl330)
>> series, both of which
>> have DMAENGINE drivers. May be it could be directly switched to using
>> those, rather than
>> via Samsung's wrapper driver.
>> Or am I overlooking something ?
> Exactly, spi_s3c64xx.c (including Sound driver) can not be used with
> pl080 and pl330 (DMAENGINE drivers) as it is.
> Recently I was trying to use PL080 DMAENGINE driver, and i was ended
> up using some #ifdef in the spi driver.
> something like
> #ifdef CONFIG_PL080
> sdd->tx_dmac.bus_id = dmatx_res->name;
> sdd->rx_dmac.bus_id = dmarx_res->name;
> #else
> sdd->tx_dmac.bus_id = dmatx_res->start;
> sdd->tx_dmac.bus_id = dmatx_res->start;
> #endif
>
> This is because, Pl080 handle the channel as a char *(name) and pl330
> expect the channel to be enum (a number).
>
> I think the solution could be changes in the either of these drivers
> to follow some symmetry or we will be ending up with
> two client driver for the same device or writing up some unnecessary
> warper code or finally using some #ifdef.
>
> Please suggest if you guys have any other idea/approach to handle such
> kind of situation.
>
> Below is the git diff of spi_s3c64xx driver using with PL080 DMAENGINE driver.
> This patch is against kgene's next-samsung-dma-v4
> ------------------------------------------------------------------------------------------------------------------
> diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> index a4cf76a..f7b9c37 100644
> --- a/drivers/spi/spi_s3c64xx.c
> +++ b/drivers/spi/spi_s3c64xx.c
> @@ -24,6 +24,7 @@
> ?#include <linux/delay.h>
> ?#include <linux/clk.h>
> ?#include <linux/dma-mapping.h>
> +#include <linux/amba/pl08x.h>
> ?#include <linux/platform_device.h>
> ?#include <linux/spi/spi.h>
>
> @@ -165,8 +166,13 @@ struct s3c64xx_spi_driver_data {
> ? ? ? ?struct work_struct ? ? ? ? ? ? ?work;
> ? ? ? ?struct list_head ? ? ? ? ? ? ? ?queue;
> ? ? ? ?spinlock_t ? ? ? ? ? ? ? ? ? ? ?lock;
> +#ifdef CONFIG_DMADEV_PL080
> + ? ? ? struct pl08x_channel_data ? ? ? rx_dmach;
> + ? ? ? struct pl08x_channel_data ? ? ? tx_dmach;
> +#else
> ? ? ? ?enum dma_ch ? ? ? ? ? ? ? ? ? ? rx_dmach;
> ? ? ? ?enum dma_ch ? ? ? ? ? ? ? ? ? ? tx_dmach;
> +#endif
> ? ? ? ?unsigned long ? ? ? ? ? ? ? ? ? sfr_start;
> ? ? ? ?struct completion ? ? ? ? ? ? ? xfer_completion;
> ? ? ? ?unsigned ? ? ? ? ? ? ? ? ? ? ? ?state;
> @@ -753,10 +759,18 @@ static int acquire_dma(struct
> s3c64xx_spi_driver_data *sdd)
> ? ? ? ?info.direction = DMA_FROM_DEVICE;
> ? ? ? ?info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
> ? ? ? ?info.width = sdd->cur_bpw / 8;
> +#ifdef CONFIG_DMADEV_PL080
> + ? ? ? sdd->rx_ch = sdd->ops->request(sdd->rx_dmach.bus_id, &info);
> +#else
> ? ? ? ?sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
> +#endif
> ? ? ? ?info.direction = DMA_TO_DEVICE;
> ? ? ? ?info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
> - ? ? ? sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
> +#ifdef CONFIG_DMADEV_PL080
> + ? ? ? sdd->tx_ch = sdd->ops->request(sdd->tx_dmach.bus_id, &info);
> +#else
> + ? ? ? ? ? ? ? sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
> +#endif
>
> ? ? ? ?return 1;
> ?}
> @@ -982,7 +996,6 @@ static int __init s3c64xx_spi_probe(struct
> platform_device *pdev)
> ? ? ? ?}
>
> ? ? ? ?/* Check for availability of necessary resource */
> -
> ? ? ? ?dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
> ? ? ? ?if (dmatx_res == NULL) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
> @@ -1015,9 +1028,13 @@ static int __init s3c64xx_spi_probe(struct
> platform_device *pdev)
> ? ? ? ?sdd->cntrlr_info = sci;
> ? ? ? ?sdd->pdev = pdev;
> ? ? ? ?sdd->sfr_start = mem_res->start;
> +#ifdef CONFIG_DMADEV_PL080
> + ? ? ? sdd->tx_dmach.bus_id = dmatx_res->name;
> + ? ? ? sdd->rx_dmach.bus_id = dmarx_res->name;
> +#else
> ? ? ? ?sdd->tx_dmach = dmatx_res->start;
> ? ? ? ?sdd->rx_dmach = dmarx_res->start;
> -
> +#endif
> ? ? ? ?sdd->cur_bpw = 8;
>
> ? ? ? ?master->bus_num = pdev->id;
> @@ -1105,7 +1122,6 @@ static int __init s3c64xx_spi_probe(struct
> platform_device *pdev)
> ? ? ? ?dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?mem_res->end, mem_res->start,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sdd->rx_dmach, sdd->tx_dmach);
> -
> ? ? ? ?return 0;
>
> ?err8:
> ----------------------------------------------------------------------------------------------------------------------
>
Hi All,
Any suggestions/comments on my concerns?

Thanks!
> Regards,
> Alim
>
>
>
>> _______________________________________________
>> 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] 88+ messages in thread

* RE: [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
  2011-08-19  5:24               ` Kukjin Kim
@ 2011-08-19 13:04                 ` Koul, Vinod
  -1 siblings, 0 replies; 88+ messages in thread
From: Koul, Vinod @ 2011-08-19 13:04 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: linux-samsung-soc, 'Russell King', 'Boojin Kim',
	'Linus Walleij', 'Jassi Brar',
	'Grant Likely', 'Mark Brown',
	Williams, Dan J, linux-arm-kernel

On Fri, 2011-08-19 at 10:54 +0530, Kukjin Kim wrote:
> Koul, Vinod wrote:
> > 
> OK, Boojin will send whole series soon.
> Then if you make a branch for me, I will merge it too.
Sure, 
I have created a branh for you off my next

git://git.infradead.org/users/vkoul/slave-dma.git samsung_dma

I will apply your series after reviewing and once its acked by other
maintainers will merge to my next

-- 
~Vinod

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

* [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA
@ 2011-08-19 13:04                 ` Koul, Vinod
  0 siblings, 0 replies; 88+ messages in thread
From: Koul, Vinod @ 2011-08-19 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2011-08-19 at 10:54 +0530, Kukjin Kim wrote:
> Koul, Vinod wrote:
> > 
> OK, Boojin will send whole series soon.
> Then if you make a branch for me, I will merge it too.
Sure, 
I have created a branh for you off my next

git://git.infradead.org/users/vkoul/slave-dma.git samsung_dma

I will apply your series after reviewing and once its acked by other
maintainers will merge to my next

-- 
~Vinod

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

* Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-08-09  4:13       ` Alim Akhtar
@ 2011-08-21  8:46         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 88+ messages in thread
From: Russell King - ARM Linux @ 2011-08-21  8:46 UTC (permalink / raw)
  To: Alim Akhtar
  Cc: Jassi Brar, Boojin Kim, Kukjin Kim, Vinod Koul, Mark Brown,
	Grant Likely, linux-samsung-soc, Dan Williams, linux-arm-kernel,
	Linus Walleij, banajit.g

On Tue, Aug 09, 2011 at 09:43:32AM +0530, Alim Akhtar wrote:
> Exactly, spi_s3c64xx.c (including Sound driver) can not be used with
> pl080 and pl330 (DMAENGINE drivers) as it is.
> Recently I was trying to use PL080 DMAENGINE driver, and i was ended
> up using some #ifdef in the spi driver.
> something like
> #ifdef CONFIG_PL080
> sdd->tx_dmac.bus_id = dmatx_res->name;
> sdd->rx_dmac.bus_id = dmarx_res->name;
> #else
> sdd->tx_dmac.bus_id = dmatx_res->start;
> sdd->tx_dmac.bus_id = dmatx_res->start;
> #endif
> 
> This is because, Pl080 handle the channel as a char *(name) and pl330
> expect the channel to be enum (a number).

The alternative is that you do as the Primecell drivers do (which was
designed from the outset to be independent of the specific dmaengine),
and pass the DMA filter parameters as pointers via platform data.

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

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-21  8:46         ` Russell King - ARM Linux
  0 siblings, 0 replies; 88+ messages in thread
From: Russell King - ARM Linux @ 2011-08-21  8:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 09, 2011 at 09:43:32AM +0530, Alim Akhtar wrote:
> Exactly, spi_s3c64xx.c (including Sound driver) can not be used with
> pl080 and pl330 (DMAENGINE drivers) as it is.
> Recently I was trying to use PL080 DMAENGINE driver, and i was ended
> up using some #ifdef in the spi driver.
> something like
> #ifdef CONFIG_PL080
> sdd->tx_dmac.bus_id = dmatx_res->name;
> sdd->rx_dmac.bus_id = dmarx_res->name;
> #else
> sdd->tx_dmac.bus_id = dmatx_res->start;
> sdd->tx_dmac.bus_id = dmatx_res->start;
> #endif
> 
> This is because, Pl080 handle the channel as a char *(name) and pl330
> expect the channel to be enum (a number).

The alternative is that you do as the Primecell drivers do (which was
designed from the outset to be independent of the specific dmaengine),
and pass the DMA filter parameters as pointers via platform data.

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

* Re: [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver
  2011-08-15 14:15     ` Thomas Abraham
@ 2011-08-21  8:51       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 88+ messages in thread
From: Russell King - ARM Linux @ 2011-08-21  8:51 UTC (permalink / raw)
  To: Thomas Abraham
  Cc: Boojin Kim, linux-arm-kernel, linux-samsung-soc, Vinod Koul,
	Dan Williams, Jassi Brar, Kukjin Kim, Mark Brown, Grant Likely

On Mon, Aug 15, 2011 at 07:45:48PM +0530, Thomas Abraham wrote:
> > +struct dma_pl330_peri pdma0_peri[28] = {
> > +       {
> > +               .peri_id = (u8)DMACH_PCM0_RX,
> > +               .rqtype = DEVTOMEM,
> > +       }, {
> 
> The client driver specifies the direction of the transfer
> (DMA_TO_DEVICE or DMA_FROM_DEVICE) when requesting for a dma channel.
> So, is the rqtype parameter required in the platform data for the dma
> driver?

That was done initially too with PL080, which has 8 uncommitted DMA
channels.  Peripheral drivers still had to pass the DMA direction.  So
it turned out to be entirely redundant information, so it got killed off,
along with other channel specific configuration which drivers should've
been doing via the slave configuration callback.

Passing lots of information via platform data which should come via
other routes makes dmaengine users fragile - you can't tell whether
they are passing the correct and full information necessary to work with
other dmaengine drivers.  So, the DMA engine platform data should only
contain the absolute _minimum_ of information.

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

* [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver
@ 2011-08-21  8:51       ` Russell King - ARM Linux
  0 siblings, 0 replies; 88+ messages in thread
From: Russell King - ARM Linux @ 2011-08-21  8:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 15, 2011 at 07:45:48PM +0530, Thomas Abraham wrote:
> > +struct dma_pl330_peri pdma0_peri[28] = {
> > + ? ? ? {
> > + ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM0_RX,
> > + ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
> > + ? ? ? }, {
> 
> The client driver specifies the direction of the transfer
> (DMA_TO_DEVICE or DMA_FROM_DEVICE) when requesting for a dma channel.
> So, is the rqtype parameter required in the platform data for the dma
> driver?

That was done initially too with PL080, which has 8 uncommitted DMA
channels.  Peripheral drivers still had to pass the DMA direction.  So
it turned out to be entirely redundant information, so it got killed off,
along with other channel specific configuration which drivers should've
been doing via the slave configuration callback.

Passing lots of information via platform data which should come via
other routes makes dmaengine users fragile - you can't tell whether
they are passing the correct and full information necessary to work with
other dmaengine drivers.  So, the DMA engine platform data should only
contain the absolute _minimum_ of information.

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

* Re: [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
  2011-08-21  8:46         ` Russell King - ARM Linux
@ 2011-08-25  1:13           ` Alim Akhtar
  -1 siblings, 0 replies; 88+ messages in thread
From: Alim Akhtar @ 2011-08-25  1:13 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Jassi Brar, Boojin Kim, Kukjin Kim, Vinod Koul, Mark Brown,
	Grant Likely, linux-samsung-soc, Dan Williams, linux-arm-kernel,
	Linus Walleij, banajit.g

On Sun, Aug 21, 2011 at 2:16 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Tue, Aug 09, 2011 at 09:43:32AM +0530, Alim Akhtar wrote:
>> Exactly, spi_s3c64xx.c (including Sound driver) can not be used with
>> pl080 and pl330 (DMAENGINE drivers) as it is.
>> Recently I was trying to use PL080 DMAENGINE driver, and i was ended
>> up using some #ifdef in the spi driver.
>> something like
>> #ifdef CONFIG_PL080
>> sdd->tx_dmac.bus_id = dmatx_res->name;
>> sdd->rx_dmac.bus_id = dmarx_res->name;
>> #else
>> sdd->tx_dmac.bus_id = dmatx_res->start;
>> sdd->tx_dmac.bus_id = dmatx_res->start;
>> #endif
>>
>> This is because, Pl080 handle the channel as a char *(name) and pl330
>> expect the channel to be enum (a number).
>
> The alternative is that you do as the Primecell drivers do (which was
> designed from the outset to be independent of the specific dmaengine),
> and pass the DMA filter parameters as pointers via platform data.
>
Thanks Russell for your suggestion and pointer.
I will Look into this alternative solution.

Regards,
Alim

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

* [PATCH 12/15] spi/s3c64xx: Add support DMA engine API
@ 2011-08-25  1:13           ` Alim Akhtar
  0 siblings, 0 replies; 88+ messages in thread
From: Alim Akhtar @ 2011-08-25  1:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Aug 21, 2011 at 2:16 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Tue, Aug 09, 2011 at 09:43:32AM +0530, Alim Akhtar wrote:
>> Exactly, spi_s3c64xx.c (including Sound driver) can not be used with
>> pl080 and pl330 (DMAENGINE drivers) as it is.
>> Recently I was trying to use PL080 DMAENGINE driver, and i was ended
>> up using some #ifdef in the spi driver.
>> something like
>> #ifdef CONFIG_PL080
>> sdd->tx_dmac.bus_id = dmatx_res->name;
>> sdd->rx_dmac.bus_id = dmarx_res->name;
>> #else
>> sdd->tx_dmac.bus_id = dmatx_res->start;
>> sdd->tx_dmac.bus_id = dmatx_res->start;
>> #endif
>>
>> This is because, Pl080 handle the channel as a char *(name) and pl330
>> expect the channel to be enum (a number).
>
> The alternative is that you do as the Primecell drivers do (which was
> designed from the outset to be independent of the specific dmaengine),
> and pass the DMA filter parameters as pointers via platform data.
>
Thanks Russell for your suggestion and pointer.
I will Look into this alternative solution.

Regards,
Alim

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

end of thread, other threads:[~2011-08-25  1:13 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-27  5:31 [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA Boojin Kim
2011-07-27  5:31 ` Boojin Kim
2011-07-27  5:31 ` [PATCH 01/15] DMA: PL330: Add support runtime PM for PL330 DMAC Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  6:14   ` [RFC PATCH] DMA: PL330: Update PL330 DMAC to support runtime PM Chanwoo Choi
2011-07-27  6:14     ` Chanwoo Choi
2011-07-27  7:31     ` Jassi Brar
2011-07-27  7:31       ` Jassi Brar
2011-07-27  8:53     ` Russell King - ARM Linux
2011-07-27  8:53       ` Russell King - ARM Linux
2011-07-27  9:43       ` Chanwoo Choi
2011-07-27  9:43         ` Chanwoo Choi
2011-07-27  7:43   ` [PATCH 01/15] DMA: PL330: Add support runtime PM for PL330 DMAC Jassi Brar
2011-07-27  7:43     ` Jassi Brar
2011-07-27  5:31 ` [PATCH 02/15] DMA: PL330: Update PL330 DMA API driver Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 03/15] DMA: PL330: Support DMA_SLAVE_CONFIG command Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 04/15] DMA: PL330: Add DMA_CYCLIC capability Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 05/15] ARM: SAMSUNG: Update to use PL330-DMA driver Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 06/15] ARM: SAMSUNG: Add common DMA operations Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 07/15] ARM: EXYNOS4: Use generic DMA PL330 driver Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-08-15  9:36   ` Thomas Abraham
2011-08-15  9:36     ` Thomas Abraham
2011-08-15 14:15   ` Thomas Abraham
2011-08-15 14:15     ` Thomas Abraham
2011-08-21  8:51     ` Russell King - ARM Linux
2011-08-21  8:51       ` Russell King - ARM Linux
2011-07-27  5:31 ` [PATCH 08/15] ARM: S5PV210: " Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 09/15] ARM: S5PC100: " Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 10/15] ARM: S5P64X0: " Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 11/15] ARM: SAMSUNG: Remove S3C-PL330-DMA driver Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-07-27  5:31 ` [PATCH 12/15] spi/s3c64xx: Add support DMA engine API Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-08-08 17:47   ` Jassi Brar
2011-08-08 17:47     ` Jassi Brar
2011-08-08 17:55     ` Heiko Stübner
2011-08-08 17:55       ` Heiko Stübner
2011-08-08 18:16       ` Jassi Brar
2011-08-08 18:16         ` Jassi Brar
2011-08-08 18:26         ` Heiko Stübner
2011-08-08 18:26           ` Heiko Stübner
2011-08-09  4:13     ` Alim Akhtar
2011-08-09  4:13       ` Alim Akhtar
2011-08-19 10:30       ` Alim Akhtar
2011-08-19 10:30         ` Alim Akhtar
2011-08-21  8:46       ` Russell King - ARM Linux
2011-08-21  8:46         ` Russell King - ARM Linux
2011-08-25  1:13         ` Alim Akhtar
2011-08-25  1:13           ` Alim Akhtar
2011-08-11  7:42     ` Boojin Kim
2011-08-11  7:42       ` Boojin Kim
2011-07-27  5:31 ` [PATCH 13/15] spi/s3c64xx: Merge dma control code Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-08-08 18:32   ` Jassi Brar
2011-08-08 18:32     ` Jassi Brar
2011-07-27  5:31 ` [PATCH 14/15] ASoC: Samsung: Update DMA interface Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-08-08 19:27   ` Jassi Brar
2011-08-08 19:27     ` Jassi Brar
2011-08-11 10:04     ` Boojin Kim
2011-08-11 10:04       ` Boojin Kim
2011-07-27  5:31 ` [PATCH 15/15] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction Boojin Kim
2011-07-27  5:31   ` Boojin Kim
2011-08-04 16:53 ` [PATCH V5 00/15] To use DMA generic APIs for Samsung DMA Linus Walleij
2011-08-04 16:53   ` Linus Walleij
2011-08-08 16:45   ` Koul, Vinod
2011-08-08 16:45     ` Koul, Vinod
2011-08-11  7:26     ` Kukjin Kim
2011-08-11  7:26       ` Kukjin Kim
2011-08-11 22:27       ` Koul, Vinod
2011-08-11 22:27         ` Koul, Vinod
2011-08-13  4:11         ` Kukjin Kim
2011-08-13  4:11           ` Kukjin Kim
2011-08-16 11:01           ` Koul, Vinod
2011-08-16 11:01             ` Koul, Vinod
2011-08-19  5:24             ` Kukjin Kim
2011-08-19  5:24               ` Kukjin Kim
2011-08-19 13:04               ` Koul, Vinod
2011-08-19 13:04                 ` Koul, Vinod

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.