mirror of
https://review.coreboot.org/flashrom.git
synced 2025-06-30 21:52:36 +02:00
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> Reviewed-on: https://review.coreboot.org/c/flashrom/+/54042 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org> Reviewed-by: Miklós Márton <martonmiklosqdev@gmail.com>
This commit is contained in:

committed by
Edward O'Callaghan

parent
59e344e904
commit
7becf17942
@ -119,11 +119,14 @@ const struct dev_entry devs_stlinkv3_spi[] = {
|
||||
{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 @@ static int stlinkv3_command(uint8_t *command, size_t command_length,
|
||||
/**
|
||||
* @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 @@ static int stlinkv3_get_clk(uint32_t *bridge_input_clk)
|
||||
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_get_clk(uint32_t *bridge_input_clk)
|
||||
|
||||
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 @@ static int stlinkv3_spi_calc_prescaler(uint16_t reqested_freq_in_kHz,
|
||||
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 @@ static int stlinkv3_check_version(enum fw_version_check_result *result)
|
||||
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 @@ static int stlinkv3_check_version(enum fw_version_check_result *result)
|
||||
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 @@ static int stlinkv3_spi_open(uint16_t reqested_freq_in_kHz)
|
||||
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 @@ static int stlinkv3_spi_open(uint16_t reqested_freq_in_kHz)
|
||||
|
||||
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 @@ static int stlinkv3_spi_open(uint16_t reqested_freq_in_kHz)
|
||||
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 @@ static int stlinkv3_get_last_readwrite_status(uint32_t *status)
|
||||
|
||||
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 @@ static int stlinkv3_spi_set_SPI_NSS(enum spi_nss_level nss_level)
|
||||
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,15 @@ static int stlinkv3_spi_transmit(const struct flashctx *flash,
|
||||
const unsigned char *write_arr,
|
||||
unsigned char *read_arr)
|
||||
{
|
||||
struct stlinkv3_spi_data *stlinkv3_data = flash->mst->spi.data;
|
||||
libusb_device_handle *stlinkv3_handle = stlinkv3_data->stlinkv3_handle;
|
||||
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_handle)) {
|
||||
msg_perr("Failed to set the NSS pin to low\n");
|
||||
return -1;
|
||||
}
|
||||
@ -374,7 +394,7 @@ static int stlinkv3_spi_transmit(const struct flashctx *flash,
|
||||
}
|
||||
}
|
||||
|
||||
if (stlinkv3_get_last_readwrite_status(&rw_status))
|
||||
if (stlinkv3_get_last_readwrite_status(&rw_status, stlinkv3_handle))
|
||||
return -1;
|
||||
|
||||
if (rw_status != 0) {
|
||||
@ -409,7 +429,7 @@ static int stlinkv3_spi_transmit(const struct flashctx *flash,
|
||||
}
|
||||
}
|
||||
|
||||
if (stlinkv3_get_last_readwrite_status(&rw_status))
|
||||
if (stlinkv3_get_last_readwrite_status(&rw_status, stlinkv3_handle))
|
||||
goto transmit_err;
|
||||
|
||||
if (rw_status != 0) {
|
||||
@ -417,20 +437,21 @@ static int stlinkv3_spi_transmit(const struct flashctx *flash,
|
||||
goto transmit_err;
|
||||
}
|
||||
|
||||
if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_HIGH)) {
|
||||
if (stlinkv3_spi_set_SPI_NSS(SPI_NSS_HIGH, 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_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,11 +461,15 @@ static int stlinkv3_spi_shutdown(void *data)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -465,6 +490,9 @@ int stlinkv3_spi_init(void)
|
||||
char *serialno = NULL;
|
||||
char *endptr = NULL;
|
||||
int ret = 1;
|
||||
struct libusb_context *usb_ctx;
|
||||
libusb_device_handle *stlinkv3_handle;
|
||||
struct stlinkv3_spi_data *stlinkv3_data;
|
||||
|
||||
libusb_init(&usb_ctx);
|
||||
if (!usb_ctx) {
|
||||
@ -505,19 +533,28 @@ int stlinkv3_spi_init(void)
|
||||
free(speed_str);
|
||||
}
|
||||
|
||||
if (stlinkv3_spi_open(sck_freq_kHz))
|
||||
if (stlinkv3_spi_open(sck_freq_kHz, stlinkv3_handle))
|
||||
goto init_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 init_err_exit;
|
||||
}
|
||||
|
||||
stlinkv3_data->usb_ctx = usb_ctx;
|
||||
stlinkv3_data->stlinkv3_handle = stlinkv3_handle;
|
||||
|
||||
if (register_shutdown(stlinkv3_spi_shutdown, stlinkv3_data))
|
||||
goto init_err_cleanup_exit;
|
||||
|
||||
if (register_spi_master(&spi_programmer_stlinkv3, NULL))
|
||||
if (register_spi_master(&spi_programmer_stlinkv3, stlinkv3_data))
|
||||
return 1; /* shutdown function does cleanup */
|
||||
|
||||
return 0;
|
||||
|
||||
init_err_cleanup_exit:
|
||||
stlinkv3_spi_shutdown(NULL);
|
||||
stlinkv3_spi_shutdown(stlinkv3_data);
|
||||
return 1;
|
||||
|
||||
init_err_exit:
|
||||
|
Reference in New Issue
Block a user