diff mbox

[RFC,v6,4/5] dma: mpc512x: register for device tree channel lookup

Message ID 1387886789-20249-5-git-send-email-a13xp0p0v88@gmail.com
State Superseded, archived
Headers show

Commit Message

Alexander Popov Dec. 24, 2013, 12:06 p.m. UTC
From: Gerhard Sittig <gsi@denx.de>

register the controller for device tree based lookup of DMA channels
(non-fatal for backwards compatibility with older device trees), provide
the '#dma-cells' property in the shared mpc5121.dtsi file, and introduce
a bindings document for the MPC512x DMA controller

Signed-off-by: Gerhard Sittig <gsi@denx.de>
[ a13xp0p0v88@gmail.com: resolve little patch conflict ]
[ a13xp0p0v88@gmail.com: set DMA_PRIVATE flag for MPC512x DMA controller ]
Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
 .../devicetree/bindings/dma/mpc512x-dma.txt        | 55 ++++++++++++++++++++++
 arch/powerpc/boot/dts/mpc5121.dtsi                 |  1 +
 drivers/dma/mpc512x_dma.c                          | 22 +++++++--
 3 files changed, 75 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/dma/mpc512x-dma.txt

Comments

Gerhard Sittig Dec. 26, 2013, 12:40 p.m. UTC | #1
On Tue, Dec 24, 2013 at 16:06 +0400, Alexander Popov wrote:
> 
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
> @@ -0,0 +1,55 @@
> +* Freescale MPC512x DMA Controller
> +
> +[ ... ]
> +
> +DMA controller node properties:
> +
> +Required properties:
> +- compatible:		should be "fsl,mpc5121-dma"
> +- reg:			address and size of the DMA controller's register set
> +- interrupts:		interrupt spec for the DMA controller
> +
> +Optional properties:
> +- #dma-cells:		must be <1>, describes the number of integer cells
> +			needed to specify the 'dmas' property in client nodes,
> +			strongly recommended since common client helper code
> +			uses this property

Given how time has passed and that we learned something in the
meantime, I guess the device tree documentation would look
different today than what was written back then.

- I'd reference the generic interrupt bindings as well, so DTS
  authors need not guess what an interrupt spec looks like
- the #dma-cells would become less confusing is it referenced the
  generic DMA binding, and just say that the value is "the length
  of the DMA specifier" for this provider
- the property's being recommended should not get hidden in the
  description but should reflect in the group's caption
- the binding doc shold not reference implementation details of
  one specific user (common client helper code)


[ device tree binding doc policy? ]

That one Linux driver handles both MPC5121 and MPC8308 hardware
and implements the same binding in both cases should get
reflected in the documentation as well.  But I'm not certain
whether adding MPC8308 into an MPX5121 document is better than
duplicating MPC5121 information in another MPC8308 document.  But
it might be the lesser evil.

Are there opinions, established preferences?  Is an exhaustive
list of compatible strings good enough since text search will
match regardless of the document's filename in this case?

There must have been this situation before of a component being
used in one SoC and getting re-used in another SoC later, too.
What's the best document to "get inspired from", i.e. how to best
put this into binding document wording as well as filenames?

> +[ ... ]
> +Client node properties:
> +
> +Required properties:
> +- dmas:			list of DMA specifiers, consisting each of a handle
> +			for the DMA controller and integer cells to specify
> +			the channel used within the DMA controller
> +- dma-names:		list of identifier strings for the DMA specifiers,
> +			client device driver code uses these strings to
> +			have DMA channels looked up at the controller

This certainly is wrong (it was before, I just wasn't aware back
then).  The phandle is not part of the specifier.  And the
binding should not discuss what driver code does.  Since the DMA
controller implements the semantics of the common DMA binding,
it's unwise to duplicate the information here.


Let me see how I can improve this document.  Alex, it may be
useful to split the code update and the binding document into
separate patches.  The current status already mixes the code
extension and the binding update with the introduction of the
document which was missing in the first place.  That's why the
binding doc patch is that late in the series.  (Yes, my RFC
"template" was rather dirty, which is why I flagged it as "RFC"
in the first place.)

I guess that I may have to introduce a binding doc reflecting the
given current status, and update it later as new features become
available.

Or -- given that the hardware remains, all the knowledge is there
already, just the implementations' capabilities change -- I might
as well introduce a binding document including OF based DMA
lookup.


