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

91 lines
1.8 KiB
C

#include "bsp/spi_flash.h"
#include "bsp/mmio.h"
#include "bsp/soc.h"
#define SPI_CTRL (BSP_SPI_BASE + 0x00u)
#define SPI_TX (BSP_SPI_BASE + 0x04u)
#define SPI_RX (BSP_SPI_BASE + 0x08u)
#define SPI_READY (BSP_SPI_BASE + 0x0cu)
#define SPI_CTRL_BUSY 0x1u
#define SPI_CTRL_CSN 0x2u
static void delay_cycles(uint32_t cycles)
{
for (volatile uint32_t i = 0; i < cycles; ++i) {
asm volatile ("" ::: "memory");
}
}
static void spi_wait_ready(void)
{
while ((bsp_read32(SPI_READY) & 1u) == 0u) {
}
while ((bsp_read32(SPI_CTRL) & SPI_CTRL_BUSY) != 0u) {
}
}
static void spi_select(int selected)
{
spi_wait_ready();
bsp_write32(SPI_CTRL, selected ? 0u : SPI_CTRL_CSN);
}
static uint8_t spi_xfer8(uint8_t value)
{
spi_wait_ready();
bsp_write32(SPI_TX, ((uint32_t)value) << 24);
spi_wait_ready();
return (uint8_t)(bsp_read32(SPI_RX) & 0xffu);
}
static void flash_cmd(uint8_t cmd)
{
spi_select(1);
(void)spi_xfer8(cmd);
spi_select(0);
}
void bsp_spi_flash_init(void)
{
bsp_write32(SPI_CTRL, SPI_CTRL_CSN);
}
void bsp_spi_flash_reset(void)
{
spi_select(0);
flash_cmd(0x66u);
delay_cycles(1000);
flash_cmd(0x99u);
delay_cycles(200000);
}
uint32_t bsp_spi_flash_read_id(void)
{
uint32_t id = 0;
spi_select(1);
(void)spi_xfer8(0x9fu);
id |= ((uint32_t)spi_xfer8(0u)) << 16;
id |= ((uint32_t)spi_xfer8(0u)) << 8;
id |= (uint32_t)spi_xfer8(0u);
spi_select(0);
return id;
}
void bsp_spi_flash_read(uint32_t flash_addr, void *dst, uint32_t len)
{
uint8_t *out = (uint8_t *)dst;
spi_select(1);
(void)spi_xfer8(0x13u);
(void)spi_xfer8((uint8_t)(flash_addr >> 24));
(void)spi_xfer8((uint8_t)(flash_addr >> 16));
(void)spi_xfer8((uint8_t)(flash_addr >> 8));
(void)spi_xfer8((uint8_t)flash_addr);
for (uint32_t i = 0; i < len; ++i) {
out[i] = spi_xfer8(0u);
}
spi_select(0);
}