Files
gps/soc/software/bsp/drivers/pmod_spi.c
T
2026-07-12 11:01:51 +03:00

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;
}
}
}