From 502d847b41e7ee80ccffb253afaae8c72e983a01 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Thu, 26 Mar 2020 09:44:57 +0100 Subject: iceprog: Add option that set QE=1 bit in SR2 This is useful when testing litex SoC that rely on that bit being set The setting is non-volatile so it only needs to be done once in case you happen to have used a flash chip that's not by default QE=1 (This has been designed for winbond flash. Others might use different bit ...) Signed-off-by: Sylvain Munaut --- iceprog/iceprog.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c index 20b05a4..8c3827b 100644 --- a/iceprog/iceprog.c +++ b/iceprog/iceprog.c @@ -446,6 +446,34 @@ static void flash_disable_protection() } +static void flash_enable_quad() +{ + fprintf(stderr, "Enabling Quad operation...\n"); + + // Allow write + flash_write_enable(); + + // Write Status Register 2 <- 0x02 + uint8_t data[2] = { FC_WSR2, 0x02 }; + flash_chip_select(); + mpsse_xfer_spi(data, 2); + flash_chip_deselect(); + + flash_wait(); + + // Read Status Register 1 + data[0] = FC_RSR2; + + flash_chip_select(); + mpsse_xfer_spi(data, 2); + flash_chip_deselect(); + + if ((data[1] & 0x02) != 0x02) + fprintf(stderr, "failed to set QE=1, SR2 now equal to 0x%02x (expected 0x%02x)\n", data[1], data[1] | 0x02); + + fprintf(stderr, "SR2: %08x\n", data[1]); +} + // --------------------------------------------------------- // iceprog implementation // --------------------------------------------------------- @@ -484,6 +512,7 @@ static void help(const char *progname) fprintf(stderr, " -c do not write flash, only verify (`check')\n"); fprintf(stderr, " -S perform SRAM programming\n"); fprintf(stderr, " -t just read the flash ID sequence\n"); + fprintf(stderr, " -Q just set the flash QE=1 bit\n"); fprintf(stderr, "\n"); fprintf(stderr, "Erase mode (only meaningful in default mode):\n"); fprintf(stderr, " [default] erase aligned chunks of 64kB in write mode\n"); @@ -543,7 +572,7 @@ int main(int argc, char **argv) bool bulk_erase = false; bool dont_erase = false; bool prog_sram = false; - bool test_mode = false; + int test_mode = 0; bool slow_clock = false; bool disable_protect = false; bool disable_verify = false; @@ -565,7 +594,7 @@ int main(int argc, char **argv) /* Decode command line parameters */ int opt; char *endptr; - while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStvspXk", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStQvspXk", long_options, NULL)) != -1) { switch (opt) { case 'd': /* device string */ devstr = optarg; @@ -653,7 +682,10 @@ int main(int argc, char **argv) prog_sram = true; break; case 't': /* just read flash id */ - test_mode = true; + test_mode = 1; + break; + case 'Q': /* just read flash id */ + test_mode = 2; break; case 'v': /* provide verbose output */ verbose = true; @@ -682,7 +714,7 @@ int main(int argc, char **argv) /* Make sure that the combination of provided parameters makes sense */ - if (read_mode + erase_mode + check_mode + prog_sram + test_mode > 1) { + if (read_mode + erase_mode + check_mode + prog_sram + !!test_mode > 1) { fprintf(stderr, "%s: options `-r'/`-R', `-e`, `-c', `-S', and `-t' are mutually exclusive\n", my_name); return EXIT_FAILURE; } @@ -840,7 +872,10 @@ int main(int argc, char **argv) flash_reset(); flash_power_up(); - flash_read_id(); + if (test_mode == 1) + flash_read_id(); + else + flash_enable_quad(); flash_power_down(); -- cgit v1.2.3 From c5a8beffec05c906b0f3a06eed1f2820d11d8b15 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 2 Jun 2020 10:31:17 +0200 Subject: iceprog: Improve reset to disable both CRM and QPI It's hard to cover 100% of cases, but this seems to improve probability that a reset works, at least for me on the icebreaker. Some other flash have a different QPI disable command though :/ Signed-off-by: Sylvain Munaut --- iceprog/iceprog.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c index 8c3827b..34245e3 100644 --- a/iceprog/iceprog.c +++ b/iceprog/iceprog.c @@ -202,9 +202,15 @@ static void flash_reset() { uint8_t data[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + // This disables CRM is if it was enabled flash_chip_select(); mpsse_xfer_spi(data, 8); flash_chip_deselect(); + + // This disables QPI if it was enable + flash_chip_select(); + mpsse_xfer_spi_bits(0xFF, 2); + flash_chip_deselect(); } static void flash_power_up() -- cgit v1.2.3 From 98d8bee04f2d51fa0e9d5804f0525e89618bce96 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 2 Jun 2020 10:31:46 +0200 Subject: iceprog: Use open-drain output to drive SS and Reset line Signed-off-by: Sylvain Munaut --- iceprog/iceprog.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c index 34245e3..c671ac1 100644 --- a/iceprog/iceprog.c +++ b/iceprog/iceprog.c @@ -96,16 +96,16 @@ enum flash_cmd { static void set_cs_creset(int cs_b, int creset_b) { uint8_t gpio = 0; - uint8_t direction = 0x93; + uint8_t direction = 0x03; - if (cs_b) { + if (!cs_b) { // ADBUS4 (GPIOL0) - gpio |= 0x10; + direction |= 0x10; } - if (creset_b) { + if (!creset_b) { // ADBUS7 (GPIOL3) - gpio |= 0x80; + direction |= 0x80; } mpsse_set_gpio(gpio, direction); -- cgit v1.2.3