Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

arch/risc-v/src/mpfs/mpfs_corespi.c: Add support for multiple bit widths #326

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 116 additions & 30 deletions arch/risc-v/src/mpfs/mpfs_corespi.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,10 +611,21 @@ static void mpfs_spi_setbits(struct spi_dev_s *dev, int nbits)

/* Bitwidth is selected when the SPI block is being fabricated */

if (nbits != priv->config->nbits)
if (nbits != priv->nbits)
{
spierr("Changing SPI bitwidth not supported\n");
DEBUGPANIC();
/* If configured frame length is even multiple of requested,
* we simulate wider frames by sending multiple shorter ones
*/

if (nbits % priv->config->nbits == 0)
{
priv->nbits = nbits;
}
else
{
spierr("SPI bitwidth %d is not supported\n", nbits);
DEBUGPANIC();
}
}
}

Expand Down Expand Up @@ -720,6 +731,52 @@ static int mpfs_spi_sem_waitdone(struct mpfs_spi_priv_s *priv)
return nxsem_tickwait_uninterruptible(&priv->sem_isr, USEC2TICK(timeout));
}

/****************************************************************************
* Name: mpfs_spi_write_tx8
*
* Description:
* Fill up the TX fifo with one word in configured size frames
*
* Input Parameters:
* priv - SPI private state data
* nframes - Number of 8-bit data per word
* last - true if this is the last word of the transfer
*
* Returned Value:
* None
*
****************************************************************************/

static inline void mpfs_spi_write_tx8(struct mpfs_spi_priv_s *priv,
unsigned nframes,
bool last)
{
uint8_t *data8 = (uint8_t *)priv->txbuf;
unsigned pos = priv->tx_pos++;
pussuw marked this conversation as resolved.
Show resolved Hide resolved

/* Calculate octet position in the tx-buffer */

pos *= nframes;

/* Write all but last 8-bit data */

while (--nframes > 0)
{
putreg32((uint32_t)data8[pos + nframes], MPFS_SPI_TX_DATA);
pussuw marked this conversation as resolved.
Show resolved Hide resolved
}

/* Write the last 8-bit data */

if (last)
{
putreg32((uint32_t)data8[pos], MPFS_SPI_TX_LAST);
}
else
{
putreg32((uint32_t)data8[pos], MPFS_SPI_TX_DATA);
}
}

/****************************************************************************
* Name: mpfs_spi_load_tx_fifo
*
Expand All @@ -728,7 +785,6 @@ static int mpfs_spi_sem_waitdone(struct mpfs_spi_priv_s *priv)
*
* Input Parameters:
* priv - SPI private state data
* txbuffer - A pointer to the buffer of data to be sent
* nwords - the length of data that to be exchanged in units of words.
* The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
Expand All @@ -741,34 +797,34 @@ static int mpfs_spi_sem_waitdone(struct mpfs_spi_priv_s *priv)
****************************************************************************/

