diff --git a/litex/soc/software/liblitespi/spiflash.c b/litex/soc/software/liblitespi/spiflash.c index cdc4552e1..e7f0cd12a 100644 --- a/litex/soc/software/liblitespi/spiflash.c +++ b/litex/soc/software/liblitespi/spiflash.c @@ -91,6 +91,135 @@ static void spiflash_master_write(uint32_t val, size_t len, size_t width, uint32 spiflash_core_master_cs_write(0); } +static volatile uint8_t w_buf[SPI_FLASH_BLOCK_SIZE + 4]; +static volatile uint8_t r_buf[SPI_FLASH_BLOCK_SIZE + 4]; + +static uint32_t transfer_byte(uint8_t b) +{ + /* wait for tx ready */ + while (!spiflash_core_master_status_tx_ready_read()); + + spiflash_core_master_rxtx_write((uint32_t)b); + + /* wait for rx ready */ + while (!spiflash_core_master_status_rx_ready_read()); + + return spiflash_core_master_rxtx_read(); +} + +static void transfer_cmd(uint8_t *bs, uint8_t *resp, int len) +{ + spiflash_core_master_phyconfig_len_write(8); + spiflash_core_master_phyconfig_width_write(1); + spiflash_core_master_phyconfig_mask_write(1); + spiflash_core_master_cs_write(1); + + for (int i=0; i < len; i++) { + resp[i] = transfer_byte(bs[i]); + } + + spiflash_core_master_cs_write(0); +} + +static uint32_t spiflash_read_status_register(void) +{ + uint8_t buf[2]; + w_buf[0] = 0x05; + w_buf[1] = 0x00; + transfer_cmd(w_buf, buf, 2); + flush_cpu_dcache(); + + /* FIXME hack: sometimes, the result is in buf[0]. + * not sure why this happens. timing? */ + if (buf[1] == 0xff) return buf[0]; + return buf[1]; +} + +static void spiflash_write_enable(void) +{ + uint8_t buf[1]; + w_buf[0] = 0x06; + transfer_cmd(w_buf, buf, 1); +} + +static void page_program(uint32_t addr, uint8_t *data, int len) +{ + w_buf[0] = 0x02; + w_buf[1] = addr>>16; + w_buf[2] = addr>>8; + w_buf[3] = addr>>0; + memcpy(w_buf+4, data, len); + flush_cpu_dcache(); + transfer_cmd(w_buf, r_buf, len+4); +} + +static void spiflash_sector_erase(uint32_t addr) +{ + w_buf[0] = 0xd8; + w_buf[1] = addr>>16; + w_buf[2] = addr>>8; + w_buf[3] = addr>>0; + flush_cpu_dcache(); + transfer_cmd(w_buf, r_buf, 4); +} + +/* erase page size in bytes, check flash datasheet */ +#define SPI_FLASH_ERASE_SIZE (64*1024) + +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +void spiflash_erase_range(uint32_t addr, uint32_t len) +{ + uint32_t i = 0; + uint32_t j = 0; + for (i=0; i