Skip to content

Commit 68a2486

Browse files
robhancocksednashif
authored andcommitted
drivers: spi_xlnx_axi_quadspi: Optimize FIFO handling
Add an optional DT property to specify the size of the RX/TX FIFO implemented within the SPI core. The property name used is the same one used by Xilinx's device tree generator. When the FIFO is known to exist, we can use the RX FIFO occupancy register to determine how many words can be read from the RX FIFO without checking the RX FIFO empty flag after every read. Likewise with the TX FIFO, we can use the FIFO size to avoid checking the FIFO full flag after every write. This can increase overall throughput. Signed-off-by: Robert Hancock <[email protected]>
1 parent cff3811 commit 68a2486

File tree

2 files changed

+40
-13
lines changed

2 files changed

+40
-13
lines changed

drivers/spi/spi_xlnx_axi_quadspi.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ struct xlnx_quadspi_config {
8686
void (*irq_config_func)(const struct device *dev);
8787
uint8_t num_ss_bits;
8888
uint8_t num_xfer_bytes;
89+
uint16_t fifo_size;
8990
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(xlnx_startup_block)
9091
bool startup_block;
9192
#endif
@@ -235,6 +236,7 @@ static void xlnx_quadspi_start_tx(const struct device *dev)
235236
uint32_t spicr = 0U;
236237
uint32_t spisr;
237238
uint32_t dtr = 0U;
239+
uint32_t fifo_avail_words = config->fifo_size ? config->fifo_size : 1;
238240

239241
if (!spi_context_tx_on(ctx) && !spi_context_rx_on(ctx)) {
240242
/* All done, de-assert slave select */
@@ -285,9 +287,19 @@ static void xlnx_quadspi_start_tx(const struct device *dev)
285287
xlnx_quadspi_write32(dev, dtr, SPI_DTR_OFFSET);
286288
spi_context_update_tx(ctx, config->num_xfer_bytes, 1);
287289

288-
spisr = xlnx_quadspi_read32(dev, SPISR_OFFSET);
289-
if (spisr & SPISR_TX_FULL) {
290-
break;
290+
if (--fifo_avail_words == 0) {
291+
spisr = xlnx_quadspi_read32(dev, SPISR_OFFSET);
292+
if (spisr & SPISR_TX_FULL) {
293+
break;
294+
}
295+
if (!config->fifo_size) {
296+
fifo_avail_words = 1;
297+
} else if (spisr & SPISR_TX_EMPTY) {
298+
fifo_avail_words = config->fifo_size;
299+
} else {
300+
fifo_avail_words = config->fifo_size -
301+
xlnx_quadspi_read32(dev, SPI_TX_FIFO_OCR_OFFSET) - 1;
302+
}
291303
}
292304
}
293305

@@ -396,19 +408,21 @@ static void xlnx_quadspi_isr(const struct device *dev)
396408
const struct xlnx_quadspi_config *config = dev->config;
397409
struct xlnx_quadspi_data *data = dev->data;
398410
struct spi_context *ctx = &data->ctx;
399-
uint32_t temp;
400-
uint32_t drr;
411+
uint32_t ipisr;
401412

402413
/* Acknowledge interrupt */
403-
temp = xlnx_quadspi_read32(dev, IPISR_OFFSET);
404-
xlnx_quadspi_write32(dev, temp, IPISR_OFFSET);
414+
ipisr = xlnx_quadspi_read32(dev, IPISR_OFFSET);
415+
xlnx_quadspi_write32(dev, ipisr, IPISR_OFFSET);
405416

406-
if (temp & IPIXR_DTR_EMPTY) {
407-
temp = xlnx_quadspi_read32(dev, SPISR_OFFSET);
417+
if (ipisr & IPIXR_DTR_EMPTY) {
418+
uint32_t spisr = xlnx_quadspi_read32(dev, SPISR_OFFSET);
419+
/* RX FIFO occupancy register only exists if FIFO is implemented */
420+
uint32_t rx_fifo_words = config->fifo_size ?
421+
xlnx_quadspi_read32(dev, SPI_RX_FIFO_OCR_OFFSET) + 1 : 1;
408422

409423
/* Read RX data */
410-
while (!(temp & SPISR_RX_EMPTY)) {
411-
drr = xlnx_quadspi_read32(dev, SPI_DRR_OFFSET);
424+
while (!(spisr & SPISR_RX_EMPTY)) {
425+
uint32_t drr = xlnx_quadspi_read32(dev, SPI_DRR_OFFSET);
412426

413427
if (spi_context_rx_buf_on(ctx)) {
414428
switch (config->num_xfer_bytes) {
@@ -432,13 +446,17 @@ static void xlnx_quadspi_isr(const struct device *dev)
432446

433447
spi_context_update_rx(ctx, config->num_xfer_bytes, 1);
434448

435-
temp = xlnx_quadspi_read32(dev, SPISR_OFFSET);
449+
if (--rx_fifo_words == 0) {
450+
spisr = xlnx_quadspi_read32(dev, SPISR_OFFSET);
451+
rx_fifo_words = config->fifo_size ?
452+
xlnx_quadspi_read32(dev, SPI_RX_FIFO_OCR_OFFSET) + 1 : 1;
453+
}
436454
}
437455

438456
/* Start next TX */
439457
xlnx_quadspi_start_tx(dev);
440458
} else {
441-
LOG_WRN("unhandled interrupt, ipisr = 0x%08x", temp);
459+
LOG_WRN("unhandled interrupt, ipisr = 0x%08x", ipisr);
442460
}
443461
}
444462

@@ -546,6 +564,7 @@ static const struct spi_driver_api xlnx_quadspi_driver_api = {
546564
.num_ss_bits = DT_INST_PROP(n, xlnx_num_ss_bits), \
547565
.num_xfer_bytes = \
548566
DT_INST_PROP(n, xlnx_num_transfer_bits) / 8, \
567+
.fifo_size = DT_INST_PROP_OR(n, fifo_size, 0), \
549568
STARTUP_BLOCK_INIT(n) \
550569
}; \
551570
\

dts/bindings/spi/xlnx,xps-spi-2.00.a.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,11 @@ properties:
4949
transaction to the SPI flash device to ensure the STARTUP block is
5050
disengaged and allow the SPI core to control the CCLK line properly.
5151
The dummy READ_ID transaction will be issued to chip select 0.
52+
53+
fifo-size:
54+
type: int
55+
description: |
56+
FIFO size configured in SPI core. 0 indicates no FIFO.
57+
If not specified, 0 is assumed.
58+
Used to optimize TX/RX read handling. If the FIFO size is 0, the driver
59+
will check for FIFO full/empty after every word.

0 commit comments

Comments
 (0)