Anastasia Klimchuk has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/54042 )
Change subject: stlinkv3_spi.c: Refactor singleton states into reentrant pattern ......................................................................
stlinkv3_spi.c: Refactor singleton states into reentrant pattern
Move global singleton states into a struct and store within the spi_master data field for the life-time of the driver.
This is one of the steps on the way to move spi_master data memory management behind the initialisation API, for more context see other patches under the same topic "register_master_api".
BUG=b:185191942 TEST=builds
Change-Id: Id044661b864b506028720ea809bc524f0640469f Signed-off-by: Anastasia Klimchuk aklm@chromium.org --- M stlinkv3_spi.c 1 file changed, 74 insertions(+), 33 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/42/54042/1
diff --git a/stlinkv3_spi.c b/stlinkv3_spi.c index 7e8336e..f1e455b 100644 --- a/stlinkv3_spi.c +++ b/stlinkv3_spi.c @@ -119,11 +119,14 @@ {0} };
-static struct libusb_context *usb_ctx; -static libusb_device_handle *stlinkv3_handle; +struct stlinkv3_spi_data { + struct libusb_context *usb_ctx; + libusb_device_handle *stlinkv3_handle; +};
static int stlinkv3_command(uint8_t *command, size_t command_length, - uint8_t *answer, size_t answer_length, const char *command_name) + uint8_t *answer, size_t answer_length, const char *command_name, + libusb_device_handle *stlinkv3_handle) { int actual_length = 0; int rc = libusb_bulk_transfer(stlinkv3_handle, STLINK_EP_OUT, @@ -151,7 +154,7 @@ /** * @param[out] bridge_input_clk Current input frequency in kHz of the given com. */ -static int stlinkv3_get_clk(uint32_t *bridge_input_clk) +static int stlinkv3_get_clk(uint32_t *bridge_input_clk, libusb_device_handle *stlinkv3_handle) { uint8_t command[16]; uint8_t answer[12]; @@ -165,7 +168,10 @@ command[1] = STLINK_BRIDGE_GET_CLOCK; command[2] = STLINK_SPI_COM;
- if (stlinkv3_command(command, sizeof(command), answer, sizeof(answer), "STLINK_BRIDGE_GET_CLOCK") != 0) + if (stlinkv3_command(command, sizeof(command), + answer, sizeof(answer), + "STLINK_BRIDGE_GET_CLOCK", + stlinkv3_handle) != 0) return -1;
*bridge_input_clk = (uint32_t)answer[4] @@ -178,13 +184,14 @@
static int stlinkv3_spi_calc_prescaler(uint16_t reqested_freq_in_kHz, enum spi_prescaler *prescaler, - uint16_t *calculated_freq_in_kHz) + uint16_t *calculated_freq_in_kHz, + libusb_device_handle *stlinkv3_handle) { uint32_t bridge_clk_in_kHz; uint32_t calculated_prescaler = 1; uint16_t prescaler_value;
- if (stlinkv3_get_clk(&bridge_clk_in_kHz)) + if (stlinkv3_get_clk(&bridge_clk_in_kHz, stlinkv3_handle)) return -1;
calculated_prescaler = bridge_clk_in_kHz/reqested_freq_in_kHz; @@ -224,7 +231,7 @@ return 0; }
-static int stlinkv3_check_version(enum fw_version_check_result *result) +static int stlinkv3_check_version(enum fw_version_check_result *result, libusb_device_handle *stlinkv3_handle) { uint8_t answer[12]; uint8_t command[16]; @@ -234,7 +241,10 @@ command[0] = ST_GETVERSION_EXT; command[1] = 0x80;
- if (stlinkv3_command(command, sizeof(command), answer, sizeof(answer), "ST_GETVERSION_EXT") != 0) + if (stlinkv3_command(command, sizeof(command), + answer, sizeof(answer), + "ST_GETVERSION_EXT", + stlinkv3_handle) != 0) return -1;
msg_pinfo("Connected to STLink V3 with bridge FW version: %d\n", answer[4]); @@ -244,7 +254,7 @@ return 0; }
-static int stlinkv3_spi_open(uint16_t reqested_freq_in_kHz) +static int stlinkv3_spi_open(uint16_t reqested_freq_in_kHz, libusb_device_handle *stlinkv3_handle) { uint8_t command[16]; uint8_t answer[2]; @@ -252,7 +262,7 @@ enum spi_prescaler prescaler; enum fw_version_check_result fw_check_result;
- if (stlinkv3_check_version(&fw_check_result)) { + if (stlinkv3_check_version(&fw_check_result, stlinkv3_handle)) { msg_perr("Failed to query FW version\n"); return -1; } @@ -267,7 +277,8 @@
if (stlinkv3_spi_calc_prescaler(reqested_freq_in_kHz, &prescaler, - &SCK_freq_in_kHz)) { + &SCK_freq_in_kHz, + stlinkv3_handle)) { msg_perr("Failed to calculate SPI clock prescaler\n"); return -1; } @@ -286,10 +297,13 @@ command[5] = SPI_NSS_SOFT; command[6] = (uint8_t)prescaler;
- return stlinkv3_command(command, sizeof(command), answer, sizeof(answer), "STLINK_BRIDGE_INIT_SPI"); + return stlinkv3_command(command, sizeof(command), + answer, sizeof(answer), + "STLINK_BRIDGE_INIT_SPI", + stlinkv3_handle); }
-static int stlinkv3_get_last_readwrite_status(uint32_t *status) +static int stlinkv3_get_last_readwrite_status(uint32_t *status, libusb_device_handle *stlinkv3_handle) { uint8_t command[16]; uint16_t answer[4]; @@ -301,14 +315,15 @@
if (stlinkv3_command(command, sizeof(command), (uint8_t *)answer, sizeof(answer), - "STLINK_BRIDGE_GET_RWCMD_STATUS") != 0) + "STLINK_BRIDGE_GET_RWCMD_STATUS", + stlinkv3_handle) != 0) return -1;
*status = (uint32_t)answer[2] | (uint32_t)answer[3]<<16; return 0; }
-static int stlinkv3_spi_set_SPI_NSS(enum spi_nss_level nss_level) +static int stlinkv3_spi_set_SPI_NSS(enum spi_nss_level nss_level, libusb_device_handle *stlinkv3_handle) { uint8_t command[16]; uint8_t answer[2]; @@ -319,7 +334,10 @@ command[1] = STLINK_BRIDGE_CS_SPI; command[2] = (uint8_t) (nss_level);
- if (stlinkv3_command(command, sizeof(command), answer, sizeof(answer), "STLINK_BRIDGE_CS_SPI") != 0) + if (stlinkv3_command(command, sizeof(command), + answer, sizeof(answer), + "STLINK_BRIDGE_CS_SPI", + stlinkv3_handle) != 0) return -1; return 0; } @@ -330,13 +348,14 @@ const unsigned char *write_arr, unsigned char *read_arr) { + struct stlinkv3_spi_data *stlinkv3_data = flash->mst->spi.data; uint8_t command[16]; int rc = 0; int actual_length = 0; uint32_t rw_status = 0; unsigned int i;
- if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_LOW)) { + if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_LOW, stlinkv3_data->stlinkv3_handle)) { msg_perr("Failed to set the NSS pin to low\n"); return -1; } @@ -351,7 +370,7 @@ for (i = 0; (i < 8) && (i < write_cnt); i++) command[4+i] = write_arr[i];
- rc = libusb_bulk_transfer(stlinkv3_handle, STLINK_EP_OUT, + rc = libusb_bulk_transfer(stlinkv3_data->stlinkv3_handle, STLINK_EP_OUT, command, sizeof(command), &actual_length, USB_TIMEOUT_IN_MS); if (rc != LIBUSB_TRANSFER_COMPLETED || actual_length != sizeof(command)) { @@ -361,7 +380,7 @@ }
if (write_cnt > 8) { - rc = libusb_bulk_transfer(stlinkv3_handle, + rc = libusb_bulk_transfer(stlinkv3_data->stlinkv3_handle, STLINK_EP_OUT, (unsigned char *)&write_arr[8], (unsigned int)(write_cnt - 8), @@ -374,7 +393,7 @@ } }
- if (stlinkv3_get_last_readwrite_status(&rw_status)) + if (stlinkv3_get_last_readwrite_status(&rw_status, stlinkv3_data->stlinkv3_handle)) return -1;
if (rw_status != 0) { @@ -387,7 +406,7 @@ command[2] = (uint8_t)read_cnt; command[3] = (uint8_t)(read_cnt >> 8);
- rc = libusb_bulk_transfer(stlinkv3_handle, STLINK_EP_OUT, + rc = libusb_bulk_transfer(stlinkv3_data->stlinkv3_handle, STLINK_EP_OUT, command, sizeof(command), &actual_length, USB_TIMEOUT_IN_MS); if (rc != LIBUSB_TRANSFER_COMPLETED || (unsigned int)actual_length != sizeof(command)) { @@ -396,7 +415,7 @@ goto transmit_err; }
- rc = libusb_bulk_transfer(stlinkv3_handle, + rc = libusb_bulk_transfer(stlinkv3_data->stlinkv3_handle, STLINK_EP_IN, (unsigned char *)read_arr, (int)read_cnt, @@ -409,7 +428,7 @@ } }
- if (stlinkv3_get_last_readwrite_status(&rw_status)) + if (stlinkv3_get_last_readwrite_status(&rw_status, stlinkv3_data->stlinkv3_handle)) goto transmit_err;
if (rw_status != 0) { @@ -417,20 +436,21 @@ goto transmit_err; }
- if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_HIGH)) { + if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_HIGH, stlinkv3_data->stlinkv3_handle)) { msg_perr("Failed to set the NSS pin to high\n"); return -1; } return 0;
transmit_err: - if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_HIGH)) + if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_HIGH, stlinkv3_data->stlinkv3_handle)) msg_perr("Failed to set the NSS pin to high\n"); return -1; }
static int stlinkv3_spi_shutdown(void *data) { + struct stlinkv3_spi_data *stlinkv3_data = data; uint8_t command[16]; uint8_t answer[2];
@@ -440,15 +460,19 @@ command[1] = STLINK_BRIDGE_CLOSE; command[2] = STLINK_SPI_COM;
- stlinkv3_command(command, sizeof(command), answer, sizeof(answer), "STLINK_BRIDGE_CLOSE"); + stlinkv3_command(command, sizeof(command), + answer, sizeof(answer), + "STLINK_BRIDGE_CLOSE", + stlinkv3_data->stlinkv3_handle);
- libusb_close(stlinkv3_handle); - libusb_exit(usb_ctx); + libusb_close(stlinkv3_data->stlinkv3_handle); + libusb_exit(stlinkv3_data->usb_ctx);
+ free(data); return 0; }
-static const struct spi_master spi_programmer_stlinkv3 = { +static struct spi_master spi_programmer_stlinkv3 = { .max_data_read = UINT16_MAX, .max_data_write = UINT16_MAX, .command = stlinkv3_spi_transmit, @@ -464,6 +488,9 @@ char *speed_str = NULL; char *serialno = NULL; char *endptr = NULL; + struct libusb_context *usb_ctx; + libusb_device_handle *stlinkv3_handle; + struct stlinkv3_spi_data *stlinkv3_data;
libusb_init(&usb_ctx); if (!usb_ctx) { @@ -503,14 +530,28 @@ free(speed_str); }
- if (stlinkv3_spi_open(sck_freq_kHz)) + if (stlinkv3_spi_open(sck_freq_kHz, stlinkv3_handle)) goto err_exit;
- if (register_shutdown(stlinkv3_spi_shutdown, NULL)) + stlinkv3_data = calloc(1, sizeof(*stlinkv3_data)); + if (!stlinkv3_data) { + msg_perr("Unable to allocate space for SPI master data\n"); goto err_exit; + }
- if (register_spi_master(&spi_programmer_stlinkv3)) + stlinkv3_data->usb_ctx = usb_ctx; + stlinkv3_data->stlinkv3_handle = stlinkv3_handle; + spi_programmer_stlinkv3.data = stlinkv3_data; + + if (register_shutdown(stlinkv3_spi_shutdown, stlinkv3_data)) { + free(stlinkv3_data); goto err_exit; + } + + if (register_spi_master(&spi_programmer_stlinkv3)) { + free(stlinkv3_data); + goto err_exit; + }
return 0;