mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-26 05:43:20 +02:00
fc54b9bf15
(stable-branch of Openmoko) git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13613 3c298f89-4303-0410-b956-a3cf2f4a3e73
637 lines
18 KiB
Diff
Executable File
637 lines
18 KiB
Diff
Executable File
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
|
|
|