Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a580c23 authored by Shantanu Jain's avatar Shantanu Jain
Browse files

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.

CRs-Fixed: 990820
Change-Id: I47520f9ba91b7645dff2c11b4c58a0b7aeed2765
Signed-off-by: default avatarShantanu Jain <shjain@codeaurora.org>
parent 17d7bd58
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -1127,4 +1127,15 @@ config TOUCHSCREEN_MAXIM_STI
	  module will be called maxim_sti.
	  module will be called maxim_sti.


source "drivers/input/touchscreen/gt9xx/Kconfig"
source "drivers/input/touchscreen/gt9xx/Kconfig"

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
endif
+85 −1
Original line number Original line Diff line number Diff line
@@ -627,6 +627,67 @@ static struct kobj_attribute virtual_key_map_attr = {
	.show = synaptics_rmi4_virtual_key_map_show,
	.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,
static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
		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 =
	const struct synaptics_dsx_board_data *bdata =
			rmi4_data->hw_if->board_data;
			rmi4_data->hw_if->board_data;


	if (IRQ_HANDLED == synaptics_filter_interrupt(data))
		return IRQ_HANDLED;

	if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state)
	if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state)
		goto exit;
		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);
	queue_work(rmi4_data->reset_workqueue, &rmi4_data->reset_work);
#endif
#endif


	/* Initialize secure touch */
	synaptics_secure_touch_init(rmi4_data);
	synaptics_secure_touch_stop(rmi4_data, true);

	return retval;
	return retval;


err_sysfs:
err_sysfs:
@@ -4106,7 +4174,9 @@ static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self,
			fb_notifier);
			fb_notifier);


	if (evdata && evdata->data && rmi4_data) {
	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;
			transition = evdata->data;
			if (*transition == FB_BLANK_POWERDOWN) {
			if (*transition == FB_BLANK_POWERDOWN) {
				synaptics_rmi4_suspend(&rmi4_data->pdev->dev);
				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)
	if (rmi4_data->stay_awake)
		return;
		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) {
	if (rmi4_data->enable_wakeup_gesture) {
		synaptics_rmi4_wakeup_gesture(rmi4_data, true);
		synaptics_rmi4_wakeup_gesture(rmi4_data, true);
		enable_irq_wake(rmi4_data->irq);
		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)
	if (rmi4_data->stay_awake)
		return;
		return;


	synaptics_secure_touch_stop(rmi4_data, false);

	if (rmi4_data->enable_wakeup_gesture) {
	if (rmi4_data->enable_wakeup_gesture) {
		synaptics_rmi4_wakeup_gesture(rmi4_data, false);
		synaptics_rmi4_wakeup_gesture(rmi4_data, false);
		disable_irq_wake(rmi4_data->irq);
		disable_irq_wake(rmi4_data->irq);
@@ -4216,6 +4296,8 @@ static int synaptics_rmi4_suspend(struct device *dev)
	if (rmi4_data->stay_awake)
	if (rmi4_data->stay_awake)
		return 0;
		return 0;


	synaptics_secure_touch_stop(rmi4_data, true);

	if (rmi4_data->enable_wakeup_gesture) {
	if (rmi4_data->enable_wakeup_gesture) {
		synaptics_rmi4_wakeup_gesture(rmi4_data, true);
		synaptics_rmi4_wakeup_gesture(rmi4_data, true);
		enable_irq_wake(rmi4_data->irq);
		enable_irq_wake(rmi4_data->irq);
@@ -4253,6 +4335,8 @@ static int synaptics_rmi4_resume(struct device *dev)
	if (rmi4_data->stay_awake)
	if (rmi4_data->stay_awake)
		return 0;
		return 0;


	synaptics_secure_touch_stop(rmi4_data, true);

	if (rmi4_data->enable_wakeup_gesture) {
	if (rmi4_data->enable_wakeup_gesture) {
		synaptics_rmi4_wakeup_gesture(rmi4_data, false);
		synaptics_rmi4_wakeup_gesture(rmi4_data, false);
		disable_irq_wake(rmi4_data->irq);
		disable_irq_wake(rmi4_data->irq);
+12 −0
Original line number Original line Diff line number Diff line
@@ -48,6 +48,12 @@
#include <linux/earlysuspend.h>
#include <linux/earlysuspend.h>
#endif
#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))
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38))
#define KERNEL_ABOVE_2_6_38
#define KERNEL_ABOVE_2_6_38
#endif
#endif
@@ -374,6 +380,12 @@ struct synaptics_rmi4_data {
			bool enable);
			bool enable);
	void (*report_touch)(struct synaptics_rmi4_data *rmi4_data,
	void (*report_touch)(struct synaptics_rmi4_data *rmi4_data,
			struct synaptics_rmi4_fn *fhandler);
			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 {
struct synaptics_dsx_bus_access {