This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 9be93addea mpfs/mpfs_corespi: Several speed optimizations to the FPGA
driver
9be93addea is described below
commit 9be93addea69850defa8fbba77416efb363f8b46
Author: Ville Juven <[email protected]>
AuthorDate: Fri Sep 22 14:34:22 2023 +0300
mpfs/mpfs_corespi: Several speed optimizations to the FPGA driver
This is a collection of tweaks / optimizations to the driver to limit
CPU usage as well as interrupt processing times.
The changes are as follows:
- setfrequency is now no-op if the frequency does not change. Accessing
MPFS_SPI_CONTROL requires synchronization to the FIC domain, which
takes unnecessary time if nothing changes
- load/unload FIFO loops optimized so !buffer, priv->nbits and i==last are
only tested once (instead of for every word written in loop).
- Disable the RX interrupt only once (again, FIC domain access is slow)
- In case a spurious MPFS_SPI_DATA_RX interrupt arrives, just wipe the
whole RX FIFO, instead of trying to read it byte-by-byte
---
arch/risc-v/src/mpfs/mpfs_corespi.c | 139 +++++++++++++++---------------------
1 file changed, 57 insertions(+), 82 deletions(-)
diff --git a/arch/risc-v/src/mpfs/mpfs_corespi.c
b/arch/risc-v/src/mpfs/mpfs_corespi.c
index a14b5cb634..65c566a6d5 100644
--- a/arch/risc-v/src/mpfs/mpfs_corespi.c
+++ b/arch/risc-v/src/mpfs/mpfs_corespi.c
@@ -529,6 +529,13 @@ static uint32_t mpfs_spi_setfrequency(struct spi_dev_s
*dev,
DEBUGASSERT(frequency > 0);
+ if (priv->frequency == frequency)
+ {
+ /* Nothing changes */
+
+ return priv->actual;
+ }
+
if (priv->enabled)
{
modifyreg32(MPFS_SPI_CONTROL, MPFS_SPI_ENABLE, 0);
@@ -739,54 +746,38 @@ static void mpfs_spi_load_tx_fifo(struct mpfs_spi_priv_s
*priv,
{
uint16_t *data16;
uint8_t *data8;
- int last;
int i;
DEBUGASSERT(nwords > 0);
data16 = (uint16_t *)txbuffer;
data8 = (uint8_t *)txbuffer;
- last = nwords - 1;
- for (i = 0; i < nwords; i++)
+ if (!txbuffer)
{
- if (txbuffer)
+ for (i = 0; i < nwords - 1; i++)
{
- if (priv->nbits == 8)
- {
- if (i == last)
- {
- putreg32((uint32_t)data8[priv->tx_pos], MPFS_SPI_TX_LAST);
- }
- else
- {
- putreg32((uint32_t)data8[priv->tx_pos], MPFS_SPI_TX_DATA);
- }
- }
- else
- {
- if (i == last)
- {
- putreg32((uint32_t)data16[priv->tx_pos], MPFS_SPI_TX_LAST);
- }
- else
- {
- putreg32((uint32_t)data16[priv->tx_pos], MPFS_SPI_TX_DATA);
- }
- }
+ putreg32(0, MPFS_SPI_TX_DATA);
}
- else
+
+ putreg32(0, MPFS_SPI_TX_LAST);
+ }
+ else if (priv->nbits == 8)
+ {
+ for (i = 0; i < nwords - 1; i++)
{
- if (i == last)
- {
- putreg32(0, MPFS_SPI_TX_LAST);
- }
- else
- {
- putreg32(0, MPFS_SPI_TX_DATA);
- }
+ putreg32((uint32_t)data8[priv->tx_pos++], MPFS_SPI_TX_DATA);
+ }
+
+ putreg32((uint32_t)data8[priv->tx_pos++], MPFS_SPI_TX_LAST);
+ }
+ else
+ {
+ for (i = 0; i < nwords - 1; i++)
+ {
+ putreg32((uint32_t)data16[priv->tx_pos++], MPFS_SPI_TX_DATA);
}
- priv->tx_pos++;
+ putreg32((uint32_t)data16[priv->tx_pos++], MPFS_SPI_TX_LAST);
}
}
@@ -813,48 +804,40 @@ static void mpfs_spi_unload_rx_fifo(struct
mpfs_spi_priv_s *priv,
{
uint16_t *data16;
uint8_t *data8;
- int last;
int i;
DEBUGASSERT(nwords > 0);
data16 = (uint16_t *)rxbuffer;
data8 = (uint8_t *)rxbuffer;
- last = nwords - 1;
- for (i = 0; i < nwords; i++)
+ if (!rxbuffer)
{
- /* The last character might not be available yet due to bus delays */
-
- if (i == last)
+ modifyreg32(MPFS_SPI_COMMAND, 0, MPFS_SPI_RXFIFORST);
+ }
+ else if (priv->nbits == 8)
+ {
+ for (i = 0; i < nwords - 1; i++)
{
- if (mpfs_rx_wait_last_frame(priv) < 0)
- {
- /* Nothing came, get out */
-
- return;
- }
+ data8[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
}
- if (rxbuffer)
+ if (mpfs_rx_wait_last_frame(priv) == 0)
{
- if (priv->nbits == 8)
- {
- data8[priv->rx_pos] = getreg32(MPFS_SPI_RX_DATA);
- }
- else
- {
- data16[priv->rx_pos] = getreg32(MPFS_SPI_RX_DATA);
- }
+ data8[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
}
- else
+ }
+ else if (priv->nbits == 16)
+ {
+ for (i = 0; i < nwords - 1; i++)
{
- getreg32(MPFS_SPI_RX_DATA);
+ data16[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
}
- priv->rx_pos++;
-
- DEBUGASSERT(priv->rx_pos <= priv->rxwords);
+ if (mpfs_rx_wait_last_frame(priv) == 0)
+ {
+ data16[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
+ }
}
}
@@ -935,10 +918,6 @@ static void mpfs_spi_irq_exchange(struct mpfs_spi_priv_s
*priv,
MPFS_SPI_INTRXOVRFLOW |
MPFS_SPI_INTTXDONE);
- /* Make sure the RX interrupt is disabled */
-
- modifyreg32(MPFS_SPI_CONTROL2, MPFS_SPI_INTEN_DATA_RX, 0);
-
if (mpfs_spi_sem_waitdone(priv) < 0)
{
spiinfo("Message timed out\n");
@@ -1304,22 +1283,6 @@ static int mpfs_spi_irq(int cpuint, void *context, void
*arg)
spiinfo("irq status=%x\n", status);
- if (status & MPFS_SPI_DATA_RX)
- {
- remaining = priv->rxwords - priv->rx_pos;
-
- if (remaining <= priv->fifosize)
- {
- mpfs_spi_unload_rx_fifo(priv, priv->rxbuf, remaining);
- }
- else
- {
- mpfs_spi_unload_rx_fifo(priv, priv->rxbuf, priv->fifolevel);
- }
-
- putreg32(MPFS_SPI_DATA_RX, MPFS_SPI_INT_CLEAR);
- }
-
if (status & MPFS_SPI_TXDONE)
{
/* TX is done, we know RX is done too -> offload the RX FIFO */
@@ -1357,6 +1320,14 @@ static int mpfs_spi_irq(int cpuint, void *context, void
*arg)
}
}
+ if (status & MPFS_SPI_DATA_RX)
+ {
+ /* We don't expect data RX interrupts, just reset RX FIFO */
+
+ modifyreg32(MPFS_SPI_COMMAND, 0, MPFS_SPI_RXFIFORST);
+ putreg32(MPFS_SPI_DATA_RX, MPFS_SPI_INT_CLEAR);
+ }
+
if (status & MPFS_SPI_RXCHOVRFLW)
{
/* Handle receive overflow */
@@ -1449,6 +1420,10 @@ static void mpfs_spi_init(struct spi_dev_s *dev)
0);
modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0, MPFS_SYSREG_SUBBLK_CORESPI);
+ /* Make sure the RX interrupt is disabled (we don't use it) */
+
+ modifyreg32(MPFS_SPI_CONTROL2, MPFS_SPI_INTEN_DATA_RX, 0);
+
/* Install some default values, mode and nbits for read back */
mpfs_spi_setfrequency(dev, config->clk_freq);