All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-15 18:21 ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko, Arnd Bergmann

Hi Vinod,

As Andy pointed out today, we don't have a good solution for the
dw_dmac DT binding in linux-next yet. I have posted my series
once before and then got distracted after getting feedback from
Viresh, Andy and Russell. I have now updated my earlier patch
based on the feedback and rebased on your tree without any
of the arm-soc patches mixed in.

Unfortunately the patches have never been tested on real hardware 
so I don't think it's a good idea to use them in v3.9 on the
spear platform. However, your dma-slave tree still contains Viresh's
earlier patches, causing a few problems:

* With those patches, the spear3xx platform currently does not build.
  (this one would be easy to fix though)
* There is a conflict between those patches and my spear multiplatform
  series, which I have not yet queued up for 3.9 because of this,
  since that would have meant that Stephen Rothwell would have to
  discard either the arm-soc tree or the dma-slave tree from linux-next.
* I really don't want the broken binding to appear in 3.9.

I believe the best way out at this point is this series, which first
first reverts the patch f9965aa2 "ARM: SPEAr13xx: Pass DW DMAC
platform data from DT" from your tree and then adds my update.

This will give us the right DT binding for dw-dmac but no in-tree
users, which means that nothing should break if I get it slightly
wrong. Please apply the first two patches from these set, and
optionally the two patches that based on this convert the pl011
uart and pl022 spi controller drivers.

I can then decide with Olof whether or not to take the spear multiplatform
changes that no longer conflict with the dma slave tree as a "late"
branch into 3.9 or wait until 3.10, but that is something you don't
need to worry about then. Also the conversion of spear to use
the new binding (patch 5 of my original series) can go through the 
arm-soc tree for 3.10 after the ST folks have tested that it works.

	Arnd

Arnd Bergmann (4):
  Revert "ARM: SPEAr13xx: Pass DW DMAC platform data from DT"
  dmaengine: dw_dmac: move to generic DMA binding
  spi: pl022: use generic DMA slave configuration if possible
  serial: pl011: use generic DMA slave configuration if possible

 .../devicetree/bindings/arm/primecell.txt          |  19 ++-
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 ++++++-----
 Documentation/devicetree/bindings/serial/pl011.txt |  17 +++
 .../devicetree/bindings/spi/spi_pl022.txt          |  36 ++++++
 arch/arm/boot/dts/spear1340.dtsi                   |  19 ---
 arch/arm/boot/dts/spear13xx.dtsi                   |  38 ------
 arch/arm/mach-spear13xx/include/mach/spear.h       |   2 +
 arch/arm/mach-spear13xx/spear1310.c                |   5 +-
 arch/arm/mach-spear13xx/spear1340.c                |  33 +++--
 arch/arm/mach-spear13xx/spear13xx.c                |  55 ++++++++-
 drivers/dma/dw_dmac.c                              | 137 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |   8 +-
 drivers/spi/spi-pl022.c                            |  43 ++++++-
 drivers/tty/serial/amba-pl011.c                    |  62 ++++++----
 include/linux/dw_dmac.h                            |   5 -
 15 files changed, 333 insertions(+), 216 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/serial/pl011.txt

-- 
1.8.1.2


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

* [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-15 18:21 ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Vinod,

As Andy pointed out today, we don't have a good solution for the
dw_dmac DT binding in linux-next yet. I have posted my series
once before and then got distracted after getting feedback from
Viresh, Andy and Russell. I have now updated my earlier patch
based on the feedback and rebased on your tree without any
of the arm-soc patches mixed in.

Unfortunately the patches have never been tested on real hardware 
so I don't think it's a good idea to use them in v3.9 on the
spear platform. However, your dma-slave tree still contains Viresh's
earlier patches, causing a few problems:

* With those patches, the spear3xx platform currently does not build.
  (this one would be easy to fix though)
* There is a conflict between those patches and my spear multiplatform
  series, which I have not yet queued up for 3.9 because of this,
  since that would have meant that Stephen Rothwell would have to
  discard either the arm-soc tree or the dma-slave tree from linux-next.
* I really don't want the broken binding to appear in 3.9.

I believe the best way out at this point is this series, which first
first reverts the patch f9965aa2 "ARM: SPEAr13xx: Pass DW DMAC
platform data from DT" from your tree and then adds my update.

This will give us the right DT binding for dw-dmac but no in-tree
users, which means that nothing should break if I get it slightly
wrong. Please apply the first two patches from these set, and
optionally the two patches that based on this convert the pl011
uart and pl022 spi controller drivers.

I can then decide with Olof whether or not to take the spear multiplatform
changes that no longer conflict with the dma slave tree as a "late"
branch into 3.9 or wait until 3.10, but that is something you don't
need to worry about then. Also the conversion of spear to use
the new binding (patch 5 of my original series) can go through the 
arm-soc tree for 3.10 after the ST folks have tested that it works.

	Arnd

Arnd Bergmann (4):
  Revert "ARM: SPEAr13xx: Pass DW DMAC platform data from DT"
  dmaengine: dw_dmac: move to generic DMA binding
  spi: pl022: use generic DMA slave configuration if possible
  serial: pl011: use generic DMA slave configuration if possible

 .../devicetree/bindings/arm/primecell.txt          |  19 ++-
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 ++++++-----
 Documentation/devicetree/bindings/serial/pl011.txt |  17 +++
 .../devicetree/bindings/spi/spi_pl022.txt          |  36 ++++++
 arch/arm/boot/dts/spear1340.dtsi                   |  19 ---
 arch/arm/boot/dts/spear13xx.dtsi                   |  38 ------
 arch/arm/mach-spear13xx/include/mach/spear.h       |   2 +
 arch/arm/mach-spear13xx/spear1310.c                |   5 +-
 arch/arm/mach-spear13xx/spear1340.c                |  33 +++--
 arch/arm/mach-spear13xx/spear13xx.c                |  55 ++++++++-
 drivers/dma/dw_dmac.c                              | 137 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |   8 +-
 drivers/spi/spi-pl022.c                            |  43 ++++++-
 drivers/tty/serial/amba-pl011.c                    |  62 ++++++----
 include/linux/dw_dmac.h                            |   5 -
 15 files changed, 333 insertions(+), 216 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/serial/pl011.txt

-- 
1.8.1.2

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

* [PATCH 1/4] Revert "ARM: SPEAr13xx: Pass DW DMAC platform data from DT"
  2013-02-15 18:21 ` Arnd Bergmann
@ 2013-02-15 18:21   ` Arnd Bergmann
  -1 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko, Arnd Bergmann

This reverts commit f9965aa20706860077cfa093d04a6351c0c1e940.
---
 arch/arm/boot/dts/spear1340.dtsi             | 19 ----------
 arch/arm/boot/dts/spear13xx.dtsi             | 38 -------------------
 arch/arm/mach-spear13xx/include/mach/spear.h |  2 +
 arch/arm/mach-spear13xx/spear1310.c          |  5 ++-
 arch/arm/mach-spear13xx/spear1340.c          | 33 ++++++++++++-----
 arch/arm/mach-spear13xx/spear13xx.c          | 55 ++++++++++++++++++++++++++--
 6 files changed, 80 insertions(+), 72 deletions(-)

diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index b2d41b7..34da11a 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -88,25 +88,6 @@
 			status = "disabled";
 		};
 
-		dma@ea800000 {
-			slave_info {
-				uart1_tx {
-					bus_id = "uart1_tx";
-					cfg_hi = <0x6000>;	/* 0xC << 11 */
-					cfg_lo = <0>;
-					src_master = <0>;
-					dst_master = <1>;
-				};
-				uart1_tx {
-					bus_id = "uart1_tx";
-					cfg_hi = <0x680>;	/* 0xD << 7 */
-					cfg_lo = <0>;
-					src_master = <1>;
-					dst_master = <0>;
-				};
-			};
-		};
-
 		spi1: spi@5d400000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x5d400000 0x1000>;
diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index 585f641..b4ca60f 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -105,37 +105,6 @@
 			reg = <0xea800000 0x1000>;
 			interrupts = <0 19 0x4>;
 			status = "disabled";
-
-			nr_channels = <8>;
-			chan_allocation_order = <1>;
-			chan_priority = <1>;
-			block_size = <0xfff>;
-			nr_masters = <2>;
-			data_width = <3 3 0 0>;
-
-			slave_info {
-				ssp0_tx {
-					bus_id = "ssp0_tx";
-					cfg_hi = <0x2000>;	/* 0x4 << 11 */
-					cfg_lo = <0>;
-					src_master = <0>;
-					dst_master = <0>;
-				};
-				ssp0_rx {
-					bus_id = "ssp0_rx";
-					cfg_hi = <0x280>;	/* 0x5 << 7 */
-					cfg_lo = <0>;
-					src_master = <0>;
-					dst_master = <0>;
-				};
-				cf {
-					bus_id = "cf";
-					cfg_hi = <0>;
-					cfg_lo = <0>;
-					src_master = <0>;
-					dst_master = <0>;
-				};
-			};
 		};
 
 		dma@eb000000 {
@@ -143,13 +112,6 @@
 			reg = <0xeb000000 0x1000>;
 			interrupts = <0 59 0x4>;
 			status = "disabled";
-
-			nr_channels = <8>;
-			chan_allocation_order = <1>;
-			chan_priority = <1>;
-			block_size = <0xfff>;
-			nr_masters = <2>;
-			data_width = <3 3 0 0>;
 		};
 
 		fsmc: flash@b0000000 {
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index 972a151..7cfa681 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -43,6 +43,8 @@
 #define VA_L2CC_BASE				IOMEM(UL(0xFB000000))
 
 /* others */
+#define DMAC0_BASE				UL(0xEA800000)
+#define DMAC1_BASE				UL(0xEB000000)
 #define MCIF_CF_BASE				UL(0xB2800000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index ec72c47..02f4724 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -36,7 +36,7 @@
 static struct arasan_cf_pdata cf_pdata = {
 	.cf_if_clk = CF_IF_CLK_166M,
 	.quirk = CF_BROKEN_UDMA,
-	.dma_priv = "cf",
+	.dma_priv = &cf_dma_priv,
 };
 
 /* ssp device registration */
@@ -47,7 +47,10 @@ static struct pl022_ssp_controller ssp1_plat_data = {
 /* Add SPEAr1310 auxdata to pass platform data */
 static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
 	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
+
 	OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data),
 	{}
 };
diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
index 69c8f72..081014f 100644
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ b/arch/arm/mach-spear13xx/spear1340.c
@@ -18,9 +18,9 @@
 #include <linux/delay.h>
 #include <linux/dw_dmac.h>
 #include <linux/of_platform.h>
-#include <linux/pata_arasan_cf_data.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
+#include <mach/dma.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
@@ -78,16 +78,26 @@
 			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
 			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
 
-static struct amba_pl011_data uart1_data = {
-	.dma_filter = dw_dma_generic_filter,
-	.dma_tx_param = "uart1_tx",
-	.dma_rx_param = "uart1_rx",
+static struct dw_dma_slave uart1_dma_param[] = {
+	{
+		/* Tx */
+		.cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_MEMORY,
+		.dst_master = SPEAR1340_DMA_MASTER_UART1,
+	}, {
+		/* Rx */
+		.cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX),
+		.cfg_lo = 0,
+		.src_master = SPEAR1340_DMA_MASTER_UART1,
+		.dst_master = DMA_MASTER_MEMORY,
+	}
 };
 
-static struct arasan_cf_pdata cf_pdata = {
-	.cf_if_clk = CF_IF_CLK_166M,
-	.quirk = CF_BROKEN_UDMA,
-	.dma_priv = "cf",
+static struct amba_pl011_data uart1_data = {
+	.dma_filter = dw_dma_filter,
+	.dma_tx_param = &uart1_dma_param[0],
+	.dma_rx_param = &uart1_dma_param[1],
 };
 
 /* SATA device registration */
@@ -148,8 +158,11 @@ static struct ahci_platform_data sata_pdata = {
 
 /* Add SPEAr1340 auxdata to pass platform data */
 static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
+	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
 	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
+
 	OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
 			&sata_pdata),
 	OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data),
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index b074db8..c4af775 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -22,16 +22,63 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/smp_twd.h>
+#include <mach/dma.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
+/* common dw_dma filter routine to be used by peripherals */
+bool dw_dma_filter(struct dma_chan *chan, void *slave)
+{
+	struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
+
+	if (chan->device->dev == dws->dma_dev) {
+		chan->private = slave;
+		return true;
+	} else {
+		return false;
+	}
+}
+
 /* ssp device registration */
+static struct dw_dma_slave ssp_dma_param[] = {
+	{
+		/* Tx */
+		.cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_MEMORY,
+		.dst_master = DMA_MASTER_SSP0,
+	}, {
+		/* Rx */
+		.cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_SSP0,
+		.dst_master = DMA_MASTER_MEMORY,
+	}
+};
+
 struct pl022_ssp_controller pl022_plat_data = {
 	.enable_dma = 1,
-	.dma_filter = dw_dma_generic_filter,
-	.dma_rx_param = "ssp0_rx",
-	.dma_tx_param = "ssp0_tx",
-	.num_chipselect = 3,
+	.dma_filter = dw_dma_filter,
+	.dma_rx_param = &ssp_dma_param[1],
+	.dma_tx_param = &ssp_dma_param[0],
+};
+
+/* CF device registration */
+struct dw_dma_slave cf_dma_priv = {
+	.cfg_hi = 0,
+	.cfg_lo = 0,
+	.src_master = 0,
+	.dst_master = 0,
+};
+
+/* dmac device registeration */
+struct dw_dma_platform_data dmac_plat_data = {
+	.nr_channels = 8,
+	.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
+	.chan_priority = CHAN_PRIORITY_DESCENDING,
+	.block_size = 4095U,
+	.nr_masters = 2,
+	.data_width = { 3, 3, 0, 0 },
 };
 
 void __init spear13xx_l2x0_init(void)
-- 
1.8.1.2


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

* [PATCH 1/4] Revert "ARM: SPEAr13xx: Pass DW DMAC platform data from DT"
@ 2013-02-15 18:21   ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: linux-arm-kernel

This reverts commit f9965aa20706860077cfa093d04a6351c0c1e940.
---
 arch/arm/boot/dts/spear1340.dtsi             | 19 ----------
 arch/arm/boot/dts/spear13xx.dtsi             | 38 -------------------
 arch/arm/mach-spear13xx/include/mach/spear.h |  2 +
 arch/arm/mach-spear13xx/spear1310.c          |  5 ++-
 arch/arm/mach-spear13xx/spear1340.c          | 33 ++++++++++++-----
 arch/arm/mach-spear13xx/spear13xx.c          | 55 ++++++++++++++++++++++++++--
 6 files changed, 80 insertions(+), 72 deletions(-)

diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index b2d41b7..34da11a 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -88,25 +88,6 @@
 			status = "disabled";
 		};
 
-		dma at ea800000 {
-			slave_info {
-				uart1_tx {
-					bus_id = "uart1_tx";
-					cfg_hi = <0x6000>;	/* 0xC << 11 */
-					cfg_lo = <0>;
-					src_master = <0>;
-					dst_master = <1>;
-				};
-				uart1_tx {
-					bus_id = "uart1_tx";
-					cfg_hi = <0x680>;	/* 0xD << 7 */
-					cfg_lo = <0>;
-					src_master = <1>;
-					dst_master = <0>;
-				};
-			};
-		};
-
 		spi1: spi at 5d400000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x5d400000 0x1000>;
diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index 585f641..b4ca60f 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -105,37 +105,6 @@
 			reg = <0xea800000 0x1000>;
 			interrupts = <0 19 0x4>;
 			status = "disabled";
-
-			nr_channels = <8>;
-			chan_allocation_order = <1>;
-			chan_priority = <1>;
-			block_size = <0xfff>;
-			nr_masters = <2>;
-			data_width = <3 3 0 0>;
-
-			slave_info {
-				ssp0_tx {
-					bus_id = "ssp0_tx";
-					cfg_hi = <0x2000>;	/* 0x4 << 11 */
-					cfg_lo = <0>;
-					src_master = <0>;
-					dst_master = <0>;
-				};
-				ssp0_rx {
-					bus_id = "ssp0_rx";
-					cfg_hi = <0x280>;	/* 0x5 << 7 */
-					cfg_lo = <0>;
-					src_master = <0>;
-					dst_master = <0>;
-				};
-				cf {
-					bus_id = "cf";
-					cfg_hi = <0>;
-					cfg_lo = <0>;
-					src_master = <0>;
-					dst_master = <0>;
-				};
-			};
 		};
 
 		dma at eb000000 {
@@ -143,13 +112,6 @@
 			reg = <0xeb000000 0x1000>;
 			interrupts = <0 59 0x4>;
 			status = "disabled";
-
-			nr_channels = <8>;
-			chan_allocation_order = <1>;
-			chan_priority = <1>;
-			block_size = <0xfff>;
-			nr_masters = <2>;
-			data_width = <3 3 0 0>;
 		};
 
 		fsmc: flash at b0000000 {
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index 972a151..7cfa681 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -43,6 +43,8 @@
 #define VA_L2CC_BASE				IOMEM(UL(0xFB000000))
 
 /* others */
+#define DMAC0_BASE				UL(0xEA800000)
+#define DMAC1_BASE				UL(0xEB000000)
 #define MCIF_CF_BASE				UL(0xB2800000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index ec72c47..02f4724 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -36,7 +36,7 @@
 static struct arasan_cf_pdata cf_pdata = {
 	.cf_if_clk = CF_IF_CLK_166M,
 	.quirk = CF_BROKEN_UDMA,
-	.dma_priv = "cf",
+	.dma_priv = &cf_dma_priv,
 };
 
 /* ssp device registration */
@@ -47,7 +47,10 @@ static struct pl022_ssp_controller ssp1_plat_data = {
 /* Add SPEAr1310 auxdata to pass platform data */
 static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
 	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
+
 	OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data),
 	{}
 };
diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
index 69c8f72..081014f 100644
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ b/arch/arm/mach-spear13xx/spear1340.c
@@ -18,9 +18,9 @@
 #include <linux/delay.h>
 #include <linux/dw_dmac.h>
 #include <linux/of_platform.h>
-#include <linux/pata_arasan_cf_data.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
+#include <mach/dma.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
@@ -78,16 +78,26 @@
 			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
 			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
 
-static struct amba_pl011_data uart1_data = {
-	.dma_filter = dw_dma_generic_filter,
-	.dma_tx_param = "uart1_tx",
-	.dma_rx_param = "uart1_rx",
+static struct dw_dma_slave uart1_dma_param[] = {
+	{
+		/* Tx */
+		.cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_MEMORY,
+		.dst_master = SPEAR1340_DMA_MASTER_UART1,
+	}, {
+		/* Rx */
+		.cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX),
+		.cfg_lo = 0,
+		.src_master = SPEAR1340_DMA_MASTER_UART1,
+		.dst_master = DMA_MASTER_MEMORY,
+	}
 };
 
-static struct arasan_cf_pdata cf_pdata = {
-	.cf_if_clk = CF_IF_CLK_166M,
-	.quirk = CF_BROKEN_UDMA,
-	.dma_priv = "cf",
+static struct amba_pl011_data uart1_data = {
+	.dma_filter = dw_dma_filter,
+	.dma_tx_param = &uart1_dma_param[0],
+	.dma_rx_param = &uart1_dma_param[1],
 };
 
 /* SATA device registration */
@@ -148,8 +158,11 @@ static struct ahci_platform_data sata_pdata = {
 
 /* Add SPEAr1340 auxdata to pass platform data */
 static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
+	OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
+	OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
 	OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
+
 	OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
 			&sata_pdata),
 	OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data),
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index b074db8..c4af775 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -22,16 +22,63 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/smp_twd.h>
+#include <mach/dma.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 
+/* common dw_dma filter routine to be used by peripherals */
+bool dw_dma_filter(struct dma_chan *chan, void *slave)
+{
+	struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
+
+	if (chan->device->dev == dws->dma_dev) {
+		chan->private = slave;
+		return true;
+	} else {
+		return false;
+	}
+}
+
 /* ssp device registration */
