aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Richardson <jonathar@broadcom.com>2015-03-22 00:04:59 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2015-03-23 14:04:48 -0400
commitd5ae685f15307c85c6267c5a2be9ba3d70eb3297 (patch)
tree416649cd967241045d14bab40121ad9d7e51a5c8
parent188933ac139a6f8ab06cad369bd0200af947b00d (diff)
Input: add Broadcom iProc touchscreen driver
Add initial version of the Broadcom touchscreen driver. Reviewed-by: Ray Jui <rjui@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com> Tested-by: Scott Branden <sbranden@broadcom.com> Signed-off-by: Jonathan Richardson <jonathar@broadcom.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt76
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/bcm_iproc_tsc.c522
4 files changed, 611 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt b/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt
new file mode 100644
index 000000000000..34e3382a0659
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt
@@ -0,0 +1,76 @@
1* Broadcom's IPROC Touchscreen Controller
2
3Required properties:
4- compatible: must be "brcm,iproc-touchscreen"
5- reg: physical base address of the controller and length of memory mapped
6 region.
7- clocks: The clock provided by the SOC to driver the tsc
8- clock-name: name for the clock
9- interrupts: The touchscreen controller's interrupt
10
11Optional properties:
12- scanning_period: Time between scans. Each step is 1024 us. Valid 1-256.
13- debounce_timeout: Each step is 512 us. Valid 0-255
14- settling_timeout: The settling duration (in ms) is the amount of time
15 the tsc waits to allow the voltage to settle after
16 turning on the drivers in detection mode.
17 Valid values: 0-11
18 0 = 0.008 ms
19 1 = 0.01 ms
20 2 = 0.02 ms
21 3 = 0.04 ms
22 4 = 0.08 ms
23 5 = 0.16 ms
24 6 = 0.32 ms
25 7 = 0.64 ms
26 8 = 1.28 ms
27 9 = 2.56 ms
28 10 = 5.12 ms
29 11 = 10.24 ms
30- touch_timeout: The continuous number of scan periods in which touch is
31 not detected before the controller returns to idle state.
32 Valid values 0-255.
33- average_data: Number of data samples which are averaged before a final
34 data point is placed into the FIFO
35 Valid values 0-7
36 0 = 1 sample
37 1 = 2 samples
38 2 = 4 samples
39 3 = 8 samples
40 4 = 16 samples
41 5 = 32 samples
42 6 = 64 samples
43 7 = 128 samples
44- fifo_threshold: Interrupt is generated whenever the number of fifo
45 entries exceeds this value
46 Valid values 0-31
47- touchscreen-size-x: horizontal resolution of touchscreen (in pixels)
48- touchscreen-size-y: vertical resolution of touchscreen (in pixels)
49- touchscreen-fuzz-x: horizontal noise value of the absolute input
50 device (in pixels)
51- touchscreen-fuzz-y: vertical noise value of the absolute input
52 device (in pixels)
53- touchscreen-inverted-x: X axis is inverted (boolean)
54- touchscreen-inverted-y: Y axis is inverted (boolean)
55
56Example:
57
58 touchscreen: tsc@0x180A6000 {
59 compatible = "brcm,iproc-touchscreen";
60 #address-cells = <1>;
61 #size-cells = <1>;
62 reg = <0x180A6000 0x40>;
63 clocks = <&adc_clk>;
64 clock-names = "tsc_clk";
65 interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
66
67 scanning_period = <5>;
68 debounce_timeout = <40>;
69 settling_timeout = <7>;
70 touch_timeout = <10>;
71 average_data = <5>;
72 fifo_threshold = <1>;
73 /* Touchscreen is rotated 180 degrees. */
74 touchscreen-inverted-x;
75 touchscreen-inverted-y;
76 };
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 1130c4059104..a1cfe16e9a81 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -324,6 +324,18 @@ config TOUCHSCREEN_ILI210X
324 To compile this driver as a module, choose M here: the 324 To compile this driver as a module, choose M here: the
325 module will be called ili210x. 325 module will be called ili210x.
326 326
327config TOUCHSCREEN_IPROC
328 tristate "IPROC touch panel driver support"
329 depends on ARCH_BCM_IPROC || COMPILE_TEST
330 help
331 Say Y here if you want to add support for the IPROC touch
332 controller to your system.
333
334 If unsure, say N.
335
336 To compile this driver as a module, choose M here: the
337 module will be called bcm_iproc_tsc.
338
327config TOUCHSCREEN_S3C2410 339config TOUCHSCREEN_S3C2410
328 tristate "Samsung S3C2410/generic touchscreen input driver" 340 tristate "Samsung S3C2410/generic touchscreen input driver"
329 depends on ARCH_S3C24XX || SAMSUNG_DEV_TS 341 depends on ARCH_S3C24XX || SAMSUNG_DEV_TS
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index a06a752966fe..09c33531ab8e 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
39obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o 39obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
40obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o 40obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
41obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o 41obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
42obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o
42obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o 43obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
43obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o 44obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
44obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o 45obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
diff --git a/drivers/input/touchscreen/bcm_iproc_tsc.c b/drivers/input/touchscreen/bcm_iproc_tsc.c
new file mode 100644
index 000000000000..ae460a5c93d5
--- /dev/null
+++ b/drivers/input/touchscreen/bcm_iproc_tsc.c
@@ -0,0 +1,522 @@
1/*
2* Copyright (C) 2015 Broadcom Corporation
3*
4* This program is free software; you can redistribute it and/or
5* modify it under the terms of the GNU General Public License as
6* published by the Free Software Foundation version 2.
7*
8* This program is distributed "as is" WITHOUT ANY WARRANTY of any
9* kind, whether express or implied; without even the implied warranty
10* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*/
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/input.h>
16#include <linux/delay.h>
17#include <linux/interrupt.h>
18#include <linux/keyboard.h>
19#include <linux/platform_device.h>
20#include <linux/slab.h>
21#include <linux/of.h>
22#include <asm/irq.h>
23#include <linux/io.h>
24#include <linux/clk.h>
25#include <linux/serio.h>
26
27#define IPROC_TS_NAME "iproc-ts"
28
29#define PEN_DOWN_STATUS 1
30#define PEN_UP_STATUS 0
31
32#define X_MIN 0
33#define Y_MIN 0
34#define X_MAX 0xFFF
35#define Y_MAX 0xFFF
36
37/* Value given by controller for invalid coordinate. */
38#define INVALID_COORD 0xFFFFFFFF
39
40/* Register offsets */
41#define REGCTL1 0x00
42#define REGCTL2 0x04
43#define INTERRUPT_THRES 0x08
44#define INTERRUPT_MASK 0x0c
45
46#define INTERRUPT_STATUS 0x10
47#define CONTROLLER_STATUS 0x14
48#define FIFO_DATA 0x18
49#define FIFO_DATA_X_Y_MASK 0xFFFF
50#define ANALOG_CONTROL 0x1c
51
52#define AUX_DATA 0x20
53#define DEBOUNCE_CNTR_STAT 0x24
54#define SCAN_CNTR_STAT 0x28
55#define REM_CNTR_STAT 0x2c
56
57#define SETTLING_TIMER_STAT 0x30
58#define SPARE_REG 0x34
59#define SOFT_BYPASS_CONTROL 0x38
60#define SOFT_BYPASS_DATA 0x3c
61
62
63/* Bit values for INTERRUPT_MASK and INTERRUPT_STATUS regs */
64#define TS_PEN_INTR_MASK BIT(0)
65#define TS_FIFO_INTR_MASK BIT(2)
66
67/* Bit values for CONTROLLER_STATUS reg1 */
68#define TS_PEN_DOWN BIT(0)
69
70/* Shift values for control reg1 */
71#define SCANNING_PERIOD_SHIFT 24
72#define DEBOUNCE_TIMEOUT_SHIFT 16
73#define SETTLING_TIMEOUT_SHIFT 8
74#define TOUCH_TIMEOUT_SHIFT 0
75
76/* Shift values for coordinates from fifo */
77#define X_COORD_SHIFT 0
78#define Y_COORD_SHIFT 16
79
80/* Bit values for REGCTL2 */
81#define TS_CONTROLLER_EN_BIT BIT(16)
82#define TS_CONTROLLER_AVGDATA_SHIFT 8
83#define TS_CONTROLLER_AVGDATA_MASK (0x7 << TS_CONTROLLER_AVGDATA_SHIFT)
84#define TS_CONTROLLER_PWR_LDO BIT(5)
85#define TS_CONTROLLER_PWR_ADC BIT(4)
86#define TS_CONTROLLER_PWR_BGP BIT(3)
87#define TS_CONTROLLER_PWR_TS BIT(2)
88#define TS_WIRE_MODE_BIT BIT(1)
89
90#define dbg_reg(dev, priv, reg) \
91 dev_dbg(dev, "%20s= 0x%08x\n", #reg, readl((priv)->regs + reg))
92
93struct tsc_param {
94 /* Each step is 1024 us. Valid 1-256 */
95 u32 scanning_period;
96
97 /* Each step is 512 us. Valid 0-255 */
98 u32 debounce_timeout;
99
100 /*
101 * The settling duration (in ms) is the amount of time the tsc
102 * waits to allow the voltage to settle after turning on the
103 * drivers in detection mode. Valid values: 0-11
104 * 0 = 0.008 ms
105 * 1 = 0.01 ms
106 * 2 = 0.02 ms
107 * 3 = 0.04 ms
108 * 4 = 0.08 ms
109 * 5 = 0.16 ms
110 * 6 = 0.32 ms
111 * 7 = 0.64 ms
112 * 8 = 1.28 ms
113 * 9 = 2.56 ms
114 * 10 = 5.12 ms
115 * 11 = 10.24 ms
116 */
117 u32 settling_timeout;
118
119 /* touch timeout in sample counts */
120 u32 touch_timeout;
121
122 /*
123 * Number of data samples which are averaged before a final data point
124 * is placed into the FIFO
125 */
126 u32 average_data;
127
128 /* FIFO threshold */
129 u32 fifo_threshold;
130
131 /* Optional standard touchscreen properties. */
132 u32 max_x;
133 u32 max_y;
134 u32 fuzz_x;
135 u32 fuzz_y;
136 bool invert_x;
137 bool invert_y;
138};
139
140struct iproc_ts_priv {
141 struct platform_device *pdev;
142 struct input_dev *idev;
143
144 void __iomem *regs;
145 struct clk *tsc_clk;
146
147 int pen_status;
148 struct tsc_param cfg_params;
149};
150
151/*
152 * Set default values the same as hardware reset values
153 * except for fifo_threshold with is set to 1.
154 */
155static const struct tsc_param iproc_default_config = {
156 .scanning_period = 0x5, /* 1 to 256 */
157 .debounce_timeout = 0x28, /* 0 to 255 */
158 .settling_timeout = 0x7, /* 0 to 11 */
159 .touch_timeout = 0xa, /* 0 to 255 */
160 .average_data = 5, /* entry 5 = 32 pts */
161 .fifo_threshold = 1, /* 0 to 31 */
162 .max_x = X_MAX,
163 .max_y = Y_MAX,
164};
165
166static void ts_reg_dump(struct iproc_ts_priv *priv)
167{
168 struct device *dev = &priv->pdev->dev;
169
170 dbg_reg(dev, priv, REGCTL1);
171 dbg_reg(dev, priv, REGCTL2);
172 dbg_reg(dev, priv, INTERRUPT_THRES);
173 dbg_reg(dev, priv, INTERRUPT_MASK);
174 dbg_reg(dev, priv, INTERRUPT_STATUS);
175 dbg_reg(dev, priv, CONTROLLER_STATUS);
176 dbg_reg(dev, priv, FIFO_DATA);
177 dbg_reg(dev, priv, ANALOG_CONTROL);
178 dbg_reg(dev, priv, AUX_DATA);
179 dbg_reg(dev, priv, DEBOUNCE_CNTR_STAT);
180 dbg_reg(dev, priv, SCAN_CNTR_STAT);
181 dbg_reg(dev, priv, REM_CNTR_STAT);
182 dbg_reg(dev, priv, SETTLING_TIMER_STAT);
183 dbg_reg(dev, priv, SPARE_REG);
184 dbg_reg(dev, priv, SOFT_BYPASS_CONTROL);
185 dbg_reg(dev, priv, SOFT_BYPASS_DATA);
186}
187
188static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data)
189{
190 struct platform_device *pdev = data;
191 struct iproc_ts_priv *priv = platform_get_drvdata(pdev);
192 u32 intr_status;
193 u32 raw_coordinate;
194 u16 x;
195 u16 y;
196 int i;
197 bool needs_sync = false;
198
199 intr_status = readl(priv->regs + INTERRUPT_STATUS);
200 intr_status &= TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK;
201 if (intr_status == 0)
202 return IRQ_NONE;
203
204 /* Clear all interrupt status bits, write-1-clear */
205 writel(intr_status, priv->regs + INTERRUPT_STATUS);
206
207 /* Pen up/down */
208 if (intr_status & TS_PEN_INTR_MASK) {
209 if (readl(priv->regs + CONTROLLER_STATUS) & TS_PEN_DOWN)
210 priv->pen_status = PEN_DOWN_STATUS;
211 else
212 priv->pen_status = PEN_UP_STATUS;
213
214 input_report_key(priv->idev, BTN_TOUCH, priv->pen_status);
215 needs_sync = true;
216
217 dev_dbg(&priv->pdev->dev,
218 "pen up-down (%d)\n", priv->pen_status);
219 }
220
221 /* coordinates in FIFO exceed the theshold */
222 if (intr_status & TS_FIFO_INTR_MASK) {
223 for (i = 0; i < priv->cfg_params.fifo_threshold; i++) {
224 raw_coordinate = readl(priv->regs + FIFO_DATA);
225 if (raw_coordinate == INVALID_COORD)
226 continue;
227
228 /*
229 * The x and y coordinate are 16 bits each
230 * with the x in the lower 16 bits and y in the
231 * upper 16 bits.
232 */
233 x = (raw_coordinate >> X_COORD_SHIFT) &
234 FIFO_DATA_X_Y_MASK;
235 y = (raw_coordinate >> Y_COORD_SHIFT) &
236 FIFO_DATA_X_Y_MASK;
237
238 /* We only want to retain the 12 msb of the 16 */
239 x = (x >> 4) & 0x0FFF;
240 y = (y >> 4) & 0x0FFF;
241
242 /* adjust x y according to lcd tsc mount angle */
243 if (priv->cfg_params.invert_x)
244 x = priv->cfg_params.max_x - x;
245
246 if (priv->cfg_params.invert_y)
247 y = priv->cfg_params.max_y - y;
248
249 input_report_abs(priv->idev, ABS_X, x);
250 input_report_abs(priv->idev, ABS_Y, y);
251 needs_sync = true;
252
253 dev_dbg(&priv->pdev->dev, "xy (0x%x 0x%x)\n", x, y);
254 }
255 }
256
257 if (needs_sync)
258 input_sync(priv->idev);
259
260 return IRQ_HANDLED;
261}
262
263static int iproc_ts_start(struct input_dev *idev)
264{
265 struct iproc_ts_priv *priv = input_get_drvdata(idev);
266 u32 val;
267 int error;
268
269 /* Enable clock */
270 error = clk_prepare_enable(priv->tsc_clk);
271 if (error) {
272 dev_err(&priv->pdev->dev, "%s clk_prepare_enable failed %d\n",
273 __func__, error);
274 return error;
275 }
276
277 /*
278 * Interrupt is generated when:
279 * FIFO reaches the int_th value, and pen event(up/down)
280 */
281 val = TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK;
282 writel(val, priv->regs + INTERRUPT_MASK);
283
284 writel(priv->cfg_params.fifo_threshold, priv->regs + INTERRUPT_THRES);
285
286 /* Initialize control reg1 */
287 val = 0;
288 val |= priv->cfg_params.scanning_period << SCANNING_PERIOD_SHIFT;
289 val |= priv->cfg_params.debounce_timeout << DEBOUNCE_TIMEOUT_SHIFT;
290 val |= priv->cfg_params.settling_timeout << SETTLING_TIMEOUT_SHIFT;
291 val |= priv->cfg_params.touch_timeout << TOUCH_TIMEOUT_SHIFT;
292 writel(val, priv->regs + REGCTL1);
293
294 /* Try to clear all interrupt status */
295 val = readl(priv->regs + INTERRUPT_STATUS);
296 val |= TS_FIFO_INTR_MASK | TS_PEN_INTR_MASK;
297 writel(val, priv->regs + INTERRUPT_STATUS);
298
299 /* Initialize control reg2 */
300 val = readl(priv->regs + REGCTL2);
301 val |= TS_CONTROLLER_EN_BIT | TS_WIRE_MODE_BIT;
302
303 val &= ~TS_CONTROLLER_AVGDATA_MASK;
304 val |= priv->cfg_params.average_data << TS_CONTROLLER_AVGDATA_SHIFT;
305
306 val &= ~(TS_CONTROLLER_PWR_LDO | /* PWR up LDO */
307 TS_CONTROLLER_PWR_ADC | /* PWR up ADC */
308 TS_CONTROLLER_PWR_BGP | /* PWR up BGP */
309 TS_CONTROLLER_PWR_TS); /* PWR up TS */
310
311 writel(val, priv->regs + REGCTL2);
312
313 ts_reg_dump(priv);
314
315 return 0;
316}
317
318static void iproc_ts_stop(struct input_dev *dev)
319{
320 u32 val;
321 struct iproc_ts_priv *priv = input_get_drvdata(dev);
322
323 writel(0, priv->regs + INTERRUPT_MASK); /* Disable all interrupts */
324
325 /* Only power down touch screen controller */
326 val = readl(priv->regs + REGCTL2);
327 val |= TS_CONTROLLER_PWR_TS;
328 writel(val, priv->regs + REGCTL2);
329
330 clk_disable(priv->tsc_clk);
331}
332
333static int iproc_get_tsc_config(struct device *dev, struct iproc_ts_priv *priv)
334{
335 struct device_node *np = dev->of_node;
336 u32 val;
337
338 priv->cfg_params = iproc_default_config;
339
340 if (!np)
341 return 0;
342
343 if (of_property_read_u32(np, "scanning_period", &val) >= 0) {
344 if (val < 1 || val > 256) {
345 dev_err(dev, "scanning_period (%u) must be [1-256]\n",
346 val);
347 return -EINVAL;
348 }
349 priv->cfg_params.scanning_period = val;
350 }
351
352 if (of_property_read_u32(np, "debounce_timeout", &val) >= 0) {
353 if (val > 255) {
354 dev_err(dev, "debounce_timeout (%u) must be [0-255]\n",
355 val);
356 return -EINVAL;
357 }
358 priv->cfg_params.debounce_timeout = val;
359 }
360
361 if (of_property_read_u32(np, "settling_timeout", &val) >= 0) {
362 if (val > 11) {
363 dev_err(dev, "settling_timeout (%u) must be [0-11]\n",
364 val);
365 return -EINVAL;
366 }
367 priv->cfg_params.settling_timeout = val;
368 }
369
370 if (of_property_read_u32(np, "touch_timeout", &val) >= 0) {
371 if (val > 255) {
372 dev_err(dev, "touch_timeout (%u) must be [0-255]\n",
373 val);
374 return -EINVAL;
375 }
376 priv->cfg_params.touch_timeout = val;
377 }
378
379 if (of_property_read_u32(np, "average_data", &val) >= 0) {
380 if (val > 8) {
381 dev_err(dev, "average_data (%u) must be [0-8]\n", val);
382 return -EINVAL;
383 }
384 priv->cfg_params.average_data = val;
385 }
386
387 if (of_property_read_u32(np, "fifo_threshold", &val) >= 0) {
388 if (val > 31) {
389 dev_err(dev, "fifo_threshold (%u)) must be [0-31]\n",
390 val);
391 return -EINVAL;
392 }
393 priv->cfg_params.fifo_threshold = val;
394 }
395
396 /* Parse optional properties. */
397 of_property_read_u32(np, "touchscreen-size-x", &priv->cfg_params.max_x);
398 of_property_read_u32(np, "touchscreen-size-y", &priv->cfg_params.max_y);
399
400 of_property_read_u32(np, "touchscreen-fuzz-x",
401 &priv->cfg_params.fuzz_x);
402 of_property_read_u32(np, "touchscreen-fuzz-y",
403 &priv->cfg_params.fuzz_y);
404
405 priv->cfg_params.invert_x =
406 of_property_read_bool(np, "touchscreen-inverted-x");
407 priv->cfg_params.invert_y =
408 of_property_read_bool(np, "touchscreen-inverted-y");
409
410 return 0;
411}
412
413static int iproc_ts_probe(struct platform_device *pdev)
414{
415 struct iproc_ts_priv *priv;
416 struct input_dev *idev;
417 struct resource *res;
418 int irq;
419 int error;
420
421 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
422 if (!priv)
423 return -ENOMEM;
424
425 /* touchscreen controller memory mapped regs */
426 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
427 priv->regs = devm_ioremap_resource(&pdev->dev, res);
428 if (IS_ERR(priv->regs)) {
429 error = PTR_ERR(priv->regs);
430 dev_err(&pdev->dev, "unable to map I/O memory: %d\n", error);
431 return error;
432 }
433
434 priv->tsc_clk = devm_clk_get(&pdev->dev, "tsc_clk");
435 if (IS_ERR(priv->tsc_clk)) {
436 error = PTR_ERR(priv->tsc_clk);
437 dev_err(&pdev->dev,
438 "failed getting clock tsc_clk: %d\n", error);
439 return error;
440 }
441
442 priv->pdev = pdev;
443 error = iproc_get_tsc_config(&pdev->dev, priv);
444 if (error) {
445 dev_err(&pdev->dev, "get_tsc_config failed: %d\n", error);
446 return error;
447 }
448
449 idev = devm_input_allocate_device(&pdev->dev);
450 if (!idev) {
451 dev_err(&pdev->dev, "failed to allocate input device\n");
452 return -ENOMEM;
453 }
454
455 priv->idev = idev;
456 priv->pen_status = PEN_UP_STATUS;
457
458 /* Set input device info */
459 idev->name = IPROC_TS_NAME;
460 idev->dev.parent = &pdev->dev;
461
462 idev->id.bustype = BUS_HOST;
463 idev->id.vendor = SERIO_UNKNOWN;
464 idev->id.product = 0;
465 idev->id.version = 0;
466
467 idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
468 __set_bit(BTN_TOUCH, idev->keybit);
469
470 input_set_abs_params(idev, ABS_X, X_MIN, priv->cfg_params.max_x,
471 priv->cfg_params.fuzz_x, 0);
472 input_set_abs_params(idev, ABS_Y, Y_MIN, priv->cfg_params.max_y,
473 priv->cfg_params.fuzz_y, 0);
474
475 idev->open = iproc_ts_start;
476 idev->close = iproc_ts_stop;
477
478 input_set_drvdata(idev, priv);
479 platform_set_drvdata(pdev, priv);
480
481 /* get interrupt */
482 irq = platform_get_irq(pdev, 0);
483 if (irq < 0) {
484 dev_err(&pdev->dev, "platform_get_irq failed: %d\n", irq);
485 return irq;
486 }
487
488 error = devm_request_irq(&pdev->dev, irq,
489 iproc_touchscreen_interrupt,
490 IRQF_SHARED, IPROC_TS_NAME, pdev);
491 if (error)
492 return error;
493
494 error = input_register_device(priv->idev);
495 if (error) {
496 dev_err(&pdev->dev,
497 "failed to register input device: %d\n", error);
498 return error;
499 }
500
501 return 0;
502}
503
504static const struct of_device_id iproc_ts_of_match[] = {
505 {.compatible = "brcm,iproc-touchscreen", },
506 { },
507};
508MODULE_DEVICE_TABLE(of, iproc_ts_of_match);
509
510static struct platform_driver iproc_ts_driver = {
511 .probe = iproc_ts_probe,
512 .driver = {
513 .name = IPROC_TS_NAME,
514 .of_match_table = of_match_ptr(iproc_ts_of_match),
515 },
516};
517
518module_platform_driver(iproc_ts_driver);
519
520MODULE_DESCRIPTION("IPROC Touchscreen driver");
521MODULE_AUTHOR("Broadcom");
522MODULE_LICENSE("GPL v2");