pickit2_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".

Change-Id: Ibacc4738bee02c371c41583d321e0337128ad18a
Signed-off-by: Anastasia Klimchuk <aklm@chromium.org>
Original-Reviewed-on: https://review.coreboot.org/c/flashrom/+/52774
Original-Reviewed-by: Nico Huber <nico.h@gmx.de>
Original-Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Original-Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72176
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/pickit2_spi.c b/pickit2_spi.c
index b8d3f76..9c78138 100644
--- a/pickit2_spi.c
+++ b/pickit2_spi.c
@@ -52,7 +52,9 @@
 	{0}
 };
 
-static libusb_device_handle *pickit2_handle;
+struct pickit2_spi_data {
+	libusb_device_handle *pickit2_handle;
+};
 
 /* Default USB transaction timeout in ms */
 #define DFLT_TIMEOUT            10000
@@ -95,7 +97,7 @@
 	return libusb_interrupt_transfer(handle, endpoint, data, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
 }
 
-static int pickit2_get_firmware_version(void)
+static int pickit2_get_firmware_version(libusb_device_handle *pickit2_handle)
 {
 	int ret;
 	uint8_t command[CMD_LENGTH] = {CMD_GET_VERSION, CMD_END_OF_BUFFER};
@@ -118,7 +120,7 @@
 	return 0;
 }
 
-static int pickit2_set_spi_voltage(int millivolt)
+static int pickit2_set_spi_voltage(libusb_device_handle *pickit2_handle, int millivolt)
 {
 	double voltage_selector;
 	switch (millivolt) {
@@ -176,7 +178,7 @@
 	{ NULL,		0x0 },
 };
 
-static int pickit2_set_spi_speed(unsigned int spispeed_idx)
+static int pickit2_set_spi_speed(libusb_device_handle *pickit2_handle, unsigned int spispeed_idx)
 {
 	msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed_idx].name);
 
@@ -202,6 +204,7 @@
 				     const unsigned char *writearr, unsigned char *readarr)
 {
 	const unsigned int total_packetsize = writecnt + readcnt + 20;
+	struct pickit2_spi_data *pickit2_data = flash->mst->spi.data;
 
 	/* Maximum number of bytes per transaction (including command overhead) is 64. Lets play it safe
 	 * and always assume the worst case scenario of 20 bytes command overhead.
@@ -258,7 +261,7 @@
 	buf[i++] = CMD_UPLOAD_DATA;
 	buf[i++] = CMD_END_OF_BUFFER;
 
-	int ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, buf);
+	int ret = pickit2_interrupt_transfer(pickit2_data->pickit2_handle, ENDPOINT_OUT, buf);
 
 	if (ret != 0) {
 		msg_perr("Send SPI failed!\n");
@@ -267,7 +270,8 @@
 
 	if (readcnt) {
 		int length = 0;
-		ret = libusb_interrupt_transfer(pickit2_handle, ENDPOINT_IN, buf, CMD_LENGTH, &length, DFLT_TIMEOUT);
+		ret = libusb_interrupt_transfer(pickit2_data->pickit2_handle,
+					ENDPOINT_IN, buf, CMD_LENGTH, &length, DFLT_TIMEOUT);
 
 		if (length == 0 || ret != 0) {
 			msg_perr("Receive SPI failed\n");
@@ -338,7 +342,7 @@
 	return millivolt;
 }
 
-static const struct spi_master spi_master_pickit2 = {
+static struct spi_master spi_master_pickit2 = {
 	.max_data_read	= 40,
 	.max_data_write	= 40,
 	.command	= pickit2_spi_send_command,
@@ -350,6 +354,8 @@
 
 static int pickit2_shutdown(void *data)
 {
+	struct pickit2_spi_data *pickit2_data = data;
+
 	/* Set all pins to float and turn voltages off */
 	uint8_t command[CMD_LENGTH] = {
 		CMD_EXEC_SCRIPT,
@@ -365,18 +371,20 @@
 		CMD_END_OF_BUFFER
 	};
 
-	int ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command);
+	int ret = pickit2_interrupt_transfer(pickit2_data->pickit2_handle, ENDPOINT_OUT, command);
 
 	if (ret != 0) {
 		msg_perr("Command Shutdown failed!\n");
 		ret = 1;
 	}
-	if (libusb_release_interface(pickit2_handle, 0) != 0) {
+	if (libusb_release_interface(pickit2_data->pickit2_handle, 0) != 0) {
 		msg_perr("Could not release USB interface!\n");
 		ret = 1;
 	}
-	libusb_close(pickit2_handle);
+	libusb_close(pickit2_data->pickit2_handle);
 	libusb_exit(NULL);
+
+	free(data);
 	return ret;
 }
 
@@ -399,7 +407,8 @@
 		CMD_END_OF_BUFFER
 	};
 
-
+	libusb_device_handle *pickit2_handle;
+	struct pickit2_spi_data *pickit2_data;
 	int spispeed_idx = 0;
 	char *spispeed = extract_programmer_param("spispeed");
 	if (spispeed != NULL) {
@@ -460,16 +469,26 @@
 		return 1;
 	}
 
-	if (pickit2_get_firmware_version())
+	pickit2_data = calloc(1, sizeof(*pickit2_data));
+	if (!pickit2_data) {
+		msg_perr("Unable to allocate space for SPI master data\n");
+		libusb_close(pickit2_handle);
+		libusb_exit(NULL);
+		return 1;
+	}
+	pickit2_data->pickit2_handle = pickit2_handle;
+	spi_master_pickit2.data = pickit2_data;
+
+	if (pickit2_get_firmware_version(pickit2_handle))
 		goto init_err_cleanup_exit;
 
 	/* Command Set SPI Speed */
-	if (pickit2_set_spi_speed(spispeed_idx))
+	if (pickit2_set_spi_speed(pickit2_handle, spispeed_idx))
 		goto init_err_cleanup_exit;
 
 	/* Command Set SPI Voltage */
 	msg_pdbg("Setting voltage to %i mV.\n", millivolt);
-	if (pickit2_set_spi_voltage(millivolt) != 0)
+	if (pickit2_set_spi_voltage(pickit2_handle, millivolt) != 0)
 		goto init_err_cleanup_exit;
 
 	/* Perform basic setup.
@@ -479,14 +498,14 @@
 		goto init_err_cleanup_exit;
 	}
 
-	if (register_shutdown(pickit2_shutdown, NULL))
+	if (register_shutdown(pickit2_shutdown, pickit2_data))
 		goto init_err_cleanup_exit;
 	register_spi_master(&spi_master_pickit2);
 
 	return 0;
 
 init_err_cleanup_exit:
-	pickit2_shutdown(NULL);
+	pickit2_shutdown(pickit2_data);
 	return 1;
 }