+static struct dw_dma_slave ssp_dma_param[] = {
+	{
+		/* Tx */
+		.cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_MEMORY,
+		.dst_master = DMA_MASTER_SSP0,
+	}, {
+		/* Rx */
+		.cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
+		.cfg_lo = 0,
+		.src_master = DMA_MASTER_SSP0,
+		.dst_master = DMA_MASTER_MEMORY,
+	}
+};
+
 struct pl022_ssp_controller pl022_plat_data = {
 	.enable_dma = 1,
-	.dma_filter = dw_dma_generic_filter,
-	.dma_rx_param = "ssp0_rx",
-	.dma_tx_param = "ssp0_tx",
-	.num_chipselect = 3,
+	.dma_filter = dw_dma_filter,
+	.dma_rx_param = &ssp_dma_param[1],
+	.dma_tx_param = &ssp_dma_param[0],
+};
+
+/* CF device registration */
+struct dw_dma_slave cf_dma_priv = {
+	.cfg_hi = 0,
+	.cfg_lo = 0,
+	.src_master = 0,
+	.dst_master = 0,
+};
+
+/* dmac device registeration */
+struct dw_dma_platform_data dmac_plat_data = {
+	.nr_channels = 8,
+	.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
+	.chan_priority = CHAN_PRIORITY_DESCENDING,
+	.block_size = 4095U,
+	.nr_masters = 2,
+	.data_width = { 3, 3, 0, 0 },
 };
 
 void __init spear13xx_l2x0_init(void)
-- 
1.8.1.2

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-15 18:21   ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko, Arnd Bergmann,
	Vinod Koul

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of linux-next, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

There are a couple of TODO items that are left remaining and are open
for ideas from other people.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 ++++++-----
 drivers/dma/dw_dmac.c                              | 137 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |   8 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 104 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..68783d3 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma@fc000000 {
+	dmahost: dma@fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a five-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial@e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 27b8e1d..208646c 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->req);
+		else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->req);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	u32 req;
+	u32 src;
+	u32 dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* both the driver and the device must match */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= 0xffffffff;
+	dws->cfg_lo	= 0xffffffff;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
+	dwc->req	= fargs->req;
 
-			return true;
-		}
-	}
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
+
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
+		return NULL;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &dma_spec->args[0]);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1510,9 +1529,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1524,7 +1542,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1539,7 +1557,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1551,36 +1569,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1644,8 +1632,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
+	if (err)
+		dev_err(&pdev->dev, "could not register of_dma_controller\n");
+
 	return 0;
 }
 
@@ -1773,6 +1763,7 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88a069f..1d17793 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -213,6 +213,10 @@ struct dw_dma_chan {
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
 
+	/* slave configuration from DT */
+	unsigned int		req;
+	struct dw_dma_slave	slave;
+
 	/* backlink to dw_dma */
 	struct dw_dma		*dw;
 };
@@ -239,10 +243,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2


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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-15 18:21   ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Vinod Koul, Viresh Kumar,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dan Williams,
	Andy Shevchenko,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of linux-next, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

There are a couple of TODO items that are left remaining and are open
for ideas from other people.

Signed-off-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Cc: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: Vinod Koul <vinod.koul-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 ++++++-----
 drivers/dma/dw_dmac.c                              | 137 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |   8 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 104 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..68783d3 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma@fc000000 {
+	dmahost: dma@fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a five-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial@e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 27b8e1d..208646c 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->req);
+		else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->req);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	u32 req;
+	u32 src;
+	u32 dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* both the driver and the device must match */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= 0xffffffff;
+	dws->cfg_lo	= 0xffffffff;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
+	dwc->req	= fargs->req;
 
-			return true;
-		}
-	}
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
+
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
+		return NULL;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &dma_spec->args[0]);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1510,9 +1529,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1524,7 +1542,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1539,7 +1557,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1551,36 +1569,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1644,8 +1632,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
+	if (err)
+		dev_err(&pdev->dev, "could not register of_dma_controller\n");
+
 	return 0;
 }
 
@@ -1773,6 +1763,7 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88a069f..1d17793 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -213,6 +213,10 @@ struct dw_dma_chan {
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
 
+	/* slave configuration from DT */
+	unsigned int		req;
+	struct dw_dma_slave	slave;
+
 	/* backlink to dw_dma */
 	struct dw_dma		*dw;
 };
@@ -239,10 +243,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-15 18:21   ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: linux-arm-kernel

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of linux-next, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

There are a couple of TODO items that are left remaining and are open
for ideas from other people.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss at lists.ozlabs.org
Cc: linux-arm-kernel at lists.infradead.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 ++++++-----
 drivers/dma/dw_dmac.c                              | 137 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |   8 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 104 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..68783d3 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma at fc000000 {
+	dmahost: dma at fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a five-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial at e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 27b8e1d..208646c 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->req);
+		else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->req);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	u32 req;
+	u32 src;
+	u32 dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* both the driver and the device must match */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= 0xffffffff;
+	dws->cfg_lo	= 0xffffffff;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
+	dwc->req	= fargs->req;
 
-			return true;
-		}
-	}
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
+
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
+		return NULL;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &dma_spec->args[0]);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1510,9 +1529,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1524,7 +1542,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1539,7 +1557,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1551,36 +1569,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1644,8 +1632,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
+	if (err)
+		dev_err(&pdev->dev, "could not register of_dma_controller\n");
+
 	return 0;
 }
 
@@ -1773,6 +1763,7 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88a069f..1d17793 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -213,6 +213,10 @@ struct dw_dma_chan {
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
 
+	/* slave configuration from DT */
+	unsigned int		req;
+	struct dw_dma_slave	slave;
+
 	/* backlink to dw_dma */
 	struct dw_dma		*dw;
 };
@@ -239,10 +243,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2

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

* [PATCH 3/4] spi: pl022: use generic DMA slave configuration if possible
  2013-02-15 18:21 ` Arnd Bergmann
@ 2013-02-15 18:21   ` Arnd Bergmann
  -1 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko, Arnd Bergmann,
	spi-devel-general, Vinod Koul

With the new OF DMA binding, it is possible to completely avoid the
need for platform_data for configuring a DMA channel. In cases where the
platform has already been converted, calling dma_request_slave_channel
should get all the necessary information from the device tree.

Like the patch that converts the dw_dma controller, this is completely
untested and is looking for someone to try it out.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: spi-devel-general@lists.sourceforge.net
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
---
 .../devicetree/bindings/spi/spi_pl022.txt          | 36 ++++++++++++++++++
 drivers/spi/spi-pl022.c                            | 43 +++++++++++++++++++++-
 2 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt
index f158fd3..22ed679 100644
--- a/Documentation/devicetree/bindings/spi/spi_pl022.txt
+++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt
@@ -16,6 +16,11 @@ Optional properties:
                             device will be suspended immediately
 - pl022,rt : indicates the controller should run the message pump with realtime
              priority to minimise the transfer latency on the bus (boolean)
+- dmas : Two or more DMA channel specifiers following the convention outlined
+         in bindings/dma/dma.txt
+- dma-names: Names for the dma channels, if present. There must be at
+	     least one channel named "tx" for transmit and named "rx" for
+             receive.
 
 
 SPI slave nodes must be children of the SPI master node and can
@@ -32,3 +37,34 @@ contain the following properties.
 - pl022,wait-state : Microwire interface: Wait state
 - pl022,duplex : Microwire interface: Full/Half duplex
 
+
+Example:
+
+	spi@e0100000 {
+		compatible = "arm,pl022", "arm,primecell";
+		reg = <0xe0100000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupts = <0 31 0x4>;
+		dmas = <&dma-controller 23 1>,
+			<&dma-controller 24 0>;
+		dma-names = "rx", "tx";
+
+		m25p80@1 {
+			compatible = "st,m25p80";
+			reg = <1>;
+			spi-max-frequency = <12000000>;
+			spi-cpol;
+			spi-cpha;
+			pl022,hierarchy = <0>;
+			pl022,interface = <0>;
+			pl022,slave-tx-disable;
+			pl022,com-mode = <0x2>;
+			pl022,rx-level-trig = <0>;
+			pl022,tx-level-trig = <0>;
+			pl022,ctrl-len = <0x11>;
+			pl022,wait-state = <0>;
+			pl022,duplex = <0>;
+		};
+	};
+	
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index b0fe393..371cc66f 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1139,6 +1139,35 @@ err_no_rxchan:
 	return -ENODEV;
 }
 
+static int pl022_dma_autoprobe(struct pl022 *pl022)
+{
+	struct device *dev = &pl022->adev->dev;
+
+	/* automatically configure DMA channels from platform, normally using DT */
+	pl022->dma_rx_channel = dma_request_slave_channel(dev, "rx");
+	if (!pl022->dma_rx_channel)
+		goto err_no_rxchan;
+
+	pl022->dma_tx_channel = dma_request_slave_channel(dev, "tx");
+	if (!pl022->dma_tx_channel)
+		goto err_no_txchan;
+
+	pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!pl022->dummypage)
+		goto err_no_dummypage;
+
+	return 0;
+
+err_no_dummypage:
+	dma_release_channel(pl022->dma_tx_channel);
+	pl022->dma_tx_channel = NULL;
+err_no_txchan:
+	dma_release_channel(pl022->dma_rx_channel);
+	pl022->dma_rx_channel = NULL;
+err_no_rxchan:
+	return -ENODEV;
+}
+		
 static void terminate_dma(struct pl022 *pl022)
 {
 	struct dma_chan *rxchan = pl022->dma_rx_channel;
@@ -1167,6 +1196,11 @@ static inline int configure_dma(struct pl022 *pl022)
 	return -ENODEV;
 }
 
+static inline int pl022_dma_autoprobe(struct pl022 *pl022)
+{
+	return 0;
+}
+
 static inline int pl022_dma_probe(struct pl022 *pl022)
 {
 	return 0;
@@ -2226,8 +2260,13 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 		goto err_no_irq;
 	}
 
-	/* Get DMA channels */
-	if (platform_info->enable_dma) {
+	/* Get DMA channels, try autoconfiguration first */
+	status = pl022_dma_autoprobe(pl022);
+
+	/* If that failed, use channels from platform_info */
+	if (status == 0)
+		platform_info->enable_dma = 1;
+	else if (platform_info->enable_dma) {
 		status = pl022_dma_probe(pl022);
 		if (status != 0)
 			platform_info->enable_dma = 0;
-- 
1.8.1.2


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

* [PATCH 3/4] spi: pl022: use generic DMA slave configuration if possible
@ 2013-02-15 18:21   ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: linux-arm-kernel

With the new OF DMA binding, it is possible to completely avoid the
need for platform_data for configuring a DMA channel. In cases where the
platform has already been converted, calling dma_request_slave_channel
should get all the necessary information from the device tree.

Like the patch that converts the dw_dma controller, this is completely
untested and is looking for someone to try it out.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: spi-devel-general at lists.sourceforge.net
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss at lists.ozlabs.org
Cc: linux-arm-kernel at lists.infradead.org
---
 .../devicetree/bindings/spi/spi_pl022.txt          | 36 ++++++++++++++++++
 drivers/spi/spi-pl022.c                            | 43 +++++++++++++++++++++-
 2 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt
index f158fd3..22ed679 100644
--- a/Documentation/devicetree/bindings/spi/spi_pl022.txt
+++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt
@@ -16,6 +16,11 @@ Optional properties:
                             device will be suspended immediately
 - pl022,rt : indicates the controller should run the message pump with realtime
              priority to minimise the transfer latency on the bus (boolean)
+- dmas : Two or more DMA channel specifiers following the convention outlined
+         in bindings/dma/dma.txt
+- dma-names: Names for the dma channels, if present. There must be at
+	     least one channel named "tx" for transmit and named "rx" for
+             receive.
 
 
 SPI slave nodes must be children of the SPI master node and can
@@ -32,3 +37,34 @@ contain the following properties.
 - pl022,wait-state : Microwire interface: Wait state
 - pl022,duplex : Microwire interface: Full/Half duplex
 
+
+Example:
+
+	spi at e0100000 {
+		compatible = "arm,pl022", "arm,primecell";
+		reg = <0xe0100000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupts = <0 31 0x4>;
+		dmas = <&dma-controller 23 1>,
+			<&dma-controller 24 0>;
+		dma-names = "rx", "tx";
+
+		m25p80 at 1 {
+			compatible = "st,m25p80";
+			reg = <1>;
+			spi-max-frequency = <12000000>;
+			spi-cpol;
+			spi-cpha;
+			pl022,hierarchy = <0>;
+			pl022,interface = <0>;
+			pl022,slave-tx-disable;
+			pl022,com-mode = <0x2>;
+			pl022,rx-level-trig = <0>;
+			pl022,tx-level-trig = <0>;
+			pl022,ctrl-len = <0x11>;
+			pl022,wait-state = <0>;
+			pl022,duplex = <0>;
+		};
+	};
+	
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index b0fe393..371cc66f 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1139,6 +1139,35 @@ err_no_rxchan:
 	return -ENODEV;
 }
 
+static int pl022_dma_autoprobe(struct pl022 *pl022)
+{
+	struct device *dev = &pl022->adev->dev;
+
+	/* automatically configure DMA channels from platform, normally using DT */
+	pl022->dma_rx_channel = dma_request_slave_channel(dev, "rx");
+	if (!pl022->dma_rx_channel)
+		goto err_no_rxchan;
+
+	pl022->dma_tx_channel = dma_request_slave_channel(dev, "tx");
+	if (!pl022->dma_tx_channel)
+		goto err_no_txchan;
+
+	pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!pl022->dummypage)
+		goto err_no_dummypage;
+
+	return 0;
+
+err_no_dummypage:
+	dma_release_channel(pl022->dma_tx_channel);
+	pl022->dma_tx_channel = NULL;
+err_no_txchan:
+	dma_release_channel(pl022->dma_rx_channel);
+	pl022->dma_rx_channel = NULL;
+err_no_rxchan:
+	return -ENODEV;
+}
+		
 static void terminate_dma(struct pl022 *pl022)
 {
 	struct dma_chan *rxchan = pl022->dma_rx_channel;
@@ -1167,6 +1196,11 @@ static inline int configure_dma(struct pl022 *pl022)
 	return -ENODEV;
 }
 
+static inline int pl022_dma_autoprobe(struct pl022 *pl022)
+{
+	return 0;
+}
+
 static inline int pl022_dma_probe(struct pl022 *pl022)
 {
 	return 0;
@@ -2226,8 +2260,13 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 		goto err_no_irq;
 	}
 
-	/* Get DMA channels */
-	if (platform_info->enable_dma) {
+	/* Get DMA channels, try autoconfiguration first */
+	status = pl022_dma_autoprobe(pl022);
+
+	/* If that failed, use channels from platform_info */
+	if (status == 0)
+		platform_info->enable_dma = 1;
+	else if (platform_info->enable_dma) {
 		status = pl022_dma_probe(pl022);
 		if (status != 0)
 			platform_info->enable_dma = 0;
-- 
1.8.1.2

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

* [PATCH 4/4] serial: pl011: use generic DMA slave configuration if possible
  2013-02-15 18:21 ` Arnd Bergmann
@ 2013-02-15 18:21   ` Arnd Bergmann
  -1 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko, Arnd Bergmann,
	Russell King, Jiri Slaby

With the new OF DMA binding, it is possible to completely avoid the
need for platform_data for configuring a DMA channel. In cases where the
platform has already been converted, calling dma_request_slave_channel
should get all the necessary information from the device tree.

This also adds a binding document specific to the pl011 controller,
and extends the generic primecell binding to mention "dmas" and other
common properties.

Like the patch that converts the dw_dma controller, this is completely
untested and is looking for someone to try it out.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
---
 .../devicetree/bindings/arm/primecell.txt          | 19 ++++++-
 Documentation/devicetree/bindings/serial/pl011.txt | 17 ++++++
 drivers/tty/serial/amba-pl011.c                    | 62 +++++++++++++---------
 3 files changed, 72 insertions(+), 26 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/serial/pl011.txt

diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt
index 64fc82b..0df6aca 100644
--- a/Documentation/devicetree/bindings/arm/primecell.txt
+++ b/Documentation/devicetree/bindings/arm/primecell.txt
@@ -16,14 +16,31 @@ Optional properties:
 - clocks : From common clock binding. First clock is phandle to clock for apb
 	pclk. Additional clocks are optional and specific to those peripherals.
 - clock-names : From common clock binding. Shall be "apb_pclk" for first clock.
+- dmas : From common DMA binding. If present, refers to one or more dma channels.
+- dma-names : From common DMA binding, needs to match the 'dmas' property.
+              Devices with exactly one receive and transmit channel shall name
+              these "rx" and "tx", respectively.
+- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
+- pinctrl-names : Names corresponding to the numbered pinctrl states
+- interrupts : one or more interrupt specifiers
+- interrupt-names : names corresponding to the interrupts properties
 
 Example:
 
 serial@fff36000 {
 	compatible = "arm,pl011", "arm,primecell";
 	arm,primecell-periphid = <0x00341011>;
+
 	clocks = <&pclk>;
 	clock-names = "apb_pclk";
-	
+
+	dmas = <&dma-controller 4>, <&dma-controller 5>;
+	dma-names = "rx", "tx";	
+
+	pinctrl-0 = <&uart0_default_mux>, <&uart0_default_mode>;
+	pinctrl-1 = <&uart0_sleep_mode>;
+	pinctrl-names = "default","sleep";
+
+	interrupts = <0 11 0x4>;
 };
 
diff --git a/Documentation/devicetree/bindings/serial/pl011.txt b/Documentation/devicetree/bindings/serial/pl011.txt
new file mode 100644
index 0000000..5d2e840
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/pl011.txt
@@ -0,0 +1,17 @@
+* ARM AMBA Primecell PL011 serial UART
+
+Required properties:
+- compatible: must be "arm,primecell", "arm,pl011"
+- reg: exactly one register range with length 0x1000
+- interrupts: exactly one interrupt specifier
+
+Optional properties:
+- pinctrl: When present, must have one state named "sleep"
+	   and one state named "default"
+- clocks:  When present, must refer to exactly one clock named
+	   "apb_pclk"
+- dmas:	   When present, may have one or two dma channels.
+	   The first one must be named "rx", the second one
+	   must be named "tx".
+
+See also bindings/arm/primecell.txt
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 7fca402..f9af04d 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -245,7 +245,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
 	}
 }
 
-static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
+static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
 {
 	/* DMA is the sole user of the platform data right now */
 	struct amba_pl011_data *plat = uap->port.dev->platform_data;
@@ -259,20 +259,25 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 	struct dma_chan *chan;
 	dma_cap_mask_t mask;
 
-	/* We need platform data */
-	if (!plat || !plat->dma_filter) {
-		dev_info(uap->port.dev, "no DMA platform data\n");
-		return;
-	}
+	chan = dma_request_slave_channel(dev, "tx");
 
-	/* Try to acquire a generic DMA engine slave TX channel */
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
 	if (!chan) {
-		dev_err(uap->port.dev, "no TX DMA channel!\n");
-		return;
+		/* We need platform data */
+		if (!plat || !plat->dma_filter) {
+			dev_info(uap->port.dev, "no DMA platform data\n");
+			return;
+		}
+
+		/* Try to acquire a generic DMA engine slave TX channel */
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		chan = dma_request_channel(mask, plat->dma_filter,
+						plat->dma_tx_param);
+		if (!chan) {
+			dev_err(uap->port.dev, "no TX DMA channel!\n");
+			return;
+		}
 	}
 
 	dmaengine_slave_config(chan, &tx_conf);
@@ -282,7 +287,18 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 		 dma_chan_name(uap->dmatx.chan));
 
 	/* Optionally make use of an RX channel as well */
