aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-11 22:17:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-11 22:17:28 -0400
commitf0c032d81f58c99b63a6e57cf883e923db910928 (patch)
treee7f8f7ba2b08681ec1e7544cba1f120f601737e3
parentfa9a67ef9de48de5474ea1e5a358340369e78b74 (diff)
parent53431d0a3534263168c8ee576bad1c2c3a4cd9e0 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull more input updates from Dmitry Torokhov: "Second round of updates for the input subsystem. This introduces two brand new touchscreen drivers (Colibri and imx6ul_tsc), some small driver fixes, and we are no longer report errors from evdev_flush() as users do not really have a way of handling errors, error codes that we were returning were not on the list of errors supposed to be returned by close(), and errors were causing issues with one of older versions of systemd" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: imx_keypad - remove obsolete comment Input: touchscreen - add imx6ul_tsc driver support Input: Add touchscreen support for Colibri VF50 Input: i8042 - lower log level for "no controller" message Input: evdev - do not report errors form flush() Input: elants_i2c - extend the calibration timeout to 12 seconds Input: sparcspkr - fix module autoload for OF platform drivers Input: regulator-haptic - fix module autoload for OF platform driver Input: pwm-beeper - fix module autoload for OF platform driver Input: ab8500-ponkey - Fix module autoload for OF platform driver Input: cyttsp - remove unnecessary MODULE_ALIAS() Input: elan_i2c - add ACPI ID "ELAN1000"
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt36
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt36
-rw-r--r--drivers/input/evdev.c13
-rw-r--r--drivers/input/keyboard/imx_keypad.c2
-rw-r--r--drivers/input/misc/ab8500-ponkey.c1
-rw-r--r--drivers/input/misc/pwm-beeper.c1
-rw-r--r--drivers/input/misc/regulator-haptic.c1
-rw-r--r--drivers/input/misc/sparcspkr.c2
-rw-r--r--drivers/input/mouse/elan_i2c_core.c1
-rw-r--r--drivers/input/serio/i8042.c2
-rw-r--r--drivers/input/touchscreen/Kconfig24
-rw-r--r--drivers/input/touchscreen/Makefile2
-rw-r--r--drivers/input/touchscreen/colibri-vf50-ts.c386
-rw-r--r--drivers/input/touchscreen/cyttsp4_i2c.c1
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c.c1
-rw-r--r--drivers/input/touchscreen/elants_i2c.c2
-rw-r--r--drivers/input/touchscreen/imx6ul_tsc.c523
17 files changed, 1019 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt
new file mode 100644
index 000000000000..9d9e930f3251
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt
@@ -0,0 +1,36 @@
1* Toradex Colibri VF50 Touchscreen driver
2
3Required Properties:
4- compatible must be toradex,vf50-touchscreen
5- io-channels: adc channels being used by the Colibri VF50 module
6- xp-gpios: FET gate driver for input of X+
7- xm-gpios: FET gate driver for input of X-
8- yp-gpios: FET gate driver for input of Y+
9- ym-gpios: FET gate driver for input of Y-
10- interrupt-parent: phandle for the interrupt controller
11- interrupts: pen irq interrupt for touch detection
12- pinctrl-names: "idle", "default", "gpios"
13- pinctrl-0: pinctrl node for pen/touch detection state pinmux
14- pinctrl-1: pinctrl node for X/Y and pressure measurement (ADC) state pinmux
15- pinctrl-2: pinctrl node for gpios functioning as FET gate drivers
16- vf50-ts-min-pressure: pressure level at which to stop measuring X/Y values
17
18Example:
19
20 touchctrl: vf50_touchctrl {
21 compatible = "toradex,vf50-touchscreen";
22 io-channels = <&adc1 0>,<&adc0 0>,
23 <&adc0 1>,<&adc1 2>;
24 xp-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
25 xm-gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>;
26 yp-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
27 ym-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
28 interrupt-parent = <&gpio0>;
29 interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
30 pinctrl-names = "idle","default","gpios";
31 pinctrl-0 = <&pinctrl_touchctrl_idle>;
32 pinctrl-1 = <&pinctrl_touchctrl_default>;
33 pinctrl-2 = <&pinctrl_touchctrl_gpios>;
34 vf50-ts-min-pressure = <200>;
35 status = "disabled";
36 };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt b/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt
new file mode 100644
index 000000000000..853dff96dd9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt
@@ -0,0 +1,36 @@
1* Freescale i.MX6UL Touch Controller
2
3Required properties:
4- compatible: must be "fsl,imx6ul-tsc".
5- reg: this touch controller address and the ADC2 address.
6- interrupts: the interrupt of this touch controller and ADC2.
7- clocks: the root clock of touch controller and ADC2.
8- clock-names; must be "tsc" and "adc".
9- xnur-gpio: the X- gpio this controller connect to.
10 This xnur-gpio returns to low once the finger leave the touch screen (The
11 last touch event the touch controller capture).
12
13Optional properties:
14- measure-delay-time: the value of measure delay time.
15 Before X-axis or Y-axis measurement, the screen need some time before
16 even potential distribution ready.
17 This value depends on the touch screen.
18- pre-charge-time: the touch screen need some time to precharge.
19 This value depends on the touch screen.
20
21Example:
22 tsc: tsc@02040000 {
23 compatible = "fsl,imx6ul-tsc";
24 reg = <0x02040000 0x4000>, <0x0219c000 0x4000>;
25 interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
26 <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
27 clocks = <&clks IMX6UL_CLK_IPG>,
28 <&clks IMX6UL_CLK_ADC2>;
29 clock-names = "tsc", "adc";
30 pinctrl-names = "default";
31 pinctrl-0 = <&pinctrl_tsc>;
32 xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
33 measure-delay-time = <0xfff>;
34 pre-charge-time = <0xffff>;
35 status = "okay";
36 };
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 9d35499faca4..08d496411f75 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -290,19 +290,14 @@ static int evdev_flush(struct file *file, fl_owner_t id)
290{ 290{
291 struct evdev_client *client = file->private_data; 291 struct evdev_client *client = file->private_data;
292 struct evdev *evdev = client->evdev; 292 struct evdev *evdev = client->evdev;
293 int retval;
294 293
295 retval = mutex_lock_interruptible(&evdev->mutex); 294 mutex_lock(&evdev->mutex);
296 if (retval)
297 return retval;
298 295
299 if (!evdev->exist || client->revoked) 296 if (evdev->exist && !client->revoked)
300 retval = -ENODEV; 297 input_flush_device(&evdev->handle, file);
301 else
302 retval = input_flush_device(&evdev->handle, file);
303 298
304 mutex_unlock(&evdev->mutex); 299 mutex_unlock(&evdev->mutex);
305 return retval; 300 return 0;
306} 301}
307 302
308static void evdev_free(struct device *dev) 303static void evdev_free(struct device *dev)
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index d2ea863d6a45..2165f3dd328b 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -5,8 +5,6 @@
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 *
9 * <<Power management needs to be implemented>>.
10 */ 8 */
11 9
12#include <linux/clk.h> 10#include <linux/clk.h>
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
index 1f7e15ca5fbe..4f5ef5bb535b 100644
--- a/drivers/input/misc/ab8500-ponkey.c
+++ b/drivers/input/misc/ab8500-ponkey.c
@@ -118,6 +118,7 @@ static const struct of_device_id ab8500_ponkey_match[] = {
118 { .compatible = "stericsson,ab8500-ponkey", }, 118 { .compatible = "stericsson,ab8500-ponkey", },
119 {} 119 {}
120}; 120};
121MODULE_DEVICE_TABLE(of, ab8500_ponkey_match);
121#endif 122#endif
122 123
123static struct platform_driver ab8500_ponkey_driver = { 124static struct platform_driver ab8500_ponkey_driver = {
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
index e82edf810d1f..f2261ab54701 100644
--- a/drivers/input/misc/pwm-beeper.c
+++ b/drivers/input/misc/pwm-beeper.c
@@ -173,6 +173,7 @@ static const struct of_device_id pwm_beeper_match[] = {
173 { .compatible = "pwm-beeper", }, 173 { .compatible = "pwm-beeper", },
174 { }, 174 { },
175}; 175};
176MODULE_DEVICE_TABLE(of, pwm_beeper_match);
176#endif 177#endif
177 178
178static struct platform_driver pwm_beeper_driver = { 179static struct platform_driver pwm_beeper_driver = {
diff --git a/drivers/input/misc/regulator-haptic.c b/drivers/input/misc/regulator-haptic.c
index 6bf3f1082f71..a804705eb04a 100644
--- a/drivers/input/misc/regulator-haptic.c
+++ b/drivers/input/misc/regulator-haptic.c
@@ -249,6 +249,7 @@ static const struct of_device_id regulator_haptic_dt_match[] = {
249 { .compatible = "regulator-haptic" }, 249 { .compatible = "regulator-haptic" },
250 { /* sentinel */ }, 250 { /* sentinel */ },
251}; 251};
252MODULE_DEVICE_TABLE(of, regulator_haptic_dt_match);
252 253
253static struct platform_driver regulator_haptic_driver = { 254static struct platform_driver regulator_haptic_driver = {
254 .probe = regulator_haptic_probe, 255 .probe = regulator_haptic_probe,
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 54116e544c96..6f997aa49183 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -253,6 +253,7 @@ static const struct of_device_id bbc_beep_match[] = {
253 }, 253 },
254 {}, 254 {},
255}; 255};
256MODULE_DEVICE_TABLE(of, bbc_beep_match);
256 257
257static struct platform_driver bbc_beep_driver = { 258static struct platform_driver bbc_beep_driver = {
258 .driver = { 259 .driver = {
@@ -332,6 +333,7 @@ static const struct of_device_id grover_beep_match[] = {
332 }, 333 },
333 {}, 334 {},
334}; 335};
336MODULE_DEVICE_TABLE(of, grover_beep_match);
335 337
336static struct platform_driver grover_beep_driver = { 338static struct platform_driver grover_beep_driver = {
337 .driver = { 339 .driver = {
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index e2b7420eed97..fa945304b9a5 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -1170,6 +1170,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
1170 { "ELAN0000", 0 }, 1170 { "ELAN0000", 0 },
1171 { "ELAN0100", 0 }, 1171 { "ELAN0100", 0 },
1172 { "ELAN0600", 0 }, 1172 { "ELAN0600", 0 },
1173 { "ELAN1000", 0 },
1173 { } 1174 { }
1174}; 1175};
1175MODULE_DEVICE_TABLE(acpi, elan_acpi_id); 1176MODULE_DEVICE_TABLE(acpi, elan_acpi_id);
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index c9c98f0ab284..db91de539ee3 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -877,7 +877,7 @@ static int __init i8042_check_aux(void)
877static int i8042_controller_check(void) 877static int i8042_controller_check(void)
878{ 878{
879 if (i8042_flush()) { 879 if (i8042_flush()) {
880 pr_err("No controller found\n"); 880 pr_info("No controller found\n");
881 return -ENODEV; 881 return -ENODEV;
882 } 882 }
883 883
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 059edeb7f04a..600dcceff542 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -479,6 +479,18 @@ config TOUCHSCREEN_MTOUCH
479 To compile this driver as a module, choose M here: the 479 To compile this driver as a module, choose M here: the
480 module will be called mtouch. 480 module will be called mtouch.
481 481
482config TOUCHSCREEN_IMX6UL_TSC
483 tristate "Freescale i.MX6UL touchscreen controller"
484 depends on (OF && GPIOLIB) || COMPILE_TEST
485 help
486 Say Y here if you have a Freescale i.MX6UL, and want to
487 use the internal touchscreen controller.
488
489 If unsure, say N.
490
491 To compile this driver as a module, choose M here: the
492 module will be called imx6ul_tsc.
493
482config TOUCHSCREEN_INEXIO 494config TOUCHSCREEN_INEXIO
483 tristate "iNexio serial touchscreens" 495 tristate "iNexio serial touchscreens"
484 select SERIO 496 select SERIO
@@ -1040,4 +1052,16 @@ config TOUCHSCREEN_ZFORCE
1040 To compile this driver as a module, choose M here: the 1052 To compile this driver as a module, choose M here: the
1041 module will be called zforce_ts. 1053 module will be called zforce_ts.
1042 1054
1055config TOUCHSCREEN_COLIBRI_VF50
1056 tristate "Toradex Colibri on board touchscreen driver"
1057 depends on GPIOLIB && IIO && VF610_ADC
1058 help
1059 Say Y here if you have a Colibri VF50 and plan to use
1060 the on-board provided 4-wire touchscreen driver.
1061
1062 If unsure, say N.
1063
1064 To compile this driver as a module, choose M here: the
1065 module will be called colibri_vf50_ts.
1066
1043endif 1067endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index c85aae23e7f8..1b79cc09744a 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
38obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o 38obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
39obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o 39obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
40obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o 40obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
41obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o
41obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o 42obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
42obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o 43obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
43obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o 44obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o
@@ -85,3 +86,4 @@ obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
85obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o 86obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o
86obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o 87obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
87obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o 88obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
89obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
diff --git a/drivers/input/touchscreen/colibri-vf50-ts.c b/drivers/input/touchscreen/colibri-vf50-ts.c
new file mode 100644
index 000000000000..5d4903a402cc
--- /dev/null
+++ b/drivers/input/touchscreen/colibri-vf50-ts.c
@@ -0,0 +1,386 @@
1/*
2 * Toradex Colibri VF50 Touchscreen driver
3 *
4 * Copyright 2015 Toradex AG
5 *
6 * Originally authored by Stefan Agner for 3.0 kernel
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/gpio.h>
17#include <linux/gpio/consumer.h>
18#include <linux/iio/consumer.h>
19#include <linux/iio/types.h>
20#include <linux/input.h>
21#include <linux/interrupt.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/pinctrl/consumer.h>
25#include <linux/platform_device.h>
26#include <linux/slab.h>
27#include <linux/types.h>
28
29#define DRIVER_NAME "colibri-vf50-ts"
30#define DRV_VERSION "1.0"
31
32#define VF_ADC_MAX ((1 << 12) - 1)
33
34#define COLI_TOUCH_MIN_DELAY_US 1000
35#define COLI_TOUCH_MAX_DELAY_US 2000
36#define COLI_PULLUP_MIN_DELAY_US 10000
37#define COLI_PULLUP_MAX_DELAY_US 11000
38#define COLI_TOUCH_NO_OF_AVGS 5
39#define COLI_TOUCH_REQ_ADC_CHAN 4
40
41struct vf50_touch_device {
42 struct platform_device *pdev;
43 struct input_dev *ts_input;
44 struct iio_channel *channels;
45 struct gpio_desc *gpio_xp;
46 struct gpio_desc *gpio_xm;
47 struct gpio_desc *gpio_yp;
48 struct gpio_desc *gpio_ym;
49 int pen_irq;
50 int min_pressure;
51 bool stop_touchscreen;
52};
53
54/*
55 * Enables given plates and measures touch parameters using ADC
56 */
57static int adc_ts_measure(struct iio_channel *channel,
58 struct gpio_desc *plate_p, struct gpio_desc *plate_m)
59{
60 int i, value = 0, val = 0;
61 int error;
62
63 gpiod_set_value(plate_p, 1);
64 gpiod_set_value(plate_m, 1);
65
66 usleep_range(COLI_TOUCH_MIN_DELAY_US, COLI_TOUCH_MAX_DELAY_US);
67
68 for (i = 0; i < COLI_TOUCH_NO_OF_AVGS; i++) {
69 error = iio_read_channel_raw(channel, &val);
70 if (error < 0) {
71 value = error;
72 goto error_iio_read;
73 }
74
75 value += val;
76 }
77
78 value /= COLI_TOUCH_NO_OF_AVGS;
79
80error_iio_read:
81 gpiod_set_value(plate_p, 0);
82 gpiod_set_value(plate_m, 0);
83
84 return value;
85}
86
87/*
88 * Enable touch detection using falling edge detection on XM
89 */
90static void vf50_ts_enable_touch_detection(struct vf50_touch_device *vf50_ts)
91{
92 /* Enable plate YM (needs to be strong GND, high active) */
93 gpiod_set_value(vf50_ts->gpio_ym, 1);
94
95 /*
96 * Let the platform mux to idle state in order to enable
97 * Pull-Up on GPIO
98 */
99 pinctrl_pm_select_idle_state(&vf50_ts->pdev->dev);
100
101 /* Wait for the pull-up to be stable on high */
102 usleep_range(COLI_PULLUP_MIN_DELAY_US, COLI_PULLUP_MAX_DELAY_US);
103}
104
105/*
106 * ADC touch screen sampling bottom half irq handler
107 */
108static irqreturn_t vf50_ts_irq_bh(int irq, void *private)
109{
110 struct vf50_touch_device *vf50_ts = private;
111 struct device *dev = &vf50_ts->pdev->dev;
112 int val_x, val_y, val_z1, val_z2, val_p = 0;
113 bool discard_val_on_start = true;
114
115 /* Disable the touch detection plates */
116 gpiod_set_value(vf50_ts->gpio_ym, 0);
117
118 /* Let the platform mux to default state in order to mux as ADC */
119 pinctrl_pm_select_default_state(dev);
120
121 while (!vf50_ts->stop_touchscreen) {
122 /* X-Direction */
123 val_x = adc_ts_measure(&vf50_ts->channels[0],
124 vf50_ts->gpio_xp, vf50_ts->gpio_xm);
125 if (val_x < 0)
126 break;
127
128 /* Y-Direction */
129 val_y = adc_ts_measure(&vf50_ts->channels[1],
130 vf50_ts->gpio_yp, vf50_ts->gpio_ym);
131 if (val_y < 0)
132 break;
133
134 /*
135 * Touch pressure
136 * Measure on XP/YM
137 */
138 val_z1 = adc_ts_measure(&vf50_ts->channels[2],
139 vf50_ts->gpio_yp, vf50_ts->gpio_xm);
140 if (val_z1 < 0)
141 break;
142 val_z2 = adc_ts_measure(&vf50_ts->channels[3],
143 vf50_ts->gpio_yp, vf50_ts->gpio_xm);
144 if (val_z2 < 0)
145 break;
146
147 /* Validate signal (avoid calculation using noise) */
148 if (val_z1 > 64 && val_x > 64) {
149 /*
150 * Calculate resistance between the plates
151 * lower resistance means higher pressure
152 */
153 int r_x = (1000 * val_x) / VF_ADC_MAX;
154
155 val_p = (r_x * val_z2) / val_z1 - r_x;
156
157 } else {
158 val_p = 2000;
159 }
160
161 val_p = 2000 - val_p;
162 dev_dbg(dev,
163 "Measured values: x: %d, y: %d, z1: %d, z2: %d, p: %d\n",
164 val_x, val_y, val_z1, val_z2, val_p);
165
166 /*
167 * If touch pressure is too low, stop measuring and reenable
168 * touch detection
169 */
170 if (val_p < vf50_ts->min_pressure || val_p > 2000)
171 break;
172
173 /*
174 * The pressure may not be enough for the first x and the
175 * second y measurement, but, the pressure is ok when the
176 * driver is doing the third and fourth measurement. To
177 * take care of this, we drop the first measurement always.
178 */
179 if (discard_val_on_start) {
180 discard_val_on_start = false;
181 } else {
182 /*
183 * Report touch position and sleep for
184 * the next measurement.
185 */
186 input_report_abs(vf50_ts->ts_input,
187 ABS_X, VF_ADC_MAX - val_x);
188 input_report_abs(vf50_ts->ts_input,
189 ABS_Y, VF_ADC_MAX - val_y);
190 input_report_abs(vf50_ts->ts_input,
191 ABS_PRESSURE, val_p);
192 input_report_key(vf50_ts->ts_input, BTN_TOUCH, 1);
193 input_sync(vf50_ts->ts_input);
194 }
195
196 usleep_range(COLI_PULLUP_MIN_DELAY_US,
197 COLI_PULLUP_MAX_DELAY_US);
198 }
199
200 /* Report no more touch, re-enable touch detection */
201 input_report_abs(vf50_ts->ts_input, ABS_PRESSURE, 0);
202 input_report_key(vf50_ts->ts_input, BTN_TOUCH, 0);
203 input_sync(vf50_ts->ts_input);
204
205 vf50_ts_enable_touch_detection(vf50_ts);
206
207 return IRQ_HANDLED;
208}
209
210static int vf50_ts_open(struct input_dev *dev_input)
211{
212 struct vf50_touch_device *touchdev = input_get_drvdata(dev_input);
213 struct device *dev = &touchdev->pdev->dev;
214
215 dev_dbg(dev, "Input device %s opened, starting touch detection\n",
216 dev_input->name);
217
218 touchdev->stop_touchscreen = false;
219
220 /* Mux detection before request IRQ, wait for pull-up to settle */
221 vf50_ts_enable_touch_detection(touchdev);
222
223 return 0;
224}
225
226static void vf50_ts_close(struct input_dev *dev_input)
227{
228 struct vf50_touch_device *touchdev = input_get_drvdata(dev_input);
229 struct device *dev = &touchdev->pdev->dev;
230
231 touchdev->stop_touchscreen = true;
232
233 /* Make sure IRQ is not running past close */
234 mb();
235 synchronize_irq(touchdev->pen_irq);
236
237 gpiod_set_value(touchdev->gpio_ym, 0);
238 pinctrl_pm_select_default_state(dev);
239
240 dev_dbg(dev, "Input device %s closed, disable touch detection\n",
241 dev_input->name);
242}
243
244static int vf50_ts_get_gpiod(struct device *dev, struct gpio_desc **gpio_d,
245 const char *con_id, enum gpiod_flags flags)
246{
247 int error;
248
249 *gpio_d = devm_gpiod_get(dev, con_id, flags);
250 if (IS_ERR(*gpio_d)) {
251 error = PTR_ERR(*gpio_d);
252 dev_err(dev, "Could not get gpio_%s %d\n", con_id, error);
253 return error;
254 }
255
256 return 0;
257}
258
259static void vf50_ts_channel_release(void *data)
260{
261 struct iio_channel *channels = data;
262
263 iio_channel_release_all(channels);
264}
265
266static int vf50_ts_probe(struct platform_device *pdev)
267{
268 struct input_dev *input;
269 struct iio_channel *channels;
270 struct device *dev = &pdev->dev;
271 struct vf50_touch_device *touchdev;
272 int num_adc_channels;
273 int error;
274
275 channels = iio_channel_get_all(dev);
276 if (IS_ERR(channels))
277 return PTR_ERR(channels);
278
279 error = devm_add_action(dev, vf50_ts_channel_release, channels);
280 if (error) {
281 iio_channel_release_all(channels);
282 dev_err(dev, "Failed to register iio channel release action");
283 return error;
284 }
285
286 num_adc_channels = 0;
287 while (channels[num_adc_channels].indio_dev)
288 num_adc_channels++;
289
290 if (num_adc_channels != COLI_TOUCH_REQ_ADC_CHAN) {
291 dev_err(dev, "Inadequate ADC channels specified\n");
292 return -EINVAL;
293 }
294
295 touchdev = devm_kzalloc(dev, sizeof(*touchdev), GFP_KERNEL);
296 if (!touchdev)
297 return -ENOMEM;
298
299 touchdev->pdev = pdev;
300 touchdev->channels = channels;
301
302 error = of_property_read_u32(dev->of_node, "vf50-ts-min-pressure",
303 &touchdev->min_pressure);
304 if (error)
305 return error;
306
307 input = devm_input_allocate_device(dev);
308 if (!input) {
309 dev_err(dev, "Failed to allocate TS input device\n");
310 return -ENOMEM;
311 }
312
313 platform_set_drvdata(pdev, touchdev);
314
315 input->name = DRIVER_NAME;
316 input->id.bustype = BUS_HOST;
317 input->dev.parent = dev;
318 input->open = vf50_ts_open;
319 input->close = vf50_ts_close;
320
321 input_set_capability(input, EV_KEY, BTN_TOUCH);
322 input_set_abs_params(input, ABS_X, 0, VF_ADC_MAX, 0, 0);
323 input_set_abs_params(input, ABS_Y, 0, VF_ADC_MAX, 0, 0);
324 input_set_abs_params(input, ABS_PRESSURE, 0, VF_ADC_MAX, 0, 0);
325
326 touchdev->ts_input = input;
327 input_set_drvdata(input, touchdev);
328
329 error = input_register_device(input);
330 if (error) {
331 dev_err(dev, "Failed to register input device\n");
332 return error;
333 }
334
335 error = vf50_ts_get_gpiod(dev, &touchdev->gpio_xp, "xp", GPIOD_OUT_LOW);
336 if (error)
337 return error;
338
339 error = vf50_ts_get_gpiod(dev, &touchdev->gpio_xm,
340 "xm", GPIOD_OUT_LOW);
341 if (error)
342 return error;
343
344 error = vf50_ts_get_gpiod(dev, &touchdev->gpio_yp, "yp", GPIOD_OUT_LOW);
345 if (error)
346 return error;
347
348 error = vf50_ts_get_gpiod(dev, &touchdev->gpio_ym, "ym", GPIOD_OUT_LOW);
349 if (error)
350 return error;
351
352 touchdev->pen_irq = platform_get_irq(pdev, 0);
353 if (touchdev->pen_irq < 0)
354 return touchdev->pen_irq;
355
356 error = devm_request_threaded_irq(dev, touchdev->pen_irq,
357 NULL, vf50_ts_irq_bh, IRQF_ONESHOT,
358 "vf50 touch", touchdev);
359 if (error) {
360 dev_err(dev, "Failed to request IRQ %d: %d\n",
361 touchdev->pen_irq, error);
362 return error;
363 }
364
365 return 0;
366}
367
368static const struct of_device_id vf50_touch_of_match[] = {
369 { .compatible = "toradex,vf50-touchscreen", },
370 { }
371};
372MODULE_DEVICE_TABLE(of, vf50_touch_of_match);
373
374static struct platform_driver vf50_touch_driver = {
375 .driver = {
376 .name = "toradex,vf50_touchctrl",
377 .of_match_table = vf50_touch_of_match,
378 },
379 .probe = vf50_ts_probe,
380};
381module_platform_driver(vf50_touch_driver);
382
383MODULE_AUTHOR("Sanchayan Maity");
384MODULE_DESCRIPTION("Colibri VF50 Touchscreen driver");
385MODULE_LICENSE("GPL");
386MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c
index 9a323dd915de..a9f95c7d3c00 100644
--- a/drivers/input/touchscreen/cyttsp4_i2c.c
+++ b/drivers/input/touchscreen/cyttsp4_i2c.c
@@ -86,4 +86,3 @@ module_i2c_driver(cyttsp4_i2c_driver);
86MODULE_LICENSE("GPL"); 86MODULE_LICENSE("GPL");
87MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); 87MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
88MODULE_AUTHOR("Cypress"); 88MODULE_AUTHOR("Cypress");
89MODULE_ALIAS("i2c:cyttsp4");
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
index 519e2de2f8df..eee51b3f2e3f 100644
--- a/drivers/input/touchscreen/cyttsp_i2c.c
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -86,4 +86,3 @@ module_i2c_driver(cyttsp_i2c_driver);
86MODULE_LICENSE("GPL"); 86MODULE_LICENSE("GPL");
87MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); 87MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
88MODULE_AUTHOR("Cypress"); 88MODULE_AUTHOR("Cypress");
89MODULE_ALIAS("i2c:cyttsp");
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index ddac134b25b1..17cc20ef4923 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -102,7 +102,7 @@
102#define ELAN_FW_PAGESIZE 132 102#define ELAN_FW_PAGESIZE 132
103 103
104/* calibration timeout definition */ 104/* calibration timeout definition */
105#define ELAN_CALI_TIMEOUT_MSEC 10000 105#define ELAN_CALI_TIMEOUT_MSEC 12000
106 106
107#define ELAN_POWERON_DELAY_USEC 500 107#define ELAN_POWERON_DELAY_USEC 500
108#define ELAN_RESET_DELAY_MSEC 20 108#define ELAN_RESET_DELAY_MSEC 20
diff --git a/drivers/input/touchscreen/imx6ul_tsc.c b/drivers/input/touchscreen/imx6ul_tsc.c
new file mode 100644
index 000000000000..ff0b75813daa
--- /dev/null
+++ b/drivers/input/touchscreen/imx6ul_tsc.c
@@ -0,0 +1,523 @@
1/*
2 * Freescale i.MX6UL touchscreen controller driver
3 *
4 * Copyright (C) 2015 Freescale Semiconductor, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/errno.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/gpio/consumer.h>
15#include <linux/input.h>
16#include <linux/slab.h>
17#include <linux/completion.h>
18#include <linux/delay.h>
19#include <linux/of.h>
20#include <linux/interrupt.h>
21#include <linux/platform_device.h>
22#include <linux/clk.h>
23#include <linux/io.h>
24
25/* ADC configuration registers field define */
26#define ADC_AIEN (0x1 << 7)
27#define ADC_CONV_DISABLE 0x1F
28#define ADC_CAL (0x1 << 7)
29#define ADC_CALF 0x2
30#define ADC_12BIT_MODE (0x2 << 2)
31#define ADC_IPG_CLK 0x00
32#define ADC_CLK_DIV_8 (0x03 << 5)
33#define ADC_SHORT_SAMPLE_MODE (0x0 << 4)
34#define ADC_HARDWARE_TRIGGER (0x1 << 13)
35#define SELECT_CHANNEL_4 0x04
36#define SELECT_CHANNEL_1 0x01
37#define DISABLE_CONVERSION_INT (0x0 << 7)
38
39/* ADC registers */
40#define REG_ADC_HC0 0x00
41#define REG_ADC_HC1 0x04
42#define REG_ADC_HC2 0x08
43#define REG_ADC_HC3 0x0C
44#define REG_ADC_HC4 0x10
45#define REG_ADC_HS 0x14
46#define REG_ADC_R0 0x18
47#define REG_ADC_CFG 0x2C
48#define REG_ADC_GC 0x30
49#define REG_ADC_GS 0x34
50
51#define ADC_TIMEOUT msecs_to_jiffies(100)
52
53/* TSC registers */
54#define REG_TSC_BASIC_SETING 0x00
55#define REG_TSC_PRE_CHARGE_TIME 0x10
56#define REG_TSC_FLOW_CONTROL 0x20
57#define REG_TSC_MEASURE_VALUE 0x30
58#define REG_TSC_INT_EN 0x40
59#define REG_TSC_INT_SIG_EN 0x50
60#define REG_TSC_INT_STATUS 0x60
61#define REG_TSC_DEBUG_MODE 0x70
62#define REG_TSC_DEBUG_MODE2 0x80
63
64/* TSC configuration registers field define */
65#define DETECT_4_WIRE_MODE (0x0 << 4)
66#define AUTO_MEASURE 0x1
67#define MEASURE_SIGNAL 0x1
68#define DETECT_SIGNAL (0x1 << 4)
69#define VALID_SIGNAL (0x1 << 8)
70#define MEASURE_INT_EN 0x1
71#define MEASURE_SIG_EN 0x1
72#define VALID_SIG_EN (0x1 << 8)
73#define DE_GLITCH_2 (0x2 << 29)
74#define START_SENSE (0x1 << 12)
75#define TSC_DISABLE (0x1 << 16)
76#define DETECT_MODE 0x2
77
78struct imx6ul_tsc {
79 struct device *dev;
80 struct input_dev *input;
81 void __iomem *tsc_regs;
82 void __iomem *adc_regs;
83 struct clk *tsc_clk;
84 struct clk *adc_clk;
85 struct gpio_desc *xnur_gpio;
86
87 int measure_delay_time;
88 int pre_charge_time;
89
90 struct completion completion;
91};
92
93/*
94 * TSC module need ADC to get the measure value. So
95 * before config TSC, we should initialize ADC module.
96 */
97static void imx6ul_adc_init(struct imx6ul_tsc *tsc)
98{
99 int adc_hc = 0;
100 int adc_gc;
101 int adc_gs;
102 int adc_cfg;
103 int timeout;
104
105 reinit_completion(&tsc->completion);
106
107 adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
108 adc_cfg |= ADC_12BIT_MODE | ADC_IPG_CLK;
109 adc_cfg |= ADC_CLK_DIV_8 | ADC_SHORT_SAMPLE_MODE;
110 adc_cfg &= ~ADC_HARDWARE_TRIGGER;
111 writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
112
113 /* enable calibration interrupt */
114 adc_hc |= ADC_AIEN;
115 adc_hc |= ADC_CONV_DISABLE;
116 writel(adc_hc, tsc->adc_regs + REG_ADC_HC0);
117
118 /* start ADC calibration */
119 adc_gc = readl(tsc->adc_regs + REG_ADC_GC);
120 adc_gc |= ADC_CAL;
121 writel(adc_gc, tsc->adc_regs + REG_ADC_GC);
122
123 timeout = wait_for_completion_timeout
124 (&tsc->completion, ADC_TIMEOUT);
125 if (timeout == 0)
126 dev_err(tsc->dev, "Timeout for adc calibration\n");
127
128 adc_gs = readl(tsc->adc_regs + REG_ADC_GS);
129 if (adc_gs & ADC_CALF)
130 dev_err(tsc->dev, "ADC calibration failed\n");
131
132 /* TSC need the ADC work in hardware trigger */
133 adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
134 adc_cfg |= ADC_HARDWARE_TRIGGER;
135 writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
136}
137
138/*
139 * This is a TSC workaround. Currently TSC misconnect two
140 * ADC channels, this function remap channel configure for
141 * hardware trigger.
142 */
143static void imx6ul_tsc_channel_config(struct imx6ul_tsc *tsc)
144{
145 int adc_hc0, adc_hc1, adc_hc2, adc_hc3, adc_hc4;
146
147 adc_hc0 = DISABLE_CONVERSION_INT;
148 writel(adc_hc0, tsc->adc_regs + REG_ADC_HC0);
149
150 adc_hc1 = DISABLE_CONVERSION_INT | SELECT_CHANNEL_4;
151 writel(adc_hc1, tsc->adc_regs + REG_ADC_HC1);
152
153 adc_hc2 = DISABLE_CONVERSION_INT;
154 writel(adc_hc2, tsc->adc_regs + REG_ADC_HC2);
155
156 adc_hc3 = DISABLE_CONVERSION_INT | SELECT_CHANNEL_1;
157 writel(adc_hc3, tsc->adc_regs + REG_ADC_HC3);
158
159 adc_hc4 = DISABLE_CONVERSION_INT;
160 writel(adc_hc4, tsc->adc_regs + REG_ADC_HC4);
161}
162
163/*
164 * TSC setting, confige the pre-charge time and measure delay time.
165 * different touch screen may need different pre-charge time and
166 * measure delay time.
167 */
168static void imx6ul_tsc_set(struct imx6ul_tsc *tsc)
169{
170 int basic_setting = 0;
171 int start;
172
173 basic_setting |= tsc->measure_delay_time << 8;
174 basic_setting |= DETECT_4_WIRE_MODE | AUTO_MEASURE;
175 writel(basic_setting, tsc->tsc_regs + REG_TSC_BASIC_SETING);
176
177 writel(DE_GLITCH_2, tsc->tsc_regs + REG_TSC_DEBUG_MODE2);
178
179 writel(tsc->pre_charge_time, tsc->tsc_regs + REG_TSC_PRE_CHARGE_TIME);
180 writel(MEASURE_INT_EN, tsc->tsc_regs + REG_TSC_INT_EN);
181 writel(MEASURE_SIG_EN | VALID_SIG_EN,
182 tsc->tsc_regs + REG_TSC_INT_SIG_EN);
183
184 /* start sense detection */
185 start = readl(tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
186 start |= START_SENSE;
187 start &= ~TSC_DISABLE;
188 writel(start, tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
189}
190
191static void imx6ul_tsc_init(struct imx6ul_tsc *tsc)
192{
193 imx6ul_adc_init(tsc);
194 imx6ul_tsc_channel_config(tsc);
195 imx6ul_tsc_set(tsc);
196}
197
198static void imx6ul_tsc_disable(struct imx6ul_tsc *tsc)
199{
200 int tsc_flow;
201 int adc_cfg;
202
203 /* TSC controller enters to idle status */
204 tsc_flow = readl(tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
205 tsc_flow |= TSC_DISABLE;
206 writel(tsc_flow, tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
207
208 /* ADC controller enters to stop mode */
209 adc_cfg = readl(tsc->adc_regs + REG_ADC_HC0);
210 adc_cfg |= ADC_CONV_DISABLE;
211 writel(adc_cfg, tsc->adc_regs + REG_ADC_HC0);
212}
213
214/* Delay some time (max 2ms), wait the pre-charge done. */
215static bool tsc_wait_detect_mode(struct imx6ul_tsc *tsc)
216{
217 unsigned long timeout = jiffies + msecs_to_jiffies(2);
218 int state_machine;
219 int debug_mode2;
220
221 do {
222 if (time_after(jiffies, timeout))
223 return false;
224
225 usleep_range(200, 400);
226 debug_mode2 = readl(tsc->tsc_regs + REG_TSC_DEBUG_MODE2);
227 state_machine = (debug_mode2 >> 20) & 0x7;
228 } while (state_machine != DETECT_MODE);
229
230 usleep_range(200, 400);
231 return true;
232}
233
234static irqreturn_t tsc_irq_fn(int irq, void *dev_id)
235{
236 struct imx6ul_tsc *tsc = dev_id;
237 int status;
238 int value;
239 int x, y;
240 int start;
241
242 status = readl(tsc->tsc_regs + REG_TSC_INT_STATUS);
243
244 /* write 1 to clear the bit measure-signal */
245 writel(MEASURE_SIGNAL | DETECT_SIGNAL,
246 tsc->tsc_regs + REG_TSC_INT_STATUS);
247
248 /* It's a HW self-clean bit. Set this bit and start sense detection */
249 start = readl(tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
250 start |= START_SENSE;
251 writel(start, tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
252
253 if (status & MEASURE_SIGNAL) {
254 value = readl(tsc->tsc_regs + REG_TSC_MEASURE_VALUE);
255 x = (value >> 16) & 0x0fff;
256 y = value & 0x0fff;
257
258 /*
259 * In detect mode, we can get the xnur gpio value,
260 * otherwise assume contact is stiull active.
261 */
262 if (!tsc_wait_detect_mode(tsc) ||
263 gpiod_get_value_cansleep(tsc->xnur_gpio)) {
264 input_report_key(tsc->input, BTN_TOUCH, 1);
265 input_report_abs(tsc->input, ABS_X, x);
266 input_report_abs(tsc->input, ABS_Y, y);
267 } else {
268 input_report_key(tsc->input, BTN_TOUCH, 0);
269 }
270
271 input_sync(tsc->input);
272 }
273
274 return IRQ_HANDLED;
275}
276
277static irqreturn_t adc_irq_fn(int irq, void *dev_id)
278{
279 struct imx6ul_tsc *tsc = dev_id;
280 int coco;
281 int value;
282
283 coco = readl(tsc->adc_regs + REG_ADC_HS);
284 if (coco & 0x01) {
285 value = readl(tsc->adc_regs + REG_ADC_R0);
286 complete(&tsc->completion);
287 }
288
289 return IRQ_HANDLED;
290}
291
292static int imx6ul_tsc_open(struct input_dev *input_dev)
293{
294 struct imx6ul_tsc *tsc = input_get_drvdata(input_dev);
295 int err;
296
297 err = clk_prepare_enable(tsc->adc_clk);
298 if (err) {
299 dev_err(tsc->dev,
300 "Could not prepare or enable the adc clock: %d\n",
301 err);
302 return err;
303 }
304
305 err = clk_prepare_enable(tsc->tsc_clk);
306 if (err) {
307 dev_err(tsc->dev,
308 "Could not prepare or enable the tsc clock: %d\n",
309 err);
310 clk_disable_unprepare(tsc->adc_clk);
311 return err;
312 }
313
314 imx6ul_tsc_init(tsc);
315
316 return 0;
317}
318
319static void imx6ul_tsc_close(struct input_dev *input_dev)
320{
321 struct imx6ul_tsc *tsc = input_get_drvdata(input_dev);
322
323 imx6ul_tsc_disable(tsc);
324
325 clk_disable_unprepare(tsc->tsc_clk);
326 clk_disable_unprepare(tsc->adc_clk);
327}
328
329static int imx6ul_tsc_probe(struct platform_device *pdev)
330{
331 struct device_node *np = pdev->dev.of_node;
332 struct imx6ul_tsc *tsc;
333 struct input_dev *input_dev;
334 struct resource *tsc_mem;
335 struct resource *adc_mem;
336 int err;
337 int tsc_irq;
338 int adc_irq;
339
340 tsc = devm_kzalloc(&pdev->dev, sizeof(struct imx6ul_tsc), GFP_KERNEL);
341 if (!tsc)
342 return -ENOMEM;
343
344 input_dev = devm_input_allocate_device(&pdev->dev);
345 if (!input_dev)
346 return -ENOMEM;
347
348 input_dev->name = "iMX6UL TouchScreen Controller";
349 input_dev->id.bustype = BUS_HOST;
350
351 input_dev->open = imx6ul_tsc_open;
352 input_dev->close = imx6ul_tsc_close;
353
354 input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
355 input_set_abs_params(input_dev, ABS_X, 0, 0xFFF, 0, 0);
356 input_set_abs_params(input_dev, ABS_Y, 0, 0xFFF, 0, 0);
357
358 input_set_drvdata(input_dev, tsc);
359
360 tsc->dev = &pdev->dev;
361 tsc->input = input_dev;
362 init_completion(&tsc->completion);
363
364 tsc->xnur_gpio = devm_gpiod_get(&pdev->dev, "xnur", GPIOD_IN);
365 if (IS_ERR(tsc->xnur_gpio)) {
366 err = PTR_ERR(tsc->xnur_gpio);
367 dev_err(&pdev->dev,
368 "failed to request GPIO tsc_X- (xnur): %d\n", err);
369 return err;
370 }
371
372 tsc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
373 tsc->tsc_regs = devm_ioremap_resource(&pdev->dev, tsc_mem);
374 if (IS_ERR(tsc->tsc_regs)) {
375 err = PTR_ERR(tsc->tsc_regs);
376 dev_err(&pdev->dev, "failed to remap tsc memory: %d\n", err);
377 return err;
378 }
379
380 adc_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
381 tsc->adc_regs = devm_ioremap_resource(&pdev->dev, adc_mem);
382 if (IS_ERR(tsc->adc_regs)) {
383 err = PTR_ERR(tsc->adc_regs);
384 dev_err(&pdev->dev, "failed to remap adc memory: %d\n", err);
385 return err;
386 }
387
388 tsc->tsc_clk = devm_clk_get(&pdev->dev, "tsc");
389 if (IS_ERR(tsc->tsc_clk)) {
390 err = PTR_ERR(tsc->tsc_clk);
391 dev_err(&pdev->dev, "failed getting tsc clock: %d\n", err);
392 return err;
393 }
394
395 tsc->adc_clk = devm_clk_get(&pdev->dev, "adc");
396 if (IS_ERR(tsc->adc_clk)) {
397 err = PTR_ERR(tsc->adc_clk);
398 dev_err(&pdev->dev, "failed getting adc clock: %d\n", err);
399 return err;
400 }
401
402 tsc_irq = platform_get_irq(pdev, 0);
403 if (tsc_irq < 0) {
404 dev_err(&pdev->dev, "no tsc irq resource?\n");
405 return tsc_irq;
406 }
407
408 adc_irq = platform_get_irq(pdev, 1);
409 if (adc_irq <= 0) {
410 dev_err(&pdev->dev, "no adc irq resource?\n");
411 return adc_irq;
412 }
413
414 err = devm_request_threaded_irq(tsc->dev, tsc_irq,
415 NULL, tsc_irq_fn, IRQF_ONESHOT,
416 dev_name(&pdev->dev), tsc);
417 if (err) {
418 dev_err(&pdev->dev,
419 "failed requesting tsc irq %d: %d\n",
420 tsc_irq, err);
421 return err;
422 }
423
424 err = devm_request_irq(tsc->dev, adc_irq, adc_irq_fn, 0,
425 dev_name(&pdev->dev), tsc);
426 if (err) {
427 dev_err(&pdev->dev,
428 "failed requesting adc irq %d: %d\n",
429 adc_irq, err);
430 return err;
431 }
432
433 err = of_property_read_u32(np, "measure-delay-time",
434 &tsc->measure_delay_time);
435 if (err)
436 tsc->measure_delay_time = 0xffff;
437
438 err = of_property_read_u32(np, "pre-charge-time",
439 &tsc->pre_charge_time);
440 if (err)
441 tsc->pre_charge_time = 0xfff;
442
443 err = input_register_device(tsc->input);
444 if (err) {
445 dev_err(&pdev->dev,
446 "failed to register input device: %d\n", err);
447 return err;
448 }
449
450 platform_set_drvdata(pdev, tsc);
451 return 0;
452}
453
454static int __maybe_unused imx6ul_tsc_suspend(struct device *dev)
455{
456 struct platform_device *pdev = to_platform_device(dev);
457 struct imx6ul_tsc *tsc = platform_get_drvdata(pdev);
458 struct input_dev *input_dev = tsc->input;
459
460 mutex_lock(&input_dev->mutex);
461
462 if (input_dev->users) {
463 imx6ul_tsc_disable(tsc);
464
465 clk_disable_unprepare(tsc->tsc_clk);
466 clk_disable_unprepare(tsc->adc_clk);
467 }
468
469 mutex_unlock(&input_dev->mutex);
470
471 return 0;
472}
473
474static int __maybe_unused imx6ul_tsc_resume(struct device *dev)
475{
476 struct platform_device *pdev = to_platform_device(dev);
477 struct imx6ul_tsc *tsc = platform_get_drvdata(pdev);
478 struct input_dev *input_dev = tsc->input;
479 int retval = 0;
480
481 mutex_lock(&input_dev->mutex);
482
483 if (input_dev->users) {
484 retval = clk_prepare_enable(tsc->adc_clk);
485 if (retval)
486 goto out;
487
488 retval = clk_prepare_enable(tsc->tsc_clk);
489 if (retval) {
490 clk_disable_unprepare(tsc->adc_clk);
491 goto out;
492 }
493
494 imx6ul_tsc_init(tsc);
495 }
496
497out:
498 mutex_unlock(&input_dev->mutex);
499 return retval;
500}
501
502static SIMPLE_DEV_PM_OPS(imx6ul_tsc_pm_ops,
503 imx6ul_tsc_suspend, imx6ul_tsc_resume);
504
505static const struct of_device_id imx6ul_tsc_match[] = {
506 { .compatible = "fsl,imx6ul-tsc", },
507 { /* sentinel */ }
508};
509MODULE_DEVICE_TABLE(of, imx6ul_tsc_match);
510
511static struct platform_driver imx6ul_tsc_driver = {
512 .driver = {
513 .name = "imx6ul-tsc",
514 .of_match_table = imx6ul_tsc_match,
515 .pm = &imx6ul_tsc_pm_ops,
516 },
517 .probe = imx6ul_tsc_probe,
518};
519module_platform_driver(imx6ul_tsc_driver);
520
521MODULE_AUTHOR("Haibo Chen <haibo.chen@freescale.com>");
522MODULE_DESCRIPTION("Freescale i.MX6UL Touchscreen controller driver");
523MODULE_LICENSE("GPL v2");