From patchwork Thu Aug 28 06:56:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 4799731 Return-Path: X-Original-To: patchwork-ltsi-dev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 41F029F375 for ; Thu, 28 Aug 2014 08:39:22 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F30962012E for ; Thu, 28 Aug 2014 08:39:20 +0000 (UTC) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B351D20145 for ; Thu, 28 Aug 2014 08:39:19 +0000 (UTC) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4B07515AC; Thu, 28 Aug 2014 07:35:32 +0000 (UTC) X-Original-To: ltsi-dev@lists.linuxfoundation.org Delivered-To: ltsi-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 30A4314C2 for ; Thu, 28 Aug 2014 07:34:56 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from kirsty.vergenet.net (kirsty.vergenet.net [202.4.237.240]) by smtp1.linuxfoundation.org (Postfix) with ESMTP id D365D2025A for ; Thu, 28 Aug 2014 07:34:54 +0000 (UTC) Received: from ayumi.isobedori.kobe.vergenet.net (p4222-ipbfp1605kobeminato.hyogo.ocn.ne.jp [114.154.95.222]) by kirsty.vergenet.net (Postfix) with ESMTP id C4F9526725D; Thu, 28 Aug 2014 17:08:06 +1000 (EST) Received: by ayumi.isobedori.kobe.vergenet.net (Postfix, from userid 7100) id 4689BEDE709; Thu, 28 Aug 2014 16:08:04 +0900 (JST) From: Simon Horman To: ltsi-dev@lists.linuxfoundation.org Date: Thu, 28 Aug 2014 15:56:44 +0900 Message-Id: <1409209620-24487-279-git-send-email-horms+renesas@verge.net.au> X-Mailer: git-send-email 2.0.1 In-Reply-To: <1409209620-24487-1-git-send-email-horms+renesas@verge.net.au> References: <1409209620-24487-1-git-send-email-horms+renesas@verge.net.au> X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org Cc: Magnus Damm Subject: [LTSI-dev] [PATCH LTSI-3.14 278/894] spi: rspi: Use core SPI_MASTER_MUST_[RT]X handling X-BeenThere: ltsi-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: "A list to discuss patches, development, and other things related to the LTSI project" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ltsi-dev-bounces@lists.linuxfoundation.org Errors-To: ltsi-dev-bounces@lists.linuxfoundation.org X-Virus-Scanned: ClamAV using ClamSMTP From: Geert Uytterhoeven RSPI needs dummy transfers to generate the SPI clock on receive. RSPI-RZ and QSPI always do both transmit and receive. Use the SPI core SPI_MASTER_MUST_RX/SPI_MASTER_MUST_TX infrastructure instead of checking for the presence of buffers and providing dummy data ourselves (for PIO), or providing a dummy buffer (for DMA). rspi_receive_dma() now provides full duplex DMA transfers on RSPI, and is renamed to rspi_send_receive_dma(). As the SPI core will always provide a TX buffer, the logic to choose between DMA send and DMA send/receive in rspi_transfer_one() now has to check for the presence of an RX buffer. Likewise for the DMA availability tests in rspi_is_dma(). The buffer tests in qspi_transfer_one() are now always true, so they're removed. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown (cherry picked from commit b42e03596db3d45980c976c8124fdc323f031dc4) Signed-off-by: Simon Horman --- drivers/spi/spi-rspi.c | 132 ++++++++++++++++++++++--------------------------- 1 file changed, 58 insertions(+), 74 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 3bd06fd..ece8f60 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -183,8 +183,6 @@ #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ -#define DUMMY_DATA 0x00 - struct rspi_data { void __iomem *addr; u32 max_speed_hz; @@ -252,6 +250,7 @@ struct spi_ops { int (*transfer_one)(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer); u16 mode_bits; + u16 flags; }; /* @@ -552,42 +551,38 @@ static void qspi_receive_init(const struct rspi_data *rspi) rspi_write8(rspi, 0, QSPI_SPBFCR); } -static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) +static int rspi_send_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) { - struct scatterlist sg, sg_dummy; - void *dummy = NULL, *rx_buf = t->rx_buf; - struct dma_async_tx_descriptor *desc, *desc_dummy; + struct scatterlist sg_rx, sg_tx; + const void *tx_buf = t->tx_buf; + void *rx_buf = t->rx_buf; + struct dma_async_tx_descriptor *desc_tx, *desc_rx; unsigned int len = t->len; int ret = 0; - /* prepare dummy transfer to generate SPI clocks */ - dummy = kzalloc(len, GFP_KERNEL); - if (!dummy) { - ret = -ENOMEM; - goto end_nomap; - } - if (!rspi_dma_map_sg(&sg_dummy, dummy, len, rspi->chan_tx, - DMA_TO_DEVICE)) { - ret = -EFAULT; - goto end_nomap; - } - desc_dummy = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_dummy, 1, + /* prepare transmit transfer */ + if (!rspi_dma_map_sg(&sg_tx, tx_buf, len, rspi->chan_tx, + DMA_TO_DEVICE)) + return -EFAULT; + + desc_tx = dmaengine_prep_slave_sg(rspi->chan_tx, &sg_tx, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc_dummy) { + if (!desc_tx) { ret = -EIO; - goto end_dummy_mapped; + goto end_tx_mapped; } /* prepare receive transfer */ - if (!rspi_dma_map_sg(&sg, rx_buf, len, rspi->chan_rx, + if (!rspi_dma_map_sg(&sg_rx, rx_buf, len, rspi->chan_rx, DMA_FROM_DEVICE)) { ret = -EFAULT; - goto end_dummy_mapped; + goto end_tx_mapped; } - desc = dmaengine_prep_slave_sg(rspi->chan_rx, &sg, 1, DMA_FROM_DEVICE, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) { + desc_rx = dmaengine_prep_slave_sg(rspi->chan_rx, &sg_rx, 1, + DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc_rx) { ret = -EIO; goto end; } @@ -606,13 +601,13 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE); rspi->dma_callbacked = 0; - desc->callback = rspi_dma_complete; - desc->callback_param = rspi; - dmaengine_submit(desc); + desc_rx->callback = rspi_dma_complete; + desc_rx->callback_param = rspi; + dmaengine_submit(desc_rx); dma_async_issue_pending(rspi->chan_rx); - desc_dummy->callback = NULL; /* No callback */ - dmaengine_submit(desc_dummy); + desc_tx->callback = NULL; /* No callback */ + dmaengine_submit(desc_tx); dma_async_issue_pending(rspi->chan_tx); ret = wait_event_interruptible_timeout(rspi->wait, @@ -628,21 +623,19 @@ static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t) enable_irq(rspi->rx_irq); end: - rspi_dma_unmap_sg(&sg, rspi->chan_rx, DMA_FROM_DEVICE); -end_dummy_mapped: - rspi_dma_unmap_sg(&sg_dummy, rspi->chan_tx, DMA_TO_DEVICE); -end_nomap: - kfree(dummy); - + rspi_dma_unmap_sg(&sg_rx, rspi->chan_rx, DMA_FROM_DEVICE); +end_tx_mapped: + rspi_dma_unmap_sg(&sg_tx, rspi->chan_tx, DMA_TO_DEVICE); return ret; } static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t) { - if (t->tx_buf && rspi->chan_tx) - return 1; /* If the module receives data by DMAC, it also needs TX DMAC */ - if (t->rx_buf && rspi->chan_tx && rspi->chan_rx) + if (t->rx_buf) + return rspi->chan_tx && rspi->chan_rx; + + if (rspi->chan_tx) return 1; return 0; @@ -654,7 +647,7 @@ static int rspi_transfer_out_in(struct rspi_data *rspi, int remain = xfer->len, ret; const u8 *tx_buf = xfer->tx_buf; u8 *rx_buf = xfer->rx_buf; - u8 spcr, data; + u8 spcr; spcr = rspi_read8(rspi, RSPI_SPCR); if (rx_buf) { @@ -666,8 +659,7 @@ static int rspi_transfer_out_in(struct rspi_data *rspi, rspi_write8(rspi, spcr, RSPI_SPCR); while (remain > 0) { - data = tx_buf ? *tx_buf++ : DUMMY_DATA; - ret = rspi_data_out(rspi, data); + ret = rspi_data_out(rspi, *tx_buf++); if (ret < 0) return ret; if (rx_buf) { @@ -689,20 +681,14 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { struct rspi_data *rspi = spi_master_get_devdata(master); - int ret; if (!rspi_is_dma(rspi, xfer)) return rspi_transfer_out_in(rspi, xfer); - if (xfer->tx_buf) { - ret = rspi_send_dma(rspi, xfer); - if (ret < 0) - return ret; - } if (xfer->rx_buf) - return rspi_receive_dma(rspi, xfer); - - return 0; + return rspi_send_receive_dma(rspi, xfer); + else + return rspi_send_dma(rspi, xfer); } static int rspi_rz_transfer_out_in(struct rspi_data *rspi, @@ -711,17 +697,14 @@ static int rspi_rz_transfer_out_in(struct rspi_data *rspi, int remain = xfer->len, ret; const u8 *tx_buf = xfer->tx_buf; u8 *rx_buf = xfer->rx_buf; - u8 data; rspi_rz_receive_init(rspi); while (remain > 0) { - data = tx_buf ? *tx_buf++ : DUMMY_DATA; - ret = rspi_data_out_in(rspi, data); + ret = rspi_data_out_in(rspi, *tx_buf++); if (ret < 0) return ret; - if (rx_buf) - *rx_buf++ = ret; + *rx_buf++ = ret; remain--; } @@ -746,17 +729,14 @@ static int qspi_transfer_out_in(struct rspi_data *rspi, int remain = xfer->len, ret; const u8 *tx_buf = xfer->tx_buf; u8 *rx_buf = xfer->rx_buf; - u8 data; qspi_receive_init(rspi); while (remain > 0) { - data = tx_buf ? *tx_buf++ : DUMMY_DATA; - ret = rspi_data_out_in(rspi, data); + ret = rspi_data_out_in(rspi, *tx_buf++); if (ret < 0) return ret; - if (rx_buf) - *rx_buf++ = ret; + *rx_buf++ = ret; remain--; } @@ -807,10 +787,10 @@ static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi, if (spi->mode & SPI_LOOP) { return qspi_transfer_out_in(rspi, xfer); - } else if (xfer->tx_buf && xfer->tx_nbits > SPI_NBITS_SINGLE) { + } else if (xfer->tx_nbits > SPI_NBITS_SINGLE) { /* Quad or Dual SPI Write */ return qspi_transfer_out(rspi, xfer); - } else if (xfer->rx_buf && xfer->rx_nbits > SPI_NBITS_SINGLE) { + } else if (xfer->rx_nbits > SPI_NBITS_SINGLE) { /* Quad or Dual SPI Read */ return qspi_transfer_in(rspi, xfer); } else { @@ -1061,23 +1041,26 @@ static int rspi_remove(struct platform_device *pdev) } static const struct spi_ops rspi_ops = { - .set_config_register = rspi_set_config_register, - .transfer_one = rspi_transfer_one, - .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, + .set_config_register = rspi_set_config_register, + .transfer_one = rspi_transfer_one, + .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, + .flags = SPI_MASTER_MUST_TX, }; static const struct spi_ops rspi_rz_ops = { - .set_config_register = rspi_rz_set_config_register, - .transfer_one = rspi_rz_transfer_one, - .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, + .set_config_register = rspi_rz_set_config_register, + .transfer_one = rspi_rz_transfer_one, + .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, + .flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX, }; static const struct spi_ops qspi_ops = { - .set_config_register = qspi_set_config_register, - .transfer_one = qspi_transfer_one, - .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP | - SPI_TX_DUAL | SPI_TX_QUAD | - SPI_RX_DUAL | SPI_RX_QUAD, + .set_config_register = qspi_set_config_register, + .transfer_one = qspi_transfer_one, + .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP | + SPI_TX_DUAL | SPI_TX_QUAD | + SPI_RX_DUAL | SPI_RX_QUAD, + .flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX, }; #ifdef CONFIG_OF @@ -1197,6 +1180,7 @@ static int rspi_probe(struct platform_device *pdev) master->prepare_message = rspi_prepare_message; master->unprepare_message = rspi_unprepare_message; master->mode_bits = ops->mode_bits; + master->flags = ops->flags; master->dev.of_node = pdev->dev.of_node; ret = platform_get_irq_byname(pdev, "rx");