diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c index 4b569e61c93c..6e403744aa3f 100644 --- a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c +++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c @@ -247,6 +247,49 @@ static void fts_ts_trusted_touch_tvm_vm_mode_disable(struct fts_ts_data *fts_dat static void fts_ts_trusted_touch_abort_tvm(struct fts_ts_data *fts_data); static void fts_ts_trusted_touch_event_notify(struct fts_ts_data *fts_data, int event); +void fts_ts_trusted_touch_tvm_i2c_failure_report(struct fts_ts_data *fts_data) +{ + pr_err("initiating trusted touch abort due to i2c failure\n"); + fts_ts_trusted_touch_abort_handler(fts_data, + TRUSTED_TOUCH_EVENT_I2C_FAILURE); +} + +static void fts_ts_trusted_touch_reset_gpio_toggle(struct fts_ts_data *fts_data) +{ + void __iomem *base; + + base = ioremap(TOUCH_RESET_GPIO_BASE, TOUCH_RESET_GPIO_SIZE); + writel_relaxed(0x1, base + TOUCH_RESET_GPIO_OFFSET); + /* wait until toggle to finish*/ + wmb(); + writel_relaxed(0x0, base + TOUCH_RESET_GPIO_OFFSET); + /* wait until toggle to finish*/ + wmb(); + iounmap(base); +} + +static void fts_trusted_touch_intr_gpio_toggle(struct fts_ts_data *fts_data, + bool enable) +{ + void __iomem *base; + u32 val; + + base = ioremap(TOUCH_INTR_GPIO_BASE, TOUCH_INTR_GPIO_SIZE); + val = readl_relaxed(base + TOUCH_RESET_GPIO_OFFSET); + if (enable) { + val |= BIT(0); + writel_relaxed(val, base + TOUCH_INTR_GPIO_OFFSET); + /* wait until toggle to finish*/ + wmb(); + } else { + val &= ~BIT(0); + writel_relaxed(val, base + TOUCH_INTR_GPIO_OFFSET); + /* wait until toggle to finish*/ + wmb(); + } + iounmap(base); +} + static int fts_ts_trusted_touch_get_tvm_driver_state(struct fts_ts_data *fts_data) { int state; @@ -376,6 +419,7 @@ static void fts_ts_trusted_touch_tvm_vm_mode_enable(struct fts_ts_data *fts_data kfree(acl_desc); irq = hh_irq_accept(fts_data->vm_info->irq_label, -1, IRQ_TYPE_EDGE_RISING); + fts_trusted_touch_intr_gpio_toggle(fts_data, false); if (irq < 0) { pr_err("failed to accept irq\n"); goto accept_fail; @@ -1040,6 +1084,14 @@ static void fts_ts_trusted_touch_abort_handler(struct fts_ts_data *fts_data, int atomic_set(&fts_data->trusted_touch_abort_status, error); pr_err("TUI session aborted with failure:%d\n", error); fts_ts_trusted_touch_event_notify(fts_data, error); +#ifdef CONFIG_ARCH_QTI_VM + pr_err("Resetting touch controller\n"); + if (fts_ts_trusted_touch_get_tvm_driver_state(fts_data) >= TVM_IOMEM_ACCEPTED + && error == TRUSTED_TOUCH_EVENT_I2C_FAILURE) { + pr_err("Resetting touch controller\n"); + fts_ts_trusted_touch_reset_gpio_toggle(fts_data); + } +#endif } static int fts_ts_vm_init(struct fts_ts_data *fts_data) diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.h b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h index ddfd46fd2c92..692408855cfd 100644 --- a/drivers/input/touchscreen/focaltech_touch/focaltech_core.h +++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h @@ -178,17 +178,25 @@ enum trusted_touch_tvm_states { TRUSTED_TOUCH_TVM_STATE_MAX }; +#ifdef CONFIG_FTS_TRUSTED_TOUCH +#define TRUSTED_TOUCH_MEM_LABEL 0x7 + +#define TOUCH_RESET_GPIO_BASE 0xF116000 +#define TOUCH_RESET_GPIO_SIZE 0x1000 +#define TOUCH_RESET_GPIO_OFFSET 0x4 +#define TOUCH_INTR_GPIO_BASE 0xF117000 +#define TOUCH_INTR_GPIO_SIZE 0x1000 +#define TOUCH_INTR_GPIO_OFFSET 0x8 + #define TRUSTED_TOUCH_EVENT_LEND_FAILURE -1 #define TRUSTED_TOUCH_EVENT_LEND_NOTIFICATION_FAILURE -2 #define TRUSTED_TOUCH_EVENT_ACCEPT_FAILURE -3 #define TRUSTED_TOUCH_EVENT_FUNCTIONAL_FAILURE -4 #define TRUSTED_TOUCH_EVENT_RELEASE_FAILURE -5 #define TRUSTED_TOUCH_EVENT_RECLAIM_FAILURE -6 +#define TRUSTED_TOUCH_EVENT_I2C_FAILURE -7 #define TRUSTED_TOUCH_EVENT_NOTIFICATIONS_PENDING 5 -#ifdef CONFIG_FTS_TRUSTED_TOUCH -#define TRUSTED_TOUCH_MEM_LABEL 0x7 - struct trusted_touch_vm_info { enum hh_irq_label irq_label; enum hh_vm_names vm_name; @@ -346,4 +354,9 @@ void fts_irq_disable(void); void fts_irq_enable(void); int fts_ts_handle_trusted_touch_pvm(struct fts_ts_data *ts_data, int value); int fts_ts_handle_trusted_touch_tvm(struct fts_ts_data *ts_data, int value); +#ifdef CONFIG_FTS_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM +void fts_ts_trusted_touch_tvm_i2c_failure_report(struct fts_ts_data *fts_data); +#endif +#endif #endif /* __LINUX_FOCALTECH_CORE_H__ */ diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c b/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c index f4e74af5535c..c9e2014b5951 100644 --- a/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c +++ b/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c @@ -35,7 +35,7 @@ * Included header files *****************************************************************************/ #include "focaltech_core.h" - +#include /***************************************************************************** * Private constant and macro definitions using #define *****************************************************************************/ @@ -101,6 +101,18 @@ int fts_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen) for (i = 0; i < I2C_RETRY_NUMBER; i++) { ret = i2c_transfer(ts_data->client->adapter, msg, msg_num); if (ret < 0) { +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM + if (atomic_read(&ts_data->trusted_touch_enabled) && + ret == -ECONNRESET) { + pr_err("failed i2c read reacquiring session\n"); + pm_runtime_put_sync( + ts_data->client->adapter->dev.parent); + pm_runtime_get_sync( + ts_data->client->adapter->dev.parent); + } +#endif +#endif FTS_ERROR("i2c_transfer(read) fail,ret:%d", ret); } else { memcpy(data, ts_data->bus_rx_buf, datalen); @@ -108,6 +120,15 @@ int fts_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen) } } + if (ret < 0) { +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM + pr_err("initiating abort due to i2c xfer failure\n"); + fts_ts_trusted_touch_tvm_i2c_failure_report(ts_data); +#endif +#endif + } + mutex_unlock(&ts_data->bus_lock); return ret; } @@ -135,11 +156,32 @@ int fts_write(u8 *writebuf, u32 writelen) for (i = 0; i < I2C_RETRY_NUMBER; i++) { ret = i2c_transfer(ts_data->client->adapter, &msgs, 1); if (ret < 0) { +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM + if (atomic_read(&ts_data->trusted_touch_enabled) && + ret == -ECONNRESET){ + pr_err("failed i2c write reacquiring session\n"); + pm_runtime_put_sync( + ts_data->client->adapter->dev.parent); + pm_runtime_get_sync( + ts_data->client->adapter->dev.parent); + } +#endif +#endif FTS_ERROR("i2c_transfer(write) fail,ret:%d", ret); } else { break; } } + + if (ret < 0) { +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM + pr_err("initiating abort due to i2c xfer failure\n"); + fts_ts_trusted_touch_tvm_i2c_failure_report(ts_data); +#endif +#endif + } mutex_unlock(&ts_data->bus_lock); return ret; }