diff --git a/drivers/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c index 18b321d50d02..89549315d215 100644 --- a/drivers/input/touchscreen/st/fts.c +++ b/drivers/input/touchscreen/st/fts.c @@ -270,6 +270,49 @@ static void fts_trusted_touch_tvm_vm_mode_disable(struct fts_ts_info *info); static void fts_trusted_touch_abort_tvm(struct fts_ts_info *info); static void fts_trusted_touch_event_notify(struct fts_ts_info *info, int event); +void fts_trusted_touch_tvm_i2c_failure_report(struct fts_ts_info *info) +{ + pr_err("initiating trusted touch abort due to i2c failure\n"); + fts_trusted_touch_abort_handler(info, + TRUSTED_TOUCH_EVENT_I2C_FAILURE); +} + +static void fts_trusted_touch_reset_gpio_toggle(struct fts_ts_info *info) +{ + 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_info *info, + 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_trusted_touch_get_tvm_driver_state(struct fts_ts_info *info) { int state; @@ -401,6 +444,7 @@ static void fts_trusted_touch_tvm_vm_mode_enable(struct fts_ts_info *info) kfree(expected_sgl_desc); kfree(acl_desc); + fts_trusted_touch_intr_gpio_toggle(info, false); irq = hh_irq_accept(info->vm_info->irq_label, -1, IRQ_TYPE_LEVEL_HIGH); if (irq < 0) { pr_err("failed to accept irq\n"); @@ -1065,6 +1109,14 @@ static void fts_trusted_touch_abort_handler(struct fts_ts_info *info, int error) { atomic_set(&info->trusted_touch_abort_status, error); pr_err("TUI session aborted with failure:%d\n", error); +#ifdef CONFIG_ARCH_QTI_VM + pr_err("Resetting touch controller\n"); + if (fts_trusted_touch_get_tvm_driver_state(info) >= TVM_IOMEM_ACCEPTED + && error == TRUSTED_TOUCH_EVENT_I2C_FAILURE) { + pr_err("Resetting touch controller\n"); + fts_trusted_touch_reset_gpio_toggle(info); + } +#endif fts_trusted_touch_event_notify(info, error); } @@ -4621,6 +4673,7 @@ static irqreturn_t fts_interrupt_handler(int irq, void *handle) pr_err("%s: Invalid info\n", __func__); return IRQ_HANDLED; } + disable_irq_nosync(info->client->irq); queue_work(info->event_wq, &info->work); @@ -4700,13 +4753,26 @@ static void fts_interrupt_uninstall(struct fts_ts_info *info) static void fts_interrupt_enable(struct fts_ts_info *info) { + int ret = 0; #ifdef FTS_USE_POLLING_MODE hrtimer_start(&info->timer, ktime_set(0, 10000000), HRTIMER_MODE_REL); #else enable_irq(info->client->irq); #endif /* enable the touch IC irq */ - fts_enableInterrupt(); + ret = fts_enableInterrupt(); +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifndef CONFIG_ARCH_QTI_VM + if ((ret < 0) && atomic_read(&info->trusted_touch_enabled)) { + fts_chip_powercycle2(info, 300); + ret = fts_system_reset(); + ret |= fts_mode_handler(info, 0); + ret |= fts_enableInterrupt(); + if (ret < 0) + pr_err("failed to enable touch interrupts\n"); + } +#endif +#endif } static void fts_interrupt_disable(struct fts_ts_info *info) diff --git a/drivers/input/touchscreen/st/fts.h b/drivers/input/touchscreen/st/fts.h index 354265d2585b..2745a18d4238 100644 --- a/drivers/input/touchscreen/st/fts.h +++ b/drivers/input/touchscreen/st/fts.h @@ -251,17 +251,25 @@ enum trusted_touch_tvm_states { TRUSTED_TOUCH_TVM_STATE_MAX }; +#ifdef CONFIG_ST_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_ST_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; @@ -279,6 +287,10 @@ struct trusted_touch_vm_info { atomic_t pvm_state; #endif }; + +#ifdef CONFIG_ARCH_QTI_VM +void fts_trusted_touch_tvm_i2c_failure_report(struct fts_ts_info *info); +#endif #endif /* diff --git a/drivers/input/touchscreen/st/fts_lib/ftsIO.c b/drivers/input/touchscreen/st/fts_lib/ftsIO.c index ba0fb18e3307..12f02d9424ff 100644 --- a/drivers/input/touchscreen/st/fts_lib/ftsIO.c +++ b/drivers/input/touchscreen/st/fts_lib/ftsIO.c @@ -34,6 +34,7 @@ * */ +#include #include #include #include @@ -141,13 +142,32 @@ int fts_readCmd(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead) while (retry < I2C_RETRY && ret < OK) { ret = i2c_transfer(client->adapter, I2CMsg, 2); retry++; - if (ret < OK) + if (ret < OK) { +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM + if (atomic_read(&info->trusted_touch_enabled) && + ret == -ECONNRESET){ + pr_err("failed i2c read reacquiring session\n"); + pm_runtime_put_sync( + info->client->adapter->dev.parent); + pm_runtime_get_sync( + info->client->adapter->dev.parent); + } +#endif +#endif msleep(I2C_WAIT_BEFORE_RETRY); + } } if (ret < 0) { +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM + pr_err("initiating abort due to i2c xfer failure\n"); + fts_trusted_touch_tvm_i2c_failure_report(info); +#endif +#endif logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_I2C_R); - return ERROR_I2C_R; + return ret; } memcpy(outBuf, buf + cmdLength, byteToRead); @@ -189,13 +209,34 @@ int fts_writeCmd(u8 *cmd, int cmdLength) while (retry < I2C_RETRY && ret < OK) { ret = i2c_transfer(client->adapter, I2CMsg, 1); retry++; - if (ret < OK) + if (ret < OK) { +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM + if (atomic_read(&info->trusted_touch_enabled) && + ret == -ECONNRESET){ + pr_err("failed i2c write reacquiring session\n"); + pm_runtime_put_sync( + info->client->adapter->dev.parent); + pm_runtime_get_sync( + info->client->adapter->dev.parent); + + } +#endif +#endif msleep(I2C_WAIT_BEFORE_RETRY); + logError(1, "ERROR: %d\n", ret); + } //logError(1,"%s fts_writeCmd: attempt %d\n", tag, retry); } if (ret < 0) { +#ifdef CONFIG_ST_TRUSTED_TOUCH +#ifdef CONFIG_ARCH_QTI_VM + pr_err("initiating abort due to i2c xfer failure\n"); + fts_trusted_touch_tvm_i2c_failure_report(info); +#endif +#endif logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_I2C_W); - return ERROR_I2C_W; + return ret; } return OK; } diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTool.c b/drivers/input/touchscreen/st/fts_lib/ftsTool.c index 543682d1e3c6..55285fd18892 100644 --- a/drivers/input/touchscreen/st/fts_lib/ftsTool.c +++ b/drivers/input/touchscreen/st/fts_lib/ftsTool.c @@ -789,11 +789,13 @@ int fts_disableInterrupt(void) int fts_enableInterrupt(void) { u8 cmd[4] = { FTS_CMD_HW_REG_W, 0x00, 0x00, IER_ENABLE }; + int ret = 0; u16ToU8_be(IER_ADDR, &cmd[1]); - if (fts_writeCmd(cmd, 4) < 0) { - logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_I2C_W); - return ERROR_I2C_W; + ret = fts_writeCmd(cmd, 4); + if (ret < 0) { + logError(1, "%s %s: ERROR %d\n", tag, __func__, ret); + return ret; } logError(0, "%s Interrupt Enabled!\n", tag); return OK;