linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Allwinner H6 DMA support
@ 2019-03-07 16:58 Jernej Skrabec
  2019-03-07 16:58 ` [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller Jernej Skrabec
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Jernej Skrabec @ 2019-03-07 16:58 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: vkoul, robh+dt, mark.rutland, dan.j.williams, dmaengine,
	devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
	jernej.skrabec

DMA engine on H6 is almost the same as on older SoCs. The biggest
difference is that it has slightly rearranged bits in registers and
it needs additional clock, probably due to iommu.

These patches were tested with I2S connected to HDMI. I2S needs
additional patches which will be sent later.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (6):
  dt-bindings: arm64: allwinner: h6: Add binding for DMA controller
  dmaengine: sun6i: Add a quirk for additional mbus clock
  dmaengine: sun6i: Add a quirk for setting DRQ fields
  dmaengine: sun6i: Add a quirk for setting mode fields
  dmaengine: sun6i: Add support for H6 DMA
  arm64: dts: allwinner: h6: Add DMA node

 .../devicetree/bindings/dma/sun6i-dma.txt     |   9 +-
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi  |  12 ++
 drivers/dma/sun6i-dma.c                       | 147 +++++++++++++-----
 3 files changed, 131 insertions(+), 37 deletions(-)

-- 
2.21.0


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

* [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller
  2019-03-07 16:58 [PATCH 0/6] Allwinner H6 DMA support Jernej Skrabec
@ 2019-03-07 16:58 ` Jernej Skrabec
  2019-03-16 10:57   ` Vinod Koul
  2019-03-27 23:47   ` Rob Herring
  2019-03-07 16:58 ` [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock Jernej Skrabec
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 17+ messages in thread
From: Jernej Skrabec @ 2019-03-07 16:58 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: vkoul, robh+dt, mark.rutland, dan.j.williams, dmaengine,
	devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
	jernej.skrabec

DMA in H6 is similar to other DMA controller, except it is first which
supports more than 32 request sources and has 16 channels. It also needs
additional clock to be enabled.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 Documentation/devicetree/bindings/dma/sun6i-dma.txt | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 7fccc20d8331..cae31f4e77ba 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -28,12 +28,17 @@ Example:
 	};
 
 ------------------------------------------------------------------------------
-For A64 DMA controller:
+For A64 and H6 DMA controller:
 
 Required properties:
-- compatible:	"allwinner,sun50i-a64-dma"
+- compatible:	Must be one of
+		  "allwinner,sun50i-a64-dma"
+		  "allwinner,sun50i-h6-dma"
 - dma-channels: Number of DMA channels supported by the controller.
 		Refer to Documentation/devicetree/bindings/dma/dma.txt
+- clocks:	In addition to parent AHB clock, it should also contain mbus
+		clock (H6 only)
+- clock-names:	Should contain "bus" and "mbus" (H6 only)
 - all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
 
 Optional properties:
-- 
2.21.0


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

* [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock
  2019-03-07 16:58 [PATCH 0/6] Allwinner H6 DMA support Jernej Skrabec
  2019-03-07 16:58 ` [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller Jernej Skrabec
@ 2019-03-07 16:58 ` Jernej Skrabec
  2019-03-11  5:47   ` Chen-Yu Tsai
  2019-03-16 11:07   ` Vinod Koul
  2019-03-07 16:58 ` [PATCH 3/6] dmaengine: sun6i: Add a quirk for setting DRQ fields Jernej Skrabec
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 17+ messages in thread
From: Jernej Skrabec @ 2019-03-07 16:58 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: vkoul, robh+dt, mark.rutland, dan.j.williams, dmaengine,
	devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
	jernej.skrabec

H6 DMA controller needs additional mbus clock to be enabled.

Add a quirk for it and handle it accordingly.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/dma/sun6i-dma.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 0cd13f17fc11..761555080325 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -129,6 +129,7 @@ struct sun6i_dma_config {
 	u32 dst_burst_lengths;
 	u32 src_addr_widths;
 	u32 dst_addr_widths;
+	bool mbus_clk;
 };
 
 /*
@@ -182,6 +183,7 @@ struct sun6i_dma_dev {
 	struct dma_device	slave;
 	void __iomem		*base;
 	struct clk		*clk;
+	struct clk		*clk_mbus;
 	int			irq;
 	spinlock_t		lock;
 	struct reset_control	*rstc;
@@ -1208,6 +1210,14 @@ static int sun6i_dma_probe(struct platform_device *pdev)
 		return PTR_ERR(sdc->clk);
 	}
 
+	if (sdc->cfg->mbus_clk) {
+		sdc->clk_mbus = devm_clk_get(&pdev->dev, "mbus");
+		if (IS_ERR(sdc->clk_mbus)) {
+			dev_err(&pdev->dev, "No mbus clock specified\n");
+			return PTR_ERR(sdc->clk_mbus);
+		}
+	}
+
 	sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
 	if (IS_ERR(sdc->rstc)) {
 		dev_err(&pdev->dev, "No reset controller specified\n");
@@ -1312,11 +1322,19 @@ static int sun6i_dma_probe(struct platform_device *pdev)
 		goto err_reset_assert;
 	}
 
+	if (sdc->cfg->mbus_clk) {
+		ret = clk_prepare_enable(sdc->clk_mbus);
+		if (ret) {
+			dev_err(&pdev->dev, "Couldn't enable mbus clock\n");
+			goto err_clk_disable;
+		}
+	}
+
 	ret = devm_request_irq(&pdev->dev, sdc->irq, sun6i_dma_interrupt, 0,
 			       dev_name(&pdev->dev), sdc);
 	if (ret) {
 		dev_err(&pdev->dev, "Cannot request IRQ\n");
-		goto err_clk_disable;
+		goto err_mbus_clk_disable;
 	}
 
 	ret = dma_async_device_register(&sdc->slave);
@@ -1341,6 +1359,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
 	dma_async_device_unregister(&sdc->slave);
 err_irq_disable:
 	sun6i_kill_tasklet(sdc);
+err_mbus_clk_disable:
+	clk_disable_unprepare(sdc->clk_mbus);
 err_clk_disable:
 	clk_disable_unprepare(sdc->clk);
 err_reset_assert:
@@ -1359,6 +1379,7 @@ static int sun6i_dma_remove(struct platform_device *pdev)
 
 	sun6i_kill_tasklet(sdc);
 
+	clk_disable_unprepare(sdc->clk_mbus);
 	clk_disable_unprepare(sdc->clk);
 	reset_control_assert(sdc->rstc);
 
-- 
2.21.0


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

* [PATCH 3/6] dmaengine: sun6i: Add a quirk for setting DRQ fields
  2019-03-07 16:58 [PATCH 0/6] Allwinner H6 DMA support Jernej Skrabec
  2019-03-07 16:58 ` [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller Jernej Skrabec
  2019-03-07 16:58 ` [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock Jernej Skrabec
@ 2019-03-07 16:58 ` Jernej Skrabec
  2019-03-07 16:58 ` [PATCH 4/6] dmaengine: sun6i: Add a quirk for setting mode fields Jernej Skrabec
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Jernej Skrabec @ 2019-03-07 16:58 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: vkoul, robh+dt, mark.rutland, dan.j.williams, dmaengine,
	devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
	jernej.skrabec

H6 DMA has more than 32 possible DRQs. That means that current maximum
of 31 DRQs is not enough anymore.

Add a quirk which will set source and destination DRQ number.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/dma/sun6i-dma.c | 48 ++++++++++++++++++++++++-----------------
 1 file changed, 28 insertions(+), 20 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 761555080325..9dd23b76d841 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -68,15 +68,15 @@
 #define DMA_CHAN_LLI_ADDR	0x08
 
 #define DMA_CHAN_CUR_CFG	0x0c
-#define DMA_CHAN_MAX_DRQ		0x1f
-#define DMA_CHAN_CFG_SRC_DRQ(x)		((x) & DMA_CHAN_MAX_DRQ)
+#define DMA_CHAN_MAX_DRQ_A31		0x1f
+#define DMA_CHAN_CFG_SRC_DRQ_A31(x)	((x) & DMA_CHAN_MAX_DRQ_A31)
 #define DMA_CHAN_CFG_SRC_IO_MODE	BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE	(0 << 5)
 #define DMA_CHAN_CFG_SRC_BURST_A31(x)	(((x) & 0x3) << 7)
 #define DMA_CHAN_CFG_SRC_BURST_H3(x)	(((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)	(((x) & 0x3) << 9)
 
-#define DMA_CHAN_CFG_DST_DRQ(x)		(DMA_CHAN_CFG_SRC_DRQ(x) << 16)
+#define DMA_CHAN_CFG_DST_DRQ_A31(x)	(DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
 #define DMA_CHAN_CFG_DST_IO_MODE	(DMA_CHAN_CFG_SRC_IO_MODE << 16)
 #define DMA_CHAN_CFG_DST_LINEAR_MODE	(DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
 #define DMA_CHAN_CFG_DST_BURST_A31(x)	(DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
@@ -125,6 +125,7 @@ struct sun6i_dma_config {
 	 */
 	void (*clock_autogate_enable)(struct sun6i_dma_dev *);
 	void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
+	void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
 	u32 src_burst_lengths;
 	u32 dst_burst_lengths;
 	u32 src_addr_widths;
@@ -311,6 +312,12 @@ static void sun6i_set_burst_length_h3(u32 *p_cfg, s8 src_burst, s8 dst_burst)
 		  DMA_CHAN_CFG_DST_BURST_H3(dst_burst);
 }
 
