summaryrefslogtreecommitdiffstats
path: root/digilent_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'digilent_spi.c')
-rw-r--r--digilent_spi.c154
1 files changed, 83 insertions, 71 deletions
diff --git a/digilent_spi.c b/digilent_spi.c
index 0f7a9da12..ef0d23cf7 100644
--- a/digilent_spi.c
+++ b/digilent_spi.c
@@ -45,13 +45,15 @@
#define DATA_WRITE_EP 0x03
#define DATA_READ_EP 0x84
-static struct libusb_device_handle *handle = NULL;
-static bool reset_board;
+struct digilent_spi_data {
+ struct libusb_device_handle *handle;
+ bool reset_board;
+};
#define DIGILENT_VID 0x1443
#define DIGILENT_JTAG_PID 0x0007
-const struct dev_entry devs_digilent_spi[] = {
+static const struct dev_entry devs_digilent_spi[] = {
{ DIGILENT_VID, DIGILENT_JTAG_PID, OK, "Digilent", "Development board JTAG" },
{ 0 },
};
@@ -97,7 +99,7 @@ enum {
CMD_SPI_TX_END = 0x87,
};
-static int do_command(uint8_t *req, int req_len, uint8_t *res, int res_len)
+static int do_command(uint8_t *req, int req_len, uint8_t *res, int res_len, struct libusb_device_handle *handle)
{
int tx_len = 0;
int ret;
@@ -133,41 +135,41 @@ static int do_command(uint8_t *req, int req_len, uint8_t *res, int res_len)
return 0;
}
-static int gpio_open(void)
+static int gpio_open(struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_GPIO, CMD_GPIO_OPEN, 0x00 };
uint8_t res[2];
- return do_command(req, sizeof(req), res, sizeof(res));
+ return do_command(req, sizeof(req), res, sizeof(res), handle);
}
-static int gpio_set_dir(uint8_t direction)
+static int gpio_set_dir(uint8_t direction, struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_GPIO, CMD_GPIO_SET_DIR, 0x00,
direction, 0x00, 0x00, 0x00 };
uint8_t res[6];
- return do_command(req, sizeof(req), res, sizeof(res));
+ return do_command(req, sizeof(req), res, sizeof(res), handle);
}
-static int gpio_set_value(uint8_t value)
+static int gpio_set_value(uint8_t value, struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_GPIO, CMD_GPIO_SET_VAL, 0x00,
value, 0x00, 0x00, 0x00 };
uint8_t res[2];
- return do_command(req, sizeof(req), res, sizeof(res));
+ return do_command(req, sizeof(req), res, sizeof(res), handle);
}
-static int spi_open(void)
+static int spi_open(struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_SPI, CMD_SPI_OPEN, 0x00 };
uint8_t res[2];
- return do_command(req, sizeof(req), res, sizeof(res));
+ return do_command(req, sizeof(req), res, sizeof(res), handle);
}
-static int spi_set_speed(uint32_t speed)
+static int spi_set_speed(uint32_t speed, struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_SPI, CMD_SPI_SET_SPEED, 0x00,
(speed) & 0xff,
@@ -178,7 +180,7 @@ static int spi_set_speed(uint32_t speed)
uint32_t real_speed;
int ret;
- ret = do_command(req, sizeof(req), res, sizeof(res));
+ ret = do_command(req, sizeof(req), res, sizeof(res), handle);
if (ret)
return ret;
@@ -189,23 +191,23 @@ static int spi_set_speed(uint32_t speed)
return 0;
}
-static int spi_set_mode(uint8_t mode)
+static int spi_set_mode(uint8_t mode, struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_SPI, CMD_SPI_SET_MODE, 0x00, mode };
uint8_t res[2];
- return do_command(req, sizeof(req), res, sizeof(res));
+ return do_command(req, sizeof(req), res, sizeof(res), handle);
}
-static int spi_set_cs(uint8_t cs)
+static int spi_set_cs(uint8_t cs, struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_SPI, CMD_SPI_SET_CS, 0x00, cs };
uint8_t res[2];
- return do_command(req, sizeof(req), res, sizeof(res));
+ return do_command(req, sizeof(req), res, sizeof(res), handle);
}
-static int spi_start_io(uint8_t read_follows, uint32_t write_len)
+static int spi_start_io(uint8_t read_follows, uint32_t write_len, struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_SPI, CMD_SPI_START_IO, 0x00,
0x00, 0x00, /* meaning unknown */
@@ -216,17 +218,17 @@ static int spi_start_io(uint8_t read_follows, uint32_t write_len)
(write_len >> 24) & 0xff };
uint8_t res[2];
- return do_command(req, sizeof(req), res, sizeof(res));
+ return do_command(req, sizeof(req), res, sizeof(res), handle);
}
-static int spi_tx_end(uint8_t read_follows, uint32_t tx_len)
+static int spi_tx_end(uint8_t read_follows, uint32_t tx_len, struct libusb_device_handle *handle)
{
uint8_t req[] = { 0x00, CMD_SPI, CMD_SPI_TX_END, 0x00 };
uint8_t res[read_follows ? 10 : 6];
int ret;
uint32_t count;
- ret = do_command(req, sizeof(req), res, sizeof(res));
+ ret = do_command(req, sizeof(req), res, sizeof(res), handle);
if (ret != 0)
return ret;
@@ -265,19 +267,20 @@ static int digilent_spi_send_command(const struct flashctx *flash, unsigned int
int tx_len = 0;
uint8_t buf[len];
uint8_t read_follows = readcnt > 0 ? 1 : 0;
+ struct digilent_spi_data *digilent_data = flash->mst->spi.data;
memcpy(buf, writearr, writecnt);
memset(buf + writecnt, 0xff, readcnt);
- ret = spi_set_cs(0);
+ ret = spi_set_cs(0, digilent_data->handle);
if (ret != 0)
return ret;
- ret = spi_start_io(read_follows, writecnt);
+ ret = spi_start_io(read_follows, writecnt, digilent_data->handle);
if (ret != 0)
return ret;
- ret = libusb_bulk_transfer(handle, DATA_WRITE_EP, buf, len, &tx_len, USB_TIMEOUT);
+ ret = libusb_bulk_transfer(digilent_data->handle, DATA_WRITE_EP, buf, len, &tx_len, USB_TIMEOUT);
if (ret != 0) {
msg_perr("%s: failed to write data: '%s'\n", __func__, libusb_error_name(ret));
return -1;
@@ -288,7 +291,7 @@ static int digilent_spi_send_command(const struct flashctx *flash, unsigned int
}
if (read_follows) {
- ret = libusb_bulk_transfer(handle, DATA_READ_EP, buf, len, &tx_len, USB_TIMEOUT);
+ ret = libusb_bulk_transfer(digilent_data->handle, DATA_READ_EP, buf, len, &tx_len, USB_TIMEOUT);
if (ret != 0) {
msg_perr("%s: failed to read data: '%s'\n", __func__, libusb_error_name(ret));
return -1;
@@ -299,11 +302,11 @@ static int digilent_spi_send_command(const struct flashctx *flash, unsigned int
}
}
- ret = spi_tx_end(read_follows, len);
+ ret = spi_tx_end(read_follows, len, digilent_data->handle);
if (ret != 0)
return ret;
- ret = spi_set_cs(1);
+ ret = spi_set_cs(1, digilent_data->handle);
if (ret != 0)
return ret;
@@ -312,30 +315,30 @@ static int digilent_spi_send_command(const struct flashctx *flash, unsigned int
return 0;
}
+static int digilent_spi_shutdown(void *data)
+{
+ struct digilent_spi_data *digilent_data = data;
+
+ if (digilent_data->reset_board)
+ gpio_set_dir(0, digilent_data->handle);
+
+ libusb_close(digilent_data->handle);
+
+ free(data);
+ return 0;
+}
+
static const struct spi_master spi_master_digilent_spi = {
.features = SPI_MASTER_4BA,
.max_data_read = 252,
.max_data_write = 252,
.command = digilent_spi_send_command,
- .multicommand = default_spi_send_multicommand,
.read = default_spi_read,
.write_256 = default_spi_write_256,
- .write_aai = default_spi_write_aai,
+ .shutdown = digilent_spi_shutdown,
};
-
-static int digilent_spi_shutdown(void *data)
-{
- if (reset_board)
- gpio_set_dir(0);
-
- libusb_close(handle);
- handle = NULL;
-
- return 0;
-}
-
-static bool default_reset(void)
+static bool default_reset(struct libusb_device_handle *handle)
{
char board[17];
@@ -368,16 +371,13 @@ static const struct digilent_spispeeds spispeeds[] = {
{ NULL, 0 },
};
-int digilent_spi_init(void)
+static int digilent_spi_init(const struct programmer_cfg *cfg)
{
- char *p;
+ char *param_str;
uint32_t speed_hz = spispeeds[0].speed;
int i;
-
- if (handle != NULL) {
- msg_cerr("%s: handle already set! Please report a bug at flashrom@flashrom.org\n", __func__);
- return -1;
- }
+ struct libusb_device_handle *handle = NULL;
+ bool reset_board;
int32_t ret = libusb_init(NULL);
if (ret < 0) {
@@ -405,52 +405,64 @@ int digilent_spi_init(void)
goto close_handle;
}
- p = extract_programmer_param("spispeed");
- if (p) {
+ param_str = extract_programmer_param_str(cfg, "spispeed");
+ if (param_str) {
for (i = 0; spispeeds[i].name; ++i) {
- if (!strcasecmp(spispeeds[i].name, p)) {
+ if (!strcasecmp(spispeeds[i].name, param_str)) {
speed_hz = spispeeds[i].speed;
break;
}
}
if (!spispeeds[i].name) {
- msg_perr("Error: Invalid spispeed value: '%s'.\n", p);
- free(p);
+ msg_perr("Error: Invalid spispeed value: '%s'.\n", param_str);
+ free(param_str);
goto close_handle;
}
- free(p);
+ free(param_str);
}
- p = extract_programmer_param("reset");
- if (p && strlen(p))
- reset_board = (p[0] == '1');
+ param_str = extract_programmer_param_str(cfg, "reset");
+ if (param_str && strlen(param_str))
+ reset_board = (param_str[0] == '1');
else
- reset_board = default_reset();
- free(p);
+ reset_board = default_reset(handle);
+ free(param_str);
+
if (reset_board) {
- if (gpio_open() != 0)
+ if (gpio_open(handle) != 0)
goto close_handle;
- if (gpio_set_dir(1) != 0)
+ if (gpio_set_dir(1, handle) != 0)
goto close_handle;
- if (gpio_set_value(0) != 0)
+ if (gpio_set_value(0, handle) != 0)
goto close_handle;
}
- if (spi_open() != 0)
+ if (spi_open(handle) != 0)
goto close_handle;
- if (spi_set_speed(speed_hz) != 0)
+ if (spi_set_speed(speed_hz, handle) != 0)
goto close_handle;
- if (spi_set_mode(0x00) != 0)
+ if (spi_set_mode(0x00, handle) != 0)
goto close_handle;
- register_shutdown(digilent_spi_shutdown, NULL);
- register_spi_master(&spi_master_digilent_spi);
+ struct digilent_spi_data *digilent_data = calloc(1, sizeof(*digilent_data));
+ if (!digilent_data) {
+ msg_perr("Unable to allocate space for SPI master data\n");
+ goto close_handle;
+ }
+ digilent_data->reset_board = reset_board;
+ digilent_data->handle = handle;
- return 0;
+ return register_spi_master(&spi_master_digilent_spi, digilent_data);
close_handle:
libusb_close(handle);
- handle = NULL;
return -1;
}
+
+const struct programmer_entry programmer_digilent_spi = {
+ .name = "digilent_spi",
+ .type = USB,
+ .devs.dev = devs_digilent_spi,
+ .init = digilent_spi_init,
+};