diff options
author | Ting Shen <phoenixshen@google.com> | 2021-01-13 17:22:10 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-01-19 10:12:49 +0000 |
commit | 409116ad8d07b5607e2643350d42b2e5f239d2d0 (patch) | |
tree | 39cc3d488fa30280ce013be785999501d517b758 | |
parent | 06da8cbc7593528981c14ae23dd4b2748bd66b89 (diff) | |
download | chrome-ec-409116ad8d07b5607e2643350d42b2e5f239d2d0.tar.gz |
touchpad_updater: implement 512 byte transfer
Migrate the touchpad probe/update logic from CL:2551939 to
touchpad_updater.
Also adjust the memory allocation on Zed to allow 512 byte packet.
BUG=b:177250972
TEST=On coachz, update detachable fw and run
`ec_touchpad_updater -p 504c -f 282.0_2.bin`
BRANCH=master
Signed-off-by: Ting Shen <phoenixshen@google.com>
Change-Id: Icc7cec1f500dca04d6cdec5b66c10bcce05b67bd
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2637304
Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Commit-Queue: Ting Shen <phoenixshen@chromium.org>
Tested-by: Ting Shen <phoenixshen@chromium.org>
-rw-r--r-- | board/hammer/board.h | 9 | ||||
-rw-r--r-- | extra/touchpad_updater/touchpad_updater.c | 108 |
2 files changed, 83 insertions, 34 deletions
diff --git a/board/hammer/board.h b/board/hammer/board.h index 15928b7ca4..d9e4236481 100644 --- a/board/hammer/board.h +++ b/board/hammer/board.h @@ -91,8 +91,8 @@ #define CONFIG_USB_UPDATE #undef CONFIG_UPDATE_PDU_SIZE -#ifdef BOARD_WAND -/* Wand does not have enough space to fit 4k PDU. */ +#if defined(BOARD_WAND) || defined(BOARD_ZED) +/* Wand/Zed does not have enough space to fit 4k PDU. */ #define CONFIG_UPDATE_PDU_SIZE 2048 #else #define CONFIG_UPDATE_PDU_SIZE 4096 @@ -175,7 +175,12 @@ * buffer size have to be power of two. */ #undef CONFIG_USB_I2C_MAX_WRITE_COUNT +#ifdef BOARD_ZED +/* Zed requires 516 byte per packet for touchpad update */ +#define CONFIG_USB_I2C_MAX_WRITE_COUNT (1024 - 4) /* 4 is maximum header size */ +#else #define CONFIG_USB_I2C_MAX_WRITE_COUNT (128 - 4) /* 4 is maximum header size */ +#endif #undef CONFIG_USB_I2C_MAX_READ_COUNT #define CONFIG_USB_I2C_MAX_READ_COUNT (1024 - 6) /* 6 is maximum header size */ diff --git a/extra/touchpad_updater/touchpad_updater.c b/extra/touchpad_updater/touchpad_updater.c index 985ab1ca46..7029d1b0cc 100644 --- a/extra/touchpad_updater/touchpad_updater.c +++ b/extra/touchpad_updater/touchpad_updater.c @@ -25,13 +25,16 @@ static uint8_t extended_i2c_exercise; /* non-zero to exercise */ static char *firmware_binary = "144.0_2.0.bin"; /* firmware blob */ /* Firmware binary blob related */ -#define FW_PAGE_SIZE 64 +#define MAX_FW_PAGE_SIZE 512 #define MAX_FW_PAGE_COUNT 1024 -#define MAX_FW_SIZE (MAX_FW_PAGE_COUNT*FW_PAGE_SIZE) +#define MAX_FW_SIZE (128 * 1024) static uint8_t fw_data[MAX_FW_SIZE]; int fw_page_count; +int fw_page_size; int fw_size; +uint8_t ic_type; +int iap_version; /* Utility functions */ static int le_bytes_to_int(uint8_t *buf) @@ -292,7 +295,7 @@ static int check_read_status(int r, int expected, int actual) #define PRIMITIVE_READING_SIZE 60 static int libusb_single_write_and_read( - uint8_t *to_write, uint16_t write_length, + const uint8_t *to_write, uint16_t write_length, uint8_t *to_read, uint16_t read_length) { int r; @@ -304,9 +307,9 @@ static int libusb_single_write_and_read( tx_transfer = rx_transfer = 0; memmove(tx_buf + offset, to_write, write_length); - tx_buf[0] = I2C_PORT_ON_HAMMER; + tx_buf[0] = I2C_PORT_ON_HAMMER | ((write_length >> 8) << 4); tx_buf[1] = I2C_ADDRESS_ON_HAMMER; - tx_buf[2] = write_length; + tx_buf[2] = write_length & 0xff; if (read_length > PRIMITIVE_READING_SIZE) { tx_buf[3] = (read_length & 0x7f) | (1 << 7); tx_buf[4] = read_length >> 7; @@ -388,33 +391,46 @@ static int elan_write_cmd(int reg, int cmd) #define ETP_I2C_FW_CHECKSUM_CMD 0x030F #define ETP_I2C_OSM_VERSION_CMD 0x0103 -static int elan_get_ic_page_count(void) +static int elan_get_version(int is_iap) { - uint8_t ic_type; + elan_read_cmd( + is_iap ? ETP_I2C_IAP_VERSION_CMD : ETP_I2C_FW_VERSION_CMD); + return le_bytes_to_int(rx_buf + 4); +} +static void elan_get_ic_page_count(void) +{ elan_read_cmd(ETP_I2C_OSM_VERSION_CMD); ic_type = rx_buf[5]; + printf("ic_type: %02x\n", ic_type); switch (ic_type) { case 0x09: - return 768; + fw_page_count = 768; + break; case 0x0D: - return 896; + fw_page_count = 896; + break; case 0x00: case 0x10: - return 1024; + case 0x14: + fw_page_count = 1024; + break; default: request_exit("The IC type is not supported.\n"); } - return -1; -} -static int elan_get_version(int is_iap) -{ - elan_read_cmd( - is_iap ? ETP_I2C_IAP_VERSION_CMD : ETP_I2C_FW_VERSION_CMD); - return le_bytes_to_int(rx_buf + 4); + iap_version = elan_get_version(1); + if (ic_type == 0x14 && iap_version >= 2) { + fw_page_count /= 8; + fw_page_size = 512; + } else if (ic_type >= 0x0D && iap_version >= 1) { + fw_page_count /= 2; + fw_page_size = 128; + } else { + fw_page_size = 64; + } } static int elan_get_checksum(int is_iap) @@ -426,7 +442,6 @@ static int elan_get_checksum(int is_iap) static uint16_t elan_get_fw_info(void) { - int iap_version = -1; int fw_version = -1; uint16_t iap_checksum = 0xffff; uint16_t fw_checksum = 0xffff; @@ -450,6 +465,7 @@ static uint16_t elan_get_fw_info(void) #define ETP_I2C_MAIN_MODE_ON (1 << 9) #define ETP_I2C_IAP_CMD 0x0311 #define ETP_I2C_IAP_PASSWORD 0x1EA5 +#define ETP_I2C_IAP_TYPE_CMD 0x0304 static int elan_in_main_mode(void) { @@ -457,6 +473,28 @@ static int elan_in_main_mode(void) return le_bytes_to_int(rx_buf + 4) & ETP_I2C_MAIN_MODE_ON; } +static int elan_read_write_iap_type(void) +{ + for (int retry = 0; retry < 3; ++retry) { + uint16_t val; + + if (elan_write_cmd(ETP_I2C_IAP_TYPE_CMD, + fw_page_size / 2)) + return -1; + + if (elan_read_cmd(ETP_I2C_IAP_TYPE_CMD)) + return -1; + + val = le_bytes_to_int(rx_buf + 4); + if (val == fw_page_size / 2) { + printf("%s: OK\n", __func__); + return 0; + } + + } + return -1; +} + static void elan_prepare_for_update(void) { printf("%s\n", __func__); @@ -474,7 +512,12 @@ static void elan_prepare_for_update(void) /* We should be in the IAP mode now */ if (elan_in_main_mode()) - request_exit("Failure to enter IAP mode, still in main mode"); + request_exit("Failure to enter IAP mode, still in main mode\n"); + + if (ic_type >= 0x0D && iap_version >= 1) { + if (elan_read_write_iap_type()) + request_exit("Failure to set IAP mode\n"); + } /* Send the passphrase again */ elan_write_cmd(ETP_I2C_IAP_CMD, ETP_I2C_IAP_PASSWORD); @@ -512,19 +555,20 @@ static int elan_get_iap_addr(void) static int elan_write_fw_block(uint8_t *raw_data, uint16_t checksum) { - uint8_t page_store[FW_PAGE_SIZE + 4]; + uint8_t page_store[MAX_FW_PAGE_SIZE + 4]; int rv; + page_store[0] = ETP_I2C_IAP_REG_L; page_store[1] = ETP_I2C_IAP_REG_H; - memcpy(page_store + 2, raw_data, FW_PAGE_SIZE); - page_store[FW_PAGE_SIZE + 2 + 0] = (checksum >> 0) & 0xff; - page_store[FW_PAGE_SIZE + 2 + 1] = (checksum >> 8) & 0xff; + memcpy(page_store + 2, raw_data, fw_page_size); + page_store[fw_page_size + 2 + 0] = (checksum >> 0) & 0xff; + page_store[fw_page_size + 2 + 1] = (checksum >> 8) & 0xff; rv = libusb_single_write_and_read( - page_store, sizeof(page_store), rx_buf, 0); + page_store, fw_page_size + 4, rx_buf, 0); if (rv) return rv; - usleep(20 * 1000); + usleep((fw_page_size >= 512 ? 50 : 35) * 1000); elan_read_cmd(ETP_I2C_IAP_CTRL_CMD); rv = le_bytes_to_int(rx_buf + 4); if (rv & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) { @@ -542,13 +586,13 @@ static uint16_t elan_update_firmware(void) printf("%s\n", __func__); - for (int i = elan_get_iap_addr(); i < fw_size; i += FW_PAGE_SIZE) { - printf("\rUpdating page %3d...", i / FW_PAGE_SIZE); + for (int i = elan_get_iap_addr(); i < fw_size; i += fw_page_size) { + printf("\rUpdating page %3d...", i / fw_page_size); fflush(stdout); - block_checksum = elan_calc_checksum(fw_data + i, FW_PAGE_SIZE); + block_checksum = elan_calc_checksum(fw_data + i, fw_page_size); rv = elan_write_fw_block(fw_data + i, block_checksum); if (rv) - request_exit("Failed to update."); + request_exit("Failed to update.\n"); checksum += block_checksum; printf(" Updated, checksum: %d", checksum); fflush(stdout); @@ -579,9 +623,9 @@ int main(int argc, char *argv[]) * Judge IC type and get page count first. * Then check the FW file. */ - fw_page_count = elan_get_ic_page_count(); - fw_size = fw_page_count * FW_PAGE_SIZE; - printf("IC page count is %04X\n", fw_page_count); + elan_get_ic_page_count(); + fw_size = fw_page_count * fw_page_size; + printf("FW has %d bytes x %d pages\n", fw_page_size, fw_page_count); /* Read the FW file */ FILE *f = fopen(firmware_binary, "rb"); |