aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches/0014-s3c2410_touchscreen.patch.patch
diff options
context:
space:
mode:
authorMirko Vogt <mirko@openwrt.org>2008-12-12 00:02:36 +0000
committerMirko Vogt <mirko@openwrt.org>2008-12-12 00:02:36 +0000
commitb9dfb81f2aa45be745a8aed9684076210aed4152 (patch)
treeaceadd7f37096911a29c929988cbcf7c964a1c0b /target/linux/s3c24xx/patches/0014-s3c2410_touchscreen.patch.patch
parent4571721ec22de116ad9998657e0a3c12da6405fb (diff)
downloadupstream-b9dfb81f2aa45be745a8aed9684076210aed4152.tar.gz
upstream-b9dfb81f2aa45be745a8aed9684076210aed4152.tar.bz2
upstream-b9dfb81f2aa45be745a8aed9684076210aed4152.zip
add support for target 3c24xx (more known as Openmoko GTA02 "Freerunner") and merge it with the openmoko-target and the work Michael Buesch <mb> did
SVN-Revision: 13609
Diffstat (limited to 'target/linux/s3c24xx/patches/0014-s3c2410_touchscreen.patch.patch')
-rwxr-xr-xtarget/linux/s3c24xx/patches/0014-s3c2410_touchscreen.patch.patch636
1 files changed, 636 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches/0014-s3c2410_touchscreen.patch.patch b/target/linux/s3c24xx/patches/0014-s3c2410_touchscreen.patch.patch
new file mode 100755
index 0000000000..27c1a9c394
--- /dev/null
+++ b/target/linux/s3c24xx/patches/0014-s3c2410_touchscreen.patch.patch
@@ -0,0 +1,636 @@
+From fc5d5366335469828d78898e2e74f8f80aa1d076 Mon Sep 17 00:00:00 2001
+From: mokopatches <mokopatches@openmoko.org>
+Date: Wed, 16 Jul 2008 14:44:49 +0100
+Subject: [PATCH] s3c2410_touchscreen.patch
+
+---
+ arch/arm/mach-s3c2410/mach-h1940.c | 8 +
+ arch/arm/plat-s3c24xx/devs.c | 18 ++
+ arch/arm/plat-s3c24xx/s3c244x.c | 1 +
+ drivers/input/touchscreen/Kconfig | 18 ++
+ drivers/input/touchscreen/Makefile | 1 +
+ drivers/input/touchscreen/s3c2410_ts.c | 437 ++++++++++++++++++++++++++++++++
+ include/asm-arm/arch-s3c2410/ts.h | 28 ++
+ include/asm-arm/plat-s3c24xx/devs.h | 1 +
+ 8 files changed, 512 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/input/touchscreen/s3c2410_ts.c
+ create mode 100644 include/asm-arm/arch-s3c2410/ts.h
+
+diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
+index 7c1145e..93cd8c8 100644
+--- a/arch/arm/mach-s3c2410/mach-h1940.c
++++ b/arch/arm/mach-s3c2410/mach-h1940.c
+@@ -38,6 +38,7 @@
+ #include <asm/arch/h1940.h>
+ #include <asm/arch/h1940-latch.h>
+ #include <asm/arch/fb.h>
++#include <asm/arch/tc.h>
+ #include <asm/plat-s3c24xx/udc.h>
+
+ #include <asm/plat-s3c24xx/clock.h>
+@@ -129,6 +130,11 @@ static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
+ .vbus_pin_inverted = 1,
+ };
+
++static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
++ .delay = 10000,
++ .presc = 49,
++ .oversampling_shift = 2,
++};
+
+ /**
+ * Set lcd on or off
+@@ -186,6 +192,7 @@ static struct platform_device *h1940_devices[] __initdata = {
+ &s3c_device_i2c,
+ &s3c_device_iis,
+ &s3c_device_usbgadget,
++ &s3c_device_ts,
+ &s3c_device_leds,
+ &s3c_device_bluetooth,
+ };
+@@ -214,6 +221,7 @@ static void __init h1940_init(void)
+ u32 tmp;
+
+ s3c24xx_fb_set_platdata(&h1940_fb_info);
++ set_s3c2410ts_info(&h1940_ts_cfg);
+ s3c24xx_udc_set_platdata(&h1940_udc_cfg);
+
+ /* Turn off suspend on both USB ports, and switch the
+diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
+index e546e93..c1fbe2d 100644
+--- a/arch/arm/plat-s3c24xx/devs.c
++++ b/arch/arm/plat-s3c24xx/devs.c
+@@ -24,6 +24,7 @@
+ #include <asm/mach/map.h>
+ #include <asm/mach/irq.h>
+ #include <asm/arch/fb.h>
++#include <asm/arch/ts.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -207,6 +208,23 @@ struct platform_device s3c_device_nand = {
+
+ EXPORT_SYMBOL(s3c_device_nand);
+
++/* Touchscreen */
++struct platform_device s3c_device_ts = {
++ .name = "s3c2410-ts",
++ .id = -1,
++};
++
++EXPORT_SYMBOL(s3c_device_ts);
++
++static struct s3c2410_ts_mach_info s3c2410ts_info;
++
++void set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
++{
++ memcpy(&s3c2410ts_info,hard_s3c2410ts_info,sizeof(struct s3c2410_ts_mach_info));
++ s3c_device_ts.dev.platform_data = &s3c2410ts_info;
++}
++EXPORT_SYMBOL(set_s3c2410ts_info);
++
+ /* USB Device (Gadget)*/
+
+ static struct resource s3c_usbgadget_resource[] = {
+diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
+index 2f01af5..7a1a12d 100644
+--- a/arch/arm/plat-s3c24xx/s3c244x.c
++++ b/arch/arm/plat-s3c24xx/s3c244x.c
+@@ -68,6 +68,7 @@ void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
+ s3c_device_sdi.name = "s3c2440-sdi";
+ s3c_device_i2c.name = "s3c2440-i2c";
+ s3c_device_nand.name = "s3c2440-nand";
++ s3c_device_ts.name = "s3c2440-ts";
+ s3c_device_usbgadget.name = "s3c2440-usbgadget";
+ }
+
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index 565ec71..52de2b0 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -67,6 +67,24 @@ config TOUCHSCREEN_FUJITSU
+ To compile this driver as a module, choose M here: the
+ module will be called fujitsu-ts.
+
++config TOUCHSCREEN_S3C2410
++ tristate "Samsung S3C2410 touchscreen input driver"
++ depends on ARCH_S3C2410 && INPUT && INPUT_TOUCHSCREEN
++ select SERIO
++ help
++ Say Y here if you have the s3c2410 touchscreen.
++
++ If unsure, say N.
++
++ To compile this driver as a module, choose M here: the
++ module will be called s3c2410_ts.
++
++config TOUCHSCREEN_S3C2410_DEBUG
++ boolean "Samsung S3C2410 touchscreen debug messages"
++ depends on TOUCHSCREEN_S3C2410
++ help
++ Select this if you want debug messages
++
+ config TOUCHSCREEN_GUNZE
+ tristate "Gunze AHL-51S touchscreen"
+ select SERIO
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index 3c096d7..7c3bd1c 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -26,3 +26,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
+ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
+ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
+ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
++obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
+diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
+new file mode 100644
+index 0000000..68071c2
+--- /dev/null
++++ b/drivers/input/touchscreen/s3c2410_ts.c
+@@ -0,0 +1,437 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
++ * iPAQ H1940 touchscreen support
++ *
++ * ChangeLog
++ *
++ * 2004-09-05: Herbert Pƶtzl <herbert@13thfloor.at>
++ * - added clock (de-)allocation code
++ *
++ * 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>
++ * - h1940_ -> s3c2410 (this driver is now also used on the n30
++ * machines :P)
++ * - Debug messages are now enabled with the config option
++ * TOUCHSCREEN_S3C2410_DEBUG
++ * - Changed the way the value are read
++ * - Input subsystem should now work
++ * - Use ioremap and readl/writel
++ *
++ * 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>
++ * - Make use of some undocumented features of the touchscreen
++ * controller
++ *
++ * 2007-05-23: Harald Welte <laforge@openmoko.org>
++ * - Add proper support for S32440
++ */
++
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/input.h>
++#include <linux/init.h>
++#include <linux/serio.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++
++#include <asm/arch/regs-gpio.h>
++#include <asm/arch/ts.h>
++
++#include <asm/plat-s3c/regs-adc.h>
++
++/* For ts.dev.id.version */
++#define S3C2410TSVERSION 0x0101
++
++#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
++
++#define WAIT4INT(x) (((x)<<8) | \
++ S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
++ S3C2410_ADCTSC_XY_PST(3))
++
++#define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
++ S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
++
++#define DEBUG_LVL KERN_DEBUG
++
++MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
++MODULE_DESCRIPTION("s3c2410 touchscreen driver");
++MODULE_LICENSE("GPL");
++
++/*
++ * Definitions & global arrays.
++ */
++
++
++static char *s3c2410ts_name = "s3c2410 TouchScreen";
++
++/*
++ * Per-touchscreen data.
++ */
++
++struct s3c2410ts {
++ struct input_dev *dev;
++ long xp;
++ long yp;
++ int count;
++ int shift;
++};
++
++static struct s3c2410ts ts;
++static void __iomem *base_addr;
++
++static inline void s3c2410_ts_connect(void)
++{
++ s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
++ s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
++ s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
++ s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
++}
++
++static void touch_timer_fire(unsigned long data)
++{
++ unsigned long data0;
++ unsigned long data1;
++ int updown;
++
++ data0 = readl(base_addr+S3C2410_ADCDAT0);
++ data1 = readl(base_addr+S3C2410_ADCDAT1);
++
++ updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
++
++ if (updown) {
++ if (ts.count != 0) {
++ ts.xp >>= ts.shift;
++ ts.yp >>= ts.shift;
++
++#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
++ {
++ struct timeval tv;
++ do_gettimeofday(&tv);
++ printk(DEBUG_LVL "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts.xp, ts.yp);
++ }
++#endif
++
++ input_report_abs(ts.dev, ABS_X, ts.xp);
++ input_report_abs(ts.dev, ABS_Y, ts.yp);
++
++ input_report_key(ts.dev, BTN_TOUCH, 1);
++ input_report_abs(ts.dev, ABS_PRESSURE, 1);
++ input_sync(ts.dev);
++ }
++
++ ts.xp = 0;
++ ts.yp = 0;
++ ts.count = 0;
++
++ writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
++ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
++ } else {
++ ts.count = 0;
++
++ input_report_key(ts.dev, BTN_TOUCH, 0);
++ input_report_abs(ts.dev, ABS_PRESSURE, 0);
++ input_sync(ts.dev);
++
++ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
++ }
++}
++
++static struct timer_list touch_timer =
++ TIMER_INITIALIZER(touch_timer_fire, 0, 0);
++
++static irqreturn_t stylus_updown(int irq, void *dev_id)
++{
++ unsigned long data0;
++ unsigned long data1;
++ int updown;
++
++ data0 = readl(base_addr+S3C2410_ADCDAT0);
++ data1 = readl(base_addr+S3C2410_ADCDAT1);
++
++ updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
++
++ /* TODO we should never get an interrupt with updown set while
++ * the timer is running, but maybe we ought to verify that the
++ * timer isn't running anyways. */
++
++ if (updown)
++ touch_timer_fire(0);
++
++ return IRQ_HANDLED;
++}
++
++
++static irqreturn_t stylus_action(int irq, void *dev_id)
++{
++ unsigned long data0;
++ unsigned long data1;
++
++ data0 = readl(base_addr+S3C2410_ADCDAT0);
++ data1 = readl(base_addr+S3C2410_ADCDAT1);
++
++ ts.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
++ ts.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
++ ts.count++;
++
++ if (ts.count < (1<<ts.shift)) {
++ writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
++ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
++ } else {
++ mod_timer(&touch_timer, jiffies+1);
++ writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static struct clk *adc_clock;
++
++/*
++ * The functions for inserting/removing us as a module.
++ */
++
++static int __init s3c2410ts_probe(struct platform_device *pdev)
++{
++ int rc;
++ struct s3c2410_ts_mach_info *info;
++ struct input_dev *input_dev;
++
++ info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
++
++ if (!info)
++ {
++ printk(KERN_ERR "Hm... too bad : no platform data for ts\n");
++ return -EINVAL;
++ }
++
++#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
++ printk(DEBUG_LVL "Entering s3c2410ts_init\n");
++#endif
++
++ adc_clock = clk_get(NULL, "adc");
++ if (!adc_clock) {
++ printk(KERN_ERR "failed to get adc clock source\n");
++ return -ENOENT;
++ }
++ clk_enable(adc_clock);
++
++#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
++ printk(DEBUG_LVL "got and enabled clock\n");
++#endif
++
++ base_addr = ioremap(S3C2410_PA_ADC,0x20);
++ if (base_addr == NULL) {
++ printk(KERN_ERR "Failed to remap register block\n");
++ return -ENOMEM;
++ }
++
++
++ /* If we acutally are a S3C2410: Configure GPIOs */
++ if (!strcmp(pdev->name, "s3c2410-ts"))
++ s3c2410_ts_connect();
++
++ if ((info->presc&0xff) > 0)
++ writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
++ base_addr+S3C2410_ADCCON);
++ else
++ writel(0,base_addr+S3C2410_ADCCON);
++
++
++ /* Initialise registers */
++ if ((info->delay&0xffff) > 0)
++ writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);
++
++ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
++
++ /* Initialise input stuff */
++ memset(&ts, 0, sizeof(struct s3c2410ts));
++ input_dev = input_allocate_device();
++
++ if (!input_dev) {
++ printk(KERN_ERR "Unable to allocate the input device !!\n");
++ return -ENOMEM;
++ }
++
++ ts.dev = input_dev;
++ ts.dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) |
++ BIT_MASK(EV_ABS);
++ ts.dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
++ input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);
++ input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
++ input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
++
++ ts.dev->private = &ts;
++ ts.dev->name = s3c2410ts_name;
++ ts.dev->id.bustype = BUS_RS232;
++ ts.dev->id.vendor = 0xDEAD;
++ ts.dev->id.product = 0xBEEF;
++ ts.dev->id.version = S3C2410TSVERSION;
++
++ ts.shift = info->oversampling_shift;
++
++ /* Get irqs */
++ if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,
++ "s3c2410_action", ts.dev)) {
++ printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");
++ iounmap(base_addr);
++ return -EIO;
++ }
++ if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
++ "s3c2410_action", ts.dev)) {
++ printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
++ free_irq(IRQ_ADC, ts.dev);
++ iounmap(base_addr);
++ return -EIO;
++ }
++
++ printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);
++
++ /* All went ok, so register to the input system */
++ rc = input_register_device(ts.dev);
++ if (rc) {
++ free_irq(IRQ_TC, ts.dev);
++ free_irq(IRQ_ADC, ts.dev);
++ clk_disable(adc_clock);
++ iounmap(base_addr);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static int s3c2410ts_remove(struct platform_device *pdev)
++{
++ disable_irq(IRQ_ADC);
++ disable_irq(IRQ_TC);
++ free_irq(IRQ_TC,ts.dev);
++ free_irq(IRQ_ADC,ts.dev);
++
++ if (adc_clock) {
++ clk_disable(adc_clock);
++ clk_put(adc_clock);
++ adc_clock = NULL;
++ }
++
++ input_unregister_device(ts.dev);
++ iounmap(base_addr);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ writel(TSC_SLEEP, base_addr+S3C2410_ADCTSC);
++ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,
++ base_addr+S3C2410_ADCCON);
++
++ disable_irq(IRQ_ADC);
++ disable_irq(IRQ_TC);
++
++ clk_disable(adc_clock);
++
++ return 0;
++}
++
++static int s3c2410ts_resume(struct platform_device *pdev)
++{
++ struct s3c2410_ts_mach_info *info =
++ ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
++
++ clk_enable(adc_clock);
++ msleep(1);
++
++ enable_irq(IRQ_ADC);
++ enable_irq(IRQ_TC);
++
++ if ((info->presc&0xff) > 0)
++ writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
++ base_addr+S3C2410_ADCCON);
++ else
++ writel(0,base_addr+S3C2410_ADCCON);
++
++ /* Initialise registers */
++ if ((info->delay&0xffff) > 0)
++ writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);
++
++ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
++
++ return 0;
++}
++
++#else
++#define s3c2410ts_suspend NULL
++#define s3c2410ts_resume NULL
++#endif
++
++static struct platform_driver s3c2410ts_driver = {
++ .driver = {
++ .name = "s3c2410-ts",
++ .owner = THIS_MODULE,
++ },
++ .probe = s3c2410ts_probe,
++ .remove = s3c2410ts_remove,
++ .suspend = s3c2410ts_suspend,
++ .resume = s3c2410ts_resume,
++
++};
++
++static struct platform_driver s3c2440ts_driver = {
++ .driver = {
++ .name = "s3c2440-ts",
++ .owner = THIS_MODULE,
++ },
++ .probe = s3c2410ts_probe,
++ .remove = s3c2410ts_remove,
++ .suspend = s3c2410ts_suspend,
++ .resume = s3c2410ts_resume,
++
++};
++
++static int __init s3c2410ts_init(void)
++{
++ int rc;
++
++ rc = platform_driver_register(&s3c2410ts_driver);
++ if (rc < 0)
++ return rc;
++
++ rc = platform_driver_register(&s3c2440ts_driver);
++ if (rc < 0)
++ platform_driver_unregister(&s3c2410ts_driver);
++
++ return rc;
++}
++
++static void __exit s3c2410ts_exit(void)
++{
++ platform_driver_unregister(&s3c2440ts_driver);
++ platform_driver_unregister(&s3c2410ts_driver);
++}
++
++module_init(s3c2410ts_init);
++module_exit(s3c2410ts_exit);
++
++/*
++ Local variables:
++ compile-command: "make ARCH=arm CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux- -k -C ../../.."
++ c-basic-offset: 8
++ End:
++*/
+diff --git a/include/asm-arm/arch-s3c2410/ts.h b/include/asm-arm/arch-s3c2410/ts.h
+new file mode 100644
+index 0000000..593632a
+--- /dev/null
++++ b/include/asm-arm/arch-s3c2410/ts.h
+@@ -0,0 +1,28 @@
++/* linux/include/asm/arch-s3c2410/ts.h
++ *
++ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *
++ * Changelog:
++ * 24-Mar-2005 RTP Created file
++ * 03-Aug-2005 RTP Renamed to ts.h
++ */
++
++#ifndef __ASM_ARM_TS_H
++#define __ASM_ARM_TS_H
++
++struct s3c2410_ts_mach_info {
++ int delay;
++ int presc;
++ int oversampling_shift;
++};
++
++void set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info);
++
++#endif /* __ASM_ARM_TS_H */
++
+diff --git a/include/asm-arm/plat-s3c24xx/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
+index f9d6f03..43de9cc 100644
+--- a/include/asm-arm/plat-s3c24xx/devs.h
++++ b/include/asm-arm/plat-s3c24xx/devs.h
+@@ -42,6 +42,7 @@ extern struct platform_device s3c_device_timer2;
+ extern struct platform_device s3c_device_timer3;
+
+ extern struct platform_device s3c_device_usbgadget;
++extern struct platform_device s3c_device_ts;
+
+ /* s3c2440 specific devices */
+
+--
+1.5.6.3
+