+static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
+{
+	*p_cfg |= DMA_CHAN_CFG_SRC_DRQ_A31(src_drq) |
+		  DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
 	struct sun6i_desc *txd = pchan->desc;
@@ -634,14 +641,13 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
 
 	burst = convert_burst(8);
 	width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES);
-	v_lli->cfg = DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
-		DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
-		DMA_CHAN_CFG_DST_LINEAR_MODE |
+	v_lli->cfg = DMA_CHAN_CFG_DST_LINEAR_MODE |
 		DMA_CHAN_CFG_SRC_LINEAR_MODE |
 		DMA_CHAN_CFG_SRC_WIDTH(width) |
 		DMA_CHAN_CFG_DST_WIDTH(width);
 
 	sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst);
+	sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, DRQ_SDRAM);
 
 	sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
 
@@ -695,9 +701,8 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
 			v_lli->dst = sconfig->dst_addr;
 			v_lli->cfg = lli_cfg |
 				DMA_CHAN_CFG_DST_IO_MODE |
-				DMA_CHAN_CFG_SRC_LINEAR_MODE |
-				DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
-				DMA_CHAN_CFG_DST_DRQ(vchan->port);
+				DMA_CHAN_CFG_SRC_LINEAR_MODE;
+			sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
 
 			dev_dbg(chan2dev(chan),
 				"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -710,9 +715,8 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
 			v_lli->dst = sg_dma_address(sg);
 			v_lli->cfg = lli_cfg |
 				DMA_CHAN_CFG_DST_LINEAR_MODE |
-				DMA_CHAN_CFG_SRC_IO_MODE |
-				DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
-				DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+				DMA_CHAN_CFG_SRC_IO_MODE;
+			sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
 
 			dev_dbg(chan2dev(chan),
 				"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -780,17 +784,15 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
 			v_lli->dst = sconfig->dst_addr;
 			v_lli->cfg = lli_cfg |
 				DMA_CHAN_CFG_DST_IO_MODE |
-				DMA_CHAN_CFG_SRC_LINEAR_MODE |
-				DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
-				DMA_CHAN_CFG_DST_DRQ(vchan->port);
+				DMA_CHAN_CFG_SRC_LINEAR_MODE;
+			sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
 		} else {
 			v_lli->src = sconfig->src_addr;
 			v_lli->dst = buf_addr + period_len * i;
 			v_lli->cfg = lli_cfg |
 				DMA_CHAN_CFG_DST_LINEAR_MODE |
-				DMA_CHAN_CFG_SRC_IO_MODE |
-				DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
-				DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+				DMA_CHAN_CFG_SRC_IO_MODE;
+			sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
 		}
 
 		prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
@@ -1055,6 +1057,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
 	.nr_max_requests = 30,
 	.nr_max_vchans   = 53,
 	.set_burst_length = sun6i_set_burst_length_a31,
+	.set_drq          = sun6i_set_drq_a31,
 	.src_burst_lengths = BIT(1) | BIT(8),
 	.dst_burst_lengths = BIT(1) | BIT(8),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1076,6 +1079,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
 	.nr_max_vchans   = 37,
 	.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 	.set_burst_length = sun6i_set_burst_length_a31,
+	.set_drq          = sun6i_set_drq_a31,
 	.src_burst_lengths = BIT(1) | BIT(8),
 	.dst_burst_lengths = BIT(1) | BIT(8),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1092,6 +1096,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
 	.nr_max_vchans   = 39,
 	.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 	.set_burst_length = sun6i_set_burst_length_a31,
+	.set_drq          = sun6i_set_drq_a31,
 	.src_burst_lengths = BIT(1) | BIT(8),
 	.dst_burst_lengths = BIT(1) | BIT(8),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1115,6 +1120,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
 	.nr_max_vchans   = 34,
 	.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
 	.set_burst_length = sun6i_set_burst_length_h3,
+	.set_drq          = sun6i_set_drq_a31,
 	.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
 	.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1134,6 +1140,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
 static struct sun6i_dma_config sun50i_a64_dma_cfg = {
 	.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
 	.set_burst_length = sun6i_set_burst_length_h3,
+	.set_drq          = sun6i_set_drq_a31,
 	.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
 	.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1157,6 +1164,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
 	.nr_max_vchans   = 24,
 	.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 	.set_burst_length = sun6i_set_burst_length_a31,
+	.set_drq          = sun6i_set_drq_a31,
 	.src_burst_lengths = BIT(1) | BIT(8),
 	.dst_burst_lengths = BIT(1) | BIT(8),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1272,8 +1280,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
 	ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
 	if (ret && !sdc->max_request) {
 		dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
-			 DMA_CHAN_MAX_DRQ);
-		sdc->max_request = DMA_CHAN_MAX_DRQ;
+			 DMA_CHAN_MAX_DRQ_A31);
+		sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
 	}
 
 	/*
-- 
2.21.0


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

* [PATCH 4/6] dmaengine: sun6i: Add a quirk for setting mode fields
  2019-03-07 16:58 [PATCH 0/6] Allwinner H6 DMA support Jernej Skrabec
                   ` (2 preceding siblings ...)
  2019-03-07 16:58 ` [PATCH 3/6] dmaengine: sun6i: Add a quirk for setting DRQ fields Jernej Skrabec
@ 2019-03-07 16:58 ` Jernej Skrabec
  2019-03-07 16:58 ` [PATCH 5/6] dmaengine: sun6i: Add support for H6 DMA Jernej Skrabec
  2019-03-07 16:58 ` [PATCH 6/6] arm64: dts: allwinner: h6: Add DMA node Jernej Skrabec
  5 siblings, 0 replies; 17+ messages in thread
From: Jernej Skrabec @ 2019-03-07 16:58 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: vkoul, robh+dt, mark.rutland, dan.j.williams, dmaengine,
	devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
	jernej.skrabec

H6 DMA has mode fields in different position than any other currently
supported DMA controller.

Add a quirk for that.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/dma/sun6i-dma.c | 46 ++++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 9dd23b76d841..6a37f8bb39b1 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -70,15 +70,13 @@
 #define DMA_CHAN_CUR_CFG	0x0c
 #define DMA_CHAN_MAX_DRQ_A31		0x1f
 #define DMA_CHAN_CFG_SRC_DRQ_A31(x)	((x) & DMA_CHAN_MAX_DRQ_A31)
-#define DMA_CHAN_CFG_SRC_IO_MODE	BIT(5)
-#define DMA_CHAN_CFG_SRC_LINEAR_MODE	(0 << 5)
+#define DMA_CHAN_CFG_SRC_MODE_A31(x)	(((x) & 0x1) << 5)
 #define DMA_CHAN_CFG_SRC_BURST_A31(x)	(((x) & 0x3) << 7)
 #define DMA_CHAN_CFG_SRC_BURST_H3(x)	(((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)	(((x) & 0x3) << 9)
 
 #define DMA_CHAN_CFG_DST_DRQ_A31(x)	(DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
-#define DMA_CHAN_CFG_DST_IO_MODE	(DMA_CHAN_CFG_SRC_IO_MODE << 16)
-#define DMA_CHAN_CFG_DST_LINEAR_MODE	(DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
+#define DMA_CHAN_CFG_DST_MODE_A31(x)	(DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
 #define DMA_CHAN_CFG_DST_BURST_A31(x)	(DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
 #define DMA_CHAN_CFG_DST_BURST_H3(x)	(DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
 #define DMA_CHAN_CFG_DST_WIDTH(x)	(DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
@@ -98,6 +96,8 @@
 #define LLI_LAST_ITEM	0xfffff800
 #define NORMAL_WAIT	8
 #define DRQ_SDRAM	1
+#define LINEAR_MODE     0
+#define IO_MODE         1
 
 /* forward declaration */
 struct sun6i_dma_dev;
