diff options
author | Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> | 2012-05-15 22:58:19 +0000 |
---|---|---|
committer | Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> | 2012-05-15 22:58:19 +0000 |
commit | 90656582e2ed197bdaa97c5ad8a228eeba123460 (patch) | |
tree | e8b1e5c4405905162c711097d21308277170e05c | |
parent | d891bf283ce22c6c191e8faee4ca8e6b665adfd0 (diff) | |
download | flashrom-90656582e2ed197bdaa97c5ad8a228eeba123460.zip flashrom-90656582e2ed197bdaa97c5ad8a228eeba123460.tar.gz |
ft2232_spi.c: add frequency divisor parameter
This adds an optional argument when using the ft2232_spi programmer to set
the frequency divisor. The valid values for the divisor is any even integer
between 2 and 131072.
Binary file (standard input) matches
Corresponding to flashrom svn r1537.
-rw-r--r-- | flashrom.8 | 11 | ||||
-rw-r--r-- | ft2232_spi.c | 54 |
2 files changed, 48 insertions, 17 deletions
@@ -549,6 +549,17 @@ The default model is .B 4232H and the default interface is .BR B . +.sp +All models supported by the ft2232_spi driver can configure the SPI clock rate by setting a divisor. The +expressible divisors are all even numbers between 2 and 2^17 (=131072) resulting in SPI clock frequencies of +6 MHz down to about 92 Hz for 12 MHz inputs. The default divisor is set to 2, but you can use another one by +specifying the optional +.B divisor +parameter with the +.sp +.B " flashrom \-p ft2232_spi:divisor=div" +.sp +syntax. .SS .BR "serprog " programmer A mandatory parameter specifies either a serial diff --git a/ft2232_spi.c b/ft2232_spi.c index 122866f..d11867e 100644 --- a/ft2232_spi.c +++ b/ft2232_spi.c @@ -64,17 +64,8 @@ const struct usbdev_status devs_ft2232spi[] = { {}, }; -/* - * The 'H' chips can run internally at either 12MHz or 60MHz. - * The non-H chips can only run at 12MHz. - */ -static uint8_t clock_5x = 1; -/* - * In either case, the divisor is a simple integer clock divider. - * If clock_5x is set, this divisor divides 30MHz, else it divides 6MHz. - */ -#define DIVIDE_BY 3 /* e.g. '3' will give either 10MHz or 2MHz SPI clock. */ +#define DEFAULT_DIVISOR 2 #define BITMODE_BITBANG_NORMAL 1 #define BITMODE_BITBANG_SPI 2 @@ -162,12 +153,28 @@ static const struct spi_programmer spi_programmer_ft2232 = { /* Returns 0 upon success, a negative number upon errors. */ int ft2232_spi_init(void) { - int f, ret = 0; + int ret = 0; struct ftdi_context *ftdic = &ftdic_context; unsigned char buf[512]; int ft2232_vid = FTDI_VID; int ft2232_type = FTDI_FT4232H_PID; enum ftdi_interface ft2232_interface = INTERFACE_B; + /* + * The 'H' chips can run with an internal clock of either 12 MHz or 60 MHz, + * but the non-H chips can only run at 12 MHz. We enable the divide-by-5 + * prescaler on the former to run on the same speed. + */ + uint8_t clock_5x = 1; + /* In addition to the prescaler mentioned above there is also another + * configurable one on all versions of the chips. Its divisor div can be + * set by a 16 bit value x according to the following formula: + * div = (1 + x) * 2 <-> x = div / 2 - 1 + * Hence the expressible divisors are all even numbers between 2 and + * 2^17 (=131072) resulting in SCK frequencies of 6 MHz down to about + * 92 Hz for 12 MHz inputs. + */ + uint32_t divisor = DEFAULT_DIVISOR; + int f; char *arg; double mpsse_clk; @@ -243,6 +250,21 @@ int ft2232_spi_init(void) } } free(arg); + arg = extract_programmer_param("divisor"); + if (arg && strlen(arg)) { + unsigned int temp = 0; + char *endptr; + temp = strtoul(arg, &endptr, 10); + if (*endptr || temp < 2 || temp > 131072 || temp & 0x1) { + 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 { + divisor = (uint32_t)temp; + } + } + free(arg); msg_pdbg("Using device type %s %s ", get_ft2232_vendorname(ft2232_vid, ft2232_type), get_ft2232_devicename(ft2232_vid, ft2232_type)); @@ -303,17 +325,15 @@ int ft2232_spi_init(void) msg_pdbg("Set clock divisor\n"); buf[0] = 0x86; /* command "set divisor" */ - /* valueL/valueH are (desired_divisor - 1) */ - buf[1] = (DIVIDE_BY - 1) & 0xff; - buf[2] = ((DIVIDE_BY - 1) >> 8) & 0xff; if (send_buf(ftdic, buf, 3)) { ret = -6; goto ftdi_err; } + buf[1] = (divisor / 2 - 1) & 0xff; + buf[2] = ((divisor / 2 - 1) >> 8) & 0xff; - msg_pdbg("MPSSE clock: %f MHz divisor: %d " - "SPI clock: %f MHz\n", mpsse_clk, DIVIDE_BY, - (double)(mpsse_clk / (((DIVIDE_BY - 1) + 1) * 2))); + msg_pdbg("MPSSE clock: %f MHz, divisor: %u, SPI clock: %f MHz\n", + mpsse_clk, divisor, (double)(mpsse_clk / divisor)); /* Disconnect TDI/DO to TDO/DI for loopback. */ msg_pdbg("No loopback of TDI/DO TDO/DI\n"); |