From patchwork Mon Apr 16 15:40:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Sylwester Nawrocki/Kernel \\(PLT\\) /SRPOL/Staff Engineer/Samsung Electronics" X-Patchwork-Id: 10343341 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 2645560548 for ; Mon, 16 Apr 2018 15:42:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19BC1287C1 for ; Mon, 16 Apr 2018 15:42:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0E6C3287BB; Mon, 16 Apr 2018 15:42:13 +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=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 97171287BD for ; Mon, 16 Apr 2018 15:42:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750979AbeDPPmM (ORCPT ); Mon, 16 Apr 2018 11:42:12 -0400 Received: from mailout4.samsung.com ([203.254.224.34]:32653 "EHLO mailout4.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750708AbeDPPmK (ORCPT ); Mon, 16 Apr 2018 11:42:10 -0400 Received: from epcas1p3.samsung.com (unknown [182.195.41.47]) by mailout4.samsung.com (KnoxPortal) with ESMTP id 20180416154209epoutp04a3bf52bbc4ff37cc4e2d534eaff28bc1~l9Oi8yB4T3185031850epoutp04N; Mon, 16 Apr 2018 15:42:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout4.samsung.com 20180416154209epoutp04a3bf52bbc4ff37cc4e2d534eaff28bc1~l9Oi8yB4T3185031850epoutp04N DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1523893329; bh=/ppuRWksEsEQFaWwOZ4/OQ3MREzZHZi3U0YJYJ8YgS4=; h=From:To:Cc:Subject:Date:In-reply-to:References:From; b=nW/gBWtfkUQHGQUccEU79kGEm+mWYeRqAIrwwf9WfS0YeJ+qWlIK9s+BtqxxSGqM+ CO33UvnEYjc838gqgZN/UMOqP5IZpZr4U40F9Npybdj5s6AeaqY7N2bHo8lt/bu9we 8pNaQzY6r4NLzOT+7eSs2Vg4lNoqxxSAy1+ajuvM= Received: from epsmges1p1.samsung.com (unknown [182.195.42.53]) by epcas1p4.samsung.com (KnoxPortal) with ESMTP id 20180416154209epcas1p41e72bbc18ff8ed992cb0204c9ca8882b~l9Oiz3AYb2416624166epcas1p46; Mon, 16 Apr 2018 15:42:09 +0000 (GMT) Received: from epcas1p4.samsung.com ( [182.195.41.48]) by epsmges1p1.samsung.com (Symantec Messaging Gateway) with SMTP id 90.D6.04078.154C4DA5; Tue, 17 Apr 2018 00:42:09 +0900 (KST) Received: from epsmgms2p1new.samsung.com (unknown [182.195.42.142]) by epcas1p1.samsung.com (KnoxPortal) with ESMTP id 20180416154208epcas1p1774dd679e3564be916901a180315943b~l9OiMRSsa1555615556epcas1p1h; Mon, 16 Apr 2018 15:42:08 +0000 (GMT) X-AuditID: b6c32a35-139ff70000000fee-48-5ad4c451ff1c Received: from epmmp2 ( [203.254.227.17]) by epsmgms2p1new.samsung.com (Symantec Messaging Gateway) with SMTP id C7.E1.03849.054C4DA5; Tue, 17 Apr 2018 00:42:08 +0900 (KST) Received: from AMDC3061.digital.local ([106.116.147.40]) by mmp2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0P7A004PTBJEDK00@mmp2.samsung.com>; Tue, 17 Apr 2018 00:42:08 +0900 (KST) From: Sylwester Nawrocki To: broonie@kernel.org Cc: andi@etezian.org, krzk@kernel.org, kgene@kernel.org, linux-spi@vger.kernel.org, linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, m.szyprowski@samsung.com, b.zolnierkie@samsung.com, Sylwester Nawrocki Subject: [PATCH 6/6] spi: spi-s3c64xx: Allow higher transfer lengths in polling IO mode Date: Mon, 16 Apr 2018 17:40:21 +0200 Message-id: <20180416154021.25626-6-s.nawrocki@samsung.com> X-Mailer: git-send-email 2.14.2 In-reply-to: <20180416154021.25626-1-s.nawrocki@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrEIsWRmVeSWpSXmKPExsWy7bCmgW7gkStRBnO+clks/vGcyWLjjPWs FlMfPmGz6H/8mtni/PkN7BabHl9jtZhxfh+TRePHm+wWa4/cZbc4/Kad1YHL4/qST8wem1Z1 snlsXlLv0bdlFaPH501yAaxRXDYpqTmZZalF+nYJXBnr/v1lKnioXHH91hqmBsbv0l2MnBwS AiYSk089YO9i5OIQEtjBKPH3znxWCOc7o8T/7a9ZYapmvprACJHYwCixe28DVMsvRonFR/az gFSxCRhK9B7tYwSxRQTEJG7P6WQGKWIWaGKSaH2wDmyUsECkxJ4fe8BsFgFViT0f5rCB2LwC 1hLdG/8zQqyTl3i/4D6YzSlgI3H870mwQRICC9gktu+eAbSNA8hxkfi/XxWiXlji1fEt7BBh aYlLR20hwtUSnW1d7BCtLYwSf6ZdYoNIWEscPn4R7AZmAT6Jd197WCF6eSU62oQgSjwkzl7b wwJhO0q0nz7IAvFwP6NEb98B9gmMUgsYGVYxiqUWFOempxYbFhjqFSfmFpfmpesl5+duYgTH rJbpDsYp53wOMQpwMCrx8ErsuBIlxJpYVlyZe4hRgoNZSYR3/iGgEG9KYmVValF+fFFpTmrx IUZpDhYlcd6nPmeihATSE0tSs1NTC1KLYLJMHJxSDYyqX3aGvp2wRTq9T+GZWsmdbdqyjP+t qgOKjnDF/609rZb1fpG3ImMSE/s0O83d3xaXu6hN/hx1U0JMLOpJUjcbkzX/ta+HPnrdODD/ V/lxQyWeOTz3BRbzXljTrX4vNj83xd5Ia7rfMafvGdJGsm9j+n8zrtkUscO7Kz5IftW0HANP 2RMblZRYijMSDbWYi4oTAd0Dhc/VAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprNLMWRmVeSWpSXmKPExsVy+t9jQd2AI1eiDK49k7VY/OM5k8XGGetZ LaY+fMJm0f/4NbPF+fMb2C02Pb7GajHj/D4mi8aPN9kt1h65y25x+E07qwOXx/Uln5g9Nq3q ZPPYvKTeo2/LKkaPz5vkAlijuGxSUnMyy1KL9O0SuDLW/fvLVPBQueL6rTVMDYzfpbsYOTkk BEwkZr6awNjFyMUhJLCOUWL57K9sEM4vRomH93sZQarYBAwleo/2gdkiAmISt+d0MoMUMQs0 MUm8//yZGSQhLBAp8e/OQrAiFgFViT0f5rCB2LwC1hLdG/8zQqyTl3i/4D6YzSlgI3H870mw XiGgmitLX7NOYORZwMiwilEytaA4Nz232KjAMC+1XK84Mbe4NC9dLzk/dxMjMMi2Hdbq28F4 f0n8IUYBDkYlHl6JHVeihFgTy4orcw8xSnAwK4nwzj8EFOJNSaysSi3Kjy8qzUktPsQozcGi JM57O+9YpJBAemJJanZqakFqEUyWiYNTqoHRRPpeoU1jgP45hef35tXuaEgxT+fZ/1ZR8+1U ge8THddP7jw1TfrmxVKGpu7fZ3Wf5N9ec6wp0fIbk6WAoPDnjAWFuREa7zyS4tuzOKrnlXno PnhmpBQf6Bl3/Zq55QztmJdCMhKbX3P+mNtQWv3I0Dkg8q+rtmdKx+IcpZxXniaZn98mTlNi Kc5INNRiLipOBADoMeC3LgIAAA== X-CMS-MailID: 20180416154208epcas1p1774dd679e3564be916901a180315943b X-Msg-Generator: CA CMS-TYPE: 101P X-CMS-RootMailID: 20180416154208epcas1p1774dd679e3564be916901a180315943b X-RootMTR: 20180416154208epcas1p1774dd679e3564be916901a180315943b References: <20180416154021.25626-1-s.nawrocki@samsung.com> Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some variants of the SPI controller have no DMA support, in such case SPI transfers longer than the FIFO length are not currently properly handled by the driver. Fix it by doing multiple transfers in the s3c64xx_spi_transfer_one() function if the SPI transfer length exceeds the FIFO size. Signed-off-by: Sylwester Nawrocki --- drivers/spi/spi-s3c64xx.c | 108 ++++++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 37 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 2723fa6bed8b..b2e8ed354dac 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -349,7 +349,7 @@ static bool s3c64xx_spi_can_dma(struct spi_master *master, } static void s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd, - struct spi_transfer *xfer, int dma_mode) + struct spi_transfer *xfer, bool dma_mode) { void __iomem *regs = sdd->regs; u32 modecfg, chcfg; @@ -634,11 +634,15 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, struct spi_transfer *xfer) { struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + const unsigned int fifo_len = (FIFO_LVL_MASK(sdd) >> 1) + 1; + const void *tx_buf = NULL; + void *rx_buf = NULL; + int target_len = 0, origin_len = 0; + bool use_dma = false; int status; u32 speed; u8 bpw; unsigned long flags; - int use_dma; reinit_completion(&sdd->xfer_completion); @@ -653,48 +657,78 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, s3c64xx_spi_config(sdd); } - /* Polling method for xfers not bigger than FIFO capacity */ - use_dma = 0; - if (!is_polling(sdd) && - (sdd->rx_dma.ch && sdd->tx_dma.ch && - (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1)))) - use_dma = 1; + if (!is_polling(sdd) && (xfer->len > fifo_len) && + sdd->rx_dma.ch && sdd->tx_dma.ch) { + use_dma = true; - spin_lock_irqsave(&sdd->lock, flags); + } else if (is_polling(sdd) && xfer->len > fifo_len) { + tx_buf = xfer->tx_buf; + rx_buf = xfer->rx_buf; + origin_len = xfer->len; - /* Pending only which is to be done */ - sdd->state &= ~RXBUSY; - sdd->state &= ~TXBUSY; + target_len = xfer->len; + if (xfer->len > fifo_len) + xfer->len = fifo_len; + } + + do { + spin_lock_irqsave(&sdd->lock, flags); - s3c64xx_enable_datapath(sdd, xfer, use_dma); + /* Pending only which is to be done */ + sdd->state &= ~RXBUSY; + sdd->state &= ~TXBUSY; - /* Start the signals */ - s3c64xx_spi_set_cs(spi, true); + s3c64xx_enable_datapath(sdd, xfer, use_dma); - spin_unlock_irqrestore(&sdd->lock, flags); + /* Start the signals */ + s3c64xx_spi_set_cs(spi, true); - if (use_dma) - status = wait_for_dma(sdd, xfer); - else - status = wait_for_pio(sdd, xfer); - - if (status) { - dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n", - xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, - (sdd->state & RXBUSY) ? 'f' : 'p', - (sdd->state & TXBUSY) ? 'f' : 'p', - xfer->len); - - if (use_dma) { - if (xfer->tx_buf != NULL - && (sdd->state & TXBUSY)) - dmaengine_terminate_all(sdd->tx_dma.ch); - if (xfer->rx_buf != NULL - && (sdd->state & RXBUSY)) - dmaengine_terminate_all(sdd->rx_dma.ch); + spin_unlock_irqrestore(&sdd->lock, flags); + + if (use_dma) + status = wait_for_dma(sdd, xfer); + else + status = wait_for_pio(sdd, xfer); + + if (status) { + dev_err(&spi->dev, + "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n", + xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, + (sdd->state & RXBUSY) ? 'f' : 'p', + (sdd->state & TXBUSY) ? 'f' : 'p', + xfer->len); + + if (use_dma) { + if (xfer->tx_buf && (sdd->state & TXBUSY)) + dmaengine_terminate_all(sdd->tx_dma.ch); + if (xfer->rx_buf && (sdd->state & RXBUSY)) + dmaengine_terminate_all(sdd->rx_dma.ch); + } + } else { + flush_fifo(sdd); } - } else { - flush_fifo(sdd); + + if (target_len > 0) { + target_len -= xfer->len; + + if (xfer->tx_buf) + xfer->tx_buf += xfer->len; + + if (xfer->rx_buf) + xfer->rx_buf += xfer->len; + + if (target_len > fifo_len) + xfer->len = fifo_len; + else + xfer->len = target_len; + } + } while (target_len > 0); + + if (origin_len) { + /* Restore original xfer buffers and length */ + xfer->tx_buf = tx_buf; + xfer->rx_buf = rx_buf; + xfer->len = origin_len; } return status;