@@ -126,6 +126,7 @@ struct sun6i_dma_config {
 	void (*clock_autogate_enable)(struct sun6i_dma_dev *);
 	void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
 	void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
+	void (*set_mode)(u32 *p_cfg, s8 src_mode, s8 dst_mode);
 	u32 src_burst_lengths;
 	u32 dst_burst_lengths;
 	u32 src_addr_widths;
@@ -318,6 +319,12 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
 		  DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
 }
 
+static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
+{
+	*p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
+		  DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
 	struct sun6i_desc *txd = pchan->desc;
@@ -641,13 +648,12 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
 
 	burst = convert_burst(8);
 	width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES);
-	v_lli->cfg = DMA_CHAN_CFG_DST_LINEAR_MODE |
-		DMA_CHAN_CFG_SRC_LINEAR_MODE |
-		DMA_CHAN_CFG_SRC_WIDTH(width) |
+	v_lli->cfg = DMA_CHAN_CFG_SRC_WIDTH(width) |
 		DMA_CHAN_CFG_DST_WIDTH(width);
 
 	sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst);
 	sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, DRQ_SDRAM);
+	sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, LINEAR_MODE);
 
 	sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
 
@@ -699,10 +705,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
 		if (dir == DMA_MEM_TO_DEV) {
 			v_lli->src = sg_dma_address(sg);
 			v_lli->dst = sconfig->dst_addr;
-			v_lli->cfg = lli_cfg |
-				DMA_CHAN_CFG_DST_IO_MODE |
-				DMA_CHAN_CFG_SRC_LINEAR_MODE;
+			v_lli->cfg = lli_cfg;
 			sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
+			sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE);
 
 			dev_dbg(chan2dev(chan),
 				"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -713,10 +718,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
 		} else {
 			v_lli->src = sconfig->src_addr;
 			v_lli->dst = sg_dma_address(sg);
-			v_lli->cfg = lli_cfg |
-				DMA_CHAN_CFG_DST_LINEAR_MODE |
-				DMA_CHAN_CFG_SRC_IO_MODE;
+			v_lli->cfg = lli_cfg;
 			sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
+			sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE);
 
 			dev_dbg(chan2dev(chan),
 				"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -782,17 +786,15 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
 		if (dir == DMA_MEM_TO_DEV) {
 			v_lli->src = buf_addr + period_len * i;
 			v_lli->dst = sconfig->dst_addr;
-			v_lli->cfg = lli_cfg |
-				DMA_CHAN_CFG_DST_IO_MODE |
-				DMA_CHAN_CFG_SRC_LINEAR_MODE;
+			v_lli->cfg = lli_cfg;
 			sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
+			sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE);
 		} else {
 			v_lli->src = sconfig->src_addr;
 			v_lli->dst = buf_addr + period_len * i;
-			v_lli->cfg = lli_cfg |
-				DMA_CHAN_CFG_DST_LINEAR_MODE |
-				DMA_CHAN_CFG_SRC_IO_MODE;
+			v_lli->cfg = lli_cfg;
 			sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
+			sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE);
 		}
 
 		prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
@@ -1058,6 +1060,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
 	.nr_max_vchans   = 53,
 	.set_burst_length = sun6i_set_burst_length_a31,
 	.set_drq          = sun6i_set_drq_a31,
+	.set_mode         = sun6i_set_mode_a31,
 	.src_burst_lengths = BIT(1) | BIT(8),
 	.dst_burst_lengths = BIT(1) | BIT(8),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1080,6 +1083,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
 	.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 	.set_burst_length = sun6i_set_burst_length_a31,
 	.set_drq          = sun6i_set_drq_a31,
+	.set_mode         = sun6i_set_mode_a31,
 	.src_burst_lengths = BIT(1) | BIT(8),
 	.dst_burst_lengths = BIT(1) | BIT(8),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1097,6 +1101,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
 	.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 	.set_burst_length = sun6i_set_burst_length_a31,
 	.set_drq          = sun6i_set_drq_a31,
+	.set_mode         = sun6i_set_mode_a31,
 	.src_burst_lengths = BIT(1) | BIT(8),
 	.dst_burst_lengths = BIT(1) | BIT(8),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1121,6 +1126,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
 	.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
 	.set_burst_length = sun6i_set_burst_length_h3,
 	.set_drq          = sun6i_set_drq_a31,
+	.set_mode         = sun6i_set_mode_a31,
 	.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
 	.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1141,6 +1147,7 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
 	.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
 	.set_burst_length = sun6i_set_burst_length_h3,
 	.set_drq          = sun6i_set_drq_a31,
+	.set_mode         = sun6i_set_mode_a31,
 	.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
 	.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1165,6 +1172,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
 	.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 	.set_burst_length = sun6i_set_burst_length_a31,
 	.set_drq          = sun6i_set_drq_a31,
+	.set_mode         = sun6i_set_mode_a31,
 	.src_burst_lengths = BIT(1) | BIT(8),
 	.dst_burst_lengths = BIT(1) | BIT(8),
 	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
-- 
2.21.0


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

* [PATCH 5/6] dmaengine: sun6i: Add support for H6 DMA
  2019-03-07 16:58 [PATCH 0/6] Allwinner H6 DMA support Jernej Skrabec
                   ` (3 preceding siblings ...)
  2019-03-07 16:58 ` [PATCH 4/6] dmaengine: sun6i: Add a quirk for setting mode fields Jernej Skrabec
