diff mbox

[09/18] spi: rspi: SPI DMA core needs both RX and TX DMA to function

Message ID 1401716301-29612-10-git-send-email-geert+renesas@glider.be (mailing list archive)
State Accepted
Commit 5f338d0ce0b4c9e6c554b92cfb288789a41bfbc1
Headers show

Commit Message

Geert Uytterhoeven June 2, 2014, 1:38 p.m. UTC
The SPI DMA core framework needs both RX and TX DMA to function.  As a
preparation for converting the driver to use this framework, fall back to
PIO if no DMA channel or only one DMA channel is available.

This affects only RSPI, which could do DMA transfers for TX-only before.
RSPI-RZ and QSPI (at least for Single SPI Transfers) will need both RX and
TX DMA anyway.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 drivers/spi/spi-rspi.c | 36 ++++++++++++++----------------------
 1 file changed, 14 insertions(+), 22 deletions(-)

Comments

Mark Brown June 2, 2014, 2:42 p.m. UTC | #1
On Mon, Jun 02, 2014 at 03:38:11PM +0200, Geert Uytterhoeven wrote:
> The SPI DMA core framework needs both RX and TX DMA to function.  As a
> preparation for converting the driver to use this framework, fall back to
> PIO if no DMA channel or only one DMA channel is available.

> This affects only RSPI, which could do DMA transfers for TX-only before.
> RSPI-RZ and QSPI (at least for Single SPI Transfers) will need both RX and
> TX DMA anyway.

Hrm, was this error handling or is it a hardware limitation that it can
only do DMA in one direction?  Perhaps the core ought to be changed to
support that if it's a hardware limit, I honestly hadn't considered that
possibility when I wrote the code.
Geert Uytterhoeven June 2, 2014, 2:55 p.m. UTC | #2
Hi Mark,

On Mon, Jun 2, 2014 at 4:42 PM, Mark Brown <broonie@kernel.org> wrote:
> On Mon, Jun 02, 2014 at 03:38:11PM +0200, Geert Uytterhoeven wrote:
>> The SPI DMA core framework needs both RX and TX DMA to function.  As a
>> preparation for converting the driver to use this framework, fall back to
>> PIO if no DMA channel or only one DMA channel is available.
>
>> This affects only RSPI, which could do DMA transfers for TX-only before.

Perhaps my wording was not so clear: "could do DMA transfers for TX-only"
does not mean "could only do DMA transfers for TX (and not RX)".

>> RSPI-RZ and QSPI (at least for Single SPI Transfers) will need both RX and
>> TX DMA anyway.
>
> Hrm, was this error handling or is it a hardware limitation that it can
> only do DMA in one direction?  Perhaps the core ought to be changed to
> support that if it's a hardware limit, I honestly hadn't considered that
> possibility when I wrote the code.

So it's not a hardware limitation, but a software optimization ;-)
If there's no data to receive, RSPI on SH can do transmit only.
If there's data to receive, it must do both transmit and receive.

Later RSPI variants cannot do TX-only, they always do both transmit and
receive (except for Dual/Quad, which are unidirectional by design).

Hence if only one DMA channel is available, RSPI on SH could still do DMA TX
before. I don't know whether anyone ever used this, as there were no in-tree
users of RSPI DMA.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown June 2, 2014, 4:28 p.m. UTC | #3
On Mon, Jun 02, 2014 at 04:55:14PM +0200, Geert Uytterhoeven wrote:
> On Mon, Jun 2, 2014 at 4:42 PM, Mark Brown <broonie@kernel.org> wrote:

> > Hrm, was this error handling or is it a hardware limitation that it can
> > only do DMA in one direction?  Perhaps the core ought to be changed to
> > support that if it's a hardware limit, I honestly hadn't considered that
> > possibility when I wrote the code.

> So it's not a hardware limitation, but a software optimization ;-)
> If there's no data to receive, RSPI on SH can do transmit only.
> If there's data to receive, it must do both transmit and receive.

...

> Hence if only one DMA channel is available, RSPI on SH could still do DMA TX
> before. I don't know whether anyone ever used this, as there were no in-tree
> users of RSPI DMA.

OK, that is quite common I guess in hardware where the number of DMA
channels is limited (which does exist).  We should probably support it
at some point.
diff mbox

Patch

diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 1ec51cb00203..7b993f75a3cf 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -640,10 +640,6 @@  end_tx_mapped:
 
 static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
 {
-	/* If the module receives data by DMAC, it also needs TX DMAC */
-	if (t->rx_buf)
-		return rspi->chan_tx && rspi->chan_rx;
-
 	if (rspi->chan_tx)
 		return 1;
 
@@ -985,29 +981,25 @@  static int rspi_request_dma(struct device *dev, struct rspi_data *rspi,
 {
 	const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
 
-	if (!rspi_pd)
+	if (!rspi_pd || !rspi_pd->dma_rx_id || !rspi_pd->dma_tx_id)
 		return 0;	/* The driver assumes no error. */
 
-	/* If the module receives data by DMAC, it also needs TX DMAC */
-	if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
-		rspi->chan_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM,
-						      rspi_pd->dma_rx_id,
-						      res->start + RSPI_SPDR);
-		if (!rspi->chan_rx)
-			return -ENODEV;
+	rspi->chan_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM,
+					      rspi_pd->dma_rx_id,
+					      res->start + RSPI_SPDR);
+	if (!rspi->chan_rx)
+		return -ENODEV;
 
-		dev_info(dev, "Use DMA when rx.\n");
-	}
-	if (rspi_pd->dma_tx_id) {
-		rspi->chan_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV,
-						      rspi_pd->dma_tx_id,
-						      res->start + RSPI_SPDR);
-		if (!rspi->chan_tx)
-			return -ENODEV;
-
-		dev_info(dev, "Use DMA when tx\n");
+	rspi->chan_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV,
+					      rspi_pd->dma_tx_id,
+					      res->start + RSPI_SPDR);
+	if (!rspi->chan_tx) {
+		dma_release_channel(rspi->chan_rx);
+		rspi->chan_rx = NULL;
+		return -ENODEV;
 	}
 
+	dev_info(dev, "DMA available");
 	return 0;
 }