linux-ti335x-psp: add 3.2 based on 3.2-staging branch
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 0008-tscadc-Add-general-purpose-mode-untested-with-touchs.patch
1 From 7cb067cd1bd237a7a9978747fc4f96fa90b5d146 Mon Sep 17 00:00:00 2001
2 From: Joel A Fernandes <joelagnel@ti.com>
3 Date: Wed, 30 Nov 2011 15:00:40 +0100
4 Subject: [PATCH 08/16] tscadc: Add general purpose mode, untested with
5  touchscreen functionality
7 Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
9 Conflicts:
11         drivers/input/touchscreen/ti_tscadc.c
12         [Fixed by Koen - needs review]
13 ---
14  arch/arm/mach-omap2/board-am335xevm.c |    2 +
15  arch/arm/mach-omap2/mux33xx.c         |   12 ++
16  arch/arm/mach-omap2/mux33xx.h         |    4 +
17  drivers/input/touchscreen/ti_tscadc.c |  209 +++++++++++++++++++++++++--------
18  include/linux/input/ti_tscadc.h       |    4 +
19  5 files changed, 180 insertions(+), 51 deletions(-)
21 diff --git a/arch/arm/mach-omap2/board-am335xevm.c b/arch/arm/mach-omap2/board-am335xevm.c
22 index 87ccf14..c7bb091 100644
23 --- a/arch/arm/mach-omap2/board-am335xevm.c
24 +++ b/arch/arm/mach-omap2/board-am335xevm.c
25 @@ -2182,6 +2182,7 @@ static struct evm_dev_cfg beaglebone_old_dev_cfg[] = {
26         {i2c2_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
27         {mmc0_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
28         {boneleds_init, DEV_ON_BASEBOARD, PROFILE_ALL},
29 +       {tsc_init,      DEV_ON_BASEBOARD, PROFILE_ALL},
30         {NULL, 0, 0},
31  };
32  
33 @@ -2194,6 +2195,7 @@ static struct evm_dev_cfg beaglebone_dev_cfg[] = {
34         {i2c2_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
35         {mmc0_init,     DEV_ON_BASEBOARD, PROFILE_NONE},
36         {boneleds_init, DEV_ON_BASEBOARD, PROFILE_ALL},
37 +       {tsc_init,      DEV_ON_BASEBOARD, PROFILE_ALL},
38         {NULL, 0, 0},
39  };
40  
41 diff --git a/arch/arm/mach-omap2/mux33xx.c b/arch/arm/mach-omap2/mux33xx.c
42 index 36bb10a..e4cd407 100644
43 --- a/arch/arm/mach-omap2/mux33xx.c
44 +++ b/arch/arm/mach-omap2/mux33xx.c
45 @@ -584,6 +584,18 @@ static struct omap_mux __initdata am33xx_muxmodes[] = {
46         _AM33XX_MUXENTRY(AIN3, 0,
47                 "ain3", NULL, NULL, NULL,
48                 NULL, NULL, NULL, NULL),
49 +       _AM33XX_MUXENTRY(AIN4, 0,
50 +               "ain4", NULL, NULL, NULL,
51 +               NULL, NULL, NULL, NULL),
52 +       _AM33XX_MUXENTRY(AIN5, 0,
53 +               "ain5", NULL, NULL, NULL,
54 +               NULL, NULL, NULL, NULL),
55 +       _AM33XX_MUXENTRY(AIN6, 0,
56 +               "ain6", NULL, NULL, NULL,
57 +               NULL, NULL, NULL, NULL),
58 +       _AM33XX_MUXENTRY(AIN7, 0,
59 +               "ain7", NULL, NULL, NULL,
60 +               NULL, NULL, NULL, NULL),
61         _AM33XX_MUXENTRY(VREFP, 0,
62                 "vrefp", NULL, NULL, NULL,
63                 NULL, NULL, NULL, NULL),
64 diff --git a/arch/arm/mach-omap2/mux33xx.h b/arch/arm/mach-omap2/mux33xx.h
65 index 70a3012..348c8e5 100644
66 --- a/arch/arm/mach-omap2/mux33xx.h
67 +++ b/arch/arm/mach-omap2/mux33xx.h
68 @@ -228,6 +228,10 @@
69  #define AM33XX_CONTROL_PADCONF_DDR_DQSN1_OFFSET                        0x0AFC
70  #define AM33XX_CONTROL_PADCONF_DDR_VREF_OFFSET                 0x0B00
71  #define AM33XX_CONTROL_PADCONF_DDR_VTP_OFFSET                  0x0B04
72 +#define AM33XX_CONTROL_PADCONF_AIN7_OFFSET                     0x0B10
73 +#define AM33XX_CONTROL_PADCONF_AIN6_OFFSET                     0x0B14
74 +#define AM33XX_CONTROL_PADCONF_AIN5_OFFSET                     0x0B18
75 +#define AM33XX_CONTROL_PADCONF_AIN4_OFFSET                     0x0B1C
76  #define AM33XX_CONTROL_PADCONF_AIN3_OFFSET                     0x0B20
77  #define AM33XX_CONTROL_PADCONF_AIN2_OFFSET                     0x0B24
78  #define AM33XX_CONTROL_PADCONF_AIN1_OFFSET                     0x0B28
79 diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
80 index e3b5775..699503d 100644
81 --- a/drivers/input/touchscreen/ti_tscadc.c
82 +++ b/drivers/input/touchscreen/ti_tscadc.c
83 @@ -27,6 +27,8 @@
84  #include <linux/input/ti_tscadc.h>
85  #include <linux/delay.h>
86  
87 +/* Memory mapped registers here have incorrect offsets!
88 + * Correct after referring TRM */
89  #define TSCADC_REG_IRQEOI              0x020
90  #define TSCADC_REG_RAWIRQSTATUS                0x024
91  #define TSCADC_REG_IRQSTATUS           0x028
92 @@ -54,12 +56,18 @@
93  
94  /*     Register Bitfields      */
95  #define TSCADC_IRQWKUP_ENB             BIT(0)
96 -#define TSCADC_STPENB_STEPENB          0x7FFF
97 +#define TSCADC_STPENB_STEPENB_TOUCHSCREEN      0x7FFF
98 +#define TSCADC_STPENB_STEPENB_GENERAL          0x0400
99  #define TSCADC_IRQENB_FIFO0THRES       BIT(2)
100 +#define TSCADC_IRQENB_FIFO0OVERRUN     BIT(3)
101  #define TSCADC_IRQENB_FIFO1THRES       BIT(5)
102 +#define TSCADC_IRQENB_EOS              BIT(1)
103  #define TSCADC_IRQENB_PENUP            BIT(9)
104 -#define TSCADC_STEPCONFIG_MODE_HWSYNC  0x2
105 +#define TSCADC_STEPCONFIG_MODE_HWSYNC          0x2
106 +#define TSCADC_STEPCONFIG_MODE_SWCONT          0x1
107 +#define TSCADC_STEPCONFIG_MODE_SWONESHOT       0x0
108  #define TSCADC_STEPCONFIG_2SAMPLES_AVG (1 << 4)
109 +#define TSCADC_STEPCONFIG_NO_AVG       0
110  #define TSCADC_STEPCONFIG_XPP          BIT(5)
111  #define TSCADC_STEPCONFIG_XNN          BIT(6)
112  #define TSCADC_STEPCONFIG_YPP          BIT(7)
113 @@ -105,6 +113,7 @@ struct tscadc {
114         int                     analog_input;
115         int                     x_plate_resistance;
116         struct clk              *tsc_ick;
117 +       int mode;
118         int                     irq;
119         void __iomem            *tsc_base;
120  };
121 @@ -120,6 +129,86 @@ static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
122         writel(val, tsc->tsc_base + reg);
123  }
124  
125 +static void tsc_adc_step_config(struct tscadc *ts_dev)
126 +{
127 +       unsigned int    stepconfig = 0, delay = 0, chargeconfig = 0;
129 +       /*
130 +        * Step Configuration
131 +        * software-enabled continous mode
132 +        * 2 sample averaging
133 +        * sample channel 1 (SEL_INP mux bits = 0)
134 +        */
135 +       stepconfig = TSCADC_STEPCONFIG_MODE_SWONESHOT |
136 +               TSCADC_STEPCONFIG_2SAMPLES_AVG |
137 +               (0x7 << 19);
139 +       delay = TSCADC_STEPCONFIG_SAMPLEDLY | TSCADC_STEPCONFIG_OPENDLY;
141 +       tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG(10), stepconfig);
142 +       tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY(10), delay);
144 +       /* Get the ball rolling, this will trigger the FSM to step through
145 +        * as soon as TSC_ADC_SS is turned on */
146 +       tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_GENERAL);
147 +}
149 +static irqreturn_t tsc_adc_interrupt(int irq, void *dev)
150 +{
151 +       struct tscadc           *ts_dev = (struct tscadc *)dev;
152 +       struct input_dev        *input_dev = ts_dev->input;
153 +       unsigned int            status, irqclr = 0;
154 +       int                     i;
155 +       int                     fsm = 0, fifo0count = 0, fifo1count = 0;
156 +       unsigned int            read_sample = 0, ready1 = 0;
157 +       unsigned int            prev_val_x = ~0, prev_val_y = ~0;
158 +       unsigned int            prev_diff_x = ~0, prev_diff_y = ~0;
159 +       unsigned int            cur_diff_x = 0, cur_diff_y = 0;
160 +       unsigned int            val_x = 0, val_y = 0, diffx = 0, diffy = 0;
162 +       status = tscadc_readl(ts_dev, TSCADC_REG_IRQSTATUS);
164 +       printk("interrupt! status=%x\n", status);
165 +       // if (status & TSCADC_IRQENB_EOS) {
166 +       //      irqclr |= TSCADC_IRQENB_EOS;
167 +       // }
169 +       if (status & TSCADC_IRQENB_FIFO0THRES) {
170 +               fifo1count = tscadc_readl(ts_dev, TSCADC_REG_FIFO0CNT);
171 +               printk("fifo 0 count = %d\n", fifo1count);
172 +       
173 +               for (i = 0; i < fifo1count; i++) {
174 +                       read_sample = tscadc_readl(ts_dev, TSCADC_REG_FIFO0);
175 +                       printk("sample: %d: %x\n", i, read_sample);
176 +               }
177 +               irqclr |= TSCADC_IRQENB_FIFO0THRES;
178 +       }
181 +       if (status & TSCADC_IRQENB_FIFO1THRES) {
182 +               fifo1count = tscadc_readl(ts_dev, TSCADC_REG_FIFO1CNT);
184 +               for (i = 0; i < fifo1count; i++) {
185 +                       read_sample = tscadc_readl(ts_dev, TSCADC_REG_FIFO1);
186 +                       // read_sample = read_sample & 0xfff;
187 +                       printk("sample: %d: %d\n", i, read_sample);
188 +                       panic("sample read from fifo1!");
189 +               }
190 +               irqclr |= TSCADC_IRQENB_FIFO1THRES;
191 +       }
193 +       mdelay(500);
195 +       tscadc_writel(ts_dev, TSCADC_REG_IRQSTATUS, irqclr);
197 +       /* check pending interrupts */
198 +       tscadc_writel(ts_dev, TSCADC_REG_IRQEOI, 0x0);
200 +       /* Turn on Step 1 again */
201 +       tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_GENERAL);
202 +       return IRQ_HANDLED;
203 +}
205  static void tsc_step_config(struct tscadc *ts_dev)
206  {
207         unsigned int    stepconfigx = 0, stepconfigy = 0;
208 @@ -224,7 +313,7 @@ static void tsc_step_config(struct tscadc *ts_dev)
209         tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG14, stepconfigz2);
210         tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY14, delay);
211  
212 -       tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
213 +       tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_TOUCHSCREEN);
214  }
215  
216  static void tsc_idle_config(struct tscadc *ts_config)
217 @@ -242,7 +331,7 @@ static void tsc_idle_config(struct tscadc *ts_config)
218         tscadc_writel(ts_config, TSCADC_REG_IDLECONFIG, idleconfig);
219  }
220  
221 -static irqreturn_t tscadc_interrupt(int irq, void *dev)
222 +static irqreturn_t tsc_interrupt(int irq, void *dev)
223  {
224         struct tscadc           *ts_dev = (struct tscadc *)dev;
225         struct input_dev        *input_dev = ts_dev->input;
226 @@ -362,7 +451,7 @@ static irqreturn_t tscadc_interrupt(int irq, void *dev)
227         /* check pending interrupts */
228         tscadc_writel(ts_dev, TSCADC_REG_IRQEOI, 0x0);
229  
230 -       tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
231 +       tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_TOUCHSCREEN);
232         return IRQ_HANDLED;
233  }
234  
235 @@ -400,13 +489,15 @@ static    int __devinit tscadc_probe(struct platform_device *pdev)
236                 return -ENODEV;
237         }
238  
239 -       input_dev = input_allocate_device();
240 -       if (!input_dev) {
241 -               dev_err(&pdev->dev, "failed to allocate input device.\n");
242 -               err = -ENOMEM;
243 -               goto err_free_mem;
244 +       if(pdata->mode == TI_TSCADC_TSCMODE) {
245 +               input_dev = input_allocate_device();
246 +               if (!input_dev) {
247 +                       dev_err(&pdev->dev, "failed to allocate input device.\n");
248 +                       err = -ENOMEM;
249 +                       goto err_free_mem;
250 +               }
251 +               ts_dev->input = input_dev;
252         }
253 -       ts_dev->input = input_dev;
254  
255         res =  request_mem_region(res->start, resource_size(res), pdev->name);
256         if (!res) {
257 @@ -422,8 +513,15 @@ static     int __devinit tscadc_probe(struct platform_device *pdev)
258                 goto err_release_mem;
259         }
260  
261 -       err = request_irq(ts_dev->irq, tscadc_interrupt, IRQF_DISABLED,
262 -                               pdev->dev.driver->name, ts_dev);
263 +       if(pdata->mode == TI_TSCADC_TSCMODE) {
264 +               err = request_irq(ts_dev->irq, tsc_interrupt, IRQF_DISABLED,
265 +                                       pdev->dev.driver->name, ts_dev);
266 +       }
267 +       else {
268 +               err = request_irq(ts_dev->irq, tsc_adc_interrupt, IRQF_DISABLED,
269 +                                       pdev->dev.driver->name, ts_dev);
270 +       }
272         if (err) {
273                 dev_err(&pdev->dev, "failed to allocate irq.\n");
274                 goto err_unmap_regs;
275 @@ -443,11 +541,17 @@ static    int __devinit tscadc_probe(struct platform_device *pdev)
276                 goto err_free_irq;
277         }
278         clock_rate = clk_get_rate(clk);
280 +       /* clk_value of atleast 21MHz required
281 +        * Clock verified on BeagleBone to be 24MHz */
284         clk_value = clock_rate / ADC_CLK;
285         if (clk_value < 7) {
286                 dev_err(&pdev->dev, "clock input less than min clock requirement\n");
287                 goto err_fail;
288         }
290         /* TSCADC_CLKDIV needs to be configured to the value minus 1 */
291         clk_value = clk_value - 1;
292         tscadc_writel(ts_dev, TSCADC_REG_CLKDIV, clk_value);
293 @@ -458,57 +562,60 @@ static    int __devinit tscadc_probe(struct platform_device *pdev)
294         ts_dev->wires = pdata->wires;
295         ts_dev->analog_input = pdata->analog_input;
296         ts_dev->x_plate_resistance = pdata->x_plate_resistance;
297 +       ts_dev->mode = pdata->mode;
298  
299 -       /* Set the control register bits */
300 +       /* Set the control register bits - 12.5.44 TRM */
301         ctrl = TSCADC_CNTRLREG_STEPCONFIGWRT |
302 -                       TSCADC_CNTRLREG_TSCENB |
303 -                       TSCADC_CNTRLREG_STEPID;
304 -       switch (ts_dev->wires) {
305 -       case 4:
306 -               ctrl |= TSCADC_CNTRLREG_4WIRE;
307 -               break;
308 -       case 5:
309 -               ctrl |= TSCADC_CNTRLREG_5WIRE;
310 -               break;
311 -       case 8:
312 -               ctrl |= TSCADC_CNTRLREG_8WIRE;
313 -               break;
314 +                               TSCADC_CNTRLREG_STEPID;
315 +       if(pdata->mode == TI_TSCADC_TSCMODE) {
316 +               ctrl |= TSCADC_CNTRLREG_TSCENB;
317 +               switch (ts_dev->wires) {
318 +                       case 4:
319 +                               ctrl |= TSCADC_CNTRLREG_4WIRE;
320 +                               break;
321 +                       case 5:
322 +                               ctrl |= TSCADC_CNTRLREG_5WIRE;
323 +                               break;
324 +                       case 8:
325 +                               ctrl |= TSCADC_CNTRLREG_8WIRE;
326 +                               break;
327 +               }
328         }
329         tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);
330  
331 -       /* Set register bits for Idel Config Mode */
332 -       tsc_idle_config(ts_dev);
334 -       /* IRQ Enable */
335 -       irqenable = TSCADC_IRQENB_FIFO1THRES;
336 +       /* Touch screen / ADC configuration */
337 +       if(pdata->mode == TI_TSCADC_TSCMODE) {
338 +               tsc_idle_config(ts_dev);
339 +               tsc_step_config(ts_dev);
340 +               tscadc_writel(ts_dev, TSCADC_REG_FIFO1THR, 6);
341 +               irqenable = TSCADC_IRQENB_FIFO1THRES;
342 +               /* Touch screen also needs an input_dev */
343 +               input_dev->name = "ti-tsc-adcc";
344 +               input_dev->dev.parent = &pdev->dev;
345 +               input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
346 +               input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
347 +               input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
348 +               input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
349 +               /* register to the input system */
350 +               err = input_register_device(input_dev);
351 +               if (err)
352 +                       goto err_fail;
353 +       }
354 +       else {
355 +               tsc_adc_step_config(ts_dev);
356 +               tscadc_writel(ts_dev, TSCADC_REG_FIFO0THR, 0);
357 +               irqenable = TSCADC_IRQENB_FIFO0THRES;
358 +       }
359         tscadc_writel(ts_dev, TSCADC_REG_IRQENABLE, irqenable);
360  
361 -       tsc_step_config(ts_dev);
363 -       tscadc_writel(ts_dev, TSCADC_REG_FIFO1THR, 6);
365         ctrl |= TSCADC_CNTRLREG_TSCSSENB;
366 -       tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);
368 -       input_dev->name = "ti-tsc-adcc";
369 -       input_dev->dev.parent = &pdev->dev;
371 -       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
372 -       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
374 -       input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
375 -       input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
376 -       input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
378 -       /* register to the input system */
379 -       err = input_register_device(input_dev);
380 -       if (err)
381 -               goto err_fail;
382 +       tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);   /* Turn on TSC_ADC */
383  
384         platform_set_drvdata(pdev, ts_dev);
385         return 0;
386  
387  err_fail:
388 +       printk(KERN_ERR "Fatal error, shutting down TSC_ADC\n");
389         clk_disable(ts_dev->tsc_ick);
390         clk_put(ts_dev->tsc_ick);
391  err_free_irq:
392 diff --git a/include/linux/input/ti_tscadc.h b/include/linux/input/ti_tscadc.h
393 index 2c547bb..850cd4b 100644
394 --- a/include/linux/input/ti_tscadc.h
395 +++ b/include/linux/input/ti_tscadc.h
396 @@ -14,8 +14,12 @@
397   * @x_plate_resistance:        X plate resistance.
398   */
399  
400 +#define TI_TSCADC_TSCMODE 0
401 +#define TI_TSCADC_GENMODE 1
403  struct tsc_data {
404         int wires;
405         int analog_input;
406         int x_plate_resistance;
407 +       int mode;
408  };
409 -- 
410 1.7.7.5