summaryrefslogtreecommitdiffstats
path: root/mstarddc_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'mstarddc_spi.c')
-rw-r--r--mstarddc_spi.c209
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