@ 2019-03-07 16:58 ` Jernej Skrabec
  2019-03-16 11:13   ` Vinod Koul
  2019-03-07 16:58 ` [PATCH 6/6] arm64: dts: allwinner: h6: Add DMA node Jernej Skrabec
  5 siblings, 1 reply; 17+ messages in thread
From: Jernej Skrabec @ 2019-03-07 16:58 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: vkoul, robh+dt, mark.rutland, dan.j.williams, dmaengine,
	devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
	jernej.skrabec

H6 DMA has more than 32 supported DRQs, which means that configuration
register is slightly rearranged. It also needs additional clock to be
enabled.

Add support for it.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/dma/sun6i-dma.c | 44 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 6a37f8bb39b1..eceedd139651 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -69,14 +69,19 @@
 
 #define DMA_CHAN_CUR_CFG	0x0c
 #define DMA_CHAN_MAX_DRQ_A31		0x1f
+#define DMA_CHAN_MAX_DRQ_H6		0x3f
 #define DMA_CHAN_CFG_SRC_DRQ_A31(x)	((x) & DMA_CHAN_MAX_DRQ_A31)
+#define DMA_CHAN_CFG_SRC_DRQ_H6(x)	((x) & DMA_CHAN_MAX_DRQ_H6)
 #define DMA_CHAN_CFG_SRC_MODE_A31(x)	(((x) & 0x1) << 5)
+#define DMA_CHAN_CFG_SRC_MODE_H6(x)	(((x) & 0x1) << 8)
 #define DMA_CHAN_CFG_SRC_BURST_A31(x)	(((x) & 0x3) << 7)
 #define DMA_CHAN_CFG_SRC_BURST_H3(x)	(((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)	(((x) & 0x3) << 9)
 
 #define DMA_CHAN_CFG_DST_DRQ_A31(x)	(DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_DRQ_H6(x)	(DMA_CHAN_CFG_SRC_DRQ_H6(x) << 16)
 #define DMA_CHAN_CFG_DST_MODE_A31(x)	(DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_MODE_H6(x)	(DMA_CHAN_CFG_SRC_MODE_H6(x) << 16)
 #define DMA_CHAN_CFG_DST_BURST_A31(x)	(DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
 #define DMA_CHAN_CFG_DST_BURST_H3(x)	(DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
 #define DMA_CHAN_CFG_DST_WIDTH(x)	(DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
@@ -319,12 +324,24 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
 		  DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
 }
 
+static void sun6i_set_drq_h6(u32 *p_cfg, s8 src_drq, s8 dst_drq)
+{
+	*p_cfg |= DMA_CHAN_CFG_SRC_DRQ_H6(src_drq) |
+		  DMA_CHAN_CFG_DST_DRQ_H6(dst_drq);
+}
+
 static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
 {
 	*p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
 		  DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
 }
 
+static void sun6i_set_mode_h6(u32 *p_cfg, s8 src_mode, s8 dst_mode)
+{
+	*p_cfg |= DMA_CHAN_CFG_SRC_MODE_H6(src_mode) |
+		  DMA_CHAN_CFG_DST_MODE_H6(dst_mode);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
 	struct sun6i_desc *txd = pchan->desc;
@@ -1160,6 +1177,28 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
 			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
 };
 
+/*
+ * The H6 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_h6_dma_cfg = {
+	.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+	.set_burst_length = sun6i_set_burst_length_h3,
+	.set_drq          = sun6i_set_drq_h6,
+	.set_mode         = sun6i_set_mode_h6,
+	.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+	.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+			     BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+			     BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+	.dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+			     BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+			     BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+	.mbus_clk = true,
+};
+
 /*
  * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
  * and a total of 24 usable source and destination endpoints.
@@ -1190,6 +1229,7 @@ static const struct of_device_id sun6i_dma_match[] = {
 	{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
 	{ .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
 	{ .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
+	{ .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dma_match);
@@ -1288,8 +1328,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
 	ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
 	if (ret && !sdc->max_request) {
 		dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
-			 DMA_CHAN_MAX_DRQ_A31);
-		sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
+			 DMA_CHAN_MAX_DRQ_H6);
+		sdc->max_request = DMA_CHAN_MAX_DRQ_H6;
 	}
 
 	/*
-- 
2.21.0


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

* [PATCH 6/6] arm64: dts: allwinner: h6: Add DMA node
  2019-03-07 16:58 [PATCH 0/6] Allwinner H6 DMA support Jernej Skrabec
                   ` (4 preceding siblings ...)
  2019-03-07 16:58 ` [PATCH 5/6] dmaengine: sun6i: Add support for H6 DMA Jernej Skrabec
@ 2019-03-07 16:58 ` Jernej Skrabec
  5 siblings, 0 replies; 17+ messages in thread
From: Jernej Skrabec @ 2019-03-07 16:58 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: vkoul, robh+dt, mark.rutland, dan.j.williams, dmaengine,
	devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
	jernej.skrabec

H6 has DMA controller which supports 16 channels.

Add a node for it.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index c9e861a50a63..ff8cf6e3b6ec 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -192,6 +192,18 @@
 			#reset-cells = <1>;
 		};
 