-	if (plat->dma_rx_param) {
+	chan = dma_request_slave_channel(dev, "rx");
+	
+	if (!chan && plat->dma_rx_param) {
+		chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
+
+		if (!chan) {
+			dev_err(uap->port.dev, "no RX DMA channel!\n");
+			return;
+		}
+	}
+
+	if (chan) {
 		struct dma_slave_config rx_conf = {
 			.src_addr = uap->port.mapbase + UART01x_DR,
 			.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@@ -291,12 +307,6 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 			.device_fc = false,
 		};
 
-		chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
-		if (!chan) {
-			dev_err(uap->port.dev, "no RX DMA channel!\n");
-			return;
-		}
-
 		dmaengine_slave_config(chan, &rx_conf);
 		uap->dmarx.chan = chan;
 
@@ -315,6 +325,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 struct dma_uap {
 	struct list_head node;
 	struct uart_amba_port *uap;
+	struct device *dev;
 };
 
 static LIST_HEAD(pl011_dma_uarts);
@@ -325,7 +336,7 @@ static int __init pl011_dma_initcall(void)
 
 	list_for_each_safe(node, tmp, &pl011_dma_uarts) {
 		struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
-		pl011_dma_probe_initcall(dmau->uap);
+		pl011_dma_probe_initcall(dmau->dev, dmau->uap);
 		list_del(node);
 		kfree(dmau);
 	}
@@ -334,18 +345,19 @@ static int __init pl011_dma_initcall(void)
 
 device_initcall(pl011_dma_initcall);
 
-static void pl011_dma_probe(struct uart_amba_port *uap)
+static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
 {
 	struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
 	if (dmau) {
 		dmau->uap = uap;
+		dmau->dev = dev;
 		list_add_tail(&dmau->node, &pl011_dma_uarts);
 	}
 }
 #else
-static void pl011_dma_probe(struct uart_amba_port *uap)
+static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
 {
-	pl011_dma_probe_initcall(uap);
+	pl011_dma_probe_initcall(dev, uap);
 }
 #endif
 
@@ -2023,7 +2035,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	uap->port.ops = &amba_pl011_pops;
 	uap->port.flags = UPF_BOOT_AUTOCONF;
 	uap->port.line = i;
-	pl011_dma_probe(uap);
+	pl011_dma_probe(&dev->dev, uap);
 
 	/* Ensure interrupts from this UART are masked and cleared */
 	writew(0, uap->port.membase + UART011_IMSC);
-- 
1.8.1.2


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

* [PATCH 4/4] serial: pl011: use generic DMA slave configuration if possible
@ 2013-02-15 18:21   ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-15 18:21 UTC (permalink / raw)
  To: linux-arm-kernel

With the new OF DMA binding, it is possible to completely avoid the
need for platform_data for configuring a DMA channel. In cases where the
platform has already been converted, calling dma_request_slave_channel
should get all the necessary information from the device tree.

This also adds a binding document specific to the pl011 controller,
and extends the generic primecell binding to mention "dmas" and other
common properties.

Like the patch that converts the dw_dma controller, this is completely
untested and is looking for someone to try it out.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: devicetree-discuss at lists.ozlabs.org
Cc: linux-arm-kernel at lists.infradead.org
---
 .../devicetree/bindings/arm/primecell.txt          | 19 ++++++-
 Documentation/devicetree/bindings/serial/pl011.txt | 17 ++++++
 drivers/tty/serial/amba-pl011.c                    | 62 +++++++++++++---------
 3 files changed, 72 insertions(+), 26 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/serial/pl011.txt

diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt
index 64fc82b..0df6aca 100644
--- a/Documentation/devicetree/bindings/arm/primecell.txt
+++ b/Documentation/devicetree/bindings/arm/primecell.txt
@@ -16,14 +16,31 @@ Optional properties:
 - clocks : From common clock binding. First clock is phandle to clock for apb
 	pclk. Additional clocks are optional and specific to those peripherals.
 - clock-names : From common clock binding. Shall be "apb_pclk" for first clock.
+- dmas : From common DMA binding. If present, refers to one or more dma channels.
+- dma-names : From common DMA binding, needs to match the 'dmas' property.
+              Devices with exactly one receive and transmit channel shall name
+              these "rx" and "tx", respectively.
+- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
+- pinctrl-names : Names corresponding to the numbered pinctrl states
+- interrupts : one or more interrupt specifiers
+- interrupt-names : names corresponding to the interrupts properties
 
 Example:
 
 serial at fff36000 {
 	compatible = "arm,pl011", "arm,primecell";
 	arm,primecell-periphid = <0x00341011>;
+
 	clocks = <&pclk>;
 	clock-names = "apb_pclk";
-	
+
+	dmas = <&dma-controller 4>, <&dma-controller 5>;
+	dma-names = "rx", "tx";	
+
+	pinctrl-0 = <&uart0_default_mux>, <&uart0_default_mode>;
+	pinctrl-1 = <&uart0_sleep_mode>;
+	pinctrl-names = "default","sleep";
+
+	interrupts = <0 11 0x4>;
 };
 
diff --git a/Documentation/devicetree/bindings/serial/pl011.txt b/Documentation/devicetree/bindings/serial/pl011.txt
new file mode 100644
index 0000000..5d2e840
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/pl011.txt
@@ -0,0 +1,17 @@
+* ARM AMBA Primecell PL011 serial UART
+
+Required properties:
+- compatible: must be "arm,primecell", "arm,pl011"
+- reg: exactly one register range with length 0x1000
+- interrupts: exactly one interrupt specifier
+
+Optional properties:
+- pinctrl: When present, must have one state named "sleep"
+	   and one state named "default"
+- clocks:  When present, must refer to exactly one clock named
+	   "apb_pclk"
+- dmas:	   When present, may have one or two dma channels.
+	   The first one must be named "rx", the second one
+	   must be named "tx".
+
+See also bindings/arm/primecell.txt
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 7fca402..f9af04d 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -245,7 +245,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
 	}
 }
 
-static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
+static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
 {
 	/* DMA is the sole user of the platform data right now */
 	struct amba_pl011_data *plat = uap->port.dev->platform_data;
@@ -259,20 +259,25 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 	struct dma_chan *chan;
 	dma_cap_mask_t mask;
 
-	/* We need platform data */
-	if (!plat || !plat->dma_filter) {
-		dev_info(uap->port.dev, "no DMA platform data\n");
-		return;
-	}
+	chan = dma_request_slave_channel(dev, "tx");
 
-	/* Try to acquire a generic DMA engine slave TX channel */
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
 	if (!chan) {
-		dev_err(uap->port.dev, "no TX DMA channel!\n");
-		return;
+		/* We need platform data */
+		if (!plat || !plat->dma_filter) {
+			dev_info(uap->port.dev, "no DMA platform data\n");
+			return;
+		}
+
+		/* Try to acquire a generic DMA engine slave TX channel */
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		chan = dma_request_channel(mask, plat->dma_filter,
+						plat->dma_tx_param);
+		if (!chan) {
+			dev_err(uap->port.dev, "no TX DMA channel!\n");
+			return;
+		}
 	}
 
 	dmaengine_slave_config(chan, &tx_conf);
@@ -282,7 +287,18 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 		 dma_chan_name(uap->dmatx.chan));
 
 	/* Optionally make use of an RX channel as well */
