[PATCH v2 7/14] input: cyapa: add gen3 trackpad device firmware update function supported
Add firmware image update function supported for gen3 trackpad device, which its function is supplied through cyapa core update_fw interface. TEST=test on Chomebooks. Signed-off-by: Du, Dudley --- diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 5345a9e..a3e1e72 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -392,6 +392,78 @@ static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) return -EAGAIN; } +/* + * Enter bootloader by soft resetting the device. + * + * If device is already in the bootloader, the function just returns. + * Otherwise, reset the device; after reset, device enters bootloader idle + * state immediately. + * + * Also, if device was unregister device from input core. Device will + * re-register after it is detected following resumption of operational mode. + * + * Returns: + * 0 on success + * -EAGAIN device was reset, but is not now in bootloader idle state + * < 0 if the device never responds within the timeout + */ +static int cyapa_gen3_bl_enter(struct cyapa *cyapa) +{ + int ret; + + if (cyapa->input) { + cyapa_disable_irq(cyapa); + input_unregister_device(cyapa->input); + cyapa->input = NULL; + } + + ret = cyapa_poll_state(cyapa, 500); + if (ret < 0) + return ret; + if (cyapa->state == CYAPA_STATE_BL_IDLE) { + /* Already in BL_IDLE. Skipping exit. */ + return 0; + } + + if (cyapa->state != CYAPA_STATE_OP) + return -EAGAIN; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01); + if (ret < 0) + return -EIO; + + usleep_range(25000, 5); + ret = cyapa_poll_state(cyapa, 500); + if (ret < 0) + return ret; + if ((cyapa->state != CYAPA_STATE_BL_IDLE) || + (cyapa->status[REG_BL_STATUS] & BL_STATUS_WATCHDOG)) + return -EAGAIN; + + return 0; +} + +static int cyapa_gen3_bl_activate(struct cyapa *cyapa) +{ + int ret; + + ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate), + bl_activate); + if (ret < 0) + return ret; + + /* Wait for bootloader to activate; takes between 2 and 12 seconds */ + msleep(2000); + ret = cyapa_poll_state(cyapa, 11000); + if (ret < 0) + return ret; + if (cyapa->state != CYAPA_STATE_BL_ACTIVE) + return -EAGAIN; + + return 0; +} + static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { int ret; @@ -452,6 +524,206 @@ static int cyapa_gen3_bl_exit(struct cyapa *cyapa) return 0; } +/* Used in gen3 bootloader commands. */ +static u16 cyapa_gen3_csum(const u8 *buf, size_t count) +{ + int i; + u16 csum = 0; + + for (i = 0; i < count; i++) + csum += buf[i]; + + return csum; +} + +/* + * Verify the integrity of a CYAPA firmware image file. + * + * The firmware image file is 30848 bytes, composed of 482 64-byte blocks. + * + * The first 2 blocks are the firmware header. + * The next 480 blocks are the firmware image. + * + * The first two bytes of the header hold the header checksum, computed by + * summing the other 126 bytes of the header. + * The last two bytes of the header hold the firmware image checksum, computed + * by summing the 30720 bytes of the image modulo 0x. + * + * Both checksums are stored little-endian. + */ +static int cyapa_gen3_check_fw(struct cyapa *cyapa, const struct firmware *fw) +{ + struct device *dev = >client->dev; + u16 csum; + u16 csum_expected; + + /* Firmware must match exact 30848 bytes = 482 64-byte blocks. */ + if (fw->size != CYAPA_FW_SIZE) { + dev_err(dev, "invalid firmware size = %zu, expected %u.\n", + fw->size, CYAPA_FW_SIZE); + return -EINVAL; + } + + /* Verify header block */ + csum_expected = (fw->data[0] << 8) | fw->data[1]; + csum = cyapa_gen3_csum(>data[2], CYAPA_FW_HDR_SIZE - 2); + if (csum != csum_expected) { + dev_err(dev, "%s %04x, expected: %04x\n", + "invalid firmware header checksum = ", + csum, csum_expected); + return -EINVAL; + } + + /* Verify firmware image */ + csum_expected = (fw->data[CYAPA_FW_HDR_SIZE - 2] << 8) | +fw->data[CYAPA_FW_HDR_SIZE - 1]; + csum = cyapa_gen3_csum(>data[CYAPA_FW_HDR_SIZE], + CYAPA_FW_DATA_SIZE); + if (csum != csum_expected) { + dev_err(dev, "%s %04x, expected: %04x\n", + "invalid firmware header checksum = ", + csum, csum_expected); + return -EINVAL;
[PATCH v2 7/14] input: cyapa: add gen3 trackpad device firmware update function supported
Add firmware image update function supported for gen3 trackpad device, which its function is supplied through cyapa core update_fw interface. TEST=test on Chomebooks. Signed-off-by: Du, Dudley d...@cypress.com --- diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 5345a9e..a3e1e72 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -392,6 +392,78 @@ static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) return -EAGAIN; } +/* + * Enter bootloader by soft resetting the device. + * + * If device is already in the bootloader, the function just returns. + * Otherwise, reset the device; after reset, device enters bootloader idle + * state immediately. + * + * Also, if device was unregister device from input core. Device will + * re-register after it is detected following resumption of operational mode. + * + * Returns: + * 0 on success + * -EAGAIN device was reset, but is not now in bootloader idle state + *0 if the device never responds within the timeout + */ +static int cyapa_gen3_bl_enter(struct cyapa *cyapa) +{ + int ret; + + if (cyapa-input) { + cyapa_disable_irq(cyapa); + input_unregister_device(cyapa-input); + cyapa-input = NULL; + } + + ret = cyapa_poll_state(cyapa, 500); + if (ret 0) + return ret; + if (cyapa-state == CYAPA_STATE_BL_IDLE) { + /* Already in BL_IDLE. Skipping exit. */ + return 0; + } + + if (cyapa-state != CYAPA_STATE_OP) + return -EAGAIN; + + cyapa-state = CYAPA_STATE_NO_DEVICE; + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01); + if (ret 0) + return -EIO; + + usleep_range(25000, 5); + ret = cyapa_poll_state(cyapa, 500); + if (ret 0) + return ret; + if ((cyapa-state != CYAPA_STATE_BL_IDLE) || + (cyapa-status[REG_BL_STATUS] BL_STATUS_WATCHDOG)) + return -EAGAIN; + + return 0; +} + +static int cyapa_gen3_bl_activate(struct cyapa *cyapa) +{ + int ret; + + ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate), + bl_activate); + if (ret 0) + return ret; + + /* Wait for bootloader to activate; takes between 2 and 12 seconds */ + msleep(2000); + ret = cyapa_poll_state(cyapa, 11000); + if (ret 0) + return ret; + if (cyapa-state != CYAPA_STATE_BL_ACTIVE) + return -EAGAIN; + + return 0; +} + static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { int ret; @@ -452,6 +524,206 @@ static int cyapa_gen3_bl_exit(struct cyapa *cyapa) return 0; } +/* Used in gen3 bootloader commands. */ +static u16 cyapa_gen3_csum(const u8 *buf, size_t count) +{ + int i; + u16 csum = 0; + + for (i = 0; i count; i++) + csum += buf[i]; + + return csum; +} + +/* + * Verify the integrity of a CYAPA firmware image file. + * + * The firmware image file is 30848 bytes, composed of 482 64-byte blocks. + * + * The first 2 blocks are the firmware header. + * The next 480 blocks are the firmware image. + * + * The first two bytes of the header hold the header checksum, computed by + * summing the other 126 bytes of the header. + * The last two bytes of the header hold the firmware image checksum, computed + * by summing the 30720 bytes of the image modulo 0x. + * + * Both checksums are stored little-endian. + */ +static int cyapa_gen3_check_fw(struct cyapa *cyapa, const struct firmware *fw) +{ + struct device *dev = cyapa-client-dev; + u16 csum; + u16 csum_expected; + + /* Firmware must match exact 30848 bytes = 482 64-byte blocks. */ + if (fw-size != CYAPA_FW_SIZE) { + dev_err(dev, invalid firmware size = %zu, expected %u.\n, + fw-size, CYAPA_FW_SIZE); + return -EINVAL; + } + + /* Verify header block */ + csum_expected = (fw-data[0] 8) | fw-data[1]; + csum = cyapa_gen3_csum(fw-data[2], CYAPA_FW_HDR_SIZE - 2); + if (csum != csum_expected) { + dev_err(dev, %s %04x, expected: %04x\n, + invalid firmware header checksum = , + csum, csum_expected); + return -EINVAL; + } + + /* Verify firmware image */ + csum_expected = (fw-data[CYAPA_FW_HDR_SIZE - 2] 8) | +fw-data[CYAPA_FW_HDR_SIZE - 1]; + csum = cyapa_gen3_csum(fw-data[CYAPA_FW_HDR_SIZE], + CYAPA_FW_DATA_SIZE); + if (csum != csum_expected) { + dev_err(dev, %s %04x, expected: %04x\n, + invalid firmware header checksum = , + csum, csum_expected); + return -EINVAL; + } +
[PATCH v2 7/14] input: cyapa: add gen3 trackpad device firmware update function supported
Add firmware image update function supported for gen3 trackpad device, which its function is supplied through cyapa core update_fw interface. TEST=test on Chomebooks. Signed-off-by: Du, Dudley --- diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 5345a9e..a3e1e72 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -392,6 +392,78 @@ static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) return -EAGAIN; } +/* + * Enter bootloader by soft resetting the device. + * + * If device is already in the bootloader, the function just returns. + * Otherwise, reset the device; after reset, device enters bootloader idle + * state immediately. + * + * Also, if device was unregister device from input core. Device will + * re-register after it is detected following resumption of operational mode. + * + * Returns: + * 0 on success + * -EAGAIN device was reset, but is not now in bootloader idle state + * < 0 if the device never responds within the timeout + */ +static int cyapa_gen3_bl_enter(struct cyapa *cyapa) +{ + int ret; + + if (cyapa->input) { + cyapa_disable_irq(cyapa); + input_unregister_device(cyapa->input); + cyapa->input = NULL; + } + + ret = cyapa_poll_state(cyapa, 500); + if (ret < 0) + return ret; + if (cyapa->state == CYAPA_STATE_BL_IDLE) { + /* Already in BL_IDLE. Skipping exit. */ + return 0; + } + + if (cyapa->state != CYAPA_STATE_OP) + return -EAGAIN; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01); + if (ret < 0) + return -EIO; + + usleep_range(25000, 5); + ret = cyapa_poll_state(cyapa, 500); + if (ret < 0) + return ret; + if ((cyapa->state != CYAPA_STATE_BL_IDLE) || + (cyapa->status[REG_BL_STATUS] & BL_STATUS_WATCHDOG)) + return -EAGAIN; + + return 0; +} + +static int cyapa_gen3_bl_activate(struct cyapa *cyapa) +{ + int ret; + + ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate), + bl_activate); + if (ret < 0) + return ret; + + /* Wait for bootloader to activate; takes between 2 and 12 seconds */ + msleep(2000); + ret = cyapa_poll_state(cyapa, 11000); + if (ret < 0) + return ret; + if (cyapa->state != CYAPA_STATE_BL_ACTIVE) + return -EAGAIN; + + return 0; +} + static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { int ret; @@ -452,6 +524,206 @@ static int cyapa_gen3_bl_exit(struct cyapa *cyapa) return 0; } +/* Used in gen3 bootloader commands. */ +static u16 cyapa_gen3_csum(const u8 *buf, size_t count) +{ + int i; + u16 csum = 0; + + for (i = 0; i < count; i++) + csum += buf[i]; + + return csum; +} + +/* + * Verify the integrity of a CYAPA firmware image file. + * + * The firmware image file is 30848 bytes, composed of 482 64-byte blocks. + * + * The first 2 blocks are the firmware header. + * The next 480 blocks are the firmware image. + * + * The first two bytes of the header hold the header checksum, computed by + * summing the other 126 bytes of the header. + * The last two bytes of the header hold the firmware image checksum, computed + * by summing the 30720 bytes of the image modulo 0x. + * + * Both checksums are stored little-endian. + */ +static int cyapa_gen3_check_fw(struct cyapa *cyapa, const struct firmware *fw) +{ + struct device *dev = >client->dev; + u16 csum; + u16 csum_expected; + + /* Firmware must match exact 30848 bytes = 482 64-byte blocks. */ + if (fw->size != CYAPA_FW_SIZE) { + dev_err(dev, "invalid firmware size = %zu, expected %u.\n", + fw->size, CYAPA_FW_SIZE); + return -EINVAL; + } + + /* Verify header block */ + csum_expected = (fw->data[0] << 8) | fw->data[1]; + csum = cyapa_gen3_csum(>data[2], CYAPA_FW_HDR_SIZE - 2); + if (csum != csum_expected) { + dev_err(dev, "%s %04x, expected: %04x\n", + "invalid firmware header checksum = ", + csum, csum_expected); + return -EINVAL; + } + + /* Verify firmware image */ + csum_expected = (fw->data[CYAPA_FW_HDR_SIZE - 2] << 8) | +fw->data[CYAPA_FW_HDR_SIZE - 1]; + csum = cyapa_gen3_csum(>data[CYAPA_FW_HDR_SIZE], + CYAPA_FW_DATA_SIZE); + if (csum != csum_expected) { + dev_err(dev, "%s %04x, expected: %04x\n", + "invalid firmware header checksum = ", + csum, csum_expected); + return -EINVAL;
[PATCH v2 7/14] input: cyapa: add gen3 trackpad device firmware update function supported
Add firmware image update function supported for gen3 trackpad device, which its function is supplied through cyapa core update_fw interface. TEST=test on Chomebooks. Signed-off-by: Du, Dudley d...@cypress.com --- diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 5345a9e..a3e1e72 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -392,6 +392,78 @@ static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) return -EAGAIN; } +/* + * Enter bootloader by soft resetting the device. + * + * If device is already in the bootloader, the function just returns. + * Otherwise, reset the device; after reset, device enters bootloader idle + * state immediately. + * + * Also, if device was unregister device from input core. Device will + * re-register after it is detected following resumption of operational mode. + * + * Returns: + * 0 on success + * -EAGAIN device was reset, but is not now in bootloader idle state + *0 if the device never responds within the timeout + */ +static int cyapa_gen3_bl_enter(struct cyapa *cyapa) +{ + int ret; + + if (cyapa-input) { + cyapa_disable_irq(cyapa); + input_unregister_device(cyapa-input); + cyapa-input = NULL; + } + + ret = cyapa_poll_state(cyapa, 500); + if (ret 0) + return ret; + if (cyapa-state == CYAPA_STATE_BL_IDLE) { + /* Already in BL_IDLE. Skipping exit. */ + return 0; + } + + if (cyapa-state != CYAPA_STATE_OP) + return -EAGAIN; + + cyapa-state = CYAPA_STATE_NO_DEVICE; + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01); + if (ret 0) + return -EIO; + + usleep_range(25000, 5); + ret = cyapa_poll_state(cyapa, 500); + if (ret 0) + return ret; + if ((cyapa-state != CYAPA_STATE_BL_IDLE) || + (cyapa-status[REG_BL_STATUS] BL_STATUS_WATCHDOG)) + return -EAGAIN; + + return 0; +} + +static int cyapa_gen3_bl_activate(struct cyapa *cyapa) +{ + int ret; + + ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate), + bl_activate); + if (ret 0) + return ret; + + /* Wait for bootloader to activate; takes between 2 and 12 seconds */ + msleep(2000); + ret = cyapa_poll_state(cyapa, 11000); + if (ret 0) + return ret; + if (cyapa-state != CYAPA_STATE_BL_ACTIVE) + return -EAGAIN; + + return 0; +} + static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { int ret; @@ -452,6 +524,206 @@ static int cyapa_gen3_bl_exit(struct cyapa *cyapa) return 0; } +/* Used in gen3 bootloader commands. */ +static u16 cyapa_gen3_csum(const u8 *buf, size_t count) +{ + int i; + u16 csum = 0; + + for (i = 0; i count; i++) + csum += buf[i]; + + return csum; +} + +/* + * Verify the integrity of a CYAPA firmware image file. + * + * The firmware image file is 30848 bytes, composed of 482 64-byte blocks. + * + * The first 2 blocks are the firmware header. + * The next 480 blocks are the firmware image. + * + * The first two bytes of the header hold the header checksum, computed by + * summing the other 126 bytes of the header. + * The last two bytes of the header hold the firmware image checksum, computed + * by summing the 30720 bytes of the image modulo 0x. + * + * Both checksums are stored little-endian. + */ +static int cyapa_gen3_check_fw(struct cyapa *cyapa, const struct firmware *fw) +{ + struct device *dev = cyapa-client-dev; + u16 csum; + u16 csum_expected; + + /* Firmware must match exact 30848 bytes = 482 64-byte blocks. */ + if (fw-size != CYAPA_FW_SIZE) { + dev_err(dev, invalid firmware size = %zu, expected %u.\n, + fw-size, CYAPA_FW_SIZE); + return -EINVAL; + } + + /* Verify header block */ + csum_expected = (fw-data[0] 8) | fw-data[1]; + csum = cyapa_gen3_csum(fw-data[2], CYAPA_FW_HDR_SIZE - 2); + if (csum != csum_expected) { + dev_err(dev, %s %04x, expected: %04x\n, + invalid firmware header checksum = , + csum, csum_expected); + return -EINVAL; + } + + /* Verify firmware image */ + csum_expected = (fw-data[CYAPA_FW_HDR_SIZE - 2] 8) | +fw-data[CYAPA_FW_HDR_SIZE - 1]; + csum = cyapa_gen3_csum(fw-data[CYAPA_FW_HDR_SIZE], + CYAPA_FW_DATA_SIZE); + if (csum != csum_expected) { + dev_err(dev, %s %04x, expected: %04x\n, + invalid firmware header checksum = , + csum, csum_expected); + return -EINVAL; + } +