summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuper Liu <supercjliu@google.com>2021-04-19 11:17:28 +0800
committerSuper Liu <supercjliu@google.com>2021-04-20 18:07:05 +0800
commit621f4776f9a1589c12c38d85ff083ed02d88a10f (patch)
tree14dfe879488222b4f5d4fff2ad1cbf0ddd3866e6
parent224c61111d1209690c3fcb7ab24c6238a58b1a64 (diff)
downloadsec_touch-621f4776f9a1589c12c38d85ff083ed02d88a10f.tar.gz
touch/sec: use hardware reset to re-initialize touch
There are some unstable SPI transfer during bus negotiation between AP and AOC. Therefore, directly use hardware reset by GPIO will force touch to default state without interference by SPI. Bug: 185557408 Test: check touch operation 10 times by power key suspend and resume. Test: echo set_touch_mode,7 > sec/tsp/cmd ; cat sec/tsp/cmd_result Test: echo set_touch_mode,7,1 > sec/tsp/cmd ; cat sec/tsp/cmd_result Test: echo set_touch_mode,7,2 > sec/tsp/cmd ; cat sec/tsp/cmd_result Signed-off-by: Super Liu <supercjliu@google.com> Change-Id: I587cdb572169be6aa45105a48d46bf05b375bec8
-rw-r--r--sec_ts.c16
-rw-r--r--sec_ts.h16
-rw-r--r--sec_ts_fn.c15
-rw-r--r--sec_ts_fw.c185
4 files changed, 123 insertions, 109 deletions
diff --git a/sec_ts.c b/sec_ts.c
index 2242b46..16068ff 100644
--- a/sec_ts.c
+++ b/sec_ts.c
@@ -681,10 +681,14 @@ skip_spi_read:
} else
ts->io_err_count = 0;
- /* do hw reset if continuously failed over SEC_TS_IO_RESET_CNT times */
- if (ts->io_err_count >= SEC_TS_IO_RESET_CNT) {
+ /*
+ * Do hw reset if continuously failed over SEC_TS_IO_RESET_CNT times
+ * except for FW update process.
+ */
+ if (ts->io_err_count >= SEC_TS_IO_RESET_CNT &&
+ (ts->bus_refmask & SEC_TS_BUS_REF_FW_UPDATE) == 0) {
ts->io_err_count = 0;
- sec_ts_hw_reset(ts);
+ sec_ts_system_reset(ts, RESET_MODE_HW, false, true);
}
return ret;
@@ -2705,14 +2709,14 @@ static void sec_ts_read_event(struct sec_ts_data *ts)
break;
case 0x40:
input_info(true, &ts->client->dev,
- "%s: sw_reset done\n",
+ "%s: sw_reset ack.\n",
__func__);
sec_ts_unlocked_release_all_finger(ts);
complete_all(&ts->boot_completed);
break;
case 0x10:
input_info(true, &ts->client->dev,
- "%s: hw_reset done\n",
+ "%s: hw_reset ack.\n",
__func__);
sec_ts_unlocked_release_all_finger(ts);
complete_all(&ts->boot_completed);
@@ -5159,7 +5163,7 @@ static void sec_ts_resume_work(struct work_struct *work)
ts->power_status = SEC_TS_STATE_POWER_ON;
- ret = sec_ts_system_reset(ts);
+ ret = sec_ts_system_reset(ts, RESET_MODE_HW, false, false);
if (ret < 0)
input_err(true, &ts->client->dev,
"%s: reset failed! ret %d\n", __func__, ret);
diff --git a/sec_ts.h b/sec_ts.h
index 2414238..5a8afc8 100644
--- a/sec_ts.h
+++ b/sec_ts.h
@@ -558,6 +558,13 @@ enum {
**/
};
+enum RESET_MODE {
+ RESET_MODE_NA = 0x00,
+ RESET_MODE_SW = 0x01,
+ RESET_MODE_HW = 0x02,
+ RESET_MODE_AUTO = (RESET_MODE_SW | RESET_MODE_HW),
+};
+
enum CUSTOMLIB_EVENT_TYPE {
CUSTOMLIB_EVENT_TYPE_SPAY = 0x04,
CUSTOMLIB_EVENT_TYPE_PRESSURE_TOUCHED = 0x05,
@@ -1154,9 +1161,12 @@ struct sec_ts_plat_data {
int sec_ts_stop_device(struct sec_ts_data *ts);
int sec_ts_start_device(struct sec_ts_data *ts);
-int sec_ts_hw_reset(struct sec_ts_data *ts);
-int sec_ts_sw_reset(struct sec_ts_data *ts);
-int sec_ts_system_reset(struct sec_ts_data *ts);
+int sec_ts_hw_reset(struct sec_ts_data *ts, bool wait_for_done);
+int sec_ts_sw_reset(struct sec_ts_data *ts, bool wait_for_done);
+int sec_ts_system_reset(struct sec_ts_data *ts,
+ enum RESET_MODE mode,
+ bool wait_for_done,
+ bool sense_on);
int sec_ts_set_lowpowermode(struct sec_ts_data *ts, u8 mode);
int sec_ts_firmware_update_on_probe(struct sec_ts_data *ts, bool force_update);
int sec_ts_firmware_update_on_hidden_menu(struct sec_ts_data *ts,
diff --git a/sec_ts_fn.c b/sec_ts_fn.c
index 8c3cc69..81a4b61 100644
--- a/sec_ts_fn.c
+++ b/sec_ts_fn.c
@@ -8376,9 +8376,18 @@ static void set_touch_mode(void *device_data)
break;
case 7:
input_info(true, &ts->client->dev,
- "%s: param = %d, do touch system reset\n",
- __func__, sec->cmd_param[0]);
- sec_ts_system_reset(ts);
+ "%s: param = %d %d, do touch system reset\n",
+ __func__, sec->cmd_param[0], sec->cmd_param[1]);
+ switch (sec->cmd_param[1]) {
+ case RESET_MODE_SW:
+ sec_ts_system_reset(ts, RESET_MODE_SW, true, true);
+ break;
+ case RESET_MODE_HW:
+ sec_ts_system_reset(ts, RESET_MODE_HW, true, true);
+ break;
+ default:
+ sec_ts_system_reset(ts, RESET_MODE_AUTO, true, true);
+ }
break;
case 8:
input_info(true, &ts->client->dev,
diff --git a/sec_ts_fw.c b/sec_ts_fw.c
index 7aec9f1..7810438 100644
--- a/sec_ts_fw.c
+++ b/sec_ts_fw.c
@@ -104,14 +104,36 @@ static int sec_ts_enter_fw_mode(struct sec_ts_data *ts)
return 1;
}
-int sec_ts_hw_reset(struct sec_ts_data *ts)
+int sec_ts_wait_for_reset_done(struct sec_ts_data *ts)
{
+ int ret = 0;
+
+ if (completion_done(&ts->bus_resumed) &&
+ ts->probe_done == true) {
+ if (!completion_done(&ts->boot_completed) &&
+ wait_for_completion_timeout(&ts->boot_completed,
+ msecs_to_jiffies(200) == 0))
+ ret = -ETIME;
+ } else {
+ ret = sec_ts_wait_for_ready_with_count(ts,
+ SEC_TS_ACK_BOOT_COMPLETE, 10);
+ }
+
+ return ret;
+}
+
+int sec_ts_hw_reset(struct sec_ts_data *ts, bool wait_for_done)
+{
+ int ret = 0;
int reset_gpio = ts->plat_data->reset_gpio;
- input_info(true, &ts->client->dev, "%s\n", __func__);
+ input_info(true, &ts->client->dev, "%s: wait_for_done %d.\n",
+ __func__, wait_for_done);
+ if (wait_for_done)
+ reinit_completion(&ts->boot_completed);
if (!gpio_is_valid(reset_gpio)) {
- input_err(true, &ts->client->dev, "%s: invalid gpio %d\n",
+ input_err(true, &ts->client->dev, "%s: invalid gpio %d.\n",
__func__, reset_gpio);
return -EINVAL;
}
@@ -119,135 +141,104 @@ int sec_ts_hw_reset(struct sec_ts_data *ts)
gpio_set_value(reset_gpio, 0);
sec_ts_delay(10);
gpio_set_value(reset_gpio, 1);
- /* wait 70 ms at least from bootloader to applicateion mode */
+
+ /* Wait 70 ms at least from bootloader to applicateion mode. */
sec_ts_delay(70);
- return 0;
+ if (wait_for_done) {
+ ret = sec_ts_wait_for_reset_done(ts);
+ if (!ret)
+ input_info(true, &ts->client->dev,
+ "%s: done.\n", __func__);
+ else
+ input_err(true, &ts->client->dev,
+ "%s: hw_reset time out!\n", __func__);
+ complete_all(&ts->boot_completed);
+ }
+
+ return ret;
}
-int sec_ts_sw_reset(struct sec_ts_data *ts)
+int sec_ts_sw_reset(struct sec_ts_data *ts, bool wait_for_done)
{
- int ret;
+ int ret = 0;
- input_info(true, &ts->client->dev, "%s\n", __func__);
+ input_info(true, &ts->client->dev, "%s: wait_for_done %d.\n",
+ __func__, wait_for_done);
+ if (wait_for_done)
+ reinit_completion(&ts->boot_completed);
ret = ts->sec_ts_write(ts, SEC_TS_CMD_SW_RESET, NULL, 0);
if (ret < 0) {
input_err(true, &ts->client->dev,
- "%s: write fail, sw_reset\n", __func__);
- return 0;
+ "%s: failed to write sw_reset.\n", __func__);
+ return -EIO;
}
- /* wait 70 ms at least from bootloader to applicateion mode */
+ /* Wait 70 ms at least from bootloader to applicateion mode. */
sec_ts_delay(70);
- ret = sec_ts_wait_for_ready(ts, SEC_TS_ACK_BOOT_COMPLETE);
- if (ret < 0) {
- input_err(true, &ts->client->dev, "%s: time out\n", __func__);
- return 0;
- }
-
- input_info(true, &ts->client->dev, "%s: sw_reset\n", __func__);
+ if (wait_for_done) {
+ ret = sec_ts_wait_for_reset_done(ts);
+ if (!ret)
+ input_info(true, &ts->client->dev,
+ "%s: done.\n", __func__);
+ else
+ input_err(true, &ts->client->dev,
+ "%s: sw_reset time out!\n", __func__);
- /* Sense_on */
- ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0);
- if (ret < 0) {
- input_err(true, &ts->client->dev,
- "%s: write fail, Sense_on\n", __func__);
- return 0;
+ complete_all(&ts->boot_completed);
}
return ret;
}
-int sec_ts_system_reset(struct sec_ts_data *ts)
+int sec_ts_system_reset(struct sec_ts_data *ts,
+ enum RESET_MODE mode,
+ bool wait_for_done,
+ bool sense_on)
{
- int ret = -1;
+ int ret = 0;
- reinit_completion(&ts->boot_completed);
- ret = ts->sec_ts_write(ts, SEC_TS_CMD_SW_RESET, NULL, 0);
- if (ret < 0)
- input_err(true, &ts->client->dev, "%s: write fail, sw_reset\n",
- __func__);
- else {
- /* wait 70 ms at least from bootloader to applicateion mode */
- sec_ts_delay(70);
- if (completion_done(&ts->bus_resumed) &&
- ts->probe_done == true) {
- if (!completion_done(&ts->boot_completed) &&
- wait_for_completion_timeout(&ts->boot_completed,
- msecs_to_jiffies(200) == 0))
- ret = -ETIME;
- } else
- /* Normally it should not happen with any retry.
- * But, if happened, retry less time to wait ack
- */
- ret = sec_ts_wait_for_ready_with_count(ts,
- SEC_TS_ACK_BOOT_COMPLETE, 10);
+ input_info(true, &ts->client->dev,
+ "%s: mode %d, wait_for_done %d, sense_on %d.\n",
+ __func__, mode, wait_for_done, sense_on);
- if (ret < 0)
+ if (mode & RESET_MODE_SW) {
+ ret = sec_ts_sw_reset(ts, wait_for_done);
+ if (ret)
input_err(true, &ts->client->dev,
- "%s: sw_reset time out!\n", __func__);
+ "%s: sw reset failed.");
else
- input_info(true,
- &ts->client->dev, "%s: sw_reset done\n",
- __func__);
+ goto sw_reset_done;
}
- if (ret < 0) {
- if (!gpio_is_valid(ts->plat_data->reset_gpio)) {
+ if (mode & RESET_MODE_HW) {
+ if (ret)
input_err(true, &ts->client->dev,
- "%s: reset gpio is unavailable!\n", __func__);
- goto err_system_reset;
- }
-
- input_err(true, &ts->client->dev,
- "%s: sw_reset failed or time out, try hw_reset to recover!\n",
- __func__);
- ret = sec_ts_hw_reset(ts);
- if (ret) {
+ "%s: sw_reset failed or time out, try hw_reset to recover!\n",
+ __func__);
+ ret = sec_ts_hw_reset(ts, wait_for_done);
+ if (ret)
input_err(true, &ts->client->dev,
- "%s: hw_reset failed\n", __func__);
- goto err_system_reset;
- }
-
- if (completion_done(&ts->bus_resumed) &&
- ts->probe_done == true) {
- if (!completion_done(&ts->boot_completed) &&
- wait_for_completion_timeout(&ts->boot_completed,
- msecs_to_jiffies(200) == 0))
- ret = -ETIME;
- } else
- ret = sec_ts_wait_for_ready_with_count(ts,
- SEC_TS_ACK_BOOT_COMPLETE, 10);
+ "%s: hw reset failed.");
+ }
+sw_reset_done:
+ /* Sense on. */
+ if (sense_on) {
+ ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0);
if (ret < 0) {
- input_err(true,
- &ts->client->dev, "%s: hw_reset time out\n",
+ input_err(true, &ts->client->dev,
+ "%s: failed to write sense_on.\n",
__func__);
- goto err_system_reset;
}
- input_info(true, &ts->client->dev, "%s: hw_reset done\n",
- __func__);
- }
-
- /* Sense_on */
- ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0);
- if (ret < 0) {
- input_err(true, &ts->client->dev, "%s: write fail, Sense_on\n",
- __func__);
- goto err_system_reset;
}
- /* initialize wet status */
+ /* Initialize wet status. */
ts->wet_mode = 0;
ts->wet_count = 0;
- return 0;
-
-err_system_reset:
-
- complete_all(&ts->boot_completed);
return ret;
}
@@ -832,13 +823,13 @@ static int sec_ts_firmware_update(struct sec_ts_data *ts, const u8 *data,
return -1;
}
- input_err(true, &ts->client->dev, "%s: num_chunk: %d\n",
+ input_info(true, &ts->client->dev, "%s: num_chunk: %d\n",
__func__, fw_hd->num_chunk);
for (i = 0; i < fw_hd->num_chunk; i++) {
fw_ch = (fw_chunk *)fd;
- input_err(true, &ts->client->dev,
+ input_info(true, &ts->client->dev,
"%s: [%d] 0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
__func__, i, fw_ch->signature, fw_ch->addr,
fw_ch->size, fw_ch->reserved);
@@ -861,7 +852,7 @@ static int sec_ts_firmware_update(struct sec_ts_data *ts, const u8 *data,
fd += fw_ch->size;
}
- sec_ts_sw_reset(ts);
+ sec_ts_system_reset(ts, RESET_MODE_SW, true, true);
#ifdef PAT_CONTROL
if (restore_cal) {