summaryrefslogtreecommitdiffstats
path: root/raiden_debug_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'raiden_debug_spi.c')
-rw-r--r--raiden_debug_spi.c192
1 files changed, 112 insertions, 80 deletions
diff --git a/raiden_debug_spi.c b/raiden_debug_spi.c
index bd7c054de..c5642ff43 100644
--- a/raiden_debug_spi.c
+++ b/raiden_debug_spi.c
@@ -343,13 +343,19 @@
#include "usb_device.h"
#include <libusb.h>
+#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-/* FIXME: Add some programmer IDs here */
-const struct dev_entry devs_raiden[] = {
+/*
+ * Table is empty as raiden_debug_spi matches against the class and
+ * subclass of the connected USB devices, rather than looking for a
+ * device with a specific vid:pid.
+ */
+static const struct dev_entry devs_raiden[] = {
{0},
};
@@ -398,6 +404,10 @@ enum usb_spi_error {
USB_SPI_UNKNOWN_ERROR = 0x8000,
};
+/* Corresponds with 'enum usb_spi_request' in,
+ * platform/cr50/chip/g/usb_spi.h and,
+ * platform/ec/chip/stm32/usb_spi.h.
+ */
enum raiden_debug_spi_request {
RAIDEN_DEBUG_SPI_REQ_ENABLE = 0x0000,
RAIDEN_DEBUG_SPI_REQ_DISABLE = 0x0001,
@@ -441,6 +451,7 @@ struct raiden_debug_spi_data {
*/
uint16_t max_spi_write_count;
uint16_t max_spi_read_count;
+ struct spi_master *spi_config;
};
/*
* USB permits a maximum bulk transfer of 64B.
@@ -881,7 +892,7 @@ static int send_command_v1(const struct flashctx *flash,
/* Reattempting will not result in a recovery. */
return status;
}
- programmer_delay(RETRY_INTERVAL_US);
+ default_delay(RETRY_INTERVAL_US);
continue;
}
@@ -916,7 +927,7 @@ static int send_command_v1(const struct flashctx *flash,
/* Reattempting will not result in a recovery. */
return status;
}
- programmer_delay(RETRY_INTERVAL_US);
+ default_delay(RETRY_INTERVAL_US);
}
}
@@ -951,7 +962,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data)
" config attempt = %d\n"
" status = 0x%05x\n",
config_attempt + 1, status);
- programmer_delay(RETRY_INTERVAL_US);
+ default_delay(RETRY_INTERVAL_US);
continue;
}
@@ -961,7 +972,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data)
" config attempt = %d\n"
" status = 0x%05x\n",
config_attempt + 1, status);
- programmer_delay(RETRY_INTERVAL_US);
+ default_delay(RETRY_INTERVAL_US);
continue;
}
@@ -982,6 +993,22 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data)
return status;
}
+ /*
+ * Check if we received an error from the device. An error will have no
+ * response data, just the packet_id and status_code.
+ */
+ const size_t err_packet_size = sizeof(struct usb_spi_response_v2) -
+ USB_SPI_PAYLOAD_SIZE_V2_RESPONSE;
+ if (rsp_config.packet_size == err_packet_size &&
+ rsp_config.packet_v2.rsp_start.status_code !=
+ USB_SPI_SUCCESS) {
+ status = rsp_config.packet_v2.rsp_start.status_code;
+ if (status == USB_SPI_DISABLED) {
+ msg_perr("Raiden: Target SPI bridge is disabled (is WP enabled?)\n");
+ return status;
+ }
+ }
+
msg_perr("Raiden: Packet is not a valid config\n"
" config attempt = %d\n"
" packet id = %u\n"
@@ -989,7 +1016,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data)
config_attempt + 1,
rsp_config.packet_v2.packet_id,
rsp_config.packet_size);
- programmer_delay(RETRY_INTERVAL_US);
+ default_delay(RETRY_INTERVAL_US);
}
return USB_SPI_HOST_INIT_FAILURE;
}
@@ -1213,7 +1240,7 @@ static int send_command_v2(const struct flashctx *flash,
/* Reattempting will not result in a recovery. */
return status;
}
- programmer_delay(RETRY_INTERVAL_US);
+ default_delay(RETRY_INTERVAL_US);
continue;
}
for (read_attempt = 0; read_attempt < READ_RETRY_ATTEMPTS;
@@ -1250,22 +1277,52 @@ static int send_command_v2(const struct flashctx *flash,
}
/* Device needs to reset its transmit index. */
restart_response_v2(ctx_data);
- programmer_delay(RETRY_INTERVAL_US);
+ default_delay(RETRY_INTERVAL_US);
}
}
}
return status;
}
+static int raiden_debug_spi_shutdown(void * data)
+{
+ struct raiden_debug_spi_data *ctx_data = (struct raiden_debug_spi_data *)data;
+ struct spi_master *spi_config = ctx_data->spi_config;
+
+ int ret = LIBUSB(libusb_control_transfer(
+ ctx_data->dev->handle,
+ LIBUSB_ENDPOINT_OUT |
+ LIBUSB_REQUEST_TYPE_VENDOR |
+ LIBUSB_RECIPIENT_INTERFACE,
+ RAIDEN_DEBUG_SPI_REQ_DISABLE,
+ 0,
+ ctx_data->dev->interface_descriptor->bInterfaceNumber,
+ NULL,
+ 0,
+ TRANSFER_TIMEOUT_MS));
+ if (ret != 0) {
+ msg_perr("Raiden: Failed to disable SPI bridge\n");
+ free(ctx_data);
+ free(spi_config);
+ return ret;
+ }
+
+ usb_device_free(ctx_data->dev);
+ libusb_exit(NULL);
+ free(ctx_data);
+ free(spi_config);
+
+ return 0;
+}
+
static const struct spi_master spi_master_raiden_debug = {
- .features = SPI_MASTER_4BA,
- .max_data_read = 0,
- .max_data_write = 0,
- .command = NULL,
- .multicommand = default_spi_send_multicommand,
- .read = default_spi_read,
- .write_256 = default_spi_write_256,
- .write_aai = default_spi_write_aai,
+ .features = SPI_MASTER_4BA,
+ .max_data_read = 0,
+ .max_data_write = 0,
+ .command = NULL,
+ .read = default_spi_read,
+ .write_256 = default_spi_write_256,
+ .shutdown = raiden_debug_spi_shutdown,
};
static int match_endpoint(struct libusb_endpoint_descriptor const *descriptor,
@@ -1316,15 +1373,14 @@ static int find_endpoints(struct usb_device *dev, uint8_t *in_ep, uint8_t *out_e
* is being used by the device USB SPI interface and if needed query the
* device for its capabilities.
*
- * @param spi_config Raiden SPI config which will be modified.
+ * @param ctx_data Raiden SPI data, data contains pointer to config which will be modified.
*
- * @returns Returns status code with 0 on success.
+ * @returns Returns status code with 0 on success.
*/
-static int configure_protocol(struct spi_master *spi_config)
+static int configure_protocol(struct raiden_debug_spi_data *ctx_data)
{
int status = 0;
- struct raiden_debug_spi_data *ctx_data =
- (struct raiden_debug_spi_data *)spi_config->data;
+ struct spi_master *spi_config = ctx_data->spi_config;
ctx_data->protocol_version =
ctx_data->dev->interface_descriptor->bInterfaceProtocol;
@@ -1375,46 +1431,16 @@ static int configure_protocol(struct spi_master *spi_config)
return 0;
}
-static int raiden_debug_spi_shutdown(void * data)
-{
- struct spi_master *spi_config = data;
- struct raiden_debug_spi_data *ctx_data =
- (struct raiden_debug_spi_data *)spi_config->data;
-
- int ret = LIBUSB(libusb_control_transfer(
- ctx_data->dev->handle,
- LIBUSB_ENDPOINT_OUT |
- LIBUSB_REQUEST_TYPE_VENDOR |
- LIBUSB_RECIPIENT_INTERFACE,
- RAIDEN_DEBUG_SPI_REQ_DISABLE,
- 0,
- ctx_data->dev->interface_descriptor->bInterfaceNumber,
- NULL,
- 0,
- TRANSFER_TIMEOUT_MS));
- if (ret != 0) {
- msg_perr("Raiden: Failed to disable SPI bridge\n");
- free(ctx_data);
- free(spi_config);
- return ret;
- }
-
- usb_device_free(ctx_data->dev);
- libusb_exit(NULL);
- free(ctx_data);
- free(spi_config);
-
- return 0;
-}
-
-static int get_ap_request_type(void)
+static int get_ap_request_type(const struct programmer_cfg *cfg)
{
int ap_request = RAIDEN_DEBUG_SPI_REQ_ENABLE_AP;
- char *custom_rst_str = extract_programmer_param("custom_rst");
+ char *custom_rst_str = extract_programmer_param_str(cfg, "custom_rst");
if (custom_rst_str) {
- if (!strcasecmp(custom_rst_str, "true"))
+ if (!strcasecmp(custom_rst_str, "true")) {
ap_request = RAIDEN_DEBUG_SPI_REQ_ENABLE_AP_CUSTOM;
- else {
+ } else if (!strcasecmp(custom_rst_str, "false")) {
+ ap_request = RAIDEN_DEBUG_SPI_REQ_ENABLE_AP;
+ } else {
msg_perr("Invalid custom rst param: %s\n",
custom_rst_str);
ap_request = -1;
@@ -1424,14 +1450,18 @@ static int get_ap_request_type(void)
return ap_request;
}
-static int get_target(void)
+static int get_target(const struct programmer_cfg *cfg)
{
+ /**
+ * REQ_ENABLE doesn't specify a target bus, and will be rejected
+ * by adapters that support more than one target.
+ */
int request_enable = RAIDEN_DEBUG_SPI_REQ_ENABLE;
- char *target_str = extract_programmer_param("target");
+ char *target_str = extract_programmer_param_str(cfg, "target");
if (target_str) {
if (!strcasecmp(target_str, "ap"))
- request_enable = get_ap_request_type();
+ request_enable = get_ap_request_type(cfg);
else if (!strcasecmp(target_str, "ec"))
request_enable = RAIDEN_DEBUG_SPI_REQ_ENABLE_EC;
else {
@@ -1454,22 +1484,22 @@ static void free_dev_list(struct usb_device **dev_lst)
dev = usb_device_free(dev);
}
-int raiden_debug_spi_init(void)
+static int raiden_debug_spi_init(const struct programmer_cfg *cfg)
{
struct usb_match match;
- char *serial = extract_programmer_param("serial");
+ char *serial = extract_programmer_param_str(cfg, "serial");
struct usb_device *current;
struct usb_device *device = NULL;
- int found = 0;
+ bool found = false;
int ret;
- int request_enable = get_target();
+ int request_enable = get_target(cfg);
if (request_enable < 0) {
free(serial);
return 1;
}
- usb_match_init(&match);
+ usb_match_init(cfg, &match);
usb_match_value_default(&match.vid, GOOGLE_VID);
usb_match_value_default(&match.class, LIBUSB_CLASS_VENDOR_SPEC);
@@ -1507,15 +1537,13 @@ int raiden_debug_spi_init(void)
}
if (!serial) {
- found = 1;
+ found = true;
goto loop_end;
} else {
- unsigned char dev_serial[32];
+ unsigned char dev_serial[32] = { 0 };
struct libusb_device_descriptor descriptor;
int rc;
- memset(dev_serial, 0, sizeof(dev_serial));
-
if (libusb_get_device_descriptor(device->device, &descriptor)) {
msg_pdbg("USB: Failed to get device descriptor.\n");
goto loop_end;
@@ -1534,7 +1562,7 @@ int raiden_debug_spi_init(void)
} else {
msg_pinfo("Raiden: Serial number %s matched device", serial);
usb_device_show(" ", current);
- found = 1;
+ found = true;
}
}
}
@@ -1579,31 +1607,31 @@ loop_end:
(request_enable == RAIDEN_DEBUG_SPI_REQ_ENABLE_EC))
usleep(50 * 1000);
- struct spi_master *spi_config = calloc(1, sizeof(struct spi_master));
+ struct spi_master *spi_config = calloc(1, sizeof(*spi_config));
if (!spi_config) {
msg_perr("Unable to allocate space for SPI master.\n");
return SPI_GENERIC_ERROR;
}
- struct raiden_debug_spi_data *data = calloc(1, sizeof(struct raiden_debug_spi_data));
+ struct raiden_debug_spi_data *data = calloc(1, sizeof(*data));
if (!data) {
free(spi_config);
msg_perr("Unable to allocate space for extra SPI master data.\n");
return SPI_GENERIC_ERROR;
}
- memcpy(spi_config, &spi_master_raiden_debug, sizeof(struct spi_master));
+ *spi_config = spi_master_raiden_debug;
data->dev = device;
data->in_ep = in_endpoint;
data->out_ep = out_endpoint;
+ data->spi_config = spi_config;
- spi_config->data = data;
/*
* The SPI master needs to be configured based on the device connected.
* Using the device protocol interrogation, we will set the limits on
* the write and read sizes and switch command functions.
*/
- ret = configure_protocol(spi_config);
+ ret = configure_protocol(data);
if (ret) {
msg_perr("Raiden: Error configuring protocol\n"
" protocol = %u\n"
@@ -1614,8 +1642,12 @@ loop_end:
return SPI_GENERIC_ERROR;
}
- register_spi_master(spi_config);
- register_shutdown(raiden_debug_spi_shutdown, spi_config);
-
- return 0;
+ return register_spi_master(spi_config, data);
}
+
+const struct programmer_entry programmer_raiden_debug_spi = {
+ .name = "raiden_debug_spi",
+ .type = USB,
+ .devs.dev = devs_raiden,
+ .init = raiden_debug_spi_init,
+};