[sw] bootloader: send wake up command to flash before trying to speak with it

The ice40 family of FPGAs, send a sleep command to the flash once it's
finished with self-programming in order to save some power [1], unless
instructed not to when generating the bitfile (icepack -s or equivalent
setting on Radiant)

We don't want the bootloader to depend on the bitfile generation settings
and thus we wake up the flash, but since we want a bootloader as small as possible,
we don't care to put it back to sleep again (because we don't even know if it was
sleeping or not) and let the user application decide what to do with it.

[1] https://www.latticesemi.com/~/media/LatticeSemi/Documents/ApplicationNotes/IK/FPGA-TN-02001-30-iCE40-Programming-Configuration.pdf?document_id=46502 , page 20
This commit is contained in:
Alvaro Gamez Machado 2023-03-16 15:23:59 +01:00
parent 7a2386beac
commit 6667dbdcc6

View file

@ -166,6 +166,7 @@ enum SPI_FLASH_CMD_enum {
SPI_FLASH_CMD_WRITE_DISABLE = 0x04, /**< Disallow write access */
SPI_FLASH_CMD_READ_STATUS = 0x05, /**< Get status register */
SPI_FLASH_CMD_WRITE_ENABLE = 0x06, /**< Allow write access */
SPI_FLASH_CMD_WAKE = 0xAB, /**< Wake up from sleep mode */
SPI_FLASH_CMD_SECTOR_ERASE = 0xD8 /**< Erase complete sector */
};
@ -245,6 +246,7 @@ void system_error(uint8_t err_code);
void print_hex_word(uint32_t num);
// SPI flash driver functions
void spi_flash_wakeup(void);
int spi_flash_check(void);
uint8_t spi_flash_read_byte(uint32_t addr);
void spi_flash_write_byte(uint32_t addr, uint8_t wdata);
@ -740,6 +742,18 @@ void print_hex_word(uint32_t num) {
// SPI flash driver functions
// -------------------------------------------------------------------------------------
/**********************************************************************//**
* Wake up flash from deep sleep state
**************************************************************************/
void spi_flash_wakeup(void) {
#if (SPI_EN != 0)
neorv32_spi_cs_en(SPI_FLASH_CS);
neorv32_spi_trans(SPI_FLASH_CMD_WAKE);
neorv32_spi_cs_dis();
#endif
}
/**********************************************************************//**
* Check if SPI and flash are available/working by making sure the WEL
* flag of the flash status register can be set and cleared again.
@ -749,6 +763,8 @@ void print_hex_word(uint32_t num) {
int spi_flash_check(void) {
#if (SPI_EN != 0)
// The flash may have been set to sleep prior to reaching this point. Make sure it's alive
spi_flash_wakeup();
// set WEL
spi_flash_write_enable();