mirror of
				https://review.coreboot.org/flashrom.git
				synced 2025-11-04 07:00:39 +01:00 
			
		
		
		
	ni845x_spi: 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. TOPIC=register_master_api Change-Id: I45fcb8e20582cb0c532c4a9f0c78543a25f8d484 Signed-off-by: Alexander Goncharov <chat@joursoir.net> Ticket: https://ticket.coreboot.org/issues/391 Reviewed-on: https://review.coreboot.org/c/flashrom/+/72160 Reviewed-by: Anastasia Klimchuk <aklm@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
		
				
					committed by
					
						
						Anastasia Klimchuk
					
				
			
			
				
	
			
			
			
						parent
						
							0f0f952740
						
					
				
				
					commit
					e0fe2c7ca1
				
			
							
								
								
									
										101
									
								
								ni845x_spi.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								ni845x_spi.c
									
									
									
									
									
								
							@@ -47,13 +47,14 @@ enum voltage_coerce_mode {
 | 
				
			|||||||
	USE_HIGHER
 | 
						USE_HIGHER
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned char CS_number;	// use chip select 0 as default
 | 
					struct ni845x_spi_data {
 | 
				
			||||||
static enum USB845x_type device_pid = Unknown_NI845X_Device;
 | 
						unsigned char CS_number; // use chip select 0 as default
 | 
				
			||||||
 | 
						enum USB845x_type device_pid;
 | 
				
			||||||
static uInt32 device_handle;
 | 
						uInt32 device_handle;
 | 
				
			||||||
static NiHandle configuration_handle;
 | 
						NiHandle configuration_handle;
 | 
				
			||||||
static uint16_t io_voltage_in_mV;
 | 
						uint16_t io_voltage_in_mV;
 | 
				
			||||||
static bool ignore_io_voltage_limits;
 | 
						bool ignore_io_voltage_limits;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB-8452 supported voltages, keep this array in ascending order!
 | 
					// USB-8452 supported voltages, keep this array in ascending order!
 | 
				
			||||||
static const uint8_t usb8452_io_voltages_in_100mV[5] = {
 | 
					static const uint8_t usb8452_io_voltages_in_100mV[5] = {
 | 
				
			||||||
@@ -394,98 +395,104 @@ static void ni845x_spi_print_available_devices(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int ni845x_spi_shutdown(void *data)
 | 
					static int ni845x_spi_shutdown(void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct ni845x_spi_data *ni_data = data;
 | 
				
			||||||
	int32 ret = 0;
 | 
						int32 ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (configuration_handle != 0) {
 | 
						if (ni_data->configuration_handle != 0) {
 | 
				
			||||||
		ret = ni845xSpiConfigurationClose(configuration_handle);
 | 
							ret = ni845xSpiConfigurationClose(ni_data->configuration_handle);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			ni845x_report_error("ni845xSpiConfigurationClose", ret);
 | 
								ni845x_report_error("ni845xSpiConfigurationClose", ret);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (device_handle != 0) {
 | 
						if (ni_data->device_handle != 0) {
 | 
				
			||||||
		ret = ni845xClose(device_handle);
 | 
							ret = ni845xClose(ni_data->device_handle);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
			ni845x_report_error("ni845xClose", ret);
 | 
								ni845x_report_error("ni845xClose", ret);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
					
 | 
				
			||||||
 | 
						free(data);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ni845x_warn_over_max_voltage(const struct flashctx *flash)
 | 
					static void ni845x_warn_over_max_voltage(const struct flashctx *flash)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (device_pid == USB8451) {
 | 
						const struct ni845x_spi_data *data = flash->mst->spi.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data->device_pid == USB8451) {
 | 
				
			||||||
		msg_pwarn("The %s chip maximum voltage is %.1fV, while the USB-8451 "
 | 
							msg_pwarn("The %s chip maximum voltage is %.1fV, while the USB-8451 "
 | 
				
			||||||
			  "IO voltage levels are 3.3V.\n"
 | 
								  "IO voltage levels are 3.3V.\n"
 | 
				
			||||||
			  "Ignoring this because ignore_io_voltage_limits parameter is set.\n",
 | 
								  "Ignoring this because ignore_io_voltage_limits parameter is set.\n",
 | 
				
			||||||
			 flash->chip->name,
 | 
								 flash->chip->name,
 | 
				
			||||||
			 flash->chip->voltage.max / 1000.0f);
 | 
								 flash->chip->voltage.max / 1000.0f);
 | 
				
			||||||
	} else if (device_pid == USB8452) {
 | 
						} else if (data->device_pid == USB8452) {
 | 
				
			||||||
		msg_pwarn("The %s chip maximum voltage is %.1fV, while the USB-8452 "
 | 
							msg_pwarn("The %s chip maximum voltage is %.1fV, while the USB-8452 "
 | 
				
			||||||
			  "IO voltage is set to %.1fV.\n"
 | 
								  "IO voltage is set to %.1fV.\n"
 | 
				
			||||||
			  "Ignoring this because ignore_io_voltage_limits parameter is set.\n",
 | 
								  "Ignoring this because ignore_io_voltage_limits parameter is set.\n",
 | 
				
			||||||
			  flash->chip->name,
 | 
								  flash->chip->name,
 | 
				
			||||||
			  flash->chip->voltage.max / 1000.0f,
 | 
								  flash->chip->voltage.max / 1000.0f,
 | 
				
			||||||
			  io_voltage_in_mV / 1000.0f);
 | 
								  data->io_voltage_in_mV / 1000.0f);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ni845x_spi_io_voltage_check(const struct flashctx *flash)
 | 
					static int ni845x_spi_io_voltage_check(const struct flashctx *flash)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct ni845x_spi_data *data = flash->mst->spi.data;
 | 
				
			||||||
	static bool first_transmit = true;
 | 
						static bool first_transmit = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (first_transmit && flash->chip) {
 | 
						if (first_transmit && flash->chip) {
 | 
				
			||||||
		first_transmit = false;
 | 
							first_transmit = false;
 | 
				
			||||||
		if (io_voltage_in_mV > flash->chip->voltage.max) {
 | 
							if (data->io_voltage_in_mV > flash->chip->voltage.max) {
 | 
				
			||||||
			if (ignore_io_voltage_limits) {
 | 
								if (data->ignore_io_voltage_limits) {
 | 
				
			||||||
				ni845x_warn_over_max_voltage(flash);
 | 
									ni845x_warn_over_max_voltage(flash);
 | 
				
			||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (device_pid == USB8451) {
 | 
								if (data->device_pid == USB8451) {
 | 
				
			||||||
				msg_perr("The %s chip maximum voltage is %.1fV, while the USB-8451 "
 | 
									msg_perr("The %s chip maximum voltage is %.1fV, while the USB-8451 "
 | 
				
			||||||
					 "IO voltage levels are 3.3V.\nAborting operations\n",
 | 
										 "IO voltage levels are 3.3V.\nAborting operations\n",
 | 
				
			||||||
					 flash->chip->name,
 | 
										 flash->chip->name,
 | 
				
			||||||
					 flash->chip->voltage.max / 1000.0f);
 | 
										 flash->chip->voltage.max / 1000.0f);
 | 
				
			||||||
				return -1;
 | 
									return -1;
 | 
				
			||||||
			} else if (device_pid == USB8452) {
 | 
								} else if (data->device_pid == USB8452) {
 | 
				
			||||||
				msg_perr("Lowering IO voltage because the %s chip maximum voltage is %.1fV, "
 | 
									msg_perr("Lowering IO voltage because the %s chip maximum voltage is %.1fV, "
 | 
				
			||||||
					 "(%.1fV was set)\n",
 | 
										 "(%.1fV was set)\n",
 | 
				
			||||||
					 flash->chip->name,
 | 
										 flash->chip->name,
 | 
				
			||||||
					 flash->chip->voltage.max / 1000.0f,
 | 
										 flash->chip->voltage.max / 1000.0f,
 | 
				
			||||||
					 io_voltage_in_mV / 1000.0f);
 | 
										 data->io_voltage_in_mV / 1000.0f);
 | 
				
			||||||
				if (usb8452_spi_set_io_voltage(flash->chip->voltage.max,
 | 
									if (usb8452_spi_set_io_voltage(flash->chip->voltage.max,
 | 
				
			||||||
							       &io_voltage_in_mV,
 | 
												       &data->io_voltage_in_mV,
 | 
				
			||||||
							       USE_LOWER,
 | 
												       USE_LOWER,
 | 
				
			||||||
							       device_pid,
 | 
												       data->device_pid,
 | 
				
			||||||
							       device_handle)) {
 | 
												       data->device_handle)) {
 | 
				
			||||||
					msg_perr("Unable to lower the IO voltage below "
 | 
										msg_perr("Unable to lower the IO voltage below "
 | 
				
			||||||
						 "the chip's maximum voltage\n");
 | 
											 "the chip's maximum voltage\n");
 | 
				
			||||||
					return -1;
 | 
										return -1;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (io_voltage_in_mV < flash->chip->voltage.min) {
 | 
							} else if (data->io_voltage_in_mV < flash->chip->voltage.min) {
 | 
				
			||||||
			if (device_pid == USB8451) {
 | 
								if (data->device_pid == USB8451) {
 | 
				
			||||||
				msg_pwarn("Flash operations might be unreliable, because the %s chip's "
 | 
									msg_pwarn("Flash operations might be unreliable, because the %s chip's "
 | 
				
			||||||
					  "minimum voltage is %.1fV, while the USB-8451's "
 | 
										  "minimum voltage is %.1fV, while the USB-8451's "
 | 
				
			||||||
					  "IO voltage levels are 3.3V.\n",
 | 
										  "IO voltage levels are 3.3V.\n",
 | 
				
			||||||
					  flash->chip->name,
 | 
										  flash->chip->name,
 | 
				
			||||||
					  flash->chip->voltage.min / 1000.0f);
 | 
										  flash->chip->voltage.min / 1000.0f);
 | 
				
			||||||
				return ignore_io_voltage_limits ? 0 : -1;
 | 
									return data->ignore_io_voltage_limits ? 0 : -1;
 | 
				
			||||||
			} else if (device_pid == USB8452) {
 | 
								} else if (data->device_pid == USB8452) {
 | 
				
			||||||
				msg_pwarn("Raising the IO voltage because the %s chip's "
 | 
									msg_pwarn("Raising the IO voltage because the %s chip's "
 | 
				
			||||||
					  "minimum voltage is %.1fV, "
 | 
										  "minimum voltage is %.1fV, "
 | 
				
			||||||
					  "(%.1fV was set)\n",
 | 
										  "(%.1fV was set)\n",
 | 
				
			||||||
					  flash->chip->name,
 | 
										  flash->chip->name,
 | 
				
			||||||
					  flash->chip->voltage.min / 1000.0f,
 | 
										  flash->chip->voltage.min / 1000.0f,
 | 
				
			||||||
					  io_voltage_in_mV / 1000.0f);
 | 
										  data->io_voltage_in_mV / 1000.0f);
 | 
				
			||||||
				if (usb8452_spi_set_io_voltage(flash->chip->voltage.min,
 | 
									if (usb8452_spi_set_io_voltage(flash->chip->voltage.min,
 | 
				
			||||||
							       &io_voltage_in_mV,
 | 
												       &data->io_voltage_in_mV,
 | 
				
			||||||
							       USE_HIGHER,
 | 
												       USE_HIGHER,
 | 
				
			||||||
							       device_pid,
 | 
												       data->device_pid,
 | 
				
			||||||
							       device_handle)) {
 | 
												       data->device_handle)) {
 | 
				
			||||||
					msg_pwarn("Unable to raise the IO voltage above the chip's "
 | 
										msg_pwarn("Unable to raise the IO voltage above the chip's "
 | 
				
			||||||
						  "minimum voltage\n"
 | 
											  "minimum voltage\n"
 | 
				
			||||||
						  "Flash operations might be unreliable.\n");
 | 
											  "Flash operations might be unreliable.\n");
 | 
				
			||||||
					return ignore_io_voltage_limits ? 0 : -1;
 | 
										return data->ignore_io_voltage_limits ? 0 : -1;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -499,6 +506,7 @@ static int ni845x_spi_transmit(const struct flashctx *flash,
 | 
				
			|||||||
			       const unsigned char *write_arr,
 | 
								       const unsigned char *write_arr,
 | 
				
			||||||
			       unsigned char *read_arr)
 | 
								       unsigned char *read_arr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						const struct ni845x_spi_data *data = flash->mst->spi.data;
 | 
				
			||||||
	uInt32 read_size = 0;
 | 
						uInt32 read_size = 0;
 | 
				
			||||||
	uInt8 *transfer_buffer = NULL;
 | 
						uInt8 *transfer_buffer = NULL;
 | 
				
			||||||
	int32 ret = 0;
 | 
						int32 ret = 0;
 | 
				
			||||||
@@ -514,8 +522,8 @@ static int ni845x_spi_transmit(const struct flashctx *flash,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	memcpy(transfer_buffer, write_arr, write_cnt);
 | 
						memcpy(transfer_buffer, write_arr, write_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = ni845xSpiWriteRead(device_handle,
 | 
						ret = ni845xSpiWriteRead(data->device_handle,
 | 
				
			||||||
				 configuration_handle,
 | 
									 data->configuration_handle,
 | 
				
			||||||
				 (write_cnt + read_cnt), transfer_buffer, &read_size, transfer_buffer);
 | 
									 (write_cnt + read_cnt), transfer_buffer, &read_size, transfer_buffer);
 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		// Negative specifies an error, meaning the function did not perform the expected behavior.
 | 
							// Negative specifies an error, meaning the function did not perform the expected behavior.
 | 
				
			||||||
@@ -560,6 +568,10 @@ static int ni845x_spi_init(const struct programmer_cfg *cfg)
 | 
				
			|||||||
	int spi_speed_KHz = 1000;		// selecting 1 MHz SCK is a good bet
 | 
						int spi_speed_KHz = 1000;		// selecting 1 MHz SCK is a good bet
 | 
				
			||||||
	char *serial_number = NULL;		// by default open the first connected device
 | 
						char *serial_number = NULL;		// by default open the first connected device
 | 
				
			||||||
	char *ignore_io_voltage_limits_str = NULL;
 | 
						char *ignore_io_voltage_limits_str = NULL;
 | 
				
			||||||
 | 
						bool ignore_io_voltage_limits;
 | 
				
			||||||
 | 
						unsigned char CS_number = 0;
 | 
				
			||||||
 | 
						enum USB845x_type device_pid = Unknown_NI845X_Device;
 | 
				
			||||||
 | 
						uInt32 device_handle;
 | 
				
			||||||
	int32 tmp = 0;
 | 
						int32 tmp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// read the cs parameter (which Chip select should we use)
 | 
						// read the cs parameter (which Chip select should we use)
 | 
				
			||||||
@@ -618,27 +630,38 @@ static int ni845x_spi_init(const struct programmer_cfg *cfg)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	free(serial_number);
 | 
						free(serial_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ni845x_spi_data *data = calloc(1, sizeof(*data));
 | 
				
			||||||
 | 
						if (!data) {
 | 
				
			||||||
 | 
							msg_perr("Unable to allocate space for SPI master data\n");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						data->CS_number = CS_number;
 | 
				
			||||||
 | 
						data->device_pid = device_pid;
 | 
				
			||||||
 | 
						data->device_handle = device_handle;
 | 
				
			||||||
 | 
						data->ignore_io_voltage_limits = ignore_io_voltage_limits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// open the SPI config handle
 | 
						// open the SPI config handle
 | 
				
			||||||
	tmp = ni845xSpiConfigurationOpen(&configuration_handle);
 | 
						tmp = ni845xSpiConfigurationOpen(&data->configuration_handle);
 | 
				
			||||||
	if (tmp != 0) {
 | 
						if (tmp != 0) {
 | 
				
			||||||
		ni845x_report_error("ni845xSpiConfigurationOpen", tmp);
 | 
							ni845x_report_error("ni845xSpiConfigurationOpen", tmp);
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (usb8452_spi_set_io_voltage(requested_io_voltage_mV, &io_voltage_in_mV, USE_LOWER, device_pid, device_handle) < 0) {
 | 
						if (usb8452_spi_set_io_voltage(requested_io_voltage_mV, &data->io_voltage_in_mV,
 | 
				
			||||||
 | 
									       USE_LOWER, data->device_pid, data->device_handle) < 0) {
 | 
				
			||||||
		// no alert here usb8452_spi_set_io_voltage already printed that
 | 
							// no alert here usb8452_spi_set_io_voltage already printed that
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ni845x_spi_set_speed(configuration_handle, spi_speed_KHz)) {
 | 
						if (ni845x_spi_set_speed(data->configuration_handle, spi_speed_KHz)) {
 | 
				
			||||||
		msg_perr("Unable to set SPI speed\n");
 | 
							msg_perr("Unable to set SPI speed\n");
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return register_spi_master(&spi_programmer_ni845x, NULL);
 | 
						return register_spi_master(&spi_programmer_ni845x, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
	ni845x_spi_shutdown(NULL);
 | 
						ni845x_spi_shutdown(data);
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user