[PATCH v2 7/14] input: cyapa: add gen3 trackpad device firmware update function supported

2014-06-30 Thread Dudley Du
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

2014-06-30 Thread Dudley Du
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

2014-06-06 Thread Dudley Du
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

2014-06-06 Thread Dudley Du
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;
+   }
+