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