summaryrefslogtreecommitdiff
path: root/util/iteflash.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/iteflash.c')
-rw-r--r--util/iteflash.c457
1 files changed, 290 insertions, 167 deletions
diff --git a/util/iteflash.c b/util/iteflash.c
index 95a60c1c97..d608031f83 100644
--- a/util/iteflash.c
+++ b/util/iteflash.c
@@ -49,10 +49,10 @@
#define CHIP_ID 0x8380
/* Embedded flash page size */
-#define PAGE_SIZE 256
+#define PAGE_SIZE (1<<8)
/* Embedded flash block write size for different programming modes. */
-#define FTDI_BLOCK_WRITE_SIZE 65536
+#define FTDI_BLOCK_WRITE_SIZE (1<<16)
/* Embedded flash number of pages in a sector erase */
#define SECTOR_ERASE_PAGES 4
@@ -78,56 +78,63 @@
#define RSTS_HGRST 0x08
#define RSTS_GRST 0x04
-/* store custom parameters */
-const char *input_filename;
-const char *output_filename;
-static int usb_vid = SERVO_USB_VID;
-static int usb_pid = SERVO_USB_PID;
-static int usb_interface = SERVO_INTERFACE;
-static char *usb_serial;
-static int flash_size;
-static int exit_requested;
-static int is8320dx;
-
-/* debug traces : default OFF*/
-static int debug;
-
-/* optional command flags */
-enum {
- FLAG_UNPROTECT = 0x01,
- FLAG_ERASE = 0x02,
- FLAG_CCD_MODE = 0x04
-};
-
-enum interface_type {
- FTDI_IF,
- CCD_IF
+static volatile sig_atomic_t exit_requested;
+
+struct i2c_interface;
+
+/* Config mostly comes from the command line. Defaults are set in main(). */
+struct iteflash_config {
+ const char *input_filename;
+ const char *output_filename;
+ int send_waveform; /* boolean */
+ int unprotect; /* boolean */
+ int erase; /* boolean */
+ int debug; /* boolean */
+ int usb_interface;
+ int usb_vid;
+ int usb_pid;
+ const char *usb_serial;
+ const struct i2c_interface *i2c_if;
};
struct common_hnd {
- enum interface_type iftype;
+ struct iteflash_config conf;
+ int flash_size;
+ int is8320dx; /* boolean */
union {
struct ftdi_context *ftdi_hnd;
struct usb_endpoint uep;
};
};
-/* number of bytes to send consecutively before checking for ACKs */
-#define TX_BUFFER_LIMIT 32
+/* For all callback return values, zero indicates success, non-zero failure. */
+struct i2c_interface {
+ /* Optional, may be NULL. */
+ int (*interface_init)(struct common_hnd *chnd);
+ /* Always called if non-NULL, even if special waveform is skipped! */
+ /* Optional, may be NULL. */
+ int (*interface_post_waveform)(struct common_hnd *chnd);
+ /* Called exactly once if and only if interface_init() succeeded. */
+ /* Optional, may be NULL. */
+ int (*interface_shutdown)(struct common_hnd *chnd);
+ /* Optional, may be NULL (unsupported for this I2C interface type). */
+ int (*send_special_waveform)(struct common_hnd *chnd);
+ /* Required, must not be NULL. */
+ int (*byte_transfer)(struct common_hnd *chnd, uint8_t addr,
+ uint8_t *data, int write, int numbytes);
+ /* Required, must be positive. */
+ int block_write_size;
+};
-/* For backwards compatibility let FTDI value be the default. */
-static int block_write_size_ = FTDI_BLOCK_WRITE_SIZE;
-static int block_write_size(void)
-{
- return block_write_size_;
-}
+/* number of bytes to send consecutively before checking for ACKs */
+#define FTDI_TX_BUFFER_LIMIT 32
static int i2c_add_send_byte(struct ftdi_context *ftdi, uint8_t *buf,
- uint8_t *ptr, uint8_t *tbuf, int tcnt)
+ uint8_t *ptr, uint8_t *tbuf, int tcnt, int debug)
{
int ret, i, j, remaining_data, ack_idx;
int tx_buffered = 0;
- static uint8_t ack[TX_BUFFER_LIMIT];
+ static uint8_t ack[FTDI_TX_BUFFER_LIMIT];
uint8_t *b = ptr;
uint8_t failed_ack = 0;
@@ -151,10 +158,10 @@ static int i2c_add_send_byte(struct ftdi_context *ftdi, uint8_t *buf,
tx_buffered++;
/*
- * On the last byte, or every TX_BUFFER_LIMIT bytes, read the
- * ACK bits.
+ * On the last byte, or every FTDI_TX_BUFFER_LIMIT bytes, read
+ * the ACK bits.
*/
- if (i == tcnt-1 || (tx_buffered == TX_BUFFER_LIMIT)) {
+ if (i == tcnt-1 || (tx_buffered == FTDI_TX_BUFFER_LIMIT)) {
/* write data */
ret = ftdi_write_data(ftdi, buf, b - buf);
if (ret < 0) {
@@ -198,7 +205,7 @@ static int i2c_add_send_byte(struct ftdi_context *ftdi, uint8_t *buf,
}
static int i2c_add_recv_bytes(struct ftdi_context *ftdi, uint8_t *buf,
- uint8_t *ptr, uint8_t *rbuf, int rcnt)
+ uint8_t *ptr, uint8_t *rbuf, int rcnt)
{
int ret, i, rbuf_idx;
uint8_t *b = ptr;
@@ -246,8 +253,15 @@ static int i2c_add_recv_bytes(struct ftdi_context *ftdi, uint8_t *buf,
return ret;
}
+static inline int i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr,
+ uint8_t *data, int write, int numbytes)
+{
+ return chnd->conf.i2c_if->byte_transfer(chnd, addr, data, write,
+ numbytes);
+}
+
#define USB_I2C_HEADER_SIZE 4
-static int ccd_i2c_byte_transfer(struct usb_endpoint *uep, uint8_t addr,
+static int ccd_i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr,
uint8_t *data, int write, int numbytes)
{
uint8_t usb_buffer[USB_I2C_HEADER_SIZE + numbytes +
@@ -292,7 +306,7 @@ static int ccd_i2c_byte_transfer(struct usb_endpoint *uep, uint8_t addr,
}
response_size = 0;
- usb_trx(uep, usb_buffer,
+ usb_trx(&chnd->uep, usb_buffer,
write ? sizeof(usb_buffer) : USB_I2C_HEADER_SIZE + extra,
usb_buffer, sizeof(usb_buffer), 1, &response_size);
@@ -325,8 +339,8 @@ static int ccd_i2c_byte_transfer(struct usb_endpoint *uep, uint8_t addr,
return 0;
}
-static int i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr,
- uint8_t *data, int write, int numbytes)
+static int ftdi_i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr,
+ uint8_t *data, int write, int numbytes)
{
int ret, rets;
static uint8_t buf[FTDI_CMD_BUF_SIZE];
@@ -334,10 +348,6 @@ static int i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr,
uint8_t slave_addr;
struct ftdi_context *ftdi;
- if (chnd->iftype == CCD_IF)
- return ccd_i2c_byte_transfer(&chnd->uep, addr,
- data, write, numbytes);
-
ret = 0;
b = buf;
ftdi = chnd->ftdi_hnd;
@@ -355,9 +365,9 @@ static int i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr,
/* send address */
slave_addr = (addr << 1) | (write ? 0 : 1);
- ret = i2c_add_send_byte(ftdi, buf, b, &slave_addr, 1);
+ ret = i2c_add_send_byte(ftdi, buf, b, &slave_addr, 1, chnd->conf.debug);
if (ret < 0) {
- if (debug)
+ if (chnd->conf.debug)
fprintf(stderr, "address %02x failed\n", addr);
ret = -ENXIO;
goto exit_xfer;
@@ -365,7 +375,8 @@ static int i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr,
b = buf;
if (write) /* write data */
- ret = i2c_add_send_byte(ftdi, buf, b, data, numbytes);
+ ret = i2c_add_send_byte(ftdi, buf, b, data, numbytes,
+ chnd->conf.debug);
else /* read data */
ret = i2c_add_recv_bytes(ftdi, buf, b, data, numbytes);
@@ -413,6 +424,7 @@ static int i2c_read_byte(struct common_hnd *chnd, uint8_t cmd, uint8_t *data)
return 0;
}
+/* Fills in chnd->flash_size */
static int check_chipid(struct common_hnd *chnd)
{
int ret;
@@ -458,19 +470,19 @@ static int check_chipid(struct common_hnd *chnd)
}
/* compute embedded flash size from CHIPVER field */
if ((ver & 0x0f) == 0x03) {
- flash_size = DX[(ver & 0xF0)>>5] * 1024;
- is8320dx = 1;
+ chnd->flash_size = DX[(ver & 0xF0)>>5] * 1024;
+ chnd->is8320dx = 1;
} else {
- flash_size = (128 + (ver & 0xF0)) * 1024;
- is8320dx = 0;
+ chnd->flash_size = (128 + (ver & 0xF0)) * 1024;
+ chnd->is8320dx = 0;
}
printf("CHIPID %04x, CHIPVER %02x, Flash size %d kB\n", id, ver,
- flash_size / 1024);
+ chnd->flash_size / 1024);
return 0;
}
-/* DBGR Reset*/
+/* DBGR Reset */
static int dbgr_reset(struct common_hnd *chnd, unsigned char val)
{
int ret = 0;
@@ -489,7 +501,7 @@ static int dbgr_reset(struct common_hnd *chnd, unsigned char val)
return 0;
}
-/* disable watchdog*/
+/* disable watchdog */
static int dbgr_disable_watchdog(struct common_hnd *chnd)
{
int ret = 0;
@@ -646,7 +658,7 @@ failed_read_status:
return ret;
}
-static int config_i2c(struct ftdi_context *ftdi)
+static int ftdi_config_i2c(struct ftdi_context *ftdi)
{
int ret;
uint8_t buf[5];
@@ -699,7 +711,7 @@ static int config_i2c(struct ftdi_context *ftdi)
#define SPECIAL_BUFFER_SIZE \
(((SPECIAL_LEN_USEC * SPECIAL_FREQ * 2 / USEC) + 7) & ~7)
-static int ccd_trigger_special_waveform(struct usb_endpoint *uep)
+static int ccd_trigger_special_waveform(struct common_hnd *chnd)
{
uint8_t response[20];
size_t rsize;
@@ -711,7 +723,8 @@ static int ccd_trigger_special_waveform(struct usb_endpoint *uep)
CROS_CMD_ITE_SYNC
};
- usb_trx(uep, req, sizeof(req), response, sizeof(response), 1, &rsize);
+ usb_trx(&chnd->uep, req, sizeof(req), response, sizeof(response), 1,
+ &rsize);
if (rsize < USB_I2C_HEADER_SIZE)
return -1;
@@ -722,17 +735,26 @@ static int ccd_trigger_special_waveform(struct usb_endpoint *uep)
return 0;
}
-static int ftdi_send_special_waveform(struct ftdi_context *ftdi, uint64_t *wave)
+static int ftdi_send_special_waveform(struct common_hnd *chnd)
{
int ret;
int i;
uint8_t release_lines[] = {SET_BITS_LOW, 0, 0};
+ uint64_t *wave;
+ struct ftdi_context *ftdi = chnd->ftdi_hnd;
+
+ wave = malloc(SPECIAL_BUFFER_SIZE);
+ if (!wave) {
+ fprintf(stderr, "malloc(%zu) failed\n",
+ (size_t)SPECIAL_BUFFER_SIZE);
+ return -1;
+ }
/* Reset the FTDI into a known state */
ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_RESET);
if (ret) {
fprintf(stderr, "failed to reset FTDI\n");
- return ret;
+ goto free_and_return;
}
/*
@@ -742,14 +764,14 @@ static int ftdi_send_special_waveform(struct ftdi_context *ftdi, uint64_t *wave)
ret = ftdi_set_baudrate(ftdi, 160000);
if (ret) {
fprintf(stderr, "failed to set bitbang clock\n");
- return ret;
+ goto free_and_return;
}
/* Enable asynchronous bit-bang mode */
ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_BITBANG);
if (ret) {
fprintf(stderr, "failed to set bitbang mode\n");
- return ret;
+ goto free_and_return;
}
/* do usb special waveform */
@@ -779,34 +801,33 @@ static int ftdi_send_special_waveform(struct ftdi_context *ftdi, uint64_t *wave)
/* clean everything to go back to regular I2C communication */
ftdi_usb_purge_buffers(ftdi);
ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET);
- config_i2c(ftdi);
+ ftdi_config_i2c(ftdi);
ftdi_write_data(ftdi, release_lines, sizeof(release_lines));
+ free_and_return:
+ free(wave);
return ret;
}
static int send_special_waveform(struct common_hnd *chnd)
{
int ret;
- uint64_t *wave;
int iterations;
- if (chnd->iftype == FTDI_IF)
- wave = malloc(SPECIAL_BUFFER_SIZE);
- else
- wave = NULL;
+ if (!chnd->conf.i2c_if->send_special_waveform) {
+ fprintf(stderr, "This binary does not support sending the ITE "
+ "special waveform with the chosen I2C interface.\n");
+ return -1;
+ }
+ /* Is this printed log line accurate here? Is this FTDI-specific? */
printf("Waiting for the EC power-on sequence ...");
fflush(stdout);
iterations = 0;
do {
- if (chnd->iftype == FTDI_IF)
- ret = ftdi_send_special_waveform(chnd->ftdi_hnd, wave);
- else
- ret = ccd_trigger_special_waveform(&chnd->uep);
-
+ ret = chnd->conf.i2c_if->send_special_waveform(chnd);
if (ret)
break;
@@ -818,7 +839,7 @@ static int send_special_waveform(struct common_hnd *chnd)
spi_flash_follow_mode_exit(chnd, "exit follow mode");
/*
* If we can talk to chip, then we can break the retry
- * loop
+ * loop.
*/
ret = check_chipid(chnd);
@@ -831,7 +852,7 @@ static int send_special_waveform(struct common_hnd *chnd)
ret = -1;
if (!(iterations % 10))
printf("!please reset EC if flashing sequence"
- " is not starting!\n");
+ " is not starting!\n");
}
} while (ret && (iterations++ < 10));
@@ -841,8 +862,6 @@ static int send_special_waveform(struct common_hnd *chnd)
else
printf(" Done.\n");
- if (wave)
- free(wave);
return ret;
}
@@ -912,6 +931,7 @@ static int command_write_pages(struct common_hnd *chnd, uint32_t address,
uint32_t size, uint8_t *buffer)
{
int res = -EIO;
+ int block_write_size = chnd->conf.i2c_if->block_write_size;
uint32_t remaining = size;
int cnt;
uint8_t addr_H, addr_M, addr_L;
@@ -921,8 +941,8 @@ static int command_write_pages(struct common_hnd *chnd, uint32_t address,
goto failed_write;
while (remaining) {
- cnt = (remaining > block_write_size()) ?
- block_write_size() : remaining;
+ cnt = (remaining > block_write_size) ?
+ block_write_size : remaining;
addr_H = (address >> 16) & 0xFF;
addr_M = (address >> 8) & 0xFF;
addr_L = (address) & 0xFF;
@@ -957,7 +977,7 @@ static int command_write_pages(struct common_hnd *chnd, uint32_t address,
if (spi_poll_busy(chnd, "AAI write") < 0)
goto failed_write;
- /* Write up to block_write_size() data */
+ /* Write up to block_write_size data */
res = i2c_write_byte(chnd, 0x10, 0x20);
res = i2c_byte_transfer(chnd, I2C_BLOCK_ADDR, buffer, 1, cnt);
buffer += cnt;
@@ -1007,7 +1027,8 @@ failed_write:
* original ITE 8903 Download board.
*/
static int command_write_pages2(struct common_hnd *chnd, uint32_t address,
- uint32_t size, uint8_t *buffer)
+ uint32_t size, uint8_t *buffer,
+ int block_write_size)
{
int res = 0;
uint8_t BA, A1, A0, data;
@@ -1064,8 +1085,8 @@ static int command_write_pages2(struct common_hnd *chnd, uint32_t address,
goto failed_write;
res = i2c_write_byte(chnd, 0x10, 0x20);
- res = i2c_byte_transfer(chnd, I2C_BLOCK_ADDR,
- buffer, 1, block_write_size()-2);
+ res = i2c_byte_transfer(chnd, I2C_BLOCK_ADDR, buffer, 1,
+ block_write_size-2);
/* No error so far */
res = size;
@@ -1096,7 +1117,7 @@ static int command_erase(struct common_hnd *chnd, uint32_t len, uint32_t off)
printf("Erasing chip...\n");
- if (off != 0 || len != flash_size) {
+ if (off != 0 || len != chnd->flash_size) {
fprintf(stderr, "Only full chip erase is supported\n");
return -EINVAL;
}
@@ -1115,7 +1136,7 @@ static int command_erase(struct common_hnd *chnd, uint32_t len, uint32_t off)
goto failed_erase;
/* do chip erase */
- if (remaining == flash_size) {
+ if (remaining == chnd->flash_size) {
if (spi_flash_command_short(chnd, SPI_CMD_CHIP_ERASE,
"chip erase") < 0)
goto failed_erase;
@@ -1138,7 +1159,7 @@ wait_busy_cleared:
"write disable for erase") < 0)
goto failed_erase;
- if (remaining == flash_size) {
+ if (remaining == chnd->flash_size) {
remaining = 0;
draw_spinner(remaining, len);
} else {
@@ -1184,7 +1205,7 @@ static int command_erase2(struct common_hnd *chnd, uint32_t len,
printf("Erasing flash...erase size=%d\n", len);
- if (off != 0 || len != flash_size) {
+ if (off != 0 || len != chnd->flash_size) {
fprintf(stderr, "Only full chip erase is supported\n");
return -EINVAL;
}
@@ -1265,7 +1286,7 @@ static int read_flash(struct common_hnd *chnd, const char *filename,
}
if (!size)
- size = flash_size;
+ size = chnd->flash_size;
printf("Reading %d bytes at 0x%08x\n", size, offset);
res = command_read_pages(chnd, offset, size, buffer);
if (res > 0) {
@@ -1285,7 +1306,7 @@ static int write_flash(struct common_hnd *chnd, const char *filename,
{
int res, written;
FILE *hnd;
- int size = flash_size;
+ int size = chnd->flash_size;
uint8_t *buffer = malloc(size);
if (!buffer) {
@@ -1331,8 +1352,9 @@ static int write_flash2(struct common_hnd *chnd, const char *filename,
uint32_t offset)
{
int res, written;
+ int block_write_size = chnd->conf.i2c_if->block_write_size;
FILE *hnd;
- int size = flash_size;
+ int size = chnd->flash_size;
int cnt;
uint8_t *buffer = malloc(size);
@@ -1359,10 +1381,9 @@ static int write_flash2(struct common_hnd *chnd, const char *filename,
offset = 0;
printf("Writing %d bytes at 0x%08x.......\n", res, offset);
while (res) {
- cnt = (res > block_write_size()) ?
- block_write_size() : res;
+ cnt = (res > block_write_size) ? block_write_size : res;
written = command_write_pages2(chnd, offset, cnt,
- &buffer[offset]);
+ &buffer[offset], block_write_size);
if (written == -EIO)
goto failed_write;
@@ -1390,11 +1411,11 @@ static int verify_flash(struct common_hnd *chnd, const char *filename,
int res;
int file_size;
FILE *hnd;
- uint8_t *buffer = malloc(flash_size);
- uint8_t *buffer2 = malloc(flash_size);
+ uint8_t *buffer = malloc(chnd->flash_size);
+ uint8_t *buffer2 = malloc(chnd->flash_size);
if (!buffer || !buffer2) {
- fprintf(stderr, "Cannot allocate %d bytes\n", flash_size);
+ fprintf(stderr, "Cannot allocate %d bytes\n", chnd->flash_size);
free(buffer);
free(buffer2);
return -ENOMEM;
@@ -1407,7 +1428,7 @@ static int verify_flash(struct common_hnd *chnd, const char *filename,
goto exit;
}
- file_size = fread(buffer, 1, flash_size, hnd);
+ file_size = fread(buffer, 1, chnd->flash_size, hnd);
fclose(hnd);
if (file_size <= 0) {
fprintf(stderr, "Cannot read %s\n", filename);
@@ -1416,7 +1437,7 @@ static int verify_flash(struct common_hnd *chnd, const char *filename,
}
printf("Verify %d bytes at 0x%08x\n", file_size, offset);
- res = command_read_pages(chnd, offset, flash_size, buffer2);
+ res = command_read_pages(chnd, offset, chnd->flash_size, buffer2);
if (res > 0)
res = memcmp(buffer, buffer2, file_size);
@@ -1429,7 +1450,7 @@ exit:
}
static struct ftdi_context *open_ftdi_device(int vid, int pid,
- int interface, char *serial)
+ int interface, const char *serial)
{
struct ftdi_context *ftdi;
int ret;
@@ -1459,14 +1480,88 @@ open_failed:
return NULL;
}
+static int ccd_i2c_interface_init(struct common_hnd *chnd)
+{
+ int ret;
+ chnd->conf.usb_vid = CR50_USB_VID;
+ chnd->conf.usb_pid = CR50_USB_PID;
+ ret = usb_findit(chnd->conf.usb_vid, chnd->conf.usb_pid,
+ CR50_I2C_SUBCLASS, CR50_I2C_PROTOCOL, &chnd->uep);
+ if (ret < 0) {
+ fprintf(stderr, "%s: usb_findit() returned %d error", __func__,
+ ret);
+ return ret;
+ }
+ printf("Using CCD device%s\n",
+ chnd->conf.usb_serial ? ", ignoring serial number" : "");
+ return 0;
+}
+
+static int ccd_i2c_interface_shutdown(struct common_hnd *chnd)
+{
+ usb_shut_down(&chnd->uep);
+ return 0;
+}
+
+static int ftdi_i2c_interface_init(struct common_hnd *chnd)
+{
+ chnd->ftdi_hnd = open_ftdi_device(chnd->conf.usb_vid,
+ chnd->conf.usb_pid, chnd->conf.usb_interface,
+ chnd->conf.usb_serial);
+ if (chnd->ftdi_hnd == NULL)
+ return -1;
+ return 0;
+}
+
+static int ftdi_i2c_interface_post_waveform(struct common_hnd *chnd)
+{
+ int ret;
+
+ ret = ftdi_config_i2c(chnd->ftdi_hnd);
+ if (ret < 0)
+ return ret;
+
+ ret = check_chipid(chnd);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/* Close the FTDI USB handle */
+static int ftdi_i2c_interface_shutdown(struct common_hnd *chnd)
+{
+ ftdi_usb_close(chnd->ftdi_hnd);
+ ftdi_free(chnd->ftdi_hnd);
+ return 0;
+}
+
+static const struct i2c_interface ccd_i2c_interface = {
+ .interface_init = ccd_i2c_interface_init,
+ .interface_shutdown = ccd_i2c_interface_shutdown,
+ .send_special_waveform = ccd_trigger_special_waveform,
+ .byte_transfer = ccd_i2c_byte_transfer,
+ .block_write_size = PAGE_SIZE,
+};
+
+static const struct i2c_interface ftdi_i2c_interface = {
+ .interface_init = ftdi_i2c_interface_init,
+ .interface_post_waveform = ftdi_i2c_interface_post_waveform,
+ .interface_shutdown = ftdi_i2c_interface_shutdown,
+ .send_special_waveform = ftdi_send_special_waveform,
+ .byte_transfer = ftdi_i2c_byte_transfer,
+ .block_write_size = FTDI_BLOCK_WRITE_SIZE,
+};
+
static const struct option longopts[] = {
- {"ccd", 0, 0, 'c'},
{"debug", 0, 0, 'd'},
{"erase", 0, 0, 'e'},
{"help", 0, 0, 'h'},
+ {"i2c-interface", 1, 0, 'c'},
{"interface", 1, 0, 'i'},
{"product", 1, 0, 'p'},
{"read", 1, 0, 'r'},
+ {"send-waveform", 1, 0, 'W'},
{"serial", 1, 0, 's'},
{"unprotect", 0, 0, 'u'},
{"vendor", 1, 0, 'v'},
@@ -1476,12 +1571,13 @@ static const struct option longopts[] = {
static void display_usage(char *program)
{
- fprintf(stderr, "Usage: %s [-c] [-d] [-v <VID>] [-p <PID>] [-i <1|2>] "
- "[-s <serial>] [-u] [-e] [-r <file>] [-w <file>]\n", program);
- fprintf(stderr, "--c[cd] : use CCD interface instead of FTDI, make "
- "sure this option is included before -p and or -v\n");
+ fprintf(stderr, "Usage: %s [-d] [-v <VID>] [-p <PID>] "
+ "[-c <ccd|ftdi>] [-i <1|2>] [-s <serial>] [-u] [-e] "
+ "[-r <file>] [-W <0|1|false|true>] [-w <file>]\n", program);
fprintf(stderr, "--d[ebug] : output debug traces\n");
fprintf(stderr, "--e[rase] : erase all the flash content\n");
+ fprintf(stderr, "-c, --i2c_interface <ccd|ftdi> : I2C interface "
+ "to use\n");
fprintf(stderr, "--i[interface] <1> : FTDI interface: A=1, B=2, ...\n");
fprintf(stderr, "--p[roduct] <0x1234> : USB product ID\n");
fprintf(stderr, "--r[ead] <file> : read the flash content and "
@@ -1489,66 +1585,88 @@ static void display_usage(char *program)
fprintf(stderr, "--s[erial] <serialname> : USB serial string\n");
fprintf(stderr, "--u[nprotect] : remove flash write protect\n");
fprintf(stderr, "--v[endor] <0x1234> : USB vendor ID\n");
+ fprintf(stderr, "-W, --send-waveform <0|1|false|true> : Send the "
+ "specal waveform? Default is false, subject to change."
+ " Set to false if ITE direct firmware update mode has "
+ "already been enabled.\n");
fprintf(stderr, "--w[rite] <file> : read <file> and "
"write it to flash\n");
exit(2);
}
-static int parse_parameters(int argc, char **argv)
+static int parse_parameters(int argc, char **argv, struct iteflash_config *conf)
{
int opt, idx;
- int flags = 0;
- while ((opt = getopt_long(argc, argv, "?cdehi:p:r:s:uv:w:",
+ while ((opt = getopt_long(argc, argv, "?dehc:i:p:r:s:uv:W:w:",
longopts, &idx)) != -1) {
switch (opt) {
case 'c':
- flags |= FLAG_CCD_MODE;
- usb_vid = CR50_USB_VID;
- usb_pid = CR50_USB_PID;
- block_write_size_ = PAGE_SIZE;
+ if (!strcasecmp(optarg, "ccd")) {
+ conf->i2c_if = &ccd_i2c_interface;
+ } else if (!strcasecmp(optarg, "ftdi")) {
+ conf->i2c_if = &ftdi_i2c_interface;
+ } else {
+ fprintf(stderr, "Unexpected -c / "
+ "--i2c-interface value: %s\n", optarg);
+ return -1;
+ }
break;
case 'd':
- debug = 1;
+ conf->debug = 1;
break;
case 'e':
- flags |= FLAG_ERASE;
+ conf->erase = 1;
break;
case 'h':
case '?':
display_usage(argv[0]);
break;
case 'i':
- usb_interface = atoi(optarg);
+ conf->usb_interface = atoi(optarg);
break;
case 'p':
- usb_pid = strtol(optarg, NULL, 16);
+ conf->usb_pid = strtol(optarg, NULL, 16);
break;
case 'r':
- input_filename = optarg;
+ conf->input_filename = optarg;
break;
case 's':
- usb_serial = optarg;
+ conf->usb_serial = optarg;
break;
case 'u':
- flags |= FLAG_UNPROTECT;
+ conf->unprotect = 1;
break;
case 'v':
- usb_vid = strtol(optarg, NULL, 16);
+ conf->usb_vid = strtol(optarg, NULL, 16);
+ break;
+ case 'W':
+ if (!strcmp(optarg, "0") ||
+ !strcasecmp(optarg, "false")) {
+ conf->send_waveform = 0;
+ } else if (!strcmp(optarg, "1") ||
+ !strcasecmp(optarg, "true")) {
+ conf->send_waveform = 1;
+ } else {
+ fprintf(stderr, "Unexpected -W / "
+ "--special-waveform value: %s\n",
+ optarg);
+ return -1;
+ }
break;
case 'w':
- output_filename = optarg;
+ conf->output_filename = optarg;
break;
}
}
- return flags;
+ return 0;
}
static void sighandler(int signum)
{
printf("\nCaught signal %d: %s\nExiting...\n",
signum, sys_siglist[signum]);
- ++exit_requested;
+ exit_requested = 1;
}
static void register_sigaction(void)
@@ -1565,70 +1683,75 @@ static void register_sigaction(void)
int main(int argc, char **argv)
{
- struct common_hnd chnd;
- int ret = 1;
- int flags;
+ int ret = 1, other_ret;
+ struct common_hnd chnd = {
+ /* Default flag settings. */
+ .conf = {
+ .usb_interface = SERVO_INTERFACE,
+ .usb_vid = SERVO_USB_VID,
+ .usb_pid = SERVO_USB_PID,
+ .i2c_if = &ftdi_i2c_interface,
+ },
+ };
/* Parse command line options */
- flags = parse_parameters(argc, argv);
+ if (parse_parameters(argc, argv, &chnd.conf) < 0)
+ return ret;
/* Open the communications channel. */
- memset(&chnd, 0, sizeof(chnd));
- if (flags & FLAG_CCD_MODE) {
- usb_findit(usb_vid, usb_pid, CR50_I2C_SUBCLASS,
- CR50_I2C_PROTOCOL, &chnd.uep);
- chnd.iftype = CCD_IF;
- printf("Using CCD device%s\n",
- usb_serial ? ", ignoring serial number" : "");
- } else {
- chnd.ftdi_hnd = open_ftdi_device(usb_vid, usb_pid,
- usb_interface, usb_serial);
- if (chnd.ftdi_hnd == NULL)
- return 1;
- chnd.iftype = FTDI_IF;
- }
+ if (chnd.conf.i2c_if->interface_init &&
+ chnd.conf.i2c_if->interface_init(&chnd))
+ return ret;
- /* Register signal handler after opening USB handle. */
+ /* Register signal handler after opening the communications channel. */
register_sigaction();
/* Trigger embedded monitor detection */
- if (send_special_waveform(&chnd) < 0)
- goto terminate;
-
- if (chnd.iftype == FTDI_IF) {
- if (config_i2c(chnd.ftdi_hnd) < 0)
+ if (chnd.conf.send_waveform) {
+ if (send_special_waveform(&chnd))
goto terminate;
- if (check_chipid(&chnd) < 0)
+ } else {
+ ret = check_chipid(&chnd);
+ if (ret) {
+ fprintf(stderr, "Failed to get ITE chip ID. This "
+ "could be because the ITE direct firmware "
+ "update (DFU) mode is not enabled.\n");
goto terminate;
+ }
}
- if (flags & FLAG_UNPROTECT)
+ if (chnd.conf.i2c_if->interface_post_waveform &&
+ chnd.conf.i2c_if->interface_post_waveform(&chnd))
+ goto terminate;
+
+ if (chnd.conf.unprotect)
command_write_unprotect(&chnd);
- if (input_filename) {
- ret = read_flash(&chnd, input_filename, 0, flash_size);
+ if (chnd.conf.input_filename) {
+ ret = read_flash(&chnd, chnd.conf.input_filename, 0,
+ chnd.flash_size);
if (ret)
goto terminate;
}
- if (flags & FLAG_ERASE) {
- if (is8320dx)
+ if (chnd.conf.erase) {
+ if (chnd.is8320dx)
/* Do Normal Erase Function */
- command_erase2(&chnd, flash_size, 0, 0);
+ command_erase2(&chnd, chnd.flash_size, 0, 0);
else
- command_erase(&chnd, flash_size, 0);
+ command_erase(&chnd, chnd.flash_size, 0);
/* Call DBGR Rest to clear the EC lock status after erasing */
dbgr_reset(&chnd, RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST);
}
- if (output_filename) {
- if (is8320dx)
- ret = write_flash2(&chnd, output_filename, 0);
+ if (chnd.conf.output_filename) {
+ if (chnd.is8320dx)
+ ret = write_flash2(&chnd, chnd.conf.output_filename, 0);
else
- ret = write_flash(&chnd, output_filename, 0);
+ ret = write_flash(&chnd, chnd.conf.output_filename, 0);
if (ret)
goto terminate;
- ret = verify_flash(&chnd, output_filename, 0);
+ ret = verify_flash(&chnd, chnd.conf.output_filename, 0);
if (ret)
goto terminate;
}
@@ -1640,10 +1763,10 @@ terminate:
/* Enable EC Host Global Reset to reset EC resource and EC domain. */
dbgr_reset(&chnd, RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST);
- /* Close the FTDI USB handle */
- if (chnd.iftype == FTDI_IF) {
- ftdi_usb_close(chnd.ftdi_hnd);
- ftdi_free(chnd.ftdi_hnd);
+ if (chnd.conf.i2c_if->interface_shutdown) {
+ other_ret = chnd.conf.i2c_if->interface_shutdown(&chnd);
+ if (!ret && other_ret)
+ ret = other_ret;
}
return ret;