Index: linux-2.6/arch/arm/mach-s3c2410/Makefile
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2410/Makefile	2006-03-17 22:31:27.000000000 +0100
+++ linux-2.6/arch/arm/mach-s3c2410/Makefile	2006-03-18 14:11:29.000000000 +0100
@@ -5,7 +5,7 @@
 
 # Object file lists.
 
-obj-y			:= cpu.o irq.o time.o gpio.o clock.o devs.o
+obj-y			:= cpu.o irq.o time.o gpio.o clock.o devs.o adcts_bus.o
 obj-m			:=
 obj-n			:=
 obj-			:=
Index: linux-2.6/arch/arm/mach-s3c2410/adcts_bus.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/arch/arm/mach-s3c2410/adcts_bus.c	2006-03-19 20:50:44.000000000 +0100
@@ -0,0 +1,287 @@
+/*
+ *
+ * Copyright (c) 2006 Arnaud Patard <arnaud.patard@rtp-net.org>
+ * s3c2410 adc/touchscreen interface support
+ *
+ * Based on drivers/base/platform.c
+ *
+ * ChangeLog
+ *
+ * 2006-02-12: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *      - First version
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-adc.h>
+#include <asm/arch/adcts_bus.h>
+
+static struct adcts_bus *my_bus;
+
+#define to_adcts_driver(drv)	(container_of((drv), struct adcts_driver, driver))
+
+struct device s3c2410adcts_bus = {
+	.bus_id		= "adcts",
+};
+
+EXPORT_SYMBOL(s3c2410adcts_bus);
+
+
+/*
+ * I/O helpers
+ */
+void adcts_writel(unsigned long b, unsigned long reg)
+{
+	writel(b,my_bus->base_addr+reg);
+}
+EXPORT_SYMBOL(adcts_writel);
+
+unsigned long adcts_readl(unsigned long reg)
+{
+	return readl(my_bus->base_addr+reg);
+}
+EXPORT_SYMBOL(adcts_readl);
+
+
+/*
+ * Bus stuff
+ **/
+static int s3c2410adcts_bus_match(struct device *_dev, struct device_driver *driver)
+{
+	struct adcts_driver *drv = to_adcts_driver(driver);
+	struct adcts_device *dev = to_adcts_device(_dev);
+	return (!strncmp(dev->name,drv->driver.name,strlen(drv->driver.name)));
+}
+
+static int s3c2410adcts_bus_suspend(struct device * dev, pm_message_t state)
+{
+	int ret = 0;
+
+	if (dev->driver && dev->driver->suspend)
+		ret = dev->driver->suspend(dev, state);
+
+	return ret;
+}
+
+static int s3c2410adcts_bus_resume(struct device * dev)
+{
+	int ret = 0;
+
+	if (dev->driver && dev->driver->resume)
+		ret = dev->driver->resume(dev);
+
+	return ret;
+}
+
+struct bus_type s3c2410adcts_bus_type = {
+	.name           = "s3c2410-adcts",
+	.match          = s3c2410adcts_bus_match,
+	.suspend        = s3c2410adcts_bus_suspend,
+	.resume         = s3c2410adcts_bus_resume,
+};
+EXPORT_SYMBOL_GPL(s3c2410adcts_bus_type);
+
+
+/*
+ * Device stuff
+ **/
+
+int adcts_dev_register(struct adcts_device *adcts_dev)
+{
+	adcts_dev->dev.bus = &s3c2410adcts_bus_type;
+	adcts_dev->dev.parent = &s3c2410adcts_bus;
+
+	strncpy(adcts_dev->dev.bus_id, adcts_dev->name, BUS_ID_SIZE);
+
+	printk(KERN_INFO "adcts_dev_register: Registering %s\n",adcts_dev->name);
+	return device_register(&adcts_dev->dev);
+}
+EXPORT_SYMBOL(adcts_dev_register);
+
+void adcts_dev_unregister(struct adcts_device *adcts_dev)
+{
+	device_unregister(&adcts_dev->dev);
+}
+EXPORT_SYMBOL(adcts_dev_unregister);
+
+/*
+ * Driver stuff
+ **/
+static int adcts_drv_probe(struct device *_dev)
+{
+	struct adcts_driver *drv = to_adcts_driver(_dev->driver);
+	struct adcts_device *dev = to_adcts_device(_dev);
+
+	return drv->bind(dev);
+}
+
+static int adcts_drv_remove(struct device *_dev)
+{
+	struct adcts_driver *drv = to_adcts_driver(_dev->driver);
+	struct adcts_device *dev = to_adcts_device(_dev);
+
+	return drv->unbind(dev);
+}
+
+static int adcts_drv_suspend(struct device *_dev, pm_message_t state)
+{
+	struct adcts_driver *drv = to_adcts_driver(_dev->driver);
+	struct adcts_device *dev = to_adcts_device(_dev);
+
+	return drv->suspend(dev, state);
+}
+
+static int adcts_drv_resume(struct device *_dev)
+{
+	struct adcts_driver *drv = to_adcts_driver(_dev->driver);
+	struct adcts_device *dev = to_adcts_device(_dev);
+	return drv->resume(dev);
+}
+
+
+int adcts_bus_register_driver (struct adcts_driver *driver)
+{
+	driver->driver.bus = &s3c2410adcts_bus_type;
+
+	if (driver->bind)
+		driver->driver.probe = adcts_drv_probe;
+	if (driver->unbind)
+		driver->driver.remove = adcts_drv_remove;
+	if (driver->suspend)
+		driver->driver.suspend = adcts_drv_suspend;
+	if (driver->resume)
+		driver->driver.resume = adcts_drv_resume;
+
+	return driver_register(&driver->driver);
+}
+EXPORT_SYMBOL(adcts_bus_register_driver);
+
+void adcts_bus_unregister_driver (struct adcts_driver *driver)
+{
+	driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL(adcts_bus_unregister_driver);
+
+
+/*
+ * Platform device stuff
+ **/
+
+static int __init s3c2410adcts_probe(struct platform_device *pdev)
+{
+	printk(KERN_INFO "Entering s3c2410adcts_probe\n");
+	my_bus = kzalloc(sizeof(struct adcts_bus),GFP_KERNEL);
+	if (!my_bus)
+		return -ENOMEM;
+
+	my_bus->info = (struct s3c2410_adcts_mach_info *)pdev->dev.platform_data;
+
+	my_bus->base_addr=ioremap(S3C2410_PA_ADC,0x20);
+	if (my_bus->base_addr == NULL) {
+		printk(KERN_ERR "Failed to remap register block\n");
+		return -ENOMEM;
+	}
+
+	if (my_bus->info) {
+		if ((my_bus->info->presc&0xff) > 0)
+			adcts_writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(my_bus->info->presc&0xFF),\
+				     S3C2410_ADCCON);
+		else
+			adcts_writel(0,S3C2410_ADCCON);
+
+		/* The ADCDELAY register should not be initialized to 0
+		 * thus if no value is specified, using the initiale value
+		 * seems to be OK.
+		 **/
+		if ((my_bus->info->delay&0xffff) > 0)
+			adcts_writel(my_bus->info->delay & 0xffff,  S3C2410_ADCDLY);
+		else
+			adcts_writel(my_bus->info->delay & 0xff,  S3C2410_ADCDLY);
+	}
+	return 0;
+}
+
+static int s3c2410adcts_remove(struct platform_device *pdev)
+{
+	iounmap(my_bus->base_addr);
+	kfree(my_bus);
+
+	return 0;
+}
+
+#if 0
+//#ifdef CONFIG_PM
+/* suspend and resume support for the controller */
+static int s3c2410adcts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	/* Go into standby mode */
+	adcts_writel(adcts_readl(S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,\
+			S3C2410_ADCCON);
+	return 0;
+}
+
+static int s3c2410adcts_resume(struct platform_device *pdev)
+{
+	int i;
+
+	/* Go out from standby mode */
+	adcts_writel(adcts_readl(S3C2410_ADCCON) & ~S3C2410_ADCCON_STDBM,\
+			S3C2410_ADCCON);
+
+	return 0;
+}
+
+#else
+#define s3c2410adcts_suspend NULL
+#define s3c2410adcts_resume  NULL
+#endif
+
+
+static struct platform_driver s3c2410adcts_driver = {
+	.driver         = {
+		.name   = "s3c2410-adcts-bus",
+	},
+	.probe          = s3c2410adcts_probe,
+	.remove         = s3c2410adcts_remove,
+	.suspend	= s3c2410adcts_suspend,
+	.resume		= s3c2410adcts_resume,
+};
+
+
+static int __init s3c2410adcts_init(void)
+{
+        return  platform_driver_register(&s3c2410adcts_driver);
+}
+
+static void __exit s3c2410adcts_exit(void)
+{
+
+        platform_driver_unregister(&s3c2410adcts_driver);
+}
+
+int __init s3c2410adcts_bus_init(void)
+{
+	printk(KERN_INFO "Entering s3c2410adcts_init\n");
+
+	device_register(&s3c2410adcts_bus);
+
+	return bus_register(&s3c2410adcts_bus_type);
+}
+
+
+module_init(s3c2410adcts_init);
+module_exit(s3c2410adcts_exit);
+
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
+MODULE_DESCRIPTION("s3c2410 adc/ts bus driver");
+MODULE_LICENSE("GPL");
Index: linux-2.6/include/asm-arm/arch-s3c2410/adcts_bus.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/include/asm-arm/arch-s3c2410/adcts_bus.h	2006-03-18 13:34:19.000000000 +0100
@@ -0,0 +1,47 @@
+#ifndef _ASM_ARCH_ADCTS_BUS_H
+#define _ASM_ARCH_ADCTS_BUS_H
+
+#define ADCTS_MAX_DEVS	2
+
+struct adcts_device {
+	const char			*name;
+	struct device			dev;
+};
+
+struct adcts_driver {
+	int			(*bind)(struct adcts_device *);
+	int			(*unbind)(struct adcts_device *);
+	int			(*suspend)(struct adcts_device *, pm_message_t );
+	int			(*resume)(struct adcts_device *);
+
+	struct device_driver	driver;
+};
+
+struct s3c2410_adcts_mach_info {
+       int             delay;
+       int             presc;
+       int             oversampling_shift;
+};
+
+struct adcts_bus {
+	int count;
+	void __iomem *base_addr;
+	struct clk *clk;
+	struct adcts_driver *driver[ADCTS_MAX_DEVS];
+	struct adcts_device dev[ADCTS_MAX_DEVS];
+	struct s3c2410_adcts_mach_info *info;
+};
+
+#define to_adcts_device(x) container_of((x), struct adcts_device, dev)
+
+void __init set_s3c2410adcts_info(struct s3c2410_adcts_mach_info *hard_s3c2410adcts_info);
+
+
+int adcts_bus_register_driver (struct adcts_driver *driver);
+void adcts_bus_unregister_driver (struct adcts_driver *driver);
+int adcts_dev_register(struct adcts_device *adcts_dev);
+void adcts_dev_unregister(struct adcts_device *adcts_dev);
+void adcts_writel(unsigned long b, unsigned long reg);
+unsigned long adcts_readl(unsigned long reg);
+
+#endif
Index: linux-2.6/arch/arm/mach-s3c2410/devs.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2410/devs.c	2006-03-17 22:31:27.000000000 +0100
+++ linux-2.6/arch/arm/mach-s3c2410/devs.c	2006-03-19 20:45:47.000000000 +0100
@@ -37,6 +37,7 @@
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/ts.h>
+#include <asm/arch/adcts_bus.h>
 #include <asm/arch/lcd.h>
 #include <asm/arch/buttons.h>
 