virtually yours
Gerhard Sittig
Gerhard Sittig Dec. 26, 2013, 12:48 p.m. UTC | #2
[ dropping devicetree, we're DMA specific here ]

On Tue, Dec 24, 2013 at 16:06 +0400, Alexander Popov wrote:
> 
> --- a/drivers/dma/mpc512x_dma.c
> +++ b/drivers/dma/mpc512x_dma.c
> [ ... ]
> @@ -950,6 +951,7 @@ static int mpc_dma_probe(struct platform_device *op)
>  	INIT_LIST_HEAD(&dma->channels);
>  	dma_cap_set(DMA_MEMCPY, dma->cap_mask);
>  	dma_cap_set(DMA_SLAVE, dma->cap_mask);
> +	dma_cap_set(DMA_PRIVATE, dma->cap_mask);
>  
>  	for (i = 0; i < dma->chancnt; i++) {
>  		mchan = &mdma->channels[i];

What are the implications of this?  Is a comment due?

I haven't found documentation about the DMA_PRIVATE flag, only
saw commit 59b5ec21446b9 "dmaengine: introduce
dma_request_channel and private channels".  Alex, unless I'm
missing something this one-line change is quite a change in
semantics, and has dramatic influence on the code's behaviour
(ignores the DMA controller when looking for channels that can do
mem-to-mem transfers).

Please reason about this change some more, and explain what it
does and why it's needed.  Consider the fact that this driver
handles both MPC5121 as well as MPC8308 hardware.


virtually yours
Gerhard Sittig
Alexander Popov Jan. 3, 2014, 8:54 p.m. UTC | #3
Hello Gerhard.
Thanks for your review.

2013/12/26 Gerhard Sittig <gsi@denx.de>:
> [ dropping devicetree, we're DMA specific here ]
>
> On Tue, Dec 24, 2013 at 16:06 +0400, Alexander Popov wrote:
>>
>> --- a/drivers/dma/mpc512x_dma.c
>> +++ b/drivers/dma/mpc512x_dma.c
>> [ ... ]
>> @@ -950,6 +951,7 @@ static int mpc_dma_probe(struct platform_device *op)
>>       INIT_LIST_HEAD(&dma->channels);
>>       dma_cap_set(DMA_MEMCPY, dma->cap_mask);
>>       dma_cap_set(DMA_SLAVE, dma->cap_mask);
>> +     dma_cap_set(DMA_PRIVATE, dma->cap_mask);
>>
>>       for (i = 0; i < dma->chancnt; i++) {
>>               mchan = &mdma->channels[i];
>
> What are the implications of this?  Is a comment due?

I've involved DMA_PRIVATE flag because new of_dma_xlate_by_chan_id()
uses dma_get_slave_channel() instead of dma_request_channel()
(PATCH RFC v6 3/5). This flag is implicitly set in dma_request_channel(),
but is not set in dma_get_slave_channel().

There are only two places in the mainline kernel, where
dma_get_slave_channel() is used. I've picked up the idea
at one of these places. Please look at this patch:
http://www.spinics.net/lists/arm-kernel/msg268718.html

> I haven't found documentation about the DMA_PRIVATE flag, only
> saw commit 59b5ec21446b9 "dmaengine: introduce
> dma_request_channel and private channels".

Unfortunately I didn't find any description of DMA_PRIVATE flag too.
But the comment at the beginning of drivers/dma/dmaengine.c
may give a clue. Quotation:
  * subsystem can get access to a channel by calling dmaengine_get() followed
  * by dma_find_channel(), or if it has need for an exclusive channel
it can call
  * dma_request_channel().  Once a channel is allocated a reference is taken
  * against its corresponding driver to disable removal.

DMA_PRIVATE capability flag might indicate that the DMA controller
can provide exclusive channels to its clients. Please correct me if I'm wrong.

> Alex, unless I'm
> missing something this one-line change is quite a change in
> semantics, and has dramatic influence on the code's behaviour
> (ignores the DMA controller when looking for channels that can do
> mem-to-mem transfers)

Excuse me, Gerhard, I don't see what you mean.
Could you point to the corresponding code?

> Consider the fact that this driver
> handles both MPC5121 as well as MPC8308 hardware.

Ah, yes, sorry. I should certainly fix this, if setting of DMA_PRIVATE flag
is needed at all.

Thanks!

Best regards,
Alexander
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/dma/mpc512x-dma.txt b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
new file mode 100644
index 0000000..a4867d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
@@ -0,0 +1,55 @@ 
+* Freescale MPC512x DMA Controller
+
+The DMA controller in the Freescale MPC512x SoC can move blocks of
+memory contents between memory and peripherals or memory to memory.
+
+Refer to the "Generic DMA Controller and DMA request bindings" description
+in the dma.txt file for a more detailled discussion of the binding.  The
+MPC512x DMA engine binding follows the common scheme, but doesn't provide
+support for the optional channels and requests counters (those values are
+derived from the detected hardware features) and has a fixed client
+specifier length of 1 integer cell (the value is the DMA channel, since
+the DMA controller uses a fixed assignment of request lines per channel).
+
+
+DMA controller node properties:
+
+Required properties:
+- compatible:		should be "fsl,mpc5121-dma"
+- reg:			address and size of the DMA controller's register set
+- interrupts:		interrupt spec for the DMA controller
+
+Optional properties:
+- #dma-cells:		must be <1>, describes the number of integer cells
+			needed to specify the 'dmas' property in client nodes,
+			strongly recommended since common client helper code
+			uses this property
+
+Example:
+
+	dma0: dma@14000 {
+		compatible = "fsl,mpc5121-dma";
+		reg = <0x14000 0x1800>;
+		interrupts = <65 0x8>;
+		#dma-cells = <1>;
+	};
+
+
+Client node properties:
+
+Required properties:
+- dmas:			list of DMA specifiers, consisting each of a handle
+			for the DMA controller and integer cells to specify
+			the channel used within the DMA controller
+- dma-names:		list of identifier strings for the DMA specifiers,
+			client device driver code uses these strings to
+			have DMA channels looked up at the controller
+
+Example:
+
+	sdhc@1500 {
+		compatible = "fsl,mpc5121-sdhc";
+		/* ... */
+		dmas = <&dma0 30>;
+		dma-names = "rx-tx";
+	};
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 2d7cb04..15b7860 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -389,6 +389,7 @@ 
 			compatible = "fsl,mpc5121-dma";
 			reg = <0x14000 0x1800>;
 			interrupts = <65 0x8>;
+			#dma-cells = <1>;
 		};
 	};
 
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index a7e7749..8fabb52 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -50,6 +50,7 @@ 
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/of_dma.h>
 #include <linux/of_platform.h>
 
 #include <linux/random.h>
@@ -950,6 +951,7 @@  static int mpc_dma_probe(struct platform_device *op)
 	INIT_LIST_HEAD(&dma->channels);
 	dma_cap_set(DMA_MEMCPY, dma->cap_mask);
 	dma_cap_set(DMA_SLAVE, dma->cap_mask);
+	dma_cap_set(DMA_PRIVATE, dma->cap_mask);
 
 	for (i = 0; i < dma->chancnt; i++) {
 		mchan = &mdma->channels[i];
@@ -1013,11 +1015,23 @@  static int mpc_dma_probe(struct platform_device *op)
 	/* Register DMA engine */
 	dev_set_drvdata(dev, mdma);
 	retval = dma_async_device_register(dma);
-	if (retval) {
-		devm_free_irq(dev, mdma->irq, mdma);
-		irq_dispose_mapping(mdma->irq);
+	if (retval)
+		goto out_irq;
+
+	/* register with OF helpers for DMA lookups (nonfatal) */
+	if (dev->of_node) {
+		retval = of_dma_controller_register(dev->of_node,
+						    of_dma_xlate_by_chan_id,
+						    mdma);
+		if (retval)
+			dev_warn(dev, "could not register for OF lookup\n");
 	}
 
+	return 0;
+
+out_irq:
+	devm_free_irq(dev, mdma->irq, mdma);
+	irq_dispose_mapping(mdma->irq);
 	return retval;
 }
 
@@ -1026,6 +1040,8 @@  static int mpc_dma_remove(struct platform_device *op)
 	struct device *dev = &op->dev;
 	struct mpc_dma *mdma = dev_get_drvdata(dev);
 
+	if (dev->of_node)
+		of_dma_controller_free(dev->of_node);
 	dma_async_device_unregister(&mdma->dma);
 	devm_free_irq(dev, mdma->irq, mdma);
 	irq_dispose_mapping(mdma->irq);