mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 07:02:34 +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:
parent
106f097ef6
commit
7b9c74f496
@ -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
|
||||
|
86
ft2232_spi.c
86
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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user