From patchwork Wed Nov 30 18:08:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 9454677 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 30D5A60585 for ; Wed, 30 Nov 2016 18:08:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2A08D2848F for ; Wed, 30 Nov 2016 18:08:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1DBC12849A; Wed, 30 Nov 2016 18:08:29 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 03F8C2848F for ; Wed, 30 Nov 2016 18:08:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758555AbcK3SIQ (ORCPT ); Wed, 30 Nov 2016 13:08:16 -0500 Received: from mezzanine.sirena.org.uk ([106.187.55.193]:36068 "EHLO mezzanine.sirena.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758497AbcK3SIJ (ORCPT ); Wed, 30 Nov 2016 13:08:09 -0500 Received: from [2001:470:1f1d:6b5::3] (helo=debutante) by mezzanine.sirena.org.uk with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1cC9Ia-0005lE-57; Wed, 30 Nov 2016 18:08:06 +0000 Received: from broonie by debutante with local (Exim 4.87) (envelope-from ) id 1cC9IX-0008P4-ES; Wed, 30 Nov 2016 18:08:01 +0000 From: Mark Brown To: Heiner Kallweit Cc: Mark Brown , Mark Brown , "linux-spi@vger.kernel.org" In-Reply-To: Message-Id: Date: Wed, 30 Nov 2016 18:08:01 +0000 X-SA-Exim-Connect-IP: 2001:470:1f1d:6b5::3 X-SA-Exim-Mail-From: broonie@sirena.org.uk Subject: Applied "spi: fsl-espi: eliminate need for linearization when writing to hardware" to the spi tree X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:24:06 +0000) X-SA-Exim-Scanned: No (on mezzanine.sirena.org.uk); Unknown failure 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 The patch spi: fsl-espi: eliminate need for linearization when writing to hardware has been applied to the spi tree at git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark From 05823432844515e6e6e0e80dd44624a36ea405b7 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 25 Nov 2016 23:59:24 +0100 Subject: [PATCH] spi: fsl-espi: eliminate need for linearization when writing to hardware Eliminate need for linearization when writing to the hardware and read from the transfer buffers directly. Signed-off-by: Heiner Kallweit Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-espi.c | 79 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index 4222578a4dd4..189ab36b787f 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -98,6 +98,11 @@ struct fsl_espi { const void *tx; void *rx; + struct list_head *m_transfers; + struct spi_transfer *tx_t; + unsigned int tx_pos; + bool tx_done; + bool swab; unsigned int rx_len; unsigned int tx_len; @@ -131,6 +136,12 @@ static inline void fsl_espi_write_reg(struct fsl_espi *espi, int offset, iowrite32be(val, espi->reg_base + offset); } +static inline void fsl_espi_write_reg16(struct fsl_espi *espi, int offset, + u16 val) +{ + iowrite16(val, espi->reg_base + offset); +} + static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset, u8 val) { @@ -260,22 +271,58 @@ static unsigned int fsl_espi_check_rxskip_mode(struct spi_message *m) static void fsl_espi_fill_tx_fifo(struct fsl_espi *espi, u32 events) { u32 tx_fifo_avail; + unsigned int tx_left; + const void *tx_buf; /* if events is zero transfer has not started and tx fifo is empty */ tx_fifo_avail = events ? SPIE_TXCNT(events) : FSL_ESPI_FIFO_SIZE; - - while (tx_fifo_avail >= min(4U, espi->tx_len) && espi->tx_len) - if (espi->tx_len >= 4) { - fsl_espi_write_reg(espi, ESPI_SPITF, *(u32 *)espi->tx); - espi->tx += 4; - espi->tx_len -= 4; +start: + tx_left = espi->tx_t->len - espi->tx_pos; + tx_buf = espi->tx_t->tx_buf; + while (tx_fifo_avail >= min(4U, tx_left) && tx_left) { + if (tx_left >= 4) { + if (!tx_buf) + fsl_espi_write_reg(espi, ESPI_SPITF, 0); + else if (espi->swab) + fsl_espi_write_reg(espi, ESPI_SPITF, + swahb32p(tx_buf + espi->tx_pos)); + else + fsl_espi_write_reg(espi, ESPI_SPITF, + *(u32 *)(tx_buf + espi->tx_pos)); + espi->tx_pos += 4; + tx_left -= 4; tx_fifo_avail -= 4; + } else if (tx_left >= 2 && tx_buf && espi->swab) { + fsl_espi_write_reg16(espi, ESPI_SPITF, + swab16p(tx_buf + espi->tx_pos)); + espi->tx_pos += 2; + tx_left -= 2; + tx_fifo_avail -= 2; } else { - fsl_espi_write_reg8(espi, ESPI_SPITF, *(u8 *)espi->tx); - espi->tx += 1; - espi->tx_len -= 1; + if (!tx_buf) + fsl_espi_write_reg8(espi, ESPI_SPITF, 0); + else + fsl_espi_write_reg8(espi, ESPI_SPITF, + *(u8 *)(tx_buf + espi->tx_pos)); + espi->tx_pos += 1; + tx_left -= 1; tx_fifo_avail -= 1; } + } + + if (!tx_left) { + /* Last transfer finished, in rxskip mode only one is needed */ + if (list_is_last(&espi->tx_t->transfer_list, + espi->m_transfers) || espi->rxskip) { + espi->tx_done = true; + return; + } + espi->tx_t = list_next_entry(espi->tx_t, transfer_list); + espi->tx_pos = 0; + /* continue with next transfer if tx fifo is not full */ + if (tx_fifo_avail) + goto start; + } } static void fsl_espi_read_rx_fifo(struct fsl_espi *espi, u32 events) @@ -369,9 +416,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) /* Won't hang up forever, SPI bus sometimes got lost interrupts... */ ret = wait_for_completion_timeout(&espi->done, 2 * HZ); if (ret == 0) - dev_err(espi->dev, - "Transaction hanging up (left %u tx bytes, %u rx bytes)\n", - espi->tx_len, espi->rx_len); + dev_err(espi->dev, "Transfer timed out!\n"); /* disable rx ints */ fsl_espi_write_reg(espi, ESPI_SPIM, 0); @@ -388,6 +433,12 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) /* In case of LSB-first and bits_per_word > 8 byte-swap all words */ espi->swab = spi->mode & SPI_LSB_FIRST && trans->bits_per_word > 8; + espi->m_transfers = &m->transfers; + espi->tx_t = list_first_entry(&m->transfers, struct spi_transfer, + transfer_list); + espi->tx_pos = 0; + espi->tx_done = false; + espi->rxskip = fsl_espi_check_rxskip_mode(m); if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) { dev_err(espi->dev, "Dual output mode requires RXSKIP mode!\n"); @@ -508,10 +559,10 @@ static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events) if (espi->rx_len) fsl_espi_read_rx_fifo(espi, events); - if (espi->tx_len) + if (!espi->tx_done) fsl_espi_fill_tx_fifo(espi, events); - if (espi->tx_len || espi->rx_len) + if (!espi->tx_done || espi->rx_len) return; /* we're done, but check for errors before returning */