linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA
@ 2013-06-22 20:42 Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 01/12] dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation Tomasz Figa
                   ` (12 more replies)
  0 siblings, 13 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

This is another version of my patches extending support of amba-pl08x
DMA engine driver to PL080S DMA engine (PL080 modified by Samsung) found
in Samsung S3C64xx SoCs.

Changes since RFC v1:
 - Returned to original way of storing quirks as booleans, as suggested
   by Russell, Linus and Arnd.
 - Added reg_config field to pl08x_phy_chan struct, which stores
   variant-specific address of channel config register, as suggested
   by Russell.
 - Simplified handling of extended maximum transfer size of PL080S
   (no more conditional passing of 0 as length to pl08x_cctl_bits()).
 - Reworked LLI handling in the driver to stop casting arbitrary memory
   to a struct and allow different word count of LLI entry, as suggested
   by Linus.
 - Removed AMBA ID override from S3C64xx PL080 initialization code.
 - Fixed brokenness of Samsung DMA wrapper API, which caused cyclic buffers
   to be queued multiple times when DMA engine is used.
 - Included patch adding clock aliases for DMA engines (depends on
   Common Clock Framework driver for S3C64xx).
 - Fixed several minor stylistic issues.
 
For reference, here is the original description of the series:

One of the biggest roadblocks on the way of S3C64xx to DeviceTree support
is its DMA driver, which is completely platform-specific and provides
private API (s3c-dma), not even saying that its design is completely
against multiplatform-awareness.

The DMA controller present on this SoC series is a custom variant
of ARM PrimeCell PL080 modified by Samsung to add some extra features.
It is mostly compatible with original PL080, except:
 - CH_CONTROL2 register is added between CH_CONTROL and CH_CONFIG,
 - offset of CH_CONFIG register is different,
 - transfer size field is moved from CH_CONTROL to CH_CONTROL2,
 - transfer size field is extended to 24 bits, allowing much bigger
     single transfer,
 - LLI consists of one more word, to account for CH_CONTROL2 register.

Since all the rest is fully compatible with standard PL080 there is no
point in having separate driver just for this single variant, so I decided
to look into adding support for it to the amba-pl08x driver.

There was already some attempt to achieve this before, but this was before
Russel's big rework of the driver to use virtual channels, making the old
patches being not much of use.

This RFC series is a proof of concept that I managed to make during last
days of hacking. Except one patch adding clkdev lookup to clock driver
(which is being replaced with a CCF-compliant driver ATM), this is enough
to get memcpy and slave transfers to work on S3C64xx.

I have tested this on Mini6410 and SMDK6410 boards using dmatest for
memcpy and Samsung I2S with madplay/aplay for slave transfers.
Unfortunately I do not have access to other platforms with PL08x so
I could not test for any regressions introduced on them.

Credits for two patches go to Alban Bedel, who made a series fixing this
driver to make it usable with audio drivers. I rebased his patches on top
of mine and corrected coding style a bit.

OK, that's all. Any comments are welcome. Feel free to start throwing eggs
and tomatoes if you find this awful, but I won't be upset if I get some
Tested-by or Acked-by as well. ;)

Alban Bedel (2):
  dmaengine: PL08x: Fix reading the byte count in cctl
  dmaengine: PL08x: Add cyclic transfer support

Tomasz Figa (10):
  dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation
  dmaengine: PL08x: Add support for different offset of CONFIG register
  dmaengine: PL08x: Rework LLI handling to be less fragile
  dmaengine: PL08x: Add support for PL080S variant
  dmaengine: PL08x: Add support for different maximum transfer size
  ASoC: Samsung: Do not queue cyclic buffers multiple times
  clk: samsung: s3c64xx: Add aliases for DMA clocks
  spi: s3c64xx: Do not require legacy DMA API in case of S3C64XX
  ASoC: Samsung: Do not require legacy DMA API in case of S3C64XX
  ARM: s3c64xx: Add support for DMA using generic amba-pl08x driver

 arch/arm/Kconfig                         |   1 +
 arch/arm/mach-s3c64xx/Kconfig            |   8 +-
 arch/arm/mach-s3c64xx/Makefile           |   1 +
 arch/arm/mach-s3c64xx/common.h           |   5 +
 arch/arm/mach-s3c64xx/include/mach/dma.h |  65 +++++
 arch/arm/mach-s3c64xx/pl080.c            | 244 ++++++++++++++++++
 arch/arm/plat-samsung/s3c-dma-ops.c      |  13 +-
 drivers/clk/samsung/clk-s3c64xx.c        |   2 +
 drivers/dma/amba-pl08x.c                 | 426 ++++++++++++++++++++++---------
 drivers/spi/Kconfig                      |   2 +-
 include/linux/amba/pl080.h               |   1 +
 sound/soc/samsung/Kconfig                |   2 +-
 sound/soc/samsung/dma.c                  |   7 +
 13 files changed, 651 insertions(+), 126 deletions(-)
 create mode 100644 arch/arm/mach-s3c64xx/pl080.c

-- 
1.8.2.1


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

* [RFC PATCH v2 01/12] dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-25 15:16   ` Vinod Koul
  2013-06-22 20:42 ` [RFC PATCH v2 02/12] dmaengine: PL08x: Add support for different offset of CONFIG register Tomasz Figa
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

Further patch will introduce support for PL080S, which requires some
things to be done conditionally, thus increasing indentation level of
some functions even more.

This patch reduces indentation level of pl08x_getbytes_chan() function
by inverting several conditions and returning from function wherever
possible.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/dma/amba-pl08x.c | 53 ++++++++++++++++++++++++++----------------------
 1 file changed, 29 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 06fe45c..6a12392 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -469,47 +469,52 @@ static inline u32 get_bytes_in_cctl(u32 cctl)
 /* The channel should be paused when calling this */
 static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
 {
+	struct pl08x_lli *llis_va;
 	struct pl08x_phy_chan *ch;
+	dma_addr_t llis_bus;
 	struct pl08x_txd *txd;
-	size_t bytes = 0;
+	size_t bytes;
+	int index;
+	u32 clli;
 
 	ch = plchan->phychan;
 	txd = plchan->at;
 
+	if (!ch || !txd)
+		return 0;
+
 	/*
 	 * Follow the LLIs to get the number of remaining
 	 * bytes in the currently active transaction.
 	 */
-	if (ch && txd) {
-		u32 clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
+	clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
 
-		/* First get the remaining bytes in the active transfer */
-		bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
+	/* First get the remaining bytes in the active transfer */
+	bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
 
-		if (clli) {
-			struct pl08x_lli *llis_va = txd->llis_va;
-			dma_addr_t llis_bus = txd->llis_bus;
-			int index;
+	if (!clli)
+		return bytes;
 
-			BUG_ON(clli < llis_bus || clli >= llis_bus +
+	llis_va = txd->llis_va;
+	llis_bus = txd->llis_bus;
+
+	BUG_ON(clli < llis_bus || clli >= llis_bus +
 				sizeof(struct pl08x_lli) * MAX_NUM_TSFR_LLIS);
 
-			/*
-			 * Locate the next LLI - as this is an array,
-			 * it's simple maths to find.
-			 */
-			index = (clli - llis_bus) / sizeof(struct pl08x_lli);
+	/*
+	 * Locate the next LLI - as this is an array,
+	 * it's simple maths to find.
+	 */
+	index = (clli - llis_bus) / sizeof(struct pl08x_lli);
 
-			for (; index < MAX_NUM_TSFR_LLIS; index++) {
-				bytes += get_bytes_in_cctl(llis_va[index].cctl);
+	for (; index < MAX_NUM_TSFR_LLIS; index++) {
+		bytes += get_bytes_in_cctl(llis_va[index].cctl);
 
-				/*
-				 * A LLI pointer of 0 terminates the LLI list
-				 */
-				if (!llis_va[index].lli)
-					break;
-			}
-		}
+		/*
+		 * A LLI pointer of 0 terminates the LLI list
+		 */
+		if (!llis_va[index].lli)
+			break;
 	}
 
 	return bytes;
-- 
1.8.2.1


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

* [RFC PATCH v2 02/12] dmaengine: PL08x: Add support for different offset of CONFIG register
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 01/12] dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-25 15:34   ` Vinod Koul
  2013-06-22 20:42 ` [RFC PATCH v2 03/12] dmaengine: PL08x: Rework LLI handling to be less fragile Tomasz Figa
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

Some variants of PL08x (namely PL080S, found in Samsung S3C64xx SoCs)
have CONFIG register at different offset. This patch makes the driver
use offset from vendor data struct.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/dma/amba-pl08x.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 6a12392..2538e05 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -102,6 +102,7 @@ struct pl08x_driver_data;
  *	missing
  */
 struct vendor_data {
+	u8 config_offset;
 	u8 channels;
 	bool dualmaster;
 	bool nomadik;
@@ -145,6 +146,7 @@ struct pl08x_bus_data {
 struct pl08x_phy_chan {
 	unsigned int id;
 	void __iomem *base;
+	void __iomem *reg_config;
 	spinlock_t lock;
 	struct pl08x_dma_chan *serving;
 	bool locked;
@@ -334,7 +336,7 @@ static int pl08x_phy_channel_busy(struct pl08x_phy_chan *ch)
 {
 	unsigned int val;
 
-	val = readl(ch->base + PL080_CH_CONFIG);
+	val = readl(ch->reg_config);
 	return val & PL080_CONFIG_ACTIVE;
 }
 
@@ -373,7 +375,7 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan)
 	writel(lli->dst, phychan->base + PL080_CH_DST_ADDR);
 	writel(lli->lli, phychan->base + PL080_CH_LLI);
 	writel(lli->cctl, phychan->base + PL080_CH_CONTROL);
-	writel(txd->ccfg, phychan->base + PL080_CH_CONFIG);
+	writel(txd->ccfg, phychan->reg_config);
 
 	/* Enable the DMA channel */
 	/* Do not access config register until channel shows as disabled */
@@ -381,11 +383,11 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan)
 		cpu_relax();
 
 	/* Do not access config register until channel shows as inactive */
-	val = readl(phychan->base + PL080_CH_CONFIG);
+	val = readl(phychan->reg_config);
 	while ((val & PL080_CONFIG_ACTIVE) || (val & PL080_CONFIG_ENABLE))
-		val = readl(phychan->base + PL080_CH_CONFIG);
+		val = readl(phychan->reg_config);
 
-	writel(val | PL080_CONFIG_ENABLE, phychan->base + PL080_CH_CONFIG);
+	writel(val | PL080_CONFIG_ENABLE, phychan->reg_config);
 }
 
 /*
@@ -404,9 +406,9 @@ static void pl08x_pause_phy_chan(struct pl08x_phy_chan *ch)
 	int timeout;
 
 	/* Set the HALT bit and wait for the FIFO to drain */
-	val = readl(ch->base + PL080_CH_CONFIG);
+	val = readl(ch->reg_config);
 	val |= PL080_CONFIG_HALT;
-	writel(val, ch->base + PL080_CH_CONFIG);
+	writel(val, ch->reg_config);
 
 	/* Wait for channel inactive */
 	for (timeout = 1000; timeout; timeout--) {
@@ -423,9 +425,9 @@ static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch)
 	u32 val;
 
 	/* Clear the HALT bit */
-	val = readl(ch->base + PL080_CH_CONFIG);
+	val = readl(ch->reg_config);
 	val &= ~PL080_CONFIG_HALT;
-	writel(val, ch->base + PL080_CH_CONFIG);
+	writel(val, ch->reg_config);
 }
 
 /*
@@ -437,12 +439,12 @@ static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch)
 static void pl08x_terminate_phy_chan(struct pl08x_driver_data *pl08x,
 	struct pl08x_phy_chan *ch)
 {
-	u32 val = readl(ch->base + PL080_CH_CONFIG);
+	u32 val = readl(ch->reg_config);
 
 	val &= ~(PL080_CONFIG_ENABLE | PL080_CONFIG_ERR_IRQ_MASK |
 	         PL080_CONFIG_TC_IRQ_MASK);
 
-	writel(val, ch->base + PL080_CH_CONFIG);
+	writel(val, ch->reg_config);
 
 	writel(1 << ch->id, pl08x->base + PL080_ERR_CLEAR);
 	writel(1 << ch->id, pl08x->base + PL080_TC_CLEAR);
@@ -1952,6 +1954,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 
 		ch->id = i;
 		ch->base = pl08x->base + PL080_Cx_BASE(i);
+		ch->reg_config = ch->base + vd->config_offset;
 		spin_lock_init(&ch->lock);
 
 		/*
@@ -1962,7 +1965,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 		if (vd->nomadik) {
 			u32 val;
 
-			val = readl(ch->base + PL080_CH_CONFIG);
+			val = readl(ch->reg_config);
 			if (val & (PL080N_CONFIG_ITPROT | PL080N_CONFIG_SECPROT)) {
 				dev_info(&adev->dev, "physical channel %d reserved for secure access only\n", i);
 				ch->locked = true;
@@ -2043,17 +2046,20 @@ out_no_pl08x:
 
 /* PL080 has 8 channels and the PL080 have just 2 */
 static struct vendor_data vendor_pl080 = {
+	.config_offset = PL080_CH_CONFIG,
 	.channels = 8,
 	.dualmaster = true,
 };
 
 static struct vendor_data vendor_nomadik = {
+	.config_offset = PL080_CH_CONFIG,
 	.channels = 8,
 	.dualmaster = true,
 	.nomadik = true,
 };
 
 static struct vendor_data vendor_pl081 = {
+	.config_offset = PL080_CH_CONFIG,
 	.channels = 2,
 	.dualmaster = false,
 };
-- 
1.8.2.1


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

* [RFC PATCH v2 03/12] dmaengine: PL08x: Rework LLI handling to be less fragile
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 01/12] dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 02/12] dmaengine: PL08x: Add support for different offset of CONFIG register Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 04/12] dmaengine: PL08x: Add support for PL080S variant Tomasz Figa
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

Currently memory allocated for LLIs is casted to an array of structs,
which is fragile and also limits the driver to a single, predefined LLI
layout, while there are some variants of PL08x, which have more fields
in LLI (namely PL080S with its extra CCTL2).

This patch makes LLIs a sequence of 32-bit words, which is just filled
with appropriate values in appropriate order and padded with required
amount of dummy words (currently zero, but PL080S will make better use
of this).

Suggested-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/dma/amba-pl08x.c | 149 ++++++++++++++++++++++++++---------------------
 1 file changed, 83 insertions(+), 66 deletions(-)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 2538e05..50d2f77 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -90,6 +90,15 @@
 
 #define DRIVER_NAME	"pl08xdmac"
 
+enum {
+	PL080_LLI_SRC,
+	PL080_LLI_DST,
+	PL080_LLI_LLI,
+	PL080_LLI_CCTL,
+
+	PL080_LLI_WORDS
+};
+
 static struct amba_driver pl08x_amba_driver;
 struct pl08x_driver_data;
 
@@ -108,19 +117,6 @@ struct vendor_data {
 	bool nomadik;
 };
 
-/*
- * PL08X private data structures
- * An LLI struct - see PL08x TRM.  Note that next uses bit[0] as a bus bit,
- * start & end do not - their bus bit info is in cctl.  Also note that these
- * are fixed 32-bit quantities.
- */
-struct pl08x_lli {
-	u32 src;
-	u32 dst;
-	u32 lli;
-	u32 cctl;
-};
-
 /**
  * struct pl08x_bus_data - information of source or destination
  * busses for a transfer
@@ -181,7 +177,7 @@ struct pl08x_txd {
 	struct virt_dma_desc vd;
 	struct list_head dsg_list;
 	dma_addr_t llis_bus;
-	struct pl08x_lli *llis_va;
+	u32 *llis_va;
 	/* Default cctl value for LLIs */
 	u32 cctl;
 	/*
@@ -265,17 +261,18 @@ struct pl08x_driver_data {
 	struct dma_pool *pool;
 	u8 lli_buses;
 	u8 mem_buses;
+	u8 lli_words;
 };
 
 /*
  * PL08X specific defines
  */
 
-/* Size (bytes) of each LLI buffer allocated for one transfer */
-# define PL08X_LLI_TSFR_SIZE	0x2000
-
-/* Maximum times we call dma_pool_alloc on this pool without freeing */
-#define MAX_NUM_TSFR_LLIS	(PL08X_LLI_TSFR_SIZE/sizeof(struct pl08x_lli))
+/*
+ * Number of LLIs in each LLI buffer allocated for one transfer
+ * (maximum times we call dma_pool_alloc on this pool without freeing)
+ */
+#define MAX_NUM_TSFR_LLIS	512
 #define PL08X_ALIGN		8
 
 static inline struct pl08x_dma_chan *to_pl08x_chan(struct dma_chan *chan)
@@ -340,6 +337,23 @@ static int pl08x_phy_channel_busy(struct pl08x_phy_chan *ch)
 	return val & PL080_CONFIG_ACTIVE;
 }
 
+static void pl08x_write_lli(struct pl08x_driver_data *pl08x,
+		struct pl08x_phy_chan *phychan, const u32 *lli, u32 ccfg)
+{
+	dev_vdbg(&pl08x->adev->dev,
+		"WRITE channel %d: csrc=0x%08x, cdst=0x%08x, "
+		"clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n",
+		phychan->id, lli[PL080_LLI_SRC], lli[PL080_LLI_DST],
+		lli[PL080_LLI_LLI], lli[PL080_LLI_CCTL], ccfg);
+
+	writel(lli[PL080_LLI_SRC], phychan->base + PL080_CH_SRC_ADDR);
+	writel(lli[PL080_LLI_DST], phychan->base + PL080_CH_DST_ADDR);
+	writel(lli[PL080_LLI_LLI], phychan->base + PL080_CH_LLI);
+	writel(lli[PL080_LLI_CCTL], phychan->base + PL080_CH_CONTROL);
+
+	writel(ccfg, phychan->reg_config);
+}
+
 /*
  * Set the initial DMA register values i.e. those for the first LLI
  * The next LLI pointer and the configuration interrupt bit have
@@ -352,7 +366,6 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan)
 	struct pl08x_phy_chan *phychan = plchan->phychan;
 	struct virt_dma_desc *vd = vchan_next_desc(&plchan->vc);
 	struct pl08x_txd *txd = to_pl08x_txd(&vd->tx);
-	struct pl08x_lli *lli;
 	u32 val;
 
 	list_del(&txd->vd.node);
@@ -363,19 +376,7 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan)
 	while (pl08x_phy_channel_busy(phychan))
 		cpu_relax();
 
-	lli = &txd->llis_va[0];
-
-	dev_vdbg(&pl08x->adev->dev,
-		"WRITE channel %d: csrc=0x%08x, cdst=0x%08x, "
-		"clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n",
-		phychan->id, lli->src, lli->dst, lli->lli, lli->cctl,
-		txd->ccfg);
-
-	writel(lli->src, phychan->base + PL080_CH_SRC_ADDR);
-	writel(lli->dst, phychan->base + PL080_CH_DST_ADDR);
-	writel(lli->lli, phychan->base + PL080_CH_LLI);
-	writel(lli->cctl, phychan->base + PL080_CH_CONTROL);
-	writel(txd->ccfg, phychan->reg_config);
+	pl08x_write_lli(pl08x, phychan, &txd->llis_va[0], txd->ccfg);
 
 	/* Enable the DMA channel */
 	/* Do not access config register until channel shows as disabled */
@@ -471,12 +472,13 @@ static inline u32 get_bytes_in_cctl(u32 cctl)
 /* The channel should be paused when calling this */
 static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
 {
-	struct pl08x_lli *llis_va;
+	struct pl08x_driver_data *pl08x = plchan->host;
+	const u32 *llis_va, *llis_va_limit;
 	struct pl08x_phy_chan *ch;
 	dma_addr_t llis_bus;
 	struct pl08x_txd *txd;
+	u32 llis_max_words;
 	size_t bytes;
-	int index;
 	u32 clli;
 
 	ch = plchan->phychan;
@@ -500,22 +502,25 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
 	llis_va = txd->llis_va;
 	llis_bus = txd->llis_bus;
 
+	llis_max_words = pl08x->lli_words * MAX_NUM_TSFR_LLIS;
 	BUG_ON(clli < llis_bus || clli >= llis_bus +
-				sizeof(struct pl08x_lli) * MAX_NUM_TSFR_LLIS);
+						sizeof(u32) * llis_max_words);
 
 	/*
 	 * Locate the next LLI - as this is an array,
 	 * it's simple maths to find.
 	 */
-	index = (clli - llis_bus) / sizeof(struct pl08x_lli);
+	llis_va += (clli - llis_bus) / sizeof(u32);
 
-	for (; index < MAX_NUM_TSFR_LLIS; index++) {
-		bytes += get_bytes_in_cctl(llis_va[index].cctl);
+	llis_va_limit = llis_va + llis_max_words;
+
+	for (; llis_va < llis_va_limit; llis_va += pl08x->lli_words) {
+		bytes += get_bytes_in_cctl(llis_va[PL080_LLI_CCTL]);
 
 		/*
 		 * A LLI pointer of 0 terminates the LLI list
 		 */
-		if (!llis_va[index].lli)
+		if (!llis_va[PL080_LLI_LLI])
 			break;
 	}
 
@@ -771,20 +776,24 @@ static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
 /*
  * Fills in one LLI for a certain transfer descriptor and advance the counter
  */
-static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
-	int num_llis, int len, u32 cctl)
+static void pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
+				    struct pl08x_lli_build_data *bd,
+				    int num_llis, int len, u32 cctl)
 {
-	struct pl08x_lli *llis_va = bd->txd->llis_va;
+	u32 offset = num_llis * pl08x->lli_words;
+	u32 *llis_va = bd->txd->llis_va + offset;
 	dma_addr_t llis_bus = bd->txd->llis_bus;
 
 	BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS);
 
-	llis_va[num_llis].cctl = cctl;
-	llis_va[num_llis].src = bd->srcbus.addr;
-	llis_va[num_llis].dst = bd->dstbus.addr;
-	llis_va[num_llis].lli = llis_bus + (num_llis + 1) *
-		sizeof(struct pl08x_lli);
-	llis_va[num_llis].lli |= bd->lli_bus;
+	/* Advance the offset to next LLI. */
+	offset += pl08x->lli_words;
+
+	llis_va[PL080_LLI_SRC] = bd->srcbus.addr;
+	llis_va[PL080_LLI_DST] = bd->dstbus.addr;
+	llis_va[PL080_LLI_LLI] = (llis_bus + sizeof(u32) * offset);
+	llis_va[PL080_LLI_LLI] |= bd->lli_bus;
+	llis_va[PL080_LLI_CCTL] = cctl;
 
 	if (cctl & PL080_CONTROL_SRC_INCR)
 		bd->srcbus.addr += len;
@@ -796,11 +805,12 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
 	bd->remainder -= len;
 }
 
-static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd,
-		u32 *cctl, u32 len, int num_llis, size_t *total_bytes)
+static inline void prep_byte_width_lli(struct pl08x_driver_data *pl08x,
+			struct pl08x_lli_build_data *bd, u32 *cctl, u32 len,
+			int num_llis, size_t *total_bytes)
 {
 	*cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
-	pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl);
+	pl08x_fill_lli_for_desc(pl08x, bd, num_llis, len, *cctl);
 	(*total_bytes) += len;
 }
 
@@ -817,7 +827,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 	int num_llis = 0;
 	u32 cctl, early_bytes = 0;
 	size_t max_bytes_per_lli, total_bytes;
-	struct pl08x_lli *llis_va;
+	u32 *llis_va, *last_lli;
 	struct pl08x_sg *dsg;
 
 	txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus);
@@ -904,7 +914,8 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 
 			cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
 					bd.dstbus.buswidth, 0);
-			pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl);
+			pl08x_fill_lli_for_desc(pl08x, &bd, num_llis++,
+					0, cctl);
 			break;
 		}
 
@@ -926,8 +937,8 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 			dev_vdbg(&pl08x->adev->dev,
 				"%s byte width LLIs (remain 0x%08x)\n",
 				__func__, bd.remainder);
-			prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++,
-				&total_bytes);
+			prep_byte_width_lli(pl08x, &bd, &cctl, early_bytes,
+				num_llis++, &total_bytes);
 		}
 
 		if (bd.remainder) {
@@ -983,7 +994,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 
 				cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
 					bd.dstbus.buswidth, tsize);
-				pl08x_fill_lli_for_desc(&bd, num_llis++,
+				pl08x_fill_lli_for_desc(pl08x, &bd, num_llis++,
 						lli_len, cctl);
 				total_bytes += lli_len;
 			}
@@ -995,8 +1006,8 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 				dev_vdbg(&pl08x->adev->dev,
 					"%s align with boundary, send odd bytes (remain %zu)\n",
 					__func__, bd.remainder);
-				prep_byte_width_lli(&bd, &cctl, bd.remainder,
-						num_llis++, &total_bytes);
+				prep_byte_width_lli(pl08x, &bd, &cctl,
+					bd.remainder, num_llis++, &total_bytes);
 			}
 		}
 
@@ -1010,16 +1021,17 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 		if (num_llis >= MAX_NUM_TSFR_LLIS) {
 			dev_err(&pl08x->adev->dev,
 				"%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
-				__func__, (u32) MAX_NUM_TSFR_LLIS);
+				__func__, MAX_NUM_TSFR_LLIS);
 			return 0;
 		}
 	}
 
 	llis_va = txd->llis_va;
+	last_lli = llis_va + (num_llis - 1) * pl08x->lli_words;
 	/* The final LLI terminates the LLI. */
-	llis_va[num_llis - 1].lli = 0;
+	last_lli[PL080_LLI_LLI] = 0;
 	/* The final LLI element shall also fire an interrupt. */
-	llis_va[num_llis - 1].cctl |= PL080_CONTROL_TC_IRQ_EN;
+	last_lli[PL080_LLI_CCTL] |= PL080_CONTROL_TC_IRQ_EN;
 
 #ifdef VERBOSE_DEBUG
 	{
@@ -1031,9 +1043,10 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 		for (i = 0; i < num_llis; i++) {
 			dev_vdbg(&pl08x->adev->dev,
 				 "%3d @%p: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-				 i, &llis_va[i], llis_va[i].src,
-				 llis_va[i].dst, llis_va[i].lli, llis_va[i].cctl
-				);
+				 i, llis_va, llis_va[PL080_LLI_SRC],
+				 llis_va[PL080_LLI_DST], llis_va[PL080_LLI_LLI],
+				 llis_va[PL080_LLI_CCTL]);
+			llis_va += pl08x->lli_words;
 		}
 	}
 #endif
@@ -1853,6 +1866,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct pl08x_driver_data *pl08x;
 	const struct vendor_data *vd = id->data;
+	u32 tsfr_size;
 	int ret = 0;
 	int i;
 
@@ -1909,9 +1923,12 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 		pl08x->mem_buses = pl08x->pd->mem_buses;
 	}
 
+	pl08x->lli_words = PL080_LLI_WORDS;
+	tsfr_size = MAX_NUM_TSFR_LLIS * pl08x->lli_words * sizeof(u32);
+
 	/* A DMA memory pool for LLIs, align on 1-byte boundary */
 	pl08x->pool = dma_pool_create(DRIVER_NAME, &pl08x->adev->dev,
-			PL08X_LLI_TSFR_SIZE, PL08X_ALIGN, 0);
+						tsfr_size, PL08X_ALIGN, 0);
 	if (!pl08x->pool) {
 		ret = -ENOMEM;
 		goto out_no_lli_pool;
-- 
1.8.2.1


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

* [RFC PATCH v2 04/12] dmaengine: PL08x: Add support for PL080S variant
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (2 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 03/12] dmaengine: PL08x: Rework LLI handling to be less fragile Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 05/12] dmaengine: PL08x: Add support for different maximum transfer size Tomasz Figa
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

PL080S is a modified version of PL080 that can be found on Samsung SoCs,
such as S3C6400 and S3C6410.

It has different offset of CONFIG register, separate CONTROL1 register
that holds transfer size and larger maximum transfer size.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/dma/amba-pl08x.c   | 73 +++++++++++++++++++++++++++++++++++++++++-----
 include/linux/amba/pl080.h |  1 +
 2 files changed, 66 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 50d2f77..103bc1a 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -96,7 +96,11 @@ enum {
 	PL080_LLI_LLI,
 	PL080_LLI_CCTL,
 
-	PL080_LLI_WORDS
+	PL080_LLI_WORDS,
+
+	PL080S_LLI_CCTL2 = PL080_LLI_WORDS,
+
+	PL080S_LLI_WORDS = 8
 };
 
 static struct amba_driver pl08x_amba_driver;
@@ -109,14 +113,18 @@ struct pl08x_driver_data;
  * @nomadik: whether the channels have Nomadik security extension bits
  *	that need to be checked for permission before use and some registers are
  *	missing
+ * @pl080s: whether this version is a PL080S, which has separate register and
+ *	LLI word for transfer size.
  */
 struct vendor_data {
 	u8 config_offset;
 	u8 channels;
 	bool dualmaster;
 	bool nomadik;
+	bool pl080s;
 };
 
+	u32 cctl1;
 /**
  * struct pl08x_bus_data - information of source or destination
  * busses for a transfer
@@ -351,6 +359,10 @@ static void pl08x_write_lli(struct pl08x_driver_data *pl08x,
 	writel(lli[PL080_LLI_LLI], phychan->base + PL080_CH_LLI);
 	writel(lli[PL080_LLI_CCTL], phychan->base + PL080_CH_CONTROL);
 
+	if (pl08x->vd->pl080s)
+		writel(lli[PL080S_LLI_CCTL2],
+				phychan->base + PL080S_CH_CONTROL2);
+
 	writel(ccfg, phychan->reg_config);
 }
 
@@ -469,6 +481,24 @@ static inline u32 get_bytes_in_cctl(u32 cctl)
 	return bytes;
 }
 
+static inline u32 get_bytes_in_cctl_pl080s(u32 cctl, u32 cctl1)
+{
+	/* The source width defines the number of bytes */
+	u32 bytes = cctl1 & PL080S_CONTROL_TRANSFER_SIZE_MASK;
+
+	switch (cctl >> PL080_CONTROL_SWIDTH_SHIFT) {
+	case PL080_WIDTH_8BIT:
+		break;
+	case PL080_WIDTH_16BIT:
+		bytes *= 2;
+		break;
+	case PL080_WIDTH_32BIT:
+		bytes *= 4;
+		break;
+	}
+	return bytes;
+}
+
 /* The channel should be paused when calling this */
 static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
 {
@@ -494,7 +524,12 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
 	clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
 
 	/* First get the remaining bytes in the active transfer */
-	bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
+	if (pl08x->vd->pl080s)
+		bytes = get_bytes_in_cctl_pl080s(
+				readl(ch->base + PL080_CH_CONTROL),
+				readl(ch->base + PL080S_CH_CONTROL2));
+	else
+		bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
 
 	if (!clli)
 		return bytes;
@@ -515,7 +550,12 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
 	llis_va_limit = llis_va + llis_max_words;
 
 	for (; llis_va < llis_va_limit; llis_va += pl08x->lli_words) {
-		bytes += get_bytes_in_cctl(llis_va[PL080_LLI_CCTL]);
+		if (pl08x->vd->pl080s)
+			bytes += get_bytes_in_cctl_pl080s(
+						llis_va[PL080_LLI_CCTL],
+						llis_va[PL080S_LLI_CCTL2]);
+		else
+			bytes += get_bytes_in_cctl(llis_va[PL080_LLI_CCTL]);
 
 		/*
 		 * A LLI pointer of 0 terminates the LLI list
@@ -778,7 +818,7 @@ static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
  */
 static void pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
 				    struct pl08x_lli_build_data *bd,
-				    int num_llis, int len, u32 cctl)
+				    int num_llis, int len, u32 cctl, u32 cctl2)
 {
 	u32 offset = num_llis * pl08x->lli_words;
 	u32 *llis_va = bd->txd->llis_va + offset;
@@ -794,6 +834,8 @@ static void pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
 	llis_va[PL080_LLI_LLI] = (llis_bus + sizeof(u32) * offset);
 	llis_va[PL080_LLI_LLI] |= bd->lli_bus;
 	llis_va[PL080_LLI_CCTL] = cctl;
+	if (pl08x->vd->pl080s)
+		llis_va[PL080S_LLI_CCTL2] = cctl2;
 
 	if (cctl & PL080_CONTROL_SRC_INCR)
 		bd->srcbus.addr += len;
@@ -810,7 +852,7 @@ static inline void prep_byte_width_lli(struct pl08x_driver_data *pl08x,
 			int num_llis, size_t *total_bytes)
 {
 	*cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
-	pl08x_fill_lli_for_desc(pl08x, bd, num_llis, len, *cctl);
+	pl08x_fill_lli_for_desc(pl08x, bd, num_llis, len, *cctl, len);
 	(*total_bytes) += len;
 }
 
@@ -915,7 +957,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 			cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
 					bd.dstbus.buswidth, 0);
 			pl08x_fill_lli_for_desc(pl08x, &bd, num_llis++,
-					0, cctl);
+					0, cctl, 0);
 			break;
 		}
 
@@ -995,7 +1037,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 				cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
 					bd.dstbus.buswidth, tsize);
 				pl08x_fill_lli_for_desc(pl08x, &bd, num_llis++,
-						lli_len, cctl);
+						lli_len, cctl, tsize);
 				total_bytes += lli_len;
 			}
 
@@ -1923,7 +1965,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 		pl08x->mem_buses = pl08x->pd->mem_buses;
 	}
 
-	pl08x->lli_words = PL080_LLI_WORDS;
+	if (vd->pl080s)
+		pl08x->lli_words = PL080S_LLI_WORDS;
+	else
+		pl08x->lli_words = PL080_LLI_WORDS;
 	tsfr_size = MAX_NUM_TSFR_LLIS * pl08x->lli_words * sizeof(u32);
 
 	/* A DMA memory pool for LLIs, align on 1-byte boundary */
@@ -2075,6 +2120,12 @@ static struct vendor_data vendor_nomadik = {
 	.nomadik = true,
 };
 
+static struct vendor_data vendor_pl080s = {
+	.config_offset = PL080S_CH_CONFIG,
+	.channels = 8,
+	.pl080s = true,
+};
+
 static struct vendor_data vendor_pl081 = {
 	.config_offset = PL080_CH_CONFIG,
 	.channels = 2,
@@ -2082,6 +2133,12 @@ static struct vendor_data vendor_pl081 = {
 };
 
 static struct amba_id pl08x_ids[] = {
+	/* Samsung PL080S variant */
+	{
+		.id	= 0x0a141080,
+		.mask	= 0xffffffff,
+		.data	= &vendor_pl080s,
+	},
 	/* PL080 */
 	{
 		.id	= 0x00041080,
diff --git a/include/linux/amba/pl080.h b/include/linux/amba/pl080.h
index 3e7b62f..ef36a0a 100644
--- a/include/linux/amba/pl080.h
+++ b/include/linux/amba/pl080.h
@@ -87,6 +87,7 @@
 #define PL080_CONTROL_SB_SIZE_MASK		(0x7 << 12)
 #define PL080_CONTROL_SB_SIZE_SHIFT		(12)
 #define PL080_CONTROL_TRANSFER_SIZE_MASK	(0xfff << 0)
+#define PL080S_CONTROL_TRANSFER_SIZE_MASK	(0xffffff << 0)
 #define PL080_CONTROL_TRANSFER_SIZE_SHIFT	(0)
 
 #define PL080_BSIZE_1				(0x0)
-- 
1.8.2.1


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

* [RFC PATCH v2 05/12] dmaengine: PL08x: Add support for different maximum transfer size
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (3 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 04/12] dmaengine: PL08x: Add support for PL080S variant Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-25 16:10   ` Vinod Koul
  2013-06-22 20:42 ` [RFC PATCH v2 06/12] dmaengine: PL08x: Fix reading the byte count in cctl Tomasz Figa
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

PL080S has separate register to store transfer size in, allowing single
transfer to be much larger than in standard PL080.

This patch makes the amba-pl08x driver aware of this and removes writing
transfer size to reserved bits of CH_CONTROL register on PL080S, which
was not a problem witn transfer sizes fitting the original bitfield
of PL080, but now would overwrite other fields.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/dma/amba-pl08x.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 103bc1a..89b8120 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -122,6 +122,7 @@ struct vendor_data {
 	bool dualmaster;
 	bool nomadik;
 	bool pl080s;
+	u32 max_transfer_size;
 };
 
 	u32 cctl1;
@@ -772,6 +773,7 @@ static inline u32 pl08x_cctl_bits(u32 cctl, u8 srcwidth, u8 dstwidth,
 		break;
 	}
 
+	tsize &= PL080_CONTROL_TRANSFER_SIZE_MASK;
 	retbits |= tsize << PL080_CONTROL_TRANSFER_SIZE_SHIFT;
 	return retbits;
 }
@@ -1001,7 +1003,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 			 * MIN(buswidths)
 			 */
 			max_bytes_per_lli = bd.srcbus.buswidth *
-				PL080_CONTROL_TRANSFER_SIZE_MASK;
+						pl08x->vd->max_transfer_size;
 			dev_vdbg(&pl08x->adev->dev,
 				"%s max bytes per lli = %zu\n",
 				__func__, max_bytes_per_lli);
@@ -2111,6 +2113,7 @@ static struct vendor_data vendor_pl080 = {
 	.config_offset = PL080_CH_CONFIG,
 	.channels = 8,
 	.dualmaster = true,
+	.max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
 };
 
 static struct vendor_data vendor_nomadik = {
@@ -2118,18 +2121,21 @@ static struct vendor_data vendor_nomadik = {
 	.channels = 8,
 	.dualmaster = true,
 	.nomadik = true,
+	.max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
 };
 
 static struct vendor_data vendor_pl080s = {
 	.config_offset = PL080S_CH_CONFIG,
 	.channels = 8,
 	.pl080s = true,
+	.max_transfer_size = PL080S_CONTROL_TRANSFER_SIZE_MASK,
 };
 
 static struct vendor_data vendor_pl081 = {
 	.config_offset = PL080_CH_CONFIG,
 	.channels = 2,
 	.dualmaster = false,
+	.max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
 };
 
 static struct amba_id pl08x_ids[] = {
-- 
1.8.2.1


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

* [RFC PATCH v2 06/12] dmaengine: PL08x: Fix reading the byte count in cctl
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (4 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 05/12] dmaengine: PL08x: Add support for different maximum transfer size Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 07/12] dmaengine: PL08x: Add cyclic transfer support Tomasz Figa
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

From: Alban Bedel <alban.bedel@avionic-design.de>

There are more fields than just SWIDTH in CH_CONTROL register, so read
register value must be masked in addition to shifting.

Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/dma/amba-pl08x.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 89b8120..1eeb911 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -469,6 +469,8 @@ static inline u32 get_bytes_in_cctl(u32 cctl)
 	/* The source width defines the number of bytes */
 	u32 bytes = cctl & PL080_CONTROL_TRANSFER_SIZE_MASK;
 
+	cctl &= PL080_CONTROL_SWIDTH_MASK;
+
 	switch (cctl >> PL080_CONTROL_SWIDTH_SHIFT) {
 	case PL080_WIDTH_8BIT:
 		break;
@@ -487,6 +489,8 @@ static inline u32 get_bytes_in_cctl_pl080s(u32 cctl, u32 cctl1)
 	/* The source width defines the number of bytes */
 	u32 bytes = cctl1 & PL080S_CONTROL_TRANSFER_SIZE_MASK;
 
+	cctl &= PL080_CONTROL_SWIDTH_MASK;
+
 	switch (cctl >> PL080_CONTROL_SWIDTH_SHIFT) {
 	case PL080_WIDTH_8BIT:
 		break;
-- 
1.8.2.1


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

* [RFC PATCH v2 07/12] dmaengine: PL08x: Add cyclic transfer support
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (5 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 06/12] dmaengine: PL08x: Fix reading the byte count in cctl Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 08/12] ASoC: Samsung: Do not queue cyclic buffers multiple times Tomasz Figa
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

From: Alban Bedel <alban.bedel@avionic-design.de>

Many audio interface drivers require support of cyclic transfers to work
correctly, for example Samsung ASoC DMA driver. This patch adds support
for cyclic transfers to the amba-pl08x driver.

Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
[tfiga: Rebase and slightly beautify the original patch.]
Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/dma/amba-pl08x.c | 147 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 118 insertions(+), 29 deletions(-)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 1eeb911..a3a86dd 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -181,6 +181,7 @@ struct pl08x_sg {
  * @ccfg: config reg values for current txd
  * @done: this marks completed descriptors, which should not have their
  *   mux released.
+ * @cyclic: indicate cyclic transfers
  */
 struct pl08x_txd {
 	struct virt_dma_desc vd;
@@ -195,6 +196,7 @@ struct pl08x_txd {
 	 */
 	u32 ccfg;
 	bool done;
+	bool cyclic;
 };
 
 /**
@@ -563,9 +565,9 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
 			bytes += get_bytes_in_cctl(llis_va[PL080_LLI_CCTL]);
 
 		/*
-		 * A LLI pointer of 0 terminates the LLI list
+		 * A LLI pointer going backward terminates the LLI list
 		 */
-		if (!llis_va[PL080_LLI_LLI])
+		if (llis_va[PL080_LLI_LLI] <= clli)
 			break;
 	}
 
@@ -1076,10 +1078,16 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
 
 	llis_va = txd->llis_va;
 	last_lli = llis_va + (num_llis - 1) * pl08x->lli_words;
-	/* The final LLI terminates the LLI. */
-	last_lli[PL080_LLI_LLI] = 0;
-	/* The final LLI element shall also fire an interrupt. */
-	last_lli[PL080_LLI_CCTL] |= PL080_CONTROL_TC_IRQ_EN;
+
+	if (txd->cyclic) {
+		/* Link back to the first LLI. */
+		last_lli[PL080_LLI_LLI] = txd->llis_bus | bd.lli_bus;
+	} else {
+		/* The final LLI terminates the LLI. */
+		last_lli[PL080_LLI_LLI] = 0;
+		/* The final LLI element shall also fire an interrupt. */
+		last_lli[PL080_LLI_CCTL] |= PL080_CONTROL_TC_IRQ_EN;
+	}
 
 #ifdef VERBOSE_DEBUG
 	{
@@ -1472,25 +1480,19 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
 	return vchan_tx_prep(&plchan->vc, &txd->vd, flags);
 }
 
-static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
-		struct dma_chan *chan, struct scatterlist *sgl,
-		unsigned int sg_len, enum dma_transfer_direction direction,
-		unsigned long flags, void *context)
+static struct pl08x_txd *pl08x_init_txd(
+		struct dma_chan *chan,
+		enum dma_transfer_direction direction,
+		dma_addr_t *slave_addr)
 {
 	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
 	struct pl08x_driver_data *pl08x = plchan->host;
 	struct pl08x_txd *txd;
-	struct pl08x_sg *dsg;
-	struct scatterlist *sg;
 	enum dma_slave_buswidth addr_width;
-	dma_addr_t slave_addr;
 	int ret, tmp;
 	u8 src_buses, dst_buses;
 	u32 maxburst, cctl;
 
-	dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
-			__func__, sg_dma_len(sgl), plchan->name);
-
 	txd = pl08x_get_txd(plchan);
 	if (!txd) {
 		dev_err(&pl08x->adev->dev, "%s no txd\n", __func__);
@@ -1504,14 +1506,14 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
 	 */
 	if (direction == DMA_MEM_TO_DEV) {
 		cctl = PL080_CONTROL_SRC_INCR;
-		slave_addr = plchan->cfg.dst_addr;
+		*slave_addr = plchan->cfg.dst_addr;
 		addr_width = plchan->cfg.dst_addr_width;
 		maxburst = plchan->cfg.dst_maxburst;
 		src_buses = pl08x->mem_buses;
 		dst_buses = plchan->cd->periph_buses;
 	} else if (direction == DMA_DEV_TO_MEM) {
 		cctl = PL080_CONTROL_DST_INCR;
-		slave_addr = plchan->cfg.src_addr;
+		*slave_addr = plchan->cfg.src_addr;
 		addr_width = plchan->cfg.src_addr_width;
 		maxburst = plchan->cfg.src_maxburst;
 		src_buses = plchan->cd->periph_buses;
@@ -1560,24 +1562,107 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
 	else
 		txd->ccfg |= plchan->signal << PL080_CONFIG_SRC_SEL_SHIFT;
 
+	return txd;
+}
+
+static int pl08x_tx_add_sg(struct pl08x_txd *txd,
+			   enum dma_transfer_direction direction,
+			   dma_addr_t slave_addr,
+			   dma_addr_t buf_addr,
+			   unsigned int len)
+{
+	struct pl08x_sg *dsg;
+
+	dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
+	if (!dsg)
+		return -ENOMEM;
+
+	list_add_tail(&dsg->node, &txd->dsg_list);
+
+	dsg->len = len;
+	if (direction == DMA_MEM_TO_DEV) {
+		dsg->src_addr = buf_addr;
+		dsg->dst_addr = slave_addr;
+	} else {
+		dsg->src_addr = slave_addr;
+		dsg->dst_addr = buf_addr;
+	}
+
+	return 0;
+}
+
+static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
+	struct pl08x_driver_data *pl08x = plchan->host;
+	struct pl08x_txd *txd;
+	struct scatterlist *sg;
+	int ret, tmp;
+	dma_addr_t slave_addr;
+
+	dev_dbg(&pl08x->adev->dev, "%s prepare transaction of %d bytes from %s\n",
+			__func__, sg_dma_len(sgl), plchan->name);
+
+	txd = pl08x_init_txd(chan, direction, &slave_addr);
+	if (!txd)
+		return NULL;
+
 	for_each_sg(sgl, sg, sg_len, tmp) {
-		dsg = kzalloc(sizeof(struct pl08x_sg), GFP_NOWAIT);
-		if (!dsg) {
+		ret = pl08x_tx_add_sg(txd, direction, slave_addr,
+				      sg_dma_address(sg),
+				      sg_dma_len(sg));
+		if (ret) {
 			pl08x_release_mux(plchan);
 			pl08x_free_txd(pl08x, txd);
 			dev_err(&pl08x->adev->dev, "%s no mem for pl080 sg\n",
 					__func__);
 			return NULL;
 		}
-		list_add_tail(&dsg->node, &txd->dsg_list);
+	}
 
-		dsg->len = sg_dma_len(sg);
-		if (direction == DMA_MEM_TO_DEV) {
-			dsg->src_addr = sg_dma_address(sg);
-			dsg->dst_addr = slave_addr;
-		} else {
-			dsg->src_addr = slave_addr;
-			dsg->dst_addr = sg_dma_address(sg);
+	ret = pl08x_fill_llis_for_desc(plchan->host, txd);
+	if (!ret) {
+		pl08x_release_mux(plchan);
+		pl08x_free_txd(pl08x, txd);
+		return NULL;
+	}
+
+	return vchan_tx_prep(&plchan->vc, &txd->vd, flags);
+}
+
+static struct dma_async_tx_descriptor *pl08x_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+		size_t period_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
+	struct pl08x_driver_data *pl08x = plchan->host;
+	struct pl08x_txd *txd;
+	int ret, tmp;
+	dma_addr_t slave_addr;
+
+	dev_dbg(&pl08x->adev->dev,
+		"%s prepare cyclic transaction of %d/%d bytes %s %s\n",
+		__func__, period_len, buf_len,
+		direction == DMA_MEM_TO_DEV ? "to" : "from",
+		plchan->name);
+
+	txd = pl08x_init_txd(chan, direction, &slave_addr);
+	if (!txd)
+		return NULL;
+
+	txd->cyclic = true;
+	txd->cctl |= PL080_CONTROL_TC_IRQ_EN;
+	for (tmp = 0; tmp < buf_len; tmp += period_len) {
+		ret = pl08x_tx_add_sg(txd, direction, slave_addr,
+				      buf_addr + tmp, period_len);
+		if (ret) {
+			pl08x_release_mux(plchan);
+			pl08x_free_txd(pl08x, txd);
+			return NULL;
 		}
 	}
 
@@ -1720,7 +1805,9 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
 
 			spin_lock(&plchan->vc.lock);
 			tx = plchan->at;
-			if (tx) {
+			if (tx && tx->cyclic) {
+				vchan_cyclic_callback(&tx->vd);
+			} else if (tx) {
 				plchan->at = NULL;
 				/*
 				 * This descriptor is done, release its mux
@@ -1942,6 +2029,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 
 	/* Initialize slave engine */
 	dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
+	dma_cap_set(DMA_CYCLIC, pl08x->slave.cap_mask);
 	pl08x->slave.dev = &adev->dev;
 	pl08x->slave.device_alloc_chan_resources = pl08x_alloc_chan_resources;
 	pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources;
@@ -1949,6 +2037,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 	pl08x->slave.device_tx_status = pl08x_dma_tx_status;
 	pl08x->slave.device_issue_pending = pl08x_issue_pending;
 	pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg;
+	pl08x->slave.device_prep_dma_cyclic = pl08x_prep_dma_cyclic;
 	pl08x->slave.device_control = pl08x_control;
 
 	/* Get the platform data */
-- 
1.8.2.1


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

* [RFC PATCH v2 08/12] ASoC: Samsung: Do not queue cyclic buffers multiple times
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (6 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 07/12] dmaengine: PL08x: Add cyclic transfer support Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 09/12] clk: samsung: s3c64xx: Add aliases for DMA clocks Tomasz Figa
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

The legacy S3C-DMA API required every period of a cyclic buffer to be
queued separately. After conversion of Samsung ASoC to Samsung DMA
wrappers somebody made an assumption that the same is needed for DMA
engine API, which is not true.

In effect, Samsung ASoC DMA code was queuing the whole cyclic buffer
multiple times with a shift of one period per iteration, leading to:
  a) severe memory waste - up to 13x times more DMA transfer descriptors
     are allocated than needed,
  b) possible memory corruption, because further cyclic buffers were out
     of the original buffers, due to the offset.

This patch fixes this problem by making the legacy S3C-DMA API use the
same semantics as DMA engine (the whole cyclic buffer is enqueued at
once) and modifying users of Samsung DMA wrappers in cyclic mode to
behave appropriately.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 arch/arm/plat-samsung/s3c-dma-ops.c | 13 +++++++++++--
 sound/soc/samsung/dma.c             |  7 +++++++
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/arm/plat-samsung/s3c-dma-ops.c b/arch/arm/plat-samsung/s3c-dma-ops.c
index 0cc40ae..98b10ba 100644
--- a/arch/arm/plat-samsung/s3c-dma-ops.c
+++ b/arch/arm/plat-samsung/s3c-dma-ops.c
@@ -82,7 +82,8 @@ static int s3c_dma_config(unsigned ch, struct samsung_dma_config *param)
 static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
 {
 	struct cb_data *data;
-	int len = (param->cap == DMA_CYCLIC) ? param->period : param->len;
+	dma_addr_t pos = param->buf;
+	dma_addr_t end = param->buf + param->len;
 
 	list_for_each_entry(data, &dma_list, node)
 		if (data->ch == ch)
@@ -94,7 +95,15 @@ static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
 		data->fp_param = param->fp_param;
 	}
 
-	s3c2410_dma_enqueue(ch, (void *)data, param->buf, len);
+	if (param->cap != DMA_CYCLIC) {
+		s3c2410_dma_enqueue(ch, (void *)data, param->buf, param->len);
+		return 0;
+	}
+
+	while (pos < end) {
+		s3c2410_dma_enqueue(ch, (void *)data, pos, param->period);
+		pos += param->period;
+	}
 
 	return 0;
 }
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 21b7926..6e2b2b4 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -90,6 +90,13 @@ static void dma_enqueue(struct snd_pcm_substream *substream)
 	dma_info.period = prtd->dma_period;
 	dma_info.len = prtd->dma_period*limit;
 
+	if (dma_info.cap == DMA_CYCLIC) {
+		dma_info.buf = pos;
+		prtd->params->ops->prepare(prtd->params->ch, &dma_info);
+		prtd->dma_loaded += limit;
+		return;
+	}
+
 	while (prtd->dma_loaded < limit) {
 		pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
 
-- 
1.8.2.1


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

* [RFC PATCH v2 09/12] clk: samsung: s3c64xx: Add aliases for DMA clocks
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (7 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 08/12] ASoC: Samsung: Do not queue cyclic buffers multiple times Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 10/12] spi: s3c64xx: Do not require legacy DMA API in case of S3C64XX Tomasz Figa
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

The new amba-pl08x driver requires another set of clock aliases, so this
patch adds them.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/clk/samsung/clk-s3c64xx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index 253a972..9fb750c 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -315,6 +315,8 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
 	ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
 	ALIAS(HCLK_DMA1, NULL, "dma1"),
 	ALIAS(HCLK_DMA0, NULL, "dma0"),
+	ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"),
+	ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"),
 	ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
 	ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
 	ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
-- 
1.8.2.1


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

* [RFC PATCH v2 10/12] spi: s3c64xx: Do not require legacy DMA API in case of S3C64XX
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (8 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 09/12] clk: samsung: s3c64xx: Add aliases for DMA clocks Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 11/12] ASoC: Samsung: " Tomasz Figa
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

With support for amba-pl08x driver, on S3C64xx the generic DMA engine
API can be used instead of the private s3c-dma interface.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 drivers/spi/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 89cbbab..241a049 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -366,7 +366,7 @@ config SPI_S3C24XX_FIQ
 config SPI_S3C64XX
 	tristate "Samsung S3C64XX series type SPI"
 	depends on (ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS)
-	select S3C64XX_DMA if ARCH_S3C64XX
+	select S3C64XX_DMA if ARCH_S3C64XX && !S3C64XX_PL080
 	help
 	  SPI driver for Samsung S3C64XX and newer SoCs.
 
-- 
1.8.2.1


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

* [RFC PATCH v2 11/12] ASoC: Samsung: Do not require legacy DMA API in case of S3C64XX
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (9 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 10/12] spi: s3c64xx: Do not require legacy DMA API in case of S3C64XX Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-22 20:42 ` [RFC PATCH v2 12/12] ARM: s3c64xx: Add support for DMA using generic amba-pl08x driver Tomasz Figa
  2013-06-25 10:28 ` [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Mark Brown
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

With support for amba-pl08x driver, on S3C64xx the generic DMA engine
API can be used instead of the private s3c-dma interface.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 sound/soc/samsung/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index ae0ea87..dbced1e 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -1,7 +1,7 @@
 config SND_SOC_SAMSUNG
 	tristate "ASoC support for Samsung"
 	depends on PLAT_SAMSUNG
-	select S3C64XX_DMA if ARCH_S3C64XX
+	select S3C64XX_DMA if ARCH_S3C64XX && !S3C64XX_PL080
 	select S3C2410_DMA if ARCH_S3C24XX
 	help
 	  Say Y or M if you want to add support for codecs attached to
-- 
1.8.2.1


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

* [RFC PATCH v2 12/12] ARM: s3c64xx: Add support for DMA using generic amba-pl08x driver
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (10 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 11/12] ASoC: Samsung: " Tomasz Figa
@ 2013-06-22 20:42 ` Tomasz Figa
  2013-06-25 10:28 ` [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Mark Brown
  12 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-22 20:42 UTC (permalink / raw)
  To: linux-samsung-soc
  Cc: linux-arm-kernel, linux-kernel, linux-spi, alsa-devel,
	Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel, Tomasz Figa

This patch adds all required platform-specific data and initialization
code to support the generic amba-pl08x driver on S3C64xx SoCs.

Also some compatibility definitions are added to make the transition
from legacy API to DMA engine easier. The biggest hack here is passing
const char * pointers through DMA resource, casted to unsigned long,
but this is how Samsung DMA wrappers (used to support both s3c-dma and
DMA engine in drivers) are designed.

Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
---
 arch/arm/Kconfig                         |   1 +
 arch/arm/mach-s3c64xx/Kconfig            |   8 +-
 arch/arm/mach-s3c64xx/Makefile           |   1 +
 arch/arm/mach-s3c64xx/common.h           |   5 +
 arch/arm/mach-s3c64xx/include/mach/dma.h |  65 ++++++++
 arch/arm/mach-s3c64xx/pl080.c            | 244 +++++++++++++++++++++++++++++++
 6 files changed, 323 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-s3c64xx/pl080.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5413187..8ab0fcc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -721,6 +721,7 @@ config ARCH_S3C64XX
 	bool "Samsung S3C64XX"
 	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
+	select ARM_AMBA
 	select ARM_VIC
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 5189d30..54ff9ab 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -19,9 +19,15 @@ config CPU_S3C6410
 	help
 	  Enable S3C6410 CPU support
 
+config S3C64XX_PL080
+	bool "S3C64XX DMA using generic PL08x driver"
+	select AMBA_PL08X
+	select SAMSUNG_DMADEV
+
 config S3C64XX_DMA
-	bool "S3C64XX DMA"
+	bool "S3C64XX DMA using legacy S3C DMA API"
 	select S3C_DMA
+	depends on !S3C64XX_PL080
 
 config S3C64XX_SETUP_SDHCI
 	bool
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 6faedcf..e8e9a46 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 # DMA support
 
 obj-$(CONFIG_S3C64XX_DMA)	+= dma.o
+obj-$(CONFIG_S3C64XX_PL080)	+= pl080.o
 
 # Device support
 
diff --git a/arch/arm/mach-s3c64xx/common.h b/arch/arm/mach-s3c64xx/common.h
index bd3bd56..7043e7a 100644
--- a/arch/arm/mach-s3c64xx/common.h
+++ b/arch/arm/mach-s3c64xx/common.h
@@ -58,4 +58,9 @@ int __init s3c64xx_pm_late_initcall(void);
 static inline int s3c64xx_pm_late_initcall(void) { return 0; }
 #endif
 
+#ifdef CONFIG_S3C64XX_PL080
+extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
+extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
+#endif
+
 #endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
index fe1a98c..6f88965 100644
--- a/arch/arm/mach-s3c64xx/include/mach/dma.h
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
+#ifdef CONFIG_S3C64XX_DMA
+
 #define S3C_DMA_CHANNELS	(16)
 
 /* see mach-s3c2410/dma.h for notes on dma channel numbers */
@@ -128,4 +130,67 @@ struct s3c2410_dma_chan {
 
 #include <plat/dma-core.h>
 
+#else
+
+#define S3C64XX_DMA_CHAN(name)		((unsigned long)(name))
+
+/* DMA0/SDMA0 */
+#define DMACH_UART0		S3C64XX_DMA_CHAN("uart0_tx")
+#define DMACH_UART0_SRC2	S3C64XX_DMA_CHAN("uart0_rx")
+#define DMACH_UART1		S3C64XX_DMA_CHAN("uart1_tx")
+#define DMACH_UART1_SRC2	S3C64XX_DMA_CHAN("uart1_rx")
+#define DMACH_UART2		S3C64XX_DMA_CHAN("uart2_tx")
+#define DMACH_UART2_SRC2	S3C64XX_DMA_CHAN("uart2_rx")
+#define DMACH_UART3		S3C64XX_DMA_CHAN("uart3_tx")
+#define DMACH_UART3_SRC2	S3C64XX_DMA_CHAN("uart3_rx")
+#define DMACH_PCM0_TX		S3C64XX_DMA_CHAN("pcm0_tx")
+#define DMACH_PCM0_RX		S3C64XX_DMA_CHAN("pcm0_rx")
+#define DMACH_I2S0_OUT		S3C64XX_DMA_CHAN("i2s0_tx")
+#define DMACH_I2S0_IN		S3C64XX_DMA_CHAN("i2s0_rx")
+#define DMACH_SPI0_TX		S3C64XX_DMA_CHAN("spi0_tx")
+#define DMACH_SPI0_RX		S3C64XX_DMA_CHAN("spi0_rx")
+#define DMACH_HSI_I2SV40_TX	S3C64XX_DMA_CHAN("i2s2_tx")
+#define DMACH_HSI_I2SV40_RX	S3C64XX_DMA_CHAN("i2s2_rx")
+
+/* DMA1/SDMA1 */
+#define DMACH_PCM1_TX		S3C64XX_DMA_CHAN("pcm1_tx")
+#define DMACH_PCM1_RX		S3C64XX_DMA_CHAN("pcm1_rx")
+#define DMACH_I2S1_OUT		S3C64XX_DMA_CHAN("i2s1_tx")
+#define DMACH_I2S1_IN		S3C64XX_DMA_CHAN("i2s1_rx")
+#define DMACH_SPI1_TX		S3C64XX_DMA_CHAN("spi1_tx")
+#define DMACH_SPI1_RX		S3C64XX_DMA_CHAN("spi1_rx")
+#define DMACH_AC97_PCMOUT	S3C64XX_DMA_CHAN("ac97_out")
+#define DMACH_AC97_PCMIN	S3C64XX_DMA_CHAN("ac97_in")
+#define DMACH_AC97_MICIN	S3C64XX_DMA_CHAN("ac97_mic")
+#define DMACH_PWM		S3C64XX_DMA_CHAN("pwm")
+#define DMACH_IRDA		S3C64XX_DMA_CHAN("irda")
+#define DMACH_EXTERNAL		S3C64XX_DMA_CHAN("external")
+#define DMACH_SECURITY_RX	S3C64XX_DMA_CHAN("sec_rx")
+#define DMACH_SECURITY_TX	S3C64XX_DMA_CHAN("sec_tx")
+
+enum dma_ch {
+	DMACH_MAX = 32
+};
+
+struct s3c2410_dma_client {
+	char	*name;
+};
+
+static inline bool samsung_dma_has_circular(void)
+{
+	return true;
+}
+
+static inline bool samsung_dma_is_dmadev(void)
+{
+	return true;
+}
+
+#define pl330_filter pl08x_filter_id
+
+#include <linux/amba/pl08x.h>
+#include <plat/dma-ops.h>
+
+#endif
+
 #endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-s3c64xx/pl080.c b/arch/arm/mach-s3c64xx/pl080.c
new file mode 100644
index 0000000..901a984
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/pl080.c
@@ -0,0 +1,244 @@
+/*
+ * Samsung's S3C64XX generic DMA support using amba-pl08x driver.
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * 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/amba/bus.h>
+#include <linux/amba/pl080.h>
+#include <linux/amba/pl08x.h>
+#include <linux/of.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include "regs-sys.h"
+
+static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
+{
+	return cd->min_signal;
+}
+
+static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
+{
+}
+
+/*
+ * DMA0
+ */
+
+static struct pl08x_channel_data s3c64xx_dma0_info[] = {
+	{
+		.bus_id = "uart0_tx",
+		.min_signal = 0,
+		.max_signal = 0,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart0_rx",
+		.min_signal = 1,
+		.max_signal = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart1_tx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart1_rx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart2_tx",
+		.min_signal = 4,
+		.max_signal = 4,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart2_rx",
+		.min_signal = 5,
+		.max_signal = 5,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart3_tx",
+		.min_signal = 6,
+		.max_signal = 6,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "uart3_rx",
+		.min_signal = 7,
+		.max_signal = 7,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "pcm0_tx",
+		.min_signal = 8,
+		.max_signal = 8,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "pcm0_rx",
+		.min_signal = 9,
+		.max_signal = 9,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2s0_tx",
+		.min_signal = 10,
+		.max_signal = 10,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2s0_rx",
+		.min_signal = 11,
+		.max_signal = 11,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "spi0_tx",
+		.min_signal = 12,
+		.max_signal = 12,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "spi0_rx",
+		.min_signal = 13,
+		.max_signal = 13,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2s2_tx",
+		.min_signal = 14,
+		.max_signal = 14,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2s2_rx",
+		.min_signal = 15,
+		.max_signal = 15,
+		.periph_buses = PL08X_AHB2,
+	}
+};
+
+struct pl08x_platform_data s3c64xx_dma0_plat_data = {
+	.memcpy_channel = {
+		.bus_id = "memcpy",
+		.cctl_memcpy =
+			(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+			PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
+			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
+			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
+			PL080_CONTROL_PROT_SYS),
+	},
+	.lli_buses = PL08X_AHB1,
+	.mem_buses = PL08X_AHB1,
+	.get_xfer_signal = pl08x_get_xfer_signal,
+	.put_xfer_signal = pl08x_put_xfer_signal,
+	.slave_channels = s3c64xx_dma0_info,
+	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
+};
+
+static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
+			0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
+
+/*
+ * DMA1
+ */
+
+static struct pl08x_channel_data s3c64xx_dma1_info[] = {
+	{
+		.bus_id = "pcm1_tx",
+		.min_signal = 0,
+		.max_signal = 0,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "pcm1_rx",
+		.min_signal = 1,
+		.max_signal = 1,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2s1_tx",
+		.min_signal = 2,
+		.max_signal = 2,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "i2s1_rx",
+		.min_signal = 3,
+		.max_signal = 3,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "spi1_tx",
+		.min_signal = 4,
+		.max_signal = 4,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "spi1_rx",
+		.min_signal = 5,
+		.max_signal = 5,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ac97_out",
+		.min_signal = 6,
+		.max_signal = 6,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ac97_in",
+		.min_signal = 7,
+		.max_signal = 7,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "ac97_mic",
+		.min_signal = 8,
+		.max_signal = 8,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "pwm",
+		.min_signal = 9,
+		.max_signal = 9,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "irda",
+		.min_signal = 10,
+		.max_signal = 10,
+		.periph_buses = PL08X_AHB2,
+	}, {
+		.bus_id = "external",
+		.min_signal = 11,
+		.max_signal = 11,
+		.periph_buses = PL08X_AHB2,
+	},
+};
+
+struct pl08x_platform_data s3c64xx_dma1_plat_data = {
+	.memcpy_channel = {
+		.bus_id = "memcpy",
+		.cctl_memcpy =
+			(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+			PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
+			PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+			PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
+			PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
+			PL080_CONTROL_PROT_SYS),
+	},
+	.lli_buses = PL08X_AHB1,
+	.mem_buses = PL08X_AHB1,
+	.get_xfer_signal = pl08x_get_xfer_signal,
+	.put_xfer_signal = pl08x_put_xfer_signal,
+	.slave_channels = s3c64xx_dma1_info,
+	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
+};
+
+static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
+			0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
+
+static int __init s3c64xx_pl080_init(void)
+{
+	/* Set all DMA configuration to be DMA, not SDMA */
+	writel(0xffffff, S3C64XX_SDMA_SEL);
+
+	if (of_have_populated_dt())
+		return 0;
+
+	amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
+	amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
+
+	return 0;
+}
+arch_initcall(s3c64xx_pl080_init);
-- 
1.8.2.1


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

* Re: [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA
  2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
                   ` (11 preceding siblings ...)
  2013-06-22 20:42 ` [RFC PATCH v2 12/12] ARM: s3c64xx: Add support for DMA using generic amba-pl08x driver Tomasz Figa
@ 2013-06-25 10:28 ` Mark Brown
  2013-06-25 11:22   ` Tomasz Figa
  12 siblings, 1 reply; 21+ messages in thread
From: Mark Brown @ 2013-06-25 10:28 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: linux-samsung-soc, linux-arm-kernel, linux-kernel, linux-spi,
	alsa-devel, Kukjin Kim, Vinod Koul, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Grant Likely, Sangbeom Kim,
	Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Padmavathi Venna,
	Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel

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

On Sat, Jun 22, 2013 at 10:42:32PM +0200, Tomasz Figa wrote:
> This is another version of my patches extending support of amba-pl08x
> DMA engine driver to PL080S DMA engine (PL080 modified by Samsung) found
> in Samsung S3C64xx SoCs.

On my non-DT s3c64xx system I get this when trying to use SPI for the
first time:

[    1.739385] s3c64xx-spi s3c6410-spi.0: Failed to get RX DMA channel
[    1.743437] spi_master spi0: failed to prepare transfer hardware

though I haven't yet tried your clock patches (there were some conficts
that I didn't get round to picking up yet).

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

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

* Re: [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA
  2013-06-25 10:28 ` [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Mark Brown
@ 2013-06-25 11:22   ` Tomasz Figa
  2013-06-25 15:38     ` Mark Brown
  0 siblings, 1 reply; 21+ messages in thread
From: Tomasz Figa @ 2013-06-25 11:22 UTC (permalink / raw)
  To: Mark Brown
  Cc: Tomasz Figa, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linux-spi, alsa-devel, Kukjin Kim, Vinod Koul, Dan Williams,
	Linus Walleij, Alessandro Rubini, Giancarlo Asnaghi,
	Grant Likely, Sangbeom Kim, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, Padmavathi Venna, Thomas Abraham, Arnd Bergmann,
	Olof Johansson, Heiko Stübner, Sylwester Nawrocki,
	Russell King - ARM Linux, Alban Bedel

Hi Mark,

Thanks for testing this series.

On Tuesday 25 of June 2013 11:28:18 Mark Brown wrote:
> On Sat, Jun 22, 2013 at 10:42:32PM +0200, Tomasz Figa wrote:
> > This is another version of my patches extending support of amba-pl08x
> > DMA engine driver to PL080S DMA engine (PL080 modified by Samsung)
> > found
> > in Samsung S3C64xx SoCs.
> 
> On my non-DT s3c64xx system I get this when trying to use SPI for the
> first time:

Could you clarify first time? Does it work on further retries?

> [    1.739385] s3c64xx-spi s3c6410-spi.0: Failed to get RX DMA channel
> [    1.743437] spi_master spi0: failed to prepare transfer hardware
> 
> though I haven't yet tried your clock patches (there were some conficts
> that I didn't get round to picking up yet).

This shouldn't really matter, as long as the pl080 drivers probes 
correctly.

Best regards,
Tomasz


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

* Re: [RFC PATCH v2 01/12] dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation
  2013-06-22 20:42 ` [RFC PATCH v2 01/12] dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation Tomasz Figa
@ 2013-06-25 15:16   ` Vinod Koul
  2013-06-25 18:30     ` Russell King - ARM Linux
  0 siblings, 1 reply; 21+ messages in thread
From: Vinod Koul @ 2013-06-25 15:16 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: linux-samsung-soc, linux-arm-kernel, linux-kernel, linux-spi,
	alsa-devel, Kukjin Kim, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel

On Sat, Jun 22, 2013 at 10:42:33PM +0200, Tomasz Figa wrote:
> Further patch will introduce support for PL080S, which requires some
> things to be done conditionally, thus increasing indentation level of
> some functions even more.
> 
> This patch reduces indentation level of pl08x_getbytes_chan() function
> by inverting several conditions and returning from function wherever
> possible.
> 
> Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
> ---
>  drivers/dma/amba-pl08x.c | 53 ++++++++++++++++++++++++++----------------------
>  1 file changed, 29 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
> index 06fe45c..6a12392 100644
> --- a/drivers/dma/amba-pl08x.c
> +++ b/drivers/dma/amba-pl08x.c
> @@ -469,47 +469,52 @@ static inline u32 get_bytes_in_cctl(u32 cctl)
>  /* The channel should be paused when calling this */
>  static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
>  {
> +	struct pl08x_lli *llis_va;
>  	struct pl08x_phy_chan *ch;
> +	dma_addr_t llis_bus;
>  	struct pl08x_txd *txd;
> -	size_t bytes = 0;
> +	size_t bytes;
> +	int index;
> +	u32 clli;
>  
>  	ch = plchan->phychan;
>  	txd = plchan->at;
>  
> +	if (!ch || !txd)
> +		return 0;
shouldnt this be err return

> +
>  	/*
>  	 * Follow the LLIs to get the number of remaining
>  	 * bytes in the currently active transaction.
>  	 */
> -	if (ch && txd) {
> -		u32 clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
> +	clli = readl(ch->base + PL080_CH_LLI) & ~PL080_LLI_LM_AHB2;
>  
> -		/* First get the remaining bytes in the active transfer */
> -		bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
> +	/* First get the remaining bytes in the active transfer */
> +	bytes = get_bytes_in_cctl(readl(ch->base + PL080_CH_CONTROL));
>  
> -		if (clli) {
> -			struct pl08x_lli *llis_va = txd->llis_va;
> -			dma_addr_t llis_bus = txd->llis_bus;
> -			int index;
> +	if (!clli)
> +		return bytes;
>  
> -			BUG_ON(clli < llis_bus || clli >= llis_bus +
> +	llis_va = txd->llis_va;
> +	llis_bus = txd->llis_bus;
> +
> +	BUG_ON(clli < llis_bus || clli >= llis_bus +
>  				sizeof(struct pl08x_lli) * MAX_NUM_TSFR_LLIS);
IMO BUG_ON is too much for this. Perhaps returning error and logging error would
be okay

--
~Vinod

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

* Re: [RFC PATCH v2 02/12] dmaengine: PL08x: Add support for different offset of CONFIG register
  2013-06-22 20:42 ` [RFC PATCH v2 02/12] dmaengine: PL08x: Add support for different offset of CONFIG register Tomasz Figa
@ 2013-06-25 15:34   ` Vinod Koul
  0 siblings, 0 replies; 21+ messages in thread
From: Vinod Koul @ 2013-06-25 15:34 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: linux-samsung-soc, linux-arm-kernel, linux-kernel, linux-spi,
	alsa-devel, Kukjin Kim, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel

On Sat, Jun 22, 2013 at 10:42:34PM +0200, Tomasz Figa wrote:
> Some variants of PL08x (namely PL080S, found in Samsung S3C64xx SoCs)
> have CONFIG register at different offset. This patch makes the driver
> use offset from vendor data struct.
> 
> Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>

--
~Vinod

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

* Re: [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA
  2013-06-25 11:22   ` Tomasz Figa
@ 2013-06-25 15:38     ` Mark Brown
  2013-06-25 15:44       ` Tomasz Figa
  0 siblings, 1 reply; 21+ messages in thread
From: Mark Brown @ 2013-06-25 15:38 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: Tomasz Figa, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linux-spi, alsa-devel, Kukjin Kim, Vinod Koul, Dan Williams,
	Linus Walleij, Alessandro Rubini, Giancarlo Asnaghi,
	Grant Likely, Sangbeom Kim, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, Padmavathi Venna, Thomas Abraham, Arnd Bergmann,
	Olof Johansson, Heiko Stübner, Sylwester Nawrocki,
	Russell King - ARM Linux, Alban Bedel

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

On Tue, Jun 25, 2013 at 01:22:20PM +0200, Tomasz Figa wrote:
> On Tuesday 25 of June 2013 11:28:18 Mark Brown wrote:

> > On my non-DT s3c64xx system I get this when trying to use SPI for the
> > first time:

> Could you clarify first time? Does it work on further retries?

No, the system appears to lock up fairly solidly - I suspect poor error
handling in the SPI driver.

> > [    1.739385] s3c64xx-spi s3c6410-spi.0: Failed to get RX DMA channel
> > [    1.743437] spi_master spi0: failed to prepare transfer hardware

> > though I haven't yet tried your clock patches (there were some conficts
> > that I didn't get round to picking up yet).

> This shouldn't really matter, as long as the pl080 drivers probes 
> correctly.

Indeed, I was wondering if it was failing to probe due to not getting
its clocks though since that's another area you've been actively working
on.

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

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

* Re: [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA
  2013-06-25 15:38     ` Mark Brown
@ 2013-06-25 15:44       ` Tomasz Figa
  0 siblings, 0 replies; 21+ messages in thread
From: Tomasz Figa @ 2013-06-25 15:44 UTC (permalink / raw)
  To: Mark Brown
  Cc: Tomasz Figa, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linux-spi, alsa-devel, Kukjin Kim, Vinod Koul, Dan Williams,
	Linus Walleij, Alessandro Rubini, Giancarlo Asnaghi,
	Grant Likely, Sangbeom Kim, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, Padmavathi Venna, Thomas Abraham, Arnd Bergmann,
	Olof Johansson, Heiko Stübner, Sylwester Nawrocki,
	Russell King - ARM Linux, Alban Bedel

On Tuesday 25 of June 2013 16:38:43 Mark Brown wrote:
> On Tue, Jun 25, 2013 at 01:22:20PM +0200, Tomasz Figa wrote:
> > On Tuesday 25 of June 2013 11:28:18 Mark Brown wrote:
> > > On my non-DT s3c64xx system I get this when trying to use SPI for the
> > 
> > > first time:
> > Could you clarify first time? Does it work on further retries?
> 
> No, the system appears to lock up fairly solidly - I suspect poor error
> handling in the SPI driver.
> 
> > > [    1.739385] s3c64xx-spi s3c6410-spi.0: Failed to get RX DMA
> > > channel
> > > [    1.743437] spi_master spi0: failed to prepare transfer hardware
> > > 
> > > though I haven't yet tried your clock patches (there were some
> > > conficts
> > > that I didn't get round to picking up yet).
> > 
> > This shouldn't really matter, as long as the pl080 drivers probes
> > correctly.
> 
> Indeed, I was wondering if it was failing to probe due to not getting
> its clocks though since that's another area you've been actively working
> on.

Let me check if I can get something with SPI interface that I would be able 
to connect to my board at home and do some testing.

Best regards,
Tomasz


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

* Re: [RFC PATCH v2 05/12] dmaengine: PL08x: Add support for different maximum transfer size
  2013-06-22 20:42 ` [RFC PATCH v2 05/12] dmaengine: PL08x: Add support for different maximum transfer size Tomasz Figa
@ 2013-06-25 16:10   ` Vinod Koul
  0 siblings, 0 replies; 21+ messages in thread
From: Vinod Koul @ 2013-06-25 16:10 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: linux-samsung-soc, linux-arm-kernel, linux-kernel, linux-spi,
	alsa-devel, Kukjin Kim, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Russell King - ARM Linux,
	Alban Bedel

On Sat, Jun 22, 2013 at 10:42:37PM +0200, Tomasz Figa wrote:
> PL080S has separate register to store transfer size in, allowing single
> transfer to be much larger than in standard PL080.
> 
> This patch makes the amba-pl08x driver aware of this and removes writing
> transfer size to reserved bits of CH_CONTROL register on PL080S, which
> was not a problem witn transfer sizes fitting the original bitfield
> of PL080, but now would overwrite other fields.
> 
> Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
Acked by: Vinod Koul <vinod.koul@intel.com>

--
~Vinod

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

* Re: [RFC PATCH v2 01/12] dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation
  2013-06-25 15:16   ` Vinod Koul
@ 2013-06-25 18:30     ` Russell King - ARM Linux
  0 siblings, 0 replies; 21+ messages in thread
From: Russell King - ARM Linux @ 2013-06-25 18:30 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Tomasz Figa, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linux-spi, alsa-devel, Kukjin Kim, Dan Williams, Linus Walleij,
	Alessandro Rubini, Giancarlo Asnaghi, Mark Brown, Grant Likely,
	Sangbeom Kim, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	Padmavathi Venna, Thomas Abraham, Arnd Bergmann, Olof Johansson,
	Heiko Stübner, Sylwester Nawrocki, Alban Bedel

On Tue, Jun 25, 2013 at 08:46:12PM +0530, Vinod Koul wrote:
> On Sat, Jun 22, 2013 at 10:42:33PM +0200, Tomasz Figa wrote:
> > -			BUG_ON(clli < llis_bus || clli >= llis_bus +
> > +	llis_va = txd->llis_va;
> > +	llis_bus = txd->llis_bus;
> > +
> > +	BUG_ON(clli < llis_bus || clli >= llis_bus +
> >  				sizeof(struct pl08x_lli) * MAX_NUM_TSFR_LLIS);
> IMO BUG_ON is too much for this. Perhaps returning error and logging error would
> be okay

That should be a separate patch, because that's an unrelated change
to this patch.  As this part is just reformatting this part of the
code, it should contain no actual changes.

There's lots that this driver "should" do differently...

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

end of thread, other threads:[~2013-06-25 18:34 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-22 20:42 [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 01/12] dmaengine: PL08x: Refactor pl08x_getbytes_chan() to lower indentation Tomasz Figa
2013-06-25 15:16   ` Vinod Koul
2013-06-25 18:30     ` Russell King - ARM Linux
2013-06-22 20:42 ` [RFC PATCH v2 02/12] dmaengine: PL08x: Add support for different offset of CONFIG register Tomasz Figa
2013-06-25 15:34   ` Vinod Koul
2013-06-22 20:42 ` [RFC PATCH v2 03/12] dmaengine: PL08x: Rework LLI handling to be less fragile Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 04/12] dmaengine: PL08x: Add support for PL080S variant Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 05/12] dmaengine: PL08x: Add support for different maximum transfer size Tomasz Figa
2013-06-25 16:10   ` Vinod Koul
2013-06-22 20:42 ` [RFC PATCH v2 06/12] dmaengine: PL08x: Fix reading the byte count in cctl Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 07/12] dmaengine: PL08x: Add cyclic transfer support Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 08/12] ASoC: Samsung: Do not queue cyclic buffers multiple times Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 09/12] clk: samsung: s3c64xx: Add aliases for DMA clocks Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 10/12] spi: s3c64xx: Do not require legacy DMA API in case of S3C64XX Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 11/12] ASoC: Samsung: " Tomasz Figa
2013-06-22 20:42 ` [RFC PATCH v2 12/12] ARM: s3c64xx: Add support for DMA using generic amba-pl08x driver Tomasz Figa
2013-06-25 10:28 ` [RFC PATCH v2 00/12] ARM: s3c64xx: Let amba-pl08x driver handle DMA Mark Brown
2013-06-25 11:22   ` Tomasz Figa
2013-06-25 15:38     ` Mark Brown
2013-06-25 15:44       ` Tomasz Figa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).