diff mbox

[v3,9/14] input: cyapa: add gen3 trackpad device read firmware image function support

Message ID 77BC725C9062764F874D79F51E1F1A8F4C90DDE0@S04-MBX01-04.s04.local (mailing list archive)
State New, archived
Headers show

Commit Message

Dudley Du July 4, 2014, 11:09 a.m. UTC
Add read firmware image function supported for gen3 trackpad device,
which its function is supplied through cyapa core read_fw interface.
TEST=test on Chromebooks.

Signed-off-by: Dudley Du <dudl@cypress.com>

---
 drivers/input/mouse/cyapa_gen3.c |   73 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

--
1.7.9.5

This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message.
diff mbox

Patch

diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c
index 2236706..7e9fe09 100644
--- a/drivers/input/mouse/cyapa_gen3.c
+++ b/drivers/input/mouse/cyapa_gen3.c
@@ -696,6 +696,36 @@  static int cyapa_gen3_write_fw_block(struct cyapa *cyapa,
        return ret;
 }

+/*
+ * A firmware block read command reads 16 bytes of data from flash starting
+ * from a given address.  The 12-byte block read command has the format:
+ *   <0xff> <CMD> <Key> <Addr>
+ *
+ *  <0xff>  - every command starts with 0xff
+ *  <CMD>   - the read command value is 0x3c
+ *  <Key>   - read commands include an 8-byte key: { 00 01 02 03 04 05 06 07 }
+ *  <Addr>  - Memory address (16-bit, big-endian)
+ *
+ * The command is followed by an i2c block read to read the 16 bytes of data.
+ */
+static int cyapa_gen3_read_fw_bytes(struct cyapa *cyapa, u16 addr, u8 *data)
+{
+       int ret;
+       u8 cmd[] = { 0xff, 0x3c, 0x00, 0x01, 0x02, 0x03, 0x04,
+               0x05, 0x06, 0x07, addr >> 8, addr };
+
+       ret = cyapa_gen3_write_buffer(cyapa, cmd, sizeof(cmd));
+       if (ret)
+               return ret;
+
+       /* read data buffer starting from offset 16 */
+       ret = cyapa_i2c_reg_read_block(cyapa, 16, CYAPA_FW_READ_SIZE, data);
+       if (ret != CYAPA_FW_READ_SIZE)
+               return (ret < 0) ? ret : -EIO;
+
+       return 0;
+}
+
 static int cyapa_gen3_write_blocks(struct cyapa *cyapa,
                size_t start_block, size_t block_count,
                const u8 *image_data)
@@ -742,6 +772,47 @@  static int cyapa_gen3_do_fw_update(struct cyapa *cyapa,
        return 0;
 }

+/*
+ * Read the entire firmware image into ->fw_image.
+ * If the ->fw_image has already been allocated, then this function
+ * doesn't do anything and just returns 0.
+ * If an error occurs while reading the image, ->fw_image is freed, and
+ * the error is returned.
+ *
+ * The firmware is a fixed size (CYAPA_FW_SIZE), and is read out in
+ * fixed length (CYAPA_FW_READ_SIZE) chunks.
+ */
+static int cyapa_gen3_read_fw(struct cyapa *cyapa)
+{
+       int ret;
+       int addr;
+
+       ret = cyapa_gen3_bl_enter(cyapa);
+       if (ret)
+               goto err;
+
+       cyapa->fw_image = kmalloc(CYAPA_FW_SIZE, GFP_KERNEL);
+       if (!cyapa->fw_image) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       for (addr = 0; addr < CYAPA_FW_SIZE; addr += CYAPA_FW_READ_SIZE) {
+               ret = cyapa_gen3_read_fw_bytes(cyapa, CYAPA_FW_HDR_START + addr,
+                                         &cyapa->fw_image[addr]);
+               if (ret) {
+                       kfree(cyapa->fw_image);
+                       cyapa->fw_image = NULL;
+                       break;
+               }
+       }
+
+err:
+       if (cyapa->fw_image)
+               cyapa->fw_image_size = CYAPA_FW_SIZE;
+       return ret;
+}
+
 static ssize_t cyapa_gen3_do_calibrate(struct device *dev,
                                     struct device_attribute *attr,
                                     const char *buf, size_t count)
@@ -1134,6 +1205,8 @@  const struct cyapa_dev_ops cyapa_gen3_ops = {
        .show_baseline = cyapa_gen3_show_baseline,
        .calibrate_store = cyapa_gen3_do_calibrate,

+       .read_fw = cyapa_gen3_read_fw,
+
        .state_parse = cyapa_gen3_state_parse,
        .operational_check = cyapa_gen3_do_operational_check,