gowin: Improved eraseSRAM/SPI Flash prepare for Arora V devices

This commit is contained in:
Gwenhael Goavec-Merou 2025-03-26 13:14:32 +01:00
parent f7b7e77a47
commit 5ced26c3f6
1 changed files with 45 additions and 32 deletions

View File

@ -911,7 +911,10 @@ bool Gowin::eraseSRAM()
// is set // is set
bool auto_boot_2nd_fail = (status & (1 << 4)) == (1 << 4); bool auto_boot_2nd_fail = (status & (1 << 4)) == (1 << 4);
bool is_timeout = (status & (1 << 3)) == (1 << 3); bool is_timeout = (status & (1 << 3)) == (1 << 3);
if (is_gw5a && (is_timeout || auto_boot_2nd_fail)) { bool bad_cmd = (status & STATUS_BAD_COMMAND) == STATUS_BAD_COMMAND;
uint8_t loop = 0;
bool must_loop = is_gw5a;
if (is_gw5a && (is_timeout || auto_boot_2nd_fail || bad_cmd)) {
send_command(CONFIG_ENABLE); send_command(CONFIG_ENABLE);
send_command(0x3F); send_command(0x3F);
send_command(CONFIG_DISABLE); send_command(CONFIG_DISABLE);
@ -920,36 +923,44 @@ bool Gowin::eraseSRAM()
send_command(NOOP); send_command(NOOP);
_jtag->toggleClk(125 * 8); _jtag->toggleClk(125 * 8);
} }
do {
if (!enableCfg()) { if (!enableCfg()) {
printError("FAIL"); printError("FAIL");
return false; return false;
} }
send_command(ERASE_SRAM); send_command(ERASE_SRAM);
send_command(NOOP); send_command(NOOP);
/* TN653 specifies to wait for 4ms with /* TN653 specifies to wait for 4ms with
* clock generated but * clock generated but
* status register bit MEMORY_ERASE goes low when ERASE_SRAM * status register bit MEMORY_ERASE goes low when ERASE_SRAM
* is send and goes high after erase * is send and goes high after erase
* this check seems enough * this check seems enough
*/ */
if (_idcode == 0x0001081b) // seems required for GW5AST... if (_idcode == 0x0001081b) // seems required for GW5AST...
sendClkUs(10000); sendClkUs(10000);
if (pollFlag(STATUS_MEMORY_ERASE, STATUS_MEMORY_ERASE)) { if (pollFlag(STATUS_MEMORY_ERASE, STATUS_MEMORY_ERASE)) {
if (_verbose) if (_verbose)
displayReadReg("after erase sram", readStatusReg()); displayReadReg("after erase sram", readStatusReg());
} else { } else {
printError("FAIL"); printError("FAIL");
return false; return false;
} }
send_command(XFER_DONE); send_command(XFER_DONE);
send_command(NOOP); send_command(NOOP);
if (!disableCfg()) { if (!disableCfg()) {
printError("FAIL"); printError("FAIL");
return false; return false;
} }
if (is_gw5a) {
uint32_t status_reg = readStatusReg();
if ((loop >= 1) && ((status_reg & (1 << 13)) == 0))
must_loop = false;
loop++;
}
} while(must_loop);
if (_mode == Device::FLASH_MODE) { if (_mode == Device::FLASH_MODE) {
uint32_t status_reg = readStatusReg(); uint32_t status_reg = readStatusReg();
@ -1179,16 +1190,18 @@ bool Gowin::dumpFlash(uint32_t base_addr, uint32_t len)
bool Gowin::prepare_flash_access() bool Gowin::prepare_flash_access()
{ {
/* Work around FPGA stuck in Bad Command status */
if (is_gw5a) {
reset();
_jtag->set_state(Jtag::RUN_TEST_IDLE);
_jtag->toggleClk(1000000);
}
if (!eraseSRAM()) { if (!eraseSRAM()) {
printError("Error: fail to erase SRAM"); printError("Error: fail to erase SRAM");
return false; return false;
} }
if (is_gw5a) { if (is_gw5a) {
if (!eraseSRAM()) {
printError("Error: fail to erase SRAM");
return false;
}
usleep(100000); usleep(100000);
if (!gw5a_enable_spi()) { if (!gw5a_enable_spi()) {
printError("Error: fail to switch GW5A to SPI mode"); printError("Error: fail to switch GW5A to SPI mode");