add support for target 3c24xx (more known as Openmoko GTA02 "Freerunner") and merge...
[openwrt.git] / target / linux / s3c24xx / patches / 0014-s3c2410_touchscreen.patch.patch
1 From fc5d5366335469828d78898e2e74f8f80aa1d076 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Wed, 16 Jul 2008 14:44:49 +0100
4 Subject: [PATCH] s3c2410_touchscreen.patch
5
6 ---
7  arch/arm/mach-s3c2410/mach-h1940.c     |    8 +
8  arch/arm/plat-s3c24xx/devs.c           |   18 ++
9  arch/arm/plat-s3c24xx/s3c244x.c        |    1 +
10  drivers/input/touchscreen/Kconfig      |   18 ++
11  drivers/input/touchscreen/Makefile     |    1 +
12  drivers/input/touchscreen/s3c2410_ts.c |  437 ++++++++++++++++++++++++++++++++
13  include/asm-arm/arch-s3c2410/ts.h      |   28 ++
14  include/asm-arm/plat-s3c24xx/devs.h    |    1 +
15  8 files changed, 512 insertions(+), 0 deletions(-)
16  create mode 100644 drivers/input/touchscreen/s3c2410_ts.c
17  create mode 100644 include/asm-arm/arch-s3c2410/ts.h
18
19 diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
20 index 7c1145e..93cd8c8 100644
21 --- a/arch/arm/mach-s3c2410/mach-h1940.c
22 +++ b/arch/arm/mach-s3c2410/mach-h1940.c
23 @@ -38,6 +38,7 @@
24  #include <asm/arch/h1940.h>
25  #include <asm/arch/h1940-latch.h>
26  #include <asm/arch/fb.h>
27 +#include <asm/arch/tc.h>
28  #include <asm/plat-s3c24xx/udc.h>
29  
30  #include <asm/plat-s3c24xx/clock.h>
31 @@ -129,6 +130,11 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
32         .vbus_pin_inverted      = 1,
33  };
34  
35 +static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
36 +               .delay = 10000,
37 +               .presc = 49,
38 +               .oversampling_shift = 2,
39 +};
40  
41  /**
42   * Set lcd on or off
43 @@ -186,6 +192,7 @@ static struct platform_device *h1940_devices[] __initdata = {
44         &s3c_device_i2c,
45         &s3c_device_iis,
46         &s3c_device_usbgadget,
47 +       &s3c_device_ts,
48         &s3c_device_leds,
49         &s3c_device_bluetooth,
50  };
51 @@ -214,6 +221,7 @@ static void __init h1940_init(void)
52         u32 tmp;
53  
54         s3c24xx_fb_set_platdata(&h1940_fb_info);
55 +       set_s3c2410ts_info(&h1940_ts_cfg);
56         s3c24xx_udc_set_platdata(&h1940_udc_cfg);
57  
58         /* Turn off suspend on both USB ports, and switch the
59 diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
60 index e546e93..c1fbe2d 100644
61 --- a/arch/arm/plat-s3c24xx/devs.c
62 +++ b/arch/arm/plat-s3c24xx/devs.c
63 @@ -24,6 +24,7 @@
64  #include <asm/mach/map.h>
65  #include <asm/mach/irq.h>
66  #include <asm/arch/fb.h>
67 +#include <asm/arch/ts.h>
68  #include <asm/hardware.h>
69  #include <asm/io.h>
70  #include <asm/irq.h>
71 @@ -207,6 +208,23 @@ struct platform_device s3c_device_nand = {
72  
73  EXPORT_SYMBOL(s3c_device_nand);
74  
75 +/* Touchscreen */
76 +struct platform_device s3c_device_ts = {
77 +       .name             = "s3c2410-ts",
78 +       .id               = -1,
79 +};
80 +
81 +EXPORT_SYMBOL(s3c_device_ts);
82 +
83 +static struct s3c2410_ts_mach_info s3c2410ts_info;
84 +
85 +void set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
86 +{
87 +       memcpy(&s3c2410ts_info,hard_s3c2410ts_info,sizeof(struct s3c2410_ts_mach_info));
88 +       s3c_device_ts.dev.platform_data = &s3c2410ts_info;
89 +}
90 +EXPORT_SYMBOL(set_s3c2410ts_info);
91 +
92  /* USB Device (Gadget)*/
93  
94  static struct resource s3c_usbgadget_resource[] = {
95 diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
96 index 2f01af5..7a1a12d 100644
97 --- a/arch/arm/plat-s3c24xx/s3c244x.c
98 +++ b/arch/arm/plat-s3c24xx/s3c244x.c
99 @@ -68,6 +68,7 @@ void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
100         s3c_device_sdi.name  = "s3c2440-sdi";
101         s3c_device_i2c.name  = "s3c2440-i2c";
102         s3c_device_nand.name = "s3c2440-nand";
103 +       s3c_device_ts.name = "s3c2440-ts";
104         s3c_device_usbgadget.name = "s3c2440-usbgadget";
105  }
106  
107 diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
108 index 565ec71..52de2b0 100644
109 --- a/drivers/input/touchscreen/Kconfig
110 +++ b/drivers/input/touchscreen/Kconfig
111 @@ -67,6 +67,24 @@ config TOUCHSCREEN_FUJITSU
112           To compile this driver as a module, choose M here: the
113           module will be called fujitsu-ts.
114  
115 +config TOUCHSCREEN_S3C2410
116 +       tristate "Samsung S3C2410 touchscreen input driver"
117 +       depends on ARCH_S3C2410 && INPUT && INPUT_TOUCHSCREEN
118 +       select SERIO
119 +       help
120 +         Say Y here if you have the s3c2410 touchscreen.
121 +
122 +         If unsure, say N.
123 +
124 +         To compile this driver as a module, choose M here: the
125 +         module will be called s3c2410_ts.
126 +
127 +config TOUCHSCREEN_S3C2410_DEBUG
128 +       boolean "Samsung S3C2410 touchscreen debug messages"
129 +       depends on TOUCHSCREEN_S3C2410
130 +       help
131 +         Select this if you want debug messages
132 +
133  config TOUCHSCREEN_GUNZE
134         tristate "Gunze AHL-51S touchscreen"
135         select SERIO
136 diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
137 index 3c096d7..7c3bd1c 100644
138 --- a/drivers/input/touchscreen/Makefile
139 +++ b/drivers/input/touchscreen/Makefile
140 @@ -26,3 +26,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)        += wm9705.o
141  wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
142  wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
143  obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)     += mainstone-wm97xx.o
144 +obj-$(CONFIG_TOUCHSCREEN_S3C2410)      += s3c2410_ts.o
145 diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
146 new file mode 100644
147 index 0000000..68071c2
148 --- /dev/null
149 +++ b/drivers/input/touchscreen/s3c2410_ts.c
150 @@ -0,0 +1,437 @@
151 +/*
152 + * This program is free software; you can redistribute it and/or modify
153 + * it under the terms of the GNU General Public License as published by
154 + * the Free Software Foundation; either version 2 of the License, or
155 + * (at your option) any later version.
156 + *
157 + * This program is distributed in the hope that it will be useful,
158 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
159 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
160 + * GNU General Public License for more details.
161 + *
162 + * You should have received a copy of the GNU General Public License
163 + * along with this program; if not, write to the Free Software
164 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
165 + *
166 + * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
167 + * iPAQ H1940 touchscreen support
168 + *
169 + * ChangeLog
170 + *
171 + * 2004-09-05: Herbert Pƶtzl <herbert@13thfloor.at>
172 + *     - added clock (de-)allocation code
173 + *
174 + * 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>
175 + *      - h1940_ -> s3c2410 (this driver is now also used on the n30
176 + *        machines :P)
177 + *      - Debug messages are now enabled with the config option
178 + *        TOUCHSCREEN_S3C2410_DEBUG
179 + *      - Changed the way the value are read
180 + *      - Input subsystem should now work
181 + *      - Use ioremap and readl/writel
182 + *
183 + * 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>
184 + *      - Make use of some undocumented features of the touchscreen
185 + *        controller
186 + *
187 + * 2007-05-23: Harald Welte <laforge@openmoko.org>
188 + *     - Add proper support for S32440
189 + */
190 +
191 +#include <linux/errno.h>
192 +#include <linux/kernel.h>
193 +#include <linux/module.h>
194 +#include <linux/slab.h>
195 +#include <linux/input.h>
196 +#include <linux/init.h>
197 +#include <linux/serio.h>
198 +#include <linux/delay.h>
199 +#include <linux/platform_device.h>
200 +#include <linux/clk.h>
201 +#include <asm/io.h>
202 +#include <asm/irq.h>
203 +
204 +#include <asm/arch/regs-gpio.h>
205 +#include <asm/arch/ts.h>
206 +
207 +#include <asm/plat-s3c/regs-adc.h>
208 +
209 +/* For ts.dev.id.version */
210 +#define S3C2410TSVERSION       0x0101
211 +
212 +#define TSC_SLEEP  (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
213 +
214 +#define WAIT4INT(x)  (((x)<<8) | \
215 +                    S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
216 +                    S3C2410_ADCTSC_XY_PST(3))
217 +
218 +#define AUTOPST             (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
219 +                    S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
220 +
221 +#define DEBUG_LVL    KERN_DEBUG
222 +
223 +MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
224 +MODULE_DESCRIPTION("s3c2410 touchscreen driver");
225 +MODULE_LICENSE("GPL");
226 +
227 +/*
228 + * Definitions & global arrays.
229 + */
230 +
231 +
232 +static char *s3c2410ts_name = "s3c2410 TouchScreen";
233 +
234 +/*
235 + * Per-touchscreen data.
236 + */
237 +
238 +struct s3c2410ts {
239 +       struct input_dev *dev;
240 +       long xp;
241 +       long yp;
242 +       int count;
243 +       int shift;
244 +};
245 +
246 +static struct s3c2410ts ts;
247 +static void __iomem *base_addr;
248 +
249 +static inline void s3c2410_ts_connect(void)
250 +{
251 +       s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
252 +       s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
253 +       s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
254 +       s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
255 +}
256 +
257 +static void touch_timer_fire(unsigned long data)
258 +{
259 +       unsigned long data0;
260 +       unsigned long data1;
261 +       int updown;
262 +
263 +       data0 = readl(base_addr+S3C2410_ADCDAT0);
264 +       data1 = readl(base_addr+S3C2410_ADCDAT1);
265 +
266 +       updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
267 +
268 +       if (updown) {
269 +               if (ts.count != 0) {
270 +                       ts.xp >>= ts.shift;
271 +                       ts.yp >>= ts.shift;
272 +
273 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
274 +                       {
275 +                               struct timeval tv;
276 +                               do_gettimeofday(&tv);
277 +                               printk(DEBUG_LVL "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts.xp, ts.yp);
278 +                       }
279 +#endif
280 +
281 +                       input_report_abs(ts.dev, ABS_X, ts.xp);
282 +                       input_report_abs(ts.dev, ABS_Y, ts.yp);
283 +
284 +                       input_report_key(ts.dev, BTN_TOUCH, 1);
285 +                       input_report_abs(ts.dev, ABS_PRESSURE, 1);
286 +                       input_sync(ts.dev);
287 +               }
288 +
289 +               ts.xp = 0;
290 +               ts.yp = 0;
291 +               ts.count = 0;
292 +
293 +               writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
294 +               writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
295 +       } else {
296 +               ts.count = 0;
297 +
298 +               input_report_key(ts.dev, BTN_TOUCH, 0);
299 +               input_report_abs(ts.dev, ABS_PRESSURE, 0);
300 +               input_sync(ts.dev);
301 +
302 +               writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
303 +       }
304 +}
305 +
306 +static struct timer_list touch_timer =
307 +               TIMER_INITIALIZER(touch_timer_fire, 0, 0);
308 +
309 +static irqreturn_t stylus_updown(int irq, void *dev_id)
310 +{
311 +       unsigned long data0;
312 +       unsigned long data1;
313 +       int updown;
314 +
315 +       data0 = readl(base_addr+S3C2410_ADCDAT0);
316 +       data1 = readl(base_addr+S3C2410_ADCDAT1);
317 +
318 +       updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
319 +
320 +       /* TODO we should never get an interrupt with updown set while
321 +        * the timer is running, but maybe we ought to verify that the
322 +        * timer isn't running anyways. */
323 +
324 +       if (updown)
325 +               touch_timer_fire(0);
326 +
327 +       return IRQ_HANDLED;
328 +}
329 +
330 +
331 +static irqreturn_t stylus_action(int irq, void *dev_id)
332 +{
333 +       unsigned long data0;
334 +       unsigned long data1;
335 +
336 +       data0 = readl(base_addr+S3C2410_ADCDAT0);
337 +       data1 = readl(base_addr+S3C2410_ADCDAT1);
338 +
339 +       ts.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
340 +       ts.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
341 +       ts.count++;
342 +
343 +        if (ts.count < (1<<ts.shift)) {
344 +               writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
345 +               writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
346 +       } else {
347 +               mod_timer(&touch_timer, jiffies+1);
348 +               writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
349 +       }
350 +
351 +       return IRQ_HANDLED;
352 +}
353 +
354 +static struct clk      *adc_clock;
355 +
356 +/*
357 + * The functions for inserting/removing us as a module.
358 + */
359 +
360 +static int __init s3c2410ts_probe(struct platform_device *pdev)
361 +{
362 +       int rc;
363 +       struct s3c2410_ts_mach_info *info;
364 +       struct input_dev *input_dev;
365 +
366 +       info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
367 +
368 +       if (!info)
369 +       {
370 +               printk(KERN_ERR "Hm... too bad : no platform data for ts\n");
371 +               return -EINVAL;
372 +       }
373 +
374 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
375 +       printk(DEBUG_LVL "Entering s3c2410ts_init\n");
376 +#endif
377 +
378 +       adc_clock = clk_get(NULL, "adc");
379 +       if (!adc_clock) {
380 +               printk(KERN_ERR "failed to get adc clock source\n");
381 +               return -ENOENT;
382 +       }
383 +       clk_enable(adc_clock);
384 +
385 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
386 +       printk(DEBUG_LVL "got and enabled clock\n");
387 +#endif
388 +
389 +       base_addr = ioremap(S3C2410_PA_ADC,0x20);
390 +       if (base_addr == NULL) {
391 +               printk(KERN_ERR "Failed to remap register block\n");
392 +               return -ENOMEM;
393 +       }
394 +
395 +
396 +       /* If we acutally are a S3C2410: Configure GPIOs */
397 +       if (!strcmp(pdev->name, "s3c2410-ts"))
398 +               s3c2410_ts_connect();
399 +
400 +       if ((info->presc&0xff) > 0)
401 +               writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
402 +                            base_addr+S3C2410_ADCCON);
403 +       else
404 +               writel(0,base_addr+S3C2410_ADCCON);
405 +
406 +
407 +       /* Initialise registers */
408 +       if ((info->delay&0xffff) > 0)
409 +               writel(info->delay & 0xffff,  base_addr+S3C2410_ADCDLY);
410 +
411 +       writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
412 +
413 +       /* Initialise input stuff */
414 +       memset(&ts, 0, sizeof(struct s3c2410ts));
415 +       input_dev = input_allocate_device();
416 +
417 +       if (!input_dev) {
418 +               printk(KERN_ERR "Unable to allocate the input device !!\n");
419 +               return -ENOMEM;
420 +       }
421 +
422 +       ts.dev = input_dev;
423 +       ts.dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) |
424 +                          BIT_MASK(EV_ABS);
425 +       ts.dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
426 +       input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);
427 +       input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
428 +       input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
429 +
430 +       ts.dev->private = &ts;
431 +       ts.dev->name = s3c2410ts_name;
432 +       ts.dev->id.bustype = BUS_RS232;
433 +       ts.dev->id.vendor = 0xDEAD;
434 +       ts.dev->id.product = 0xBEEF;
435 +       ts.dev->id.version = S3C2410TSVERSION;
436 +
437 +       ts.shift = info->oversampling_shift;
438 +
439 +       /* Get irqs */
440 +       if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,
441 +               "s3c2410_action", ts.dev)) {
442 +               printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");
443 +               iounmap(base_addr);
444 +               return -EIO;
445 +       }
446 +       if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
447 +                       "s3c2410_action", ts.dev)) {
448 +               printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
449 +               free_irq(IRQ_ADC, ts.dev);
450 +               iounmap(base_addr);
451 +               return -EIO;
452 +       }
453 +
454 +       printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);
455 +
456 +       /* All went ok, so register to the input system */
457 +       rc = input_register_device(ts.dev);
458 +       if (rc) {
459 +               free_irq(IRQ_TC, ts.dev);
460 +               free_irq(IRQ_ADC, ts.dev);
461 +               clk_disable(adc_clock);
462 +               iounmap(base_addr);
463 +               return -EIO;
464 +       }
465 +
466 +       return 0;
467 +}
468 +
469 +static int s3c2410ts_remove(struct platform_device *pdev)
470 +{
471 +       disable_irq(IRQ_ADC);
472 +       disable_irq(IRQ_TC);
473 +       free_irq(IRQ_TC,ts.dev);
474 +       free_irq(IRQ_ADC,ts.dev);
475 +
476 +       if (adc_clock) {
477 +               clk_disable(adc_clock);
478 +               clk_put(adc_clock);
479 +               adc_clock = NULL;
480 +       }
481 +
482 +       input_unregister_device(ts.dev);
483 +       iounmap(base_addr);
484 +
485 +       return 0;
486 +}
487 +
488 +#ifdef CONFIG_PM
489 +static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state)
490 +{
491 +       writel(TSC_SLEEP, base_addr+S3C2410_ADCTSC);
492 +       writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,
493 +              base_addr+S3C2410_ADCCON);
494 +
495 +       disable_irq(IRQ_ADC);
496 +       disable_irq(IRQ_TC);
497 +
498 +       clk_disable(adc_clock);
499 +
500 +       return 0;
501 +}
502 +
503 +static int s3c2410ts_resume(struct platform_device *pdev)
504 +{
505 +       struct s3c2410_ts_mach_info *info =
506 +               ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
507 +
508 +       clk_enable(adc_clock);
509 +       msleep(1);
510 +
511 +       enable_irq(IRQ_ADC);
512 +       enable_irq(IRQ_TC);
513 +
514 +       if ((info->presc&0xff) > 0)
515 +               writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
516 +                            base_addr+S3C2410_ADCCON);
517 +       else
518 +               writel(0,base_addr+S3C2410_ADCCON);
519 +
520 +       /* Initialise registers */
521 +       if ((info->delay&0xffff) > 0)
522 +               writel(info->delay & 0xffff,  base_addr+S3C2410_ADCDLY);
523 +
524 +       writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
525 +
526 +       return 0;
527 +}
528 +
529 +#else
530 +#define s3c2410ts_suspend NULL
531 +#define s3c2410ts_resume  NULL
532 +#endif
533 +
534 +static struct platform_driver s3c2410ts_driver = {
535 +       .driver         = {
536 +              .name   = "s3c2410-ts",
537 +              .owner  = THIS_MODULE,
538 +       },
539 +       .probe          = s3c2410ts_probe,
540 +       .remove         = s3c2410ts_remove,
541 +       .suspend        = s3c2410ts_suspend,
542 +       .resume         = s3c2410ts_resume,
543 +
544 +};
545 +
546 +static struct platform_driver s3c2440ts_driver = {
547 +       .driver         = {
548 +              .name   = "s3c2440-ts",
549 +              .owner  = THIS_MODULE,
550 +       },
551 +       .probe          = s3c2410ts_probe,
552 +       .remove         = s3c2410ts_remove,
553 +       .suspend        = s3c2410ts_suspend,
554 +       .resume         = s3c2410ts_resume,
555 +
556 +};
557 +
558 +static int __init s3c2410ts_init(void)
559 +{
560 +       int rc;
561 +
562 +       rc = platform_driver_register(&s3c2410ts_driver);
563 +       if (rc < 0)
564 +               return rc;
565 +
566 +       rc = platform_driver_register(&s3c2440ts_driver);
567 +       if (rc < 0)
568 +               platform_driver_unregister(&s3c2410ts_driver);
569 +
570 +       return rc;
571 +}
572 +
573 +static void __exit s3c2410ts_exit(void)
574 +{
575 +       platform_driver_unregister(&s3c2440ts_driver);
576 +       platform_driver_unregister(&s3c2410ts_driver);
577 +}
578 +
579 +module_init(s3c2410ts_init);
580 +module_exit(s3c2410ts_exit);
581 +
582 +/*
583 +    Local variables:
584 +        compile-command: "make ARCH=arm CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux- -k -C ../../.."
585 +        c-basic-offset: 8
586 +    End:
587 +*/
588 diff --git a/include/asm-arm/arch-s3c2410/ts.h b/include/asm-arm/arch-s3c2410/ts.h
589 new file mode 100644
590 index 0000000..593632a
591 --- /dev/null
592 +++ b/include/asm-arm/arch-s3c2410/ts.h
593 @@ -0,0 +1,28 @@
594 +/* linux/include/asm/arch-s3c2410/ts.h
595 + *
596 + * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
597 + *
598 + *
599 + * This program is free software; you can redistribute it and/or modify
600 + * it under the terms of the GNU General Public License version 2 as
601 + * published by the Free Software Foundation.
602 + *
603 + *
604 + *  Changelog:
605 + *     24-Mar-2005     RTP     Created file
606 + *     03-Aug-2005     RTP     Renamed to ts.h
607 + */
608 +
609 +#ifndef __ASM_ARM_TS_H
610 +#define __ASM_ARM_TS_H
611 +
612 +struct s3c2410_ts_mach_info {
613 +       int             delay;
614 +       int             presc;
615 +       int             oversampling_shift;
616 +};
617 +
618 +void set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info);
619 +
620 +#endif /* __ASM_ARM_TS_H */
621 +
622 diff --git a/include/asm-arm/plat-s3c24xx/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
623 index f9d6f03..43de9cc 100644
624 --- a/include/asm-arm/plat-s3c24xx/devs.h
625 +++ b/include/asm-arm/plat-s3c24xx/devs.h
626 @@ -42,6 +42,7 @@ extern struct platform_device s3c_device_timer2;
627  extern struct platform_device s3c_device_timer3;
628  
629  extern struct platform_device s3c_device_usbgadget;
630 +extern struct platform_device s3c_device_ts;
631  
632  /* s3c2440 specific devices */
633  
634 -- 
635 1.5.6.3
636