@@ -155,6 +156,12 @@
 
 EXPORT_SYMBOL(s3c_device_nand);
 
+struct platform_device s3c_device_adcts_bus = {
+	.name             = "s3c2410-adcts-bus",
+	.id               = -1,
+};
+EXPORT_SYMBOL(s3c_device_adcts_bus);
+
 /* Touchscreen */
 struct platform_device s3c_device_ts = {
 	.name		  = "s3c2410-ts",
@@ -172,6 +179,15 @@
 }
 EXPORT_SYMBOL(set_s3c2410ts_info);
 
+static struct s3c2410_adcts_mach_info s3c2410adcts_info;
+
+void __init set_s3c2410adcts_info(struct s3c2410_adcts_mach_info *hard_s3c2410adcts_info)
+{
+	memcpy(&s3c2410adcts_info,hard_s3c2410adcts_info,sizeof(struct s3c2410_adcts_mach_info));
+	s3c_device_adcts_bus.dev.platform_data = &s3c2410adcts_info;
+}
+EXPORT_SYMBOL(set_s3c2410adcts_info);
+
 /* 'Keyboard' */
 struct platform_device s3c_device_buttons = {
 	.name             = "s3c2410-buttons",
Index: linux-2.6/arch/arm/mach-s3c2410/devs.h
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2410/devs.h	2006-03-17 22:31:27.000000000 +0100
+++ linux-2.6/arch/arm/mach-s3c2410/devs.h	2006-03-19 20:45:47.000000000 +0100
@@ -40,6 +40,7 @@
 extern struct platform_device s3c_device_timer3;
 
 extern struct platform_device s3c_device_usbgadget;
+extern struct platform_device s3c_device_adcts_bus;
 extern struct platform_device s3c_device_ts;
 extern struct platform_device s3c_device_buttons;
 
Index: linux-2.6/arch/arm/mach-s3c2410/mach-h1940.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2410/mach-h1940.c	2006-03-17 22:31:27.000000000 +0100
+++ linux-2.6/arch/arm/mach-s3c2410/mach-h1940.c	2006-03-19 20:45:47.000000000 +0100
@@ -66,6 +66,7 @@
 #include <asm/arch/irqs.h>
 #include <asm/arch/fb.h>
 #include <asm/arch/udc.h>
+#include <asm/arch/adcts_bus.h>
 #include <asm/arch/ts.h>
 #include <asm/arch/lcd.h>
 #include <asm/arch/mmc.h>
@@ -155,6 +156,11 @@
 	.udc_command	= h1940_udc_pullup,
 };
 
