summaryrefslogtreecommitdiff
path: root/util/iteflash.c
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2018-09-05 18:02:53 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-09-27 19:44:25 -0700
commit72cd97f4b84e0076099b4a15698fc28e807e00f8 (patch)
tree226c0335f265d140113e5d3407658e62690c742f /util/iteflash.c
parent80769acb65ddf155170b3d119fd88ec0623e68ed (diff)
downloadchrome-ec-72cd97f4b84e0076099b4a15698fc28e807e00f8.tar.gz
iteflash: add ability to program ITE chips over CCD
It is necessary to be able to program ITE chips using Cr50 as the USB to I2C bridge when Closed Case Debugging (CCD) is enabled. The existing iteflash utility already implements all logic of translating programming commands into sequences of I2C transactions, all what's missing is the ability to send I2C transactions over Cr50 instead of FTDI. This patch adds a new command line option for the iteflash utility, -c for ccd. When given, the utility instead of opening an FTDI connection tries to find a Cr50 USB endpoint for the I2C bridge. A common structure is introduced to communicate the properties of the interface down the stack, such that at the lowest level, when I2C commands need to be synthesized the correct interface is used. Another addition is using a special I2C address to send command to Cr50 to trigger generation of the ITE EC sync sequence (not yet supported on the Cr50 side, implemented in the following patches). BRANCH=none BUG=b:75976718 TEST=verified that iteflash still operates properly - updated the EC image on the dragonegg board. No Cr50 tests yet. Change-Id: Ibcc052b86021c0c4b4dbccadc3fded3100c92ccf Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1212525 Reviewed-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'util/iteflash.c')
-rw-r--r--util/iteflash.c675
1 files changed, 424 insertions, 251 deletions
diff --git a/util/iteflash.c b/util/iteflash.c
index 800cddab08..6308f5c142 100644
--- a/util/iteflash.c
+++ b/util/iteflash.c
@@ -6,6 +6,7 @@
*/
#include <errno.h>
+#include <ftdi.h>
#include <getopt.h>
#include <signal.h>
#include <stdint.h>
@@ -15,15 +16,24 @@
#include <time.h>
#include <unistd.h>
-#pragma GCC diagnostic ignored "-Wstrict-prototypes"
-#include <ftdi.h>
-#pragma GCC diagnostic pop
+#include "usb_if.h"
-/* default USB device : Servo v2 */
+/* Default FTDI device : Servo v2. */
#define SERVO_USB_VID 0x18d1
#define SERVO_USB_PID 0x5002
#define SERVO_INTERFACE INTERFACE_B
+/* Default CCD device: Cr50. */
+#define CR50_USB_VID 0x18d1
+#define CR50_USB_PID 0x5014
+
+/* Cr50 exposed properties of the USB I2C endpoint. */
+#define CR50_I2C_SUBCLASS 82
+#define CR50_I2C_PROTOCOL 1
+
+#define CROS_CMD_ADDR 0x78
+#define CROS_CMD_ITE_SYNC 0
+
/* DBGR I2C addresses */
#define I2C_CMD_ADDR 0x5A
#define I2C_DATA_ADDR 0x35
@@ -41,8 +51,9 @@
/* Embedded flash page size */
#define PAGE_SIZE 256
-/* Embedded flash block write size */
-#define BLOCK_WRITE_SIZE 65536
+/* Embedded flash block write size for different programming modes. */
+#define FTDI_BLOCK_WRITE_SIZE 65536
+#define CCD_BLOCK_WRITE_SIZE 56
/* Embedded flash number of pages in a sector erase */
#define SECTOR_ERASE_PAGES 4
@@ -88,11 +99,32 @@ static int debug;
enum {
FLAG_UNPROTECT = 0x01,
FLAG_ERASE = 0x02,
+ FLAG_CCD_MODE = 0x04
+};
+
+enum interface_type {
+ FTDI_IF,
+ CCD_IF
+};
+
+struct common_hnd {
+ enum interface_type iftype;
+ 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 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_;
+}
+
static int i2c_add_send_byte(struct ftdi_context *ftdi, uint8_t *buf,
uint8_t *ptr, uint8_t *tbuf, int tcnt)
{
@@ -217,13 +249,88 @@ static int i2c_add_recv_bytes(struct ftdi_context *ftdi, uint8_t *buf,
return ret;
}
-static int i2c_byte_transfer(struct ftdi_context *ftdi, uint8_t addr,
+#define USB_I2C_HEADER_SIZE 4
+static int ccd_i2c_byte_transfer(struct usb_endpoint *uep, uint8_t addr,
+ uint8_t *data, int write, int numbytes)
+{
+ uint8_t usb_buffer[USB_I2C_HEADER_SIZE + numbytes +
+ (((!write * numbytes) > 0x7f) ? 2 : 0)];
+ size_t response_size;
+ size_t extra = 0;
+
+ /* Do nothing if user wants to quit. */
+ if (exit_requested)
+ return -1;
+
+ /* Build a message following format described in ./include/usb_i2c.h. */
+ usb_buffer[0] = 0; /* Hardcode port 0, may need to change this. */
+ usb_buffer[1] = addr;
+ if (write) {
+ usb_buffer[2] = numbytes;
+ usb_buffer[3] = 0;
+ memcpy(usb_buffer + USB_I2C_HEADER_SIZE, data, numbytes);
+ } else {
+ usb_buffer[2] = 0;
+ if (numbytes < 0x80) {
+ usb_buffer[3] = numbytes;
+ } else {
+ usb_buffer[3] = (numbytes & 0x7f) | 0x80;
+ usb_buffer[4] = numbytes >> 7;
+ usb_buffer[5] = 0;
+ extra = 2;
+ }
+ }
+
+ response_size = 0;
+ usb_trx(uep, usb_buffer,
+ write ? sizeof(usb_buffer) : USB_I2C_HEADER_SIZE + extra,
+ usb_buffer, sizeof(usb_buffer), 1, &response_size);
+
+ if (response_size < (USB_I2C_HEADER_SIZE + (write ? 0 : numbytes))) {
+ fprintf(stderr, "%s: got too few bytes (%zd) in response\n",
+ __func__, response_size);
+ return -1;
+ }
+
+ if (usb_buffer[0]) {
+ uint32_t rv;
+
+ /*
+ * Error is reported as a 16 bit value in little endian byte
+ * order.
+ */
+ rv = usb_buffer[1];
+ rv = (rv << 8) + usb_buffer[0];
+
+ fprintf(stderr, "%s: usb i2c error %d\n",
+ __func__,
+ (((uint16_t)usb_buffer[1]) << 8) + usb_buffer[0]);
+
+ return -rv;
+ }
+
+ if (!write)
+ memcpy(data, usb_buffer + USB_I2C_HEADER_SIZE, numbytes);
+
+ return 0;
+}
+
+static int i2c_byte_transfer(struct common_hnd *chnd, uint8_t addr,
uint8_t *data, int write, int numbytes)
{
- int ret = 0, rets;
+ int ret, rets;
static uint8_t buf[FTDI_CMD_BUF_SIZE];
- uint8_t *b = buf;
+ uint8_t *b;
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;
/* START condition */
/* SCL & SDA high */
@@ -268,35 +375,35 @@ exit_xfer:
return ret;
}
-static int i2c_write_byte(struct ftdi_context *ftdi, uint8_t cmd, uint8_t data)
+static int i2c_write_byte(struct common_hnd *chnd, uint8_t cmd, uint8_t data)
{
int ret;
- ret = i2c_byte_transfer(ftdi, I2C_CMD_ADDR, &cmd, 1, 1);
+ ret = i2c_byte_transfer(chnd, I2C_CMD_ADDR, &cmd, 1, 1);
if (ret < 0)
return -EIO;
- ret = i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &data, 1, 1);
+ ret = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &data, 1, 1);
if (ret < 0)
return -EIO;
return 0;
}
-static int i2c_read_byte(struct ftdi_context *ftdi, uint8_t cmd, uint8_t *data)
+static int i2c_read_byte(struct common_hnd *chnd, uint8_t cmd, uint8_t *data)
{
int ret;
- ret = i2c_byte_transfer(ftdi, I2C_CMD_ADDR, &cmd, 1, 1);
+ ret = i2c_byte_transfer(chnd, I2C_CMD_ADDR, &cmd, 1, 1);
if (ret < 0)
return -EIO;
- ret = i2c_byte_transfer(ftdi, I2C_DATA_ADDR, data, 0, 1);
+ ret = i2c_byte_transfer(chnd, I2C_DATA_ADDR, data, 0, 1);
if (ret < 0)
return -EIO;
return 0;
}
-static int check_chipid(struct ftdi_context *ftdi)
+static int check_chipid(struct common_hnd *chnd)
{
int ret;
uint8_t ver = 0xff;
@@ -326,13 +433,13 @@ static int check_chipid(struct ftdi_context *ftdi)
* 8:512KB
*/
- ret = i2c_read_byte(ftdi, 0x00, (uint8_t *)&id + 1);
+ ret = i2c_read_byte(chnd, 0x00, (uint8_t *)&id + 1);
if (ret < 0)
return ret;
- ret = i2c_read_byte(ftdi, 0x01, (uint8_t *)&id);
+ ret = i2c_read_byte(chnd, 0x01, (uint8_t *)&id);
if (ret < 0)
return ret;
- ret = i2c_read_byte(ftdi, 0x02, &ver);
+ ret = i2c_read_byte(chnd, 0x02, &ver);
if (ret < 0)
return ret;
if ((id & 0xff00) != (CHIP_ID & 0xff00)) {
@@ -354,18 +461,18 @@ static int check_chipid(struct ftdi_context *ftdi)
}
/* DBGR Reset*/
-static int dbgr_reset(struct ftdi_context *ftdi, unsigned char val)
+static int dbgr_reset(struct common_hnd *chnd, unsigned char val)
{
int ret = 0;
/* Reset CPU only, and we keep power state until flashing is done. */
- ret |= i2c_write_byte(ftdi, 0x2f, 0x20);
- ret |= i2c_write_byte(ftdi, 0x2e, 0x06);
+ ret |= i2c_write_byte(chnd, 0x2f, 0x20);
+ ret |= i2c_write_byte(chnd, 0x2e, 0x06);
/* Enable the Reset Status by val */
- ret |= i2c_write_byte(ftdi, 0x30, val);
+ ret |= i2c_write_byte(chnd, 0x30, val);
- ret |= i2c_write_byte(ftdi, 0x27, 0x80);
+ ret |= i2c_write_byte(chnd, 0x27, 0x80);
if (ret < 0)
printf("DBGR RESET FAILED\n");
@@ -373,15 +480,15 @@ static int dbgr_reset(struct ftdi_context *ftdi, unsigned char val)
}
/* Enter follow mode and FSCE# high level */
-static int spi_flash_follow_mode(struct ftdi_context *ftdi, char *desc)
+static int spi_flash_follow_mode(struct common_hnd *chnd, char *desc)
{
int ret = 0;
- ret |= i2c_write_byte(ftdi, 0x07, 0x7f);
- ret |= i2c_write_byte(ftdi, 0x06, 0xff);
- ret |= i2c_write_byte(ftdi, 0x05, 0xfe);
- ret |= i2c_write_byte(ftdi, 0x04, 0x00);
- ret |= i2c_write_byte(ftdi, 0x08, 0x00);
+ ret |= i2c_write_byte(chnd, 0x07, 0x7f);
+ ret |= i2c_write_byte(chnd, 0x06, 0xff);
+ ret |= i2c_write_byte(chnd, 0x05, 0xfe);
+ ret |= i2c_write_byte(chnd, 0x04, 0x00);
+ ret |= i2c_write_byte(chnd, 0x08, 0x00);
ret = (ret ? -EIO : 0);
if (ret < 0)
@@ -392,12 +499,12 @@ static int spi_flash_follow_mode(struct ftdi_context *ftdi, char *desc)
}
/* Exit follow mode */
-static int spi_flash_follow_mode_exit(struct ftdi_context *ftdi, char *desc)
+static int spi_flash_follow_mode_exit(struct common_hnd *chnd, char *desc)
{
int ret = 0;
- ret |= i2c_write_byte(ftdi, 0x07, 0x00);
- ret |= i2c_write_byte(ftdi, 0x06, 0x00);
+ ret |= i2c_write_byte(chnd, 0x07, 0x00);
+ ret |= i2c_write_byte(chnd, 0x06, 0x00);
ret = (ret ? -EIO : 0);
if (ret < 0)
@@ -408,16 +515,15 @@ static int spi_flash_follow_mode_exit(struct ftdi_context *ftdi, char *desc)
}
/* SPI Flash generic command, short version */
-static int spi_flash_command_short(struct ftdi_context *ftdi,
- uint8_t cmd,
- char *desc)
+static int spi_flash_command_short(struct common_hnd *chnd,
+ uint8_t cmd, char *desc)
{
int ret = 0;
- ret |= i2c_write_byte(ftdi, 0x05, 0xfe);
- ret |= i2c_write_byte(ftdi, 0x08, 0x00);
- ret |= i2c_write_byte(ftdi, 0x05, 0xfd);
- ret |= i2c_write_byte(ftdi, 0x08, cmd);
+ ret |= i2c_write_byte(chnd, 0x05, 0xfe);
+ ret |= i2c_write_byte(chnd, 0x08, 0x00);
+ ret |= i2c_write_byte(chnd, 0x05, 0xfd);
+ ret |= i2c_write_byte(chnd, 0x08, cmd);
ret = (ret ? -EIO : 0);
if (ret < 0)
@@ -427,15 +533,14 @@ static int spi_flash_command_short(struct ftdi_context *ftdi,
}
/* SPI Flash set erase page */
-static int spi_flash_set_erase_page(struct ftdi_context *ftdi,
- int page,
- char *desc)
+static int spi_flash_set_erase_page(struct common_hnd *chnd,
+ int page, char *desc)
{
int ret = 0;
- ret |= i2c_write_byte(ftdi, 0x08, page >> 8);
- ret |= i2c_write_byte(ftdi, 0x08, page & 0xff);
- ret |= i2c_write_byte(ftdi, 0x08, 0);
+ ret |= i2c_write_byte(chnd, 0x08, page >> 8);
+ ret |= i2c_write_byte(chnd, 0x08, page & 0xff);
+ ret |= i2c_write_byte(chnd, 0x08, 0);
ret = (ret ? -EIO : 0);
if (ret < 0)
@@ -445,19 +550,19 @@ static int spi_flash_set_erase_page(struct ftdi_context *ftdi,
}
/* Poll SPI Flash Read Status register until BUSY is reset */
-static int spi_poll_busy(struct ftdi_context *ftdi, char *desc)
+static int spi_poll_busy(struct common_hnd *chnd, char *desc)
{
uint8_t reg = 0xff;
int ret = -EIO;
- if (spi_flash_command_short(ftdi, SPI_CMD_READ_STATUS,
+ if (spi_flash_command_short(chnd, SPI_CMD_READ_STATUS,
"read status for busy bit") < 0) {
fprintf(stderr, "Flash %s wait busy cleared FAILED\n", desc);
goto failed_read_status;
}
while (1) {
- if (i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &reg, 0, 1) < 0) {
+ if (i2c_byte_transfer(chnd, I2C_DATA_ADDR, &reg, 0, 1) < 0) {
fprintf(stderr, "Flash polling busy cleared FAILED\n");
break;
}
@@ -472,19 +577,19 @@ failed_read_status:
return ret;
}
-static int spi_check_write_enable(struct ftdi_context *ftdi, char *desc)
+static int spi_check_write_enable(struct common_hnd *chnd, char *desc)
{
uint8_t reg = 0xff;
int ret = -EIO;
- if (spi_flash_command_short(ftdi, SPI_CMD_READ_STATUS,
+ if (spi_flash_command_short(chnd, SPI_CMD_READ_STATUS,
"read status for write enable bit") < 0) {
fprintf(stderr, "Flash %s wait WE FAILED\n", desc);
goto failed_read_status;
}
while (1) {
- if (i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &reg, 0, 1) < 0) {
+ if (i2c_byte_transfer(chnd, I2C_DATA_ADDR, &reg, 0, 1) < 0) {
fprintf(stderr, "Flash polling WE FAILED\n");
break;
}
@@ -553,86 +658,129 @@ static int config_i2c(struct ftdi_context *ftdi)
#define SPECIAL_BUFFER_SIZE \
(((SPECIAL_LEN_USEC * SPECIAL_FREQ * 2 / USEC) + 7) & ~7)
-static int send_special_waveform(struct ftdi_context *ftdi)
+static int ccd_trigger_special_waveform(struct usb_endpoint *uep)
+{
+ uint8_t response[20];
+ size_t rsize;
+ uint8_t req[] = {
+ 0, /* Port 0. Might be necessary to modify. */
+ CROS_CMD_ADDR, /* Chrome OS dedicated address. */
+ 1, /* Will send a single byte command. */
+ 0, /* No need to read back anything. */
+ CROS_CMD_ITE_SYNC
+ };
+
+ usb_trx(uep, req, sizeof(req), response, sizeof(response), 1, &rsize);
+
+ if (rsize < USB_I2C_HEADER_SIZE)
+ return -1;
+
+ if (response[0])
+ return -response[0];
+
+ return 0;
+}
+
+static int ftdi_send_special_waveform(struct ftdi_context *ftdi, uint64_t *wave)
{
int ret;
int i;
- uint64_t *wave;
uint8_t release_lines[] = {SET_BITS_LOW, 0, 0};
- wave = malloc(SPECIAL_BUFFER_SIZE);
+ /* 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;
+ }
- printf("Waiting for the EC power-on sequence ...");
- fflush(stdout);
+ /*
+ * set the clock divider, so we output a new bitbang value every
+ * 2.5us.
+ */
+ ret = ftdi_set_baudrate(ftdi, 160000);
+ if (ret) {
+ fprintf(stderr, "failed to set bitbang clock\n");
+ return ret;
+ }
- do {
- /* Reset the FTDI into a known state */
- ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_RESET);
- if (ret != 0) {
- fprintf(stderr, "failed to reset FTDI\n");
- break;
- }
+ /* 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;
+ }
- /*
- * set the clock divider,
- * so we output a new bitbang value every 2.5us.
- */
- ret = ftdi_set_baudrate(ftdi, 160000);
- if (ret != 0) {
- fprintf(stderr, "failed to set bitbang clock\n");
- break;
- }
+ /* do usb special waveform */
+ wave[0] = 0x0;
+ ftdi_write_data(ftdi, (uint8_t *)wave, 1);
+ usleep(5000);
- /* Enable asynchronous bit-bang mode */
- ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_BITBANG);
- if (ret != 0) {
- fprintf(stderr, "failed to set bitbang mode\n");
- break;
- }
+ /* program each special tick */
+ for (i = 0; i < TICK_COUNT; ) {
+ wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L;
+ wave[i++] = SPECIAL_PATTERN_SDA_H_SCL_L;
+ wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L;
+ }
+ wave[19] = SPECIAL_PATTERN_SDA_H_SCL_H;
- /* do usb special waveform */
- wave[0] = 0x0;
- ftdi_write_data(ftdi, (uint8_t *)wave, 1);
- usleep(5000);
+ /* fill the buffer with the waveform pattern */
+ for (i = TICK_COUNT; i < SPECIAL_BUFFER_SIZE / sizeof(uint64_t); i++)
+ wave[i] = SPECIAL_PATTERN;
- /* program each special tick */
- for (i = 0; i < TICK_COUNT; ) {
- wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L;
- wave[i++] = SPECIAL_PATTERN_SDA_H_SCL_L;
- wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L;
- }
- wave[19] = SPECIAL_PATTERN_SDA_H_SCL_H;
+ ret = ftdi_write_data(ftdi, (uint8_t *)wave, SPECIAL_BUFFER_SIZE);
+ if (ret < 0)
+ fprintf(stderr, "Cannot output special waveform\n");
+
+ /* 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_write_data(ftdi, release_lines, sizeof(release_lines));
+
+ 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;
+
+ printf("Waiting for the EC power-on sequence ...");
+ fflush(stdout);
- /* fill the buffer with the waveform pattern */
- for (i = TICK_COUNT; i < SPECIAL_BUFFER_SIZE / sizeof(uint64_t);
- i++)
- wave[i] = SPECIAL_PATTERN;
+ iterations = 0;
- ret = ftdi_write_data(ftdi, (uint8_t *)wave,
- SPECIAL_BUFFER_SIZE);
- if (ret < 0)
- fprintf(stderr, "Cannot output special waveform\n");
+ do {
+ if (chnd->iftype == FTDI_IF)
+ ret = ftdi_send_special_waveform(chnd->ftdi_hnd, wave);
+ else
+ ret = ccd_trigger_special_waveform(&chnd->uep);
- /* 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_write_data(ftdi, release_lines, sizeof(release_lines));
+ if (ret)
+ break;
/* wait for PLL stable for 5ms (plus remaining USB transfers) */
usleep(10 * MSEC);
/* If we can talk to chip, then we can break the retry loop */
- ret = check_chipid(ftdi);
+ ret = check_chipid(chnd);
- } while (ret != 0);
+ } while (ret && (iterations++ < 50));
if (ret)
printf(" Failed!\n");
else
printf(" Done.\n");
- free(wave);
+ if (wave)
+ free(wave);
return ret;
}
@@ -645,7 +793,7 @@ static void draw_spinner(uint32_t remaining, uint32_t size)
windex %= sizeof(wheel);
}
-int command_read_pages(struct ftdi_context *ftdi, uint32_t address,
+int command_read_pages(struct common_hnd *chnd, uint32_t address,
uint32_t size, uint8_t *buffer)
{
int res = -EIO;
@@ -653,7 +801,7 @@ int command_read_pages(struct ftdi_context *ftdi, uint32_t address,
int cnt;
uint16_t page;
- if (spi_flash_follow_mode(ftdi, "fast read") < 0)
+ if (spi_flash_follow_mode(chnd, "fast read") < 0)
goto failed_read;
while (remaining) {
@@ -665,21 +813,21 @@ int command_read_pages(struct ftdi_context *ftdi, uint32_t address,
draw_spinner(remaining, size);
/* Fast Read command */
- if (spi_flash_command_short(ftdi, SPI_CMD_FAST_READ,
+ if (spi_flash_command_short(chnd, SPI_CMD_FAST_READ,
"fast read") < 0)
goto failed_read;
- res = i2c_write_byte(ftdi, 0x08, page >> 8);
- res += i2c_write_byte(ftdi, 0x08, page & 0xff);
- res += i2c_write_byte(ftdi, 0x08, 0x00);
- res += i2c_write_byte(ftdi, 0x08, 0x00);
+ res = i2c_write_byte(chnd, 0x08, page >> 8);
+ res += i2c_write_byte(chnd, 0x08, page & 0xff);
+ res += i2c_write_byte(chnd, 0x08, 0x00);
+ res += i2c_write_byte(chnd, 0x08, 0x00);
if (res < 0) {
fprintf(stderr, "page address set failed\n");
goto failed_read;
}
/* read page data */
- res = i2c_byte_transfer(ftdi, I2C_CMD_ADDR, &cmd, 1, 1);
- res = i2c_byte_transfer(ftdi, I2C_BLOCK_ADDR, buffer, 0, cnt);
+ res = i2c_byte_transfer(chnd, I2C_CMD_ADDR, &cmd, 1, 1);
+ res = i2c_byte_transfer(chnd, I2C_BLOCK_ADDR, buffer, 0, cnt);
if (res < 0) {
fprintf(stderr, "page data read failed\n");
goto failed_read;
@@ -692,13 +840,13 @@ int command_read_pages(struct ftdi_context *ftdi, uint32_t address,
/* No error so far */
res = size;
failed_read:
- if (spi_flash_follow_mode_exit(ftdi, "fast read") < 0)
+ if (spi_flash_follow_mode_exit(chnd, "fast read") < 0)
res = -EIO;
return res;
}
-int command_write_pages(struct ftdi_context *ftdi, uint32_t address,
+int command_write_pages(struct common_hnd *chnd, uint32_t address,
uint32_t size, uint8_t *buffer)
{
int res = -EIO;
@@ -707,12 +855,12 @@ int command_write_pages(struct ftdi_context *ftdi, uint32_t address,
uint8_t addr_H, addr_M, addr_L;
uint8_t cmd;
- if (spi_flash_follow_mode(ftdi, "AAI write") < 0)
+ if (spi_flash_follow_mode(chnd, "AAI write") < 0)
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;
@@ -720,23 +868,23 @@ int command_write_pages(struct ftdi_context *ftdi, uint32_t address,
draw_spinner(remaining, size);
/* Write enable */
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_ENABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE,
"write enable for AAI write") < 0)
goto failed_write;
/* Check write enable bit */
- if (spi_check_write_enable(ftdi, "AAI write") < 0)
+ if (spi_check_write_enable(chnd, "AAI write") < 0)
goto failed_write;
/* Setup write */
- if (spi_flash_command_short(ftdi, SPI_CMD_WORD_PROGRAM,
+ if (spi_flash_command_short(chnd, SPI_CMD_WORD_PROGRAM,
"AAI write") < 0)
goto failed_write;
/* Set eflash page address */
- res = i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &addr_H, 1, 1);
- res |= i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &addr_M, 1, 1);
- res |= i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &addr_L, 1, 1);
+ res = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_H, 1, 1);
+ res |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_M, 1, 1);
+ res |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &addr_L, 1, 1);
if (res < 0) {
fprintf(stderr, "Flash write set page FAILED (%d)\n",
res);
@@ -744,12 +892,12 @@ int command_write_pages(struct ftdi_context *ftdi, uint32_t address,
}
/* Wait until not busy */
- if (spi_poll_busy(ftdi, "AAI write") < 0)
+ if (spi_poll_busy(chnd, "AAI write") < 0)
goto failed_write;
- /* Write up to BLOCK_WRITE_SIZE data */
- res = i2c_write_byte(ftdi, 0x10, 0x20);
- res = i2c_byte_transfer(ftdi, I2C_BLOCK_ADDR, buffer, 1, cnt);
+ /* 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;
if (res < 0) {
@@ -758,8 +906,8 @@ int command_write_pages(struct ftdi_context *ftdi, uint32_t address,
}
cmd = 0xff;
- res = i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &cmd, 1, 1);
- res |= i2c_write_byte(ftdi, 0x10, 0x00);
+ res = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &cmd, 1, 1);
+ res |= i2c_write_byte(chnd, 0x10, 0x00);
if (res < 0) {
fprintf(stderr, "Flash end data write FAILED (%d)\n",
res);
@@ -767,12 +915,12 @@ int command_write_pages(struct ftdi_context *ftdi, uint32_t address,
}
/* Write disable */
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_DISABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE,
"write disable for AAI write") < 0)
goto failed_write;
/* Wait until available */
- if (spi_poll_busy(ftdi, "write disable for AAI write") < 0)
+ if (spi_poll_busy(chnd, "write disable for AAI write") < 0)
goto failed_write;
address += cnt;
@@ -782,11 +930,11 @@ int command_write_pages(struct ftdi_context *ftdi, uint32_t address,
/* No error so far */
res = size;
failed_write:
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_DISABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE,
"write disable exit AAI write") < 0)
res = -EIO;
- if (spi_flash_follow_mode_exit(ftdi, "AAI write") < 0)
+ if (spi_flash_follow_mode_exit(chnd, "AAI write") < 0)
res = -EIO;
return res;
@@ -797,11 +945,10 @@ failed_write:
* Write another program flow to match the
* original ITE 8903 Download board.
*/
-int command_write_pages2(struct ftdi_context *ftdi, uint32_t address,
- uint32_t size, uint8_t *buffer)
+int command_write_pages2(struct common_hnd *chnd, uint32_t address,
+ uint32_t size, uint8_t *buffer)
{
int res = 0;
- uint32_t remaining = size;
uint8_t BA, A1, A0, data;
/*
@@ -809,33 +956,33 @@ int command_write_pages2(struct ftdi_context *ftdi, uint32_t address,
* The code will merge to the original function
*/
- res |= i2c_write_byte(ftdi, 0x07, 0x7f);
- res |= i2c_write_byte(ftdi, 0x06, 0xff);
- res |= i2c_write_byte(ftdi, 0x04, 0xFF);
+ res |= i2c_write_byte(chnd, 0x07, 0x7f);
+ res |= i2c_write_byte(chnd, 0x06, 0xff);
+ res |= i2c_write_byte(chnd, 0x04, 0xFF);
/* SMB_SPI_Flash_Enable_Write_Status */
- if (spi_flash_command_short(ftdi, SPI_CMD_EWSR,
+ if (spi_flash_command_short(chnd, SPI_CMD_EWSR,
"Enable Write Status Register") < 0) {
res = -EIO;
goto failed_write;
}
/* SMB_SPI_Flash_Write_Status_Reg */
- res |= i2c_write_byte(ftdi, 0x05, 0xfe);
- res |= i2c_write_byte(ftdi, 0x08, 0x00);
- res |= i2c_write_byte(ftdi, 0x05, 0xfd);
- res |= i2c_write_byte(ftdi, 0x08, 0x01);
- res |= i2c_write_byte(ftdi, 0x08, 0x00);
+ res |= i2c_write_byte(chnd, 0x05, 0xfe);
+ res |= i2c_write_byte(chnd, 0x08, 0x00);
+ res |= i2c_write_byte(chnd, 0x05, 0xfd);
+ res |= i2c_write_byte(chnd, 0x08, 0x01);
+ res |= i2c_write_byte(chnd, 0x08, 0x00);
/* SMB_SPI_Flash_Write_Enable */
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_ENABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE,
"SPI Command Write Enable") < 0) {
res = -EIO;
goto failed_write;
}
/* SMB_SST_SPI_Flash_AAI2_Program */
- if (spi_flash_command_short(ftdi, SPI_CMD_WORD_PROGRAM,
+ if (spi_flash_command_short(chnd, SPI_CMD_WORD_PROGRAM,
"SPI AAI2 Program") < 0) {
res = -EIO;
goto failed_write;
@@ -845,32 +992,30 @@ int command_write_pages2(struct ftdi_context *ftdi, uint32_t address,
A1 = address>>8;
A0 = 0;
- res = i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &BA, 1, 1);
- res |= i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &A1, 1, 1);
- res |= i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &A0, 1, 1);
- res |= i2c_byte_transfer(ftdi, I2C_DATA_ADDR, buffer++, 1, 1);
- res |= i2c_byte_transfer(ftdi, I2C_DATA_ADDR, buffer++, 1, 1);
+ res = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &BA, 1, 1);
+ res |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &A1, 1, 1);
+ res |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, &A0, 1, 1);
+ res |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, buffer++, 1, 1);
+ res |= i2c_byte_transfer(chnd, I2C_DATA_ADDR, buffer++, 1, 1);
/* Wait until not busy */
- if (spi_poll_busy(ftdi, "AAI write") < 0)
+ if (spi_poll_busy(chnd, "AAI write") < 0)
goto failed_write;
- res = i2c_write_byte(ftdi, 0x10, 0x20);
- res = i2c_byte_transfer(ftdi, I2C_BLOCK_ADDR,
- buffer, 1, BLOCK_WRITE_SIZE-2);
- remaining = size - BLOCK_WRITE_SIZE;
+ res = i2c_write_byte(chnd, 0x10, 0x20);
+ res = i2c_byte_transfer(chnd, I2C_BLOCK_ADDR,
+ buffer, 1, block_write_size()-2);
- draw_spinner(remaining, size);
/* No error so far */
res = size;
data = 0xff;
- res = i2c_byte_transfer(ftdi, I2C_DATA_ADDR, &data, 1, 1);
- res = i2c_write_byte(ftdi, 0x10, 0x00);
+ res = i2c_byte_transfer(chnd, I2C_DATA_ADDR, &data, 1, 1);
+ res = i2c_write_byte(chnd, 0x10, 0x00);
failed_write:
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_DISABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE,
"write disable exit AAI write") < 0)
res = -EIO;
@@ -878,13 +1023,13 @@ failed_write:
}
-int command_write_unprotect(struct ftdi_context *ftdi)
+int command_write_unprotect(struct common_hnd *chnd)
{
/* TODO(http://crosbug.com/p/23576): implement me */
return 0;
}
-int command_erase(struct ftdi_context *ftdi, uint32_t len, uint32_t off)
+int command_erase(struct common_hnd *chnd, uint32_t len, uint32_t off)
{
int res = -EIO;
int page = 0;
@@ -897,40 +1042,40 @@ int command_erase(struct ftdi_context *ftdi, uint32_t len, uint32_t off)
return -EINVAL;
}
- if (spi_flash_follow_mode(ftdi, "erase") < 0)
+ if (spi_flash_follow_mode(chnd, "erase") < 0)
goto failed_erase;
while (remaining) {
draw_spinner(remaining, len);
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_ENABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE,
"write enable for erase") < 0)
goto failed_erase;
- if (spi_check_write_enable(ftdi, "erase") < 0)
+ if (spi_check_write_enable(chnd, "erase") < 0)
goto failed_erase;
/* do chip erase */
if (remaining == flash_size) {
- if (spi_flash_command_short(ftdi, SPI_CMD_CHIP_ERASE,
+ if (spi_flash_command_short(chnd, SPI_CMD_CHIP_ERASE,
"chip erase") < 0)
goto failed_erase;
goto wait_busy_cleared;
}
/* do sector erase */
- if (spi_flash_command_short(ftdi, SPI_CMD_SECTOR_ERASE,
+ if (spi_flash_command_short(chnd, SPI_CMD_SECTOR_ERASE,
"sector erase") < 0)
goto failed_erase;
- if (spi_flash_set_erase_page(ftdi, page, "sector erase") < 0)
+ if (spi_flash_set_erase_page(chnd, page, "sector erase") < 0)
goto failed_erase;
wait_busy_cleared:
- if (spi_poll_busy(ftdi, "erase") < 0)
+ if (spi_poll_busy(chnd, "erase") < 0)
goto failed_erase;
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_DISABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE,
"write disable for erase") < 0)
goto failed_erase;
@@ -946,11 +1091,11 @@ wait_busy_cleared:
printf("\n\rErasing Done.\n");
res = 0;
failed_erase:
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_DISABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE,
"write disable exit erase") < 0)
res = -EIO;
- if (spi_flash_follow_mode_exit(ftdi, "erase") < 0)
+ if (spi_flash_follow_mode_exit(chnd, "erase") < 0)
res = -EIO;
return res;
@@ -963,8 +1108,8 @@ failed_erase:
* reset issue while flash.
* Add such function to prevent the reset issue.
*/
-int command_erase2(struct ftdi_context *ftdi, uint32_t len,
- uint32_t off, uint32_t reset)
+int command_erase2(struct common_hnd *chnd, uint32_t len,
+ uint32_t off, uint32_t reset)
{
int res = -EIO;
int page = 0;
@@ -984,32 +1129,32 @@ int command_erase2(struct ftdi_context *ftdi, uint32_t len,
return -EINVAL;
}
- if (spi_flash_follow_mode(ftdi, "erase") < 0)
+ if (spi_flash_follow_mode(chnd, "erase") < 0)
goto failed_erase;
while (remaining) {
draw_spinner(remaining, len);
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_ENABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_ENABLE,
"write enable for erase") < 0)
goto failed_erase;
- if (spi_check_write_enable(ftdi, "erase") < 0)
+ if (spi_check_write_enable(chnd, "erase") < 0)
goto failed_erase;
/* do sector erase */
- if (spi_flash_command_short(ftdi, SPI_CMD_SECTOR_ERASE,
+ if (spi_flash_command_short(chnd, SPI_CMD_SECTOR_ERASE,
"sector erase") < 0)
goto failed_erase;
- if (spi_flash_set_erase_page(ftdi, page, "sector erase") < 0)
+ if (spi_flash_set_erase_page(chnd, page, "sector erase") < 0)
goto failed_erase;
- if (spi_poll_busy(ftdi, "erase") < 0)
+ if (spi_poll_busy(chnd, "erase") < 0)
goto failed_erase;
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_DISABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE,
"write disable for erase") < 0)
goto failed_erase;
@@ -1027,18 +1172,18 @@ int command_erase2(struct ftdi_context *ftdi, uint32_t len,
printf("\n\rErasing Done.\n");
res = 0;
failed_erase:
- if (spi_flash_command_short(ftdi, SPI_CMD_WRITE_DISABLE,
+ if (spi_flash_command_short(chnd, SPI_CMD_WRITE_DISABLE,
"write disable exit erase") < 0)
res = -EIO;
- if (spi_flash_follow_mode_exit(ftdi, "erase") < 0)
+ if (spi_flash_follow_mode_exit(chnd, "erase") < 0)
res = -EIO;
return res;
}
/* Return zero on success, a negative error value on failures. */
-int read_flash(struct ftdi_context *ftdi, const char *filename,
+int read_flash(struct common_hnd *chnd, const char *filename,
uint32_t offset, uint32_t size)
{
int res;
@@ -1060,7 +1205,7 @@ int read_flash(struct ftdi_context *ftdi, const char *filename,
if (!size)
size = flash_size;
printf("Reading %d bytes at 0x%08x\n", size, offset);
- res = command_read_pages(ftdi, offset, size, buffer);
+ res = command_read_pages(chnd, offset, size, buffer);
if (res > 0) {
if (fwrite(buffer, res, 1, hnd) != 1)
fprintf(stderr, "Cannot write %s\n", filename);
@@ -1073,7 +1218,7 @@ int read_flash(struct ftdi_context *ftdi, const char *filename,
}
/* Return zero on success, a negative error value on failures. */
-int write_flash(struct ftdi_context *ftdi, const char *filename,
+int write_flash(struct common_hnd *chnd, const char *filename,
uint32_t offset)
{
int res, written;
@@ -1101,7 +1246,7 @@ int write_flash(struct ftdi_context *ftdi, const char *filename,
fclose(hnd);
printf("Writing %d bytes at 0x%08x\n", res, offset);
- written = command_write_pages(ftdi, offset, res, buffer);
+ written = command_write_pages(chnd, offset, res, buffer);
if (written != res) {
fprintf(stderr, "Error writing to flash\n");
free(buffer);
@@ -1120,7 +1265,7 @@ int write_flash(struct ftdi_context *ftdi, const char *filename,
* The original flow may not work on the DX chip.
*
*/
-int write_flash2(struct ftdi_context *ftdi, const char *filename,
+int write_flash2(struct common_hnd *chnd, const char *filename,
uint32_t offset)
{
int res, written;
@@ -1152,16 +1297,16 @@ int write_flash2(struct ftdi_context *ftdi, 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;
- written = command_write_pages2(ftdi, offset, cnt,
+ cnt = (res > block_write_size()) ?
+ block_write_size() : res;
+ written = command_write_pages2(chnd, offset, cnt,
&buffer[offset]);
if (written == -EIO)
goto failed_write;
res -= cnt;
offset += cnt;
- draw_spinner(res, size);
+ draw_spinner(res, res + offset);
}
if (written != res) {
@@ -1178,7 +1323,7 @@ failed_write:
/* Return zero on success, a negative error value on failures. */
-int verify_flash(struct ftdi_context *ftdi, const char *filename,
+int verify_flash(struct common_hnd *chnd, const char *filename,
uint32_t offset)
{
int res;
@@ -1210,7 +1355,7 @@ int verify_flash(struct ftdi_context *ftdi, const char *filename,
}
printf("Verify %d bytes at 0x%08x\n", file_size, offset);
- res = command_read_pages(ftdi, offset, flash_size, buffer2);
+ res = command_read_pages(chnd, offset, flash_size, buffer2);
draw_spinner(flash_size-res, flash_size);
res = memcmp(buffer, buffer2, file_size);
printf("\n\rVerify %s\n", res ? "Failed!" : "Done.");
@@ -1253,35 +1398,37 @@ open_failed:
}
static const struct option longopts[] = {
+ {"ccd", 0, 0, 'c'},
{"debug", 0, 0, 'd'},
- {"product", 1, 0, 'p'},
- {"vendor", 1, 0, 'v'},
- {"interface", 1, 0, 'i'},
- {"serial", 1, 0, 's'},
- {"read", 1, 0, 'r'},
- {"write", 1, 0, 'w'},
{"erase", 0, 0, 'e'},
{"help", 0, 0, 'h'},
+ {"interface", 1, 0, 'i'},
+ {"product", 1, 0, 'p'},
+ {"read", 1, 0, 'r'},
+ {"serial", 1, 0, 's'},
{"unprotect", 0, 0, 'u'},
+ {"vendor", 1, 0, 'v'},
+ {"write", 1, 0, 'w'},
{NULL, 0, 0, 0}
};
void display_usage(char *program)
{
- fprintf(stderr, "Usage: %s [-d] [-v <VID>] [-p <PID>] [-i <1|2>] "
+ 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, "--d[ebug] : output debug traces\n");
- fprintf(stderr, "--v[endor] <0x1234> : USB vendor ID\n");
- fprintf(stderr, "--p[roduct] <0x1234> : USB product ID\n");
- fprintf(stderr, "--s[erial] <serialname> : USB serial string\n");
- fprintf(stderr, "--i[interface] <1> : FTDI interface: A=1, B=2, ...\n");
- fprintf(stderr, "--u[nprotect] : remove flash write protect\n");
fprintf(stderr, "--e[rase] : erase all the flash content\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 "
"write it into <file>\n");
+ 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[rite] <file> : read <file> and "
"write it to flash\n");
-
exit(2);
}
@@ -1290,24 +1437,18 @@ int parse_parameters(int argc, char **argv)
int opt, idx;
int flags = 0;
- while ((opt = getopt_long(argc, argv, "dv:p:i:s:ehr:w:u?",
+ while ((opt = getopt_long(argc, argv, "?cdehi:p:r:s:uv: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_ = CCD_BLOCK_WRITE_SIZE;
+ break;
case 'd':
debug = 1;
break;
- case 'v':
- usb_vid = strtol(optarg, NULL, 16);
- break;
- case 'p':
- usb_pid = strtol(optarg, NULL, 16);
- break;
- case 'i':
- usb_interface = atoi(optarg);
- break;
- case 's':
- usb_serial = optarg;
- break;
case 'e':
flags |= FLAG_ERASE;
break;
@@ -1315,15 +1456,27 @@ int parse_parameters(int argc, char **argv)
case '?':
display_usage(argv[0]);
break;
+ case 'i':
+ usb_interface = atoi(optarg);
+ break;
+ case 'p':
+ usb_pid = strtol(optarg, NULL, 16);
+ break;
case 'r':
input_filename = optarg;
break;
- case 'w':
- output_filename = optarg;
+ case 's':
+ usb_serial = optarg;
break;
case 'u':
flags |= FLAG_UNPROTECT;
break;
+ case 'v':
+ usb_vid = strtol(optarg, NULL, 16);
+ break;
+ case 'w':
+ output_filename = optarg;
+ break;
}
}
return flags;
@@ -1350,37 +1503,51 @@ static void register_sigaction(void)
int main(int argc, char **argv)
{
- void *hnd;
+ struct common_hnd chnd;
int ret = 1;
int flags;
/* Parse command line options */
flags = parse_parameters(argc, argv);
- /* Open the USB device */
- hnd = open_ftdi_device(usb_vid, usb_pid, usb_interface, usb_serial);
- if (hnd == NULL)
- return 1;
+ /* 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;
+ }
/* Register signal handler after opening USB handle. */
register_sigaction();
/* Trigger embedded monitor detection */
- if (send_special_waveform(hnd) < 0)
+ if (send_special_waveform(&chnd) < 0)
goto terminate;
- if (config_i2c(hnd) < 0)
- goto terminate;
+ if (chnd.iftype == FTDI_IF) {
+ if (config_i2c(chnd.ftdi_hnd) < 0)
+ goto terminate;
- if (check_chipid(hnd) < 0)
- goto terminate;
+ if (check_chipid(&chnd) < 0)
+ goto terminate;
+ }
if (flags & FLAG_UNPROTECT)
- command_write_unprotect(hnd);
+ command_write_unprotect(&chnd);
if (input_filename) {
- dbgr_reset(hnd, RSTS_VCCDO_PW_ON);
- ret = read_flash(hnd, input_filename, 0, flash_size);
+ dbgr_reset(&chnd, RSTS_VCCDO_PW_ON);
+ ret = read_flash(&chnd, input_filename, 0, flash_size);
+
if (ret)
goto terminate;
}
@@ -1394,18 +1561,22 @@ int main(int argc, char **argv)
* Erase first sector to prevent watchdog reset
* from happening
*/
- command_erase2(hnd, flash_size, 0, 1);
+ command_erase2(&chnd, flash_size, 0, 1);
/* Call DBGR Rest to clear the EC lock status */
- dbgr_reset(hnd, RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST);
- if (config_i2c(hnd) < 0)
+
+ dbgr_reset(&chnd,
+ RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST);
+ if (!(flags & FLAG_CCD_MODE) &&
+ (config_i2c(chnd.ftdi_hnd) < 0))
goto terminate;
/* Do Normal Erase Function */
- command_erase2(hnd, flash_size, 0, 0);
+ command_erase2(&chnd, flash_size, 0, 0);
} else {
- command_erase(hnd, flash_size, 0);
+ command_erase(&chnd, flash_size, 0);
/* Call DBGR Rest to clear the EC lock status */
- dbgr_reset(hnd, RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST);
+ dbgr_reset(&chnd,
+ RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST);
}
}
@@ -1413,14 +1584,14 @@ int main(int argc, char **argv)
if (output_filename) {
if (is8320dx)
- ret = write_flash2(hnd, output_filename, 0);
+ ret = write_flash2(&chnd, output_filename, 0);
else
- ret = write_flash(hnd, output_filename, 0);
+ ret = write_flash(&chnd, output_filename, 0);
if (ret)
goto terminate;
- ret = verify_flash(hnd, output_filename, 0);
+ ret = verify_flash(&chnd, output_filename, 0);
if (ret)
goto terminate;
}
@@ -1432,9 +1603,11 @@ terminate:
/*
* Enable EC Host Global Reset to reset EC resource and EC domain
*/
- dbgr_reset(hnd, RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST);
+ dbgr_reset(&chnd, RSTS_VCCDO_PW_ON|RSTS_HGRST|RSTS_GRST);
/* Close the FTDI USB handle */
- ftdi_usb_close(hnd);
- ftdi_free(hnd);
+ if (chnd.iftype == FTDI_IF) {
+ ftdi_usb_close(chnd.ftdi_hnd);
+ ftdi_free(chnd.ftdi_hnd);
+ }
return ret;
}