[flashrom] [PATCH] Fast flash read speed with FTDI FT2232H programmer

Boris Baykov dev at borisbaykov.com
Sun Jan 18 06:50:57 CET 2015


The patch increases flash read speed via FTDI FT2232H programmer.
New ft2232_spi_read function used instead of spi_read_chunked
to read by 64k chunks instead of 256b chunks.

According to 3-7 ms FTDI delay for each flash instruction
this patch makes read operation faster in about 10 times.

To have stable transfers with 64k buffer SPI frequency should
be decreased to 5 MHz. I don't know why but higher freqs
aren't working correct. DEFAULT_DIVISOR is changed to 12.

Signed-off-by: Boris Baykov <dev at borisbaykov.com>, Russia, Jan 2015
---
diff -U 5 -N ./flashrom/ft2232_spi.c ./flashrom.fast_ftdi/ft2232_spi.c
--- ./flashrom/ft2232_spi.c     2015-01-08 15:21:54.000000000 +0300
+++ ./flashrom.fast_ftdi/ft2232_spi.c   2015-01-18 08:44:26.000000000 +0300
@@ -27,10 +27,11 @@
 #include <ctype.h>
 #include "flash.h"
 #include "programmer.h"
 #include "spi.h"
 #include <ftdi.h>
+#include "chipdrivers.h"
 
 /* This is not defined in libftdi.h <0.20 (c7e4c09e68cfa6f5e112334aa1b3bb23401c8dc7 to be exact).
  * Some tests indicate that his is the only change that it is needed to support the FT232H in flashrom. */
 #if !defined(HAVE_FT232H)
 #define TYPE_232H      6
@@ -73,11 +74,14 @@
        {OLIMEX_VID, OLIMEX_ARM_TINY_H_PID, OK, "Olimex", "ARM-USB-TINY-H"},
 
        {0},
 };
 
-#define DEFAULT_DIVISOR 2
+/* Default divisor has been changed to 12 to provide 5 MHz frequency.
+ * This frequency is maximum stable frequency for operate with 64k buffer.
+ */
+#define DEFAULT_DIVISOR 12
 
 #define BITMODE_BITBANG_NORMAL 1
 #define BITMODE_BITBANG_SPI    2
 
 /* Set data bits low-byte command:
@@ -144,17 +148,20 @@
 static int ft2232_spi_send_command(struct flashctx *flash,
                                   unsigned int writecnt, unsigned int readcnt,
                                   const unsigned char *writearr,
                                   unsigned char *readarr);
 
+static int ft2232_spi_read(struct flashctx *flash, uint8_t *buf,
+                           unsigned int start, unsigned int len);
+
 static const struct spi_master spi_master_ft2232 = {
        .type           = SPI_CONTROLLER_FT2232,
        .max_data_read  = 64 * 1024,
        .max_data_write = 256,
        .command        = ft2232_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
-       .read           = default_spi_read,
+       .read           = ft2232_spi_read,
        .write_256      = default_spi_write_256,
        .write_aai      = default_spi_write_aai,
 };
 
 /* Returns 0 upon success, a negative number upon errors. */
@@ -294,10 +301,15 @@
                        msg_perr("Error: Invalid SPI frequency divisor specified: \"%s\".\n"
                                 "Valid are even values between 2 and 131072.\n", arg);
                        free(arg);
                        return -2;
                } else {
+                       if (temp < DEFAULT_DIVISOR) {
+                               msg_pinfo("\nWarning: SPI frequency is too high for FT2232H with 64k buffer.\n"
+                                         "Some data from SPI may be lost. To ensure stability please\n"
+                                         "encrease the divisor value at least to %d.\n\n", DEFAULT_DIVISOR);
+                       }
                        divisor = (uint32_t)temp;
                }
        }
        free(arg);
 
@@ -486,6 +498,53 @@
                msg_perr("send_buf failed at end: %i\n", ret);
 
        return failed ? -1 : 0;
 }
 
+/* FIXME: This function is optimized so that it does not split each transaction
+ * into chip page_size long blocks unnecessarily like spi_read_chunked. This has
+ * the advantage that it is much faster for most chips, but breaks those with
+ * non-continuous reads. When spi_read_chunked is fixed this method can be removed. */
+static int ft2232_spi_read(struct flashctx *flash, uint8_t *buf,
+                           unsigned int start, unsigned int len)
+{
+       int ret;
+       unsigned int i, cur_len;
+       const unsigned int max_read = spi_master_ft2232.max_data_read;
+       int show_progress = 0;
+       unsigned int percent_last = 0, percent_current = 0;
+
+       /* progress visualizaion init */
+       if(len >= MIN_LENGTH_TO_SHOW_READ_PROGRESS) {
+               msg_cinfo(" "); /* only this space will go to logfile but
+                                all strings with \b wont. */
+               msg_cinfo("\b 0%%");
+               percent_last = percent_current = 0;
+               show_progress = 1; /* enable progress visualizaion */
+       }
+
+       for (i = 0; i < len; i += cur_len) {
+               cur_len = min(max_read, (len - i));
+               ret = (flash->chip->feature_bits & FEATURE_4BA_SUPPORT) == 0
+                       ? spi_nbyte_read(flash, start + i, buf + i, cur_len)
+                       : flash->chip->four_bytes_addr_funcs.read_nbyte(flash,
+                                                start + i, buf + i, cur_len);
+               if (ret)
+                       break;
+
+               if(show_progress) {
+                       percent_current = (unsigned int)
+                           (((unsigned long long)(i + cur_len)) * 100 / len);
+                       if(percent_current != percent_last) {
+                               msg_cinfo("\b\b\b%2d%%", percent_current);
+                               percent_last = percent_current;
+                       }
+               }
+       }
+
+       if(show_progress && !ret)
+               msg_cinfo("\b\b\b\b"); /* remove progress percents from the screen */
+
+       return ret;
+}
+
 #endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: flashrom-r1868-fastftdi.patch
Type: application/octet-stream
Size: 4606 bytes
Desc: not available
URL: <http://www.flashrom.org/pipermail/flashrom/attachments/20150118/5d49f82e/attachment.obj>


More information about the flashrom mailing list