1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * TI Touch Screen driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or
7*4882a593Smuzhiyun * modify it under the terms of the GNU General Public License as
8*4882a593Smuzhiyun * published by the Free Software Foundation version 2.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11*4882a593Smuzhiyun * kind, whether express or implied; without even the implied warranty
12*4882a593Smuzhiyun * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*4882a593Smuzhiyun * GNU General Public License for more details.
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/kernel.h>
18*4882a593Smuzhiyun #include <linux/err.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/input.h>
21*4882a593Smuzhiyun #include <linux/slab.h>
22*4882a593Smuzhiyun #include <linux/interrupt.h>
23*4882a593Smuzhiyun #include <linux/clk.h>
24*4882a593Smuzhiyun #include <linux/platform_device.h>
25*4882a593Smuzhiyun #include <linux/io.h>
26*4882a593Smuzhiyun #include <linux/delay.h>
27*4882a593Smuzhiyun #include <linux/of.h>
28*4882a593Smuzhiyun #include <linux/of_device.h>
29*4882a593Smuzhiyun #include <linux/sort.h>
30*4882a593Smuzhiyun #include <linux/pm_wakeirq.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #include <linux/mfd/ti_am335x_tscadc.h>
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define ADCFSM_STEPID 0x10
35*4882a593Smuzhiyun #define SEQ_SETTLE 275
36*4882a593Smuzhiyun #define MAX_12BIT ((1 << 12) - 1)
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define TSC_IRQENB_MASK (IRQENB_FIFO0THRES | IRQENB_EOS | IRQENB_HW_PEN)
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static const int config_pins[] = {
41*4882a593Smuzhiyun STEPCONFIG_XPP,
42*4882a593Smuzhiyun STEPCONFIG_XNN,
43*4882a593Smuzhiyun STEPCONFIG_YPP,
44*4882a593Smuzhiyun STEPCONFIG_YNN,
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun struct titsc {
48*4882a593Smuzhiyun struct input_dev *input;
49*4882a593Smuzhiyun struct ti_tscadc_dev *mfd_tscadc;
50*4882a593Smuzhiyun struct device *dev;
51*4882a593Smuzhiyun unsigned int irq;
52*4882a593Smuzhiyun unsigned int wires;
53*4882a593Smuzhiyun unsigned int x_plate_resistance;
54*4882a593Smuzhiyun bool pen_down;
55*4882a593Smuzhiyun int coordinate_readouts;
56*4882a593Smuzhiyun u32 config_inp[4];
57*4882a593Smuzhiyun u32 bit_xp, bit_xn, bit_yp, bit_yn;
58*4882a593Smuzhiyun u32 inp_xp, inp_xn, inp_yp, inp_yn;
59*4882a593Smuzhiyun u32 step_mask;
60*4882a593Smuzhiyun u32 charge_delay;
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun
titsc_readl(struct titsc * ts,unsigned int reg)63*4882a593Smuzhiyun static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun return readl(ts->mfd_tscadc->tscadc_base + reg);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
titsc_writel(struct titsc * tsc,unsigned int reg,unsigned int val)68*4882a593Smuzhiyun static void titsc_writel(struct titsc *tsc, unsigned int reg,
69*4882a593Smuzhiyun unsigned int val)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun writel(val, tsc->mfd_tscadc->tscadc_base + reg);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
titsc_config_wires(struct titsc * ts_dev)74*4882a593Smuzhiyun static int titsc_config_wires(struct titsc *ts_dev)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun u32 analog_line[4];
77*4882a593Smuzhiyun u32 wire_order[4];
78*4882a593Smuzhiyun int i, bit_cfg;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
81*4882a593Smuzhiyun /*
82*4882a593Smuzhiyun * Get the order in which TSC wires are attached
83*4882a593Smuzhiyun * w.r.t. each of the analog input lines on the EVM.
84*4882a593Smuzhiyun */
85*4882a593Smuzhiyun analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4;
86*4882a593Smuzhiyun wire_order[i] = ts_dev->config_inp[i] & 0x0F;
87*4882a593Smuzhiyun if (WARN_ON(analog_line[i] > 7))
88*4882a593Smuzhiyun return -EINVAL;
89*4882a593Smuzhiyun if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
90*4882a593Smuzhiyun return -EINVAL;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
94*4882a593Smuzhiyun int an_line;
95*4882a593Smuzhiyun int wi_order;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun an_line = analog_line[i];
98*4882a593Smuzhiyun wi_order = wire_order[i];
99*4882a593Smuzhiyun bit_cfg = config_pins[wi_order];
100*4882a593Smuzhiyun if (bit_cfg == 0)
101*4882a593Smuzhiyun return -EINVAL;
102*4882a593Smuzhiyun switch (wi_order) {
103*4882a593Smuzhiyun case 0:
104*4882a593Smuzhiyun ts_dev->bit_xp = bit_cfg;
105*4882a593Smuzhiyun ts_dev->inp_xp = an_line;
106*4882a593Smuzhiyun break;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun case 1:
109*4882a593Smuzhiyun ts_dev->bit_xn = bit_cfg;
110*4882a593Smuzhiyun ts_dev->inp_xn = an_line;
111*4882a593Smuzhiyun break;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun case 2:
114*4882a593Smuzhiyun ts_dev->bit_yp = bit_cfg;
115*4882a593Smuzhiyun ts_dev->inp_yp = an_line;
116*4882a593Smuzhiyun break;
117*4882a593Smuzhiyun case 3:
118*4882a593Smuzhiyun ts_dev->bit_yn = bit_cfg;
119*4882a593Smuzhiyun ts_dev->inp_yn = an_line;
120*4882a593Smuzhiyun break;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
titsc_step_config(struct titsc * ts_dev)126*4882a593Smuzhiyun static void titsc_step_config(struct titsc *ts_dev)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun unsigned int config;
129*4882a593Smuzhiyun int i;
130*4882a593Smuzhiyun int end_step, first_step, tsc_steps;
131*4882a593Smuzhiyun u32 stepenable;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun config = STEPCONFIG_MODE_HWSYNC |
134*4882a593Smuzhiyun STEPCONFIG_AVG_16 | ts_dev->bit_xp;
135*4882a593Smuzhiyun switch (ts_dev->wires) {
136*4882a593Smuzhiyun case 4:
137*4882a593Smuzhiyun config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
138*4882a593Smuzhiyun break;
139*4882a593Smuzhiyun case 5:
140*4882a593Smuzhiyun config |= ts_dev->bit_yn |
141*4882a593Smuzhiyun STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
142*4882a593Smuzhiyun ts_dev->bit_yp;
143*4882a593Smuzhiyun break;
144*4882a593Smuzhiyun case 8:
145*4882a593Smuzhiyun config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
146*4882a593Smuzhiyun break;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun tsc_steps = ts_dev->coordinate_readouts * 2 + 2;
150*4882a593Smuzhiyun first_step = TOTAL_STEPS - tsc_steps;
151*4882a593Smuzhiyun /* Steps 16 to 16-coordinate_readouts is for X */
152*4882a593Smuzhiyun end_step = first_step + tsc_steps;
153*4882a593Smuzhiyun for (i = end_step - ts_dev->coordinate_readouts; i < end_step; i++) {
154*4882a593Smuzhiyun titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
155*4882a593Smuzhiyun titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun config = 0;
159*4882a593Smuzhiyun config = STEPCONFIG_MODE_HWSYNC |
160*4882a593Smuzhiyun STEPCONFIG_AVG_16 | ts_dev->bit_yn |
161*4882a593Smuzhiyun STEPCONFIG_INM_ADCREFM;
162*4882a593Smuzhiyun switch (ts_dev->wires) {
163*4882a593Smuzhiyun case 4:
164*4882a593Smuzhiyun config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
165*4882a593Smuzhiyun break;
166*4882a593Smuzhiyun case 5:
167*4882a593Smuzhiyun config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
168*4882a593Smuzhiyun STEPCONFIG_XNP | STEPCONFIG_YPN;
169*4882a593Smuzhiyun break;
170*4882a593Smuzhiyun case 8:
171*4882a593Smuzhiyun config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
172*4882a593Smuzhiyun break;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /* 1 ... coordinate_readouts is for Y */
176*4882a593Smuzhiyun end_step = first_step + ts_dev->coordinate_readouts;
177*4882a593Smuzhiyun for (i = first_step; i < end_step; i++) {
178*4882a593Smuzhiyun titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
179*4882a593Smuzhiyun titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* Make CHARGECONFIG same as IDLECONFIG */
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun config = titsc_readl(ts_dev, REG_IDLECONFIG);
185*4882a593Smuzhiyun titsc_writel(ts_dev, REG_CHARGECONFIG, config);
186*4882a593Smuzhiyun titsc_writel(ts_dev, REG_CHARGEDELAY, ts_dev->charge_delay);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* coordinate_readouts + 1 ... coordinate_readouts + 2 is for Z */
189*4882a593Smuzhiyun config = STEPCONFIG_MODE_HWSYNC |
190*4882a593Smuzhiyun STEPCONFIG_AVG_16 | ts_dev->bit_yp |
191*4882a593Smuzhiyun ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
192*4882a593Smuzhiyun STEPCONFIG_INP(ts_dev->inp_xp);
193*4882a593Smuzhiyun titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
194*4882a593Smuzhiyun titsc_writel(ts_dev, REG_STEPDELAY(end_step),
195*4882a593Smuzhiyun STEPCONFIG_OPENDLY);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun end_step++;
198*4882a593Smuzhiyun config |= STEPCONFIG_INP(ts_dev->inp_yn);
199*4882a593Smuzhiyun titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
200*4882a593Smuzhiyun titsc_writel(ts_dev, REG_STEPDELAY(end_step),
201*4882a593Smuzhiyun STEPCONFIG_OPENDLY);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /* The steps end ... end - readouts * 2 + 2 and bit 0 for TS_Charge */
204*4882a593Smuzhiyun stepenable = 1;
205*4882a593Smuzhiyun for (i = 0; i < tsc_steps; i++)
206*4882a593Smuzhiyun stepenable |= 1 << (first_step + i + 1);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun ts_dev->step_mask = stepenable;
209*4882a593Smuzhiyun am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
titsc_cmp_coord(const void * a,const void * b)212*4882a593Smuzhiyun static int titsc_cmp_coord(const void *a, const void *b)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun return *(int *)a - *(int *)b;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
titsc_read_coordinates(struct titsc * ts_dev,u32 * x,u32 * y,u32 * z1,u32 * z2)217*4882a593Smuzhiyun static void titsc_read_coordinates(struct titsc *ts_dev,
218*4882a593Smuzhiyun u32 *x, u32 *y, u32 *z1, u32 *z2)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun unsigned int yvals[7], xvals[7];
221*4882a593Smuzhiyun unsigned int i, xsum = 0, ysum = 0;
222*4882a593Smuzhiyun unsigned int creads = ts_dev->coordinate_readouts;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun for (i = 0; i < creads; i++) {
225*4882a593Smuzhiyun yvals[i] = titsc_readl(ts_dev, REG_FIFO0);
226*4882a593Smuzhiyun yvals[i] &= 0xfff;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun *z1 = titsc_readl(ts_dev, REG_FIFO0);
230*4882a593Smuzhiyun *z1 &= 0xfff;
231*4882a593Smuzhiyun *z2 = titsc_readl(ts_dev, REG_FIFO0);
232*4882a593Smuzhiyun *z2 &= 0xfff;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun for (i = 0; i < creads; i++) {
235*4882a593Smuzhiyun xvals[i] = titsc_readl(ts_dev, REG_FIFO0);
236*4882a593Smuzhiyun xvals[i] &= 0xfff;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /*
240*4882a593Smuzhiyun * If co-ordinates readouts is less than 4 then
241*4882a593Smuzhiyun * report the average. In case of 4 or more
242*4882a593Smuzhiyun * readouts, sort the co-ordinate samples, drop
243*4882a593Smuzhiyun * min and max values and report the average of
244*4882a593Smuzhiyun * remaining values.
245*4882a593Smuzhiyun */
246*4882a593Smuzhiyun if (creads <= 3) {
247*4882a593Smuzhiyun for (i = 0; i < creads; i++) {
248*4882a593Smuzhiyun ysum += yvals[i];
249*4882a593Smuzhiyun xsum += xvals[i];
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun ysum /= creads;
252*4882a593Smuzhiyun xsum /= creads;
253*4882a593Smuzhiyun } else {
254*4882a593Smuzhiyun sort(yvals, creads, sizeof(unsigned int),
255*4882a593Smuzhiyun titsc_cmp_coord, NULL);
256*4882a593Smuzhiyun sort(xvals, creads, sizeof(unsigned int),
257*4882a593Smuzhiyun titsc_cmp_coord, NULL);
258*4882a593Smuzhiyun for (i = 1; i < creads - 1; i++) {
259*4882a593Smuzhiyun ysum += yvals[i];
260*4882a593Smuzhiyun xsum += xvals[i];
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun ysum /= creads - 2;
263*4882a593Smuzhiyun xsum /= creads - 2;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun *y = ysum;
266*4882a593Smuzhiyun *x = xsum;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
titsc_irq(int irq,void * dev)269*4882a593Smuzhiyun static irqreturn_t titsc_irq(int irq, void *dev)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun struct titsc *ts_dev = dev;
272*4882a593Smuzhiyun struct input_dev *input_dev = ts_dev->input;
273*4882a593Smuzhiyun unsigned int fsm, status, irqclr = 0;
274*4882a593Smuzhiyun unsigned int x = 0, y = 0;
275*4882a593Smuzhiyun unsigned int z1, z2, z;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
278*4882a593Smuzhiyun if (status & IRQENB_HW_PEN) {
279*4882a593Smuzhiyun ts_dev->pen_down = true;
280*4882a593Smuzhiyun irqclr |= IRQENB_HW_PEN;
281*4882a593Smuzhiyun pm_stay_awake(ts_dev->dev);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun if (status & IRQENB_PENUP) {
285*4882a593Smuzhiyun fsm = titsc_readl(ts_dev, REG_ADCFSM);
286*4882a593Smuzhiyun if (fsm == ADCFSM_STEPID) {
287*4882a593Smuzhiyun ts_dev->pen_down = false;
288*4882a593Smuzhiyun input_report_key(input_dev, BTN_TOUCH, 0);
289*4882a593Smuzhiyun input_report_abs(input_dev, ABS_PRESSURE, 0);
290*4882a593Smuzhiyun input_sync(input_dev);
291*4882a593Smuzhiyun pm_relax(ts_dev->dev);
292*4882a593Smuzhiyun } else {
293*4882a593Smuzhiyun ts_dev->pen_down = true;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun irqclr |= IRQENB_PENUP;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (status & IRQENB_EOS)
299*4882a593Smuzhiyun irqclr |= IRQENB_EOS;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /*
302*4882a593Smuzhiyun * ADC and touchscreen share the IRQ line.
303*4882a593Smuzhiyun * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
304*4882a593Smuzhiyun */
305*4882a593Smuzhiyun if (status & IRQENB_FIFO0THRES) {
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
310*4882a593Smuzhiyun /*
311*4882a593Smuzhiyun * Calculate pressure using formula
312*4882a593Smuzhiyun * Resistance(touch) = x plate resistance *
313*4882a593Smuzhiyun * x postion/4096 * ((z2 / z1) - 1)
314*4882a593Smuzhiyun */
315*4882a593Smuzhiyun z = z1 - z2;
316*4882a593Smuzhiyun z *= x;
317*4882a593Smuzhiyun z *= ts_dev->x_plate_resistance;
318*4882a593Smuzhiyun z /= z2;
319*4882a593Smuzhiyun z = (z + 2047) >> 12;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (z <= MAX_12BIT) {
322*4882a593Smuzhiyun input_report_abs(input_dev, ABS_X, x);
323*4882a593Smuzhiyun input_report_abs(input_dev, ABS_Y, y);
324*4882a593Smuzhiyun input_report_abs(input_dev, ABS_PRESSURE, z);
325*4882a593Smuzhiyun input_report_key(input_dev, BTN_TOUCH, 1);
326*4882a593Smuzhiyun input_sync(input_dev);
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun irqclr |= IRQENB_FIFO0THRES;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun if (irqclr) {
332*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
333*4882a593Smuzhiyun if (status & IRQENB_EOS)
334*4882a593Smuzhiyun am335x_tsc_se_set_cache(ts_dev->mfd_tscadc,
335*4882a593Smuzhiyun ts_dev->step_mask);
336*4882a593Smuzhiyun return IRQ_HANDLED;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun return IRQ_NONE;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
titsc_parse_dt(struct platform_device * pdev,struct titsc * ts_dev)341*4882a593Smuzhiyun static int titsc_parse_dt(struct platform_device *pdev,
342*4882a593Smuzhiyun struct titsc *ts_dev)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun struct device_node *node = pdev->dev.of_node;
345*4882a593Smuzhiyun int err;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun if (!node)
348*4882a593Smuzhiyun return -EINVAL;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
351*4882a593Smuzhiyun if (err < 0)
352*4882a593Smuzhiyun return err;
353*4882a593Smuzhiyun switch (ts_dev->wires) {
354*4882a593Smuzhiyun case 4:
355*4882a593Smuzhiyun case 5:
356*4882a593Smuzhiyun case 8:
357*4882a593Smuzhiyun break;
358*4882a593Smuzhiyun default:
359*4882a593Smuzhiyun return -EINVAL;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun err = of_property_read_u32(node, "ti,x-plate-resistance",
363*4882a593Smuzhiyun &ts_dev->x_plate_resistance);
364*4882a593Smuzhiyun if (err < 0)
365*4882a593Smuzhiyun return err;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun /*
368*4882a593Smuzhiyun * Try with the new binding first. If it fails, try again with
369*4882a593Smuzhiyun * bogus, miss-spelled version.
370*4882a593Smuzhiyun */
371*4882a593Smuzhiyun err = of_property_read_u32(node, "ti,coordinate-readouts",
372*4882a593Smuzhiyun &ts_dev->coordinate_readouts);
373*4882a593Smuzhiyun if (err < 0) {
374*4882a593Smuzhiyun dev_warn(&pdev->dev, "please use 'ti,coordinate-readouts' instead\n");
375*4882a593Smuzhiyun err = of_property_read_u32(node, "ti,coordiante-readouts",
376*4882a593Smuzhiyun &ts_dev->coordinate_readouts);
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun if (err < 0)
380*4882a593Smuzhiyun return err;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun if (ts_dev->coordinate_readouts <= 0) {
383*4882a593Smuzhiyun dev_warn(&pdev->dev,
384*4882a593Smuzhiyun "invalid co-ordinate readouts, resetting it to 5\n");
385*4882a593Smuzhiyun ts_dev->coordinate_readouts = 5;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun err = of_property_read_u32(node, "ti,charge-delay",
389*4882a593Smuzhiyun &ts_dev->charge_delay);
390*4882a593Smuzhiyun /*
391*4882a593Smuzhiyun * If ti,charge-delay value is not specified, then use
392*4882a593Smuzhiyun * CHARGEDLY_OPENDLY as the default value.
393*4882a593Smuzhiyun */
394*4882a593Smuzhiyun if (err < 0) {
395*4882a593Smuzhiyun ts_dev->charge_delay = CHARGEDLY_OPENDLY;
396*4882a593Smuzhiyun dev_warn(&pdev->dev, "ti,charge-delay not specified\n");
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun return of_property_read_u32_array(node, "ti,wire-config",
400*4882a593Smuzhiyun ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun /*
404*4882a593Smuzhiyun * The functions for inserting/removing driver as a module.
405*4882a593Smuzhiyun */
406*4882a593Smuzhiyun
titsc_probe(struct platform_device * pdev)407*4882a593Smuzhiyun static int titsc_probe(struct platform_device *pdev)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun struct titsc *ts_dev;
410*4882a593Smuzhiyun struct input_dev *input_dev;
411*4882a593Smuzhiyun struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
412*4882a593Smuzhiyun int err;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun /* Allocate memory for device */
415*4882a593Smuzhiyun ts_dev = kzalloc(sizeof(*ts_dev), GFP_KERNEL);
416*4882a593Smuzhiyun input_dev = input_allocate_device();
417*4882a593Smuzhiyun if (!ts_dev || !input_dev) {
418*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to allocate memory.\n");
419*4882a593Smuzhiyun err = -ENOMEM;
420*4882a593Smuzhiyun goto err_free_mem;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun tscadc_dev->tsc = ts_dev;
424*4882a593Smuzhiyun ts_dev->mfd_tscadc = tscadc_dev;
425*4882a593Smuzhiyun ts_dev->input = input_dev;
426*4882a593Smuzhiyun ts_dev->irq = tscadc_dev->irq;
427*4882a593Smuzhiyun ts_dev->dev = &pdev->dev;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun err = titsc_parse_dt(pdev, ts_dev);
430*4882a593Smuzhiyun if (err) {
431*4882a593Smuzhiyun dev_err(&pdev->dev, "Could not find valid DT data.\n");
432*4882a593Smuzhiyun goto err_free_mem;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun err = request_irq(ts_dev->irq, titsc_irq,
436*4882a593Smuzhiyun IRQF_SHARED, pdev->dev.driver->name, ts_dev);
437*4882a593Smuzhiyun if (err) {
438*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to allocate irq.\n");
439*4882a593Smuzhiyun goto err_free_mem;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun device_init_wakeup(&pdev->dev, true);
443*4882a593Smuzhiyun err = dev_pm_set_wake_irq(&pdev->dev, ts_dev->irq);
444*4882a593Smuzhiyun if (err)
445*4882a593Smuzhiyun dev_err(&pdev->dev, "irq wake enable failed.\n");
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQSTATUS, TSC_IRQENB_MASK);
448*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
449*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_EOS);
450*4882a593Smuzhiyun err = titsc_config_wires(ts_dev);
451*4882a593Smuzhiyun if (err) {
452*4882a593Smuzhiyun dev_err(&pdev->dev, "wrong i/p wire configuration\n");
453*4882a593Smuzhiyun goto err_free_irq;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun titsc_step_config(ts_dev);
456*4882a593Smuzhiyun titsc_writel(ts_dev, REG_FIFO0THR,
457*4882a593Smuzhiyun ts_dev->coordinate_readouts * 2 + 2 - 1);
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun input_dev->name = "ti-tsc";
460*4882a593Smuzhiyun input_dev->dev.parent = &pdev->dev;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
463*4882a593Smuzhiyun input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
466*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
467*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun /* register to the input system */
470*4882a593Smuzhiyun err = input_register_device(input_dev);
471*4882a593Smuzhiyun if (err)
472*4882a593Smuzhiyun goto err_free_irq;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun platform_set_drvdata(pdev, ts_dev);
475*4882a593Smuzhiyun return 0;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun err_free_irq:
478*4882a593Smuzhiyun dev_pm_clear_wake_irq(&pdev->dev);
479*4882a593Smuzhiyun device_init_wakeup(&pdev->dev, false);
480*4882a593Smuzhiyun free_irq(ts_dev->irq, ts_dev);
481*4882a593Smuzhiyun err_free_mem:
482*4882a593Smuzhiyun input_free_device(input_dev);
483*4882a593Smuzhiyun kfree(ts_dev);
484*4882a593Smuzhiyun return err;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
titsc_remove(struct platform_device * pdev)487*4882a593Smuzhiyun static int titsc_remove(struct platform_device *pdev)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun struct titsc *ts_dev = platform_get_drvdata(pdev);
490*4882a593Smuzhiyun u32 steps;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun dev_pm_clear_wake_irq(&pdev->dev);
493*4882a593Smuzhiyun device_init_wakeup(&pdev->dev, false);
494*4882a593Smuzhiyun free_irq(ts_dev->irq, ts_dev);
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun /* total steps followed by the enable mask */
497*4882a593Smuzhiyun steps = 2 * ts_dev->coordinate_readouts + 2;
498*4882a593Smuzhiyun steps = (1 << steps) - 1;
499*4882a593Smuzhiyun am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun input_unregister_device(ts_dev->input);
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun kfree(ts_dev);
504*4882a593Smuzhiyun return 0;
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
titsc_suspend(struct device * dev)507*4882a593Smuzhiyun static int __maybe_unused titsc_suspend(struct device *dev)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun struct titsc *ts_dev = dev_get_drvdata(dev);
510*4882a593Smuzhiyun unsigned int idle;
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun if (device_may_wakeup(dev)) {
513*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQSTATUS, TSC_IRQENB_MASK);
514*4882a593Smuzhiyun idle = titsc_readl(ts_dev, REG_IRQENABLE);
515*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQENABLE,
516*4882a593Smuzhiyun (idle | IRQENB_HW_PEN));
517*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun return 0;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
titsc_resume(struct device * dev)522*4882a593Smuzhiyun static int __maybe_unused titsc_resume(struct device *dev)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun struct titsc *ts_dev = dev_get_drvdata(dev);
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (device_may_wakeup(dev)) {
527*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQWAKEUP,
528*4882a593Smuzhiyun 0x00);
529*4882a593Smuzhiyun titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
530*4882a593Smuzhiyun pm_relax(dev);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun titsc_step_config(ts_dev);
533*4882a593Smuzhiyun titsc_writel(ts_dev, REG_FIFO0THR,
534*4882a593Smuzhiyun ts_dev->coordinate_readouts * 2 + 2 - 1);
535*4882a593Smuzhiyun return 0;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(titsc_pm_ops, titsc_suspend, titsc_resume);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun static const struct of_device_id ti_tsc_dt_ids[] = {
541*4882a593Smuzhiyun { .compatible = "ti,am3359-tsc", },
542*4882a593Smuzhiyun { }
543*4882a593Smuzhiyun };
544*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun static struct platform_driver ti_tsc_driver = {
547*4882a593Smuzhiyun .probe = titsc_probe,
548*4882a593Smuzhiyun .remove = titsc_remove,
549*4882a593Smuzhiyun .driver = {
550*4882a593Smuzhiyun .name = "TI-am335x-tsc",
551*4882a593Smuzhiyun .pm = &titsc_pm_ops,
552*4882a593Smuzhiyun .of_match_table = ti_tsc_dt_ids,
553*4882a593Smuzhiyun },
554*4882a593Smuzhiyun };
555*4882a593Smuzhiyun module_platform_driver(ti_tsc_driver);
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun MODULE_DESCRIPTION("TI touchscreen controller driver");
558*4882a593Smuzhiyun MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
559*4882a593Smuzhiyun MODULE_LICENSE("GPL");
560