* [PATCH v2 00/15] spi/xilinx: Speed-up
@ 2015-01-28 12:23 Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 01/15] spi/xilinx: Simplify spi_fill_tx_fifo Ricardo Ribalda Delgado
` (15 more replies)
0 siblings, 16 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
This set of patches has been developed after using the core to access a spi
nor flash. The initial performance was not as desired. The following changes
have been done.
-This series of patches add driver support for hardware implemented modes:
LSB_FIRS, LOOP and CS_HIGH.
-There is support for irq less operations.
-The buffer size of the core is detected at probe time, speeding up the
operations.
-Code has been simplify and cleaned
This are the results, before and after the patchet
Original
root@qt5022:~# dd if=/dev/mtd0 of=/dev/null
16384+0 records in
16384+0 records out
8388608 bytes (8.4 MB) copied, 117.985 s, 71.1 kB/s
37: 107 82853 Xilinx INTC Level 1 b0010000.spi-flash
After patchset (irq):
root@qt5022:~# dd if=/dev/mtd0 of=/dev/null
16384+0 records in
16384+0 records out
8388608 bytes (8.4 MB) copied, 49.009 s, 171 kB/s
After patchset (polling):
root@qt5022:~# dd if=/dev/mtd0 of=/dev/null
16384+0 records in
16384+0 records out
8388608 bytes (8.4 MB) copied, 41.2526 s, 203 kB/s
IRQS: ZERO
Changelog v2:
-Add patch spi/xilinx: Use polling mode on small transfers
-Merge spi/xilinx: Reset core before buffer_size detection with spi/xilinx:
Simplify spi_fill_tx_fifo
-Fix codestyle on Remove rx_fn and tx_fn pointer
-Remove already merged patches
Ricardo Ribalda Delgado (15):
spi/xilinx: Simplify spi_fill_tx_fifo
spi/xilinx: Leave the IRQ always enabled.
spi/xilinx: Code cleanup
spi/xilinx: Use cached value of register
spi/xilinx: Support cores with no interrupt
spi/xilinx: Do not inhibit transmission in polling mode
spi/xilinx: Support for spi mode CS_HIGH
spi/xilinx: Remove rx_fn and tx_fn pointer
spi/xilinx: Make spi_tx and spi_rx simmetric
spi/xilinx: Convert remainding_bytes in remaining words
spi/xilinx: Convert bits_per_word in bytes_per_word
spi/xilinx: Remove iowrite/ioread wrappers
spi/xilinx: Remove remaining_words driver data variable
spi/xilinx: Check number of slaves range
spi/xilinx: Use polling mode on small transfers
drivers/spi/spi-xilinx.c | 337 ++++++++++++++++++++++-------------------------
1 file changed, 157 insertions(+), 180 deletions(-)
--
2.1.4
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 01/15] spi/xilinx: Simplify spi_fill_tx_fifo
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 02/15] spi/xilinx: Leave the IRQ always enabled Ricardo Ribalda Delgado
` (14 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
Instead of checking the TX_FULL flag for every transaction, find out the
size of the buffer at probe time and use it.
To avoid situations where the core had some data on the buffer before
initialization, the core is reseted before the buffer size is detected
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
v2: Changes Requested by Mark Brown <broonie@kernel.org>
Before discovering the buffer size, reset the core.
drivers/spi/spi-xilinx.c | 46 +++++++++++++++++++++++++++++++++-------------
1 file changed, 33 insertions(+), 13 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 416b227..1890af8 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -88,6 +88,7 @@ struct xilinx_spi {
const u8 *tx_ptr; /* pointer in the Rx buffer */
int remaining_bytes; /* the number of bytes left to transfer */
u8 bits_per_word;
+ int buffer_size; /* buffer size in words */
unsigned int (*read_fn)(void __iomem *);
void (*write_fn)(u32, void __iomem *);
void (*tx_fn)(struct xilinx_spi *);
@@ -221,24 +222,16 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
return 0;
}
-static int xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
+static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi, int n_words)
{
- u8 sr;
- int n_words = 0;
+ xspi->remaining_bytes -= n_words * xspi->bits_per_word / 8;
- /* Fill the Tx FIFO with as many bytes as possible */
- sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
- while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
+ while (n_words--)
if (xspi->tx_ptr)
xspi->tx_fn(xspi);
else
xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
- xspi->remaining_bytes -= xspi->bits_per_word / 8;
- sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
- n_words++;
- }
-
- return n_words;
+ return;
}
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
@@ -265,7 +258,10 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
u16 cr;
int n_words;
- n_words = xilinx_spi_fill_tx_fifo(xspi);
+ n_words = (xspi->remaining_bytes * 8) / xspi->bits_per_word;
+ n_words = min(n_words, xspi->buffer_size);
+
+ xilinx_spi_fill_tx_fifo(xspi, n_words);
/* Start the transfer by not inhibiting the transmitter any
* longer
@@ -322,6 +318,28 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi)
+{
+ u8 sr;
+ int n_words = 0;
+
+ /*
+ * Before the buffer_size detection we reset the core
+ * to make sure we start with a clean state.
+ */
+ xspi->write_fn(XIPIF_V123B_RESET_MASK,
+ xspi->regs + XIPIF_V123B_RESETR_OFFSET);
+
+ /* Fill the Tx FIFO with as many words as possible */
+ do {
+ xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
+ sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+ n_words++;
+ } while (!(sr & XSPI_SR_TX_FULL_MASK));
+
+ return n_words;
+}
+
static const struct of_device_id xilinx_spi_of_match[] = {
{ .compatible = "xlnx,xps-spi-2.00.a", },
{ .compatible = "xlnx,xps-spi-2.00.b", },
@@ -413,6 +431,8 @@ static int xilinx_spi_probe(struct platform_device *pdev)
goto put_master;
}
+ xspi->buffer_size = xilinx_spi_find_buffer_size(xspi);
+
/* SPI controller initializations */
xspi_init_hw(xspi);
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 02/15] spi/xilinx: Leave the IRQ always enabled.
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 01/15] spi/xilinx: Simplify spi_fill_tx_fifo Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 19:38 ` Mark Brown
2015-01-28 12:23 ` [PATCH v2 03/15] spi/xilinx: Code cleanup Ricardo Ribalda Delgado
` (13 subsequent siblings)
15 siblings, 1 reply; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
Instead of enabling the IRQ and disabling it for every transaction.
Specially the small transactions (1,2 words) benefit from removing 3 bus
accesses.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 1890af8..d933207 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -167,8 +167,11 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
/* Reset the SPI device */
xspi->write_fn(XIPIF_V123B_RESET_MASK,
regs_base + XIPIF_V123B_RESETR_OFFSET);
- /* Disable all the interrupts just in case */
- xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
+ /* Enable the transmit empty interrupt, which we use to determine
+ * progress on the transmission.
+ */
+ xspi->write_fn(XSPI_INTR_TX_EMPTY,
+ regs_base + XIPIF_V123B_IIER_OFFSET);
/* Enable the global IPIF interrupt */
xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
regs_base + XIPIF_V123B_DGIER_OFFSET);
@@ -237,7 +240,6 @@ static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi, int n_words)
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
- u32 ipif_ier;
/* We get here with transmitter inhibited */
@@ -246,14 +248,6 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->remaining_bytes = t->len;
reinit_completion(&xspi->done);
-
- /* Enable the transmit empty interrupt, which we use to determine
- * progress on the transmission.
- */
- ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET);
- xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
- xspi->regs + XIPIF_V123B_IIER_OFFSET);
-
for (;;) {
u16 cr;
int n_words;
@@ -290,9 +284,6 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
break;
}
- /* Disable the transmit empty interrupt */
- xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);
-
return t->len - xspi->remaining_bytes;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 03/15] spi/xilinx: Code cleanup
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 01/15] spi/xilinx: Simplify spi_fill_tx_fifo Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 02/15] spi/xilinx: Leave the IRQ always enabled Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 04/15] spi/xilinx: Use cached value of register Ricardo Ribalda Delgado
` (12 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
On the transmission loop, check for remaining bytes at the loop
condition.
This way we can handle transmissions of 0 bytes and clean the code.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
v2: Changes Requested by Mark Brown <broonie@kernel.org>
Improve description
drivers/spi/spi-xilinx.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index d933207..a0f7c9d 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -248,7 +248,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->remaining_bytes = t->len;
reinit_completion(&xspi->done);
- for (;;) {
+ while (xspi->remaining_bytes) {
u16 cr;
int n_words;
@@ -278,10 +278,6 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
/* Read out all the data from the Rx FIFO */
while (n_words--)
xspi->rx_fn(xspi);
-
- /* See if there is more data to send */
- if (xspi->remaining_bytes <= 0)
- break;
}
return t->len - xspi->remaining_bytes;
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 04/15] spi/xilinx: Use cached value of register
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (2 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 03/15] spi/xilinx: Code cleanup Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 05/15] spi/xilinx: Support cores with no interrupt Ricardo Ribalda Delgado
` (11 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
The control register has not changed since the previous access.
Therefore we can use the cached value and safe one bus access.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index a0f7c9d..12b311e 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -271,7 +271,6 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
* transmitter while the Isr refills the transmit register/FIFO,
* or make sure it is stopped if we're done.
*/
- cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET);
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 05/15] spi/xilinx: Support cores with no interrupt
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (3 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 04/15] spi/xilinx: Use cached value of register Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 06/15] spi/xilinx: Do not inhibit transmission in polling mode Ricardo Ribalda Delgado
` (10 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
The core can run in polling mode. In fact, the performance of the core
is similar (or even better), due to the fact most of the spi
transactions are just a couple of bytes and there is one irq per
transactions.
When an mtd device is connected via spi, reading 8MB of data produces
more than 80K interrupts (with irq disabling, context swith....)
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 33 +++++++++++++++++++--------------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 12b311e..f21e857 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -173,8 +173,11 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
xspi->write_fn(XSPI_INTR_TX_EMPTY,
regs_base + XIPIF_V123B_IIER_OFFSET);
/* Enable the global IPIF interrupt */
- xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
- regs_base + XIPIF_V123B_DGIER_OFFSET);
+ if (xspi->irq >= 0)
+ xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+ regs_base + XIPIF_V123B_DGIER_OFFSET);
+ else
+ xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
/* Deselect the slave on the SPI bus */
xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
/* Disable the transmitter, enable Manual Slave Select Assertion,
@@ -264,7 +267,12 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
~XSPI_CR_TRANS_INHIBIT;
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
- wait_for_completion(&xspi->done);
+ if (xspi->irq >= 0)
+ wait_for_completion(&xspi->done);
+ else
+ while (!(xspi->read_fn(xspi->regs + XSPI_SR_OFFSET) &
+ XSPI_SR_TX_EMPTY_MASK))
+ ;
/* A transmit has just completed. Process received data and
* check for more data to transmit. Always inhibit the
@@ -419,20 +427,17 @@ static int xilinx_spi_probe(struct platform_device *pdev)
xspi->buffer_size = xilinx_spi_find_buffer_size(xspi);
- /* SPI controller initializations */
- xspi_init_hw(xspi);
-
xspi->irq = platform_get_irq(pdev, 0);
- if (xspi->irq < 0) {
- ret = xspi->irq;
- goto put_master;
+ if (xspi->irq >= 0) {
+ /* Register for SPI Interrupt */
+ ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
+ dev_name(&pdev->dev), xspi);
+ if (ret)
+ goto put_master;
}
- /* Register for SPI Interrupt */
- ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
- dev_name(&pdev->dev), xspi);
- if (ret)
- goto put_master;
+ /* SPI controller initializations */
+ xspi_init_hw(xspi);
ret = spi_bitbang_start(&xspi->bitbang);
if (ret) {
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 06/15] spi/xilinx: Do not inhibit transmission in polling mode
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (4 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 05/15] spi/xilinx: Support cores with no interrupt Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 07/15] spi/xilinx: Support for spi mode CS_HIGH Ricardo Ribalda Delgado
` (9 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
When no irq is used, there is no need to inhibit the transmission for
every transaction. This inhibition was implemented to avoid a race
condition with the irq handler.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index f21e857..6656b2c 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -163,6 +163,7 @@ static void xspi_rx32(struct xilinx_spi *xspi)
static void xspi_init_hw(struct xilinx_spi *xspi)
{
void __iomem *regs_base = xspi->regs;
+ u32 inhibit;
/* Reset the SPI device */
xspi->write_fn(XIPIF_V123B_RESET_MASK,
@@ -173,16 +174,19 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
xspi->write_fn(XSPI_INTR_TX_EMPTY,
regs_base + XIPIF_V123B_IIER_OFFSET);
/* Enable the global IPIF interrupt */
- if (xspi->irq >= 0)
+ if (xspi->irq >= 0) {
xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
regs_base + XIPIF_V123B_DGIER_OFFSET);
- else
+ inhibit = XSPI_CR_TRANS_INHIBIT;
+ } else {
xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
+ inhibit = 0;
+ }
/* Deselect the slave on the SPI bus */
xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
/* Disable the transmitter, enable Manual Slave Select Assertion,
* put SPI controller into master mode, and enable it */
- xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT |
+ xspi->write_fn(inhibit | XSPI_CR_MANUAL_SSELECT |
XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |
XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET);
}
@@ -252,7 +256,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
reinit_completion(&xspi->done);
while (xspi->remaining_bytes) {
- u16 cr;
+ u16 cr = 0;
int n_words;
n_words = (xspi->remaining_bytes * 8) / xspi->bits_per_word;
@@ -263,13 +267,13 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
/* Start the transfer by not inhibiting the transmitter any
* longer
*/
- cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
- ~XSPI_CR_TRANS_INHIBIT;
- xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
- if (xspi->irq >= 0)
+ if (xspi->irq >= 0) {
+ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
+ ~XSPI_CR_TRANS_INHIBIT;
+ xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
wait_for_completion(&xspi->done);
- else
+ } else
while (!(xspi->read_fn(xspi->regs + XSPI_SR_OFFSET) &
XSPI_SR_TX_EMPTY_MASK))
;
@@ -279,7 +283,8 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
* transmitter while the Isr refills the transmit register/FIFO,
* or make sure it is stopped if we're done.
*/
- xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
+ if (xspi->irq >= 0)
+ xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET);
/* Read out all the data from the Rx FIFO */
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 07/15] spi/xilinx: Support for spi mode CS_HIGH
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (5 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 06/15] spi/xilinx: Do not inhibit transmission in polling mode Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 08/15] spi/xilinx: Remove rx_fn and tx_fn pointer Ricardo Ribalda Delgado
` (8 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
The core controls the chip select lines individually.
By default, all the lines are consider active_low. After
spi_setup_transfer, it has its real value.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 62 +++++++++++++++++++++++++++++-------------------
1 file changed, 38 insertions(+), 24 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 6656b2c..523da73 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -89,6 +89,7 @@ struct xilinx_spi {
int remaining_bytes; /* the number of bytes left to transfer */
u8 bits_per_word;
int buffer_size; /* buffer size in words */
+ u32 cs_inactive; /* Level of the CS pins when inactive*/
unsigned int (*read_fn)(void __iomem *);
void (*write_fn)(u32, void __iomem *);
void (*tx_fn)(struct xilinx_spi *);
@@ -194,33 +195,37 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
{
struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+ u16 cr;
+ u32 cs;
if (is_on == BITBANG_CS_INACTIVE) {
/* Deselect the slave on the SPI bus */
- xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET);
- } else if (is_on == BITBANG_CS_ACTIVE) {
- /* Set the SPI clock phase and polarity */
- u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)
- & ~XSPI_CR_MODE_MASK;
- if (spi->mode & SPI_CPHA)
- cr |= XSPI_CR_CPHA;
- if (spi->mode & SPI_CPOL)
- cr |= XSPI_CR_CPOL;
- if (spi->mode & SPI_LSB_FIRST)
- cr |= XSPI_CR_LSB_FIRST;
- if (spi->mode & SPI_LOOP)
- cr |= XSPI_CR_LOOP;
- xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-
- /* We do not check spi->max_speed_hz here as the SPI clock
- * frequency is not software programmable (the IP block design
- * parameter)
- */
-
- /* Activate the chip select */
- xspi->write_fn(~(0x0001 << spi->chip_select),
- xspi->regs + XSPI_SSR_OFFSET);
+ xspi->write_fn(xspi->cs_inactive, xspi->regs + XSPI_SSR_OFFSET);
+ return;
}
+
+ /* Set the SPI clock phase and polarity */
+ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_MODE_MASK;
+ if (spi->mode & SPI_CPHA)
+ cr |= XSPI_CR_CPHA;
+ if (spi->mode & SPI_CPOL)
+ cr |= XSPI_CR_CPOL;
+ if (spi->mode & SPI_LSB_FIRST)
+ cr |= XSPI_CR_LSB_FIRST;
+ if (spi->mode & SPI_LOOP)
+ cr |= XSPI_CR_LOOP;
+ xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
+
+ /* We do not check spi->max_speed_hz here as the SPI clock
+ * frequency is not software programmable (the IP block design
+ * parameter)
+ */
+
+ cs = xspi->cs_inactive;
+ cs ^= BIT(spi->chip_select);
+
+ /* Activate the chip select */
+ xspi->write_fn(cs, xspi->regs + XSPI_SSR_OFFSET);
}
/* spi_bitbang requires custom setup_transfer() to be defined if there is a
@@ -229,6 +234,13 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
static int xilinx_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
+ struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+
+ if (spi->mode & SPI_CS_HIGH)
+ xspi->cs_inactive &= ~BIT(spi->chip_select);
+ else
+ xspi->cs_inactive |= BIT(spi->chip_select);
+
return 0;
}
@@ -376,9 +388,11 @@ static int xilinx_spi_probe(struct platform_device *pdev)
return -ENODEV;
/* the spi->mode bits understood by this driver: */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP |
+ SPI_CS_HIGH;
xspi = spi_master_get_devdata(master);
+ xspi->cs_inactive = 0xffffffff;
xspi->bitbang.master = master;
xspi->bitbang.chipselect = xilinx_spi_chipselect;
xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 08/15] spi/xilinx: Remove rx_fn and tx_fn pointer
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (6 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 07/15] spi/xilinx: Support for spi mode CS_HIGH Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 09/15] spi/xilinx: Make spi_tx and spi_rx simmetric Ricardo Ribalda Delgado
` (7 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
Simplify the code by removing the tx and and rx function pointers and
substitute them by a single function.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
v2: Changes Requested by Mark Brown <broonie@kernel.org>
Code style a / 8 instead of a/8
drivers/spi/spi-xilinx.c | 69 +++++++++++++-----------------------------------
1 file changed, 18 insertions(+), 51 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 523da73..ac94e54 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -92,8 +92,6 @@ struct xilinx_spi {
u32 cs_inactive; /* Level of the CS pins when inactive*/
unsigned int (*read_fn)(void __iomem *);
void (*write_fn)(u32, void __iomem *);
- void (*tx_fn)(struct xilinx_spi *);
- void (*rx_fn)(struct xilinx_spi *);
};
static void xspi_write32(u32 val, void __iomem *addr)
@@ -116,49 +114,32 @@ static unsigned int xspi_read32_be(void __iomem *addr)
return ioread32be(addr);
}
-static void xspi_tx8(struct xilinx_spi *xspi)
-{
- xspi->write_fn(*xspi->tx_ptr, xspi->regs + XSPI_TXD_OFFSET);
- xspi->tx_ptr++;
-}
-
-static void xspi_tx16(struct xilinx_spi *xspi)
-{
- xspi->write_fn(*(u16 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
- xspi->tx_ptr += 2;
-}
-
-static void xspi_tx32(struct xilinx_spi *xspi)
+static void xilinx_spi_tx(struct xilinx_spi *xspi)
{
xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
- xspi->tx_ptr += 4;
+ xspi->tx_ptr += xspi->bits_per_word / 8;
}
-static void xspi_rx8(struct xilinx_spi *xspi)
+static void xilinx_spi_rx(struct xilinx_spi *xspi)
{
u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
- if (xspi->rx_ptr) {
- *xspi->rx_ptr = data & 0xff;
- xspi->rx_ptr++;
- }
-}
-static void xspi_rx16(struct xilinx_spi *xspi)
-{
- u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
- if (xspi->rx_ptr) {
- *(u16 *)(xspi->rx_ptr) = data & 0xffff;
- xspi->rx_ptr += 2;
- }
-}
+ if (!xspi->rx_ptr)
+ return;
-static void xspi_rx32(struct xilinx_spi *xspi)
-{
- u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
- if (xspi->rx_ptr) {
+ switch (xspi->bits_per_word) {
+ case 8:
+ *(u8 *)(xspi->rx_ptr) = data;
+ break;
+ case 16:
+ *(u16 *)(xspi->rx_ptr) = data;
+ break;
+ case 32:
*(u32 *)(xspi->rx_ptr) = data;
- xspi->rx_ptr += 4;
+ break;
}
+
+ xspi->rx_ptr += xspi->bits_per_word / 8;
}
static void xspi_init_hw(struct xilinx_spi *xspi)
@@ -250,7 +231,7 @@ static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi, int n_words)
while (n_words--)
if (xspi->tx_ptr)
- xspi->tx_fn(xspi);
+ xilinx_spi_tx(xspi);
else
xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
return;
@@ -301,7 +282,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
/* Read out all the data from the Rx FIFO */
while (n_words--)
- xspi->rx_fn(xspi);
+ xilinx_spi_rx(xspi);
}
return t->len - xspi->remaining_bytes;
@@ -430,20 +411,6 @@ static int xilinx_spi_probe(struct platform_device *pdev)
master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word);
xspi->bits_per_word = bits_per_word;
- if (xspi->bits_per_word == 8) {
- xspi->tx_fn = xspi_tx8;
- xspi->rx_fn = xspi_rx8;
- } else if (xspi->bits_per_word == 16) {
- xspi->tx_fn = xspi_tx16;
- xspi->rx_fn = xspi_rx16;
- } else if (xspi->bits_per_word == 32) {
- xspi->tx_fn = xspi_tx32;
- xspi->rx_fn = xspi_rx32;
- } else {
- ret = -EINVAL;
- goto put_master;
- }
-
xspi->buffer_size = xilinx_spi_find_buffer_size(xspi);
xspi->irq = platform_get_irq(pdev, 0);
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 09/15] spi/xilinx: Make spi_tx and spi_rx simmetric
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (7 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 08/15] spi/xilinx: Remove rx_fn and tx_fn pointer Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 10/15] spi/xilinx: Convert remainding_bytes in remaining words Ricardo Ribalda Delgado
` (6 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
spi_rx handles the case where the buffer is null. Nevertheless spi_tx
did not handle it, and was handled by the caller function.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index ac94e54..6ce1066 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -116,6 +116,10 @@ static unsigned int xspi_read32_be(void __iomem *addr)
static void xilinx_spi_tx(struct xilinx_spi *xspi)
{
+ if (!xspi->tx_ptr) {
+ xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
+ return;
+ }
xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
xspi->tx_ptr += xspi->bits_per_word / 8;
}
@@ -230,10 +234,7 @@ static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi, int n_words)
xspi->remaining_bytes -= n_words * xspi->bits_per_word / 8;
while (n_words--)
- if (xspi->tx_ptr)
- xilinx_spi_tx(xspi);
- else
- xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
+ xilinx_spi_tx(xspi);
return;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 10/15] spi/xilinx: Convert remainding_bytes in remaining words
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (8 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 09/15] spi/xilinx: Make spi_tx and spi_rx simmetric Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 11/15] spi/xilinx: Convert bits_per_word in bytes_per_word Ricardo Ribalda Delgado
` (5 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
Simplify the code by using the unit used on most of the code logic.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 6ce1066..8ed306e 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -86,7 +86,7 @@ struct xilinx_spi {
u8 *rx_ptr; /* pointer in the Tx buffer */
const u8 *tx_ptr; /* pointer in the Rx buffer */
- int remaining_bytes; /* the number of bytes left to transfer */
+ int remaining_words; /* the number of words left to transfer */
u8 bits_per_word;
int buffer_size; /* buffer size in words */
u32 cs_inactive; /* Level of the CS pins when inactive*/
@@ -231,7 +231,7 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi, int n_words)
{
- xspi->remaining_bytes -= n_words * xspi->bits_per_word / 8;
+ xspi->remaining_words -= n_words;
while (n_words--)
xilinx_spi_tx(xspi);
@@ -246,15 +246,14 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->tx_ptr = t->tx_buf;
xspi->rx_ptr = t->rx_buf;
- xspi->remaining_bytes = t->len;
+ xspi->remaining_words = (t->len * 8) / xspi->bits_per_word;
reinit_completion(&xspi->done);
- while (xspi->remaining_bytes) {
+ while (xspi->remaining_words) {
u16 cr = 0;
int n_words;
- n_words = (xspi->remaining_bytes * 8) / xspi->bits_per_word;
- n_words = min(n_words, xspi->buffer_size);
+ n_words = min(xspi->remaining_words, xspi->buffer_size);
xilinx_spi_fill_tx_fifo(xspi, n_words);
@@ -286,7 +285,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xilinx_spi_rx(xspi);
}
- return t->len - xspi->remaining_bytes;
+ return t->len;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 11/15] spi/xilinx: Convert bits_per_word in bytes_per_word
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (9 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 10/15] spi/xilinx: Convert remainding_bytes in remaining words Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 12/15] spi/xilinx: Remove iowrite/ioread wrappers Ricardo Ribalda Delgado
` (4 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
Simplify the code by using the unit used on most of the code logic.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 8ed306e..b16fccf 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -87,7 +87,7 @@ struct xilinx_spi {
u8 *rx_ptr; /* pointer in the Tx buffer */
const u8 *tx_ptr; /* pointer in the Rx buffer */
int remaining_words; /* the number of words left to transfer */
- u8 bits_per_word;
+ u8 bytes_per_word;
int buffer_size; /* buffer size in words */
u32 cs_inactive; /* Level of the CS pins when inactive*/
unsigned int (*read_fn)(void __iomem *);
@@ -121,7 +121,7 @@ static void xilinx_spi_tx(struct xilinx_spi *xspi)
return;
}
xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
- xspi->tx_ptr += xspi->bits_per_word / 8;
+ xspi->tx_ptr += xspi->bytes_per_word;
}
static void xilinx_spi_rx(struct xilinx_spi *xspi)
@@ -131,19 +131,19 @@ static void xilinx_spi_rx(struct xilinx_spi *xspi)
if (!xspi->rx_ptr)
return;
- switch (xspi->bits_per_word) {
- case 8:
+ switch (xspi->bytes_per_word) {
+ case 1:
*(u8 *)(xspi->rx_ptr) = data;
break;
- case 16:
+ case 2:
*(u16 *)(xspi->rx_ptr) = data;
break;
- case 32:
+ case 4:
*(u32 *)(xspi->rx_ptr) = data;
break;
}
- xspi->rx_ptr += xspi->bits_per_word / 8;
+ xspi->rx_ptr += xspi->bytes_per_word;
}
static void xspi_init_hw(struct xilinx_spi *xspi)
@@ -246,7 +246,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->tx_ptr = t->tx_buf;
xspi->rx_ptr = t->rx_buf;
- xspi->remaining_words = (t->len * 8) / xspi->bits_per_word;
+ xspi->remaining_words = t->len / xspi->bytes_per_word;
reinit_completion(&xspi->done);
while (xspi->remaining_words) {
@@ -410,7 +410,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
}
master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word);
- xspi->bits_per_word = bits_per_word;
+ xspi->bytes_per_word = bits_per_word / 8;
xspi->buffer_size = xilinx_spi_find_buffer_size(xspi);
xspi->irq = platform_get_irq(pdev, 0);
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 12/15] spi/xilinx: Remove iowrite/ioread wrappers
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (10 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 11/15] spi/xilinx: Convert bits_per_word in bytes_per_word Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-30 6:13 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 13/15] spi/xilinx: Remove remaining_words driver data variable Ricardo Ribalda Delgado
` (3 subsequent siblings)
15 siblings, 1 reply; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
Save a stack level and cleanup code.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 28 ++++------------------------
1 file changed, 4 insertions(+), 24 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index b16fccf..8c25c59 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -94,26 +94,6 @@ struct xilinx_spi {
void (*write_fn)(u32, void __iomem *);
};
-static void xspi_write32(u32 val, void __iomem *addr)
-{
- iowrite32(val, addr);
-}
-
-static unsigned int xspi_read32(void __iomem *addr)
-{
- return ioread32(addr);
-}
-
-static void xspi_write32_be(u32 val, void __iomem *addr)
-{
- iowrite32be(val, addr);
-}
-
-static unsigned int xspi_read32_be(void __iomem *addr)
-{
- return ioread32be(addr);
-}
-
static void xilinx_spi_tx(struct xilinx_spi *xspi)
{
if (!xspi->tx_ptr) {
@@ -398,15 +378,15 @@ static int xilinx_spi_probe(struct platform_device *pdev)
* Setup little endian helper functions first and try to use them
* and check if bit was correctly setup or not.
*/
- xspi->read_fn = xspi_read32;
- xspi->write_fn = xspi_write32;
+ xspi->read_fn = ioread32;
+ xspi->write_fn = iowrite32;
xspi->write_fn(XSPI_CR_LOOP, xspi->regs + XSPI_CR_OFFSET);
tmp = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
tmp &= XSPI_CR_LOOP;
if (tmp != XSPI_CR_LOOP) {
- xspi->read_fn = xspi_read32_be;
- xspi->write_fn = xspi_write32_be;
+ xspi->read_fn = ioread32be;
+ xspi->write_fn = iowrite32be;
}
master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word);
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 13/15] spi/xilinx: Remove remaining_words driver data variable
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (11 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 12/15] spi/xilinx: Remove iowrite/ioread wrappers Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 14/15] spi/xilinx: Check number of slaves range Ricardo Ribalda Delgado
` (2 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
The variable never leaves the scope of txrx_bufs.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 8c25c59..026f4c5 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -86,7 +86,6 @@ struct xilinx_spi {
u8 *rx_ptr; /* pointer in the Tx buffer */
const u8 *tx_ptr; /* pointer in the Rx buffer */
- int remaining_words; /* the number of words left to transfer */
u8 bytes_per_word;
int buffer_size; /* buffer size in words */
u32 cs_inactive; /* Level of the CS pins when inactive*/
@@ -209,33 +208,27 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
return 0;
}
-static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi, int n_words)
-{
- xspi->remaining_words -= n_words;
-
- while (n_words--)
- xilinx_spi_tx(xspi);
- return;
-}
-
static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
+ int remaining_words; /* the number of words left to transfer */
/* We get here with transmitter inhibited */
xspi->tx_ptr = t->tx_buf;
xspi->rx_ptr = t->rx_buf;
- xspi->remaining_words = t->len / xspi->bytes_per_word;
+ remaining_words = t->len / xspi->bytes_per_word;
reinit_completion(&xspi->done);
- while (xspi->remaining_words) {
+ while (remaining_words) {
u16 cr = 0;
- int n_words;
+ int n_words, tx_words, rx_words;
- n_words = min(xspi->remaining_words, xspi->buffer_size);
+ n_words = min(remaining_words, xspi->buffer_size);
- xilinx_spi_fill_tx_fifo(xspi, n_words);
+ tx_words = n_words;
+ while (tx_words--)
+ xilinx_spi_tx(xspi);
/* Start the transfer by not inhibiting the transmitter any
* longer
@@ -261,8 +254,11 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
xspi->regs + XSPI_CR_OFFSET);
/* Read out all the data from the Rx FIFO */
- while (n_words--)
+ rx_words = n_words;
+ while (rx_words--)
xilinx_spi_rx(xspi);
+
+ remaining_words -= n_words;
}
return t->len;
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 14/15] spi/xilinx: Check number of slaves range
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (12 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 13/15] spi/xilinx: Remove remaining_words driver data variable Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 19:40 ` Mark Brown
2015-01-28 12:23 ` [PATCH v2 15/15] spi/xilinx: Use polling mode on small transfers Ricardo Ribalda Delgado
2015-01-28 19:43 ` [PATCH v2 00/15] spi/xilinx: Speed-up Mark Brown
15 siblings, 1 reply; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
The core only supports up to 32 slaves, and the chipselect function
expects the same.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 026f4c5..134d8cd 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -22,6 +22,8 @@
#include <linux/spi/xilinx_spi.h>
#include <linux/io.h>
+#define MAX_CS 32
+
#define XILINX_SPI_NAME "xilinx_spi"
/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
@@ -340,6 +342,11 @@ static int xilinx_spi_probe(struct platform_device *pdev)
return -EINVAL;
}
+ if (num_cs > MAX_CS) {
+ dev_err(&pdev->dev, "Invalid number of spi slaves\n");
+ return -EINVAL;
+ }
+
master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi));
if (!master)
return -ENODEV;
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 15/15] spi/xilinx: Use polling mode on small transfers
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (13 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 14/15] spi/xilinx: Check number of slaves range Ricardo Ribalda Delgado
@ 2015-01-28 12:23 ` Ricardo Ribalda Delgado
2015-01-28 19:43 ` [PATCH v2 00/15] spi/xilinx: Speed-up Mark Brown
15 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-28 12:23 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
linux-arm-kernel, linux-kernel
Cc: Ricardo Ribalda Delgado
Small transfers generally can be accomplished faster in polling mode.
This patch select the transfer which size is bellow the buffer size to
be done on polling mode
Suggested-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/spi/spi-xilinx.c | 43 +++++++++++++++++++++++++------------------
1 file changed, 25 insertions(+), 18 deletions(-)
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 134d8cd..c6b0a6e 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -130,7 +130,6 @@ static void xilinx_spi_rx(struct xilinx_spi *xspi)
static void xspi_init_hw(struct xilinx_spi *xspi)
{
void __iomem *regs_base = xspi->regs;
- u32 inhibit;
/* Reset the SPI device */
xspi->write_fn(XIPIF_V123B_RESET_MASK,
@@ -140,22 +139,15 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
*/
xspi->write_fn(XSPI_INTR_TX_EMPTY,
regs_base + XIPIF_V123B_IIER_OFFSET);
- /* Enable the global IPIF interrupt */
- if (xspi->irq >= 0) {
- xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
- regs_base + XIPIF_V123B_DGIER_OFFSET);
- inhibit = XSPI_CR_TRANS_INHIBIT;
- } else {
- xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
- inhibit = 0;
- }
+ /* Disable the global IPIF interrupt */
+ xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
/* Deselect the slave on the SPI bus */
xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
/* Disable the transmitter, enable Manual Slave Select Assertion,
* put SPI controller into master mode, and enable it */
- xspi->write_fn(inhibit | XSPI_CR_MANUAL_SSELECT |
- XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |
- XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET);
+ xspi->write_fn(XSPI_CR_MANUAL_SSELECT | XSPI_CR_MASTER_MODE |
+ XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET | XSPI_CR_RXFIFO_RESET,
+ regs_base + XSPI_CR_OFFSET);
}
static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
@@ -214,6 +206,8 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
{
struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
int remaining_words; /* the number of words left to transfer */
+ bool use_irq = false;
+ u16 cr = 0;
/* We get here with transmitter inhibited */
@@ -222,8 +216,20 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
remaining_words = t->len / xspi->bytes_per_word;
reinit_completion(&xspi->done);
+ if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) {
+ use_irq = true;
+ xspi->write_fn(XSPI_INTR_TX_EMPTY,
+ xspi->regs + XIPIF_V123B_IISR_OFFSET);
+ /* Enable the global IPIF interrupt */
+ xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+ xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+ /* Inhibit irq to avoid spurious irqs on tx_empty*/
+ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
+ xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
+ xspi->regs + XSPI_CR_OFFSET);
+ }
+
while (remaining_words) {
- u16 cr = 0;
int n_words, tx_words, rx_words;
n_words = min(remaining_words, xspi->buffer_size);
@@ -236,9 +242,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
* longer
*/
- if (xspi->irq >= 0) {
- cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
- ~XSPI_CR_TRANS_INHIBIT;
+ if (use_irq) {
xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
wait_for_completion(&xspi->done);
} else
@@ -251,7 +255,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
* transmitter while the Isr refills the transmit register/FIFO,
* or make sure it is stopped if we're done.
*/
- if (xspi->irq >= 0)
+ if (use_irq)
xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
xspi->regs + XSPI_CR_OFFSET);
@@ -263,6 +267,9 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
remaining_words -= n_words;
}
+ if (use_irq)
+ xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+
return t->len;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 02/15] spi/xilinx: Leave the IRQ always enabled.
2015-01-28 12:23 ` [PATCH v2 02/15] spi/xilinx: Leave the IRQ always enabled Ricardo Ribalda Delgado
@ 2015-01-28 19:38 ` Mark Brown
0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2015-01-28 19:38 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: Michal Simek, Sören Brinkmann, linux-spi, linux-arm-kernel,
linux-kernel
[-- Attachment #1: Type: text/plain, Size: 448 bytes --]
On Wed, Jan 28, 2015 at 01:23:41PM +0100, Ricardo Ribalda Delgado wrote:
> Instead of enabling the IRQ and disabling it for every transaction.
>
> Specially the small transactions (1,2 words) benefit from removing 3 bus
> accesses.
For this particular change I don't think it matters but in general
moving things that do need to be enabled and disabled to
{un,}prepare_transfer_hardware() will avoid quite a bit of overhead
under load.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 14/15] spi/xilinx: Check number of slaves range
2015-01-28 12:23 ` [PATCH v2 14/15] spi/xilinx: Check number of slaves range Ricardo Ribalda Delgado
@ 2015-01-28 19:40 ` Mark Brown
0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2015-01-28 19:40 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: Michal Simek, Sören Brinkmann, linux-spi, linux-arm-kernel,
linux-kernel
[-- Attachment #1: Type: text/plain, Size: 138 bytes --]
On Wed, Jan 28, 2015 at 01:23:53PM +0100, Ricardo Ribalda Delgado wrote:
> +#define MAX_CS 32
> +
This really ought to be namespaced.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 00/15] spi/xilinx: Speed-up
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
` (14 preceding siblings ...)
2015-01-28 12:23 ` [PATCH v2 15/15] spi/xilinx: Use polling mode on small transfers Ricardo Ribalda Delgado
@ 2015-01-28 19:43 ` Mark Brown
15 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2015-01-28 19:43 UTC (permalink / raw)
To: Ricardo Ribalda Delgado
Cc: Michal Simek, Sören Brinkmann, linux-spi, linux-arm-kernel,
linux-kernel
[-- Attachment #1: Type: text/plain, Size: 351 bytes --]
On Wed, Jan 28, 2015 at 01:23:39PM +0100, Ricardo Ribalda Delgado wrote:
> This set of patches has been developed after using the core to access a spi
> nor flash. The initial performance was not as desired. The following changes
> have been done.
Applied everything except the MAX_CS change, thanks - that's fine, just
needs the define namespacing.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 12/15] spi/xilinx: Remove iowrite/ioread wrappers
2015-01-28 12:23 ` [PATCH v2 12/15] spi/xilinx: Remove iowrite/ioread wrappers Ricardo Ribalda Delgado
@ 2015-01-30 6:13 ` Ricardo Ribalda Delgado
0 siblings, 0 replies; 20+ messages in thread
From: Ricardo Ribalda Delgado @ 2015-01-30 6:13 UTC (permalink / raw)
To: Mark Brown, Michal Simek, Sören Brinkmann, linux-spi,
moderated list:ARM/S5P EXYNOS AR...,
LKML
Cc: Ricardo Ribalda Delgado
Hello Mark
This patch has caused a lot of issues on linux-next :S, sorry.
The root of the issue is that iowrite/ioread behaves differently in
different arches.
1) It does not necesary need to be a symbol in all the arches. It can
be declared as a function macro:
#define iowrite32(a,b) iowrite32(a,b)
2) Sometimes, even the function has a different prototype.
include/asm-generic/iomap.h
extern unsigned int ioread16be(void __iomem *);
include/asm-generic/io.h
extern unsigned int ioread16be(void __iomem *);
Until this is fixed, please revert this patch.
Sorry for the mess.
--
Ricardo Ribalda
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2015-01-30 6:13 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-28 12:23 [PATCH v2 00/15] spi/xilinx: Speed-up Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 01/15] spi/xilinx: Simplify spi_fill_tx_fifo Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 02/15] spi/xilinx: Leave the IRQ always enabled Ricardo Ribalda Delgado
2015-01-28 19:38 ` Mark Brown
2015-01-28 12:23 ` [PATCH v2 03/15] spi/xilinx: Code cleanup Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 04/15] spi/xilinx: Use cached value of register Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 05/15] spi/xilinx: Support cores with no interrupt Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 06/15] spi/xilinx: Do not inhibit transmission in polling mode Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 07/15] spi/xilinx: Support for spi mode CS_HIGH Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 08/15] spi/xilinx: Remove rx_fn and tx_fn pointer Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 09/15] spi/xilinx: Make spi_tx and spi_rx simmetric Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 10/15] spi/xilinx: Convert remainding_bytes in remaining words Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 11/15] spi/xilinx: Convert bits_per_word in bytes_per_word Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 12/15] spi/xilinx: Remove iowrite/ioread wrappers Ricardo Ribalda Delgado
2015-01-30 6:13 ` Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 13/15] spi/xilinx: Remove remaining_words driver data variable Ricardo Ribalda Delgado
2015-01-28 12:23 ` [PATCH v2 14/15] spi/xilinx: Check number of slaves range Ricardo Ribalda Delgado
2015-01-28 19:40 ` Mark Brown
2015-01-28 12:23 ` [PATCH v2 15/15] spi/xilinx: Use polling mode on small transfers Ricardo Ribalda Delgado
2015-01-28 19:43 ` [PATCH v2 00/15] spi/xilinx: Speed-up Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).