112 lines
2.6 KiB
C
112 lines
2.6 KiB
C
#include "bsp/pmod_spi.h"
|
|
|
|
#include "bsp/mmio.h"
|
|
#include "bsp/soc.h"
|
|
|
|
#define PMOD_SPI_CTRL (BSP_PMOD_SPI_BASE + 0x00u)
|
|
#define PMOD_SPI_TX (BSP_PMOD_SPI_BASE + 0x04u)
|
|
#define PMOD_SPI_RX (BSP_PMOD_SPI_BASE + 0x08u)
|
|
#define PMOD_SPI_READY (BSP_PMOD_SPI_BASE + 0x0cu)
|
|
|
|
#define PMOD_SPI_CTRL_BUSY 0x1u
|
|
#define PMOD_SPI_CTRL_CSN 0x2u
|
|
#define PMOD_SPI_CTRL_QUAD 0x4u
|
|
|
|
static uint32_t pmod_spi_ctrl_shadow = PMOD_SPI_CTRL_CSN;
|
|
|
|
static void pmod_spi_wait_ready(void)
|
|
{
|
|
while ((bsp_read32(PMOD_SPI_READY) & 1u) == 0u) {
|
|
}
|
|
while ((bsp_read32(PMOD_SPI_CTRL) & PMOD_SPI_CTRL_BUSY) != 0u) {
|
|
}
|
|
}
|
|
|
|
static void pmod_spi_write_ctrl(uint32_t ctrl)
|
|
{
|
|
pmod_spi_wait_ready();
|
|
pmod_spi_ctrl_shadow = ctrl & (PMOD_SPI_CTRL_CSN | PMOD_SPI_CTRL_QUAD);
|
|
bsp_write32(PMOD_SPI_CTRL, pmod_spi_ctrl_shadow);
|
|
}
|
|
|
|
void bsp_pmod_spi_init(void)
|
|
{
|
|
pmod_spi_write_ctrl(PMOD_SPI_CTRL_CSN);
|
|
}
|
|
|
|
void bsp_pmod_spi_set_mode(bsp_pmod_spi_mode_t mode)
|
|
{
|
|
uint32_t ctrl = pmod_spi_ctrl_shadow & ~PMOD_SPI_CTRL_QUAD;
|
|
if (mode == BSP_PMOD_SPI_MODE_QUAD) {
|
|
ctrl |= PMOD_SPI_CTRL_QUAD;
|
|
}
|
|
pmod_spi_write_ctrl(ctrl);
|
|
}
|
|
|
|
bsp_pmod_spi_mode_t bsp_pmod_spi_mode(void)
|
|
{
|
|
return (pmod_spi_ctrl_shadow & PMOD_SPI_CTRL_QUAD) != 0u
|
|
? BSP_PMOD_SPI_MODE_QUAD
|
|
: BSP_PMOD_SPI_MODE_SINGLE;
|
|
}
|
|
|
|
void bsp_pmod_spi_set_quad(int enabled)
|
|
{
|
|
bsp_pmod_spi_set_mode(enabled ? BSP_PMOD_SPI_MODE_QUAD : BSP_PMOD_SPI_MODE_SINGLE);
|
|
}
|
|
|
|
void bsp_pmod_spi_select(void)
|
|
{
|
|
pmod_spi_write_ctrl(pmod_spi_ctrl_shadow & ~PMOD_SPI_CTRL_CSN);
|
|
}
|
|
|
|
void bsp_pmod_spi_deselect(void)
|
|
{
|
|
pmod_spi_write_ctrl(pmod_spi_ctrl_shadow | PMOD_SPI_CTRL_CSN);
|
|
}
|
|
|
|
int bsp_pmod_spi_ready(void)
|
|
{
|
|
return ((bsp_read32(PMOD_SPI_READY) & 1u) != 0u) &&
|
|
((bsp_read32(PMOD_SPI_CTRL) & PMOD_SPI_CTRL_BUSY) == 0u);
|
|
}
|
|
|
|
uint32_t bsp_pmod_spi_ctrl(void)
|
|
{
|
|
return bsp_read32(PMOD_SPI_CTRL);
|
|
}
|
|
|
|
uint32_t bsp_pmod_spi_rx(void)
|
|
{
|
|
return bsp_read32(PMOD_SPI_RX);
|
|
}
|
|
|
|
uint8_t bsp_pmod_spi_xfer8(uint8_t value)
|
|
{
|
|
pmod_spi_wait_ready();
|
|
bsp_pmod_spi_set_mode(BSP_PMOD_SPI_MODE_SINGLE);
|
|
bsp_write32(PMOD_SPI_TX, ((uint32_t)value) << 24);
|
|
pmod_spi_wait_ready();
|
|
return (uint8_t)(bsp_read32(PMOD_SPI_RX) & 0xffu);
|
|
}
|
|
|
|
uint32_t bsp_pmod_spi_xfer32(uint32_t value)
|
|
{
|
|
pmod_spi_wait_ready();
|
|
bsp_pmod_spi_set_mode(BSP_PMOD_SPI_MODE_QUAD);
|
|
bsp_write32(PMOD_SPI_TX, value);
|
|
pmod_spi_wait_ready();
|
|
return bsp_read32(PMOD_SPI_RX);
|
|
}
|
|
|
|
void bsp_pmod_spi_transfer(const uint8_t *tx, uint8_t *rx, size_t len)
|
|
{
|
|
for (size_t i = 0; i < len; ++i) {
|
|
uint8_t out = tx ? tx[i] : 0xffu;
|
|
uint8_t in = bsp_pmod_spi_xfer8(out);
|
|
if (rx) {
|
|
rx[i] = in;
|
|
}
|
|
}
|
|
}
|