diff --git a/src/device.hpp b/src/device.hpp index cb396df..d4dd21b 100644 --- a/src/device.hpp +++ b/src/device.hpp @@ -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; diff --git a/src/main.cpp b/src/main.cpp index 3b0b89c..3f2a249 100644 --- a/src/main.cpp +++ b/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(args->bulk_erase_flash)) + ("enable-quad", "Enable quad mode for SPI Flash", + cxxopts::value(args->enable_quad)) + ("disable-quad", "Disable quad mode for SPI Flash", + cxxopts::value(args->disable_quad)) ("target-flash", "for boards with multiple flash chips (some Xilinx UltraScale" " boards), select the target flash: primary (default), secondary or both", @@ -1047,6 +1071,8 @@ int parse_opt(int argc, char **argv, struct arguments *args, !args->detect && !args->protect_flash && !args->unprotect_flash && + !args->enable_quad && + !args->disable_quad && !args->bulk_erase_flash && !args->xvc && !args->reset && diff --git a/src/spiInterface.cpp b/src/spiInterface.cpp index 09f616b..571b6ec 100644 --- a/src/spiInterface.cpp +++ b/src/spiInterface.cpp @@ -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; diff --git a/src/spiInterface.hpp b/src/spiInterface.hpp index 6566df2..c502d99 100644 --- a/src/spiInterface.hpp +++ b/src/spiInterface.hpp @@ -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;} diff --git a/src/xilinx.cpp b/src/xilinx.cpp index 1ecc342..7e5332d 100644 --- a/src/xilinx.cpp +++ b/src/xilinx.cpp @@ -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) { diff --git a/src/xilinx.hpp b/src/xilinx.hpp index ae4dfa5..8993fb4 100644 --- a/src/xilinx.hpp +++ b/src/xilinx.hpp @@ -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 */