summaryrefslogtreecommitdiff
path: root/driver/touchpad_st.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/touchpad_st.c')
-rw-r--r--driver/touchpad_st.c116
1 files changed, 94 insertions, 22 deletions
diff --git a/driver/touchpad_st.c b/driver/touchpad_st.c
index 903fee843a..c92da46bca 100644
--- a/driver/touchpad_st.c
+++ b/driver/touchpad_st.c
@@ -32,6 +32,7 @@
#define CPRINTS(format, args...) cprints(CC_TOUCHPAD, format, ## args)
#define TASK_EVENT_POWER TASK_EVENT_CUSTOM(1)
+#define TASK_EVENT_TP_UPDATED TASK_EVENT_CUSTOM(2)
#define SPI (&(spi_devices[SPI_ST_TP_DEVICE_ID]))
@@ -59,6 +60,7 @@ static int system_state;
#define SYSTEM_STATE_ENABLE_DOME_SWITCH (1 << 2)
#define SYSTEM_STATE_ACTIVE_MODE (1 << 3)
#define SYSTEM_STATE_DOME_SWITCH_LEVEL (1 << 4)
+#define SYSTEM_STATE_READY (1 << 5)
/*
* Pending action for touchpad.
@@ -68,10 +70,11 @@ static int tp_control;
#define TP_CONTROL_SHALL_HALT (1 << 0)
#define TP_CONTROL_SHALL_RESET (1 << 1)
#define TP_CONTROL_SHALL_INIT (1 << 2)
-#define TP_CONTROL_SHALL_DUMP_ERROR (1 << 3)
-#define TP_CONTROL_RESETTING (1 << 4)
-#define TP_CONTROL_INIT (1 << 5)
-#define TP_CONTROL_INIT_FULL (1 << 6)
+#define TP_CONTROL_SHALL_INIT_FULL (1 << 3)
+#define TP_CONTROL_SHALL_DUMP_ERROR (1 << 4)
+#define TP_CONTROL_RESETTING (1 << 5)
+#define TP_CONTROL_INIT (1 << 6)
+#define TP_CONTROL_INIT_FULL (1 << 7)
/*
* Number of times we have reset the touchpad because of errors.
@@ -641,7 +644,7 @@ static void st_tp_handle_error(uint8_t error_type)
}
/*
- * Corrupted panel configuration, a full initialization should fix it.
+ * Corrupted panel configuration, a panel init should fix it.
*/
if (error_type >= 0x28 && error_type <= 0x2A) {
tp_control |= TP_CONTROL_SHALL_INIT;
@@ -649,6 +652,14 @@ static void st_tp_handle_error(uint8_t error_type)
}
/*
+ * Corrupted CX section, a full panel init should fix it.
+ */
+ if (error_type >= 0xA0 && error_type <= 0xA6) {
+ tp_control |= TP_CONTROL_SHALL_INIT_FULL;
+ return;
+ }
+
+ /*
* When 0xFF is received, it's very likely ST touchpad is down.
* Try if touchpad can be recovered by reset.
*/
@@ -665,11 +676,6 @@ static void st_tp_handle_error(uint8_t error_type)
/*
* Handles error reports.
- *
- * @param suppress_error: log and don't react on errors.
- *
- * @return 0 for minor errors, 1 for major errors (should not handle non-error
- * events).
*/
static void st_tp_handle_error_report(struct st_tp_event_t *e)
{
@@ -766,6 +772,7 @@ static int st_tp_read_all_events(int show_error)
i = 0;
}
tp_control &= ~TP_CONTROL_SHALL_DUMP_ERROR;
+
return i;
}
@@ -811,17 +818,22 @@ static int st_tp_reset(void)
static void st_tp_init(void)
{
tp_control = 0;
+ system_state = 0;
if (st_tp_reset())
return;
+
+ if (tp_control) {
+ CPRINTS("tp_control = %x", tp_control);
+ return;
+ }
/*
* On boot, ST firmware will load system info to host data memory,
* So we don't need to reload it.
*/
st_tp_read_system_info(0);
- system_state = 0;
- tp_control &= ~TP_CONTROL_RESETTING;
+ system_state = SYSTEM_STATE_READY;
touch_slot = 0;
touchpad_power_control();
@@ -1079,8 +1091,9 @@ static uint8_t get_cx_version(uint8_t tp_version)
* This function will wait until the initialization is done, or 10 second
* timeout is reached.
*
- * @param full: 1 => perform "full" panel initialization.
- * -1 => decide by comparing previous and current cx version.
+ * @param full: 1 => force "full" panel initialization. Otherwise, tp_control
+ * will be checked to decide if full panel initialization is
+ * required.
*
* @return EC_SUCCESS or error code.
*/
@@ -1099,7 +1112,9 @@ static int st_tp_panel_init(int full)
if (ret)
return ret;
- if (full) { /* should perform full panel initialization */
+ full |= tp_control & TP_CONTROL_SHALL_INIT_FULL;
+ if (full) {
+ /* should perform full panel initialization */
tx_buf[2] = 0x3;
tp_control = TP_CONTROL_INIT_FULL;
} else {
@@ -1122,9 +1137,12 @@ static int st_tp_panel_init(int full)
return EC_SUCCESS;
} else if (ret == EC_ERROR_BUSY) {
CPRINTS("Panel initialization on going...");
- } else {
- CPRINTS("Panel initialization failed: %x", -ret);
- return -ret;
+ } else if (tp_control & ~(TP_CONTROL_INIT |
+ TP_CONTROL_INIT_FULL)) {
+ /* there are other kind of errors. */
+ CPRINTS("Panel initialization failed, tp_control: %x",
+ tp_control);
+ return EC_ERROR_UNKNOWN;
}
}
return EC_ERROR_TIMEOUT;
@@ -1146,11 +1164,22 @@ int touchpad_update_write(int offset, int size, const uint8_t *data)
const struct st_tp_fw_header_t *header;
uint8_t old_cx_version;
uint8_t new_cx_version;
+ int retry;
header = (const struct st_tp_fw_header_t *)data;
if (header->signature != 0xAA55AA55)
return EC_ERROR_INVAL;
+ for (retry = 50; retry > 0; retry--) {
+ watchdog_reload();
+ if (system_state & SYSTEM_STATE_READY)
+ break;
+ if (retry % 10 == 0)
+ CPRINTS("TP not ready for update, "
+ "will check again");
+ msleep(100);
+ }
+
old_cx_version = get_cx_version(system_info.release_info);
new_cx_version = get_cx_version(header->release_info);
@@ -1181,7 +1210,9 @@ int touchpad_update_write(int offset, int size, const uint8_t *data)
if (offset + size == CONFIG_TOUCHPAD_VIRTUAL_SIZE) {
CPRINTS("%s: End update, wait for reset.", __func__);
- return st_tp_panel_init(full_init_required);
+ ret = st_tp_panel_init(full_init_required);
+ task_set_event(TASK_ID_TOUCHPAD, TASK_EVENT_TP_UPDATED, 0);
+ return ret;
}
return EC_SUCCESS;
@@ -1376,7 +1407,44 @@ void touchpad_task(void *u)
{
uint32_t event;
- st_tp_init();
+ while (1) {
+ uint32_t retry;
+
+ for (retry = 0; retry < 3; retry++) {
+ CPRINTS("st_tp_init: trial %d", retry + 1);
+ st_tp_init();
+
+ if (system_state & SYSTEM_STATE_READY)
+ break;
+ /*
+ * React on touchpad errors.
+ */
+ if (tp_control & TP_CONTROL_SHALL_INIT_FULL) {
+ /* suppress other handlers */
+ tp_control = TP_CONTROL_SHALL_INIT_FULL;
+ st_tp_panel_init(1);
+ } else if (tp_control & TP_CONTROL_SHALL_INIT) {
+ /* suppress other handlers */
+ tp_control = TP_CONTROL_SHALL_INIT;
+ st_tp_panel_init(0);
+ } else if (tp_control & TP_CONTROL_SHALL_RESET) {
+ /* suppress other handlers */
+ tp_control = TP_CONTROL_SHALL_RESET;
+ } else if (tp_control & TP_CONTROL_SHALL_HALT) {
+ CPRINTS("shall halt");
+ tp_control = 0;
+ break;
+ }
+ }
+
+ if (system_state & SYSTEM_STATE_READY)
+ break;
+
+ /* failed to init, mark it as ready to allow upgrade */
+ system_state = SYSTEM_STATE_READY;
+ /* wait for upgrade complete */
+ task_wait_event_mask(TASK_EVENT_TP_UPDATED, -1);
+ }
touchpad_power_control();
while (1) {
@@ -1400,10 +1468,14 @@ void touchpad_task(void *u)
/*
* React on touchpad errors.
*/
- if (tp_control & TP_CONTROL_SHALL_INIT) {
+ if (tp_control & TP_CONTROL_SHALL_INIT_FULL) {
/* suppress other handlers */
- tp_control = TP_CONTROL_SHALL_INIT;
+ tp_control = TP_CONTROL_SHALL_INIT_FULL;
st_tp_panel_init(1);
+ } else if (tp_control & TP_CONTROL_SHALL_INIT) {
+ /* suppress other handlers */
+ tp_control = TP_CONTROL_SHALL_INIT;
+ st_tp_panel_init(0);
} else if (tp_control & TP_CONTROL_SHALL_RESET) {
/* suppress other handlers */
tp_control = TP_CONTROL_SHALL_RESET;