input: synaptics: Correct bugs in fw update
- Fixed reset command could fail after firmware update
- Config reset pin if reset gpio is defined in platform data
- Force do a reset in function probe
- Skip fw/config update process if image firmware id is smaller
than device firmware id
Change-Id: I3525410c791454f64c680506fe4c77e9da650a46
Git-commit: db1a35c603df138842bdee3b0d9e7f9e24012e4e
Git-repo: git://github.com/synaptics-touch/synaptics-dsx-i2c.git
[amaloche@codeaurora.org: modified change w.r.t current driver]
Signed-off-by: Amy Maloche <amaloche@codeaurora.org>
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 7452587..5d66241 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -561,8 +561,6 @@
goto exit;
}
- imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
-
/* Force update firmware when device is in bootloader mode */
if (f01_device_status.flash_prog) {
dev_info(&i2c_client->dev,
@@ -616,6 +614,11 @@
if (imageFirmwareID > deviceFirmwareID) {
flash_area = UI_FIRMWARE;
goto exit;
+ } else if (imageFirmwareID < deviceFirmwareID) {
+ flash_area = NONE;
+ dev_info(&i2c_client->dev,
+ "Img fw is older than device fw. Skip fw update.\n");
+ goto exit;
}
/* device config id */
@@ -1650,6 +1653,9 @@
&fwu->fwu_work,
msecs_to_jiffies(1000));
#endif
+
+ init_completion(&remove_complete);
+
return 0;
exit_remove_attrs:
@@ -1700,7 +1706,6 @@
static void __exit rmi4_fw_update_module_exit(void)
{
- init_completion(&remove_complete);
synaptics_rmi4_new_function(RMI_FW_UPDATER, false,
synaptics_rmi4_fwu_init,
synaptics_rmi4_fwu_remove,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index b696987..e1b3884 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -1483,27 +1483,6 @@
}
break;
- case SYNAPTICS_RMI4_F34:
- if (rmi_fd.intr_src_count == 0)
- break;
-
- retval = synaptics_rmi4_alloc_fh(&fhandler,
- &rmi_fd, page_number);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc for F%d\n",
- __func__,
- rmi_fd.fn_number);
- return retval;
- }
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi_fd.ctrl_base_addr,
- rmi->config_id,
- sizeof(rmi->config_id));
- if (retval < 0)
- return retval;
- break;
-
case SYNAPTICS_RMI4_F11:
if (rmi_fd.intr_src_count == 0)
break;
@@ -1602,14 +1581,51 @@
return 0;
}
-static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
+static int synaptics_rmi4_reset_command(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
+ int page_number;
unsigned char command = 0x01;
- struct synaptics_rmi4_fn *fhandler;
- struct synaptics_rmi4_device_info *rmi;
+ unsigned short pdt_entry_addr;
+ struct synaptics_rmi4_fn_desc rmi_fd;
+ bool done = false;
- rmi = &(rmi4_data->rmi4_mod_info);
+ /* Scan the page description tables of the pages to service */
+ for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) {
+ for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END;
+ pdt_entry_addr -= PDT_ENTRY_SIZE) {
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ pdt_entry_addr,
+ (unsigned char *)&rmi_fd,
+ sizeof(rmi_fd));
+ if (retval < 0)
+ return retval;
+
+ if (rmi_fd.fn_number == 0)
+ break;
+
+ switch (rmi_fd.fn_number) {
+ case SYNAPTICS_RMI4_F01:
+ rmi4_data->f01_cmd_base_addr =
+ rmi_fd.cmd_base_addr;
+ done = true;
+ break;
+ }
+ }
+ if (done) {
+ dev_info(&rmi4_data->i2c_client->dev,
+ "%s: Find F01 in page description table 0x%x\n",
+ __func__, rmi4_data->f01_cmd_base_addr);
+ break;
+ }
+ }
+
+ if (!done) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Cannot find F01 in page description table\n",
+ __func__);
+ return -EINVAL;
+ }
retval = synaptics_rmi4_i2c_write(rmi4_data,
rmi4_data->f01_cmd_base_addr,
@@ -1623,6 +1639,24 @@
}
msleep(100);
+ return retval;
+};
+
+static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ retval = synaptics_rmi4_reset_command(rmi4_data);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to send command reset\n",
+ __func__);
+ return retval;
+ }
if (!list_empty(&rmi->support_fn_list)) {
list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
@@ -2068,7 +2102,8 @@
usleep(RMI4_GPIO_SLEEP_LOW_US);
gpio_set_value(platform_data->reset_gpio, 1);
msleep(RMI4_GPIO_WAIT_HIGH_MS);
- }
+ } else
+ synaptics_rmi4_reset_command(rmi4_data);
init_waitqueue_head(&rmi4_data->wait);
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index 89eb3a9..9356937 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -24,7 +24,7 @@
#define SYNAPTICS_DS4 (1 << 0)
#define SYNAPTICS_DS5 (1 << 1)
#define SYNAPTICS_DSX_DRIVER_PRODUCT SYNAPTICS_DS4
-#define SYNAPTICS_DSX_DRIVER_VERSION 0x1002
+#define SYNAPTICS_DSX_DRIVER_VERSION 0x1004
#include <linux/version.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index 7f1aac5..c6b8a1c 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -619,6 +619,8 @@
}
}
+ init_completion(&remove_complete);
+
return 0;
err_sysfs_attrs: