From patchwork Thu Apr 19 02:00:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "(Exiting) Baolin Wang" X-Patchwork-Id: 10349067 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5F8F26053F for ; Thu, 19 Apr 2018 02:02:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 50668287FE for ; Thu, 19 Apr 2018 02:02:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 44CCE2881B; Thu, 19 Apr 2018 02:02:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5F989287FE for ; Thu, 19 Apr 2018 02:01:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753153AbeDSCB5 (ORCPT ); Wed, 18 Apr 2018 22:01:57 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:36102 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752826AbeDSCBo (ORCPT ); Wed, 18 Apr 2018 22:01:44 -0400 Received: by mail-pf0-f194.google.com with SMTP id g14so1831022pfh.3 for ; Wed, 18 Apr 2018 19:01:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=u/3qjb5C5bTzfE5TE9aNFaM74weWHJiI5xbTQ0Gb0Rk=; b=APUZr/GE9mMpPq3rKecMM7aPr47hj6uobRHZu+q7jLVhkqFdnQzhQG9WRGPRZ8W991 SGoXkF/9ewoQ54YPDSTMxA8AkJySREiF8c9kT7maKJE/er7e8CsK0pqWHeB7OmOLnux3 kthzPvbKbMqkVNJJ3ym03OP+ayiaGkDuys07g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=u/3qjb5C5bTzfE5TE9aNFaM74weWHJiI5xbTQ0Gb0Rk=; b=BP2rgDuO/6ECSI4x3uAPH8O99xUExsHWxh7CBZ9CNk9lXMgmyrjkhdyKuwT42429kN FmBL71AaVwbzoSzsnxf8XkJ6XnQsa4jb70dpTHIxmvxWhOiT/6XwOZniACzH7FzdUq8W TJ9Tbjd6KUncTtDnDZDyQUBLntplwIgYNXR2AI9rxfoj6MKoMMVIjAA25A6BFrrEj3+I MuIEblPwwf+mFL9gIXeL2QtlceQog9FrIIiZbxnvvcrtfvyGUdXG/bYNMFnVsWoS2z1X h+EgB769Zb+Ktm+603kUP/Ksx5pm7nCaBNZk8OiOecEZ27sGLF7zuwzE2OceZdDBuMJB z22Q== X-Gm-Message-State: ALQs6tBwbZfecchEznafQuzfx54dII07/b0FqnABmmJVgtjbe3FyeERZ TT4SWjEc2QvvG5vc0zalOVtAOg== X-Google-Smtp-Source: AIpwx48M8hgg14GgJwhqbVZfoPJXKshUhUsFAGUaSmLAR96U+5t85PgszK5M+N+3D3RdlWMyj4F/sQ== X-Received: by 10.99.184.1 with SMTP id p1mr3539580pge.250.1524103303980; Wed, 18 Apr 2018 19:01:43 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id e83sm6136938pfd.175.2018.04.18.19.01.41 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 18 Apr 2018 19:01:43 -0700 (PDT) From: Baolin Wang To: dan.j.williams@intel.com, vinod.koul@intel.com Cc: eric.long@spreadtrum.com, broonie@kernel.org, dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org, baolin.wang@linaro.org Subject: [PATCH v2 5/5] dmaengine: sprd: Add 'device_config' and 'device_prep_slave_sg' interfaces Date: Thu, 19 Apr 2018 10:00:50 +0800 Message-Id: <2efb90f1d86529a51e566824566016b9430f56ea.1524054807.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <2ec1e8ddade0be5b4412b031b98d0d69a1af421f.1524054807.git.baolin.wang@linaro.org> References: <2ec1e8ddade0be5b4412b031b98d0d69a1af421f.1524054807.git.baolin.wang@linaro.org> In-Reply-To: <2ec1e8ddade0be5b4412b031b98d0d69a1af421f.1524054807.git.baolin.wang@linaro.org> References: <2ec1e8ddade0be5b4412b031b98d0d69a1af421f.1524054807.git.baolin.wang@linaro.org> Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Long This patch adds the 'device_config' and 'device_prep_slave_sg' interfaces for users to configure DMA. Signed-off-by: Eric Long Signed-off-by: Baolin Wang --- Changes since v1: - The request mode and interrupt type will be passed from flags. - Add sprd_dma_get_step() to get src/dst step. - Add sprd_dma_get_datawidth() to convert data width values which can be used by Spreadtrum DMA. --- drivers/dma/sprd-dma.c | 115 ++++++++++++++++++++++++++++++++++++++++++ include/linux/dma/sprd-dma.h | 4 ++ 2 files changed, 119 insertions(+) diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index 23846ed..f2598ed 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -590,6 +590,47 @@ static void sprd_dma_issue_pending(struct dma_chan *chan) spin_unlock_irqrestore(&schan->vc.lock, flags); } +static enum sprd_dma_datawidth +sprd_dma_get_datawidth(enum dma_slave_buswidth buswidth) +{ + switch (buswidth) { + case DMA_SLAVE_BUSWIDTH_1_BYTE: + return SPRD_DMA_DATAWIDTH_1_BYTE; + + case DMA_SLAVE_BUSWIDTH_2_BYTES: + return SPRD_DMA_DATAWIDTH_2_BYTES; + + case DMA_SLAVE_BUSWIDTH_4_BYTES: + return SPRD_DMA_DATAWIDTH_4_BYTES; + + case DMA_SLAVE_BUSWIDTH_8_BYTES: + return SPRD_DMA_DATAWIDTH_8_BYTES; + + default: + return SPRD_DMA_DATAWIDTH_4_BYTES; + } +} + +static u32 sprd_dma_get_step(enum sprd_dma_datawidth datawidth) +{ + switch (datawidth) { + case SPRD_DMA_DATAWIDTH_1_BYTE: + return SPRD_DMA_BYTE_STEP; + + case SPRD_DMA_DATAWIDTH_2_BYTES: + return SPRD_DMA_SHORT_STEP; + + case SPRD_DMA_DATAWIDTH_4_BYTES: + return SPRD_DMA_WORD_STEP; + + case SPRD_DMA_DATAWIDTH_8_BYTES: + return SPRD_DMA_DWORD_STEP; + + default: + return SPRD_DMA_DWORD_STEP; + } +} + static int sprd_dma_config(struct dma_chan *chan, struct sprd_dma_desc *sdesc, struct sprd_dma_config *slave_cfg) { @@ -711,6 +752,78 @@ static int sprd_dma_config(struct dma_chan *chan, struct sprd_dma_desc *sdesc, return vchan_tx_prep(&schan->vc, &sdesc->vd, flags); } +static struct dma_async_tx_descriptor * +sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sglen, enum dma_transfer_direction dir, + unsigned long flags, void *context) +{ + struct sprd_dma_chn *schan = to_sprd_dma_chan(chan); + struct sprd_dma_config *slave_cfg = &schan->slave_cfg; + struct sprd_dma_desc *sdesc; + struct scatterlist *sg; + int ret, i; + + /* TODO: now we only support one sg for each DMA configuration. */ + if (!is_slave_direction(dir) || sglen > 1) + return NULL; + + sdesc = kzalloc(sizeof(*sdesc), GFP_NOWAIT); + if (!sdesc) + return NULL; + + for_each_sg(sgl, sg, sglen, i) { + if (dir == DMA_MEM_TO_DEV) { + slave_cfg->src_addr = sg_dma_address(sg); + slave_cfg->src_step = + sprd_dma_get_step(slave_cfg->src_datawidth); + slave_cfg->dst_step = SPRD_DMA_NONE_STEP; + } else { + slave_cfg->dst_addr = sg_dma_address(sg); + slave_cfg->src_step = SPRD_DMA_NONE_STEP; + slave_cfg->dst_step = + sprd_dma_get_step(slave_cfg->dst_datawidth); + } + + slave_cfg->block_len = sg_dma_len(sg); + slave_cfg->transcation_len = sg_dma_len(sg); + } + + slave_cfg->req_mode = + (flags >> SPRD_DMA_REQ_SHIFT) & SPRD_DMA_REQ_MODE_MASK; + slave_cfg->int_mode = flags & SPRD_DMA_INT_MASK; + + ret = sprd_dma_config(chan, sdesc, slave_cfg); + if (ret) { + kfree(sdesc); + return NULL; + } + + return vchan_tx_prep(&schan->vc, &sdesc->vd, flags); +} + +static int sprd_dma_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) +{ + struct sprd_dma_chn *schan = to_sprd_dma_chan(chan); + struct sprd_dma_config *slave_cfg = &schan->slave_cfg; + + if (!is_slave_direction(config->direction)) + return -EINVAL; + + memset(slave_cfg, 0, sizeof(*slave_cfg)); + + slave_cfg->slave_id = config->slave_id; + slave_cfg->src_addr = config->src_addr; + slave_cfg->dst_addr = config->dst_addr; + slave_cfg->fragment_len = config->src_maxburst; + slave_cfg->src_datawidth = + sprd_dma_get_datawidth(config->src_addr_width); + slave_cfg->dst_datawidth = + sprd_dma_get_datawidth(config->dst_addr_width); + + return 0; +} + static int sprd_dma_pause(struct dma_chan *chan) { struct sprd_dma_chn *schan = to_sprd_dma_chan(chan); @@ -838,6 +951,8 @@ static int sprd_dma_probe(struct platform_device *pdev) sdev->dma_dev.device_tx_status = sprd_dma_tx_status; sdev->dma_dev.device_issue_pending = sprd_dma_issue_pending; sdev->dma_dev.device_prep_dma_memcpy = sprd_dma_prep_dma_memcpy; + sdev->dma_dev.device_prep_slave_sg = sprd_dma_prep_slave_sg; + sdev->dma_dev.device_config = sprd_dma_slave_config; sdev->dma_dev.device_pause = sprd_dma_pause; sdev->dma_dev.device_resume = sprd_dma_resume; sdev->dma_dev.device_terminate_all = sprd_dma_terminate_all; diff --git a/include/linux/dma/sprd-dma.h b/include/linux/dma/sprd-dma.h index c545162..b0115e3 100644 --- a/include/linux/dma/sprd-dma.h +++ b/include/linux/dma/sprd-dma.h @@ -3,6 +3,10 @@ #ifndef _SPRD_DMA_H_ #define _SPRD_DMA_H_ +#define SPRD_DMA_REQ_SHIFT 16 +#define SPRD_DMA_FLAGS(req_mode, int_type) \ + ((req_mode) << SPRD_DMA_REQ_SHIFT | (int_type)) + /* * enum sprd_dma_req_mode: define the DMA request mode * @SPRD_DMA_FRAG_REQ: fragment request mode