input: TSC: Add suspend/resume feature for TSC
[sitara-epos/sitara-epos-kernel.git] / drivers / input / touchscreen / ti_tscadc.c
1 /*
2  * TI Touch Screen driver
3  *
4  * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation version 2.
9  *
10  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11  * kind, whether express or implied; without even the implied warranty
12  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/err.h>
20 #include <linux/module.h>
21 #include <linux/input.h>
22 #include <linux/slab.h>
23 #include <linux/interrupt.h>
24 #include <linux/clk.h>
25 #include <linux/platform_device.h>
26 #include <linux/io.h>
27 #include <linux/input/ti_tscadc.h>
28 #include <linux/delay.h>
29 #include <linux/pm_runtime.h>
31 #define TSCADC_REG_IRQEOI               0x020
32 #define TSCADC_REG_RAWIRQSTATUS         0x024
33 #define TSCADC_REG_IRQSTATUS            0x028
34 #define TSCADC_REG_IRQENABLE            0x02C
35 #define TSCADC_REG_IRQCLR               0x030
36 #define TSCADC_REG_IRQWAKEUP            0x034
37 #define TSCADC_REG_CTRL                 0x040
38 #define TSCADC_REG_ADCFSM               0x044
39 #define TSCADC_REG_CLKDIV               0x04C
40 #define TSCADC_REG_SE                   0x054
41 #define TSCADC_REG_IDLECONFIG           0x058
42 #define TSCADC_REG_CHARGECONFIG         0x05C
43 #define TSCADC_REG_CHARGEDELAY          0x060
44 #define TSCADC_REG_STEPCONFIG(n)        (0x64 + ((n-1) * 8))
45 #define TSCADC_REG_STEPDELAY(n)         (0x68 + ((n-1) * 8))
46 #define TSCADC_REG_STEPCONFIG13         0x0C4
47 #define TSCADC_REG_STEPDELAY13          0x0C8
48 #define TSCADC_REG_STEPCONFIG14         0x0CC
49 #define TSCADC_REG_STEPDELAY14          0x0D0
50 #define TSCADC_REG_FIFO0CNT             0xE4
51 #define TSCADC_REG_FIFO0THR             0xE8
52 #define TSCADC_REG_FIFO1CNT             0xF0
53 #define TSCADC_REG_FIFO1THR             0xF4
54 #define TSCADC_REG_FIFO0                0x100
55 #define TSCADC_REG_FIFO1                0x200
57 /*      Register Bitfields      */
58 #define TSCADC_IRQWKUP_ENB              BIT(0)
59 #define TSCADC_IRQWKUP_DISABLE          0x00
60 #define TSCADC_STPENB_STEPENB           0x7FFF
61 #define TSCADC_IRQENB_FIFO0THRES        BIT(2)
62 #define TSCADC_IRQENB_FIFO1THRES        BIT(5)
63 #define TSCADC_IRQENB_PENUP             BIT(9)
64 #define TSCADC_IRQENB_HW_PEN            BIT(0)
65 #define TSCADC_STEPCONFIG_MODE_HWSYNC   0x2
66 #define TSCADC_STEPCONFIG_2SAMPLES_AVG  (1 << 4)
67 #define TSCADC_STEPCONFIG_XPP           BIT(5)
68 #define TSCADC_STEPCONFIG_XNN           BIT(6)
69 #define TSCADC_STEPCONFIG_YPP           BIT(7)
70 #define TSCADC_STEPCONFIG_YNN           BIT(8)
71 #define TSCADC_STEPCONFIG_XNP           BIT(9)
72 #define TSCADC_STEPCONFIG_YPN           BIT(10)
73 #define TSCADC_STEPCONFIG_RFP           (1 << 12)
74 #define TSCADC_STEPCONFIG_INM           (1 << 18)
75 #define TSCADC_STEPCONFIG_INP_4         (1 << 19)
76 #define TSCADC_STEPCONFIG_INP           (1 << 20)
77 #define TSCADC_STEPCONFIG_INP_5         (1 << 21)
78 #define TSCADC_STEPCONFIG_FIFO1         (1 << 26)
79 #define TSCADC_STEPCONFIG_IDLE_INP      (1 << 22)
80 #define TSCADC_STEPCONFIG_OPENDLY       0x018
81 #define TSCADC_STEPCONFIG_SAMPLEDLY     0x88
82 #define TSCADC_STEPCONFIG_Z1            (3 << 19)
83 #define TSCADC_STEPCHARGE_INM_SWAP      BIT(16)
84 #define TSCADC_STEPCHARGE_INM           BIT(15)
85 #define TSCADC_STEPCHARGE_INP_SWAP      BIT(20)
86 #define TSCADC_STEPCHARGE_INP           BIT(19)
87 #define TSCADC_STEPCHARGE_RFM           (1 << 23)
88 #define TSCADC_STEPCHARGE_DELAY         0x1
89 #define TSCADC_CNTRLREG_TSCSSENB        BIT(0)
90 #define TSCADC_CNTRLREG_STEPID          BIT(1)
91 #define TSCADC_CNTRLREG_STEPCONFIGWRT   BIT(2)
92 #define TSCADC_CNTRLREG_TSCENB          BIT(7)
93 #define TSCADC_CNTRLREG_4WIRE           (0x1 << 5)
94 #define TSCADC_CNTRLREG_5WIRE           (0x1 << 6)
95 #define TSCADC_CNTRLREG_8WIRE           (0x3 << 5)
96 #define TSCADC_ADCFSM_STEPID            0x10
97 #define TSCADC_ADCFSM_FSM               BIT(5)
99 #define ADC_CLK                         3000000
101 #define MAX_12BIT                       ((1 << 12) - 1)
103 int pen = 1;
104 unsigned int bckup_x = 0, bckup_y = 0;
106 struct tscadc {
107         struct input_dev        *input;
108         int                     wires;
109         int                     analog_input;
110         int                     x_plate_resistance;
111         int                     irq;
112         void __iomem            *tsc_base;
113         unsigned int            ctrl;
114 };
116 static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
118         return readl(ts->tsc_base + reg);
121 static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
122                                         unsigned int val)
124         writel(val, tsc->tsc_base + reg);
127 static void tsc_step_config(struct tscadc *ts_dev)
129         unsigned int    stepconfigx = 0, stepconfigy = 0;
130         unsigned int    delay, chargeconfig = 0;
131         unsigned int    stepconfigz1 = 0, stepconfigz2 = 0;
132         int i;
134         /* Configure the Step registers */
136         delay = TSCADC_STEPCONFIG_SAMPLEDLY | TSCADC_STEPCONFIG_OPENDLY;
138         stepconfigx = TSCADC_STEPCONFIG_MODE_HWSYNC |
139                         TSCADC_STEPCONFIG_2SAMPLES_AVG | TSCADC_STEPCONFIG_XPP;
141         switch (ts_dev->wires) {
142         case 4:
143                 if (ts_dev->analog_input == 0)
144                         stepconfigx |= TSCADC_STEPCONFIG_INP_4 |
145                                 TSCADC_STEPCONFIG_YPN;
146                 else
147                         stepconfigx |= TSCADC_STEPCONFIG_INP |
148                                 TSCADC_STEPCONFIG_XNN;
149                 break;
150         case 5:
151                 stepconfigx |= TSCADC_STEPCONFIG_YNN |
152                                 TSCADC_STEPCONFIG_INP_5;
153                 if (ts_dev->analog_input == 0)
154                         stepconfigx |= TSCADC_STEPCONFIG_XNP |
155                                 TSCADC_STEPCONFIG_YPN;
156                 else
157                         stepconfigx |= TSCADC_STEPCONFIG_XNN |
158                                 TSCADC_STEPCONFIG_YPP;
159                 break;
160         case 8:
161                 if (ts_dev->analog_input == 0)
162                         stepconfigx |= TSCADC_STEPCONFIG_INP_4 |
163                                 TSCADC_STEPCONFIG_YPN;
164                 else
165                         stepconfigx |= TSCADC_STEPCONFIG_INP |
166                                 TSCADC_STEPCONFIG_XNN;
167                 break;
168         }
170         for (i = 1; i < 7; i++) {
171                 tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG(i), stepconfigx);
172                 tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY(i), delay);
173         }
175         stepconfigy = TSCADC_STEPCONFIG_MODE_HWSYNC |
176                         TSCADC_STEPCONFIG_2SAMPLES_AVG | TSCADC_STEPCONFIG_YNN |
177                         TSCADC_STEPCONFIG_INM | TSCADC_STEPCONFIG_FIFO1;
178         switch (ts_dev->wires) {
179         case 4:
180                 if (ts_dev->analog_input == 0)
181                         stepconfigy |= TSCADC_STEPCONFIG_XNP;
182                 else
183                         stepconfigy |= TSCADC_STEPCONFIG_YPP;
184                 break;
185         case 5:
186                 stepconfigy |= TSCADC_STEPCONFIG_XPP | TSCADC_STEPCONFIG_INP_5;
187                 if (ts_dev->analog_input == 0)
188                         stepconfigy |= TSCADC_STEPCONFIG_XNN |
189                                 TSCADC_STEPCONFIG_YPP;
190                 else
191                         stepconfigy |= TSCADC_STEPCONFIG_XNP |
192                                 TSCADC_STEPCONFIG_YPN;
193                 break;
194         case 8:
195                 if (ts_dev->analog_input == 0)
196                         stepconfigy |= TSCADC_STEPCONFIG_XNP;
197                 else
198                         stepconfigy |= TSCADC_STEPCONFIG_YPP;
199                 break;
200         }
202         for (i = 7; i < 13; i++) {
203                 tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG(i), stepconfigy);
204                 tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY(i), delay);
205         }
207         chargeconfig = TSCADC_STEPCONFIG_XPP |
208                         TSCADC_STEPCONFIG_YNN |
209                         TSCADC_STEPCONFIG_RFP |
210                         TSCADC_STEPCHARGE_RFM;
211         if (ts_dev->analog_input == 0)
212                 chargeconfig |= TSCADC_STEPCHARGE_INM_SWAP |
213                         TSCADC_STEPCHARGE_INP_SWAP;
214         else
215                 chargeconfig |= TSCADC_STEPCHARGE_INM | TSCADC_STEPCHARGE_INP;
216         tscadc_writel(ts_dev, TSCADC_REG_CHARGECONFIG, chargeconfig);
217         tscadc_writel(ts_dev, TSCADC_REG_CHARGEDELAY, TSCADC_STEPCHARGE_DELAY);
219          /* Configure to calculate pressure */
220         stepconfigz1 = TSCADC_STEPCONFIG_MODE_HWSYNC |
221                                 TSCADC_STEPCONFIG_2SAMPLES_AVG |
222                                 TSCADC_STEPCONFIG_XNP |
223                                 TSCADC_STEPCONFIG_YPN | TSCADC_STEPCONFIG_INM;
224         stepconfigz2 = stepconfigz1 | TSCADC_STEPCONFIG_Z1 |
225                                 TSCADC_STEPCONFIG_FIFO1;
226         tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG13, stepconfigz1);
227         tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY13, delay);
228         tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG14, stepconfigz2);
229         tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY14, delay);
231         tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
234 static void tsc_idle_config(struct tscadc *ts_config)
236         /* Idle mode touch screen config */
237         unsigned int     idleconfig;
239         idleconfig = TSCADC_STEPCONFIG_YNN |
240                         TSCADC_STEPCONFIG_INM | TSCADC_STEPCONFIG_IDLE_INP;
241         if (ts_config->analog_input == 0)
242                 idleconfig |= TSCADC_STEPCONFIG_XNN;
243         else
244                 idleconfig |= TSCADC_STEPCONFIG_YPN;
246         tscadc_writel(ts_config, TSCADC_REG_IDLECONFIG, idleconfig);
249 static irqreturn_t tscadc_interrupt(int irq, void *dev)
251         struct tscadc           *ts_dev = (struct tscadc *)dev;
252         struct input_dev        *input_dev = ts_dev->input;
253         unsigned int            status, irqclr = 0;
254         int                     i;
255         int                     fsm = 0, fifo0count = 0, fifo1count = 0;
256         unsigned int            readx1 = 0, ready1 = 0;
257         unsigned int            prev_val_x = ~0, prev_val_y = ~0;
258         unsigned int            prev_diff_x = ~0, prev_diff_y = ~0;
259         unsigned int            cur_diff_x = 0, cur_diff_y = 0;
260         unsigned int            val_x = 0, val_y = 0, diffx = 0, diffy = 0;
261         unsigned int            z1 = 0, z2 = 0, z = 0;
263         status = tscadc_readl(ts_dev, TSCADC_REG_IRQSTATUS);
265         if (status & TSCADC_IRQENB_FIFO1THRES) {
266                 fifo0count = tscadc_readl(ts_dev, TSCADC_REG_FIFO0CNT);
267                 fifo1count = tscadc_readl(ts_dev, TSCADC_REG_FIFO1CNT);
268                 for (i = 0; i < (fifo0count-1); i++) {
269                         readx1 = tscadc_readl(ts_dev, TSCADC_REG_FIFO0);
270                         readx1 = readx1 & 0xfff;
271                         if (readx1 > prev_val_x)
272                                 cur_diff_x = readx1 - prev_val_x;
273                         else
274                                 cur_diff_x = prev_val_x - readx1;
276                         if (cur_diff_x < prev_diff_x) {
277                                 prev_diff_x = cur_diff_x;
278                                 val_x = readx1;
279                         }
281                         prev_val_x = readx1;
282                         ready1 = tscadc_readl(ts_dev, TSCADC_REG_FIFO1);
283                                 ready1 &= 0xfff;
284                         if (ready1 > prev_val_y)
285                                 cur_diff_y = ready1 - prev_val_y;
286                         else
287                                 cur_diff_y = prev_val_y - ready1;
289                         if (cur_diff_y < prev_diff_y) {
290                                 prev_diff_y = cur_diff_y;
291                                 val_y = ready1;
292                         }
294                         prev_val_y = ready1;
295                 }
297                 if (val_x > bckup_x) {
298                         diffx = val_x - bckup_x;
299                         diffy = val_y - bckup_y;
300                 } else {
301                         diffx = bckup_x - val_x;
302                         diffy = bckup_y - val_y;
303                 }
304                 bckup_x = val_x;
305                 bckup_y = val_y;
307                 z1 = ((tscadc_readl(ts_dev, TSCADC_REG_FIFO0)) & 0xfff);
308                 z2 = ((tscadc_readl(ts_dev, TSCADC_REG_FIFO1)) & 0xfff);
310                 if ((z1 != 0) && (z2 != 0)) {
311                         /*
312                          * cal pressure using formula
313                          * Resistance(touch) = x plate resistance *
314                          * x postion/4096 * ((z2 / z1) - 1)
315                          */
316                         z = z2 - z1;
317                         z *= val_x;
318                         z *= ts_dev->x_plate_resistance;
319                         z /= z1;
320                         z = (z + 2047) >> 12;
322                         /*
323                          * Sample found inconsistent by debouncing
324                          * or pressure is beyond the maximum.
325                          * Don't report it to user space.
326                          */
327                         if (pen == 0) {
328                                 if ((diffx < 15) && (diffy < 15)
329                                                 && (z <= MAX_12BIT)) {
330                                         input_report_abs(input_dev, ABS_X,
331                                                         val_x);
332                                         input_report_abs(input_dev, ABS_Y,
333                                                         val_y);
334                                         input_report_abs(input_dev, ABS_PRESSURE,
335                                                         z);
336                                         input_report_key(input_dev, BTN_TOUCH,
337                                                         1);
338                                         input_sync(input_dev);
339                                 }
340                         }
341                 }
342                 irqclr |= TSCADC_IRQENB_FIFO1THRES;
343         }
345         udelay(315);
347         status = tscadc_readl(ts_dev, TSCADC_REG_RAWIRQSTATUS);
348         if (status & TSCADC_IRQENB_PENUP) {
349                 /* Pen up event */
350                 fsm = tscadc_readl(ts_dev, TSCADC_REG_ADCFSM);
351                 if (fsm == 0x10) {
352                         pen = 1;
353                         bckup_x = 0;
354                         bckup_y = 0;
355                         input_report_key(input_dev, BTN_TOUCH, 0);
356                         input_report_abs(input_dev, ABS_PRESSURE, 0);
357                         input_sync(input_dev);
358                 } else {
359                         pen = 0;
360                 }
361                 irqclr |= TSCADC_IRQENB_PENUP;
362         }
363         irqclr |= TSCADC_IRQENB_HW_PEN;
365         tscadc_writel(ts_dev, TSCADC_REG_IRQSTATUS, irqclr);
367         /* check pending interrupts */
368         tscadc_writel(ts_dev, TSCADC_REG_IRQEOI, 0x0);
370         tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
371         return IRQ_HANDLED;
374 /*
375 * The functions for inserting/removing driver as a module.
376 */
378 static  int __devinit tscadc_probe(struct platform_device *pdev)
380         struct tscadc                   *ts_dev;
381         struct input_dev                *input_dev;
382         int                             err;
383         int                             clk_value;
384         int                             clock_rate, irqenable, ctrl;
385         struct  tsc_data                *pdata = pdev->dev.platform_data;
386         struct resource                 *res;
387         struct clk                      *clk;
389         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
390         if (!res) {
391                 dev_err(&pdev->dev, "no memory resource defined.\n");
392                 return -EINVAL;
393         }
395         /* Allocate memory for device */
396         ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL);
397         if (!ts_dev) {
398                 dev_err(&pdev->dev, "failed to allocate memory.\n");
399                 return -ENOMEM;
400         }
402         ts_dev->irq = platform_get_irq(pdev, 0);
403         if (ts_dev->irq < 0) {
404                 dev_err(&pdev->dev, "no irq ID is specified.\n");
405                 return -ENODEV;
406         }
408         input_dev = input_allocate_device();
409         if (!input_dev) {
410                 dev_err(&pdev->dev, "failed to allocate input device.\n");
411                 err = -ENOMEM;
412                 goto err_free_mem;
413         }
414         ts_dev->input = input_dev;
416         res =  request_mem_region(res->start, resource_size(res), pdev->name);
417         if (!res) {
418                 dev_err(&pdev->dev, "failed to reserve registers.\n");
419                 err = -EBUSY;
420                 goto err_free_mem;
421         }
423         ts_dev->tsc_base = ioremap(res->start, resource_size(res));
424         if (!ts_dev->tsc_base) {
425                 dev_err(&pdev->dev, "failed to map registers.\n");
426                 err = -ENOMEM;
427                 goto err_release_mem;
428         }
430         err = request_irq(ts_dev->irq, tscadc_interrupt, IRQF_DISABLED,
431                                 pdev->dev.driver->name, ts_dev);
432         if (err) {
433                 dev_err(&pdev->dev, "failed to allocate irq.\n");
434                 goto err_unmap_regs;
435         }
437         pm_runtime_enable(&pdev->dev);
438         pm_runtime_get_sync(&pdev->dev);
440         clk = clk_get(&pdev->dev, "adc_tsc_fck");
441         if (IS_ERR(clk)) {
442                 dev_err(&pdev->dev, "failed to get TSC fck\n");
443                 err = PTR_ERR(clk);
444                 goto err_free_irq;
445         }
446         clock_rate = clk_get_rate(clk);
447         clk_value = clock_rate / ADC_CLK;
448         if (clk_value < 7) {
449                 dev_err(&pdev->dev, "clock input less than min clock requirement\n");
450                 goto err_fail;
451         }
452         /* TSCADC_CLKDIV needs to be configured to the value minus 1 */
453         clk_value = clk_value - 1;
454         tscadc_writel(ts_dev, TSCADC_REG_CLKDIV, clk_value);
456         ts_dev->wires = pdata->wires;
457         ts_dev->analog_input = pdata->analog_input;
458         ts_dev->x_plate_resistance = pdata->x_plate_resistance;
460         /* Set the control register bits */
461         ctrl = TSCADC_CNTRLREG_STEPCONFIGWRT |
462                         TSCADC_CNTRLREG_TSCENB |
463                         TSCADC_CNTRLREG_STEPID;
464         switch (ts_dev->wires) {
465         case 4:
466                 ctrl |= TSCADC_CNTRLREG_4WIRE;
467                 break;
468         case 5:
469                 ctrl |= TSCADC_CNTRLREG_5WIRE;
470                 break;
471         case 8:
472                 ctrl |= TSCADC_CNTRLREG_8WIRE;
473                 break;
474         }
475         tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);
476         ts_dev->ctrl = ctrl;
478         /* Set register bits for Idel Config Mode */
479         tsc_idle_config(ts_dev);
481         /* IRQ Enable */
482         irqenable = TSCADC_IRQENB_FIFO1THRES;
483         tscadc_writel(ts_dev, TSCADC_REG_IRQENABLE, irqenable);
485         tsc_step_config(ts_dev);
487         tscadc_writel(ts_dev, TSCADC_REG_FIFO1THR, 6);
489         ctrl |= TSCADC_CNTRLREG_TSCSSENB;
490         tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);
492         input_dev->name = "ti-tsc-adcc";
493         input_dev->dev.parent = &pdev->dev;
495         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
496         input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
498         input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
499         input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
500         input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
502         /* register to the input system */
503         err = input_register_device(input_dev);
504         if (err)
505                 goto err_fail;
507         device_init_wakeup(&pdev->dev, true);
508         platform_set_drvdata(pdev, ts_dev);
509         return 0;
511 err_fail:
512         pm_runtime_disable(&pdev->dev);
513 err_free_irq:
514         free_irq(ts_dev->irq, ts_dev);
515 err_unmap_regs:
516         iounmap(ts_dev->tsc_base);
517 err_release_mem:
518         release_mem_region(res->start, resource_size(res));
519         input_free_device(ts_dev->input);
520 err_free_mem:
521         kfree(ts_dev);
522         return err;
525 static int __devexit tscadc_remove(struct platform_device *pdev)
527         struct tscadc           *ts_dev = platform_get_drvdata(pdev);
528         struct resource         *res;
530         free_irq(ts_dev->irq, ts_dev);
532         input_unregister_device(ts_dev->input);
534         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
535         iounmap(ts_dev->tsc_base);
536         release_mem_region(res->start, resource_size(res));
538         pm_runtime_disable(&pdev->dev);
540         kfree(ts_dev);
542         device_init_wakeup(&pdev->dev, 0);
543         platform_set_drvdata(pdev, NULL);
544         return 0;
547 static int tscadc_suspend(struct platform_device *pdev, pm_message_t state)
549         struct tscadc *ts_dev = platform_get_drvdata(pdev);
550         unsigned int idle;
552         if (device_may_wakeup(&pdev->dev)) {
553                 idle = tscadc_readl(ts_dev, TSCADC_REG_IRQENABLE);
554                 tscadc_writel(ts_dev, TSCADC_REG_IRQENABLE,
555                                 (idle | TSCADC_IRQENB_HW_PEN));
556                 tscadc_writel(ts_dev, TSCADC_REG_IRQWAKEUP, TSCADC_IRQWKUP_ENB);
557         }
559         /* module disable */
560         idle = 0;
561         idle = tscadc_readl(ts_dev, TSCADC_REG_CTRL);
562         idle &= ~(TSCADC_CNTRLREG_TSCSSENB);
563         tscadc_writel(ts_dev, TSCADC_REG_CTRL, idle);
565         pm_runtime_put_sync(&pdev->dev);
567         return 0;
571 static int tscadc_resume(struct platform_device *pdev)
573         struct tscadc *ts_dev = platform_get_drvdata(pdev);
574         unsigned int restore;
576         pm_runtime_get_sync(&pdev->dev);
578         if (device_may_wakeup(&pdev->dev)) {
579                 tscadc_writel(ts_dev, TSCADC_REG_IRQWAKEUP,
580                                 TSCADC_IRQWKUP_DISABLE);
581                 tscadc_writel(ts_dev, TSCADC_REG_IRQCLR, TSCADC_IRQENB_HW_PEN);
582         }
584         /* context restore */
585         tscadc_writel(ts_dev, TSCADC_REG_CTRL, ts_dev->ctrl);
586         tsc_idle_config(ts_dev);
587         tsc_step_config(ts_dev);
588         tscadc_writel(ts_dev, TSCADC_REG_FIFO1THR, 6);
589         restore = tscadc_readl(ts_dev, TSCADC_REG_CTRL);
590         tscadc_writel(ts_dev, TSCADC_REG_CTRL,
591                         (restore | TSCADC_CNTRLREG_TSCSSENB));
593         return 0;
596 static struct platform_driver ti_tsc_driver = {
597         .probe    = tscadc_probe,
598         .remove  = __devexit_p(tscadc_remove),
599         .driver  = {
600                 .name   = "tsc",
601                 .owner  = THIS_MODULE,
602         },
603         .suspend = tscadc_suspend,
604         .resume  = tscadc_resume,
605 };
607 static int __init ti_tsc_init(void)
609         return platform_driver_register(&ti_tsc_driver);
611 module_init(ti_tsc_init);
613 static void __exit ti_tsc_exit(void)
615         platform_driver_unregister(&ti_tsc_driver);
617 module_exit(ti_tsc_exit);
619 MODULE_DESCRIPTION("TI touchscreen controller driver");
620 MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
621 MODULE_LICENSE("GPL");