+static struct s3c2410_adcts_mach_info h1940_adcts_cfg __initdata = {
+		.delay = 10000,
+		.presc = 49,
+		.oversampling_shift = 2,
+};
 
 static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
 		.delay = 10000,
@@ -359,6 +365,7 @@
 	&s3c_device_sdi,
 	&s3c_device_usbgadget,
 	&s3c_device_ts,
+	&s3c_device_adcts_bus,
 	&s3c_device_buttons,
 	&s3c_device_nand,
 	&s3c_device_leds,
@@ -367,9 +374,14 @@
 	&s3c_device_interrupts,
 };
 
+static struct adcts_device *h1940_adevices[] __initdata = {
+};
+
 static struct s3c24xx_board h1940_board __initdata = {
-	.devices       = h1940_devices,
-	.devices_count = ARRAY_SIZE(h1940_devices)
+	.devices        = h1940_devices,
+	.devices_count  = ARRAY_SIZE(h1940_devices),
+	.adevices       = h1940_adevices,
+	.adevices_count = ARRAY_SIZE(h1940_adevices)
 };
 
 static void __init h1940_map_io(void)
@@ -390,6 +402,7 @@
 	u32 tmp;
 
 	s3c24xx_fb_set_platdata(&h1940_lcdcfg);
+	set_s3c2410adcts_info(&h1940_adcts_cfg);
 	set_s3c2410ts_info(&h1940_ts_cfg);
 	set_s3c2410bl_info(&h1940_blcfg);
  	s3c24xx_udc_set_platdata(&h1940_udc_cfg);
