* [PATCH 01/18] spi: rspi: Extract rspi_wait_for_{tx_empty,rx_full}()
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 02/18] spi: rspi: Do not call rspi_receive_init() for TX-only Geert Uytterhoeven
` (11 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 5639f9529e0b..d04a4acce231 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -405,11 +405,22 @@ static int rspi_wait_for_interrupt(struct rspi_data *rspi, u8 wait_mask,
return 0;
}
+static inline int rspi_wait_for_tx_empty(struct rspi_data *rspi)
+{
+ return rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+}
+
+static inline int rspi_wait_for_rx_full(struct rspi_data *rspi)
+{
+ return rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE);
+}
+
static int rspi_data_out(struct rspi_data *rspi, u8 data)
{
- if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
+ int error = rspi_wait_for_tx_empty(rspi);
+ if (error < 0) {
dev_err(&rspi->master->dev, "transmit timeout\n");
- return -ETIMEDOUT;
+ return error;
}
rspi_write_data(rspi, data);
return 0;
@@ -417,11 +428,13 @@ static int rspi_data_out(struct rspi_data *rspi, u8 data)
static int rspi_data_in(struct rspi_data *rspi)
{
+ int error;
u8 data;
- if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
+ error = rspi_wait_for_rx_full(rspi);
+ if (error < 0) {
dev_err(&rspi->master->dev, "receive timeout\n");
- return -ETIMEDOUT;
+ return error;
}
data = rspi_read_data(rspi);
return data;
@@ -737,7 +750,7 @@ static int rspi_transfer_out_in(struct rspi_data *rspi,
}
/* Wait for the last transmission */
- rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+ rspi_wait_for_tx_empty(rspi);
return 0;
}
@@ -783,7 +796,7 @@ static int rspi_rz_transfer_out_in(struct rspi_data *rspi,
}
/* Wait for the last transmission */
- rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+ rspi_wait_for_tx_empty(rspi);
return 0;
}
@@ -818,7 +831,7 @@ static int qspi_transfer_out_in(struct rspi_data *rspi,
}
/* Wait for the last transmission */
- rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+ rspi_wait_for_tx_empty(rspi);
return 0;
}
@@ -836,7 +849,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
}
/* Wait for the last transmission */
- rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+ rspi_wait_for_tx_empty(rspi);
return 0;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 02/18] spi: rspi: Do not call rspi_receive_init() for TX-only
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 01/18] spi: rspi: Extract rspi_wait_for_{tx_empty,rx_full}() Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 03/18] [RFC] spi: rspi: Remove unused 16-bit DMA support Geert Uytterhoeven
` (10 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
Since commit 8449fd76deb9ac67a15a6fb8ead7bb4595d019d2 ("spi: rspi: Merge
rspi_send_pio() and rspi_receive_pio()"), rspi_receive_init() is called
for transmit-only transfers too, while this is not needed.
Only call rspi_receive_init() when receiving, to preserve behavior on
RSPI on SH.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index d04a4acce231..57beda209599 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -726,13 +726,13 @@ static int rspi_transfer_out_in(struct rspi_data *rspi,
u8 *rx_buf = xfer->rx_buf;
u8 spcr, data;
- rspi_receive_init(rspi);
-
spcr = rspi_read8(rspi, RSPI_SPCR);
- if (rx_buf)
+ if (rx_buf) {
+ rspi_receive_init(rspi);
spcr &= ~SPCR_TXMD;
- else
+ } else {
spcr |= SPCR_TXMD;
+ }
rspi_write8(rspi, spcr, RSPI_SPCR);
while (remain > 0) {
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 03/18] [RFC] spi: rspi: Remove unused 16-bit DMA support
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 01/18] spi: rspi: Extract rspi_wait_for_{tx_empty,rx_full}() Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 02/18] spi: rspi: Do not call rspi_receive_init() for TX-only Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 05/18] spi: rspi: Extract rspi_pio_transfer() Geert Uytterhoeven
` (9 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
The 16-bit DMA support doesn't fit well within the SPI core DMA framework,
as it needs to manage its own double-sized temporary buffers, for handling
the interleaved data.
Remove it, as there is no in-tree board code that sets
rspi_plat_data.dma_width_16bit.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 84 ++++--------------------------------------------
include/linux/spi/rspi.h | 2 --
2 files changed, 6 insertions(+), 80 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 57beda209599..3bd06fd9af47 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -201,7 +201,6 @@ struct rspi_data {
struct dma_chan *chan_tx;
struct dma_chan *chan_rx;
- unsigned dma_width_16bit:1;
unsigned dma_callbacked:1;
unsigned byte_access:1;
};
@@ -475,60 +474,17 @@ static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan,
dma_unmap_sg(chan->device->dev, sg, 1, dir);
}
-static void rspi_memory_to_8bit(void *buf, const void *data, unsigned len)
-{
- u16 *dst = buf;
- const u8 *src = data;
-
- while (len) {
- *dst++ = (u16)(*src++);
- len--;
- }
-}
-
-static void rspi_memory_from_8bit(void *buf, const void *data, unsigned len)
-{
- u8 *dst = buf;
- const u16 *src = data;
-
- while (len) {
- *dst++ = (u8)*src++;
- len--;
- }
-}
-
static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
{
struct scatterlist sg;
- const void *buf = NULL;
+ const void *buf = t->tx_buf;
struct dma_async_tx_descriptor *desc;
- unsigned int len;
+ unsigned int len = t->len;
int ret = 0;
- if (rspi->dma_width_16bit) {
- void *tmp;
- /*
- * If DMAC bus width is 16-bit, the driver allocates a dummy
- * buffer. And, the driver converts original data into the
- * DMAC data as the following format:
- * original data: 1st byte, 2nd byte ...
- * DMAC data: 1st byte, dummy, 2nd byte, dummy ...
- */
- len = t->len * 2;
- tmp = kmalloc(len, GFP_KERNEL);
- if (!tmp)
- return -ENOMEM;
- rspi_memory_to_8bit(tmp, t->tx_buf, t->len);
- buf = tmp;
- } else {
- len = t->len;
- buf = t->tx_buf;
- }
+ if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE))
+ return -EFAULT;
- if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE)) {
- ret = -EFAULT;
- goto end_nomap;
- }
desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
@@ -563,10 +519,6 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
end:
rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE);
-end_nomap:
- if (rspi->dma_width_16bit)
- kfree(buf);
-
return ret;
}
@@ -603,28 +555,11 @@ static void qspi_receive_init(const struct rspi_data *rspi)
static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
{
struct scatterlist sg, sg_dummy;
- void *dummy = NULL, *rx_buf = NULL;
+ void *dummy = NULL, *rx_buf = t->rx_buf;
struct dma_async_tx_descriptor *desc, *desc_dummy;
- unsigned int len;
+ unsigned int len = t->len;
int ret = 0;
- if (rspi->dma_width_16bit) {
- /*
- * If DMAC bus width is 16-bit, the driver allocates a dummy
- * buffer. And, finally the driver converts the DMAC data into
- * actual data as the following format:
- * DMAC data: 1st byte, dummy, 2nd byte, dummy ...
- * actual data: 1st byte, 2nd byte ...
- */
- len = t->len * 2;
- rx_buf = kmalloc(len, GFP_KERNEL);
- if (!rx_buf)
- return -ENOMEM;
- } else {
- len = t->len;
- rx_buf = t->rx_buf;
- }
-
/* prepare dummy transfer to generate SPI clocks */
dummy = kzalloc(len, GFP_KERNEL);
if (!dummy) {
@@ -697,11 +632,6 @@ end:
end_dummy_mapped:
rspi_dma_unmap_sg(&sg_dummy, rspi->chan_tx, DMA_TO_DEVICE);
end_nomap:
- if (rspi->dma_width_16bit) {
- if (!ret)
- rspi_memory_from_8bit(t->rx_buf, rx_buf, t->len);
- kfree(rx_buf);
- }
kfree(dummy);
return ret;
@@ -1073,8 +1003,6 @@ static int rspi_request_dma(struct rspi_data *rspi,
if (!res || !rspi_pd)
return 0; /* The driver assumes no error. */
- rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
-
/* If the module receives data by DMAC, it also needs TX DMAC */
if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
dma_cap_zero(mask);
diff --git a/include/linux/spi/rspi.h b/include/linux/spi/rspi.h
index a25bd6f65e7f..e546b2ceb623 100644
--- a/include/linux/spi/rspi.h
+++ b/include/linux/spi/rspi.h
@@ -25,8 +25,6 @@ struct rspi_plat_data {
unsigned int dma_tx_id;
unsigned int dma_rx_id;
- unsigned dma_width_16bit:1; /* DMAC read/write width = 16-bit */
-
u16 num_chipselect;
};
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 05/18] spi: rspi: Extract rspi_pio_transfer()
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (2 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 03/18] [RFC] spi: rspi: Remove unused 16-bit DMA support Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 06/18] spi: rspi: Don't consider DMA configuration failures fatal Geert Uytterhoeven
` (8 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
The various PIO loops are very similar. Consolidate into a single
function rspi_pio_transfer().
Both buffer pointers can be NULL, as RSPI supports TX-only mode, and
Dual/Quad SPI Transfers are unidirectional.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 95 ++++++++++++++++++--------------------------------
1 file changed, 33 insertions(+), 62 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index ece8f6037943..fdbd46d0c570 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -438,15 +438,24 @@ static int rspi_data_in(struct rspi_data *rspi)
return data;
}
-static int rspi_data_out_in(struct rspi_data *rspi, u8 data)
+static int rspi_pio_transfer(struct rspi_data *rspi, const u8 *tx, u8 *rx,
+ unsigned int n)
{
- int ret;
-
- ret = rspi_data_out(rspi, data);
- if (ret < 0)
- return ret;
+ while (n-- > 0) {
+ if (tx) {
+ int ret = rspi_data_out(rspi, *tx++);
+ if (ret < 0)
+ return ret;
+ }
+ if (rx) {
+ int ret = rspi_data_in(rspi);
+ if (ret < 0)
+ return ret;
+ *rx++ = ret;
+ }
+ }
- return rspi_data_in(rspi);
+ return 0;
}
static void rspi_dma_complete(void *arg)
@@ -644,13 +653,11 @@ static int rspi_is_dma(const struct rspi_data *rspi, struct spi_transfer *t)
static int rspi_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer)
{
- int remain = xfer->len, ret;
- const u8 *tx_buf = xfer->tx_buf;
- u8 *rx_buf = xfer->rx_buf;
u8 spcr;
+ int ret;
spcr = rspi_read8(rspi, RSPI_SPCR);
- if (rx_buf) {
+ if (xfer->rx_buf) {
rspi_receive_init(rspi);
spcr &= ~SPCR_TXMD;
} else {
@@ -658,18 +665,9 @@ static int rspi_transfer_out_in(struct rspi_data *rspi,
}
rspi_write8(rspi, spcr, RSPI_SPCR);
- while (remain > 0) {
- ret = rspi_data_out(rspi, *tx_buf++);
- if (ret < 0)
- return ret;
- if (rx_buf) {
- ret = rspi_data_in(rspi);
- if (ret < 0)
- return ret;
- *rx_buf++ = ret;
- }
- remain--;
- }
+ ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
+ if (ret < 0)
+ return ret;
/* Wait for the last transmission */
rspi_wait_for_tx_empty(rspi);
@@ -694,19 +692,13 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
static int rspi_rz_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer)
{
- int remain = xfer->len, ret;
- const u8 *tx_buf = xfer->tx_buf;
- u8 *rx_buf = xfer->rx_buf;
+ int ret;
rspi_rz_receive_init(rspi);
- while (remain > 0) {
- ret = rspi_data_out_in(rspi, *tx_buf++);
- if (ret < 0)
- return ret;
- *rx_buf++ = ret;
- remain--;
- }
+ ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
+ if (ret < 0)
+ return ret;
/* Wait for the last transmission */
rspi_wait_for_tx_empty(rspi);
@@ -726,19 +718,13 @@ static int rspi_rz_transfer_one(struct spi_master *master,
static int qspi_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer)
{
- int remain = xfer->len, ret;
- const u8 *tx_buf = xfer->tx_buf;
- u8 *rx_buf = xfer->rx_buf;
+ int ret;
qspi_receive_init(rspi);
- while (remain > 0) {
- ret = rspi_data_out_in(rspi, *tx_buf++);
- if (ret < 0)
- return ret;
- *rx_buf++ = ret;
- remain--;
- }
+ ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
+ if (ret < 0)
+ return ret;
/* Wait for the last transmission */
rspi_wait_for_tx_empty(rspi);
@@ -748,15 +734,11 @@ static int qspi_transfer_out_in(struct rspi_data *rspi,
static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
{
- const u8 *buf = xfer->tx_buf;
- unsigned int i;
int ret;
- for (i = 0; i < xfer->len; i++) {
- ret = rspi_data_out(rspi, *buf++);
- if (ret < 0)
- return ret;
- }
+ ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len);
+ if (ret < 0)
+ return ret;
/* Wait for the last transmission */
rspi_wait_for_tx_empty(rspi);
@@ -766,18 +748,7 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
{
- u8 *buf = xfer->rx_buf;
- unsigned int i;
- int ret;
-
- for (i = 0; i < xfer->len; i++) {
- ret = rspi_data_in(rspi);
- if (ret < 0)
- return ret;
- *buf++ = ret;
- }
-
- return 0;
+ return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);
}
static int qspi_transfer_one(struct spi_master *master, struct spi_device *spi,
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 06/18] spi: rspi: Don't consider DMA configuration failures fatal
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (3 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 05/18] spi: rspi: Extract rspi_pio_transfer() Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 09/18] spi: rspi: SPI DMA core needs both RX and TX DMA to function Geert Uytterhoeven
` (7 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
Fall back to PIO if DMA configuration failed.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index fdbd46d0c570..94a99ec7d989 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -1190,10 +1190,8 @@ static int rspi_probe(struct platform_device *pdev)
}
ret = rspi_request_dma(rspi, pdev);
- if (ret < 0) {
- dev_err(&pdev->dev, "rspi_request_dma failed.\n");
- goto error3;
- }
+ if (ret < 0)
+ dev_warn(&pdev->dev, "DMA not available, using PIO\n");
ret = devm_spi_register_master(&pdev->dev, master);
if (ret < 0) {
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 09/18] spi: rspi: SPI DMA core needs both RX and TX DMA to function
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (4 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 06/18] spi: rspi: Don't consider DMA configuration failures fatal Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
[not found] ` <1401716301-29612-10-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
2014-06-02 13:38 ` [PATCH 12/18] spi: rspi: Pass sg_tables instead of spi_tranfer to rspi_*_dma() Geert Uytterhoeven
` (6 subsequent siblings)
12 siblings, 1 reply; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
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(-)
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;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 12/18] spi: rspi: Pass sg_tables instead of spi_tranfer to rspi_*_dma()
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (5 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 09/18] spi: rspi: SPI DMA core needs both RX and TX DMA to function Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 13/18] spi: rspi: Merge rspi_*_dma() into rspi_dma_transfer() Geert Uytterhoeven
` (5 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
The DMA routines only need access to the scatter-gather tables inside the
spi_transfer structures, hence just pass those.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 3dea8adfdcf3..bfa5e7e5df5a 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -463,13 +463,13 @@ static void rspi_dma_complete(void *arg)
wake_up_interruptible(&rspi->wait);
}
-static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
+static int rspi_send_dma(struct rspi_data *rspi, struct sg_table *tx)
{
struct dma_async_tx_descriptor *desc;
int ret;
- desc = dmaengine_prep_slave_sg(rspi->master->dma_tx, t->tx_sg.sgl,
- t->tx_sg.nents, DMA_TO_DEVICE,
+ desc = dmaengine_prep_slave_sg(rspi->master->dma_tx, tx->sgl,
+ tx->nents, DMA_TO_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc)
return -EIO;
@@ -530,21 +530,22 @@ static void qspi_receive_init(const struct rspi_data *rspi)
rspi_write8(rspi, 0, QSPI_SPBFCR);
}
-static int rspi_send_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
+static int rspi_send_receive_dma(struct rspi_data *rspi, struct sg_table *tx,
+ struct sg_table *rx)
{
struct dma_async_tx_descriptor *desc_tx, *desc_rx;
int ret;
/* prepare transmit transfer */
- desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, t->tx_sg.sgl,
- t->tx_sg.nents, DMA_TO_DEVICE,
+ desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, tx->sgl,
+ tx->nents, DMA_TO_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx)
return -EIO;
/* prepare receive transfer */
- desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx, t->rx_sg.sgl,
- t->rx_sg.nents, DMA_FROM_DEVICE,
+ desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx, rx->sgl,
+ rx->nents, DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_rx)
return -EIO;
@@ -616,9 +617,10 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
if (master->can_dma && __rspi_can_dma(rspi, xfer)) {
if (xfer->rx_buf)
- return rspi_send_receive_dma(rspi, xfer);
+ return rspi_send_receive_dma(rspi, &xfer->tx_sg,
+ &xfer->rx_sg);
else
- return rspi_send_dma(rspi, xfer);
+ return rspi_send_dma(rspi, &xfer->tx_sg);
}
ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 13/18] spi: rspi: Merge rspi_*_dma() into rspi_dma_transfer()
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (6 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 12/18] spi: rspi: Pass sg_tables instead of spi_tranfer to rspi_*_dma() Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 14/18] spi: rspi: Absorb rspi_rz_transfer_out_in() into rspi_rz_transfer_one() Geert Uytterhoeven
` (4 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
rspi_send_dma() and rspi_send_receive_dma() are very similar. Consolidate
into a single function rspi_dma_transfer(), and add missing checks for
dmaengine_submit() failures.
Both sg_table pointer parameters can be NULL, as RSPI supports TX-only
mode, and unidirectional DMA transfers will also be needed later for
Dual/Quad DMA support.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 139 ++++++++++++++++++++++---------------------------
1 file changed, 61 insertions(+), 78 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index bfa5e7e5df5a..c77cfe654b0e 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -463,30 +463,67 @@ static void rspi_dma_complete(void *arg)
wake_up_interruptible(&rspi->wait);
}
-static int rspi_send_dma(struct rspi_data *rspi, struct sg_table *tx)
+static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
+ struct sg_table *rx)
{
- struct dma_async_tx_descriptor *desc;
+ struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
+ u8 irq_mask = 0;
+ unsigned int other_irq = 0;
+ dma_cookie_t cookie;
int ret;
- desc = dmaengine_prep_slave_sg(rspi->master->dma_tx, tx->sgl,
- tx->nents, DMA_TO_DEVICE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc)
- return -EIO;
+ if (tx) {
+ desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
+ tx->sgl, tx->nents, DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc_tx)
+ return -EIO;
+
+ irq_mask |= SPCR_SPTIE;
+ }
+ if (rx) {
+ desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
+ rx->sgl, rx->nents, DMA_FROM_DEVICE,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc_rx)
+ return -EIO;
+
+ irq_mask |= SPCR_SPRIE;
+ }
/*
- * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
+ * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be
* called. So, this driver disables the IRQ while DMA transfer.
*/
- disable_irq(rspi->tx_irq);
+ if (tx)
+ disable_irq(other_irq = rspi->tx_irq);
+ if (rx && rspi->rx_irq != other_irq)
+ disable_irq(rspi->rx_irq);
- rspi_enable_irq(rspi, SPCR_SPTIE);
+ rspi_enable_irq(rspi, irq_mask);
rspi->dma_callbacked = 0;
- desc->callback = rspi_dma_complete;
- desc->callback_param = rspi;
- dmaengine_submit(desc);
- dma_async_issue_pending(rspi->master->dma_tx);
+ if (rx) {
+ desc_rx->callback = rspi_dma_complete;
+ desc_rx->callback_param = rspi;
+ cookie = dmaengine_submit(desc_rx);
+ if (dma_submit_error(cookie))
+ return cookie;
+ dma_async_issue_pending(rspi->master->dma_rx);
+ }
+ if (tx) {
+ if (rx) {
+ /* No callback */
+ desc_tx->callback = NULL;
+ } else {
+ desc_tx->callback = rspi_dma_complete;
+ desc_tx->callback_param = rspi;
+ }
+ cookie = dmaengine_submit(desc_tx);
+ if (dma_submit_error(cookie))
+ return cookie;
+ dma_async_issue_pending(rspi->master->dma_tx);
+ }
ret = wait_event_interruptible_timeout(rspi->wait,
rspi->dma_callbacked, HZ);
@@ -494,9 +531,14 @@ static int rspi_send_dma(struct rspi_data *rspi, struct sg_table *tx)
ret = 0;
else if (!ret)
ret = -ETIMEDOUT;
- rspi_disable_irq(rspi, SPCR_SPTIE);
- enable_irq(rspi->tx_irq);
+ rspi_disable_irq(rspi, irq_mask);
+
+ if (tx)
+ enable_irq(rspi->tx_irq);
+ if (rx && rspi->rx_irq != other_irq)
+ enable_irq(rspi->rx_irq);
+
return ret;
}
@@ -530,61 +572,6 @@ static void qspi_receive_init(const struct rspi_data *rspi)
rspi_write8(rspi, 0, QSPI_SPBFCR);
}
-static int rspi_send_receive_dma(struct rspi_data *rspi, struct sg_table *tx,
- struct sg_table *rx)
-{
- struct dma_async_tx_descriptor *desc_tx, *desc_rx;
- int ret;
-
- /* prepare transmit transfer */
- desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, tx->sgl,
- tx->nents, DMA_TO_DEVICE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc_tx)
- return -EIO;
-
- /* prepare receive transfer */
- desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx, rx->sgl,
- rx->nents, DMA_FROM_DEVICE,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc_rx)
- return -EIO;
-
- /*
- * DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
- * called. So, this driver disables the IRQ while DMA transfer.
- */
- disable_irq(rspi->tx_irq);
- if (rspi->rx_irq != rspi->tx_irq)
- disable_irq(rspi->rx_irq);
-
- rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
- rspi->dma_callbacked = 0;
-
- desc_rx->callback = rspi_dma_complete;
- desc_rx->callback_param = rspi;
- dmaengine_submit(desc_rx);
- dma_async_issue_pending(rspi->master->dma_rx);
-
- desc_tx->callback = NULL; /* No callback */
- dmaengine_submit(desc_tx);
- dma_async_issue_pending(rspi->master->dma_tx);
-
- ret = wait_event_interruptible_timeout(rspi->wait,
- rspi->dma_callbacked, HZ);
- if (ret > 0 && rspi->dma_callbacked)
- ret = 0;
- else if (!ret)
- ret = -ETIMEDOUT;
- rspi_disable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
-
- enable_irq(rspi->tx_irq);
- if (rspi->rx_irq != rspi->tx_irq)
- enable_irq(rspi->rx_irq);
-
- return ret;
-}
-
static bool __rspi_can_dma(const struct rspi_data *rspi,
const struct spi_transfer *xfer)
{
@@ -615,13 +602,9 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
}
rspi_write8(rspi, spcr, RSPI_SPCR);
- if (master->can_dma && __rspi_can_dma(rspi, xfer)) {
- if (xfer->rx_buf)
- return rspi_send_receive_dma(rspi, &xfer->tx_sg,
- &xfer->rx_sg);
- else
- return rspi_send_dma(rspi, &xfer->tx_sg);
- }
+ if (master->can_dma && __rspi_can_dma(rspi, xfer))
+ return rspi_dma_transfer(rspi, &xfer->tx_sg,
+ xfer->rx_buf ? &xfer->rx_sg : NULL);
ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
if (ret < 0)
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 14/18] spi: rspi: Absorb rspi_rz_transfer_out_in() into rspi_rz_transfer_one()
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (7 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 13/18] spi: rspi: Merge rspi_*_dma() into rspi_dma_transfer() Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 15/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (3 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index c77cfe654b0e..b7f8be81423b 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -616,9 +616,11 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
return 0;
}
-static int rspi_rz_transfer_out_in(struct rspi_data *rspi,
- struct spi_transfer *xfer)
+static int rspi_rz_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;
rspi_rz_receive_init(rspi);
@@ -633,15 +635,6 @@ static int rspi_rz_transfer_out_in(struct rspi_data *rspi,
return 0;
}
-static int rspi_rz_transfer_one(struct spi_master *master,
- struct spi_device *spi,
- struct spi_transfer *xfer)
-{
- struct rspi_data *rspi = spi_master_get_devdata(master);
-
- return rspi_rz_transfer_out_in(rspi, xfer);
-}
-
static int qspi_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer)
{
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 15/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (8 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 14/18] spi: rspi: Absorb rspi_rz_transfer_out_in() into rspi_rz_transfer_one() Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
` (2 subsequent siblings)
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
Enable DMA support for QSPI on R-Car Gen2, for Single, Dual, and Quad SPI
Transfers.
Performance figures for reading from a QSPI FLASH driven at 24.375 MHz
on r8a7791/koelsch:
- Single: 1.1 Mbps PIO, 23 Mbps DMA
- Dual : 12.7 Mbps PIO, 48 Mbps DMA
- Quad : 13 Mbps PIO, 70 Mbps DMA
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index b7f8be81423b..bec81470dd9c 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -642,6 +642,9 @@ static int qspi_transfer_out_in(struct rspi_data *rspi,
qspi_receive_init(rspi);
+ if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
+ return rspi_dma_transfer(rspi, &xfer->tx_sg, &xfer->rx_sg);
+
ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
if (ret < 0)
return ret;
@@ -656,6 +659,9 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
{
int ret;
+ if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
+ return rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
+
ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len);
if (ret < 0)
return ret;
@@ -668,6 +674,9 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
{
+ if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
+ return rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
+
return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);
}
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
[parent not found: <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>]
* [PATCH 04/18] spi: rspi: Use core SPI_MASTER_MUST_[RT]X handling
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 07/18] spi: rspi: Extract rspi_request_dma_chan() Geert Uytterhoeven
` (5 subsequent siblings)
6 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, 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 <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
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 3bd06fd9af47..ece8f6037943 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");
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 07/18] spi: rspi: Extract rspi_request_dma_chan()
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
2014-06-02 13:38 ` [PATCH 04/18] spi: rspi: Use core SPI_MASTER_MUST_[RT]X handling Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 08/18] spi: rspi: Remove unneeded resource test in DMA setup Geert Uytterhoeven
` (4 subsequent siblings)
6 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven
Setup of the receive and transmit DMA channels is very similar, so let's
consolidate.
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
drivers/spi/spi-rspi.c | 89 +++++++++++++++++++++++++++++++-------------------
1 file changed, 55 insertions(+), 34 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 94a99ec7d989..0a7a2d618f0f 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -942,52 +942,73 @@ static irqreturn_t rspi_irq_tx(int irq, void *_sr)
return 0;
}
-static int rspi_request_dma(struct rspi_data *rspi,
- struct platform_device *pdev)
+static struct dma_chan *rspi_request_dma_chan(struct device *dev,
+ enum dma_transfer_direction dir,
+ unsigned int id,
+ dma_addr_t port_addr)
{
- const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dma_cap_mask_t mask;
+ struct dma_chan *chan;
struct dma_slave_config cfg;
int ret;
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ chan = dma_request_channel(mask, shdma_chan_filter,
+ (void *)(unsigned long)id);
+ if (!chan) {
+ dev_warn(dev, "dma_request_channel failed\n");
+ return NULL;
+ }
+
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.slave_id = id;
+ cfg.direction = dir;
+ if (dir == DMA_MEM_TO_DEV)
+ cfg.dst_addr = port_addr;
+ else
+ cfg.src_addr = port_addr;
+
+ ret = dmaengine_slave_config(chan, &cfg);
+ if (ret) {
+ dev_warn(dev, "dmaengine_slave_config failed %d\n", ret);
+ dma_release_channel(chan);
+ return NULL;
+ }
+
+ return chan;
+}
+
+static int rspi_request_dma(struct rspi_data *rspi,
+ struct platform_device *pdev)
+{
+ const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
if (!res || !rspi_pd)
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) {
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
- (void *)rspi_pd->dma_rx_id);
- if (rspi->chan_rx) {
- cfg.slave_id = rspi_pd->dma_rx_id;
- cfg.direction = DMA_DEV_TO_MEM;
- cfg.dst_addr = 0;
- cfg.src_addr = res->start + RSPI_SPDR;
- ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
- if (!ret)
- dev_info(&pdev->dev, "Use DMA when rx.\n");
- else
- return ret;
- }
+ rspi->chan_rx = rspi_request_dma_chan(&pdev->dev,
+ DMA_DEV_TO_MEM,
+ rspi_pd->dma_rx_id,
+ res->start + RSPI_SPDR);
+ if (!rspi->chan_rx)
+ return -ENODEV;
+
+ dev_info(&pdev->dev, "Use DMA when rx.\n");
}
if (rspi_pd->dma_tx_id) {
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
- (void *)rspi_pd->dma_tx_id);
- if (rspi->chan_tx) {
- cfg.slave_id = rspi_pd->dma_tx_id;
- cfg.direction = DMA_MEM_TO_DEV;
- cfg.dst_addr = res->start + RSPI_SPDR;
- cfg.src_addr = 0;
- ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
- if (!ret)
- dev_info(&pdev->dev, "Use DMA when tx\n");
- else
- return ret;
- }
+ rspi->chan_tx = rspi_request_dma_chan(&pdev->dev,
+ DMA_MEM_TO_DEV,
+ rspi_pd->dma_tx_id,
+ res->start + RSPI_SPDR);
+ if (!rspi->chan_tx)
+ return -ENODEV;
+
+ dev_info(&pdev->dev, "Use DMA when tx\n");
}
return 0;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 08/18] spi: rspi: Remove unneeded resource test in DMA setup
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
2014-06-02 13:38 ` [PATCH 04/18] spi: rspi: Use core SPI_MASTER_MUST_[RT]X handling Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 07/18] spi: rspi: Extract rspi_request_dma_chan() Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 10/18] spi: rspi: Use SPI core DMA mapping framework Geert Uytterhoeven
` (3 subsequent siblings)
6 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven
The resource is know to exist, as rspi_probe() already mapped it.
Remove the test, and just pass the resource.
Pass the device pointer instead of the platform device pointer, as the
latter is no longer needed.
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
drivers/spi/spi-rspi.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 0a7a2d618f0f..1ec51cb00203 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -980,35 +980,32 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
return chan;
}
-static int rspi_request_dma(struct rspi_data *rspi,
- struct platform_device *pdev)
+static int rspi_request_dma(struct device *dev, struct rspi_data *rspi,
+ const struct resource *res)
{
- const struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
- if (!res || !rspi_pd)
+ if (!rspi_pd)
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(&pdev->dev,
- DMA_DEV_TO_MEM,
+ 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(&pdev->dev, "Use DMA when rx.\n");
+ dev_info(dev, "Use DMA when rx.\n");
}
if (rspi_pd->dma_tx_id) {
- rspi->chan_tx = rspi_request_dma_chan(&pdev->dev,
- DMA_MEM_TO_DEV,
+ 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(&pdev->dev, "Use DMA when tx\n");
+ dev_info(dev, "Use DMA when tx\n");
}
return 0;
@@ -1210,7 +1207,7 @@ static int rspi_probe(struct platform_device *pdev)
goto error2;
}
- ret = rspi_request_dma(rspi, pdev);
+ ret = rspi_request_dma(&pdev->dev, rspi, res);
if (ret < 0)
dev_warn(&pdev->dev, "DMA not available, using PIO\n");
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 10/18] spi: rspi: Use SPI core DMA mapping framework
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
` (2 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 08/18] spi: rspi: Remove unneeded resource test in DMA setup Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 11/18] spi: rspi: Move RSPI-specific setup out of DMA routines Geert Uytterhoeven
` (2 subsequent siblings)
6 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven
Use the SPI core DMA mapping framework instead of our own.
If available, DMA is used for transfers larger than the FIFO size
(8 or 32 bytes).
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
drivers/spi/spi-rspi.c | 140 ++++++++++++++++++-------------------------------
1 file changed, 50 insertions(+), 90 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 7b993f75a3cf..753ac7bdfd55 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -195,10 +195,6 @@ struct rspi_data {
int rx_irq, tx_irq;
const struct spi_ops *ops;
- /* for dmaengine */
- struct dma_chan *chan_tx;
- struct dma_chan *chan_rx;
-
unsigned dma_callbacked:1;
unsigned byte_access:1;
};
@@ -251,6 +247,7 @@ struct spi_ops {
struct spi_transfer *xfer);
u16 mode_bits;
u16 flags;
+ u16 fifo_size;
};
/*
@@ -466,39 +463,16 @@ static void rspi_dma_complete(void *arg)
wake_up_interruptible(&rspi->wait);
}
-static int rspi_dma_map_sg(struct scatterlist *sg, const void *buf,
- unsigned len, struct dma_chan *chan,
- enum dma_transfer_direction dir)
-{
- sg_init_table(sg, 1);
- sg_set_buf(sg, buf, len);
- sg_dma_len(sg) = len;
- return dma_map_sg(chan->device->dev, sg, 1, dir);
-}
-
-static void rspi_dma_unmap_sg(struct scatterlist *sg, struct dma_chan *chan,
- enum dma_transfer_direction dir)
-{
- dma_unmap_sg(chan->device->dev, sg, 1, dir);
-}
-
static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
{
- struct scatterlist sg;
- const void *buf = t->tx_buf;
struct dma_async_tx_descriptor *desc;
- unsigned int len = t->len;
- int ret = 0;
-
- if (!rspi_dma_map_sg(&sg, buf, len, rspi->chan_tx, DMA_TO_DEVICE))
- return -EFAULT;
+ int ret;
- desc = dmaengine_prep_slave_sg(rspi->chan_tx, &sg, 1, DMA_TO_DEVICE,
+ desc = dmaengine_prep_slave_sg(rspi->master->dma_tx, t->tx_sg.sgl,
+ t->tx_sg.nents, DMA_TO_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- ret = -EIO;
- goto end;
- }
+ if (!desc)
+ return -EIO;
/*
* DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
@@ -513,7 +487,7 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
desc->callback = rspi_dma_complete;
desc->callback_param = rspi;
dmaengine_submit(desc);
- dma_async_issue_pending(rspi->chan_tx);
+ dma_async_issue_pending(rspi->master->dma_tx);
ret = wait_event_interruptible_timeout(rspi->wait,
rspi->dma_callbacked, HZ);
@@ -524,9 +498,6 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
rspi_disable_irq(rspi, SPCR_SPTIE);
enable_irq(rspi->tx_irq);
-
-end:
- rspi_dma_unmap_sg(&sg, rspi->chan_tx, DMA_TO_DEVICE);
return ret;
}
@@ -562,39 +533,22 @@ static void qspi_receive_init(const struct rspi_data *rspi)
static int rspi_send_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
{
- 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;
+ int ret;
/* 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_tx) {
- ret = -EIO;
- goto end_tx_mapped;
- }
+ desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, t->tx_sg.sgl,
+ t->tx_sg.nents, DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc_tx)
+ return -EIO;
/* prepare receive transfer */
- if (!rspi_dma_map_sg(&sg_rx, rx_buf, len, rspi->chan_rx,
- DMA_FROM_DEVICE)) {
- ret = -EFAULT;
- goto end_tx_mapped;
-
- }
- desc_rx = dmaengine_prep_slave_sg(rspi->chan_rx, &sg_rx, 1,
- DMA_FROM_DEVICE,
+ desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx, t->rx_sg.sgl,
+ t->rx_sg.nents, DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc_rx) {
- ret = -EIO;
- goto end;
- }
+ if (!desc_rx)
+ return -EIO;
rspi_receive_init(rspi);
@@ -613,11 +567,11 @@ static int rspi_send_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
desc_rx->callback = rspi_dma_complete;
desc_rx->callback_param = rspi;
dmaengine_submit(desc_rx);
- dma_async_issue_pending(rspi->chan_rx);
+ dma_async_issue_pending(rspi->master->dma_rx);
desc_tx->callback = NULL; /* No callback */
dmaengine_submit(desc_tx);
- dma_async_issue_pending(rspi->chan_tx);
+ dma_async_issue_pending(rspi->master->dma_tx);
ret = wait_event_interruptible_timeout(rspi->wait,
rspi->dma_callbacked, HZ);
@@ -631,19 +585,21 @@ static int rspi_send_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
if (rspi->rx_irq != rspi->tx_irq)
enable_irq(rspi->rx_irq);
-end:
- 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)
+static bool __rspi_can_dma(const struct rspi_data *rspi,
+ const struct spi_transfer *xfer)
{
- if (rspi->chan_tx)
- return 1;
+ return xfer->len > rspi->ops->fifo_size;
+}
- return 0;
+static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
+ struct spi_transfer *xfer)
+{
+ struct rspi_data *rspi = spi_master_get_devdata(master);
+
+ return __rspi_can_dma(rspi, xfer);
}
static int rspi_transfer_out_in(struct rspi_data *rspi,
@@ -676,7 +632,7 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
{
struct rspi_data *rspi = spi_master_get_devdata(master);
- if (!rspi_is_dma(rspi, xfer))
+ if (!master->can_dma || !__rspi_can_dma(rspi, xfer))
return rspi_transfer_out_in(rspi, xfer);
if (xfer->rx_buf)
@@ -976,7 +932,7 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
return chan;
}
-static int rspi_request_dma(struct device *dev, struct rspi_data *rspi,
+static int rspi_request_dma(struct device *dev, struct spi_master *master,
const struct resource *res)
{
const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
@@ -984,31 +940,32 @@ static int rspi_request_dma(struct device *dev, struct rspi_data *rspi,
if (!rspi_pd || !rspi_pd->dma_rx_id || !rspi_pd->dma_tx_id)
return 0; /* The driver assumes no error. */
- 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)
+ master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM,
+ rspi_pd->dma_rx_id,
+ res->start + RSPI_SPDR);
+ if (!master->dma_rx)
return -ENODEV;
- 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;
+ master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV,
+ rspi_pd->dma_tx_id,
+ res->start + RSPI_SPDR);
+ if (!master->dma_tx) {
+ dma_release_channel(master->dma_rx);
+ master->dma_rx = NULL;
return -ENODEV;
}
+ master->can_dma = rspi_can_dma;
dev_info(dev, "DMA available");
return 0;
}
static void rspi_release_dma(struct rspi_data *rspi)
{
- if (rspi->chan_tx)
- dma_release_channel(rspi->chan_tx);
- if (rspi->chan_rx)
- dma_release_channel(rspi->chan_rx);
+ if (rspi->master->dma_tx)
+ dma_release_channel(rspi->master->dma_tx);
+ if (rspi->master->dma_rx)
+ dma_release_channel(rspi->master->dma_rx);
}
static int rspi_remove(struct platform_device *pdev)
@@ -1026,6 +983,7 @@ static const struct spi_ops rspi_ops = {
.transfer_one = rspi_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
.flags = SPI_MASTER_MUST_TX,
+ .fifo_size = 8,
};
static const struct spi_ops rspi_rz_ops = {
@@ -1033,6 +991,7 @@ static const struct spi_ops rspi_rz_ops = {
.transfer_one = rspi_rz_transfer_one,
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
.flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
+ .fifo_size = 8, /* 8 for TX, 32 for RX */
};
static const struct spi_ops qspi_ops = {
@@ -1042,6 +1001,7 @@ static const struct spi_ops qspi_ops = {
SPI_TX_DUAL | SPI_TX_QUAD |
SPI_RX_DUAL | SPI_RX_QUAD,
.flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX,
+ .fifo_size = 32,
};
#ifdef CONFIG_OF
@@ -1199,7 +1159,7 @@ static int rspi_probe(struct platform_device *pdev)
goto error2;
}
- ret = rspi_request_dma(&pdev->dev, rspi, res);
+ ret = rspi_request_dma(&pdev->dev, master, res);
if (ret < 0)
dev_warn(&pdev->dev, "DMA not available, using PIO\n");
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 11/18] spi: rspi: Move RSPI-specific setup out of DMA routines
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
` (3 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 10/18] spi: rspi: Use SPI core DMA mapping framework Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 16/18] spi: rspi: Add DMA support for RSPI on RZ/A1H Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 18/18] [RFC] spi: rspi: Add DT support to DMA setup Geert Uytterhoeven
6 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven
Refactor RSPI (on SH) DMA handling to make it reusable for other RSPI
implementations:
- Call the DMA routines after configuring the TX Mode bit and after
calling rspi_receive_init(), so these RSPI-specific operations can be
removed from the DMA routines,
- Absorb rspi_transfer_out_in() into rspi_transfer_one().
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
drivers/spi/spi-rspi.c | 30 ++++++++++--------------------
1 file changed, 10 insertions(+), 20 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 753ac7bdfd55..3dea8adfdcf3 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -480,7 +480,6 @@ static int rspi_send_dma(struct rspi_data *rspi, struct spi_transfer *t)
*/
disable_irq(rspi->tx_irq);
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | SPCR_TXMD, RSPI_SPCR);
rspi_enable_irq(rspi, SPCR_SPTIE);
rspi->dma_callbacked = 0;
@@ -550,8 +549,6 @@ static int rspi_send_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
if (!desc_rx)
return -EIO;
- rspi_receive_init(rspi);
-
/*
* DMAC needs SPTIE, but if SPTIE is set, this IRQ routine will be
* called. So, this driver disables the IRQ while DMA transfer.
@@ -560,7 +557,6 @@ static int rspi_send_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
if (rspi->rx_irq != rspi->tx_irq)
disable_irq(rspi->rx_irq);
- rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_TXMD, RSPI_SPCR);
rspi_enable_irq(rspi, SPCR_SPTIE | SPCR_SPRIE);
rspi->dma_callbacked = 0;
@@ -602,9 +598,10 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
return __rspi_can_dma(rspi, xfer);
}
-static int rspi_transfer_out_in(struct rspi_data *rspi,
- struct spi_transfer *xfer)
+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);
u8 spcr;
int ret;
@@ -617,6 +614,13 @@ static int rspi_transfer_out_in(struct rspi_data *rspi,
}
rspi_write8(rspi, spcr, RSPI_SPCR);
+ if (master->can_dma && __rspi_can_dma(rspi, xfer)) {
+ if (xfer->rx_buf)
+ return rspi_send_receive_dma(rspi, xfer);
+ else
+ return rspi_send_dma(rspi, xfer);
+ }
+
ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
if (ret < 0)
return ret;
@@ -627,20 +631,6 @@ static int rspi_transfer_out_in(struct rspi_data *rspi,
return 0;
}
-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);
-
- if (!master->can_dma || !__rspi_can_dma(rspi, xfer))
- return rspi_transfer_out_in(rspi, xfer);
-
- if (xfer->rx_buf)
- 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,
struct spi_transfer *xfer)
{
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 16/18] spi: rspi: Add DMA support for RSPI on RZ/A1H
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
` (4 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 11/18] spi: rspi: Move RSPI-specific setup out of DMA routines Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 13:38 ` [PATCH 18/18] [RFC] spi: rspi: Add DT support to DMA setup Geert Uytterhoeven
6 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven
Enable DMA support for RSPI on r7s72100 (RZ/A1H).
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
---
This is untested, due to lack of DMA integration code on r7s72100/genmai.
---
drivers/spi/spi-rspi.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index bec81470dd9c..4bc4138e002b 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -625,6 +625,9 @@ static int rspi_rz_transfer_one(struct spi_master *master,
rspi_rz_receive_init(rspi);
+ if (master->can_dma && __rspi_can_dma(rspi, xfer))
+ return rspi_dma_transfer(rspi, &xfer->tx_sg, &xfer->rx_sg);
+
ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
if (ret < 0)
return ret;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH 18/18] [RFC] spi: rspi: Add DT support to DMA setup
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
` (5 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 16/18] spi: rspi: Add DMA support for RSPI on RZ/A1H Geert Uytterhoeven
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-02 14:54 ` Mark Brown
6 siblings, 1 reply; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, Geert Uytterhoeven,
devicetree-u79uwXL29TY76Z2rM5mHXA
Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
The format of the DMA specifiers depends on the DT bindings for SHDMA,
which are still under development.
---
Documentation/devicetree/bindings/spi/spi-rspi.txt | 6 ++++
drivers/spi/spi-rspi.c | 37 ++++++++++++++--------
2 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/Documentation/devicetree/bindings/spi/spi-rspi.txt b/Documentation/devicetree/bindings/spi/spi-rspi.txt
index d57d82a74054..a274073bd41d 100644
--- a/Documentation/devicetree/bindings/spi/spi-rspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-rspi.txt
@@ -30,6 +30,9 @@ Required properties:
Optional properties:
- clocks : Must contain a reference to the functional clock.
+- dmas : Must contain a list of two references to DMA specifiers,
+ one for transmission, and one for reception.
+- dma-names : Must contain a list of two DMA names, "tx" and "rx".
Pinctrl properties might be needed, too. See
Documentation/devicetree/bindings/pinctrl/renesas,*.
@@ -58,4 +61,7 @@ Examples:
num-cs = <1>;
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&dma0 R8A7791_DMA_QSPI_TX CHCR_TX_8BIT>,
+ <&dma0 R8A7791_DMA_QSPI_RX CHCR_RX_8BIT>;
+ dma-names = "tx", "rx";
};
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 10112745bb17..16de9ad60d74 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -874,10 +874,11 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- chan = dma_request_channel(mask, shdma_chan_filter,
- (void *)(unsigned long)id);
+ chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+ (void *)(unsigned long)id, dev,
+ dir == DMA_MEM_TO_DEV ? "tx" : "rx");
if (!chan) {
- dev_warn(dev, "dma_request_channel failed\n");
+ dev_warn(dev, "dma_request_slave_channel_compat failed\n");
return NULL;
}
@@ -903,22 +904,30 @@ static int rspi_request_dma(struct device *dev, struct spi_master *master,
const struct resource *res)
{
const struct rspi_plat_data *rspi_pd = dev_get_platdata(dev);
+ unsigned int dma_tx_id, dma_rx_id;
+
+ if (dev->of_node) {
+ /* In the OF case we will get the slave IDs from the DT */
+ dma_tx_id = 0;
+ dma_rx_id = 0;
+ } else if (rspi_pd && rspi_pd->dma_tx_id && rspi_pd->dma_rx_id) {
+ dma_tx_id = rspi_pd->dma_tx_id;
+ dma_rx_id = rspi_pd->dma_rx_id;
+ } else {
+ /* The driver assumes no error. */
+ return 0;
+ }
- if (!rspi_pd || !rspi_pd->dma_rx_id || !rspi_pd->dma_tx_id)
- return 0; /* The driver assumes no error. */
-
- master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM,
- rspi_pd->dma_rx_id,
+ master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id,
res->start + RSPI_SPDR);
- if (!master->dma_rx)
+ if (!master->dma_tx)
return -ENODEV;
- master->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV,
- rspi_pd->dma_tx_id,
+ master->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id,
res->start + RSPI_SPDR);
- if (!master->dma_tx) {
- dma_release_channel(master->dma_rx);
- master->dma_rx = NULL;
+ if (!master->dma_rx) {
+ dma_release_channel(master->dma_tx);
+ master->dma_tx = NULL;
return -ENODEV;
}
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 18/18] [RFC] spi: rspi: Add DT support to DMA setup
2014-06-02 13:38 ` [PATCH 18/18] [RFC] spi: rspi: Add DT support to DMA setup Geert Uytterhoeven
@ 2014-06-02 14:54 ` Mark Brown
[not found] ` <20140602145447.GJ31751-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
0 siblings, 1 reply; 25+ messages in thread
From: Mark Brown @ 2014-06-02 14:54 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh, devicetree
[-- Attachment #1: Type: text/plain, Size: 470 bytes --]
On Mon, Jun 02, 2014 at 03:38:20PM +0200, Geert Uytterhoeven wrote:
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: devicetree@vger.kernel.org
> ---
> The format of the DMA specifiers depends on the DT bindings for SHDMA,
> which are still under development.
This looks fine to me, can you resend when the DMA specifiers for the
controller are resolved? I've applied everything up to here, it all
looks good especially the performance improvement.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 17/18] spi: rspi: Extract rspi_common_transfer()
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (10 preceding siblings ...)
[not found] ` <1401716301-29612-1-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
@ 2014-06-02 13:38 ` Geert Uytterhoeven
2014-06-05 5:58 ` [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Yoshihiro Shimoda
12 siblings, 0 replies; 25+ messages in thread
From: Geert Uytterhoeven @ 2014-06-02 13:38 UTC (permalink / raw)
To: Mark Brown
Cc: Yoshihiro Shimoda, Magnus Damm, linux-spi, linux-sh,
Geert Uytterhoeven
Extract the common parts of rspi_transfer_one(), rspi_rz_transfer_one(),
and qspi_transfer_out_in() into the new function rspi_common_transfer().
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/spi/spi-rspi.c | 61 ++++++++++++++++++++------------------------------
1 file changed, 24 insertions(+), 37 deletions(-)
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 4bc4138e002b..10112745bb17 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -586,12 +586,32 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi,
return __rspi_can_dma(rspi, xfer);
}
+static int rspi_common_transfer(struct rspi_data *rspi,
+ struct spi_transfer *xfer)
+{
+ int ret;
+
+ if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
+ /* rx_buf can be NULL on RSPI on SH in TX-only Mode */
+ return rspi_dma_transfer(rspi, &xfer->tx_sg,
+ xfer->rx_buf ? &xfer->rx_sg : NULL);
+ }
+
+ ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
+ if (ret < 0)
+ return ret;
+
+ /* Wait for the last transmission */
+ rspi_wait_for_tx_empty(rspi);
+
+ return 0;
+}
+
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);
u8 spcr;
- int ret;
spcr = rspi_read8(rspi, RSPI_SPCR);
if (xfer->rx_buf) {
@@ -602,18 +622,7 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi,
}
rspi_write8(rspi, spcr, RSPI_SPCR);
- if (master->can_dma && __rspi_can_dma(rspi, xfer))
- return rspi_dma_transfer(rspi, &xfer->tx_sg,
- xfer->rx_buf ? &xfer->rx_sg : NULL);
-
- ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
- if (ret < 0)
- return ret;
-
- /* Wait for the last transmission */
- rspi_wait_for_tx_empty(rspi);
-
- return 0;
+ return rspi_common_transfer(rspi, xfer);
}
static int rspi_rz_transfer_one(struct spi_master *master,
@@ -625,37 +634,15 @@ static int rspi_rz_transfer_one(struct spi_master *master,
rspi_rz_receive_init(rspi);
- if (master->can_dma && __rspi_can_dma(rspi, xfer))
- return rspi_dma_transfer(rspi, &xfer->tx_sg, &xfer->rx_sg);
-
- ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
- if (ret < 0)
- return ret;
-
- /* Wait for the last transmission */
- rspi_wait_for_tx_empty(rspi);
-
- return 0;
+ return rspi_common_transfer(rspi, xfer);
}
static int qspi_transfer_out_in(struct rspi_data *rspi,
struct spi_transfer *xfer)
{
- int ret;
-
qspi_receive_init(rspi);
- if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
- return rspi_dma_transfer(rspi, &xfer->tx_sg, &xfer->rx_sg);
-
- ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
- if (ret < 0)
- return ret;
-
- /* Wait for the last transmission */
- rspi_wait_for_tx_empty(rspi);
-
- return 0;
+ return rspi_common_transfer(rspi, xfer);
}
static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
--
1.9.1
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2
2014-06-02 13:38 [PATCH 00/18] spi: rspi: Add DMA support for QSPI on R-Car Gen2 Geert Uytterhoeven
` (11 preceding siblings ...)
2014-06-02 13:38 ` [PATCH 17/18] spi: rspi: Extract rspi_common_transfer() Geert Uytterhoeven
@ 2014-06-05 5:58 ` Yoshihiro Shimoda
12 siblings, 0 replies; 25+ messages in thread
From: Yoshihiro Shimoda @ 2014-06-05 5:58 UTC (permalink / raw)
To: Geert Uytterhoeven, Mark Brown
Cc: Magnus Damm, linux-spi@vger.kernel.org, linux-sh@vger.kernel.org
Hi Geert-san,
Thank you for the patches!
(2014/06/02 22:38), Geert Uytterhoeven wrote:
> This patch series refactors the Renesas SPI driver and adds DMA support
> using the SPI DMA framework for QSPI on R-Car Gen2, for Single, Dual, and
> Quad SPI Transfers.
> It also adds DMA support for RZ/A1H, but this was untested.
>
> Apart from refactorings that don't change behavior:
> - [02/18] reverts a (harmless?) behavioral change for RSPI on SH,
> - [03/18] removes 16-bit DMA support, which has no in-tree users.
> 16-bit DMA support requires using a double-sized buffer to
> accomodate the interleaved data format.
> If there's a strong requirement to keep this, I think it's best
> to re-add support after this series.
I agree with you.
(I wrote this 16-bit DMA function. But, as you know, nobody uses this function.)
< snip >
> Documentation/devicetree/bindings/spi/spi-rspi.txt | 6 +
> drivers/spi/spi-rspi.c | 604 ++++++++-------------
> include/linux/spi/rspi.h | 2 -
> 3 files changed, 228 insertions(+), 384 deletions(-)
All of the patch series:
Acked-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Best regards,
Yoshihiro Shimoda
^ permalink raw reply [flat|nested] 25+ messages in thread