input: synaptics_dsx_2.6: add secure touch support for Synaptics V2.6
8953 QRD supports Synaptics touch controller. For synaptics_dsx_2.6 driver to work with the TrustZone secure touch, all the touch interrupts must be forwarded between the Linux Kernel and the TrustZone input driver. Add APIs and configuration to support this. Change-Id: I47520f9ba91b7645dff2c11b4c58a0b7aeed2765 Signed-off-by: Shantanu Jain <shjain@codeaurora.org>
This commit is contained in:
parent
e97b6a0e02
commit
930440dc31
3 changed files with 107 additions and 1 deletions
|
@ -1177,4 +1177,14 @@ config TOUCHSCREEN_FT5X06
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ft5x06_ts.
|
||||
|
||||
config SECURE_TOUCH_SYNAPTICS_DSX_V26
|
||||
bool "Secure Touch support for Synaptics V2.6 Touchscreen"
|
||||
depends on TOUCHSCREEN_SYNAPTICS_DSX_I2C_v26
|
||||
help
|
||||
Say Y here
|
||||
-Synaptics DSX V2.6 touch driver is connected
|
||||
-To enable secure touch for Synaptics DSX V2.6 touch driver
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endif
|
||||
|
|
|
@ -627,6 +627,67 @@ static struct kobj_attribute virtual_key_map_attr = {
|
|||
.show = synaptics_rmi4_virtual_key_map_show,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26)
|
||||
static void synaptics_secure_touch_init(struct synaptics_rmi4_data *data)
|
||||
{
|
||||
init_completion(&data->st_powerdown);
|
||||
init_completion(&data->st_irq_processed);
|
||||
}
|
||||
|
||||
static void synaptics_secure_touch_notify(struct synaptics_rmi4_data *rmi4_data)
|
||||
{
|
||||
sysfs_notify(&rmi4_data->input_dev->dev.kobj, NULL, "secure_touch");
|
||||
}
|
||||
|
||||
static irqreturn_t synaptics_filter_interrupt(
|
||||
struct synaptics_rmi4_data *rmi4_data)
|
||||
{
|
||||
if (atomic_read(&rmi4_data->st_enabled)) {
|
||||
if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, 0, 1) == 0) {
|
||||
reinit_completion(&rmi4_data->st_irq_processed);
|
||||
synaptics_secure_touch_notify(rmi4_data);
|
||||
wait_for_completion_interruptible(
|
||||
&rmi4_data->st_irq_processed);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'blocking' variable will have value 'true' when we want to prevent the driver
|
||||
* from accessing the xPU/SMMU protected HW resources while the session is
|
||||
* active.
|
||||
*/
|
||||
static void synaptics_secure_touch_stop(struct synaptics_rmi4_data *rmi4_data,
|
||||
bool blocking)
|
||||
{
|
||||
if (atomic_read(&rmi4_data->st_enabled)) {
|
||||
atomic_set(&rmi4_data->st_pending_irqs, -1);
|
||||
synaptics_secure_touch_notify(rmi4_data);
|
||||
if (blocking)
|
||||
wait_for_completion_interruptible(
|
||||
&rmi4_data->st_powerdown);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static void synaptics_secure_touch_init(struct synaptics_rmi4_data *rmi4_data)
|
||||
{
|
||||
}
|
||||
|
||||
static irqreturn_t synaptics_filter_interrupt(
|
||||
struct synaptics_rmi4_data *rmi4_data)
|
||||
{
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static void synaptics_secure_touch_stop(struct synaptics_rmi4_data *rmi4_data,
|
||||
bool blocking)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
|
@ -1512,6 +1573,9 @@ static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
|
|||
const struct synaptics_dsx_board_data *bdata =
|
||||
rmi4_data->hw_if->board_data;
|
||||
|
||||
if (synaptics_filter_interrupt(data) == IRQ_HANDLED)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state)
|
||||
goto exit;
|
||||
|
||||
|
@ -3866,6 +3930,10 @@ static int synaptics_rmi4_probe(struct platform_device *pdev)
|
|||
queue_work(rmi4_data->reset_workqueue, &rmi4_data->reset_work);
|
||||
#endif
|
||||
|
||||
/* Initialize secure touch */
|
||||
synaptics_secure_touch_init(rmi4_data);
|
||||
synaptics_secure_touch_stop(rmi4_data, true);
|
||||
|
||||
return retval;
|
||||
|
||||
err_sysfs:
|
||||
|
@ -4106,7 +4174,9 @@ static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self,
|
|||
fb_notifier);
|
||||
|
||||
if (evdata && evdata->data && rmi4_data) {
|
||||
if (event == FB_EVENT_BLANK) {
|
||||
if (event == FB_EARLY_EVENT_BLANK) {
|
||||
synaptics_secure_touch_stop(rmi4_data, false);
|
||||
} else if (event == FB_EVENT_BLANK) {
|
||||
transition = evdata->data;
|
||||
if (*transition == FB_BLANK_POWERDOWN) {
|
||||
synaptics_rmi4_suspend(&rmi4_data->pdev->dev);
|
||||
|
@ -4133,6 +4203,14 @@ static void synaptics_rmi4_early_suspend(struct early_suspend *h)
|
|||
if (rmi4_data->stay_awake)
|
||||
return;
|
||||
|
||||
/*
|
||||
* During early suspend/late resume, the driver doesn't access xPU/SMMU
|
||||
* protected HW resources. So, there is no compelling need to block,
|
||||
* but notifying the userspace that a power event has occurred is
|
||||
* enough. Hence 'blocking' variable can be set to false.
|
||||
*/
|
||||
synaptics_secure_touch_stop(rmi4_data, false);
|
||||
|
||||
if (rmi4_data->enable_wakeup_gesture) {
|
||||
synaptics_rmi4_wakeup_gesture(rmi4_data, true);
|
||||
enable_irq_wake(rmi4_data->irq);
|
||||
|
@ -4170,6 +4248,8 @@ static void synaptics_rmi4_late_resume(struct early_suspend *h)
|
|||
if (rmi4_data->stay_awake)
|
||||
return;
|
||||
|
||||
synaptics_secure_touch_stop(rmi4_data, false);
|
||||
|
||||
if (rmi4_data->enable_wakeup_gesture) {
|
||||
synaptics_rmi4_wakeup_gesture(rmi4_data, false);
|
||||
disable_irq_wake(rmi4_data->irq);
|
||||
|
@ -4216,6 +4296,8 @@ static int synaptics_rmi4_suspend(struct device *dev)
|
|||
if (rmi4_data->stay_awake)
|
||||
return 0;
|
||||
|
||||
synaptics_secure_touch_stop(rmi4_data, true);
|
||||
|
||||
if (rmi4_data->enable_wakeup_gesture) {
|
||||
synaptics_rmi4_wakeup_gesture(rmi4_data, true);
|
||||
enable_irq_wake(rmi4_data->irq);
|
||||
|
@ -4253,6 +4335,8 @@ static int synaptics_rmi4_resume(struct device *dev)
|
|||
if (rmi4_data->stay_awake)
|
||||
return 0;
|
||||
|
||||
synaptics_secure_touch_stop(rmi4_data, true);
|
||||
|
||||
if (rmi4_data->enable_wakeup_gesture) {
|
||||
synaptics_rmi4_wakeup_gesture(rmi4_data, false);
|
||||
disable_irq_wake(rmi4_data->irq);
|
||||
|
|
|
@ -48,6 +48,12 @@
|
|||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26)
|
||||
#include <linux/completion.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38))
|
||||
#define KERNEL_ABOVE_2_6_38
|
||||
#endif
|
||||
|
@ -374,6 +380,12 @@ struct synaptics_rmi4_data {
|
|||
bool enable);
|
||||
void (*report_touch)(struct synaptics_rmi4_data *rmi4_data,
|
||||
struct synaptics_rmi4_fn *fhandler);
|
||||
#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26)
|
||||
atomic_t st_enabled;
|
||||
atomic_t st_pending_irqs;
|
||||
struct completion st_powerdown;
|
||||
struct completion st_irq_processed;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct synaptics_dsx_bus_access {
|
||||
|
|
Loading…
Add table
Reference in a new issue