Index: linux-2.6/arch/arm/mach-s3c2410/cpu.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2410/cpu.c	2006-01-04 02:02:31.000000000 +0100
+++ linux-2.6/arch/arm/mach-s3c2410/cpu.c	2006-03-19 20:37:33.000000000 +0100
@@ -38,6 +38,8 @@
 
 #include <asm/arch/regs-gpio.h>
 
+#include <asm/arch/adcts_bus.h>
+
 #include "cpu.h"
 #include "clock.h"
 #include "s3c2410.h"
@@ -218,8 +220,11 @@
 	if (ret != 0)
 		return ret;
 
+	s3c2410adcts_bus_init();
+
 	if (board != NULL) {
 		struct platform_device **ptr = board->devices;
+		struct adcts_device **aptr = board->adevices;
 		int i;
 
 		for (i = 0; i < board->devices_count; i++, ptr++) {
@@ -229,6 +234,13 @@
 				printk(KERN_ERR "s3c24xx: failed to add board device %s (%d) @%p\n", (*ptr)->name, ret, *ptr);
 			}
 		}
+		for (i = 0; i < board->adevices_count; i++, aptr++) {
+			ret = adcts_dev_register(*aptr);
+
+			if (ret) {
+				printk(KERN_ERR "s3c24xx: failed to add adcts device %s (%d) @%p\n", (*aptr)->name, ret, *aptr);
+			}
+		}
 
 		/* mask any error, we may not need all these board
 		 * devices */
Index: linux-2.6/arch/arm/mach-s3c2410/cpu.h
===================================================================
--- linux-2.6.orig/arch/arm/mach-s3c2410/cpu.h	2006-01-04 02:02:31.000000000 +0100
+++ linux-2.6/arch/arm/mach-s3c2410/cpu.h	2006-03-19 20:36:49.000000000 +0100
@@ -43,6 +43,8 @@
 
 extern void s3c24xx_init_clocks(int xtal);
 
+extern int s3c2410adcts_bus_init(void);
+
 /* the board structure is used at first initialsation time
  * to get info such as the devices to register for this
  * board. This is done because platfrom_add_devices() cannot
@@ -53,6 +55,9 @@
 	struct platform_device  **devices;
 	unsigned int              devices_count;
 
+	struct adcts_device	**adevices;
+	unsigned int		  adevices_count;
+
 	struct clk		**clocks;
 	unsigned int		  clocks_count;
 };

