diff options
Diffstat (limited to 'mstarddc_spi.c')
-rw-r--r-- | mstarddc_spi.c | 209 |
1 files changed, 116 insertions, 93 deletions
diff --git a/mstarddc_spi.c b/mstarddc_spi.c index 48d620454..44ebd0545 100644 --- a/mstarddc_spi.c +++ b/mstarddc_spi.c @@ -13,10 +13,9 @@ * GNU General Public License for more details. */ -#if CONFIG_MSTARDDC_SPI == 1 - #include <stdio.h> #include <string.h> +#include <stdbool.h> #include <stdlib.h> #include <ctype.h> #include <sys/types.h> @@ -31,11 +30,11 @@ #include "programmer.h" #include "spi.h" -static const struct spi_master spi_master_mstarddc; - -static int mstarddc_fd; -static int mstarddc_addr; -static int mstarddc_doreset = 1; +struct mstarddc_spi_data { + int fd; + int addr; + bool doreset; +}; // MSTAR DDC Commands #define MSTARDDC_SPI_WRITE 0x10 @@ -46,10 +45,12 @@ static int mstarddc_doreset = 1; /* Returns 0 upon success, a negative number upon errors. */ static int mstarddc_spi_shutdown(void *data) { + struct mstarddc_spi_data *mstarddc_data = data; + // Reset, disables ISP mode - if (mstarddc_doreset == 1) { + if (mstarddc_data->doreset) { uint8_t cmd = MSTARDDC_SPI_RESET; - if (write(mstarddc_fd, &cmd, 1) < 0) { + if (write(mstarddc_data->fd, &cmd, 1) < 0) { msg_perr("Error sending reset command: errno %d.\n", errno); return -1; @@ -60,20 +61,103 @@ static int mstarddc_spi_shutdown(void *data) "or an error occurred.\n"); } - if (close(mstarddc_fd) < 0) { + if (close(mstarddc_data->fd) < 0) { msg_perr("Error closing device: errno %d.\n", errno); return -1; } + + free(data); return 0; } /* Returns 0 upon success, a negative number upon errors. */ -int mstarddc_spi_init(void) +static int mstarddc_spi_send_command(const struct flashctx *flash, + unsigned int writecnt, + unsigned int readcnt, + const unsigned char *writearr, + unsigned char *readarr) { + struct mstarddc_spi_data *mstarddc_data = flash->mst->spi.data; int ret = 0; + uint8_t *cmd = malloc((writecnt + 1) * sizeof(uint8_t)); + if (cmd == NULL) { + msg_perr("Error allocating memory: errno %d.\n", errno); + ret = -1; + } + + if (!ret && writecnt) { + cmd[0] = MSTARDDC_SPI_WRITE; + memcpy(cmd + 1, writearr, writecnt); + if (write(mstarddc_data->fd, cmd, writecnt + 1) < 0) { + msg_perr("Error sending write command: errno %d.\n", + errno); + ret = -1; + } + } + + if (!ret && readcnt) { + struct i2c_rdwr_ioctl_data i2c_data; + struct i2c_msg msg[2]; + + cmd[0] = MSTARDDC_SPI_READ; + i2c_data.nmsgs = 2; + i2c_data.msgs = msg; + i2c_data.msgs[0].addr = mstarddc_data->addr; + i2c_data.msgs[0].len = 1; + i2c_data.msgs[0].flags = 0; + i2c_data.msgs[0].buf = cmd; + i2c_data.msgs[1].addr = mstarddc_data->addr; + i2c_data.msgs[1].len = readcnt; + i2c_data.msgs[1].flags = I2C_M_RD; + i2c_data.msgs[1].buf = readarr; + + if (ioctl(mstarddc_data->fd, I2C_RDWR, &i2c_data) < 0) { + msg_perr("Error sending read command: errno %d.\n", + errno); + ret = -1; + } + } + + if (!ret && (writecnt || readcnt)) { + cmd[0] = MSTARDDC_SPI_END; + if (write(mstarddc_data->fd, cmd, 1) < 0) { + msg_perr("Error sending end command: errno %d.\n", + errno); + ret = -1; + } + } + + /* Do not reset if something went wrong, as it might prevent from + * retrying flashing. */ + if (ret != 0) + mstarddc_data->doreset = false; + + if (cmd) + free(cmd); + + return ret; +} + +static const struct spi_master spi_master_mstarddc = { + .max_data_read = 256, + .max_data_write = 256, + .command = mstarddc_spi_send_command, + .read = default_spi_read, + .write_256 = default_spi_write_256, + .shutdown = mstarddc_spi_shutdown, +}; + +/* Returns 0 upon success, a negative number upon errors. */ +static int mstarddc_spi_init(const struct programmer_cfg *cfg) +{ + int ret = 0; + int mstarddc_fd = -1; + int mstarddc_addr; + bool mstarddc_doreset = true; + struct mstarddc_spi_data *mstarddc_data; // Get device, address from command-line - char *i2c_device = extract_programmer_param("dev"); + char *i2c_device = extract_programmer_param_str(cfg, "dev"); if (i2c_device != NULL && strlen(i2c_device) > 0) { char *i2c_address = strchr(i2c_device, ':'); if (i2c_address != NULL) { @@ -96,9 +180,9 @@ int mstarddc_spi_init(void) msg_pinfo("Info: Will try to use device %s and address 0x%02x.\n", i2c_device, mstarddc_addr); // Get noreset=1 option from command-line - char *noreset = extract_programmer_param("noreset"); + char *noreset = extract_programmer_param_str(cfg, "noreset"); if (noreset != NULL && noreset[0] == '1') - mstarddc_doreset = 0; + mstarddc_doreset = false; free(noreset); msg_pinfo("Info: Will %sreset the device at the end.\n", mstarddc_doreset ? "" : "NOT "); // Open device @@ -142,91 +226,30 @@ int mstarddc_spi_init(void) goto out; } } - // Register shutdown function - register_shutdown(mstarddc_spi_shutdown, NULL); - // Register programmer - register_spi_master(&spi_master_mstarddc); -out: - free(i2c_device); - return ret; -} - -/* Returns 0 upon success, a negative number upon errors. */ -static int mstarddc_spi_send_command(const struct flashctx *flash, - unsigned int writecnt, - unsigned int readcnt, - const unsigned char *writearr, - unsigned char *readarr) -{ - int ret = 0; - uint8_t *cmd = malloc((writecnt + 1) * sizeof(uint8_t)); - if (cmd == NULL) { - msg_perr("Error allocating memory: errno %d.\n", errno); + mstarddc_data = calloc(1, sizeof(*mstarddc_data)); + if (!mstarddc_data) { + msg_perr("Unable to allocate space for SPI master data\n"); ret = -1; + goto out; } - if (!ret && writecnt) { - cmd[0] = MSTARDDC_SPI_WRITE; - memcpy(cmd + 1, writearr, writecnt); - if (write(mstarddc_fd, cmd, writecnt + 1) < 0) { - msg_perr("Error sending write command: errno %d.\n", - errno); - ret = -1; - } - } - - if (!ret && readcnt) { - struct i2c_rdwr_ioctl_data i2c_data; - struct i2c_msg msg[2]; - - cmd[0] = MSTARDDC_SPI_READ; - i2c_data.nmsgs = 2; - i2c_data.msgs = msg; - i2c_data.msgs[0].addr = mstarddc_addr; - i2c_data.msgs[0].len = 1; - i2c_data.msgs[0].flags = 0; - i2c_data.msgs[0].buf = cmd; - i2c_data.msgs[1].addr = mstarddc_addr; - i2c_data.msgs[1].len = readcnt; - i2c_data.msgs[1].flags = I2C_M_RD; - i2c_data.msgs[1].buf = readarr; - - if (ioctl(mstarddc_fd, I2C_RDWR, &i2c_data) < 0) { - msg_perr("Error sending read command: errno %d.\n", - errno); - ret = -1; - } - } - - if (!ret && (writecnt || readcnt)) { - cmd[0] = MSTARDDC_SPI_END; - if (write(mstarddc_fd, cmd, 1) < 0) { - msg_perr("Error sending end command: errno %d.\n", - errno); - ret = -1; - } - } - - /* Do not reset if something went wrong, as it might prevent from - * retrying flashing. */ - if (ret != 0) - mstarddc_doreset = 0; - - if (cmd) - free(cmd); + mstarddc_data->fd = mstarddc_fd; + mstarddc_data->addr = mstarddc_addr; + mstarddc_data->doreset = mstarddc_doreset; + // Register programmer + register_spi_master(&spi_master_mstarddc, mstarddc_data); +out: + free(i2c_device); + if (ret && (mstarddc_fd >= 0)) + close(mstarddc_fd); return ret; } -static const struct spi_master spi_master_mstarddc = { - .max_data_read = 256, - .max_data_write = 256, - .command = mstarddc_spi_send_command, - .multicommand = default_spi_send_multicommand, - .read = default_spi_read, - .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, +const struct programmer_entry programmer_mstarddc_spi = { + .name = "mstarddc_spi", + .type = OTHER, + .devs.note = "MSTAR DDC devices addressable via /dev/i2c-* on Linux.\n", + .init = mstarddc_spi_init, }; - -#endif |