-	if (plat->dma_rx_param) {
+	chan = dma_request_slave_channel(dev, "rx");
+	
+	if (!chan && plat->dma_rx_param) {
+		chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
+
+		if (!chan) {
+			dev_err(uap->port.dev, "no RX DMA channel!\n");
+			return;
+		}
+	}
+
+	if (chan) {
 		struct dma_slave_config rx_conf = {
 			.src_addr = uap->port.mapbase + UART01x_DR,
 			.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@@ -291,12 +307,6 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 			.device_fc = false,
 		};
 
-		chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
-		if (!chan) {
-			dev_err(uap->port.dev, "no RX DMA channel!\n");
-			return;
-		}
-
 		dmaengine_slave_config(chan, &rx_conf);
 		uap->dmarx.chan = chan;
 
@@ -315,6 +325,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 struct dma_uap {
 	struct list_head node;
 	struct uart_amba_port *uap;
+	struct device *dev;
 };
 
 static LIST_HEAD(pl011_dma_uarts);
@@ -325,7 +336,7 @@ static int __init pl011_dma_initcall(void)
 
 	list_for_each_safe(node, tmp, &pl011_dma_uarts) {
 		struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
-		pl011_dma_probe_initcall(dmau->uap);
+		pl011_dma_probe_initcall(dmau->dev, dmau->uap);
 		list_del(node);
 		kfree(dmau);
 	}
@@ -334,18 +345,19 @@ static int __init pl011_dma_initcall(void)
 
 device_initcall(pl011_dma_initcall);
 
-static void pl011_dma_probe(struct uart_amba_port *uap)
+static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
 {
 	struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
 	if (dmau) {
 		dmau->uap = uap;
+		dmau->dev = dev;
 		list_add_tail(&dmau->node, &pl011_dma_uarts);
 	}
 }
 #else
-static void pl011_dma_probe(struct uart_amba_port *uap)
+static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
 {
-	pl011_dma_probe_initcall(uap);
+	pl011_dma_probe_initcall(dev, uap);
 }
 #endif
 
@@ -2023,7 +2035,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 	uap->port.ops = &amba_pl011_pops;
 	uap->port.flags = UPF_BOOT_AUTOCONF;
 	uap->port.line = i;
-	pl011_dma_probe(uap);
+	pl011_dma_probe(&dev->dev, uap);
 
 	/* Ensure interrupts from this UART are masked and cleared */
 	writew(0, uap->port.membase + UART011_IMSC);
-- 
1.8.1.2

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
  2013-02-15 18:21   ` Arnd Bergmann
@ 2013-02-16  3:26     ` Viresh Kumar
  -1 siblings, 0 replies; 53+ messages in thread
From: Viresh Kumar @ 2013-02-16  3:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Olof Johansson, linux-kernel, Andy Shevchenko, Vinod Koul

On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
> +- #dma-cells: must be <3>

> +DMA clients connected to the Designware DMA controller must use the format
> +described in the dma.txt file, using a five-cell specifier for each channel.

s/five/four ?

> +The four cells in order are:
> +
> +1. A phandle pointing to the DMA controller
> +2. The DMA request line number
> +3. Source master for transfers on allocated channel
> +4. Destination master for transfers on allocated channel

> diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c

> +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
>  {

> +       dws->cfg_hi     = 0xffffffff;
> +       dws->cfg_lo     = 0xffffffff;

s/0xffffffff/-1 ?

> +       dws->src_master = fargs->src;
> +       dws->dst_master = fargs->dst;
> +       dwc->req        = fargs->req;
>
> -                       return true;
> -               }
> -       }
> +       chan->private = dws;
> +
> +       return true;
> +}
> +
> +static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
> +                                        struct of_dma *ofdma)
> +{
> +       struct dw_dma *dw = ofdma->of_dma_data;
> +       struct dw_dma_filter_args fargs = {
> +               .dw = dw,
> +       };
> +       dma_cap_mask_t cap;
> +
> +       if (dma_spec->args_count != 3)
> +               return NULL;
> +
> +       fargs.req = be32_to_cpup(dma_spec->args+0);
> +       fargs.src = be32_to_cpup(dma_spec->args+1);
> +       fargs.dst = be32_to_cpup(dma_spec->args+2);
> +
> +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
> +               return NULL;
>
> -       last_dw = dw;
> -       last_bus_id = param;
> -       return false;
> +       dma_cap_zero(cap);
> +       dma_cap_set(DMA_SLAVE, cap);
> +
> +       /* TODO: there should be a simpler way to do this */
> +       return dma_request_channel(cap, dw_dma_generic_filter, &dma_spec->args[0]);
>  }
> -EXPORT_SYMBOL(dw_dma_generic_filter);
>
>  /* --------------------- Cyclic DMA API extensions -------------------- */
>
> @@ -1510,9 +1529,8 @@ static void dw_dma_off(struct dw_dma *dw)
>  static struct dw_dma_platform_data *
>  dw_dma_parse_dt(struct platform_device *pdev)
>  {
> -       struct device_node *sn, *cn, *np = pdev->dev.of_node;
> +       struct device_node *np = pdev->dev.of_node;
>         struct dw_dma_platform_data *pdata;
> -       struct dw_dma_slave *sd;
>         u32 tmp, arr[4];
>
>         if (!np) {
> @@ -1524,7 +1542,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
>         if (!pdata)
>                 return NULL;
>
> -       if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
> +       if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
>                 return NULL;

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16  3:26     ` Viresh Kumar
  0 siblings, 0 replies; 53+ messages in thread
From: Viresh Kumar @ 2013-02-16  3:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
> +- #dma-cells: must be <3>

> +DMA clients connected to the Designware DMA controller must use the format
> +described in the dma.txt file, using a five-cell specifier for each channel.

s/five/four ?

> +The four cells in order are:
> +
> +1. A phandle pointing to the DMA controller
> +2. The DMA request line number
> +3. Source master for transfers on allocated channel
> +4. Destination master for transfers on allocated channel

> diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c

> +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
>  {

> +       dws->cfg_hi     = 0xffffffff;
> +       dws->cfg_lo     = 0xffffffff;

s/0xffffffff/-1 ?

> +       dws->src_master = fargs->src;
> +       dws->dst_master = fargs->dst;
> +       dwc->req        = fargs->req;
>
> -                       return true;
> -               }
> -       }
> +       chan->private = dws;
> +
> +       return true;
> +}
> +
> +static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
> +                                        struct of_dma *ofdma)
> +{
> +       struct dw_dma *dw = ofdma->of_dma_data;
> +       struct dw_dma_filter_args fargs = {
> +               .dw = dw,
> +       };
> +       dma_cap_mask_t cap;
> +
> +       if (dma_spec->args_count != 3)
> +               return NULL;
> +
> +       fargs.req = be32_to_cpup(dma_spec->args+0);
> +       fargs.src = be32_to_cpup(dma_spec->args+1);
> +       fargs.dst = be32_to_cpup(dma_spec->args+2);
> +
> +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
> +               return NULL;
>
> -       last_dw = dw;
> -       last_bus_id = param;
> -       return false;
> +       dma_cap_zero(cap);
> +       dma_cap_set(DMA_SLAVE, cap);
> +
> +       /* TODO: there should be a simpler way to do this */
> +       return dma_request_channel(cap, dw_dma_generic_filter, &dma_spec->args[0]);
>  }
> -EXPORT_SYMBOL(dw_dma_generic_filter);
>
>  /* --------------------- Cyclic DMA API extensions -------------------- */
>
> @@ -1510,9 +1529,8 @@ static void dw_dma_off(struct dw_dma *dw)
>  static struct dw_dma_platform_data *
>  dw_dma_parse_dt(struct platform_device *pdev)
>  {
> -       struct device_node *sn, *cn, *np = pdev->dev.of_node;
> +       struct device_node *np = pdev->dev.of_node;
>         struct dw_dma_platform_data *pdata;
> -       struct dw_dma_slave *sd;
>         u32 tmp, arr[4];
>
>         if (!np) {
> @@ -1524,7 +1542,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
>         if (!pdata)
>                 return NULL;
>
> -       if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
> +       if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
>                 return NULL;

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

* Re: [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-16  3:26   ` Viresh Kumar
  0 siblings, 0 replies; 53+ messages in thread
From: Viresh Kumar @ 2013-02-16  3:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Olof Johansson, linux-kernel, Andy Shevchenko

On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> As Andy pointed out today, we don't have a good solution for the
> dw_dmac DT binding in linux-next yet. I have posted my series
> once before and then got distracted after getting feedback from
> Viresh, Andy and Russell. I have now updated my earlier patch
> based on the feedback and rebased on your tree without any
> of the arm-soc patches mixed in.

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

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

* Re: [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-16  3:26   ` Viresh Kumar
  0 siblings, 0 replies; 53+ messages in thread
From: Viresh Kumar @ 2013-02-16  3:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vinod Koul, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dan Williams,
	Andy Shevchenko,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 15 February 2013 23:51, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> As Andy pointed out today, we don't have a good solution for the
> dw_dmac DT binding in linux-next yet. I have posted my series
> once before and then got distracted after getting feedback from
> Viresh, Andy and Russell. I have now updated my earlier patch
> based on the feedback and rebased on your tree without any
> of the arm-soc patches mixed in.

Acked-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

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

* [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-16  3:26   ` Viresh Kumar
  0 siblings, 0 replies; 53+ messages in thread
From: Viresh Kumar @ 2013-02-16  3:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> As Andy pointed out today, we don't have a good solution for the
> dw_dmac DT binding in linux-next yet. I have posted my series
> once before and then got distracted after getting feedback from
> Viresh, Andy and Russell. I have now updated my earlier patch
> based on the feedback and rebased on your tree without any
> of the arm-soc patches mixed in.

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 10:07       ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 10:07 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Olof Johansson, linux-kernel, Andy Shevchenko, Vinod Koul

On Saturday 16 February 2013, Viresh Kumar wrote:
> On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> > diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
> > +- #dma-cells: must be <3>
> 
> > +DMA clients connected to the Designware DMA controller must use the format
> > +described in the dma.txt file, using a five-cell specifier for each channel.
> 
> s/five/four ?

Right. I thought I had fixed up all instances.

> > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> >  {
> 
> > +       dws->cfg_hi     = 0xffffffff;
> > +       dws->cfg_lo     = 0xffffffff;
> 
> s/0xffffffff/-1 ?

It's an 'unsigned int'. While -1 would work here, I always find it a little
odd to rely on that feature of the C language.

Thannks for the review.

	Arnd

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 10:07       ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 10:07 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Vinod Koul, Vinod Koul,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dan Williams,
	Andy Shevchenko,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Saturday 16 February 2013, Viresh Kumar wrote:
> On 15 February 2013 23:51, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> > diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
> > +- #dma-cells: must be <3>
> 
> > +DMA clients connected to the Designware DMA controller must use the format
> > +described in the dma.txt file, using a five-cell specifier for each channel.
> 
> s/five/four ?

Right. I thought I had fixed up all instances.

> > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> >  {
> 
> > +       dws->cfg_hi     = 0xffffffff;
> > +       dws->cfg_lo     = 0xffffffff;
> 
> s/0xffffffff/-1 ?

It's an 'unsigned int'. While -1 would work here, I always find it a little
odd to rely on that feature of the C language.

Thannks for the review.

	Arnd

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 10:07       ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 16 February 2013, Viresh Kumar wrote:
> On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> > diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
> > +- #dma-cells: must be <3>
> 
> > +DMA clients connected to the Designware DMA controller must use the format
> > +described in the dma.txt file, using a five-cell specifier for each channel.
> 
> s/five/four ?

Right. I thought I had fixed up all instances.

> > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> >  {
> 
> > +       dws->cfg_hi     = 0xffffffff;
> > +       dws->cfg_lo     = 0xffffffff;
> 
> s/0xffffffff/-1 ?

It's an 'unsigned int'. While -1 would work here, I always find it a little
odd to rely on that feature of the C language.

Thannks for the review.

	Arnd

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 10:51         ` Russell King - ARM Linux
  0 siblings, 0 replies; 53+ messages in thread
From: Russell King - ARM Linux @ 2013-02-16 10:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Viresh Kumar, Vinod Koul, Vinod Koul, devicetree-discuss,
	linux-kernel, Dan Williams, Olof Johansson, Andy Shevchenko,
	linux-arm-kernel

On Sat, Feb 16, 2013 at 10:07:39AM +0000, Arnd Bergmann wrote:
> On Saturday 16 February 2013, Viresh Kumar wrote:
> > On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> > > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> > >  {
> > 
> > > +       dws->cfg_hi     = 0xffffffff;
> > > +       dws->cfg_lo     = 0xffffffff;
> > 
> > s/0xffffffff/-1 ?
> 
> It's an 'unsigned int'. While -1 would work here, I always find it a little
> odd to rely on that feature of the C language.

However, relying on an 'int' being 32-bits is also rather odd, and
probably much more dubious too.  If you want to set all bits in an
int, the portable way to do that is ~0.

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 10:51         ` Russell King - ARM Linux
  0 siblings, 0 replies; 53+ messages in thread
From: Russell King - ARM Linux @ 2013-02-16 10:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vinod Koul, Vinod Koul, Viresh Kumar,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dan Williams,
	Andy Shevchenko,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Sat, Feb 16, 2013 at 10:07:39AM +0000, Arnd Bergmann wrote:
> On Saturday 16 February 2013, Viresh Kumar wrote:
> > On 15 February 2013 23:51, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> > > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> > >  {
> > 
> > > +       dws->cfg_hi     = 0xffffffff;
> > > +       dws->cfg_lo     = 0xffffffff;
> > 
> > s/0xffffffff/-1 ?
> 
> It's an 'unsigned int'. While -1 would work here, I always find it a little
> odd to rely on that feature of the C language.

However, relying on an 'int' being 32-bits is also rather odd, and
probably much more dubious too.  If you want to set all bits in an
int, the portable way to do that is ~0.

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 10:51         ` Russell King - ARM Linux
  0 siblings, 0 replies; 53+ messages in thread
From: Russell King - ARM Linux @ 2013-02-16 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Feb 16, 2013 at 10:07:39AM +0000, Arnd Bergmann wrote:
> On Saturday 16 February 2013, Viresh Kumar wrote:
> > On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> > > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> > >  {
> > 
> > > +       dws->cfg_hi     = 0xffffffff;
> > > +       dws->cfg_lo     = 0xffffffff;
> > 
> > s/0xffffffff/-1 ?
> 
> It's an 'unsigned int'. While -1 would work here, I always find it a little
> odd to rely on that feature of the C language.

However, relying on an 'int' being 32-bits is also rather odd, and
probably much more dubious too.  If you want to set all bits in an
int, the portable way to do that is ~0.

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 11:13     ` Andy Shevchenko
  0 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2013-02-16 11:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Viresh Kumar, Olof Johansson, linux-kernel, Andy Shevchenko,
	Vinod Koul

On Fri, Feb 15, 2013 at 8:21 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> The original device tree binding for this driver, from Viresh Kumar
> unfortunately conflicted with the generic DMA binding, and did not allow
> to completely seperate slave device configuration from the controller.
>
> This is an attempt to replace it with an implementation of the generic
> binding, but it is currently completely untested, because I do not have
> any hardware with this particular controller.
>
> The patch applies on top of linux-next, which contains both the base
> support for the generic DMA binding, as well as the earlier attempt from
> Viresh. Both of these are currently not merged upstream however.
>
> There are a couple of TODO items that are left remaining and are open
> for ideas from other people.

> --- a/drivers/dma/dw_dmac.c
> +++ b/drivers/dma/dw_dmac.c

> @@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
>         if (dwc->initialized == true)
>                 return;
>
> -       if (dws) {
> +       if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
> +               /* autoconfigure based on request line from DT */
> +               if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
> +                       cfghi = DWC_CFGH_DST_PER(dwc->req);
> +               else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
> +                       cfghi = DWC_CFGH_SRC_PER(dwc->req);

Please, use dwc->direction instead of field in the slave_config. If I
remember correctly it's marked like obsoleted/deprecated.

> @@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
>         dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
>  }
>
> -bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> +struct dw_dma_filter_args {
> +       struct dw_dma *dw;
> +       u32 req;

Why this is u32 and not unsigned int?

> +       u32 src;
> +       u32 dst;

And this could be also just unsigned int.

> +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
>  {

> +       dws->cfg_hi     = 0xffffffff;
> +       dws->cfg_lo     = 0xffffffff;

Agree with Russell about ~0.

> +static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
> +                                        struct of_dma *ofdma)
> +{
> +       struct dw_dma *dw = ofdma->of_dma_data;
> +       struct dw_dma_filter_args fargs = {
> +               .dw = dw,
> +       };
> +       dma_cap_mask_t cap;
> +
> +       if (dma_spec->args_count != 3)
> +               return NULL;
> +
> +       fargs.req = be32_to_cpup(dma_spec->args+0);
> +       fargs.src = be32_to_cpup(dma_spec->args+1);
> +       fargs.dst = be32_to_cpup(dma_spec->args+2);

You could cast them to usual C types like unsigned int. I see u32 in
rare cases in the driver like for reading/writting from/to hw and when
API contains it. Here I doubt we have to leave them as u32.

> +
> +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
> +               return NULL;

16 here is a magic number for me. I would like to see something like
#define DW_MAX_REQUEST_LINES 16 in the dw_dmac_regs.h.

Besides of that, what 2 does come from?

> @@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
>
>         dma_async_device_register(&dw->dma);
>
> +       err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
> +       if (err)
> +               dev_err(&pdev->dev, "could not register of_dma_controller\n");

It's not an error, dev_dbg. Consider case when !CONFIG_OF.

> --- a/drivers/dma/dw_dmac_regs.h
> +++ b/drivers/dma/dw_dmac_regs.h
> @@ -213,6 +213,10 @@ struct dw_dma_chan {
>         /* configuration passed via DMA_SLAVE_CONFIG */
>         struct dma_slave_config dma_sconfig;
>
> +       /* slave configuration from DT */
> +       unsigned int            req;

Could you use here full name like "request_line"? And I think the
better place for it in subsection "hardware configuration" (consider
non-DT cases of use).

>         /* backlink to dw_dma */
>         struct dw_dma           *dw;
>  };

We should not have this in linux-next. Are you sure you rebased it on
top of recent one?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 11:13     ` Andy Shevchenko
  0 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2013-02-16 11:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vinod Koul, Vinod Koul, Viresh Kumar,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dan Williams,
	Andy Shevchenko,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Fri, Feb 15, 2013 at 8:21 PM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
> The original device tree binding for this driver, from Viresh Kumar
> unfortunately conflicted with the generic DMA binding, and did not allow
> to completely seperate slave device configuration from the controller.
>
> This is an attempt to replace it with an implementation of the generic
> binding, but it is currently completely untested, because I do not have
> any hardware with this particular controller.
>
> The patch applies on top of linux-next, which contains both the base
> support for the generic DMA binding, as well as the earlier attempt from
> Viresh. Both of these are currently not merged upstream however.
>
> There are a couple of TODO items that are left remaining and are open
> for ideas from other people.

> --- a/drivers/dma/dw_dmac.c
> +++ b/drivers/dma/dw_dmac.c

> @@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
>         if (dwc->initialized == true)
>                 return;
>
> -       if (dws) {
> +       if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
> +               /* autoconfigure based on request line from DT */
> +               if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
> +                       cfghi = DWC_CFGH_DST_PER(dwc->req);
> +               else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
> +                       cfghi = DWC_CFGH_SRC_PER(dwc->req);

Please, use dwc->direction instead of field in the slave_config. If I
remember correctly it's marked like obsoleted/deprecated.

> @@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
>         dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
>  }
>
> -bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> +struct dw_dma_filter_args {
> +       struct dw_dma *dw;
> +       u32 req;

Why this is u32 and not unsigned int?

> +       u32 src;
> +       u32 dst;

And this could be also just unsigned int.

> +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
>  {

> +       dws->cfg_hi     = 0xffffffff;
> +       dws->cfg_lo     = 0xffffffff;

Agree with Russell about ~0.

> +static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
> +                                        struct of_dma *ofdma)
> +{
> +       struct dw_dma *dw = ofdma->of_dma_data;
> +       struct dw_dma_filter_args fargs = {
> +               .dw = dw,
> +       };
> +       dma_cap_mask_t cap;
> +
> +       if (dma_spec->args_count != 3)
> +               return NULL;
> +
> +       fargs.req = be32_to_cpup(dma_spec->args+0);
> +       fargs.src = be32_to_cpup(dma_spec->args+1);
> +       fargs.dst = be32_to_cpup(dma_spec->args+2);

You could cast them to usual C types like unsigned int. I see u32 in
rare cases in the driver like for reading/writting from/to hw and when
API contains it. Here I doubt we have to leave them as u32.

> +
> +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
> +               return NULL;

16 here is a magic number for me. I would like to see something like
#define DW_MAX_REQUEST_LINES 16 in the dw_dmac_regs.h.

Besides of that, what 2 does come from?

> @@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
>
>         dma_async_device_register(&dw->dma);
>
> +       err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
> +       if (err)
> +               dev_err(&pdev->dev, "could not register of_dma_controller\n");

It's not an error, dev_dbg. Consider case when !CONFIG_OF.

> --- a/drivers/dma/dw_dmac_regs.h
> +++ b/drivers/dma/dw_dmac_regs.h
> @@ -213,6 +213,10 @@ struct dw_dma_chan {
>         /* configuration passed via DMA_SLAVE_CONFIG */
>         struct dma_slave_config dma_sconfig;
>
> +       /* slave configuration from DT */
> +       unsigned int            req;

Could you use here full name like "request_line"? And I think the
better place for it in subsection "hardware configuration" (consider
non-DT cases of use).

>         /* backlink to dw_dma */
>         struct dw_dma           *dw;
>  };

We should not have this in linux-next. Are you sure you rebased it on
top of recent one?

-- 
With Best Regards,
Andy Shevchenko

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 11:13     ` Andy Shevchenko
  0 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2013-02-16 11:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 15, 2013 at 8:21 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> The original device tree binding for this driver, from Viresh Kumar
> unfortunately conflicted with the generic DMA binding, and did not allow
> to completely seperate slave device configuration from the controller.
>
> This is an attempt to replace it with an implementation of the generic
> binding, but it is currently completely untested, because I do not have
> any hardware with this particular controller.
>
> The patch applies on top of linux-next, which contains both the base
> support for the generic DMA binding, as well as the earlier attempt from
> Viresh. Both of these are currently not merged upstream however.
>
> There are a couple of TODO items that are left remaining and are open
> for ideas from other people.

> --- a/drivers/dma/dw_dmac.c
> +++ b/drivers/dma/dw_dmac.c

> @@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
>         if (dwc->initialized == true)
>                 return;
>
> -       if (dws) {
> +       if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
> +               /* autoconfigure based on request line from DT */
> +               if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
> +                       cfghi = DWC_CFGH_DST_PER(dwc->req);
> +               else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
> +                       cfghi = DWC_CFGH_SRC_PER(dwc->req);

Please, use dwc->direction instead of field in the slave_config. If I
remember correctly it's marked like obsoleted/deprecated.

> @@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
>         dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
>  }
>
> -bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> +struct dw_dma_filter_args {
> +       struct dw_dma *dw;
> +       u32 req;

Why this is u32 and not unsigned int?

> +       u32 src;
> +       u32 dst;

And this could be also just unsigned int.

> +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
>  {

> +       dws->cfg_hi     = 0xffffffff;
> +       dws->cfg_lo     = 0xffffffff;

Agree with Russell about ~0.

> +static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
> +                                        struct of_dma *ofdma)
> +{
> +       struct dw_dma *dw = ofdma->of_dma_data;
> +       struct dw_dma_filter_args fargs = {
> +               .dw = dw,
> +       };
> +       dma_cap_mask_t cap;
> +
> +       if (dma_spec->args_count != 3)
> +               return NULL;
> +
> +       fargs.req = be32_to_cpup(dma_spec->args+0);
> +       fargs.src = be32_to_cpup(dma_spec->args+1);
> +       fargs.dst = be32_to_cpup(dma_spec->args+2);

You could cast them to usual C types like unsigned int. I see u32 in
rare cases in the driver like for reading/writting from/to hw and when
API contains it. Here I doubt we have to leave them as u32.

> +
> +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
> +               return NULL;

16 here is a magic number for me. I would like to see something like
#define DW_MAX_REQUEST_LINES 16 in the dw_dmac_regs.h.

Besides of that, what 2 does come from?

> @@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
>
>         dma_async_device_register(&dw->dma);
>
> +       err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
> +       if (err)
> +               dev_err(&pdev->dev, "could not register of_dma_controller\n");

It's not an error, dev_dbg. Consider case when !CONFIG_OF.

> --- a/drivers/dma/dw_dmac_regs.h
> +++ b/drivers/dma/dw_dmac_regs.h
> @@ -213,6 +213,10 @@ struct dw_dma_chan {
>         /* configuration passed via DMA_SLAVE_CONFIG */
>         struct dma_slave_config dma_sconfig;
>
> +       /* slave configuration from DT */
> +       unsigned int            req;

Could you use here full name like "request_line"? And I think the
better place for it in subsection "hardware configuration" (consider
non-DT cases of use).

>         /* backlink to dw_dma */
>         struct dw_dma           *dw;
>  };

We should not have this in linux-next. Are you sure you rebased it on
top of recent one?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
  2013-02-16 10:51         ` Russell King - ARM Linux
@ 2013-02-16 13:43           ` Arnd Bergmann
  -1 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 13:43 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Viresh Kumar, Vinod Koul, Vinod Koul, devicetree-discuss,
	linux-kernel, Dan Williams, Olof Johansson, Andy Shevchenko,
	linux-arm-kernel

On Saturday 16 February 2013, Russell King - ARM Linux wrote:
> On Sat, Feb 16, 2013 at 10:07:39AM +0000, Arnd Bergmann wrote:
> > On Saturday 16 February 2013, Viresh Kumar wrote:
> > > On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> > > > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> > > >  {
> > > 
> > > > +       dws->cfg_hi     = 0xffffffff;
> > > > +       dws->cfg_lo     = 0xffffffff;
> > > 
> > > s/0xffffffff/-1 ?
> > 
> > It's an 'unsigned int'. While -1 would work here, I always find it a little
> > odd to rely on that feature of the C language.
> 
> However, relying on an 'int' being 32-bits is also rather odd, and
> probably much more dubious too.  If you want to set all bits in an
> int, the portable way to do that is ~0.

Right, I can do that, too. All I really need here though is to make sure
I use the same value in this place and when comparing it in dwc_initialize,
and it needs to be something that cannot be a valid register setting.

Thanks,

	Arnd

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 13:43           ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 16 February 2013, Russell King - ARM Linux wrote:
> On Sat, Feb 16, 2013 at 10:07:39AM +0000, Arnd Bergmann wrote:
> > On Saturday 16 February 2013, Viresh Kumar wrote:
> > > On 15 February 2013 23:51, Arnd Bergmann <arnd@arndb.de> wrote:
> > > > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> > > >  {
> > > 
> > > > +       dws->cfg_hi     = 0xffffffff;
> > > > +       dws->cfg_lo     = 0xffffffff;
> > > 
> > > s/0xffffffff/-1 ?
> > 
> > It's an 'unsigned int'. While -1 would work here, I always find it a little
> > odd to rely on that feature of the C language.
> 
> However, relying on an 'int' being 32-bits is also rather odd, and
> probably much more dubious too.  If you want to set all bits in an
> int, the portable way to do that is ~0.

Right, I can do that, too. All I really need here though is to make sure
I use the same value in this place and when comparing it in dwc_initialize,
and it needs to be something that cannot be a valid register setting.

Thanks,

	Arnd

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 14:00       ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 14:00 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Viresh Kumar, Olof Johansson, linux-kernel, Andy Shevchenko,
	Vinod Koul

On Saturday 16 February 2013, Andy Shevchenko wrote:
> On Fri, Feb 15, 2013 at 8:21 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>
> > @@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
> >         if (dwc->initialized == true)
> >                 return;
> >
> > -       if (dws) {
> > +       if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
> > +               /* autoconfigure based on request line from DT */
> > +               if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
> > +                       cfghi = DWC_CFGH_DST_PER(dwc->req);
> > +               else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
> > +                       cfghi = DWC_CFGH_SRC_PER(dwc->req);
> 
> Please, use dwc->direction instead of field in the slave_config. If I
> remember correctly it's marked like obsoleted/deprecated.

Ok, that's easy to change. I was copying from the code you added
a few lines below, but was using an older version than the one where
you had made the change to use dwc->direction.

> > @@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
> >         dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
> >  }
> >
> > -bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> > +struct dw_dma_filter_args {
> > +       struct dw_dma *dw;
> > +       u32 req;
> 
> Why this is u32 and not unsigned int?
> 
> > +       u32 src;
> > +       u32 dst;
> 
> And this could be also just unsigned int.

I was using u32 since I copied the values from a 32 bit
DT property value. I'll change it to unsigned int.

> > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> >  {
> 
> > +       dws->cfg_hi     = 0xffffffff;
> > +       dws->cfg_lo     = 0xffffffff;
> 
> Agree with Russell about ~0.

ok.

> > +static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
> > +                                        struct of_dma *ofdma)
> > +{
> > +       struct dw_dma *dw = ofdma->of_dma_data;
> > +       struct dw_dma_filter_args fargs = {
> > +               .dw = dw,
> > +       };
> > +       dma_cap_mask_t cap;
> > +
> > +       if (dma_spec->args_count != 3)
> > +               return NULL;
> > +
> > +       fargs.req = be32_to_cpup(dma_spec->args+0);
> > +       fargs.src = be32_to_cpup(dma_spec->args+1);
> > +       fargs.dst = be32_to_cpup(dma_spec->args+2);
> 
> You could cast them to usual C types like unsigned int. I see u32 in
> rare cases in the driver like for reading/writting from/to hw and when
> API contains it. Here I doubt we have to leave them as u32.

Right. 

> > +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
> > +               return NULL;
> 
> 16 here is a magic number for me. I would like to see something like
> #define DW_MAX_REQUEST_LINES 16 in the dw_dmac_regs.h.

Ok.

> Besides of that, what 2 does come from?

I thought that Viresh had commented that there could only be two masters.
It's probably best to compare against dw->nr_masters here.

> > @@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
> >
> >         dma_async_device_register(&dw->dma);
> >
> > +       err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
> > +       if (err)
> > +               dev_err(&pdev->dev, "could not register of_dma_controller\n");
> 
> It's not an error, dev_dbg. Consider case when !CONFIG_OF.

Ah right. I expected of_dma_controller_register to return 0 in that case, but
it returns -ENODEV. How about I change this to this?

	if (pdev->dev.of_node)
		err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
	if (err && err != -ENODEV)
		dev_err(&pdev->dev, "could not register of_dma_controller\n");

That would warn only when we have a dw_dmac device that was registered from
device tree but does not follow the binding or gets an -ENOMEM.

> > --- a/drivers/dma/dw_dmac_regs.h
> > +++ b/drivers/dma/dw_dmac_regs.h
> > @@ -213,6 +213,10 @@ struct dw_dma_chan {
> >         /* configuration passed via DMA_SLAVE_CONFIG */
> >         struct dma_slave_config dma_sconfig;
> >
> > +       /* slave configuration from DT */
> > +       unsigned int            req;
> 
> Could you use here full name like "request_line"? And I think the
> better place for it in subsection "hardware configuration" (consider
> non-DT cases of use).

Ok

> 
> >         /* backlink to dw_dma */
> >         struct dw_dma           *dw;
> >  };
> 
> We should not have this in linux-next. Are you sure you rebased it on
> top of recent one?

I was basing on the earliest commit that had Viresh's changes in it.
I'll rebase on top of Vinod's branch now.

Thanks for your review!

	Arnd

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 14:00       ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 14:00 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vinod Koul, Vinod Koul, Viresh Kumar,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dan Williams,
	Andy Shevchenko,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Saturday 16 February 2013, Andy Shevchenko wrote:
> On Fri, Feb 15, 2013 at 8:21 PM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
>
> > @@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
> >         if (dwc->initialized == true)
> >                 return;
> >
> > -       if (dws) {
> > +       if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
> > +               /* autoconfigure based on request line from DT */
> > +               if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
> > +                       cfghi = DWC_CFGH_DST_PER(dwc->req);
> > +               else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
> > +                       cfghi = DWC_CFGH_SRC_PER(dwc->req);
> 
> Please, use dwc->direction instead of field in the slave_config. If I
> remember correctly it's marked like obsoleted/deprecated.

Ok, that's easy to change. I was copying from the code you added
a few lines below, but was using an older version than the one where
you had made the change to use dwc->direction.

> > @@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
> >         dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
> >  }
> >
> > -bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> > +struct dw_dma_filter_args {
> > +       struct dw_dma *dw;
> > +       u32 req;
> 
> Why this is u32 and not unsigned int?
> 
> > +       u32 src;
> > +       u32 dst;
> 
> And this could be also just unsigned int.

I was using u32 since I copied the values from a 32 bit
DT property value. I'll change it to unsigned int.

> > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> >  {
> 
> > +       dws->cfg_hi     = 0xffffffff;
> > +       dws->cfg_lo     = 0xffffffff;
> 
> Agree with Russell about ~0.

ok.

> > +static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
> > +                                        struct of_dma *ofdma)
> > +{
> > +       struct dw_dma *dw = ofdma->of_dma_data;
> > +       struct dw_dma_filter_args fargs = {
> > +               .dw = dw,
> > +       };
> > +       dma_cap_mask_t cap;
> > +
> > +       if (dma_spec->args_count != 3)
> > +               return NULL;
> > +
> > +       fargs.req = be32_to_cpup(dma_spec->args+0);
> > +       fargs.src = be32_to_cpup(dma_spec->args+1);
> > +       fargs.dst = be32_to_cpup(dma_spec->args+2);
> 
> You could cast them to usual C types like unsigned int. I see u32 in
> rare cases in the driver like for reading/writting from/to hw and when
> API contains it. Here I doubt we have to leave them as u32.

Right. 

> > +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
> > +               return NULL;
> 
> 16 here is a magic number for me. I would like to see something like
> #define DW_MAX_REQUEST_LINES 16 in the dw_dmac_regs.h.

Ok.

> Besides of that, what 2 does come from?

I thought that Viresh had commented that there could only be two masters.
It's probably best to compare against dw->nr_masters here.

> > @@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
> >
> >         dma_async_device_register(&dw->dma);
> >
> > +       err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
> > +       if (err)
> > +               dev_err(&pdev->dev, "could not register of_dma_controller\n");
> 
> It's not an error, dev_dbg. Consider case when !CONFIG_OF.

Ah right. I expected of_dma_controller_register to return 0 in that case, but
it returns -ENODEV. How about I change this to this?

	if (pdev->dev.of_node)
		err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
	if (err && err != -ENODEV)
		dev_err(&pdev->dev, "could not register of_dma_controller\n");

That would warn only when we have a dw_dmac device that was registered from
device tree but does not follow the binding or gets an -ENOMEM.

> > --- a/drivers/dma/dw_dmac_regs.h
> > +++ b/drivers/dma/dw_dmac_regs.h
> > @@ -213,6 +213,10 @@ struct dw_dma_chan {
> >         /* configuration passed via DMA_SLAVE_CONFIG */
> >         struct dma_slave_config dma_sconfig;
> >
> > +       /* slave configuration from DT */
> > +       unsigned int            req;
> 
> Could you use here full name like "request_line"? And I think the
> better place for it in subsection "hardware configuration" (consider
> non-DT cases of use).

Ok

> 
> >         /* backlink to dw_dma */
> >         struct dw_dma           *dw;
> >  };
> 
> We should not have this in linux-next. Are you sure you rebased it on
> top of recent one?

I was basing on the earliest commit that had Viresh's changes in it.
I'll rebase on top of Vinod's branch now.

Thanks for your review!

	Arnd

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 14:00       ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 14:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 16 February 2013, Andy Shevchenko wrote:
> On Fri, Feb 15, 2013 at 8:21 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>
> > @@ -168,7 +169,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
> >         if (dwc->initialized == true)
> >                 return;
> >
> > -       if (dws) {
> > +       if (dws && dws->cfg_hi == 0xffffffff && dws->cfg_lo == 0xffffffff) {
> > +               /* autoconfigure based on request line from DT */
> > +               if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
> > +                       cfghi = DWC_CFGH_DST_PER(dwc->req);
> > +               else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
> > +                       cfghi = DWC_CFGH_SRC_PER(dwc->req);
> 
> Please, use dwc->direction instead of field in the slave_config. If I
> remember correctly it's marked like obsoleted/deprecated.

Ok, that's easy to change. I was copying from the code you added
a few lines below, but was using an older version than the one where
you had made the change to use dwc->direction.

> > @@ -1179,49 +1186,61 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
> >         dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
> >  }
> >
> > -bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> > +struct dw_dma_filter_args {
> > +       struct dw_dma *dw;
> > +       u32 req;
> 
> Why this is u32 and not unsigned int?
> 
> > +       u32 src;
> > +       u32 dst;
> 
> And this could be also just unsigned int.

I was using u32 since I copied the values from a 32 bit
DT property value. I'll change it to unsigned int.

> > +static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
> >  {
> 
> > +       dws->cfg_hi     = 0xffffffff;
> > +       dws->cfg_lo     = 0xffffffff;
> 
> Agree with Russell about ~0.

ok.

> > +static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
> > +                                        struct of_dma *ofdma)
> > +{
> > +       struct dw_dma *dw = ofdma->of_dma_data;
> > +       struct dw_dma_filter_args fargs = {
> > +               .dw = dw,
> > +       };
> > +       dma_cap_mask_t cap;
> > +
> > +       if (dma_spec->args_count != 3)
> > +               return NULL;
> > +
> > +       fargs.req = be32_to_cpup(dma_spec->args+0);
> > +       fargs.src = be32_to_cpup(dma_spec->args+1);
> > +       fargs.dst = be32_to_cpup(dma_spec->args+2);
> 
> You could cast them to usual C types like unsigned int. I see u32 in
> rare cases in the driver like for reading/writting from/to hw and when
> API contains it. Here I doubt we have to leave them as u32.

Right. 

> > +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
> > +               return NULL;
> 
> 16 here is a magic number for me. I would like to see something like
> #define DW_MAX_REQUEST_LINES 16 in the dw_dmac_regs.h.

Ok.

> Besides of that, what 2 does come from?

I thought that Viresh had commented that there could only be two masters.
It's probably best to compare against dw->nr_masters here.

> > @@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
> >
> >         dma_async_device_register(&dw->dma);
> >
> > +       err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
> > +       if (err)
> > +               dev_err(&pdev->dev, "could not register of_dma_controller\n");
> 
> It's not an error, dev_dbg. Consider case when !CONFIG_OF.

Ah right. I expected of_dma_controller_register to return 0 in that case, but
it returns -ENODEV. How about I change this to this?

	if (pdev->dev.of_node)
		err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
	if (err && err != -ENODEV)
		dev_err(&pdev->dev, "could not register of_dma_controller\n");

That would warn only when we have a dw_dmac device that was registered from
device tree but does not follow the binding or gets an -ENOMEM.

> > --- a/drivers/dma/dw_dmac_regs.h
> > +++ b/drivers/dma/dw_dmac_regs.h
> > @@ -213,6 +213,10 @@ struct dw_dma_chan {
> >         /* configuration passed via DMA_SLAVE_CONFIG */
> >         struct dma_slave_config dma_sconfig;
> >
> > +       /* slave configuration from DT */
> > +       unsigned int            req;
> 
> Could you use here full name like "request_line"? And I think the
> better place for it in subsection "hardware configuration" (consider
> non-DT cases of use).

Ok

> 
> >         /* backlink to dw_dma */
> >         struct dw_dma           *dw;
> >  };
> 
> We should not have this in linux-next. Are you sure you rebased it on
> top of recent one?

I was basing on the earliest commit that had Viresh's changes in it.
I'll rebase on top of Vinod's branch now.

Thanks for your review!

	Arnd

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

* Re: [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
  2013-02-16 14:00       ` Arnd Bergmann
@ 2013-02-16 14:53         ` Andy Shevchenko
  -1 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2013-02-16 14:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Viresh Kumar, Olof Johansson, linux-kernel, Andy Shevchenko,
	Vinod Koul

On Sat, Feb 16, 2013 at 4:00 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Saturday 16 February 2013, Andy Shevchenko wrote:
>> On Fri, Feb 15, 2013 at 8:21 PM, Arnd Bergmann <arnd@arndb.de> wrote:

>> > +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
>> > +               return NULL;
>>
>> 16 here is a magic number for me. I would like to see something like
>> #define DW_MAX_REQUEST_LINES 16 in the dw_dmac_regs.h.
>
> Ok.
>
>> Besides of that, what 2 does come from?
>
> I thought that Viresh had commented that there could only be two masters.
> It's probably best to compare against dw->nr_masters here.

Right.

>> > @@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
>> >
>> >         dma_async_device_register(&dw->dma);
>> >
>> > +       err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
>> > +       if (err)
>> > +               dev_err(&pdev->dev, "could not register of_dma_controller\n");
>>
>> It's not an error, dev_dbg. Consider case when !CONFIG_OF.
>
> Ah right. I expected of_dma_controller_register to return 0 in that case, but
> it returns -ENODEV. How about I change this to this?
>
>         if (pdev->dev.of_node)
>                 err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
>         if (err && err != -ENODEV)
>                 dev_err(&pdev->dev, "could not register of_dma_controller\n");
>
> That would warn only when we have a dw_dmac device that was registered from
> device tree but does not follow the binding or gets an -ENOMEM.

I'm okay with it.

> Thanks for your review!

Thanks for the patch!

-- 
With Best Regards,
Andy Shevchenko

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

* [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 14:53         ` Andy Shevchenko
  0 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2013-02-16 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Feb 16, 2013 at 4:00 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Saturday 16 February 2013, Andy Shevchenko wrote:
>> On Fri, Feb 15, 2013 at 8:21 PM, Arnd Bergmann <arnd@arndb.de> wrote:

>> > +       if (WARN_ON(fargs.req >= 16 || fargs.src >= 2 || fargs.dst >= 2))
>> > +               return NULL;
>>
>> 16 here is a magic number for me. I would like to see something like
>> #define DW_MAX_REQUEST_LINES 16 in the dw_dmac_regs.h.
>
> Ok.
>
>> Besides of that, what 2 does come from?
>
> I thought that Viresh had commented that there could only be two masters.
> It's probably best to compare against dw->nr_masters here.

Right.

>> > @@ -1765,6 +1751,10 @@ static int dw_probe(struct platform_device *pdev)
>> >
>> >         dma_async_device_register(&dw->dma);
>> >
>> > +       err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
>> > +       if (err)
>> > +               dev_err(&pdev->dev, "could not register of_dma_controller\n");
>>
>> It's not an error, dev_dbg. Consider case when !CONFIG_OF.
>
> Ah right. I expected of_dma_controller_register to return 0 in that case, but
> it returns -ENODEV. How about I change this to this?
>
>         if (pdev->dev.of_node)
>                 err = of_dma_controller_register(pdev->dev.of_node, dw_dma_xlate, dw);
>         if (err && err != -ENODEV)
>                 dev_err(&pdev->dev, "could not register of_dma_controller\n");
>
> That would warn only when we have a dw_dmac device that was registered from
> device tree but does not follow the binding or gets an -ENOMEM.

I'm okay with it.

> Thanks for your review!

Thanks for the patch!

-- 
With Best Regards,
Andy Shevchenko

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

* [PATCHv3 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 22:21           ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 22:21 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Viresh Kumar, Olof Johansson, linux-kernel, Andy Shevchenko,
	Vinod Koul

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of the slave-dma tree, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

This version incorporates feedback from Viresh Kumar, Andy Shevchenko
and Russell King.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 +++++-----
 drivers/dma/dw_dmac.c                              | 142 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |  11 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 112 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..d58675e 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma@fc000000 {
+	dmahost: dma@fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a four-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial@e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 4c83f18..72d6abf 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -170,7 +171,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
+		else if (dwc->direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1225,49 +1232,64 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	unsigned int req;
+	unsigned int src;
+	unsigned int dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* ensure the device matches our channel */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= ~0;
+	dws->cfg_lo	= ~0;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
 
-			return true;
-		}
-	}
+	dwc->request_line = fargs->req;
+
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
+		    fargs.src >= dw->nr_masters ||
+		    fargs.dst >= dw->nr_masters))
+		return NULL;
+
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &fargs);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1553,9 +1575,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1567,7 +1588,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1582,7 +1603,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1594,36 +1615,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1704,8 +1695,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1836,6 +1825,12 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	if (pdev->dev.of_node)
+		err = of_dma_controller_register(pdev->dev.of_node,
+						 dw_dma_xlate, dw);
+	if (err && err != -ENODEV)
+		dev_err(&pdev->dev, "could not register of_dma_controller\n");
+
 	return 0;
 }
 
@@ -1844,6 +1839,7 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88dd8eb..b632082 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -13,6 +13,7 @@
 #include <linux/dw_dmac.h>
 
 #define DW_DMA_MAX_NR_CHANNELS	8
+#define DW_DMA_MAX_NR_REQUESTS	16
 
 /* flow controller */
 enum dw_dma_fc {
@@ -211,9 +212,15 @@ struct dw_dma_chan {
 	/* hardware configuration */
 	unsigned int		block_size;
 	bool			nollp;
+	unsigned int		request_line;
+	struct dw_dma_slave	slave;
+
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
+
+	/* backlink to dw_dma */
+	struct dw_dma		*dw;
 };
 
 static inline struct dw_dma_chan_regs __iomem *
@@ -239,10 +246,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2


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

* [PATCHv3 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 22:21           ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 22:21 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vinod Koul, Vinod Koul, Viresh Kumar,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dan Williams,
	Andy Shevchenko,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of the slave-dma tree, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

This version incorporates feedback from Viresh Kumar, Andy Shevchenko
and Russell King.

Signed-off-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Acked: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: Vinod Koul <vinod.koul-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 +++++-----
 drivers/dma/dw_dmac.c                              | 142 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |  11 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 112 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..d58675e 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma@fc000000 {
+	dmahost: dma@fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a four-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial@e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 4c83f18..72d6abf 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -170,7 +171,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
+		else if (dwc->direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1225,49 +1232,64 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	unsigned int req;
+	unsigned int src;
+	unsigned int dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* ensure the device matches our channel */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= ~0;
+	dws->cfg_lo	= ~0;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
 
-			return true;
-		}
-	}
+	dwc->request_line = fargs->req;
+
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
+		    fargs.src >= dw->nr_masters ||
+		    fargs.dst >= dw->nr_masters))
+		return NULL;
+
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &fargs);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1553,9 +1575,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1567,7 +1588,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1582,7 +1603,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1594,36 +1615,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1704,8 +1695,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1836,6 +1825,12 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	if (pdev->dev.of_node)
+		err = of_dma_controller_register(pdev->dev.of_node,
+						 dw_dma_xlate, dw);
+	if (err && err != -ENODEV)
+		dev_err(&pdev->dev, "could not register of_dma_controller\n");
+
 	return 0;
 }
 
@@ -1844,6 +1839,7 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88dd8eb..b632082 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -13,6 +13,7 @@
 #include <linux/dw_dmac.h>
 
 #define DW_DMA_MAX_NR_CHANNELS	8
+#define DW_DMA_MAX_NR_REQUESTS	16
 
 /* flow controller */
 enum dw_dma_fc {
@@ -211,9 +212,15 @@ struct dw_dma_chan {
 	/* hardware configuration */
 	unsigned int		block_size;
 	bool			nollp;
+	unsigned int		request_line;
+	struct dw_dma_slave	slave;
+
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
+
+	/* backlink to dw_dma */
+	struct dw_dma		*dw;
 };
 
 static inline struct dw_dma_chan_regs __iomem *
@@ -239,10 +246,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2

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

* [PATCHv3 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 22:21           ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 22:21 UTC (permalink / raw)
  To: linux-arm-kernel

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of the slave-dma tree, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

This version incorporates feedback from Viresh Kumar, Andy Shevchenko
and Russell King.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss at lists.ozlabs.org
Cc: linux-arm-kernel at lists.infradead.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 +++++-----
 drivers/dma/dw_dmac.c                              | 142 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |  11 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 112 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..d58675e 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma at fc000000 {
+	dmahost: dma at fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a four-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial at e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 4c83f18..72d6abf 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -170,7 +171,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
+		else if (dwc->direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1225,49 +1232,64 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	unsigned int req;
+	unsigned int src;
+	unsigned int dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* ensure the device matches our channel */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= ~0;
+	dws->cfg_lo	= ~0;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
 
-			return true;
-		}
-	}
+	dwc->request_line = fargs->req;
+
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
+		    fargs.src >= dw->nr_masters ||
+		    fargs.dst >= dw->nr_masters))
+		return NULL;
+
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &fargs);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1553,9 +1575,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1567,7 +1588,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1582,7 +1603,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1594,36 +1615,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1704,8 +1695,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1836,6 +1825,12 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	if (pdev->dev.of_node)
+		err = of_dma_controller_register(pdev->dev.of_node,
+						 dw_dma_xlate, dw);
+	if (err && err != -ENODEV)
+		dev_err(&pdev->dev, "could not register of_dma_controller\n");
+
 	return 0;
 }
 
@@ -1844,6 +1839,7 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88dd8eb..b632082 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -13,6 +13,7 @@
 #include <linux/dw_dmac.h>
 
 #define DW_DMA_MAX_NR_CHANNELS	8
+#define DW_DMA_MAX_NR_REQUESTS	16
 
 /* flow controller */
 enum dw_dma_fc {
@@ -211,9 +212,15 @@ struct dw_dma_chan {
 	/* hardware configuration */
 	unsigned int		block_size;
 	bool			nollp;
+	unsigned int		request_line;
+	struct dw_dma_slave	slave;
+
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
+
+	/* backlink to dw_dma */
+	struct dw_dma		*dw;
 };
 
 static inline struct dw_dma_chan_regs __iomem *
@@ -239,10 +246,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2

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

* [BONUS PATCH] dmaengine: dw_dmac: simplify master selection
  2013-02-16 14:53         ` Andy Shevchenko
@ 2013-02-16 22:23           ` Arnd Bergmann
  -1 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 22:23 UTC (permalink / raw)
  To: Andy Shevchenko, linux-kernel
  Cc: Vinod Koul, linux-arm-kernel, Viresh Kumar, Andy Shevchenko, Vinod Koul

The patch to add the common DMA binding added a dummy dw_dma_slave
structure into the dw_dma_chan structure in order to configure the
masters correctly. It turns out that this can be simplified if we
pick the DMA masters in the dwc_alloc_chan_resources function instead
and save them in the dw_dma_chan structure directly.

This could be simplified further once all users that today use
dw_dma_slave for configuration get converted to device tree based
setup instead.

This is just a proof of concept patch and should not get merged in
3.9, but I hope that Andy and Viresh find it useful and submit it
for 3.10 after testing and refining it.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: linux-arm-kernel@lists.infradead.org
---
 drivers/dma/dw_dmac.c      | 96 ++++++++++++++++------------------------------
 drivers/dma/dw_dmac_regs.h |  4 +-
 2 files changed, 36 insertions(+), 64 deletions(-)

diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 72d6abf..72c6f6d 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -37,40 +37,10 @@
  * The driver has currently been tested only with the Atmel AT32AP7000,
  * which does not support descriptor writeback.
  */
-
-static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave)
-{
-	return slave ? slave->dst_master : 0;
-}
-
-static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave)
-{
-	return slave ? slave->src_master : 1;
-}
-
-#define SRC_MASTER	0
-#define DST_MASTER	1
-
-static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
-{
-	struct dw_dma *dw = to_dw_dma(chan->device);
-	struct dw_dma_slave *dws = chan->private;
-	unsigned int m;
-
-	if (master == SRC_MASTER)
-		m = dwc_get_sms(dws);
-	else
-		m = dwc_get_dms(dws);
-
-	return min_t(unsigned int, dw->nr_masters - 1, m);
-}
-
 #define DWC_DEFAULT_CTLLO(_chan) ({				\
 		struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan);	\
 		struct dma_slave_config	*_sconfig = &_dwc->dma_sconfig;	\
 		bool _is_slave = is_slave_direction(_dwc->direction);	\
-		int _dms = dwc_get_master(_chan, DST_MASTER);		\
-		int _sms = dwc_get_master(_chan, SRC_MASTER);		\
 		u8 _smsize = _is_slave ? _sconfig->src_maxburst :	\
 			DW_DMA_MSIZE_16;			\
 		u8 _dmsize = _is_slave ? _sconfig->dst_maxburst :	\
@@ -80,8 +50,8 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
 		 | DWC_CTLL_SRC_MSIZE(_smsize)			\
 		 | DWC_CTLL_LLP_D_EN				\
 		 | DWC_CTLL_LLP_S_EN				\
-		 | DWC_CTLL_DMS(_dms)				\
-		 | DWC_CTLL_SMS(_sms));				\
+		 | DWC_CTLL_DMS(_dwc->dst_master)			\
+		 | DWC_CTLL_SMS(_dwc->src_master));			\
 	})
 
 /*
@@ -91,13 +61,6 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
  */
 #define NR_DESCS_PER_CHANNEL	64
 
-static inline unsigned int dwc_get_data_width(struct dma_chan *chan, int master)
-{
-	struct dw_dma *dw = to_dw_dma(chan->device);
-
-	return dw->data_width[dwc_get_master(chan, master)];
-}
-
 /*----------------------------------------------------------------------*/
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -171,13 +134,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
-		/* autoconfigure based on request line from DT */
-		if (dwc->direction == DMA_MEM_TO_DEV)
-			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
-		else if (dwc->direction == DMA_DEV_TO_MEM)
-			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
-	} else if (dws) {
+	if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -187,10 +144,12 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 		cfghi = dws->cfg_hi;
 		cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
 	} else {
+		unsigned int request_line = (dwc->request_line != ~0) ?
+			    dwc->request_line : dwc->dma_sconfig.slave_id;
 		if (dwc->direction == DMA_MEM_TO_DEV)
-			cfghi = DWC_CFGH_DST_PER(dwc->dma_sconfig.slave_id);
+			cfghi = DWC_CFGH_DST_PER(request_line);
 		else if (dwc->direction == DMA_DEV_TO_MEM)
-			cfghi = DWC_CFGH_SRC_PER(dwc->dma_sconfig.slave_id);
+			cfghi = DWC_CFGH_SRC_PER(request_line);
 	}
 
 	channel_writel(dwc, CFG_LO, cfglo);
@@ -743,6 +702,7 @@ static struct dma_async_tx_descriptor *
 dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 		size_t len, unsigned long flags)
 {
+	struct dw_dma		*dw = to_dw_dma(chan->device);
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
 	struct dw_desc		*desc;
 	struct dw_desc		*first;
@@ -766,8 +726,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 
 	dwc->direction = DMA_MEM_TO_MEM;
 
-	data_width = min_t(unsigned int, dwc_get_data_width(chan, SRC_MASTER),
-			   dwc_get_data_width(chan, DST_MASTER));
+	data_width = min(dw->data_width[dwc->src_master], dw->data_width[dwc->dst_master]);
 
 	src_width = dst_width = min_t(unsigned int, data_width,
 				      dwc_fast_fls(src | dest | len));
@@ -824,6 +783,7 @@ dwc_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 dw_dma		*dw = to_dw_dma(chan->device);
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
 	struct dma_slave_config	*sconfig = &dwc->dma_sconfig;
 	struct dw_desc		*prev;
@@ -858,7 +818,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
 			DWC_CTLL_FC(DW_DMA_FC_D_M2P);
 
-		data_width = dwc_get_data_width(chan, SRC_MASTER);
+		data_width = dw->data_width[dwc->src_master];
 
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
@@ -918,7 +878,7 @@ slave_sg_todev_fill_desc:
 		ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
 			DWC_CTLL_FC(DW_DMA_FC_D_P2M);
 
-		data_width = dwc_get_data_width(chan, DST_MASTER);
+		data_width = dw->data_width[dwc->dst_master];
 
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
@@ -1139,6 +1099,7 @@ static void dwc_issue_pending(struct dma_chan *chan)
 static int dwc_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_dma_slave	*dws = chan->private;
 	struct dw_dma		*dw = to_dw_dma(chan->device);
 	struct dw_desc		*desc;
 	int			i;
@@ -1153,6 +1114,17 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
 	}
 
 	dma_cookie_init(chan);
+	/* masters may be set up from dws, from DT or autoconfigured here */
+	if (dws) {
+		dwc->src_master = dws->src_master;
+		dwc->dst_master = dws->dst_master;
+	}
+	/* if unconfigured, default to source 1 dest 0 */
+	if (dwc->src_master == ~0)
+		dwc->src_master = 1;
+	if (dwc->dst_master == ~0)
+		dwc->dst_master = 0;
+
 
 	/*
 	 * NOTE: some controllers may have additional features that we
@@ -1218,6 +1190,10 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dwc->descs_allocated = 0;
 	dwc->initialized = false;
 
+	/* invalidate slave configuration */
+	dwc->request_line = ~0;
+	dwc->src_master = dwc->dst_master = ~0; 
+
 	/* Disable interrupts */
 	channel_clear_bit(dw, MASK.XFER, dwc->mask);
 	channel_clear_bit(dw, MASK.ERROR, dwc->mask);
@@ -1242,23 +1218,15 @@ struct dw_dma_filter_args {
 static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
 	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
-	struct dw_dma *dw = to_dw_dma(chan->device);
 	struct dw_dma_filter_args *fargs = param;
-	struct dw_dma_slave *dws = &dwc->slave;
 
 	/* ensure the device matches our channel */
         if (chan->device != &fargs->dw->dma)
                 return false;
 
-	dws->dma_dev	= dw->dma.dev;
-	dws->cfg_hi	= ~0;
-	dws->cfg_lo	= ~0;
-	dws->src_master	= fargs->src;
-	dws->dst_master	= fargs->dst;
-
 	dwc->request_line = fargs->req;
-
-	chan->private = dws;
+	dwc->src_master = fargs->src;
+	dwc->dst_master = fargs->dst;
 
 	return true;
 }
@@ -1767,6 +1735,10 @@ static int dw_probe(struct platform_device *pdev)
 
 		dwc->direction = DMA_TRANS_NONE;
 
+		/* invalidate slave configuration */
+		dwc->request_line = ~0;
+		dwc->src_master = dwc->dst_master = ~0; 
+
 		/* hardware configuration */
 		if (autocfg) {
 			unsigned int dwc_params;
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index b632082..fa4e5f7 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -213,8 +213,8 @@ struct dw_dma_chan {
 	unsigned int		block_size;
 	bool			nollp;
 	unsigned int		request_line;
-	struct dw_dma_slave	slave;
-
+	unsigned char		src_master;
+	unsigned char		dst_master;
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
-- 
1.8.1.2


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

* [BONUS PATCH] dmaengine: dw_dmac: simplify master selection
@ 2013-02-16 22:23           ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 22:23 UTC (permalink / raw)
  To: linux-arm-kernel

The patch to add the common DMA binding added a dummy dw_dma_slave
structure into the dw_dma_chan structure in order to configure the
masters correctly. It turns out that this can be simplified if we
pick the DMA masters in the dwc_alloc_chan_resources function instead
and save them in the dw_dma_chan structure directly.

This could be simplified further once all users that today use
dw_dma_slave for configuration get converted to device tree based
setup instead.

This is just a proof of concept patch and should not get merged in
3.9, but I hope that Andy and Viresh find it useful and submit it
for 3.10 after testing and refining it.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: linux-arm-kernel at lists.infradead.org
---
 drivers/dma/dw_dmac.c      | 96 ++++++++++++++++------------------------------
 drivers/dma/dw_dmac_regs.h |  4 +-
 2 files changed, 36 insertions(+), 64 deletions(-)

diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 72d6abf..72c6f6d 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -37,40 +37,10 @@
  * The driver has currently been tested only with the Atmel AT32AP7000,
  * which does not support descriptor writeback.
  */
-
-static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave)
-{
-	return slave ? slave->dst_master : 0;
-}
-
-static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave)
-{
-	return slave ? slave->src_master : 1;
-}
-
-#define SRC_MASTER	0
-#define DST_MASTER	1
-
-static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
-{
-	struct dw_dma *dw = to_dw_dma(chan->device);
-	struct dw_dma_slave *dws = chan->private;
-	unsigned int m;
-
-	if (master == SRC_MASTER)
-		m = dwc_get_sms(dws);
-	else
-		m = dwc_get_dms(dws);
-
-	return min_t(unsigned int, dw->nr_masters - 1, m);
-}
-
 #define DWC_DEFAULT_CTLLO(_chan) ({				\
 		struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan);	\
 		struct dma_slave_config	*_sconfig = &_dwc->dma_sconfig;	\
 		bool _is_slave = is_slave_direction(_dwc->direction);	\
-		int _dms = dwc_get_master(_chan, DST_MASTER);		\
-		int _sms = dwc_get_master(_chan, SRC_MASTER);		\
 		u8 _smsize = _is_slave ? _sconfig->src_maxburst :	\
 			DW_DMA_MSIZE_16;			\
 		u8 _dmsize = _is_slave ? _sconfig->dst_maxburst :	\
@@ -80,8 +50,8 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
 		 | DWC_CTLL_SRC_MSIZE(_smsize)			\
 		 | DWC_CTLL_LLP_D_EN				\
 		 | DWC_CTLL_LLP_S_EN				\
-		 | DWC_CTLL_DMS(_dms)				\
-		 | DWC_CTLL_SMS(_sms));				\
+		 | DWC_CTLL_DMS(_dwc->dst_master)			\
+		 | DWC_CTLL_SMS(_dwc->src_master));			\
 	})
 
 /*
@@ -91,13 +61,6 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
  */
 #define NR_DESCS_PER_CHANNEL	64
 
-static inline unsigned int dwc_get_data_width(struct dma_chan *chan, int master)
-{
-	struct dw_dma *dw = to_dw_dma(chan->device);
-
-	return dw->data_width[dwc_get_master(chan, master)];
-}
-
 /*----------------------------------------------------------------------*/
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -171,13 +134,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
-		/* autoconfigure based on request line from DT */
-		if (dwc->direction == DMA_MEM_TO_DEV)
-			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
-		else if (dwc->direction == DMA_DEV_TO_MEM)
-			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
-	} else if (dws) {
+	if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -187,10 +144,12 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 		cfghi = dws->cfg_hi;
 		cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
 	} else {
+		unsigned int request_line = (dwc->request_line != ~0) ?
+			    dwc->request_line : dwc->dma_sconfig.slave_id;
 		if (dwc->direction == DMA_MEM_TO_DEV)
-			cfghi = DWC_CFGH_DST_PER(dwc->dma_sconfig.slave_id);
+			cfghi = DWC_CFGH_DST_PER(request_line);
 		else if (dwc->direction == DMA_DEV_TO_MEM)
-			cfghi = DWC_CFGH_SRC_PER(dwc->dma_sconfig.slave_id);
+			cfghi = DWC_CFGH_SRC_PER(request_line);
 	}
 
 	channel_writel(dwc, CFG_LO, cfglo);
@@ -743,6 +702,7 @@ static struct dma_async_tx_descriptor *
 dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 		size_t len, unsigned long flags)
 {
+	struct dw_dma		*dw = to_dw_dma(chan->device);
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
 	struct dw_desc		*desc;
 	struct dw_desc		*first;
@@ -766,8 +726,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 
 	dwc->direction = DMA_MEM_TO_MEM;
 
-	data_width = min_t(unsigned int, dwc_get_data_width(chan, SRC_MASTER),
-			   dwc_get_data_width(chan, DST_MASTER));
+	data_width = min(dw->data_width[dwc->src_master], dw->data_width[dwc->dst_master]);
 
 	src_width = dst_width = min_t(unsigned int, data_width,
 				      dwc_fast_fls(src | dest | len));
@@ -824,6 +783,7 @@ dwc_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 dw_dma		*dw = to_dw_dma(chan->device);
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
 	struct dma_slave_config	*sconfig = &dwc->dma_sconfig;
 	struct dw_desc		*prev;
@@ -858,7 +818,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
 			DWC_CTLL_FC(DW_DMA_FC_D_M2P);
 
-		data_width = dwc_get_data_width(chan, SRC_MASTER);
+		data_width = dw->data_width[dwc->src_master];
 
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
@@ -918,7 +878,7 @@ slave_sg_todev_fill_desc:
 		ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
 			DWC_CTLL_FC(DW_DMA_FC_D_P2M);
 
-		data_width = dwc_get_data_width(chan, DST_MASTER);
+		data_width = dw->data_width[dwc->dst_master];
 
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
@@ -1139,6 +1099,7 @@ static void dwc_issue_pending(struct dma_chan *chan)
 static int dwc_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_dma_slave	*dws = chan->private;
 	struct dw_dma		*dw = to_dw_dma(chan->device);
 	struct dw_desc		*desc;
 	int			i;
@@ -1153,6 +1114,17 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
 	}
 
 	dma_cookie_init(chan);
+	/* masters may be set up from dws, from DT or autoconfigured here */
+	if (dws) {
+		dwc->src_master = dws->src_master;
+		dwc->dst_master = dws->dst_master;
+	}
+	/* if unconfigured, default to source 1 dest 0 */
+	if (dwc->src_master == ~0)
+		dwc->src_master = 1;
+	if (dwc->dst_master == ~0)
+		dwc->dst_master = 0;
+
 
 	/*
 	 * NOTE: some controllers may have additional features that we
@@ -1218,6 +1190,10 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dwc->descs_allocated = 0;
 	dwc->initialized = false;
 
+	/* invalidate slave configuration */
+	dwc->request_line = ~0;
+	dwc->src_master = dwc->dst_master = ~0; 
+
 	/* Disable interrupts */
 	channel_clear_bit(dw, MASK.XFER, dwc->mask);
 	channel_clear_bit(dw, MASK.ERROR, dwc->mask);
@@ -1242,23 +1218,15 @@ struct dw_dma_filter_args {
 static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
 	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
-	struct dw_dma *dw = to_dw_dma(chan->device);
 	struct dw_dma_filter_args *fargs = param;
-	struct dw_dma_slave *dws = &dwc->slave;
 
 	/* ensure the device matches our channel */
         if (chan->device != &fargs->dw->dma)
                 return false;
 
-	dws->dma_dev	= dw->dma.dev;
-	dws->cfg_hi	= ~0;
-	dws->cfg_lo	= ~0;
-	dws->src_master	= fargs->src;
-	dws->dst_master	= fargs->dst;
-
 	dwc->request_line = fargs->req;
-
-	chan->private = dws;
+	dwc->src_master = fargs->src;
+	dwc->dst_master = fargs->dst;
 
 	return true;
 }
@@ -1767,6 +1735,10 @@ static int dw_probe(struct platform_device *pdev)
 
 		dwc->direction = DMA_TRANS_NONE;
 
+		/* invalidate slave configuration */
+		dwc->request_line = ~0;
+		dwc->src_master = dwc->dst_master = ~0; 
+
 		/* hardware configuration */
 		if (autocfg) {
 			unsigned int dwc_params;
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index b632082..fa4e5f7 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -213,8 +213,8 @@ struct dw_dma_chan {
 	unsigned int		block_size;
 	bool			nollp;
 	unsigned int		request_line;
-	struct dw_dma_slave	slave;
-
+	unsigned char		src_master;
+	unsigned char		dst_master;
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
-- 
1.8.1.2

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

* Re: [PATCHv3 2/4] dmaengine: dw_dmac: move to generic DMA binding
  2013-02-16 22:21           ` Arnd Bergmann
@ 2013-02-16 22:54             ` Andy Shevchenko
  -1 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2013-02-16 22:54 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Viresh Kumar, Olof Johansson, linux-kernel, Andy Shevchenko,
	Vinod Koul

On Sun, Feb 17, 2013 at 12:21 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> The original device tree binding for this driver, from Viresh Kumar
> unfortunately conflicted with the generic DMA binding, and did not allow
> to completely seperate slave device configuration from the controller.
>
> This is an attempt to replace it with an implementation of the generic
> binding, but it is currently completely untested, because I do not have
> any hardware with this particular controller.
>
> The patch applies on top of the slave-dma tree, which contains both the base
> support for the generic DMA binding, as well as the earlier attempt from
> Viresh. Both of these are currently not merged upstream however.
>
> This version incorporates feedback from Viresh Kumar, Andy Shevchenko
> and Russell King.

Sorry, few comments below.
After addressing them take my Acked-by: Andy Shevchenko
<andriy.shevchenko@linux.intel.com>

> --- a/drivers/dma/dw_dmac.c
> +++ b/drivers/dma/dw_dmac.c


> @@ -1836,6 +1825,12 @@ static int dw_probe(struct platform_device *pdev)
>
>         dma_async_device_register(&dw->dma);
>
> +       if (pdev->dev.of_node)
> +               err = of_dma_controller_register(pdev->dev.of_node,
> +                                                dw_dma_xlate, dw);
> +       if (err && err != -ENODEV)
> +               dev_err(&pdev->dev, "could not register of_dma_controller\n");

I believe we may make it as
 if (...of_node) {
  err = ...register();
  if (err...)
    dev_err();
 }

> --- a/drivers/dma/dw_dmac_regs.h
> +++ b/drivers/dma/dw_dmac_regs.h

> @@ -211,9 +212,15 @@ struct dw_dma_chan {
>         /* hardware configuration */
>         unsigned int            block_size;
>         bool                    nollp;
> +       unsigned int            request_line;
> +       struct dw_dma_slave     slave;
> +

Do we really need an extra empty line here?

>
>         /* configuration passed via DMA_SLAVE_CONFIG */
>         struct dma_slave_config dma_sconfig;
> +
> +       /* backlink to dw_dma */
> +       struct dw_dma           *dw;

Seems it's not needed and came from rebase?

-- 
With Best Regards,
Andy Shevchenko

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

* [PATCHv3 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 22:54             ` Andy Shevchenko
  0 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2013-02-16 22:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Feb 17, 2013 at 12:21 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> The original device tree binding for this driver, from Viresh Kumar
> unfortunately conflicted with the generic DMA binding, and did not allow
> to completely seperate slave device configuration from the controller.
>
> This is an attempt to replace it with an implementation of the generic
> binding, but it is currently completely untested, because I do not have
> any hardware with this particular controller.
>
> The patch applies on top of the slave-dma tree, which contains both the base
> support for the generic DMA binding, as well as the earlier attempt from
> Viresh. Both of these are currently not merged upstream however.
>
> This version incorporates feedback from Viresh Kumar, Andy Shevchenko
> and Russell King.

Sorry, few comments below.
After addressing them take my Acked-by: Andy Shevchenko
<andriy.shevchenko@linux.intel.com>

> --- a/drivers/dma/dw_dmac.c
> +++ b/drivers/dma/dw_dmac.c


> @@ -1836,6 +1825,12 @@ static int dw_probe(struct platform_device *pdev)
>
>         dma_async_device_register(&dw->dma);
>
> +       if (pdev->dev.of_node)
> +               err = of_dma_controller_register(pdev->dev.of_node,
> +                                                dw_dma_xlate, dw);
> +       if (err && err != -ENODEV)
> +               dev_err(&pdev->dev, "could not register of_dma_controller\n");

I believe we may make it as
 if (...of_node) {
  err = ...register();
  if (err...)
    dev_err();
 }

> --- a/drivers/dma/dw_dmac_regs.h
> +++ b/drivers/dma/dw_dmac_regs.h

> @@ -211,9 +212,15 @@ struct dw_dma_chan {
>         /* hardware configuration */
>         unsigned int            block_size;
>         bool                    nollp;
> +       unsigned int            request_line;
> +       struct dw_dma_slave     slave;
> +

Do we really need an extra empty line here?

>
>         /* configuration passed via DMA_SLAVE_CONFIG */
>         struct dma_slave_config dma_sconfig;
> +
> +       /* backlink to dw_dma */
> +       struct dw_dma           *dw;

Seems it's not needed and came from rebase?

-- 
With Best Regards,
Andy Shevchenko

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

* [PATCHv4 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 23:24               ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 23:24 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Viresh Kumar, Olof Johansson, linux-kernel, Andy Shevchenko,
	Vinod Koul

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of the slave-dma tree, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

This version incorporates feedback from Viresh Kumar, Andy Shevchenko
and Russell King.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 +++++-----
 drivers/dma/dw_dmac.c                              | 145 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |   7 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 111 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..d58675e 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma@fc000000 {
+	dmahost: dma@fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a four-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial@e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 4c83f18..c3159ab 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -170,7 +171,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
+		else if (dwc->direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1225,49 +1232,64 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	unsigned int req;
+	unsigned int src;
+	unsigned int dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* ensure the device matches our channel */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= ~0;
+	dws->cfg_lo	= ~0;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
 
-			return true;
-		}
-	}
+	dwc->request_line = fargs->req;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
+
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
+		    fargs.src >= dw->nr_masters ||
+		    fargs.dst >= dw->nr_masters))
+		return NULL;
+
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &fargs);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1553,9 +1575,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1567,7 +1588,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1582,7 +1603,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1594,36 +1615,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1704,8 +1695,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1836,6 +1825,14 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	if (pdev->dev.of_node) {
+		err = of_dma_controller_register(pdev->dev.of_node,
+						 dw_dma_xlate, dw);
+		if (err && err != -ENODEV)
+			dev_err(&pdev->dev,
+				"could not register of_dma_controller\n");
+	}
+
 	return 0;
 }
 
@@ -1844,6 +1841,8 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	if (pdev->dev.of_node)
+		of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88dd8eb..cf0ce5c 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -13,6 +13,7 @@
 #include <linux/dw_dmac.h>
 
 #define DW_DMA_MAX_NR_CHANNELS	8
+#define DW_DMA_MAX_NR_REQUESTS	16
 
 /* flow controller */
 enum dw_dma_fc {
@@ -211,6 +212,8 @@ struct dw_dma_chan {
 	/* hardware configuration */
 	unsigned int		block_size;
 	bool			nollp;
+	unsigned int		request_line;
+	struct dw_dma_slave	slave;
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
@@ -239,10 +242,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2


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

* [PATCHv4 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 23:24               ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 23:24 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vinod Koul, Vinod Koul, Viresh Kumar,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dan Williams,
	Andy Shevchenko,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of the slave-dma tree, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

This version incorporates feedback from Viresh Kumar, Andy Shevchenko
and Russell King.

Signed-off-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Acked-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Acked-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: Vinod Koul <vinod.koul-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 +++++-----
 drivers/dma/dw_dmac.c                              | 145 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |   7 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 111 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..d58675e 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma@fc000000 {
+	dmahost: dma@fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a four-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial@e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 4c83f18..c3159ab 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -170,7 +171,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
+		else if (dwc->direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1225,49 +1232,64 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	unsigned int req;
+	unsigned int src;
+	unsigned int dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* ensure the device matches our channel */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= ~0;
+	dws->cfg_lo	= ~0;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
 
-			return true;
-		}
-	}
+	dwc->request_line = fargs->req;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
+
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
+		    fargs.src >= dw->nr_masters ||
+		    fargs.dst >= dw->nr_masters))
+		return NULL;
+
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &fargs);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1553,9 +1575,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1567,7 +1588,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1582,7 +1603,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1594,36 +1615,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1704,8 +1695,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1836,6 +1825,14 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	if (pdev->dev.of_node) {
+		err = of_dma_controller_register(pdev->dev.of_node,
+						 dw_dma_xlate, dw);
+		if (err && err != -ENODEV)
+			dev_err(&pdev->dev,
+				"could not register of_dma_controller\n");
+	}
+
 	return 0;
 }
 
@@ -1844,6 +1841,8 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	if (pdev->dev.of_node)
+		of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88dd8eb..cf0ce5c 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -13,6 +13,7 @@
 #include <linux/dw_dmac.h>
 
 #define DW_DMA_MAX_NR_CHANNELS	8
+#define DW_DMA_MAX_NR_REQUESTS	16
 
 /* flow controller */
 enum dw_dma_fc {
@@ -211,6 +212,8 @@ struct dw_dma_chan {
 	/* hardware configuration */
 	unsigned int		block_size;
 	bool			nollp;
+	unsigned int		request_line;
+	struct dw_dma_slave	slave;
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
@@ -239,10 +242,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2

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

* [PATCHv4 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 23:24               ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 23:24 UTC (permalink / raw)
  To: linux-arm-kernel

The original device tree binding for this driver, from Viresh Kumar
unfortunately conflicted with the generic DMA binding, and did not allow
to completely seperate slave device configuration from the controller.

This is an attempt to replace it with an implementation of the generic
binding, but it is currently completely untested, because I do not have
any hardware with this particular controller.

The patch applies on top of the slave-dma tree, which contains both the base
support for the generic DMA binding, as well as the earlier attempt from
Viresh. Both of these are currently not merged upstream however.

This version incorporates feedback from Viresh Kumar, Andy Shevchenko
and Russell King.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss at lists.ozlabs.org
Cc: linux-arm-kernel at lists.infradead.org
---
 Documentation/devicetree/bindings/dma/snps-dma.txt |  70 +++++-----
 drivers/dma/dw_dmac.c                              | 145 ++++++++++-----------
 drivers/dma/dw_dmac_regs.h                         |   7 +-
 include/linux/dw_dmac.h                            |   5 -
 4 files changed, 111 insertions(+), 116 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 5bb3dfb..d58675e 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -3,59 +3,61 @@
 Required properties:
 - compatible: "snps,dma-spear1340"
 - reg: Address range of the DMAC registers
-- interrupt-parent: Should be the phandle for the interrupt controller
-  that services interrupts for this device
 - interrupt: Should contain the DMAC interrupt number
-- nr_channels: Number of channels supported by hardware
-- is_private: The device channels should be marked as private and not for by the
-  general purpose DMA channel allocator. False if not passed.
+- dma-channels: Number of channels supported by hardware
+- dma-requests: Number of DMA request lines supported, up to 16
+- dma-masters: Number of AHB masters supported by the controller
+- #dma-cells: must be <3>
 - chan_allocation_order: order of allocation of channel, 0 (default): ascending,
   1: descending
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
-- nr_masters: Number of AHB masters supported by the controller
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
-- slave_info:
-	- bus_id: name of this device channel, not just a device name since
-	  devices may have more than one channel e.g. "foo_tx". For using the
-	  dw_generic_filter(), slave drivers must pass exactly this string as
-	  param to filter function.
-	- cfg_hi: Platform-specific initializer for the CFG_HI register
-	- cfg_lo: Platform-specific initializer for the CFG_LO register
-	- src_master: src master for transfers on allocated channel.
-	- dst_master: dest master for transfers on allocated channel.
+
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- is_private: The device channels should be marked as private and not for by the
+  general purpose DMA channel allocator. False if not passed.
 
 Example:
 
-	dma at fc000000 {
+	dmahost: dma at fc000000 {
 		compatible = "snps,dma-spear1340";
 		reg = <0xfc000000 0x1000>;
 		interrupt-parent = <&vic1>;
 		interrupts = <12>;
 
-		nr_channels = <8>;
+		dma-channels = <8>;
+		dma-requests = <16>;
+		dma-masters = <2>;
+		#dma-cells = <3>;
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		nr_masters = <2>;
 		data_width = <3 3 0 0>;
+	};
 
-		slave_info {
-			uart0-tx {
-				bus_id = "uart0-tx";
-				cfg_hi = <0x4000>;	/* 0x8 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <1>;
-			};
-			spi0-tx {
-				bus_id = "spi0-tx";
-				cfg_hi = <0x2000>;	/* 0x4 << 11 */
-				cfg_lo = <0>;
-				src_master = <0>;
-				dst_master = <0>;
-			};
-		};
+DMA clients connected to the Designware DMA controller must use the format
+described in the dma.txt file, using a four-cell specifier for each channel.
+The four cells in order are:
+
+1. A phandle pointing to the DMA controller
+2. The DMA request line number
+3. Source master for transfers on allocated channel
+4. Destination master for transfers on allocated channel
+
+Example:
+	
+	serial at e0000000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0xe0000000 0x1000>;
+		interrupts = <0 35 0x4>;
+		status = "disabled";
+		dmas = <&dmahost 12 0 1>,
+			<&dmahost 13 0 1 0>;
+		dma-names = "rx", "rx";
 	};
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 4c83f18..c3159ab 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_dma.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -170,7 +171,13 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 	if (dwc->initialized == true)
 		return;
 
-	if (dws) {
+	if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) {
+		/* autoconfigure based on request line from DT */
+		if (dwc->direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->request_line);
+		else if (dwc->direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
+	} else if (dws) {
 		/*
 		 * We need controller-specific data to set up slave
 		 * transfers.
@@ -1225,49 +1232,64 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
+struct dw_dma_filter_args {
+	struct dw_dma *dw;
+	unsigned int req;
+	unsigned int src;
+	unsigned int dst;
+};
+
+static bool dw_dma_generic_filter(struct dma_chan *chan, void *param)
 {
+	struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
 	struct dw_dma *dw = to_dw_dma(chan->device);
-	static struct dw_dma *last_dw;
-	static char *last_bus_id;
-	int i = -1;
+	struct dw_dma_filter_args *fargs = param;
+	struct dw_dma_slave *dws = &dwc->slave;
 
-	/*
-	 * dmaengine framework calls this routine for all channels of all dma
-	 * controller, until true is returned. If 'param' bus_id is not
-	 * registered with a dma controller (dw), then there is no need of
-	 * running below function for all channels of dw.
-	 *
-	 * This block of code does this by saving the parameters of last
-	 * failure. If dw and param are same, i.e. trying on same dw with
-	 * different channel, return false.
-	 */
-	if ((last_dw == dw) && (last_bus_id == param))
-		return false;
-	/*
-	 * Return true:
-	 * - If dw_dma's platform data is not filled with slave info, then all
-	 *   dma controllers are fine for transfer.
-	 * - Or if param is NULL
-	 */
-	if (!dw->sd || !param)
-		return true;
+	/* ensure the device matches our channel */
+        if (chan->device != &fargs->dw->dma)
+                return false;
 
-	while (++i < dw->sd_count) {
-		if (!strcmp(dw->sd[i].bus_id, param)) {
-			chan->private = &dw->sd[i];
-			last_dw = NULL;
-			last_bus_id = NULL;
+	dws->dma_dev	= dw->dma.dev;
+	dws->cfg_hi	= ~0;
+	dws->cfg_lo	= ~0;
+	dws->src_master	= fargs->src;
+	dws->dst_master	= fargs->dst;
 
-			return true;
-		}
-	}
+	dwc->request_line = fargs->req;
 
-	last_dw = dw;
-	last_bus_id = param;
-	return false;
+	chan->private = dws;
+
+	return true;
+}
+
+static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct dw_dma *dw = ofdma->of_dma_data;
+	struct dw_dma_filter_args fargs = {
+		.dw = dw,
+	};
+	dma_cap_mask_t cap;
+
+	if (dma_spec->args_count != 3)
+		return NULL;
+
+	fargs.req = be32_to_cpup(dma_spec->args+0);
+	fargs.src = be32_to_cpup(dma_spec->args+1);
+	fargs.dst = be32_to_cpup(dma_spec->args+2);
+
+	if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
+		    fargs.src >= dw->nr_masters ||
+		    fargs.dst >= dw->nr_masters))
+		return NULL;
+
+	dma_cap_zero(cap);
+	dma_cap_set(DMA_SLAVE, cap);
+
+	/* TODO: there should be a simpler way to do this */
+	return dma_request_channel(cap, dw_dma_generic_filter, &fargs);
 }
-EXPORT_SYMBOL(dw_dma_generic_filter);
 
 /* --------------------- Cyclic DMA API extensions -------------------- */
 
@@ -1553,9 +1575,8 @@ static void dw_dma_off(struct dw_dma *dw)
 static struct dw_dma_platform_data *
 dw_dma_parse_dt(struct platform_device *pdev)
 {
-	struct device_node *sn, *cn, *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	struct dw_dma_slave *sd;
 	u32 tmp, arr[4];
 
 	if (!np) {
@@ -1567,7 +1588,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!pdata)
 		return NULL;
 
-	if (of_property_read_u32(np, "nr_channels", &pdata->nr_channels))
+	if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 		return NULL;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -1582,7 +1603,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "nr_masters", &tmp)) {
+	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 		if (tmp > 4)
 			return NULL;
 
@@ -1594,36 +1615,6 @@ dw_dma_parse_dt(struct platform_device *pdev)
 		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
 
-	/* parse slave data */
-	sn = of_find_node_by_name(np, "slave_info");
-	if (!sn)
-		return pdata;
-
-	/* calculate number of slaves */
-	tmp = of_get_child_count(sn);
-	if (!tmp)
-		return NULL;
-
-	sd = devm_kzalloc(&pdev->dev, sizeof(*sd) * tmp, GFP_KERNEL);
-	if (!sd)
-		return NULL;
-
-	pdata->sd = sd;
-	pdata->sd_count = tmp;
-
-	for_each_child_of_node(sn, cn) {
-		sd->dma_dev = &pdev->dev;
-		of_property_read_string(cn, "bus_id", &sd->bus_id);
-		of_property_read_u32(cn, "cfg_hi", &sd->cfg_hi);
-		of_property_read_u32(cn, "cfg_lo", &sd->cfg_lo);
-		if (!of_property_read_u32(cn, "src_master", &tmp))
-			sd->src_master = tmp;
-
-		if (!of_property_read_u32(cn, "dst_master", &tmp))
-			sd->dst_master = tmp;
-		sd++;
-	}
-
 	return pdata;
 }
 #else
@@ -1704,8 +1695,6 @@ static int dw_probe(struct platform_device *pdev)
 	clk_prepare_enable(dw->clk);
 
 	dw->regs = regs;
-	dw->sd = pdata->sd;
-	dw->sd_count = pdata->sd_count;
 
 	/* get hardware configuration parameters */
 	if (autocfg) {
@@ -1836,6 +1825,14 @@ static int dw_probe(struct platform_device *pdev)
 
 	dma_async_device_register(&dw->dma);
 
+	if (pdev->dev.of_node) {
+		err = of_dma_controller_register(pdev->dev.of_node,
+						 dw_dma_xlate, dw);
+		if (err && err != -ENODEV)
+			dev_err(&pdev->dev,
+				"could not register of_dma_controller\n");
+	}
+
 	return 0;
 }
 
@@ -1844,6 +1841,8 @@ static int __devexit dw_remove(struct platform_device *pdev)
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
 
+	if (pdev->dev.of_node)
+		of_dma_controller_free(pdev->dev.of_node);
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 88dd8eb..cf0ce5c 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -13,6 +13,7 @@
 #include <linux/dw_dmac.h>
 
 #define DW_DMA_MAX_NR_CHANNELS	8
+#define DW_DMA_MAX_NR_REQUESTS	16
 
 /* flow controller */
 enum dw_dma_fc {
@@ -211,6 +212,8 @@ struct dw_dma_chan {
 	/* hardware configuration */
 	unsigned int		block_size;
 	bool			nollp;
+	unsigned int		request_line;
+	struct dw_dma_slave	slave;
 
 	/* configuration passed via DMA_SLAVE_CONFIG */
 	struct dma_slave_config dma_sconfig;
@@ -239,10 +242,6 @@ struct dw_dma {
 	struct tasklet_struct	tasklet;
 	struct clk		*clk;
 
-	/* slave information */
-	struct dw_dma_slave	*sd;
-	unsigned int		sd_count;
-
 	u8			all_chan_mask;
 
 	/* hardware configuration */
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index 41766de..481ab23 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -27,7 +27,6 @@
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
-	const char		*bus_id;
 	u32			cfg_hi;
 	u32			cfg_lo;
 	u8			src_master;
@@ -60,9 +59,6 @@ struct dw_dma_platform_data {
 	unsigned short	block_size;
 	unsigned char	nr_masters;
 	unsigned char	data_width[4];
-
-	struct dw_dma_slave *sd;
-	unsigned int sd_count;
 };
 
 /* bursts size */
@@ -114,6 +110,5 @@ void dw_dma_cyclic_stop(struct dma_chan *chan);
 dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan);
 
 dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan);
-bool dw_dma_generic_filter(struct dma_chan *chan, void *param);
 
 #endif /* DW_DMAC_H */
-- 
1.8.1.2

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

* Re: [PATCHv3 2/4] dmaengine: dw_dmac: move to generic DMA binding
  2013-02-16 22:54             ` Andy Shevchenko
@ 2013-02-16 23:28               ` Arnd Bergmann
  -1 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 23:28 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vinod Koul, Dan Williams, linux-arm-kernel, devicetree-discuss,
	Viresh Kumar, Olof Johansson, linux-kernel, Andy Shevchenko,
	Vinod Koul

On Saturday 16 February 2013, Andy Shevchenko wrote:

> > @@ -1836,6 +1825,12 @@ static int dw_probe(struct platform_device *pdev)
> >
> >         dma_async_device_register(&dw->dma);
> >
> > +       if (pdev->dev.of_node)
> > +               err = of_dma_controller_register(pdev->dev.of_node,
> > +                                                dw_dma_xlate, dw);
> > +       if (err && err != -ENODEV)
> > +               dev_err(&pdev->dev, "could not register of_dma_controller\n");
> 
> I believe we may make it as
>  if (...of_node) {
>   err = ...register();
>   if (err...)
>     dev_err();
>  }

I thing the two are equivalent because we only get to the first if()
when err is 0. However, I agree that your version is a bit clearer,
so I'll change it.

> > --- a/drivers/dma/dw_dmac_regs.h
> > +++ b/drivers/dma/dw_dmac_regs.h
> 
> > @@ -211,9 +212,15 @@ struct dw_dma_chan {
> >         /* hardware configuration */
> >         unsigned int            block_size;
> >         bool                    nollp;
> > +       unsigned int            request_line;
> > +       struct dw_dma_slave     slave;
> > +
> 
> Do we really need an extra empty line here?

No, that was an accident.

> >         /* configuration passed via DMA_SLAVE_CONFIG */
> >         struct dma_slave_config dma_sconfig;
> > +
> > +       /* backlink to dw_dma */
> > +       struct dw_dma           *dw;
> 
> Seems it's not needed and came from rebase?

Probably. It certainly was not intentional.

	Arnd

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

* [PATCHv3 2/4] dmaengine: dw_dmac: move to generic DMA binding
@ 2013-02-16 23:28               ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-16 23:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 16 February 2013, Andy Shevchenko wrote:

> > @@ -1836,6 +1825,12 @@ static int dw_probe(struct platform_device *pdev)
> >
> >         dma_async_device_register(&dw->dma);
> >
> > +       if (pdev->dev.of_node)
> > +               err = of_dma_controller_register(pdev->dev.of_node,
> > +                                                dw_dma_xlate, dw);
> > +       if (err && err != -ENODEV)
> > +               dev_err(&pdev->dev, "could not register of_dma_controller\n");
> 
> I believe we may make it as
>  if (...of_node) {
>   err = ...register();
>   if (err...)
>     dev_err();
>  }

I thing the two are equivalent because we only get to the first if()
when err is 0. However, I agree that your version is a bit clearer,
so I'll change it.

> > --- a/drivers/dma/dw_dmac_regs.h
> > +++ b/drivers/dma/dw_dmac_regs.h
> 
> > @@ -211,9 +212,15 @@ struct dw_dma_chan {
> >         /* hardware configuration */
> >         unsigned int            block_size;
> >         bool                    nollp;
> > +       unsigned int            request_line;
> > +       struct dw_dma_slave     slave;
> > +
> 
> Do we really need an extra empty line here?

No, that was an accident.

> >         /* configuration passed via DMA_SLAVE_CONFIG */
> >         struct dma_slave_config dma_sconfig;
> > +
> > +       /* backlink to dw_dma */
> > +       struct dw_dma           *dw;
> 
> Seems it's not needed and came from rebase?

Probably. It certainly was not intentional.

	Arnd

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

* Re: [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
  2013-02-15 18:21 ` Arnd Bergmann
@ 2013-02-20  8:03   ` Vinod Koul
  -1 siblings, 0 replies; 53+ messages in thread
From: Vinod Koul @ 2013-02-20  8:03 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko

On Fri, Feb 15, 2013 at 07:21:48PM +0100, Arnd Bergmann wrote:
> Hi Vinod,
> 
> As Andy pointed out today, we don't have a good solution for the
> dw_dmac DT binding in linux-next yet. I have posted my series
> once before and then got distracted after getting feedback from
> Viresh, Andy and Russell. I have now updated my earlier patch
> based on the feedback and rebased on your tree without any
> of the arm-soc patches mixed in.
> 
> Unfortunately the patches have never been tested on real hardware 
> so I don't think it's a good idea to use them in v3.9 on the
> spear platform. However, your dma-slave tree still contains Viresh's
> earlier patches, causing a few problems:
> 
> * With those patches, the spear3xx platform currently does not build.
>   (this one would be easy to fix though)
> * There is a conflict between those patches and my spear multiplatform
>   series, which I have not yet queued up for 3.9 because of this,
>   since that would have meant that Stephen Rothwell would have to
>   discard either the arm-soc tree or the dma-slave tree from linux-next.
> * I really don't want the broken binding to appear in 3.9.
> 
> I believe the best way out at this point is this series, which first
> first reverts the patch f9965aa2 "ARM: SPEAr13xx: Pass DW DMAC
> platform data from DT" from your tree and then adds my update.
> 
> This will give us the right DT binding for dw-dmac but no in-tree
> users, which means that nothing should break if I get it slightly
> wrong. Please apply the first two patches from these set, and
> optionally the two patches that based on this convert the pl011
> uart and pl022 spi controller drivers.
Arnd,

Since there is still churn, would it make sense if I just revert the SPEAr13xx
patch (your first patch) and send a pull request to Linus.
Since there are no users and not much testing has been done, I think we can push
these to 3.10 via arm-soc/slave-dma tree.

Gives more testing and usage will go along as well.
Since merge window is open, I would like my pull to go soonish and not churn the
tree much.

--
~Vinod
> 
> I can then decide with Olof whether or not to take the spear multiplatform
> changes that no longer conflict with the dma slave tree as a "late"
> branch into 3.9 or wait until 3.10, but that is something you don't
> need to worry about then. Also the conversion of spear to use
> the new binding (patch 5 of my original series) can go through the 
> arm-soc tree for 3.10 after the ST folks have tested that it works.
> 
> 	Arnd
> 
> Arnd Bergmann (4):
>   Revert "ARM: SPEAr13xx: Pass DW DMAC platform data from DT"
>   dmaengine: dw_dmac: move to generic DMA binding
>   spi: pl022: use generic DMA slave configuration if possible
>   serial: pl011: use generic DMA slave configuration if possible
> 
>  .../devicetree/bindings/arm/primecell.txt          |  19 ++-
>  Documentation/devicetree/bindings/dma/snps-dma.txt |  70 ++++++-----
>  Documentation/devicetree/bindings/serial/pl011.txt |  17 +++
>  .../devicetree/bindings/spi/spi_pl022.txt          |  36 ++++++
>  arch/arm/boot/dts/spear1340.dtsi                   |  19 ---
>  arch/arm/boot/dts/spear13xx.dtsi                   |  38 ------
>  arch/arm/mach-spear13xx/include/mach/spear.h       |   2 +
>  arch/arm/mach-spear13xx/spear1310.c                |   5 +-
>  arch/arm/mach-spear13xx/spear1340.c                |  33 +++--
>  arch/arm/mach-spear13xx/spear13xx.c                |  55 ++++++++-
>  drivers/dma/dw_dmac.c                              | 137 ++++++++++-----------
>  drivers/dma/dw_dmac_regs.h                         |   8 +-
>  drivers/spi/spi-pl022.c                            |  43 ++++++-
>  drivers/tty/serial/amba-pl011.c                    |  62 ++++++----
>  include/linux/dw_dmac.h                            |   5 -
>  15 files changed, 333 insertions(+), 216 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/serial/pl011.txt
> 
> -- 
> 1.8.1.2
> 

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

* [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-20  8:03   ` Vinod Koul
  0 siblings, 0 replies; 53+ messages in thread
From: Vinod Koul @ 2013-02-20  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 15, 2013 at 07:21:48PM +0100, Arnd Bergmann wrote:
> Hi Vinod,
> 
> As Andy pointed out today, we don't have a good solution for the
> dw_dmac DT binding in linux-next yet. I have posted my series
> once before and then got distracted after getting feedback from
> Viresh, Andy and Russell. I have now updated my earlier patch
> based on the feedback and rebased on your tree without any
> of the arm-soc patches mixed in.
> 
> Unfortunately the patches have never been tested on real hardware 
> so I don't think it's a good idea to use them in v3.9 on the
> spear platform. However, your dma-slave tree still contains Viresh's
> earlier patches, causing a few problems:
> 
> * With those patches, the spear3xx platform currently does not build.
>   (this one would be easy to fix though)
> * There is a conflict between those patches and my spear multiplatform
>   series, which I have not yet queued up for 3.9 because of this,
>   since that would have meant that Stephen Rothwell would have to
>   discard either the arm-soc tree or the dma-slave tree from linux-next.
> * I really don't want the broken binding to appear in 3.9.
> 
> I believe the best way out at this point is this series, which first
> first reverts the patch f9965aa2 "ARM: SPEAr13xx: Pass DW DMAC
> platform data from DT" from your tree and then adds my update.
> 
> This will give us the right DT binding for dw-dmac but no in-tree
> users, which means that nothing should break if I get it slightly
> wrong. Please apply the first two patches from these set, and
> optionally the two patches that based on this convert the pl011
> uart and pl022 spi controller drivers.
Arnd,

Since there is still churn, would it make sense if I just revert the SPEAr13xx
patch (your first patch) and send a pull request to Linus.
Since there are no users and not much testing has been done, I think we can push
these to 3.10 via arm-soc/slave-dma tree.

Gives more testing and usage will go along as well.
Since merge window is open, I would like my pull to go soonish and not churn the
tree much.

--
~Vinod
> 
> I can then decide with Olof whether or not to take the spear multiplatform
> changes that no longer conflict with the dma slave tree as a "late"
> branch into 3.9 or wait until 3.10, but that is something you don't
> need to worry about then. Also the conversion of spear to use
> the new binding (patch 5 of my original series) can go through the 
> arm-soc tree for 3.10 after the ST folks have tested that it works.
> 
> 	Arnd
> 
> Arnd Bergmann (4):
>   Revert "ARM: SPEAr13xx: Pass DW DMAC platform data from DT"
>   dmaengine: dw_dmac: move to generic DMA binding
>   spi: pl022: use generic DMA slave configuration if possible
>   serial: pl011: use generic DMA slave configuration if possible
> 
>  .../devicetree/bindings/arm/primecell.txt          |  19 ++-
>  Documentation/devicetree/bindings/dma/snps-dma.txt |  70 ++++++-----
>  Documentation/devicetree/bindings/serial/pl011.txt |  17 +++
>  .../devicetree/bindings/spi/spi_pl022.txt          |  36 ++++++
>  arch/arm/boot/dts/spear1340.dtsi                   |  19 ---
>  arch/arm/boot/dts/spear13xx.dtsi                   |  38 ------
>  arch/arm/mach-spear13xx/include/mach/spear.h       |   2 +
>  arch/arm/mach-spear13xx/spear1310.c                |   5 +-
>  arch/arm/mach-spear13xx/spear1340.c                |  33 +++--
>  arch/arm/mach-spear13xx/spear13xx.c                |  55 ++++++++-
>  drivers/dma/dw_dmac.c                              | 137 ++++++++++-----------
>  drivers/dma/dw_dmac_regs.h                         |   8 +-
>  drivers/spi/spi-pl022.c                            |  43 ++++++-
>  drivers/tty/serial/amba-pl011.c                    |  62 ++++++----
>  include/linux/dw_dmac.h                            |   5 -
>  15 files changed, 333 insertions(+), 216 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/serial/pl011.txt
> 
> -- 
> 1.8.1.2
> 

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

* Re: [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-20  9:50     ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-20  9:50 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko

On Wednesday 20 February 2013, Vinod Koul wrote:
> Since there is still churn, would it make sense if I just revert the SPEAr13xx
> patch (your first patch) and send a pull request to Linus.
> Since there are no users and not much testing has been done, I think we can push
> these to 3.10 via arm-soc/slave-dma tree.
> 
> Gives more testing and usage will go along as well.
> Since merge window is open, I would like my pull to go soonish and not churn the
> tree much.

Reverting the SPEAr13xx would definitely help, yes. The reason why I'd also like
to see the second patch get merged is so that we can do the SPEAr changes in 3.10
without having an interdependency between the trees. I tried very hard to
make the patch have a minimal impact on the non-DT code path to avoid regressions.

Maybe you can send your tree now with just the revert applied, and then send the
other one separately next week along with any bug fixes that may have accumulated
by then?

	Arnd

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

* Re: [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-20  9:50     ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-20  9:50 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Viresh Kumar, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Andy Shevchenko,
	Dan Williams, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Wednesday 20 February 2013, Vinod Koul wrote:
> Since there is still churn, would it make sense if I just revert the SPEAr13xx
> patch (your first patch) and send a pull request to Linus.
> Since there are no users and not much testing has been done, I think we can push
> these to 3.10 via arm-soc/slave-dma tree.
> 
> Gives more testing and usage will go along as well.
> Since merge window is open, I would like my pull to go soonish and not churn the
> tree much.

Reverting the SPEAr13xx would definitely help, yes. The reason why I'd also like
to see the second patch get merged is so that we can do the SPEAr changes in 3.10
without having an interdependency between the trees. I tried very hard to
make the patch have a minimal impact on the non-DT code path to avoid regressions.

Maybe you can send your tree now with just the revert applied, and then send the
other one separately next week along with any bug fixes that may have accumulated
by then?

	Arnd

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

* [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-20  9:50     ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-20  9:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 20 February 2013, Vinod Koul wrote:
> Since there is still churn, would it make sense if I just revert the SPEAr13xx
> patch (your first patch) and send a pull request to Linus.
> Since there are no users and not much testing has been done, I think we can push
> these to 3.10 via arm-soc/slave-dma tree.
> 
> Gives more testing and usage will go along as well.
> Since merge window is open, I would like my pull to go soonish and not churn the
> tree much.

Reverting the SPEAr13xx would definitely help, yes. The reason why I'd also like
to see the second patch get merged is so that we can do the SPEAr changes in 3.10
without having an interdependency between the trees. I tried very hard to
make the patch have a minimal impact on the non-DT code path to avoid regressions.

Maybe you can send your tree now with just the revert applied, and then send the
other one separately next week along with any bug fixes that may have accumulated
by then?

	Arnd

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

* Re: [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
  2013-02-20  9:50     ` Arnd Bergmann
@ 2013-02-20  9:58       ` Vinod Koul
  -1 siblings, 0 replies; 53+ messages in thread
From: Vinod Koul @ 2013-02-20  9:58 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko

On Wed, Feb 20, 2013 at 09:50:25AM +0000, Arnd Bergmann wrote:
> On Wednesday 20 February 2013, Vinod Koul wrote:
> > Since there is still churn, would it make sense if I just revert the SPEAr13xx
> > patch (your first patch) and send a pull request to Linus.
> > Since there are no users and not much testing has been done, I think we can push
> > these to 3.10 via arm-soc/slave-dma tree.
> > 
> > Gives more testing and usage will go along as well.
> > Since merge window is open, I would like my pull to go soonish and not churn the
> > tree much.
> 
> Reverting the SPEAr13xx would definitely help, yes. The reason why I'd also like
> to see the second patch get merged is so that we can do the SPEAr changes in 3.10
> without having an interdependency between the trees. I tried very hard to
> make the patch have a minimal impact on the non-DT code path to avoid regressions.
Ok, i have applied your revert patch. Will send the PULL to linus by friday.

> Maybe you can send your tree now with just the revert applied, and then send the
> other one separately next week along with any bug fixes that may have accumulated
> by then?
And then makes sense to send second PULL with fixes accumulated and the second
patch, so that 3.10 is easier for all.  think we can compact() patch is second
request as well

--
~Vinod

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

* [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-20  9:58       ` Vinod Koul
  0 siblings, 0 replies; 53+ messages in thread
From: Vinod Koul @ 2013-02-20  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 20, 2013 at 09:50:25AM +0000, Arnd Bergmann wrote:
> On Wednesday 20 February 2013, Vinod Koul wrote:
> > Since there is still churn, would it make sense if I just revert the SPEAr13xx
> > patch (your first patch) and send a pull request to Linus.
> > Since there are no users and not much testing has been done, I think we can push
> > these to 3.10 via arm-soc/slave-dma tree.
> > 
> > Gives more testing and usage will go along as well.
> > Since merge window is open, I would like my pull to go soonish and not churn the
> > tree much.
> 
> Reverting the SPEAr13xx would definitely help, yes. The reason why I'd also like
> to see the second patch get merged is so that we can do the SPEAr changes in 3.10
> without having an interdependency between the trees. I tried very hard to
> make the patch have a minimal impact on the non-DT code path to avoid regressions.
Ok, i have applied your revert patch. Will send the PULL to linus by friday.

> Maybe you can send your tree now with just the revert applied, and then send the
> other one separately next week along with any bug fixes that may have accumulated
> by then?
And then makes sense to send second PULL with fixes accumulated and the second
patch, so that 3.10 is easier for all.  think we can compact() patch is second
request as well

--
~Vinod

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

* Re: [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
  2013-02-20  9:58       ` Vinod Koul
@ 2013-02-20 11:10         ` Arnd Bergmann
  -1 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-20 11:10 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Dan Williams, linux-arm-kernel, devicetree-discuss, Viresh Kumar,
	Olof Johansson, linux-kernel, Andy Shevchenko

On Wednesday 20 February 2013, Vinod Koul wrote:
> On Wed, Feb 20, 2013 at 09:50:25AM +0000, Arnd Bergmann wrote:
> > On Wednesday 20 February 2013, Vinod Koul wrote:
> > > Since there is still churn, would it make sense if I just revert the SPEAr13xx
> > > patch (your first patch) and send a pull request to Linus.
> > > Since there are no users and not much testing has been done, I think we can push
> > > these to 3.10 via arm-soc/slave-dma tree.
> > > 
> > > Gives more testing and usage will go along as well.
> > > Since merge window is open, I would like my pull to go soonish and not churn the
> > > tree much.
> > 
> > Reverting the SPEAr13xx would definitely help, yes. The reason why I'd also like
> > to see the second patch get merged is so that we can do the SPEAr changes in 3.10
> > without having an interdependency between the trees. I tried very hard to
> > make the patch have a minimal impact on the non-DT code path to avoid regressions.
> Ok, i have applied your revert patch. Will send the PULL to linus by friday.

Ok, thanks.

> > Maybe you can send your tree now with just the revert applied, and then send the
> > other one separately next week along with any bug fixes that may have accumulated
> > by then?
> And then makes sense to send second PULL with fixes accumulated and the second
> patch, so that 3.10 is easier for all.  think we can compact() patch is second
> request as well

Yes, sounds good.

	Arnd

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

* [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT
@ 2013-02-20 11:10         ` Arnd Bergmann
  0 siblings, 0 replies; 53+ messages in thread
From: Arnd Bergmann @ 2013-02-20 11:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 20 February 2013, Vinod Koul wrote:
> On Wed, Feb 20, 2013 at 09:50:25AM +0000, Arnd Bergmann wrote:
> > On Wednesday 20 February 2013, Vinod Koul wrote:
> > > Since there is still churn, would it make sense if I just revert the SPEAr13xx
> > > patch (your first patch) and send a pull request to Linus.
> > > Since there are no users and not much testing has been done, I think we can push
> > > these to 3.10 via arm-soc/slave-dma tree.
> > > 
> > > Gives more testing and usage will go along as well.
> > > Since merge window is open, I would like my pull to go soonish and not churn the
> > > tree much.
> > 
> > Reverting the SPEAr13xx would definitely help, yes. The reason why I'd also like
> > to see the second patch get merged is so that we can do the SPEAr changes in 3.10
> > without having an interdependency between the trees. I tried very hard to
> > make the patch have a minimal impact on the non-DT code path to avoid regressions.
> Ok, i have applied your revert patch. Will send the PULL to linus by friday.

Ok, thanks.

> > Maybe you can send your tree now with just the revert applied, and then send the
> > other one separately next week along with any bug fixes that may have accumulated
> > by then?
> And then makes sense to send second PULL with fixes accumulated and the second
> patch, so that 3.10 is easier for all.  think we can compact() patch is second
> request as well

Yes, sounds good.

	Arnd

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

end of thread, other threads:[~2013-02-20 11:10 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-15 18:21 [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT Arnd Bergmann
2013-02-15 18:21 ` Arnd Bergmann
2013-02-15 18:21 ` [PATCH 1/4] Revert "ARM: SPEAr13xx: Pass DW DMAC platform data from DT" Arnd Bergmann
2013-02-15 18:21   ` Arnd Bergmann
2013-02-15 18:21 ` [PATCH 2/4] dmaengine: dw_dmac: move to generic DMA binding Arnd Bergmann
2013-02-15 18:21   ` Arnd Bergmann
2013-02-15 18:21   ` Arnd Bergmann
2013-02-16  3:26   ` Viresh Kumar
2013-02-16  3:26     ` Viresh Kumar
2013-02-16 10:07     ` Arnd Bergmann
2013-02-16 10:07       ` Arnd Bergmann
2013-02-16 10:07       ` Arnd Bergmann
2013-02-16 10:51       ` Russell King - ARM Linux
2013-02-16 10:51         ` Russell King - ARM Linux
2013-02-16 10:51         ` Russell King - ARM Linux
2013-02-16 13:43         ` Arnd Bergmann
2013-02-16 13:43           ` Arnd Bergmann
2013-02-16 11:13   ` Andy Shevchenko
2013-02-16 11:13     ` Andy Shevchenko
2013-02-16 11:13     ` Andy Shevchenko
2013-02-16 14:00     ` Arnd Bergmann
2013-02-16 14:00       ` Arnd Bergmann
2013-02-16 14:00       ` Arnd Bergmann
2013-02-16 14:53       ` Andy Shevchenko
2013-02-16 14:53         ` Andy Shevchenko
2013-02-16 22:21         ` [PATCHv3 " Arnd Bergmann
2013-02-16 22:21           ` Arnd Bergmann
2013-02-16 22:21           ` Arnd Bergmann
2013-02-16 22:54           ` Andy Shevchenko
2013-02-16 22:54             ` Andy Shevchenko
2013-02-16 23:24             ` [PATCHv4 " Arnd Bergmann
2013-02-16 23:24               ` Arnd Bergmann
2013-02-16 23:24               ` Arnd Bergmann
2013-02-16 23:28             ` [PATCHv3 " Arnd Bergmann
2013-02-16 23:28               ` Arnd Bergmann
2013-02-16 22:23         ` [BONUS PATCH] dmaengine: dw_dmac: simplify master selection Arnd Bergmann
2013-02-16 22:23           ` Arnd Bergmann
2013-02-15 18:21 ` [PATCH 3/4] spi: pl022: use generic DMA slave configuration if possible Arnd Bergmann
2013-02-15 18:21   ` Arnd Bergmann
2013-02-15 18:21 ` [PATCH 4/4] serial: pl011: " Arnd Bergmann
2013-02-15 18:21   ` Arnd Bergmann
2013-02-16  3:26 ` [PATCH 0/4] dw_dmac: introduce generic DMA binding for DT Viresh Kumar
2013-02-16  3:26   ` Viresh Kumar
2013-02-16  3:26   ` Viresh Kumar
2013-02-20  8:03 ` Vinod Koul
2013-02-20  8:03   ` Vinod Koul
2013-02-20  9:50   ` Arnd Bergmann
2013-02-20  9:50     ` Arnd Bergmann
2013-02-20  9:50     ` Arnd Bergmann
2013-02-20  9:58     ` Vinod Koul
2013-02-20  9:58       ` Vinod Koul
2013-02-20 11:10       ` Arnd Bergmann
2013-02-20 11:10         ` Arnd Bergmann

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.