+		dma: dma-controller@3002000 {
+			compatible = "allwinner,sun50i-h6-dma";
+			reg = <0x03002000 0x1000>;
+			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+			clock-names = "bus", "mbus";
+			dma-channels = <16>;
+			dma-requests = <46>;
+			resets = <&ccu RST_BUS_DMA>;
+			#dma-cells = <1>;
+		};
+
 		pio: pinctrl@300b000 {
 			compatible = "allwinner,sun50i-h6-pinctrl";
 			reg = <0x0300b000 0x400>;
-- 
2.21.0


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

* Re: [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock
  2019-03-07 16:58 ` [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock Jernej Skrabec
@ 2019-03-11  5:47   ` Chen-Yu Tsai
  2019-03-16 11:07   ` Vinod Koul
  1 sibling, 0 replies; 17+ messages in thread
From: Chen-Yu Tsai @ 2019-03-11  5:47 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: Maxime Ripard, vkoul, Rob Herring, Mark Rutland, Dan Williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

On Fri, Mar 8, 2019 at 12:58 AM Jernej Skrabec <jernej.skrabec@siol.net> wrote:
>
> H6 DMA controller needs additional mbus clock to be enabled.
>
> Add a quirk for it and handle it accordingly.
>
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/dma/sun6i-dma.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index 0cd13f17fc11..761555080325 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -129,6 +129,7 @@ struct sun6i_dma_config {
>         u32 dst_burst_lengths;
>         u32 src_addr_widths;
>         u32 dst_addr_widths;
> +       bool mbus_clk;

Nit: has_mbus_clk. Be explicit. Leave nothing to assumptions.

>  };
>
>  /*
> @@ -182,6 +183,7 @@ struct sun6i_dma_dev {
>         struct dma_device       slave;
>         void __iomem            *base;
>         struct clk              *clk;
> +       struct clk              *clk_mbus;
>         int                     irq;
>         spinlock_t              lock;
>         struct reset_control    *rstc;
> @@ -1208,6 +1210,14 @@ static int sun6i_dma_probe(struct platform_device *pdev)
>                 return PTR_ERR(sdc->clk);
>         }
>
> +       if (sdc->cfg->mbus_clk) {
> +               sdc->clk_mbus = devm_clk_get(&pdev->dev, "mbus");
> +               if (IS_ERR(sdc->clk_mbus)) {
> +                       dev_err(&pdev->dev, "No mbus clock specified\n");
> +                       return PTR_ERR(sdc->clk_mbus);
> +               }
> +       }
> +
>         sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
>         if (IS_ERR(sdc->rstc)) {
>                 dev_err(&pdev->dev, "No reset controller specified\n");
> @@ -1312,11 +1322,19 @@ static int sun6i_dma_probe(struct platform_device *pdev)
>                 goto err_reset_assert;
>         }
>
> +       if (sdc->cfg->mbus_clk) {
> +               ret = clk_prepare_enable(sdc->clk_mbus);

The clk API checks for NULL pointer, so you could just drop the
conditional here.

> +               if (ret) {
> +                       dev_err(&pdev->dev, "Couldn't enable mbus clock\n");
> +                       goto err_clk_disable;
> +               }
> +       }
> +
>         ret = devm_request_irq(&pdev->dev, sdc->irq, sun6i_dma_interrupt, 0,
>                                dev_name(&pdev->dev), sdc);
>         if (ret) {
>                 dev_err(&pdev->dev, "Cannot request IRQ\n");
> -               goto err_clk_disable;
> +               goto err_mbus_clk_disable;
>         }
>
>         ret = dma_async_device_register(&sdc->slave);
> @@ -1341,6 +1359,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
>         dma_async_device_unregister(&sdc->slave);
>  err_irq_disable:
>         sun6i_kill_tasklet(sdc);
> +err_mbus_clk_disable:
> +       clk_disable_unprepare(sdc->clk_mbus);

Since you aren't using it here either.

ChenYu


>  err_clk_disable:
>         clk_disable_unprepare(sdc->clk);
>  err_reset_assert:
> @@ -1359,6 +1379,7 @@ static int sun6i_dma_remove(struct platform_device *pdev)
>
>         sun6i_kill_tasklet(sdc);
>
> +       clk_disable_unprepare(sdc->clk_mbus);
>         clk_disable_unprepare(sdc->clk);
>         reset_control_assert(sdc->rstc);
>
> --
> 2.21.0
>

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

* Re: [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller
  2019-03-07 16:58 ` [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller Jernej Skrabec
@ 2019-03-16 10:57   ` Vinod Koul
  2019-03-16 11:27     ` Jernej Škrabec
  2019-03-27 23:47   ` Rob Herring
  1 sibling, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2019-03-16 10:57 UTC (permalink / raw)
  To: Jernej Skrabec, Rob Herring
  Cc: maxime.ripard, wens, robh+dt, mark.rutland, dan.j.williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

On 07-03-19, 17:58, Jernej Skrabec wrote:
> DMA in H6 is similar to other DMA controller, except it is first which
> supports more than 32 request sources and has 16 channels. It also needs
> additional clock to be enabled.

Please see DT folks on this patch, when in doubt, use get_maintainers.pl
Need an ack on this patch before applying

> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  Documentation/devicetree/bindings/dma/sun6i-dma.txt | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
> index 7fccc20d8331..cae31f4e77ba 100644
> --- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
> +++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
> @@ -28,12 +28,17 @@ Example:
>  	};
>  
>  ------------------------------------------------------------------------------
> -For A64 DMA controller:
> +For A64 and H6 DMA controller:
>  
>  Required properties:
> -- compatible:	"allwinner,sun50i-a64-dma"
> +- compatible:	Must be one of
> +		  "allwinner,sun50i-a64-dma"
> +		  "allwinner,sun50i-h6-dma"
>  - dma-channels: Number of DMA channels supported by the controller.
>  		Refer to Documentation/devicetree/bindings/dma/dma.txt
> +- clocks:	In addition to parent AHB clock, it should also contain mbus
> +		clock (H6 only)
> +- clock-names:	Should contain "bus" and "mbus" (H6 only)
>  - all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
>  
>  Optional properties:
> -- 
> 2.21.0

-- 
~Vinod

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

* Re: [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock
  2019-03-07 16:58 ` [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock Jernej Skrabec
  2019-03-11  5:47   ` Chen-Yu Tsai
@ 2019-03-16 11:07   ` Vinod Koul
  2019-03-16 11:23     ` Jernej Škrabec
  1 sibling, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2019-03-16 11:07 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: maxime.ripard, wens, robh+dt, mark.rutland, dan.j.williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

On 07-03-19, 17:58, Jernej Skrabec wrote:
> H6 DMA controller needs additional mbus clock to be enabled.
> 
> Add a quirk for it and handle it accordingly.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/dma/sun6i-dma.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index 0cd13f17fc11..761555080325 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -129,6 +129,7 @@ struct sun6i_dma_config {
>  	u32 dst_burst_lengths;
>  	u32 src_addr_widths;
>  	u32 dst_addr_widths;
> +	bool mbus_clk;
>  };
>  
>  /*
> @@ -182,6 +183,7 @@ struct sun6i_dma_dev {
>  	struct dma_device	slave;
>  	void __iomem		*base;
>  	struct clk		*clk;
> +	struct clk		*clk_mbus;

So rather than have mbus_clk and then a ptr, why not use the ptr and use
NULL value to check for..?

>  	int			irq;
>  	spinlock_t		lock;
>  	struct reset_control	*rstc;
> @@ -1208,6 +1210,14 @@ static int sun6i_dma_probe(struct platform_device *pdev)
>  		return PTR_ERR(sdc->clk);
>  	}
>  
> +	if (sdc->cfg->mbus_clk) {

where is the populated? I was expecting this to be set based on DT!

> +		sdc->clk_mbus = devm_clk_get(&pdev->dev, "mbus");
> +		if (IS_ERR(sdc->clk_mbus)) {
> +			dev_err(&pdev->dev, "No mbus clock specified\n");
> +			return PTR_ERR(sdc->clk_mbus);
> +		}
> +	}
> +
>  	sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
>  	if (IS_ERR(sdc->rstc)) {
>  		dev_err(&pdev->dev, "No reset controller specified\n");
> @@ -1312,11 +1322,19 @@ static int sun6i_dma_probe(struct platform_device *pdev)
>  		goto err_reset_assert;
>  	}
>  
> +	if (sdc->cfg->mbus_clk) {
> +		ret = clk_prepare_enable(sdc->clk_mbus);
> +		if (ret) {
> +			dev_err(&pdev->dev, "Couldn't enable mbus clock\n");
> +			goto err_clk_disable;
> +		}
> +	}
> +
>  	ret = devm_request_irq(&pdev->dev, sdc->irq, sun6i_dma_interrupt, 0,
>  			       dev_name(&pdev->dev), sdc);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Cannot request IRQ\n");
> -		goto err_clk_disable;
> +		goto err_mbus_clk_disable;
>  	}
>  
>  	ret = dma_async_device_register(&sdc->slave);
> @@ -1341,6 +1359,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
>  	dma_async_device_unregister(&sdc->slave);
>  err_irq_disable:
>  	sun6i_kill_tasklet(sdc);
> +err_mbus_clk_disable:
> +	clk_disable_unprepare(sdc->clk_mbus);
>  err_clk_disable:
>  	clk_disable_unprepare(sdc->clk);
>  err_reset_assert:
> @@ -1359,6 +1379,7 @@ static int sun6i_dma_remove(struct platform_device *pdev)
>  
>  	sun6i_kill_tasklet(sdc);
>  
> +	clk_disable_unprepare(sdc->clk_mbus);
>  	clk_disable_unprepare(sdc->clk);
>  	reset_control_assert(sdc->rstc);
>  
> -- 
> 2.21.0

-- 
~Vinod

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

* Re: [PATCH 5/6] dmaengine: sun6i: Add support for H6 DMA
  2019-03-07 16:58 ` [PATCH 5/6] dmaengine: sun6i: Add support for H6 DMA Jernej Skrabec
@ 2019-03-16 11:13   ` Vinod Koul
  2019-03-16 11:37     ` Jernej Škrabec
  0 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2019-03-16 11:13 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: maxime.ripard, wens, robh+dt, mark.rutland, dan.j.williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

On 07-03-19, 17:58, Jernej Skrabec wrote:
> H6 DMA has more than 32 supported DRQs, which means that configuration
> register is slightly rearranged. It also needs additional clock to be
> enabled.

Okay how many register are rearraged in the new IP block. If there are
large changes, consider using regmap_fields to abstract the register and
bit differences..

> 
> Add support for it.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/dma/sun6i-dma.c | 44 +++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index 6a37f8bb39b1..eceedd139651 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -69,14 +69,19 @@
>  
>  #define DMA_CHAN_CUR_CFG	0x0c
>  #define DMA_CHAN_MAX_DRQ_A31		0x1f
> +#define DMA_CHAN_MAX_DRQ_H6		0x3f
>  #define DMA_CHAN_CFG_SRC_DRQ_A31(x)	((x) & DMA_CHAN_MAX_DRQ_A31)
> +#define DMA_CHAN_CFG_SRC_DRQ_H6(x)	((x) & DMA_CHAN_MAX_DRQ_H6)
>  #define DMA_CHAN_CFG_SRC_MODE_A31(x)	(((x) & 0x1) << 5)
> +#define DMA_CHAN_CFG_SRC_MODE_H6(x)	(((x) & 0x1) << 8)
>  #define DMA_CHAN_CFG_SRC_BURST_A31(x)	(((x) & 0x3) << 7)
>  #define DMA_CHAN_CFG_SRC_BURST_H3(x)	(((x) & 0x3) << 6)
>  #define DMA_CHAN_CFG_SRC_WIDTH(x)	(((x) & 0x3) << 9)
>  
>  #define DMA_CHAN_CFG_DST_DRQ_A31(x)	(DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
> +#define DMA_CHAN_CFG_DST_DRQ_H6(x)	(DMA_CHAN_CFG_SRC_DRQ_H6(x) << 16)
>  #define DMA_CHAN_CFG_DST_MODE_A31(x)	(DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
> +#define DMA_CHAN_CFG_DST_MODE_H6(x)	(DMA_CHAN_CFG_SRC_MODE_H6(x) << 16)
>  #define DMA_CHAN_CFG_DST_BURST_A31(x)	(DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
>  #define DMA_CHAN_CFG_DST_BURST_H3(x)	(DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
>  #define DMA_CHAN_CFG_DST_WIDTH(x)	(DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
> @@ -319,12 +324,24 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
>  		  DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
>  }
>  
> +static void sun6i_set_drq_h6(u32 *p_cfg, s8 src_drq, s8 dst_drq)
> +{
> +	*p_cfg |= DMA_CHAN_CFG_SRC_DRQ_H6(src_drq) |
> +		  DMA_CHAN_CFG_DST_DRQ_H6(dst_drq);
> +}
> +
>  static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
>  {
>  	*p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
>  		  DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
>  }
>  
> +static void sun6i_set_mode_h6(u32 *p_cfg, s8 src_mode, s8 dst_mode)
> +{
> +	*p_cfg |= DMA_CHAN_CFG_SRC_MODE_H6(src_mode) |
> +		  DMA_CHAN_CFG_DST_MODE_H6(dst_mode);
> +}
> +
>  static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
>  {
>  	struct sun6i_desc *txd = pchan->desc;
> @@ -1160,6 +1177,28 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
>  			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
>  };
>  
> +/*
> + * The H6 binding uses the number of dma channels from the
> + * device tree node.
> + */
> +static struct sun6i_dma_config sun50i_h6_dma_cfg = {
> +	.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
> +	.set_burst_length = sun6i_set_burst_length_h3,
> +	.set_drq          = sun6i_set_drq_h6,
> +	.set_mode         = sun6i_set_mode_h6,
> +	.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> +	.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> +	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> +	.dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> +			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> +	.mbus_clk = true,
> +};
> +
>  /*
>   * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
>   * and a total of 24 usable source and destination endpoints.
> @@ -1190,6 +1229,7 @@ static const struct of_device_id sun6i_dma_match[] = {
>  	{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
>  	{ .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
>  	{ .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
> +	{ .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, sun6i_dma_match);
> @@ -1288,8 +1328,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
>  	ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
>  	if (ret && !sdc->max_request) {
>  		dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
> -			 DMA_CHAN_MAX_DRQ_A31);
> -		sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
> +			 DMA_CHAN_MAX_DRQ_H6);
> +		sdc->max_request = DMA_CHAN_MAX_DRQ_H6;
>  	}
>  
>  	/*
> -- 
> 2.21.0

-- 
~Vinod

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

* Re: [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock
  2019-03-16 11:07   ` Vinod Koul
@ 2019-03-16 11:23     ` Jernej Škrabec
  2019-03-22 12:59       ` Vinod Koul
  0 siblings, 1 reply; 17+ messages in thread
From: Jernej Škrabec @ 2019-03-16 11:23 UTC (permalink / raw)
  To: Vinod Koul
  Cc: maxime.ripard, wens, robh+dt, mark.rutland, dan.j.williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

Hi!

Dne sobota, 16. marec 2019 ob 12:07:53 CET je Vinod Koul napisal(a):
> On 07-03-19, 17:58, Jernej Skrabec wrote:
> > H6 DMA controller needs additional mbus clock to be enabled.
> > 
> > Add a quirk for it and handle it accordingly.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  drivers/dma/sun6i-dma.c | 23 ++++++++++++++++++++++-
> >  1 file changed, 22 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> > index 0cd13f17fc11..761555080325 100644
> > --- a/drivers/dma/sun6i-dma.c
> > +++ b/drivers/dma/sun6i-dma.c
> > @@ -129,6 +129,7 @@ struct sun6i_dma_config {
> > 
> >  	u32 dst_burst_lengths;
> >  	u32 src_addr_widths;
> >  	u32 dst_addr_widths;
> > 
> > +	bool mbus_clk;
> > 
> >  };
> >  
> >  /*
> > 
> > @@ -182,6 +183,7 @@ struct sun6i_dma_dev {
> > 
> >  	struct dma_device	slave;
> >  	void __iomem		*base;
> >  	struct clk		*clk;
> > 
> > +	struct clk		*clk_mbus;
> 
> So rather than have mbus_clk and then a ptr, why not use the ptr and use
> NULL value to check for..?
> 

I'm not sure what you mean here. clk_mbus will hold a reference to a clock 
retrieved by devm_clk_get() so it has to be "struct clk *".

What I'm missing here?

> >  	int			irq;
> >  	spinlock_t		lock;
> >  	struct reset_control	*rstc;
> > 
> > @@ -1208,6 +1210,14 @@ static int sun6i_dma_probe(struct platform_device
> > *pdev)> 
> >  		return PTR_ERR(sdc->clk);
> >  	
> >  	}
> > 
> > +	if (sdc->cfg->mbus_clk) {
> 
> where is the populated? I was expecting this to be set based on DT!

Of course it is based on DT. Check patch 5, where quirks structure attached to 
H6 DMA compatible contains ".mbus_clk = true,". "sdc->cfg" points to this 
quirk structure.

> 
> > +		sdc->clk_mbus = devm_clk_get(&pdev->dev, "mbus");
> > +		if (IS_ERR(sdc->clk_mbus)) {
> > +			dev_err(&pdev->dev, "No mbus clock 
specified\n");
> > +			return PTR_ERR(sdc->clk_mbus);
> > +		}
> > +	}
> > +
> > 
> >  	sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
> >  	if (IS_ERR(sdc->rstc)) {
> >  	
> >  		dev_err(&pdev->dev, "No reset controller specified\n");
> > 
> > @@ -1312,11 +1322,19 @@ static int sun6i_dma_probe(struct platform_device
> > *pdev)> 
> >  		goto err_reset_assert;
> >  	
> >  	}
> > 
> > +	if (sdc->cfg->mbus_clk) {
> > +		ret = clk_prepare_enable(sdc->clk_mbus);
> > +		if (ret) {
> > +			dev_err(&pdev->dev, "Couldn't enable mbus 
clock\n");
> > +			goto err_clk_disable;
> > +		}
> > +	}
> > +
> > 
> >  	ret = devm_request_irq(&pdev->dev, sdc->irq, sun6i_dma_interrupt, 
0,
> >  	
> >  			       dev_name(&pdev->dev), sdc);
> >  	
> >  	if (ret) {
> >  	
> >  		dev_err(&pdev->dev, "Cannot request IRQ\n");
> > 
> > -		goto err_clk_disable;
> > +		goto err_mbus_clk_disable;
> > 
> >  	}
> >  	
> >  	ret = dma_async_device_register(&sdc->slave);
> > 
> > @@ -1341,6 +1359,8 @@ static int sun6i_dma_probe(struct platform_device
> > *pdev)> 
> >  	dma_async_device_unregister(&sdc->slave);
> >  
> >  err_irq_disable:
> >  	sun6i_kill_tasklet(sdc);
> > 
> > +err_mbus_clk_disable:
> > +	clk_disable_unprepare(sdc->clk_mbus);
> > 
> >  err_clk_disable:
> >  	clk_disable_unprepare(sdc->clk);
> >  
> >  err_reset_assert:
> > @@ -1359,6 +1379,7 @@ static int sun6i_dma_remove(struct platform_device
> > *pdev)> 
> >  	sun6i_kill_tasklet(sdc);
> > 
> > +	clk_disable_unprepare(sdc->clk_mbus);
> > 
> >  	clk_disable_unprepare(sdc->clk);
> >  	reset_control_assert(sdc->rstc);





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

* Re: [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller
  2019-03-16 10:57   ` Vinod Koul
@ 2019-03-16 11:27     ` Jernej Škrabec
  0 siblings, 0 replies; 17+ messages in thread
From: Jernej Škrabec @ 2019-03-16 11:27 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Rob Herring, maxime.ripard, wens, mark.rutland, dan.j.williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

Dne sobota, 16. marec 2019 ob 11:57:11 CET je Vinod Koul napisal(a):
> On 07-03-19, 17:58, Jernej Skrabec wrote:
> > DMA in H6 is similar to other DMA controller, except it is first which
> > supports more than 32 request sources and has 16 channels. It also needs
> > additional clock to be enabled.
> 
> Please see DT folks on this patch, when in doubt, use get_maintainers.pl
> Need an ack on this patch before applying

They are already in CC.

> 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  Documentation/devicetree/bindings/dma/sun6i-dma.txt | 9 +++++++--
> >  1 file changed, 7 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
> > b/Documentation/devicetree/bindings/dma/sun6i-dma.txt index
> > 7fccc20d8331..cae31f4e77ba 100644
> > --- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
> > +++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
> > 
> > @@ -28,12 +28,17 @@ Example:
> >  	};
> >  
> >  -------------------------------------------------------------------------
> >  -----> 
> > -For A64 DMA controller:
> > 
> > +For A64 and H6 DMA controller:
> >  Required properties:
> > -- compatible:	"allwinner,sun50i-a64-dma"
> > +- compatible:	Must be one of
> > +		  "allwinner,sun50i-a64-dma"
> > +		  "allwinner,sun50i-h6-dma"
> > 
> >  - dma-channels: Number of DMA channels supported by the controller.
> >  
> >  		Refer to Documentation/devicetree/bindings/dma/dma.txt
> > 
> > +- clocks:	In addition to parent AHB clock, it should also contain mbus
> > +		clock (H6 only)
> > +- clock-names:	Should contain "bus" and "mbus" (H6 only)
> > 
> >  - all properties above, i.e. reg, interrupts, clocks, resets and
> >  #dma-cells
> >  
> >  Optional properties:





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

* Re: [PATCH 5/6] dmaengine: sun6i: Add support for H6 DMA
  2019-03-16 11:13   ` Vinod Koul
@ 2019-03-16 11:37     ` Jernej Škrabec
  0 siblings, 0 replies; 17+ messages in thread
From: Jernej Škrabec @ 2019-03-16 11:37 UTC (permalink / raw)
  To: Vinod Koul
  Cc: maxime.ripard, wens, robh+dt, mark.rutland, dan.j.williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

Dne sobota, 16. marec 2019 ob 12:13:24 CET je Vinod Koul napisal(a):
> On 07-03-19, 17:58, Jernej Skrabec wrote:
> > H6 DMA has more than 32 supported DRQs, which means that configuration
> > register is slightly rearranged. It also needs additional clock to be
> > enabled.
> 
> Okay how many register are rearraged in the new IP block. If there are
> large changes, consider using regmap_fields to abstract the register and
> bit differences..

Only one, config register. Regmap unfortunately is not an option here, because 
how DMA peripheral works. Register values are actually stored in linked list 
somewhere in RAM and when current DMA request is finished, DMA peripheral auto 
loads next set of registers from memory.

> 
> > Add support for it.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  drivers/dma/sun6i-dma.c | 44 +++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 42 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> > index 6a37f8bb39b1..eceedd139651 100644
> > --- a/drivers/dma/sun6i-dma.c
> > +++ b/drivers/dma/sun6i-dma.c
> > @@ -69,14 +69,19 @@
> > 
> >  #define DMA_CHAN_CUR_CFG	0x0c
> >  #define DMA_CHAN_MAX_DRQ_A31		0x1f
> > 
> > +#define DMA_CHAN_MAX_DRQ_H6		0x3f
> > 
> >  #define DMA_CHAN_CFG_SRC_DRQ_A31(x)	((x) & DMA_CHAN_MAX_DRQ_A31)
> > 
> > +#define DMA_CHAN_CFG_SRC_DRQ_H6(x)	((x) & DMA_CHAN_MAX_DRQ_H6)
> > 
> >  #define DMA_CHAN_CFG_SRC_MODE_A31(x)	(((x) & 0x1) << 5)
> > 
> > +#define DMA_CHAN_CFG_SRC_MODE_H6(x)	(((x) & 0x1) << 8)
> > 
> >  #define DMA_CHAN_CFG_SRC_BURST_A31(x)	(((x) & 0x3) << 7)
> >  #define DMA_CHAN_CFG_SRC_BURST_H3(x)	(((x) & 0x3) << 6)
> >  #define DMA_CHAN_CFG_SRC_WIDTH(x)	(((x) & 0x3) << 9)
> >  
> >  #define DMA_CHAN_CFG_DST_DRQ_A31(x)	(DMA_CHAN_CFG_SRC_DRQ_A31(x) << 
16)
> > 
> > +#define DMA_CHAN_CFG_DST_DRQ_H6(x)	(DMA_CHAN_CFG_SRC_DRQ_H6(x) << 16)
> > 
> >  #define DMA_CHAN_CFG_DST_MODE_A31(x)	(DMA_CHAN_CFG_SRC_MODE_A31(x) << 
16)
> > 
> > +#define DMA_CHAN_CFG_DST_MODE_H6(x)	(DMA_CHAN_CFG_SRC_MODE_H6(x) << 16)
> > 
> >  #define DMA_CHAN_CFG_DST_BURST_A31(x)	(DMA_CHAN_CFG_SRC_BURST_A31(x) <<
> >  16)
> >  #define DMA_CHAN_CFG_DST_BURST_H3(x)	(DMA_CHAN_CFG_SRC_BURST_H3(x) << 
16)
> >  #define DMA_CHAN_CFG_DST_WIDTH(x)	(DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
> > 
> > @@ -319,12 +324,24 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8
> > src_drq, s8 dst_drq)> 
> >  		  DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
> >  
> >  }
> > 
> > +static void sun6i_set_drq_h6(u32 *p_cfg, s8 src_drq, s8 dst_drq)
> > +{
> > +	*p_cfg |= DMA_CHAN_CFG_SRC_DRQ_H6(src_drq) |
> > +		  DMA_CHAN_CFG_DST_DRQ_H6(dst_drq);
> > +}
> > +
> > 
> >  static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
> >  {
> >  
> >  	*p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
> >  	
> >  		  DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
> >  
> >  }
> > 
> > +static void sun6i_set_mode_h6(u32 *p_cfg, s8 src_mode, s8 dst_mode)
> > +{
> > +	*p_cfg |= DMA_CHAN_CFG_SRC_MODE_H6(src_mode) |
> > +		  DMA_CHAN_CFG_DST_MODE_H6(dst_mode);
> > +}
> > +
> > 
> >  static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
> >  {
> >  
> >  	struct sun6i_desc *txd = pchan->desc;
> > 
> > @@ -1160,6 +1177,28 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg =
> > {> 
> >  			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> >  
> >  };
> > 
> > +/*
> > + * The H6 binding uses the number of dma channels from the
> > + * device tree node.
> > + */
> > +static struct sun6i_dma_config sun50i_h6_dma_cfg = {
> > +	.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
> > +	.set_burst_length = sun6i_set_burst_length_h3,
> > +	.set_drq          = sun6i_set_drq_h6,
> > +	.set_mode         = sun6i_set_mode_h6,
> > +	.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> > +	.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> > +	.src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > +			     BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> > +			     BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> > +			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> > +	.dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > +			     BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> > +			     BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> > +			     BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> > +	.mbus_clk = true,
> > +};
> > +
> > 
> >  /*
> >  
> >   * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
> >   * and a total of 24 usable source and destination endpoints.
> > 
> > @@ -1190,6 +1229,7 @@ static const struct of_device_id sun6i_dma_match[] =
> > {> 
> >  	{ .compatible = "allwinner,sun8i-h3-dma", .data = 
&sun8i_h3_dma_cfg },
> >  	{ .compatible = "allwinner,sun8i-v3s-dma", .data = 
&sun8i_v3s_dma_cfg },
> >  	{ .compatible = "allwinner,sun50i-a64-dma", .data = 
&sun50i_a64_dma_cfg
> >  	},
> > 
> > +	{ .compatible = "allwinner,sun50i-h6-dma", .data = 
&sun50i_h6_dma_cfg },
> > 
> >  	{ /* sentinel */ }
> >  
> >  };
> >  MODULE_DEVICE_TABLE(of, sun6i_dma_match);
> > 
> > @@ -1288,8 +1328,8 @@ static int sun6i_dma_probe(struct platform_device
> > *pdev)> 
> >  	ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
> >  	if (ret && !sdc->max_request) {
> >  	
> >  		dev_info(&pdev->dev, "Missing dma-requests, using %u.
\n",
> > 
> > -			 DMA_CHAN_MAX_DRQ_A31);
> > -		sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
> > +			 DMA_CHAN_MAX_DRQ_H6);
> > +		sdc->max_request = DMA_CHAN_MAX_DRQ_H6;
> > 
> >  	}
> >  	
> >  	/*





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

* Re: [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock
  2019-03-16 11:23     ` Jernej Škrabec
@ 2019-03-22 12:59       ` Vinod Koul
  2019-03-22 13:03         ` Maxime Ripard
  0 siblings, 1 reply; 17+ messages in thread
From: Vinod Koul @ 2019-03-22 12:59 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: maxime.ripard, wens, robh+dt, mark.rutland, dan.j.williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

On 16-03-19, 12:23, Jernej Škrabec wrote:
> Hi!
> 
> Dne sobota, 16. marec 2019 ob 12:07:53 CET je Vinod Koul napisal(a):
> > On 07-03-19, 17:58, Jernej Skrabec wrote:
> > > H6 DMA controller needs additional mbus clock to be enabled.
> > > 
> > > Add a quirk for it and handle it accordingly.
> > > 
> > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > > ---
> > > 
> > >  drivers/dma/sun6i-dma.c | 23 ++++++++++++++++++++++-
> > >  1 file changed, 22 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> > > index 0cd13f17fc11..761555080325 100644
> > > --- a/drivers/dma/sun6i-dma.c
> > > +++ b/drivers/dma/sun6i-dma.c
> > > @@ -129,6 +129,7 @@ struct sun6i_dma_config {
> > > 
> > >  	u32 dst_burst_lengths;
> > >  	u32 src_addr_widths;
> > >  	u32 dst_addr_widths;
> > > 
> > > +	bool mbus_clk;
> > > 
> > >  };
> > >  
> > >  /*
> > > 
> > > @@ -182,6 +183,7 @@ struct sun6i_dma_dev {
> > > 
> > >  	struct dma_device	slave;
> > >  	void __iomem		*base;
> > >  	struct clk		*clk;
> > > 
> > > +	struct clk		*clk_mbus;
> > 
> > So rather than have mbus_clk and then a ptr, why not use the ptr and use
> > NULL value to check for..?
> > 
> 
> I'm not sure what you mean here. clk_mbus will hold a reference to a clock 
> retrieved by devm_clk_get() so it has to be "struct clk *".
> 
> What I'm missing here?

IIRC there were two variable one clk ptr and one an integer to mark
presence, you may be able to skip variable and use ptr..
-- 
~Vinod

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

* Re: [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock
  2019-03-22 12:59       ` Vinod Koul
@ 2019-03-22 13:03         ` Maxime Ripard
  0 siblings, 0 replies; 17+ messages in thread
From: Maxime Ripard @ 2019-03-22 13:03 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Jernej Škrabec, wens, robh+dt, mark.rutland, dan.j.williams,
	dmaengine, devicetree, linux-arm-kernel, linux-kernel,
	linux-sunxi

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

On Fri, Mar 22, 2019 at 06:29:40PM +0530, Vinod Koul wrote:
> On 16-03-19, 12:23, Jernej Škrabec wrote:
> > Hi!
> >
> > Dne sobota, 16. marec 2019 ob 12:07:53 CET je Vinod Koul napisal(a):
> > > On 07-03-19, 17:58, Jernej Skrabec wrote:
> > > > H6 DMA controller needs additional mbus clock to be enabled.
> > > >
> > > > Add a quirk for it and handle it accordingly.
> > > >
> > > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > > > ---
> > > >
> > > >  drivers/dma/sun6i-dma.c | 23 ++++++++++++++++++++++-
> > > >  1 file changed, 22 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> > > > index 0cd13f17fc11..761555080325 100644
> > > > --- a/drivers/dma/sun6i-dma.c
> > > > +++ b/drivers/dma/sun6i-dma.c
> > > > @@ -129,6 +129,7 @@ struct sun6i_dma_config {
> > > >
> > > >  	u32 dst_burst_lengths;
> > > >  	u32 src_addr_widths;
> > > >  	u32 dst_addr_widths;
> > > >
> > > > +	bool mbus_clk;
> > > >
> > > >  };
> > > >
> > > >  /*
> > > >
> > > > @@ -182,6 +183,7 @@ struct sun6i_dma_dev {
> > > >
> > > >  	struct dma_device	slave;
> > > >  	void __iomem		*base;
> > > >  	struct clk		*clk;
> > > >
> > > > +	struct clk		*clk_mbus;
> > >
> > > So rather than have mbus_clk and then a ptr, why not use the ptr and use
> > > NULL value to check for..?
> > >
> >
> > I'm not sure what you mean here. clk_mbus will hold a reference to a clock
> > retrieved by devm_clk_get() so it has to be "struct clk *".
> >
> > What I'm missing here?
>
> IIRC there were two variable one clk ptr and one an integer to mark
> presence, you may be able to skip variable and use ptr..

If we're doing that, then we would effectively make it optional. That
DMA engine cannot operate without it.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA  controller
  2019-03-07 16:58 ` [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller Jernej Skrabec
  2019-03-16 10:57   ` Vinod Koul
@ 2019-03-27 23:47   ` Rob Herring
  1 sibling, 0 replies; 17+ messages in thread
From: Rob Herring @ 2019-03-27 23:47 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: maxime.ripard, wens, mark.rutland, devicetree, jernej.skrabec,
	linux-sunxi, linux-kernel, vkoul, robh+dt, dmaengine,
	dan.j.williams, linux-arm-kernel

On Thu,  7 Mar 2019 17:58:24 +0100, Jernej Skrabec wrote:
> DMA in H6 is similar to other DMA controller, except it is first which
> supports more than 32 request sources and has 16 channels. It also needs
> additional clock to be enabled.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  Documentation/devicetree/bindings/dma/sun6i-dma.txt | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

end of thread, other threads:[~2019-03-27 23:48 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-07 16:58 [PATCH 0/6] Allwinner H6 DMA support Jernej Skrabec
2019-03-07 16:58 ` [PATCH 1/6] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller Jernej Skrabec
2019-03-16 10:57   ` Vinod Koul
2019-03-16 11:27     ` Jernej Škrabec
2019-03-27 23:47   ` Rob Herring
2019-03-07 16:58 ` [PATCH 2/6] dmaengine: sun6i: Add a quirk for additional mbus clock Jernej Skrabec
2019-03-11  5:47   ` Chen-Yu Tsai
2019-03-16 11:07   ` Vinod Koul
2019-03-16 11:23     ` Jernej Škrabec
2019-03-22 12:59       ` Vinod Koul
2019-03-22 13:03         ` Maxime Ripard
2019-03-07 16:58 ` [PATCH 3/6] dmaengine: sun6i: Add a quirk for setting DRQ fields Jernej Skrabec
2019-03-07 16:58 ` [PATCH 4/6] dmaengine: sun6i: Add a quirk for setting mode fields Jernej Skrabec
2019-03-07 16:58 ` [PATCH 5/6] dmaengine: sun6i: Add support for H6 DMA Jernej Skrabec
2019-03-16 11:13   ` Vinod Koul
2019-03-16 11:37     ` Jernej Škrabec
2019-03-07 16:58 ` [PATCH 6/6] arm64: dts: allwinner: h6: Add DMA node Jernej Skrabec

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