Nico Huber has submitted this change. ( https://review.coreboot.org/c/flashrom/+/57810 )
Change subject: ft2232_spi: reintroduce generic GPIOL control ......................................................................
ft2232_spi: reintroduce generic GPIOL control
This reintroduces a reworked version of the GPIOL pin control first introduced in commit 3207844 (CB:49637), which was reverted in commit 6518cf3 (CB:55692) due to breakage.
This change introduces a new argument `gpiolX` to allow use of the four GPIOL pins either as generic gpios or as additional CS# signal(s). `X` specifies the GPIOL pin (0-3) to be set to one of [HLC] with the following meaning:
* H - set the pin as output high * L - set the pin as output low * C - use the pin as additional CS# signal
The third value, `C`, aims to replace the parameter `csgpiol`, that is now marked as deprecated and can be removed at some point in the future. `gpiol` and `csgpiol` are mutually exclusive and use of both results in an error.
Multiple pins may be set by specifying the parameter multiple times.
Documentation was updated/added accordingly.
Test: All pin levels/modes have been verified to behave correctly with a logic analyzer.
Change-Id: I3989f0f9596c090de52dca67183b1363dae59d3a Signed-off-by: Alan Green avg@google.com Signed-off-by: Michael Niewöhner foss@mniewoehner.de Reviewed-on: https://review.coreboot.org/c/flashrom/+/57810 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Nico Huber nico.h@gmx.de --- M flashrom.8.tmpl M ft2232_spi.c 2 files changed, 109 insertions(+), 9 deletions(-)
Approvals: build bot (Jenkins): Verified Nico Huber: Looks good to me, approved
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl index de93453..989d677 100644 --- a/flashrom.8.tmpl +++ b/flashrom.8.tmpl @@ -883,12 +883,42 @@ syntax. .sp Using the parameter -.B csgpiol +.B csgpiol (DEPRECATED - use gpiol instead) an additional CS# pin can be chosen, where the value can be a number between 0 and 3, denoting GPIOL0-GPIOL3 correspondingly. Example: .sp .B " flashrom -p ft2232_spi:csgpiol=3" .sp +The parameter +.B gpiolX=[HLC] +allows use of the GPIOL pins either as generic gpios with a fixed value during flashing or as addtional CS# +signal, where +.B X +can be a number between 0 and 3, denoting GPIOL0-GPIOL3 correspondingly. The parameter may be specified +multiple times, one time per GPIOL pin. +Valid values are +.B H +, +.B L +and +.B C +: +.br +.B " H " +- Set GPIOL output high +.br +.B " L " +- Set GPIOL output low +.br +.B " C " +- Use GPIOL as additional CS# output +.sp +.B Example: +.sp +.B " flashrom -p ft2232_spi:gpiol0=H" +.sp +.B Note +that not all GPIOL pins are freely usable with all programmers as some have special functionality. .SS .BR "serprog " programmer .IP diff --git a/ft2232_spi.c b/ft2232_spi.c index 110bdec..65326f9 100644 --- a/ft2232_spi.c +++ b/ft2232_spi.c @@ -91,9 +91,10 @@ * to high and will be toggled during SPI transactions. All other * output pins will be kept low all the time. For some programmers, * some reserved GPIOL* pins are used as outputs. Free GPIOL* pins - * are configured as inputs, while it's possible to use one of them - * as additional CS# signal through the parameter `csgpiol`. On exit, - * all pins will be reconfigured as inputs. + * are configured as inputs, while it's possible to use them either + * as generic gpios or as additional CS# signal(s) through the + * parameter(s) `gpiolX`. On exit, all pins will be reconfigured + * as inputs. * * The pin offsets are as follows: * TCK/SK is bit 0. @@ -112,6 +113,7 @@ */ struct ft2232_data { uint8_t cs_bits; + uint8_t aux_bits; uint8_t pindir; struct ftdi_context ftdic_context; }; @@ -233,7 +235,8 @@
msg_pspew("Assert CS#\n"); buf[i++] = SET_BITS_LOW; - buf[i++] = 0; /* assert CS# pins, all other output pins stay low */ + /* assert CS# pins, keep aux_bits, all other output pins stay low */ + buf[i++] = spi_data->aux_bits; buf[i++] = spi_data->pindir;
/* WREN, OP(PROGRAM, ERASE), ADDR, DATA */ @@ -255,7 +258,7 @@ /* Add final de-assert CS# */ msg_pspew("De-assert CS#\n"); buf[i++] = SET_BITS_LOW; - buf[i++] = spi_data->cs_bits; + buf[i++] = spi_data->cs_bits | spi_data->aux_bits; buf[i++] = spi_data->pindir;
/* continue if there is no read-cmd and further cmds exist */ @@ -325,6 +328,7 @@ double mpsse_clk;
uint8_t cs_bits = 0x08; + uint8_t aux_bits = 0x00; uint8_t pindir = 0x0b; struct ftdi_context ftdic; struct ft2232_data *spi_data; @@ -470,8 +474,13 @@ } free(arg);
+ bool csgpiol_set = false; arg = extract_programmer_param("csgpiol"); if (arg) { + csgpiol_set = true; + msg_pwarn("Deprecation warning: `csgpiol` is deprectated and will be removed " + "in the future.\nUse `gpiolX=C` instead.\n"); + char *endptr; unsigned int temp = strtoul(arg, &endptr, 10); if (*endptr || endptr == arg || temp > 3) { @@ -480,8 +489,8 @@ free(arg); return -2; } - unsigned int pin = temp + 4;
+ unsigned int pin = temp + 4; if (rsv_bits & 1 << pin) { msg_perr("Error: Invalid GPIOL specified: "%s".\n" "The pin is reserved on this programmer.\n", @@ -491,10 +500,70 @@ }
cs_bits |= 1 << pin; - pindir |= 1 << pin; + pindir |= 1 << pin; } free(arg);
+ /* gpiolX */ + for (int pin = 0; pin < 4; pin++) { + char gpiol_param[7]; + snprintf(gpiol_param, sizeof(gpiol_param), "gpiol%d", pin); + arg = extract_programmer_param(gpiol_param); + + if (!arg) + continue; + + if (csgpiol_set) { + msg_perr("Error: `csgpiol` and `gpiolX` are mutually exclusive.\n" + "Since `csgpiol` is deprecated and will be removed in the " + "future, use of `gpiolX=C` is recommended.\n"); + free(arg); + return -2; + } + + uint8_t bit = 1 << (pin + 4); + if (rsv_bits & bit) { + msg_perr("Error: Invalid GPIOL specified: "gpiol%d=%s".\n" + "Pin GPIOL%i is reserved on this programmer.\n", + pin, arg, pin); + free(arg); + return -2; + } + + if (strlen(arg) != 1) + goto format_error; + + switch (toupper(arg[0])) { + case 'H': + aux_bits |= bit; + pindir |= bit; + break; + case 'L': + pindir |= bit; + break; + case 'C': + cs_bits |= bit; + pindir |= bit; + break; + default: + goto format_error; + } + + free(arg); + continue; + +format_error: + msg_perr("Error: Invalid GPIOL specified: "gpiol%d=%s".\n" + "Valid values are H, L and C.\n" + " H - Set GPIOL output high\n" + " L - Set GPIOL output low\n" + " C - Use GPIOL as additional CS# output\n", + pin, arg); + + free(arg); + return -2; + } + msg_pdbg("Using device type %s %s ", get_ft2232_vendorname(ft2232_vid, ft2232_type), get_ft2232_devicename(ft2232_vid, ft2232_type)); @@ -577,7 +646,7 @@
msg_pdbg("Set data bits\n"); buf[0] = SET_BITS_LOW; - buf[1] = cs_bits; + buf[1] = cs_bits | aux_bits; buf[2] = pindir; if (send_buf(&ftdic, buf, 3)) { ret = -8; @@ -590,6 +659,7 @@ return SPI_GENERIC_ERROR; } spi_data->cs_bits = cs_bits; + spi_data->aux_bits = aux_bits; spi_data->pindir = pindir; spi_data->ftdic_context = ftdic;