input: touchscreen: st: toggle reset gpio during error on SVM

Toggle reset gpio of touch controller during an error
scenario on Secondary Virtual Machine(SVM).

Change-Id: I5d296248c88a6eef13887884892894faa4c984e6
Signed-off-by: Shashank Babu Chinta Venkata <sbchin@codeaurora.org>
This commit is contained in:
Shashank Babu Chinta Venkata 2020-09-28 01:54:39 -07:00
commit f57ed9297e
4 changed files with 132 additions and 11 deletions

View file

@ -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)

View file

@ -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
/*

View file

@ -34,6 +34,7 @@
*
*/
#include <linux/pm_runtime.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
@ -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;
}

View file

@ -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;