From patchwork Tue Jun 23 08:42:54 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shengjiu Wang X-Patchwork-Id: 6659271 Return-Path: X-Original-To: patchwork-dmaengine@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 2C65BC05AC for ; Tue, 23 Jun 2015 08:58:05 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D5CC820525 for ; Tue, 23 Jun 2015 08:58:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 73C4F204F6 for ; Tue, 23 Jun 2015 08:58:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753977AbbFWI6B (ORCPT ); Tue, 23 Jun 2015 04:58:01 -0400 Received: from mail-bl2on0121.outbound.protection.outlook.com ([65.55.169.121]:14176 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752883AbbFWI55 (ORCPT ); Tue, 23 Jun 2015 04:57:57 -0400 X-Greylist: delayed 874 seconds by postgrey-1.27 at vger.kernel.org; Tue, 23 Jun 2015 04:57:57 EDT Received: from BY2PR03CA070.namprd03.prod.outlook.com (10.141.249.43) by BL2PR03MB275.namprd03.prod.outlook.com (10.255.231.22) with Microsoft SMTP Server (TLS) id 15.1.201.11; Tue, 23 Jun 2015 08:43:22 +0000 Received: from BN1BFFO11FD046.protection.gbl (2a01:111:f400:7c10::1:130) by BY2PR03CA070.outlook.office365.com (2a01:111:e400:2c5d::43) with Microsoft SMTP Server (TLS) id 15.1.195.15 via Frontend Transport; Tue, 23 Jun 2015 08:43:22 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=freescale.com; vger.kernel.org; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BN1BFFO11FD046.mail.protection.outlook.com (10.58.145.1) with Microsoft SMTP Server (TLS) id 15.1.190.9 via Frontend Transport; Tue, 23 Jun 2015 08:43:21 +0000 Received: from audiosh1.ap.freescale.net (audiosh1.ap.freescale.net [10.192.241.212]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id t5N8hIes012190; Tue, 23 Jun 2015 01:43:18 -0700 From: Shengjiu Wang To: , CC: , Subject: [PATCH] dmaengine: imx-sdma: Add device to device support Date: Tue, 23 Jun 2015 16:42:54 +0800 Message-ID: <1435048974-23700-1-git-send-email-shengjiu.wang@freescale.com> X-Mailer: git-send-email 1.7.9.5 X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BN1BFFO11FD046; 1:D8DtNh2Eeq+Up8pHoQHxEz2zWc4PwZD7mIwHlqB0LP7s8hpIUkkOUBD8eGKV4T/UaAr0Yg3MAw8UK5yvbt3jf8B/Je708pwG5GZ0EDiBmzoBeA2tbl9k6oARtp3/6qGdw6MeMGNctWnbWVUAYAiY/NenADDDIsj5Q3ml0WqtbFcs2H7KOeuhEKTF9DJL6XyB8LaNhCyXeOHJ3lyQT3cHCJuQfm6232x2eEiw5VXSoPbD0B53XvZPc16ok5JSXn3G0bHjqM+Y2zVWe+NF4Z+2mEph5NXFqcGGsiXuxA/vf0S/j1He5GiT5qrXPYoBVa5nXCAcJDoSaEp//Cpgb8kqCQ== X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(2980300002)(339900001)(199003)(189002)(104016003)(33646002)(62966003)(50226001)(229853001)(36756003)(106466001)(50986999)(5001960100002)(85426001)(87936001)(48376002)(5001920100001)(47776003)(19580395003)(6806004)(77156002)(77096005)(19580405001)(86362001)(46102003)(92566002)(189998001)(50466002); DIR:OUT; SFP:1102; SCL:1; SRVR:BL2PR03MB275; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; MLV:sfv; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB275; 2:FAtSEjisCVOfY7nn8mEHwNH77x80TjnqFEeHWHmE5+tvhPXXbQKPK7pef0m2AhFA; 3:k3kLt/nOJVrd8G+/u9Z9qis167Sk2cuNtz/UZ8ndShk1njmqCIHtS5kcuQekBn0sfGQwL5/eMrb5HKBfJN7/BkWIDF819jD7ll9l+3vG8FciOgfxK10ipL7YQy/Vg2WNglKkseTQWv5M4FKiSowA7FMk9ZNJ4jJMxEZCpqXlZ7v/1dvRB37MLY2gfDy9o+cDqjvIXmm1+XZ98rwaaP7hSLiGPOEbTk31Bw+TFFqVkIE=; 20:mm1ztovuR51Fysw8quWKfSJsI7JopvcqDBCkMvCKgvQHtXJGakijJHj34obBSNcjL6AXM9pfEbLSdR+3s1dcAbEXhyCAcI+jc8JaylIIqENdpWBDpOnKfFbDUnB0vYp3zdmsACiwHGA7J5nH14oeAN4xEB9jGka53wqY0jwR0rHDsZJQb9SL8ejqeZrnohDarFmDA8ylOifkhCw464cLjOgRM08JF9urRDfcjz1x+m6VYV+cPYDPui+pKDZxmidFnFlw5/8dIX9SvnUzHXllZ0J6UfV/RAqkNV1E+4+ufH886OGA8waxkrJXTyiQ+A9UQ7m3r76CuXxqAC1GoFrUlJ2yNorAvH+gAH/N6sm8+5g=; 4:ftf0aF5Zc6+THWuDNkCUwDnMTwf4lTFlWIRucKiQPeET0toKGPHXRoUgwiPjJHITG5M3xUJRpqFTz4A+vVBDjHdAf77bmHSBgGTg5OaHQEL5+Q9NJRe+ignlpbtzn4vTwbqgxmrqBfPsCKFAn2ceb2Bj73Ez1SHe9m8uQkpnMbSukzEBQVKlUaCo4WCaE/MVU8T1OPdjzw80XxncFxmcd7Cf7XKgV2njZrM8dLT6TM5euY6LQ773bf5Bw9zoEcOQ7LCQEmj2+ e/KEmN7UattXel9NLdeKqCEM1o8Hqdl7rA= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BL2PR03MB275; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(5005006)(3002001); SRVR:BL2PR03MB275; BCL:0; PCL:0; RULEID:; SRVR:BL2PR03MB275; X-Forefront-PRVS: 06167FAD59 X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB275; 23:Zv5tH3J7LS8KMI6eIrBIBSlKAcYEaVSKYACcxOFGBUCMgf2+oT3h1aqUI1ys3iUnV9KcPHdeVCmICC0ft45T2EXh5SXsv48K7kfeRCpRzPYHShiN2ZCV4LnKXsVMbpLtKOu/mss+V+LC9fDChUV5YV7EcVKDVYxT5qRvJ16mGH0UtZei9MMZuqqEXfvI4Hj2gVle1XGKIPukGMQiGIewkp1d6yII9dZeztNPvD0IqFgADZ+7NJxnsvydizVtuMFHWvpCb32rK0ooOHeZbW0porZVP08qEwBthIItCF2yKyB+ZKWYGm4rUiwyilmw4Ylh3JkHxwTweaBe91rMzeL2qs5dSgGMFn2jd4qt3jNvq7xqIf5PNYidD/RN2UtjbCgYs19Y+5TU2YQ0/hE9T4e7en5nQbE5hcHBIREpRZL/Oh/Rk5fEOpu/gHCoBoGrmp3MKnCpvV10SWFO+NDCeVAxfH3TuQfE+PxPn6otxSfwoUOzCPtlvoRYWFhyvuY9AcDj4Q9aPbN3rTCyFvy2GDKvAfbqEQXpp2DI532BQlg41NqmV3xBjJgOjtpKczIcpYKnbXbAYT7EgESC1Ez3cYlTDZECULgPDyyh8628Qu7vXc9/qjLAkqoHexWTco3/7mNak7C65s+/9aDRwdCK0s0TLulCW/YrLShcDUPlY9BU7KmlzKFV94G+PjDFGGOHMiS6Hj++x81EGVh4uJHwz255wtVNSqosGjbPesJblRr7y6qZNtjL5KQwgfp1fJZ+cCDOaI44rFAo48MSSn3/8gpkg24lT89Fv2RXjORQXON+MJA=; 5:7ZRcZbinNfubbX+PGFdvG2oKcfEfJDZFiX9NesKZ9KR1U2HlGK7gHUeBd/PpA7pQoPWeRijFpDoWaPiZGEbvVIHgb/kGIKrybdjWIEh4rg9C7Z+JQGHpB7fAQHu 9DzgYsmn8ri9ODt0WcDa53/KEvw== X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB275; 24:+sD6cvADUYiKHoC7PTp7upTirRXyVERBtb/Apokhzfp+M78NvcsSKryCP3YTX3QvSu4Z/Ww2t6IXy4a46+doelUcJG0zaSQmrjdA7NkyMl8=; 20:bmVbBORe8PgVdsY2w4wpN5Gi9nlSj9O8NkzKz9JylnjYIkQhHYWplTk7ZsyVJ9BMiH2zVjbCl19puLqNZHEI7Q== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Jun 2015 08:43:21.4835 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL2PR03MB275 Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds DEV_TO_DEV support for i.MX SDMA driver to support data transfer between two peripheral FIFOs. The per_2_per script requires two peripheral addresses and two DMA requests, and it need to check the src addr and dst addr is in the SPBA bus space or in the AIPS bus space. Signed-off-by: Shengjiu Wang --- drivers/dma/imx-sdma.c | 137 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 124 insertions(+), 13 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 77b6aab..5e44821 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -259,8 +260,9 @@ struct sdma_channel { struct sdma_buffer_descriptor *bd; dma_addr_t bd_phys; unsigned int pc_from_device, pc_to_device; + unsigned int device_to_device; unsigned long flags; - dma_addr_t per_address; + dma_addr_t per_address, per_address2; unsigned long event_mask[2]; unsigned long watermark_level; u32 shp_addr, per_addr; @@ -328,6 +330,8 @@ struct sdma_engine { u32 script_number; struct sdma_script_start_addrs *script_addrs; const struct sdma_driver_data *drvdata; + u32 spba_start_addr; + u32 spba_end_addr; }; static struct sdma_driver_data sdma_imx31 = { @@ -705,6 +709,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac, sdmac->pc_from_device = 0; sdmac->pc_to_device = 0; + sdmac->device_to_device = 0; switch (peripheral_type) { case IMX_DMATYPE_MEMORY: @@ -780,6 +785,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac, sdmac->pc_from_device = per_2_emi; sdmac->pc_to_device = emi_2_per; + sdmac->device_to_device = per_2_per; } static int sdma_load_context(struct sdma_channel *sdmac) @@ -792,11 +798,12 @@ static int sdma_load_context(struct sdma_channel *sdmac) int ret; unsigned long flags; - if (sdmac->direction == DMA_DEV_TO_MEM) { + if (sdmac->direction == DMA_DEV_TO_MEM) load_address = sdmac->pc_from_device; - } else { + else if (sdmac->direction == DMA_DEV_TO_DEV) + load_address = sdmac->device_to_device; + else load_address = sdmac->pc_to_device; - } if (load_address < 0) return load_address; @@ -851,6 +858,75 @@ static int sdma_disable_channel(struct dma_chan *chan) return 0; } +static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac) +{ + struct sdma_engine *sdma = sdmac->sdma; + + int lwml = sdmac->watermark_level & 0xff; + int hwml = (sdmac->watermark_level >> 16) & 0xff; + + if (sdmac->event_id0 > 31) { + sdmac->event_mask[0] |= 0; + __set_bit(28, &sdmac->watermark_level); + sdmac->event_mask[1] |= + BIT(sdmac->event_id0 % 32); + } else { + sdmac->event_mask[0] |= 0; + sdmac->event_mask[1] |= + BIT(sdmac->event_id0 % 32); + } + if (sdmac->event_id1 > 31) { + sdmac->event_mask[1] |= 0; + __set_bit(29, &sdmac->watermark_level); + sdmac->event_mask[0] |= + BIT(sdmac->event_id1 % 32); + } else { + sdmac->event_mask[1] |= 0; + sdmac->event_mask[0] |= + BIT(sdmac->event_id1 % 32); + } + + /* + * If LWML(src_maxburst) > HWML(dst_maxburst), we need + * swap LWML and HWML of INFO(A.3.2.5.1), also need swap + * r0(event_mask[1]) and r1(event_mask[0]). + */ + if (lwml > hwml) { + sdmac->watermark_level &= ~0xff00ff; + sdmac->watermark_level |= hwml; + sdmac->watermark_level |= lwml << 16; + swap(sdmac->event_mask[0], sdmac->event_mask[1]); + } + /* BIT 11: + * 1 : Source on SPBA + * 0 : Source on AIPS + */ + if (sdmac->per_address >= sdma->spba_start_addr && + sdmac->per_address <= sdma->spba_end_addr) + __set_bit(11, &sdmac->watermark_level); + /* BIT 12: + * 1 : Destination on SPBA + * 0 : Destination on AIPS + */ + if (sdmac->per_address2 >= sdma->spba_start_addr && + sdmac->per_address2 <= sdma->spba_end_addr) + __set_bit(12, &sdmac->watermark_level); + + __set_bit(31, &sdmac->watermark_level); + /* BIT 31: + * 1 : Amount of samples to be transferred is + * unknown and script will keep on transferring + * samples as long as both events are detected + * and script must be manually stopped by the + * application. + * 0 : The amount of samples to be is equal to + * the count field of mode word + * + */ + __set_bit(25, &sdmac->watermark_level); + __clear_bit(24, &sdmac->watermark_level); +} + static int sdma_config_channel(struct dma_chan *chan) { struct sdma_channel *sdmac = to_sdma_chan(chan); @@ -869,6 +945,12 @@ static int sdma_config_channel(struct dma_chan *chan) sdma_event_enable(sdmac, sdmac->event_id0); } + if (sdmac->event_id1) { + if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events) + return -EINVAL; + sdma_event_enable(sdmac, sdmac->event_id1); + } + switch (sdmac->peripheral_type) { case IMX_DMATYPE_DSP: sdma_config_ownership(sdmac, false, true, true); @@ -887,19 +969,21 @@ static int sdma_config_channel(struct dma_chan *chan) (sdmac->peripheral_type != IMX_DMATYPE_DSP)) { /* Handle multiple event channels differently */ if (sdmac->event_id1) { - sdmac->event_mask[1] = BIT(sdmac->event_id1 % 32); - if (sdmac->event_id1 > 31) - __set_bit(31, &sdmac->watermark_level); - sdmac->event_mask[0] = BIT(sdmac->event_id0 % 32); - if (sdmac->event_id0 > 31) - __set_bit(30, &sdmac->watermark_level); - } else { + if (sdmac->peripheral_type == IMX_DMATYPE_ASRC_SP || + sdmac->peripheral_type == IMX_DMATYPE_ASRC) + sdma_set_watermarklevel_for_p2p(sdmac); + } else __set_bit(sdmac->event_id0, sdmac->event_mask); - } + /* Watermark Level */ sdmac->watermark_level |= sdmac->watermark_level; /* Address */ - sdmac->shp_addr = sdmac->per_address; + if (sdmac->direction == DMA_DEV_TO_DEV) { + sdmac->shp_addr = sdmac->per_address2; + sdmac->per_addr = sdmac->per_address; + } else { + sdmac->shp_addr = sdmac->per_address; + } } else { sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */ } @@ -987,6 +1071,7 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan) sdmac->peripheral_type = data->peripheral_type; sdmac->event_id0 = data->dma_request; + sdmac->event_id1 = data->dma_request2; clk_enable(sdmac->sdma->clk_ipg); clk_enable(sdmac->sdma->clk_ahb); @@ -1221,6 +1306,14 @@ static int sdma_config(struct dma_chan *chan, sdmac->watermark_level = dmaengine_cfg->src_maxburst * dmaengine_cfg->src_addr_width; sdmac->word_size = dmaengine_cfg->src_addr_width; + } else if (dmaengine_cfg->direction == DMA_DEV_TO_DEV) { + sdmac->per_address = dmaengine_cfg->src_addr; + sdmac->per_address2 = dmaengine_cfg->dst_addr; + sdmac->watermark_level = + dmaengine_cfg->src_maxburst & 0xff; + sdmac->watermark_level |= + (dmaengine_cfg->dst_maxburst & 0xff) << 16; + sdmac->word_size = dmaengine_cfg->dst_addr_width; } else { sdmac->per_address = dmaengine_cfg->dst_addr; sdmac->watermark_level = dmaengine_cfg->dst_maxburst * @@ -1444,6 +1537,14 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec, data.dma_request = dma_spec->args[0]; data.peripheral_type = dma_spec->args[1]; data.priority = dma_spec->args[2]; + /* + * init dma_request2 to zero, which is not used by the dts. + * For P2P, dma_request2 is init from dma_request_channel(), + * chan->private will point to the imx_dma_data, and in + * device_alloc_chan_resources(), imx_dma_data.dma_request2 will + * be set to sdmac->event_id1. + */ + data.dma_request2 = 0; return dma_request_channel(mask, sdma_filter_fn, &data); } @@ -1453,10 +1554,12 @@ static int sdma_probe(struct platform_device *pdev) const struct of_device_id *of_id = of_match_device(sdma_dt_ids, &pdev->dev); struct device_node *np = pdev->dev.of_node; + struct device_node *spba_bus; const char *fw_name; int ret; int irq; struct resource *iores; + struct resource spba_res; struct sdma_platform_data *pdata = dev_get_platdata(&pdev->dev); int i; struct sdma_engine *sdma; @@ -1608,6 +1711,14 @@ static int sdma_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to register controller\n"); goto err_register; } + + spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus"); + ret = of_address_to_resource(spba_bus, 0, &spba_res); + if (!ret) { + sdma->spba_start_addr = spba_res.start; + sdma->spba_end_addr = spba_res.end; + } + of_node_put(spba_bus); } dev_info(sdma->dev, "initialized\n");