core: added option/methods to enable/disable quad mode on SPI Flash
This commit is contained in:
parent
e0b841f5b1
commit
d38083517c
|
|
@ -53,6 +53,9 @@ class Device {
|
|||
printError("dump flash not supported"); return false;}
|
||||
virtual bool protect_flash(uint32_t len) = 0;
|
||||
virtual bool unprotect_flash() = 0;
|
||||
virtual bool set_quad_bit(bool set_quad) {
|
||||
(void)set_quad;
|
||||
printError("Error: SPI Flash Quad mode configuration unsupported"); return false;}
|
||||
virtual bool bulk_erase_flash() = 0;
|
||||
|
||||
virtual uint32_t idCode() = 0;
|
||||
|
|
|
|||
26
src/main.cpp
26
src/main.cpp
|
|
@ -81,6 +81,8 @@ struct arguments {
|
|||
string ip_adr;
|
||||
uint32_t protect_flash;
|
||||
bool unprotect_flash;
|
||||
bool enable_quad;
|
||||
bool disable_quad;
|
||||
bool bulk_erase_flash;
|
||||
string flash_sector;
|
||||
bool skip_load_bridge;
|
||||
|
|
@ -123,7 +125,7 @@ int main(int argc, char **argv)
|
|||
-1, 0, "primary", false, -1,
|
||||
/* vid, pid, index bus_addr, device_addr */
|
||||
0, 0, -1, 0, 0,
|
||||
"127.0.0.1", 0, false, false, "", false, false,
|
||||
"127.0.0.1", 0, false, false, false, false, "", false, false,
|
||||
/* xvc server */
|
||||
false, 3721, "-",
|
||||
"", false, {}, // mcufw conmcu, user_misc_dev_list
|
||||
|
|
@ -636,6 +638,24 @@ int main(int argc, char **argv)
|
|||
fpga->protect_flash(args.protect_flash);
|
||||
}
|
||||
|
||||
/* Enable/disable SPI Flash quad mode */
|
||||
if (args.enable_quad || args.disable_quad) {
|
||||
bool ret = true;
|
||||
if (args.enable_quad && args.disable_quad) {
|
||||
printError("Error: can't set enable and disable Quad mode at same time");
|
||||
ret = false;
|
||||
} else if (!fpga->set_quad_bit(args.enable_quad)) {
|
||||
printError("Error: Failed to enable/disable Quad mode");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
delete(fpga);
|
||||
delete(jtag);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* detect/display flash */
|
||||
if (args.detect_flash != 0) {
|
||||
fpga->detect_flash();
|
||||
|
|
@ -769,6 +789,10 @@ int parse_opt(int argc, char **argv, struct arguments *args,
|
|||
("dump-flash", "Dump flash mode")
|
||||
("bulk-erase", "Bulk erase flash",
|
||||
cxxopts::value<bool>(args->bulk_erase_flash))
|
||||
("enable-quad", "Enable quad mode for SPI Flash",
|
||||
cxxopts::value<bool>(args->enable_quad))
|
||||
("disable-quad", "Disable quad mode for SPI Flash",
|
||||
cxxopts::value<bool>(args->disable_quad))
|
||||
("target-flash",
|
||||
"for boards with multiple flash chips (some Xilinx UltraScale"
|
||||
" boards), select the target flash: primary (default), secondary or both",
|
||||
|
|
|
|||
|
|
@ -891,26 +891,36 @@ int SPIFlash::enable_protection(uint32_t length)
|
|||
|
||||
bool SPIFlash::set_quad_bit(bool set_quad)
|
||||
{
|
||||
uint8_t reg_wr, reg_rd, reg_val, reg_val_verif;
|
||||
uint8_t reg_wr, reg_rd; // read/write registers code
|
||||
uint16_t reg_val;
|
||||
uint32_t nb_rd_byte = 1; // Number of bytes to read (may differ from Flash models).
|
||||
uint32_t nb_wr_byte = 1; // Number of bytes to write.
|
||||
uint16_t quad_bit = 0; // quad_mask copy when bit must be set
|
||||
|
||||
if (!_flash_model) {
|
||||
printError("spiFlash Error: can't configure Quad mode on unknown SPI Flash");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_flash_model->quad_offset == 0 || _flash_model->quad_register == NONER) {
|
||||
if (_flash_model->quad_mask == 0 || _flash_model->quad_register == NONER) {
|
||||
printError("spiFlash Error: SPI Flash has no Quad bit (or spiFlashdb must be updated)");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (_flash_model->quad_register) {
|
||||
case STATR:
|
||||
reg_wr = FLASH_WRSR;
|
||||
reg_rd = FLASH_RDSR;
|
||||
reg_wr = FLASH_WRSR;
|
||||
break;
|
||||
case NVCONFR:
|
||||
reg_rd = FLASH_RDNVCR;
|
||||
reg_wr = FLASH_WRNVCR;
|
||||
nb_rd_byte = nb_wr_byte = 2;
|
||||
break;
|
||||
case CONFR:
|
||||
reg_wr = FLASH_WRSR;
|
||||
reg_rd = FLASH_RDCR;
|
||||
reg_wr = FLASH_WRSR;
|
||||
nb_wr_byte = 2;
|
||||
break;
|
||||
default:
|
||||
printError("spiFlash Error: Unsupported register for Quad Enable bit configuration");
|
||||
|
|
@ -918,12 +928,17 @@ bool SPIFlash::set_quad_bit(bool set_quad)
|
|||
}
|
||||
|
||||
/* Read current register value */
|
||||
_spi->spi_put(reg_rd, NULL, ®_val, 1);
|
||||
/* Only update Quad bit */
|
||||
if (set_quad)
|
||||
reg_val |= _flash_model->quad_offset;
|
||||
else
|
||||
reg_val &= ~_flash_model->quad_offset;
|
||||
_spi->spi_put(reg_rd, NULL, (uint8_t *)®_val, nb_rd_byte);
|
||||
reg_val &= ~_flash_model->quad_mask; // mask quad bit
|
||||
|
||||
/* Micron: enable 0, disable 1 */
|
||||
if (_jedec_id == 0x20BA)
|
||||
set_quad = ~set_quad;
|
||||
if (set_quad) // set quad_bit when required
|
||||
quad_bit = _flash_model->quad_mask;
|
||||
|
||||
/* update Quad bit */
|
||||
reg_val |= quad_bit;
|
||||
|
||||
/* enable write access */
|
||||
if (write_enable() != 0) {
|
||||
|
|
@ -931,25 +946,31 @@ bool SPIFlash::set_quad_bit(bool set_quad)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Write register with the updated value */
|
||||
if (_flash_model->quad_register == CONFR) {
|
||||
uint8_t status = read_status_reg();
|
||||
uint8_t write_val[2] = {status, reg_val};
|
||||
_spi->spi_put(reg_wr, write_val, NULL, 2);
|
||||
} else {
|
||||
_spi->spi_put(reg_wr, ®_val, NULL, 1);
|
||||
/* Configuration register has no dedicated write instruction
|
||||
* -> a 16bits sequence must be sent to status register
|
||||
*/
|
||||
switch (_flash_model->quad_register) {
|
||||
case CONFR:
|
||||
uint8_t status = read_status_reg();
|
||||
reg_val = ((reg_val & 0xff) << 8) | status;
|
||||
_spi->spi_put(reg_wr, (uint8_t*) ®_val, NULL, nb_wr_byte);
|
||||
break;
|
||||
}
|
||||
|
||||
/* disable write access (wait for completion) */
|
||||
if (write_enable() != 0) {
|
||||
printError("SPIFlash Error: failed to enable write");
|
||||
/* Write register with the updated value */
|
||||
_spi->spi_put(reg_wr, (uint8_t *)®_val, NULL, nb_wr_byte);
|
||||
|
||||
/* Wait for completion */
|
||||
if (_spi->spi_wait(FLASH_RDSR, FLASH_RDSR_WEL, 0x00, 1000) != 0) {
|
||||
printError("SPIFlash Error: failed to disable write");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check if current value match written value */
|
||||
_spi->spi_put(reg_rd, NULL, ®_val_verif, 1);
|
||||
/* Check if register is correctly updated */
|
||||
_spi->spi_put(reg_rd, NULL, (uint8_t *)®_val, nb_rd_byte);
|
||||
|
||||
if ((reg_val_verif & _flash_model->quad_offset) == (reg_val & _flash_model->quad_offset)) {
|
||||
if ((reg_val & _flash_model->quad_mask) == quad_bit) {
|
||||
printf("%04x %04x %04x\n", reg_val, reg_val & _flash_model->quad_mask, quad_bit);
|
||||
printError("SPIFlash Error: failed to update Quad bit");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,37 @@ bool SPIInterface::unprotect_flash()
|
|||
return post_flash_access() && ret;
|
||||
}
|
||||
|
||||
bool SPIInterface::set_quad_bit(bool set_quad)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
/* move device to spi access */
|
||||
if (!prepare_flash_access()) {
|
||||
printError("SPI Flash prepare access failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* spi flash access */
|
||||
try {
|
||||
SPIFlash flash(this, false, _spif_verbose);
|
||||
|
||||
/* configure flash protection */
|
||||
printInfo("set_quad_bit: ", false);
|
||||
ret = flash.set_quad_bit(set_quad);
|
||||
if (!ret)
|
||||
printError("Fail");
|
||||
else
|
||||
printSuccess("Done");
|
||||
} catch (std::exception &e) {
|
||||
printError("SPI Flash access failed: ", false);
|
||||
printError(e.what());
|
||||
ret = false;
|
||||
}
|
||||
|
||||
/* reload bitstream */
|
||||
return post_flash_access() && ret;
|
||||
}
|
||||
|
||||
bool SPIInterface::bulk_erase_flash()
|
||||
{
|
||||
bool ret = true;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class SPIInterface {
|
|||
bool detect_flash();
|
||||
bool protect_flash(uint32_t len);
|
||||
bool unprotect_flash();
|
||||
bool set_quad_bit(bool set_quad);
|
||||
bool bulk_erase_flash();
|
||||
void set_filename(const std::string &filename) {_spif_filename = filename;}
|
||||
|
||||
|
|
|
|||
|
|
@ -1197,6 +1197,21 @@ bool Xilinx::unprotect_flash()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Xilinx::set_quad_bit(bool set_quad)
|
||||
{
|
||||
if (_flash_chips & PRIMARY_FLASH) {
|
||||
select_flash_chip(PRIMARY_FLASH);
|
||||
if (!SPIInterface::set_quad_bit(set_quad))
|
||||
return false;
|
||||
}
|
||||
if (_flash_chips & SECONDARY_FLASH) {
|
||||
select_flash_chip(SECONDARY_FLASH);
|
||||
if (!SPIInterface::set_quad_bit(set_quad))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Xilinx::bulk_erase_flash()
|
||||
{
|
||||
if (_flash_chips & PRIMARY_FLASH) {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,10 @@ class Xilinx: public Device, SPIInterface {
|
|||
* \brief unprotect SPI flash blocks
|
||||
*/
|
||||
bool unprotect_flash() override;
|
||||
/*!
|
||||
* \brief configure Quad mode for SPI Flash
|
||||
*/
|
||||
bool set_quad_bit(bool set_quad) override;
|
||||
/*!
|
||||
* \brief erase SPI flash blocks
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue