diff -urNp linux-2.6.28.5/arch/arm/mach-s3c2410/clock.c linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/clock.c
--- linux-2.6.28.5/arch/arm/mach-s3c2410/clock.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/clock.c	2009-02-14 15:49:39.000000000 +0100
@@ -89,12 +89,6 @@ static int s3c2410_upll_enable(struct cl
 
 static struct clk init_clocks_disable[] = {
 	{
-		.name		= "nand",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_NAND,
-	}, {
 		.name		= "sdi",
 		.id		= -1,
 		.parent		= &clk_p,
@@ -129,6 +123,12 @@ static struct clk init_clocks_disable[] 
 
 static struct clk init_clocks[] = {
 	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_NAND,
+	}, {
 		.name		= "lcd",
 		.id		= -1,
 		.parent		= &clk_h,
@@ -160,18 +160,21 @@ static struct clk init_clocks[] = {
 		.ctrlbit	= S3C2410_CLKCON_PWMT,
 	}, {
 		.name		= "uart",
+		.sys_name	= "uart.0",
 		.id		= 0,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_UART0,
 	}, {
 		.name		= "uart",
+		.sys_name	= "uart.1",
 		.id		= 1,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
 		.ctrlbit	= S3C2410_CLKCON_UART1,
 	}, {
 		.name		= "uart",
+		.sys_name	= "uart.2",
 		.id		= 2,
 		.parent		= &clk_p,
 		.enable		= s3c2410_clkcon_enable,
diff -urNp linux-2.6.28.5/arch/arm/mach-s3c2410/Kconfig linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/Kconfig
--- linux-2.6.28.5/arch/arm/mach-s3c2410/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/Kconfig	2009-01-06 18:24:37.000000000 +0100
@@ -133,4 +133,10 @@ config MACH_QT2410
 	help
 	   Say Y here if you are using the Armzone QT2410
 
+config MACH_RD129
+	bool "RD129"
+	select CPU_S3C2410
+	help
+	  Say Y here if you are using the Elpa RD129 Cpu board
+
 endmenu
diff -urNp linux-2.6.28.5/arch/arm/mach-s3c2410/mach-rd129.c linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/mach-rd129.c
--- linux-2.6.28.5/arch/arm/mach-s3c2410/mach-rd129.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/mach-rd129.c	2009-02-15 12:02:06.000000000 +0100
@@ -0,0 +1,790 @@
+/*
+ * linux/arch/arm/mach-s3c2410/mach-rd129.c
+ *
+ * Copyright (c) 2007 ELPA sas
+ *	Davide Rizzo <elpa.rizzo@gmail.com>
+ *
+ * RD129 card specific code
+ *
+ * RD129 is based on a Samsung S3C2410 SoC
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/serial_core.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/pwm_backlight.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <mach/fb.h>
+
+#include <asm/plat-s3c/nand.h>
+#include <asm/plat-s3c24xx/mci.h>
+#include <mach/spi.h>
+#include <mach/regs-gpio.h>
+#include <plat/regs-serial.h>
+
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/clock.h>
+#include <plat/gpio.h>
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg rd129_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport = 0,
+		.flags  = 0,
+		.ucon   = UCON,
+		.ulcon  = ULCON,
+		.ufcon  = UFCON,
+	},
+	 [1] = {
+		.hwport = 1,
+		.flags  = 0,
+		.ucon   = UCON,
+		.ulcon  = ULCON,
+		.ufcon  = UFCON,
+	},
+	 [2] = {
+		.hwport = 2,
+		.flags  = 0,
+		.ucon   = UCON,
+		.ulcon  = ULCON,
+		.ufcon  = UFCON,
+	}
+};
+
+/* NAND parititions for rd129 */
+static struct mtd_partition rd129_default_nand_part[] = {
+	[0] = {
+		.name = "boot",
+		.size = SZ_1M,
+		.offset = 0,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	 [1] = {
+		.name = "kernel",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_2M,
+	},
+	 [2] = {
+		.name = "root",
+		.offset = MTDPART_OFS_APPEND,
+		.size = MTDPART_SIZ_FULL,
+	},
+	 [3] = {
+		.name = "dummy",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0,
+	},
+	 [4] = {
+		.name = "dummy",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0,
+	},
+	 [5] = {
+		.name = "dummy",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0,
+	},
+	 [6] = {
+		.name = "dummy",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0,
+	},
+	 [7] = {
+		.name = "dummy",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0,
+	}
+};
+
+static struct s3c2410_nand_set rd129_nand_sets[] = {
+	[0] = {
+		.name = "s3c2410-nand",
+		.nr_chips = 1,
+		.nr_partitions = 3,
+		.partitions = rd129_default_nand_part,
+	},
+};
+
+static struct s3c2410_platform_nand rd129_nand_info = {
+	.tacls = 10,
+	.twrph0 = 30,
+	.twrph1 = 10,
+	.nr_sets = ARRAY_SIZE(rd129_nand_sets),
+	.sets = rd129_nand_sets,
+};
+
+static struct s3c24xx_mci_pdata rd129_mmc_cfg = {
+	.gpio_detect = S3C2410_GPG0,
+	.gpio_wprotect = S3C2410_GPG1,
+	.set_power = NULL,
+	.ocr_avail = MMC_VDD_32_33,
+};
+
+static struct s3c24xx_gpio_platdata rd129_gpio_cfg = {
+	.port_mask = {
+		0x21F000, 0x00001F, 0x00FF1F, 0x00FFFF,
+		0x00FFFF, 0x0000FF, 0x00FFFF, 0x0006FF
+	}
+};
+
+static struct platform_device s3c_device_gpio = {
+	.name   = "s3c2410-gpio",
+	.id	= -1,
+	.dev		= {
+		.platform_data = &rd129_gpio_cfg,
+	}
+};
+
+#ifdef CONFIG_BACKLIGHT_PWM
+static struct platform_pwm_backlight_data rd129_backlight = {
+/* Timer 0 is used by LCD backlight driver */
+	.pwm_id = 0,
+	.max_brightness = 100,
+	.dft_brightness = 100,
+	.pwm_period_ns = 1000000000 / CONFIG_BACKLIGHT_PWM_FREQUENCY,
+};
+
+static struct platform_device s3c_device_backlight = {
+	.name   = "pwm-backlight",
+	.id	= -1,
+	.dev		= {
+		.platform_data = &rd129_backlight,
+	}
+};
+#else /* CONFIG_BACKLIGHT_PWM */
+static struct platform_device s3c_device_timer0 = {
+	.name   = "um_timer",
+	.id	= 0,
+};
+#endif /* CONFIG_BACKLIGHT_PWM */
+
+static struct platform_device s3c_device_timer1 = {
+	.name   = "um_timer",
+	.id	= 1,
+};
+
+static struct platform_device s3c_device_timer2 = {
+	.name   = "um_timer",
+	.id	= 2,
+};
+
+static struct platform_device s3c_device_timer3 = {
+	.name   = "um_timer",
+	.id	= 3,
+};
+
+/*
+ * GPIO Buttons
+ */
+static struct gpio_keys_button buttons[] = {
+	{
+		.gpio = S3C2410_GPF0,
+		.code = KEY_LEFT,
+		.desc = "Left",
+		.active_low = 1,
+	},
+	{
+		.gpio = S3C2410_GPF1,
+		.code = KEY_RIGHT,
+		.desc = "Right",
+		.active_low = 1,
+	},
+	{
+		.gpio = S3C2410_GPF2,
+		.code = KEY_SPACE,
+		.desc = "Space",
+		.active_low = 1,
+	},
+	{
+		.gpio = S3C2410_GPF3,
+		.code = KEY_TAB,
+		.desc = "Tab",
+		.active_low = 1,
+	},
+	{
+		.gpio = S3C2410_GPF4,
+		.code = KEY_ESC,
+		.desc = "Escape",
+		.active_low = 1,
+	}
+};
+
+static struct gpio_keys_platform_data button_data = {
+	.buttons	= buttons,
+	.nbuttons	= ARRAY_SIZE(buttons),
+};
+
+static struct platform_device button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &button_data,
+	}
+};
+
+/* devices we initialise */
+static struct platform_device *rd129_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_adc,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+	&s3c_device_sdi,
+	&s3c_device_nand,
+	&s3c_device_timer[0],
+	&s3c_device_timer[1],
+	&s3c_device_timer[2],
+	&s3c_device_timer[3],
+	&s3c_device_gpio,
+	&s3c_device_spi0,
+	&s3c_device_spi1,
+#ifdef CONFIG_BACKLIGHT_PWM
+	&s3c_device_backlight,
+#else /* CONFIG_BACKLIGHT_PWM */
+	&s3c_device_timer0,
+#endif /* CONFIG_BACKLIGHT_PWM */
+	&s3c_device_timer1,
+	&s3c_device_timer2,
+	&s3c_device_timer3,
+	&button_device,
+};
+
+static struct map_desc rd129_iodesc[] __initdata = {
+};
+
+static struct s3c2410fb_display s3c2410_fb_displays[] = {
+	{
+		/* Hitachi TX09D70VM1CCA 3.5" 240x320 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 240,
+		.height = 320,
+		.xres = 240,
+		.yres = 320,
+		.bpp = 8,
+		.pixclock = 186697, /* 327*273*60=5.35626MHz */
+		.left_margin = 17,
+		.right_margin = 11,
+		.hsync_len = 5,
+		.upper_margin = 4,
+		.lower_margin = 2,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE |
+			S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */
+			S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,
+	},
+  {
+		/* Hitachi TX09D70VM1CCA 3.5" 240x320 64K colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 240,
+		.height = 320,
+		.xres = 240,
+		.yres = 320,
+		.bpp = 16,
+		.pixclock = 186697, /* 327*273*60=5.35626MHz */
+		.left_margin = 17,
+		.right_margin = 11,
+		.hsync_len = 5,
+		.upper_margin = 4,
+		.lower_margin = 2,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE |
+			S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */
+			S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Hitachi TX14D11VM1CAA 5.7" 320x240 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 320,
+		.height = 240,
+		.xres = 320,
+		.yres = 240,
+		.bpp = 8,
+		.pixclock = 156250, /* 357*245*73.17=6.4MHz */
+		.left_margin = 16,
+		.right_margin = 16,
+		.hsync_len = 5,
+		.upper_margin = 2,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
+			S3C2410_LCDCON5_INVVLINE | /* Doesn't use Hsync */
+			S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */
+			S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Hitachi TX14D11VM1CAA 5.7" 320x240 64K colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 320,
+		.height = 240,
+		.xres = 320,
+		.yres = 240,
+		.bpp = 16,
+		.pixclock = 156250, /* 357*245*73.17=6.4MHz */
+		.left_margin = 16,
+		.right_margin = 16,
+		.hsync_len = 5,
+		.upper_margin = 2,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
+			S3C2410_LCDCON5_INVVLINE | /* Doesn't use Hsync */
+			S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */
+			S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Ampire AM320240N1TMQWT30H(R) e AM320240NTMQWT30H 5.7"
+       320x240 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 320,
+		.height = 240,
+		.xres = 320,
+		.yres = 241, /* This panel needs one dummy line */
+		.bpp = 8,
+		.pixclock = 156250, /* 357*245*73.17=6.4MHz */
+		.left_margin = 16,
+		.right_margin = 16,
+		.hsync_len = 5,
+		.upper_margin = 2,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
+			S3C2410_LCDCON5_INVVLINE | /* Doesn't use Hsync */
+			S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */
+			S3C2410_LCDCON5_INVVCLK | /* Clocks on rising edge */
+			S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Ampire AM320240N1TMQWT30H(R) e AM320240NTMQWT30H 5.7"
+       320x240 64K colori*/
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 320,
+		.height = 240,
+		.xres = 320,
+		.yres = 241, /* This panel needs one dummy line */
+		.bpp = 16,
+		.pixclock = 156250, /* 357*245*73.17=6.4MHz */
+		.left_margin = 16,
+		.right_margin = 16,
+		.hsync_len = 5,
+		.upper_margin = 2,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
+			S3C2410_LCDCON5_INVVLINE | /* Doesn't use Hsync */
+			S3C2410_LCDCON5_INVVFRAME | /* Doesn't use Vsync */
+			S3C2410_LCDCON5_INVVCLK | /* Clocks on rising edge */
+			S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Ampire AM640480GTMQWT00H 5.7" 640x480 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 640,
+		.height = 480,
+		.xres = 640,
+		.yres = 480,
+		.bpp = 8,
+		.pixclock = 40000, /* 25MHz */
+		.left_margin = 53,
+		.right_margin = 53,
+		.hsync_len = 54,
+		.upper_margin = 15,
+		.lower_margin = 15,
+		.vsync_len = 15,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Ampire AM640480GTMQWT00H 5.7" 640x480 64K colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 640,
+		.height = 480,
+		.xres = 640,
+		.yres = 480,
+		.bpp = 16,
+		.pixclock = 40000, /* 25MHz */
+		.left_margin = 53,
+		.right_margin = 53,
+		.hsync_len = 54,
+		.upper_margin = 15,
+		.lower_margin = 15,
+		.vsync_len = 15,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Varitronix TLM-T700MPZC-01 7" 800x480 256 colori */
+		/* Samsung LMS700KF07-004 7" 800x480 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 800,
+		.height = 480,
+		.xres = 800,
+		.yres = 480,
+		.bpp = 8,
+		.pixclock = 45115, /* 22.167MHz 56Hz */
+		.left_margin = 6, /* Varitronix needs 45, Frate = 53.4Hz */
+		.right_margin = 1,
+		.hsync_len = 1,
+		.upper_margin = 8,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Varitronix TLM-T700MPZC-01 7" 800x480 64K colori */
+		/* Samsung LMS700KF07-004 7" 800x480 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 800,
+		.height = 480,
+		.xres = 800,
+		.yres = 480,
+		.bpp = 16,
+		.pixclock = 45115, /* 22.167MHz 56Hz */
+		.left_margin = 6, /* Varitronix needs 45, Frate = 53.4Hz */
+		.right_margin = 1,
+		.hsync_len = 1,
+		.upper_margin = 8,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Ampire AM800600CL-TMQW01H 800x600 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 800,
+		.height = 600,
+		.xres = 800,
+		.yres = 600,
+		.bpp = 8,
+		.pixclock = 45115, /* 22.167MHz 41.82Hz */
+		/*.pixclock = 30076,  33.25MHz 62.74Hz */
+		.left_margin = 46,
+		.right_margin = 1,
+		.hsync_len = 1,
+		.upper_margin = 33,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* Ampire AM800600CL-TMQW01H 800x600 64K colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 800,
+		.height = 600,
+		.xres = 800,
+		.yres = 600,
+		.bpp = 16,
+		.pixclock = 45115, /* 22.167MHz 41.82Hz */
+		/*.pixclock = 30076,  33.25MHz 62.74Hz */
+		.left_margin = 46,
+		.right_margin = 1,
+		.hsync_len = 1,
+		.upper_margin = 33,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+#if 0
+	{
+		/* 1024x768 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 1024,
+		.height = 768,
+		.xres = 1024,
+		.yres = 768,
+		.bpp = 8,
+		.pixclock = 15038, /* 66.5MHz */
+		.left_margin = 3,
+		.right_margin = 3,
+		.hsync_len = 3,
+		.upper_margin = 1,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* 1024x768 64K colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 1024,
+		.height = 768,
+		.xres = 1024,
+		.yres = 768,
+		.bpp = 16,
+		.pixclock = 15038, /* 66.5MHz */
+		.left_margin = 3,
+		.right_margin = 3,
+		.hsync_len = 3,
+		.upper_margin = 1,
+		.lower_margin = 1,
+		.vsync_len = 1,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* 1280x800 256 colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 1280,
+		.height = 800,
+		.xres = 1280,
+		.yres = 800,
+		.bpp = 8,
+		.pixclock = 15038, /* 66.5MHz */
+		.left_margin = 32,
+		.right_margin = 32,
+		.hsync_len = 64,
+		.upper_margin = 4,
+		.lower_margin = 4,
+		.vsync_len = 8,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+	{
+		/* 1280x800 64K colori */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 1280,
+		.height = 800,
+		.xres = 1280,
+		.yres = 800,
+		.bpp = 16,
+		.pixclock = 15038, /* 66.5MHz */
+		.left_margin = 32,
+		.right_margin = 32,
+		.hsync_len = 64,
+		.upper_margin = 4,
+		.lower_margin = 4,
+		.vsync_len = 8,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_PWREN |
+			S3C2410_LCDCON5_HWSWP,
+	},
+#endif
+	{
+		/* tft 384x256 */
+		.type = S3C2410_LCDCON1_TFT,
+		.width = 384,
+		.height = 256,
+		.xres = 384,
+		.yres = 256,
+		.bpp = 16,
+		.pixclock = 117318, /* 396*287*75=8.5239MHz */
+		.left_margin = 4,
+		.right_margin = 4,
+		.hsync_len = 4,
+		.upper_margin = 10,
+		.lower_margin = 10,
+		.vsync_len = 11,
+		.lcdcon5 = S3C2410_LCDCON5_FRM565 |
+			S3C2410_LCDCON5_INVVCLK |  /* Clocks on rising edge */
+			S3C2410_LCDCON5_PWREN |	S3C2410_LCDCON5_HWSWP,
+	},
+};
+
+static struct s3c2410fb_mach_info fbinfo = {
+	.displays = s3c2410_fb_displays,
+	.num_displays = ARRAY_SIZE(s3c2410_fb_displays),
+	.default_display = 0,
+	.gpcup = 0xfc1e,
+	.gpcup_mask = 0xfc1e,
+	.gpccon = 0xaaa002a8,
+	.gpccon_mask = 0xfff003fc,
+	.gpdup = 0xfcfc,
+	.gpdup_mask = 0xfcfc,
+	.gpdcon = 0xaaa0aaa0,
+	.gpdcon_mask = 0xfff0fff0,
+	.lpcsel = 0,
+};
+
+static void __init usb_init(void)
+{
+#ifdef CONFIG_RD129_USB_1HOST
+	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0);
+	platform_device_register(&s3c_device_usbgadget);
+	printk(KERN_INFO "Usb: 1 Host port, 1 Device port\n");
+#endif
+#ifdef CONFIG_RD129_USB_2HOST
+	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, S3C2410_MISCCR_USBHOST);
+	printk(KERN_INFO "Usb: 2 Host ports\n");
+#endif
+#ifdef CONFIG_RD129_USB_AUTO
+	s3c2410_gpio_cfgpin(S3C2410_GPD0, S3C2410_GPD0_INP);
+	s3c2410_gpio_pullup(S3C2410_GPD0, 0); /* Enable pullup */
+	if (s3c2410_gpio_getpin(S3C2410_GPD0)) {
+		/* Host */
+		s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
+			S3C2410_MISCCR_USBHOST);
+		printk(KERN_INFO "Autodetected Usb: 2 Host ports\n");
+	} else {
+		/* Device */
+		s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0);
+		platform_device_register(&s3c_device_usbgadget);
+		printk(KERN_INFO
+			"Autodetected Usb: 1 Host port, 1 Device port\n");
+	}
+#endif
+}
+
+static struct clk *rd129_clocks[] __initdata = {
+	&s3c24xx_dclk0,
+	&s3c24xx_dclk1,
+	&s3c24xx_clkout0,
+	&s3c24xx_clkout1,
+};
+
+static void __init rd129_map_io(void)
+{
+	s3c24xx_register_clocks(rd129_clocks, ARRAY_SIZE(rd129_clocks));
+	s3c24xx_init_io(rd129_iodesc, ARRAY_SIZE(rd129_iodesc));
+	s3c24xx_init_clocks(0);
+	s3c24xx_init_uarts(rd129_uartcfgs, ARRAY_SIZE(rd129_uartcfgs));
+}
+
+static struct i2c_board_info rd126_i2c_devices[] = {
+#ifdef CONFIG_AT24
+	{
+		I2C_BOARD_INFO("at24", 0x50),
+		.type = CONFIG_AT24_TYPE,
+	},
+#endif	/* CONFIG_AT24 */
+#ifdef CONFIG_RTC_DRV_DS1307
+	{
+		I2C_BOARD_INFO("rtc-ds1307", 0x68),
+		.type = "ds1338",
+	},
+#endif	/* CONFIG_RTC_DRV_DS1307 */
+#ifdef CONFIG_RTC_DRV_FM3130
+	{
+		I2C_BOARD_INFO("rtc-fm3130", 0x68),
+		.type = "fm3130",
+	},
+#endif	/* CONFIG_RTC_DRV_FM3130 */
+#ifdef CONFIG_LM75
+	{
+		I2C_BOARD_INFO("lm75", 0x48),
+		.type = "lm75a",
+	},
+#endif	/* CONFIG_LM75 */
+#ifdef CONFIG_LM95241
+	{
+		I2C_BOARD_INFO("lm95241", 0x2b),
+		.type = "lm95241",
+	},
+#endif	/* CONFIG_LM95241 */
+};
+
+
+/* This can be used only directly from user, CS is GPA16 */
+static struct s3c2410_spi_info spi0_platform_data = {
+	.pin_cs = S3C2410_GPA16,
+	.num_cs = 1,
+	.bus_num = 0,
+};
+
+/* This can be used:
+   - directly from user, CS is GPA14
+   - to connect a Microchip ENC28J60 Ethernet controller, CS is GPA15
+   interrupt is GPG10 */
+
+static const unsigned int spi1_cs[] = {
+	S3C2410_GPA14, S3C2410_GPA15
+};
+
+static void s3c2410_spi1_cs(struct s3c2410_spi_info *spi, int cs, int pol)
+{
+	if (cs < 0)
+		cs = 0;
+	if (cs > 1)
+		cs = 1;
+	s3c2410_gpio_setpin(spi1_cs[cs], pol ? 1 : 0);
+}
+
+static struct s3c2410_spi_info spi1_platform_data = {
+	.num_cs = 2,
+	.bus_num = 1,
+	.set_cs = s3c2410_spi1_cs,
+};
+
+/* Generic spidev device */
+static struct spi_board_info rd126_spi_devices[] __initdata = {
+	{
+		.modalias = "spidev",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 0,
+	},
+	{
+		.modalias = "spidev",
+		.max_speed_hz = 25000000,
+		.bus_num = 1,
+		.chip_select = 0,
+	},
+#ifdef CONFIG_ENC28J60
+	{
+		.modalias = "enc28j60",
+		.max_speed_hz = 25000000,
+		.bus_num = 1,
+		.chip_select = 1,
+		.irq = IRQ_EINT18,	/* GPG10 */
+	},
+#endif /* CONFIG_ENC28J60 */
+};
+
+static void __init rd129_init(void)
+{
+	s3c_device_nand.dev.platform_data = &rd129_nand_info;
+	s3c_device_sdi.dev.platform_data = &rd129_mmc_cfg;
+	usb_init();
+	s3c24xx_fb_set_platdata(&fbinfo);
+	s3c_device_spi0.dev.platform_data = &spi0_platform_data;
+	s3c_device_spi1.dev.platform_data = &spi1_platform_data;
+	i2c_register_board_info(0, rd126_i2c_devices,
+		ARRAY_SIZE(rd126_i2c_devices));
+	spi_register_board_info(rd126_spi_devices,
+		ARRAY_SIZE(rd126_spi_devices));
+	platform_add_devices(rd129_devices, ARRAY_SIZE(rd129_devices));
+}
+
+MACHINE_START(RD129, "Elpa RD129")
+/* Maintainer: Davide Rizzo <elpa.rizzo@gmail.com> */
+.phys_io = S3C2410_PA_UART,
+.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+.boot_params = S3C2410_SDRAM_PA + 0x100,
+.map_io = rd129_map_io,
+.init_irq = s3c24xx_init_irq,
+.init_machine = rd129_init,
+.timer = &s3c24xx_timer,
+MACHINE_END
diff -urNp linux-2.6.28.5/arch/arm/mach-s3c2410/Makefile linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/Makefile
--- linux-2.6.28.5/arch/arm/mach-s3c2410/Makefile	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/mach-s3c2410/Makefile	2009-01-08 08:10:01.000000000 +0100
@@ -19,6 +19,7 @@ obj-$(CONFIG_S3C2410_CLOCK)	+= clock.o
 
 # Machine support
 
+obj-$(CONFIG_MACH_RD129)	+= mach-rd129.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
 obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o h1940-bluetooth.o
 obj-$(CONFIG_PM_H1940)		+= pm-h1940.o
diff -urNp linux-2.6.28.5/arch/arm/plat-s3c/include/plat/gpio.h linux-2.6.28.5.elpa/arch/arm/plat-s3c/include/plat/gpio.h
--- linux-2.6.28.5/arch/arm/plat-s3c/include/plat/gpio.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/plat-s3c/include/plat/gpio.h	2009-01-28 20:08:31.000000000 +0100
@@ -0,0 +1,24 @@
+/* arch/arm/plat-s3c/include/plat/gpio.h
+ *
+ * Copyright (c) 2008 ELPA sas
+ *	Davide Rizzo <elpa.rizzo@gmail.com>
+ *
+ * S3C2410 - GPIO platfrom_device info
+ *
+ * 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.
+*/
+
+/* struct s3c24xx_gpio_platdata
+ *
+ * define one set of hardwired gpio pins
+ *
+ * port_mask = bitmask, each bit enables corresponding pin in the bank
+ *
+*/
+
+
+struct s3c24xx_gpio_platdata {
+	unsigned long port_mask[8];	/* One for each bank of IO pins */
+};
diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/clock.c linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/clock.c
--- linux-2.6.28.5/arch/arm/plat-s3c24xx/clock.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/clock.c	2009-02-15 17:04:54.000000000 +0100
@@ -392,7 +392,7 @@ static int s3c24xx_clkout_setparent(stru
 
 	/* calculate the MISCCR setting for the clock */
 
-	if (parent == &clk_xtal)
+	if (parent == &clk_mpll)
 		source = S3C2410_MISCCR_CLK0_MPLL;
 	else if (parent == &clk_upll)
 		source = S3C2410_MISCCR_CLK0_UPLL;
@@ -422,6 +422,27 @@ static int s3c24xx_clkout_setparent(stru
 	return 0;
 }
 
+int clk_for_each(int(*fn)(struct clk *, void *), void *data)
+{
+	struct clk *clk;
+	int ret = 0;
+
+	list_for_each_entry(clk, &clocks, list)
+	{
+		ret = fn(clk, data);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(clk_for_each);
+
+const char *clk_get_sysname(struct clk *clk)
+{
+	return clk->sys_name;
+}
+EXPORT_SYMBOL(clk_get_sysname);
+
 /* external clock definitions */
 
 struct clk s3c24xx_dclk0 = {
@@ -473,6 +494,21 @@ int s3c24xx_register_clock(struct clk *c
 	/* add to the list of available clocks */
 
 	mutex_lock(&clocks_mutex);
+
+	if(clk->sys_name == NULL) {
+		if(clk->id < 0)
+			clk->sys_name = clk->name;
+		else {
+			int sys_name_len = strlen(clk->name) + 4;
+			char *sys_name = kmalloc(sys_name_len, GFP_KERNEL);
+			if(sys_name) {
+				snprintf(sys_name, sys_name_len - 1, "%s.%d",
+					clk->name, clk->id);
+				sys_name[sys_name_len - 1] = '\0';
+				clk->sys_name = sys_name;
+			}
+		}
+	}
 	list_add(&clk->list, &clocks);
 	mutex_unlock(&clocks_mutex);
 
diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/dma.c linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/dma.c
--- linux-2.6.28.5/arch/arm/plat-s3c24xx/dma.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/dma.c	2009-01-04 08:06:00.000000000 +0100
@@ -1232,7 +1232,7 @@ int s3c2410_dma_getposition(dmach_t chan
  	if (dst != NULL)
  		*dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
 
- 	return 0;
+	return s3c2410_dma_started(chan);
 }
 
 EXPORT_SYMBOL(s3c2410_dma_getposition);
diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/include/plat/clock.h linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/include/plat/clock.h
--- linux-2.6.28.5/arch/arm/plat-s3c24xx/include/plat/clock.h	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/include/plat/clock.h	2009-02-12 18:58:31.000000000 +0100
@@ -15,6 +15,7 @@ struct clk {
 	struct module        *owner;
 	struct clk           *parent;
 	const char           *name;
+	const char           *sys_name;
 	int		      id;
 	int		      usage;
 	unsigned long         rate;
diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/pwm.c linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/pwm.c
--- linux-2.6.28.5/arch/arm/plat-s3c24xx/pwm.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/pwm.c	2009-01-06 19:04:44.000000000 +0100
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
+#include <linux/interrupt.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/pwm.h>
@@ -22,6 +23,8 @@
 #include <plat/devs.h>
 #include <plat/regs-timer.h>
 
+#define DEV_NAME "s3c24xx-pwm"
+
 struct pwm_device {
 	struct list_head	 list;
 	struct platform_device	*pdev;
@@ -37,6 +40,11 @@ struct pwm_device {
 	unsigned char		 running;
 	unsigned char		 use_count;
 	unsigned char		 pwm_id;
+
+	/* For one-shot mode callback*/
+	int irq;
+	void (*expired)(struct pwm_device *, void *arg);
+	void *arg;
 };
 
 #define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg)
@@ -57,7 +65,7 @@ static struct clk *clk_scaler[2];
 	}
 
 #define DEFINE_S3C_TIMER(_tmr_no, _irq)			\
-	.name		= "s3c24xx-pwm",		\
+	.name		= DEV_NAME,		\
 	.id		= _tmr_no,			\
 	.num_resources	= TIMER_RESOURCE_SIZE,		\
 	.resource	= TIMER_RESOURCE(_tmr_no, _irq),	\
@@ -272,6 +280,88 @@ int pwm_config(struct pwm_device *pwm, i
 
 EXPORT_SYMBOL(pwm_config);
 
+static irqreturn_t timer_isr(int irq, void *arg)
+{
+	struct pwm_device *pwm = arg;
+
+	if (pwm->expired) {
+		disable_irq(irq);
+		pwm_disable(pwm);
+		pwm->expired(pwm, pwm->arg);
+		pwm->expired = NULL;
+	}
+	return IRQ_HANDLED;
+}
+
+int pwm_one_shot(struct pwm_device *pwm, int timeout_ns,
+	void(*expired)(struct pwm_device *, void *arg), void *arg)
+{
+	unsigned long tin_rate;
+	unsigned long tin_ns;
+	unsigned long period;
+	unsigned long flags;
+	unsigned long tcon;
+	unsigned long tcnt;
+
+	/* We currently avoid using 64bit arithmetic by using the
+	 * fact that anything faster than 1Hz is easily representable
+	 * by 32bits. */
+
+	if (timeout_ns > NS_IN_HZ)
+		return -ERANGE;
+
+	/* The TCMP and TCNT can be read without a lock, they're not
+	 * shared between the timers. */
+
+	tcnt = __raw_readl(S3C2410_TCNTB(pwm->pwm_id));
+
+	period = NS_IN_HZ / timeout_ns;
+
+	pwm_dbg(pwm, "one shot timeout_ns=%d\n", timeout_ns);
+
+	if (pwm_is_tdiv(pwm)) {
+		tin_rate = pwm_calc_tin(pwm, period);
+		clk_set_rate(pwm->clk_div, tin_rate);
+	} else
+		tin_rate = clk_get_rate(pwm->clk);
+
+	pwm_dbg(pwm, "tin_rate=%lu\n", tin_rate);
+
+	tin_ns = NS_IN_HZ / tin_rate;
+	tcnt = timeout_ns / tin_ns;
+	/* Note, counters count down */
+
+	pwm_dbg(pwm, "tin_ns=%lu\n", tin_ns);
+
+	/* Update the PWM register block. */
+
+	local_irq_save(flags);
+
+	if (!pwm->expired)
+		enable_irq(pwm->irq);
+
+	__raw_writel(tcnt, S3C2410_TCNTB(pwm->pwm_id));
+
+	tcon = __raw_readl(S3C2410_TCON);
+	tcon |= pwm_tcon_manulupdate(pwm);
+	tcon &= ~pwm_tcon_autoreload(pwm);
+	tcon &= ~pwm_tcon_start(pwm);
+	__raw_writel(tcon, S3C2410_TCON);
+
+
+	pwm->expired = expired;
+	pwm->arg = arg;
+
+	tcon &= ~pwm_tcon_manulupdate(pwm);
+	tcon |= pwm_tcon_start(pwm);
+	__raw_writel(tcon, S3C2410_TCON);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_one_shot);
+
 static int pwm_register(struct pwm_device *pwm)
 {
 	pwm->duty_ns = -1;
@@ -288,6 +378,7 @@ static int s3c_pwm_probe(struct platform
 {
 	struct device *dev = &pdev->dev;
 	struct pwm_device *pwm;
+	struct resource *res;
 	unsigned long flags;
 	unsigned long tcon;
 	unsigned int id = pdev->id;
@@ -306,6 +397,22 @@ static int s3c_pwm_probe(struct platform
 
 	pwm->pdev = pdev;
 	pwm->pwm_id = id;
+	pwm->expired = NULL;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "cannot get platform interrupt resource\n");
+		ret = -EBUSY;
+		goto err_getresources;
+	}
+	pwm->irq = res->start;
+	ret = request_irq(pwm->irq, timer_isr, IRQF_DISABLED,
+		DEV_NAME, pwm);
+	if (ret) {
+		dev_err(dev, "request_irq failed\n");
+		goto err_getirq;
+	}
+	disable_irq(pwm->irq);
 
 	/* calculate base of control bits in TCON */
 	pwm->tcon_base = id == 0 ? 0 : (id * 4) + 4;
@@ -354,6 +461,10 @@ static int s3c_pwm_probe(struct platform
 	clk_put(pwm->clk_div);
 
  err_clk_tin:
+ err_getresources:
+	free_irq(pwm->irq, DEV_NAME);
+
+ err_getirq:
 	clk_put(pwm->clk);
 
  err_alloc:
@@ -365,6 +476,7 @@ static int s3c_pwm_remove(struct platfor
 {
 	struct pwm_device *pwm = platform_get_drvdata(pdev);
 
+	free_irq(pwm->irq, DEV_NAME);
 	clk_put(pwm->clk_div);
 	clk_put(pwm->clk);
 	kfree(pwm);
@@ -374,7 +486,7 @@ static int s3c_pwm_remove(struct platfor
 
 static struct platform_driver s3c_pwm_driver = {
 	.driver		= {
-		.name	= "s3c24xx-pwm",
+		.name	= DEV_NAME,
 		.owner	= THIS_MODULE,
 	},
 	.probe		= s3c_pwm_probe,
diff -urNp linux-2.6.28.5/arch/arm/plat-s3c24xx/pwm-clock.c linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/pwm-clock.c
--- linux-2.6.28.5/arch/arm/plat-s3c24xx/pwm-clock.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/arch/arm/plat-s3c24xx/pwm-clock.c	2009-01-08 08:25:39.000000000 +0100
@@ -77,7 +77,7 @@ static unsigned long clk_pwm_scaler_getr
 {
 	unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
 
-	if (clk->id == 1) {
+	if (strcmp(clk->name, "pwm-scaler1") == 0) {
 		tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK;
 		tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT;
 	} else {
@@ -87,6 +87,39 @@ static unsigned long clk_pwm_scaler_getr
 	return clk_get_rate(clk->parent) / (tcfg0 + 1);
 }
 
+/* WARNING! By changing the scalers rates you influence all child timers */
+/* Use this with care, you could corrupt the main tick generator */
+
+static int clk_pwm_scaler_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
+	int div;
+
+	if (IS_ERR(clk))
+		return -EINVAL;
+
+	if (rate <= 0)
+		return -EINVAL;
+
+	div = clk_get_rate(clk->parent) / rate - 1;
+
+	if (div < 0)
+		div = 0;
+	if (div > 255)
+		div = 255;
+
+	if (strcmp(clk->name, "pwm-scaler1") == 0) {
+		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+		tcfg0 |= div << S3C2410_TCFG_PRESCALER1_SHIFT;
+	} else {
+		tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
+		tcfg0 |= div;
+	}
+	__raw_writel(tcfg0, S3C2410_TCFG0);
+
+	return clk_pwm_scaler_getrate(clk);
+}
+
 /* TODO - add set rate calls. */
 
 static struct clk clk_timer_scaler[] = {
@@ -94,11 +127,13 @@ static struct clk clk_timer_scaler[] = {
 		.name		= "pwm-scaler0",
 		.id		= -1,
 		.get_rate	= clk_pwm_scaler_getrate,
+		.set_rate = clk_pwm_scaler_setrate,
 	},
 	[1]	= {
 		.name		= "pwm-scaler1",
 		.id		= -1,
 		.get_rate	= clk_pwm_scaler_getrate,
+		.set_rate = clk_pwm_scaler_setrate,
 	},
 };
 
@@ -399,7 +434,8 @@ static __init int s3c24xx_pwmclk_init(vo
 		clk_timer_scaler[clk].parent = clk_timers;
 		ret = s3c24xx_register_clock(&clk_timer_scaler[clk]);
 		if (ret < 0) {
-			printk(KERN_ERR "error adding pwm scaler%d clock\n", clk);
+			printk(KERN_ERR "error adding pwm scaler%d clock\n",
+				clk);
 			goto err;
 		}
 	}
@@ -407,7 +443,7 @@ static __init int s3c24xx_pwmclk_init(vo
 	for (clk = 0; clk < ARRAY_SIZE(clk_timer_tclk); clk++) {
 		ret = s3c24xx_register_clock(&clk_timer_tclk[clk]);
 		if (ret < 0) {
-			printk(KERN_ERR "error adding pww tclk%d\n", clk);
+			printk(KERN_ERR "error adding pwm tclk%d\n", clk);
 			goto err;
 		}
 	}
diff -urNp linux-2.6.28.5/.config linux-2.6.28.5.elpa/.config
--- linux-2.6.28.5/.config	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/.config	2009-02-15 18:16:12.000000000 +0100
@@ -0,0 +1,1572 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28.5
+# Sun Feb 15 18:16:12 2009
+#
+CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_MMU=y
+CONFIG_NO_IOPORT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+CONFIG_ARCH_S3C2410=y
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+CONFIG_PLAT_S3C24XX=y
+CONFIG_S3C24XX_PWM=y
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+CONFIG_PLAT_S3C=y
+CONFIG_CPU_LLSERIAL_S3C2410_ONLY=y
+CONFIG_CPU_LLSERIAL_S3C2410=y
+
+#
+# Boot options
+#
+# CONFIG_S3C_BOOT_WATCHDOG is not set
+# CONFIG_S3C_BOOT_ERROR_RESET is not set
+
+#
+# Power management
+#
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+
+#
+# S3C2400 Machines
+#
+CONFIG_CPU_S3C2410=y
+CONFIG_CPU_S3C2410_DMA=y
+CONFIG_S3C2410_GPIO=y
+CONFIG_S3C2410_CLOCK=y
+
+#
+# S3C2410 Machines
+#
+# CONFIG_ARCH_SMDK2410 is not set
+# CONFIG_ARCH_H1940 is not set
+# CONFIG_MACH_N30 is not set
+# CONFIG_ARCH_BAST is not set
+# CONFIG_MACH_OTOM is not set
+# CONFIG_MACH_AML_M5900 is not set
+# CONFIG_MACH_TCT_HAMMER is not set
+# CONFIG_MACH_VR1000 is not set
+# CONFIG_MACH_QT2410 is not set
+CONFIG_MACH_RD129=y
+
+#
+# S3C2412 Machines
+#
+# CONFIG_MACH_JIVE is not set
+# CONFIG_MACH_SMDK2413 is not set
+# CONFIG_MACH_SMDK2412 is not set
+# CONFIG_MACH_VSTMS is not set
+
+#
+# S3C2440 Machines
+#
+# CONFIG_MACH_ANUBIS is not set
+# CONFIG_MACH_OSIRIS is not set
+# CONFIG_MACH_RX3715 is not set
+# CONFIG_ARCH_S3C2440 is not set
+# CONFIG_MACH_NEXCODER_2440 is not set
+# CONFIG_MACH_AT2440EVB is not set
+
+#
+# S3C2442 Machines
+#
+
+#
+# S3C2443 Machines
+#
+# CONFIG_MACH_SMDK2443 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4T=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=200
+# CONFIG_AEABI is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_BLOCK2MTD=y
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_S3C2410=y
+# CONFIG_MTD_NAND_S3C2410_DEBUG is not set
+CONFIG_MTD_NAND_S3C2410_HWECC=y
+CONFIG_MTD_NAND_S3C2410_CLKSTOP=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+CONFIG_UM_TIMER=y
+CONFIG_UM_TIMER_ONESHOT=y
+CONFIG_UM_CLOCK=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+# CONFIG_RT2X00 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+CONFIG_TOUCHSCREEN_S3C2410=y
+CONFIG_TOUCHSCREEN_ENABLE_S3C2410=y
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_S3C2410=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_S3C2410=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+CONFIG_AT24=y
+CONFIG_AT24_TYPE="24c64"
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_S3C24XX=y
+# CONFIG_SPI_S3C24XX_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+CONFIG_SENSORS_LM75=y
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+CONFIG_SENSORS_LM95241=y
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_S3C2410_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_S3C2410=y
+# CONFIG_FB_S3C2410_DEBUG is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_PWM_FREQUENCY=20000
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_S3C24XX_SOC=y
+CONFIG_SND_S3C24XX_SOC_I2S=y
+CONFIG_SND_S3C24XX_SOC_RD126_PCM3006=y
+# CONFIG_SND_S3C24XX_SOC_RD126_WM8731 is not set
+# CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650 is not set
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_PCM3006=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_RD129_USB_1HOST is not set
+# CONFIG_RD129_USB_2HOST is not set
+CONFIG_RD129_USB_AUTO=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+CONFIG_USB_GADGET_S3C2410=y
+CONFIG_USB_S3C2410=y
+# CONFIG_USB_S3C2410_DEBUG is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_S3C=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_S3C is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+CONFIG_UIO=y
+CONFIG_UIO_S3C2410_GPIO=y
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_S3C_UART=2
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff -urNp linux-2.6.28.5/Documentation/ABI/testing/sysfs-class-clock linux-2.6.28.5.elpa/Documentation/ABI/testing/sysfs-class-clock
--- linux-2.6.28.5/Documentation/ABI/testing/sysfs-class-clock	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/Documentation/ABI/testing/sysfs-class-clock	2009-01-28 19:10:42.000000000 +0100
@@ -0,0 +1,20 @@
+What:		/sys/class/clock
+Date:		January 2009
+Contact:	Davide Rizzo <elpa.rizzo@gmail.com>
+Description:
+		The /sys/class/clock directory will consist of a group of
+		subdirectories each one describing an internal clock in the kernel.
+		The name of the subdirectory is the clock's name.
+		If a clock is device specific, its name is in the form "name.id".
+		In each directory there are 2 virtual files: rate and parent.
+		Both these files are r/w, but there can be some architecture-dependent
+		limitations on write access on one or both of them.
+		For this interface to work, it needs some low-level implementations (look
+		at include/linux/clk.h):
+		- clk_for_each()
+		- clk_name()
+		- clk_get() should recognize also the "name.id" format
+		Actually I implemented these only for Samsung S3C SoC in
+		arch/arm/plat-s3c/clock.c
+
+Users:
diff -urNp linux-2.6.28.5/drivers/hwmon/Kconfig linux-2.6.28.5.elpa/drivers/hwmon/Kconfig
--- linux-2.6.28.5/drivers/hwmon/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/hwmon/Kconfig	2009-01-04 08:07:39.000000000 +0100
@@ -548,6 +548,15 @@ config SENSORS_LM93
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm93.
 
+config SENSORS_LM95241
+	tristate "National Semiconductor LM95241 sensor chip"
+	depends on I2C
+	help
+	  If you say yes here you get support for LM95241 sensor chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm95241.
+
 config SENSORS_MAX1111
 	tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip"
 	depends on SPI_MASTER
diff -urNp linux-2.6.28.5/drivers/hwmon/lm95241.c linux-2.6.28.5.elpa/drivers/hwmon/lm95241.c
--- linux-2.6.28.5/drivers/hwmon/lm95241.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/hwmon/lm95241.c	2009-01-28 20:08:54.000000000 +0100
@@ -0,0 +1,527 @@
+/*
+ * lm95241.c - Part of lm_sensors, Linux kernel modules for hardware
+ *             monitoring
+ * Copyright (C) 2008 Davide Rizzo <elpa.rizzo@gmail.com>
+ *
+ * Based on the max1619 driver. The LM95241 is a sensor chip made by National
+ *   Semiconductors.
+ * It reports up to three temperatures (its own plus up to
+ * two external ones). Complete datasheet can be
+ * obtained from National's website at:
+ *   http://www.national.com/ds.cgi/LM/LM95241.pdf
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+static const unsigned short normal_i2c[] = {
+	0x19, 0x2a, 0x2b, I2C_CLIENT_END};
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(lm95241);
+
+/* LM95241 registers */
+#define LM95241_REG_R_MAN_ID		0xFE
+#define LM95241_REG_R_CHIP_ID		0xFF
+#define LM95241_REG_R_STATUS		0x02
+#define LM95241_REG_RW_CONFIG		0x03
+#define LM95241_REG_RW_REM_FILTER	0x06
+#define LM95241_REG_RW_TRUTHERM		0x07
+#define LM95241_REG_W_ONE_SHOT  	0x0F
+#define LM95241_REG_R_LOCAL_TEMPH	0x10
+#define LM95241_REG_R_REMOTE1_TEMPH	0x11
+#define LM95241_REG_R_REMOTE2_TEMPH	0x12
+#define LM95241_REG_R_LOCAL_TEMPL	0x20
+#define LM95241_REG_R_REMOTE1_TEMPL	0x21
+#define LM95241_REG_R_REMOTE2_TEMPL	0x22
+#define LM95241_REG_RW_REMOTE_MODEL	0x30
+
+/* LM95241 specific bitfields */
+#define CFG_STOP 0x40
+#define CFG_CR0076 0x00
+#define CFG_CR0182 0x10
+#define CFG_CR1000 0x20
+#define CFG_CR2700 0x30
+#define R1MS_SHIFT 0
+#define R2MS_SHIFT 2
+#define R1MS_MASK (0x01 << (R1MS_SHIFT))
+#define R2MS_MASK (0x01 << (R2MS_SHIFT))
+#define R1DF_SHIFT 1
+#define R2DF_SHIFT 2
+#define R1DF_MASK (0x01 << (R1DF_SHIFT))
+#define R2DF_MASK (0x01 << (R2DF_SHIFT))
+#define R1FE_MASK 0x01
+#define R2FE_MASK 0x05
+#define TT1_SHIFT 0
+#define TT2_SHIFT 4
+#define TT_OFF 0
+#define TT_ON 1
+#define TT_MASK 7
+#define MANUFACTURER_ID 0x01
+#define DEFAULT_REVISION 0xA4
+
+/* Conversions and various macros */
+#define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \
+    (val_h)) * 1000 + (val_l) * 1000 / 256)
+
+/* Functions declaration */
+static int lm95241_attach_adapter(struct i2c_adapter *adapter);
+static int lm95241_detect(struct i2c_adapter *adapter, int address,
+			  int kind);
+static void lm95241_init_client(struct i2c_client *client);
+static int lm95241_detach_client(struct i2c_client *client);
+static struct lm95241_data *lm95241_update_device(struct device *dev);
+
+/* Driver data (common to all clients) */
+static struct i2c_driver lm95241_driver = {
+	.driver = {
+		.name   = "lm95241",
+	},
+	.attach_adapter = lm95241_attach_adapter,
+	.detach_client  = lm95241_detach_client,
+};
+
+/* Client data (each client gets its own) */
+struct lm95241_data {
+	struct i2c_client client;
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	unsigned long last_updated, rate; /* in jiffies */
+	char valid; /* zero until following fields are valid */
+	/* registers values */
+	u8 local_h, local_l; /* local */
+	u8 remote1_h, remote1_l; /* remote1 */
+	u8 remote2_h, remote2_l; /* remote2 */
+	u8 config, model, trutherm;
+};
+
+/* Sysfs stuff */
+#define show_temp(value) \
+static ssize_t show_##value(struct device *dev, \
+    struct device_attribute *attr, char *buf) \
+{ \
+	struct lm95241_data *data = lm95241_update_device(dev); \
+	snprintf(buf, PAGE_SIZE - 1, "%d\n", \
+		TEMP_FROM_REG(data->value##_h, data->value##_l)); \
+	return strlen(buf); \
+}
+show_temp(local);
+show_temp(remote1);
+show_temp(remote2);
+
+static ssize_t show_rate(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct lm95241_data *data = lm95241_update_device(dev);
+
+	snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ);
+	return strlen(buf);
+}
+
+static ssize_t set_rate(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
+
+	strict_strtol(buf, 10, &data->rate);
+	data->rate = data->rate * HZ / 1000;
+
+	return count;
+}
+
+#define show_type(flag) \
+static ssize_t show_type##flag(struct device *dev, \
+				   struct device_attribute *attr, char *buf) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm95241_data *data = i2c_get_clientdata(client); \
+\
+	snprintf(buf, PAGE_SIZE - 1, \
+		data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \
+	return strlen(buf); \
+}
+show_type(1);
+show_type(2);
+
+#define show_min(flag) \
+static ssize_t show_min##flag(struct device *dev, \
+    struct device_attribute *attr, char *buf) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm95241_data *data = i2c_get_clientdata(client); \
+\
+	snprintf(buf, PAGE_SIZE - 1, \
+		data->config & R##flag##DF_MASK ?	\
+		"-127000\n" : "0\n"); \
+	return strlen(buf); \
+}
+show_min(1);
+show_min(2);
+
+#define show_max(flag) \
+static ssize_t show_max##flag(struct device *dev, \
+    struct device_attribute *attr, char *buf) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm95241_data *data = i2c_get_clientdata(client); \
+\
+	snprintf(buf, PAGE_SIZE - 1, \
+		data->config & R##flag##DF_MASK ? \
+		"127000\n" : "255000\n"); \
+	return strlen(buf); \
+}
+show_max(1);
+show_max(2);
+
+#define set_type(flag) \
+static ssize_t set_type##flag(struct device *dev, \
+				  struct device_attribute *attr, \
+				  const char *buf, size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm95241_data *data = i2c_get_clientdata(client); \
+\
+	long val; \
+	strict_strtol(buf, 10, &val); \
+\
+	if ((val == 1) || (val == 2)) { \
+\
+		mutex_lock(&data->update_lock); \
+\
+		data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \
+		if (val == 1) { \
+			data->model |= R##flag##MS_MASK; \
+			data->trutherm |= (TT_ON << TT##flag##_SHIFT); \
+		} \
+		else { \
+			data->model &= ~R##flag##MS_MASK; \
+			data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \
+		} \
+\
+		data->valid = 0; \
+\
+		i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \
+					  data->model); \
+		i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \
+					  data->trutherm); \
+\
+		mutex_unlock(&data->update_lock); \
+\
+	} \
+	return count; \
+}
+set_type(1);
+set_type(2);
+
+#define set_min(flag) \
+static ssize_t set_min##flag(struct device *dev, \
+	struct device_attribute *devattr, const char *buf, size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm95241_data *data = i2c_get_clientdata(client); \
+\
+	long val; \
+	strict_strtol(buf, 10, &val); \
+\
+	mutex_lock(&data->update_lock); \
+\
+	if (val < 0) \
+		data->config |= R##flag##DF_MASK; \
+	else \
+		data->config &= ~R##flag##DF_MASK; \
+\
+	data->valid = 0; \
+\
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \
+		data->config); \
+\
+	mutex_unlock(&data->update_lock); \
+\
+	return count; \
+}
+set_min(1);
+set_min(2);
+
+#define set_max(flag) \
+static ssize_t set_max##flag(struct device *dev, \
+	struct device_attribute *devattr, const char *buf, size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm95241_data *data = i2c_get_clientdata(client); \
+\
+	long val; \
+	strict_strtol(buf, 10, &val); \
+\
+	mutex_lock(&data->update_lock); \
+\
+	if (val <= 127000) \
+		data->config |= R##flag##DF_MASK; \
+	else \
+		data->config &= ~R##flag##DF_MASK; \
+\
+	data->valid = 0; \
+\
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \
+		data->config); \
+\
+	mutex_unlock(&data->update_lock); \
+\
+	return count; \
+}
+set_max(1);
+set_max(2);
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL);
+static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL);
+static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL);
+static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1);
+static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2);
+static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1);
+static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2);
+static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1);
+static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2);
+static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate);
+
+static struct attribute *lm95241_attributes[] = {
+	&dev_attr_temp1_input.attr,
+	&dev_attr_temp2_input.attr,
+	&dev_attr_temp3_input.attr,
+	&dev_attr_temp2_type.attr,
+	&dev_attr_temp3_type.attr,
+	&dev_attr_temp2_min.attr,
+	&dev_attr_temp3_min.attr,
+	&dev_attr_temp2_max.attr,
+	&dev_attr_temp3_max.attr,
+	&dev_attr_rate.attr,
+	NULL
+};
+
+static const struct attribute_group lm95241_group = {
+	.attrs = lm95241_attributes,
+};
+
+/* Init/exit code */
+static int lm95241_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, lm95241_detect);
+}
+
+/*
+ * The following function does more than just detection. If detection
+ * succeeds, it also registers the new chip.
+ */
+static int lm95241_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct lm95241_data *data;
+	int err = 0;
+	const char *name = "";
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto exit;
+
+	data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	/* The common I2C client data is placed right before the
+	   LM95241-specific data. */
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &lm95241_driver;
+	new_client->flags = 0;
+
+	/*
+	 * Now we do the remaining detection. A negative kind means that
+	 * the driver was loaded with no force parameter (default), so we
+	 * must both detect and identify the chip. A zero kind means that
+	 * the driver was loaded with the force parameter, the detection
+	 * step shall be skipped. A positive kind means that the driver
+	 * was loaded with the force parameter and a given kind of chip is
+	 * requested, so both the detection and the identification steps
+	 * are skipped.
+	 */
+	if (kind < 0) {	/* detection */
+		if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
+		     != MANUFACTURER_ID)
+		|| (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
+		    < DEFAULT_REVISION)) {
+			dev_dbg(&adapter->dev,
+				"LM95241 detection failed at 0x%02x.\n",
+				address);
+			goto exit_free;
+		}
+	}
+
+	if (kind <= 0) { /* identification */
+		if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
+		     == MANUFACTURER_ID)
+		&& (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
+		    >= DEFAULT_REVISION)) {
+
+			kind = lm95241;
+
+			if (kind <= 0) { /* identification failed */
+				dev_info(&adapter->dev, "Unsupported chip\n");
+				goto exit_free;
+			}
+		}
+	}
+
+	if (kind == lm95241)
+		name = "lm95241";
+
+	/* We can fill in the remaining client fields */
+	strlcpy(new_client->name, name, I2C_NAME_SIZE);
+	data->valid = 0;
+	mutex_init(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	err = i2c_attach_client(new_client);
+	if (err)
+		goto exit_free;
+
+	/* Initialize the LM95241 chip */
+	lm95241_init_client(new_client);
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group);
+	if (err)
+		goto exit_detach;
+
+	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove_files;
+	}
+
+	return 0;
+
+exit_remove_files:
+	sysfs_remove_group(&new_client->dev.kobj, &lm95241_group);
+exit_detach:
+	i2c_detach_client(new_client);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static void lm95241_init_client(struct i2c_client *client)
+{
+	struct lm95241_data *data = i2c_get_clientdata(client);
+
+	data->rate = HZ;    /* 1 sec default */
+	data->valid = 0;
+	data->config = CFG_CR0076;
+	data->model = 0;
+	data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT);
+
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG,
+				  data->config);
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER,
+				  R1FE_MASK | R2FE_MASK);
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM,
+				  data->trutherm);
+	i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL,
+				  data->model);
+}
+
+static int lm95241_detach_client(struct i2c_client *client)
+{
+	struct lm95241_data *data = i2c_get_clientdata(client);
+	int err;
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm95241_group);
+
+	err = i2c_detach_client(client);
+	if (err)
+		return err;
+
+	kfree(data);
+	return 0;
+}
+
+static struct lm95241_data *lm95241_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm95241_data *data = i2c_get_clientdata(client);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + data->rate) ||
+	    !data->valid) {
+		dev_dbg(&client->dev, "Updating lm95241 data.\n");
+		data->local_h =
+			i2c_smbus_read_byte_data(client,
+						 LM95241_REG_R_LOCAL_TEMPH);
+		data->local_l =
+			i2c_smbus_read_byte_data(client,
+						 LM95241_REG_R_LOCAL_TEMPL);
+		data->remote1_h =
+			i2c_smbus_read_byte_data(client,
+						 LM95241_REG_R_REMOTE1_TEMPH);
+		data->remote1_l =
+			i2c_smbus_read_byte_data(client,
+						 LM95241_REG_R_REMOTE1_TEMPL);
+		data->remote2_h =
+			i2c_smbus_read_byte_data(client,
+						 LM95241_REG_R_REMOTE2_TEMPH);
+		data->remote2_l =
+			i2c_smbus_read_byte_data(client,
+						 LM95241_REG_R_REMOTE2_TEMPL);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+static int __init sensors_lm95241_init(void)
+{
+	return i2c_add_driver(&lm95241_driver);
+}
+
+static void __exit sensors_lm95241_exit(void)
+{
+	i2c_del_driver(&lm95241_driver);
+}
+
+MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
+MODULE_DESCRIPTION("LM95241 sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_lm95241_init);
+module_exit(sensors_lm95241_exit);
diff -urNp linux-2.6.28.5/drivers/hwmon/Makefile linux-2.6.28.5.elpa/drivers/hwmon/Makefile
--- linux-2.6.28.5/drivers/hwmon/Makefile	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/hwmon/Makefile	2009-01-04 08:14:42.000000000 +0100
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_LM87)	+= lm87.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
 obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
 obj-$(CONFIG_SENSORS_LM93)	+= lm93.o
+obj-$(CONFIG_SENSORS_LM95241)	+= lm95241.o
 obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
diff -urNp linux-2.6.28.5/drivers/i2c/chips/Kconfig linux-2.6.28.5.elpa/drivers/i2c/chips/Kconfig
--- linux-2.6.28.5/drivers/i2c/chips/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/i2c/chips/Kconfig	2009-01-06 18:24:39.000000000 +0100
@@ -42,6 +42,16 @@ config AT24
 	  This driver can also be built as a module.  If so, the module
 	  will be called at24.
 
+config AT24_TYPE
+	string "Eeprom model"
+	depends on AT24
+	default "24c64"
+	help
+	  IICBus Eeprom model (must be specified, driver cannot automatically
+	  recognize it). Valid values:
+	  24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
+	  24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
+
 config SENSORS_EEPROM
 	tristate "EEPROM reader"
 	depends on EXPERIMENTAL
diff -urNp linux-2.6.28.5/drivers/input/touchscreen/Kconfig linux-2.6.28.5.elpa/drivers/input/touchscreen/Kconfig
--- linux-2.6.28.5/drivers/input/touchscreen/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/input/touchscreen/Kconfig	2009-01-04 07:40:45.000000000 +0100
@@ -287,6 +287,18 @@ config TOUCHSCREEN_WM97XX_MAINSTONE
 	  To compile this driver as a module, choose M here: the
 	  module will be called mainstone-wm97xx.
 
+config TOUCHSCREEN_S3C2410
+	tristate "Samsung S3C2410 ADC/Touchscreen"
+	depends on ARCH_S3C2410
+	help
+	  This enables support for S3C2410 internal ADC/Touchscreen driver
+
+config TOUCHSCREEN_ENABLE_S3C2410
+	bool "Samsung S3C2410 Touchscreen"
+	depends on TOUCHSCREEN_S3C2410
+	help
+	  This enables support for S3C2410 internal Touchscreen driver
+
 config TOUCHSCREEN_USB_COMPOSITE
 	tristate "USB Touchscreen Driver"
 	depends on USB_ARCH_HAS_HCD
diff -urNp linux-2.6.28.5/drivers/input/touchscreen/Makefile linux-2.6.28.5.elpa/drivers/input/touchscreen/Makefile
--- linux-2.6.28.5/drivers/input/touchscreen/Makefile	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/input/touchscreen/Makefile	2009-01-04 07:40:45.000000000 +0100
@@ -31,3 +31,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)	+
 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)	+= s3c2410ts.o
diff -urNp linux-2.6.28.5/drivers/input/touchscreen/s3c2410ts.c linux-2.6.28.5.elpa/drivers/input/touchscreen/s3c2410ts.c
--- linux-2.6.28.5/drivers/input/touchscreen/s3c2410ts.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/input/touchscreen/s3c2410ts.c	2009-01-28 20:09:11.000000000 +0100
@@ -0,0 +1,573 @@
+/*
+ drivers/input/touchscreen/s3c2410ts.c
+
+ Written Feb 2008 by Davide Rizzo <elpa.rizzo@gmail.com>
+
+ This is a Touchscreen/ADC driver for the Samsung S3C2410 ARM9 SoC
+ ADC samples can be requested by reading "ainX" virtual files.
+ Touchscreen interface generates standard input events.
+ Touchscreen's parameters "samples" and "trigger" are exposed by virtual files
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+#include <plat/regs-adc.h>
+#include <mach/regs-gpio.h>
+#include <linux/io.h>
+
+/* At least FILTER_SAMPLES must be within NOISE_TRIGGER interval */
+#define DEFAULT_FILTER_SAMPLES 16
+#define DEFAULT_NOISE_TRIGGER 64
+#define ADC_DELAY_TIME 0xFFFF /* Maximum allovable */
+#define ADC_CLK 1000000
+#define DRIVER_NAME "s3c2410-adc"
+#define TS_INT_NAME "touchscreen"
+#define ADC_INT_NAME "adc"
+
+enum pen_state {
+	IDLE, /* Touchscreen not pressed */
+	TOUCHING, /*Performing double ADC conversion because touch pressed */
+	DUMMY, /*Dummy conversion between Touch samples groups to check if the
+	touch is still pressed */
+	CONVERTING, /* Performing single ADC conversion (external request) */
+};
+
+struct s3c2410_ts_info {
+	struct clk *adc_clk, *pclk;
+	void __iomem *regs;
+	wait_queue_head_t waitq; /* Wait queue for reading adc values */
+	struct mutex mtx; /* Mutex to synchronize multithread adc access */
+	spinlock_t lock; /* To sync with isr */
+	unsigned int adc_data_ready, adc_data, adc_channel;
+	unsigned int adc_conversion_request, prescaler, irq_adc, irq_ts;
+	enum pen_state state, old_state;
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+	struct input_dev *idev;
+	unsigned int x_avrg, y_avrg, samples, trigger;
+	unsigned int x_min, x_max, y_min, y_max, sample;
+#endif	/* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+};
+
+static void AdcWait(struct s3c2410_ts_info *info)
+{
+	writel(
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+		S3C2410_ADCTSC_XY_PST(3) |
+#else /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+		S3C2410_ADCTSC_XY_PST(0) |
+#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+		S3C2410_ADCTSC_YM_SEN |
+		S3C2410_ADCTSC_YP_SEN |
+		S3C2410_ADCTSC_XP_SEN,
+		info->regs + S3C2410_ADCTSC);
+	writel(S3C2410_ADCCON_PRSCEN |
+		S3C2410_ADCCON_PRSCVL(info->prescaler) |
+		S3C2410_ADCCON_SELMUX(7),
+		info->regs + S3C2410_ADCCON);
+}
+
+/* Setups ADC for next state manages stylus-up messages
+   It should be called from isr or with lock held (and int disabled) */
+static void isr_common(struct s3c2410_ts_info *info)
+{
+	/* If there is a direct adc conversion pending request,
+	   interrupts current state and performs conversion */
+	if (info->adc_conversion_request) {
+		info->old_state = info->state;
+		info->state = CONVERTING;
+		info->adc_conversion_request = 0;
+	}
+
+	switch (info->state) {
+	case IDLE:
+		AdcWait(info);
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+		input_report_key(info->idev, BTN_TOUCH, 0);
+		input_sync(info->idev);
+#endif	/* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+		break;
+	case CONVERTING:
+		/* Adc Single conversion */
+		writel(
+			S3C2410_ADCTSC_YM_SEN |
+			S3C2410_ADCTSC_YP_SEN |
+			S3C2410_ADCTSC_XM_SEN |
+			S3C2410_ADCTSC_XP_SEN |
+			S3C2410_ADCTSC_PULL_UP_DISABLE |
+			S3C2410_ADCTSC_XY_PST(0),
+			info->regs + S3C2410_ADCTSC);
+		writel(S3C2410_ADCCON_PRSCEN |
+			S3C2410_ADCCON_PRSCVL(info->prescaler) |
+			S3C2410_ADCCON_SELMUX(info->adc_channel) |
+			S3C2410_ADCCON_ENABLE_START,
+			info->regs + S3C2410_ADCCON);
+		break;
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+	case DUMMY:
+		/* Adc Single conversion */
+		writel(
+			S3C2410_ADCTSC_YM_SEN |
+			S3C2410_ADCTSC_YP_SEN |
+			S3C2410_ADCTSC_XP_SEN |
+			S3C2410_ADCTSC_XY_PST(3),
+			info->regs + S3C2410_ADCTSC);
+		writel(S3C2410_ADCCON_PRSCEN |
+			S3C2410_ADCCON_PRSCVL(info->prescaler) |
+			S3C2410_ADCCON_SELMUX(0) |
+			S3C2410_ADCCON_ENABLE_START,
+			info->regs + S3C2410_ADCCON);
+		break;
+	case TOUCHING:
+		/* Adc Auto conversion mode */
+		writel(
+			S3C2410_ADCTSC_YM_SEN |
+			S3C2410_ADCTSC_YP_SEN |
+			S3C2410_ADCTSC_XP_SEN |
+			S3C2410_ADCTSC_AUTO_PST |
+			S3C2410_ADCTSC_XY_PST(0),
+			info->regs + S3C2410_ADCTSC);
+		writel(S3C2410_ADCCON_PRSCEN |
+			S3C2410_ADCCON_PRSCVL(info->prescaler) |
+			S3C2410_ADCCON_SELMUX(7) |
+			S3C2410_ADCCON_ENABLE_START,
+			info->regs + S3C2410_ADCCON);
+		break;
+#endif	/* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+	default:
+		break;
+	}
+}
+
+static irqreturn_t isr_adc(int irq, void *dev_id)
+{
+	struct s3c2410_ts_info *info = dev_id;
+	unsigned int x, y;
+
+	switch (info->state) {
+	case CONVERTING:
+		info->adc_data = readl(info->regs + S3C2410_ADCDAT0) & 0x3FF;
+		info->adc_data_ready = 1;
+		wake_up(&info->waitq);
+		info->state = info->old_state; /* Restore previous state */
+		break;
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+	case TOUCHING:
+		x = readl(info->regs + S3C2410_ADCDAT0) & 0x3FF;
+		y = readl(info->regs + S3C2410_ADCDAT1) & 0x3FF;
+		writel(
+			S3C2410_ADCTSC_YM_SEN |
+			S3C2410_ADCTSC_YP_SEN |
+			S3C2410_ADCTSC_XM_SEN |
+			S3C2410_ADCTSC_XP_SEN |
+			S3C2410_ADCTSC_XY_PST(3),
+			info->regs + S3C2410_ADCTSC);
+		info->x_avrg += x;
+		info->y_avrg += y;
+		if (x < info->x_min)
+			info->x_min = x;
+		if (x > info->x_max)
+			info->x_max = x;
+		if (y < info->y_min)
+			info->y_min = y;
+		if (y > info->y_max)
+			info->y_max = y;
+		if ((info->x_max - info->x_min < info->trigger) &&
+			(info->y_max - info->y_min < info->trigger)) {
+			if (++info->sample < info->samples)
+				break;
+			input_report_key(info->idev, BTN_TOUCH, 1);
+			input_report_abs(info->idev, ABS_X,
+				info->x_avrg / info->samples);
+			input_report_abs(info->idev, ABS_Y,
+				info->y_avrg / info->samples);
+			input_sync(info->idev);
+		}
+		info->state = DUMMY;
+		break;
+	case DUMMY:
+		AdcWait(info);
+		if ((readl(info->regs + S3C2410_ADCDAT0) &
+			S3C2410_ADCDAT0_UPDOWN) &&
+			(readl(info->regs + S3C2410_ADCDAT1) &
+			S3C2410_ADCDAT1_UPDOWN))
+			info->state = IDLE;
+		else {
+			info->state = TOUCHING;
+			info->sample = 0;
+			info->x_avrg = info->y_avrg = 0;
+			info->x_min = info->y_min = 32767;
+			info->x_max = info->y_max = 0;
+		}
+		break;
+#endif	/* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+	default:
+		break;
+	}
+	isr_common(info);
+	return IRQ_HANDLED;
+}
+
+static ssize_t adc_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct s3c2410_ts_info *info = dev_get_drvdata(dev);
+	unsigned long flags;
+	int t;
+
+	mutex_lock(&info->mtx);	/* It should always succeed in a short time */
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	info->adc_channel = attr->attr.name[3] - '0';
+	info->adc_data_ready = 0;
+	info->adc_conversion_request = 1;
+	if (info->state == IDLE)
+		isr_common(info);
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	wait_event(info->waitq, info->adc_data_ready); /* It should always
+	 succeed in a short time */
+	t = info->adc_data;
+
+	mutex_unlock(&info->mtx);
+
+	snprintf(buffer, PAGE_SIZE - 1, "%d\n", t);
+	return strlen(buffer);
+}
+
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+
+static irqreturn_t isr_ts(int irq, void *dev_id)
+{
+	struct s3c2410_ts_info *info = dev_id;
+
+	if ((readl(info->regs + S3C2410_ADCDAT0) & S3C2410_ADCDAT0_UPDOWN) ||
+		(readl(info->regs + S3C2410_ADCDAT1) &
+		S3C2410_ADCDAT1_UPDOWN))
+		info->state = IDLE;
+	else if (info->state == IDLE) {
+		info->state = TOUCHING;
+		info->sample = 0;
+		info->x_avrg = info->y_avrg = 0;
+		info->x_min = info->y_min = 32767;
+		info->x_max = info->y_max = 0;
+	}
+	isr_common(info);
+	return IRQ_HANDLED;
+}
+
+static ssize_t samples_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct s3c2410_ts_info *info = dev_get_drvdata(dev);
+
+	snprintf(buffer, PAGE_SIZE - 1, "%d\n", info->samples);
+	return strlen(buffer);
+}
+
+static ssize_t samples_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	struct s3c2410_ts_info *info = dev_get_drvdata(dev);
+	unsigned long samples, flags;
+	int err = strict_strtoul(buffer, 10, &samples);
+
+	if (err)
+		return err;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	info->samples = samples;
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	return count;
+}
+
+static ssize_t trigger_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct s3c2410_ts_info *info = dev_get_drvdata(dev);
+
+	snprintf(buffer, PAGE_SIZE - 1, "%d\n", info->trigger);
+	return strlen(buffer);
+}
+
+static ssize_t trigger_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	struct s3c2410_ts_info *info = dev_get_drvdata(dev);
+	unsigned long trigger, flags;
+	int err = strict_strtoul(buffer, 10, &trigger);
+
+	if (err)
+		return err;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	info->trigger = trigger;
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	return count;
+}
+
+static DEVICE_ATTR(samples, S_IRUGO | S_IWUSR, samples_show, samples_store);
+static DEVICE_ATTR(trigger, S_IRUGO | S_IWUSR, trigger_show, trigger_store);
+
+#else /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+
+static DEVICE_ATTR(ain5, S_IRUGO, adc_show, NULL);
+static DEVICE_ATTR(ain7, S_IRUGO, adc_show, NULL);
+
+#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+
+static DEVICE_ATTR(ain0, S_IRUGO, adc_show, NULL);
+static DEVICE_ATTR(ain1, S_IRUGO, adc_show, NULL);
+static DEVICE_ATTR(ain2, S_IRUGO, adc_show, NULL);
+static DEVICE_ATTR(ain3, S_IRUGO, adc_show, NULL);
+static DEVICE_ATTR(ain4, S_IRUGO, adc_show, NULL);
+static DEVICE_ATTR(ain6, S_IRUGO, adc_show, NULL);
+
+static struct device_attribute *at[] = {
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+	&dev_attr_samples,
+	&dev_attr_trigger,
+#else /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+	&dev_attr_ain5,
+	&dev_attr_ain7,
+#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+	&dev_attr_ain0,
+	&dev_attr_ain1,
+	&dev_attr_ain2,
+	&dev_attr_ain3,
+	&dev_attr_ain4,
+	&dev_attr_ain6,
+	NULL
+};
+
+static int s3c2410ts_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *res;
+	struct s3c2410_ts_info *info;
+	struct device_attribute **curr_at;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&pdev->dev, "out of kernel memory\n");
+		ret = -ENOMEM;
+		goto fail_malloc;
+	}
+	platform_set_drvdata(pdev, info);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "cannot get platform memory resource\n");
+		ret = -EBUSY;
+		goto fail_getresources1;
+	}
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+		DRIVER_NAME)) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		ret = -EBUSY;
+		goto fail_reqmem;
+	}
+	info->regs = ioremap(res->start, res->end - res->start + 1);
+	if (!info->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENXIO;
+		goto fail_ioremap;
+	}
+	info->pclk = clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(info->pclk)) {
+		dev_err(&pdev->dev, "failed to get pclk\n");
+		ret = PTR_ERR(info->pclk);
+		goto fail_getpclk;
+	}
+	info->prescaler = clk_get_rate(info->pclk) / ADC_CLK - 1;
+	info->adc_clk = clk_get(&pdev->dev, "adc");
+	if (IS_ERR(info->adc_clk)) {
+		dev_err(&pdev->dev, "failed to get adc_clk\n");
+		ret = PTR_ERR(info->pclk);
+		goto fail_getadcclk;
+	}
+	clk_enable(info->adc_clk);	/* Abilita clock su ADC */
+	mutex_init(&info->mtx);
+	init_waitqueue_head(&info->waitq);
+	spin_lock_init(&info->lock);
+	info->state = IDLE;
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+	/* Set GPG15 to use as nYPON, GPG14 to use as YMON,
+	   GPG13 to use as nXPON, GPG12 to use as XMON */
+	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);
+	/* Disable pull up function */
+	s3c2410_gpio_pullup(S3C2410_GPG12, 1);
+	s3c2410_gpio_pullup(S3C2410_GPG13, 1);
+	s3c2410_gpio_pullup(S3C2410_GPG14, 1);
+	s3c2410_gpio_pullup(S3C2410_GPG15, 1);
+	info->idev = input_allocate_device();
+	if (!info->idev) {
+		dev_err(&pdev->dev, "Unable to allocate device\n");
+		ret = -ENOMEM;
+		goto fail_inputalloc;
+	}
+	info->idev->name = "S3C2410 Touchscreen";
+	info->idev->phys = "s3c2410ts";
+	info->samples = DEFAULT_FILTER_SAMPLES;
+	info->trigger = DEFAULT_NOISE_TRIGGER;
+	input_set_abs_params(info->idev, ABS_X, 0, 1023, 3, 0);
+	input_set_abs_params(info->idev, ABS_Y, 0, 1023, 3, 0);
+	set_bit(EV_KEY, info->idev->evbit);
+	set_bit(EV_ABS, info->idev->evbit);
+	set_bit(BTN_TOUCH, info->idev->keybit);
+	ret = input_register_device(info->idev);
+	if (ret) {
+		input_free_device(info->idev);
+		dev_err(&pdev->dev, "Unable to register input driver\n");
+		goto fail_inputregister;
+	}
+	/* Allocate IRQ_TC, Touchscreen interrupt must be the 1st in the list */
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "cannot get platform interrupt resource\n");
+		ret = -EBUSY;
+		goto fail_getresources2;
+	}
+	info->irq_ts = res->start;
+	ret = request_irq(info->irq_ts, isr_ts, IRQF_DISABLED, TS_INT_NAME,
+		info);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to get IRQ_TC\n");
+		goto fail_reqtcirq;
+	}
+#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+	/* Allocate IRQ_ADC, Adc interrupt must be the 2nd in the list */
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "cannot get platform interrupt resource\n");
+		ret = -EBUSY;
+		goto fail_getresources3;
+	}
+	info->irq_adc = res->start;
+	ret = request_irq(info->irq_adc, isr_adc, IRQF_DISABLED, ADC_INT_NAME,
+		info);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to get IRQ_ADC\n");
+		goto fail_reqadcirq;
+	}
+	for (curr_at = at; *curr_at; curr_at++) {
+		ret = device_create_file(&pdev->dev, *curr_at);
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Unable to create virtual file\n");
+			goto fail_vf;
+		}
+	}
+	/* ADC Start or Interval Delay */
+	writel(ADC_DELAY_TIME, info->regs + S3C2410_ADCDLY);
+	AdcWait(info);
+	dev_notice(&pdev->dev, "S3C2410 Touch Screen / ADC Driver loaded OK\n");
+	return ret;
+fail_vf:
+	while (--curr_at >= at)
+		device_remove_file(&pdev->dev, *curr_at);
+	free_irq(info->irq_adc, info);
+fail_reqadcirq:
+fail_getresources3:
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+	free_irq(info->irq_ts, info);
+fail_reqtcirq:
+fail_getresources2:
+	input_unregister_device(info->idev);
+fail_inputregister:
+fail_inputalloc:
+#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+	clk_disable(info->adc_clk);
+	clk_put(info->adc_clk);
+fail_getadcclk:
+	clk_put(info->pclk);
+fail_getpclk:
+	iounmap(info->regs);
+fail_ioremap:
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, res->end - res->start + 1);
+fail_reqmem:
+fail_getresources1:
+	platform_set_drvdata(pdev, NULL);
+	kfree(info);
+fail_malloc:
+	return ret;
+}
+
+static int s3c2410ts_remove(struct platform_device *pdev)
+{
+	struct s3c2410_ts_info *info = platform_get_drvdata(pdev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct device_attribute **curr_at;
+
+	dev_notice(&pdev->dev, "S3C2410 Touch Screen / ADC Exit !!!\n");
+	for (curr_at = at; *curr_at; curr_at++)
+		device_remove_file(&pdev->dev, *curr_at);
+
+	while (mutex_is_locked(&info->mtx))
+		schedule();
+	free_irq(info->irq_adc, info);
+#ifdef CONFIG_TOUCHSCREEN_ENABLE_S3C2410
+	free_irq(info->irq_ts, info);
+	input_unregister_device(info->idev);
+#endif /* CONFIG_TOUCHSCREEN_ENABLE_S3C2410 */
+	clk_disable(info->adc_clk);
+	clk_put(info->adc_clk);
+	clk_put(info->pclk);
+	iounmap(info->regs);
+	release_mem_region(res->start, res->end - res->start + 1);
+	platform_set_drvdata(pdev, NULL);
+	kfree(info);
+	return 0;
+}
+
+static struct platform_driver s3c2410ts_driver = {
+	.probe = s3c2410ts_probe,
+	.remove = s3c2410ts_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init s3c2410_ts_init_module(void)
+{
+	return platform_driver_register(&s3c2410ts_driver);
+}
+
+static void __exit s3c2410_ts_cleanup_module(void)
+{
+	platform_driver_unregister(&s3c2410ts_driver);
+}
+
+module_init(s3c2410_ts_init_module);
+module_exit(s3c2410_ts_cleanup_module);
+
+MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
+MODULE_DESCRIPTION("S3C2410 ELPA ADC/Touchscreen driver");
+MODULE_SUPPORTED_DEVICE("touchscreen/s3c2410");
+MODULE_LICENSE("GPL");
diff -urNp linux-2.6.28.5/drivers/misc/Kconfig linux-2.6.28.5.elpa/drivers/misc/Kconfig
--- linux-2.6.28.5/drivers/misc/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/misc/Kconfig	2009-01-28 19:15:29.000000000 +0100
@@ -500,4 +500,41 @@ config SGI_GRU_DEBUG
 
 source "drivers/misc/c2port/Kconfig"
 
+config UM_TIMER
+	bool "User mode timer driver"
+	depends on SYSFS
+	default n
+	---help---
+	Allows user mode programs to configure and control general purpose
+	 timers.
+
+	If unsure, say N.
+
+config UM_TIMER_ONESHOT
+	bool "User mode timer driver uses one-shot mode"
+	depends on UM_TIMER
+	default n
+	---help---
+	Enable this to allow general purpose timer driver to use timers
+	 in one-shot mode. For this to work, the function pwm_one_shot()
+	 must be implemented in low-level drivers.
+	Currently it's implemented only on Samsung S3C24xx platforms.
+
+	If unsure, say N.
+
+config UM_CLOCK
+	bool "User mode clock driver"
+	depends on SYSFS
+	default n
+	---help---
+	Allows user mode programs to configure and control internal clocks'
+	 rates and parents through virtual files in sysfs.
+	This driver requires implementation of some additional functions
+	 in architecture specific low-level drivers: clk_for_each() and
+	 clk_get_name(). Moreover, it requires clk_get() to recognize the
+	 "name.id" format
+	Currently they're implemented only on Samsung S3C24xx platforms.
+
+	If unsure, say N.
+
 endif # MISC_DEVICES
diff -urNp linux-2.6.28.5/drivers/misc/Makefile linux-2.6.28.5.elpa/drivers/misc/Makefile
--- linux-2.6.28.5/drivers/misc/Makefile	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/misc/Makefile	2009-01-17 11:42:09.000000000 +0100
@@ -33,3 +33,5 @@ obj-$(CONFIG_SGI_XP)		+= sgi-xp/
 obj-$(CONFIG_SGI_GRU)		+= sgi-gru/
 obj-$(CONFIG_HP_ILO)		+= hpilo.o
 obj-$(CONFIG_C2PORT)		+= c2port/
+obj-$(CONFIG_UM_CLOCK) += um_clock.o
+obj-$(CONFIG_UM_TIMER) += um_timer.o
diff -urNp linux-2.6.28.5/drivers/misc/um_clock.c linux-2.6.28.5.elpa/drivers/misc/um_clock.c
--- linux-2.6.28.5/drivers/misc/um_clock.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/misc/um_clock.c	2009-02-12 19:07:25.000000000 +0100
@@ -0,0 +1,169 @@
+/*
+ driver/misc/clock.c
+
+ Written Feb 2008 by Davide Rizzo <elpa.rizzo@gmail.com>
+
+ This driver allows to read and modify internal clocks' rates using
+  virtual files. User can also read and modify parents.
+
+ This driver requires implementation of clk_name() and clk_enum() functions
+  in architecture specific clock.c
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/kdev_t.h>
+#include <linux/err.h>
+
+static DEFINE_MUTEX(mutex);
+
+static ssize_t rate_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	unsigned long rate;
+	struct clk *clk;
+
+	clk = dev_get_drvdata(dev);
+	rate = 0;
+
+	mutex_lock(&mutex);
+
+	rate = clk_get_rate(clk);
+
+	mutex_unlock(&mutex);
+
+	return sprintf(buffer, "%ld\n", rate);
+}
+
+static ssize_t rate_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	unsigned long rate;
+	struct clk *clk;
+	int err;
+
+	clk = dev_get_drvdata(dev);
+	err = strict_strtoul(buffer, 10, &rate);
+	if (err)
+		return err;
+
+	mutex_lock(&mutex);
+
+	if (rate != 0) {
+		clk_set_rate(clk, clk_round_rate(clk, rate));
+		clk_enable(clk);
+	} else
+		clk_disable(clk);
+
+	mutex_unlock(&mutex);
+
+	return count;
+}
+
+static ssize_t parent_show(struct device *dev,
+	struct device_attribute *attr, char *buffer)
+{
+	struct clk *parent, *clk;
+
+	clk = dev_get_drvdata(dev);
+
+	mutex_lock(&mutex);
+
+	parent = clk_get_parent(clk);
+	if (parent && !IS_ERR(parent))
+		strlcpy(buffer, clk_get_sysname(parent), PAGE_SIZE);
+	else
+		buffer[0] = '\0';
+	strlcat(buffer, "\n", PAGE_SIZE);
+
+	mutex_unlock(&mutex);
+
+	return strlen(buffer);
+}
+
+static ssize_t parent_store(struct device *dev,
+	struct device_attribute *attr, const char *buffer, size_t count)
+{
+	struct clk *parent;
+
+	char *s = kstrdup(buffer, GFP_KERNEL);
+
+	if (!s)
+		return -ENOMEM;
+	if (s[strlen(s) - 1] == '\n')
+		s[strlen(s) - 1] = '\0';
+	parent = clk_get(dev, s);
+	kfree(s);
+	if (IS_ERR(parent))
+		return PTR_ERR(parent);
+
+	mutex_lock(&mutex);
+
+	clk_set_parent(dev_get_drvdata(dev), parent);
+
+	mutex_unlock(&mutex);
+
+	clk_put(parent);
+	return count;
+}
+
+static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, rate_show, rate_store);
+static DEVICE_ATTR(parent, S_IRUGO | S_IWUSR, parent_show, parent_store);
+
+static const struct attribute *clock_attrs[] = {
+	&dev_attr_rate.attr,
+	&dev_attr_parent.attr,
+	NULL,
+};
+
+static const struct attribute_group clock_attr_group = {
+	.attrs = (struct attribute **) clock_attrs,
+};
+
+static struct class gpclock_class = {
+	.name =		"clock",
+	.owner =	THIS_MODULE,
+};
+
+static int create_clock_attr(struct clk *clk, void *data)
+{
+	struct device *dev;
+	const char *name;
+
+	name = clk_get_sysname(clk);
+	if (name == NULL || IS_ERR(name)) {
+		pr_debug("Invalid clock's name\n");
+		return PTR_ERR(name);
+	}
+	dev = device_create(&gpclock_class, (struct device *)data, MKDEV(0, 0),
+		clk, name);
+	if (!dev)
+		return -ENODEV;
+	return sysfs_create_group(&dev->kobj, &clock_attr_group);
+}
+
+static int __init gpclock_init(void)
+{
+	int ret;
+
+	ret = class_register(&gpclock_class);
+	if (ret >= 0)
+		ret = clk_for_each(create_clock_attr, NULL);
+	return ret;
+}
+subsys_initcall(gpclock_init);
+
diff -urNp linux-2.6.28.5/drivers/misc/um_timer.c linux-2.6.28.5.elpa/drivers/misc/um_timer.c
--- linux-2.6.28.5/drivers/misc/um_timer.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/misc/um_timer.c	2009-01-28 20:09:40.000000000 +0100
@@ -0,0 +1,281 @@
+/*
+ * drivers/misc/timer.c
+ *
+ * Written Jan 2009 by Davide Rizzo <elpa.rizzo@gmail.com>
+ *
+ * This driver allows user to access internal timers
+ * You can use any timer to generate a fixed frequency signal, or to wait for a
+ * defined short time (if hardware can do it).
+ * To generate a PWM signal, you have to write the frequency value in Hz into
+ * the virtual file "freq". After that you can program the duty cycle in the
+ * virtual file "duty", in 1/1000 units (500 = 50%).
+ * To wait for a time, you have to write the number of microseconds in virtual
+ * file "wait". Reading from same file will complete when timer will expire.
+ * Licensed under the GPLv2 only.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/pwm.h>
+
+struct timer_info {
+	int id;
+	struct pwm_device *pwm;
+	unsigned long period_ns, duty_ns;
+	struct mutex mtx;
+#ifdef CONFIG_UM_TIMER_ONESHOT
+	int flag;
+	wait_queue_head_t wq;
+#endif	/* CONFIG_UM_TIMER_ONESHOT */
+};
+
+#ifdef CONFIG_UM_TIMER_ONESHOT
+static void expired(struct pwm_device *pwm, void *arg)
+{
+	struct timer_info *info = dev_get_drvdata((struct device *)arg);
+
+	info->flag = 1;
+
+	wake_up_interruptible(&info->wq);
+}
+
+/* Delay is in usec */
+static ssize_t wait_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	struct timer_info *info = dev_get_drvdata(dev);
+	unsigned long delay;
+	int err = strict_strtoul(buffer, 10, &delay);
+
+	if (err)
+		return err;
+
+	mutex_lock(&info->mtx);
+
+	info->flag = 0;
+	pwm_one_shot(info->pwm, delay * 1000, expired, dev);
+
+	mutex_unlock(&info->mtx);
+
+	return count;
+}
+
+/* Waits for delay */
+static ssize_t wait_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct timer_info *info = dev_get_drvdata(dev);
+	int ret;
+
+	mutex_lock(&info->mtx);
+
+	/* !=0 if interrupted by some other signal */
+	ret = wait_event_interruptible(info->wq, info->flag);
+
+	mutex_unlock(&info->mtx);
+
+	snprintf(buffer, PAGE_SIZE - 1, "%d\n", ret);
+	return strlen(buffer);
+}
+#endif	/* CONFIG_UM_TIMER_ONESHOT */
+
+#define NS_IN_HZ (1000000000UL)
+
+/* Freq is in Hz */
+static ssize_t freq_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	struct timer_info *info = dev_get_drvdata(dev);
+	unsigned long output_freq;
+	int err = strict_strtoul(buffer, 10, &output_freq);
+	if (err)
+		return err;
+
+	mutex_lock(&info->mtx);
+
+	if (output_freq == 0) { /* Stop timer */
+		pwm_disable(info->pwm);
+		info->period_ns = 0;
+		info->duty_ns = 0;
+	} else {
+		unsigned long new_period = NS_IN_HZ / output_freq;
+		if (info->period_ns == 0)
+			info->duty_ns = new_period / 2;
+		else {
+			unsigned long long ll = (unsigned long long)new_period *
+				info->duty_ns ;
+			do_div(ll, info->period_ns);
+			info->duty_ns = ll;
+		}
+		info->period_ns = new_period;
+		pwm_config(info->pwm, info->duty_ns, info->period_ns);
+		pwm_enable(info->pwm);
+	}
+
+	mutex_unlock(&info->mtx);
+
+	return count;
+}
+
+/* Freq is in Hz */
+static ssize_t freq_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct timer_info *info = dev_get_drvdata(dev);
+	if (info->period_ns)
+		snprintf(buffer, PAGE_SIZE - 1, "%ld\n", NS_IN_HZ /
+			info->period_ns);
+	else
+		strlcpy(buffer, "0\n", PAGE_SIZE);
+	return strlen(buffer);
+}
+
+/* Duty is in 1/1000 units */
+static ssize_t duty_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	struct timer_info *info = dev_get_drvdata(dev);
+	unsigned long duty;
+	int err = strict_strtoul(buffer, 10, &duty);
+	if (err)
+		return err;
+	if (duty > 1000)
+		return -ERANGE;
+
+	mutex_lock(&info->mtx);
+
+	if ((info->period_ns == 0) || (duty == 0)) { /* Stop timer */
+		info->duty_ns = 0;
+		pwm_disable(info->pwm);
+	} else {
+		unsigned long long ll = (unsigned long long)duty *
+			info->period_ns;
+		do_div(ll, 1000);
+		info->duty_ns = ll;
+		pwm_config(info->pwm, info->duty_ns, info->period_ns);
+		pwm_enable(info->pwm);
+	}
+
+	mutex_unlock(&info->mtx);
+
+	return count;
+}
+
+/* Duty is in 1/1000 units */
+static ssize_t duty_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct timer_info *info = dev_get_drvdata(dev);
+
+	mutex_lock(&info->mtx);
+
+	if (info->period_ns) {
+		volatile unsigned long long ll = info->duty_ns * 1000;
+		do_div(ll, info->period_ns);
+		snprintf(buffer, PAGE_SIZE - 1, "%ld\n", (long int)ll);
+	} else
+		strlcpy(buffer, "0\n", PAGE_SIZE);
+
+	mutex_unlock(&info->mtx);
+
+	return strlen(buffer);
+}
+
+#ifdef CONFIG_UM_TIMER_ONESHOT
+DEVICE_ATTR(wait, S_IRUGO | S_IWUSR, wait_show, wait_store);
+#endif	/* CONFIG_UM_TIMER_ONESHOT */
+DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR, freq_show, freq_store);
+DEVICE_ATTR(duty, S_IRUGO | S_IWUSR, duty_show, duty_store);
+
+static struct attribute *attrs[] = {
+#ifdef CONFIG_UM_TIMER_ONESHOT
+	&dev_attr_wait.attr,
+#endif	/* CONFIG_UM_TIMER_ONESHOT */
+	&dev_attr_frequency.attr,
+	&dev_attr_duty.attr,
+	NULL,
+};
+
+static struct attribute_group attr_grp = {
+	.attrs = attrs,
+};
+
+static int timer_probe(struct platform_device *pdev)
+{
+	struct timer_info *info;
+	int err;
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&pdev->dev, "out of kernel memory\n");
+		err = -ENOMEM;
+		goto fail_malloc;
+	}
+	platform_set_drvdata(pdev, info);
+	mutex_init(&info->mtx);
+	info->pwm = pwm_request(pdev->id, "timer driver");
+	if (IS_ERR(info->pwm)) {
+		err = PTR_ERR(info->pwm);
+		goto fail_req;
+	}
+#ifdef CONFIG_UM_TIMER_ONESHOT
+	init_waitqueue_head(&info->wq);
+	info->flag = 1;
+#endif	/* CONFIG_UM_TIMER_ONESHOT */
+	err = sysfs_create_group(&pdev->dev.kobj, &attr_grp);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to create virtual files\n");
+		goto fail_req;
+	}
+	dev_notice(&pdev->dev, "timer %d device driver loaded OK\n", pdev->id);
+	return 0;
+fail_req:
+	platform_set_drvdata(pdev, NULL);
+	kfree(info);
+fail_malloc:
+	return err;
+}
+
+static int timer_remove(struct platform_device *pdev)
+{
+	struct timer_info *info = platform_get_drvdata(pdev);
+
+	mutex_lock(&info->mtx);
+
+	sysfs_remove_group(&pdev->dev.kobj, &attr_grp);
+
+	pwm_free(info->pwm);
+	platform_set_drvdata(pdev, NULL);
+
+	mutex_unlock(&info->mtx);
+
+	kfree(info);
+	return 0;
+}
+
+static struct platform_driver timer_driver = {
+	.probe  = timer_probe,
+	.remove = timer_remove,
+	.driver = {
+		.name = "um_timer",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init timer_init_module(void)
+{
+	return platform_driver_register(&timer_driver);
+}
+
+static void __exit timer_cleanup_module(void)
+{
+	platform_driver_unregister(&timer_driver);
+}
+
+module_init(timer_init_module);
+module_exit(timer_cleanup_module);
+
+MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
+MODULE_DESCRIPTION("Timers driver");
+MODULE_SUPPORTED_DEVICE("um_timers");
+MODULE_LICENSE("GPL v2");
diff -urNp linux-2.6.28.5/drivers/mtd/nand/s3c2410.c linux-2.6.28.5.elpa/drivers/mtd/nand/s3c2410.c
--- linux-2.6.28.5/drivers/mtd/nand/s3c2410.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/mtd/nand/s3c2410.c	2009-01-04 07:40:59.000000000 +0100
@@ -898,6 +898,18 @@ static int s3c24xx_nand_probe(struct pla
 						 (sets) ? sets->nr_chips : 1);
 
 		if (nmtd->scan_res == 0) {
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+			/* Replaces 1st set parsing cmdline */
+			if (setno == 0) {
+				const char *part_probes[] = {
+					"cmdlinepart", NULL
+				};
+				info->mtds->mtd.name = sets->name;
+				sets->nr_partitions = parse_mtd_partitions(
+					&info->mtds->mtd, part_probes,
+					&sets->partitions, 0);
+			}
+#endif
 			s3c2410_nand_update_chip(info, nmtd);
 			nand_scan_tail(&nmtd->mtd);
 			s3c2410_nand_add_partition(info, nmtd, sets);
diff -urNp linux-2.6.28.5/drivers/net/enc28j60.c linux-2.6.28.5.elpa/drivers/net/enc28j60.c
--- linux-2.6.28.5/drivers/net/enc28j60.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/net/enc28j60.c	2009-01-04 07:40:59.000000000 +0100
@@ -88,26 +88,25 @@ static struct {
 static int
 spi_read_buf(struct enc28j60_net *priv, int len, u8 *data)
 {
-	u8 *rx_buf = priv->spi_transfer_buf + 4;
-	u8 *tx_buf = priv->spi_transfer_buf;
 	struct spi_transfer t = {
-		.tx_buf = tx_buf,
-		.rx_buf = rx_buf,
-		.len = SPI_OPLEN + len,
+		.tx_buf = priv->spi_transfer_buf,
+		.len = SPI_OPLEN,
+	};
+	struct spi_transfer r = {
+		.rx_buf = data,
+		.len = len,
 	};
 	struct spi_message msg;
 	int ret;
 
-	tx_buf[0] = ENC28J60_READ_BUF_MEM;
-	tx_buf[1] = tx_buf[2] = tx_buf[3] = 0;	/* don't care */
+	priv->spi_transfer_buf[0] = ENC28J60_READ_BUF_MEM;
 
 	spi_message_init(&msg);
 	spi_message_add_tail(&t, &msg);
+	spi_message_add_tail(&r, &msg);
 	ret = spi_sync(priv->spi, &msg);
-	if (ret == 0) {
-		memcpy(data, &rx_buf[SPI_OPLEN], len);
+	if (ret == 0)
 		ret = msg.status;
-	}
 	if (ret && netif_msg_drv(priv))
 		printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
 			__func__, ret);
diff -urNp linux-2.6.28.5/drivers/spi/spi_s3c24xx.c linux-2.6.28.5.elpa/drivers/spi/spi_s3c24xx.c
--- linux-2.6.28.5/drivers/spi/spi_s3c24xx.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/spi/spi_s3c24xx.c	2009-01-04 07:40:59.000000000 +0100
@@ -120,15 +120,13 @@ static int s3c24xx_spi_setupxfer(struct 
 		return -EINVAL;
 	}
 
-	div = clk_get_rate(hw->clk) / hz;
+	if (hz > 25000000)
+		hz = 25000000;
 
-	/* is clk = pclk / (2 * (pre+1)), or is it
-	 *    clk = (pclk * 2) / ( pre + 1) */
+	div = clk_get_rate(hw->clk) / (hz + 1) / 2;
 
-	div /= 2;
-
-	if (div > 0)
-		div -= 1;
+	if (div < 0)
+		div = 0;
 
 	if (div > 255)
 		div = 255;
diff -urNp linux-2.6.28.5/drivers/uio/Kconfig linux-2.6.28.5.elpa/drivers/uio/Kconfig
--- linux-2.6.28.5/drivers/uio/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/uio/Kconfig	2009-01-08 16:38:52.000000000 +0100
@@ -13,6 +13,14 @@ menuconfig UIO
 
 if UIO
 
+config UIO_S3C2410_GPIO
+	tristate "S3C2410 general purpose digital I/O driver"
+	depends on ARCH_S3C2410
+	default y
+	---help---
+	  This allows to configure and control general purpose digital
+	   I/O lines from user level code on Samsung S3C2410 SoC
+
 config UIO_CIF
 	tristate "generic Hilscher CIF Card driver"
 	depends on PCI
diff -urNp linux-2.6.28.5/drivers/uio/Makefile linux-2.6.28.5.elpa/drivers/uio/Makefile
--- linux-2.6.28.5/drivers/uio/Makefile	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/uio/Makefile	2009-01-08 16:37:43.000000000 +0100
@@ -1,4 +1,5 @@
 obj-$(CONFIG_UIO)	+= uio.o
+obj-$(CONFIG_UIO_S3C2410_GPIO)  += s3c2410-gpio.o
 obj-$(CONFIG_UIO_CIF)	+= uio_cif.o
 obj-$(CONFIG_UIO_PDRV)	+= uio_pdrv.o
 obj-$(CONFIG_UIO_PDRV_GENIRQ)	+= uio_pdrv_genirq.o
diff -urNp linux-2.6.28.5/drivers/uio/s3c2410-gpio.c linux-2.6.28.5.elpa/drivers/uio/s3c2410-gpio.c
--- linux-2.6.28.5/drivers/uio/s3c2410-gpio.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/uio/s3c2410-gpio.c	2009-01-28 20:09:54.000000000 +0100
@@ -0,0 +1,715 @@
+/*
+ drivers/uio/s3c2410-gpio.c
+
+ Written Feb 2008 by Davide Rizzo <elpa.rizzo@gmail.com>
+
+ This driver allows users to read/write general purpose digital I/O functions
+ and values.
+ Pin's functions can be accessed with XX-cfg virtual files (can be one of:
+ input, output, fn1, fn2 or direct function name).
+ Pin's status (when function is input or output) can be read/set by XX virtual
+ file.
+ Pin's pullup can be read/set with XX-pup virtual file (1=on, 0=off).
+ When a pin is programmed for external interrupt, you can use 2 additional
+ virtual files:
+ eintX-cfg access interrupt's mode, can be one of: rising, falling or both.
+ eintX when read waits until interrupt triggers.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-irq.h>
+#include <linux/io.h>
+#include <plat/irq.h>
+#include <plat/gpio.h>
+
+#define EXT_INTS_NR 24
+
+#define S3C2410_GPIO_BANK(x) ((x) * 32)
+#define S3C2410_BANKNUM S3C2400_BANKNUM
+
+struct fn_name {
+	unsigned int pin;
+	const char *fn1_name, *fn2_name;
+};
+
+static const struct fn_name pins[] =
+{
+	{S3C2410_GPA0, "addr0", NULL},
+	{S3C2410_GPA1, "addr16", NULL},
+	{S3C2410_GPA2, "addr17", NULL},
+	{S3C2410_GPA3, "addr18", NULL},
+	{S3C2410_GPA4, "addr19", NULL},
+	{S3C2410_GPA5, "addr20", NULL},
+	{S3C2410_GPA6, "addr21", NULL},
+	{S3C2410_GPA7, "addr22", NULL},
+	{S3C2410_GPA8, "addr23", NULL},
+	{S3C2410_GPA9, "addr24", NULL},
+	{S3C2410_GPA10, "addr25", NULL},
+	{S3C2410_GPA11, "addr26", NULL},
+	{S3C2410_GPA12, "gcs1", NULL},
+	{S3C2410_GPA13, "gcs2", NULL},
+	{S3C2410_GPA14, "gcs3", NULL},
+	{S3C2410_GPA15, "gcs4", NULL},
+	{S3C2410_GPA16, "gcs5", NULL},
+	{S3C2410_GPA17, "cle", NULL},
+	{S3C2410_GPA18, "ale", NULL},
+	{S3C2410_GPA19, "fwe", NULL},
+	{S3C2410_GPA20, "fre", NULL},
+	{S3C2410_GPA21, "rstout", NULL},
+	{S3C2410_GPA22, "fce", NULL},
+	{S3C2410_GPB0, "tout0", NULL},
+	{S3C2410_GPB1, "tout1", NULL},
+	{S3C2410_GPB2, "tout2", NULL},
+	{S3C2410_GPB3, "tout3", NULL},
+	{S3C2410_GPB4, "tclk0", NULL},
+	{S3C2410_GPB5, "xback", NULL},
+	{S3C2410_GPB6, "xbreq", NULL},
+	{S3C2410_GPB7, "xdack1", NULL},
+	{S3C2410_GPB8, "xdreq1", NULL},
+	{S3C2410_GPB9, "xdack0", NULL},
+	{S3C2410_GPB10, "xdreq0", NULL},
+	{S3C2410_GPC0, "lend", NULL},
+	{S3C2410_GPC1, "vclk", NULL},
+	{S3C2410_GPC2, "vline", NULL},
+	{S3C2410_GPC3, "vframe", NULL},
+	{S3C2410_GPC4, "vm", NULL},
+	{S3C2410_GPC5, "lcdvf0", NULL},
+	{S3C2410_GPC6, "lcdvf1", NULL},
+	{S3C2410_GPC7, "lcdvf2", NULL},
+	{S3C2410_GPC8, "vd0", NULL},
+	{S3C2410_GPC9, "vd1", NULL},
+	{S3C2410_GPC10, "vd2", NULL},
+	{S3C2410_GPC11, "vd3", NULL},
+	{S3C2410_GPC12, "vd4", NULL},
+	{S3C2410_GPC13, "vd5", NULL},
+	{S3C2410_GPC14, "vd6", NULL},
+	{S3C2410_GPC15, "vd7", NULL},
+	{S3C2410_GPD0, "vd8", NULL},
+	{S3C2410_GPD1, "vd9", NULL},
+	{S3C2410_GPD2, "vd10", NULL},
+	{S3C2410_GPD3, "vd11", NULL},
+	{S3C2410_GPD4, "vd12", NULL},
+	{S3C2410_GPD5, "vd13", NULL},
+	{S3C2410_GPD6, "vd14", NULL},
+	{S3C2410_GPD7, "vd15", NULL},
+	{S3C2410_GPD8, "vd16", NULL},
+	{S3C2410_GPD9, "vd17", NULL},
+	{S3C2410_GPD10, "vd18", NULL},
+	{S3C2410_GPD11, "vd19", NULL},
+	{S3C2410_GPD12, "vd20", NULL},
+	{S3C2410_GPD13, "vd21", NULL},
+	{S3C2410_GPD14, "vd22", "ss1"},
+	{S3C2410_GPD15, "vd23", "ss0"},
+	{S3C2410_GPE0, "i2slrck", NULL},
+	{S3C2410_GPE1, "i2ssclk", NULL},
+	{S3C2410_GPE2, "cdclk", NULL},
+	{S3C2410_GPE3, "i2ssdi", "ss0"},
+	{S3C2410_GPE4, "i2ssdo", "i2ssdi"},
+	{S3C2410_GPE5, "sdclk", NULL},
+	{S3C2410_GPE6, "sdcmd", NULL},
+	{S3C2410_GPE7, "sddat0", NULL},
+	{S3C2410_GPE8, "sddat1", NULL},
+	{S3C2410_GPE9, "sddat2", NULL},
+	{S3C2410_GPE10, "sddat3", NULL},
+	{S3C2410_GPE11, "spimiso0", NULL},
+	{S3C2410_GPE12, "spimosi0", NULL},
+	{S3C2410_GPE13, "spiclk0", NULL},
+	{S3C2410_GPE14, "iicscl", NULL},
+	{S3C2410_GPE15, "iicsda", NULL},
+	{S3C2410_GPF0, "eint0", NULL},
+	{S3C2410_GPF1, "eint1", NULL},
+	{S3C2410_GPF2, "eint2", NULL},
+	{S3C2410_GPF3, "eint3", NULL},
+	{S3C2410_GPF4, "eint4", NULL},
+	{S3C2410_GPF5, "eint5", NULL},
+	{S3C2410_GPF6, "eint6", NULL},
+	{S3C2410_GPF7, "eint7", NULL},
+	{S3C2410_GPG0, "eint8", NULL},
+	{S3C2410_GPG1, "eint9", NULL},
+	{S3C2410_GPG2, "eint10", "ss0"},
+	{S3C2410_GPG3, "eint11", "ss1"},
+	{S3C2410_GPG4, "eint12", "lcdpwren"},
+	{S3C2410_GPG5, "eint13", "spimiso1"},
+	{S3C2410_GPG6, "eint14", "spimosi1"},
+	{S3C2410_GPG7, "eint15", "spiclk1"},
+	{S3C2410_GPG8, "eint16", NULL},
+	{S3C2410_GPG9, "eint17", NULL},
+	{S3C2410_GPG10, "eint18", NULL},
+	{S3C2410_GPG11, "eint19", "tclk1"},
+	{S3C2410_GPG12, "eint20", "xmon"},
+	{S3C2410_GPG13, "eint21", "xpon"},
+	{S3C2410_GPG14, "eint22", "ymon"},
+	{S3C2410_GPG15, "eint23", "ypon"},
+	{S3C2410_GPH0, "cts0", NULL},
+	{S3C2410_GPH1, "rts0", NULL},
+	{S3C2410_GPH2, "txd0", NULL},
+	{S3C2410_GPH3, "rxd0", NULL},
+	{S3C2410_GPH4, "txd1", NULL},
+	{S3C2410_GPH5, "rxd1", NULL},
+	{S3C2410_GPH6, "txd2", "rts1"},
+	{S3C2410_GPH7, "rxd2", "cts1"},
+	{S3C2410_GPH8, "uextclk", NULL},
+	{S3C2410_GPH9, "clkout0", NULL},
+	{S3C2410_GPH10, "clkout1", NULL}
+};
+
+struct ext_int {
+	unsigned int on, flag;
+	struct device_attribute int_wait, int_cfg;
+	wait_queue_head_t wq;
+	struct mutex mtx;
+	char int_wait_name[8], int_cfg_name[12];
+	unsigned long irqflags;
+};
+
+struct s3c2410_gpio_info {
+	struct mutex mtx;
+	struct device_attribute at[3 * ARRAY_SIZE(pins)];
+	struct device_attribute at_pd[8];
+	struct device_attribute at_pwrmask[8];
+	struct ext_int eint[EXT_INTS_NR];
+	const struct s3c24xx_gpio_platdata *pdata;
+	unsigned long wrmask[8];
+	char pd_name[8][2];
+	char pwmsk_name[8][6];
+	char at_name[ARRAY_SIZE(pins)][3][8];
+};
+
+static const struct s3c24xx_gpio_platdata s3c2410_gpio_defplat = {
+	.port_mask = {
+		0xFFFFFF, 0x0007FF, 0x00FFFF, 0x00FFFF,
+		0x00FFFF, 0x0000FF, 0x00FFFF, 0x0007FF }
+};
+
+static const char *pin_fn1_name(unsigned int pin)
+{
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(pins); i++)
+		if (pins[i].pin == pin)
+			return pins[i].fn1_name;
+	return NULL;
+}
+
+static const char *pin_fn2_name(unsigned int pin)
+{
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(pins); i++)
+		if (pins[i].pin == pin)
+			return pins[i].fn2_name;
+	return NULL;
+}
+
+static unsigned int getpin(const char *name)
+{
+	return S3C2410_GPIONO(S3C2410_GPIO_BANK(name[0] - 'a'),
+		simple_strtoul(name + 1, NULL, 10));
+}
+
+static irqreturn_t eint_isr(int irq, void *arg)
+{
+	struct ext_int *ext = arg;
+
+	ext->flag = 1;
+	wake_up_interruptible(&ext->wq);
+	return IRQ_HANDLED;
+}
+
+static void update_interrupt_handler(struct device *dev, unsigned int pin)
+{
+	struct ext_int *ei;
+	struct s3c2410_gpio_info *info = dev_get_drvdata(dev);
+	int eintnr;
+
+	if ((pin >= S3C2410_GPF0) && (pin <= S3C2410_GPF7))
+		eintnr = pin - S3C2410_GPF0;
+	else if ((pin >= S3C2410_GPG0) && (pin <= S3C2410_GPG15))
+		eintnr = pin - S3C2410_GPG0 + 8;
+	else
+		return;
+
+	ei = &info->eint[eintnr];
+	if (s3c2410_gpio_getcfg(pin) == S3C2410_GPIO_IRQ) {
+		if (!ei->on) {
+			/* Create device nodes and allocate irq */
+			ei->irqflags = IRQ_TYPE_EDGE_FALLING | IRQF_DISABLED;
+			if (!device_create_file(dev, &ei->int_cfg)) {
+				if (!device_create_file(dev, &ei->int_wait))
+					ei->on = 1;
+				else
+					device_remove_file(dev, &ei->int_cfg);
+			}
+		}
+	} else {
+		if (ei->on) {
+			/* Remove device nodes and deallocate irq */
+			device_remove_file(dev, &ei->int_cfg);
+			device_remove_file(dev, &ei->int_wait);
+			while (mutex_is_locked(&ei->mtx)) {
+				ei->flag = 1;
+				wake_up_interruptible(&ei->wq);
+				schedule();
+			}
+			ei->on = 0;
+		}
+	}
+}
+
+static ssize_t pullup_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	snprintf(buffer, PAGE_SIZE - 1, "%d\n",
+		s3c2410_gpio_getpull(getpin(attr->attr.name)) ? 0 : 1);
+	return strlen(buffer);
+}
+
+static ssize_t config_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	const char *name;
+	unsigned int pin = getpin(attr->attr.name);
+
+	switch (s3c2410_gpio_getcfg(pin)) {
+	case S3C2410_GPIO_INPUT:
+		strlcpy(buffer, "in\n", PAGE_SIZE);
+		break;
+	case S3C2410_GPIO_OUTPUT:
+		strlcpy(buffer, "out\n", PAGE_SIZE);
+		break;
+	case S3C2410_GPIO_SFN2:
+		name = pin_fn1_name(pin);
+		strlcpy(buffer, name ? name : "invalid", PAGE_SIZE);
+		strlcat(buffer, "\n", PAGE_SIZE);
+		break;
+	case S3C2410_GPIO_SFN3:
+		name = pin_fn2_name(pin);
+		strlcpy(buffer, name ? name : "invalid", PAGE_SIZE);
+		strlcat(buffer, "\n", PAGE_SIZE);
+		break;
+	default:
+		buffer[0] = '\0';
+		break;
+	}
+	return strlen(buffer);
+}
+
+static ssize_t value_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	snprintf(buffer, PAGE_SIZE - 1, "%d\n",
+		s3c2410_gpio_getpin(getpin(attr->attr.name)) ? 1 : 0);
+	return strlen(buffer);
+}
+
+static ssize_t pullup_store(struct device *dev, struct device_attribute *attr,
+	const char *buf, size_t count)
+{
+	s3c2410_gpio_pullup(getpin(attr->attr.name), (buf[0] == '0') ? 1 : 0);
+	return count;
+}
+
+static ssize_t config_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	const char *name;
+	unsigned int pin = getpin(attr->attr.name);
+	struct s3c2410_gpio_info *info = dev_get_drvdata(dev);
+
+	mutex_lock(&info->mtx);
+
+	do {
+		if (S3C2410_BANKNUM(pin) != 0) {
+			/* No input on bank A */
+			if (!strncasecmp(buffer, "in", 2)) {
+				s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
+				break;
+			}
+		}
+		if (!strncasecmp(buffer, "out", 3)) {
+			s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_OUTPUT);
+			break;
+		}
+		name = pin_fn1_name(pin);
+		if (name) {
+			if ((!strncasecmp(buffer, name, strlen(name))) ||
+			  !strncasecmp(buffer, "fn1", 3)) {
+				s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_SFN2);
+				break;
+			}
+		}
+		name = pin_fn2_name(pin);
+		if (name) {
+			if ((!strncasecmp(buffer, name, strlen(name))) ||
+			  !strncasecmp(buffer, "fn2", 3)) {
+				s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_SFN3);
+				break;
+			}
+		}
+	} while (0);
+	update_interrupt_handler(dev, pin);
+
+	mutex_unlock(&info->mtx);
+
+	return count;
+}
+
+static ssize_t value_store(struct device *dev, struct device_attribute *attr,
+	const char *buf, size_t count)
+{
+	s3c2410_gpio_setpin(getpin(attr->attr.name), (buf[0] == '0') ? 0 : 1);
+	return count;
+}
+
+static ssize_t eint_cfg_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct s3c2410_gpio_info *info = dev_get_drvdata(dev);
+
+	switch (info->eint[simple_strtoul(attr->attr.name + 4, NULL, 10)]
+		.irqflags) {
+	case IRQ_TYPE_EDGE_RISING | IRQF_DISABLED:
+		strlcpy(buffer, "rising\n", PAGE_SIZE);
+		break;
+	case IRQ_TYPE_EDGE_FALLING | IRQF_DISABLED:
+		strlcpy(buffer, "falling\n", PAGE_SIZE);
+		break;
+	case IRQ_TYPE_EDGE_BOTH | IRQF_DISABLED:
+		strlcpy(buffer, "bothedge\n", PAGE_SIZE);
+		break;
+	case IRQ_TYPE_LEVEL_LOW | IRQF_DISABLED:
+		strlcpy(buffer, "low\n", PAGE_SIZE);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH | IRQF_DISABLED:
+		strlcpy(buffer, "high\n", PAGE_SIZE);
+		break;
+	default:
+		buffer[0] = 0;
+	}
+	return strlen(buffer);
+}
+
+static ssize_t eint_cfg_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	struct s3c2410_gpio_info *info = dev_get_drvdata(dev);
+	int eint = simple_strtoul(attr->attr.name + 4, NULL, 10);
+	struct ext_int *ei = &info->eint[eint];
+
+	mutex_lock(&ei->mtx);
+
+	if (!strncasecmp(buffer, "rising", 6))
+		ei->irqflags = IRQ_TYPE_EDGE_RISING | IRQF_DISABLED;
+	else if (!strncasecmp(buffer, "bothedge", 8))
+		ei->irqflags = IRQ_TYPE_EDGE_BOTH | IRQF_DISABLED;
+	else if (!strncasecmp(buffer, "low", 3))
+		ei->irqflags = IRQ_TYPE_LEVEL_LOW | IRQF_DISABLED;
+	else if (!strncasecmp(buffer, "high", 4))
+		ei->irqflags = IRQ_TYPE_LEVEL_HIGH | IRQF_DISABLED;
+	else	/* Default: falling edge */
+		ei->irqflags = IRQ_TYPE_EDGE_FALLING | IRQF_DISABLED;
+
+	update_interrupt_handler(dev, eint < 8 ?
+		eint + S3C2410_GPF0 : eint - 8 + S3C2410_GPG0);
+
+	mutex_unlock(&ei->mtx);
+
+	return strlen(buffer);
+}
+
+/* Waits for eint */
+static ssize_t eint_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct s3c2410_gpio_info *info = dev_get_drvdata(dev);
+	unsigned long eint = simple_strtoul(attr->attr.name + 4, NULL, 10);
+	struct ext_int *ei = &info->eint[eint];
+	int ret;
+
+	mutex_lock(&ei->mtx);
+
+	ei->flag = 0;
+	ret = request_irq(IRQ_EINT(eint), eint_isr, ei->irqflags,
+		ei->int_wait_name, ei);
+	if (ret == 0) {
+		ret = wait_event_interruptible(ei->wq, ei->flag);
+		/* ret!=0 if interrupted by some other signal */
+		free_irq(IRQ_EINT(eint), ei);
+	}
+
+	mutex_unlock(&ei->mtx);
+
+	snprintf(buffer, PAGE_SIZE - 1, "%d\n", ret);
+	return strlen(buffer);
+}
+
+static ssize_t port_mask_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	struct s3c2410_gpio_info *info = dev_get_drvdata(dev);
+	int port = attr->attr.name[0] - 'a';
+
+	snprintf(buffer, PAGE_SIZE - 1, "%lu\n", info->wrmask[port]);
+	return strlen(buffer);
+}
+
+static ssize_t port_mask_store(struct device *dev,
+	struct device_attribute *attr, const char *buffer, size_t count)
+{
+	struct s3c2410_gpio_info *info = dev_get_drvdata(dev);
+	unsigned long mask;
+	int port = attr->attr.name[0] - 'a';
+	int err = strict_strtoul(buffer, 10, &mask);
+
+	if (err)
+		return err;
+
+	info->wrmask[port] = mask & info->pdata->port_mask[port];
+	return strlen(buffer);
+}
+
+static ssize_t port_show(struct device *dev, struct device_attribute *attr,
+	char *buffer)
+{
+	int port = attr->attr.name[0] - 'a';
+
+	snprintf(buffer, PAGE_SIZE - 1, "%u\n",
+		readl(S3C2410_GPADAT + 16 * port));
+	return strlen(buffer);
+}
+
+static ssize_t port_store(struct device *dev, struct device_attribute *attr,
+	const char *buffer, size_t count)
+{
+	struct s3c2410_gpio_info *info = dev_get_drvdata(dev);
+	int port = attr->attr.name[0] - 'a';
+	unsigned long new, old;
+	int err = strict_strtoul(buffer, 10, &new);
+
+	if (err)
+		return err;
+
+	mutex_lock(&info->mtx);
+
+	old = readl(S3C2410_GPADAT + 16 * port);
+
+	writel(((old & ~info->wrmask[port]) | (new & info->wrmask[port])),
+		S3C2410_GPADAT + 16 * port);
+
+	mutex_unlock(&info->mtx);
+
+	return strlen(buffer);
+}
+
+static int s3c2410gpio_probe(struct platform_device *pdev)
+{
+	int i, err;
+	struct s3c2410_gpio_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
+	struct device_attribute *at;
+
+	if (!info) {
+		dev_err(&pdev->dev, "out of kernel memory\n");
+		err = -ENOMEM;
+		goto fail_malloc;
+	}
+	mutex_init(&info->mtx);
+	platform_set_drvdata(pdev, info);
+	info->pdata = pdev->dev.platform_data ?
+		pdev->dev.platform_data : &s3c2410_gpio_defplat;
+
+	for (i = 0; i < 8; i++) {
+		snprintf(info->pd_name[i],
+			sizeof(info->pd_name[0]), "%c", 'a' + i);
+		info->at_pd[i].attr.mode = S_IRUGO | S_IWUSR;
+		info->at_pd[i].attr.name = info->pd_name[i];
+		info->at_pd[i].show = port_show;
+		info->at_pd[i].store = port_store;
+		err = device_create_file(&pdev->dev, &info->at_pd[i]);
+		if (err) {
+			dev_err(&pdev->dev,
+			    "Unable to create virtual file\n");
+			goto fail_create;
+		}
+		snprintf(info->pwmsk_name[i],
+			sizeof(info->pwmsk_name[0]), "%c-msk", 'a' + i);
+		info->at_pwrmask[i].attr.mode = S_IRUGO | S_IWUSR;
+		info->at_pwrmask[i].attr.name = info->pwmsk_name[i];
+		info->at_pwrmask[i].show = port_mask_show;
+		info->at_pwrmask[i].store = port_mask_store;
+		err = device_create_file(&pdev->dev, &info->at_pwrmask[i]);
+		if (err) {
+			dev_err(&pdev->dev,
+			    "Unable to create virtual file\n");
+			goto fail_create;
+		}
+	}
+
+	for (i = 0; i < EXT_INTS_NR; i++) {
+		/* Initialize eint device attributes */
+		snprintf(info->eint[i].int_cfg_name,
+			sizeof(info->eint[0].int_cfg_name), "eint%d-cfg", i);
+		info->eint[i].int_cfg.attr.mode = S_IRUGO | S_IWUSR;
+		info->eint[i].int_cfg.attr.name = info->eint[i].int_cfg_name;
+		info->eint[i].int_cfg.show = eint_cfg_show;
+		info->eint[i].int_cfg.store = eint_cfg_store;
+		snprintf(info->eint[i].int_wait_name,
+			sizeof(info->eint[0].int_wait_name), "eint%d", i);
+		info->eint[i].int_wait.attr.mode = S_IRUGO;
+		info->eint[i].int_wait.attr.name = info->eint[i].int_wait_name;
+		info->eint[i].int_wait.show = eint_show;
+		mutex_init(&info->eint[i].mtx);
+		init_waitqueue_head(&info->eint[i].wq);
+	}
+
+	for (at = info->at, i = 0; i < ARRAY_SIZE(pins); i++) {
+		int pin = pins[i].pin;
+		int bank = S3C2410_BANKNUM(pin);
+		int offset = S3C2410_GPIO_OFFSET(pin);
+		if ((info->pdata->port_mask[bank]) & (1 << offset)) {
+			if (bank > 0) {
+				/* No pullup on bank A */
+				at->attr.mode = S_IRUGO | S_IWUSR;
+				snprintf(info->at_name[i][0],
+					sizeof(info->at_name[0][0]),
+					"%c%d-pup",
+					bank + 'a', offset);
+				at->attr.name = info->at_name[i][0];
+				at->show = pullup_show;
+				at->store = pullup_store;
+				err = device_create_file(&pdev->dev, at++);
+				if (err) {
+					dev_err(&pdev->dev,
+					    "Unable to create virtual file\n");
+					goto fail_create;
+				}
+			}
+			at->attr.mode = S_IRUGO | S_IWUSR;
+			snprintf(info->at_name[i][1],
+				sizeof(info->at_name[0][0]),
+				"%c%d-cfg", bank + 'a',
+				offset);
+			at->attr.name = info->at_name[i][1];
+			at->show = config_show;
+			at->store = config_store;
+			err = device_create_file(&pdev->dev, at++);
+			if (err) {
+				dev_err(&pdev->dev,
+					"Unable to create virtual file\n");
+				goto fail_create;
+			}
+			at->attr.mode = S_IRUGO | S_IWUSR;
+			snprintf(info->at_name[i][2],
+				sizeof(info->at_name[0][0]),
+				"%c%d", bank + 'a',
+				offset);
+			at->attr.name = info->at_name[i][2];
+			at->show = value_show;
+			at->store = value_store;
+			err = device_create_file(&pdev->dev, at++);
+			if (err) {
+				dev_err(&pdev->dev,
+					"Unable to create virtual file\n");
+				goto fail_create;
+			}
+			update_interrupt_handler(&pdev->dev, pin);
+		}
+	}
+	dev_notice(&pdev->dev, "S3C2410 gpio driver loaded OK\n");
+	return 0;
+
+fail_create:
+	at = info->at;
+	while (at-- >= info->at)
+		device_remove_file(&pdev->dev, at);
+
+	for (i = 0; i < EXT_INTS_NR; i++)
+		if (info->eint[i].on) {
+			device_remove_file(&pdev->dev, &info->eint[i].int_cfg);
+			device_remove_file(&pdev->dev, &info->eint[i].int_wait);
+		}
+
+	for (i = 0; i < 8; i++) {
+		device_remove_file(&pdev->dev, &info->at_pd[i]);
+		device_remove_file(&pdev->dev, &info->at_pwrmask[i]);
+	}
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(info);
+
+fail_malloc:
+	return err;
+}
+
+static int s3c2410gpio_remove(struct platform_device *pdev)
+{
+	struct s3c2410_gpio_info *info = platform_get_drvdata(pdev);
+	struct device_attribute *at;
+	int i;
+
+	for (at = info->at, i = 0; i < 3 * ARRAY_SIZE(pins); i++, at++)
+		if (at->attr.name)
+			device_remove_file(&pdev->dev, at);
+
+	for (i = 0; i < EXT_INTS_NR; i++)
+		if (info->eint[i].on) {
+			device_remove_file(&pdev->dev, &info->eint[i].int_cfg);
+			device_remove_file(&pdev->dev, &info->eint[i].int_wait);
+			while (mutex_is_locked(&info->eint[i].mtx)) {
+				info->eint[i].flag = 1;
+				wake_up_interruptible(&info->eint[i].wq);
+				schedule();
+			}
+		}
+
+	for (i = 0; i < 8; i++) {
+		device_remove_file(&pdev->dev, &info->at_pd[i]);
+		device_remove_file(&pdev->dev, &info->at_pwrmask[i]);
+	}
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(info);
+	dev_notice(&pdev->dev, "S3C2410 gpio driver exit\n");
+	return 0;
+}
+
+static struct platform_driver s3c2410gpio_driver = {
+	.probe  = s3c2410gpio_probe,
+	.remove = s3c2410gpio_remove,
+	.driver = {
+		.name = "s3c2410-gpio",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init s3c2410_gpio_init_module(void)
+{
+	return platform_driver_register(&s3c2410gpio_driver);
+}
+
+static void __exit s3c2410_gpio_cleanup_module(void)
+{
+	platform_driver_unregister(&s3c2410gpio_driver);
+}
+
+module_init(s3c2410_gpio_init_module);
+module_exit(s3c2410_gpio_cleanup_module);
+
+MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
+MODULE_DESCRIPTION("S3C2410 ELPA Gpio driver");
+MODULE_SUPPORTED_DEVICE("gpio/s3c2410");
+MODULE_LICENSE("GPL");
diff -urNp linux-2.6.28.5/drivers/usb/gadget/Kconfig linux-2.6.28.5.elpa/drivers/usb/gadget/Kconfig
--- linux-2.6.28.5/drivers/usb/gadget/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/usb/gadget/Kconfig	2009-01-04 07:40:59.000000000 +0100
@@ -272,7 +272,7 @@ config USB_PXA27X
 
 config USB_GADGET_S3C2410
 	boolean "S3C2410 USB Device Controller"
-	depends on ARCH_S3C2410
+	depends on ARCH_S3C2410 && (RD129_USB_1HOST || RD129_USB_AUTO || !MACH_RD129)
 	help
 	  Samsung's S3C2410 is an ARM-4 processor with an integrated
 	  full speed USB 1.1 device controller.  It has 4 configurable
diff -urNp linux-2.6.28.5/drivers/usb/host/Kconfig linux-2.6.28.5.elpa/drivers/usb/host/Kconfig
--- linux-2.6.28.5/drivers/usb/host/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/usb/host/Kconfig	2009-01-04 07:40:59.000000000 +0100
@@ -140,6 +140,32 @@ config USB_OHCI_HCD
 	  To compile this driver as a module, choose M here: the
 	  module will be called ohci-hcd.
 
++choice
+	depends on USB_OHCI_HCD && MACH_RD129
+	prompt "Samsung S3C2410 USB Host ports"
+	default RD129_USB_2HOST
+
+config RD129_USB_1HOST
+	bool "1 Usb Host port, 1 Usb Device (gadget) port"
+	select USB_GADGET_S3C2410
+	help
+	  Usb port 2 is configured like usb device (gadget)
+
+config RD129_USB_2HOST
+	bool "2 Usb Host ports"
+	help
+	  Usb port 2 is configured like usb host
+
+config RD129_USB_AUTO
+	bool "Autoselect"
+	select USB_GADGET_S3C2410
+	depends on ARCH_S3C2410
+	help
+	  If GPD0 is strapped down, Usb port 2 is configured like usb device
+	  Otherwise, it's configured like usb host
+
+endchoice
+
 config USB_OHCI_HCD_PPC_SOC
 	bool "OHCI support for on-chip PPC USB controller"
 	depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
diff -urNp linux-2.6.28.5/drivers/video/backlight/Kconfig linux-2.6.28.5.elpa/drivers/video/backlight/Kconfig
--- linux-2.6.28.5/drivers/video/backlight/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/video/backlight/Kconfig	2009-01-06 18:31:15.000000000 +0100
@@ -183,6 +183,13 @@ config BACKLIGHT_PWM
 	  If you have a LCD backlight adjustable by PWM, say Y to enable
 	  this driver.
 
+config BACKLIGHT_PWM_FREQUENCY
+	int "PWM Backlight Dimming Frequency"
+	depends on BACKLIGHT_PWM
+	default 20000
+	help
+	  Frequency of PWM signal for backlight dimming
+
 config BACKLIGHT_DA903X
 	tristate "Backlight Driver for DA9030/DA9034 using WLED"
 	depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X
diff -urNp linux-2.6.28.5/drivers/video/s3c2410fb.c linux-2.6.28.5.elpa/drivers/video/s3c2410fb.c
--- linux-2.6.28.5/drivers/video/s3c2410fb.c	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/video/s3c2410fb.c	2009-01-06 19:31:16.000000000 +0100
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
+#include <linux/wait.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -50,6 +51,8 @@ static int debug	= 0;
 
 /* useful functions */
 
+static int s3c2410fb_init_registers(struct fb_info *info);
+
 static int is_s3c2412(struct s3c2410fb_info *fbi)
 {
 	return (fbi->drv_type == DRV_S3C2412);
@@ -124,6 +127,12 @@ static int s3c2410fb_check_var(struct fb
 
 	dprintk("check_var(var=%p, info=%p)\n", var, info);
 
+	if (var->nonstd) {
+		fbi->regs.lcdcon1 = var->nonstd & 0xFFFF;
+		fbi->regs.lcdcon5 = var->nonstd >> 16;
+		return 0;
+	}
+
 	/* validate x/y resolution */
 	/* choose default mode if possible */
 	if (var->yres == default_display->yres &&
@@ -245,7 +254,7 @@ static void s3c2410fb_calculate_stn_lcd_
 {
 	const struct s3c2410fb_info *fbi = info->par;
 	const struct fb_var_screeninfo *var = &info->var;
-	int type = regs->lcdcon1 & ~S3C2410_LCDCON1_TFT;
+	int type = regs->lcdcon1 & S3C2410_LCDCON1_TFT;
 	int hs = var->xres >> 2;
 	unsigned wdly = (var->left_margin >> 4) - 1;
 	unsigned wlh = (var->hsync_len >> 4) - 1;
@@ -350,8 +359,8 @@ static void s3c2410fb_calculate_tft_lcd_
 			S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
 			S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
 
-	regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
-			S3C2410_LCDCON3_HFPD(var->left_margin - 1) |
+	regs->lcdcon3 = S3C2410_LCDCON3_HBPD(var->left_margin - 1) |
+			S3C2410_LCDCON3_HFPD(var->right_margin - 1) |
 			S3C2410_LCDCON3_HOZVAL(var->xres - 1);
 
 	regs->lcdcon4 = S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
@@ -396,15 +405,22 @@ static void s3c2410fb_activate_var(struc
 	dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
 	dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);
 
-	writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,
-		regs + S3C2410_LCDCON1);
-	writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);
-	writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);
-	writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);
-	writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);
-
-	/* set lcd address pointers */
-	s3c2410fb_set_lcdaddr(info);
+	/* This was added to change refresh without stopping LCD controller */
+	if (((fbi->regs.lcdcon1 & 0xFE) !=
+	  (readl(regs + S3C2410_LCDCON1) & 0xFE)) ||
+	  (fbi->regs.lcdcon2 != readl(regs + S3C2410_LCDCON2)) ||
+	  (fbi->regs.lcdcon3 != readl(regs + S3C2410_LCDCON3)) ||
+	  (fbi->regs.lcdcon4 != readl(regs + S3C2410_LCDCON4)) ||
+	  (fbi->regs.lcdcon5 != readl(regs + S3C2410_LCDCON5))) {
+		writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,
+		  regs + S3C2410_LCDCON1);
+		writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);
+		writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);
+		writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);
+		writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);
+		/* set lcd address pointers */
+		s3c2410fb_set_lcdaddr(info);
+	}
 
 	fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,
 	writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);
@@ -419,6 +435,8 @@ static int s3c2410fb_set_par(struct fb_i
 {
 	struct fb_var_screeninfo *var = &info->var;
 
+	s3c2410fb_init_registers(info);
+
 	switch (var->bits_per_pixel) {
 	case 32:
 	case 16:
@@ -607,6 +625,28 @@ static int s3c2410fb_debug_store(struct 
 	return len;
 }
 
+static int s3c2410fb_wait_vsync_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	long ret;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct s3c2410fb_info *fbi = info->par;
+	void __iomem *irq_base = fbi->irq_base;
+	fbi->flag_endframe = 0;
+	/* enable IRQ */
+	writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND);
+	writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND);
+	writel(readl(fbi->io + S3C2410_LCDINTMSK) & ~S3C2410_LCDINT_FRSYNC,
+	  fbi->io + S3C2410_LCDINTMSK);
+	ret = wait_event_interruptible_timeout(fbi->ctrlr_wait,
+	  fbi->flag_endframe, HZ / 5);
+	/* disable IRQ */
+	writel(readl(fbi->io + S3C2410_LCDINTMSK) | S3C2410_LCDINT_FRSYNC,
+	  fbi->io + S3C2410_LCDINTMSK);
+	return snprintf(buf, PAGE_SIZE, "%ld\n", ret);
+}
+
+static DEVICE_ATTR(wait_vsync, S_IRUGO, s3c2410fb_wait_vsync_show, NULL);
 static DEVICE_ATTR(debug, 0666, s3c2410fb_debug_show, s3c2410fb_debug_store);
 
 static struct fb_ops s3c2410fb_ops = {
@@ -753,6 +793,10 @@ static irqreturn_t s3c2410fb_irq(int irq
 
 		writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND);
 		writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND);
+
+		fbi->flag_endframe = 1;
+		wake_up_interruptible(&fbi->ctrlr_wait);
+
 	}
 
 	return IRQ_HANDLED;
@@ -773,7 +817,9 @@ static int __init s3c24xxfb_probe(struct
 	int i;
 	int size;
 	u32 lcdcon1;
+	int base;	/* To store address of original image */
 
+	base = 0;
 	mach_info = pdev->dev.platform_data;
 	if (mach_info == NULL) {
 		dev_err(&pdev->dev,
@@ -831,11 +877,18 @@ static int __init s3c24xxfb_probe(struct
 
 	dprintk("devinit\n");
 
-	strcpy(fbinfo->fix.id, driver_name);
+	init_waitqueue_head(&info->ctrlr_wait);
 
-	/* Stop the video */
 	lcdcon1 = readl(info->io + S3C2410_LCDCON1);
-	writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
+	if (S3C2410_LCDCON1_ENVID & lcdcon1)
+		/* Store bootloader image's address */
+		base = 2 * readl(info->io + S3C2410_LCDSADDR1);
+	else
+		/* Stop the video */
+		writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID,
+			info->io + S3C2410_LCDCON1);
+
+	strlcpy(fbinfo->fix.id, driver_name, sizeof(fbinfo->fix.id));
 
 	fbinfo->fix.type	    = FB_TYPE_PACKED_PIXELS;
 	fbinfo->fix.type_aux	    = 0;
@@ -900,8 +953,6 @@ static int __init s3c24xxfb_probe(struct
 	fbinfo->var.yres = display->yres;
 	fbinfo->var.bits_per_pixel = display->bpp;
 
-	s3c2410fb_init_registers(fbinfo);
-
 	s3c2410fb_check_var(&fbinfo->var, fbinfo);
 
 	ret = register_framebuffer(fbinfo);
@@ -917,9 +968,16 @@ static int __init s3c24xxfb_probe(struct
 		printk(KERN_ERR "failed to add debug attribute\n");
 	}
 
+	device_create_file(&pdev->dev, &dev_attr_wait_vsync);
+
 	printk(KERN_INFO "fb%d: %s frame buffer device\n",
 		fbinfo->node, fbinfo->fix.id);
 
+	/* To restore bootloader image */
+	if (base)
+		memcpy((void *)fbinfo->screen_base, __va((const void *)base),
+			fbinfo->fix.smem_len);
+
 	return 0;
 
 free_video_memory:
@@ -960,6 +1018,9 @@ static int s3c2410fb_remove(struct platf
 	struct s3c2410fb_info *info = fbinfo->par;
 	int irq;
 
+	device_remove_file(&pdev->dev, &dev_attr_debug);
+	device_remove_file(&pdev->dev, &dev_attr_wait_vsync);
+
 	unregister_framebuffer(fbinfo);
 
 	s3c2410fb_lcd_enable(info, 0);
diff -urNp linux-2.6.28.5/drivers/video/s3c2410fb.h linux-2.6.28.5.elpa/drivers/video/s3c2410fb.h
--- linux-2.6.28.5/drivers/video/s3c2410fb.h	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/drivers/video/s3c2410fb.h	2009-01-04 07:40:59.000000000 +0100
@@ -31,6 +31,9 @@ struct s3c2410fb_info {
 
 	unsigned int		palette_ready;
 
+	wait_queue_head_t	ctrlr_wait;
+	int			flag_endframe;
+
 	/* keep these registers in case we need to re-write palette */
 	u32			palette_buffer[256];
 	u32			pseudo_pal[16];
diff -urNp linux-2.6.28.5/include/linux/clk.h linux-2.6.28.5.elpa/include/linux/clk.h
--- linux-2.6.28.5/include/linux/clk.h	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/include/linux/clk.h	2009-02-12 19:05:31.000000000 +0100
@@ -125,4 +125,21 @@ int clk_set_parent(struct clk *clk, stru
  */
 struct clk *clk_get_parent(struct clk *clk);
 
+/**
+ * clk_for_each - calls fn, iterating between registered clocks
+ * @fn: function to be called, passing each clk structure in 1st argument
+ * @data: 2nd argument to pass to fn function
+ *
+ * Returns 0 or the called fn return code if != 0
+ */
+int clk_for_each(int(*fn)(struct clk *, void *), void *data);
+
+/**
+ * clk_name - get clock name
+ * @clk: clock source
+ *
+ * Returns clock's sysname
+ */
+const char *clk_get_sysname(struct clk *clk);
+
 #endif
diff -urNp linux-2.6.28.5/include/linux/pwm.h linux-2.6.28.5.elpa/include/linux/pwm.h
--- linux-2.6.28.5/include/linux/pwm.h	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/include/linux/pwm.h	2009-01-06 19:35:19.000000000 +0100
@@ -19,6 +19,13 @@ void pwm_free(struct pwm_device *pwm);
 int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
 
 /*
+ * pwm_one_shot - programs and starts a timer for one-shot operation
+ *  when expired calls callback
+ */
+int pwm_one_shot(struct pwm_device *pwm, int timeout_ns,
+	void(*expired)(struct pwm_device *, void *arg), void *arg);
+
+/*
  * pwm_enable - start a PWM output toggling
  */
 int pwm_enable(struct pwm_device *pwm);
diff -urNp linux-2.6.28.5/sound/soc/codecs/Kconfig linux-2.6.28.5.elpa/sound/soc/codecs/Kconfig
--- linux-2.6.28.5/sound/soc/codecs/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/sound/soc/codecs/Kconfig	2009-01-08 12:19:02.000000000 +0100
@@ -6,6 +6,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_AD73311
 	select SND_SOC_AK4535
 	select SND_SOC_CS4270
+	select SND_SOC_PCM3006
 	select SND_SOC_SSM2602
 	select SND_SOC_TLV320AIC23
 	select SND_SOC_TLV320AIC26
@@ -60,6 +61,9 @@ config SND_SOC_CS4270_VD33_ERRATA
 	bool
 	depends on SND_SOC_CS4270
 
+config SND_SOC_PCM3006
+	tristate
+
 config SND_SOC_SSM2602
 	tristate
 
diff -urNp linux-2.6.28.5/sound/soc/codecs/Makefile linux-2.6.28.5.elpa/sound/soc/codecs/Makefile
--- linux-2.6.28.5/sound/soc/codecs/Makefile	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/sound/soc/codecs/Makefile	2009-01-04 09:00:28.000000000 +0100
@@ -3,6 +3,7 @@ snd-soc-ad1980-objs := ad1980.o
 snd-soc-ad73311-objs := ad73311.o
 snd-soc-ak4535-objs := ak4535.o
 snd-soc-cs4270-objs := cs4270.o
+snd-soc-pcm3006-objs := pcm3006.o
 snd-soc-ssm2602-objs := ssm2602.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
@@ -25,6 +26,7 @@ obj-$(CONFIG_SND_SOC_AD1980)	+= snd-soc-
 obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
 obj-$(CONFIG_SND_SOC_AK4535)	+= snd-soc-ak4535.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
+obj-$(CONFIG_SND_SOC_PCM3006)	+= snd-soc-pcm3006.o
 obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
diff -urNp linux-2.6.28.5/sound/soc/codecs/pcm3006.c linux-2.6.28.5.elpa/sound/soc/codecs/pcm3006.c
--- linux-2.6.28.5/sound/soc/codecs/pcm3006.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/sound/soc/codecs/pcm3006.c	2009-01-28 20:10:17.000000000 +0100
@@ -0,0 +1,104 @@
+/*
+ * pcm3006.c  --  ALSA Soc PCM3006 codec support
+ *
+ * Copyright 2008 ELPA sas
+ * Author: Davide Rizzo
+ *         elpa.rizzo@gmail.com
+ *
+ *  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.
+ *
+ */
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#define STD_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
+	SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai pcm3006_dai = {
+	.name = "PCM3006",
+	.type = SND_SOC_DAI_I2S,
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000,
+		.formats = STD_I2S_FORMATS,},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000,
+		.formats = STD_I2S_FORMATS,},
+};
+EXPORT_SYMBOL_GPL(pcm3006_dai);
+
+static int pcm3006_soc_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec;
+	int ret;
+
+	printk(KERN_INFO "PCM3006 SoC Audio Codec\n");
+
+	socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (socdev->codec == NULL)
+		return -ENOMEM;
+	codec = socdev->codec;
+	mutex_init(&codec->mutex);
+
+	codec->name = "PCM3006";
+	codec->owner = THIS_MODULE;
+	codec->dai = &pcm3006_dai;
+	codec->num_dai = 1;
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0)
+		goto err;
+
+	ret = snd_soc_register_card(socdev);
+	if (ret < 0)
+		goto bus_err;
+	return 0;
+
+bus_err:
+	snd_soc_free_pcms(socdev);
+
+err:
+	kfree(socdev->codec->reg_cache);
+	kfree(socdev->codec);
+	socdev->codec = NULL;
+	return ret;
+}
+
+static int pcm3006_soc_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	if (codec == NULL)
+		return 0;
+
+	snd_soc_free_pcms(socdev);
+	kfree(socdev->codec->reg_cache);
+	kfree(socdev->codec);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_pcm3006 = {
+	.probe = 	pcm3006_soc_probe,
+	.remove = 	pcm3006_soc_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3006);
+
+MODULE_DESCRIPTION("PCM3006 audio codec driver");
+MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
+MODULE_LICENSE("GPL");
diff -urNp linux-2.6.28.5/sound/soc/codecs/pcm3006.h linux-2.6.28.5.elpa/sound/soc/codecs/pcm3006.h
--- linux-2.6.28.5/sound/soc/codecs/pcm3006.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/sound/soc/codecs/pcm3006.h	2009-01-28 20:10:07.000000000 +0100
@@ -0,0 +1,19 @@
+/*
+ * linux/sound/soc/codecs/pcm3006.h -- ALSA SoC Layer
+ *
+ * Author:		Davide Rizzo <elpa.rizzo@gmail.com>
+ * Created:		Mar 20 2008
+ * Copyright:	ELPA sas
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_SND_SOC_PCM3006_H
+#define __LINUX_SND_SOC_PCM3006_H
+
+extern struct snd_soc_codec_device soc_codec_dev_pcm3006;
+extern struct snd_soc_dai pcm3006_dai;
+
+#endif
diff -urNp linux-2.6.28.5/sound/soc/s3c24xx/Kconfig linux-2.6.28.5.elpa/sound/soc/s3c24xx/Kconfig
--- linux-2.6.28.5/sound/soc/s3c24xx/Kconfig	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/sound/soc/s3c24xx/Kconfig	2009-01-04 07:43:58.000000000 +0100
@@ -7,7 +7,26 @@ config SND_S3C24XX_SOC
 	  to select the audio interfaces to support below.
 
 config SND_S3C24XX_SOC_I2S
-	tristate
+	tristate "Soc Audio dor the Samsung S3C24XX chips through I2S interface"
+	depends on SND_S3C24XX_SOC
+
+config SND_S3C24XX_SOC_RD126_PCM3006
+	tristate "SoC I2S Audio support for RD126 with PCM3006 codec"
+	depends on SND_S3C24XX_SOC_I2S && MACH_RD129
+	select SND_SOC_PCM3006
+	help
+	  Say Y if you want to add support for SoC audio on RD126 boards.
+	  RD126 is the starter kit for ELPA RD129 CPU board.
+	  RD126 has a PCM3006 stereo codec connected on I2S port.
+
+config SND_S3C24XX_SOC_RD126_WM8731
+	tristate "SoC I2S Audio support for RD126 with WM8731 codec"
+	depends on SND_S3C24XX_SOC_I2S && MACH_RD129
+	select SND_SOC_WM8731
+	help
+	  Say Y if you want to add support for SoC audio on RD126 boards.
+	  RD126 is the starter kit for ELPA RD129 CPU board.
+	  WM8731 audio codec can be optionally mounted on RD126.
 
 config SND_S3C2412_SOC_I2S
 	tristate
diff -urNp linux-2.6.28.5/sound/soc/s3c24xx/Makefile linux-2.6.28.5.elpa/sound/soc/s3c24xx/Makefile
--- linux-2.6.28.5/sound/soc/s3c24xx/Makefile	2008-12-25 00:26:37.000000000 +0100
+++ linux-2.6.28.5.elpa/sound/soc/s3c24xx/Makefile	2009-01-04 07:43:58.000000000 +0100
@@ -13,7 +13,11 @@ obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd
 snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
 snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
 snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
+snd-soc-rd126-pcm3006-objs := rd126_pcm3006.o
+snd-soc-rd126-wm8731-objs := rd126_wm8731.o
 
 obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
 obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
 obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
+obj-$(CONFIG_SND_S3C24XX_SOC_RD126_PCM3006) += snd-soc-rd126-pcm3006.o
+obj-$(CONFIG_SND_S3C24XX_SOC_RD126_WM8731) += snd-soc-rd126-wm8731.o
diff -urNp linux-2.6.28.5/sound/soc/s3c24xx/rd126_pcm3006.c linux-2.6.28.5.elpa/sound/soc/s3c24xx/rd126_pcm3006.c
--- linux-2.6.28.5/sound/soc/s3c24xx/rd126_pcm3006.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/sound/soc/s3c24xx/rd126_pcm3006.c	2009-02-05 12:15:12.000000000 +0100
@@ -0,0 +1,209 @@
+/*
+ * rd126_pcm3006  --  SoC audio for S3C2410-based RD129+RD126 board.
+ *
+ * Author:	Davide Rizzo <elpa.rizzo@gmail.com>
+ *		ELPA sas
+ * Created:	Jul 26, 2007
+ *
+ *  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.
+ *
+ */
+
+#include <linux/module.h>
+#include <sound/soc-dapm.h>
+#include <asm/plat-s3c24xx/regs-iis.h>
+
+#include "../codecs/pcm3006.h"
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+
+#if 0
+#define	DBG(x...) printk(KERN_INFO "rd129_snd: " x)
+#else
+#define	DBG(x...)
+#endif
+
+static int rd129_startup(struct snd_pcm_substream *substream)
+{
+	DBG("rd129_startup\n");
+
+	return 0;
+}
+
+static void rd129_shutdown(struct snd_pcm_substream *substream)
+{
+	DBG("rd129_shutdown\n");
+}
+
+static int rd129_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+	int ret, t, div, div256, div384, err, best;
+
+	unsigned long rate = params_rate(params);
+	unsigned long iis_clkrate = s3c24xx_i2s_get_clockrate();
+
+	DBG("rd129_hw_params\n");
+
+	/* set cpu DAI configuration */
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_LEFT_J |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	/* set MCLK division for sample rate */
+/*	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, S3C24XX_CLKSRC_PCLK, 0, 0);
+	ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, S3C24XX_CLKSRC_MPLL, 0, 0);
+	if (ret < 0)
+		return ret;*/
+
+	div256 = iis_clkrate / rate / 256;
+	err = iis_clkrate / div256 / 256 - rate;
+	best = 256;
+	t = rate - iis_clkrate / (div256 + 1) / 256;
+	if (t < err) {
+		div256++;
+		err = t;
+	}
+	div384 = iis_clkrate / rate / 384;
+	t = iis_clkrate / div384 / 384 - rate;
+	if (t < err) {
+		err = t;
+		best = 384;
+	}
+	t = rate - iis_clkrate / (div384 + 1) / 384;
+	if (t < err) {
+		div384++;
+		best = 384;
+	}
+	if (best == 256) {
+		/* set BCLK division for sample rate */
+		ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
+			S3C2410_IISMOD_256FS);
+		div = div256;
+		if (ret < 0)
+			return ret;
+	} else {
+		/* set BCLK division for sample rate */
+		ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
+			S3C2410_IISMOD_384FS);
+		div = div384;
+		if (ret < 0)
+			return ret;
+	}
+	/* set prescaler division for sample rate */
+	ret = snd_soc_dai_set_clkdiv(cpu_dai,
+		S3C24XX_DIV_PRESCALER, S3C24XX_PRESCALE(div, div));
+	if (ret < 0)
+		return ret;
+
+	/* set MCLK division for sample rate */
+	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
+		S3C2410_IISMOD_32FS);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* It must start i2s peripheral BEFORE triggering DMA stuff */
+/* in this way i2s is retriggered by soc-sore.c after triggering DMA */
+/* but creates no problem */
+static int rd129_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai_link *machine = rtd->dai;
+	struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+	int ret;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+printk("RD129 TRIGGER\n");
+			if (cpu_dai->ops.trigger) {
+				ret = cpu_dai->ops.trigger(substream, cmd);
+				if (ret < 0)
+					return ret;
+			}
+			break;
+	}
+	return 0;
+}
+
+static struct snd_soc_ops rd129_ops = {
+	.startup = rd129_startup,
+	.hw_params = rd129_hw_params,
+	.shutdown = rd129_shutdown,
+	.trigger = rd129_trigger,
+};
+
+/*
+ * Logic for a pcm3006 connected on a S3C2410
+ */
+static int pcm3006_init(struct snd_soc_codec *codec)
+{
+
+	DBG("pcm3006_init() called\n");
+
+	return 0;
+}
+
+static struct snd_soc_dai_link rd129_dai = {
+	.name = "PCM3006",
+	.stream_name = "PCM3006 PCM",
+	.cpu_dai = &s3c24xx_i2s_dai,
+	.codec_dai = &pcm3006_dai,
+	.init = pcm3006_init,
+	.ops = &rd129_ops,
+};
+
+static struct snd_soc_machine snd_soc_machine_rd129 = {
+	.name = "RD129-PCM3006",
+	.dai_link = &rd129_dai,
+	.num_links = 1,
+};
+
+static struct snd_soc_device rd129_snd_devdata = {
+	.machine = &snd_soc_machine_rd129,
+	.platform = &s3c24xx_soc_platform,
+	.codec_dev = &soc_codec_dev_pcm3006,
+};
+
+static struct platform_device *rd129_snd_device;
+
+static int __init rd129_snd_init(void)
+{
+	int ret;
+	DBG("Installing RD129 PCM3006 driver\n");
+	rd129_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!rd129_snd_device)
+		return -ENOMEM;
+	platform_set_drvdata(rd129_snd_device, &rd129_snd_devdata);
+	rd129_snd_devdata.dev = &rd129_snd_device->dev;
+	ret = platform_device_add(rd129_snd_device);
+	if (ret) {
+		DBG("platform device add failed\n");
+		platform_device_put(rd129_snd_device);
+	}
+	return ret;
+}
+
+static void __exit rd129_snd_exit(void)
+{
+	platform_device_unregister(rd129_snd_device);
+}
+
+module_init(rd129_snd_init);
+module_exit(rd129_snd_exit);
+
+/* Module information */
+MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC RD129 + PCM3006");
+MODULE_LICENSE("GPL");
+
diff -urNp linux-2.6.28.5/sound/soc/s3c24xx/rd126_wm8731.c linux-2.6.28.5.elpa/sound/soc/s3c24xx/rd126_wm8731.c
--- linux-2.6.28.5/sound/soc/s3c24xx/rd126_wm8731.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.5.elpa/sound/soc/s3c24xx/rd126_wm8731.c	2009-02-14 17:32:59.000000000 +0100
@@ -0,0 +1,189 @@
+/*
+ * rd126_wm8731  --  SoC audio for S3C2410-based RD129+RD126 board.
+ *
+ * Author:	Davide Rizzo <elpa.rizzo@gmail.com>
+ *		ELPA sas
+ * Created:	Apr 25, 2008
+ *
+ *  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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <sound/pcm.h>
+#include <sound/soc-dapm.h>
+#include <mach/regs-gpio.h>
+
+#include "../codecs/wm8731.h"
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+
+#if 1
+#define	DBG(x...) printk(KERN_INFO "rd129_snd: " x)
+#else
+#define	DBG(x...)
+#endif
+
+/* Clkout1 generates 12MHz and is connected to Xin, WM8731 is master */
+#define FCLOCK 12000000
+
+static int rd129_startup(struct snd_pcm_substream *substream)
+{
+	DBG("rd129_startup\n");
+	return 0;
+}
+
+static void rd129_shutdown(struct snd_pcm_substream *substream)
+{
+	DBG("rd129_shutdown\n");
+}
+
+static int rd129_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+	int ret;
+
+	DBG("rd129_hw_params\n");
+
+	/* set cpu DAI configuration */
+	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret < 0)
+		return ret;
+
+	/* set codec DAI configuration */
+	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+	if (ret < 0)
+		return ret;
+
+	/* set the codec system clock for DAC and ADC */
+	ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, FCLOCK,
+		SND_SOC_CLOCK_OUT);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops rd129_ops = {
+	.startup = rd129_startup,
+	.hw_params = rd129_hw_params,
+	.shutdown = rd129_shutdown,
+};
+
+static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Audio Out", NULL),
+};
+
+static const struct snd_soc_dapm_route dapm_routes[] = {
+	{"Audio Out", NULL, "LHPOUT"},
+	{"Audio Out", NULL, "RHPOUT"},
+};
+
+/*
+ * Logic for a wm8731 connected on a S3C2410
+ */
+static int rd129_wm8731_init(struct snd_soc_codec *codec)
+{
+	struct clk *upll, *dclk1, *clkout1;
+
+	/* Program CLKOUT1 to generate 12MHz */
+	upll = clk_get(NULL, "upll");
+	dclk1 = clk_get(NULL, "dclk1");
+	clkout1 = clk_get(NULL, "clkout1");
+	clk_set_parent(dclk1, upll);
+	clk_set_rate(dclk1, FCLOCK);
+	clk_set_parent(clkout1, dclk1);
+	clk_put(dclk1);
+	clk_put(upll);
+	clk_enable(clkout1);
+	s3c2410_gpio_cfgpin(S3C2410_GPH10, S3C2410_GPH10_CLKOUT1);
+
+	snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
+				  ARRAY_SIZE(wm8731_dapm_widgets));
+
+	snd_soc_dapm_enable_pin(codec, "Audio Out");
+
+	snd_soc_dapm_add_routes(codec, dapm_routes, ARRAY_SIZE(dapm_routes));
+
+	snd_soc_dapm_sync(codec);
+	snd_soc_dapm_enable_pin(codec, "HiFi Playback");
+	snd_soc_dapm_enable_pin(codec, "HiFi Playback Switch");
+
+/*	snd_soc_dapm_enable_pin(codec, "LHPOUT");
+	snd_soc_dapm_enable_pin(codec, "RHPOUT");
+	snd_soc_dapm_enable_pin(codec, "DAC");
+	snd_soc_dapm_sync(codec);*/
+	DBG("rd129_wm8731_init() called\n");
+
+	return 0;
+}
+
+static struct snd_soc_dai_link rd129_dai = {
+	.name = "WM8731",
+	.stream_name = "WM8731 PCM",
+	.cpu_dai = &s3c24xx_i2s_dai,
+	.codec_dai = &wm8731_dai,
+	.init = rd129_wm8731_init,
+	.ops = &rd129_ops,
+};
+
+static struct snd_soc_machine snd_soc_machine_rd129 = {
+	.name = "RD129-WM8731",
+	.dai_link = &rd129_dai,
+	.num_links = 1,
+};
+
+static struct wm8731_setup_data rd129_wm8731_setup = {
+	.i2c_bus = 0,
+	.i2c_address = 0x1a,
+};
+
+static struct snd_soc_device rd129_snd_devdata = {
+	.machine = &snd_soc_machine_rd129,
+	.platform = &s3c24xx_soc_platform,
+	.codec_dev = &soc_codec_dev_wm8731,
+	.codec_data = &rd129_wm8731_setup,
+};
+
+static struct platform_device *rd129_snd_device;
+
+static int __init rd129_wm8731_snd_init(void)
+{
+	int ret;
+	DBG("Installing RD129 WM8731 driver\n");
+	rd129_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!rd129_snd_device)
+		return -ENOMEM;
+	platform_set_drvdata(rd129_snd_device, &rd129_snd_devdata);
+	rd129_snd_devdata.dev = &rd129_snd_device->dev;
+	ret = platform_device_add(rd129_snd_device);
+	if (ret) {
+		DBG("platform device add failed\n");
+		platform_device_put(rd129_snd_device);
+	}
+	return ret;
+}
+
+static void __exit rd129_wm8731_snd_exit(void)
+{
+	platform_device_unregister(rd129_snd_device);
+}
+
+module_init(rd129_wm8731_snd_init);
+module_exit(rd129_wm8731_snd_exit);
+
+/* Module information */
+MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
+MODULE_DESCRIPTION("ALSA SoC RD129 + WM8731");
+MODULE_LICENSE("GPL");
+
