Angel Pons has uploaded this change for review.

View Change

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);

To view, visit change 67906. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I36b9f5f8481907bd605e9310bef08592bb7d9827
Gerrit-Change-Number: 67906
Gerrit-PatchSet: 1
Gerrit-Owner: Angel Pons <th3fanbus@gmail.com>
Gerrit-MessageType: newchange