From 7b9c74f49607dda18243138e87d71b773cec7a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Niew=C3=B6hner?= Date: Tue, 21 Sep 2021 20:15:32 +0200 Subject: ft2232_spi: reintroduce generic GPIOL control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Michael Niewöhner Reviewed-on: https://review.coreboot.org/c/flashrom/+/57810 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- ft2232_spi.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 8 deletions(-) (limited to 'ft2232_spi.c') diff --git a/ft2232_spi.c b/ft2232_spi.c index 110bdece..65326f9a 100644 --- a/ft2232_spi.c +++ b/ft2232_spi.c @@ -91,9 +91,10 @@ static const struct dev_entry devs_ft2232spi[] = { * 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 @@ static const struct dev_entry devs_ft2232spi[] = { */ struct ft2232_data { uint8_t cs_bits; + uint8_t aux_bits; uint8_t pindir; struct ftdi_context ftdic_context; }; @@ -233,7 +235,8 @@ static int ft2232_spi_send_multicommand(const struct flashctx *flash, struct spi 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 @@ static int ft2232_spi_send_multicommand(const struct flashctx *flash, struct spi /* 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 @@ static int ft2232_spi_init(void) 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 @@ static int ft2232_spi_init(void) } 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 @@ static int ft2232_spi_init(void) 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 @@ static int ft2232_spi_init(void) } 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 @@ static int ft2232_spi_init(void) 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 @@ static int ft2232_spi_init(void) 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; -- cgit v1.2.3