1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 15:12:36 +02:00

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>
This commit is contained in:
Michael Niewöhner 2021-09-21 20:15:32 +02:00 committed by Nico Huber
parent 106f097ef6
commit 7b9c74f496
2 changed files with 109 additions and 9 deletions

View File

@ -883,12 +883,42 @@ parameter with the
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

View File

@ -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",
@ -495,6 +504,66 @@ static int ft2232_spi_init(void)
}
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;