Angel Pons has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/67906 )
Change subject: ft2232_spi.c: Add struct for programmer params ......................................................................
ft2232_spi.c: Add struct for programmer params
Introduce a struct to store ft2232_spi programmer parameters. This struct allows separating the parsing of programmer params from the code that uses the values, which should allow specifying parameter values directly into the struct.
Change-Id: I36b9f5f8481907bd605e9310bef08592bb7d9827 Signed-off-by: Angel Pons th3fanbus@gmail.com --- M ft2232_spi.c 1 file changed, 126 insertions(+), 94 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/06/67906/1
diff --git a/ft2232_spi.c b/ft2232_spi.c index 6d7aa6a..c8772a7 100644 --- a/ft2232_spi.c +++ b/ft2232_spi.c @@ -304,22 +304,13 @@ .probe_opcode = default_spi_probe_opcode, };
-/* Returns 0 upon success, a negative number upon errors. */ -static int ft2232_spi_init(const struct programmer_cfg *cfg) -{ - int ret = 0; - unsigned char buf[512]; - int ft2232_vid = FTDI_VID; - int ft2232_type = FTDI_FT4232H_PID; - int channel_count = 4; /* Stores the number of channels of the device. */ - enum ftdi_interface ft2232_interface = INTERFACE_A; +struct ft2232_parameters { + int ft2232_vid; + int ft2232_type; + enum ftdi_interface ft2232_interface; + /* - * 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 disable the divide-by-5 - * prescaler on 'H' chips so they run at 60MHz. - */ - bool clock_5x = true; - /* In addition to the prescaler mentioned above there is also another + * In addition to the divide-by-5 prescaler 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 @@ -328,115 +319,141 @@ * 92 Hz for 12 MHz inputs and 30 MHz down to about 458 Hz for 60 MHz * inputs. */ - uint32_t divisor = DEFAULT_DIVISOR; + uint32_t divisor; + uint8_t cs_bits; + uint8_t aux_bits; + uint8_t pindir; + uint8_t aux_bits_high; + uint8_t pindir_high; +}; + +/* Returns 0 upon success, a negative number upon errors. */ +static int ft2232_spi_init(const struct programmer_cfg *cfg) +{ + int ret = 0; + unsigned char buf[512]; + int channel_count = 4; /* Stores the number of channels of the device. */ + /* + * 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 disable the divide-by-5 + * prescaler on 'H' chips so they run at 60MHz. + */ + bool clock_5x = true; int f; char *arg, *arg2; double mpsse_clk;
- uint8_t cs_bits = 0x08; - uint8_t aux_bits = 0x00; - uint8_t pindir = 0x0b; - uint8_t aux_bits_high = 0x00; - uint8_t pindir_high = 0x00; + struct ft2232_parameters parameters = { + .ft2232_vid = FTDI_VID, + .ft2232_type = FTDI_FT4232H_PID, + .ft2232_interface = INTERFACE_A, + .divisor = DEFAULT_DIVISOR, + .cs_bits = 0x08, + .aux_bits = 0x00, + .pindir = 0x0b, + .aux_bits_high = 0x00, + .pindir_high = 0x00, + }; + struct ftdi_context ftdic; struct ft2232_data *spi_data;
arg = extract_programmer_param_str(cfg, "type"); if (arg) { if (!strcasecmp(arg, "2232H")) { - ft2232_type = FTDI_FT2232H_PID; + parameters.ft2232_type = FTDI_FT2232H_PID; channel_count = 2; } else if (!strcasecmp(arg, "4232H")) { - ft2232_type = FTDI_FT4232H_PID; + parameters.ft2232_type = FTDI_FT4232H_PID; channel_count = 4; } else if (!strcasecmp(arg, "232H")) { - ft2232_type = FTDI_FT232H_PID; + parameters.ft2232_type = FTDI_FT232H_PID; channel_count = 1; } else if (!strcasecmp(arg, "4233H")) { - ft2232_type = FTDI_FT4233H_PID; + parameters.ft2232_type = FTDI_FT4233H_PID; channel_count = 4; } else if (!strcasecmp(arg, "jtagkey")) { - ft2232_type = AMONTEC_JTAGKEY_PID; + parameters.ft2232_type = AMONTEC_JTAGKEY_PID; channel_count = 2; /* JTAGkey(2) needs to enable its output via Bit4 / GPIOL0 * value: 0x18 OE=high, CS=high, DI=low, DO=low, SK=low * dir: 0x1b OE=output, CS=output, DI=input, DO=output, SK=output */ - cs_bits = 0x18; - pindir = 0x1b; + parameters.cs_bits = 0x18; + parameters.pindir = 0x1b; } else if (!strcasecmp(arg, "picotap")) { - ft2232_vid = GOEPEL_VID; - ft2232_type = GOEPEL_PICOTAP_PID; + parameters.ft2232_vid = GOEPEL_VID; + parameters.ft2232_type = GOEPEL_PICOTAP_PID; channel_count = 2; } else if (!strcasecmp(arg, "tumpa")) { /* Interface A is SPI1, B is SPI2. */ - ft2232_type = TIAO_TUMPA_PID; + parameters.ft2232_type = TIAO_TUMPA_PID; channel_count = 2; } else if (!strcasecmp(arg, "tumpalite")) { /* Only one channel is used on lite edition */ - ft2232_type = TIAO_TUMPA_LITE_PID; + parameters.ft2232_type = TIAO_TUMPA_LITE_PID; channel_count = 1; } else if (!strcasecmp(arg, "busblaster")) { /* In its default configuration it is a jtagkey clone */ - ft2232_type = FTDI_FT2232H_PID; + parameters.ft2232_type = FTDI_FT2232H_PID; channel_count = 2; - cs_bits = 0x18; - pindir = 0x1b; + parameters.cs_bits = 0x18; + parameters.pindir = 0x1b; } else if (!strcasecmp(arg, "openmoko")) { - ft2232_vid = FIC_VID; - ft2232_type = OPENMOKO_DBGBOARD_PID; + parameters.ft2232_vid = FIC_VID; + parameters.ft2232_type = OPENMOKO_DBGBOARD_PID; channel_count = 2; } else if (!strcasecmp(arg, "arm-usb-ocd")) { - ft2232_vid = OLIMEX_VID; - ft2232_type = OLIMEX_ARM_OCD_PID; + parameters.ft2232_vid = OLIMEX_VID; + parameters.ft2232_type = OLIMEX_ARM_OCD_PID; channel_count = 2; /* arm-usb-ocd(-h) has an output buffer that needs to be enabled by pulling ADBUS4 low. * value: 0x08 #OE=low, CS=high, DI=low, DO=low, SK=low * dir: 0x1b #OE=output, CS=output, DI=input, DO=output, SK=output */ - cs_bits = 0x08; - pindir = 0x1b; + parameters.cs_bits = 0x08; + parameters.pindir = 0x1b; } else if (!strcasecmp(arg, "arm-usb-tiny")) { - ft2232_vid = OLIMEX_VID; - ft2232_type = OLIMEX_ARM_TINY_PID; + parameters.ft2232_vid = OLIMEX_VID; + parameters.ft2232_type = OLIMEX_ARM_TINY_PID; channel_count = 2; } else if (!strcasecmp(arg, "arm-usb-ocd-h")) { - ft2232_vid = OLIMEX_VID; - ft2232_type = OLIMEX_ARM_OCD_H_PID; + parameters.ft2232_vid = OLIMEX_VID; + parameters.ft2232_type = OLIMEX_ARM_OCD_H_PID; channel_count = 2; /* See arm-usb-ocd */ - cs_bits = 0x08; - pindir = 0x1b; + parameters.cs_bits = 0x08; + parameters.pindir = 0x1b; } else if (!strcasecmp(arg, "arm-usb-tiny-h")) { - ft2232_vid = OLIMEX_VID; - ft2232_type = OLIMEX_ARM_TINY_H_PID; + parameters.ft2232_vid = OLIMEX_VID; + parameters.ft2232_type = OLIMEX_ARM_TINY_H_PID; channel_count = 2; } else if (!strcasecmp(arg, "google-servo")) { - ft2232_vid = GOOGLE_VID; - ft2232_type = GOOGLE_SERVO_PID; + parameters.ft2232_vid = GOOGLE_VID; + parameters.ft2232_type = GOOGLE_SERVO_PID; } else if (!strcasecmp(arg, "google-servo-v2")) { - ft2232_vid = GOOGLE_VID; - ft2232_type = GOOGLE_SERVO_V2_PID1; + parameters.ft2232_vid = GOOGLE_VID; + parameters.ft2232_type = GOOGLE_SERVO_V2_PID1; /* Default divisor is too fast, and chip ID fails */ - divisor = 6; + parameters.divisor = 6; } else if (!strcasecmp(arg, "google-servo-v2-legacy")) { - ft2232_vid = GOOGLE_VID; - ft2232_type = GOOGLE_SERVO_V2_PID0; + parameters.ft2232_vid = GOOGLE_VID; + parameters.ft2232_type = GOOGLE_SERVO_V2_PID0; } else if (!strcasecmp(arg, "flyswatter")) { - ft2232_type = FTDI_FT2232H_PID; + parameters.ft2232_type = FTDI_FT2232H_PID; channel_count = 2; /* Flyswatter and Flyswatter-2 require GPIO bits 0x80 * and 0x40 to be driven low to enable output buffers */ - pindir = 0xcb; + parameters.pindir = 0xcb; } else if (!strcasecmp(arg, "kt-link")) { - ft2232_type = KT_LINK_PID; + parameters.ft2232_type = KT_LINK_PID; /* port B is used as uart */ channel_count = 1; /* Set GPIOL1 output high - route TMS and TDO through multiplexers */ - aux_bits = 0x20; - pindir = 0x2b; + parameters.aux_bits = 0x20; + parameters.pindir = 0x2b; /* Set GPIOH4 output low - enable TMS output buffer */ /* Set GPIOH5 output low - enable TDI output buffer */ /* Set GPIOH6 output low - enable TCK output buffer */ - pindir_high = 0x70; + parameters.pindir_high = 0x70; } else { msg_perr("Error: Invalid device type specified.\n"); free(arg); @@ -445,27 +462,27 @@ } free(arg);
- /* Remember reserved pins before pindir gets modified. */ - const uint8_t rsv_bits = pindir & 0xf0; + /* Remember reserved pins before parameters.pindir gets modified. */ + const uint8_t rsv_bits = parameters.pindir & 0xf0;
arg = extract_programmer_param_str(cfg, "port"); if (arg) { switch (toupper((unsigned char)*arg)) { case 'A': - ft2232_interface = INTERFACE_A; + parameters.ft2232_interface = INTERFACE_A; break; case 'B': - ft2232_interface = INTERFACE_B; + parameters.ft2232_interface = INTERFACE_B; if (channel_count < 2) channel_count = -1; break; case 'C': - ft2232_interface = INTERFACE_C; + parameters.ft2232_interface = INTERFACE_C; if (channel_count < 3) channel_count = -1; break; case 'D': - ft2232_interface = INTERFACE_D; + parameters.ft2232_interface = INTERFACE_D; if (channel_count < 4) channel_count = -1; break; @@ -492,7 +509,7 @@ free(arg); return -2; } - divisor = (uint32_t)temp; + parameters.divisor = (uint32_t)temp; } free(arg);
@@ -521,8 +538,8 @@ return -2; }
- cs_bits |= 1 << pin; - pindir |= 1 << pin; + parameters.cs_bits |= 1 << pin; + parameters.pindir |= 1 << pin; } free(arg);
@@ -557,15 +574,15 @@
switch (toupper(arg[0])) { case 'H': - aux_bits |= bit; - pindir |= bit; + parameters.aux_bits |= bit; + parameters.pindir |= bit; break; case 'L': - pindir |= bit; + parameters.pindir |= bit; break; case 'C': - cs_bits |= bit; - pindir |= bit; + parameters.cs_bits |= bit; + parameters.pindir |= bit; break; default: goto format_error; @@ -587,26 +604,26 @@ }
msg_pdbg("Using device type %s %s ", - get_ft2232_vendorname(ft2232_vid, ft2232_type), - get_ft2232_devicename(ft2232_vid, ft2232_type)); + get_ft2232_vendorname(parameters.ft2232_vid, parameters.ft2232_type), + get_ft2232_devicename(parameters.ft2232_vid, parameters.ft2232_type)); msg_pdbg("channel %s.\n", - (ft2232_interface == INTERFACE_A) ? "A" : - (ft2232_interface == INTERFACE_B) ? "B" : - (ft2232_interface == INTERFACE_C) ? "C" : "D"); + (parameters.ft2232_interface == INTERFACE_A) ? "A" : + (parameters.ft2232_interface == INTERFACE_B) ? "B" : + (parameters.ft2232_interface == INTERFACE_C) ? "C" : "D");
if (ftdi_init(&ftdic) < 0) { msg_perr("ftdi_init failed.\n"); return -3; }
- if (ftdi_set_interface(&ftdic, ft2232_interface) < 0) { + if (ftdi_set_interface(&ftdic, parameters.ft2232_interface) < 0) { msg_perr("Unable to select channel (%s).\n", ftdi_get_error_string(&ftdic)); }
arg = extract_programmer_param_str(cfg, "serial"); arg2 = extract_programmer_param_str(cfg, "description");
- f = ftdi_usb_open_desc(&ftdic, ft2232_vid, ft2232_type, arg2, arg); + f = ftdi_usb_open_desc(&ftdic, parameters.ft2232_vid, parameters.ft2232_type, arg2, arg);
free(arg); free(arg2); @@ -648,15 +665,15 @@
msg_pdbg("Set clock divisor\n"); buf[0] = TCK_DIVISOR; - buf[1] = (divisor / 2 - 1) & 0xff; - buf[2] = ((divisor / 2 - 1) >> 8) & 0xff; + buf[1] = (parameters.divisor / 2 - 1) & 0xff; + buf[2] = ((parameters.divisor / 2 - 1) >> 8) & 0xff; if (send_buf(&ftdic, buf, 3)) { ret = -6; goto ftdi_err; }
msg_pdbg("MPSSE clock: %f MHz, divisor: %u, SPI clock: %f MHz\n", - mpsse_clk, divisor, (double)(mpsse_clk / divisor)); + mpsse_clk, parameters.divisor, (double)(mpsse_clk / parameters.divisor));
/* Disconnect TDI/DO to TDO/DI for loopback. */ msg_pdbg("No loopback of TDI/DO TDO/DI\n"); @@ -668,18 +685,18 @@
msg_pdbg("Set data bits\n"); buf[0] = SET_BITS_LOW; - buf[1] = cs_bits | aux_bits; - buf[2] = pindir; + buf[1] = parameters.cs_bits | parameters.aux_bits; + buf[2] = parameters.pindir; if (send_buf(&ftdic, buf, 3)) { ret = -8; goto ftdi_err; }
- if (pindir_high) { + if (parameters.pindir_high) { msg_pdbg("Set data bits HighByte\n"); buf[0] = SET_BITS_HIGH; - buf[1] = aux_bits_high; - buf[2] = pindir_high; + buf[1] = parameters.aux_bits_high; + buf[2] = parameters.pindir_high; if (send_buf(&ftdic, buf, 3)) { ret = -8; goto ftdi_err; @@ -691,9 +708,9 @@ msg_perr("Unable to allocate space for SPI master data\n"); return SPI_GENERIC_ERROR; } - spi_data->cs_bits = cs_bits; - spi_data->aux_bits = aux_bits; - spi_data->pindir = pindir; + spi_data->cs_bits = parameters.cs_bits; + spi_data->aux_bits = parameters.aux_bits; + spi_data->pindir = parameters.pindir; spi_data->ftdic_context = ftdic;
return register_spi_master(&spi_master_ft2232, spi_data);