From patchwork Fri Sep 12 07:37:36 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 37287 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 674B4203EE for ; Fri, 12 Sep 2014 07:39:49 +0000 (UTC) Received: by mail-la0-f72.google.com with SMTP id gi9sf204686lab.11 for ; Fri, 12 Sep 2014 00:39:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:subject:date:message-id:cc :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=SMybMXJ6fTeMXHhAWkm5BcJuTsGR/79DayplQAHU6xk=; b=jdu3uPM19W+Jyts/ng7QjHdHcWVi4BOvoS5V3g5G1iadOg4CApdvcS9DcM9N9IKAWV 0eUA6s+iPfpdVJnkBQ+0tV8bxv2mkBn5YwzzSnY2utpp9c0bEx2DMOs92ZRKYu1AfZOt ZTVzdmFIIG9Nee9/dCjBMSHPyzvA2aBYT+wP+qeAaz36xcZ2ZPGKChVpfwQGao6uffao zCO7wlf/GCAia5zsbOuKpL9h8s6trVeGzq1Z1hpLEscrDWspdIm5j5Z5kSqP5rLhEvj1 KyOPUn9Ju1mOfnqoHxgS8sz6GGePvvUd/4rv/UWKMmhaR+JkeqgBh39SlKiZz5DD04ra 4ZdA== X-Gm-Message-State: ALoCoQmI9mEqQZXcMu+M/5H8jayoNRAgiP/XSdLuLec3DodRZp2KOvy0V6KwAeR77iZkOuo4zzL4 X-Received: by 10.112.149.67 with SMTP id ty3mr1675884lbb.1.1410507588177; Fri, 12 Sep 2014 00:39:48 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.20.201 with SMTP id p9ls132059lae.15.gmail; Fri, 12 Sep 2014 00:39:48 -0700 (PDT) X-Received: by 10.152.205.9 with SMTP id lc9mr6939311lac.34.1410507588026; Fri, 12 Sep 2014 00:39:48 -0700 (PDT) Received: from mail-lb0-f170.google.com (mail-lb0-f170.google.com [209.85.217.170]) by mx.google.com with ESMTPS id d7si4756382lah.87.2014.09.12.00.39.47 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 12 Sep 2014 00:39:47 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) client-ip=209.85.217.170; Received: by mail-lb0-f170.google.com with SMTP id c11so391495lbj.1 for ; Fri, 12 Sep 2014 00:39:47 -0700 (PDT) X-Received: by 10.112.76.6 with SMTP id g6mr6562028lbw.22.1410507587742; Fri, 12 Sep 2014 00:39:47 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.141.42 with SMTP id rl10csp686700lbb; Fri, 12 Sep 2014 00:39:46 -0700 (PDT) X-Received: by 10.68.68.238 with SMTP id z14mr8827243pbt.121.1410507585889; Fri, 12 Sep 2014 00:39:45 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id t4si6135752pdn.117.2014.09.12.00.39.45 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 12 Sep 2014 00:39:45 -0700 (PDT) Received-SPF: none (google.com: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org does not designate permitted sender hosts) client-ip=2001:1868:205::9; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XSLQt-0001AM-6f; Fri, 12 Sep 2014 07:38:15 +0000 Received: from mail-wi0-f171.google.com ([209.85.212.171]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XSLQo-0000qS-Vw for linux-arm-kernel@lists.infradead.org; Fri, 12 Sep 2014 07:38:12 +0000 Received: by mail-wi0-f171.google.com with SMTP id bs8so84282wib.10 for ; Fri, 12 Sep 2014 00:37:47 -0700 (PDT) X-Received: by 10.194.9.228 with SMTP id d4mr8138013wjb.99.1410507467631; Fri, 12 Sep 2014 00:37:47 -0700 (PDT) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id z5sm838921wib.20.2014.09.12.00.37.46 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 12 Sep 2014 00:37:46 -0700 (PDT) From: Linus Walleij To: linux-arm-kernel@lists.infradead.org, dmaengine@vger.kernel.org, Vinod Koul , Roland Stigge , Arnd Bergmann Subject: [PATCH 3/4] dmaengine: support device tree channel assignment Date: Fri, 12 Sep 2014 09:37:36 +0200 Message-Id: <1410507456-32491-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 1.9.3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140912_003811_330932_0137277E X-CRM114-Status: GOOD ( 20.66 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.212.171 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [209.85.212.171 listed in wl.mailspike.net] -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders Cc: Dan Williams , Russell King , Linus Walleij X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: linus.walleij@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 For the fixed signal case, support assigning channels with specific signals taken from the device tree. For more information see the device tree binding patch. Signed-off-by: Linus Walleij --- drivers/dma/amba-pl08x.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 3 deletions(-) diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 1e523a094cc5..f2300e5ed55c 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -91,6 +91,8 @@ #include #include #include +#include +#include #include "dmaengine.h" #include "virt-dma.h" @@ -2045,10 +2047,221 @@ static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) } #endif +#ifdef CONFIG_OF +static int pl08x_of_parse_channel(struct amba_device *adev, + struct device_node *np, + struct pl08x_channel_data *chan) +{ + const char *signal_name; + int ret; + + ret = of_property_read_string(np, "signal", &signal_name); + if (ret) { + dev_err(&adev->dev, "no signal name for channel\n"); + return ret; + } + chan->bus_id = signal_name; + + /* Parse the channel settings */ + chan->bus_id = signal_name; + if (of_property_read_bool(np, "bus-interface-ahb1")) + chan->periph_buses |= PL08X_AHB1; + if (of_property_read_bool(np, "bus-interface-ahb2")) + chan->periph_buses |= PL08X_AHB2; + if (!chan->periph_buses) { + dev_err(&adev->dev, "no bus master for channel %s!\n", + signal_name); + return -EINVAL; + } + + return 0; +} + +static struct dma_chan *pl08x_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct pl08x_driver_data *pl08x = ofdma->of_dma_data; + u32 index = dma_spec->args[0]; + const char *channel_name; + dma_cap_mask_t cap; + dma_cap_zero(cap); + dma_cap_set(DMA_SLAVE, cap); + + if (index > pl08x->pd->num_slave_channels) { + dev_err(&pl08x->adev->dev, "undefined channel requested (%u)\n", + index); + return NULL; + } + channel_name = pl08x->pd->slave_channels[index].bus_id; + dev_dbg(&pl08x->adev->dev, "requested channel %u \"%s\"\n", + index, channel_name); + + return dma_request_channel(cap, pl08x_filter_id, (void *) channel_name); +} + +static int pl08x_of_probe(struct amba_device *adev, + struct pl08x_driver_data *pl08x, + struct device_node *np) +{ + struct device_node *child; + struct pl08x_channel_data *chanp = NULL; + struct pl08x_platform_data *pd; + u32 cctl_memcpy = 0; + u32 val; + int channels; + int ret; + + pd = devm_kzalloc(&adev->dev, + sizeof(struct pl08x_platform_data), + GFP_KERNEL); + if (!pd) + return -ENOMEM; + + + /* Eligible bus masters for fetching LLIs */ + if (of_property_read_bool(np, "lli-bus-interface-ahb1")) + pd->lli_buses |= PL08X_AHB1; + if (of_property_read_bool(np, "lli-bus-interface-ahb2")) + pd->lli_buses |= PL08X_AHB2; + if (!pd->lli_buses) { + dev_info(&adev->dev, "no bus masters for LLIs stated, assume all\n"); + pd->lli_buses |= PL08X_AHB1 | PL08X_AHB2; + } + + /* Eligible bus masters for memory access */ + if (of_property_read_bool(np, "mem-bus-interface-ahb1")) + pd->mem_buses |= PL08X_AHB1; + if (of_property_read_bool(np, "mem-bus-interface-ahb2")) + pd->mem_buses |= PL08X_AHB2; + if (!pd->mem_buses) { + dev_info(&adev->dev, "no bus masters for memory stated, assume all\n"); + pd->mem_buses |= PL08X_AHB1 | PL08X_AHB2; + } + + /* Parse the memcpy channel properties */ + ret = of_property_read_u32(np, "memcpy-burst-size", &val); + if (ret) { + dev_info(&adev->dev, "no memcpy burst size specified, using 1 byte\n"); + val = 1; + } + switch (val) { + default: + dev_err(&adev->dev, "illegal burst size for memcpy, set to 1\n"); + /* Fall through */ + case 1: + cctl_memcpy |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT; + break; + case 4: + cctl_memcpy |= PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT; + break; + case 8: + cctl_memcpy |= PL080_BSIZE_8 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_8 << PL080_CONTROL_DB_SIZE_SHIFT; + break; + case 16: + cctl_memcpy |= PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT; + break; + case 32: + cctl_memcpy |= PL080_BSIZE_32 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_32 << PL080_CONTROL_DB_SIZE_SHIFT; + break; + case 64: + cctl_memcpy |= PL080_BSIZE_64 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_64 << PL080_CONTROL_DB_SIZE_SHIFT; + break; + case 128: + cctl_memcpy |= PL080_BSIZE_128 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_128 << PL080_CONTROL_DB_SIZE_SHIFT; + break; + case 256: + cctl_memcpy |= PL080_BSIZE_256 << PL080_CONTROL_SB_SIZE_SHIFT | + PL080_BSIZE_256 << PL080_CONTROL_DB_SIZE_SHIFT; + break; + } + + ret = of_property_read_u32(np, "memcpy-bus-width", &val); + if (ret) { + dev_info(&adev->dev, "no memcpy bus width specified, using 8 bits\n"); + val = 8; + } + switch (val) { + default: + dev_err(&adev->dev, "illegal bus width for memcpy, set to 8 bits\n"); + /* Fall through */ + case 8: + cctl_memcpy |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT | + PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT; + break; + case 16: + cctl_memcpy |= PL080_WIDTH_16BIT << PL080_CONTROL_SWIDTH_SHIFT | + PL080_WIDTH_16BIT << PL080_CONTROL_DWIDTH_SHIFT; + break; + case 32: + cctl_memcpy |= PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | + PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT; + break; + } + + /* This is currently the only thing making sense */ + cctl_memcpy |= PL080_CONTROL_PROT_SYS; + + /* Set up memcpy channel */ + pd->memcpy_channel.bus_id = "memcpy"; + pd->memcpy_channel.cctl_memcpy = cctl_memcpy; + /* Use the buses that can access memory, obviously */ + pd->memcpy_channel.periph_buses = pd->mem_buses; + + channels = of_get_child_count(np); + if (!channels) + goto out_no_slaves; + if (channels > 32) { + dev_info(&adev->dev, "more than 32 channels specified, ignoring the surplus channels\n"); + channels = 32; + } + + pd->num_slave_channels = channels; + chanp = devm_kzalloc(&adev->dev, + channels * + sizeof(struct pl08x_channel_data), + GFP_KERNEL); + if (!chanp) + return -ENOMEM; + pd->slave_channels = chanp; + + /* Parse all children, defining the channels */ + for_each_child_of_node(np, child) { + ret = pl08x_of_parse_channel(adev, child, chanp); + if (ret) + return ret; + chanp++; + } + + ret = of_dma_controller_register(adev->dev.of_node, pl08x_of_xlate, + pl08x); + if (ret) + return ret; + +out_no_slaves: + pl08x->pd = pd; + return 0; +} +#else +static inline int pl08x_of_probe(struct amba_device *adev, + struct pl08x_driver_data *pl08x, + struct device_node *np) +{ + return -EINVAL; +} +#endif + static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) { struct pl08x_driver_data *pl08x; const struct vendor_data *vd = id->data; + struct device_node *np = adev->dev.of_node; u32 tsfr_size; int ret = 0; int i; @@ -2096,9 +2309,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) /* Get the platform data */ pl08x->pd = dev_get_platdata(&adev->dev); if (!pl08x->pd) { - dev_err(&adev->dev, "no platform data supplied\n"); - ret = -EINVAL; - goto out_no_platdata; + if (np) { + ret = pl08x_of_probe(adev, pl08x, np); + if (ret) + goto out_no_platdata; + } else { + dev_err(&adev->dev, "no platform data supplied\n"); + ret = -EINVAL; + goto out_no_platdata; + } } /* Assign useful pointers to the driver state */