From patchwork Fri Feb 10 15:29:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frode Isaksen X-Patchwork-Id: 9566989 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 CCBC6601C3 for ; Fri, 10 Feb 2017 15:37:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9FB8285A0 for ; Fri, 10 Feb 2017 15:37:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD3D4285A3; Fri, 10 Feb 2017 15:37:57 +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=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable 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 3F759285A0 for ; Fri, 10 Feb 2017 15:37:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753141AbdBJPht (ORCPT ); Fri, 10 Feb 2017 10:37:49 -0500 Received: from mail-wr0-f176.google.com ([209.85.128.176]:35725 "EHLO mail-wr0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752209AbdBJPh2 (ORCPT ); Fri, 10 Feb 2017 10:37:28 -0500 Received: by mail-wr0-f176.google.com with SMTP id 89so110682208wrr.2 for ; Fri, 10 Feb 2017 07:36:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Mgulh3EucKoUyM8crDZmggYbNlW9jMGXJESbPV4GmxM=; b=NJVDM0Vk0jCmroyJa32X/JWXV26CaU/jnNLx1FnF7PIGsxK6s6un/8nchxzrtNJ6z6 nHVzv3DscFGgAaD6Z4DQv0By2eyfzs+Pm0Q/wFRnaZHQTr2Y0UY/BZo3qg3hcLp7R4iD 0twCKomz/LTRJHErYn9J5QyqPfrfDB8w8T4rJmW5FQYo5GotozXgiswzp2uztHxd08XH S8IkGNpZjQJ0gPbiun3f8bkWoVAf/Ek3I3V/2wENF6GbTTwVdQW5G+loTS9cysD35zRE hJsre8W6b7IqMqdaYYjX5cv/2kC4m3RlSojqcZstO1K+S4wiIV5zjMtg4qeHKW7o5AE5 JLiA== 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; bh=Mgulh3EucKoUyM8crDZmggYbNlW9jMGXJESbPV4GmxM=; b=TOXnAUnra2F4i/7HuI2+8y9Gh1wBp7PJaPEYp3pEElPOhm85hGZD8SomfbjPHnMzQK OtelfLk0OP+hQFTe69Qqph4euIqZ7zwLLGcYHNkDnFKqnWzOX734XNMAtGtTIx3lN22j X52AHn8kAh6Nng69j7nkDChv/w1eAxccmLP9JAl6MBDLlCttHeKp+GjGr+PXkdKSQC4A mTR6/CP6jBC42m4aCUf2+j2W04kLSe1Y8QLdq/kHSdhsGgMwO1Thd8rA6JK7z/MuXH3C SFTwBfq0R1/M2sMEenB310OacyJVaZF1hIcwn+2F/fSTfvxLs4+bFfo3cIyETqnrsuNe 9Dew== X-Gm-Message-State: AMke39k+6w77XrvSHv+mm0THwV9+FvJpACxPrdDO0F62VL+Vr/wcXa2fr5BY+Jg9/CxpcMeU X-Received: by 10.223.134.218 with SMTP id 26mr8133299wry.104.1486740641293; Fri, 10 Feb 2017 07:30:41 -0800 (PST) Received: from localhost.localdomain ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id o143sm2068192wmd.3.2017.02.10.07.30.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 10 Feb 2017 07:30:40 -0800 (PST) From: Frode Isaksen To: nsekhar@ti.com, khilman@baylibre.com, ptitiano@baylibre.com, linux-arm-kernel@lists.infradead.org Cc: broonie@kernel.org, linux-spi@vger.kernel.org, Fabien Parent Subject: [PATCH 1/8] spi: davinci: Use SPI framework to handle DMA mapping Date: Fri, 10 Feb 2017 16:29:37 +0100 Message-Id: <1486740584-17875-2-git-send-email-fisaksen@baylibre.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486740584-17875-1-git-send-email-fisaksen@baylibre.com> References: <1486740584-17875-1-git-send-email-fisaksen@baylibre.com> Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Fabien Parent Uppers layers like MTD can pass vmalloc'd buffers to the SPI driver, and the current implementation will fail to map these kind of buffers. The SPI framework is able to detect the best way to handle and map buffers. This commit updates the davinci SPI driver in order to use the SPI framework to handle the DMA mapping of buffers coming from an upper layer. Note that the dummy buffer used when doing one-way transfer, must still be mapped in this module. Signed-off-by: Fabien Parent --- drivers/spi/spi-davinci.c | 80 ++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 02fb967..84c0d76 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -467,6 +467,20 @@ static void davinci_spi_cleanup(struct spi_device *spi) kfree(spicfg); } +static inline bool __davinci_spi_can_dma(struct spi_device *spi) +{ + struct davinci_spi_config *spicfg = spi->controller_data; + + return spicfg ? spicfg->io_type == SPI_IO_TYPE_DMA : false; +} + +static bool davinci_spi_can_dma(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + return __davinci_spi_can_dma(spi); +} + static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status) { struct device *sdev = dspi->bitbang.master->dev.parent; @@ -630,7 +644,6 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) }; struct dma_async_tx_descriptor *rxdesc; struct dma_async_tx_descriptor *txdesc; - void *buf; dummy_buf = kzalloc(t->len, GFP_KERNEL); if (!dummy_buf) @@ -639,42 +652,40 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) dmaengine_slave_config(dspi->dma_rx, &dma_rx_conf); dmaengine_slave_config(dspi->dma_tx, &dma_tx_conf); - sg_init_table(&sg_rx, 1); - if (!t->rx_buf) - buf = dummy_buf; - else - buf = t->rx_buf; - t->rx_dma = dma_map_single(&spi->dev, buf, - t->len, DMA_FROM_DEVICE); - if (dma_mapping_error(&spi->dev, !t->rx_dma)) { - ret = -EFAULT; - goto err_rx_map; + if (!t->rx_buf) { + sg_init_table(&sg_rx, 1); + t->rx_dma = dma_map_single(&spi->dev, dummy_buf, + t->len, DMA_FROM_DEVICE); + if (dma_mapping_error(&spi->dev, !t->rx_dma)) { + ret = -EFAULT; + goto err_rx_map; + } + sg_dma_address(&sg_rx) = t->rx_dma; + sg_dma_len(&sg_rx) = t->len; } - sg_dma_address(&sg_rx) = t->rx_dma; - sg_dma_len(&sg_rx) = t->len; sg_init_table(&sg_tx, 1); - if (!t->tx_buf) - buf = dummy_buf; - else - buf = (void *)t->tx_buf; - t->tx_dma = dma_map_single(&spi->dev, buf, - t->len, DMA_TO_DEVICE); - if (dma_mapping_error(&spi->dev, t->tx_dma)) { - ret = -EFAULT; - goto err_tx_map; + if (!t->tx_buf) { + t->tx_dma = dma_map_single(&spi->dev, dummy_buf, + t->len, DMA_TO_DEVICE); + if (dma_mapping_error(&spi->dev, t->tx_dma)) { + ret = -EFAULT; + goto err_tx_map; + } + sg_dma_address(&sg_tx) = t->tx_dma; + sg_dma_len(&sg_tx) = t->len; } - sg_dma_address(&sg_tx) = t->tx_dma; - sg_dma_len(&sg_tx) = t->len; rxdesc = dmaengine_prep_slave_sg(dspi->dma_rx, - &sg_rx, 1, DMA_DEV_TO_MEM, + t->rx_sg.sgl ?: &sg_rx, t->rx_sg.nents ?: 1, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!rxdesc) goto err_desc; txdesc = dmaengine_prep_slave_sg(dspi->dma_tx, - &sg_tx, 1, DMA_MEM_TO_DEV, + t->tx_sg.sgl ?: &sg_tx, t->tx_sg.nents ?: 1, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!txdesc) goto err_desc; @@ -713,10 +724,12 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) if (spicfg->io_type == SPI_IO_TYPE_DMA) { clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN); - dma_unmap_single(&spi->dev, t->rx_dma, - t->len, DMA_FROM_DEVICE); - dma_unmap_single(&spi->dev, t->tx_dma, - t->len, DMA_TO_DEVICE); + if (!t->rx_buf) + dma_unmap_single(&spi->dev, t->rx_dma, + t->len, DMA_FROM_DEVICE); + if (!t->tx_buf) + dma_unmap_single(&spi->dev, t->tx_dma, + t->len, DMA_TO_DEVICE); kfree(dummy_buf); } @@ -742,9 +755,11 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) return t->len; err_desc: - dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE); + if (!t->tx_buf) + dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE); err_tx_map: - dma_unmap_single(&spi->dev, t->rx_dma, t->len, DMA_FROM_DEVICE); + if (!t->rx_buf) + dma_unmap_single(&spi->dev, t->rx_dma, t->len, DMA_FROM_DEVICE); err_rx_map: kfree(dummy_buf); err_alloc_dummy_buf: @@ -990,6 +1005,7 @@ static int davinci_spi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); master->setup = davinci_spi_setup; master->cleanup = davinci_spi_cleanup; + master->can_dma = davinci_spi_can_dma; dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;