[PATCH v3 13/14] input: cyapa: add gen5 trackpad device read firmware image and raw data functions support
Add read firmware image function supported for gen5 trackpad device, which its function is supplied through cyapa core read_fw interface. Through this interface, upper layer application can read out, check and backup the firmware image in trackpad device before updated with new one when new firmware image may have problems. Also add interfaces to report all sensor's raw data values to upper layer, so it can help to find out the performance issue when users reports problem, and also it's useful and required interface for some customers that require sensors' raw data. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 258 ++ 1 file changed, 258 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 08820eb..c6568be 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1206,6 +1206,158 @@ static int cyapa_gen5_write_fw_block(struct cyapa *cyapa, return 0; } +static int cyapa_gen5_read_fw_bytes(struct cyapa *cyapa, u16 row_num, u8 *data) +{ + int ret; + u8 cmd[16]; + size_t cmd_len; + u8 resp_data[CYAPA_TSG_FW_ROW_SIZE / 2 + GEN5_MIN_BL_RESP_LENGTH]; + int resp_len; + u16 offset; + u16 cmd_crc; + struct cyapa_tsg_bin_image_data_record *fw_img_record; + + fw_img_record = (struct cyapa_tsg_bin_image_data_record *)data; + + cmd[0] = 0x04; /* register address */ + cmd[1] = 0x00; + cmd[2] = 0x0e; + cmd[3] = 0x00; + cmd[4] = 0x40; /* report id 40h */ + cmd[5] = 0x00; + cmd[6] = GEN5_SOP_KEY; + cmd[7] = 0x3d; /* read application image command code */ + cmd[8] = 0x03; + cmd[9] = 0x00; + offset = row_num * CYAPA_TSG_FW_ROW_SIZE - + CYAPA_TSG_START_OF_APPLICATION; + put_unaligned_le16(offset, &cmd[10]); + cmd[12] = CYAPA_TSG_IMG_READ_SIZE; + cmd_crc = crc_itu_t(0x, &cmd[6], 7); + put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */ + cmd[15] = GEN5_EOP_KEY; /* EOP = 17h */ + cmd_len = 16; + + resp_len = CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH; + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, cmd_len, + resp_data, &resp_len, + 50, cyapa_gen5_sort_tsg_pip_bl_resp_data); + if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) || + ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return (ret < 0) ? ret : -EAGAIN; + + /* copy first 64 bytes in the row. */ + memcpy(&fw_img_record->record_data[0], &resp_data[8], + CYAPA_TSG_IMG_READ_SIZE); + + if (row_num == CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM) { + /* last row's rest 64 bytes are bootloader metadata, +* it's not allowed to be read out, will respond with error. */ + memset(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE], + 0, CYAPA_TSG_IMG_READ_SIZE); + goto skip_last_row; + } + + /* read next 64 bytes in the row. */ + offset = offset + CYAPA_TSG_IMG_READ_SIZE; + put_unaligned_le16(offset, &cmd[10]); + cmd_crc = crc_itu_t(0x, &cmd[6], 7); + put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */ + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, cmd_len, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_bl_resp_data); + if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) || + ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return (ret < 0) ? ret : -EAGAIN; + + /* copy last 64 bytes in the row. */ + memcpy(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE], + &resp_data[8], CYAPA_TSG_IMG_READ_SIZE); + +skip_last_row: + fw_img_record->flash_array_id = 0; + put_unaligned_be16(row_num, &fw_img_record->row_number); + put_unaligned_be16(CYAPA_TSG_FW_ROW_SIZE, &fw_img_record->record_len); + + return 0; +} + +static int cyapa_gen5_read_fw(struct cyapa *cyapa) +{ + int ret; + int fw_img_head_size; + int fw_img_record_size; + int row_index; + int array_index; + u32 img_start; + u16 img_len; + u16 img_start_row; + u16 img_end_row; + struct cyapa_tsg_bin_image_data_record app_integrity; + u8 *record_data; + + ret = cyapa_gen5_bl_enter(cyapa); + if (ret) + goto err; + + cyapa_empty_pip_output_data(cyapa, NULL,
RE: [PATCH v2 0/14] input: cyapa: re-architecture driver to support multi-trackpads in one driver
Hi Patrik, Thanks for your patient and detail instructions. I will try to fix these issues and resubmit again. Thanks, Dudley > -Original Message- > From: Patrik Fimml [mailto:patr...@chromium.org] > Sent: Tuesday, July 01, 2014 4:00 AM > To: Dudley Du > Cc: Dmitry Torokhov; Rafael J. Wysocki; Alan Stern; Benson Leung; Lily Rui; > Daniel Kurtz; linux-in...@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH v2 0/14] input: cyapa: re-architecture driver to support > multi-trackpads in one driver > > Hi Dudley, > > On Mon, Jun 30, 2014 at 05:43:06AM +, Dudley Du wrote: > > Attached are the patches files, I sent it firstly. > > Thanks for the response, I was able to apply the patches now. > > The attached files lack headers and commit messages though, so I don't have > fine-grained history in my git tree for convenient later review. The file > names > suggest to me that you might just have copy-and-pasted the patches from > somewhere. > > It would be great if you could attach them again in the format produced by > "git > format-patch", with no further modifications done by hand. (If you feel the > need to do modifications, you should modify the actual commits e.g. with "git > rebase -i" before using format-patch.) Others can then simply import your > changes - including commit messages - into their tree with "git am". > > Thanks, > Patrik 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. N�r��yb�X��ǧv�^�){.n�+{zX����ܨ}���Ơz�&j:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a��� 0��h���i
[PATCH V5 14/14] input: cyapa: add function to monitor LID close event to off trackpad device
Add the function to monitor lid close event to suspend and resume trackpad device. Because system suspend takes some time to trigger from user space, and in that time, the lid panel of the laptop may couple with the active trackpad. This may generate stray input events, which may in turn cancel the suspend if the drivers use pm_wakup_event(), and those input events may trigger something unwanted in the UI. So this patch adds the function to do off the trackpad device quickly. When the lid is closed, as soon as possible, the trakcpad device must be off. And furthermore, the policy on lid close is not always to enter suspend (lid closed with external display), and at this time, the trackpad device must be disabled as well as again to avoid the risk of generating stray events. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 136 drivers/input/mouse/cyapa.h | 3 + 2 files changed, 139 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 385523d..f980888 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -1082,6 +1082,140 @@ static const struct attribute_group cyapa_sysfs_group = { .attrs = cyapa_sysfs_entries, }; + +/* + * We rely on EV_SW and SW_LID bits to identify a LID device, and hook + * up our filter to listen for SW_LID events to enable/disable touchpad when + * LID is open/closed. + */ +static const struct input_device_id lid_device_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | +INPUT_DEVICE_ID_MATCH_SWBIT, + .evbit = { BIT_MASK(EV_SW) }, + .swbit = { BIT_MASK(SW_LID) }, + }, + { }, +}; + +static int lid_device_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *lid_handle; + int error; + + pr_info("cyapa: LID device: '%s' connected\n", dev->name); + lid_handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!lid_handle) + return -ENOMEM; + + lid_handle->dev = dev; + lid_handle->handler = handler; + lid_handle->name = "lid_event_handler"; + lid_handle->private = handler->private; + + error = input_register_handle(lid_handle); + if (error) { + pr_err("Failed to register lid_event_handler, error %d\n", + error); + goto err_free; + } + + error = input_open_device(lid_handle); + if (error) { + pr_err("Failed to open input device, error %d\n", error); + goto err_unregister; + } + + return 0; +err_unregister: + input_unregister_handle(lid_handle); +err_free: + kfree(lid_handle); + return error; +} + +static void lid_device_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static bool lid_event_filter(struct input_handle *handle, +unsigned int type, unsigned int code, int value) +{ + struct cyapa *cyapa = handle->private; + struct device *dev = &cyapa->client->dev; + + if (type == EV_SW && code == SW_LID) { + pr_info("cyapa %s: %s touch device\n", + dev_name(&cyapa->client->dev), + (value ? "disable" : "enable")); + if (cyapa->suspended) { + /* +* If the lid event filter is called while suspended, +* there is no guarantee that the underlying i2cs are +* resumed at this point, so it is not safe to issue +* the command to change power modes. +* Instead, rely on cyapa_resume to set us back to +* PWR_MODE_FULL_ACTIVE. +*/ + pr_info("cyapa %s: skipping lid pm change in suspend\n", + dev_name(&cyapa->client->dev)); + return false; + } + if (value == 0) { + if (cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + } else { + pm_runtime_disable(dev); + if (cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, +
[PATCH V5 13/14] input: cyapa: add gen5 trackpad device read firmware image and raw data functions support
Add read firmware image function supported for gen5 trackpad device, which its function is supplied through cyapa core read_fw interface. Through this interface, upper layer application can read out, check and backup the firmware image in trackpad device before updated with new one when new firmware image may have problems. Also add interfaces to report all sensor's raw data values to upper layer, so it can help to find out the performance issue when users reports problem, and also it's useful and required interface for some customers that require sensors' raw data. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 267 ++- 1 file changed, 266 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 452cb5d..e7f410d 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1221,6 +1221,158 @@ static int cyapa_gen5_write_fw_block(struct cyapa *cyapa, return 0; } +static int cyapa_gen5_read_fw_bytes(struct cyapa *cyapa, u16 row_num, u8 *data) +{ + int ret; + u8 cmd[16]; + size_t cmd_len; + u8 resp_data[CYAPA_TSG_FW_ROW_SIZE / 2 + GEN5_MIN_BL_RESP_LENGTH]; + int resp_len; + u16 offset; + u16 cmd_crc; + struct cyapa_tsg_bin_image_data_record *fw_img_record; + + fw_img_record = (struct cyapa_tsg_bin_image_data_record *)data; + + cmd[0] = 0x04; /* Register address */ + cmd[1] = 0x00; + cmd[2] = 0x0e; + cmd[3] = 0x00; + cmd[4] = 0x40; /* Report id 40h */ + cmd[5] = 0x00; + cmd[6] = GEN5_SOP_KEY; + cmd[7] = 0x3d; /* Read application image command code */ + cmd[8] = 0x03; + cmd[9] = 0x00; + offset = row_num * CYAPA_TSG_FW_ROW_SIZE - + CYAPA_TSG_START_OF_APPLICATION; + put_unaligned_le16(offset, &cmd[10]); + cmd[12] = CYAPA_TSG_IMG_READ_SIZE; + cmd_crc = crc_itu_t(0x, &cmd[6], 7); + put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */ + cmd[15] = GEN5_EOP_KEY; /* EOP = 17h */ + cmd_len = 16; + + resp_len = CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH; + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, cmd_len, + resp_data, &resp_len, + 50, cyapa_gen5_sort_tsg_pip_bl_resp_data); + if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) || + ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return (ret < 0) ? ret : -EAGAIN; + + /* Copy first 64 bytes in the row. */ + memcpy(&fw_img_record->record_data[0], &resp_data[8], + CYAPA_TSG_IMG_READ_SIZE); + + if (row_num == CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM) { + /* Last row's rest 64 bytes are bootloader metadata, +* it's not allowed to be read out, will respond with error. */ + memset(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE], + 0, CYAPA_TSG_IMG_READ_SIZE); + goto skip_last_row; + } + + /* Read next 64 bytes in the row. */ + offset = offset + CYAPA_TSG_IMG_READ_SIZE; + put_unaligned_le16(offset, &cmd[10]); + cmd_crc = crc_itu_t(0x, &cmd[6], 7); + put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */ + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, cmd_len, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_bl_resp_data); + if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) || + ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return (ret < 0) ? ret : -EAGAIN; + + /* Copy last 64 bytes in the row. */ + memcpy(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE], + &resp_data[8], CYAPA_TSG_IMG_READ_SIZE); + +skip_last_row: + fw_img_record->flash_array_id = 0; + put_unaligned_be16(row_num, &fw_img_record->row_number); + put_unaligned_be16(CYAPA_TSG_FW_ROW_SIZE, &fw_img_record->record_len); + + return 0; +} + +static int cyapa_gen5_read_fw(struct cyapa *cyapa) +{ + int ret; + int fw_img_head_size; + int fw_img_record_size; + int row_index; + int array_index; + u32 img_start; + u16 img_len; + u16 img_start_row; + u16 img_end_row; + struct cyapa_tsg_bin_image_data_record app_integrity; + u8 *record_data; + + ret = cyapa_gen5_bl_enter(cyapa); + if (ret) + goto err; + + cyapa_empty_
[PATCH V5 11/14] input: cyapa: add gen5 trackpad device firmware update function support
Add firmware image update function supported for gen5 trackpad device, which its function is supplied through cyapa core update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Kconfig | 2 +- drivers/input/mouse/cyapa_gen5.c | 294 +++ 2 files changed, 295 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 366fc7a..005d69b 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -205,7 +205,7 @@ config MOUSE_BCM5974 config MOUSE_CYAPA tristate "Cypress APA I2C Trackpad support" - depends on I2C + depends on I2C && CRC_ITU_T help This driver adds support for Cypress All Points Addressable (APA) I2C Trackpads, including the ones used in 2012 Samsung Chromebooks. diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 4f64b0b..0c84b1b 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "cyapa.h" @@ -918,6 +919,86 @@ static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) return -EAGAIN; } +static int cyapa_gen5_bl_initiate(struct cyapa *cyapa, + const struct firmware *fw) +{ + int ret = 0; + u16 length = 0; + u16 data_len = 0; + u16 meta_data_crc = 0; + u16 cmd_crc = 0; + u8 bl_gen5_activate[18 + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE + 3]; + int bl_gen5_activate_size = 0; + u8 resp_data[11]; + int resp_len; + struct cyapa_tsg_bin_image *image; + int records_num; + u8 *data; + + /* Try to dump all bufferred report data before send any command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + bl_gen5_activate_size = sizeof(bl_gen5_activate); + memset(bl_gen5_activate, 0, bl_gen5_activate_size); + + /* Output Report Register Address[15:0] = 0004h */ + bl_gen5_activate[0] = 0x04; + bl_gen5_activate[1] = 0x00; + + /* Total command length[15:0] */ + length = bl_gen5_activate_size - 2; + put_unaligned_le16(length, &bl_gen5_activate[2]); + bl_gen5_activate[4] = 0x40; /* Report ID = 40h */ + bl_gen5_activate[5] = 0x00; /* RSVD = 00h */ + + bl_gen5_activate[6] = GEN5_SOP_KEY; /* SOP = 01h */ + bl_gen5_activate[7] = 0x48; /* Command Code = 48h */ + + /* 8 Key bytes and block size */ + data_len = CYAPA_TSG_BL_KEY_SIZE + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE; + /* Data Length[15:0] */ + put_unaligned_le16(data_len, &bl_gen5_activate[8]); + bl_gen5_activate[10] = 0xa5; /* Key Byte 0 */ + bl_gen5_activate[11] = 0x01; + bl_gen5_activate[12] = 0x02; /* . */ + bl_gen5_activate[13] = 0x03; /* . */ + bl_gen5_activate[14] = 0xff; /* . */ + bl_gen5_activate[15] = 0xfe; + bl_gen5_activate[16] = 0xfd; + bl_gen5_activate[17] = 0x5a; /* Key Byte 7 */ + + /* Copy 60 bytes Meta Data Row Parameters */ + image = (struct cyapa_tsg_bin_image *)fw->data; + records_num = (fw->size - sizeof(struct cyapa_tsg_bin_image_head)) / + sizeof(struct cyapa_tsg_bin_image_data_record); + /* APP_INTEGRITY row is always the last row block */ + data = image->records[records_num - 1].record_data; + memcpy(&bl_gen5_activate[18], data, CYAPA_TSG_FLASH_MAP_METADATA_SIZE); + + meta_data_crc = crc_itu_t(0x, &bl_gen5_activate[18], + CYAPA_TSG_FLASH_MAP_METADATA_SIZE); + /* Meta Data CRC[15:0] */ + put_unaligned_le16(meta_data_crc, + &bl_gen5_activate[18 + CYAPA_TSG_FLASH_MAP_METADATA_SIZE]); + + cmd_crc = crc_itu_t(0x, &bl_gen5_activate[6], 4 + data_len); + put_unaligned_le16(cmd_crc, + &bl_gen5_activate[bl_gen5_activate_size - 3]); /* CRC[15:0] */ + bl_gen5_activate[bl_gen5_activate_size - 1] = GEN5_EOP_KEY; + + resp_len = sizeof(resp_data); + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + bl_gen5_activate, sizeof(bl_gen5_activate), + resp_data, &resp_len, 12000, + cyapa_gen5_sort_tsg_pip_bl_resp_data); + if (ret || resp_len != GEN5_BL_INITIATE_RESP_LEN || + resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return (ret < 0) ? ret : -EAGAIN; + + return 0; +} + bool cyapa_gen5_sort_bl_exit_data(struct cyapa *cyapa, u8 *buf, int len) { if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE) @@ -966,6 +1047,214 @@ static int cyapa_gen5_bl_exit(struct cyapa *cyapa) return -EAGAIN;
[PATCH V5 10/14] input: cyapa: add gen5 trackpad device basic functions support
Based on the cyapa core, add the gen5 trackpad device's basic functions supported, so gen5 trackpad device can work with kernel input system. And also based on the state parse interface, the cyapa driver can automatically determine the attached is gen3 or gen5 protocol trackpad device, then set the correct protocol to work with the attached trackpad device. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |2 +- drivers/input/mouse/cyapa.c | 29 +- drivers/input/mouse/cyapa.h |1 + drivers/input/mouse/cyapa_gen5.c | 1660 ++ 4 files changed, 1687 insertions(+), 5 deletions(-) create mode 100644 drivers/input/mouse/cyapa_gen5.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 63b42e0..08785a5 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -35,4 +35,4 @@ psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT)+= trackpoint.o psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o psmouse-$(CONFIG_MOUSE_PS2_CYPRESS)+= cypress_ps2.o -cyapatp-y := cyapa.o cyapa_gen3.o +cyapatp-y := cyapa.o cyapa_gen3.o cyapa_gen5.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 0463505..385523d 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -122,6 +122,8 @@ void cyapa_default_irq_handler(struct cyapa *cyapa) cont = true; if (cyapa_gen3_ops.irq_cmd_handler) cont = cyapa_gen3_ops.irq_cmd_handler(cyapa); + if (cont && cyapa_gen5_ops.irq_cmd_handler) + cont = cyapa_gen5_ops.irq_cmd_handler(cyapa); if (!cont) return; @@ -264,6 +266,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return ret; switch (cyapa->gen) { + case CYAPA_GEN5: + cyapa->ops = &cyapa_gen5_ops; + break; case CYAPA_GEN3: cyapa->ops = &cyapa_gen3_ops; break; @@ -377,6 +382,14 @@ static int cyapa_get_state(struct cyapa *cyapa) if (ret == 0) goto out_detected; } + if ((cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN5) && + !smbus && even_addr) { + ret = cyapa_gen5_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (ret == 0) + goto out_detected; + } /* * Cannot detect communication protocol based on current @@ -1096,18 +1109,26 @@ static void cyapa_detect_and_start(void *data, async_cookie_t cookie) static int cyapa_tp_modules_init(struct cyapa *cyapa) { + int ret = 0; + if (cyapa_gen3_ops.initialize) - return cyapa_gen3_ops.initialize(cyapa); + ret = cyapa_gen3_ops.initialize(cyapa); + if (!ret && cyapa_gen5_ops.initialize) + ret = cyapa_gen5_ops.initialize(cyapa); - return 0; + return ret; } static int cyapa_tp_modules_uninit(struct cyapa *cyapa) { + int ret = 0; + if (cyapa_gen3_ops.uninitialize) - return cyapa_gen3_ops.uninitialize(cyapa); + ret = cyapa_gen3_ops.uninitialize(cyapa); + if (!ret && cyapa_gen5_ops.uninitialize) + ret = cyapa_gen5_ops.uninitialize(cyapa); - return 0; + return ret; } static int cyapa_probe(struct i2c_client *client, diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index 0b8d023..36e87c3 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -299,5 +299,6 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode); extern const char unique_str[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; +extern const struct cyapa_dev_ops cyapa_gen5_ops; #endif diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c new file mode 100644 index 000..4f64b0b --- /dev/null +++ b/drivers/input/mouse/cyapa_gen5.c @@ -0,0 +1,1660 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du + * + * Copyright (C) 2014 Cypress Semiconductor, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cyapa.h" + + +/* Macro of Gen5 */ +#define RECORD_EVENT_NONE0 +#define RECORD_EVENT_TOUCHDOWN 1 +#define RECORD_EVENT_DISPLACE2 +#define RECORD_EVENT_LIFTOFF 3 + +#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80 +#define CYAPA_TSG_IMG_FW_HDR_SIZE 13 +#define
[PATCH V5 04/14] input: cyapa: add cyapa key function interfaces in sysfs system
>From b642644b26f35db9cda9a79e519026c584fcf7bc Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Fri, 29 Aug 2014 14:04:50 + Subject: [PATCH 04/14] input: cyapa: add cyapa key function interfaces in sysfs system To: dmitry.torok...@gmail.com, rydb...@euromail.se Cc: ble...@google.com, pat...@google.com, linux-in...@vger.kernel.org, linux-kernel@vger.kernel.org Add key basic function interfaces in cyapa driver in sysfs system, these interfaces are commonly used in pre- and after production, and for trackpad device state checking, manage and firmware image updating. These interfaces including firmware_version and product_id interfaces for reading firmware version and trackpad device product id values, and including update_fw interface to command firmware image update process. Also including baseline and calibrate interfaces, so can read and check the trackpad device states. If the baseline values are invalid, then can use calibrate interface to recover it. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 192 drivers/input/mouse/cyapa.h | 27 +++ 2 files changed, 219 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index eb3a5a8..96f28e7 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -391,6 +391,78 @@ static void cyapa_detect(struct cyapa *cyapa) } } +static int cyapa_firmware(struct cyapa *cyapa, const char *fw_name) +{ + struct device *dev = &cyapa->client->dev; + int ret; + const struct firmware *fw; + + ret = request_firmware(&fw, fw_name, dev); + if (ret) { + dev_err(dev, "Could not load firmware from %s, %d\n", + fw_name, ret); + return ret; + } + + if (cyapa->ops->check_fw) { + ret = cyapa->ops->check_fw(cyapa, fw); + if (ret) { + dev_err(dev, "Invalid CYAPA firmware image: %s\n", + fw_name); + goto done; + } + } else { + dev_err(dev, "Unknown status, operation forbidden, gen=%d\n", + cyapa->gen); + ret = -EINVAL; + goto done; + } + + /* +* Resume the potentially suspended device because doing FW +* update on a device not in the FULL mode has a chance to +* fail. +*/ + pm_runtime_get_sync(dev); + + if (cyapa->ops->bl_enter) { + ret = cyapa->ops->bl_enter(cyapa); + if (ret) + goto err_detect; + } + + if (cyapa->ops->bl_activate) { + ret = cyapa->ops->bl_activate(cyapa); + if (ret) + goto err_detect; + } + + if (cyapa->ops->bl_initiate) { + ret = cyapa->ops->bl_initiate(cyapa, fw); + if (ret) + goto err_detect; + } + + if (cyapa->ops->update_fw) { + ret = cyapa->ops->update_fw(cyapa, fw); + if (ret) + goto err_detect; + } + + if (cyapa->ops->bl_verify_app_integrity) { + ret = cyapa->ops->bl_verify_app_integrity(cyapa); + if (ret) + goto err_detect; + } + +err_detect: + pm_runtime_put_noidle(dev); + +done: + release_firmware(fw); + return ret; +} + /* * Sysfs Interface. */ @@ -592,6 +664,122 @@ static void cyapa_start_runtime(struct cyapa *cyapa) static void cyapa_start_runtime(struct cyapa *cyapa) {} #endif /* CONFIG_PM_RUNTIME */ +static ssize_t cyapa_show_fm_ver(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int ret; + struct cyapa *cyapa = dev_get_drvdata(dev); + + mutex_lock(&cyapa->state_sync_lock); + ret = scnprintf(buf, PAGE_SIZE, "%d.%d\n", cyapa->fw_maj_ver, +cyapa->fw_min_ver); + mutex_unlock(&cyapa->state_sync_lock); + return ret; +} + +static ssize_t cyapa_show_product_id(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int ret; + struct cyapa *cyapa = dev_get_drvdata(dev); + + mutex_lock(&cyapa->state_sync_lock); + ret = scnprintf(buf, PAGE_SIZE, "%s\n", cyapa->product_id); + mutex_unlock(&cyapa->state_sync_lock); + return ret; +} + +static ssize_t cyapa_update_fw_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa
[PATCH V5 01/14] input: cyapa: re-architecture driver to support multi-trackpads in one driver
In order to support two different communication protocol based trackpad device in one cyapa, the new cyapa driver is re-designed with one cyapa driver core and two devices' functions component. The cyapa driver core is contained in this patch, it supplies the basic function with input and kernel system and also defined the interfaces that the devices' functions component needs to apply and support. Also, in order to speed up the system boot time, the device states detecting and probing process is put into the async thread. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |4 +- drivers/input/mouse/cyapa.c | 1120 +++--- drivers/input/mouse/cyapa.h | 275 +++ 3 files changed, 682 insertions(+), 717 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index c25efdb..8608eb7 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974)+= bcm5974.o -obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o @@ -34,3 +34,5 @@ psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o psmouse-$(CONFIG_MOUSE_PS2_CYPRESS)+= cypress_ps2.o + +cyapatp-y := cyapa.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index b409c3d..3edd23e 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -6,7 +6,7 @@ * Daniel Kurtz * Benson Leung * - * Copyright (C) 2011-2012 Cypress Semiconductor, Inc. + * Copyright (C) 2011-2014 Cypress Semiconductor, Inc. * Copyright (C) 2011-2012 Google, Inc. * * This file is subject to the terms and conditions of the GNU General Public @@ -14,461 +14,301 @@ * more details. */ +#include #include #include #include #include #include #include +#include #include +#include +#include +#include "cyapa.h" -/* APA trackpad firmware generation */ -#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ -#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" +#define CYAPA_ADAPTER_FUNC_NONE 0 +#define CYAPA_ADAPTER_FUNC_I2C1 +#define CYAPA_ADAPTER_FUNC_SMBUS 2 +#define CYAPA_ADAPTER_FUNC_BOTH 3 -/* commands for read/write registers of Cypress trackpad */ -#define CYAPA_CMD_SOFT_RESET 0x00 -#define CYAPA_CMD_POWER_MODE 0x01 -#define CYAPA_CMD_DEV_STATUS 0x02 -#define CYAPA_CMD_GROUP_DATA 0x03 -#define CYAPA_CMD_GROUP_CMD0x04 -#define CYAPA_CMD_GROUP_QUERY 0x05 -#define CYAPA_CMD_BL_STATUS0x06 -#define CYAPA_CMD_BL_HEAD 0x07 -#define CYAPA_CMD_BL_CMD 0x08 -#define CYAPA_CMD_BL_DATA 0x09 -#define CYAPA_CMD_BL_ALL 0x0a -#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b -#define CYAPA_CMD_BLK_HEAD 0x0c +#define CYAPA_DEBUGFS_READ_FW "read_fw" +#define CYAPA_DEBUGFS_RAW_DATA "raw_data" +#define CYAPA_FW_NAME "cyapa.bin" -/* report data start reg offset address. */ -#define DATA_REG_START_OFFSET 0x +const char unique_str[] = "CYTRA"; -#define BL_HEAD_OFFSET 0x00 -#define BL_DATA_OFFSET 0x10 -/* - * Operational Device Status Register - * - * bit 7: Valid interrupt source - * bit 6 - 4: Reserved - * bit 3 - 2: Power status - * bit 1 - 0: Device status - */ -#define REG_OP_STATUS 0x00 -#define OP_STATUS_SRC 0x80 -#define OP_STATUS_POWER 0x0c -#define OP_STATUS_DEV 0x03 -#define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) -/* - * Operational Finger Count/Button Flags Register - * - * bit 7 - 4: Number of touched finger - * bit 3: Valid data - * bit 2: Middle Physical Button - * bit 1: Right Physical Button - * bit 0: Left physical Button - */ -#define REG_OP_DATA1 0x01 -#define OP_DATA_VALID 0x08 -#define OP_DATA_MIDDLE_BTN 0x04 -#define OP_DATA_RIGHT_BTN 0x02 -#define OP_DATA_LEFT_BTN 0x01 -#define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ - OP_DATA_LEFT_BTN) +ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, + u8 *values) +{ + return i2c_smbus_read_i2c_block_data(cyapa->client, reg, len, values); +} -/* - * Bootloader Status Register - * - * bit 7: Busy - * bit 6 - 5: Reserved - * bit 4: Bootloader running - * bit 3 - 1: Reserved - * bit 0: Check
[PATCH V5 07/14] input: cyapa: add gen3 trackpad device firmware update function support
Add firmware image update function supported for gen3 trackpad device, which its function is supplied through cyapa core update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 290 +++ 1 file changed, 290 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 0f1537c..f753a94 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -412,6 +412,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) { + data_reporting_started = false; + 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 reset. */ + 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; @@ -472,6 +544,218 @@ 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], +
[PATCH V5 06/14] input: cyapa: add gen3 trackpad device basic functions support
Based on the cyapa core, add the gen3 trackpad device's basic functions supported, so gen3 trackpad device can work with kernel input system. The basic function is absolutely same as previous cyapa driver only support gen3 trackpad device. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile | 2 +- drivers/input/mouse/cyapa.c | 96 - drivers/input/mouse/cyapa.h | 1 + drivers/input/mouse/cyapa_gen3.c | 783 +++ 4 files changed, 880 insertions(+), 2 deletions(-) create mode 100644 drivers/input/mouse/cyapa_gen3.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 8608eb7..63b42e0 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -35,4 +35,4 @@ psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT)+= trackpoint.o psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o psmouse-$(CONFIG_MOUSE_PS2_CYPRESS)+= cypress_ps2.o -cyapatp-y := cyapa.o +cyapatp-y := cyapa.o cyapa_gen3.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index d588938..0463505 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -116,6 +116,15 @@ ssize_t cyapa_i2c_write(struct cyapa *cyapa, u8 reg, void cyapa_default_irq_handler(struct cyapa *cyapa) { + bool cont; + + /* Interrupt triggerred by command response in detecting. */ + cont = true; + if (cyapa_gen3_ops.irq_cmd_handler) + cont = cyapa_gen3_ops.irq_cmd_handler(cyapa); + if (!cont) + return; + /* * Do redetecting when device states is still unknown and * interrupt envent is received from device. @@ -255,6 +264,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return ret; switch (cyapa->gen) { + case CYAPA_GEN3: + cyapa->ops = &cyapa_gen3_ops; + break; default: cyapa->ops = &cyapa_default_ops; cyapa->gen = CYAPA_GEN_UNKNOWN; @@ -317,9 +329,85 @@ out: */ static int cyapa_get_state(struct cyapa *cyapa) { + int ret; + u8 status[BL_STATUS_SIZE]; + u8 cmd[32]; + /* The i2c address of gen4 and gen5 trackpad device must be even. */ + bool even_addr = ((cyapa->client->addr & 0x0001) == 0); + bool smbus = false; + int retries = 2; + cyapa->state = CYAPA_STATE_NO_DEVICE; - return -ENODEV; + /* +* Get trackpad status by reading 3 registers starting from 0. +* If the device is in the bootloader, this will be BL_HEAD. +* If the device is in operation mode, this will be the DATA regs. +* +*/ + ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE, + status); + + /* +* On smbus systems in OP mode, the i2c_reg_read will fail with +* -ETIMEDOUT. In this case, try again using the smbus equivalent +* command. This should return a BL_HEAD indicating CYAPA_STATE_OP. +*/ + if (cyapa->smbus && (ret == -ETIMEDOUT || ret == -ENXIO)) { + if (!even_addr) + ret = cyapa_read_block(cyapa, + CYAPA_CMD_BL_STATUS, status); + smbus = true; + } + if (ret != BL_STATUS_SIZE) + goto error; + + /* +* Detect trackpad protocol based on characristic registers and bits. +*/ + do { + cyapa->status[REG_OP_STATUS] = status[REG_OP_STATUS]; + cyapa->status[REG_BL_STATUS] = status[REG_BL_STATUS]; + cyapa->status[REG_BL_ERROR] = status[REG_BL_ERROR]; + + if (cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN3) { + ret = cyapa_gen3_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (ret == 0) + goto out_detected; + } + + /* +* Cannot detect communication protocol based on current +* charateristic registers and bits. +* So write error command to do further detection. +* this method only valid on I2C bus. +* for smbus interface, it won't have overwrite issue. +*/ + if (!smbus) { + cmd[0] = 0x00; + cmd[1] = 0x00; + ret = cyapa_i2c_write(cyapa, 0, 2, cmd); + if (ret) + goto error; + + msleep(50); + + ret = cyapa_i2c_read(cyapa, BL_HEAD_OFFSET, + BL_STATUS_SIZE, status); +
[PATCH V5 05/14] input: cyapa: add read firmware image and raw data interfaces in debugfs system
Add read_fw and raw_data debugfs interfaces for easier issues location and collection when report by user. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 221 1 file changed, 221 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 96f28e7..d588938 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -39,6 +39,8 @@ const char unique_str[] = "CYTRA"; +/* Global root node of the cyapa debugfs directory. */ +static struct dentry *cyapa_debugfs_root; ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, @@ -464,6 +466,205 @@ done: } /* + ** + * debugfs interface + ** +*/ +static int cyapa_debugfs_open(struct inode *inode, struct file *file) +{ + struct cyapa *cyapa = inode->i_private; + int ret; + + if (!cyapa) + return -ENODEV; + + ret = mutex_lock_interruptible(&cyapa->debugfs_mutex); + if (ret) + return ret; + + if (!get_device(&cyapa->client->dev)) { + ret = -ENODEV; + goto out; + } + + file->private_data = cyapa; + + if (cyapa->fw_image) { + ret = 0; + goto out; + } + + mutex_lock(&cyapa->state_sync_lock); + /* +* If firmware hasn't been read yet, read it all in one pass. +* Subsequent opens will reuse the data in this same buffer. +*/ + if (cyapa->ops->read_fw) + ret = cyapa->ops->read_fw(cyapa); + else + ret = -EPERM; + mutex_unlock(&cyapa->state_sync_lock); + + /* Redetect trackpad device states. */ + cyapa_detect_async(cyapa, 0); + +out: + mutex_unlock(&cyapa->debugfs_mutex); + return ret; +} + +static int cyapa_debugfs_release(struct inode *inode, struct file *file) +{ + struct cyapa *cyapa = file->private_data; + int ret; + + if (!cyapa) + return 0; + + ret = mutex_lock_interruptible(&cyapa->debugfs_mutex); + if (ret) + return ret; + file->private_data = NULL; + put_device(&cyapa->client->dev); + mutex_unlock(&cyapa->debugfs_mutex); + + return 0; +} + +/* Return some bytes from the buffered firmware image, starting from *ppos */ +static ssize_t cyapa_debugfs_read_fw(struct file *file, char __user *buffer, +size_t count, loff_t *ppos) +{ + struct cyapa *cyapa = file->private_data; + + if (!cyapa->fw_image) + return -EINVAL; + + if (*ppos >= cyapa->fw_image_size) + return 0; + + if (count + *ppos > cyapa->fw_image_size) + count = cyapa->fw_image_size - *ppos; + + if (copy_to_user(buffer, &cyapa->fw_image[*ppos], count)) + return -EFAULT; + + *ppos += count; + return count; +} + +static const struct file_operations cyapa_read_fw_fops = { + .open = cyapa_debugfs_open, + .release = cyapa_debugfs_release, + .read = cyapa_debugfs_read_fw +}; + +static int cyapa_debugfs_raw_data_open(struct inode *inode, struct file *file) +{ + struct cyapa *cyapa = inode->i_private; + int ret; + + if (!cyapa) + return -ENODEV; + + /* Start to be supported after Gen5 trackpad devices. */ + if (cyapa->gen < CYAPA_GEN5) + return -ENOTSUPP; + + ret = mutex_lock_interruptible(&cyapa->debugfs_mutex); + if (ret) + return ret; + + if (!get_device(&cyapa->client->dev)) { + ret = -ENODEV; + goto out; + } + + file->private_data = cyapa; + + mutex_lock(&cyapa->state_sync_lock); + if (cyapa->ops->read_raw_data) + ret = cyapa->ops->read_raw_data(cyapa); + else + ret = -EPERM; + mutex_unlock(&cyapa->state_sync_lock); +out: + mutex_unlock(&cyapa->debugfs_mutex); + return ret; +} + +static int cyapa_debugfs_raw_data_release(struct inode *inode, + struct file *file) +{ + struct cyapa *cyapa = file->private_data; + int ret; + + if (!cyapa) + return 0; + + ret = mutex_lock_interruptible(&cyapa->debugfs_mutex); + if (ret) + return ret; + file->private_data = NULL; + put_device(&cyapa->client->dev); + mutex_unlock(&cyapa->debugfs_mutex); + + return 0; +} + +/* Always return the sensors' latest raw data from trackpad device. */ +static
[PATCH V5 08/14] input: cyapa: add gen3 trackpad device baseline and calibrate functions support
Add report baseline and force calibrate functions supported for gen3 trackpad device, which these functions are supplied through cyapa core baseline and calibrate interfaces. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 135 +++ 1 file changed, 135 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index f753a94..1f4668a 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -756,6 +756,138 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int tries = 20; /* max recalibration timeout 2s. */ + int ret; + + data_reporting_started = false; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_RECALIBRATION_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send calibrate command. ret = %d\n", + ret); + goto out; + } + + do { + /* +* For this recalibration, the max time will not exceed 2s. +* The average time is approximately 500 - 700 ms, and we +* will check the status every 100 - 200ms. +*/ + usleep_range(10, 20); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Failed to calibrate. Timeout.\n"); + ret = -ETIMEDOUT; + goto out; + } + dev_dbg(dev, "Calibration successful.\n"); + +out: + data_reporting_started = true; + return ret < 0 ? ret : count; +} + +static ssize_t cyapa_gen3_show_baseline(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int max_baseline, min_baseline; + int tries = 3; + int ret; + + data_reporting_started = false; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_REPORT_BASELINE_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send report baseline command. %d\n", + ret); + goto out; + } + + do { + usleep_range(1, 2); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Device timed out going to Normal state.\n"); + ret = -ETIMEDOUT; + goto out; + } + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MAX_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read max baseline. err = %d\n", ret); + goto out; + } + max_baseline = ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MIN_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read min baseline. err = %d\n", ret); + goto out; + }
[PATCH V5 02/14] input: cyapa: add cyapa driver power management interfaces support
Add suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 85 + 1 file changed, 85 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 3edd23e..d61ccbc 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -427,6 +427,82 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode) : (encoded_time - 5) * 20; } +#ifdef CONFIG_PM_SLEEP +static ssize_t cyapa_show_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd = cyapa->suspend_power_mode; + u16 sleep_time; + int len; + + mutex_lock(&cyapa->state_sync_lock); + pwr_cmd = cyapa->suspend_power_mode; + sleep_time = cyapa->suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (pwr_cmd == PWR_MODE_BTN_ONLY) + len = scnprintf(buf, PAGE_SIZE, "%s\n", BTN_ONLY_MODE_NAME); + else if (pwr_cmd == PWR_MODE_OFF) + len = scnprintf(buf, PAGE_SIZE, "%s\n", OFF_MODE_NAME); + else { + if (cyapa->gen == CYAPA_GEN3) + sleep_time = cyapa_pwr_cmd_to_sleep_time(pwr_cmd); + len = scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); + } + + return len; +} + +static u16 cyapa_clamp_sleep_time(u16 sleep_time) +{ + if (sleep_time > 1000) + sleep_time = 1000; + return sleep_time; +} + +static ssize_t cyapa_update_suspend_scanrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 sleep_time; + + mutex_lock(&cyapa->state_sync_lock); + + if (sysfs_streq(buf, BTN_ONLY_MODE_NAME)) + cyapa->suspend_power_mode = PWR_MODE_BTN_ONLY; + else if (sysfs_streq(buf, OFF_MODE_NAME)) + cyapa->suspend_power_mode = PWR_MODE_OFF; + else if (!kstrtou16(buf, 10, &sleep_time)) { + cyapa->suspend_sleep_time = cyapa_clamp_sleep_time(sleep_time); + cyapa->suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time); + } else + count = 0; + + mutex_unlock(&cyapa->state_sync_lock); + if (!count) + dev_err(dev, "invalid suspend scanrate ms parameters\n"); + return count ? count : -EINVAL; +} + +static DEVICE_ATTR(suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_suspend_scanrate, + cyapa_update_suspend_scanrate); + +static struct attribute *cyapa_power_wakeup_entries[] = { + &dev_attr_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_wakeup_group = { + .name = power_group_name, + .attrs = cyapa_power_wakeup_entries, +}; +#endif /* CONFIG_PM_SLEEP */ + void cyapa_detect_async(void *data, async_cookie_t cookie) { struct cyapa *cyapa = (struct cyapa *)data; @@ -521,6 +597,12 @@ static int cyapa_probe(struct i2c_client *client, goto err_uninit_tp_modules; } +#ifdef CONFIG_PM_SLEEP + if (device_can_wakeup(dev) && + sysfs_merge_group(&client->dev.kobj, &cyapa_power_wakeup_group)) + dev_warn(dev, "error creating wakeup power entries.\n"); +#endif /* CONFIG_PM_SLEEP */ + async_schedule(cyapa_detect_and_start, cyapa); return 0; @@ -543,6 +625,9 @@ static int cyapa_remove(struct i2c_client *client) cyapa->removed = true; mutex_unlock(&cyapa->state_sync_lock); +#ifdef CONFIG_PM_SLEEP + sysfs_unmerge_group(&client->dev.kobj, &cyapa_power_wakeup_group); +#endif free_irq(cyapa->irq, cyapa); input_unregister_device(cyapa->input); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V5 0/14] input: cyapa: re-architecture driver to support multi-trackpads in one driver
This v5 patch set is updated based on cyapa v4 patches, it has below updates: 1) Uses get_device()/put_device() instead of kobject_get()/kobject_put(); 2) Fix memories freed before debugfs entries issue; 3) Make cyapa_debugs_root valid in driver module level in module_init()/moudle_exit() ; 4) Fix i2c_transfer() may return partial transfer issues. 5) Add cyapa->removed flag to avoid detecting thread may still running when driver module is removed. 6) Fix the meanings of some comments and return error code not clear issue. This patch set is aimed to re-architecture the cyapa driver to support old gen3 trackpad device and new gen5 trackpad device in one cyapa driver for easily productions support based on customers' requirements, and add sysfs functions and interfaces supported that required by users and customers. Because the earlier gen3 and the latest gen5 trackpad devies using two different chipsets, and have different protocol and interfaces. If supported these two trackpad devices in two different drivers, then it will be difficult to manage productions and later firmware updates. it will cause customer don't know which one to use and update because these two trackpad devices have been used and integrated in same one productions at a time, so must to support these two trackpad devices in same on driver. The new architecture is made of: cyapa.c - the core of the architecture, supply interfaces and functions to system and read trackpad devices. cyapa_gen3.c - functions support for gen3 trackpad devices, cyapa_gen5.c - functions support for gen5 trackpad devices. Beside this introduction patch, it has 14 patches listed as below. For these patches each one is patched based on previous one. patch 1/14: re-architecture cyapa driver with core functions, and applying the device detecting function in async thread to speed up system boot time. patch 2/14: add cyapa driver power management interfaces support. patch 3/14: add cyapa driver runtime power management interfaces support. patch 4/14: add cyapa key function interfaces in sysfs system. Including read firmware version, get production ID, read baseline, re-calibrate trackpad baselines and do trackpad firmware update. patch 5/14: add read firmware image and read raw trackpad device' sensors' raw data interface in debugfs system. patch 6/14: add gen3 trackpad device basic functions support. patch 7/14: add gen3 trackpad device firmware update function support. patch 8/14: add gen3 trackpad device report baseline and do force re-calibrate functions support. patch 9/14: add gen3 trackpad device read firmware image function support. patch 10/14: add gen5 trackpad device basic functions support. patch 11/14: add gen5 trackpad device firmware update function support. patch 12/14: add gen5 trackpad device report baseline and do force re-calibrate functions support. patch 13/14: add gen5 trackpad device read firmware image and report sensors' raw data values functions support. patch 14/14: add function to monitor LID close event to off trackpad device. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V5 03/14] input: cyapa: add cyapa driver runtime power management interfaces support
Add runtime_suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the runtime power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 142 1 file changed, 142 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index d61ccbc..eb3a5a8 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -271,9 +271,16 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) static irqreturn_t cyapa_irq(int irq, void *dev_id) { struct cyapa *cyapa = dev_id; + struct device *dev = &cyapa->client->dev; struct input_dev *input = cyapa->input; bool cont; + pm_runtime_get_sync(dev); + pm_runtime_mark_last_busy(dev); + + if (device_may_wakeup(dev)) + pm_wakeup_event(dev, 0); + /* Interrupt event maybe cuased by host command to trackpad device. */ cont = true; if (cyapa->ops->irq_cmd_handler) @@ -297,6 +304,8 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) mutex_unlock(&cyapa->state_sync_lock); } + + pm_runtime_put_sync_autosuspend(dev); out: return IRQ_HANDLED; } @@ -503,6 +512,86 @@ static const struct attribute_group cyapa_power_wakeup_group = { }; #endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_PM_RUNTIME +static ssize_t cyapa_show_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd; + u16 sleep_time; + + mutex_lock(&cyapa->state_sync_lock); + pwr_cmd = cyapa->runtime_suspend_power_mode; + sleep_time = cyapa->runtime_suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (cyapa->gen == CYAPA_GEN3) + return scnprintf(buf, PAGE_SIZE, "%u\n", + cyapa_pwr_cmd_to_sleep_time(pwr_cmd)); + return scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); +} + +static ssize_t cyapa_update_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 time; + + if (buf == NULL || count == 0 || kstrtou16(buf, 10, &time)) { + dev_err(dev, "invalid runtime suspend scanrate ms parameter\n"); + return -EINVAL; + } + + /* +* When the suspend scanrate is changed, pm_runtime_get to resume +* a potentially suspended device, update to the new pwr_cmd +* and then pm_runtime_put to suspend into the new power mode. +*/ + pm_runtime_get_sync(dev); + mutex_lock(&cyapa->state_sync_lock); + cyapa->runtime_suspend_sleep_time = cyapa_clamp_sleep_time(time); + cyapa->runtime_suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time); + mutex_unlock(&cyapa->state_sync_lock); + pm_runtime_put_sync_autosuspend(dev); + + return count; +} + +static DEVICE_ATTR(runtime_suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_rt_suspend_scanrate, + cyapa_update_rt_suspend_scanrate); + +static struct attribute *cyapa_power_runtime_entries[] = { + &dev_attr_runtime_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_runtime_group = { + .name = power_group_name, + .attrs = cyapa_power_runtime_entries, +}; + +static void cyapa_start_runtime(struct cyapa *cyapa) +{ + struct device *dev = &cyapa->client->dev; + + cyapa->runtime_suspend_power_mode = PWR_MODE_IDLE; + cyapa->runtime_suspend_sleep_time = + cyapa_pwr_cmd_to_sleep_time(cyapa->runtime_suspend_power_mode); + if (sysfs_merge_group(&dev->kobj, &cyapa_power_runtime_group)) + dev_warn(dev, "error creating wakeup runtime entries.\n"); + pm_runtime_set_active(dev); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_DELAY); + pm_runtime_enable(dev); +} +#else +static void cyapa_start_runtime(struct cyapa *cyapa) {} +#endif /* CONFIG_PM_RUNTIME */ + void cyapa_detect_async(void *data, async_cookie_t cookie) { struct cyapa *cyapa = (struct cyapa *)data; @@ -521,7 +610,11 @@ void cyapa_detect_async(void *data, async_cookie_t cookie) static void cyapa_detect_and_start(void *data, async_cookie_t cookie) { + struct cyapa
[PATCH V5 09/14] input: cyapa: add gen3 trackpad device read firmware image function support
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 --- drivers/input/mouse/cyapa_gen3.c | 73 1 file changed, 73 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 1f4668a..6bcc25b 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -710,6 +710,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> + * + * <0xff> - every command starts with 0xff + * - the read command value is 0x3c + * - read commands include an 8-byte key: { 00 01 02 03 04 05 06 07 } + *- 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) @@ -756,6 +786,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) @@ -1198,6 +1269,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, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH V5 12/14] input: cyapa: add gen5 trackpad device baseline and calibrate functions support
Add report baseline and force calibrate functions supported for gen5 trackpad device, which these functions are supplied through cyapa core baseline and calibrate interfaces. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 670 +++ 1 file changed, 670 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 0c84b1b..452cb5d 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1540,6 +1540,673 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, return ret; } +static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) +{ + u8 cmd[7] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 }; + u8 resp_data[6]; + int resp_len; + int ret; + + /* Try to dump all bufferred data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = 6; + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, 7, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data); + if (ret || !VALID_CMD_RESP_HEADER(resp_data, 0x04)) + return -EINVAL; + + /* Try to dump all bufferred data when resuming scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) +{ + u8 cmd[7] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 }; + u8 resp_data[6]; + int resp_len; + int ret; + + /* Try to dump all bufferred data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = 6; + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, 7, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data); + if (ret || !VALID_CMD_RESP_HEADER(resp_data, 0x03)) + return -EINVAL; + + /* Try to dump all bufferred data when suspending scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa, + u8 calibrate_sensing_mode_type) +{ + int ret; + u8 cmd[8]; + u8 resp_data[6]; + int resp_len; + + /* Try to dump all bufferred data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + cmd[0] = 0x04; + cmd[1] = 0x00; + cmd[2] = 0x06; + cmd[3] = 0x00; + cmd[4] = GEN5_APP_CMD_REPORT_ID; + cmd[5] = 0x00; + cmd[6] = GEN5_CMD_CALIBRATE; + cmd[7] = calibrate_sensing_mode_type; + resp_len = sizeof(resp_data); + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 5000, cyapa_gen5_sort_tsg_pip_app_resp_data); + if (ret || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_CALIBRATE) || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return ret < 0 ? ret : -EAGAIN; + + return 0; +} + +static ssize_t cyapa_gen5_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int ret, calibrate_ret; + + /* 1. Suspend Scanning*/ + ret = cyapa_gen5_suspend_scanning(cyapa); + if (ret) + return ret; + + /* 2. Do mutual capacitance fine calibrate. */ + calibrate_ret = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_MUTUAL_CAP_FINE); + if (calibrate_ret) + goto resume_scanning; + + /* 3. Do self capacitance calibrate. */ + calibrate_ret = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_SELF_CAP); + if (calibrate_ret) + goto resume_scanning; + +resume_scanning: + /* 4. Resume Scanning*/ + ret = cyapa_gen5_resume_scanning(cyapa); + if (ret || calibrate_ret) + return ret ? ret : calibrate_ret; + + return count; +} + +static s32 two_complement_to_s32(s32 value, int num_bits) +{ + if (value >> (num_bits - 1)) + value |= -1 << num_bits; + return value; +} + +static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len) +{ + int data_size; + bool big_endian; + bool unsigned_type; + s32 value; + + data_size = (data_format & 0x07); + big_endian = ((data_format & 0x10) == 0x00); + unsigned_type = ((data_format & 0x20) == 0x00); + + if (buf_len < data_size) + return 0; + + switch (data_siz
RE: [BUG] [PATCH] next: cyapa: fix inop touchpad after resume on Acer C720
More info: I did all testings based on kernel 3.14.0 on Acer C70. Thanks, Dudley > -Original Message- > From: Dudley Du > Sent: 2014?11?26? 14:01 > To: 'Jeremiah Mahler' > Cc: 'linux-kernel@vger.kernel.org' > Subject: RE: [BUG] [PATCH] next: cyapa: fix inop touchpad after resume on Acer > C720 > > Hi Jermiah, > > Does your code merged from chromiumos gerrit? > If so, the patch you used seems very old, because the log shown the cyapa > driver > module name still be "cyapa", and it has already been changed to "cyapatp" > for log > time. > Currently, I have already removed all old pathces from the gerrit system, now > only > v11 pathces existing in gerrit system. > Could you please try to refetch again, > or > could you try the v11 patches that from > http://patchwork.kernel.org/bundle/dudlx/input_cyapa_v11/ > or > The attached zip file contians the v11 patches for chromiumos projects, same > as > currently existing in gerrit system. > Besides the first and the latest patches which are specifical for chromionos, > the > reset pathces are exactly same as the cyapa v11 pathces that submitted to this > kernel commuinty. > > Thanks, > Dudley > > > -Original Message- > > From: Jeremiah Mahler [mailto:jmmah...@gmail.com] > > Sent: 2014?11?25? 18:07 > > To: Dudley Du > > Cc: linux-kernel@vger.kernel.org > > Subject: [BUG] [PATCH] next: cyapa: fix inop touchpad after resume on Acer > > C720 > > > > On an Acer C720 running linux-next (20141124) the touchpad will become > > inoperative after a resume. Reloading the cyapa driver restores normal > > operation. > > > > The following trace appeared in dmesg after a resume. > > > > [ 21.803878] [ cut here ] > > [ 21.803886] WARNING: CPU: 0 PID: 901 at kernel/irq/manage.c:444 > > enable_irq+0x3a/0x80() > > [ 21.803886] Unbalanced enable for IRQ 0 > > [ 21.803927] Modules linked in: binfmt_misc bnep ecb ath3k btusb > bluetooth > > uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_core v4l2_common > > videodev media nfsd auth_rpcgss oid_registry nfs_acl nfs lockd grace fscache > > sunrpc arc4 ath9k snd_hda_codec_hdmi ath9k_common ath9k_hw ath > > tpm_infineon mac80211 i915 joydev x86_pkg_temp_thermal iTCO_wdt > > intel_powerclamp cyapa iTCO_vendor_support intel_rapl iosf_mbi coretemp > > kvm_intel kvm cfg80211 snd_hda_codec_realtek snd_hda_codec_generic > > chromeos_laptop crct10dif_pclmul crc32_pclmul i2c_algo_bit crc32c_intel > > snd_hda_intel drm_kms_helper xhci_pci xhci_hcd ghash_clmulni_intel > > snd_hda_controller snd_hda_codec cryptd rfkill drm usbcore evdev pcspkr > > snd_hwdep serio_raw snd_pcm i2c_i801 shpchp snd_timer usb_common lpc_ich > > snd tpm_tis mfd_core video i2c_designware_pci > > [ 21.803941] tpm battery ac soundcore i2c_designware_platform > > i2c_designware_core i2c_core processor button fuse autofs4 ext4 crc16 > > mbcache > > jbd2 sg sd_mod ahci libahci libata scsi_mod fan thermal thermal_sys > > sdhci_acpi > > sdhci mmc_core > > [ 21.803945] CPU: 0 PID: 901 Comm: systemd-sleep Not tainted > > 3.18.0-rc5-next-20141121 #50 > > [ 21.803946] Hardware name: Acer Peppy, BIOS 04/30/2014 > > [ 21.803949] 81725091 81535c6c > > 8800740cbc78 > > [ 21.803951] 81069f61 880100405400 > > 88006c9c1c20 > > [ 21.803953] 88006ae73220 0010 81069fda > > 8171bbb8 > > [ 21.803953] Call Trace: > > [ 21.803959] [] ? dump_stack+0x40/0x50 > > [ 21.803964] [] ? warn_slowpath_common+0x81/0xb0 > > [ 21.803967] [] ? warn_slowpath_fmt+0x4a/0x50 > > [ 21.803969] [] ? __irq_get_desc_lock+0x52/0x90 > > [ 21.803971] [] ? enable_irq+0x3a/0x80 > > [ 21.803976] [] ? cyapa_resume+0x85/0xb0 [cyapa] > > [ 21.803984] [] ? i2c_device_pm_thaw+0x40/0x40 > > [i2c_core] > > [ 21.803988] [] ? dpm_run_callback+0x4a/0x100 > > [ 21.803991] [] ? device_resume+0xd6/0x210 > > [ 21.803994] [] ? dpm_resume+0x109/0x2c0 > > [ 21.803997] [] ? dpm_resume_end+0xd/0x20 > > [ 21.804000] [] ? > > suspend_devices_and_enter+0x137/0x630 > > [ 21.804003] [] ? pm_suspend+0x352/0x3d0 > > [ 21.804005] [] ? state_store+0x76/0xf0 > > [ 21.804010] [] ? kernfs_fop_write+0x12c/0x180 > > [ 21.804013] [] ? vfs_write+0xb2/0x1f0 > > [ 21.804015] [] ? SyS_write+0x42/0xb0 > > [ 21.804018] [] ? syste
RE: [BUG] [PATCH] next: cyapa: fix inop touchpad after resume on Acer C720
Jeremiah, I didn't make the special patch for the linux-next before, so I don't know why this patch is there and have issue. Based on current code in the linux-next, I made below patch to fix this issue. Could you please try again with attached patch fix. Thanks, Dudley > -Original Message- > From: Jeremiah Mahler [mailto:jmmah...@gmail.com] > Sent: 2014?11?27? 4:03 > To: Dudley Du > Cc: linux-kernel@vger.kernel.org > Subject: Re: [BUG] [PATCH] next: cyapa: fix inop touchpad after resume on Acer > C720 > > Dudley, > > On Wed, Nov 26, 2014 at 06:16:00AM +, Dudley Du wrote: > > More info: I did all testings based on kernel 3.14.0 on Acer C70. > > > > I am testing with linux-next 3.18-rc6 on an Acer C720. > > http://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/ > > > Thanks, > > Dudley > > > [] > > -- > - Jeremiah Mahler >From bb717b1c1525ef6b889f0ef735d920eed9e76e72 Mon Sep 17 00:00:00 2001 From: Dudley Du Date: Thu, 27 Nov 2014 13:35:09 +0800 Subject: [PATCH] input: cyapa: fix irq error issue in cyapa_resume To: dmitry.torok...@gmail.com, jmmah...@gmail.com Cc: ble...@google.com, linux-in...@vger.kernel.org This patch is aimed to fix the irq error happened on cyapa_resume when doing suspend/resume testing. The root cause of this issue is that the cyapa->irq has been removed but still used in the driver. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index c84a9eb..caaba7b 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -938,7 +938,7 @@ static int __maybe_unused cyapa_suspend(struct device *dev) power_mode, error); if (device_may_wakeup(dev)) - cyapa->irq_wake = (enable_irq_wake(cyapa->irq) == 0); + cyapa->irq_wake = (enable_irq_wake(cyapa->client->irq) == 0); mutex_unlock(&input->mutex); @@ -956,7 +956,7 @@ static int __maybe_unused cyapa_resume(struct device *dev) mutex_lock(&input->mutex); if (device_may_wakeup(dev) && cyapa->irq_wake) - disable_irq_wake(cyapa->irq); + disable_irq_wake(cyapa->client->irq); power_mode = input->users ? PWR_MODE_FULL_ACTIVE : PWR_MODE_OFF; error = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); @@ -964,7 +964,7 @@ static int __maybe_unused cyapa_resume(struct device *dev) dev_warn(dev, "resume: set power mode to %d failed: %d\n", power_mode, error); - enable_irq(cyapa->irq); + enable_irq(cyapa->client->irq); mutex_unlock(&input->mutex); -- 1.9.1 input-cyapa-fix-irq-error-issue-in-cyapa_resume.patch Description: Binary data
RE: [PATCH v15 09/12] input: cyapa: add gen5 trackpad device firmware update function support
> -Original Message- > From: linux-input-ow...@vger.kernel.org > [mailto:linux-input-ow...@vger.kernel.org] On Behalf Of Benson Leung > Sent: 2014年12月17日 4:25 > To: Jeremiah Mahler; Dudley Du; Dmitry Torokhov; Henrik Rydberg; Benson Leung; > linux-in...@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH v15 09/12] input: cyapa: add gen5 trackpad device firmware > update function support > > On Tue, Dec 16, 2014 at 5:56 AM, Jeremiah Mahler wrote: > > On Mon, Dec 15, 2014 at 02:23:20PM +0800, Dudley Du wrote: > >> Add firmware image update function supported for gen5 trackpad device, > >> it can be used through sysfs update_fw interface. > >> TEST=test on Chromebooks. > >> > >> Signed-off-by: Dudley Du > >> --- > >> drivers/input/mouse/Kconfig | 1 + > >> drivers/input/mouse/cyapa_gen5.c | 292 > ++- > >> 2 files changed, 292 insertions(+), 1 deletion(-) > >> > >> diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig > >> index d8b46b0..728490e 100644 > >> --- a/drivers/input/mouse/Kconfig > >> +++ b/drivers/input/mouse/Kconfig > >> @@ -206,6 +206,7 @@ config MOUSE_BCM5974 > >> config MOUSE_CYAPA > >> tristate "Cypress APA I2C Trackpad support" > >> depends on I2C > >> + select CRC_ITU_T > >> help > > > > Just found out that if I2C_DESIGNWARE_PCI isn't enabled the touchpad > > won't work. Verify this on your machines. Then perhaps add a depends > > for I2C_DESIGNWARE_PCI instead of I2C since it would include the former. > > This isn't strictly true on all devices, though. This is true on > DESIGNWARE_PCI based devices like the Acer C720 and the HP Chromebook > 14, but on other platforms that use Cypress trackpads, such as ARM > platforms like the Samsung Chromebook Series 3 DESIGNWARE_PCI is not > required, and will just result in a driver that's never used being > built. > > The specific I2C bus that's being used here shouldn't matter here... > that's more of a platform issue. In the case with Chromebooks, it > might make sense to change drivers/platform/chrome/Kconfig so that > CHROMEOS_LAPTOP depends on I2C_DESIGNWARE_PCI, maybe. > Thank you all for the information. Then I won't change this depending on I2C. > -- > Benson Leung > Software Engineer, Chrome OS > Google Inc. > ble...@google.com > -- > To unsubscribe from this list: send the line "unsubscribe linux-input" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html 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. N�r��yb�X��ǧv�^�){.n�+{zX����ܨ}���Ơz�&j:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a��� 0��h���i
[PATCH v16 01/12] input: cyapa: re-design driver to support
In order to support multiple different chipsets and communication protocols trackpad devices in one cyapa driver, the new cyapa driver is re-designed with one cyapa driver core and multiple device specific functions component. The cyapa driver core is contained in this patch, it supplies basic functions that working with kernel and input subsystem, and also supplies the interfaces that the specific devices' component can connect and work together with as one driver. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |3 +- drivers/input/mouse/cyapa.c | 1047 ++ drivers/input/mouse/cyapa.h | 307 +++ drivers/input/mouse/cyapa_gen3.c | 801 + 4 files changed, 1492 insertions(+), 666 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h create mode 100644 drivers/input/mouse/cyapa_gen3.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 560003d..8bd950d 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974)+= bcm5974.o -obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o @@ -24,6 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o +cyapatp-objs := cyapa.o cyapa_gen3.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 1bece8c..ae1df15 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -20,408 +20,100 @@ #include #include #include +#include #include +#include +#include "cyapa.h" -/* APA trackpad firmware generation */ -#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ - -#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" - -/* commands for read/write registers of Cypress trackpad */ -#define CYAPA_CMD_SOFT_RESET 0x00 -#define CYAPA_CMD_POWER_MODE 0x01 -#define CYAPA_CMD_DEV_STATUS 0x02 -#define CYAPA_CMD_GROUP_DATA 0x03 -#define CYAPA_CMD_GROUP_CMD0x04 -#define CYAPA_CMD_GROUP_QUERY 0x05 -#define CYAPA_CMD_BL_STATUS0x06 -#define CYAPA_CMD_BL_HEAD 0x07 -#define CYAPA_CMD_BL_CMD 0x08 -#define CYAPA_CMD_BL_DATA 0x09 -#define CYAPA_CMD_BL_ALL 0x0a -#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b -#define CYAPA_CMD_BLK_HEAD 0x0c - -/* report data start reg offset address. */ -#define DATA_REG_START_OFFSET 0x - -#define BL_HEAD_OFFSET 0x00 -#define BL_DATA_OFFSET 0x10 - -/* - * Operational Device Status Register - * - * bit 7: Valid interrupt source - * bit 6 - 4: Reserved - * bit 3 - 2: Power status - * bit 1 - 0: Device status - */ -#define REG_OP_STATUS 0x00 -#define OP_STATUS_SRC 0x80 -#define OP_STATUS_POWER 0x0c -#define OP_STATUS_DEV 0x03 -#define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) - -/* - * Operational Finger Count/Button Flags Register - * - * bit 7 - 4: Number of touched finger - * bit 3: Valid data - * bit 2: Middle Physical Button - * bit 1: Right Physical Button - * bit 0: Left physical Button - */ -#define REG_OP_DATA1 0x01 -#define OP_DATA_VALID 0x08 -#define OP_DATA_MIDDLE_BTN 0x04 -#define OP_DATA_RIGHT_BTN 0x02 -#define OP_DATA_LEFT_BTN 0x01 -#define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ - OP_DATA_LEFT_BTN) - -/* - * Bootloader Status Register - * - * bit 7: Busy - * bit 6 - 5: Reserved - * bit 4: Bootloader running - * bit 3 - 1: Reserved - * bit 0: Checksum valid - */ -#define REG_BL_STATUS0x01 -#define BL_STATUS_BUSY 0x80 -#define BL_STATUS_RUNNING0x10 -#define BL_STATUS_DATA_VALID 0x08 -#define BL_STATUS_CSUM_VALID 0x01 - -/* - * Bootloader Error Register - * - * bit 7: Invalid - * bit 6: Invalid security key - * bit 5: Bootloading - * bit 4: Command checksum - * bit 3: Flash protection error - * bit 2: Flash checksum error - * bit 1 - 0: Reserved - */ -#define REG_BL_ERROR 0x02 -#define BL_ERROR_INVALID 0x80 -#define BL_ERROR_INVALID_KEY 0x40 -#define BL_ERROR_BOOTLOADING 0x20 -#define BL_ERROR_CMD_CSUM0x10 -#define BL_ERROR_FLASH_PROT 0x08 -#define BL_ERROR_FLASH_CSUM 0x04 - -#define BL_STATUS_SIZE 3 /* length of bootloader status registers */ -#define BLK_HEAD_BYTES 32 - -#define PRODUCT_ID_SIZE 16 -#d
[PATCH v16 10/12] input: cyapa: add gen5 trackpad device read baseline
Add read baseline function supported for gen5 trackpad device, it can be used through sysfs baseline interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.h | 2 + drivers/input/mouse/cyapa_gen5.c | 640 +++ 2 files changed, 642 insertions(+) diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index 922a473..e5de0b2 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -276,6 +276,8 @@ struct cyapa { u8 y_origin; /* Y Axis Origin: 0 = top; 1 = bottom. */ int electrodes_x; /* Number of electrodes on the X Axis*/ int electrodes_y; /* Number of electrodes on the Y Axis*/ + int electrodes_rx; /* Number of Rx electrodes */ + int aligned_electrodes_rx; /* 4 aligned */ int max_z; /* diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 840f5d6..2b800e3 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -363,6 +363,12 @@ struct gen5_app_get_parameter_data { u8 parameter_id; } __packed; +struct gen5_retrieve_panel_scan_data { + __le16 read_offset; + __le16 read_elements; + u8 data_id; +} __packed; + /* Variables to record latest gen5 trackpad power states. */ #define GEN5_DEV_SET_PWR_STATE(cyapa, s) ((cyapa)->dev_pwr_mode = (s)) #define GEN5_DEV_GET_PWR_STATE(cyapa) ((cyapa)->dev_pwr_mode) @@ -1659,6 +1665,638 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, return 0; } +static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) +{ + u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 }; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x04)) + return -EINVAL; + + /* Try to dump all buffered data when resuming scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) +{ + u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 }; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x03)) + return -EINVAL; + + /* Try to dump all buffered data when suspending scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static s32 twos_complement_to_s32(s32 value, int num_bits) +{ + if (value >> (num_bits - 1)) + value |= -1 << num_bits; + return value; +} + +static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len) +{ + int data_size; + bool big_endian; + bool unsigned_type; + s32 value; + + data_size = (data_format & 0x07); + big_endian = ((data_format & 0x10) == 0x00); + unsigned_type = ((data_format & 0x20) == 0x00); + + if (buf_len < data_size) + return 0; + + switch (data_size) { + case 1: + value = buf[0]; + break; + case 2: + if (big_endian) + value = get_unaligned_be16(buf); + else + value = get_unaligned_le16(buf); + break; + case 4: + if (big_endian) + value = get_unaligned_be32(buf); + else + value = get_unaligned_le32(buf); + break; + default: + /* Should not happen, just as default case here. */ + value = 0; + break; + } + + if (!unsigned_type) + value = twos_complement_to_s32(value, data_size * 8); + + return value; +} + +static void cyapa_gen5_guess_electrodes(struct cyapa *cyapa, + int *electrodes_rx, int *electrodes_tx) +{ + if (cyapa->electrodes_rx != 0) { + *electrodes_rx = cyapa->electrodes_rx; + *electrodes_tx = (cyapa->electrodes_x == *electrodes_rx) ? + cyapa-&
[PATCH v16 12/12] input: cyapa: add acpi device id support
Add acpi device tree support. acpi device id "CYAP" is for old gen3 trackpad devices. acpi device id "CYAP0001" is for new gen5 trackpad devices. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 406f38b..62ef19a 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "cyapa.h" @@ -1315,11 +1316,23 @@ static const struct i2c_device_id cyapa_id_table[] = { }; MODULE_DEVICE_TABLE(i2c, cyapa_id_table); +#ifdef CONFIG_ACPI +static const struct acpi_device_id cyapa_acpi_id[] = { + { "CYAP", 0 }, /* Gen3 trackpad with 0x67 I2C address. */ + { "CYAP0001", 0 }, /* Gen5 trackpad with 0x24 I2C address. */ + { } +}; +MODULE_DEVICE_TABLE(acpi, cyapa_acpi_id); +#endif + static struct i2c_driver cyapa_driver = { .driver = { .name = "cyapa", .owner = THIS_MODULE, .pm = &cyapa_pm_ops, +#ifdef CONFIG_ACPI + .acpi_match_table = ACPI_PTR(cyapa_acpi_id), +#endif }, .probe = cyapa_probe, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v16 09/12] input: cyapa: add gen5 trackpad device firmware update
Add firmware image update function supported for gen5 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Kconfig | 1 + drivers/input/mouse/cyapa_gen5.c | 385 +++ 2 files changed, 386 insertions(+) diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index d8b46b0..728490e 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -206,6 +206,7 @@ config MOUSE_BCM5974 config MOUSE_CYAPA tristate "Cypress APA I2C Trackpad support" depends on I2C + select CRC_ITU_T help This driver adds support for Cypress All Points Addressable (APA) I2C Trackpads, including the ones used in 2012 Samsung Chromebooks. diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 2ce0149..840f5d6 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "cyapa.h" @@ -264,6 +265,79 @@ struct cyapa_gen5_report_data { struct cyapa_gen5_touch_record touch_records[10]; } __packed; +struct cyapa_tsg_bin_image_head { + u8 head_size; /* Unit: bytes, including itself. */ + u8 ttda_driver_major_version; /* Reserved as 0. */ + u8 ttda_driver_minor_version; /* Reserved as 0. */ + u8 fw_major_version; + u8 fw_minor_version; + u8 fw_revision_control_number[8]; +} __packed; + +struct cyapa_tsg_bin_image_data_record { + u8 flash_array_id; + __be16 row_number; + /* The number of bytes of flash data contained in this record. */ + __be16 record_len; + /* The flash program data. */ + u8 record_data[CYAPA_TSG_FW_ROW_SIZE]; +} __packed; + +struct cyapa_tsg_bin_image { + struct cyapa_tsg_bin_image_head image_head; + struct cyapa_tsg_bin_image_data_record records[0]; +} __packed; + +struct gen5_bl_packet_start { + u8 sop; /* Start of packet, must be 01h */ + u8 cmd_code; + __le16 data_length; /* Size of data parameter start from data[0] */ +} __packed; + +struct gen5_bl_packet_end { + __le16 crc; + u8 eop; /* End of packet, must be 17h */ +} __packed; + +struct gen5_bl_cmd_head { + __le16 addr; /* Output report register address, must be 0004h */ + /* Size of packet not including output report register address */ + __le16 length; + u8 report_id; /* Bootloader output report id, must be 40h */ + u8 rsvd; /* Reserved, must be 0 */ + struct gen5_bl_packet_start packet_start; + u8 data[0]; /* Command data variable based on commands */ +} __packed; + +/* Initiate bootload command data structure. */ +struct gen5_bl_initiate_cmd_data { + /* Key must be "A5h 01h 02h 03h FFh FEh FDh 5Ah" */ + u8 key[CYAPA_TSG_BL_KEY_SIZE]; + u8 metadata_raw_parameter[CYAPA_TSG_FLASH_MAP_METADATA_SIZE]; + __le16 metadata_crc; +} __packed; + +struct gen5_bl_metadata_row_params { + __le16 size; + __le16 maximun_size; + __le32 app_start; + __le16 app_len; + __le16 app_crc; + __le32 app_entry; + __le32 upgrade_start; + __le16 upgrade_len; + __le16 entry_row_crc; + u8 padding[36]; /* Padding data must be 0 */ + __le16 metadata_crc; /* CRC starts at offset of 60 */ +} __packed; + +/* Bootload program and verify row command data structure */ +struct gen5_bl_flash_row_head { + u8 flash_array_id; + __le16 flash_row_id; + u8 flash_data[0]; +} __packed; + struct gen5_app_cmd_head { __le16 addr; /* Output report register address, must be 0004h */ /* Size of packet not including output report register address */ @@ -297,6 +371,10 @@ struct gen5_app_get_parameter_data { #define GEN5_DEV_UNINIT_SLEEP_TIME(cyapa) \ (((cyapa)->dev_sleep_time) == UNINIT_SLEEP_TIME) + +static u8 cyapa_gen5_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03, + 0xff, 0xfe, 0xfd, 0x5a }; + static int cyapa_gen5_initialize(struct cyapa *cyapa) { struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; @@ -618,6 +696,22 @@ static bool cyapa_gen5_sort_tsg_pip_app_resp_data(struct cyapa *cyapa, return false; } +static bool cyapa_gen5_sort_application_launch_data(struct cyapa *cyapa, + u8 *buf, int len) +{ + if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE) + return false; + + /* +* After reset or power on, trackpad device always sets to 0x00 0x00 +* to indicate a reset or power on event. +*/ + if (buf[0] == 0 && buf[1] == 0) + return true; + + return false; +} + static bool cyapa_gen5_sort_hid_descriptor_data(struct cyapa *cyapa, u8 *buf, int len) { @@ -923,6 +1017,8
[PATCH v16 02/12] input: cyapa: add gen5 trackpad device basic functions
Based on the cyapa core, add the gen5 trackpad device's basic functions supported, so gen5 trackpad device can work with kernel input system. And also based on the state parse interface, the cyapa driver can automatically determine the attached is gen3 or gen5 protocol trackpad device, then set the correct protocol to work with the attached trackpad device. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |2 +- drivers/input/mouse/cyapa.c | 13 + drivers/input/mouse/cyapa.h |1 + drivers/input/mouse/cyapa_gen5.c | 1677 ++ 4 files changed, 1692 insertions(+), 1 deletion(-) create mode 100644 drivers/input/mouse/cyapa_gen5.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 8bd950d..8a9c98e 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o -cyapatp-objs := cyapa.o cyapa_gen3.o +cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index ae1df15..d4560a3 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -157,6 +157,14 @@ static int cyapa_get_state(struct cyapa *cyapa) if (!error) goto out_detected; } + if ((cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN5) && + !smbus && even_addr) { + error = cyapa_gen5_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (!error) + goto out_detected; + } /* * Write 0x00 0x00 to trackpad device to force update its @@ -240,6 +248,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return error; switch (cyapa->gen) { + case CYAPA_GEN5: + cyapa->ops = &cyapa_gen5_ops; + break; case CYAPA_GEN3: cyapa->ops = &cyapa_gen3_ops; break; @@ -476,6 +487,8 @@ static int cyapa_initialize(struct cyapa *cyapa) if (cyapa_gen3_ops.initialize) error = cyapa_gen3_ops.initialize(cyapa); + if (!error && cyapa_gen5_ops.initialize) + error = cyapa_gen5_ops.initialize(cyapa); if (error) return error; diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index 8a75c52..4c09be4 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -303,5 +303,6 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode); extern const char product_id[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; +extern const struct cyapa_dev_ops cyapa_gen5_ops; #endif diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c new file mode 100644 index 000..2ce0149 --- /dev/null +++ b/drivers/input/mouse/cyapa_gen5.c @@ -0,0 +1,1677 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du + * + * Copyright (C) 2014 Cypress Semiconductor, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cyapa.h" + + +/* Macro of Gen5 */ +#define RECORD_EVENT_NONE0 +#define RECORD_EVENT_TOUCHDOWN 1 +#define RECORD_EVENT_DISPLACE2 +#define RECORD_EVENT_LIFTOFF 3 + +#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80 +#define CYAPA_TSG_IMG_FW_HDR_SIZE 13 +#define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE) +#define CYAPA_TSG_IMG_START_ROW_NUM 0x002e +#define CYAPA_TSG_IMG_END_ROW_NUM 0x01fe +#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff +#define CYAPA_TSG_IMG_MAX_RECORDS (CYAPA_TSG_IMG_END_ROW_NUM - \ + CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1) +#define CYAPA_TSG_IMG_READ_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2) +#define CYAPA_TSG_START_OF_APPLICATION 0x1700 +#define CYAPA_TSG_APP_INTEGRITY_SIZE60 +#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE 60 +#define CYAPA_TSG_BL_KEY_SIZE 8 + +#define CYAPA_TSG_MAX_CMD_SIZE 256 + +#define GEN5_BL_CMD_VERIFY_APP_INTEGRITY0x31 +#define GEN5_BL_CMD_GET_BL_INFO0x38 +#define GEN5_BL_CMD_PROGRAM_VERIFY_ROW
[PATCH v16 11/12] input: cyapa: add gen5 trackpad device force
Add force re-calibrate function supported for gen5 trackpad device, it can be used through sysfs calibrate interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 65 1 file changed, 65 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 2b800e3..4bb6f34 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1713,6 +1713,70 @@ static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) return 0; } +static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa, + u8 calibrate_sensing_mode_type) +{ + struct gen5_app_cmd_head *app_cmd_head; + u8 cmd[8]; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + memset(cmd, 0, sizeof(cmd)); + app_cmd_head = (struct gen5_app_cmd_head *)cmd; + put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); + put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length); + app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; + app_cmd_head->cmd_code = GEN5_CMD_CALIBRATE; + app_cmd_head->parameter_data[0] = calibrate_sensing_mode_type; + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 5000, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_CALIBRATE) || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return error < 0 ? error : -EAGAIN; + + return 0; +} + +static ssize_t cyapa_gen5_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int error, calibrate_error; + + /* 1. Suspend Scanning*/ + error = cyapa_gen5_suspend_scanning(cyapa); + if (error) + return error; + + /* 2. Do mutual capacitance fine calibrate. */ + calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_MUTUAL_CAP_FINE); + if (calibrate_error) + goto resume_scanning; + + /* 3. Do self capacitance calibrate. */ + calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_SELF_CAP); + if (calibrate_error) + goto resume_scanning; + +resume_scanning: + /* 4. Resume Scanning*/ + error = cyapa_gen5_resume_scanning(cyapa); + if (error || calibrate_error) + return error ? error : calibrate_error; + + return count; +} + static s32 twos_complement_to_s32(s32 value, int num_bits) { if (value >> (num_bits - 1)) @@ -2689,6 +2753,7 @@ const struct cyapa_dev_ops cyapa_gen5_ops = { .update_fw = cyapa_gen5_do_fw_update, .show_baseline = cyapa_gen5_show_baseline, + .calibrate_store = cyapa_gen5_do_calibrate, .initialize = cyapa_gen5_initialize, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v16 07/12] input: cyapa: add gen3 trackpad device read baseline
Add read baseline function supported for gen3 trackpad device, it can be used through sysfs baseline interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 72 1 file changed, 72 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index cd4f1db..92b3d6d 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -765,6 +765,76 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_show_baseline(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int max_baseline, min_baseline; + int tries; + int ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_REPORT_BASELINE_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send report baseline command. %d\n", + ret); + goto out; + } + + tries = 3; /* Try for 30 to 60 ms */ + do { + usleep_range(1, 2); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Device timed out going to Normal state.\n"); + ret = -ETIMEDOUT; + goto out; + } + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MAX_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read max baseline. err = %d\n", ret); + goto out; + } + max_baseline = ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MIN_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read min baseline. err = %d\n", ret); + goto out; + } + min_baseline = ret; + + dev_dbg(dev, "Baseline report successful. Max: %d Min: %d\n", + max_baseline, min_baseline); + ret = scnprintf(buf, PAGE_SIZE, "%d %d\n", max_baseline, min_baseline); + +out: + return ret; +} + /* * cyapa_get_wait_time_for_pwr_cmd * @@ -1079,6 +1149,8 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .update_fw = cyapa_gen3_do_fw_update, .bl_deactivate = cyapa_gen3_bl_deactivate, + .show_baseline = cyapa_gen3_show_baseline, + .state_parse = cyapa_gen3_state_parse, .operational_check = cyapa_gen3_do_operational_check, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v16 00/12] input: cyapa: instruction of cyapa patches
Jmmahler, Thank you very much for your review and comments based on v15 patches. I have modified all points based on your comments and generate this v16 patches. Could you please help review again when have time. By the way, since gmail is blocked again in my side, so I use private email du...@outlook.com instead to send these patches manually. Thanks, Dudley > -Original Message- > From: Dudley Du [mailto:du...@outlook.com] > Sent: 2014年12月17日 17:55 > To: dmitry.torok...@gmail.com; jmmah...@gmail.com; rydb...@euromail.se > Cc: ble...@google.com; David Solda; linux-in...@vger.kernel.org; > linux-kernel@vger.kernel.org > Subject: [PATCH v16 00/12] input: cyapa: instruction of cyapa patches > > V16 patches have below updates, details of other updates see history list: > 1) Fix all miss-spelling and space issue. > 2) Rename variables and functions with much more clearer names. > 3) Initialize and document tries near where it will be used. > 4) Modify cmd buffer to struct for more descriptive way. > > > This patch series is aimed to re-design the cyapa driver to support > old gen3 trackpad devices and new gen5 trackpad devices in one > cyapa driver, it's for easily productions support based on > customers' requirements. And add sysfs functions and interfaces > supported that required by users and customers. > > Since the earlier gen3 and the latest gen5 trackpad devices using > two different chipsets, and have different protocols and interfaces, > so if supported these two type trackpad devices in two different drivers, > then it will be difficult to manage productions and later firmware updates. > e.g.: It will cause customer don't know which one trackpad device firmware > image to use and update when it has been used and integrated > in same one productions, so here we support these two trackpad > devices in same on driver. > > The new design cyapa driver contains: > cyapa.c - the core of the re-design, supply interfaces and > functions to system and read trackpad devices. > cyapa.h - header file including macros and data structure definitions. > cyapa_gen3.c - functions support for gen3 trackpad devices, > cyapa_gen5.c - functions support for gen5 trackpad devices. > > Beside this introduction patch, it has 12 patches listed as below. > For these patches, each one is patched based on previous one. > > patch 1/12: re-design cyapa driver with core functions and interface > to support multi-type trackpad devices. > > patch 2/12: add gen5 trackpad device basic functions support in the > re-design cyapa driver. > > patch 3/12: add power management interfaces support for the device. > > patch 4/12: add runtime power management interfaces support for the device. > > patch 5/12: add sysfs interfaces supported in the cyapa driver. > Including read firmware version, get production ID, read baseline, > re-calibrate trackpad baselines and do trackpad firmware update. > > patch 6/12: add gen3 trackpad device's firmware update function support. > > patch 7/12: add gen3 trackpad device's read baseline function support. > > patch 8/12: add gen3 trackpad device's force re-calibrate function support. > > patch 9/12: add gen5 trackpad device's firmware update function support. > > patch 10/12: add gen5 trackpad device's read baseline function support. > > patch 11/12: add gen5 trackpad device's force re-calibrate function. > > patch 12/12: add acpi device id support. > > > History patch series modifications list: > V15 patches have below main updates compared with v14 patches: > 1) Fix all warning errors of sparse tool when running with "make C=1". > 2) Change variable name "unique_str" to "product_id" for clearer meanings. > 3) Update cyapa_i2c_write function to return error directly when length > 31. > > V14 patches have below main updates compared with v13 patches: > 1) Correct 9 miss spelling issues of "bufferred" to "buffered". > 2) Fix the upgrade issue of removing MOUSE_CYAPA config when make oldconfig >by replase "depends on I2C && CRC_ITU_T" with > "depends on I2C" > "select CRC_ITU_T" >in patch 9. > > V13 patches have below main updates compared with v12 patches: > 1) Remove all debugfs interface, including read_fw and raw_data interfaces. > 2) This patches are made based linux next-20141208. > > V12 patches have below main updates compared with v11 patches: > 1) Add check that when TP is detected but not operational, do not exit driver >immediately, but wait and export the update_fw interface for recovering. > 2) Re-arrange the function codes, remove u
[PATCH v16 04/12] input: cyapa: add runtime power management interfaces
Add runtime_suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the runtime power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 171 +++- drivers/input/mouse/cyapa.h | 4 ++ 2 files changed, 174 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 73f6817..3bcfce3 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "cyapa.h" @@ -327,6 +328,8 @@ static int cyapa_open(struct input_dev *input) } enable_irq(client->irq); + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); out: mutex_unlock(&cyapa->state_sync_lock); return error; @@ -340,8 +343,10 @@ static void cyapa_close(struct input_dev *input) mutex_lock(&cyapa->state_sync_lock); disable_irq(client->irq); + pm_runtime_disable(&client->dev); if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + pm_runtime_set_suspended(&client->dev); mutex_unlock(&cyapa->state_sync_lock); } @@ -542,6 +547,7 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) struct device *dev = &cyapa->client->dev; bool cont; + pm_runtime_get_sync(dev); if (device_may_wakeup(dev)) pm_wakeup_event(dev, 0); @@ -572,6 +578,8 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) } out: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); return IRQ_HANDLED; } @@ -665,6 +673,116 @@ static void cyapa_remove_power_wakeup_group(void *data) } #endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_PM_RUNTIME +static ssize_t cyapa_show_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd; + u16 sleep_time; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + pwr_cmd = cyapa->runtime_suspend_power_mode; + sleep_time = cyapa->runtime_suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (cyapa->gen == CYAPA_GEN3) + return scnprintf(buf, PAGE_SIZE, "%u\n", + cyapa_pwr_cmd_to_sleep_time(pwr_cmd)); + return scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); +} + +static ssize_t cyapa_update_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 time; + int error; + + if (buf == NULL || count == 0 || kstrtou16(buf, 10, &time)) { + dev_err(dev, "invalid runtime suspend scanrate ms parameter\n"); + return -EINVAL; + } + + /* +* When the suspend scanrate is changed, pm_runtime_get to resume +* a potentially suspended device, update to the new pwr_cmd +* and then pm_runtime_put to suspend into the new power mode. +*/ + pm_runtime_get_sync(dev); + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + cyapa->runtime_suspend_sleep_time = max_t(u16, time, 1000); + cyapa->runtime_suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time); + mutex_unlock(&cyapa->state_sync_lock); + pm_runtime_put_sync_autosuspend(dev); + + return count; +} + +static DEVICE_ATTR(runtime_suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_rt_suspend_scanrate, + cyapa_update_rt_suspend_scanrate); + +static struct attribute *cyapa_power_runtime_entries[] = { + &dev_attr_runtime_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_runtime_group = { + .name = power_group_name, + .attrs = cyapa_power_runtime_entries, +}; + +static void cyapa_remove_power_runtime_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_runtime_group); +} + +static int cyapa_start_runtime(struct cyapa *cyapa) +{ + struct device *de
[PATCH v16 00/12] input: cyapa: instruction of cyapa patches
V16 patches have below updates, details of other updates see history list: 1) Fix all miss-spelling and space issue. 2) Rename variables and functions with much more clearer names. 3) Initialize and document tries near where it will be used. 4) Modify cmd buffer to struct for more descriptive way. This patch series is aimed to re-design the cyapa driver to support old gen3 trackpad devices and new gen5 trackpad devices in one cyapa driver, it's for easily productions support based on customers' requirements. And add sysfs functions and interfaces supported that required by users and customers. Since the earlier gen3 and the latest gen5 trackpad devices using two different chipsets, and have different protocols and interfaces, so if supported these two type trackpad devices in two different drivers, then it will be difficult to manage productions and later firmware updates. e.g.: It will cause customer don't know which one trackpad device firmware image to use and update when it has been used and integrated in same one productions, so here we support these two trackpad devices in same on driver. The new design cyapa driver contains: cyapa.c - the core of the re-design, supply interfaces and functions to system and read trackpad devices. cyapa.h - header file including macros and data structure definitions. cyapa_gen3.c - functions support for gen3 trackpad devices, cyapa_gen5.c - functions support for gen5 trackpad devices. Beside this introduction patch, it has 12 patches listed as below. For these patches, each one is patched based on previous one. patch 1/12: re-design cyapa driver with core functions and interface to support multi-type trackpad devices. patch 2/12: add gen5 trackpad device basic functions support in the re-design cyapa driver. patch 3/12: add power management interfaces support for the device. patch 4/12: add runtime power management interfaces support for the device. patch 5/12: add sysfs interfaces supported in the cyapa driver. Including read firmware version, get production ID, read baseline, re-calibrate trackpad baselines and do trackpad firmware update. patch 6/12: add gen3 trackpad device's firmware update function support. patch 7/12: add gen3 trackpad device's read baseline function support. patch 8/12: add gen3 trackpad device's force re-calibrate function support. patch 9/12: add gen5 trackpad device's firmware update function support. patch 10/12: add gen5 trackpad device's read baseline function support. patch 11/12: add gen5 trackpad device's force re-calibrate function. patch 12/12: add acpi device id support. History patch series modifications list: V15 patches have below main updates compared with v14 patches: 1) Fix all warning errors of sparse tool when running with "make C=1". 2) Change variable name "unique_str" to "product_id" for clearer meanings. 3) Update cyapa_i2c_write function to return error directly when length > 31. V14 patches have below main updates compared with v13 patches: 1) Correct 9 miss spelling issues of "bufferred" to "buffered". 2) Fix the upgrade issue of removing MOUSE_CYAPA config when make oldconfig by replase "depends on I2C && CRC_ITU_T" with "depends on I2C" "select CRC_ITU_T" in patch 9. V13 patches have below main updates compared with v12 patches: 1) Remove all debugfs interface, including read_fw and raw_data interfaces. 2) This patches are made based linux next-20141208. V12 patches have below main updates compared with v11 patches: 1) Add check that when TP is detected but not operational, do not exit driver immediately, but wait and export the update_fw interface for recovering. 2) Re-arrange the function codes, remove unnesseary protype definitions in the header file. V11 patches have below main updates compared with v10 patches: 1) Add add acpi device id supported for old gen3 and new gen5 trackpad devices. 2) Fix the unable to update firmware issue when cyapa_open is not called which means the irq for firwmare update process is not enabled. This fix by checking if the irq is enabled, if not then enable irq before start to do firmware update. V10 patches have below main updates compared with v9 patches: 1) Modify code to following kernel code style. e.g.: correct to use error as return name when there is only error path, and fix the checkpatch.sh wanting in the driver. 2) Remove cyapa_remove method and use input open and close interface to following device resouse management infrastructure. 3) Modify cyapa_detect method to return tristate issue to make the return value much more consistent and clear. 4) Use platform supplied functions as possible instead of driver specific rewritten version. V9 patches have below updates compared with v8 patches: 1) Removed all async thread stuff from the driver. 2) Split driver into 18 patches for each function change one patch. V8 patches have below updates compared with v7 patches: 1) [PATCH v8 01/13] - Remove the
[PATCH v16 05/12] input: cyapa: add sysfs interfaces support in the cyapa
Add device's basic control and features supported in cyapa driver through sysfs file system interfaces. These interfaces are commonly used in pre- and after production, for trackpad device state checking, managing and firmware image updating. These interfaces including mode, firmware_version and product_id interfaces for reading firmware version and trackpad device product id values, and including update_fw interface to command firmware image update process. Also including baseline and calibrate interfaces for reading and checking trackpad device's sensors states. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 327 1 file changed, 327 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 3bcfce3..406f38b 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -32,6 +32,8 @@ #define CYAPA_ADAPTER_FUNC_SMBUS 2 #define CYAPA_ADAPTER_FUNC_BOTH 3 +#define CYAPA_FW_NAME "cyapa.bin" + const char product_id[] = "CYTRA"; static int cyapa_reinitialize(struct cyapa *cyapa); @@ -442,6 +444,29 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) return 0; } +static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa) +{ + struct input_dev *input = cyapa->input; + + if (!input || !input->users) { + if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0); + enable_irq(cyapa->client->irq); + } +} + +static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa) +{ + struct input_dev *input = cyapa->input; + + if (!input || !input->users) { + disable_irq(cyapa->client->irq); + if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + } +} + /* * cyapa_sleep_time_to_pwr_cmd and cyapa_pwr_cmd_to_sleep_time * @@ -783,6 +808,295 @@ static int cyapa_start_runtime(struct cyapa *cyapa) } #endif /* CONFIG_PM_RUNTIME */ +static ssize_t cyapa_show_fm_ver(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int error; + struct cyapa *cyapa = dev_get_drvdata(dev); + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + error = scnprintf(buf, PAGE_SIZE, "%d.%d\n", cyapa->fw_maj_ver, +cyapa->fw_min_ver); + mutex_unlock(&cyapa->state_sync_lock); + return error; +} + +static ssize_t cyapa_show_product_id(struct device *dev, +struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int size; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + size = scnprintf(buf, PAGE_SIZE, "%s\n", cyapa->product_id); + mutex_unlock(&cyapa->state_sync_lock); + return size; +} + +static int cyapa_firmware(struct cyapa *cyapa, const char *fw_name) +{ + struct device *dev = &cyapa->client->dev; + const struct firmware *fw; + int error; + + error = request_firmware(&fw, fw_name, dev); + if (error) { + dev_err(dev, "Could not load firmware from %s: %d\n", + fw_name, error); + return error; + } + + if (cyapa->ops->check_fw) { + error = cyapa->ops->check_fw(cyapa, fw); + if (error) { + dev_err(dev, "Invalid CYAPA firmware image: %s\n", + fw_name); + goto done; + } + } else { + dev_err(dev, "No valid device ops->check_fw handler set.\n"); + error = -ENODEV; + goto done; + } + + /* +* Resume the potentially suspended device because doing FW +* update on a device not in the FULL mode has a chance to +* fail. +*/ + pm_runtime_get_sync(dev); + + /* Require IRQ support for firmware update commands. */ + cyapa_enable_irq_for_cmd(cyapa); + + if (cyapa->ops->bl_enter) { + error = cyapa->ops->bl_enter(cyapa); + if (error) { + dev_err(dev, "bl_enter failed, %d\n", error); + goto err_detect; + } + } + + if (cyapa->ops->bl_activate) { + error = cyapa->ops->bl_activate(cyapa); +
[PATCH v16 03/12] input: cyapa: add power management interfaces support
Add suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 111 1 file changed, 111 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index d4560a3..73f6817 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -575,6 +575,96 @@ out: return IRQ_HANDLED; } +/* + ** + * sysfs interface + ** +*/ +#ifdef CONFIG_PM_SLEEP +static ssize_t cyapa_show_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd = cyapa->suspend_power_mode; + u16 sleep_time; + int len; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + pwr_cmd = cyapa->suspend_power_mode; + sleep_time = cyapa->suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (pwr_cmd == PWR_MODE_BTN_ONLY) { + len = scnprintf(buf, PAGE_SIZE, "%s\n", BTN_ONLY_MODE_NAME); + } else if (pwr_cmd == PWR_MODE_OFF) { + len = scnprintf(buf, PAGE_SIZE, "%s\n", OFF_MODE_NAME); + } else { + if (cyapa->gen == CYAPA_GEN3) + sleep_time = cyapa_pwr_cmd_to_sleep_time(pwr_cmd); + len = scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); + } + + return len; +} + +static ssize_t cyapa_update_suspend_scanrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 sleep_time; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + + if (sysfs_streq(buf, BTN_ONLY_MODE_NAME)) { + cyapa->suspend_power_mode = PWR_MODE_BTN_ONLY; + } else if (sysfs_streq(buf, OFF_MODE_NAME)) { + cyapa->suspend_power_mode = PWR_MODE_OFF; + } else if (!kstrtou16(buf, 10, &sleep_time)) { + cyapa->suspend_sleep_time = max_t(u16, sleep_time, 1000); + cyapa->suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time); + } else { + count = 0; + } + + mutex_unlock(&cyapa->state_sync_lock); + + if (!count) + dev_err(dev, "invalid suspend scanrate ms parameters\n"); + return count ? count : -EINVAL; +} + +static DEVICE_ATTR(suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_suspend_scanrate, + cyapa_update_suspend_scanrate); + +static struct attribute *cyapa_power_wakeup_entries[] = { + &dev_attr_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_wakeup_group = { + .name = power_group_name, + .attrs = cyapa_power_wakeup_entries, +}; + +static void cyapa_remove_power_wakeup_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_wakeup_group); +} +#endif /* CONFIG_PM_SLEEP */ + static int cyapa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { @@ -614,6 +704,27 @@ static int cyapa_probe(struct i2c_client *client, return error; } +#ifdef CONFIG_PM_SLEEP + if (device_can_wakeup(dev)) { + error = sysfs_merge_group(&client->dev.kobj, + &cyapa_power_wakeup_group); + if (error) { + dev_err(dev, "failed to add power wakeup group: %d\n", + error); + return error; + } + + error = devm_add_action(dev, + cyapa_remove_power_wakeup_group, cyapa); + if (error) { + cyapa_remove_power_wakeup_group(cyapa); + dev_err(dev, "failed to add power cleanup action: %d\n", + error); + return error; + } + } +#endif /* CONFIG_PM_SLEEP */ + error = devm_request_threaded_irq(dev, client->irq,
[PATCH v16 08/12] input: cyapa: add gen3 trackpad device force
Add force re-calibrate function supported for gen3 trackpad device, it can be used through sysfs calibrate interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 59 1 file changed, 59 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 92b3d6d..7351fce 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -765,6 +765,64 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int tries; + int ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status: %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy, device state: 0x%02x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_RECALIBRATION_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send calibrate command: %d\n", + ret); + goto out; + } + + tries = 20; /* max recalibration timeout 2s. */ + do { + /* +* For this recalibration, the max time will not exceed 2s. +* The average time is approximately 500 - 700 ms, and we +* will check the status every 100 - 200ms. +*/ + usleep_range(10, 20); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status: %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Failed to calibrate. Timeout.\n"); + ret = -ETIMEDOUT; + goto out; + } + dev_dbg(dev, "Calibration successful.\n"); + +out: + return ret < 0 ? ret : count; +} + static ssize_t cyapa_gen3_show_baseline(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1150,6 +1208,7 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .bl_deactivate = cyapa_gen3_bl_deactivate, .show_baseline = cyapa_gen3_show_baseline, + .calibrate_store = cyapa_gen3_do_calibrate, .state_parse = cyapa_gen3_state_parse, .operational_check = cyapa_gen3_do_operational_check, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v16 06/12] input: cyapa: add gen3 trackpad device firmware update
Add firmware image update function supported for gen3 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 288 +++ 1 file changed, 288 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 228fd2d..cd4f1db 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "cyapa.h" @@ -115,6 +116,18 @@ struct cyapa_reg_data { struct cyapa_touch touches[5]; } __packed; +struct gen3_write_block_cmd { + u8 checksum_seed; /* Always be 0xff */ + u8 cmd_code; /* command code: 0x39 */ + u8 key[8]; /* 8-byte security key */ + __be16 block_num; + u8 block_data[CYAPA_FW_BLOCK_SIZE]; + u8 block_checksum; /* Calculated using bytes 12 - 75 */ + u8 cmd_checksum;/* Calculated using bytes 0-76 */ +} __packed; + +static const u8 security_key[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; static const u8 bl_activate[] = { 0x00, 0xff, 0x38, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; static const u8 bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03, @@ -423,6 +436,69 @@ 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. + * + * Returns: + * 0on 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 error; + + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; + if (cyapa->state == CYAPA_STATE_BL_IDLE) { + /* Already in BL_IDLE. Skipping reset. */ + return 0; + } + + if (cyapa->state != CYAPA_STATE_OP) + return -EAGAIN; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + error = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01); + if (error) + return -EIO; + + usleep_range(25000, 5); + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; + 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 error; + + error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate), + bl_activate); + if (error) + return error; + + /* Wait for bootloader to activate; takes between 2 and 12 seconds */ + msleep(2000); + error = cyapa_poll_state(cyapa, 11000); + if (error) + return error; + if (cyapa->state != CYAPA_STATE_BL_ACTIVE) + return -EAGAIN; + + return 0; +} + static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { int error; @@ -483,6 +559,212 @@ static int cyapa_gen3_bl_exit(struct cyapa *cyapa) return 0; } +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); + i
RE: [PATCH v16 01/12] input: cyapa: re-design driver to support
> -Original Message- > From: Jeremiah Mahler [mailto:jmmah...@gmail.com] > Sent: 2014?12?17? 23:05 > To: DuDudley > Cc: Dudley Du; dmitry.torok...@gmail.com; rydb...@euromail.se; > ble...@google.com; linux-in...@vger.kernel.org; linux-kernel@vger.kernel.org; > David Solda > Subject: Re: [PATCH v16 01/12] input: cyapa: re-design driver to support > > Dudley, > > On Wed, Dec 17, 2014 at 01:53:38PM +, DuDudley wrote: > > > > > > > Date: Wed, 17 Dec 2014 04:17:19 -0800 > > > From: jmmah...@gmail.com > > > To: d...@cypress.com > > > CC: du...@outlook.com; dmitry.torok...@gmail.com; rydb...@euromail.se; > ble...@google.com; linux-in...@vger.kernel.org; linux-kernel@vger.kernel.org; > d...@cypress.com > > > Subject: Re: [PATCH v16 01/12] input: cyapa: re-design driver to support > > > > > > Dudley, > > > > > > On Wed, Dec 17, 2014 at 10:55:00AM +, Dudley Du wrote: > > > > Jeremiah, > > > > > > > > Thanks for the feedback. > > > > Yes, the our net proxy may broken this. It needs sometime to fix this. > > > > > > > > Attched are the patch files, could you try to apply these patch files > > > > firstly. > > > > > > > > Thanks, > > > > Dudley > > > > > > > > > > Attachments are difficult to comment on [1]. Just re-send the series > > > when you can format them properly. > > Sorry, I cannot fix it today. I need IT help to try to fix this tommorrow. > > That is fine. What do you normally use to send your patches? I use > git send-email after creating a series with git format-patch and it has > always worked well. Yes, I also use git format-path and git send-email to create and send patches. This working fine during several months, but stop working on this Wednesday when I do same as before. :( The connect to smtp.gmail.com is blocked (connection refused always). I will talk with IT to find out the problem. > > > > > > > [1]: linux/Documentation/SubmittingPatches > > > > > > [...] > > > > > > -- > > > - Jeremiah Mahler > > > > -- > - Jeremiah Mahler 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. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v16 01/12] input: cyapa: re-design driver to support multi-trackpad in one driver
In order to support multiple different chipsets and communication protocols trackpad devices in one cyapa driver, the new cyapa driver is re-designed with one cyapa driver core and multiple device specific functions component. The cyapa driver core is contained in this patch, it supplies basic functions that working with kernel and input subsystem, and also supplies the interfaces that the specific devices' component can connect and work together with as one driver. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |3 +- drivers/input/mouse/cyapa.c | 1047 ++ drivers/input/mouse/cyapa.h | 307 +++ drivers/input/mouse/cyapa_gen3.c | 801 + 4 files changed, 1492 insertions(+), 666 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h create mode 100644 drivers/input/mouse/cyapa_gen3.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 560003d..8bd950d 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974)+= bcm5974.o -obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o @@ -24,6 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o +cyapatp-objs := cyapa.o cyapa_gen3.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 1bece8c..ae1df15 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -20,408 +20,100 @@ #include #include #include +#include #include +#include +#include "cyapa.h" -/* APA trackpad firmware generation */ -#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ - -#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" - -/* commands for read/write registers of Cypress trackpad */ -#define CYAPA_CMD_SOFT_RESET 0x00 -#define CYAPA_CMD_POWER_MODE 0x01 -#define CYAPA_CMD_DEV_STATUS 0x02 -#define CYAPA_CMD_GROUP_DATA 0x03 -#define CYAPA_CMD_GROUP_CMD0x04 -#define CYAPA_CMD_GROUP_QUERY 0x05 -#define CYAPA_CMD_BL_STATUS0x06 -#define CYAPA_CMD_BL_HEAD 0x07 -#define CYAPA_CMD_BL_CMD 0x08 -#define CYAPA_CMD_BL_DATA 0x09 -#define CYAPA_CMD_BL_ALL 0x0a -#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b -#define CYAPA_CMD_BLK_HEAD 0x0c - -/* report data start reg offset address. */ -#define DATA_REG_START_OFFSET 0x - -#define BL_HEAD_OFFSET 0x00 -#define BL_DATA_OFFSET 0x10 - -/* - * Operational Device Status Register - * - * bit 7: Valid interrupt source - * bit 6 - 4: Reserved - * bit 3 - 2: Power status - * bit 1 - 0: Device status - */ -#define REG_OP_STATUS 0x00 -#define OP_STATUS_SRC 0x80 -#define OP_STATUS_POWER 0x0c -#define OP_STATUS_DEV 0x03 -#define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) - -/* - * Operational Finger Count/Button Flags Register - * - * bit 7 - 4: Number of touched finger - * bit 3: Valid data - * bit 2: Middle Physical Button - * bit 1: Right Physical Button - * bit 0: Left physical Button - */ -#define REG_OP_DATA1 0x01 -#define OP_DATA_VALID 0x08 -#define OP_DATA_MIDDLE_BTN 0x04 -#define OP_DATA_RIGHT_BTN 0x02 -#define OP_DATA_LEFT_BTN 0x01 -#define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ - OP_DATA_LEFT_BTN) - -/* - * Bootloader Status Register - * - * bit 7: Busy - * bit 6 - 5: Reserved - * bit 4: Bootloader running - * bit 3 - 1: Reserved - * bit 0: Checksum valid - */ -#define REG_BL_STATUS0x01 -#define BL_STATUS_BUSY 0x80 -#define BL_STATUS_RUNNING0x10 -#define BL_STATUS_DATA_VALID 0x08 -#define BL_STATUS_CSUM_VALID 0x01 - -/* - * Bootloader Error Register - * - * bit 7: Invalid - * bit 6: Invalid security key - * bit 5: Bootloading - * bit 4: Command checksum - * bit 3: Flash protection error - * bit 2: Flash checksum error - * bit 1 - 0: Reserved - */ -#define REG_BL_ERROR 0x02 -#define BL_ERROR_INVALID 0x80 -#define BL_ERROR_INVALID_KEY 0x40 -#define BL_ERROR_BOOTLOADING 0x20 -#define BL_ERROR_CMD_CSUM0x10 -#define BL_ERROR_FLASH_PROT 0x08 -#define BL_ERROR_FLASH_CSUM 0x04 - -#define BL_STATUS_SIZE 3 /* length of bootloader status registers */ -#define BLK_HEAD_BYTES 32 - -#define PRODUCT_ID_SIZE 16 -#d
[PATCH v16 10/12] input: cyapa: add gen5 trackpad device read baseline function support
Add read baseline function supported for gen5 trackpad device, it can be used through sysfs baseline interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.h | 2 + drivers/input/mouse/cyapa_gen5.c | 640 +++ 2 files changed, 642 insertions(+) diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index 922a473..e5de0b2 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -276,6 +276,8 @@ struct cyapa { u8 y_origin; /* Y Axis Origin: 0 = top; 1 = bottom. */ int electrodes_x; /* Number of electrodes on the X Axis*/ int electrodes_y; /* Number of electrodes on the Y Axis*/ + int electrodes_rx; /* Number of Rx electrodes */ + int aligned_electrodes_rx; /* 4 aligned */ int max_z; /* diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 840f5d6..2b800e3 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -363,6 +363,12 @@ struct gen5_app_get_parameter_data { u8 parameter_id; } __packed; +struct gen5_retrieve_panel_scan_data { + __le16 read_offset; + __le16 read_elements; + u8 data_id; +} __packed; + /* Variables to record latest gen5 trackpad power states. */ #define GEN5_DEV_SET_PWR_STATE(cyapa, s) ((cyapa)->dev_pwr_mode = (s)) #define GEN5_DEV_GET_PWR_STATE(cyapa) ((cyapa)->dev_pwr_mode) @@ -1659,6 +1665,638 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, return 0; } +static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) +{ + u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 }; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x04)) + return -EINVAL; + + /* Try to dump all buffered data when resuming scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) +{ + u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 }; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x03)) + return -EINVAL; + + /* Try to dump all buffered data when suspending scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static s32 twos_complement_to_s32(s32 value, int num_bits) +{ + if (value >> (num_bits - 1)) + value |= -1 << num_bits; + return value; +} + +static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len) +{ + int data_size; + bool big_endian; + bool unsigned_type; + s32 value; + + data_size = (data_format & 0x07); + big_endian = ((data_format & 0x10) == 0x00); + unsigned_type = ((data_format & 0x20) == 0x00); + + if (buf_len < data_size) + return 0; + + switch (data_size) { + case 1: + value = buf[0]; + break; + case 2: + if (big_endian) + value = get_unaligned_be16(buf); + else + value = get_unaligned_le16(buf); + break; + case 4: + if (big_endian) + value = get_unaligned_be32(buf); + else + value = get_unaligned_le32(buf); + break; + default: + /* Should not happen, just as default case here. */ + value = 0; + break; + } + + if (!unsigned_type) + value = twos_complement_to_s32(value, data_size * 8); + + return value; +} + +static void cyapa_gen5_guess_electrodes(struct cyapa *cyapa, + int *electrodes_rx, int *electrodes_tx) +{ + if (cyapa->electrodes_rx != 0) { + *electrodes_rx = cyapa->electrodes_rx; + *electrodes_tx = (cyapa->electrodes_x == *electrodes_rx) ? + cyapa-&
[PATCH v16 04/12] input: cyapa: add runtime power management interfaces support for the device
Add runtime_suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the runtime power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 171 +++- drivers/input/mouse/cyapa.h | 4 ++ 2 files changed, 174 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 73f6817..3bcfce3 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "cyapa.h" @@ -327,6 +328,8 @@ static int cyapa_open(struct input_dev *input) } enable_irq(client->irq); + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); out: mutex_unlock(&cyapa->state_sync_lock); return error; @@ -340,8 +343,10 @@ static void cyapa_close(struct input_dev *input) mutex_lock(&cyapa->state_sync_lock); disable_irq(client->irq); + pm_runtime_disable(&client->dev); if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + pm_runtime_set_suspended(&client->dev); mutex_unlock(&cyapa->state_sync_lock); } @@ -542,6 +547,7 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) struct device *dev = &cyapa->client->dev; bool cont; + pm_runtime_get_sync(dev); if (device_may_wakeup(dev)) pm_wakeup_event(dev, 0); @@ -572,6 +578,8 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) } out: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); return IRQ_HANDLED; } @@ -665,6 +673,116 @@ static void cyapa_remove_power_wakeup_group(void *data) } #endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_PM_RUNTIME +static ssize_t cyapa_show_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd; + u16 sleep_time; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + pwr_cmd = cyapa->runtime_suspend_power_mode; + sleep_time = cyapa->runtime_suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (cyapa->gen == CYAPA_GEN3) + return scnprintf(buf, PAGE_SIZE, "%u\n", + cyapa_pwr_cmd_to_sleep_time(pwr_cmd)); + return scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); +} + +static ssize_t cyapa_update_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 time; + int error; + + if (buf == NULL || count == 0 || kstrtou16(buf, 10, &time)) { + dev_err(dev, "invalid runtime suspend scanrate ms parameter\n"); + return -EINVAL; + } + + /* +* When the suspend scanrate is changed, pm_runtime_get to resume +* a potentially suspended device, update to the new pwr_cmd +* and then pm_runtime_put to suspend into the new power mode. +*/ + pm_runtime_get_sync(dev); + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + cyapa->runtime_suspend_sleep_time = max_t(u16, time, 1000); + cyapa->runtime_suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time); + mutex_unlock(&cyapa->state_sync_lock); + pm_runtime_put_sync_autosuspend(dev); + + return count; +} + +static DEVICE_ATTR(runtime_suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_rt_suspend_scanrate, + cyapa_update_rt_suspend_scanrate); + +static struct attribute *cyapa_power_runtime_entries[] = { + &dev_attr_runtime_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_runtime_group = { + .name = power_group_name, + .attrs = cyapa_power_runtime_entries, +}; + +static void cyapa_remove_power_runtime_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_runtime_group); +} + +static int cyapa_start_runtime(struct cyapa *cyapa) +{ + struct device *de
[PATCH v16 09/12] input: cyapa: add gen5 trackpad device firmware update function support
Add firmware image update function supported for gen5 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Kconfig | 1 + drivers/input/mouse/cyapa_gen5.c | 385 +++ 2 files changed, 386 insertions(+) diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index d8b46b0..728490e 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -206,6 +206,7 @@ config MOUSE_BCM5974 config MOUSE_CYAPA tristate "Cypress APA I2C Trackpad support" depends on I2C + select CRC_ITU_T help This driver adds support for Cypress All Points Addressable (APA) I2C Trackpads, including the ones used in 2012 Samsung Chromebooks. diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 2ce0149..840f5d6 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "cyapa.h" @@ -264,6 +265,79 @@ struct cyapa_gen5_report_data { struct cyapa_gen5_touch_record touch_records[10]; } __packed; +struct cyapa_tsg_bin_image_head { + u8 head_size; /* Unit: bytes, including itself. */ + u8 ttda_driver_major_version; /* Reserved as 0. */ + u8 ttda_driver_minor_version; /* Reserved as 0. */ + u8 fw_major_version; + u8 fw_minor_version; + u8 fw_revision_control_number[8]; +} __packed; + +struct cyapa_tsg_bin_image_data_record { + u8 flash_array_id; + __be16 row_number; + /* The number of bytes of flash data contained in this record. */ + __be16 record_len; + /* The flash program data. */ + u8 record_data[CYAPA_TSG_FW_ROW_SIZE]; +} __packed; + +struct cyapa_tsg_bin_image { + struct cyapa_tsg_bin_image_head image_head; + struct cyapa_tsg_bin_image_data_record records[0]; +} __packed; + +struct gen5_bl_packet_start { + u8 sop; /* Start of packet, must be 01h */ + u8 cmd_code; + __le16 data_length; /* Size of data parameter start from data[0] */ +} __packed; + +struct gen5_bl_packet_end { + __le16 crc; + u8 eop; /* End of packet, must be 17h */ +} __packed; + +struct gen5_bl_cmd_head { + __le16 addr; /* Output report register address, must be 0004h */ + /* Size of packet not including output report register address */ + __le16 length; + u8 report_id; /* Bootloader output report id, must be 40h */ + u8 rsvd; /* Reserved, must be 0 */ + struct gen5_bl_packet_start packet_start; + u8 data[0]; /* Command data variable based on commands */ +} __packed; + +/* Initiate bootload command data structure. */ +struct gen5_bl_initiate_cmd_data { + /* Key must be "A5h 01h 02h 03h FFh FEh FDh 5Ah" */ + u8 key[CYAPA_TSG_BL_KEY_SIZE]; + u8 metadata_raw_parameter[CYAPA_TSG_FLASH_MAP_METADATA_SIZE]; + __le16 metadata_crc; +} __packed; + +struct gen5_bl_metadata_row_params { + __le16 size; + __le16 maximun_size; + __le32 app_start; + __le16 app_len; + __le16 app_crc; + __le32 app_entry; + __le32 upgrade_start; + __le16 upgrade_len; + __le16 entry_row_crc; + u8 padding[36]; /* Padding data must be 0 */ + __le16 metadata_crc; /* CRC starts at offset of 60 */ +} __packed; + +/* Bootload program and verify row command data structure */ +struct gen5_bl_flash_row_head { + u8 flash_array_id; + __le16 flash_row_id; + u8 flash_data[0]; +} __packed; + struct gen5_app_cmd_head { __le16 addr; /* Output report register address, must be 0004h */ /* Size of packet not including output report register address */ @@ -297,6 +371,10 @@ struct gen5_app_get_parameter_data { #define GEN5_DEV_UNINIT_SLEEP_TIME(cyapa) \ (((cyapa)->dev_sleep_time) == UNINIT_SLEEP_TIME) + +static u8 cyapa_gen5_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03, + 0xff, 0xfe, 0xfd, 0x5a }; + static int cyapa_gen5_initialize(struct cyapa *cyapa) { struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5; @@ -618,6 +696,22 @@ static bool cyapa_gen5_sort_tsg_pip_app_resp_data(struct cyapa *cyapa, return false; } +static bool cyapa_gen5_sort_application_launch_data(struct cyapa *cyapa, + u8 *buf, int len) +{ + if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE) + return false; + + /* +* After reset or power on, trackpad device always sets to 0x00 0x00 +* to indicate a reset or power on event. +*/ + if (buf[0] == 0 && buf[1] == 0) + return true; + + return false; +} + static bool cyapa_gen5_sort_hid_descriptor_data(struct cyapa *cyapa, u8 *buf, int len) { @@ -923,6 +1017,8
[PATCH v16 05/12] input: cyapa: add sysfs interfaces support in the cyapa driver
Add device's basic control and features supported in cyapa driver through sysfs file system interfaces. These interfaces are commonly used in pre- and after production, for trackpad device state checking, managing and firmware image updating. These interfaces including mode, firmware_version and product_id interfaces for reading firmware version and trackpad device product id values, and including update_fw interface to command firmware image update process. Also including baseline and calibrate interfaces for reading and checking trackpad device's sensors states. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 327 1 file changed, 327 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 3bcfce3..406f38b 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -32,6 +32,8 @@ #define CYAPA_ADAPTER_FUNC_SMBUS 2 #define CYAPA_ADAPTER_FUNC_BOTH 3 +#define CYAPA_FW_NAME "cyapa.bin" + const char product_id[] = "CYTRA"; static int cyapa_reinitialize(struct cyapa *cyapa); @@ -442,6 +444,29 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) return 0; } +static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa) +{ + struct input_dev *input = cyapa->input; + + if (!input || !input->users) { + if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0); + enable_irq(cyapa->client->irq); + } +} + +static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa) +{ + struct input_dev *input = cyapa->input; + + if (!input || !input->users) { + disable_irq(cyapa->client->irq); + if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + } +} + /* * cyapa_sleep_time_to_pwr_cmd and cyapa_pwr_cmd_to_sleep_time * @@ -783,6 +808,295 @@ static int cyapa_start_runtime(struct cyapa *cyapa) } #endif /* CONFIG_PM_RUNTIME */ +static ssize_t cyapa_show_fm_ver(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int error; + struct cyapa *cyapa = dev_get_drvdata(dev); + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + error = scnprintf(buf, PAGE_SIZE, "%d.%d\n", cyapa->fw_maj_ver, +cyapa->fw_min_ver); + mutex_unlock(&cyapa->state_sync_lock); + return error; +} + +static ssize_t cyapa_show_product_id(struct device *dev, +struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int size; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + size = scnprintf(buf, PAGE_SIZE, "%s\n", cyapa->product_id); + mutex_unlock(&cyapa->state_sync_lock); + return size; +} + +static int cyapa_firmware(struct cyapa *cyapa, const char *fw_name) +{ + struct device *dev = &cyapa->client->dev; + const struct firmware *fw; + int error; + + error = request_firmware(&fw, fw_name, dev); + if (error) { + dev_err(dev, "Could not load firmware from %s: %d\n", + fw_name, error); + return error; + } + + if (cyapa->ops->check_fw) { + error = cyapa->ops->check_fw(cyapa, fw); + if (error) { + dev_err(dev, "Invalid CYAPA firmware image: %s\n", + fw_name); + goto done; + } + } else { + dev_err(dev, "No valid device ops->check_fw handler set.\n"); + error = -ENODEV; + goto done; + } + + /* +* Resume the potentially suspended device because doing FW +* update on a device not in the FULL mode has a chance to +* fail. +*/ + pm_runtime_get_sync(dev); + + /* Require IRQ support for firmware update commands. */ + cyapa_enable_irq_for_cmd(cyapa); + + if (cyapa->ops->bl_enter) { + error = cyapa->ops->bl_enter(cyapa); + if (error) { + dev_err(dev, "bl_enter failed, %d\n", error); + goto err_detect; + } + } + + if (cyapa->ops->bl_activate) { + error = cyapa->ops->bl_activate(cyapa); +
[PATCH v16 06/12] input: cyapa: add gen3 trackpad device firmware update function support
Add firmware image update function supported for gen3 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 288 +++ 1 file changed, 288 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 228fd2d..cd4f1db 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "cyapa.h" @@ -115,6 +116,18 @@ struct cyapa_reg_data { struct cyapa_touch touches[5]; } __packed; +struct gen3_write_block_cmd { + u8 checksum_seed; /* Always be 0xff */ + u8 cmd_code; /* command code: 0x39 */ + u8 key[8]; /* 8-byte security key */ + __be16 block_num; + u8 block_data[CYAPA_FW_BLOCK_SIZE]; + u8 block_checksum; /* Calculated using bytes 12 - 75 */ + u8 cmd_checksum;/* Calculated using bytes 0-76 */ +} __packed; + +static const u8 security_key[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; static const u8 bl_activate[] = { 0x00, 0xff, 0x38, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; static const u8 bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03, @@ -423,6 +436,69 @@ 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. + * + * Returns: + * 0on 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 error; + + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; + if (cyapa->state == CYAPA_STATE_BL_IDLE) { + /* Already in BL_IDLE. Skipping reset. */ + return 0; + } + + if (cyapa->state != CYAPA_STATE_OP) + return -EAGAIN; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + error = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01); + if (error) + return -EIO; + + usleep_range(25000, 5); + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; + 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 error; + + error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate), + bl_activate); + if (error) + return error; + + /* Wait for bootloader to activate; takes between 2 and 12 seconds */ + msleep(2000); + error = cyapa_poll_state(cyapa, 11000); + if (error) + return error; + if (cyapa->state != CYAPA_STATE_BL_ACTIVE) + return -EAGAIN; + + return 0; +} + static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { int error; @@ -483,6 +559,212 @@ static int cyapa_gen3_bl_exit(struct cyapa *cyapa) return 0; } +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); + i
[PATCH v16 07/12] input: cyapa: add gen3 trackpad device read baseline function support
Add read baseline function supported for gen3 trackpad device, it can be used through sysfs baseline interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 72 1 file changed, 72 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index cd4f1db..92b3d6d 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -765,6 +765,76 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_show_baseline(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int max_baseline, min_baseline; + int tries; + int ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_REPORT_BASELINE_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send report baseline command. %d\n", + ret); + goto out; + } + + tries = 3; /* Try for 30 to 60 ms */ + do { + usleep_range(1, 2); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Device timed out going to Normal state.\n"); + ret = -ETIMEDOUT; + goto out; + } + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MAX_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read max baseline. err = %d\n", ret); + goto out; + } + max_baseline = ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MIN_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read min baseline. err = %d\n", ret); + goto out; + } + min_baseline = ret; + + dev_dbg(dev, "Baseline report successful. Max: %d Min: %d\n", + max_baseline, min_baseline); + ret = scnprintf(buf, PAGE_SIZE, "%d %d\n", max_baseline, min_baseline); + +out: + return ret; +} + /* * cyapa_get_wait_time_for_pwr_cmd * @@ -1079,6 +1149,8 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .update_fw = cyapa_gen3_do_fw_update, .bl_deactivate = cyapa_gen3_bl_deactivate, + .show_baseline = cyapa_gen3_show_baseline, + .state_parse = cyapa_gen3_state_parse, .operational_check = cyapa_gen3_do_operational_check, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v16 03/12] input: cyapa: add power management interfaces support for the device
Add suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 111 1 file changed, 111 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index d4560a3..73f6817 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -575,6 +575,96 @@ out: return IRQ_HANDLED; } +/* + ** + * sysfs interface + ** +*/ +#ifdef CONFIG_PM_SLEEP +static ssize_t cyapa_show_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd = cyapa->suspend_power_mode; + u16 sleep_time; + int len; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + pwr_cmd = cyapa->suspend_power_mode; + sleep_time = cyapa->suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (pwr_cmd == PWR_MODE_BTN_ONLY) { + len = scnprintf(buf, PAGE_SIZE, "%s\n", BTN_ONLY_MODE_NAME); + } else if (pwr_cmd == PWR_MODE_OFF) { + len = scnprintf(buf, PAGE_SIZE, "%s\n", OFF_MODE_NAME); + } else { + if (cyapa->gen == CYAPA_GEN3) + sleep_time = cyapa_pwr_cmd_to_sleep_time(pwr_cmd); + len = scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); + } + + return len; +} + +static ssize_t cyapa_update_suspend_scanrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 sleep_time; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + + if (sysfs_streq(buf, BTN_ONLY_MODE_NAME)) { + cyapa->suspend_power_mode = PWR_MODE_BTN_ONLY; + } else if (sysfs_streq(buf, OFF_MODE_NAME)) { + cyapa->suspend_power_mode = PWR_MODE_OFF; + } else if (!kstrtou16(buf, 10, &sleep_time)) { + cyapa->suspend_sleep_time = max_t(u16, sleep_time, 1000); + cyapa->suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time); + } else { + count = 0; + } + + mutex_unlock(&cyapa->state_sync_lock); + + if (!count) + dev_err(dev, "invalid suspend scanrate ms parameters\n"); + return count ? count : -EINVAL; +} + +static DEVICE_ATTR(suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_suspend_scanrate, + cyapa_update_suspend_scanrate); + +static struct attribute *cyapa_power_wakeup_entries[] = { + &dev_attr_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_wakeup_group = { + .name = power_group_name, + .attrs = cyapa_power_wakeup_entries, +}; + +static void cyapa_remove_power_wakeup_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_wakeup_group); +} +#endif /* CONFIG_PM_SLEEP */ + static int cyapa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { @@ -614,6 +704,27 @@ static int cyapa_probe(struct i2c_client *client, return error; } +#ifdef CONFIG_PM_SLEEP + if (device_can_wakeup(dev)) { + error = sysfs_merge_group(&client->dev.kobj, + &cyapa_power_wakeup_group); + if (error) { + dev_err(dev, "failed to add power wakeup group: %d\n", + error); + return error; + } + + error = devm_add_action(dev, + cyapa_remove_power_wakeup_group, cyapa); + if (error) { + cyapa_remove_power_wakeup_group(cyapa); + dev_err(dev, "failed to add power cleanup action: %d\n", + error); + return error; + } + } +#endif /* CONFIG_PM_SLEEP */ + error = devm_request_threaded_irq(dev, client->irq,
[PATCH v16 12/12] input: cyapa: add acpi device id support
Add acpi device tree support. acpi device id "CYAP" is for old gen3 trackpad devices. acpi device id "CYAP0001" is for new gen5 trackpad devices. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 406f38b..62ef19a 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "cyapa.h" @@ -1315,11 +1316,23 @@ static const struct i2c_device_id cyapa_id_table[] = { }; MODULE_DEVICE_TABLE(i2c, cyapa_id_table); +#ifdef CONFIG_ACPI +static const struct acpi_device_id cyapa_acpi_id[] = { + { "CYAP", 0 }, /* Gen3 trackpad with 0x67 I2C address. */ + { "CYAP0001", 0 }, /* Gen5 trackpad with 0x24 I2C address. */ + { } +}; +MODULE_DEVICE_TABLE(acpi, cyapa_acpi_id); +#endif + static struct i2c_driver cyapa_driver = { .driver = { .name = "cyapa", .owner = THIS_MODULE, .pm = &cyapa_pm_ops, +#ifdef CONFIG_ACPI + .acpi_match_table = ACPI_PTR(cyapa_acpi_id), +#endif }, .probe = cyapa_probe, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v16 11/12] input: cyapa: add gen5 trackpad device force re-calibrate function support
Add force re-calibrate function supported for gen5 trackpad device, it can be used through sysfs calibrate interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 65 1 file changed, 65 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 2b800e3..4bb6f34 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1713,6 +1713,70 @@ static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) return 0; } +static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa, + u8 calibrate_sensing_mode_type) +{ + struct gen5_app_cmd_head *app_cmd_head; + u8 cmd[8]; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + memset(cmd, 0, sizeof(cmd)); + app_cmd_head = (struct gen5_app_cmd_head *)cmd; + put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); + put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length); + app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID; + app_cmd_head->cmd_code = GEN5_CMD_CALIBRATE; + app_cmd_head->parameter_data[0] = calibrate_sensing_mode_type; + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 5000, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_CALIBRATE) || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return error < 0 ? error : -EAGAIN; + + return 0; +} + +static ssize_t cyapa_gen5_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int error, calibrate_error; + + /* 1. Suspend Scanning*/ + error = cyapa_gen5_suspend_scanning(cyapa); + if (error) + return error; + + /* 2. Do mutual capacitance fine calibrate. */ + calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_MUTUAL_CAP_FINE); + if (calibrate_error) + goto resume_scanning; + + /* 3. Do self capacitance calibrate. */ + calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_SELF_CAP); + if (calibrate_error) + goto resume_scanning; + +resume_scanning: + /* 4. Resume Scanning*/ + error = cyapa_gen5_resume_scanning(cyapa); + if (error || calibrate_error) + return error ? error : calibrate_error; + + return count; +} + static s32 twos_complement_to_s32(s32 value, int num_bits) { if (value >> (num_bits - 1)) @@ -2689,6 +2753,7 @@ const struct cyapa_dev_ops cyapa_gen5_ops = { .update_fw = cyapa_gen5_do_fw_update, .show_baseline = cyapa_gen5_show_baseline, + .calibrate_store = cyapa_gen5_do_calibrate, .initialize = cyapa_gen5_initialize, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v16 08/12] input: cyapa: add gen3 trackpad device force re-calibrate function support
Add force re-calibrate function supported for gen3 trackpad device, it can be used through sysfs calibrate interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 59 1 file changed, 59 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 92b3d6d..7351fce 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -765,6 +765,64 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int tries; + int ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status: %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy, device state: 0x%02x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_RECALIBRATION_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send calibrate command: %d\n", + ret); + goto out; + } + + tries = 20; /* max recalibration timeout 2s. */ + do { + /* +* For this recalibration, the max time will not exceed 2s. +* The average time is approximately 500 - 700 ms, and we +* will check the status every 100 - 200ms. +*/ + usleep_range(10, 20); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status: %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Failed to calibrate. Timeout.\n"); + ret = -ETIMEDOUT; + goto out; + } + dev_dbg(dev, "Calibration successful.\n"); + +out: + return ret < 0 ? ret : count; +} + static ssize_t cyapa_gen3_show_baseline(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1150,6 +1208,7 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .bl_deactivate = cyapa_gen3_bl_deactivate, .show_baseline = cyapa_gen3_show_baseline, + .calibrate_store = cyapa_gen3_do_calibrate, .state_parse = cyapa_gen3_state_parse, .operational_check = cyapa_gen3_do_operational_check, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v16 00/12] input: cyapa: instruction of cyapa patches
V16 patches have below updates, details of other updates see history list: 1) Fix all miss-spelling and space issue. 2) Rename variables and functions with much more clearer names. 3) Initialize and document tries near where it will be used. 4) Modify cmd buffer to struct for more descriptive way. This patch series is aimed to re-design the cyapa driver to support old gen3 trackpad devices and new gen5 trackpad devices in one cyapa driver, it's for easily productions support based on customers' requirements. And add sysfs functions and interfaces supported that required by users and customers. Since the earlier gen3 and the latest gen5 trackpad devices using two different chipsets, and have different protocols and interfaces, so if supported these two type trackpad devices in two different drivers, then it will be difficult to manage productions and later firmware updates. e.g.: It will cause customer don't know which one trackpad device firmware image to use and update when it has been used and integrated in same one productions, so here we support these two trackpad devices in same on driver. Dudley Du (12): input: cyapa: re-design driver to support multi-trackpad in one driver input: cyapa: add gen5 trackpad device basic functions support input: cyapa: add power management interfaces support for the device input: cyapa: add runtime power management interfaces support for the device input: cyapa: add sysfs interfaces support in the cyapa driver input: cyapa: add gen3 trackpad device firmware update function support input: cyapa: add gen3 trackpad device read baseline function support input: cyapa: add gen3 trackpad device force re-calibrate function support input: cyapa: add gen5 trackpad device firmware update function support input: cyapa: add gen5 trackpad device read baseline function support input: cyapa: add gen5 trackpad device force re-calibrate function support input: cyapa: add acpi device id support drivers/input/mouse/Kconfig |1 + drivers/input/mouse/Makefile |3 +- drivers/input/mouse/cyapa.c | 1692 ++- drivers/input/mouse/cyapa.h | 314 + drivers/input/mouse/cyapa_gen3.c | 1220 + drivers/input/mouse/cyapa_gen5.c | 2767 ++ 6 files changed, 5325 insertions(+), 672 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h create mode 100644 drivers/input/mouse/cyapa_gen3.c create mode 100644 drivers/input/mouse/cyapa_gen5.c History patch series modifications list: V15 patches have below main updates compared with v14 patches: 1) Fix all warning errors of sparse tool when running with "make C=1". 2) Change variable name "unique_str" to "product_id" for clearer meanings. 3) Update cyapa_i2c_write function to return error directly when length > 31. V14 patches have below main updates compared with v13 patches: 1) Correct 9 miss spelling issues of "bufferred" to "buffered". 2) Fix the upgrade issue of removing MOUSE_CYAPA config when make oldconfig by replase "depends on I2C && CRC_ITU_T" with "depends on I2C" "select CRC_ITU_T" in patch 9. V13 patches have below main updates compared with v12 patches: 1) Remove all debugfs interface, including read_fw and raw_data interfaces. 2) This patches are made based linux next-20141208. V12 patches have below main updates compared with v11 patches: 1) Add check that when TP is detected but not operational, do not exit driver immediately, but wait and export the update_fw interface for recovering. 2) Re-arrange the function codes, remove unnesseary protype definitions in the header file. V11 patches have below main updates compared with v10 patches: 1) Add add acpi device id supported for old gen3 and new gen5 trackpad devices. 2) Fix the unable to update firmware issue when cyapa_open is not called which means the irq for firwmare update process is not enabled. This fix by checking if the irq is enabled, if not then enable irq before start to do firmware update. V10 patches have below main updates compared with v9 patches: 1) Modify code to following kernel code style. e.g.: correct to use error as return name when there is only error path, and fix the checkpatch.sh wanting in the driver. 2) Remove cyapa_remove method and use input open and close interface to following device resouse management infrastructure. 3) Modify cyapa_detect method to return tristate issue to make the return value much more consistent and clear. 4) Use platform supplied functions as possible instead of driver specific rewritten version. V9 patches have below updates compared with v8 patches: 1) Removed all async thread stuff from the driver. 2) Split driver into 18 patches for each function change one patch. V8 patches have below updates compared wit
[PATCH v16 01/12] input: cyapa: re-design driver to support multi-trackpad in one driver
In order to support multiple different chipsets and communication protocols trackpad devices in one cyapa driver, the new cyapa driver is re-designed with one cyapa driver core and multiple device specific functions component. The cyapa driver core is contained in this patch, it supplies basic functions that working with kernel and input subsystem, and also supplies the interfaces that the specific devices' component can connect and work together with as one driver. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |3 +- drivers/input/mouse/cyapa.c | 1047 ++ drivers/input/mouse/cyapa.h | 307 +++ drivers/input/mouse/cyapa_gen3.c | 801 + 4 files changed, 1492 insertions(+), 666 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h create mode 100644 drivers/input/mouse/cyapa_gen3.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 560003d..8bd950d 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974)+= bcm5974.o -obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o @@ -24,6 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o +cyapatp-objs := cyapa.o cyapa_gen3.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 1bece8c..ae1df15 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -20,408 +20,100 @@ #include #include #include +#include #include +#include +#include "cyapa.h" -/* APA trackpad firmware generation */ -#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ - -#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" - -/* commands for read/write registers of Cypress trackpad */ -#define CYAPA_CMD_SOFT_RESET 0x00 -#define CYAPA_CMD_POWER_MODE 0x01 -#define CYAPA_CMD_DEV_STATUS 0x02 -#define CYAPA_CMD_GROUP_DATA 0x03 -#define CYAPA_CMD_GROUP_CMD0x04 -#define CYAPA_CMD_GROUP_QUERY 0x05 -#define CYAPA_CMD_BL_STATUS0x06 -#define CYAPA_CMD_BL_HEAD 0x07 -#define CYAPA_CMD_BL_CMD 0x08 -#define CYAPA_CMD_BL_DATA 0x09 -#define CYAPA_CMD_BL_ALL 0x0a -#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b -#define CYAPA_CMD_BLK_HEAD 0x0c - -/* report data start reg offset address. */ -#define DATA_REG_START_OFFSET 0x - -#define BL_HEAD_OFFSET 0x00 -#define BL_DATA_OFFSET 0x10 - -/* - * Operational Device Status Register - * - * bit 7: Valid interrupt source - * bit 6 - 4: Reserved - * bit 3 - 2: Power status - * bit 1 - 0: Device status - */ -#define REG_OP_STATUS 0x00 -#define OP_STATUS_SRC 0x80 -#define OP_STATUS_POWER 0x0c -#define OP_STATUS_DEV 0x03 -#define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) - -/* - * Operational Finger Count/Button Flags Register - * - * bit 7 - 4: Number of touched finger - * bit 3: Valid data - * bit 2: Middle Physical Button - * bit 1: Right Physical Button - * bit 0: Left physical Button - */ -#define REG_OP_DATA1 0x01 -#define OP_DATA_VALID 0x08 -#define OP_DATA_MIDDLE_BTN 0x04 -#define OP_DATA_RIGHT_BTN 0x02 -#define OP_DATA_LEFT_BTN 0x01 -#define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ - OP_DATA_LEFT_BTN) - -/* - * Bootloader Status Register - * - * bit 7: Busy - * bit 6 - 5: Reserved - * bit 4: Bootloader running - * bit 3 - 1: Reserved - * bit 0: Checksum valid - */ -#define REG_BL_STATUS0x01 -#define BL_STATUS_BUSY 0x80 -#define BL_STATUS_RUNNING0x10 -#define BL_STATUS_DATA_VALID 0x08 -#define BL_STATUS_CSUM_VALID 0x01 - -/* - * Bootloader Error Register - * - * bit 7: Invalid - * bit 6: Invalid security key - * bit 5: Bootloading - * bit 4: Command checksum - * bit 3: Flash protection error - * bit 2: Flash checksum error - * bit 1 - 0: Reserved - */ -#define REG_BL_ERROR 0x02 -#define BL_ERROR_INVALID 0x80 -#define BL_ERROR_INVALID_KEY 0x40 -#define BL_ERROR_BOOTLOADING 0x20 -#define BL_ERROR_CMD_CSUM0x10 -#define BL_ERROR_FLASH_PROT 0x08 -#define BL_ERROR_FLASH_CSUM 0x04 - -#define BL_STATUS_SIZE 3 /* length of bootloader status registers */ -#define BLK_HEAD_BYTES 32 - -#define PRODUCT_ID_SIZE 16 -#d
[PATCH v16 02/12] input: cyapa: add gen5 trackpad device basic functions support
Based on the cyapa core, add the gen5 trackpad device's basic functions supported, so gen5 trackpad device can work with kernel input system. And also based on the state parse interface, the cyapa driver can automatically determine the attached is gen3 or gen5 protocol trackpad device, then set the correct protocol to work with the attached trackpad device. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |2 +- drivers/input/mouse/cyapa.c | 13 + drivers/input/mouse/cyapa.h |1 + drivers/input/mouse/cyapa_gen5.c | 1677 ++ 4 files changed, 1692 insertions(+), 1 deletion(-) create mode 100644 drivers/input/mouse/cyapa_gen5.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 8bd950d..8a9c98e 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o -cyapatp-objs := cyapa.o cyapa_gen3.o +cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index ae1df15..d4560a3 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -157,6 +157,14 @@ static int cyapa_get_state(struct cyapa *cyapa) if (!error) goto out_detected; } + if ((cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN5) && + !smbus && even_addr) { + error = cyapa_gen5_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (!error) + goto out_detected; + } /* * Write 0x00 0x00 to trackpad device to force update its @@ -240,6 +248,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return error; switch (cyapa->gen) { + case CYAPA_GEN5: + cyapa->ops = &cyapa_gen5_ops; + break; case CYAPA_GEN3: cyapa->ops = &cyapa_gen3_ops; break; @@ -476,6 +487,8 @@ static int cyapa_initialize(struct cyapa *cyapa) if (cyapa_gen3_ops.initialize) error = cyapa_gen3_ops.initialize(cyapa); + if (!error && cyapa_gen5_ops.initialize) + error = cyapa_gen5_ops.initialize(cyapa); if (error) return error; diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index 8a75c52..4c09be4 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -303,5 +303,6 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode); extern const char product_id[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; +extern const struct cyapa_dev_ops cyapa_gen5_ops; #endif diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c new file mode 100644 index 000..2ce0149 --- /dev/null +++ b/drivers/input/mouse/cyapa_gen5.c @@ -0,0 +1,1677 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du + * + * Copyright (C) 2014 Cypress Semiconductor, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cyapa.h" + + +/* Macro of Gen5 */ +#define RECORD_EVENT_NONE0 +#define RECORD_EVENT_TOUCHDOWN 1 +#define RECORD_EVENT_DISPLACE2 +#define RECORD_EVENT_LIFTOFF 3 + +#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80 +#define CYAPA_TSG_IMG_FW_HDR_SIZE 13 +#define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE) +#define CYAPA_TSG_IMG_START_ROW_NUM 0x002e +#define CYAPA_TSG_IMG_END_ROW_NUM 0x01fe +#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff +#define CYAPA_TSG_IMG_MAX_RECORDS (CYAPA_TSG_IMG_END_ROW_NUM - \ + CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1) +#define CYAPA_TSG_IMG_READ_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2) +#define CYAPA_TSG_START_OF_APPLICATION 0x1700 +#define CYAPA_TSG_APP_INTEGRITY_SIZE60 +#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE 60 +#define CYAPA_TSG_BL_KEY_SIZE 8 + +#define CYAPA_TSG_MAX_CMD_SIZE 256 + +#define GEN5_BL_CMD_VERIFY_APP_INTEGRITY0x31 +#define GEN5_BL_CMD_GET_BL_INFO0x38 +#define GEN5_BL_CMD_PROGRAM_VERIFY_ROW
RE: [PATCH v16 00/12] input: cyapa: instruction of cyapa patches
Jeremiah, I re-sent the v16 patches through the new internal email server with my emal d...@cypress.com. Could you help check if all patches were fine and not broken. Thanks, Dudley > -Original Message- > From: Dudley Du [mailto:d...@cypress.com] > Sent: 2014?12?18? 18:01 > To: dmitry.torok...@gmail.com; jmmah...@gmail.com; rydb...@euromail.se > Cc: Dudley Du; ble...@google.com; David Solda; linux-in...@vger.kernel.org; > linux-kernel@vger.kernel.org > Subject: [PATCH v16 00/12] input: cyapa: instruction of cyapa patches > > V16 patches have below updates, details of other updates see history list: > 1) Fix all miss-spelling and space issue. > 2) Rename variables and functions with much more clearer names. > 3) Initialize and document tries near where it will be used. > 4) Modify cmd buffer to struct for more descriptive way. > > > This patch series is aimed to re-design the cyapa driver to support > old gen3 trackpad devices and new gen5 trackpad devices in one > cyapa driver, it's for easily productions support based on > customers' requirements. And add sysfs functions and interfaces > supported that required by users and customers. > > Since the earlier gen3 and the latest gen5 trackpad devices using > two different chipsets, and have different protocols and interfaces, > so if supported these two type trackpad devices in two different drivers, > then it will be difficult to manage productions and later firmware updates. > e.g.: It will cause customer don't know which one trackpad device firmware > image to use and update when it has been used and integrated > in same one productions, so here we support these two trackpad > devices in same on driver. > > > Dudley Du (12): > input: cyapa: re-design driver to support multi-trackpad in one driver > input: cyapa: add gen5 trackpad device basic functions support > input: cyapa: add power management interfaces support for the device > input: cyapa: add runtime power management interfaces support for the > device > input: cyapa: add sysfs interfaces support in the cyapa driver > input: cyapa: add gen3 trackpad device firmware update function > support > input: cyapa: add gen3 trackpad device read baseline function support > input: cyapa: add gen3 trackpad device force re-calibrate function > support > input: cyapa: add gen5 trackpad device firmware update function > support > input: cyapa: add gen5 trackpad device read baseline function support > input: cyapa: add gen5 trackpad device force re-calibrate function > support > input: cyapa: add acpi device id support > > drivers/input/mouse/Kconfig |1 + > drivers/input/mouse/Makefile |3 +- > drivers/input/mouse/cyapa.c | 1692 ++- > drivers/input/mouse/cyapa.h | 314 + > drivers/input/mouse/cyapa_gen3.c | 1220 + > drivers/input/mouse/cyapa_gen5.c | 2767 > ++ > 6 files changed, 5325 insertions(+), 672 deletions(-) > create mode 100644 drivers/input/mouse/cyapa.h > create mode 100644 drivers/input/mouse/cyapa_gen3.c > create mode 100644 drivers/input/mouse/cyapa_gen5.c > > > History patch series modifications list: > V15 patches have below main updates compared with v14 patches: > 1) Fix all warning errors of sparse tool when running with "make C=1". > 2) Change variable name "unique_str" to "product_id" for clearer meanings. > 3) Update cyapa_i2c_write function to return error directly when length > 31. > > V14 patches have below main updates compared with v13 patches: > 1) Correct 9 miss spelling issues of "bufferred" to "buffered". > 2) Fix the upgrade issue of removing MOUSE_CYAPA config when make oldconfig >by replase "depends on I2C && CRC_ITU_T" with > "depends on I2C" > "select CRC_ITU_T" >in patch 9. > > V13 patches have below main updates compared with v12 patches: > 1) Remove all debugfs interface, including read_fw and raw_data interfaces. > 2) This patches are made based linux next-20141208. > > V12 patches have below main updates compared with v11 patches: > 1) Add check that when TP is detected but not operational, do not exit driver >immediately, but wait and export the update_fw interface for recovering. > 2) Re-arrange the function codes, remove unnesseary protype definitions in >the header file. > > V11 patches have below main updates compared with v10 patches: > 1) Add add acpi device id supported for old gen3 and new gen5 trackpad > devices. > 2) Fix the unable to update firmware issue when cyapa_open is not called >whic
RE: [PATCH v16 00/12] input: cyapa: instruction of cyapa patches
Benson, Jeremiah, Thank you for the help and confirm. Dudley > -Original Message- > From: Jeremiah Mahler [mailto:jmmah...@gmail.com] > Sent: 2014?12?19? 6:14 > To: Dudley Du > Cc: dmitry.torok...@gmail.com; rydb...@euromail.se; ble...@google.com; > David Solda; linux-in...@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH v16 00/12] input: cyapa: instruction of cyapa patches > > Dudley, > > On Thu, Dec 18, 2014 at 11:06:40AM +, Dudley Du wrote: > > Jeremiah, > > > > I re-sent the v16 patches through the new internal email server with my emal > d...@cypress.com. > > Could you help check if all patches were fine and not broken. > > > > Thanks, > > Dudley > > > [...] > > These patches apply without any problems. > > I will have a look and review them again. > > -- > - Jeremiah Mahler 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. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v11 00/19] input: cyapa: instruction of cyapa patches
Jeremiah, Thank you very much for your information. I will look into this issue. Could you send me the system log if possible when you encounter this issue. Thanks Dudley > -Original Message- > From: Jeremiah Mahler [mailto:jmmah...@gmail.com] > Sent: 2014?11?21? 16:56 > To: Dudley Du > Cc: linux-kernel@vger.kernel.org > Subject: Re: [PATCH v11 00/19] input: cyapa: instruction of cyapa patches > > Dudley, > > On Wed, Nov 19, 2014 at 04:37:32PM +0800, Dudley Du wrote: > > V11 patches have below main updates compared with v10 patches: > > 1) Add add acpi device id supported for old gen3 and new gen5 trackpad devices. > > 2) Fix the unable to update firmware issue when cyapa_open is not called > >which means the irq for firwmare update process is not enabled. This fix > [] > > I am having a problem with an older patch which is currently in > linux-next (20141120) and which might be related to this new patch set. > > On an Acer C720 if a suspend and resume is performed the touchpad will > stop working. If the cyapa driver is reloaded it will begin working > again. > > I performed a bisect and found that the following patch was the cause. > > From b1cfa7b4388285c0f0b486f152ab0cb18612c779 Mon Sep 17 00:00:00 2001 > From: Dudley Du > Date: Sun, 9 Nov 2014 12:36:34 -0800 > Subject: [PATCH] Input: cyapa - switch to using managed resources > > Use of managed resources simplifies error handling and device removal > code. > > Signed-off-by: Dudley Du > [Dmitry: added open/close methods so cyapa_remove is no longer needed.] > Signed-off-by: Dmitry Torokhov > > If I can provide any other information that would be of help let me know. > I will try out your new patchset if I get a chance. > > -- > - Jeremiah Mahler -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v11 02/19] input: cyapa: add device resource management infrastructure support
Remove cyapa_remove() method, add cyapa_open() and cyapa_close() methods for input interface, also modified together with driver's memory and IRQ resource allocations to support device resource management infrastructure to reduce the mistakes of resource management. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 77 + 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index c35f398..06c94a3 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -753,6 +753,22 @@ static u8 cyapa_check_adapter_functionality(struct i2c_client *client) return ret; } +static int cyapa_open(struct input_dev *input) +{ + struct cyapa *cyapa = input_get_drvdata(input); + struct i2c_client *client = cyapa->client; + + enable_irq(client->irq); + return 0; +} + +static void cyapa_close(struct input_dev *input) +{ + struct cyapa *cyapa = input_get_drvdata(input); + + disable_irq(cyapa->client->irq); +} + static int cyapa_create_input_dev(struct cyapa *cyapa) { struct device *dev = &cyapa->client->dev; @@ -762,7 +778,7 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) if (!cyapa->physical_size_x || !cyapa->physical_size_y) return -EINVAL; - input = cyapa->input = input_allocate_device(); + input = cyapa->input = devm_input_allocate_device(dev); if (!input) { dev_err(dev, "allocate memory for input device failed\n"); return -ENOMEM; @@ -775,6 +791,9 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) input->id.product = 0; /* means any product in eventcomm. */ input->dev.parent = &cyapa->client->dev; + input->open = cyapa_open; + input->close = cyapa_close; + input_set_drvdata(input, cyapa); __set_bit(EV_ABS, input->evbit); @@ -807,21 +826,17 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) if (error) { dev_err(dev, "allocate memory for MT slots failed, %d\n", error); - goto err_free_device; + return error; } /* Register the device in input subsystem */ error = input_register_device(input); if (error) { dev_err(dev, "input device register failed, %d\n", error); - goto err_free_device; + return error; } - return 0; -err_free_device: - input_free_device(input); - cyapa->input = NULL; - return error; + return 0; } static int cyapa_probe(struct i2c_client *client, @@ -838,7 +853,7 @@ static int cyapa_probe(struct i2c_client *client, return -EIO; } - cyapa = kzalloc(sizeof(struct cyapa), GFP_KERNEL); + cyapa = devm_kzalloc(dev, sizeof(struct cyapa), GFP_KERNEL); if (!cyapa) return -ENOMEM; @@ -855,51 +870,45 @@ static int cyapa_probe(struct i2c_client *client, error = cyapa_check_is_operational(cyapa); if (error) { dev_err(dev, "device not operational, %d\n", error); - goto err_mem_free; - } - - error = cyapa_create_input_dev(cyapa); - if (error) { - dev_err(dev, "create input_dev instance failed, %d\n", error); - goto err_mem_free; + return error; } error = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); if (error) { dev_err(dev, "set active power failed, %d\n", error); - goto err_unregister_device; + return error; } cyapa->irq = client->irq; - error = request_threaded_irq(cyapa->irq, - NULL, - cyapa_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "cyapa", - cyapa); + error = devm_request_threaded_irq(dev, + cyapa->irq, + NULL, + cyapa_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "cyapa", + cyapa); if (error) { dev_err(dev, "IRQ request failed: %d\n, ", error); - goto err_unregister_device; + return error; } + /* Disable IRQ until the device is opened. */ + disable_irq(client->irq); - return 0; - -err_unregister_device: - input_unregister_device(cya
[PATCH v11 05/19] input: cyapa: add power management interfaces supported for the device
Add suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 105 1 file changed, 105 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index a053a90..9fc60c3 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -505,6 +505,90 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode) : (encoded_time - 5) * 20; } +#ifdef CONFIG_PM_SLEEP +static ssize_t cyapa_show_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd = cyapa->suspend_power_mode; + u16 sleep_time; + int len; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + pwr_cmd = cyapa->suspend_power_mode; + sleep_time = cyapa->suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (pwr_cmd == PWR_MODE_BTN_ONLY) { + len = scnprintf(buf, PAGE_SIZE, "%s\n", BTN_ONLY_MODE_NAME); + } else if (pwr_cmd == PWR_MODE_OFF) { + len = scnprintf(buf, PAGE_SIZE, "%s\n", OFF_MODE_NAME); + } else { + if (cyapa->gen == CYAPA_GEN3) + sleep_time = cyapa_pwr_cmd_to_sleep_time(pwr_cmd); + len = scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); + } + + return len; +} + +static ssize_t cyapa_update_suspend_scanrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 sleep_time; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + + if (sysfs_streq(buf, BTN_ONLY_MODE_NAME)) { + cyapa->suspend_power_mode = PWR_MODE_BTN_ONLY; + } else if (sysfs_streq(buf, OFF_MODE_NAME)) { + cyapa->suspend_power_mode = PWR_MODE_OFF; + } else if (!kstrtou16(buf, 10, &sleep_time)) { + cyapa->suspend_sleep_time = max_t(u16, sleep_time, 1000); + cyapa->suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time); + } else { + count = 0; + } + + mutex_unlock(&cyapa->state_sync_lock); + if (!count) + dev_err(dev, "invalid suspend scanrate ms parameters\n"); + return count ? count : -EINVAL; +} + +static DEVICE_ATTR(suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_suspend_scanrate, + cyapa_update_suspend_scanrate); + +static struct attribute *cyapa_power_wakeup_entries[] = { + &dev_attr_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_wakeup_group = { + .name = power_group_name, + .attrs = cyapa_power_wakeup_entries, +}; + +static void cyapa_remove_power_wakeup_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_wakeup_group); +} +#endif /* CONFIG_PM_SLEEP */ + /* * Returns: * 0Driver and device initialization successfully done. @@ -576,6 +660,27 @@ static int cyapa_probe(struct i2c_client *client, return error; } +#ifdef CONFIG_PM_SLEEP + if (device_can_wakeup(dev)) { + error = sysfs_merge_group(&client->dev.kobj, + &cyapa_power_wakeup_group); + if (error) { + dev_err(dev, "failed to add power wakeup group: %d\n", + error); + return error; + } + + error = devm_add_action(dev, + cyapa_remove_power_wakeup_group, cyapa); + if (error) { + cyapa_remove_power_wakeup_group(cyapa); + dev_err(dev, "failed to add power cleanup action: %d\n", + error); + return error; + } + } +#endif /* CONFIG_PM_SLEEP */ + error = devm_request_threaded_irq(dev, client->irq, NULL, -- 1.9.1 -- To unsubscribe from this list: send
[PATCH v11 04/19] input: cyapa: add gen5 trackpad device basic functions support
Based on the cyapa core, add the gen5 trackpad device's basic functions supported, so gen5 trackpad device can work with kernel input system. And also based on the state parse interface, the cyapa driver can automatically determine the attached is gen3 or gen5 protocol trackpad device, then set the correct protocol to work with the attached trackpad device. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |2 +- drivers/input/mouse/cyapa.c | 13 + drivers/input/mouse/cyapa.h |1 + drivers/input/mouse/cyapa_gen5.c | 1658 ++ 4 files changed, 1673 insertions(+), 1 deletion(-) create mode 100644 drivers/input/mouse/cyapa_gen5.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 4bf6c83..1d3d997 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o -cyapatp-objs := cyapa.o cyapa_gen3.o +cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 3771c5b..a053a90 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -275,6 +275,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return error; switch (cyapa->gen) { + case CYAPA_GEN5: + cyapa->ops = &cyapa_gen5_ops; + break; case CYAPA_GEN3: cyapa->ops = &cyapa_gen3_ops; break; @@ -380,6 +383,14 @@ static int cyapa_get_state(struct cyapa *cyapa) if (!error) goto out_detected; } + if ((cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN5) && + !smbus && even_addr) { + error = cyapa_gen5_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (!error) + goto out_detected; + } /* * Write 0x00 0x00 to trackpad device to force update its @@ -518,6 +529,8 @@ static int cyapa_initialize(struct cyapa *cyapa) if (cyapa_gen3_ops.initialize) error = cyapa_gen3_ops.initialize(cyapa); + if (!error && cyapa_gen5_ops.initialize) + error = cyapa_gen5_ops.initialize(cyapa); if (error) return error; diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index aebc777..10eaff0 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -314,5 +314,6 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode); extern const char unique_str[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; +extern const struct cyapa_dev_ops cyapa_gen5_ops; #endif diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c new file mode 100644 index 000..ee93e63 --- /dev/null +++ b/drivers/input/mouse/cyapa_gen5.c @@ -0,0 +1,1658 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du + * + * Copyright (C) 2014 Cypress Semiconductor, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cyapa.h" + + +/* Macro of Gen5 */ +#define RECORD_EVENT_NONE0 +#define RECORD_EVENT_TOUCHDOWN 1 +#define RECORD_EVENT_DISPLACE2 +#define RECORD_EVENT_LIFTOFF 3 + +#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80 +#define CYAPA_TSG_IMG_FW_HDR_SIZE 13 +#define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE) +#define CYAPA_TSG_IMG_START_ROW_NUM 0x002e +#define CYAPA_TSG_IMG_END_ROW_NUM 0x01fe +#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff +#define CYAPA_TSG_IMG_MAX_RECORDS (CYAPA_TSG_IMG_END_ROW_NUM - \ + CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1) +#define CYAPA_TSG_IMG_READ_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2) +#define CYAPA_TSG_START_OF_APPLICATION 0x1700 +#define CYAPA_TSG_APP_INTEGRITY_SIZE60 +#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE 60 +#define CYAPA_TSG_BL_KEY_SIZE 8 + +/* Macro definitions for Gen5 trackpad device. */ +#define GEN5_TOUCH_REPORT_HEAD_SIZE 7 +#define GEN5_TOUCH_REPORT_MAX_SIZE 127 +#define GEN5_BTN_REPORT_HEAD_SIZE 6 +#define GEN5_BTN_REPORT_MAX_SIZE
[PATCH v11 00/19] input: cyapa: instruction of cyapa patches
V11 patches have below main updates compared with v10 patches: 1) Add add acpi device id supported for old gen3 and new gen5 trackpad devices. 2) Fix the unable to update firmware issue when cyapa_open is not called which means the irq for firwmare update process is not enabled. This fix by checking if the irq is enabled, if not then enable irq before start to do firmware update. V10 patches have below main updates compared with v9 patches: 1) Modify code to following kernel code style. e.g.: correct to use error as return name when there is only error path, and fix the checkpatch.sh wanting in the driver. 2) Remove cyapa_remove method and use input open and close interface to following device resouse management infrastructure. 3) Modify cyapa_detect method to return tristate issue to make the return value much more consistent and clear. 4) Use platform supplied functions as possible instead of driver specific rewritten version. V9 patches have below updates compared with v8 patches: 1) Removed all async thread stuff from the driver. 2) Split driver into 18 patches for each function change one patch. V8 patches have below updates compared with v7 patches: 1) [PATCH v8 01/13] - Remove the async thread for device detect in probe routine, now the device detect process is completely done within the device probe routine. 2) [PATCH v8 01/13] - Split the irq cmd hander function to separated function cyapa_default_irq_cmd_handler() and set it to interface cyapa_default_ops.irq_cmd_handler. 3) [PATCH v8 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler() to avoid miss-enter when device protocol is still in detecting. V7 patches have below updates compared with v6 patches: 1) [PATCH v7 01/13] - Split the irq cmd hander function to separated function cyapa_default_irq_cmd_handler() and set it to interface cyapa_default_ops.irq_cmd_handler. 2) [PATCH v7 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler() to avoid miss-enter when device protocol is still in detecting. V6 patches have below updates compared with v5 patches: 1) Remove patch 14 of the lid filtering from the cyapa driver. V5 patches have below updates compared with v4 patches: 1) Uses get_device()/put_device() instead of kobject_get()/kobject_put(); 2) Fix memories freed before debugfs entries issue; 3) Make cyapa_debugs_root valid in driver module level in module_init()/moudle_exit() ; 4) Fix i2c_transfer() may return partial transfer issues. 5) Add cyapa->removed flag to avoid detecting thread may still running when driver module is removed. 6) Fix the meanings of some comments and return error code not clear issue. This patch set is aimed to re-design the cyapa driver to support old gen3 trackpad devices and new gen5 trackpad devices in one cyapa driver, it's for easily productions support based on customers' requirements. And add sysfs functions and interfaces supported that required by users and customers. Since the earlier gen3 and the latest gen5 trackpad devices using two different chipsets, and have different protocols and interfaces, so if supported these two type trackpad devices in two different drivers, then it will be difficult to manage productions and later firmware updates. e.g.: It will cause customer don't know which one trackpad device firmware image to use and update when it has been used and integrated in same one productions, so here we support these two trackpad devices in same on driver. The new design cyapa driver contains: cyapa.c - the core of the re-design, supply interfaces and functions to system and read trackpad devices. cyapa.h - header file including macros and data structure definitions. cyapa_gen3.c - functions support for gen3 trackpad devices, cyapa_gen5.c - functions support for gen5 trackpad devices. Beside this introduction patch, it has 18 patches listed as below. For these patches each one is patched based on previous one. patch 1/19: modify code to following kernel code style. patch 2/19: add device resource management infrastructure support. patch 3/19: re-design cyapa driver with core functions and interface to support multi-type trackpad devices. patch 4/19: add gen5 trackpad device basic functions supported into the re-design cyapa driver. patch 5/19: add power management interfaces supported for the deivce. patch 6/19: add runtime power management interfaces supported for the device. patch 7/19: add sysfs interfaces supported in the cyapa driver. Including read firmware version, get production ID, read baseline, re-calibrate trackpad baselines and do trackpad firmware update. patch 8/19: add gen3 trackpad device's firmware update function supported. patch 9/19: add gen3 trackpad device's read baseline function supported. patch 10/19: add gen3 trackpad device's force re-calibrate function supported. patch 11/19: add gen5 trackpad device's firmware update function supported. patch 12/19: add gen5 trackpad device's
[PATCH v11 01/19] input: cyapa: modify code to following kernel code style
This patch modified the code to fix the patch check warning issue with latest checkpatch.sh tool, and also changed the return variable name from "ret" to "error" when there is only one error path to follow code style. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 151 ++-- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index b409c3d..c35f398 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -409,11 +409,11 @@ static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) cmd = cyapa_smbus_cmds[cmd_idx].cmd; len = cyapa_smbus_cmds[cmd_idx].len; return cyapa_smbus_read_block(cyapa, cmd, len, values); - } else { - cmd = cyapa_i2c_cmds[cmd_idx].cmd; - len = cyapa_i2c_cmds[cmd_idx].len; - return cyapa_i2c_reg_read_block(cyapa, cmd, len, values); } + + cmd = cyapa_i2c_cmds[cmd_idx].cmd; + len = cyapa_i2c_cmds[cmd_idx].len; + return cyapa_i2c_reg_read_block(cyapa, cmd, len, values); } /* @@ -422,8 +422,8 @@ static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) */ static int cyapa_get_state(struct cyapa *cyapa) { - int ret; u8 status[BL_STATUS_SIZE]; + int error; cyapa->state = CYAPA_STATE_NO_DEVICE; @@ -433,7 +433,7 @@ static int cyapa_get_state(struct cyapa *cyapa) * If the device is in operation mode, this will be the DATA regs. * */ - ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE, + error = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE, status); /* @@ -441,10 +441,10 @@ static int cyapa_get_state(struct cyapa *cyapa) * -ETIMEDOUT. In this case, try again using the smbus equivalent * command. This should return a BL_HEAD indicating CYAPA_STATE_OP. */ - if (cyapa->smbus && (ret == -ETIMEDOUT || ret == -ENXIO)) - ret = cyapa_read_block(cyapa, CYAPA_CMD_BL_STATUS, status); + if (cyapa->smbus && (error == -ETIMEDOUT || error == -ENXIO)) + error = cyapa_read_block(cyapa, CYAPA_CMD_BL_STATUS, status); - if (ret != BL_STATUS_SIZE) + if (error != BL_STATUS_SIZE) goto error; if ((status[REG_OP_STATUS] & OP_STATUS_SRC) == OP_STATUS_SRC) { @@ -454,7 +454,7 @@ static int cyapa_get_state(struct cyapa *cyapa) cyapa->state = CYAPA_STATE_OP; break; default: - ret = -EAGAIN; + error = -EAGAIN; goto error; } } else { @@ -468,7 +468,7 @@ static int cyapa_get_state(struct cyapa *cyapa) return 0; error: - return (ret < 0) ? ret : -EAGAIN; + return (error < 0) ? error : -EAGAIN; } /* @@ -487,31 +487,31 @@ error: */ static int cyapa_poll_state(struct cyapa *cyapa, unsigned int timeout) { - int ret; + int error; int tries = timeout / 100; - ret = cyapa_get_state(cyapa); - while ((ret || cyapa->state >= CYAPA_STATE_BL_BUSY) && tries--) { + error = cyapa_get_state(cyapa); + while ((error || cyapa->state >= CYAPA_STATE_BL_BUSY) && tries--) { msleep(100); - ret = cyapa_get_state(cyapa); + error = cyapa_get_state(cyapa); } - return (ret == -EAGAIN || ret == -ETIMEDOUT) ? -ETIMEDOUT : ret; + return (error == -EAGAIN || error == -ETIMEDOUT) ? -ETIMEDOUT : error; } static int cyapa_bl_deactivate(struct cyapa *cyapa) { - int ret; + int error; - ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate), + error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate), bl_deactivate); - if (ret < 0) - return ret; + if (error) + return error; /* wait for bootloader to switch to idle state; should take < 100ms */ msleep(100); - ret = cyapa_poll_state(cyapa, 500); - if (ret < 0) - return ret; + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; if (cyapa->state != CYAPA_STATE_BL_IDLE) return -EAGAIN; return 0; @@ -532,11 +532,11 @@ static int cyapa_bl_deactivate(struct cyapa *cyapa) */ static int cyapa_bl_exit(struct cyapa *cyapa) { - int ret; + int error; - ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit); - if (ret < 0) - return
[PATCH v11 03/19] input: cyapa: re-design driver to support multi-trackpad in one driver
In order to support multiple different chipsets and communication protocols trackpad devices in one cyapa driver, the new cyapa driver is re-designed with one cyapa driver core and multiple device specific functions component. The cyapa driver core is contained in this patch, it supplies basic functions that working with kernel and input subsystem, and also supplies the interfaces that the specific devices' component can connect and work together with as one driver. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |3 +- drivers/input/mouse/cyapa.c | 1148 ++ drivers/input/mouse/cyapa.h | 318 +++ drivers/input/mouse/cyapa_gen3.c | 792 ++ 4 files changed, 1534 insertions(+), 727 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h create mode 100644 drivers/input/mouse/cyapa_gen3.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index dda507f..4bf6c83 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974)+= bcm5974.o -obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o @@ -23,6 +23,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o +cyapatp-objs := cyapa.o cyapa_gen3.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 06c94a3..3771c5b 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -6,7 +6,7 @@ * Daniel Kurtz * Benson Leung * - * Copyright (C) 2011-2012 Cypress Semiconductor, Inc. + * Copyright (C) 2011-2014 Cypress Semiconductor, Inc. * Copyright (C) 2011-2012 Google, Inc. * * This file is subject to the terms and conditions of the GNU General Public @@ -20,409 +20,324 @@ #include #include #include +#include #include +#include +#include "cyapa.h" -/* APA trackpad firmware generation */ -#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ -#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" +#define CYAPA_ADAPTER_FUNC_NONE 0 +#define CYAPA_ADAPTER_FUNC_I2C1 +#define CYAPA_ADAPTER_FUNC_SMBUS 2 +#define CYAPA_ADAPTER_FUNC_BOTH 3 -/* commands for read/write registers of Cypress trackpad */ -#define CYAPA_CMD_SOFT_RESET 0x00 -#define CYAPA_CMD_POWER_MODE 0x01 -#define CYAPA_CMD_DEV_STATUS 0x02 -#define CYAPA_CMD_GROUP_DATA 0x03 -#define CYAPA_CMD_GROUP_CMD0x04 -#define CYAPA_CMD_GROUP_QUERY 0x05 -#define CYAPA_CMD_BL_STATUS0x06 -#define CYAPA_CMD_BL_HEAD 0x07 -#define CYAPA_CMD_BL_CMD 0x08 -#define CYAPA_CMD_BL_DATA 0x09 -#define CYAPA_CMD_BL_ALL 0x0a -#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b -#define CYAPA_CMD_BLK_HEAD 0x0c +const char unique_str[] = "CYTRA"; -/* report data start reg offset address. */ -#define DATA_REG_START_OFFSET 0x +/* Returns 0 on success, else negative errno on failure. */ +ssize_t cyapa_i2c_read(struct cyapa *cyapa, u8 reg, size_t len, + u8 *values) +{ + int ret; + struct i2c_client *client = cyapa->client; + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = ®, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = len, + .buf = values, + }, + }; + + ret = i2c_transfer(client->adapter, msgs, 2); + + if (ret != ARRAY_SIZE(msgs)) + return ret < 0 ? ret : -EIO; -#define BL_HEAD_OFFSET 0x00 -#define BL_DATA_OFFSET 0x10 + return 0; +} -/* - * Operational Device Status Register +/** + * cyapa_i2c_write - Execute i2c block data write operation + * @cyapa: Handle to this driver + * @ret: Offset of the data to written in the register map + * @len: number of bytes to write + * @values: Data to be written * - * bit 7: Valid interrupt source - * bit 6 - 4: Reserved - * bit 3 - 2: Power status - * bit 1 - 0: Device status + * Return negative errno code on error; return zero when success. */ -#define REG_OP_STATUS
[PATCH v9 01/18] input: cyapa: instruction of cyapa patches
V9 patches have below updates compared with v8 patches: 1) Removed all async thread stuff from the driver. 2) Split driver into 18 patches for each function change one patch. V8 patches have below updates compared with v7 patches: 1) [PATCH v8 01/13] - Remove the async thread for device detect in probe routine, now the device detect process is completely done within the device probe routine. 2) [PATCH v8 01/13] - Split the irq cmd hander function to separated function cyapa_default_irq_cmd_handler() and set it to interface cyapa_default_ops.irq_cmd_handler. 3) [PATCH v8 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler() to avoid miss-enter when device protocol is still in detecting. V7 patches have below updates compared with v6 patches: 1) [PATCH v7 01/13] - Split the irq cmd hander function to separated function cyapa_default_irq_cmd_handler() and set it to interface cyapa_default_ops.irq_cmd_handler. 2) [PATCH v7 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler() to avoid miss-enter when device protocol is still in detecting. V6 patches have below updates compared with v5 patches: 1) Remove patch 14 of the lid filtering from the cyapa driver. V5 patches have below updates compared with v4 patches: 1) Uses get_device()/put_device() instead of kobject_get()/kobject_put(); 2) Fix memories freed before debugfs entries issue; 3) Make cyapa_debugs_root valid in driver module level in module_init()/moudle_exit() ; 4) Fix i2c_transfer() may return partial transfer issues. 5) Add cyapa->removed flag to avoid detecting thread may still running when driver module is removed. 6) Fix the meanings of some comments and return error code not clear issue. This patch set is aimed to re-design the cyapa driver to support old gen3 trackpad devices and new gen5 trackpad devices in one cyapa driver, it's for easily productions support based on customers' requirements. And add sysfs functions and interfaces supported that required by users and customers. Since the earlier gen3 and the latest gen5 trackpad devices using two different chipsets, and have different protocols and interfaces, so if supported these two type trackpad devices in two different drivers, then it will be difficult to manage productions and later firmware updates. e.g.: It will cause customer don't know which one trackpad device firmware image to use and update when it has been used and integrated in same one productions, so here we support these two trackpad devices in same on driver. The new design cyapa driver contains: cyapa.c - the core of the re-design, supply interfaces and functions to system and read trackpad devices. cyapa.h - header file including macros and data structure definitions. cyapa_gen3.c - functions support for gen3 trackpad devices, cyapa_gen5.c - functions support for gen5 trackpad devices. Beside this introduction patch, it has 18 patches listed as below. For these patches each one is patched based on previous one. patch 1/18: add device resource management infrastructure supported. patch 2/18: re-design cyapa driver with core functions and interface to support multi-type trackpad devices. patch 3/18: add gen3 trackpad device basic functions supported into the re-design cyapa driver. patch 4/18: add gen5 trackpad device basic functions supported into the re-design cyapa driver. patch 5/18: add power management interfaces supported for the deivce. patch 6/18: add runtime power management interfaces supported for the device. patch 7/18: add sysfs interfaces supported in the cyapa driver. Including read firmware version, get production ID, read baseline, re-calibrate trackpad baselines and do trackpad firmware update. patch 8/18: add gen3 trackpad device's firmware update function supported. patch 9/18: add gen3 trackpad device's read baseline function supported. patch 10/18: add gen3 trackpad device's force re-calibrate function supported. patch 11/18: add gen5 trackpad device's firmware update function supported. patch 12/18: add gen5 trackpad device's read baseline function supported. patch 13/18: add gen5 trackpad device's force re-calibrate function. patch 14/18: add read firmware image debugfs interface supported in the cyapa driver. patch 15/18: add gen3 trackpad device's read firmware image function supported. patch 16/18: add gen5 trackpad device's read firmware image function supported. patch 17/18: add read trackpad device's sensors' raw data debugfs interface supported in the cyapa driver. patch 18/18: add gen5 trackpad device's read read raw function supported. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v9 01/18] input: cyapa: add device resource management infrastructure support
Modify cyapa driver to support device resource management infrastructure to reduce the mistakes of resource management. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 48 ++--- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index b409c3d..b3d7a2a 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -409,11 +409,11 @@ static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) cmd = cyapa_smbus_cmds[cmd_idx].cmd; len = cyapa_smbus_cmds[cmd_idx].len; return cyapa_smbus_read_block(cyapa, cmd, len, values); - } else { - cmd = cyapa_i2c_cmds[cmd_idx].cmd; - len = cyapa_i2c_cmds[cmd_idx].len; - return cyapa_i2c_reg_read_block(cyapa, cmd, len, values); } + + cmd = cyapa_i2c_cmds[cmd_idx].cmd; + len = cyapa_i2c_cmds[cmd_idx].len; + return cyapa_i2c_reg_read_block(cyapa, cmd, len, values); } /* @@ -762,7 +762,7 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) if (!cyapa->physical_size_x || !cyapa->physical_size_y) return -EINVAL; - input = cyapa->input = input_allocate_device(); + input = cyapa->input = devm_input_allocate_device(dev); if (!input) { dev_err(dev, "allocate memory for input device failed\n"); return -ENOMEM; @@ -837,11 +837,9 @@ static int cyapa_probe(struct i2c_client *client, return -EIO; } - cyapa = kzalloc(sizeof(struct cyapa), GFP_KERNEL); - if (!cyapa) { - dev_err(dev, "allocate memory for cyapa failed\n"); + cyapa = devm_kzalloc(dev, sizeof(struct cyapa), GFP_KERNEL); + if (!cyapa) return -ENOMEM; - } cyapa->gen = CYAPA_GEN3; cyapa->client = client; @@ -856,51 +854,43 @@ static int cyapa_probe(struct i2c_client *client, ret = cyapa_check_is_operational(cyapa); if (ret) { dev_err(dev, "device not operational, %d\n", ret); - goto err_mem_free; + return ret; } ret = cyapa_create_input_dev(cyapa); if (ret) { dev_err(dev, "create input_dev instance failed, %d\n", ret); - goto err_mem_free; + return ret; } ret = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); if (ret) { dev_err(dev, "set active power failed, %d\n", ret); - goto err_unregister_device; + return ret; } cyapa->irq = client->irq; - ret = request_threaded_irq(cyapa->irq, - NULL, - cyapa_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "cyapa", - cyapa); + ret = devm_request_threaded_irq(dev, + cyapa->irq, + NULL, + cyapa_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "cyapa", + cyapa); if (ret) { dev_err(dev, "IRQ request failed: %d\n, ", ret); - goto err_unregister_device; + return ret; } return 0; - -err_unregister_device: - input_unregister_device(cyapa->input); -err_mem_free: - kfree(cyapa); - - return ret; } static int cyapa_remove(struct i2c_client *client) { struct cyapa *cyapa = i2c_get_clientdata(client); - free_irq(cyapa->irq, cyapa); - input_unregister_device(cyapa->input); + disable_irq(cyapa->irq); cyapa_set_power_mode(cyapa, PWR_MODE_OFF); - kfree(cyapa); return 0; } -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v9 07/18] input: cyapa: add sysfs interfaces supported in the cyapa driver
Add device's basic control and features supported in cyapa driver through sysfs file system interfaces. These interfaces are commonly used in pre- and after production, for trackpad device state checking, managing and firmware image updating. These interfaces including firmware_version and product_id interfaces for reading firmware version and trackpad device product id values, and including update_fw interface to command firmware image update process. Also including baseline and calibrate interfaces for reading and checking trackpad device's sensors states. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 220 1 file changed, 220 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index d4b7c42..5f384ff 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -709,6 +709,213 @@ static int cyapa_start_runtime(struct cyapa *cyapa) } #endif /* CONFIG_PM_RUNTIME */ +static ssize_t cyapa_show_fm_ver(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int ret; + struct cyapa *cyapa = dev_get_drvdata(dev); + + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + return ret; + ret = scnprintf(buf, PAGE_SIZE, "%d.%d\n", cyapa->fw_maj_ver, +cyapa->fw_min_ver); + mutex_unlock(&cyapa->state_sync_lock); + return ret; +} + +static ssize_t cyapa_show_product_id(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int ret; + struct cyapa *cyapa = dev_get_drvdata(dev); + + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + return ret; + ret = scnprintf(buf, PAGE_SIZE, "%s\n", cyapa->product_id); + mutex_unlock(&cyapa->state_sync_lock); + return ret; +} + +static int cyapa_firmware(struct cyapa *cyapa, const char *fw_name) +{ + struct device *dev = &cyapa->client->dev; + int ret; + const struct firmware *fw; + + ret = request_firmware(&fw, fw_name, dev); + if (ret) { + dev_err(dev, "Could not load firmware from %s, %d\n", + fw_name, ret); + return ret; + } + + if (cyapa->ops->check_fw) { + ret = cyapa->ops->check_fw(cyapa, fw); + if (ret) { + dev_err(dev, "Invalid CYAPA firmware image: %s\n", + fw_name); + goto done; + } + } else { + dev_err(dev, "No valid device ops->check_fw handler set.\n"); + ret = -ENODEV; + goto done; + } + + /* +* Resume the potentially suspended device because doing FW +* update on a device not in the FULL mode has a chance to +* fail. +*/ + pm_runtime_get_sync(dev); + + if (cyapa->ops->bl_enter) { + ret = cyapa->ops->bl_enter(cyapa); + if (ret) + goto err_detect; + } + + if (cyapa->ops->bl_activate) { + ret = cyapa->ops->bl_activate(cyapa); + if (ret) + goto err_detect; + } + + if (cyapa->ops->bl_initiate) { + ret = cyapa->ops->bl_initiate(cyapa, fw); + if (ret) + goto err_detect; + } + + if (cyapa->ops->update_fw) { + ret = cyapa->ops->update_fw(cyapa, fw); + if (ret) + goto err_detect; + } + + if (cyapa->ops->bl_verify_app_integrity) { + ret = cyapa->ops->bl_verify_app_integrity(cyapa); + if (ret) + goto err_detect; + } + +err_detect: + pm_runtime_put_noidle(dev); + +done: + release_firmware(fw); + return ret; +} + +static ssize_t cyapa_update_fw_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + char fw_name[64]; + int ret; + + if (count > 64) { + dev_err(dev, "File name too long\n"); + return -EINVAL; + } + + memcpy(fw_name, buf, count); + if (fw_name[count - 1] == '\n') + fw_name[count - 1] = '\0'; + else + fw_name[count] = '\0'; + + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + return ret; + + ret = cyap
[PATCH v9 03/18] input: cyapa: add gen3 trackpad device basic functions support
Based on the cyapa core, add the gen3 trackpad device's basic functions supported, so gen3 trackpad device can work with kernel input system. The basic function is absolutely same as previous cyapa driver. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile | 3 +- drivers/input/mouse/cyapa.c | 90 - drivers/input/mouse/cyapa.h | 1 + drivers/input/mouse/cyapa_gen3.c | 788 +++ 4 files changed, 880 insertions(+), 2 deletions(-) create mode 100644 drivers/input/mouse/cyapa_gen3.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index dda507f..4bf6c83 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974)+= bcm5974.o -obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o @@ -23,6 +23,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o +cyapatp-objs := cyapa.o cyapa_gen3.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 5029618..cb81baf 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -234,6 +234,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return ret; switch (cyapa->gen) { + case CYAPA_GEN3: + cyapa->ops = &cyapa_gen3_ops; + break; default: return -ENODEV; } @@ -284,7 +287,85 @@ out: */ static int cyapa_get_state(struct cyapa *cyapa) { - return -ENODEV; + int ret; + u8 status[BL_STATUS_SIZE]; + u8 cmd[32]; + /* The i2c address of gen4 and gen5 trackpad device must be even. */ + bool even_addr = ((cyapa->client->addr & 0x0001) == 0); + bool smbus = false; + int retries = 2; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + + /* +* Get trackpad status by reading 3 registers starting from 0. +* If the device is in the bootloader, this will be BL_HEAD. +* If the device is in operation mode, this will be the DATA regs. +* +*/ + ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE, + status); + + /* +* On smbus systems in OP mode, the i2c_reg_read will fail with +* -ETIMEDOUT. In this case, try again using the smbus equivalent +* command. This should return a BL_HEAD indicating CYAPA_STATE_OP. +*/ + if (cyapa->smbus && (ret == -ETIMEDOUT || ret == -ENXIO)) { + if (!even_addr) + ret = cyapa_read_block(cyapa, + CYAPA_CMD_BL_STATUS, status); + smbus = true; + } + if (ret != BL_STATUS_SIZE) + goto error; + + /* +* Detect trackpad protocol based on characristic registers and bits. +*/ + do { + cyapa->status[REG_OP_STATUS] = status[REG_OP_STATUS]; + cyapa->status[REG_BL_STATUS] = status[REG_BL_STATUS]; + cyapa->status[REG_BL_ERROR] = status[REG_BL_ERROR]; + + if (cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN3) { + ret = cyapa_gen3_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (ret == 0) + goto out_detected; + } + + /* +* Cannot detect communication protocol based on current +* charateristic registers and bits. +* So write error command to do further detection. +* this method only valid on I2C bus. +* for smbus interface, it won't have overwrite issue. +*/ + if (!smbus) { + cmd[0] = 0x00; + cmd[1] = 0x00; + ret = cyapa_i2c_write(cyapa, 0, 2, cmd); + if (ret) + goto error; + + msleep(50); + + ret = cyapa_i2c_read(cyapa, BL_HEAD_OFFSET, + BL_STATUS_SIZE, status); + if (ret < 0) +
[PATCH v9 08/18] input: cyapa: add gen3 trackpad device firmware update function support
Add firmware image update function supported for gen3 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 290 +++ 1 file changed, 290 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index bd00c6e..7caa93f 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -412,6 +412,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) { + data_reporting_started = false; + 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 reset. */ + 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; @@ -472,6 +544,218 @@ 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], +
[PATCH v9 06/18] input: cyapa: add runtime power management interfaces supported for the device
Add runtime_suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the runtime power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 168 1 file changed, 168 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 420696d..d4b7c42 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "cyapa.h" @@ -259,6 +260,7 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) bool cont; int ret; + pm_runtime_get_sync(dev); if (device_may_wakeup(dev)) pm_wakeup_event(dev, 0); @@ -282,6 +284,8 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) } out: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); return IRQ_HANDLED; } @@ -595,6 +599,116 @@ static void cyapa_remove_power_wakeup_group(void *data) } #endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_PM_RUNTIME +static ssize_t cyapa_show_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd; + u16 sleep_time; + int ret; + + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + return ret; + pwr_cmd = cyapa->runtime_suspend_power_mode; + sleep_time = cyapa->runtime_suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (cyapa->gen == CYAPA_GEN3) + return scnprintf(buf, PAGE_SIZE, "%u\n", + cyapa_pwr_cmd_to_sleep_time(pwr_cmd)); + return scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); +} + +static ssize_t cyapa_update_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 time; + int ret; + + if (buf == NULL || count == 0 || kstrtou16(buf, 10, &time)) { + dev_err(dev, "invalid runtime suspend scanrate ms parameter\n"); + return -EINVAL; + } + + /* +* When the suspend scanrate is changed, pm_runtime_get to resume +* a potentially suspended device, update to the new pwr_cmd +* and then pm_runtime_put to suspend into the new power mode. +*/ + pm_runtime_get_sync(dev); + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + return ret; + cyapa->runtime_suspend_sleep_time = cyapa_clamp_sleep_time(time); + cyapa->runtime_suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time); + mutex_unlock(&cyapa->state_sync_lock); + pm_runtime_put_sync_autosuspend(dev); + + return count; +} + +static DEVICE_ATTR(runtime_suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_rt_suspend_scanrate, + cyapa_update_rt_suspend_scanrate); + +static struct attribute *cyapa_power_runtime_entries[] = { + &dev_attr_runtime_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_runtime_group = { + .name = power_group_name, + .attrs = cyapa_power_runtime_entries, +}; + +static void cyapa_remove_power_runtime_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_runtime_group); +} + +static int cyapa_start_runtime(struct cyapa *cyapa) +{ + int ret; + struct device *dev = &cyapa->client->dev; + + cyapa->runtime_suspend_power_mode = PWR_MODE_IDLE; + cyapa->runtime_suspend_sleep_time = + cyapa_pwr_cmd_to_sleep_time(cyapa->runtime_suspend_power_mode); + + ret = sysfs_merge_group(&dev->kobj, &cyapa_power_runtime_group); + if (ret) { + dev_err(dev, + "failed to create power runtime group, %d\n", ret); + return ret; + } + + ret = devm_add_action(dev, cyapa_remove_power_runtime_group, cyapa); + if (ret) { + cyapa_remove_power_runtime_group(cyapa); + dev_err(dev, + "failed to add power runtime cleanup action, (%d)\n", + ret); + return ret; + } + + pm_runtime_set_active(dev); +
[PATCH v9 05/18] input: cyapa: add power management interfaces supported for the device
Add suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 112 1 file changed, 112 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index fac361a..420696d 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -505,6 +505,96 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode) : (encoded_time - 5) * 20; } +#ifdef CONFIG_PM_SLEEP +static ssize_t cyapa_show_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd = cyapa->suspend_power_mode; + u16 sleep_time; + int len; + int ret; + + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + return ret; + pwr_cmd = cyapa->suspend_power_mode; + sleep_time = cyapa->suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (pwr_cmd == PWR_MODE_BTN_ONLY) + len = scnprintf(buf, PAGE_SIZE, "%s\n", BTN_ONLY_MODE_NAME); + else if (pwr_cmd == PWR_MODE_OFF) + len = scnprintf(buf, PAGE_SIZE, "%s\n", OFF_MODE_NAME); + else { + if (cyapa->gen == CYAPA_GEN3) + sleep_time = cyapa_pwr_cmd_to_sleep_time(pwr_cmd); + len = scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); + } + + return len; +} + +static u16 cyapa_clamp_sleep_time(u16 sleep_time) +{ + if (sleep_time > 1000) + sleep_time = 1000; + return sleep_time; +} + +static ssize_t cyapa_update_suspend_scanrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 sleep_time; + int ret; + + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + return ret; + + if (sysfs_streq(buf, BTN_ONLY_MODE_NAME)) + cyapa->suspend_power_mode = PWR_MODE_BTN_ONLY; + else if (sysfs_streq(buf, OFF_MODE_NAME)) + cyapa->suspend_power_mode = PWR_MODE_OFF; + else if (!kstrtou16(buf, 10, &sleep_time)) { + cyapa->suspend_sleep_time = cyapa_clamp_sleep_time(sleep_time); + cyapa->suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time); + } else + count = 0; + + mutex_unlock(&cyapa->state_sync_lock); + if (!count) + dev_err(dev, "invalid suspend scanrate ms parameters\n"); + return count ? count : -EINVAL; +} + +static DEVICE_ATTR(suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_suspend_scanrate, + cyapa_update_suspend_scanrate); + +static struct attribute *cyapa_power_wakeup_entries[] = { + &dev_attr_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_wakeup_group = { + .name = power_group_name, + .attrs = cyapa_power_wakeup_entries, +}; + +static void cyapa_remove_power_wakeup_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_wakeup_group); +} +#endif /* CONFIG_PM_SLEEP */ + /* * Returns: * 0Driver and device initialization successfully done. @@ -588,6 +678,28 @@ static int cyapa_probe(struct i2c_client *client, return ret; } +#ifdef CONFIG_PM_SLEEP + if (device_can_wakeup(dev)) { + ret = sysfs_merge_group(&client->dev.kobj, + &cyapa_power_wakeup_group); + if (ret) { + dev_err(dev, "failed to add power wakeup group, (%d)\n", + ret); + return ret; + } + + ret = devm_add_action(dev, + cyapa_remove_power_wakeup_group, cyapa); + if (ret) { + cyapa_remove_power_wakeup_group(cyapa); + dev_err(dev, + "failed to add power cleanup action, (%d)\n", + ret); + return ret; + } + } +#endif /* CONFIG_PM_SLEEP */ + return 0; } -- 1.9.1 -- To unsubscribe from this l
[PATCH v9 16/18] input: cyapa: add gen5 trackpad device read firmware image function support
Add read firmware image function supported for gen5 trackpad device, it can be used through debugfs read_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 154 +++ 1 file changed, 154 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 7e7de12..35334dc 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1213,6 +1213,153 @@ static int cyapa_gen5_write_fw_block(struct cyapa *cyapa, return 0; } +static int cyapa_gen5_read_fw_bytes(struct cyapa *cyapa, u16 row_num, u8 *data) +{ + int ret; + u8 cmd[16]; + size_t cmd_len; + u8 resp_data[CYAPA_TSG_FW_ROW_SIZE / 2 + GEN5_MIN_BL_RESP_LENGTH]; + int resp_len; + u16 offset; + u16 cmd_crc; + struct cyapa_tsg_bin_image_data_record *fw_img_record; + + fw_img_record = (struct cyapa_tsg_bin_image_data_record *)data; + + cmd[0] = 0x04; /* Register address */ + cmd[1] = 0x00; + cmd[2] = 0x0e; + cmd[3] = 0x00; + cmd[4] = 0x40; /* Report id 40h */ + cmd[5] = 0x00; + cmd[6] = GEN5_SOP_KEY; + cmd[7] = 0x3d; /* Read application image command code */ + cmd[8] = 0x03; + cmd[9] = 0x00; + offset = row_num * CYAPA_TSG_FW_ROW_SIZE - + CYAPA_TSG_START_OF_APPLICATION; + put_unaligned_le16(offset, &cmd[10]); + cmd[12] = CYAPA_TSG_IMG_READ_SIZE; + cmd_crc = crc_itu_t(0x, &cmd[6], 7); + put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */ + cmd[15] = GEN5_EOP_KEY; /* EOP = 17h */ + cmd_len = 16; + + resp_len = CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH; + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, cmd_len, + resp_data, &resp_len, + 50, cyapa_gen5_sort_tsg_pip_bl_resp_data, true); + if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) || + ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return (ret < 0) ? ret : -EAGAIN; + + /* Copy first 64 bytes in the row. */ + memcpy(&fw_img_record->record_data[0], &resp_data[8], + CYAPA_TSG_IMG_READ_SIZE); + + if (row_num == CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM) { + /* Last row's rest 64 bytes are bootloader metadata, +* it's not allowed to be read out, will respond with error. */ + memset(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE], + 0, CYAPA_TSG_IMG_READ_SIZE); + goto skip_last_row; + } + + /* Read next 64 bytes in the row. */ + offset = offset + CYAPA_TSG_IMG_READ_SIZE; + put_unaligned_le16(offset, &cmd[10]); + cmd_crc = crc_itu_t(0x, &cmd[6], 7); + put_unaligned_le16(cmd_crc, &cmd[13]); /* CRC[15:0] */ + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, cmd_len, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_bl_resp_data, true); + if (resp_len != (CYAPA_TSG_IMG_READ_SIZE + GEN5_MIN_BL_RESP_LENGTH) || + ret || resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return (ret < 0) ? ret : -EAGAIN; + + /* Copy last 64 bytes in the row. */ + memcpy(&fw_img_record->record_data[CYAPA_TSG_IMG_READ_SIZE], + &resp_data[8], CYAPA_TSG_IMG_READ_SIZE); + +skip_last_row: + fw_img_record->flash_array_id = 0; + put_unaligned_be16(row_num, &fw_img_record->row_number); + put_unaligned_be16(CYAPA_TSG_FW_ROW_SIZE, &fw_img_record->record_len); + + return 0; +} + +static int cyapa_gen5_read_fw(struct cyapa *cyapa) +{ + int ret; + int fw_img_head_size; + int fw_img_record_size; + int fw_img_size; + int row_index; + int array_index; + u32 img_start; + u16 img_len; + u16 img_start_row; + u16 img_end_row; + struct cyapa_tsg_bin_image_data_record app_integrity; + u8 *record_data; + + ret = cyapa_gen5_bl_enter(cyapa); + if (ret) + return ret; + + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + fw_img_head_size = sizeof(struct cyapa_tsg_bin_image_head); + fw_img_record_size = sizeof(struct cyapa_tsg_bin_image_data_record); + + /* Read app integrity block data. */ + row_index = CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM; + ret = cyapa_gen5_read_fw_bytes(cyapa, row_index, (u8 *)&app_integrity); + if (ret) + return ret; + img_start = get_unaligned_le3
[PATCH v9 09/18] input: cyapa: add gen3 trackpad device read baseline function support
Add read baseline function supported for gen3 trackpad device, it can be used through sysfs baseline interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 74 1 file changed, 74 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 7caa93f..406b5db 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -756,6 +756,78 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_show_baseline(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int max_baseline, min_baseline; + int tries = 3; + int ret; + + data_reporting_started = false; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_REPORT_BASELINE_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send report baseline command. %d\n", + ret); + goto out; + } + + do { + usleep_range(1, 2); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Device timed out going to Normal state.\n"); + ret = -ETIMEDOUT; + goto out; + } + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MAX_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read max baseline. err = %d\n", ret); + goto out; + } + max_baseline = ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MIN_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read min baseline. err = %d\n", ret); + goto out; + } + min_baseline = ret; + + dev_dbg(dev, "Baseline report successful. Max: %d Min: %d\n", + max_baseline, min_baseline); + ret = scnprintf(buf, PAGE_SIZE, "%d %d\n", max_baseline, min_baseline); + +out: + data_reporting_started = true; + return ret; +} + /* * cyapa_get_wait_time_for_pwr_cmd * @@ -1068,6 +1140,8 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .update_fw = cyapa_gen3_do_fw_update, .bl_deactivate = cyapa_gen3_bl_deactivate, + .show_baseline = cyapa_gen3_show_baseline, + .state_parse = cyapa_gen3_state_parse, .operational_check = cyapa_gen3_do_operational_check, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v9 14/18] input: cyapa: add read firmware image debugfs interface support
Add read firmware image from trackpad device interface supported in cyapa driver through debugfs read_fw interface. Through this interface user can read out, check and backup the firmware image of the trackpad device before any firmware update, or can use the backed image to do firmware image recovery. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 174 +++- drivers/input/mouse/cyapa.h | 11 +++ 2 files changed, 184 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 5f384ff..bc1d75a 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -14,6 +14,7 @@ * more details. */ +#include #include #include #include @@ -38,6 +39,9 @@ const char unique_str[] = "CYTRA"; +/* Global root node of the cyapa debugfs directory. */ +static struct dentry *cyapa_debugfs_root; + ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, u8 *values) @@ -475,6 +479,134 @@ int cyapa_detect(struct cyapa *cyapa) } /* + ** + * debugfs interface + ** +*/ +static int cyapa_debugfs_open(struct inode *inode, struct file *file) +{ + struct cyapa *cyapa = inode->i_private; + int ret; + + if (!cyapa) + return -ENODEV; + + ret = mutex_lock_interruptible(&cyapa->debugfs_mutex); + if (ret) + return ret; + + if (!get_device(&cyapa->client->dev)) { + ret = -ENODEV; + goto out; + } + + file->private_data = cyapa; + + if (cyapa->fw_image && cyapa->fw_image_size) { + ret = 0; + goto out; + } + + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + goto out; + /* +* If firmware hasn't been read yet, read it all in one pass. +* Subsequent opens will reuse the data in this same buffer. +*/ + if (cyapa->ops->read_fw) { + ret = cyapa->ops->read_fw(cyapa); + + /* +* Redetect trackpad device states because read_fw will +* reset trackpad device into bootloader mode. +*/ + cyapa_detect(cyapa); + } else + ret = -EPERM; + + mutex_unlock(&cyapa->state_sync_lock); +out: + mutex_unlock(&cyapa->debugfs_mutex); + return ret; +} + +static int cyapa_debugfs_release(struct inode *inode, struct file *file) +{ + struct cyapa *cyapa = file->private_data; + int ret; + + if (!cyapa) + return 0; + + ret = mutex_lock_interruptible(&cyapa->debugfs_mutex); + if (ret) + return ret; + file->private_data = NULL; + put_device(&cyapa->client->dev); + mutex_unlock(&cyapa->debugfs_mutex); + + return 0; +} + +/* Return some bytes from the buffered firmware image, starting from *ppos */ +static ssize_t cyapa_debugfs_read_fw(struct file *file, char __user *buffer, +size_t count, loff_t *ppos) +{ + struct cyapa *cyapa = file->private_data; + + if (!cyapa->fw_image) + return -EINVAL; + + if (*ppos >= cyapa->fw_image_size) + return 0; + + if (count + *ppos > cyapa->fw_image_size) + count = cyapa->fw_image_size - *ppos; + + if (copy_to_user(buffer, &cyapa->fw_image[*ppos], count)) + return -EFAULT; + + *ppos += count; + return count; +} + +static const struct file_operations cyapa_read_fw_fops = { + .open = cyapa_debugfs_open, + .release = cyapa_debugfs_release, + .read = cyapa_debugfs_read_fw +}; + +static int cyapa_debugfs_init(struct cyapa *cyapa) +{ + struct device *dev = &cyapa->client->dev; + + if (!cyapa_debugfs_root) + return -ENODEV; + + cyapa->dentry_dev = debugfs_create_dir(kobject_name(&dev->kobj), + cyapa_debugfs_root); + + if (!cyapa->dentry_dev) + return -ENODEV; + + mutex_init(&cyapa->debugfs_mutex); + + debugfs_create_file(CYAPA_DEBUGFS_READ_FW, S_IRUSR, cyapa->dentry_dev, + cyapa, &cyapa_read_fw_fops); + + return 0; +} + +static void cyapa_remove_debugfs(void *data) +{ + struct cyapa *cyapa = data; + + debugfs_remove_recursive(cyapa->dentry_dev); + mutex_destroy(&cyapa->debugfs_mutex); +} + +/* * Sysfs Interface. */ @@ -1012,6 +1144,20 @@ static int cyapa_probe(struct i2c_cli
[PATCH v9 13/18] input: cyapa: add gen5 trackpad device force re-calibrate function support
Add force re-calibrate function supported for gen5 trackpad device, it can be used through sysfs calibrate interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 65 1 file changed, 65 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 011c8f5..7e7de12 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1583,6 +1583,70 @@ static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) return 0; } +static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa, + u8 calibrate_sensing_mode_type) +{ + int ret; + u8 cmd[8]; + u8 resp_data[6]; + int resp_len; + + /* Try to dump all bufferred data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + cmd[0] = 0x04; + cmd[1] = 0x00; + cmd[2] = 0x06; + cmd[3] = 0x00; + cmd[4] = GEN5_APP_CMD_REPORT_ID; + cmd[5] = 0x00; + cmd[6] = GEN5_CMD_CALIBRATE; + cmd[7] = calibrate_sensing_mode_type; + resp_len = sizeof(resp_data); + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 5000, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (ret || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_CALIBRATE) || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return ret < 0 ? ret : -EAGAIN; + + return 0; +} + +static ssize_t cyapa_gen5_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int ret, calibrate_ret; + + /* 1. Suspend Scanning*/ + ret = cyapa_gen5_suspend_scanning(cyapa); + if (ret) + return ret; + + /* 2. Do mutual capacitance fine calibrate. */ + calibrate_ret = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_MUTUAL_CAP_FINE); + if (calibrate_ret) + goto resume_scanning; + + /* 3. Do self capacitance calibrate. */ + calibrate_ret = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_SELF_CAP); + if (calibrate_ret) + goto resume_scanning; + +resume_scanning: + /* 4. Resume Scanning*/ + ret = cyapa_gen5_resume_scanning(cyapa); + if (ret || calibrate_ret) + return ret ? ret : calibrate_ret; + + return count; +} + static s32 two_complement_to_s32(s32 value, int num_bits) { if (value >> (num_bits - 1)) @@ -2543,6 +2607,7 @@ const struct cyapa_dev_ops cyapa_gen5_ops = { .update_fw = cyapa_gen5_do_fw_update, .show_baseline = cyapa_gen5_show_baseline, + .calibrate_store = cyapa_gen5_do_calibrate, .initialize = cyapa_gen5_initialize, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v9 18/18] input: cyapa: add gen5 trackpad device read raw data function support
Add read raw data function supported for gen5 trackpad device, it can be used through debugfs raw_data interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 109 +++ 1 file changed, 109 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 35334dc..bbc2e20 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -2350,6 +2350,114 @@ resume_scanning: return ret + err; } +static int cyapa_gen5_read_raw_data(struct cyapa *cyapa) +{ + int ret, err; + int raw_cap_mutual_max, raw_cap_mutual_min, raw_cap_mutual_ave; + int raw_cap_self_max, raw_cap_self_min, raw_cap_self_ave; + int offset; + int data_size, max, min, ave; + ktime_t time_mono; + + offset = 0; + if (!cyapa->tp_raw_data) { + if (cyapa->state != CYAPA_STATE_GEN5_APP || + !cyapa->electrodes_x || !cyapa->electrodes_y) + return -EINVAL; + + cyapa->tp_raw_data_size = sizeof(s32) * (cyapa->electrodes_x * + cyapa->electrodes_y + cyapa->electrodes_x + + cyapa->electrodes_y) + GEN5_RAW_DATA_HEAD_SIZE; + /* +* This buffer will be hold after used until the driver is +* unloaded, the purpose of it is to improve the performace +* to avoid frequently allocate and release the buffer. +*/ + cyapa->tp_raw_data = devm_kzalloc(&cyapa->client->dev, + cyapa->tp_raw_data_size, GFP_KERNEL); + if (!cyapa->tp_raw_data) + return -ENOMEM; + } + + /* +* 1. Suspend Scanning. +* +* After suspend scanning, the raw data will not be updated, +* so the time of the raw data is before scanning suspended. +*/ + time_mono = ktime_get(); + ret = cyapa_gen5_suspend_scanning(cyapa); + if (ret) + return ret; + + /* 2. Get the correct electrodes_rx number. */ + if (cyapa->electrodes_rx == 0) { + /* +* Through the read global idac interface to get the Rx number. +* this value is useful to the raw data map. +*/ + data_size = 0; + err = cyapa_gen5_read_idac_data(cyapa, + GEN5_CMD_RETRIEVE_DATA_STRUCTURE, + GEN5_RETRIEVE_MUTUAL_PWC_DATA, + &data_size, &max, &min, &ave); + if (err || cyapa->electrodes_rx == 0) + goto resume_scanning; + } + + /* 3. Execuate panel scan. It must be executed before read data. */ + err = cyapa_gen5_execute_panel_scan(cyapa); + if (err) + goto resume_scanning; + + /* 4. Retrieve panel scan, mutual cap raw data. */ + offset = GEN5_RAW_DATA_HEAD_SIZE; + err = cyapa_gen5_read_panel_scan_raw_data(cyapa, + GEN5_CMD_RETRIEVE_PANEL_SCAN, + GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT, + cyapa->electrodes_x * cyapa->electrodes_y, + &raw_cap_mutual_max, &raw_cap_mutual_min, + &raw_cap_mutual_ave, + cyapa->tp_raw_data + offset); + if (err) + goto resume_scanning; + + offset += sizeof(s32) * cyapa->electrodes_x * cyapa->electrodes_y; + + /* 5. Retrieve panel scan, self cap raw data. */ + err = cyapa_gen5_read_panel_scan_raw_data(cyapa, + GEN5_CMD_RETRIEVE_PANEL_SCAN, + GEN5_PANEL_SCAN_SELF_DIFFCOUNT, + cyapa->electrodes_x + cyapa->electrodes_y, + &raw_cap_self_max, &raw_cap_self_min, + &raw_cap_self_ave, + cyapa->tp_raw_data + offset); + if (err) + goto resume_scanning; + + offset += sizeof(s32) * (cyapa->electrodes_x + cyapa->electrodes_y); + +resume_scanning: + /* 6. Resume Scanning*/ + ret = cyapa_gen5_resume_scanning(cyapa); + if (ret || err) + return ret ? ret : err; + + *((struct timeval *)&cyapa->tp_raw_data[0]) = + ktime_to_timeval(time_mono); + cyapa->tp_raw_data[16] = (u8)cyapa->electrodes_x; + cyapa->tp_raw_data[17] = (u8)cyapa->electrodes_y; + cyapa->tp_raw_data[18] = (u8)cyapa->x_origin; + cyapa->tp_raw_data[19] = (u8)cyapa->y_origin; +
[PATCH v9 17/18] input: cyapa: add read sensors raw data debugfs interface support
Add read sensors' raw data from trackpad device interface supported in cyapa driver through debugfs raw_data interface. Through this interface, user can read difference count map of each sensors directly from trackpad device (some customers want). And it's useful to help users to find out the root cause when there is performance gap happened. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 89 + drivers/input/mouse/cyapa.h | 4 ++ 2 files changed, 93 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index bc1d75a..e200beb 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -577,6 +577,91 @@ static const struct file_operations cyapa_read_fw_fops = { .read = cyapa_debugfs_read_fw }; +static int cyapa_debugfs_raw_data_open(struct inode *inode, struct file *file) +{ + struct cyapa *cyapa = inode->i_private; + int ret; + + if (!cyapa) + return -ENODEV; + + /* Start to be supported after Gen5 trackpad devices. */ + if (cyapa->gen < CYAPA_GEN5) + return -ENOTSUPP; + + ret = mutex_lock_interruptible(&cyapa->debugfs_mutex); + if (ret) + return ret; + + if (!get_device(&cyapa->client->dev)) { + ret = -ENODEV; + goto out; + } + + file->private_data = cyapa; +out: + mutex_unlock(&cyapa->debugfs_mutex); + return ret; +} + +static int cyapa_debugfs_raw_data_release(struct inode *inode, + struct file *file) +{ + struct cyapa *cyapa = file->private_data; + int ret; + + if (!cyapa) + return 0; + + ret = mutex_lock_interruptible(&cyapa->debugfs_mutex); + if (ret) + return ret; + file->private_data = NULL; + put_device(&cyapa->client->dev); + mutex_unlock(&cyapa->debugfs_mutex); + + return 0; +} + +/* Always return the sensors' latest raw data from trackpad device. */ +static ssize_t cyapa_debugfs_read_raw_data(struct file *file, +char __user *buffer, +size_t count, loff_t *ppos) +{ + int ret; + struct cyapa *cyapa = file->private_data; + + ret = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (ret) + return ret; + + if (cyapa->ops->read_raw_data) + ret = cyapa->ops->read_raw_data(cyapa); + else + ret = -EPERM; + mutex_unlock(&cyapa->state_sync_lock); + if (ret) + return ret; + + if (*ppos >= cyapa->tp_raw_data_size) + return 0; + + if (count + *ppos > cyapa->tp_raw_data_size) + count = cyapa->tp_raw_data_size - *ppos; + + if (copy_to_user(buffer, &cyapa->tp_raw_data[*ppos], count)) + return -EFAULT; + + *ppos += count; + return count; +} + +static const struct file_operations cyapa_read_raw_data_fops = { + .open = cyapa_debugfs_raw_data_open, + .release = cyapa_debugfs_raw_data_release, + .read = cyapa_debugfs_read_raw_data +}; + static int cyapa_debugfs_init(struct cyapa *cyapa) { struct device *dev = &cyapa->client->dev; @@ -595,6 +680,10 @@ static int cyapa_debugfs_init(struct cyapa *cyapa) debugfs_create_file(CYAPA_DEBUGFS_READ_FW, S_IRUSR, cyapa->dentry_dev, cyapa, &cyapa_read_fw_fops); + if (cyapa->gen >= CYAPA_GEN5) + debugfs_create_file(CYAPA_DEBUGFS_RAW_DATA, S_IRUSR, + cyapa->dentry_dev, cyapa, &cyapa_read_raw_data_fops); + return 0; } diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index 288c7de..75b0c33 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -190,6 +190,7 @@ struct cyapa_dev_ops { struct device_attribute *, const char *, size_t); int (*read_fw)(struct cyapa *); + int (*read_raw_data)(struct cyapa *); int (*initialize)(struct cyapa *cyapa); @@ -298,6 +299,9 @@ struct cyapa { struct cyapa_tsg_bin_image_head fw_img_head; u8 *fw_image; size_t fw_image_size; + /* Buffer to store sensors' raw data */ + u8 *tp_raw_data; + size_t tp_raw_data_size; const struct cyapa_dev_ops *ops; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v9 12/18] input: cyapa: add gen5 trackpad device read baseline function support
Add read baseline function supported for gen5 trackpad device, it can be used through sysfs baseline interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 606 +++ 1 file changed, 606 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index a6df556..011c8f5 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1535,6 +1535,610 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, return 0; } +static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) +{ + u8 cmd[7] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 }; + u8 resp_data[6]; + int resp_len; + int ret; + + /* Try to dump all bufferred data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = 6; + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, 7, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (ret || !VALID_CMD_RESP_HEADER(resp_data, 0x04)) + return -EINVAL; + + /* Try to dump all bufferred data when resuming scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) +{ + u8 cmd[7] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 }; + u8 resp_data[6]; + int resp_len; + int ret; + + /* Try to dump all bufferred data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = 6; + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, 7, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (ret || !VALID_CMD_RESP_HEADER(resp_data, 0x03)) + return -EINVAL; + + /* Try to dump all bufferred data when suspending scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static s32 two_complement_to_s32(s32 value, int num_bits) +{ + if (value >> (num_bits - 1)) + value |= -1 << num_bits; + return value; +} + +static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len) +{ + int data_size; + bool big_endian; + bool unsigned_type; + s32 value; + + data_size = (data_format & 0x07); + big_endian = ((data_format & 0x10) == 0x00); + unsigned_type = ((data_format & 0x20) == 0x00); + + if (buf_len < data_size) + return 0; + + switch (data_size) { + case 1: + value = buf[0]; + break; + case 2: + if (big_endian) + value = get_unaligned_be16(buf); + else + value = get_unaligned_le16(buf); + break; + case 4: + if (big_endian) + value = get_unaligned_be32(buf); + else + value = get_unaligned_le32(buf); + break; + default: + /* Should not happen, just as default case here. */ + value = 0; + break; + } + + if (!unsigned_type) + value = two_complement_to_s32(value, data_size * 8); + + return value; +} + + +/* + * Read all the global mutual or self idac data or mutual or self local PWC + * data based on the @idac_data_type. + * If the input value of @data_size is 0, then means read global mutual or + * self idac data. For read global mutual idac data, @idac_max, @idac_min and + * @idac_ave are in order used to return the max value of global mutual idac + * data, the min value of global mutual idac and the average value of the + * global mutual idac data. For read global self idac data, @idac_max is used + * to return the global self cap idac data in Rx direction, @idac_min is used + * to return the global self cap idac data in Tx direction. @idac_ave is not + * used. + * If the input value of @data_size is not 0, than means read the mutual or + * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to + * return the max, min and average value of the mutual or self local PWC data. + * Note, in order to raed mutual local PWC data, must read invoke this function + * to read the mutual global idac data firstly to set the correct Rx number + * value, otherwise, the read mutual idac and PWC data may not correct. + */ +static int cyapa_gen5_read_idac_data(struct cyapa *cyapa, + u8 cmd_code, u8 idac_data_type, int *data_size, + int *idac_max, int *idac_min, int *idac_ave) +{ + int ret; + int i; + u8 cmd[12]; + u8 resp_data[256]; + int resp_len; +
[PATCH v9 10/18] input: cyapa: add gen3 trackpad device force re-calibrate function support
Add force re-calibrate function supported for gen3 trackpad device, it can be used through sysfs calibrate interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 61 1 file changed, 61 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 406b5db..b477d67 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -756,6 +756,66 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int tries = 20; /* max recalibration timeout 2s. */ + int ret; + + data_reporting_started = false; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_RECALIBRATION_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send calibrate command. ret = %d\n", + ret); + goto out; + } + + do { + /* +* For this recalibration, the max time will not exceed 2s. +* The average time is approximately 500 - 700 ms, and we +* will check the status every 100 - 200ms. +*/ + usleep_range(10, 20); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Failed to calibrate. Timeout.\n"); + ret = -ETIMEDOUT; + goto out; + } + dev_dbg(dev, "Calibration successful.\n"); + +out: + data_reporting_started = true; + return ret < 0 ? ret : count; +} + static ssize_t cyapa_gen3_show_baseline(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1141,6 +1201,7 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .bl_deactivate = cyapa_gen3_bl_deactivate, .show_baseline = cyapa_gen3_show_baseline, + .calibrate_store = cyapa_gen3_do_calibrate, .state_parse = cyapa_gen3_state_parse, .operational_check = cyapa_gen3_do_operational_check, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v9 11/18] input: cyapa: add gen5 trackpad device firmware update function support
Add firmware image update function supported for gen5 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Kconfig | 2 +- drivers/input/mouse/cyapa_gen5.c | 294 +++ 2 files changed, 295 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 366fc7a..005d69b 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -205,7 +205,7 @@ config MOUSE_BCM5974 config MOUSE_CYAPA tristate "Cypress APA I2C Trackpad support" - depends on I2C + depends on I2C && CRC_ITU_T help This driver adds support for Cypress All Points Addressable (APA) I2C Trackpads, including the ones used in 2012 Samsung Chromebooks. diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 86cf50b..a6df556 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -910,6 +910,86 @@ static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) return -EAGAIN; } +static int cyapa_gen5_bl_initiate(struct cyapa *cyapa, + const struct firmware *fw) +{ + int ret = 0; + u16 length = 0; + u16 data_len = 0; + u16 meta_data_crc = 0; + u16 cmd_crc = 0; + u8 bl_gen5_activate[18 + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE + 3]; + int bl_gen5_activate_size = 0; + u8 resp_data[11]; + int resp_len; + struct cyapa_tsg_bin_image *image; + int records_num; + u8 *data; + + /* Try to dump all bufferred report data before send any command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + bl_gen5_activate_size = sizeof(bl_gen5_activate); + memset(bl_gen5_activate, 0, bl_gen5_activate_size); + + /* Output Report Register Address[15:0] = 0004h */ + bl_gen5_activate[0] = 0x04; + bl_gen5_activate[1] = 0x00; + + /* Total command length[15:0] */ + length = bl_gen5_activate_size - 2; + put_unaligned_le16(length, &bl_gen5_activate[2]); + bl_gen5_activate[4] = 0x40; /* Report ID = 40h */ + bl_gen5_activate[5] = 0x00; /* RSVD = 00h */ + + bl_gen5_activate[6] = GEN5_SOP_KEY; /* SOP = 01h */ + bl_gen5_activate[7] = 0x48; /* Command Code = 48h */ + + /* 8 Key bytes and block size */ + data_len = CYAPA_TSG_BL_KEY_SIZE + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE; + /* Data Length[15:0] */ + put_unaligned_le16(data_len, &bl_gen5_activate[8]); + bl_gen5_activate[10] = 0xa5; /* Key Byte 0 */ + bl_gen5_activate[11] = 0x01; + bl_gen5_activate[12] = 0x02; /* . */ + bl_gen5_activate[13] = 0x03; /* . */ + bl_gen5_activate[14] = 0xff; /* . */ + bl_gen5_activate[15] = 0xfe; + bl_gen5_activate[16] = 0xfd; + bl_gen5_activate[17] = 0x5a; /* Key Byte 7 */ + + /* Copy 60 bytes Meta Data Row Parameters */ + image = (struct cyapa_tsg_bin_image *)fw->data; + records_num = (fw->size - sizeof(struct cyapa_tsg_bin_image_head)) / + sizeof(struct cyapa_tsg_bin_image_data_record); + /* APP_INTEGRITY row is always the last row block */ + data = image->records[records_num - 1].record_data; + memcpy(&bl_gen5_activate[18], data, CYAPA_TSG_FLASH_MAP_METADATA_SIZE); + + meta_data_crc = crc_itu_t(0x, &bl_gen5_activate[18], + CYAPA_TSG_FLASH_MAP_METADATA_SIZE); + /* Meta Data CRC[15:0] */ + put_unaligned_le16(meta_data_crc, + &bl_gen5_activate[18 + CYAPA_TSG_FLASH_MAP_METADATA_SIZE]); + + cmd_crc = crc_itu_t(0x, &bl_gen5_activate[6], 4 + data_len); + put_unaligned_le16(cmd_crc, + &bl_gen5_activate[bl_gen5_activate_size - 3]); /* CRC[15:0] */ + bl_gen5_activate[bl_gen5_activate_size - 1] = GEN5_EOP_KEY; + + resp_len = sizeof(resp_data); + ret = cyapa_i2c_pip_cmd_irq_sync(cyapa, + bl_gen5_activate, sizeof(bl_gen5_activate), + resp_data, &resp_len, 12000, + cyapa_gen5_sort_tsg_pip_bl_resp_data, true); + if (ret || resp_len != GEN5_BL_INITIATE_RESP_LEN || + resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return (ret < 0) ? ret : -EAGAIN; + + return 0; +} + bool cyapa_gen5_sort_bl_exit_data(struct cyapa *cyapa, u8 *buf, int len) { if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE) @@ -958,6 +1038,215 @@ static int cyapa_gen5_bl_exit(struct cyapa *cyapa) return -ENODEV; } +static int cyapa_gen5_bl_enter(struct cyapa *cyapa) +{ + int ret; + u8 cmd[] = { 0x04, 0x00, 0x0
[PATCH v9 15/18] input: cyapa: add gen3 trackpad device read firmware image function support
Add read firmware image function supported for gen3 trackpad device, it can be used through debugfs read_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 67 1 file changed, 67 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index b477d67..f8aeb58 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -710,6 +710,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> + * + * <0xff> - every command starts with 0xff + * - the read command value is 0x3c + * - read commands include an 8-byte key: { 00 01 02 03 04 05 06 07 } + *- 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) @@ -756,6 +786,41 @@ 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) + return ret; + + cyapa->fw_image = cyapa->fw_image ? cyapa->fw_image : + devm_kzalloc(&cyapa->client->dev, CYAPA_FW_SIZE, GFP_KERNEL); + if (!cyapa->fw_image) + return -ENOMEM; + + 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) + return ret; + } + + cyapa->fw_image_size = CYAPA_FW_SIZE; + return 0; +} + static ssize_t cyapa_gen3_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1203,6 +1268,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, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v9 04/18] input: cyapa: add gen5 trackpad device basic functions support
Based on the cyapa core, add the gen5 trackpad device's basic functions supported, so gen5 trackpad device can work with kernel input system. And also based on the state parse interface, the cyapa driver can automatically determine the attached is gen3 or gen5 protocol trackpad device, then set the correct protocol to work with the attached trackpad device. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |2 +- drivers/input/mouse/cyapa.c | 13 + drivers/input/mouse/cyapa.h |1 + drivers/input/mouse/cyapa_gen5.c | 1656 ++ 4 files changed, 1671 insertions(+), 1 deletion(-) create mode 100644 drivers/input/mouse/cyapa_gen5.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 4bf6c83..1d3d997 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o -cyapatp-objs := cyapa.o cyapa_gen3.o +cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index cb81baf..fac361a 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -234,6 +234,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return ret; switch (cyapa->gen) { + case CYAPA_GEN5: + cyapa->ops = &cyapa_gen5_ops; + break; case CYAPA_GEN3: cyapa->ops = &cyapa_gen3_ops; break; @@ -335,6 +338,14 @@ static int cyapa_get_state(struct cyapa *cyapa) if (ret == 0) goto out_detected; } + if ((cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN5) && + !smbus && even_addr) { + ret = cyapa_gen5_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (ret == 0) + goto out_detected; + } /* * Cannot detect communication protocol based on current @@ -518,6 +529,8 @@ static int cyapa_initialize(struct cyapa *cyapa) if (cyapa_gen3_ops.initialize) ret = cyapa_gen3_ops.initialize(cyapa); + if (!ret && cyapa_gen5_ops.initialize) + ret = cyapa_gen5_ops.initialize(cyapa); if (ret) return ret; diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index b281dcb..060ac7d 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -318,5 +318,6 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode); extern const char unique_str[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; +extern const struct cyapa_dev_ops cyapa_gen5_ops; #endif diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c new file mode 100644 index 000..86cf50b --- /dev/null +++ b/drivers/input/mouse/cyapa_gen5.c @@ -0,0 +1,1656 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du + * + * Copyright (C) 2014 Cypress Semiconductor, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cyapa.h" + + +/* Macro of Gen5 */ +#define RECORD_EVENT_NONE0 +#define RECORD_EVENT_TOUCHDOWN 1 +#define RECORD_EVENT_DISPLACE2 +#define RECORD_EVENT_LIFTOFF 3 + +#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80 +#define CYAPA_TSG_IMG_FW_HDR_SIZE 13 +#define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE) +#define CYAPA_TSG_IMG_START_ROW_NUM 0x002e +#define CYAPA_TSG_IMG_END_ROW_NUM 0x01fe +#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff +#define CYAPA_TSG_IMG_MAX_RECORDS (CYAPA_TSG_IMG_END_ROW_NUM - \ + CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1) +#define CYAPA_TSG_IMG_READ_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2) +#define CYAPA_TSG_START_OF_APPLICATION 0x1700 +#define CYAPA_TSG_APP_INTEGRITY_SIZE60 +#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE 60 +#define CYAPA_TSG_BL_KEY_SIZE 8 + +/* Macro definitions for Gen5 trackpad device. */ +#define GEN5_TOUCH_REPORT_HEAD_SIZE 7 +#define GEN5_TOUCH_REPORT_MAX_SIZE 127 +#define GEN5_BTN_REPORT_HEAD_SIZE 6 +#define GEN5_BTN_REPORT_MAX_SIZE
[PATCH v9 02/18] input: cyapa: re-design driver to support multi-trackpad in one driver
In order to support multiple different chipsets and communication protocols trackpad devices in one cyapa driver, the new cyapa driver is re-designed with one cyapa driver core and multiple device specific functions component. The cyapa driver core is contained in this patch, it supplies basic functions that working with kernel and input subsystem, and also supplies the interfaces that the specific devices' component can connect and work together with as one driver. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 1087 ++- drivers/input/mouse/cyapa.h | 321 + 2 files changed, 682 insertions(+), 726 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index b3d7a2a..5029618 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -6,7 +6,7 @@ * Daniel Kurtz * Benson Leung * - * Copyright (C) 2011-2012 Cypress Semiconductor, Inc. + * Copyright (C) 2011-2014 Cypress Semiconductor, Inc. * Copyright (C) 2011-2012 Google, Inc. * * This file is subject to the terms and conditions of the GNU General Public @@ -20,601 +20,193 @@ #include #include #include +#include #include +#include +#include "cyapa.h" -/* APA trackpad firmware generation */ -#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ - -#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" - -/* commands for read/write registers of Cypress trackpad */ -#define CYAPA_CMD_SOFT_RESET 0x00 -#define CYAPA_CMD_POWER_MODE 0x01 -#define CYAPA_CMD_DEV_STATUS 0x02 -#define CYAPA_CMD_GROUP_DATA 0x03 -#define CYAPA_CMD_GROUP_CMD0x04 -#define CYAPA_CMD_GROUP_QUERY 0x05 -#define CYAPA_CMD_BL_STATUS0x06 -#define CYAPA_CMD_BL_HEAD 0x07 -#define CYAPA_CMD_BL_CMD 0x08 -#define CYAPA_CMD_BL_DATA 0x09 -#define CYAPA_CMD_BL_ALL 0x0a -#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b -#define CYAPA_CMD_BLK_HEAD 0x0c - -/* report data start reg offset address. */ -#define DATA_REG_START_OFFSET 0x - -#define BL_HEAD_OFFSET 0x00 -#define BL_DATA_OFFSET 0x10 - -/* - * Operational Device Status Register - * - * bit 7: Valid interrupt source - * bit 6 - 4: Reserved - * bit 3 - 2: Power status - * bit 1 - 0: Device status - */ -#define REG_OP_STATUS 0x00 -#define OP_STATUS_SRC 0x80 -#define OP_STATUS_POWER 0x0c -#define OP_STATUS_DEV 0x03 -#define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) - -/* - * Operational Finger Count/Button Flags Register - * - * bit 7 - 4: Number of touched finger - * bit 3: Valid data - * bit 2: Middle Physical Button - * bit 1: Right Physical Button - * bit 0: Left physical Button - */ -#define REG_OP_DATA1 0x01 -#define OP_DATA_VALID 0x08 -#define OP_DATA_MIDDLE_BTN 0x04 -#define OP_DATA_RIGHT_BTN 0x02 -#define OP_DATA_LEFT_BTN 0x01 -#define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ - OP_DATA_LEFT_BTN) - -/* - * Bootloader Status Register - * - * bit 7: Busy - * bit 6 - 5: Reserved - * bit 4: Bootloader running - * bit 3 - 1: Reserved - * bit 0: Checksum valid - */ -#define REG_BL_STATUS0x01 -#define BL_STATUS_BUSY 0x80 -#define BL_STATUS_RUNNING0x10 -#define BL_STATUS_DATA_VALID 0x08 -#define BL_STATUS_CSUM_VALID 0x01 - -/* - * Bootloader Error Register - * - * bit 7: Invalid - * bit 6: Invalid security key - * bit 5: Bootloading - * bit 4: Command checksum - * bit 3: Flash protection error - * bit 2: Flash checksum error - * bit 1 - 0: Reserved - */ -#define REG_BL_ERROR 0x02 -#define BL_ERROR_INVALID 0x80 -#define BL_ERROR_INVALID_KEY 0x40 -#define BL_ERROR_BOOTLOADING 0x20 -#define BL_ERROR_CMD_CSUM0x10 -#define BL_ERROR_FLASH_PROT 0x08 -#define BL_ERROR_FLASH_CSUM 0x04 - -#define BL_STATUS_SIZE 3 /* length of bootloader status registers */ -#define BLK_HEAD_BYTES 32 - -#define PRODUCT_ID_SIZE 16 -#define QUERY_DATA_SIZE 27 -#define REG_PROTOCOL_GEN_QUERY_OFFSET 20 - -#define REG_OFFSET_DATA_BASE 0x -#define REG_OFFSET_COMMAND_BASE 0x0028 -#define REG_OFFSET_QUERY_BASE0x002a - -#define CAPABILITY_LEFT_BTN_MASK (0x01 << 3) -#define CAPABILITY_RIGHT_BTN_MASK (0x01 << 4) -#define CAPABILITY_MIDDLE_BTN_MASK (0x01 << 5) -#define CAPABILITY_BTN_MASK (CAPABILITY_LEFT_BTN_MASK | \ - CAPABILITY_RIGHT_BTN_MASK | \ - CAPABILITY_MIDDLE_BTN_MASK) - -#define CYAPA_OFFSET_SOFT_RESET REG_OFFSET_COMMAND_BASE - -#define REG_OFFSET_POWER_MODE (REG_OFFSET_COMMAND_BASE + 1) - -#define PWR_MODE_MASK 0xfc -#define PWR_MODE_FULL_ACTIVE (0x3f << 2) -#define PWR_MODE_IDLE(0x05 << 2) /* default sleep time is 50 ms. */ -#define PWR_MODE_OFF (0x00 << 2) - -#define PWR_STATUS_MASK
[PATCH v9 00/18] input: cyapa: instruction of cyapa patches
V9 patches have below updates compared with v8 patches: 1) Removed all async thread stuff from the driver. 2) Split driver into 18 patches for each function change one patch. V8 patches have below updates compared with v7 patches: 1) [PATCH v8 01/13] - Remove the async thread for device detect in probe routine, now the device detect process is completely done within the device probe routine. 2) [PATCH v8 01/13] - Split the irq cmd hander function to separated function cyapa_default_irq_cmd_handler() and set it to interface cyapa_default_ops.irq_cmd_handler. 3) [PATCH v8 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler() to avoid miss-enter when device protocol is still in detecting. V7 patches have below updates compared with v6 patches: 1) [PATCH v7 01/13] - Split the irq cmd hander function to separated function cyapa_default_irq_cmd_handler() and set it to interface cyapa_default_ops.irq_cmd_handler. 2) [PATCH v7 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler() to avoid miss-enter when device protocol is still in detecting. V6 patches have below updates compared with v5 patches: 1) Remove patch 14 of the lid filtering from the cyapa driver. V5 patches have below updates compared with v4 patches: 1) Uses get_device()/put_device() instead of kobject_get()/kobject_put(); 2) Fix memories freed before debugfs entries issue; 3) Make cyapa_debugs_root valid in driver module level in module_init()/moudle_exit() ; 4) Fix i2c_transfer() may return partial transfer issues. 5) Add cyapa->removed flag to avoid detecting thread may still running when driver module is removed. 6) Fix the meanings of some comments and return error code not clear issue. This patch set is aimed to re-design the cyapa driver to support old gen3 trackpad devices and new gen5 trackpad devices in one cyapa driver, it's for easily productions support based on customers' requirements. And add sysfs functions and interfaces supported that required by users and customers. Since the earlier gen3 and the latest gen5 trackpad devices using two different chipsets, and have different protocols and interfaces, so if supported these two type trackpad devices in two different drivers, then it will be difficult to manage productions and later firmware updates. e.g.: It will cause customer don't know which one trackpad device firmware image to use and update when it has been used and integrated in same one productions, so here we support these two trackpad devices in same on driver. The new design cyapa driver contains: cyapa.c - the core of the re-design, supply interfaces and functions to system and read trackpad devices. cyapa.h - header file including macros and data structure definitions. cyapa_gen3.c - functions support for gen3 trackpad devices, cyapa_gen5.c - functions support for gen5 trackpad devices. Beside this introduction patch, it has 18 patches listed as below. For these patches each one is patched based on previous one. patch 1/18: add device resource management infrastructure supported. patch 2/18: re-design cyapa driver with core functions and interface to support multi-type trackpad devices. patch 3/18: add gen3 trackpad device basic functions supported into the re-design cyapa driver. patch 4/18: add gen5 trackpad device basic functions supported into the re-design cyapa driver. patch 5/18: add power management interfaces supported for the deivce. patch 6/18: add runtime power management interfaces supported for the device. patch 7/18: add sysfs interfaces supported in the cyapa driver. Including read firmware version, get production ID, read baseline, re-calibrate trackpad baselines and do trackpad firmware update. patch 8/18: add gen3 trackpad device's firmware update function supported. patch 9/18: add gen3 trackpad device's read baseline function supported. patch 10/18: add gen3 trackpad device's force re-calibrate function supported. patch 11/18: add gen5 trackpad device's firmware update function supported. patch 12/18: add gen5 trackpad device's read baseline function supported. patch 13/18: add gen5 trackpad device's force re-calibrate function. patch 14/18: add read firmware image debugfs interface supported in the cyapa driver. patch 15/18: add gen3 trackpad device's read firmware image function supported. patch 16/18: add gen5 trackpad device's read firmware image function supported. patch 17/18: add read trackpad device's sensors' raw data debugfs interface supported in the cyapa driver. patch 18/18: add gen5 trackpad device's read read raw function supported. 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. <>
RE: [PATCH v13 00/12] input: cyapa: instruction of cyapa patches
Jeremiah, Thank you very much for your review, comments and test. I will correct the spelling issues in next submit version. Thanks, Dudley > -Original Message- > From: linux-input-ow...@vger.kernel.org > [mailto:linux-input-ow...@vger.kernel.org] On Behalf Of Jeremiah Mahler > Sent: 2014?12?10? 12:10 > To: Dudley Du > Cc: dmitry.torok...@gmail.com; rydb...@euromail.se; ble...@google.com; > David Solda; linux-in...@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH v13 00/12] input: cyapa: instruction of cyapa patches > > Dudley, all, > > On Tue, Dec 09, 2014 at 05:11:32PM +0800, Dudley Du wrote: > > V13 patches have below updates, details of other updates see history list: > > 1) Remove all debugfs interface, including read_fw and raw_data interfaces. > > 2) This patches are made based linux next-20141208. > > > [...] > > I tested this patch set on an Acer C720 and other than the minor > problems I pointed out in other emails (CONFIG_CYAPA, spelling) it seems > to work fine and there are no obvious problems. > > Reviewed-by: Jeremiah Mahler > > -- > - Jeremiah Mahler > -- > To unsubscribe from this list: send the line "unsubscribe linux-input" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html 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. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v13 09/12] input: cyapa: add gen5 trackpad device firmware update function support
Jeremiah, Thank you very much for the solution. I will aplly it to my local patches immediately. Do you think it is required to re-submit the patch set right now? Thanks, Dudley > -Original Message- > From: linux-input-ow...@vger.kernel.org > [mailto:linux-input-ow...@vger.kernel.org] On Behalf Of Jeremiah Mahler > Sent: 2014?12?10? 16:55 > To: Dudley Du > Cc: linux-kernel@vger.kernel.org; linux-in...@vger.kernel.org > Subject: Re: [PATCH v13 09/12] input: cyapa: add gen5 trackpad device firmware > update function support > > Dudley, > > On Tue, Dec 09, 2014 at 07:33:03PM -0800, Jeremiah Mahler wrote: > > Dudley, > > > > On Tue, Dec 09, 2014 at 05:11:41PM +0800, Dudley Du wrote: > > > Add firmware image update function supported for gen5 trackpad device, > > > it can be used through sysfs update_fw interface. > > > TEST=test on Chromebooks. > > > > > > Signed-off-by: Dudley Du > > > --- > > > drivers/input/mouse/Kconfig | 2 +- > > > drivers/input/mouse/cyapa_gen5.c | 290 > +++ > > > 2 files changed, 291 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig > > > index d8b46b0..63e8b40 100644 > > > --- a/drivers/input/mouse/Kconfig > > > +++ b/drivers/input/mouse/Kconfig > > > @@ -205,7 +205,7 @@ config MOUSE_BCM5974 > > > > > > config MOUSE_CYAPA > > > tristate "Cypress APA I2C Trackpad support" > > > -depends on I2C > > > +depends on I2C && CRC_ITU_T > If this line is instead changed to: > > + depends on I2C > + select CRC_ITU_T > > It will upgrade correctly during make oldconfig without removing > MOUSE_CYAPA. > > And it looks like several other Kconfig files do it this way already. > > linux-next$ grep -r CRC_ITU_T $(find ./ -name Kconfig) > > > > help > > >This driver adds support for Cypress All Points Addressable (APA) > > >I2C Trackpads, including the ones used in 2012 Samsung Chromebooks. > > > diff --git a/drivers/input/mouse/cyapa_gen5.c > b/drivers/input/mouse/cyapa_gen5.c > > > > My initial config had MOUSE_CYAPA=m and CRC_ITU_T=n. > > I did a 'make oldconfig', no questions were asked, but it removed > > MOUSE_CYAPA since CRC_ITU_T wasn't enabled. Since the cyapa modules > > were removed the touchpad no longer works. Not a very good upgrade path :-( > > To fix this I have to manually enable MOUSE_CYAPA and CRC_ITU_T to get > > it working again. > > > > [...] > > > > -- > > - Jeremiah Mahler > > -- > - Jeremiah Mahler > -- > To unsubscribe from this list: send the line "unsubscribe linux-input" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html 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. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v14 00/12] input: cyapa: instruction of cyapa patches
V14 patches have below updates, details of other updates see history list: 1) Correct 9 miss spelling issues of "bufferred" to "buffered". 2) Fix the upgrade issue of removing MOUSE_CYAPA config when make oldconfig by replase "depends on I2C && CRC_ITU_T" with "depends on I2C" "select CRC_ITU_T" in patch 9. This patch series is aimed to re-design the cyapa driver to support old gen3 trackpad devices and new gen5 trackpad devices in one cyapa driver, it's for easily productions support based on customers' requirements. And add sysfs functions and interfaces supported that required by users and customers. Since the earlier gen3 and the latest gen5 trackpad devices using two different chipsets, and have different protocols and interfaces, so if supported these two type trackpad devices in two different drivers, then it will be difficult to manage productions and later firmware updates. e.g.: It will cause customer don't know which one trackpad device firmware image to use and update when it has been used and integrated in same one productions, so here we support these two trackpad devices in same on driver. The new design cyapa driver contains: cyapa.c - the core of the re-design, supply interfaces and functions to system and read trackpad devices. cyapa.h - header file including macros and data structure definitions. cyapa_gen3.c - functions support for gen3 trackpad devices, cyapa_gen5.c - functions support for gen5 trackpad devices. Beside this introduction patch, it has 12 patches listed as below. For these patches, each one is patched based on previous one. patch 1/12: re-design cyapa driver with core functions and interface to support multi-type trackpad devices. patch 2/12: add gen5 trackpad device basic functions supported into the re-design cyapa driver. patch 3/12: add power management interfaces supported for the device. patch 4/12: add runtime power management interfaces supported for the device. patch 5/12: add sysfs interfaces supported in the cyapa driver. Including read firmware version, get production ID, read baseline, re-calibrate trackpad baselines and do trackpad firmware update. patch 6/12: add gen3 trackpad device's firmware update function supported. patch 7/12: add gen3 trackpad device's read baseline function supported. patch 8/12: add gen3 trackpad device's force re-calibrate function supported. patch 9/12: add gen5 trackpad device's firmware update function supported. patch 10/12: add gen5 trackpad device's read baseline function supported. patch 11/12: add gen5 trackpad device's force re-calibrate function. patch 12/12: add acpi device id supported. History patch series modifications list: V13 patches have below updates, details of other updates see history list: 1) Remove all debugfs interface, including read_fw and raw_data interfaces. 2) This patches are made based linux next-20141208. V12 patches have below main updates compared with v11 patches: 1) Add check that when TP is detected but not operational, do not exit driver immediately, but wait and export the update_fw interface for recovering. 2) Re-arrange the function codes, remove unnesseary protype definitions in the header file. V11 patches have below main updates compared with v10 patches: 1) Add add acpi device id supported for old gen3 and new gen5 trackpad devices. 2) Fix the unable to update firmware issue when cyapa_open is not called which means the irq for firwmare update process is not enabled. This fix by checking if the irq is enabled, if not then enable irq before start to do firmware update. V10 patches have below main updates compared with v9 patches: 1) Modify code to following kernel code style. e.g.: correct to use error as return name when there is only error path, and fix the checkpatch.sh wanting in the driver. 2) Remove cyapa_remove method and use input open and close interface to following device resouse management infrastructure. 3) Modify cyapa_detect method to return tristate issue to make the return value much more consistent and clear. 4) Use platform supplied functions as possible instead of driver specific rewritten version. V9 patches have below updates compared with v8 patches: 1) Removed all async thread stuff from the driver. 2) Split driver into 18 patches for each function change one patch. V8 patches have below updates compared with v7 patches: 1) [PATCH v8 01/13] - Remove the async thread for device detect in probe routine, now the device detect process is completely done within the device probe routine. 2) [PATCH v8 01/13] - Split the irq cmd hander function to separated function cyapa_default_irq_cmd_handler() and set it to interface cyapa_default_ops.irq_cmd_handler. 3) [PATCH v8 06/13] - Add cyapa->gen check in cyapa_gen3_irq_cmd_handler() to avoid miss-enter when device protocol is still in detecting. V7 patches have below updates compared with v6 patches: 1) [PATCH v7 01/13] - Split the i
[PATCH v14 03/12] input: cyapa: add power management interfaces supported for the device
Add suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 111 1 file changed, 111 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 72eb44a..055f1df 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -582,6 +582,96 @@ out: return IRQ_HANDLED; } +/* + ** + * sysfs interface + ** +*/ +#ifdef CONFIG_PM_SLEEP +static ssize_t cyapa_show_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd = cyapa->suspend_power_mode; + u16 sleep_time; + int len; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + pwr_cmd = cyapa->suspend_power_mode; + sleep_time = cyapa->suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (pwr_cmd == PWR_MODE_BTN_ONLY) { + len = scnprintf(buf, PAGE_SIZE, "%s\n", BTN_ONLY_MODE_NAME); + } else if (pwr_cmd == PWR_MODE_OFF) { + len = scnprintf(buf, PAGE_SIZE, "%s\n", OFF_MODE_NAME); + } else { + if (cyapa->gen == CYAPA_GEN3) + sleep_time = cyapa_pwr_cmd_to_sleep_time(pwr_cmd); + len = scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); + } + + return len; +} + +static ssize_t cyapa_update_suspend_scanrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 sleep_time; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + + if (sysfs_streq(buf, BTN_ONLY_MODE_NAME)) { + cyapa->suspend_power_mode = PWR_MODE_BTN_ONLY; + } else if (sysfs_streq(buf, OFF_MODE_NAME)) { + cyapa->suspend_power_mode = PWR_MODE_OFF; + } else if (!kstrtou16(buf, 10, &sleep_time)) { + cyapa->suspend_sleep_time = max_t(u16, sleep_time, 1000); + cyapa->suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time); + } else { + count = 0; + } + + mutex_unlock(&cyapa->state_sync_lock); + + if (!count) + dev_err(dev, "invalid suspend scanrate ms parameters\n"); + return count ? count : -EINVAL; +} + +static DEVICE_ATTR(suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_suspend_scanrate, + cyapa_update_suspend_scanrate); + +static struct attribute *cyapa_power_wakeup_entries[] = { + &dev_attr_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_wakeup_group = { + .name = power_group_name, + .attrs = cyapa_power_wakeup_entries, +}; + +static void cyapa_remove_power_wakeup_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_wakeup_group); +} +#endif /* CONFIG_PM_SLEEP */ + static int cyapa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { @@ -621,6 +711,27 @@ static int cyapa_probe(struct i2c_client *client, return error; } +#ifdef CONFIG_PM_SLEEP + if (device_can_wakeup(dev)) { + error = sysfs_merge_group(&client->dev.kobj, + &cyapa_power_wakeup_group); + if (error) { + dev_err(dev, "failed to add power wakeup group: %d\n", + error); + return error; + } + + error = devm_add_action(dev, + cyapa_remove_power_wakeup_group, cyapa); + if (error) { + cyapa_remove_power_wakeup_group(cyapa); + dev_err(dev, "failed to add power cleanup action: %d\n", + error); + return error; + } + } +#endif /* CONFIG_PM_SLEEP */ + error = devm_request_threaded_irq(dev, client->irq,
[PATCH v14 02/12] input: cyapa: add gen5 trackpad device basic functions support
Based on the cyapa core, add the gen5 trackpad device's basic functions supported, so gen5 trackpad device can work with kernel input system. And also based on the state parse interface, the cyapa driver can automatically determine the attached is gen3 or gen5 protocol trackpad device, then set the correct protocol to work with the attached trackpad device. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |2 +- drivers/input/mouse/cyapa.c | 13 + drivers/input/mouse/cyapa.h |1 + drivers/input/mouse/cyapa_gen5.c | 1660 ++ 4 files changed, 1675 insertions(+), 1 deletion(-) create mode 100644 drivers/input/mouse/cyapa_gen5.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 8bd950d..8a9c98e 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o -cyapatp-objs := cyapa.o cyapa_gen3.o +cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index ec25445..72eb44a 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -164,6 +164,14 @@ static int cyapa_get_state(struct cyapa *cyapa) if (!error) goto out_detected; } + if ((cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN5) && + !smbus && even_addr) { + error = cyapa_gen5_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (!error) + goto out_detected; + } /* * Write 0x00 0x00 to trackpad device to force update its @@ -247,6 +255,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return error; switch (cyapa->gen) { + case CYAPA_GEN5: + cyapa->ops = &cyapa_gen5_ops; + break; case CYAPA_GEN3: cyapa->ops = &cyapa_gen3_ops; break; @@ -483,6 +494,8 @@ static int cyapa_initialize(struct cyapa *cyapa) if (cyapa_gen3_ops.initialize) error = cyapa_gen3_ops.initialize(cyapa); + if (!error && cyapa_gen5_ops.initialize) + error = cyapa_gen5_ops.initialize(cyapa); if (error) return error; diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index d79eeb1..4a73081 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -312,5 +312,6 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode); extern const char unique_str[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; +extern const struct cyapa_dev_ops cyapa_gen5_ops; #endif diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c new file mode 100644 index 000..c2340ae --- /dev/null +++ b/drivers/input/mouse/cyapa_gen5.c @@ -0,0 +1,1660 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du + * + * Copyright (C) 2014 Cypress Semiconductor, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cyapa.h" + + +/* Macro of Gen5 */ +#define RECORD_EVENT_NONE0 +#define RECORD_EVENT_TOUCHDOWN 1 +#define RECORD_EVENT_DISPLACE2 +#define RECORD_EVENT_LIFTOFF 3 + +#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80 +#define CYAPA_TSG_IMG_FW_HDR_SIZE 13 +#define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE) +#define CYAPA_TSG_IMG_START_ROW_NUM 0x002e +#define CYAPA_TSG_IMG_END_ROW_NUM 0x01fe +#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff +#define CYAPA_TSG_IMG_MAX_RECORDS (CYAPA_TSG_IMG_END_ROW_NUM - \ + CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1) +#define CYAPA_TSG_IMG_READ_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2) +#define CYAPA_TSG_START_OF_APPLICATION 0x1700 +#define CYAPA_TSG_APP_INTEGRITY_SIZE60 +#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE 60 +#define CYAPA_TSG_BL_KEY_SIZE 8 + +/* Macro definitions for Gen5 trackpad device. */ +#define GEN5_TOUCH_REPORT_HEAD_SIZE 7 +#define GEN5_TOUCH_REPORT_MAX_SIZE 127 +#define GEN5_BTN_REPORT_HEAD_SIZE 6 +#define GEN5_BTN_REPORT_MAX_SIZE
[PATCH v14 01/12] input: cyapa: re-design driver to support multi-trackpad in one driver
In order to support multiple different chipsets and communication protocols trackpad devices in one cyapa driver, the new cyapa driver is re-designed with one cyapa driver core and multiple device specific functions component. The cyapa driver core is contained in this patch, it supplies basic functions that working with kernel and input subsystem, and also supplies the interfaces that the specific devices' component can connect and work together with as one driver. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |3 +- drivers/input/mouse/cyapa.c | 1050 ++ drivers/input/mouse/cyapa.h | 316 drivers/input/mouse/cyapa_gen3.c | 793 4 files changed, 1498 insertions(+), 664 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h create mode 100644 drivers/input/mouse/cyapa_gen3.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 560003d..8bd950d 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974)+= bcm5974.o -obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o @@ -24,6 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o +cyapatp-objs := cyapa.o cyapa_gen3.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 1bece8c..ec25445 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -20,408 +20,107 @@ #include #include #include +#include #include +#include +#include "cyapa.h" -/* APA trackpad firmware generation */ -#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ - -#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" - -/* commands for read/write registers of Cypress trackpad */ -#define CYAPA_CMD_SOFT_RESET 0x00 -#define CYAPA_CMD_POWER_MODE 0x01 -#define CYAPA_CMD_DEV_STATUS 0x02 -#define CYAPA_CMD_GROUP_DATA 0x03 -#define CYAPA_CMD_GROUP_CMD0x04 -#define CYAPA_CMD_GROUP_QUERY 0x05 -#define CYAPA_CMD_BL_STATUS0x06 -#define CYAPA_CMD_BL_HEAD 0x07 -#define CYAPA_CMD_BL_CMD 0x08 -#define CYAPA_CMD_BL_DATA 0x09 -#define CYAPA_CMD_BL_ALL 0x0a -#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b -#define CYAPA_CMD_BLK_HEAD 0x0c - -/* report data start reg offset address. */ -#define DATA_REG_START_OFFSET 0x - -#define BL_HEAD_OFFSET 0x00 -#define BL_DATA_OFFSET 0x10 - -/* - * Operational Device Status Register - * - * bit 7: Valid interrupt source - * bit 6 - 4: Reserved - * bit 3 - 2: Power status - * bit 1 - 0: Device status - */ -#define REG_OP_STATUS 0x00 -#define OP_STATUS_SRC 0x80 -#define OP_STATUS_POWER 0x0c -#define OP_STATUS_DEV 0x03 -#define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) - -/* - * Operational Finger Count/Button Flags Register - * - * bit 7 - 4: Number of touched finger - * bit 3: Valid data - * bit 2: Middle Physical Button - * bit 1: Right Physical Button - * bit 0: Left physical Button - */ -#define REG_OP_DATA1 0x01 -#define OP_DATA_VALID 0x08 -#define OP_DATA_MIDDLE_BTN 0x04 -#define OP_DATA_RIGHT_BTN 0x02 -#define OP_DATA_LEFT_BTN 0x01 -#define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ - OP_DATA_LEFT_BTN) - -/* - * Bootloader Status Register - * - * bit 7: Busy - * bit 6 - 5: Reserved - * bit 4: Bootloader running - * bit 3 - 1: Reserved - * bit 0: Checksum valid - */ -#define REG_BL_STATUS0x01 -#define BL_STATUS_BUSY 0x80 -#define BL_STATUS_RUNNING0x10 -#define BL_STATUS_DATA_VALID 0x08 -#define BL_STATUS_CSUM_VALID 0x01 - -/* - * Bootloader Error Register - * - * bit 7: Invalid - * bit 6: Invalid security key - * bit 5: Bootloading - * bit 4: Command checksum - * bit 3: Flash protection error - * bit 2: Flash checksum error - * bit 1 - 0: Reserved - */ -#define REG_BL_ERROR 0x02 -#define BL_ERROR_INVALID 0x80 -#define BL_ERROR_INVALID_KEY 0x40 -#define BL_ERROR_BOOTLOADING 0x20 -#define BL_ERROR_CMD_CSUM0x10 -#define BL_ERROR_FLASH_PROT 0x08 -#define BL_ERROR_FLASH_CSUM 0x04 - -#define BL_STATUS_SIZE 3 /* length of bootloader status registers */ -#define BLK_HEAD_BYTES 32 - -#define PRODUCT_ID_SIZE 16 -#d
[PATCH v14 07/12] input: cyapa: add gen3 trackpad device read baseline function support
Add read baseline function supported for gen3 trackpad device, it can be used through sysfs baseline interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 71 1 file changed, 71 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 1110668..3b2ad88 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -754,6 +754,75 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_show_baseline(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int max_baseline, min_baseline; + int tries = 3; + int ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_REPORT_BASELINE_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send report baseline command. %d\n", + ret); + goto out; + } + + do { + usleep_range(1, 2); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status. err = %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Device timed out going to Normal state.\n"); + ret = -ETIMEDOUT; + goto out; + } + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MAX_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read max baseline. err = %d\n", ret); + goto out; + } + max_baseline = ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_MIN_BASELINE); + if (ret < 0) { + dev_err(dev, "Failed to read min baseline. err = %d\n", ret); + goto out; + } + min_baseline = ret; + + dev_dbg(dev, "Baseline report successful. Max: %d Min: %d\n", + max_baseline, min_baseline); + ret = scnprintf(buf, PAGE_SIZE, "%d %d\n", max_baseline, min_baseline); + +out: + return ret; +} + /* * cyapa_get_wait_time_for_pwr_cmd * @@ -1067,6 +1136,8 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .update_fw = cyapa_gen3_do_fw_update, .bl_deactivate = cyapa_gen3_bl_deactivate, + .show_baseline = cyapa_gen3_show_baseline, + .state_parse = cyapa_gen3_state_parse, .operational_check = cyapa_gen3_do_operational_check, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v14 05/12] input: cyapa: add sysfs interfaces supported in the cyapa driver
Add device's basic control and features supported in cyapa driver through sysfs file system interfaces. These interfaces are commonly used in pre- and after production, for trackpad device state checking, managing and firmware image updating. These interfaces including mode, firmware_version and product_id interfaces for reading firmware version and trackpad device product id values, and including update_fw interface to command firmware image update process. Also including baseline and calibrate interfaces for reading and checking trackpad device's sensors states. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 327 1 file changed, 327 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index f19754c..ff8cd9b 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -32,6 +32,8 @@ #define CYAPA_ADAPTER_FUNC_SMBUS 2 #define CYAPA_ADAPTER_FUNC_BOTH 3 +#define CYAPA_FW_NAME "cyapa.bin" + const char unique_str[] = "CYTRA"; static int cyapa_reinitialize(struct cyapa *cyapa); @@ -449,6 +451,29 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) return 0; } +static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa) +{ + struct input_dev *input = cyapa->input; + + if (!input || !input->users) { + if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0); + enable_irq(cyapa->client->irq); + } +} + +static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa) +{ + struct input_dev *input = cyapa->input; + + if (!input || !input->users) { + disable_irq(cyapa->client->irq); + if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + } +} + /* * cyapa_sleep_time_to_pwr_cmd and cyapa_pwr_cmd_to_sleep_time * @@ -790,6 +815,295 @@ static int cyapa_start_runtime(struct cyapa *cyapa) } #endif /* CONFIG_PM_RUNTIME */ +static ssize_t cyapa_show_fm_ver(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int error; + struct cyapa *cyapa = dev_get_drvdata(dev); + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + error = scnprintf(buf, PAGE_SIZE, "%d.%d\n", cyapa->fw_maj_ver, +cyapa->fw_min_ver); + mutex_unlock(&cyapa->state_sync_lock); + return error; +} + +static ssize_t cyapa_show_product_id(struct device *dev, +struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int size; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + size = scnprintf(buf, PAGE_SIZE, "%s\n", cyapa->product_id); + mutex_unlock(&cyapa->state_sync_lock); + return size; +} + +static int cyapa_firmware(struct cyapa *cyapa, const char *fw_name) +{ + struct device *dev = &cyapa->client->dev; + const struct firmware *fw; + int error; + + error = request_firmware(&fw, fw_name, dev); + if (error) { + dev_err(dev, "Could not load firmware from %s: %d\n", + fw_name, error); + return error; + } + + if (cyapa->ops->check_fw) { + error = cyapa->ops->check_fw(cyapa, fw); + if (error) { + dev_err(dev, "Invalid CYAPA firmware image: %s\n", + fw_name); + goto done; + } + } else { + dev_err(dev, "No valid device ops->check_fw handler set.\n"); + error = -ENODEV; + goto done; + } + + /* +* Resume the potentially suspended device because doing FW +* update on a device not in the FULL mode has a chance to +* fail. +*/ + pm_runtime_get_sync(dev); + + /* Require IRQ support for firmware update commands. */ + cyapa_enable_irq_for_cmd(cyapa); + + if (cyapa->ops->bl_enter) { + error = cyapa->ops->bl_enter(cyapa); + if (error) { + dev_err(dev, "bl_enter failed, %d\n", error); + goto err_detect; + } + } + + if (cyapa->ops->bl_activate) { + error = cyapa->ops->bl_activate(cyapa); +
[PATCH v14 08/12] input: cyapa: add gen3 trackpad device force re-calibrate function support
Add force re-calibrate function supported for gen3 trackpad device, it can be used through sysfs calibrate interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 58 1 file changed, 58 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 3b2ad88..c654109 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -754,6 +754,63 @@ static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, return 0; } +static ssize_t cyapa_gen3_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int tries = 20; /* max recalibration timeout 2s. */ + int ret; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status: %d\n", ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) { + dev_warn(dev, "Trackpad device is busy, device state: 0x%02x\n", +ret); + ret = -EAGAIN; + goto out; + } + + ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, + OP_RECALIBRATION_MASK); + if (ret < 0) { + dev_err(dev, "Failed to send calibrate command: %d\n", + ret); + goto out; + } + + do { + /* +* For this recalibration, the max time will not exceed 2s. +* The average time is approximately 500 - 700 ms, and we +* will check the status every 100 - 200ms. +*/ + usleep_range(10, 20); + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS); + if (ret < 0) { + dev_err(dev, "Error reading dev status: %d\n", + ret); + goto out; + } + if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) + break; + } while (--tries); + + if (tries == 0) { + dev_err(dev, "Failed to calibrate. Timeout.\n"); + ret = -ETIMEDOUT; + goto out; + } + dev_dbg(dev, "Calibration successful.\n"); + +out: + return ret < 0 ? ret : count; +} + static ssize_t cyapa_gen3_show_baseline(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1137,6 +1194,7 @@ const struct cyapa_dev_ops cyapa_gen3_ops = { .bl_deactivate = cyapa_gen3_bl_deactivate, .show_baseline = cyapa_gen3_show_baseline, + .calibrate_store = cyapa_gen3_do_calibrate, .state_parse = cyapa_gen3_state_parse, .operational_check = cyapa_gen3_do_operational_check, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v14 04/12] input: cyapa: add runtime power management interfaces supported for the device
Add runtime_suspend_scanrate_ms power management interfaces in device's power group, so users or applications can control the runtime power management strategy of trackpad device as their requirements. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 171 +++- drivers/input/mouse/cyapa.h | 4 ++ 2 files changed, 174 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 055f1df..f19754c 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "cyapa.h" @@ -334,6 +335,8 @@ static int cyapa_open(struct input_dev *input) } enable_irq(client->irq); + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); out: mutex_unlock(&cyapa->state_sync_lock); return error; @@ -347,8 +350,10 @@ static void cyapa_close(struct input_dev *input) mutex_lock(&cyapa->state_sync_lock); disable_irq(client->irq); + pm_runtime_disable(&client->dev); if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + pm_runtime_set_suspended(&client->dev); mutex_unlock(&cyapa->state_sync_lock); } @@ -549,6 +554,7 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) struct device *dev = &cyapa->client->dev; bool cont; + pm_runtime_get_sync(dev); if (device_may_wakeup(dev)) pm_wakeup_event(dev, 0); @@ -579,6 +585,8 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) } out: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); return IRQ_HANDLED; } @@ -672,6 +680,116 @@ static void cyapa_remove_power_wakeup_group(void *data) } #endif /* CONFIG_PM_SLEEP */ +#ifdef CONFIG_PM_RUNTIME +static ssize_t cyapa_show_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u8 pwr_cmd; + u16 sleep_time; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + pwr_cmd = cyapa->runtime_suspend_power_mode; + sleep_time = cyapa->runtime_suspend_sleep_time; + mutex_unlock(&cyapa->state_sync_lock); + + if (cyapa->gen == CYAPA_GEN3) + return scnprintf(buf, PAGE_SIZE, "%u\n", + cyapa_pwr_cmd_to_sleep_time(pwr_cmd)); + return scnprintf(buf, PAGE_SIZE, "%u\n", sleep_time); +} + +static ssize_t cyapa_update_rt_suspend_scanrate(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + u16 time; + int error; + + if (buf == NULL || count == 0 || kstrtou16(buf, 10, &time)) { + dev_err(dev, "invalid runtime suspend scanrate ms parameter\n"); + return -EINVAL; + } + + /* +* When the suspend scanrate is changed, pm_runtime_get to resume +* a potentially suspended device, update to the new pwr_cmd +* and then pm_runtime_put to suspend into the new power mode. +*/ + pm_runtime_get_sync(dev); + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + cyapa->runtime_suspend_sleep_time = max_t(u16, time, 1000); + cyapa->runtime_suspend_power_mode = + cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time); + mutex_unlock(&cyapa->state_sync_lock); + pm_runtime_put_sync_autosuspend(dev); + + return count; +} + +static DEVICE_ATTR(runtime_suspend_scanrate_ms, S_IRUGO|S_IWUSR, + cyapa_show_rt_suspend_scanrate, + cyapa_update_rt_suspend_scanrate); + +static struct attribute *cyapa_power_runtime_entries[] = { + &dev_attr_runtime_suspend_scanrate_ms.attr, + NULL, +}; + +static const struct attribute_group cyapa_power_runtime_group = { + .name = power_group_name, + .attrs = cyapa_power_runtime_entries, +}; + +static void cyapa_remove_power_runtime_group(void *data) +{ + struct cyapa *cyapa = data; + + sysfs_unmerge_group(&cyapa->client->dev.kobj, + &cyapa_power_runtime_group); +} + +static int cyapa_start_runtime(struct cyapa *cyapa) +{ + struct device *de
[PATCH v14 09/12] input: cyapa: add gen5 trackpad device firmware update function support
Add firmware image update function supported for gen5 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Kconfig | 1 + drivers/input/mouse/cyapa_gen5.c | 290 +++ 2 files changed, 291 insertions(+) diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index d8b46b0..728490e 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -206,6 +206,7 @@ config MOUSE_BCM5974 config MOUSE_CYAPA tristate "Cypress APA I2C Trackpad support" depends on I2C + select CRC_ITU_T help This driver adds support for Cypress All Points Addressable (APA) I2C Trackpads, including the ones used in 2012 Samsung Chromebooks. diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index c2340ae..e4bb6e4 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "cyapa.h" @@ -911,6 +912,86 @@ static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) return -EAGAIN; } +static int cyapa_gen5_bl_initiate(struct cyapa *cyapa, + const struct firmware *fw) +{ + u16 length = 0; + u16 data_len = 0; + u16 meta_data_crc = 0; + u16 cmd_crc = 0; + u8 bl_gen5_activate[18 + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE + 3]; + int bl_gen5_activate_size = 0; + u8 resp_data[11]; + int resp_len; + struct cyapa_tsg_bin_image *image; + int records_num; + u8 *data; + int error; + + /* Try to dump all buffered report data before send any command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + bl_gen5_activate_size = sizeof(bl_gen5_activate); + memset(bl_gen5_activate, 0, bl_gen5_activate_size); + + /* Output Report Register Address[15:0] = 0004h */ + bl_gen5_activate[0] = 0x04; + bl_gen5_activate[1] = 0x00; + + /* Total command length[15:0] */ + length = bl_gen5_activate_size - 2; + put_unaligned_le16(length, &bl_gen5_activate[2]); + bl_gen5_activate[4] = 0x40; /* Report ID = 40h */ + bl_gen5_activate[5] = 0x00; /* RSVD = 00h */ + + bl_gen5_activate[6] = GEN5_SOP_KEY; /* SOP = 01h */ + bl_gen5_activate[7] = 0x48; /* Command Code = 48h */ + + /* 8 Key bytes and block size */ + data_len = CYAPA_TSG_BL_KEY_SIZE + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE; + /* Data Length[15:0] */ + put_unaligned_le16(data_len, &bl_gen5_activate[8]); + bl_gen5_activate[10] = 0xa5; /* Key Byte 0 */ + bl_gen5_activate[11] = 0x01; + bl_gen5_activate[12] = 0x02; /* . */ + bl_gen5_activate[13] = 0x03; /* . */ + bl_gen5_activate[14] = 0xff; /* . */ + bl_gen5_activate[15] = 0xfe; + bl_gen5_activate[16] = 0xfd; + bl_gen5_activate[17] = 0x5a; /* Key Byte 7 */ + + /* Copy 60 bytes Meta Data Row Parameters */ + image = (struct cyapa_tsg_bin_image *)fw->data; + records_num = (fw->size - sizeof(struct cyapa_tsg_bin_image_head)) / + sizeof(struct cyapa_tsg_bin_image_data_record); + /* APP_INTEGRITY row is always the last row block */ + data = image->records[records_num - 1].record_data; + memcpy(&bl_gen5_activate[18], data, CYAPA_TSG_FLASH_MAP_METADATA_SIZE); + + meta_data_crc = crc_itu_t(0x, &bl_gen5_activate[18], + CYAPA_TSG_FLASH_MAP_METADATA_SIZE); + /* Meta Data CRC[15:0] */ + put_unaligned_le16(meta_data_crc, + &bl_gen5_activate[18 + CYAPA_TSG_FLASH_MAP_METADATA_SIZE]); + + cmd_crc = crc_itu_t(0x, &bl_gen5_activate[6], 4 + data_len); + put_unaligned_le16(cmd_crc, + &bl_gen5_activate[bl_gen5_activate_size - 3]); /* CRC[15:0] */ + bl_gen5_activate[bl_gen5_activate_size - 1] = GEN5_EOP_KEY; + + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + bl_gen5_activate, sizeof(bl_gen5_activate), + resp_data, &resp_len, 12000, + cyapa_gen5_sort_tsg_pip_bl_resp_data, true); + if (error || resp_len != GEN5_BL_INITIATE_RESP_LEN || + resp_data[2] != GEN5_BL_RESP_REPORT_ID || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return error ? error : -EAGAIN; + + return 0; +} + bool cyapa_gen5_sort_bl_exit_data(struct cyapa *cyapa, u8 *buf, int len) { if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE) @@ -960,6 +1041,210 @@ static int cyapa_gen5_bl_exit(struct cyapa *cyapa) return -ENODEV; } +static int cyapa_gen5_bl_enter(struct cyapa *cyapa) +
[PATCH v14 12/12] input: cyapa: add acpi device id supported
Add acpi device tree supported. acpi device id "CYAP" is for old gen3 trackpad devices. acpi device id "CYAP0001" is for new gen5 trackpad devices. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index ff8cd9b..c992bd6 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "cyapa.h" @@ -1322,11 +1323,23 @@ static const struct i2c_device_id cyapa_id_table[] = { }; MODULE_DEVICE_TABLE(i2c, cyapa_id_table); +#ifdef CONFIG_ACPI +static const struct acpi_device_id cyapa_acpi_id[] = { + { "CYAP", 0 }, /* Gen3 trackpad with 0x67 I2C address. */ + { "CYAP0001", 0 }, /* Gen5 trackpad with 0x24 I2C address. */ + { } +}; +MODULE_DEVICE_TABLE(acpi, cyapa_acpi_id); +#endif + static struct i2c_driver cyapa_driver = { .driver = { .name = "cyapa", .owner = THIS_MODULE, .pm = &cyapa_pm_ops, +#ifdef CONFIG_ACPI + .acpi_match_table = ACPI_PTR(cyapa_acpi_id), +#endif }, .probe = cyapa_probe, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v14 10/12] input: cyapa: add gen5 trackpad device read baseline function support
Add read baseline function supported for gen5 trackpad device, it can be used through sysfs baseline interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.h | 2 + drivers/input/mouse/cyapa_gen5.c | 621 +++ 2 files changed, 623 insertions(+) diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index eafeb79..39e7941 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -285,6 +285,8 @@ struct cyapa { u8 y_origin; /* Y Axis Origin: 0 = top; 1 = bottom. */ int electrodes_x; /* Number of electrodes on the X Axis*/ int electrodes_y; /* Number of electrodes on the Y Axis*/ + int electrodes_rx; /* Number of Rx electrodes */ + int algined_electrodes_rx; /* 4 aligned */ int max_z; /* diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index e4bb6e4..365a5b9 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1533,6 +1533,625 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, return 0; } +static int cyapa_gen5_resume_scanning(struct cyapa *cyapa) +{ + u8 cmd[7] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 }; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = 6; + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, 7, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x04)) + return -EINVAL; + + /* Try to dump all buffered data when resuming scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) +{ + u8 cmd[7] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 }; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + resp_len = 6; + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, 7, + resp_data, &resp_len, + 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x03)) + return -EINVAL; + + /* Try to dump all buffered data when suspending scanning. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + return 0; +} + +static s32 two_complement_to_s32(s32 value, int num_bits) +{ + if (value >> (num_bits - 1)) + value |= -1 << num_bits; + return value; +} + +static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len) +{ + int data_size; + bool big_endian; + bool unsigned_type; + s32 value; + + data_size = (data_format & 0x07); + big_endian = ((data_format & 0x10) == 0x00); + unsigned_type = ((data_format & 0x20) == 0x00); + + if (buf_len < data_size) + return 0; + + switch (data_size) { + case 1: + value = buf[0]; + break; + case 2: + if (big_endian) + value = get_unaligned_be16(buf); + else + value = get_unaligned_le16(buf); + break; + case 4: + if (big_endian) + value = get_unaligned_be32(buf); + else + value = get_unaligned_le32(buf); + break; + default: + /* Should not happen, just as default case here. */ + value = 0; + break; + } + + if (!unsigned_type) + value = two_complement_to_s32(value, data_size * 8); + + return value; +} + + +/* + * Read all the global mutual or self idac data or mutual or self local PWC + * data based on the @idac_data_type. + * If the input value of @data_size is 0, then means read global mutual or + * self idac data. For read global mutual idac data, @idac_max, @idac_min and + * @idac_ave are in order used to return the max value of global mutual idac + * data, the min value of global mutual idac and the average value of the + * global mutual idac data. For read global self idac data, @idac_max is used + * to return the global self cap idac data in Rx direction, @idac_min is used + * to return the global self cap idac data in Tx direction. @idac_ave is not + * used. + * If the input value of @data_size is not 0, than means read the mutual or + * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to + * return th
[PATCH v14 11/12] input: cyapa: add gen5 trackpad device force re-calibrate function support
Add force re-calibrate function supported for gen5 trackpad device, it can be used through sysfs calibrate interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen5.c | 65 1 file changed, 65 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 365a5b9..f673bb3 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -1581,6 +1581,70 @@ static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa) return 0; } +static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa, + u8 calibrate_sensing_mode_type) +{ + u8 cmd[8]; + u8 resp_data[6]; + int resp_len; + int error; + + /* Try to dump all buffered data before doing command. */ + cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); + + cmd[0] = 0x04; + cmd[1] = 0x00; + cmd[2] = 0x06; + cmd[3] = 0x00; + cmd[4] = GEN5_APP_CMD_REPORT_ID; + cmd[5] = 0x00; + cmd[6] = GEN5_CMD_CALIBRATE; + cmd[7] = calibrate_sensing_mode_type; + resp_len = sizeof(resp_data); + error = cyapa_i2c_pip_cmd_irq_sync(cyapa, + cmd, sizeof(cmd), + resp_data, &resp_len, + 5000, cyapa_gen5_sort_tsg_pip_app_resp_data, true); + if (error || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_CALIBRATE) || + !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5])) + return error < 0 ? error : -EAGAIN; + + return 0; +} + +static ssize_t cyapa_gen5_do_calibrate(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t count) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int error, calibrate_error; + + /* 1. Suspend Scanning*/ + error = cyapa_gen5_suspend_scanning(cyapa); + if (error) + return error; + + /* 2. Do mutual capacitance fine calibrate. */ + calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_MUTUAL_CAP_FINE); + if (calibrate_error) + goto resume_scanning; + + /* 3. Do self capacitance calibrate. */ + calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa, + CYAPA_SENSING_MODE_SELF_CAP); + if (calibrate_error) + goto resume_scanning; + +resume_scanning: + /* 4. Resume Scanning*/ + error = cyapa_gen5_resume_scanning(cyapa); + if (error || calibrate_error) + return error ? error : calibrate_error; + + return count; +} + static s32 two_complement_to_s32(s32 value, int num_bits) { if (value >> (num_bits - 1)) @@ -2558,6 +2622,7 @@ const struct cyapa_dev_ops cyapa_gen5_ops = { .update_fw = cyapa_gen5_do_fw_update, .show_baseline = cyapa_gen5_show_baseline, + .calibrate_store = cyapa_gen5_do_calibrate, .initialize = cyapa_gen5_initialize, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v14 06/12] input: cyapa: add gen3 trackpad device firmware update function support
Add firmware image update function supported for gen3 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 284 +++ 1 file changed, 284 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index a50986c..1110668 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -416,6 +416,72 @@ 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 error; + + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; + if (cyapa->state == CYAPA_STATE_BL_IDLE) { + /* Already in BL_IDLE. Skipping reset. */ + return 0; + } + + if (cyapa->state != CYAPA_STATE_OP) + return -EAGAIN; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + error = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01); + if (error) + return -EIO; + + usleep_range(25000, 5); + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; + 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 error; + + error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate), + bl_activate); + if (error) + return error; + + /* Wait for bootloader to activate; takes between 2 and 12 seconds */ + msleep(2000); + error = cyapa_poll_state(cyapa, 11000); + if (error) + return error; + if (cyapa->state != CYAPA_STATE_BL_ACTIVE) + return -EAGAIN; + + return 0; +} + static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { int error; @@ -476,6 +542,218 @@ 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 =
RE: [PATCH v14 00/12] input: cyapa: instruction of cyapa patches
Jeremiah, Thanks for your information. I will fix the space check warnning. Are there any other driver check tools that need to be run? Thanks. Dudley > -Original Message- > From: linux-input-ow...@vger.kernel.org > [mailto:linux-input-ow...@vger.kernel.org] On Behalf Of Jeremiah Mahler > Sent: 2014?12?13? 18:18 > To: Dudley Du > Cc: linux-in...@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH v14 00/12] input: cyapa: instruction of cyapa patches > > Dudley, > > On Fri, Dec 12, 2014 at 10:27:30AM +0800, Dudley Du wrote: > > V14 patches have below updates, details of other updates see history list: > > 1) Correct 9 miss spelling issues of "bufferred" to "buffered". > > 2) Fix the upgrade issue of removing MOUSE_CYAPA config when make oldconfig > >by replase "depends on I2C && CRC_ITU_T" with > > "depends on I2C" > > "select CRC_ITU_T" > >in patch 9. > > > [...] > > I found some sparse warnings that should be fixed. > > jeri@newt:~/linux-next$ touch drivers/input/mouse/*.c > jeri@newt:~/linux-next$ touch drivers/input/mouse/*.h > jeri@newt:~/linux-next$ make C=1 > CHK include/config/kernel.release > CHK include/generated/uapi/linux/version.h > CHK include/generated/utsrelease.h > CALLscripts/checksyscalls.sh > CHK include/generated/compile.h > CHK kernel/config_data.h > CHECK drivers/input/mouse/cyapa.c > drivers/input/mouse/cyapa.c:43:9: warning: symbol 'cyapa_i2c_read' was > not declared. Should it be static? > drivers/input/mouse/cyapa.c:80:9: warning: symbol 'cyapa_i2c_write' was > not declared. Should it be static? > drivers/input/mouse/cyapa.c:289:5: warning: symbol 'cyapa_detect' was > not declared. Should it be static? > CC [M] drivers/input/mouse/cyapa.o > CHECK drivers/input/mouse/cyapa_gen3.c > drivers/input/mouse/cyapa_gen3.c:299:5: warning: symbol > 'cyapa_read_byte' was not declared. Should it be static? > drivers/input/mouse/cyapa_gen3.c:312:5: warning: symbol > 'cyapa_write_byte' was not declared. Should it be static? > drivers/input/mouse/cyapa_gen3.c:331:9: warning: symbol > 'cyapa_i2c_reg_write_block' was not declared. Should it be static? > CC [M] drivers/input/mouse/cyapa_gen3.o > CHECK drivers/input/mouse/cyapa_gen5.c > drivers/input/mouse/cyapa_gen5.c:334:5: warning: symbol > 'cyapa_empty_pip_output_data' was not declared. Should it be static? > drivers/input/mouse/cyapa_gen5.c:553:6: warning: symbol > 'cyapa_gen5_sort_tsg_pip_bl_resp_data' was not declared. Should it be > static? > drivers/input/mouse/cyapa_gen5.c:568:6: warning: symbol > 'cyapa_gen5_sort_tsg_pip_app_resp_data' was not declared. Should it be > static? > drivers/input/mouse/cyapa_gen5.c:595:6: warning: symbol > 'cyapa_gen5_sort_application_launch_data' was not declared. Should it be > static? > drivers/input/mouse/cyapa_gen5.c:995:6: warning: symbol > 'cyapa_gen5_sort_bl_exit_data' was not declared. Should it be static? > drivers/input/mouse/cyapa_gen5.c:1112:72: warning: Using plain integer > as NULL pointer > CC [M] drivers/input/mouse/cyapa_gen5.o > LD [M] drivers/input/mouse/cyapatp.o > Kernel: arch/x86/boot/bzImage is ready (#127) > Building modules, stage 2. > MODPOST 187 modules > CC drivers/input/mouse/cyapatp.mod.o > LDFINAL [M] drivers/input/mouse/cyapatp.ko > jeri@newt:~/linux-next > > -- > - Jeremiah Mahler > -- > To unsubscribe from this list: send the line "unsubscribe linux-input" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html 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. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v14 01/12] input: cyapa: re-design driver to support multi-trackpad in one driver
Thanks for your remove and comments. Dudley > -Original Message- > From: linux-input-ow...@vger.kernel.org > [mailto:linux-input-ow...@vger.kernel.org] On Behalf Of Jeremiah Mahler > Sent: 2014?12?13? 19:16 > To: Dudley Du > Cc: dmitry.torok...@gmail.com; rydb...@euromail.se; ble...@google.com; > linux-in...@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH v14 01/12] input: cyapa: re-design driver to support > multi-trackpad in one driver > > Dudley, > > A few suggestions and questions below... > > On Fri, Dec 12, 2014 at 10:27:31AM +0800, Dudley Du wrote: > > In order to support multiple different chipsets and communication protocols > > trackpad devices in one cyapa driver, the new cyapa driver is re-designed > > with one cyapa driver core and multiple device specific functions component. > > The cyapa driver core is contained in this patch, it supplies basic > > functions > > that working with kernel and input subsystem, and also supplies the > > interfaces > > that the specific devices' component can connect and work together with as > > one driver. > > TEST=test on Chromebooks. > > > > Signed-off-by: Dudley Du > > --- > > drivers/input/mouse/Makefile |3 +- > > drivers/input/mouse/cyapa.c | 1050 > > ++ > > drivers/input/mouse/cyapa.h | 316 > [...] > > -{ REG_OFFSET_QUERY_BASE, QUERY_DATA_SIZE }, > > -{ BL_HEAD_OFFSET, 3 }, > > -{ BL_HEAD_OFFSET, 16 }, > > -{ BL_HEAD_OFFSET, 16 }, > > -{ BL_DATA_OFFSET, 16 }, > > -{ BL_HEAD_OFFSET, 32 }, > > -{ REG_OFFSET_QUERY_BASE, PRODUCT_ID_SIZE }, > > -{ REG_OFFSET_DATA_BASE, 32 } > > -}; > > +const char unique_str[] = "CYTRA"; > > > Since 'unique_str' is used to check the product id why not call it > 'product_id'? Thanks, I will rename it to product_id. > > [...] > > +/** > > + * cyapa_i2c_write - Execute i2c block data write operation > > + * @cyapa: Handle to this driver > > + * @ret: Offset of the data to written in the register map > > + * @len: number of bytes to write > > + * @values: Data to be written > > * > > - * Note: > > - * In trackpad device, the memory block allocated for I2C register map > > - * is 256 bytes, so the max read block for I2C bus is 256 bytes. > > + * Return negative errno code on error; return zero when success. > > */ > > -static ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t > > len, > > - u8 *values) > > +ssize_t cyapa_i2c_write(struct cyapa *cyapa, u8 reg, > > + size_t len, const void *values) > > { > > -ssize_t ret; > > -u8 index; > > -u8 smbus_cmd; > > -u8 *buf; > > +int ret; > > struct i2c_client *client = cyapa->client; > > +char data[32], *buf; > > > > -if (!(SMBUS_BYTE_BLOCK_CMD_MASK & cmd)) > > -return -EINVAL; > > - > > -if (SMBUS_GROUP_BLOCK_CMD_MASK & cmd) { > > -/* read specific block registers command. */ > > -smbus_cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ); > > -ret = i2c_smbus_read_block_data(client, smbus_cmd, values); > > -goto out; > > -} > > - > > -ret = 0; > > -for (index = 0; index * I2C_SMBUS_BLOCK_MAX < len; index++) { > > -smbus_cmd = SMBUS_ENCODE_IDX(cmd, index); > > -smbus_cmd = SMBUS_ENCODE_RW(smbus_cmd, SMBUS_READ); > > -buf = values + I2C_SMBUS_BLOCK_MAX * index; > > -ret = i2c_smbus_read_block_data(client, smbus_cmd, buf); > > -if (ret < 0) > > -goto out; > > -} > > - > > -out: > > -return ret > 0 ? len : ret; > > -} > > - > > -static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx) > > -{ > > -u8 cmd; > > - > > -if (cyapa->smbus) { > > -cmd = cyapa_smbus_cmds[cmd_idx].cmd; > > -cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ); > > +if (len > 31) { > > +buf = kzalloc(len + 1, GFP_KERNEL); > > +if (!buf) > > +return -ENOMEM; > > } else { > > -cmd = cyapa_i2c_cmds[cmd_idx].cmd; > > +buf = data; > > } > > -return i2c_smbus_read_byte_data(cyapa->client, cmd); > > -} > > > > -static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value) > > -{ > > -u8 cmd; > > +buf[0] = reg; > > +memcpy(&buf[1], values, len); > > +ret = i2c_master_send(client, buf, len + 1); > > > > -if (cyapa->smbus) { > > -cmd = cyapa_smbus_cmds[cmd_idx].cmd; > > -cmd = SMBUS_ENCODE_RW(cmd, SMBUS_WRITE); > > -} else { > > -cmd
[PATCH v15 00/12] input: cyapa: instruction of cyapa patches
V15 patches have below updates, details of other updates see history list: 1) Fix all warning errors of sparse tool when running with "make C=1". 2) Change variable name "unique_str" to "product_id" for clearer meanings. This patch series is aimed to re-design the cyapa driver to support old gen3 trackpad devices and new gen5 trackpad devices in one cyapa driver, it's for easily productions support based on customers' requirements. And add sysfs functions and interfaces supported that required by users and customers. Since the earlier gen3 and the latest gen5 trackpad devices using two different chipsets, and have different protocols and interfaces, so if supported these two type trackpad devices in two different drivers, then it will be difficult to manage productions and later firmware updates. e.g.: It will cause customer don't know which one trackpad device firmware image to use and update when it has been used and integrated in same one productions, so here we support these two trackpad devices in same on driver. The new design cyapa driver contains: cyapa.c - the core of the re-design, supply interfaces and functions to system and read trackpad devices. cyapa.h - header file including macros and data structure definitions. cyapa_gen3.c - functions support for gen3 trackpad devices, cyapa_gen5.c - functions support for gen5 trackpad devices. Beside this introduction patch, it has 12 patches listed as below. For these patches, each one is patched based on previous one. patch 1/12: re-design cyapa driver with core functions and interface to support multi-type trackpad devices. patch 2/12: add gen5 trackpad device basic functions supported into the re-design cyapa driver. patch 3/12: add power management interfaces supported for the device. patch 4/12: add runtime power management interfaces supported for the device. patch 5/12: add sysfs interfaces supported in the cyapa driver. Including read firmware version, get production ID, read baseline, re-calibrate trackpad baselines and do trackpad firmware update. patch 6/12: add gen3 trackpad device's firmware update function supported. patch 7/12: add gen3 trackpad device's read baseline function supported. patch 8/12: add gen3 trackpad device's force re-calibrate function supported. patch 9/12: add gen5 trackpad device's firmware update function supported. patch 10/12: add gen5 trackpad device's read baseline function supported. patch 11/12: add gen5 trackpad device's force re-calibrate function. patch 12/12: add acpi device id supported. History patch series modifications list: V14 patches have below main updates compared with v13 patches: 1) Correct 9 miss spelling issues of "bufferred" to "buffered". 2) Fix the upgrade issue of removing MOUSE_CYAPA config when make oldconfig by replase "depends on I2C && CRC_ITU_T" with "depends on I2C" "select CRC_ITU_T" in patch 9. V13 patches have below main updates compared with v12 patches: 1) Remove all debugfs interface, including read_fw and raw_data interfaces. 2) This patches are made based linux next-20141208. V12 patches have below main updates compared with v11 patches: 1) Add check that when TP is detected but not operational, do not exit driver immediately, but wait and export the update_fw interface for recovering. 2) Re-arrange the function codes, remove unnesseary protype definitions in the header file. V11 patches have below main updates compared with v10 patches: 1) Add add acpi device id supported for old gen3 and new gen5 trackpad devices. 2) Fix the unable to update firmware issue when cyapa_open is not called which means the irq for firwmare update process is not enabled. This fix by checking if the irq is enabled, if not then enable irq before start to do firmware update. V10 patches have below main updates compared with v9 patches: 1) Modify code to following kernel code style. e.g.: correct to use error as return name when there is only error path, and fix the checkpatch.sh wanting in the driver. 2) Remove cyapa_remove method and use input open and close interface to following device resouse management infrastructure. 3) Modify cyapa_detect method to return tristate issue to make the return value much more consistent and clear. 4) Use platform supplied functions as possible instead of driver specific rewritten version. V9 patches have below updates compared with v8 patches: 1) Removed all async thread stuff from the driver. 2) Split driver into 18 patches for each function change one patch. V8 patches have below updates compared with v7 patches: 1) [PATCH v8 01/13] - Remove the async thread for device detect in probe routine, now the device detect process is completely done within the device probe routine. 2) [PATCH v8 01/13] - Split the irq cmd hander function to separated function cyapa_default_irq_cmd_handler() and set it to interface cyapa_default_ops.irq_cmd_handler. 3) [PATCH v8 06/13] - Add cyapa->g
[PATCH v15 01/12] input: cyapa: re-design driver to support multi-trackpad in one driver
In order to support multiple different chipsets and communication protocols trackpad devices in one cyapa driver, the new cyapa driver is re-designed with one cyapa driver core and multiple device specific functions component. The cyapa driver core is contained in this patch, it supplies basic functions that working with kernel and input subsystem, and also supplies the interfaces that the specific devices' component can connect and work together with as one driver. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |3 +- drivers/input/mouse/cyapa.c | 1047 ++ drivers/input/mouse/cyapa.h | 316 drivers/input/mouse/cyapa_gen3.c | 793 + 4 files changed, 1493 insertions(+), 666 deletions(-) create mode 100644 drivers/input/mouse/cyapa.h create mode 100644 drivers/input/mouse/cyapa_gen3.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 560003d..8bd950d 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974)+= bcm5974.o -obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapatp.o obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o @@ -24,6 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o +cyapatp-objs := cyapa.o cyapa_gen3.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 1bece8c..ae1df15 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -20,408 +20,100 @@ #include #include #include +#include #include +#include +#include "cyapa.h" -/* APA trackpad firmware generation */ -#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ - -#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" - -/* commands for read/write registers of Cypress trackpad */ -#define CYAPA_CMD_SOFT_RESET 0x00 -#define CYAPA_CMD_POWER_MODE 0x01 -#define CYAPA_CMD_DEV_STATUS 0x02 -#define CYAPA_CMD_GROUP_DATA 0x03 -#define CYAPA_CMD_GROUP_CMD0x04 -#define CYAPA_CMD_GROUP_QUERY 0x05 -#define CYAPA_CMD_BL_STATUS0x06 -#define CYAPA_CMD_BL_HEAD 0x07 -#define CYAPA_CMD_BL_CMD 0x08 -#define CYAPA_CMD_BL_DATA 0x09 -#define CYAPA_CMD_BL_ALL 0x0a -#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b -#define CYAPA_CMD_BLK_HEAD 0x0c - -/* report data start reg offset address. */ -#define DATA_REG_START_OFFSET 0x - -#define BL_HEAD_OFFSET 0x00 -#define BL_DATA_OFFSET 0x10 - -/* - * Operational Device Status Register - * - * bit 7: Valid interrupt source - * bit 6 - 4: Reserved - * bit 3 - 2: Power status - * bit 1 - 0: Device status - */ -#define REG_OP_STATUS 0x00 -#define OP_STATUS_SRC 0x80 -#define OP_STATUS_POWER 0x0c -#define OP_STATUS_DEV 0x03 -#define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) - -/* - * Operational Finger Count/Button Flags Register - * - * bit 7 - 4: Number of touched finger - * bit 3: Valid data - * bit 2: Middle Physical Button - * bit 1: Right Physical Button - * bit 0: Left physical Button - */ -#define REG_OP_DATA1 0x01 -#define OP_DATA_VALID 0x08 -#define OP_DATA_MIDDLE_BTN 0x04 -#define OP_DATA_RIGHT_BTN 0x02 -#define OP_DATA_LEFT_BTN 0x01 -#define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ - OP_DATA_LEFT_BTN) - -/* - * Bootloader Status Register - * - * bit 7: Busy - * bit 6 - 5: Reserved - * bit 4: Bootloader running - * bit 3 - 1: Reserved - * bit 0: Checksum valid - */ -#define REG_BL_STATUS0x01 -#define BL_STATUS_BUSY 0x80 -#define BL_STATUS_RUNNING0x10 -#define BL_STATUS_DATA_VALID 0x08 -#define BL_STATUS_CSUM_VALID 0x01 - -/* - * Bootloader Error Register - * - * bit 7: Invalid - * bit 6: Invalid security key - * bit 5: Bootloading - * bit 4: Command checksum - * bit 3: Flash protection error - * bit 2: Flash checksum error - * bit 1 - 0: Reserved - */ -#define REG_BL_ERROR 0x02 -#define BL_ERROR_INVALID 0x80 -#define BL_ERROR_INVALID_KEY 0x40 -#define BL_ERROR_BOOTLOADING 0x20 -#define BL_ERROR_CMD_CSUM0x10 -#define BL_ERROR_FLASH_PROT 0x08 -#define BL_ERROR_FLASH_CSUM 0x04 - -#define BL_STATUS_SIZE 3 /* length of bootloader status registers */ -#define BLK_HEAD_BYTES 32 - -#define PRODUCT_ID_SIZE 16 -#d
[PATCH v15 02/12] input: cyapa: add gen5 trackpad device basic functions support
Based on the cyapa core, add the gen5 trackpad device's basic functions supported, so gen5 trackpad device can work with kernel input system. And also based on the state parse interface, the cyapa driver can automatically determine the attached is gen3 or gen5 protocol trackpad device, then set the correct protocol to work with the attached trackpad device. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/Makefile |2 +- drivers/input/mouse/cyapa.c | 13 + drivers/input/mouse/cyapa.h |1 + drivers/input/mouse/cyapa_gen5.c | 1660 ++ 4 files changed, 1675 insertions(+), 1 deletion(-) create mode 100644 drivers/input/mouse/cyapa_gen5.c diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 8bd950d..8a9c98e 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o obj-$(CONFIG_MOUSE_VSXXXAA)+= vsxxxaa.o -cyapatp-objs := cyapa.o cyapa_gen3.o +cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index ae1df15..d4560a3 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -157,6 +157,14 @@ static int cyapa_get_state(struct cyapa *cyapa) if (!error) goto out_detected; } + if ((cyapa->gen == CYAPA_GEN_UNKNOWN || + cyapa->gen == CYAPA_GEN5) && + !smbus && even_addr) { + error = cyapa_gen5_ops.state_parse(cyapa, + status, BL_STATUS_SIZE); + if (!error) + goto out_detected; + } /* * Write 0x00 0x00 to trackpad device to force update its @@ -240,6 +248,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) return error; switch (cyapa->gen) { + case CYAPA_GEN5: + cyapa->ops = &cyapa_gen5_ops; + break; case CYAPA_GEN3: cyapa->ops = &cyapa_gen3_ops; break; @@ -476,6 +487,8 @@ static int cyapa_initialize(struct cyapa *cyapa) if (cyapa_gen3_ops.initialize) error = cyapa_gen3_ops.initialize(cyapa); + if (!error && cyapa_gen5_ops.initialize) + error = cyapa_gen5_ops.initialize(cyapa); if (error) return error; diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h index 709ad47..d7d4f11 100644 --- a/drivers/input/mouse/cyapa.h +++ b/drivers/input/mouse/cyapa.h @@ -312,5 +312,6 @@ u16 cyapa_pwr_cmd_to_sleep_time(u8 pwr_mode); extern const char product_id[]; extern const struct cyapa_dev_ops cyapa_gen3_ops; +extern const struct cyapa_dev_ops cyapa_gen5_ops; #endif diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c new file mode 100644 index 000..1ac264d --- /dev/null +++ b/drivers/input/mouse/cyapa_gen5.c @@ -0,0 +1,1660 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du + * + * Copyright (C) 2014 Cypress Semiconductor, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cyapa.h" + + +/* Macro of Gen5 */ +#define RECORD_EVENT_NONE0 +#define RECORD_EVENT_TOUCHDOWN 1 +#define RECORD_EVENT_DISPLACE2 +#define RECORD_EVENT_LIFTOFF 3 + +#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80 +#define CYAPA_TSG_IMG_FW_HDR_SIZE 13 +#define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE) +#define CYAPA_TSG_IMG_START_ROW_NUM 0x002e +#define CYAPA_TSG_IMG_END_ROW_NUM 0x01fe +#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff +#define CYAPA_TSG_IMG_MAX_RECORDS (CYAPA_TSG_IMG_END_ROW_NUM - \ + CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1) +#define CYAPA_TSG_IMG_READ_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2) +#define CYAPA_TSG_START_OF_APPLICATION 0x1700 +#define CYAPA_TSG_APP_INTEGRITY_SIZE60 +#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE 60 +#define CYAPA_TSG_BL_KEY_SIZE 8 + +/* Macro definitions for Gen5 trackpad device. */ +#define GEN5_TOUCH_REPORT_HEAD_SIZE 7 +#define GEN5_TOUCH_REPORT_MAX_SIZE 127 +#define GEN5_BTN_REPORT_HEAD_SIZE 6 +#define GEN5_BTN_REPORT_MAX_SIZE
[PATCH v15 06/12] input: cyapa: add gen3 trackpad device firmware update function support
Add firmware image update function supported for gen3 trackpad device, it can be used through sysfs update_fw interface. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa_gen3.c | 284 +++ 1 file changed, 284 insertions(+) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 433c5b1..9851337 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -416,6 +416,72 @@ 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 error; + + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; + if (cyapa->state == CYAPA_STATE_BL_IDLE) { + /* Already in BL_IDLE. Skipping reset. */ + return 0; + } + + if (cyapa->state != CYAPA_STATE_OP) + return -EAGAIN; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + error = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01); + if (error) + return -EIO; + + usleep_range(25000, 5); + error = cyapa_poll_state(cyapa, 500); + if (error) + return error; + 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 error; + + error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate), + bl_activate); + if (error) + return error; + + /* Wait for bootloader to activate; takes between 2 and 12 seconds */ + msleep(2000); + error = cyapa_poll_state(cyapa, 11000); + if (error) + return error; + if (cyapa->state != CYAPA_STATE_BL_ACTIVE) + return -EAGAIN; + + return 0; +} + static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { int error; @@ -476,6 +542,218 @@ 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 =
[PATCH v15 05/12] input: cyapa: add sysfs interfaces supported in the cyapa driver
Add device's basic control and features supported in cyapa driver through sysfs file system interfaces. These interfaces are commonly used in pre- and after production, for trackpad device state checking, managing and firmware image updating. These interfaces including mode, firmware_version and product_id interfaces for reading firmware version and trackpad device product id values, and including update_fw interface to command firmware image update process. Also including baseline and calibrate interfaces for reading and checking trackpad device's sensors states. TEST=test on Chromebooks. Signed-off-by: Dudley Du --- drivers/input/mouse/cyapa.c | 327 1 file changed, 327 insertions(+) diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 3bcfce3..dac3996 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -32,6 +32,8 @@ #define CYAPA_ADAPTER_FUNC_SMBUS 2 #define CYAPA_ADAPTER_FUNC_BOTH 3 +#define CYAPA_FW_NAME "cyapa.bin" + const char product_id[] = "CYTRA"; static int cyapa_reinitialize(struct cyapa *cyapa); @@ -442,6 +444,29 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) return 0; } +static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa) +{ + struct input_dev *input = cyapa->input; + + if (!input || !input->users) { + if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0); + enable_irq(cyapa->client->irq); + } +} + +static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa) +{ + struct input_dev *input = cyapa->input; + + if (!input || !input->users) { + disable_irq(cyapa->client->irq); + if (!CYAPA_BOOTLOADER(cyapa) && cyapa->ops->set_power_mode) + cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + } +} + /* * cyapa_sleep_time_to_pwr_cmd and cyapa_pwr_cmd_to_sleep_time * @@ -783,6 +808,295 @@ static int cyapa_start_runtime(struct cyapa *cyapa) } #endif /* CONFIG_PM_RUNTIME */ +static ssize_t cyapa_show_fm_ver(struct device *dev, +struct device_attribute *attr, char *buf) +{ + int error; + struct cyapa *cyapa = dev_get_drvdata(dev); + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + error = scnprintf(buf, PAGE_SIZE, "%d.%d\n", cyapa->fw_maj_ver, +cyapa->fw_min_ver); + mutex_unlock(&cyapa->state_sync_lock); + return error; +} + +static ssize_t cyapa_show_product_id(struct device *dev, +struct device_attribute *attr, char *buf) +{ + struct cyapa *cyapa = dev_get_drvdata(dev); + int size; + int error; + + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) + return error; + size = scnprintf(buf, PAGE_SIZE, "%s\n", cyapa->product_id); + mutex_unlock(&cyapa->state_sync_lock); + return size; +} + +static int cyapa_firmware(struct cyapa *cyapa, const char *fw_name) +{ + struct device *dev = &cyapa->client->dev; + const struct firmware *fw; + int error; + + error = request_firmware(&fw, fw_name, dev); + if (error) { + dev_err(dev, "Could not load firmware from %s: %d\n", + fw_name, error); + return error; + } + + if (cyapa->ops->check_fw) { + error = cyapa->ops->check_fw(cyapa, fw); + if (error) { + dev_err(dev, "Invalid CYAPA firmware image: %s\n", + fw_name); + goto done; + } + } else { + dev_err(dev, "No valid device ops->check_fw handler set.\n"); + error = -ENODEV; + goto done; + } + + /* +* Resume the potentially suspended device because doing FW +* update on a device not in the FULL mode has a chance to +* fail. +*/ + pm_runtime_get_sync(dev); + + /* Require IRQ support for firmware update commands. */ + cyapa_enable_irq_for_cmd(cyapa); + + if (cyapa->ops->bl_enter) { + error = cyapa->ops->bl_enter(cyapa); + if (error) { + dev_err(dev, "bl_enter failed, %d\n", error); + goto err_detect; + } + } + + if (cyapa->ops->bl_activate) { + error = cyapa->ops->bl_activate(cyapa); +