aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2015-09-11 12:02:36 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2015-09-11 12:02:36 -0400
commit53431d0a3534263168c8ee576bad1c2c3a4cd9e0 (patch)
tree84b3dda2e2409d1eda7c2273053c78cd6aa3a677
parent01b944fe1cd4e21a2a9ed51adbdbafe2d5e905ba (diff)
parentade9c1a47c811a7ae1c874882ad9178af1ed1098 (diff)
Merge branch 'next' into for-linus
Prepare second round of input updates for 4.3 merge window.
-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");