diff options
Diffstat (limited to 'util/iteflash.c')
-rw-r--r-- | util/iteflash.c | 457 |
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; |