On Sun, 28 Jun 2015 16:52:51 -0700 David Hendricks david.hendricks@gmail.com wrote:
Sounds good to me.
Acked-by: David Hendricks dhendrix@chromium.org
Thanks, r1896.
On Sun, 2015-07-05 at 19:09 +0200, Stefan Tauner wrote:
On Sun, 28 Jun 2015 16:52:51 -0700 David Hendricks david.hendricks@gmail.com wrote:
Sounds good to me.
Acked-by: David Hendricks dhendrix@chromium.org
Thanks, r1896.
Here's an updated version of the next patch in the sequence. I've tested this with an SF100 V:5.2.00 and a Winbind W25Q128.V in an Intel Skylake board, and it seems to be working.
Have we now resolved the issue discussed at http://www.flashrom.org/pipermail/flashrom/2013-June/011074.html which was preventing us from enabling dediprog (SF100) support by default?
----- From: Stefan Tauner stefan.tauner@alumni.tuwien.ac.at Date: Mon, 22 Jun 2015 03:37:23 +0200 Subject: [PATCH] dediprog: Support new communication protocol.
There are some changed commands, so adjust the code to support these. Use helper functions to reduce duplication in libusb calls.
Based on the following chromiumos change: Change-Id: Ibd1e27d9e8273ba879b9b5d95675b99596255c89
Signed-off-by: Simon Glass sjg@chromium.org Signed-off-by: Stefan Tauner stefan.tauner@alumni.tuwien.ac.at --- dediprog.c | 125 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 41 deletions(-)
diff --git a/dediprog.c b/dediprog.c index 996d2d7..7ccac12 100644 --- a/dediprog.c +++ b/dediprog.c @@ -141,6 +141,27 @@ static void print_hex(void *buf, size_t len) } #endif
+/* Returns true if firmware (and thus hardware) supports the "new" protocol */ +static bool is_new_prot(void) +{ + /* if (SF100) */ + return dediprog_firmwareversion >= FIRMWARE_VERSION(5, 5, 0); + /* else if (SF600) + return dediprog_firmwareversion >= FIRMWARE_VERSION(6, 9, 0); */ +} + +static int dediprog_read(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, uint8_t *bytes, size_t size) +{ + return usb_control_msg(dediprog_handle, REQTYPE_EP_IN, cmd, value, idx, + (char *)bytes, size, DEFAULT_TIMEOUT); +} + +static int dediprog_write(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, const uint8_t *bytes, size_t size) +{ + return usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, cmd, value, idx, + (char *)bytes, size, DEFAULT_TIMEOUT); +} + /* Might be useful for other USB devices as well. static for now. */ /* device parameter allows user to specify one device of multiple installed */ static struct usb_device *get_device_by_vid_pid(uint16_t vid, uint16_t pid, unsigned int device) @@ -166,24 +187,30 @@ static int dediprog_set_leds(int leds) if (leds < LED_NONE || leds > LED_ALL) leds = LED_ALL;
- /* Older Dediprogs with 2.x.x and 3.x.x firmware only had - * two LEDs, and they were reversed. So map them around if - * we have an old device. On those devices the LEDs map as - * follows: + /* Older Dediprogs with 2.x.x and 3.x.x firmware only had two LEDs, assigned to different bits. So map + * them around if we have an old device. On those devices the LEDs map as follows: * bit 2 == 0: green light is on. - * bit 0 == 0: red light is on. + * bit 0 == 0: red light is on. + * + * Additionally, the command structure has changed with the "new" protocol. + * + * FIXME: take IO pins into account */ - int target_leds; - if (dediprog_firmwareversion < FIRMWARE_VERSION(5,0,0)) { - target_leds = ((leds & LED_ERROR) >> 2) | - ((leds & LED_PASS) << 2); + int target_leds, ret; + if (is_new_prot()) { + target_leds = (leds ^ 7) << 8; + ret = dediprog_write(CMD_SET_IO_LED, target_leds, 0, NULL, 0); } else { - target_leds = leds; + if (dediprog_firmwareversion < FIRMWARE_VERSION(5, 0, 0)) { + target_leds = ((leds & LED_ERROR) >> 2) | ((leds & LED_PASS) << 2); + } else { + target_leds = leds; + } + target_leds ^= 7; + + ret = dediprog_write(CMD_SET_IO_LED, 0x9, target_leds, NULL, 0); }
- target_leds ^= 7; - int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_SET_IO_LED, 0x09, target_leds, - NULL, 0x0, DEFAULT_TIMEOUT); if (ret != 0x0) { msg_perr("Command Set LED 0x%x failed (%s)!\n", leds, usb_strerror()); return 1; @@ -222,8 +249,7 @@ static int dediprog_set_spi_voltage(int millivolt) /* Wait some time as the original driver does. */ programmer_delay(200 * 1000); } - ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_SET_VCC, voltage_selector, 0, - NULL, 0x0, DEFAULT_TIMEOUT); + ret = dediprog_write(CMD_SET_VCC, voltage_selector, 0, NULL, 0); if (ret != 0x0) { msg_perr("Command Set SPI Voltage 0x%x failed!\n", voltage_selector); @@ -263,8 +289,7 @@ static int dediprog_set_spi_speed(unsigned int spispeed_idx) const struct dediprog_spispeeds *spispeed = &spispeeds[spispeed_idx]; msg_pdbg("SPI speed is %sHz\n", spispeed->name);
- int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_SET_SPI_CLK, spispeed->speed, 0xff, - NULL, 0x0, DEFAULT_TIMEOUT); + int ret = dediprog_write(CMD_SET_SPI_CLK, spispeed->speed, 0, NULL, 0); if (ret != 0x0) { msg_perr("Command Set SPI Speed 0x%x failed!\n", spispeed->speed); return 1; @@ -285,10 +310,7 @@ static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf, /* chunksize must be 512, other sizes will NOT work at all. */ const unsigned int chunksize = 0x200; const unsigned int count = len / chunksize; - const char count_and_chunk[] = {count & 0xff, - (count >> 8) & 0xff, - chunksize & 0xff, - (chunksize >> 8) & 0xff}; + unsigned int cmd_len;
if ((start % chunksize) || (len % chunksize)) { msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug " @@ -299,15 +321,34 @@ static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf, /* No idea if the hardware can handle empty reads, so chicken out. */ if (!len) return 0; - /* Command Read SPI Bulk. No idea which read command is used on the - * SPI side. - */ - ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_READ, start % 0x10000, - start / 0x10000, (char *)count_and_chunk, - sizeof(count_and_chunk), DEFAULT_TIMEOUT); - if (ret != sizeof(count_and_chunk)) { - msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret, - usb_strerror()); + /* Command Read SPI Bulk. */ + if (is_new_prot()) { + const uint8_t read_cmd[] = { + count & 0xff, + (count >> 8) & 0xff, + 0, + READ_MODE_FAST, + 0, + 0, + start & 0xff, + (start >> 8) & 0xff, + (start >> 16) & 0xff, + (start >> 24) & 0xff, + }; + + cmd_len = sizeof(read_cmd); + ret = dediprog_write(CMD_READ, 0, 0, read_cmd, cmd_len); + } else { + const uint8_t read_cmd[] = {count & 0xff, + (count >> 8) & 0xff, + chunksize & 0xff, + (chunksize >> 8) & 0xff}; + + cmd_len = sizeof(read_cmd); + ret = dediprog_write(CMD_READ, start % 0x10000, start / 0x10000, read_cmd, cmd_len); + } + if (ret != cmd_len) { + msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret, usb_strerror()); return 1; }
@@ -515,8 +556,12 @@ static int dediprog_spi_send_command(struct flashctx *flash, return 1; } - ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_TRANSCEIVE, 0, readcnt ? 0x1 : 0x0, - (char *)writearr, writecnt, DEFAULT_TIMEOUT); + /* New protocol has the read flag as value while the old protocol had it in the index field. */ + if (is_new_prot()) { + ret = dediprog_write(CMD_TRANSCEIVE, readcnt ? 1 : 0, 0, writearr, writecnt); + } else { + ret = dediprog_write(CMD_TRANSCEIVE, 0, readcnt ? 1 : 0, writearr, writecnt); + } if (ret != writecnt) { msg_perr("Send SPI failed, expected %i, got %i %s!\n", writecnt, ret, usb_strerror()); @@ -525,8 +570,7 @@ static int dediprog_spi_send_command(struct flashctx *flash, if (readcnt == 0) return 0;
- ret = usb_control_msg(dediprog_handle, REQTYPE_EP_IN, CMD_TRANSCEIVE, 0, 0, - (char *)readarr, readcnt, DEFAULT_TIMEOUT); + ret = dediprog_read(CMD_TRANSCEIVE, 0, 0, readarr, readcnt); if (ret != readcnt) { msg_perr("Receive SPI failed, expected %i, got %i %s!\n", readcnt, ret, usb_strerror()); @@ -553,8 +597,7 @@ static int dediprog_check_devicestring(void) } #endif /* Command Receive Device String. */ - ret = usb_control_msg(dediprog_handle, REQTYPE_EP_IN, CMD_READ_PROG_INFO, 0, 0, - buf, 0x10, DEFAULT_TIMEOUT); + ret = dediprog_read(CMD_READ_PROG_INFO, 0, 0, (uint8_t *)buf, 0x10); if (ret != 0x10) { msg_perr("Incomplete/failed Command Receive Device String!\n"); return 1; @@ -566,16 +609,16 @@ static int dediprog_check_devicestring(void) return 1; } if (sscanf(buf, "SF100 V:%d.%d.%d ", &fw[0], &fw[1], &fw[2]) != 3) { - msg_perr("Unexpected firmware version string!\n"); + msg_perr("Unexpected firmware version string '%s'\n", buf); return 1; } - /* Only these versions were tested. */ - if (fw[0] < 2 || fw[0] > 5) { - msg_perr("Unexpected firmware version %d.%d.%d!\n", fw[0], - fw[1], fw[2]); + /* Only these major versions were tested. */ + if (fw[0] < 2 || fw[0] > 6) { + msg_perr("Unexpected firmware version %d.%d.%d!\n", fw[0], fw[1], fw[2]); return 1; } dediprog_firmwareversion = FIRMWARE_VERSION(fw[0], fw[1], fw[2]); + return 0; }
On Thu, 2015-07-09 at 16:59 +0100, David Woodhouse wrote:
Here's an updated version of the next patch in the sequence.
...
From: Stefan Tauner stefan.tauner@alumni.tuwien.ac.at Date: Mon, 22 Jun 2015 03:37:23 +0200 Subject: [PATCH] dediprog: Support new communication protocol.
On top of that, I tried the patch at http://git.infradead.org/users/dwmw2/flashrom.git/commitdiff/81ad0cc50 to attempt to enable SF600 support. I got someone to test it for me on an SF600Plus with firmware 7.1.1. It doesn't work.
Firstly, whatever dediprog_device_init() is doing is not covered by the recently-provided documentation for *either* the old or the new protocol, and the SF600 doesn't like it:
Unexpected response to init! Error: Programmer initialization failed.
If we just comment that out, and also make it accept firmware v7, then we can successfully identify a W25Q64.W chip and read sane-looking contents from it. Writes fail, though:
Calibrating delay loop... OS timer resolution is 1 usecs, 3206M loops per second, delay more than 10% too short (got 84% of expected delay), recalculating... 3512M loops per second, 10 myus = 15 us, 100 myus = 175 us, 1000 myus = 1643 us, 10000 myus = 16156 us, 4 myus = 16 us, OK. Initializing dediprog programmer dediprog_init Setting voltage to 1800 mV Found USB device (0483:dada). ANDY: stubbing dediprog_device_init Found a SF600 V:7.1.1 Unexpected firmware version 7.1.1! SPI speed is 12MHz Setting SPI voltage to 1.800 V The following protocols are supported: SPI. Probing for AMIC A25L05PT, 64 kB: programmer_map_flash_region: mapping A25L05PT from 0x00000000ffff0000 to 0x0000000000000000 dediprog_spi_send_command, writecnt=1, readcnt=4 RDID returned 0xef 0x60 0x17 0x00. probe_spi_rdid_generic: id1 0xef, id2 0x6017 programmer_unmap_flash_region: unmapped 0x0000000000000000 ... Probing for Generic unknown SPI chip (REMS), 0 kB: dediprog_spi_send_command, writecnt=4, readcnt=2 REMS returned 0xef 0x16. probe_spi_rems: id1 0xef, id2 0x16 Found Winbond flash chip "W25Q64.W" (8192 kB, SPI). This chip may contain one-time programmable memory. flashrom cannot read and may never be able to write it, hence it may not be able to completely clone the contents of this chip (see man page for details). programmer_map_flash_region: mapping W25Q64.W from 0x00000000ff800000 to 0x0000000000000000 dediprog_spi_send_command, writecnt=1, readcnt=2 Block protection is disabled. Reading old flash chip contents... done. Erasing and writing flash chip... Trying erase function 0... 0x000000-0x000fff:Edediprog_spi_send_command, writecnt=1, readcnt=0 dediprog_spi_send_command, writecnt=4, readcnt=0 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 FAILED at 0x00000226! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x00000fff: 0x1da ERASE FAILED! Reading current flash chip contents... done. Looking for another erase function. Trying erase function 1... 0x000000-0x007fff:Edediprog_spi_send_command, writecnt=1, readcnt=0 dediprog_spi_send_command, writecnt=4, readcnt=0 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 FAILED at 0x0000089d! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x00007fff: 0x356 ERASE FAILED! Reading current flash chip contents... done. Looking for another erase function. Trying erase function 2... 0x000000-0x00ffff:Edediprog_spi_send_command, writecnt=1, readcnt=0 dediprog_spi_send_command, writecnt=4, readcnt=0 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 FAILED at 0x00000e0e! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x0000ffff: 0x5d5 ERASE FAILED! Reading current flash chip contents... done. Looking for another erase function. Trying erase function 3... 0x000000-0x7fffff:Edediprog_spi_send_command, writecnt=1, readcnt=0 dediprog_spi_send_command, writecnt=1, readcnt=0 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 FAILED at 0x000009ee! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x007fffff: 0x26fb4 ERASE FAILED! Reading current flash chip contents... done. Looking for another erase function. Trying erase function 4... 0x000000-0x7fffff:Edediprog_spi_send_command, writecnt=1, readcnt=0 dediprog_spi_send_command, writecnt=1, readcnt=0 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 dediprog_spi_send_command, writecnt=1, readcnt=2 FAILED at 0x00001a0f! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x007fffff: 0x26f6b ERASE FAILED! Looking for another erase function. No usable erase functions left. FAILED! Uh oh. Erase/write failed. Checking if anything has changed. Reading current flash chip contents... done. Apparently at least some data has changed. Your flash chip is in an unknown state. Please report this on IRC at chat.freenode.net (channel #flashrom) or mail flashrom@flashrom.org, thanks! programmer_unmap_flash_region: unmapped 0x0000000000000000 dediprog_shutdown Setting SPI voltage to 0.000 V
On Thu, Jul 9, 2015 at 9:24 AM, David Woodhouse dwmw2@infradead.org wrote:
On Thu, 2015-07-09 at 16:59 +0100, David Woodhouse wrote:
Here's an updated version of the next patch in the sequence.
...
From: Stefan Tauner stefan.tauner@alumni.tuwien.ac.at Date: Mon, 22 Jun 2015 03:37:23 +0200 Subject: [PATCH] dediprog: Support new communication protocol.
On top of that, I tried the patch at http://git.infradead.org/users/dwmw2/flashrom.git/commitdiff/81ad0cc50 to attempt to enable SF600 support. I got someone to test it for me on an SF600Plus with firmware 7.1.1. It doesn't work.
Firstly, whatever dediprog_device_init() is doing is not covered by the recently-provided documentation for *either* the old or the new protocol, and the SF600 doesn't like it:
Unexpected response to init! Error: Programmer initialization failed.
If we just comment that out, and also make it accept firmware v7, then we can successfully identify a W25Q64.W chip and read sane-looking contents from it. Writes fail, though:
I tried this out on an SF600 Plus (FW 7.1.4) and got the same result. Though if we comment it out, then subsequent commands on the SF100 (FW 5.1.5) fail :-/
Attempting to write using the SF600 gives me: flashrom v0.9.8-r1896 on Linux 4.0.4-gentoo (x86_64) flashrom is free software, get the source code at http://www.flashrom.org
flashrom was built with libpci 3.3.1, GCC 4.7.3, little endian Command line (5 args): ./flashrom -V -p dediprog -w /tmp/random_2M.bin Calibrating delay loop... OS timer resolution is 1 usecs, 1299M loops per second, 10 myus = 11 us, 100 myus = 100 us, 1000 myus = 999 us, 10000 myus = 9999 us, 4 myus = 5 us, OK. Initializing dediprog programmer Found USB device (0483:dada). Found a SF600 V:7.1.4 SPI speed is 12MHz Setting SPI voltage to 3.500 V The following protocols are supported: SPI. Probing for AMIC A25L05PT, 64 kB: probe_spi_rdid_generic: id1 0xef, id2 0x4015 ... Found Winbond flash chip "W25Q16.V" (2048 kB, SPI). This chip may contain one-time programmable memory. flashrom cannot read and may never be able to write it, hence it may not be able to completely clone the contents of this chip (see man page for details). Reading old flash chip contents... done. Erasing and writing flash chip... Trying erase function 0... 0x000000-0x000fff:WSPI bulk write failed, expected 512, got -5 Input/output error! Command Set LED 0x4 failed (Connection timed out)! Reading current flash chip contents... Command Set LED 0x2 failed (Connection timed out)! Command Read SPI Bulk failed, -110 Connection timed out! Command Set LED 0x4 failed (Connection timed out)! Can't read anymore! Aborting. FAILED! Uh oh. Erase/write failed. Checking if anything has changed. Reading current flash chip contents... Command Set LED 0x2 failed (Connection timed out)! Command Read SPI Bulk failed, -110 Connection timed out! Command Set LED 0x4 failed (Connection timed out)! Can't even read anymore! Your flash chip is in an unknown state. Please report this on IRC at chat.freenode.net (channel #flashrom) or mail flashrom@flashrom.org, thanks! Setting SPI voltage to 0.000 V Command Set SPI Voltage 0x0 failed!