From patchwork Thu Jun 6 15:47:24 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 2681681 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 30FA23FD4E for ; Thu, 6 Jun 2013 15:48:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751728Ab3FFPsE (ORCPT ); Thu, 6 Jun 2013 11:48:04 -0400 Received: from moutng.kundenserver.de ([212.227.126.186]:63282 "EHLO moutng.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751353Ab3FFPsE (ORCPT ); Thu, 6 Jun 2013 11:48:04 -0400 Received: from axis700.grange (dslb-088-077-167-013.pools.arcor-ip.net [88.77.167.13]) by mrelayeu.kundenserver.de (node=mreu1) with ESMTP (Nemesis) id 0M852L-1UOqKt0DyL-00vP5Z; Thu, 06 Jun 2013 17:47:26 +0200 Received: from 6a.grange (6a.grange [192.168.1.11]) by axis700.grange (Postfix) with ESMTPS id B8B5540BB5; Thu, 6 Jun 2013 17:47:25 +0200 (CEST) Received: from lyakh by 6a.grange with local (Exim 4.72) (envelope-from ) id 1UkcPN-0006Ad-KO; Thu, 06 Jun 2013 17:47:25 +0200 From: Guennadi Liakhovetski To: linux-sh@vger.kernel.org Cc: Vinod Koul , devicetree-discuss@lists.ozlabs.org, Rob Herring , Grant Likely , Magnus Damm , Simon Horman , Guennadi Liakhovetski Subject: [PATCH 2/3] dmaengine: add support for DMA multiplexer DT nodes Date: Thu, 6 Jun 2013 17:47:24 +0200 Message-Id: <1370533645-23690-3-git-send-email-g.liakhovetski@gmx.de> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1370533645-23690-1-git-send-email-g.liakhovetski@gmx.de> References: <1370533645-23690-1-git-send-email-g.liakhovetski@gmx.de> X-Provags-ID: V02:K0:t38ahnfIBfxqetOPHdpZlP51yyBAvpTeK5XNV2FWd6t VlOVIi27kHuR3w1MNlzP8kw3tn0tKOKkjwp64wizb580jkCRIP C8LtMgoujvOx8JYGK3MoyJlcmW47yUzAslftye3Ig99lBFh63d tMflelRd9IzscPxpzSeQ8Iqzu6Zy+mYFFJdzmHBgsM3QHgdelM Cang5sZotIt6/cNZsIDWEgQaNmXKym/t3meMdGNmy1nmF8g17R zsqgcGXCKLgrsvTlXQ7cZ4etyMlXdsv1V786YMBDfxFLTHwPRe vW4JkohW4SmvT5FKVcctPZx4cwTdXfRuQwu77I3FLWJggIbwmW 4ubgM1XfTo0WF0ziuKXQ3tP5b3Ja9RAyAg9zheEjutpPJYuojM +rdHyHQx09KKw== Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org If a slave can use any of several DMA controllers on the system, multiple DMA descriptors can be listed in its "dmas" DT property with the same channel name and different DMA controller phandles. However, if multiple such slaves can use any of a set of DMA controllers on the system, listing them all in each slave's "dmas" property becomes counterproductive. This patch adds support for a "dma-mux" DT node, whose sole purpose is to group such DMA controller DT nodes. Slaves can then specify the group's phandle in their "dmas" property. DMA controllers, belonging to the same group must have the same #dma-cells number and use the same slave IDs. Signed-off-by: Guennadi Liakhovetski --- Documentation/devicetree/bindings/dma/dma.txt | 44 +++++++++++++++++++++++++ drivers/dma/of-dma.c | 31 +++++++++++++---- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt index 8f504e6..a861298 100644 --- a/Documentation/devicetree/bindings/dma/dma.txt +++ b/Documentation/devicetree/bindings/dma/dma.txt @@ -31,6 +31,50 @@ Example: dma-requests = <127>; }; +* DMA multiplexer + +Several DMA controllers with the same #dma-cells number and the same request +line IDs can be grouped under a DMA multiplexer super-node, if slaves can use +DMA channels on any of them. + +Required property: +- compatible: Must include "dma-mux". + +Some standard optional properties can be helpful: + +Optional properties: +- compatible: You will probably also want to include compatibility + with "simple-bus" to automatically create platform + devices from subnodes. +- ranges: Map DMA controller memory areas in the parent address + space. +- #address-cells: Number of address cells in case automatic propagation + with the help of "ranges" doesn't work. +- #size-cells: Number of size cells. + +Example: + + dmac: dma-mux { + compatible = "simple-bus", "dma-mux"; + ranges; + + dma0: dma@10000000 { + #dma-cells = <1>; + ... + }; + + dma1: dma@20000000 { + #dma-cells = <1>; + ... + }; + }; + + mmc0: mmc@30000000 { + dmas = <&dmac 1 + &dmac 2>; + dma-names = "tx", "rx"; + ... + }; * DMA client diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c index 7aa0864..ec58022 100644 --- a/drivers/dma/of-dma.c +++ b/drivers/dma/of-dma.c @@ -146,8 +146,8 @@ static int of_dma_match_channel(struct device_node *np, const char *name, if (strcmp(name, s)) return -ENODEV; - if (of_parse_phandle_with_args(np, "dmas", "#dma-cells", index, - dma_spec)) + if (of_parse_phandle_with_child_args(np, "dmas", "#dma-cells", index, + dma_spec, "dma-mux")) return -ENODEV; return 0; @@ -165,7 +165,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np, { struct of_phandle_args dma_spec; struct of_dma *ofdma; - struct dma_chan *chan; + struct dma_chan *chan = NULL; int count, i; if (!np || !name) { @@ -180,20 +180,35 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np, } for (i = 0; i < count; i++) { + struct device_node *dma = NULL, *parent; + bool is_mux; + if (of_dma_match_channel(np, name, i, &dma_spec)) continue; mutex_lock(&of_dma_lock); - ofdma = of_dma_find_controller(&dma_spec); + parent = of_node_get(dma_spec.np->parent); + is_mux = of_device_is_compatible(parent, "dma-mux"); + + do { + /* If we're in a mux, try all nodes */ + if (is_mux) { + dma = of_get_next_available_child(parent, dma); + if (!dma) + break; + dma_spec.np = dma; + } + + ofdma = of_dma_find_controller(&dma_spec); - if (ofdma) - chan = ofdma->of_dma_xlate(&dma_spec, ofdma); - else - chan = NULL; + if (ofdma) + chan = ofdma->of_dma_xlate(&dma_spec, ofdma); + } while (dma && !chan); mutex_unlock(&of_dma_lock); of_node_put(dma_spec.np); + of_node_put(parent); if (chan) return chan;