static void mpfs_spi_load_tx_fifo(struct mpfs_spi_priv_s *priv,
const void *txbuffer,
uint32_t nwords)
{
uint16_t *data16;
uint8_t *data8;
int i;
unsigned frames_per_word;

DEBUGASSERT(nwords > 0);
data16 = (uint16_t *)txbuffer;
data8 = (uint8_t *)txbuffer;
data16 = (uint16_t *)priv->txbuf;
frames_per_word = priv->nbits / priv->config->nbits;

if (!txbuffer)
if (!priv->txbuf)
{
for (i = 0; i < nwords - 1; i++)
for (i = 0; i < nwords * frames_per_word - 1; i++)
{
putreg32(0, MPFS_SPI_TX_DATA);
}

putreg32(0, MPFS_SPI_TX_LAST);
priv->tx_pos += nwords;
}
else if (priv->nbits == 8)
else if (priv->config->nbits == 8)
{
for (i = 0; i < nwords - 1; i++)
{
putreg32((uint32_t)data8[priv->tx_pos++], MPFS_SPI_TX_DATA);
mpfs_spi_write_tx8(priv, frames_per_word, false);
}

putreg32((uint32_t)data8[priv->tx_pos++], MPFS_SPI_TX_LAST);
mpfs_spi_write_tx8(priv, frames_per_word, true);
}
else
{
Expand All @@ -781,6 +837,39 @@ static void mpfs_spi_load_tx_fifo(struct mpfs_spi_priv_s *priv,
}
}

/****************************************************************************
* Name: mpfs_spi_read_rx8
*
* Description:
* Read one word from RX fifo in configured size frames
*
* Input Parameters:
* priv - SPI private state data
* nframes - Number of 8-bit data per word
*
* Returned Value:
* None
*
****************************************************************************/

static inline void mpfs_spi_read_rx8(struct mpfs_spi_priv_s *priv,
unsigned nframes)
{
uint8_t *data8 = (uint8_t *)priv->rxbuf;
unsigned pos = priv->rx_pos++;
pussuw marked this conversation as resolved.
Show resolved Hide resolved

/* Calculate octet position in the rx-buffer */

pos *= nframes;

/* Read all octets for of the word */

while (nframes-- > 0)
{
data8[pos + nframes] = getreg32(MPFS_SPI_RX_DATA);
}
}

/****************************************************************************
* Name: mpfs_spi_unload_rx_fifo
*
Expand All @@ -790,7 +879,6 @@ static void mpfs_spi_load_tx_fifo(struct mpfs_spi_priv_s *priv,
*
* Input Parameters:
* priv - SPI private state data
* txbuffer - A pointer to the buffer of data for receiving data
* nwords - the length of data that to be exchanged in units of words.
*
* Returned Value:
Expand All @@ -799,36 +887,34 @@ static void mpfs_spi_load_tx_fifo(struct mpfs_spi_priv_s *priv,
****************************************************************************/

static void mpfs_spi_unload_rx_fifo(struct mpfs_spi_priv_s *priv,
void *rxbuffer,
uint32_t nwords)
{
uint16_t *data16;
uint8_t *data8;
int i;
unsigned frames_per_word;

DEBUGASSERT(nwords > 0);

data16 = (uint16_t *)rxbuffer;
data8 = (uint8_t *)rxbuffer;

if (!rxbuffer)
if (!priv->rxbuf)
{
modifyreg32(MPFS_SPI_COMMAND, 0, MPFS_SPI_RXFIFORST);
}
else if (priv->nbits == 8)
else if (priv->config->nbits == 8)
{
frames_per_word = priv->nbits / priv->config->nbits;
for (i = 0; i < nwords - 1; i++)
{
data8[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
mpfs_spi_read_rx8(priv, frames_per_word);
}

if (mpfs_rx_wait_last_frame(priv) == 0)
{
data8[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
mpfs_spi_read_rx8(priv, frames_per_word);
}
}
else if (priv->nbits == 16)
else
{
data16 = (uint16_t *)priv->rxbuf;
for (i = 0; i < nwords - 1; i++)
{
data16[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA);
Expand Down Expand Up @@ -905,11 +991,11 @@ static void mpfs_spi_irq_exchange(struct mpfs_spi_priv_s *priv,

if (nwords > priv->fifosize)
{
mpfs_spi_load_tx_fifo(priv, txbuffer, priv->fifolevel);
mpfs_spi_load_tx_fifo(priv, priv->fifolevel);
}
else
{
mpfs_spi_load_tx_fifo(priv, txbuffer, nwords);
mpfs_spi_load_tx_fifo(priv, nwords);
}

/* Enable TX, RX, underrun and overflow interrupts */
Expand Down Expand Up @@ -1303,11 +1389,11 @@ static int mpfs_spi_irq(int cpuint, void *context, void *arg)

if (remaining <= priv->fifosize)
{
mpfs_spi_unload_rx_fifo(priv, priv->rxbuf, remaining);
mpfs_spi_unload_rx_fifo(priv, remaining);
}
else
{
mpfs_spi_unload_rx_fifo(priv, priv->rxbuf, priv->fifolevel);
mpfs_spi_unload_rx_fifo(priv, priv->fifolevel);
}

remaining = priv->txwords - priv->tx_pos;
Expand All @@ -1323,11 +1409,11 @@ static int mpfs_spi_irq(int cpuint, void *context, void *arg)
{
if (remaining <= priv->fifosize)
{
mpfs_spi_load_tx_fifo(priv, priv->txbuf, remaining);
mpfs_spi_load_tx_fifo(priv, remaining);
}
else
{
mpfs_spi_load_tx_fifo(priv, priv->txbuf, priv->fifolevel);
mpfs_spi_load_tx_fifo(priv, priv->fifolevel);
}
}
}
Expand Down
Loading