summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@chromium.org>2018-01-18 08:13:51 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-01-21 22:20:48 -0800
commitd9f4ce13f2a49a260db7bb6d42234439184e9e55 (patch)
tree3c3d3d936bf7309cdf72a83de84fbcb004df9650
parent667a35bb9c0ffd61d4c7d8a2897a8f7c313a9202 (diff)
downloadchrome-ec-d9f4ce13f2a49a260db7bb6d42234439184e9e55.tar.gz
touchpad_elan: Add retry logic if the touchpad does not respond
After 3 tries, the touchpad is reset by power-cycling it. BRANCH=none BUG=b:71688150 TEST=Short SDA/SCL lines, press on touchpad, see that touchpad tasks retries transaction, and then resets the touchpad power. TEST=Do ESD discharge, and see that touchpad always recovers. Change-Id: If0b5eb936d4d2feb3d34a7ec8748869a1b915c34 Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/872131 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/hammer/board.c16
-rw-r--r--driver/touchpad_elan.c35
-rw-r--r--include/touchpad.h3
3 files changed, 52 insertions, 2 deletions
diff --git a/board/hammer/board.c b/board/hammer/board.c
index be0d2f465a..f9ac182934 100644
--- a/board/hammer/board.c
+++ b/board/hammer/board.c
@@ -217,6 +217,22 @@ void board_usb_wake(void)
#endif
}
+/* Reset the touchpad, mainly used to recover it from malfunction. */
+void board_touchpad_reset(void)
+{
+#ifdef BOARD_WHISKERS
+ gpio_set_level(GPIO_EN_PP3300_TP, 0);
+ msleep(10);
+ gpio_set_level(GPIO_EN_PP3300_TP, 1);
+ msleep(10);
+#else
+ gpio_set_level(GPIO_EN_PP3300_TP_ODL, 1);
+ msleep(10);
+ gpio_set_level(GPIO_EN_PP3300_TP_ODL, 0);
+ msleep(10);
+#endif
+}
+
/*
* Get entropy based on Clock Recovery System, which is enabled on hammer to
* synchronize USB SOF with internal oscillator.
diff --git a/driver/touchpad_elan.c b/driver/touchpad_elan.c
index ba0d543a4d..9c5a924239 100644
--- a/driver/touchpad_elan.c
+++ b/driver/touchpad_elan.c
@@ -144,6 +144,12 @@ static int finger_status[ETP_MAX_FINGERS] = {0};
*/
static uint32_t irq_ts;
+/*
+ * Read touchpad report.
+ * Returns 0 on success, positive (EC_RES_*) value on I2C error, and a negative
+ * value if the I2C transaction is successful but the data is invalid (fairly
+ * common).
+ */
static int elan_tp_read_report(void)
{
int rv;
@@ -164,7 +170,7 @@ static int elan_tp_read_report(void)
i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 0);
if (rv) {
- CPRINTS("read report error");
+ CPRINTS("read report error (%d)", rv);
return rv;
}
@@ -637,6 +643,31 @@ int touchpad_debug(const uint8_t *param, unsigned int param_size,
}
#endif
+/*
+ * Try to read touchpad report up to 3 times, reset the touchpad if we still
+ * fail.
+ */
+void elan_tp_read_report_retry(void)
+{
+ int ret;
+ int retry = 3;
+
+ while (retry--) {
+ ret = elan_tp_read_report();
+
+ if (ret <= 0)
+ return;
+
+ /* Try again */
+ msleep(1);
+ }
+
+ /* Failed to read data, reset the touchpad. */
+ CPRINTF("Resetting TP.\n");
+ board_touchpad_reset();
+ elan_tp_init();
+}
+
void touchpad_interrupt(enum gpio_signal signal)
{
irq_ts = __hw_clock_source_read();
@@ -651,6 +682,6 @@ void touchpad_task(void *u)
while (1) {
task_wait_event(-1);
- elan_tp_read_report();
+ elan_tp_read_report_retry();
}
}
diff --git a/include/touchpad.h b/include/touchpad.h
index ce0ee5cc3e..4e746d8dc1 100644
--- a/include/touchpad.h
+++ b/include/touchpad.h
@@ -8,4 +8,7 @@
void touchpad_interrupt(enum gpio_signal signal);
+/* Reset the touchpad, mainly used to recover it from malfunction. */
+void board_touchpad_reset(void);
+
#endif